diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-11-15 20:56:07 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-11-15 20:56:07 -0500 |
commit | 77ed78e5cf32be1c3fae5c477cc1d78e2e3f17db (patch) | |
tree | 805db8c5c180ee7ee85b3c484461100c91f6c781 | |
parent | 68bdbdf0b32566e1ebd41415bde9a7c43b47bf48 (diff) | |
parent | f6ff56cd56b83d8edf4b3cffc5c53c56b37a5081 (diff) |
Merge branch 'master'
451 files changed, 13491 insertions, 14550 deletions
@@ -1097,7 +1097,7 @@ S: 80050-430 - Curitiba - Paraná | |||
1097 | S: Brazil | 1097 | S: Brazil |
1098 | 1098 | ||
1099 | N: Kumar Gala | 1099 | N: Kumar Gala |
1100 | E: kumar.gala@freescale.com | 1100 | E: galak@kernel.crashing.org |
1101 | D: Embedded PowerPC 6xx/7xx/74xx/82xx/83xx/85xx support | 1101 | D: Embedded PowerPC 6xx/7xx/74xx/82xx/83xx/85xx support |
1102 | S: Austin, Texas 78729 | 1102 | S: Austin, Texas 78729 |
1103 | S: USA | 1103 | S: USA |
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 7018f5c6a447..1c955883cf58 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile | |||
@@ -20,6 +20,12 @@ DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \ | |||
20 | # +--> DIR=file (htmldocs) | 20 | # +--> DIR=file (htmldocs) |
21 | # +--> man/ (mandocs) | 21 | # +--> man/ (mandocs) |
22 | 22 | ||
23 | |||
24 | # for PDF and PS output you can choose between xmlto and docbook-utils tools | ||
25 | PDF_METHOD = $(prefer-db2x) | ||
26 | PS_METHOD = $(prefer-db2x) | ||
27 | |||
28 | |||
23 | ### | 29 | ### |
24 | # The targets that may be used. | 30 | # The targets that may be used. |
25 | .PHONY: xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs | 31 | .PHONY: xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs |
@@ -93,27 +99,39 @@ C-procfs-example = procfs_example.xml | |||
93 | C-procfs-example2 = $(addprefix $(obj)/,$(C-procfs-example)) | 99 | C-procfs-example2 = $(addprefix $(obj)/,$(C-procfs-example)) |
94 | $(obj)/procfs-guide.xml: $(C-procfs-example2) | 100 | $(obj)/procfs-guide.xml: $(C-procfs-example2) |
95 | 101 | ||
96 | ### | 102 | notfoundtemplate = echo "*** You have to install docbook-utils or xmlto ***"; \ |
97 | # Rules to generate postscript, PDF and HTML | 103 | exit 1 |
98 | # db2html creates a directory. Generate a html file used for timestamp | 104 | db2xtemplate = db2TYPE -o $(dir $@) $< |
105 | xmltotemplate = xmlto TYPE $(XMLTOFLAGS) -o $(dir $@) $< | ||
106 | |||
107 | # determine which methods are available | ||
108 | ifeq ($(shell which db2ps >/dev/null 2>&1 && echo found),found) | ||
109 | use-db2x = db2x | ||
110 | prefer-db2x = db2x | ||
111 | else | ||
112 | use-db2x = notfound | ||
113 | prefer-db2x = $(use-xmlto) | ||
114 | endif | ||
115 | ifeq ($(shell which xmlto >/dev/null 2>&1 && echo found),found) | ||
116 | use-xmlto = xmlto | ||
117 | prefer-xmlto = xmlto | ||
118 | else | ||
119 | use-xmlto = notfound | ||
120 | prefer-xmlto = $(use-db2x) | ||
121 | endif | ||
99 | 122 | ||
100 | quiet_cmd_db2ps = XMLTO $@ | 123 | # the commands, generated from the chosen template |
101 | cmd_db2ps = xmlto ps $(XMLTOFLAGS) -o $(dir $@) $< | 124 | quiet_cmd_db2ps = PS $@ |
125 | cmd_db2ps = $(subst TYPE,ps, $($(PS_METHOD)template)) | ||
102 | %.ps : %.xml | 126 | %.ps : %.xml |
103 | @(which xmlto > /dev/null 2>&1) || \ | ||
104 | (echo "*** You need to install xmlto ***"; \ | ||
105 | exit 1) | ||
106 | $(call cmd,db2ps) | 127 | $(call cmd,db2ps) |
107 | 128 | ||
108 | quiet_cmd_db2pdf = XMLTO $@ | 129 | quiet_cmd_db2pdf = PDF $@ |
109 | cmd_db2pdf = xmlto pdf $(XMLTOFLAGS) -o $(dir $@) $< | 130 | cmd_db2pdf = $(subst TYPE,pdf, $($(PDF_METHOD)template)) |
110 | %.pdf : %.xml | 131 | %.pdf : %.xml |
111 | @(which xmlto > /dev/null 2>&1) || \ | ||
112 | (echo "*** You need to install xmlto ***"; \ | ||
113 | exit 1) | ||
114 | $(call cmd,db2pdf) | 132 | $(call cmd,db2pdf) |
115 | 133 | ||
116 | quiet_cmd_db2html = XMLTO $@ | 134 | quiet_cmd_db2html = HTML $@ |
117 | cmd_db2html = xmlto xhtml $(XMLTOFLAGS) -o $(patsubst %.html,%,$@) $< && \ | 135 | cmd_db2html = xmlto xhtml $(XMLTOFLAGS) -o $(patsubst %.html,%,$@) $< && \ |
118 | echo '<a HREF="$(patsubst %.html,%,$(notdir $@))/index.html"> \ | 136 | echo '<a HREF="$(patsubst %.html,%,$(notdir $@))/index.html"> \ |
119 | Goto $(patsubst %.html,%,$(notdir $@))</a><p>' > $@ | 137 | Goto $(patsubst %.html,%,$(notdir $@))</a><p>' > $@ |
@@ -127,7 +145,7 @@ quiet_cmd_db2html = XMLTO $@ | |||
127 | @if [ ! -z "$(PNG-$(basename $(notdir $@)))" ]; then \ | 145 | @if [ ! -z "$(PNG-$(basename $(notdir $@)))" ]; then \ |
128 | cp $(PNG-$(basename $(notdir $@))) $(patsubst %.html,%,$@); fi | 146 | cp $(PNG-$(basename $(notdir $@))) $(patsubst %.html,%,$@); fi |
129 | 147 | ||
130 | quiet_cmd_db2man = XMLTO $@ | 148 | quiet_cmd_db2man = MAN $@ |
131 | cmd_db2man = if grep -q refentry $<; then xmlto man $(XMLTOFLAGS) -o $(obj)/man $< ; gzip -f $(obj)/man/*.9; fi | 149 | cmd_db2man = if grep -q refentry $<; then xmlto man $(XMLTOFLAGS) -o $(obj)/man $< ; gzip -f $(obj)/man/*.9; fi |
132 | %.9 : %.xml | 150 | %.9 : %.xml |
133 | @(which xmlto > /dev/null 2>&1) || \ | 151 | @(which xmlto > /dev/null 2>&1) || \ |
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index a8316b1a3e3d..096aed62c326 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl | |||
@@ -68,9 +68,7 @@ X!Iinclude/linux/kobject.h | |||
68 | 68 | ||
69 | <sect1><title>Kernel utility functions</title> | 69 | <sect1><title>Kernel utility functions</title> |
70 | !Iinclude/linux/kernel.h | 70 | !Iinclude/linux/kernel.h |
71 | <!-- This needs to clean up to make kernel-doc happy | 71 | !Ekernel/printk.c |
72 | X!Ekernel/printk.c | ||
73 | --> | ||
74 | !Ekernel/panic.c | 72 | !Ekernel/panic.c |
75 | !Ekernel/sys.c | 73 | !Ekernel/sys.c |
76 | !Ekernel/rcupdate.c | 74 | !Ekernel/rcupdate.c |
@@ -388,7 +386,7 @@ X!Edrivers/pnp/system.c | |||
388 | 386 | ||
389 | <chapter id="blkdev"> | 387 | <chapter id="blkdev"> |
390 | <title>Block Devices</title> | 388 | <title>Block Devices</title> |
391 | !Edrivers/block/ll_rw_blk.c | 389 | !Eblock/ll_rw_blk.c |
392 | </chapter> | 390 | </chapter> |
393 | 391 | ||
394 | <chapter id="miscdev"> | 392 | <chapter id="miscdev"> |
diff --git a/Documentation/DocBook/stylesheet.xsl b/Documentation/DocBook/stylesheet.xsl index 64be9f7ee3bb..3ccce886c349 100644 --- a/Documentation/DocBook/stylesheet.xsl +++ b/Documentation/DocBook/stylesheet.xsl | |||
@@ -3,4 +3,5 @@ | |||
3 | <param name="chunk.quietly">1</param> | 3 | <param name="chunk.quietly">1</param> |
4 | <param name="funcsynopsis.style">ansi</param> | 4 | <param name="funcsynopsis.style">ansi</param> |
5 | <param name="funcsynopsis.tabular.threshold">80</param> | 5 | <param name="funcsynopsis.tabular.threshold">80</param> |
6 | <!-- <param name="paper.type">A4</param> --> | ||
6 | </stylesheet> | 7 | </stylesheet> |
diff --git a/Documentation/atomic_ops.txt b/Documentation/atomic_ops.txt index 8eedaa24f5e2..23a1c2402bcc 100644 --- a/Documentation/atomic_ops.txt +++ b/Documentation/atomic_ops.txt | |||
@@ -115,6 +115,33 @@ boolean is return which indicates whether the resulting counter value | |||
115 | is negative. It requires explicit memory barrier semantics around the | 115 | is negative. It requires explicit memory barrier semantics around the |
116 | operation. | 116 | operation. |
117 | 117 | ||
118 | Then: | ||
119 | |||
120 | int atomic_cmpxchg(atomic_t *v, int old, int new); | ||
121 | |||
122 | This performs an atomic compare exchange operation on the atomic value v, | ||
123 | with the given old and new values. Like all atomic_xxx operations, | ||
124 | atomic_cmpxchg will only satisfy its atomicity semantics as long as all | ||
125 | other accesses of *v are performed through atomic_xxx operations. | ||
126 | |||
127 | atomic_cmpxchg requires explicit memory barriers around the operation. | ||
128 | |||
129 | The semantics for atomic_cmpxchg are the same as those defined for 'cas' | ||
130 | below. | ||
131 | |||
132 | Finally: | ||
133 | |||
134 | int atomic_add_unless(atomic_t *v, int a, int u); | ||
135 | |||
136 | If the atomic value v is not equal to u, this function adds a to v, and | ||
137 | returns non zero. If v is equal to u then it returns zero. This is done as | ||
138 | an atomic operation. | ||
139 | |||
140 | atomic_add_unless requires explicit memory barriers around the operation. | ||
141 | |||
142 | atomic_inc_not_zero, equivalent to atomic_add_unless(v, 1, 0) | ||
143 | |||
144 | |||
118 | If a caller requires memory barrier semantics around an atomic_t | 145 | If a caller requires memory barrier semantics around an atomic_t |
119 | operation which does not return a value, a set of interfaces are | 146 | operation which does not return a value, a set of interfaces are |
120 | defined which accomplish this: | 147 | defined which accomplish this: |
diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt index 2d65c2182161..0fe01c805480 100644 --- a/Documentation/block/biodoc.txt +++ b/Documentation/block/biodoc.txt | |||
@@ -1063,8 +1063,8 @@ Aside: | |||
1063 | 4.4 I/O contexts | 1063 | 4.4 I/O contexts |
1064 | I/O contexts provide a dynamically allocated per process data area. They may | 1064 | I/O contexts provide a dynamically allocated per process data area. They may |
1065 | be used in I/O schedulers, and in the block layer (could be used for IO statis, | 1065 | be used in I/O schedulers, and in the block layer (could be used for IO statis, |
1066 | priorities for example). See *io_context in drivers/block/ll_rw_blk.c, and | 1066 | priorities for example). See *io_context in block/ll_rw_blk.c, and as-iosched.c |
1067 | as-iosched.c for an example of usage in an i/o scheduler. | 1067 | for an example of usage in an i/o scheduler. |
1068 | 1068 | ||
1069 | 1069 | ||
1070 | 5. Scalability related changes | 1070 | 5. Scalability related changes |
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 429db4bf98ec..24fe8edad304 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt | |||
@@ -140,3 +140,12 @@ What: EXPORT_SYMBOL(lookup_hash) | |||
140 | When: January 2006 | 140 | When: January 2006 |
141 | Why: Too low-level interface. Use lookup_one_len or lookup_create instead. | 141 | Why: Too low-level interface. Use lookup_one_len or lookup_create instead. |
142 | Who: Christoph Hellwig <hch@lst.de> | 142 | Who: Christoph Hellwig <hch@lst.de> |
143 | |||
144 | --------------------------- | ||
145 | |||
146 | What: START_ARRAY ioctl for md | ||
147 | When: July 2006 | ||
148 | Files: drivers/md/md.c | ||
149 | Why: Not reliable by design - can fail when most needed. | ||
150 | Alternatives exist | ||
151 | Who: NeilBrown <neilb@suse.de> | ||
diff --git a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt index c563842ed805..05960f8a748e 100644 --- a/Documentation/oops-tracing.txt +++ b/Documentation/oops-tracing.txt | |||
@@ -30,7 +30,12 @@ the disk is not available then you have three options :- | |||
30 | 30 | ||
31 | (1) Hand copy the text from the screen and type it in after the machine | 31 | (1) Hand copy the text from the screen and type it in after the machine |
32 | has restarted. Messy but it is the only option if you have not | 32 | has restarted. Messy but it is the only option if you have not |
33 | planned for a crash. | 33 | planned for a crash. Alternatively, you can take a picture of |
34 | the screen with a digital camera - not nice, but better than | ||
35 | nothing. If the messages scroll off the top of the console, you | ||
36 | may find that booting with a higher resolution (eg, vga=791) | ||
37 | will allow you to read more of the text. (Caveat: This needs vesafb, | ||
38 | so won't help for 'early' oopses) | ||
34 | 39 | ||
35 | (2) Boot with a serial console (see Documentation/serial-console.txt), | 40 | (2) Boot with a serial console (see Documentation/serial-console.txt), |
36 | run a null modem to a second machine and capture the output there | 41 | run a null modem to a second machine and capture the output there |
diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index 2404099996ac..330246ac80f8 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv | |||
@@ -140,3 +140,4 @@ | |||
140 | 139 -> Prolink PixelView PlayTV MPEG2 PV-M4900 | 140 | 139 -> Prolink PixelView PlayTV MPEG2 PV-M4900 |
141 | 140 -> Osprey 440 [0070:ff07] | 141 | 140 -> Osprey 440 [0070:ff07] |
142 | 141 -> Asound Skyeye PCTV | 142 | 141 -> Asound Skyeye PCTV |
143 | 142 -> Sabrent TV-FM (bttv version) | ||
diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 57c9d631db56..efb708ec116a 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 | |||
@@ -80,3 +80,5 @@ | |||
80 | 79 -> Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B) | 80 | 79 -> Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B) |
81 | 80 -> ASUS Digimatrix TV [1043:0210] | 81 | 80 -> ASUS Digimatrix TV [1043:0210] |
82 | 81 -> Philips Tiger reference design [1131:2018] | 82 | 81 -> Philips Tiger reference design [1131:2018] |
83 | 82 -> MSI TV@Anywhere plus [1462:6231] | ||
84 | |||
diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index ec840ca6f455..9d6544ea9f41 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner | |||
@@ -67,3 +67,4 @@ tuner=65 - Ymec TVF66T5-B/DFF | |||
67 | tuner=66 - LG NTSC (TALN mini series) | 67 | tuner=66 - LG NTSC (TALN mini series) |
68 | tuner=67 - Philips TD1316 Hybrid Tuner | 68 | tuner=67 - Philips TD1316 Hybrid Tuner |
69 | tuner=68 - Philips TUV1236D ATSC/NTSC dual in | 69 | tuner=68 - Philips TUV1236D ATSC/NTSC dual in |
70 | tuner=69 - Tena TNF 5335 MF | ||
diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt index ffe1c062088b..e566affeed7f 100644 --- a/Documentation/x86_64/boot-options.txt +++ b/Documentation/x86_64/boot-options.txt | |||
@@ -7,10 +7,12 @@ Machine check | |||
7 | 7 | ||
8 | mce=off disable machine check | 8 | mce=off disable machine check |
9 | mce=bootlog Enable logging of machine checks left over from booting. | 9 | mce=bootlog Enable logging of machine checks left over from booting. |
10 | Disabled by default because some BIOS leave bogus ones. | 10 | Disabled by default on AMD because some BIOS leave bogus ones. |
11 | If your BIOS doesn't do that it's a good idea to enable though | 11 | If your BIOS doesn't do that it's a good idea to enable though |
12 | to make sure you log even machine check events that result | 12 | to make sure you log even machine check events that result |
13 | in a reboot. | 13 | in a reboot. On Intel systems it is enabled by default. |
14 | mce=nobootlog | ||
15 | Disable boot machine check logging. | ||
14 | mce=tolerancelevel (number) | 16 | mce=tolerancelevel (number) |
15 | 0: always panic, 1: panic if deadlock possible, | 17 | 0: always panic, 1: panic if deadlock possible, |
16 | 2: try to avoid panic, 3: never panic or exit (for testing) | 18 | 2: try to avoid panic, 3: never panic or exit (for testing) |
@@ -122,6 +124,9 @@ SMP | |||
122 | 124 | ||
123 | cpumask=MASK only use cpus with bits set in mask | 125 | cpumask=MASK only use cpus with bits set in mask |
124 | 126 | ||
127 | additional_cpus=NUM Allow NUM more CPUs for hotplug | ||
128 | (defaults are specified by the BIOS or half the available CPUs) | ||
129 | |||
125 | NUMA | 130 | NUMA |
126 | 131 | ||
127 | numa=off Only set up a single NUMA node spanning all memory. | 132 | numa=off Only set up a single NUMA node spanning all memory. |
@@ -188,6 +193,9 @@ Debugging | |||
188 | 193 | ||
189 | kstack=N Print that many words from the kernel stack in oops dumps. | 194 | kstack=N Print that many words from the kernel stack in oops dumps. |
190 | 195 | ||
196 | pagefaulttrace Dump all page faults. Only useful for extreme debugging | ||
197 | and will create a lot of output. | ||
198 | |||
191 | Misc | 199 | Misc |
192 | 200 | ||
193 | noreplacement Don't replace instructions with more appropiate ones | 201 | noreplacement Don't replace instructions with more appropiate ones |
diff --git a/Documentation/x86_64/mm.txt b/Documentation/x86_64/mm.txt index 662b73971a67..133561b9cb0c 100644 --- a/Documentation/x86_64/mm.txt +++ b/Documentation/x86_64/mm.txt | |||
@@ -6,7 +6,7 @@ Virtual memory map with 4 level page tables: | |||
6 | 0000000000000000 - 00007fffffffffff (=47bits) user space, different per mm | 6 | 0000000000000000 - 00007fffffffffff (=47bits) user space, different per mm |
7 | hole caused by [48:63] sign extension | 7 | hole caused by [48:63] sign extension |
8 | ffff800000000000 - ffff80ffffffffff (=40bits) guard hole | 8 | ffff800000000000 - ffff80ffffffffff (=40bits) guard hole |
9 | ffff810000000000 - ffffc0ffffffffff (=46bits) direct mapping of phys. memory | 9 | ffff810000000000 - ffffc0ffffffffff (=46bits) direct mapping of all phys. memory |
10 | ffffc10000000000 - ffffc1ffffffffff (=40bits) hole | 10 | ffffc10000000000 - ffffc1ffffffffff (=40bits) hole |
11 | ffffc20000000000 - ffffe1ffffffffff (=45bits) vmalloc/ioremap space | 11 | ffffc20000000000 - ffffe1ffffffffff (=45bits) vmalloc/ioremap space |
12 | ... unused hole ... | 12 | ... unused hole ... |
@@ -14,6 +14,10 @@ ffffffff80000000 - ffffffff82800000 (=40MB) kernel text mapping, from phys 0 | |||
14 | ... unused hole ... | 14 | ... unused hole ... |
15 | ffffffff88000000 - fffffffffff00000 (=1919MB) module mapping space | 15 | ffffffff88000000 - fffffffffff00000 (=1919MB) module mapping space |
16 | 16 | ||
17 | The direct mapping covers all memory in the system upto the highest | ||
18 | memory address (this means in some cases it can also include PCI memory | ||
19 | holes) | ||
20 | |||
17 | vmalloc space is lazily synchronized into the different PML4 pages of | 21 | vmalloc space is lazily synchronized into the different PML4 pages of |
18 | the processes using the page fault handler, with init_level4_pgt as | 22 | the processes using the page fault handler, with init_level4_pgt as |
19 | reference. | 23 | reference. |
diff --git a/MAINTAINERS b/MAINTAINERS index 2313de23b0da..509927e40bbb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -1565,7 +1565,7 @@ S: Maintained | |||
1565 | 1565 | ||
1566 | LINUX FOR POWERPC EMBEDDED PPC83XX AND PPC85XX | 1566 | LINUX FOR POWERPC EMBEDDED PPC83XX AND PPC85XX |
1567 | P: Kumar Gala | 1567 | P: Kumar Gala |
1568 | M: kumar.gala@freescale.com | 1568 | M: galak@kernel.crashing.org |
1569 | W: http://www.penguinppc.org/ | 1569 | W: http://www.penguinppc.org/ |
1570 | L: linuxppc-embedded@ozlabs.org | 1570 | L: linuxppc-embedded@ozlabs.org |
1571 | S: Maintained | 1571 | S: Maintained |
@@ -1873,6 +1873,16 @@ L: linux-tr@linuxtr.net | |||
1873 | W: http://www.linuxtr.net | 1873 | W: http://www.linuxtr.net |
1874 | S: Maintained | 1874 | S: Maintained |
1875 | 1875 | ||
1876 | OMNIKEY CARDMAN 4000 DRIVER | ||
1877 | P: Harald Welte | ||
1878 | M: laforge@gnumonks.org | ||
1879 | S: Maintained | ||
1880 | |||
1881 | OMNIKEY CARDMAN 4040 DRIVER | ||
1882 | P: Harald Welte | ||
1883 | M: laforge@gnumonks.org | ||
1884 | S: Maintained | ||
1885 | |||
1876 | ONSTREAM SCSI TAPE DRIVER | 1886 | ONSTREAM SCSI TAPE DRIVER |
1877 | P: Willem Riede | 1887 | P: Willem Riede |
1878 | M: osst@riede.org | 1888 | M: osst@riede.org |
@@ -1193,6 +1193,17 @@ else | |||
1193 | __srctree = $(srctree)/ | 1193 | __srctree = $(srctree)/ |
1194 | endif | 1194 | endif |
1195 | 1195 | ||
1196 | ifeq ($(ALLSOURCE_ARCHS),) | ||
1197 | ifeq ($(ARCH),um) | ||
1198 | ALLINCLUDE_ARCHS := $(ARCH) $(SUBARCH) | ||
1199 | else | ||
1200 | ALLINCLUDE_ARCHS := $(ARCH) | ||
1201 | endif | ||
1202 | else | ||
1203 | #Allow user to specify only ALLSOURCE_PATHS on the command line, keeping existing behaviour. | ||
1204 | ALLINCLUDE_ARCHS := $(ALLSOURCE_ARCHS) | ||
1205 | endif | ||
1206 | |||
1196 | ALLSOURCE_ARCHS := $(ARCH) | 1207 | ALLSOURCE_ARCHS := $(ARCH) |
1197 | 1208 | ||
1198 | define all-sources | 1209 | define all-sources |
@@ -1208,7 +1219,7 @@ define all-sources | |||
1208 | find $(__srctree)include $(RCS_FIND_IGNORE) \ | 1219 | find $(__srctree)include $(RCS_FIND_IGNORE) \ |
1209 | \( -name config -o -name 'asm-*' \) -prune \ | 1220 | \( -name config -o -name 'asm-*' \) -prune \ |
1210 | -o -name '*.[chS]' -print; \ | 1221 | -o -name '*.[chS]' -print; \ |
1211 | for ARCH in $(ALLSOURCE_ARCHS) ; do \ | 1222 | for ARCH in $(ALLINCLUDE_ARCHS) ; do \ |
1212 | find $(__srctree)include/asm-$${ARCH} $(RCS_FIND_IGNORE) \ | 1223 | find $(__srctree)include/asm-$${ARCH} $(RCS_FIND_IGNORE) \ |
1213 | -name '*.[chS]' -print; \ | 1224 | -name '*.[chS]' -print; \ |
1214 | done ; \ | 1225 | done ; \ |
@@ -81,6 +81,11 @@ INSTALLING the kernel: | |||
81 | failed patches (xxx# or xxx.rej). If there are, either you or me has | 81 | failed patches (xxx# or xxx.rej). If there are, either you or me has |
82 | made a mistake. | 82 | made a mistake. |
83 | 83 | ||
84 | Unlike patches for the 2.6.x kernels, patches for the 2.6.x.y kernels | ||
85 | (also known as the -stable kernels) are not incremental but instead apply | ||
86 | directly to the base 2.6.x kernel. Please read | ||
87 | Documentation/applying-patches.txt for more information. | ||
88 | |||
84 | Alternatively, the script patch-kernel can be used to automate this | 89 | Alternatively, the script patch-kernel can be used to automate this |
85 | process. It determines the current kernel version and applies any | 90 | process. It determines the current kernel version and applies any |
86 | patches found. | 91 | patches found. |
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3df7cbd924a1..4b15f5f1e254 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -652,25 +652,11 @@ endmenu | |||
652 | 652 | ||
653 | menu "Power management options" | 653 | menu "Power management options" |
654 | 654 | ||
655 | config PM | 655 | source "kernel/power/Kconfig" |
656 | bool "Power Management support" | ||
657 | ---help--- | ||
658 | "Power Management" means that parts of your computer are shut | ||
659 | off or put into a power conserving "sleep" mode if they are not | ||
660 | being used. There are two competing standards for doing this: APM | ||
661 | and ACPI. If you want to use either one, say Y here and then also | ||
662 | to the requisite support below. | ||
663 | |||
664 | Power Management is most important for battery powered laptop | ||
665 | computers; if you have a laptop, check out the Linux Laptop home | ||
666 | page on the WWW at <http://www.linux-on-laptops.com/> or | ||
667 | Tuxmobil - Linux on Mobile Computers at <http://www.tuxmobil.org/> | ||
668 | and the Battery Powered Linux mini-HOWTO, available from | ||
669 | <http://www.tldp.org/docs.html#howto>. | ||
670 | 656 | ||
671 | config APM | 657 | config APM |
672 | tristate "Advanced Power Management Emulation" | 658 | tristate "Advanced Power Management Emulation" |
673 | depends on PM | 659 | depends on PM_LEGACY |
674 | ---help--- | 660 | ---help--- |
675 | APM is a BIOS specification for saving power using several different | 661 | APM is a BIOS specification for saving power using several different |
676 | techniques. This is mostly useful for battery powered laptops with | 662 | techniques. This is mostly useful for battery powered laptops with |
@@ -702,6 +688,8 @@ menu "Device Drivers" | |||
702 | 688 | ||
703 | source "drivers/base/Kconfig" | 689 | source "drivers/base/Kconfig" |
704 | 690 | ||
691 | source "drivers/connector/Kconfig" | ||
692 | |||
705 | if ALIGNMENT_TRAP | 693 | if ALIGNMENT_TRAP |
706 | source "drivers/mtd/Kconfig" | 694 | source "drivers/mtd/Kconfig" |
707 | endif | 695 | endif |
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c index 557e52c1c869..1b7eaab02b9e 100644 --- a/arch/arm/common/locomo.c +++ b/arch/arm/common/locomo.c | |||
@@ -623,8 +623,6 @@ static int locomo_resume(struct platform_device *dev) | |||
623 | locomo_writel(0x1, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KCMD); | 623 | locomo_writel(0x1, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KCMD); |
624 | 624 | ||
625 | spin_unlock_irqrestore(&lchip->lock, flags); | 625 | spin_unlock_irqrestore(&lchip->lock, flags); |
626 | |||
627 | dev->power.saved_state = NULL; | ||
628 | kfree(save); | 626 | kfree(save); |
629 | 627 | ||
630 | return 0; | 628 | return 0; |
@@ -775,7 +773,7 @@ static int locomo_probe(struct platform_device *dev) | |||
775 | 773 | ||
776 | static int locomo_remove(struct platform_device *dev) | 774 | static int locomo_remove(struct platform_device *dev) |
777 | { | 775 | { |
778 | struct locomo *lchip = platform__get_drvdata(dev); | 776 | struct locomo *lchip = platform_get_drvdata(dev); |
779 | 777 | ||
780 | if (lchip) { | 778 | if (lchip) { |
781 | __locomo_remove(lchip); | 779 | __locomo_remove(lchip); |
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index 7b07acb03f3b..39a6eea300a2 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c | |||
@@ -1266,7 +1266,7 @@ static void __exit sa1111_exit(void) | |||
1266 | bus_unregister(&sa1111_bus_type); | 1266 | bus_unregister(&sa1111_bus_type); |
1267 | } | 1267 | } |
1268 | 1268 | ||
1269 | module_init(sa1111_init); | 1269 | subsys_initcall(sa1111_init); |
1270 | module_exit(sa1111_exit); | 1270 | module_exit(sa1111_exit); |
1271 | 1271 | ||
1272 | MODULE_DESCRIPTION("Intel Corporation SA1111 core driver"); | 1272 | MODULE_DESCRIPTION("Intel Corporation SA1111 core driver"); |
diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c index 32924c6714fe..0c3cbd9a388b 100644 --- a/arch/arm/common/scoop.c +++ b/arch/arm/common/scoop.c | |||
@@ -153,7 +153,7 @@ int __init scoop_probe(struct platform_device *pdev) | |||
153 | printk("Sharp Scoop Device found at 0x%08x -> 0x%08x\n",(unsigned int)mem->start,(unsigned int)devptr->base); | 153 | printk("Sharp Scoop Device found at 0x%08x -> 0x%08x\n",(unsigned int)mem->start,(unsigned int)devptr->base); |
154 | 154 | ||
155 | SCOOP_REG(devptr->base, SCOOP_MCR) = 0x0140; | 155 | SCOOP_REG(devptr->base, SCOOP_MCR) = 0x0140; |
156 | reset_scoop(dev); | 156 | reset_scoop(&pdev->dev); |
157 | SCOOP_REG(devptr->base, SCOOP_GPCR) = inf->io_dir & 0xffff; | 157 | SCOOP_REG(devptr->base, SCOOP_GPCR) = inf->io_dir & 0xffff; |
158 | SCOOP_REG(devptr->base, SCOOP_GPWR) = inf->io_out & 0xffff; | 158 | SCOOP_REG(devptr->base, SCOOP_GPWR) = inf->io_out & 0xffff; |
159 | 159 | ||
diff --git a/arch/arm/kernel/apm.c b/arch/arm/kernel/apm.c index b0bbd1e62ebb..a2843be05557 100644 --- a/arch/arm/kernel/apm.c +++ b/arch/arm/kernel/apm.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/apm_bios.h> | 20 | #include <linux/apm_bios.h> |
21 | #include <linux/sched.h> | 21 | #include <linux/sched.h> |
22 | #include <linux/pm.h> | 22 | #include <linux/pm.h> |
23 | #include <linux/pm_legacy.h> | ||
23 | #include <linux/device.h> | 24 | #include <linux/device.h> |
24 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
25 | #include <linux/list.h> | 26 | #include <linux/list.h> |
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index e55ea952f7aa..373c0959bc2f 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
@@ -256,9 +256,7 @@ void __cpuexit cpu_die(void) | |||
256 | asmlinkage void __cpuinit secondary_start_kernel(void) | 256 | asmlinkage void __cpuinit secondary_start_kernel(void) |
257 | { | 257 | { |
258 | struct mm_struct *mm = &init_mm; | 258 | struct mm_struct *mm = &init_mm; |
259 | unsigned int cpu; | 259 | unsigned int cpu = smp_processor_id(); |
260 | |||
261 | cpu = smp_processor_id(); | ||
262 | 260 | ||
263 | printk("CPU%u: Booted secondary processor\n", cpu); | 261 | printk("CPU%u: Booted secondary processor\n", cpu); |
264 | 262 | ||
diff --git a/arch/arm/mach-footbridge/common.c b/arch/arm/mach-footbridge/common.c index dc09fd200c16..bbe6e4a0bf6a 100644 --- a/arch/arm/mach-footbridge/common.c +++ b/arch/arm/mach-footbridge/common.c | |||
@@ -132,14 +132,14 @@ void __init footbridge_init_irq(void) | |||
132 | static struct map_desc fb_common_io_desc[] __initdata = { | 132 | static struct map_desc fb_common_io_desc[] __initdata = { |
133 | { | 133 | { |
134 | .virtual = ARMCSR_BASE, | 134 | .virtual = ARMCSR_BASE, |
135 | .pfn = DC21285_ARMCSR_BASE, | 135 | .pfn = __phys_to_pfn(DC21285_ARMCSR_BASE), |
136 | .length = ARMCSR_SIZE, | 136 | .length = ARMCSR_SIZE, |
137 | .type = MT_DEVICE | 137 | .type = MT_DEVICE, |
138 | }, { | 138 | }, { |
139 | .virtual = XBUS_BASE, | 139 | .virtual = XBUS_BASE, |
140 | .pfn = __phys_to_pfn(0x40000000), | 140 | .pfn = __phys_to_pfn(0x40000000), |
141 | .length = XBUS_SIZE, | 141 | .length = XBUS_SIZE, |
142 | .type = MT_DEVICE | 142 | .type = MT_DEVICE, |
143 | } | 143 | } |
144 | }; | 144 | }; |
145 | 145 | ||
@@ -153,28 +153,28 @@ static struct map_desc ebsa285_host_io_desc[] __initdata = { | |||
153 | .virtual = PCIMEM_BASE, | 153 | .virtual = PCIMEM_BASE, |
154 | .pfn = __phys_to_pfn(DC21285_PCI_MEM), | 154 | .pfn = __phys_to_pfn(DC21285_PCI_MEM), |
155 | .length = PCIMEM_SIZE, | 155 | .length = PCIMEM_SIZE, |
156 | .type = MT_DEVICE | 156 | .type = MT_DEVICE, |
157 | }, { | 157 | }, { |
158 | .virtual = PCICFG0_BASE, | 158 | .virtual = PCICFG0_BASE, |
159 | .pfn = __phys_to_pfn(DC21285_PCI_TYPE_0_CONFIG), | 159 | .pfn = __phys_to_pfn(DC21285_PCI_TYPE_0_CONFIG), |
160 | .length = PCICFG0_SIZE, | 160 | .length = PCICFG0_SIZE, |
161 | .type = MT_DEVICE | 161 | .type = MT_DEVICE, |
162 | }, { | 162 | }, { |
163 | .virtual = PCICFG1_BASE, | 163 | .virtual = PCICFG1_BASE, |
164 | .pfn = __phys_to_pfn(DC21285_PCI_TYPE_1_CONFIG), | 164 | .pfn = __phys_to_pfn(DC21285_PCI_TYPE_1_CONFIG), |
165 | .length = PCICFG1_SIZE, | 165 | .length = PCICFG1_SIZE, |
166 | .type = MT_DEVICE | 166 | .type = MT_DEVICE, |
167 | }, { | 167 | }, { |
168 | .virtual = PCIIACK_BASE, | 168 | .virtual = PCIIACK_BASE, |
169 | .pfn = __phys_to_pfn(DC21285_PCI_IACK), | 169 | .pfn = __phys_to_pfn(DC21285_PCI_IACK), |
170 | .length = PCIIACK_SIZE, | 170 | .length = PCIIACK_SIZE, |
171 | .type = MT_DEVICE | 171 | .type = MT_DEVICE, |
172 | }, { | 172 | }, { |
173 | .virtual = PCIO_BASE, | 173 | .virtual = PCIO_BASE, |
174 | .pfn = __phys_to_pfn(DC21285_PCI_IO), | 174 | .pfn = __phys_to_pfn(DC21285_PCI_IO), |
175 | .length = PCIO_SIZE, | 175 | .length = PCIO_SIZE, |
176 | .type = MT_DEVICE | 176 | .type = MT_DEVICE, |
177 | } | 177 | }, |
178 | #endif | 178 | #endif |
179 | }; | 179 | }; |
180 | 180 | ||
@@ -187,13 +187,13 @@ static struct map_desc co285_io_desc[] __initdata = { | |||
187 | .virtual = PCIO_BASE, | 187 | .virtual = PCIO_BASE, |
188 | .pfn = __phys_to_pfn(DC21285_PCI_IO), | 188 | .pfn = __phys_to_pfn(DC21285_PCI_IO), |
189 | .length = PCIO_SIZE, | 189 | .length = PCIO_SIZE, |
190 | .type = MT_DEVICE | 190 | .type = MT_DEVICE, |
191 | }, { | 191 | }, { |
192 | .virtual = PCIMEM_BASE, | 192 | .virtual = PCIMEM_BASE, |
193 | .pfn = __phys_to_pfn(DC21285_PCI_MEM), | 193 | .pfn = __phys_to_pfn(DC21285_PCI_MEM), |
194 | .length = PCIMEM_SIZE, | 194 | .length = PCIMEM_SIZE, |
195 | .type = MT_DEVICE | 195 | .type = MT_DEVICE, |
196 | } | 196 | }, |
197 | #endif | 197 | #endif |
198 | }; | 198 | }; |
199 | 199 | ||
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index e201aa9765b9..cd506646801a 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig | |||
@@ -72,6 +72,12 @@ config MACH_HUSKY | |||
72 | depends PXA_SHARPSL_25x | 72 | depends PXA_SHARPSL_25x |
73 | select PXA_SHARP_C7xx | 73 | select PXA_SHARP_C7xx |
74 | 74 | ||
75 | config MACH_AKITA | ||
76 | bool "Enable Sharp SL-1000 (Akita) Support" | ||
77 | depends PXA_SHARPSL_27x | ||
78 | select PXA_SHARP_Cxx00 | ||
79 | select MACH_SPITZ | ||
80 | |||
75 | config MACH_SPITZ | 81 | config MACH_SPITZ |
76 | bool "Enable Sharp Zaurus SL-3000 (Spitz) Support" | 82 | bool "Enable Sharp Zaurus SL-3000 (Spitz) Support" |
77 | depends PXA_SHARPSL_27x | 83 | depends PXA_SHARPSL_27x |
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index d210bd5032ce..32526a0a6f86 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile | |||
@@ -11,8 +11,9 @@ obj-$(CONFIG_PXA27x) += pxa27x.o | |||
11 | obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o | 11 | obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o |
12 | obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o | 12 | obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o |
13 | obj-$(CONFIG_ARCH_PXA_IDP) += idp.o | 13 | obj-$(CONFIG_ARCH_PXA_IDP) += idp.o |
14 | obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o | 14 | obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o corgi_pm.o |
15 | obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o | 15 | obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o spitz_pm.o |
16 | obj-$(CONFIG_MACH_AKITA) += akita-ioexp.o | ||
16 | obj-$(CONFIG_MACH_POODLE) += poodle.o | 17 | obj-$(CONFIG_MACH_POODLE) += poodle.o |
17 | obj-$(CONFIG_MACH_TOSA) += tosa.o | 18 | obj-$(CONFIG_MACH_TOSA) += tosa.o |
18 | 19 | ||
diff --git a/arch/arm/mach-pxa/akita-ioexp.c b/arch/arm/mach-pxa/akita-ioexp.c new file mode 100644 index 000000000000..f6d73cc01f78 --- /dev/null +++ b/arch/arm/mach-pxa/akita-ioexp.c | |||
@@ -0,0 +1,223 @@ | |||
1 | /* | ||
2 | * Support for the Extra GPIOs on the Sharp SL-C1000 (Akita) | ||
3 | * (uses a Maxim MAX7310 8 Port IO Expander) | ||
4 | * | ||
5 | * Copyright 2005 Openedhand Ltd. | ||
6 | * | ||
7 | * Author: Richard Purdie <richard@openedhand.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/i2c.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/workqueue.h> | ||
22 | #include <asm/arch/akita.h> | ||
23 | |||
24 | /* MAX7310 Regiser Map */ | ||
25 | #define MAX7310_INPUT 0x00 | ||
26 | #define MAX7310_OUTPUT 0x01 | ||
27 | #define MAX7310_POLINV 0x02 | ||
28 | #define MAX7310_IODIR 0x03 /* 1 = Input, 0 = Output */ | ||
29 | #define MAX7310_TIMEOUT 0x04 | ||
30 | |||
31 | /* Addresses to scan */ | ||
32 | static unsigned short normal_i2c[] = { 0x18, I2C_CLIENT_END }; | ||
33 | |||
34 | /* I2C Magic */ | ||
35 | I2C_CLIENT_INSMOD; | ||
36 | |||
37 | static int max7310_write(struct i2c_client *client, int address, int data); | ||
38 | static struct i2c_client max7310_template; | ||
39 | static void akita_ioexp_work(void *private_); | ||
40 | |||
41 | static struct device *akita_ioexp_device; | ||
42 | static unsigned char ioexp_output_value = AKITA_IOEXP_IO_OUT; | ||
43 | DECLARE_WORK(akita_ioexp, akita_ioexp_work, NULL); | ||
44 | |||
45 | |||
46 | /* | ||
47 | * MAX7310 Access | ||
48 | */ | ||
49 | static int max7310_config(struct device *dev, int iomode, int polarity) | ||
50 | { | ||
51 | int ret; | ||
52 | struct i2c_client *client = to_i2c_client(dev); | ||
53 | |||
54 | ret = max7310_write(client, MAX7310_POLINV, polarity); | ||
55 | if (ret < 0) | ||
56 | return ret; | ||
57 | ret = max7310_write(client, MAX7310_IODIR, iomode); | ||
58 | return ret; | ||
59 | } | ||
60 | |||
61 | static int max7310_set_ouputs(struct device *dev, int outputs) | ||
62 | { | ||
63 | struct i2c_client *client = to_i2c_client(dev); | ||
64 | |||
65 | return max7310_write(client, MAX7310_OUTPUT, outputs); | ||
66 | } | ||
67 | |||
68 | /* | ||
69 | * I2C Functions | ||
70 | */ | ||
71 | static int max7310_write(struct i2c_client *client, int address, int value) | ||
72 | { | ||
73 | u8 data[2]; | ||
74 | |||
75 | data[0] = address & 0xff; | ||
76 | data[1] = value & 0xff; | ||
77 | |||
78 | if (i2c_master_send(client, data, 2) == 2) | ||
79 | return 0; | ||
80 | return -1; | ||
81 | } | ||
82 | |||
83 | static int max7310_detect(struct i2c_adapter *adapter, int address, int kind) | ||
84 | { | ||
85 | struct i2c_client *new_client; | ||
86 | int err; | ||
87 | |||
88 | if (!(new_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) | ||
89 | return -ENOMEM; | ||
90 | |||
91 | max7310_template.adapter = adapter; | ||
92 | max7310_template.addr = address; | ||
93 | |||
94 | memcpy(new_client, &max7310_template, sizeof(struct i2c_client)); | ||
95 | |||
96 | if ((err = i2c_attach_client(new_client))) { | ||
97 | kfree(new_client); | ||
98 | return err; | ||
99 | } | ||
100 | |||
101 | max7310_config(&new_client->dev, AKITA_IOEXP_IO_DIR, 0); | ||
102 | akita_ioexp_device = &new_client->dev; | ||
103 | schedule_work(&akita_ioexp); | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static int max7310_attach_adapter(struct i2c_adapter *adapter) | ||
109 | { | ||
110 | return i2c_probe(adapter, &addr_data, max7310_detect); | ||
111 | } | ||
112 | |||
113 | static int max7310_detach_client(struct i2c_client *client) | ||
114 | { | ||
115 | int err; | ||
116 | |||
117 | akita_ioexp_device = NULL; | ||
118 | |||
119 | if ((err = i2c_detach_client(client))) | ||
120 | return err; | ||
121 | |||
122 | kfree(client); | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | static struct i2c_driver max7310_i2c_driver = { | ||
127 | .owner = THIS_MODULE, | ||
128 | .name = "akita-max7310", | ||
129 | .id = I2C_DRIVERID_AKITAIOEXP, | ||
130 | .flags = I2C_DF_NOTIFY, | ||
131 | .attach_adapter = max7310_attach_adapter, | ||
132 | .detach_client = max7310_detach_client, | ||
133 | }; | ||
134 | |||
135 | static struct i2c_client max7310_template = { | ||
136 | name: "akita-max7310", | ||
137 | flags: I2C_CLIENT_ALLOW_USE, | ||
138 | driver: &max7310_i2c_driver, | ||
139 | }; | ||
140 | |||
141 | void akita_set_ioexp(struct device *dev, unsigned char bit) | ||
142 | { | ||
143 | ioexp_output_value |= bit; | ||
144 | |||
145 | if (akita_ioexp_device) | ||
146 | schedule_work(&akita_ioexp); | ||
147 | return; | ||
148 | } | ||
149 | |||
150 | void akita_reset_ioexp(struct device *dev, unsigned char bit) | ||
151 | { | ||
152 | ioexp_output_value &= ~bit; | ||
153 | |||
154 | if (akita_ioexp_device) | ||
155 | schedule_work(&akita_ioexp); | ||
156 | return; | ||
157 | } | ||
158 | |||
159 | EXPORT_SYMBOL(akita_set_ioexp); | ||
160 | EXPORT_SYMBOL(akita_reset_ioexp); | ||
161 | |||
162 | static void akita_ioexp_work(void *private_) | ||
163 | { | ||
164 | if (akita_ioexp_device) | ||
165 | max7310_set_ouputs(akita_ioexp_device, ioexp_output_value); | ||
166 | } | ||
167 | |||
168 | |||
169 | #ifdef CONFIG_PM | ||
170 | static int akita_ioexp_suspend(struct platform_device *pdev, pm_message_t state) | ||
171 | { | ||
172 | flush_scheduled_work(); | ||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static int akita_ioexp_resume(struct platform_device *pdev) | ||
177 | { | ||
178 | schedule_work(&akita_ioexp); | ||
179 | return 0; | ||
180 | } | ||
181 | #else | ||
182 | #define akita_ioexp_suspend NULL | ||
183 | #define akita_ioexp_resume NULL | ||
184 | #endif | ||
185 | |||
186 | static int __init akita_ioexp_probe(struct platform_device *pdev) | ||
187 | { | ||
188 | return i2c_add_driver(&max7310_i2c_driver); | ||
189 | } | ||
190 | |||
191 | static int akita_ioexp_remove(struct platform_device *pdev) | ||
192 | { | ||
193 | i2c_del_driver(&max7310_i2c_driver); | ||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | static struct platform_driver akita_ioexp_driver = { | ||
198 | .probe = akita_ioexp_probe, | ||
199 | .remove = akita_ioexp_remove, | ||
200 | .suspend = akita_ioexp_suspend, | ||
201 | .resume = akita_ioexp_resume, | ||
202 | .driver = { | ||
203 | .name = "akita-ioexp", | ||
204 | }, | ||
205 | }; | ||
206 | |||
207 | static int __init akita_ioexp_init(void) | ||
208 | { | ||
209 | return platform_driver_register(&akita_ioexp_driver); | ||
210 | } | ||
211 | |||
212 | static void __exit akita_ioexp_exit(void) | ||
213 | { | ||
214 | platform_driver_unregister(&akita_ioexp_driver); | ||
215 | } | ||
216 | |||
217 | MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>"); | ||
218 | MODULE_DESCRIPTION("Akita IO-Expander driver"); | ||
219 | MODULE_LICENSE("GPL"); | ||
220 | |||
221 | fs_initcall(akita_ioexp_init); | ||
222 | module_exit(akita_ioexp_exit); | ||
223 | |||
diff --git a/arch/arm/mach-pxa/corgi_pm.c b/arch/arm/mach-pxa/corgi_pm.c new file mode 100644 index 000000000000..599be14754f9 --- /dev/null +++ b/arch/arm/mach-pxa/corgi_pm.c | |||
@@ -0,0 +1,228 @@ | |||
1 | /* | ||
2 | * Battery and Power Management code for the Sharp SL-C7xx | ||
3 | * | ||
4 | * Copyright (c) 2005 Richard Purdie | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/stat.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <asm/apm.h> | ||
20 | #include <asm/irq.h> | ||
21 | #include <asm/mach-types.h> | ||
22 | #include <asm/hardware.h> | ||
23 | #include <asm/hardware/scoop.h> | ||
24 | |||
25 | #include <asm/arch/sharpsl.h> | ||
26 | #include <asm/arch/corgi.h> | ||
27 | #include <asm/arch/pxa-regs.h> | ||
28 | #include "sharpsl.h" | ||
29 | |||
30 | static void corgi_charger_init(void) | ||
31 | { | ||
32 | pxa_gpio_mode(CORGI_GPIO_ADC_TEMP_ON | GPIO_OUT); | ||
33 | pxa_gpio_mode(CORGI_GPIO_CHRG_ON | GPIO_OUT); | ||
34 | pxa_gpio_mode(CORGI_GPIO_CHRG_UKN | GPIO_OUT); | ||
35 | pxa_gpio_mode(CORGI_GPIO_KEY_INT | GPIO_IN); | ||
36 | } | ||
37 | |||
38 | static void corgi_charge_led(int val) | ||
39 | { | ||
40 | if (val == SHARPSL_LED_ERROR) { | ||
41 | dev_dbg(sharpsl_pm.dev, "Charge LED Error\n"); | ||
42 | } else if (val == SHARPSL_LED_ON) { | ||
43 | dev_dbg(sharpsl_pm.dev, "Charge LED On\n"); | ||
44 | GPSR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE); | ||
45 | } else { | ||
46 | dev_dbg(sharpsl_pm.dev, "Charge LED Off\n"); | ||
47 | GPCR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE); | ||
48 | } | ||
49 | } | ||
50 | |||
51 | static void corgi_measure_temp(int on) | ||
52 | { | ||
53 | if (on) | ||
54 | GPSR(CORGI_GPIO_ADC_TEMP_ON) = GPIO_bit(CORGI_GPIO_ADC_TEMP_ON); | ||
55 | else | ||
56 | GPCR(CORGI_GPIO_ADC_TEMP_ON) = GPIO_bit(CORGI_GPIO_ADC_TEMP_ON); | ||
57 | } | ||
58 | |||
59 | static void corgi_charge(int on) | ||
60 | { | ||
61 | if (on) { | ||
62 | if (machine_is_corgi() && (sharpsl_pm.flags & SHARPSL_SUSPENDED)) { | ||
63 | GPCR(CORGI_GPIO_CHRG_ON) = GPIO_bit(CORGI_GPIO_CHRG_ON); | ||
64 | GPSR(CORGI_GPIO_CHRG_UKN) = GPIO_bit(CORGI_GPIO_CHRG_UKN); | ||
65 | } else { | ||
66 | GPSR(CORGI_GPIO_CHRG_ON) = GPIO_bit(CORGI_GPIO_CHRG_ON); | ||
67 | GPCR(CORGI_GPIO_CHRG_UKN) = GPIO_bit(CORGI_GPIO_CHRG_UKN); | ||
68 | } | ||
69 | } else { | ||
70 | GPCR(CORGI_GPIO_CHRG_ON) = GPIO_bit(CORGI_GPIO_CHRG_ON); | ||
71 | GPCR(CORGI_GPIO_CHRG_UKN) = GPIO_bit(CORGI_GPIO_CHRG_UKN); | ||
72 | } | ||
73 | } | ||
74 | |||
75 | static void corgi_discharge(int on) | ||
76 | { | ||
77 | if (on) | ||
78 | GPSR(CORGI_GPIO_DISCHARGE_ON) = GPIO_bit(CORGI_GPIO_DISCHARGE_ON); | ||
79 | else | ||
80 | GPCR(CORGI_GPIO_DISCHARGE_ON) = GPIO_bit(CORGI_GPIO_DISCHARGE_ON); | ||
81 | } | ||
82 | |||
83 | static void corgi_presuspend(void) | ||
84 | { | ||
85 | int i; | ||
86 | unsigned long wakeup_mask; | ||
87 | |||
88 | /* charging , so CHARGE_ON bit is HIGH during OFF. */ | ||
89 | if (READ_GPIO_BIT(CORGI_GPIO_CHRG_ON)) | ||
90 | PGSR1 |= GPIO_bit(CORGI_GPIO_CHRG_ON); | ||
91 | else | ||
92 | PGSR1 &= ~GPIO_bit(CORGI_GPIO_CHRG_ON); | ||
93 | |||
94 | if (READ_GPIO_BIT(CORGI_GPIO_LED_ORANGE)) | ||
95 | PGSR0 |= GPIO_bit(CORGI_GPIO_LED_ORANGE); | ||
96 | else | ||
97 | PGSR0 &= ~GPIO_bit(CORGI_GPIO_LED_ORANGE); | ||
98 | |||
99 | if (READ_GPIO_BIT(CORGI_GPIO_CHRG_UKN)) | ||
100 | PGSR1 |= GPIO_bit(CORGI_GPIO_CHRG_UKN); | ||
101 | else | ||
102 | PGSR1 &= ~GPIO_bit(CORGI_GPIO_CHRG_UKN); | ||
103 | |||
104 | /* Resume on keyboard power key */ | ||
105 | PGSR2 = (PGSR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(0); | ||
106 | |||
107 | wakeup_mask = GPIO_bit(CORGI_GPIO_KEY_INT) | GPIO_bit(CORGI_GPIO_WAKEUP) | GPIO_bit(CORGI_GPIO_AC_IN) | GPIO_bit(CORGI_GPIO_CHRG_FULL); | ||
108 | |||
109 | if (!machine_is_corgi()) | ||
110 | wakeup_mask |= GPIO_bit(CORGI_GPIO_MAIN_BAT_LOW); | ||
111 | |||
112 | PWER = wakeup_mask | PWER_RTC; | ||
113 | PRER = wakeup_mask; | ||
114 | PFER = wakeup_mask; | ||
115 | |||
116 | for (i = 0; i <=15; i++) { | ||
117 | if (PRER & PFER & GPIO_bit(i)) { | ||
118 | if (GPLR0 & GPIO_bit(i) ) | ||
119 | PRER &= ~GPIO_bit(i); | ||
120 | else | ||
121 | PFER &= ~GPIO_bit(i); | ||
122 | } | ||
123 | } | ||
124 | } | ||
125 | |||
126 | static void corgi_postsuspend(void) | ||
127 | { | ||
128 | } | ||
129 | |||
130 | /* | ||
131 | * Check what brought us out of the suspend. | ||
132 | * Return: 0 to sleep, otherwise wake | ||
133 | */ | ||
134 | static int corgi_should_wakeup(unsigned int resume_on_alarm) | ||
135 | { | ||
136 | int is_resume = 0; | ||
137 | |||
138 | dev_dbg(sharpsl_pm.dev, "GPLR0 = %x,%x\n", GPLR0, PEDR); | ||
139 | |||
140 | if ((PEDR & GPIO_bit(CORGI_GPIO_AC_IN))) { | ||
141 | if (STATUS_AC_IN()) { | ||
142 | /* charge on */ | ||
143 | dev_dbg(sharpsl_pm.dev, "ac insert\n"); | ||
144 | sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG; | ||
145 | } else { | ||
146 | /* charge off */ | ||
147 | dev_dbg(sharpsl_pm.dev, "ac remove\n"); | ||
148 | CHARGE_LED_OFF(); | ||
149 | CHARGE_OFF(); | ||
150 | sharpsl_pm.charge_mode = CHRG_OFF; | ||
151 | } | ||
152 | } | ||
153 | |||
154 | if ((PEDR & GPIO_bit(CORGI_GPIO_CHRG_FULL))) | ||
155 | dev_dbg(sharpsl_pm.dev, "Charge full interrupt\n"); | ||
156 | |||
157 | if (PEDR & GPIO_bit(CORGI_GPIO_KEY_INT)) | ||
158 | is_resume |= GPIO_bit(CORGI_GPIO_KEY_INT); | ||
159 | |||
160 | if (PEDR & GPIO_bit(CORGI_GPIO_WAKEUP)) | ||
161 | is_resume |= GPIO_bit(CORGI_GPIO_WAKEUP); | ||
162 | |||
163 | if (resume_on_alarm && (PEDR & PWER_RTC)) | ||
164 | is_resume |= PWER_RTC; | ||
165 | |||
166 | dev_dbg(sharpsl_pm.dev, "is_resume: %x\n",is_resume); | ||
167 | return is_resume; | ||
168 | } | ||
169 | |||
170 | static unsigned long corgi_charger_wakeup(void) | ||
171 | { | ||
172 | return ~GPLR0 & ( GPIO_bit(CORGI_GPIO_AC_IN) | GPIO_bit(CORGI_GPIO_KEY_INT) | GPIO_bit(CORGI_GPIO_WAKEUP) ); | ||
173 | } | ||
174 | |||
175 | static int corgi_acin_status(void) | ||
176 | { | ||
177 | return ((GPLR(CORGI_GPIO_AC_IN) & GPIO_bit(CORGI_GPIO_AC_IN)) != 0); | ||
178 | } | ||
179 | |||
180 | static struct sharpsl_charger_machinfo corgi_pm_machinfo = { | ||
181 | .init = corgi_charger_init, | ||
182 | .gpio_batlock = CORGI_GPIO_BAT_COVER, | ||
183 | .gpio_acin = CORGI_GPIO_AC_IN, | ||
184 | .gpio_batfull = CORGI_GPIO_CHRG_FULL, | ||
185 | .status_acin = corgi_acin_status, | ||
186 | .discharge = corgi_discharge, | ||
187 | .charge = corgi_charge, | ||
188 | .chargeled = corgi_charge_led, | ||
189 | .measure_temp = corgi_measure_temp, | ||
190 | .presuspend = corgi_presuspend, | ||
191 | .postsuspend = corgi_postsuspend, | ||
192 | .charger_wakeup = corgi_charger_wakeup, | ||
193 | .should_wakeup = corgi_should_wakeup, | ||
194 | .bat_levels = 40, | ||
195 | .bat_levels_noac = spitz_battery_levels_noac, | ||
196 | .bat_levels_acin = spitz_battery_levels_acin, | ||
197 | .status_high_acin = 188, | ||
198 | .status_low_acin = 178, | ||
199 | .status_high_noac = 185, | ||
200 | .status_low_noac = 175, | ||
201 | }; | ||
202 | |||
203 | static struct platform_device *corgipm_device; | ||
204 | |||
205 | static int __devinit corgipm_init(void) | ||
206 | { | ||
207 | int ret; | ||
208 | |||
209 | corgipm_device = platform_device_alloc("sharpsl-pm", -1); | ||
210 | if (!corgipm_device) | ||
211 | return -ENOMEM; | ||
212 | |||
213 | corgipm_device->dev.platform_data = &corgi_pm_machinfo; | ||
214 | ret = platform_device_add(corgipm_device); | ||
215 | |||
216 | if (ret) | ||
217 | platform_device_put(corgipm_device); | ||
218 | |||
219 | return ret; | ||
220 | } | ||
221 | |||
222 | static void corgipm_exit(void) | ||
223 | { | ||
224 | platform_device_unregister(corgipm_device); | ||
225 | } | ||
226 | |||
227 | module_init(corgipm_init); | ||
228 | module_exit(corgipm_exit); | ||
diff --git a/arch/arm/mach-pxa/sharpsl.h b/arch/arm/mach-pxa/sharpsl.h index 4879c0f7da72..b0c40a1d6671 100644 --- a/arch/arm/mach-pxa/sharpsl.h +++ b/arch/arm/mach-pxa/sharpsl.h | |||
@@ -115,7 +115,7 @@ extern struct battery_thresh spitz_battery_levels_noac[]; | |||
115 | #define CHARGE_LED_ERR() sharpsl_pm.machinfo->chargeled(SHARPSL_LED_ERROR) | 115 | #define CHARGE_LED_ERR() sharpsl_pm.machinfo->chargeled(SHARPSL_LED_ERROR) |
116 | #define DISCHARGE_ON() sharpsl_pm.machinfo->discharge(1) | 116 | #define DISCHARGE_ON() sharpsl_pm.machinfo->discharge(1) |
117 | #define DISCHARGE_OFF() sharpsl_pm.machinfo->discharge(0) | 117 | #define DISCHARGE_OFF() sharpsl_pm.machinfo->discharge(0) |
118 | #define STATUS_AC_IN sharpsl_pm.machinfo->status_acin() | 118 | #define STATUS_AC_IN() sharpsl_pm.machinfo->status_acin() |
119 | #define STATUS_BATT_LOCKED READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_batlock) | 119 | #define STATUS_BATT_LOCKED() READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_batlock) |
120 | #define STATUS_CHRG_FULL READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_batfull) | 120 | #define STATUS_CHRG_FULL() READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_batfull) |
121 | #define STATUS_FATAL READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_fatal) | 121 | #define STATUS_FATAL() READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_fatal) |
diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c index 6c9e871c53d8..c10be00fb526 100644 --- a/arch/arm/mach-pxa/sharpsl_pm.c +++ b/arch/arm/mach-pxa/sharpsl_pm.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <linux/apm_bios.h> | 21 | #include <linux/apm_bios.h> |
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/device.h> | 24 | #include <linux/platform_device.h> |
25 | 25 | ||
26 | #include <asm/hardware.h> | 26 | #include <asm/hardware.h> |
27 | #include <asm/hardware/scoop.h> | 27 | #include <asm/hardware/scoop.h> |
@@ -45,15 +45,15 @@ | |||
45 | #define SHARPSL_WAIT_DISCHARGE_ON 100 /* 100 msec */ | 45 | #define SHARPSL_WAIT_DISCHARGE_ON 100 /* 100 msec */ |
46 | #define SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP 10 /* 10 msec */ | 46 | #define SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP 10 /* 10 msec */ |
47 | #define SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT 10 /* 10 msec */ | 47 | #define SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT 10 /* 10 msec */ |
48 | #define SHARPSL_CHECK_BATTERY_WAIT_TIME_JKVAD 10 /* 10 msec */ | 48 | #define SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN 10 /* 10 msec */ |
49 | #define SHARPSL_CHARGE_WAIT_TIME 15 /* 15 msec */ | 49 | #define SHARPSL_CHARGE_WAIT_TIME 15 /* 15 msec */ |
50 | #define SHARPSL_CHARGE_CO_CHECK_TIME 5 /* 5 msec */ | 50 | #define SHARPSL_CHARGE_CO_CHECK_TIME 5 /* 5 msec */ |
51 | #define SHARPSL_CHARGE_RETRY_CNT 1 /* eqv. 10 min */ | 51 | #define SHARPSL_CHARGE_RETRY_CNT 1 /* eqv. 10 min */ |
52 | 52 | ||
53 | #define SHARPSL_CHARGE_ON_VOLT 0x99 /* 2.9V */ | 53 | #define SHARPSL_CHARGE_ON_VOLT 0x99 /* 2.9V */ |
54 | #define SHARPSL_CHARGE_ON_TEMP 0xe0 /* 2.9V */ | 54 | #define SHARPSL_CHARGE_ON_TEMP 0xe0 /* 2.9V */ |
55 | #define SHARPSL_CHARGE_ON_JKVAD_HIGH 0x9b /* 6V */ | 55 | #define SHARPSL_CHARGE_ON_ACIN_HIGH 0x9b /* 6V */ |
56 | #define SHARPSL_CHARGE_ON_JKVAD_LOW 0x34 /* 2V */ | 56 | #define SHARPSL_CHARGE_ON_ACIN_LOW 0x34 /* 2V */ |
57 | #define SHARPSL_FATAL_ACIN_VOLT 182 /* 3.45V */ | 57 | #define SHARPSL_FATAL_ACIN_VOLT 182 /* 3.45V */ |
58 | #define SHARPSL_FATAL_NOACIN_VOLT 170 /* 3.40V */ | 58 | #define SHARPSL_FATAL_NOACIN_VOLT 170 /* 3.40V */ |
59 | 59 | ||
@@ -160,9 +160,10 @@ struct battery_thresh spitz_battery_levels_noac[] = { | |||
160 | /* | 160 | /* |
161 | * Prototypes | 161 | * Prototypes |
162 | */ | 162 | */ |
163 | static int sharpsl_read_MainBattery(void); | 163 | static int sharpsl_read_main_battery(void); |
164 | static int sharpsl_off_charge_battery(void); | 164 | static int sharpsl_off_charge_battery(void); |
165 | static int sharpsl_check_battery(int mode); | 165 | static int sharpsl_check_battery_temp(void); |
166 | static int sharpsl_check_battery_voltage(void); | ||
166 | static int sharpsl_ac_check(void); | 167 | static int sharpsl_ac_check(void); |
167 | static int sharpsl_fatal_check(void); | 168 | static int sharpsl_fatal_check(void); |
168 | static int sharpsl_average_value(int ad); | 169 | static int sharpsl_average_value(int ad); |
@@ -228,7 +229,7 @@ static void sharpsl_battery_thread(void *private_) | |||
228 | if (!sharpsl_pm.machinfo) | 229 | if (!sharpsl_pm.machinfo) |
229 | return; | 230 | return; |
230 | 231 | ||
231 | sharpsl_pm.battstat.ac_status = (!(STATUS_AC_IN) ? APM_AC_OFFLINE : APM_AC_ONLINE); | 232 | sharpsl_pm.battstat.ac_status = (STATUS_AC_IN() ? APM_AC_ONLINE : APM_AC_OFFLINE); |
232 | 233 | ||
233 | /* Corgi cannot confirm when battery fully charged so periodically kick! */ | 234 | /* Corgi cannot confirm when battery fully charged so periodically kick! */ |
234 | if (machine_is_corgi() && (sharpsl_pm.charge_mode == CHRG_ON) | 235 | if (machine_is_corgi() && (sharpsl_pm.charge_mode == CHRG_ON) |
@@ -236,7 +237,7 @@ static void sharpsl_battery_thread(void *private_) | |||
236 | schedule_work(&toggle_charger); | 237 | schedule_work(&toggle_charger); |
237 | 238 | ||
238 | while(1) { | 239 | while(1) { |
239 | voltage = sharpsl_read_MainBattery(); | 240 | voltage = sharpsl_read_main_battery(); |
240 | if (voltage > 0) break; | 241 | if (voltage > 0) break; |
241 | if (i++ > 5) { | 242 | if (i++ > 5) { |
242 | voltage = sharpsl_pm.machinfo->bat_levels_noac[0].voltage; | 243 | voltage = sharpsl_pm.machinfo->bat_levels_noac[0].voltage; |
@@ -317,10 +318,10 @@ static void sharpsl_charge_toggle(void *private_) | |||
317 | { | 318 | { |
318 | dev_dbg(sharpsl_pm.dev, "Toogling Charger at time: %lx\n", jiffies); | 319 | dev_dbg(sharpsl_pm.dev, "Toogling Charger at time: %lx\n", jiffies); |
319 | 320 | ||
320 | if (STATUS_AC_IN == 0) { | 321 | if (STATUS_AC_IN() == 0) { |
321 | sharpsl_charge_off(); | 322 | sharpsl_charge_off(); |
322 | return; | 323 | return; |
323 | } else if ((sharpsl_check_battery(1) < 0) || (sharpsl_ac_check() < 0)) { | 324 | } else if ((sharpsl_check_battery_temp() < 0) || (sharpsl_ac_check() < 0)) { |
324 | sharpsl_charge_error(); | 325 | sharpsl_charge_error(); |
325 | return; | 326 | return; |
326 | } | 327 | } |
@@ -335,7 +336,7 @@ static void sharpsl_charge_toggle(void *private_) | |||
335 | 336 | ||
336 | static void sharpsl_ac_timer(unsigned long data) | 337 | static void sharpsl_ac_timer(unsigned long data) |
337 | { | 338 | { |
338 | int acin = STATUS_AC_IN; | 339 | int acin = STATUS_AC_IN(); |
339 | 340 | ||
340 | dev_dbg(sharpsl_pm.dev, "AC Status: %d\n",acin); | 341 | dev_dbg(sharpsl_pm.dev, "AC Status: %d\n",acin); |
341 | 342 | ||
@@ -364,7 +365,7 @@ static void sharpsl_chrg_full_timer(unsigned long data) | |||
364 | 365 | ||
365 | sharpsl_pm.full_count++; | 366 | sharpsl_pm.full_count++; |
366 | 367 | ||
367 | if (STATUS_AC_IN == 0) { | 368 | if (STATUS_AC_IN() == 0) { |
368 | dev_dbg(sharpsl_pm.dev, "Charge Full: AC removed - stop charging!\n"); | 369 | dev_dbg(sharpsl_pm.dev, "Charge Full: AC removed - stop charging!\n"); |
369 | if (sharpsl_pm.charge_mode == CHRG_ON) | 370 | if (sharpsl_pm.charge_mode == CHRG_ON) |
370 | sharpsl_charge_off(); | 371 | sharpsl_charge_off(); |
@@ -399,12 +400,12 @@ static irqreturn_t sharpsl_fatal_isr(int irq, void *dev_id, struct pt_regs *fp) | |||
399 | { | 400 | { |
400 | int is_fatal = 0; | 401 | int is_fatal = 0; |
401 | 402 | ||
402 | if (STATUS_BATT_LOCKED == 0) { | 403 | if (STATUS_BATT_LOCKED() == 0) { |
403 | dev_err(sharpsl_pm.dev, "Battery now Unlocked! Suspending.\n"); | 404 | dev_err(sharpsl_pm.dev, "Battery now Unlocked! Suspending.\n"); |
404 | is_fatal = 1; | 405 | is_fatal = 1; |
405 | } | 406 | } |
406 | 407 | ||
407 | if (sharpsl_pm.machinfo->gpio_fatal && (STATUS_FATAL == 0)) { | 408 | if (sharpsl_pm.machinfo->gpio_fatal && (STATUS_FATAL() == 0)) { |
408 | dev_err(sharpsl_pm.dev, "Fatal Batt Error! Suspending.\n"); | 409 | dev_err(sharpsl_pm.dev, "Fatal Batt Error! Suspending.\n"); |
409 | is_fatal = 1; | 410 | is_fatal = 1; |
410 | } | 411 | } |
@@ -461,12 +462,12 @@ static int read_max1111(int channel) | |||
461 | | MAXCTRL_SGL | MAXCTRL_UNI | MAXCTRL_STR); | 462 | | MAXCTRL_SGL | MAXCTRL_UNI | MAXCTRL_STR); |
462 | } | 463 | } |
463 | 464 | ||
464 | static int sharpsl_read_MainBattery(void) | 465 | static int sharpsl_read_main_battery(void) |
465 | { | 466 | { |
466 | return read_max1111(BATT_AD); | 467 | return read_max1111(BATT_AD); |
467 | } | 468 | } |
468 | 469 | ||
469 | static int sharpsl_read_Temp(void) | 470 | static int sharpsl_read_temp(void) |
470 | { | 471 | { |
471 | int temp; | 472 | int temp; |
472 | 473 | ||
@@ -480,7 +481,7 @@ static int sharpsl_read_Temp(void) | |||
480 | return temp; | 481 | return temp; |
481 | } | 482 | } |
482 | 483 | ||
483 | static int sharpsl_read_jkvad(void) | 484 | static int sharpsl_read_acin(void) |
484 | { | 485 | { |
485 | return read_max1111(JK_VAD); | 486 | return read_max1111(JK_VAD); |
486 | } | 487 | } |
@@ -522,16 +523,14 @@ static int get_select_val(int *val) | |||
522 | return (sum/3); | 523 | return (sum/3); |
523 | } | 524 | } |
524 | 525 | ||
525 | /* mode 0 - Check temperature and voltage | 526 | static int sharpsl_check_battery_temp(void) |
526 | * 1 - Check temperature only */ | ||
527 | static int sharpsl_check_battery(int mode) | ||
528 | { | 527 | { |
529 | int val, i, buff[5]; | 528 | int val, i, buff[5]; |
530 | 529 | ||
531 | /* Check battery temperature */ | 530 | /* Check battery temperature */ |
532 | for (i=0; i<5; i++) { | 531 | for (i=0; i<5; i++) { |
533 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP); | 532 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP); |
534 | buff[i] = sharpsl_read_Temp(); | 533 | buff[i] = sharpsl_read_temp(); |
535 | } | 534 | } |
536 | 535 | ||
537 | val = get_select_val(buff); | 536 | val = get_select_val(buff); |
@@ -539,8 +538,13 @@ static int sharpsl_check_battery(int mode) | |||
539 | dev_dbg(sharpsl_pm.dev, "Temperature: %d\n", val); | 538 | dev_dbg(sharpsl_pm.dev, "Temperature: %d\n", val); |
540 | if (val > SHARPSL_CHARGE_ON_TEMP) | 539 | if (val > SHARPSL_CHARGE_ON_TEMP) |
541 | return -1; | 540 | return -1; |
542 | if (mode == 1) | 541 | |
543 | return 0; | 542 | return 0; |
543 | } | ||
544 | |||
545 | static int sharpsl_check_battery_voltage(void) | ||
546 | { | ||
547 | int val, i, buff[5]; | ||
544 | 548 | ||
545 | /* disable charge, enable discharge */ | 549 | /* disable charge, enable discharge */ |
546 | CHARGE_OFF(); | 550 | CHARGE_OFF(); |
@@ -552,7 +556,7 @@ static int sharpsl_check_battery(int mode) | |||
552 | 556 | ||
553 | /* Check battery voltage */ | 557 | /* Check battery voltage */ |
554 | for (i=0; i<5; i++) { | 558 | for (i=0; i<5; i++) { |
555 | buff[i] = sharpsl_read_MainBattery(); | 559 | buff[i] = sharpsl_read_main_battery(); |
556 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT); | 560 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT); |
557 | } | 561 | } |
558 | 562 | ||
@@ -575,14 +579,14 @@ static int sharpsl_ac_check(void) | |||
575 | int temp, i, buff[5]; | 579 | int temp, i, buff[5]; |
576 | 580 | ||
577 | for (i=0; i<5; i++) { | 581 | for (i=0; i<5; i++) { |
578 | buff[i] = sharpsl_read_jkvad(); | 582 | buff[i] = sharpsl_read_acin(); |
579 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_JKVAD); | 583 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN); |
580 | } | 584 | } |
581 | 585 | ||
582 | temp = get_select_val(buff); | 586 | temp = get_select_val(buff); |
583 | dev_dbg(sharpsl_pm.dev, "AC Voltage: %d\n",temp); | 587 | dev_dbg(sharpsl_pm.dev, "AC Voltage: %d\n",temp); |
584 | 588 | ||
585 | if ((temp > SHARPSL_CHARGE_ON_JKVAD_HIGH) || (temp < SHARPSL_CHARGE_ON_JKVAD_LOW)) { | 589 | if ((temp > SHARPSL_CHARGE_ON_ACIN_HIGH) || (temp < SHARPSL_CHARGE_ON_ACIN_LOW)) { |
586 | dev_err(sharpsl_pm.dev, "Error: AC check failed.\n"); | 590 | dev_err(sharpsl_pm.dev, "Error: AC check failed.\n"); |
587 | return -1; | 591 | return -1; |
588 | } | 592 | } |
@@ -591,7 +595,7 @@ static int sharpsl_ac_check(void) | |||
591 | } | 595 | } |
592 | 596 | ||
593 | #ifdef CONFIG_PM | 597 | #ifdef CONFIG_PM |
594 | static int sharpsl_pm_suspend(struct device *dev, pm_message_t state) | 598 | static int sharpsl_pm_suspend(struct platform_device *pdev, pm_message_t state) |
595 | { | 599 | { |
596 | sharpsl_pm.flags |= SHARPSL_SUSPENDED; | 600 | sharpsl_pm.flags |= SHARPSL_SUSPENDED; |
597 | flush_scheduled_work(); | 601 | flush_scheduled_work(); |
@@ -604,7 +608,7 @@ static int sharpsl_pm_suspend(struct device *dev, pm_message_t state) | |||
604 | return 0; | 608 | return 0; |
605 | } | 609 | } |
606 | 610 | ||
607 | static int sharpsl_pm_resume(struct device *dev) | 611 | static int sharpsl_pm_resume(struct platform_device *pdev) |
608 | { | 612 | { |
609 | /* Clear the reset source indicators as they break the bootloader upon reboot */ | 613 | /* Clear the reset source indicators as they break the bootloader upon reboot */ |
610 | RCSR = 0x0f; | 614 | RCSR = 0x0f; |
@@ -622,7 +626,7 @@ static void corgi_goto_sleep(unsigned long alarm_time, unsigned int alarm_enable | |||
622 | dev_dbg(sharpsl_pm.dev, "Offline Charge Activate = %d\n",sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG); | 626 | dev_dbg(sharpsl_pm.dev, "Offline Charge Activate = %d\n",sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG); |
623 | /* not charging and AC-IN! */ | 627 | /* not charging and AC-IN! */ |
624 | 628 | ||
625 | if ((sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG) && (STATUS_AC_IN != 0)) { | 629 | if ((sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG) && (STATUS_AC_IN() != 0)) { |
626 | dev_dbg(sharpsl_pm.dev, "Activating Offline Charger...\n"); | 630 | dev_dbg(sharpsl_pm.dev, "Activating Offline Charger...\n"); |
627 | sharpsl_pm.charge_mode = CHRG_OFF; | 631 | sharpsl_pm.charge_mode = CHRG_OFF; |
628 | sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG; | 632 | sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG; |
@@ -671,7 +675,7 @@ static int corgi_enter_suspend(unsigned long alarm_time, unsigned int alarm_enab | |||
671 | dev_dbg(sharpsl_pm.dev, "User triggered wakeup in offline charger.\n"); | 675 | dev_dbg(sharpsl_pm.dev, "User triggered wakeup in offline charger.\n"); |
672 | } | 676 | } |
673 | 677 | ||
674 | if ((STATUS_BATT_LOCKED == 0) || (sharpsl_fatal_check() < 0) ) | 678 | if ((STATUS_BATT_LOCKED() == 0) || (sharpsl_fatal_check() < 0) ) |
675 | { | 679 | { |
676 | dev_err(sharpsl_pm.dev, "Fatal condition. Suspend.\n"); | 680 | dev_err(sharpsl_pm.dev, "Fatal condition. Suspend.\n"); |
677 | corgi_goto_sleep(alarm_time, alarm_enable, state); | 681 | corgi_goto_sleep(alarm_time, alarm_enable, state); |
@@ -711,7 +715,7 @@ static int sharpsl_fatal_check(void) | |||
711 | dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check entered\n"); | 715 | dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check entered\n"); |
712 | 716 | ||
713 | /* Check AC-Adapter */ | 717 | /* Check AC-Adapter */ |
714 | acin = STATUS_AC_IN; | 718 | acin = STATUS_AC_IN(); |
715 | 719 | ||
716 | if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) { | 720 | if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) { |
717 | CHARGE_OFF(); | 721 | CHARGE_OFF(); |
@@ -725,7 +729,7 @@ static int sharpsl_fatal_check(void) | |||
725 | 729 | ||
726 | /* Check battery : check inserting battery ? */ | 730 | /* Check battery : check inserting battery ? */ |
727 | for (i=0; i<5; i++) { | 731 | for (i=0; i<5; i++) { |
728 | buff[i] = sharpsl_read_MainBattery(); | 732 | buff[i] = sharpsl_read_main_battery(); |
729 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT); | 733 | mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT); |
730 | } | 734 | } |
731 | 735 | ||
@@ -739,7 +743,7 @@ static int sharpsl_fatal_check(void) | |||
739 | } | 743 | } |
740 | 744 | ||
741 | temp = get_select_val(buff); | 745 | temp = get_select_val(buff); |
742 | dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check: acin: %d, discharge voltage: %d, no discharge: %d\n", acin, temp, sharpsl_read_MainBattery()); | 746 | dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check: acin: %d, discharge voltage: %d, no discharge: %d\n", acin, temp, sharpsl_read_main_battery()); |
743 | 747 | ||
744 | if ((acin && (temp < SHARPSL_FATAL_ACIN_VOLT)) || | 748 | if ((acin && (temp < SHARPSL_FATAL_ACIN_VOLT)) || |
745 | (!acin && (temp < SHARPSL_FATAL_NOACIN_VOLT))) | 749 | (!acin && (temp < SHARPSL_FATAL_NOACIN_VOLT))) |
@@ -771,7 +775,7 @@ static int sharpsl_off_charge_battery(void) | |||
771 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 1\n"); | 775 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 1\n"); |
772 | 776 | ||
773 | /* AC Check */ | 777 | /* AC Check */ |
774 | if ((sharpsl_ac_check() < 0) || (sharpsl_check_battery(1) < 0)) | 778 | if ((sharpsl_ac_check() < 0) || (sharpsl_check_battery_temp() < 0)) |
775 | return sharpsl_off_charge_error(); | 779 | return sharpsl_off_charge_error(); |
776 | 780 | ||
777 | /* Start Charging */ | 781 | /* Start Charging */ |
@@ -793,7 +797,7 @@ static int sharpsl_off_charge_battery(void) | |||
793 | 797 | ||
794 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 2\n"); | 798 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 2\n"); |
795 | 799 | ||
796 | if (sharpsl_check_battery(0) < 0) | 800 | if ((sharpsl_check_battery_temp() < 0) || (sharpsl_check_battery_voltage() < 0)) |
797 | return sharpsl_off_charge_error(); | 801 | return sharpsl_off_charge_error(); |
798 | 802 | ||
799 | CHARGE_OFF(); | 803 | CHARGE_OFF(); |
@@ -811,7 +815,7 @@ static int sharpsl_off_charge_battery(void) | |||
811 | /* Check for timeout */ | 815 | /* Check for timeout */ |
812 | if ((RCNR - time) > SHARPSL_WAIT_CO_TIME) | 816 | if ((RCNR - time) > SHARPSL_WAIT_CO_TIME) |
813 | return 1; | 817 | return 1; |
814 | if (STATUS_CHRG_FULL) { | 818 | if (STATUS_CHRG_FULL()) { |
815 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Charge full occured. Retrying to check\n"); | 819 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Charge full occured. Retrying to check\n"); |
816 | sharpsl_pm.full_count++; | 820 | sharpsl_pm.full_count++; |
817 | CHARGE_OFF(); | 821 | CHARGE_OFF(); |
@@ -840,7 +844,7 @@ static int sharpsl_off_charge_battery(void) | |||
840 | sharpsl_pm.full_count++; | 844 | sharpsl_pm.full_count++; |
841 | return 1; | 845 | return 1; |
842 | } | 846 | } |
843 | if (STATUS_CHRG_FULL) { | 847 | if (STATUS_CHRG_FULL()) { |
844 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Charging complete.\n"); | 848 | dev_dbg(sharpsl_pm.dev, "Offline Charger: Charging complete.\n"); |
845 | CHARGE_LED_OFF(); | 849 | CHARGE_LED_OFF(); |
846 | CHARGE_OFF(); | 850 | CHARGE_OFF(); |
@@ -886,13 +890,13 @@ static struct pm_ops sharpsl_pm_ops = { | |||
886 | .finish = pxa_pm_finish, | 890 | .finish = pxa_pm_finish, |
887 | }; | 891 | }; |
888 | 892 | ||
889 | static int __init sharpsl_pm_probe(struct device *dev) | 893 | static int __init sharpsl_pm_probe(struct platform_device *pdev) |
890 | { | 894 | { |
891 | if (!dev->platform_data) | 895 | if (!pdev->dev.platform_data) |
892 | return -EINVAL; | 896 | return -EINVAL; |
893 | 897 | ||
894 | sharpsl_pm.dev = dev; | 898 | sharpsl_pm.dev = &pdev->dev; |
895 | sharpsl_pm.machinfo = dev->platform_data; | 899 | sharpsl_pm.machinfo = pdev->dev.platform_data; |
896 | sharpsl_pm.charge_mode = CHRG_OFF; | 900 | sharpsl_pm.charge_mode = CHRG_OFF; |
897 | sharpsl_pm.flags = 0; | 901 | sharpsl_pm.flags = 0; |
898 | 902 | ||
@@ -935,8 +939,8 @@ static int __init sharpsl_pm_probe(struct device *dev) | |||
935 | else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull),IRQT_RISING); | 939 | else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull),IRQT_RISING); |
936 | } | 940 | } |
937 | 941 | ||
938 | device_create_file(dev, &dev_attr_battery_percentage); | 942 | device_create_file(&pdev->dev, &dev_attr_battery_percentage); |
939 | device_create_file(dev, &dev_attr_battery_voltage); | 943 | device_create_file(&pdev->dev, &dev_attr_battery_voltage); |
940 | 944 | ||
941 | apm_get_power_status = sharpsl_apm_get_power_status; | 945 | apm_get_power_status = sharpsl_apm_get_power_status; |
942 | 946 | ||
@@ -947,12 +951,12 @@ static int __init sharpsl_pm_probe(struct device *dev) | |||
947 | return 0; | 951 | return 0; |
948 | } | 952 | } |
949 | 953 | ||
950 | static int sharpsl_pm_remove(struct device *dev) | 954 | static int sharpsl_pm_remove(struct platform_device *pdev) |
951 | { | 955 | { |
952 | pm_set_ops(NULL); | 956 | pm_set_ops(NULL); |
953 | 957 | ||
954 | device_remove_file(dev, &dev_attr_battery_percentage); | 958 | device_remove_file(&pdev->dev, &dev_attr_battery_percentage); |
955 | device_remove_file(dev, &dev_attr_battery_voltage); | 959 | device_remove_file(&pdev->dev, &dev_attr_battery_voltage); |
956 | 960 | ||
957 | free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr); | 961 | free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr); |
958 | free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr); | 962 | free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr); |
@@ -969,23 +973,24 @@ static int sharpsl_pm_remove(struct device *dev) | |||
969 | return 0; | 973 | return 0; |
970 | } | 974 | } |
971 | 975 | ||
972 | static struct device_driver sharpsl_pm_driver = { | 976 | static struct platform_driver sharpsl_pm_driver = { |
973 | .name = "sharpsl-pm", | ||
974 | .bus = &platform_bus_type, | ||
975 | .probe = sharpsl_pm_probe, | 977 | .probe = sharpsl_pm_probe, |
976 | .remove = sharpsl_pm_remove, | 978 | .remove = sharpsl_pm_remove, |
977 | .suspend = sharpsl_pm_suspend, | 979 | .suspend = sharpsl_pm_suspend, |
978 | .resume = sharpsl_pm_resume, | 980 | .resume = sharpsl_pm_resume, |
981 | .driver = { | ||
982 | .name = "sharpsl-pm", | ||
983 | }, | ||
979 | }; | 984 | }; |
980 | 985 | ||
981 | static int __devinit sharpsl_pm_init(void) | 986 | static int __devinit sharpsl_pm_init(void) |
982 | { | 987 | { |
983 | return driver_register(&sharpsl_pm_driver); | 988 | return platform_driver_register(&sharpsl_pm_driver); |
984 | } | 989 | } |
985 | 990 | ||
986 | static void sharpsl_pm_exit(void) | 991 | static void sharpsl_pm_exit(void) |
987 | { | 992 | { |
988 | driver_unregister(&sharpsl_pm_driver); | 993 | platform_driver_unregister(&sharpsl_pm_driver); |
989 | } | 994 | } |
990 | 995 | ||
991 | late_initcall(sharpsl_pm_init); | 996 | late_initcall(sharpsl_pm_init); |
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 4e9a699ee428..2df1b56615b1 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c | |||
@@ -345,6 +345,16 @@ static void spitz_irda_transceiver_mode(struct device *dev, int mode) | |||
345 | reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_IR_ON); | 345 | reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_IR_ON); |
346 | } | 346 | } |
347 | 347 | ||
348 | #ifdef CONFIG_MACH_AKITA | ||
349 | static void akita_irda_transceiver_mode(struct device *dev, int mode) | ||
350 | { | ||
351 | if (mode & IR_OFF) | ||
352 | akita_set_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_IR_ON); | ||
353 | else | ||
354 | akita_reset_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_IR_ON); | ||
355 | } | ||
356 | #endif | ||
357 | |||
348 | static struct pxaficp_platform_data spitz_ficp_platform_data = { | 358 | static struct pxaficp_platform_data spitz_ficp_platform_data = { |
349 | .transceiver_cap = IR_SIRMODE | IR_OFF, | 359 | .transceiver_cap = IR_SIRMODE | IR_OFF, |
350 | .transceiver_mode = spitz_irda_transceiver_mode, | 360 | .transceiver_mode = spitz_irda_transceiver_mode, |
@@ -417,6 +427,32 @@ static void __init spitz_init(void) | |||
417 | platform_device_register(&spitzscoop2_device); | 427 | platform_device_register(&spitzscoop2_device); |
418 | } | 428 | } |
419 | 429 | ||
430 | #ifdef CONFIG_MACH_AKITA | ||
431 | /* | ||
432 | * Akita IO Expander | ||
433 | */ | ||
434 | struct platform_device akitaioexp_device = { | ||
435 | .name = "akita-ioexp", | ||
436 | .id = -1, | ||
437 | }; | ||
438 | |||
439 | static void __init akita_init(void) | ||
440 | { | ||
441 | spitz_ficp_platform_data.transceiver_mode = akita_irda_transceiver_mode; | ||
442 | |||
443 | /* We just pretend the second element of the array doesn't exist */ | ||
444 | spitz_pcmcia_config.num_devs = 1; | ||
445 | platform_scoop_config = &spitz_pcmcia_config; | ||
446 | spitz_bl_machinfo.set_bl_intensity = akita_bl_set_intensity; | ||
447 | |||
448 | platform_device_register(&akitaioexp_device); | ||
449 | |||
450 | spitzscoop_device.dev.parent = &akitaioexp_device.dev; | ||
451 | common_init(); | ||
452 | } | ||
453 | #endif | ||
454 | |||
455 | |||
420 | static void __init fixup_spitz(struct machine_desc *desc, | 456 | static void __init fixup_spitz(struct machine_desc *desc, |
421 | struct tag *tags, char **cmdline, struct meminfo *mi) | 457 | struct tag *tags, char **cmdline, struct meminfo *mi) |
422 | { | 458 | { |
@@ -452,3 +488,16 @@ MACHINE_START(BORZOI, "SHARP Borzoi") | |||
452 | .timer = &pxa_timer, | 488 | .timer = &pxa_timer, |
453 | MACHINE_END | 489 | MACHINE_END |
454 | #endif | 490 | #endif |
491 | |||
492 | #ifdef CONFIG_MACH_AKITA | ||
493 | MACHINE_START(AKITA, "SHARP Akita") | ||
494 | .phys_ram = 0xa0000000, | ||
495 | .phys_io = 0x40000000, | ||
496 | .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, | ||
497 | .fixup = fixup_spitz, | ||
498 | .map_io = pxa_map_io, | ||
499 | .init_irq = pxa_init_irq, | ||
500 | .init_machine = akita_init, | ||
501 | .timer = &pxa_timer, | ||
502 | MACHINE_END | ||
503 | #endif | ||
diff --git a/arch/arm/mach-pxa/spitz_pm.c b/arch/arm/mach-pxa/spitz_pm.c new file mode 100644 index 000000000000..3ce7486daa51 --- /dev/null +++ b/arch/arm/mach-pxa/spitz_pm.c | |||
@@ -0,0 +1,233 @@ | |||
1 | /* | ||
2 | * Battery and Power Management code for the Sharp SL-Cxx00 | ||
3 | * | ||
4 | * Copyright (c) 2005 Richard Purdie | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/stat.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <asm/apm.h> | ||
20 | #include <asm/irq.h> | ||
21 | #include <asm/mach-types.h> | ||
22 | #include <asm/hardware.h> | ||
23 | #include <asm/hardware/scoop.h> | ||
24 | |||
25 | #include <asm/arch/sharpsl.h> | ||
26 | #include <asm/arch/spitz.h> | ||
27 | #include <asm/arch/pxa-regs.h> | ||
28 | #include "sharpsl.h" | ||
29 | |||
30 | static int spitz_last_ac_status; | ||
31 | |||
32 | static void spitz_charger_init(void) | ||
33 | { | ||
34 | pxa_gpio_mode(SPITZ_GPIO_KEY_INT | GPIO_IN); | ||
35 | pxa_gpio_mode(SPITZ_GPIO_SYNC | GPIO_IN); | ||
36 | } | ||
37 | |||
38 | static void spitz_charge_led(int val) | ||
39 | { | ||
40 | if (val == SHARPSL_LED_ERROR) { | ||
41 | dev_dbg(sharpsl_pm.dev, "Charge LED Error\n"); | ||
42 | } else if (val == SHARPSL_LED_ON) { | ||
43 | dev_dbg(sharpsl_pm.dev, "Charge LED On\n"); | ||
44 | set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE); | ||
45 | } else { | ||
46 | dev_dbg(sharpsl_pm.dev, "Charge LED Off\n"); | ||
47 | reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE); | ||
48 | } | ||
49 | } | ||
50 | |||
51 | static void spitz_measure_temp(int on) | ||
52 | { | ||
53 | if (on) | ||
54 | set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_ADC_TEMP_ON); | ||
55 | else | ||
56 | reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_ADC_TEMP_ON); | ||
57 | } | ||
58 | |||
59 | static void spitz_charge(int on) | ||
60 | { | ||
61 | if (on) { | ||
62 | if (sharpsl_pm.flags & SHARPSL_SUSPENDED) { | ||
63 | set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_JK_B); | ||
64 | reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_CHRG_ON); | ||
65 | } else { | ||
66 | reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_JK_B); | ||
67 | reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_CHRG_ON); | ||
68 | } | ||
69 | } else { | ||
70 | reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_JK_B); | ||
71 | set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_CHRG_ON); | ||
72 | } | ||
73 | } | ||
74 | |||
75 | static void spitz_discharge(int on) | ||
76 | { | ||
77 | if (on) | ||
78 | set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_JK_A); | ||
79 | else | ||
80 | reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_JK_A); | ||
81 | } | ||
82 | |||
83 | /* HACK - For unknown reasons, accurate voltage readings are only made with a load | ||
84 | on the power bus which the green led on spitz provides */ | ||
85 | static void spitz_discharge1(int on) | ||
86 | { | ||
87 | if (on) | ||
88 | set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN); | ||
89 | else | ||
90 | reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN); | ||
91 | } | ||
92 | |||
93 | static void spitz_presuspend(void) | ||
94 | { | ||
95 | spitz_last_ac_status = STATUS_AC_IN(); | ||
96 | |||
97 | /* GPIO Sleep Register */ | ||
98 | PGSR0 = 0x00144018; | ||
99 | PGSR1 = 0x00EF0000; | ||
100 | if (machine_is_akita()) { | ||
101 | PGSR2 = 0x2121C000; | ||
102 | PGSR3 = 0x00600400; | ||
103 | } else { | ||
104 | PGSR2 = 0x0121C000; | ||
105 | PGSR3 = 0x00600000; | ||
106 | } | ||
107 | |||
108 | PGSR0 &= ~SPITZ_GPIO_G0_STROBE_BIT; | ||
109 | PGSR1 &= ~SPITZ_GPIO_G1_STROBE_BIT; | ||
110 | PGSR2 &= ~SPITZ_GPIO_G2_STROBE_BIT; | ||
111 | PGSR3 &= ~SPITZ_GPIO_G3_STROBE_BIT; | ||
112 | PGSR2 |= GPIO_bit(SPITZ_GPIO_KEY_STROBE0); | ||
113 | |||
114 | pxa_gpio_mode(GPIO18_RDY|GPIO_OUT | GPIO_DFLT_HIGH); | ||
115 | |||
116 | PRER = GPIO_bit(SPITZ_GPIO_KEY_INT); | ||
117 | PFER = GPIO_bit(SPITZ_GPIO_KEY_INT) | GPIO_bit(SPITZ_GPIO_RESET); | ||
118 | PWER = GPIO_bit(SPITZ_GPIO_KEY_INT) | GPIO_bit(SPITZ_GPIO_RESET) | PWER_RTC; | ||
119 | PKWR = GPIO_bit(SPITZ_GPIO_SYNC) | GPIO_bit(SPITZ_GPIO_KEY_INT) | GPIO_bit(SPITZ_GPIO_RESET); | ||
120 | PKSR = 0xffffffff; // clear | ||
121 | |||
122 | /* nRESET_OUT Disable */ | ||
123 | PSLR |= PSLR_SL_ROD; | ||
124 | |||
125 | /* Clear reset status */ | ||
126 | RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; | ||
127 | |||
128 | /* Stop 3.6MHz and drive HIGH to PCMCIA and CS */ | ||
129 | PCFR = PCFR_GPR_EN | PCFR_OPDE; | ||
130 | } | ||
131 | |||
132 | static void spitz_postsuspend(void) | ||
133 | { | ||
134 | pxa_gpio_mode(GPIO18_RDY_MD); | ||
135 | pxa_gpio_mode(10 | GPIO_IN); | ||
136 | } | ||
137 | |||
138 | static int spitz_should_wakeup(unsigned int resume_on_alarm) | ||
139 | { | ||
140 | int is_resume = 0; | ||
141 | int acin = STATUS_AC_IN(); | ||
142 | |||
143 | if (spitz_last_ac_status != acin) { | ||
144 | if (acin) { | ||
145 | /* charge on */ | ||
146 | sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG; | ||
147 | dev_dbg(sharpsl_pm.dev, "AC Inserted\n"); | ||
148 | } else { | ||
149 | /* charge off */ | ||
150 | dev_dbg(sharpsl_pm.dev, "AC Removed\n"); | ||
151 | CHARGE_LED_OFF(); | ||
152 | CHARGE_OFF(); | ||
153 | sharpsl_pm.charge_mode = CHRG_OFF; | ||
154 | } | ||
155 | spitz_last_ac_status = acin; | ||
156 | /* Return to suspend as this must be what we were woken for */ | ||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | if (PEDR & GPIO_bit(SPITZ_GPIO_KEY_INT)) | ||
161 | is_resume |= GPIO_bit(SPITZ_GPIO_KEY_INT); | ||
162 | |||
163 | if (PKSR & GPIO_bit(SPITZ_GPIO_SYNC)) | ||
164 | is_resume |= GPIO_bit(SPITZ_GPIO_SYNC); | ||
165 | |||
166 | if (resume_on_alarm && (PEDR & PWER_RTC)) | ||
167 | is_resume |= PWER_RTC; | ||
168 | |||
169 | dev_dbg(sharpsl_pm.dev, "is_resume: %x\n",is_resume); | ||
170 | return is_resume; | ||
171 | } | ||
172 | |||
173 | static unsigned long spitz_charger_wakeup(void) | ||
174 | { | ||
175 | return (~GPLR0 & GPIO_bit(SPITZ_GPIO_KEY_INT)) | (GPLR0 & GPIO_bit(SPITZ_GPIO_SYNC)); | ||
176 | } | ||
177 | |||
178 | static int spitz_acin_status(void) | ||
179 | { | ||
180 | return (((~GPLR(SPITZ_GPIO_AC_IN)) & GPIO_bit(SPITZ_GPIO_AC_IN)) != 0); | ||
181 | } | ||
182 | |||
183 | struct sharpsl_charger_machinfo spitz_pm_machinfo = { | ||
184 | .init = spitz_charger_init, | ||
185 | .gpio_batlock = SPITZ_GPIO_BAT_COVER, | ||
186 | .gpio_acin = SPITZ_GPIO_AC_IN, | ||
187 | .gpio_batfull = SPITZ_GPIO_CHRG_FULL, | ||
188 | .gpio_fatal = SPITZ_GPIO_FATAL_BAT, | ||
189 | .status_acin = spitz_acin_status, | ||
190 | .discharge = spitz_discharge, | ||
191 | .discharge1 = spitz_discharge1, | ||
192 | .charge = spitz_charge, | ||
193 | .chargeled = spitz_charge_led, | ||
194 | .measure_temp = spitz_measure_temp, | ||
195 | .presuspend = spitz_presuspend, | ||
196 | .postsuspend = spitz_postsuspend, | ||
197 | .charger_wakeup = spitz_charger_wakeup, | ||
198 | .should_wakeup = spitz_should_wakeup, | ||
199 | .bat_levels = 40, | ||
200 | .bat_levels_noac = spitz_battery_levels_noac, | ||
201 | .bat_levels_acin = spitz_battery_levels_acin, | ||
202 | .status_high_acin = 188, | ||
203 | .status_low_acin = 178, | ||
204 | .status_high_noac = 185, | ||
205 | .status_low_noac = 175, | ||
206 | }; | ||
207 | |||
208 | static struct platform_device *spitzpm_device; | ||
209 | |||
210 | static int __devinit spitzpm_init(void) | ||
211 | { | ||
212 | int ret; | ||
213 | |||
214 | spitzpm_device = platform_device_alloc("sharpsl-pm", -1); | ||
215 | if (!spitzpm_device) | ||
216 | return -ENOMEM; | ||
217 | |||
218 | spitzpm_device->dev.platform_data = &spitz_pm_machinfo; | ||
219 | ret = platform_device_add(spitzpm_device); | ||
220 | |||
221 | if (ret) | ||
222 | platform_device_put(spitzpm_device); | ||
223 | |||
224 | return ret; | ||
225 | } | ||
226 | |||
227 | static void spitzpm_exit(void) | ||
228 | { | ||
229 | platform_device_unregister(spitzpm_device); | ||
230 | } | ||
231 | |||
232 | module_init(spitzpm_init); | ||
233 | module_exit(spitzpm_exit); | ||
diff --git a/arch/frv/kernel/pm.c b/arch/frv/kernel/pm.c index 1a1e8a119c3d..712c3c24c954 100644 --- a/arch/frv/kernel/pm.c +++ b/arch/frv/kernel/pm.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/config.h> | 14 | #include <linux/config.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/pm.h> | 16 | #include <linux/pm.h> |
17 | #include <linux/pm_legacy.h> | ||
17 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
18 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
19 | #include <linux/sysctl.h> | 20 | #include <linux/sysctl.h> |
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index dbf90ad6eac3..6004bb0795e0 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig | |||
@@ -699,7 +699,7 @@ depends on PM && !X86_VISWS | |||
699 | 699 | ||
700 | config APM | 700 | config APM |
701 | tristate "APM (Advanced Power Management) BIOS support" | 701 | tristate "APM (Advanced Power Management) BIOS support" |
702 | depends on PM | 702 | depends on PM && PM_LEGACY |
703 | ---help--- | 703 | ---help--- |
704 | APM is a BIOS specification for saving power using several different | 704 | APM is a BIOS specification for saving power using several different |
705 | techniques. This is mostly useful for battery powered laptops with | 705 | techniques. This is mostly useful for battery powered laptops with |
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c index b66c13c0cc0f..f36677241ecd 100644 --- a/arch/i386/kernel/acpi/boot.c +++ b/arch/i386/kernel/acpi/boot.c | |||
@@ -39,17 +39,14 @@ | |||
39 | 39 | ||
40 | #ifdef CONFIG_X86_64 | 40 | #ifdef CONFIG_X86_64 |
41 | 41 | ||
42 | static inline void acpi_madt_oem_check(char *oem_id, char *oem_table_id) | ||
43 | { | ||
44 | } | ||
45 | extern void __init clustered_apic_check(void); | 42 | extern void __init clustered_apic_check(void); |
46 | static inline int ioapic_setup_disabled(void) | ||
47 | { | ||
48 | return 0; | ||
49 | } | ||
50 | 43 | ||
44 | extern int gsi_irq_sharing(int gsi); | ||
51 | #include <asm/proto.h> | 45 | #include <asm/proto.h> |
52 | 46 | ||
47 | static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) { return 0; } | ||
48 | |||
49 | |||
53 | #else /* X86 */ | 50 | #else /* X86 */ |
54 | 51 | ||
55 | #ifdef CONFIG_X86_LOCAL_APIC | 52 | #ifdef CONFIG_X86_LOCAL_APIC |
@@ -57,6 +54,8 @@ static inline int ioapic_setup_disabled(void) | |||
57 | #include <mach_mpparse.h> | 54 | #include <mach_mpparse.h> |
58 | #endif /* CONFIG_X86_LOCAL_APIC */ | 55 | #endif /* CONFIG_X86_LOCAL_APIC */ |
59 | 56 | ||
57 | static inline int gsi_irq_sharing(int gsi) { return gsi; } | ||
58 | |||
60 | #endif /* X86 */ | 59 | #endif /* X86 */ |
61 | 60 | ||
62 | #define BAD_MADT_ENTRY(entry, end) ( \ | 61 | #define BAD_MADT_ENTRY(entry, end) ( \ |
@@ -459,7 +458,7 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) | |||
459 | *irq = IO_APIC_VECTOR(gsi); | 458 | *irq = IO_APIC_VECTOR(gsi); |
460 | else | 459 | else |
461 | #endif | 460 | #endif |
462 | *irq = gsi; | 461 | *irq = gsi_irq_sharing(gsi); |
463 | return 0; | 462 | return 0; |
464 | } | 463 | } |
465 | 464 | ||
@@ -543,7 +542,7 @@ acpi_scan_rsdp(unsigned long start, unsigned long length) | |||
543 | * RSDP signature. | 542 | * RSDP signature. |
544 | */ | 543 | */ |
545 | for (offset = 0; offset < length; offset += 16) { | 544 | for (offset = 0; offset < length; offset += 16) { |
546 | if (strncmp((char *)(start + offset), "RSD PTR ", sig_len)) | 545 | if (strncmp((char *)(phys_to_virt(start) + offset), "RSD PTR ", sig_len)) |
547 | continue; | 546 | continue; |
548 | return (start + offset); | 547 | return (start + offset); |
549 | } | 548 | } |
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index 003548b8735f..1e60acbed3c1 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c | |||
@@ -218,6 +218,7 @@ | |||
218 | #include <linux/time.h> | 218 | #include <linux/time.h> |
219 | #include <linux/sched.h> | 219 | #include <linux/sched.h> |
220 | #include <linux/pm.h> | 220 | #include <linux/pm.h> |
221 | #include <linux/pm_legacy.h> | ||
221 | #include <linux/device.h> | 222 | #include <linux/device.h> |
222 | #include <linux/kernel.h> | 223 | #include <linux/kernel.h> |
223 | #include <linux/smp.h> | 224 | #include <linux/smp.h> |
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c index 53a1681cd964..e344ef88cfcd 100644 --- a/arch/i386/kernel/cpu/amd.c +++ b/arch/i386/kernel/cpu/amd.c | |||
@@ -206,9 +206,9 @@ static void __init init_amd(struct cpuinfo_x86 *c) | |||
206 | display_cacheinfo(c); | 206 | display_cacheinfo(c); |
207 | 207 | ||
208 | if (cpuid_eax(0x80000000) >= 0x80000008) { | 208 | if (cpuid_eax(0x80000000) >= 0x80000008) { |
209 | c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1; | 209 | c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1; |
210 | if (c->x86_num_cores & (c->x86_num_cores - 1)) | 210 | if (c->x86_max_cores & (c->x86_max_cores - 1)) |
211 | c->x86_num_cores = 1; | 211 | c->x86_max_cores = 1; |
212 | } | 212 | } |
213 | 213 | ||
214 | #ifdef CONFIG_X86_HT | 214 | #ifdef CONFIG_X86_HT |
@@ -217,15 +217,15 @@ static void __init init_amd(struct cpuinfo_x86 *c) | |||
217 | * distingush the cores. Assumes number of cores is a power | 217 | * distingush the cores. Assumes number of cores is a power |
218 | * of two. | 218 | * of two. |
219 | */ | 219 | */ |
220 | if (c->x86_num_cores > 1) { | 220 | if (c->x86_max_cores > 1) { |
221 | int cpu = smp_processor_id(); | 221 | int cpu = smp_processor_id(); |
222 | unsigned bits = 0; | 222 | unsigned bits = 0; |
223 | while ((1 << bits) < c->x86_num_cores) | 223 | while ((1 << bits) < c->x86_max_cores) |
224 | bits++; | 224 | bits++; |
225 | cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<<bits)-1); | 225 | cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<<bits)-1); |
226 | phys_proc_id[cpu] >>= bits; | 226 | phys_proc_id[cpu] >>= bits; |
227 | printk(KERN_INFO "CPU %d(%d) -> Core %d\n", | 227 | printk(KERN_INFO "CPU %d(%d) -> Core %d\n", |
228 | cpu, c->x86_num_cores, cpu_core_id[cpu]); | 228 | cpu, c->x86_max_cores, cpu_core_id[cpu]); |
229 | } | 229 | } |
230 | #endif | 230 | #endif |
231 | } | 231 | } |
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index c145fb30002e..31e344b26bae 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c | |||
@@ -231,10 +231,10 @@ static void __init early_cpu_detect(void) | |||
231 | cpuid(0x00000001, &tfms, &misc, &junk, &cap0); | 231 | cpuid(0x00000001, &tfms, &misc, &junk, &cap0); |
232 | c->x86 = (tfms >> 8) & 15; | 232 | c->x86 = (tfms >> 8) & 15; |
233 | c->x86_model = (tfms >> 4) & 15; | 233 | c->x86_model = (tfms >> 4) & 15; |
234 | if (c->x86 == 0xf) { | 234 | if (c->x86 == 0xf) |
235 | c->x86 += (tfms >> 20) & 0xff; | 235 | c->x86 += (tfms >> 20) & 0xff; |
236 | if (c->x86 >= 0x6) | ||
236 | c->x86_model += ((tfms >> 16) & 0xF) << 4; | 237 | c->x86_model += ((tfms >> 16) & 0xF) << 4; |
237 | } | ||
238 | c->x86_mask = tfms & 15; | 238 | c->x86_mask = tfms & 15; |
239 | if (cap0 & (1<<19)) | 239 | if (cap0 & (1<<19)) |
240 | c->x86_cache_alignment = ((misc >> 8) & 0xff) * 8; | 240 | c->x86_cache_alignment = ((misc >> 8) & 0xff) * 8; |
@@ -333,7 +333,7 @@ void __devinit identify_cpu(struct cpuinfo_x86 *c) | |||
333 | c->x86_model = c->x86_mask = 0; /* So far unknown... */ | 333 | c->x86_model = c->x86_mask = 0; /* So far unknown... */ |
334 | c->x86_vendor_id[0] = '\0'; /* Unset */ | 334 | c->x86_vendor_id[0] = '\0'; /* Unset */ |
335 | c->x86_model_id[0] = '\0'; /* Unset */ | 335 | c->x86_model_id[0] = '\0'; /* Unset */ |
336 | c->x86_num_cores = 1; | 336 | c->x86_max_cores = 1; |
337 | memset(&c->x86_capability, 0, sizeof c->x86_capability); | 337 | memset(&c->x86_capability, 0, sizeof c->x86_capability); |
338 | 338 | ||
339 | if (!have_cpuid_p()) { | 339 | if (!have_cpuid_p()) { |
@@ -443,52 +443,44 @@ void __devinit identify_cpu(struct cpuinfo_x86 *c) | |||
443 | void __devinit detect_ht(struct cpuinfo_x86 *c) | 443 | void __devinit detect_ht(struct cpuinfo_x86 *c) |
444 | { | 444 | { |
445 | u32 eax, ebx, ecx, edx; | 445 | u32 eax, ebx, ecx, edx; |
446 | int index_msb, tmp; | 446 | int index_msb, core_bits; |
447 | int cpu = smp_processor_id(); | 447 | int cpu = smp_processor_id(); |
448 | 448 | ||
449 | cpuid(1, &eax, &ebx, &ecx, &edx); | ||
450 | |||
451 | c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0); | ||
452 | |||
449 | if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY)) | 453 | if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY)) |
450 | return; | 454 | return; |
451 | 455 | ||
452 | cpuid(1, &eax, &ebx, &ecx, &edx); | ||
453 | smp_num_siblings = (ebx & 0xff0000) >> 16; | 456 | smp_num_siblings = (ebx & 0xff0000) >> 16; |
454 | 457 | ||
455 | if (smp_num_siblings == 1) { | 458 | if (smp_num_siblings == 1) { |
456 | printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); | 459 | printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); |
457 | } else if (smp_num_siblings > 1 ) { | 460 | } else if (smp_num_siblings > 1 ) { |
458 | index_msb = 31; | ||
459 | 461 | ||
460 | if (smp_num_siblings > NR_CPUS) { | 462 | if (smp_num_siblings > NR_CPUS) { |
461 | printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings); | 463 | printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings); |
462 | smp_num_siblings = 1; | 464 | smp_num_siblings = 1; |
463 | return; | 465 | return; |
464 | } | 466 | } |
465 | tmp = smp_num_siblings; | 467 | |
466 | while ((tmp & 0x80000000 ) == 0) { | 468 | index_msb = get_count_order(smp_num_siblings); |
467 | tmp <<=1 ; | ||
468 | index_msb--; | ||
469 | } | ||
470 | if (smp_num_siblings & (smp_num_siblings - 1)) | ||
471 | index_msb++; | ||
472 | phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb); | 469 | phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb); |
473 | 470 | ||
474 | printk(KERN_INFO "CPU: Physical Processor ID: %d\n", | 471 | printk(KERN_INFO "CPU: Physical Processor ID: %d\n", |
475 | phys_proc_id[cpu]); | 472 | phys_proc_id[cpu]); |
476 | 473 | ||
477 | smp_num_siblings = smp_num_siblings / c->x86_num_cores; | 474 | smp_num_siblings = smp_num_siblings / c->x86_max_cores; |
478 | 475 | ||
479 | tmp = smp_num_siblings; | 476 | index_msb = get_count_order(smp_num_siblings) ; |
480 | index_msb = 31; | ||
481 | while ((tmp & 0x80000000) == 0) { | ||
482 | tmp <<=1 ; | ||
483 | index_msb--; | ||
484 | } | ||
485 | 477 | ||
486 | if (smp_num_siblings & (smp_num_siblings - 1)) | 478 | core_bits = get_count_order(c->x86_max_cores); |
487 | index_msb++; | ||
488 | 479 | ||
489 | cpu_core_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb); | 480 | cpu_core_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb) & |
481 | ((1 << core_bits) - 1); | ||
490 | 482 | ||
491 | if (c->x86_num_cores > 1) | 483 | if (c->x86_max_cores > 1) |
492 | printk(KERN_INFO "CPU: Processor Core ID: %d\n", | 484 | printk(KERN_INFO "CPU: Processor Core ID: %d\n", |
493 | cpu_core_id[cpu]); | 485 | cpu_core_id[cpu]); |
494 | } | 486 | } |
diff --git a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c index 43601de0f633..5e2da704f0fa 100644 --- a/arch/i386/kernel/cpu/intel.c +++ b/arch/i386/kernel/cpu/intel.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <linux/bitops.h> | 6 | #include <linux/bitops.h> |
7 | #include <linux/smp.h> | 7 | #include <linux/smp.h> |
8 | #include <linux/thread_info.h> | 8 | #include <linux/thread_info.h> |
9 | #include <linux/module.h> | ||
9 | 10 | ||
10 | #include <asm/processor.h> | 11 | #include <asm/processor.h> |
11 | #include <asm/msr.h> | 12 | #include <asm/msr.h> |
@@ -157,7 +158,7 @@ static void __devinit init_intel(struct cpuinfo_x86 *c) | |||
157 | if ( p ) | 158 | if ( p ) |
158 | strcpy(c->x86_model_id, p); | 159 | strcpy(c->x86_model_id, p); |
159 | 160 | ||
160 | c->x86_num_cores = num_cpu_cores(c); | 161 | c->x86_max_cores = num_cpu_cores(c); |
161 | 162 | ||
162 | detect_ht(c); | 163 | detect_ht(c); |
163 | 164 | ||
@@ -264,5 +265,52 @@ __init int intel_cpu_init(void) | |||
264 | return 0; | 265 | return 0; |
265 | } | 266 | } |
266 | 267 | ||
268 | #ifndef CONFIG_X86_CMPXCHG | ||
269 | unsigned long cmpxchg_386_u8(volatile void *ptr, u8 old, u8 new) | ||
270 | { | ||
271 | u8 prev; | ||
272 | unsigned long flags; | ||
273 | |||
274 | /* Poor man's cmpxchg for 386. Unsuitable for SMP */ | ||
275 | local_irq_save(flags); | ||
276 | prev = *(u8 *)ptr; | ||
277 | if (prev == old) | ||
278 | *(u8 *)ptr = new; | ||
279 | local_irq_restore(flags); | ||
280 | return prev; | ||
281 | } | ||
282 | EXPORT_SYMBOL(cmpxchg_386_u8); | ||
283 | |||
284 | unsigned long cmpxchg_386_u16(volatile void *ptr, u16 old, u16 new) | ||
285 | { | ||
286 | u16 prev; | ||
287 | unsigned long flags; | ||
288 | |||
289 | /* Poor man's cmpxchg for 386. Unsuitable for SMP */ | ||
290 | local_irq_save(flags); | ||
291 | prev = *(u16 *)ptr; | ||
292 | if (prev == old) | ||
293 | *(u16 *)ptr = new; | ||
294 | local_irq_restore(flags); | ||
295 | return prev; | ||
296 | } | ||
297 | EXPORT_SYMBOL(cmpxchg_386_u16); | ||
298 | |||
299 | unsigned long cmpxchg_386_u32(volatile void *ptr, u32 old, u32 new) | ||
300 | { | ||
301 | u32 prev; | ||
302 | unsigned long flags; | ||
303 | |||
304 | /* Poor man's cmpxchg for 386. Unsuitable for SMP */ | ||
305 | local_irq_save(flags); | ||
306 | prev = *(u32 *)ptr; | ||
307 | if (prev == old) | ||
308 | *(u32 *)ptr = new; | ||
309 | local_irq_restore(flags); | ||
310 | return prev; | ||
311 | } | ||
312 | EXPORT_SYMBOL(cmpxchg_386_u32); | ||
313 | #endif | ||
314 | |||
267 | // arch_initcall(intel_cpu_init); | 315 | // arch_initcall(intel_cpu_init); |
268 | 316 | ||
diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c index 4dc42a189ae5..fbfd374aa336 100644 --- a/arch/i386/kernel/cpu/intel_cacheinfo.c +++ b/arch/i386/kernel/cpu/intel_cacheinfo.c | |||
@@ -293,29 +293,45 @@ static struct _cpuid4_info *cpuid4_info[NR_CPUS]; | |||
293 | #ifdef CONFIG_SMP | 293 | #ifdef CONFIG_SMP |
294 | static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) | 294 | static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) |
295 | { | 295 | { |
296 | struct _cpuid4_info *this_leaf; | 296 | struct _cpuid4_info *this_leaf, *sibling_leaf; |
297 | unsigned long num_threads_sharing; | 297 | unsigned long num_threads_sharing; |
298 | #ifdef CONFIG_X86_HT | 298 | int index_msb, i; |
299 | struct cpuinfo_x86 *c = cpu_data + cpu; | 299 | struct cpuinfo_x86 *c = cpu_data; |
300 | #endif | ||
301 | 300 | ||
302 | this_leaf = CPUID4_INFO_IDX(cpu, index); | 301 | this_leaf = CPUID4_INFO_IDX(cpu, index); |
303 | num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing; | 302 | num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing; |
304 | 303 | ||
305 | if (num_threads_sharing == 1) | 304 | if (num_threads_sharing == 1) |
306 | cpu_set(cpu, this_leaf->shared_cpu_map); | 305 | cpu_set(cpu, this_leaf->shared_cpu_map); |
307 | #ifdef CONFIG_X86_HT | 306 | else { |
308 | else if (num_threads_sharing == smp_num_siblings) | 307 | index_msb = get_count_order(num_threads_sharing); |
309 | this_leaf->shared_cpu_map = cpu_sibling_map[cpu]; | 308 | |
310 | else if (num_threads_sharing == (c->x86_num_cores * smp_num_siblings)) | 309 | for_each_online_cpu(i) { |
311 | this_leaf->shared_cpu_map = cpu_core_map[cpu]; | 310 | if (c[i].apicid >> index_msb == |
312 | else | 311 | c[cpu].apicid >> index_msb) { |
313 | printk(KERN_DEBUG "Number of CPUs sharing cache didn't match " | 312 | cpu_set(i, this_leaf->shared_cpu_map); |
314 | "any known set of CPUs\n"); | 313 | if (i != cpu && cpuid4_info[i]) { |
315 | #endif | 314 | sibling_leaf = CPUID4_INFO_IDX(i, index); |
315 | cpu_set(cpu, sibling_leaf->shared_cpu_map); | ||
316 | } | ||
317 | } | ||
318 | } | ||
319 | } | ||
320 | } | ||
321 | static void __devinit cache_remove_shared_cpu_map(unsigned int cpu, int index) | ||
322 | { | ||
323 | struct _cpuid4_info *this_leaf, *sibling_leaf; | ||
324 | int sibling; | ||
325 | |||
326 | this_leaf = CPUID4_INFO_IDX(cpu, index); | ||
327 | for_each_cpu_mask(sibling, this_leaf->shared_cpu_map) { | ||
328 | sibling_leaf = CPUID4_INFO_IDX(sibling, index); | ||
329 | cpu_clear(cpu, sibling_leaf->shared_cpu_map); | ||
330 | } | ||
316 | } | 331 | } |
317 | #else | 332 | #else |
318 | static void __init cache_shared_cpu_map_setup(unsigned int cpu, int index) {} | 333 | static void __init cache_shared_cpu_map_setup(unsigned int cpu, int index) {} |
334 | static void __init cache_remove_shared_cpu_map(unsigned int cpu, int index) {} | ||
319 | #endif | 335 | #endif |
320 | 336 | ||
321 | static void free_cache_attributes(unsigned int cpu) | 337 | static void free_cache_attributes(unsigned int cpu) |
@@ -574,8 +590,10 @@ static void __cpuexit cache_remove_dev(struct sys_device * sys_dev) | |||
574 | unsigned int cpu = sys_dev->id; | 590 | unsigned int cpu = sys_dev->id; |
575 | unsigned long i; | 591 | unsigned long i; |
576 | 592 | ||
577 | for (i = 0; i < num_cache_leaves; i++) | 593 | for (i = 0; i < num_cache_leaves; i++) { |
594 | cache_remove_shared_cpu_map(cpu, i); | ||
578 | kobject_unregister(&(INDEX_KOBJECT_PTR(cpu,i)->kobj)); | 595 | kobject_unregister(&(INDEX_KOBJECT_PTR(cpu,i)->kobj)); |
596 | } | ||
579 | kobject_unregister(cache_kobject[cpu]); | 597 | kobject_unregister(cache_kobject[cpu]); |
580 | cpuid4_cache_sysfs_exit(cpu); | 598 | cpuid4_cache_sysfs_exit(cpu); |
581 | return; | 599 | return; |
diff --git a/arch/i386/kernel/cpu/mtrr/main.c b/arch/i386/kernel/cpu/mtrr/main.c index dd4ebd6af7e4..1e9db198c440 100644 --- a/arch/i386/kernel/cpu/mtrr/main.c +++ b/arch/i386/kernel/cpu/mtrr/main.c | |||
@@ -626,6 +626,14 @@ void __init mtrr_bp_init(void) | |||
626 | if (cpuid_eax(0x80000000) >= 0x80000008) { | 626 | if (cpuid_eax(0x80000000) >= 0x80000008) { |
627 | u32 phys_addr; | 627 | u32 phys_addr; |
628 | phys_addr = cpuid_eax(0x80000008) & 0xff; | 628 | phys_addr = cpuid_eax(0x80000008) & 0xff; |
629 | /* CPUID workaround for Intel 0F33/0F34 CPU */ | ||
630 | if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && | ||
631 | boot_cpu_data.x86 == 0xF && | ||
632 | boot_cpu_data.x86_model == 0x3 && | ||
633 | (boot_cpu_data.x86_mask == 0x3 || | ||
634 | boot_cpu_data.x86_mask == 0x4)) | ||
635 | phys_addr = 36; | ||
636 | |||
629 | size_or_mask = ~((1 << (phys_addr - PAGE_SHIFT)) - 1); | 637 | size_or_mask = ~((1 << (phys_addr - PAGE_SHIFT)) - 1); |
630 | size_and_mask = ~size_or_mask & 0xfff00000; | 638 | size_and_mask = ~size_or_mask & 0xfff00000; |
631 | } else if (boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR && | 639 | } else if (boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR && |
diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c index 41b871ecf4b3..e7921315ae9d 100644 --- a/arch/i386/kernel/cpu/proc.c +++ b/arch/i386/kernel/cpu/proc.c | |||
@@ -94,12 +94,11 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
94 | if (c->x86_cache_size >= 0) | 94 | if (c->x86_cache_size >= 0) |
95 | seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); | 95 | seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); |
96 | #ifdef CONFIG_X86_HT | 96 | #ifdef CONFIG_X86_HT |
97 | if (c->x86_num_cores * smp_num_siblings > 1) { | 97 | if (c->x86_max_cores * smp_num_siblings > 1) { |
98 | seq_printf(m, "physical id\t: %d\n", phys_proc_id[n]); | 98 | seq_printf(m, "physical id\t: %d\n", phys_proc_id[n]); |
99 | seq_printf(m, "siblings\t: %d\n", | 99 | seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[n])); |
100 | c->x86_num_cores * smp_num_siblings); | ||
101 | seq_printf(m, "core id\t\t: %d\n", cpu_core_id[n]); | 100 | seq_printf(m, "core id\t\t: %d\n", cpu_core_id[n]); |
102 | seq_printf(m, "cpu cores\t: %d\n", c->x86_num_cores); | 101 | seq_printf(m, "cpu cores\t: %d\n", c->booted_cores); |
103 | } | 102 | } |
104 | #endif | 103 | #endif |
105 | 104 | ||
diff --git a/arch/i386/kernel/crash.c b/arch/i386/kernel/crash.c index af809ccf5fbe..0248e084017c 100644 --- a/arch/i386/kernel/crash.c +++ b/arch/i386/kernel/crash.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <asm/hardirq.h> | 21 | #include <asm/hardirq.h> |
22 | #include <asm/nmi.h> | 22 | #include <asm/nmi.h> |
23 | #include <asm/hw_irq.h> | 23 | #include <asm/hw_irq.h> |
24 | #include <asm/apic.h> | ||
24 | #include <mach_ipi.h> | 25 | #include <mach_ipi.h> |
25 | 26 | ||
26 | 27 | ||
@@ -147,6 +148,7 @@ static int crash_nmi_callback(struct pt_regs *regs, int cpu) | |||
147 | regs = &fixed_regs; | 148 | regs = &fixed_regs; |
148 | } | 149 | } |
149 | crash_save_this_cpu(regs, cpu); | 150 | crash_save_this_cpu(regs, cpu); |
151 | disable_local_APIC(); | ||
150 | atomic_dec(&waiting_for_crash_ipi); | 152 | atomic_dec(&waiting_for_crash_ipi); |
151 | /* Assume hlt works */ | 153 | /* Assume hlt works */ |
152 | halt(); | 154 | halt(); |
@@ -186,6 +188,7 @@ static void nmi_shootdown_cpus(void) | |||
186 | } | 188 | } |
187 | 189 | ||
188 | /* Leave the nmi callback set */ | 190 | /* Leave the nmi callback set */ |
191 | disable_local_APIC(); | ||
189 | } | 192 | } |
190 | #else | 193 | #else |
191 | static void nmi_shootdown_cpus(void) | 194 | static void nmi_shootdown_cpus(void) |
@@ -210,5 +213,9 @@ void machine_crash_shutdown(struct pt_regs *regs) | |||
210 | /* Make a note of crashing cpu. Will be used in NMI callback.*/ | 213 | /* Make a note of crashing cpu. Will be used in NMI callback.*/ |
211 | crashing_cpu = smp_processor_id(); | 214 | crashing_cpu = smp_processor_id(); |
212 | nmi_shootdown_cpus(); | 215 | nmi_shootdown_cpus(); |
216 | lapic_shutdown(); | ||
217 | #if defined(CONFIG_X86_IO_APIC) | ||
218 | disable_IO_APIC(); | ||
219 | #endif | ||
213 | crash_save_self(regs); | 220 | crash_save_self(regs); |
214 | } | 221 | } |
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index 9e24f7b207ee..e50b93155249 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S | |||
@@ -560,11 +560,10 @@ nmi_stack_fixup: | |||
560 | nmi_debug_stack_check: | 560 | nmi_debug_stack_check: |
561 | cmpw $__KERNEL_CS,16(%esp) | 561 | cmpw $__KERNEL_CS,16(%esp) |
562 | jne nmi_stack_correct | 562 | jne nmi_stack_correct |
563 | cmpl $debug - 1,(%esp) | 563 | cmpl $debug,(%esp) |
564 | jle nmi_stack_correct | 564 | jb nmi_stack_correct |
565 | cmpl $debug_esp_fix_insn,(%esp) | 565 | cmpl $debug_esp_fix_insn,(%esp) |
566 | jle nmi_debug_stack_fixup | 566 | ja nmi_stack_correct |
567 | nmi_debug_stack_fixup: | ||
568 | FIX_STACK(24,nmi_stack_correct, 1) | 567 | FIX_STACK(24,nmi_stack_correct, 1) |
569 | jmp nmi_stack_correct | 568 | jmp nmi_stack_correct |
570 | 569 | ||
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index bc5a9d97466b..d16520da4550 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c | |||
@@ -72,9 +72,11 @@ int phys_proc_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID}; | |||
72 | /* Core ID of each logical CPU */ | 72 | /* Core ID of each logical CPU */ |
73 | int cpu_core_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID}; | 73 | int cpu_core_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID}; |
74 | 74 | ||
75 | /* representing HT siblings of each logical CPU */ | ||
75 | cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; | 76 | cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; |
76 | EXPORT_SYMBOL(cpu_sibling_map); | 77 | EXPORT_SYMBOL(cpu_sibling_map); |
77 | 78 | ||
79 | /* representing HT and core siblings of each logical CPU */ | ||
78 | cpumask_t cpu_core_map[NR_CPUS] __read_mostly; | 80 | cpumask_t cpu_core_map[NR_CPUS] __read_mostly; |
79 | EXPORT_SYMBOL(cpu_core_map); | 81 | EXPORT_SYMBOL(cpu_core_map); |
80 | 82 | ||
@@ -442,35 +444,60 @@ static void __devinit smp_callin(void) | |||
442 | 444 | ||
443 | static int cpucount; | 445 | static int cpucount; |
444 | 446 | ||
447 | /* representing cpus for which sibling maps can be computed */ | ||
448 | static cpumask_t cpu_sibling_setup_map; | ||
449 | |||
445 | static inline void | 450 | static inline void |
446 | set_cpu_sibling_map(int cpu) | 451 | set_cpu_sibling_map(int cpu) |
447 | { | 452 | { |
448 | int i; | 453 | int i; |
454 | struct cpuinfo_x86 *c = cpu_data; | ||
455 | |||
456 | cpu_set(cpu, cpu_sibling_setup_map); | ||
449 | 457 | ||
450 | if (smp_num_siblings > 1) { | 458 | if (smp_num_siblings > 1) { |
451 | for (i = 0; i < NR_CPUS; i++) { | 459 | for_each_cpu_mask(i, cpu_sibling_setup_map) { |
452 | if (!cpu_isset(i, cpu_callout_map)) | 460 | if (phys_proc_id[cpu] == phys_proc_id[i] && |
453 | continue; | 461 | cpu_core_id[cpu] == cpu_core_id[i]) { |
454 | if (cpu_core_id[cpu] == cpu_core_id[i]) { | ||
455 | cpu_set(i, cpu_sibling_map[cpu]); | 462 | cpu_set(i, cpu_sibling_map[cpu]); |
456 | cpu_set(cpu, cpu_sibling_map[i]); | 463 | cpu_set(cpu, cpu_sibling_map[i]); |
464 | cpu_set(i, cpu_core_map[cpu]); | ||
465 | cpu_set(cpu, cpu_core_map[i]); | ||
457 | } | 466 | } |
458 | } | 467 | } |
459 | } else { | 468 | } else { |
460 | cpu_set(cpu, cpu_sibling_map[cpu]); | 469 | cpu_set(cpu, cpu_sibling_map[cpu]); |
461 | } | 470 | } |
462 | 471 | ||
463 | if (current_cpu_data.x86_num_cores > 1) { | 472 | if (current_cpu_data.x86_max_cores == 1) { |
464 | for (i = 0; i < NR_CPUS; i++) { | ||
465 | if (!cpu_isset(i, cpu_callout_map)) | ||
466 | continue; | ||
467 | if (phys_proc_id[cpu] == phys_proc_id[i]) { | ||
468 | cpu_set(i, cpu_core_map[cpu]); | ||
469 | cpu_set(cpu, cpu_core_map[i]); | ||
470 | } | ||
471 | } | ||
472 | } else { | ||
473 | cpu_core_map[cpu] = cpu_sibling_map[cpu]; | 473 | cpu_core_map[cpu] = cpu_sibling_map[cpu]; |
474 | c[cpu].booted_cores = 1; | ||
475 | return; | ||
476 | } | ||
477 | |||
478 | for_each_cpu_mask(i, cpu_sibling_setup_map) { | ||
479 | if (phys_proc_id[cpu] == phys_proc_id[i]) { | ||
480 | cpu_set(i, cpu_core_map[cpu]); | ||
481 | cpu_set(cpu, cpu_core_map[i]); | ||
482 | /* | ||
483 | * Does this new cpu bringup a new core? | ||
484 | */ | ||
485 | if (cpus_weight(cpu_sibling_map[cpu]) == 1) { | ||
486 | /* | ||
487 | * for each core in package, increment | ||
488 | * the booted_cores for this new cpu | ||
489 | */ | ||
490 | if (first_cpu(cpu_sibling_map[i]) == i) | ||
491 | c[cpu].booted_cores++; | ||
492 | /* | ||
493 | * increment the core count for all | ||
494 | * the other cpus in this package | ||
495 | */ | ||
496 | if (i != cpu) | ||
497 | c[i].booted_cores++; | ||
498 | } else if (i != cpu && !c[cpu].booted_cores) | ||
499 | c[cpu].booted_cores = c[i].booted_cores; | ||
500 | } | ||
474 | } | 501 | } |
475 | } | 502 | } |
476 | 503 | ||
@@ -1095,11 +1122,8 @@ static void __init smp_boot_cpus(unsigned int max_cpus) | |||
1095 | 1122 | ||
1096 | current_thread_info()->cpu = 0; | 1123 | current_thread_info()->cpu = 0; |
1097 | smp_tune_scheduling(); | 1124 | smp_tune_scheduling(); |
1098 | cpus_clear(cpu_sibling_map[0]); | ||
1099 | cpu_set(0, cpu_sibling_map[0]); | ||
1100 | 1125 | ||
1101 | cpus_clear(cpu_core_map[0]); | 1126 | set_cpu_sibling_map(0); |
1102 | cpu_set(0, cpu_core_map[0]); | ||
1103 | 1127 | ||
1104 | /* | 1128 | /* |
1105 | * If we couldn't find an SMP configuration at boot time, | 1129 | * If we couldn't find an SMP configuration at boot time, |
@@ -1278,15 +1302,24 @@ static void | |||
1278 | remove_siblinginfo(int cpu) | 1302 | remove_siblinginfo(int cpu) |
1279 | { | 1303 | { |
1280 | int sibling; | 1304 | int sibling; |
1305 | struct cpuinfo_x86 *c = cpu_data; | ||
1281 | 1306 | ||
1307 | for_each_cpu_mask(sibling, cpu_core_map[cpu]) { | ||
1308 | cpu_clear(cpu, cpu_core_map[sibling]); | ||
1309 | /* | ||
1310 | * last thread sibling in this cpu core going down | ||
1311 | */ | ||
1312 | if (cpus_weight(cpu_sibling_map[cpu]) == 1) | ||
1313 | c[sibling].booted_cores--; | ||
1314 | } | ||
1315 | |||
1282 | for_each_cpu_mask(sibling, cpu_sibling_map[cpu]) | 1316 | for_each_cpu_mask(sibling, cpu_sibling_map[cpu]) |
1283 | cpu_clear(cpu, cpu_sibling_map[sibling]); | 1317 | cpu_clear(cpu, cpu_sibling_map[sibling]); |
1284 | for_each_cpu_mask(sibling, cpu_core_map[cpu]) | ||
1285 | cpu_clear(cpu, cpu_core_map[sibling]); | ||
1286 | cpus_clear(cpu_sibling_map[cpu]); | 1318 | cpus_clear(cpu_sibling_map[cpu]); |
1287 | cpus_clear(cpu_core_map[cpu]); | 1319 | cpus_clear(cpu_core_map[cpu]); |
1288 | phys_proc_id[cpu] = BAD_APICID; | 1320 | phys_proc_id[cpu] = BAD_APICID; |
1289 | cpu_core_id[cpu] = BAD_APICID; | 1321 | cpu_core_id[cpu] = BAD_APICID; |
1322 | cpu_clear(cpu, cpu_sibling_setup_map); | ||
1290 | } | 1323 | } |
1291 | 1324 | ||
1292 | int __cpu_disable(void) | 1325 | int __cpu_disable(void) |
diff --git a/arch/i386/kernel/srat.c b/arch/i386/kernel/srat.c index 8de658db8146..52b3ed5d2cb5 100644 --- a/arch/i386/kernel/srat.c +++ b/arch/i386/kernel/srat.c | |||
@@ -137,8 +137,8 @@ static void __init parse_memory_affinity_structure (char *sratp) | |||
137 | "enabled and removable" : "enabled" ) ); | 137 | "enabled and removable" : "enabled" ) ); |
138 | } | 138 | } |
139 | 139 | ||
140 | #if MAX_NR_ZONES != 3 | 140 | #if MAX_NR_ZONES != 4 |
141 | #error "MAX_NR_ZONES != 3, chunk_to_zone requires review" | 141 | #error "MAX_NR_ZONES != 4, chunk_to_zone requires review" |
142 | #endif | 142 | #endif |
143 | /* Take a chunk of pages from page frame cstart to cend and count the number | 143 | /* Take a chunk of pages from page frame cstart to cend and count the number |
144 | * of pages in each zone, returned via zones[]. | 144 | * of pages in each zone, returned via zones[]. |
diff --git a/arch/i386/kernel/timers/timer_pit.c b/arch/i386/kernel/timers/timer_pit.c index e42e46d35159..b9b6bd56b9ba 100644 --- a/arch/i386/kernel/timers/timer_pit.c +++ b/arch/i386/kernel/timers/timer_pit.c | |||
@@ -25,8 +25,9 @@ static int __init init_pit(char* override) | |||
25 | { | 25 | { |
26 | /* check clock override */ | 26 | /* check clock override */ |
27 | if (override[0] && strncmp(override,"pit",3)) | 27 | if (override[0] && strncmp(override,"pit",3)) |
28 | printk(KERN_ERR "Warning: clock= override failed. Defaulting to PIT\n"); | 28 | printk(KERN_ERR "Warning: clock= override failed. Defaulting " |
29 | 29 | "to PIT\n"); | |
30 | init_cpu_khz(); | ||
30 | count_p = LATCH; | 31 | count_p = LATCH; |
31 | return 0; | 32 | return 0; |
32 | } | 33 | } |
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index 542d9298da5e..06e26f006238 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/proc_fs.h> | 28 | #include <linux/proc_fs.h> |
29 | #include <linux/efi.h> | 29 | #include <linux/efi.h> |
30 | #include <linux/memory_hotplug.h> | 30 | #include <linux/memory_hotplug.h> |
31 | #include <linux/initrd.h> | ||
31 | 32 | ||
32 | #include <asm/processor.h> | 33 | #include <asm/processor.h> |
33 | #include <asm/system.h> | 34 | #include <asm/system.h> |
@@ -267,7 +268,7 @@ static void __init permanent_kmaps_init(pgd_t *pgd_base) | |||
267 | pkmap_page_table = pte; | 268 | pkmap_page_table = pte; |
268 | } | 269 | } |
269 | 270 | ||
270 | void __devinit free_new_highpage(struct page *page) | 271 | static void __devinit free_new_highpage(struct page *page) |
271 | { | 272 | { |
272 | set_page_count(page, 1); | 273 | set_page_count(page, 1); |
273 | __free_page(page); | 274 | __free_page(page); |
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 8796e12c56f3..b76ce1fe2e7f 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig | |||
@@ -58,6 +58,10 @@ config IA64_UNCACHED_ALLOCATOR | |||
58 | bool | 58 | bool |
59 | select GENERIC_ALLOCATOR | 59 | select GENERIC_ALLOCATOR |
60 | 60 | ||
61 | config ZONE_DMA_IS_DMA32 | ||
62 | bool | ||
63 | default y | ||
64 | |||
61 | choice | 65 | choice |
62 | prompt "System type" | 66 | prompt "System type" |
63 | default IA64_GENERIC | 67 | default IA64_GENERIC |
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index e92ea64d8040..4305d2ba76f6 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c | |||
@@ -202,12 +202,9 @@ default_idle (void) | |||
202 | { | 202 | { |
203 | local_irq_enable(); | 203 | local_irq_enable(); |
204 | while (!need_resched()) { | 204 | while (!need_resched()) { |
205 | if (can_do_pal_halt) { | 205 | if (can_do_pal_halt) |
206 | local_irq_disable(); | 206 | safe_halt(); |
207 | if (!need_resched()) | 207 | else |
208 | safe_halt(); | ||
209 | local_irq_enable(); | ||
210 | } else | ||
211 | cpu_relax(); | 208 | cpu_relax(); |
212 | } | 209 | } |
213 | } | 210 | } |
@@ -272,10 +269,14 @@ cpu_idle (void) | |||
272 | { | 269 | { |
273 | void (*mark_idle)(int) = ia64_mark_idle; | 270 | void (*mark_idle)(int) = ia64_mark_idle; |
274 | int cpu = smp_processor_id(); | 271 | int cpu = smp_processor_id(); |
275 | set_thread_flag(TIF_POLLING_NRFLAG); | ||
276 | 272 | ||
277 | /* endless idle loop with no priority at all */ | 273 | /* endless idle loop with no priority at all */ |
278 | while (1) { | 274 | while (1) { |
275 | if (can_do_pal_halt) | ||
276 | clear_thread_flag(TIF_POLLING_NRFLAG); | ||
277 | else | ||
278 | set_thread_flag(TIF_POLLING_NRFLAG); | ||
279 | |||
279 | if (!need_resched()) { | 280 | if (!need_resched()) { |
280 | void (*idle)(void); | 281 | void (*idle)(void); |
281 | #ifdef CONFIG_SMP | 282 | #ifdef CONFIG_SMP |
diff --git a/arch/m68k/fpsp040/skeleton.S b/arch/m68k/fpsp040/skeleton.S index 9571a21d6ad4..a1629194e3fd 100644 --- a/arch/m68k/fpsp040/skeleton.S +++ b/arch/m68k/fpsp040/skeleton.S | |||
@@ -381,10 +381,8 @@ fpsp_done: | |||
381 | .Lnotkern: | 381 | .Lnotkern: |
382 | SAVE_ALL_INT | 382 | SAVE_ALL_INT |
383 | GET_CURRENT(%d0) | 383 | GET_CURRENT(%d0) |
384 | tstb %curptr@(TASK_NEEDRESCHED) | 384 | | deliver signals, reschedule etc.. |
385 | jne ret_from_exception | deliver signals, | 385 | jra ret_from_exception |
386 | | reschedule etc.. | ||
387 | RESTORE_ALL | ||
388 | 386 | ||
389 | | | 387 | | |
390 | | mem_write --- write to user or supervisor address space | 388 | | mem_write --- write to user or supervisor address space |
diff --git a/arch/m68k/ifpsp060/iskeleton.S b/arch/m68k/ifpsp060/iskeleton.S index 4ba2c74da93d..b2dbdf5ee309 100644 --- a/arch/m68k/ifpsp060/iskeleton.S +++ b/arch/m68k/ifpsp060/iskeleton.S | |||
@@ -75,10 +75,8 @@ _060_isp_done: | |||
75 | .Lnotkern: | 75 | .Lnotkern: |
76 | SAVE_ALL_INT | 76 | SAVE_ALL_INT |
77 | GET_CURRENT(%d0) | 77 | GET_CURRENT(%d0) |
78 | tstb %curptr@(TASK_NEEDRESCHED) | 78 | | deliver signals, reschedule etc.. |
79 | jne ret_from_exception | deliver signals, | 79 | jra ret_from_exception |
80 | | reschedule etc.. | ||
81 | RESTORE_ALL | ||
82 | 80 | ||
83 | | | 81 | | |
84 | | _060_real_chk(): | 82 | | _060_real_chk(): |
diff --git a/arch/m68k/kernel/asm-offsets.c b/arch/m68k/kernel/asm-offsets.c index cee3317b8665..c787c5ba9513 100644 --- a/arch/m68k/kernel/asm-offsets.c +++ b/arch/m68k/kernel/asm-offsets.c | |||
@@ -25,12 +25,8 @@ int main(void) | |||
25 | DEFINE(TASK_STATE, offsetof(struct task_struct, state)); | 25 | DEFINE(TASK_STATE, offsetof(struct task_struct, state)); |
26 | DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags)); | 26 | DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags)); |
27 | DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace)); | 27 | DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace)); |
28 | DEFINE(TASK_WORK, offsetof(struct task_struct, thread.work)); | ||
29 | DEFINE(TASK_NEEDRESCHED, offsetof(struct task_struct, thread.work.need_resched)); | ||
30 | DEFINE(TASK_SYSCALL_TRACE, offsetof(struct task_struct, thread.work.syscall_trace)); | ||
31 | DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, thread.work.sigpending)); | ||
32 | DEFINE(TASK_NOTIFY_RESUME, offsetof(struct task_struct, thread.work.notify_resume)); | ||
33 | DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); | 28 | DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); |
29 | DEFINE(TASK_INFO, offsetof(struct task_struct, thread.info)); | ||
34 | DEFINE(TASK_MM, offsetof(struct task_struct, mm)); | 30 | DEFINE(TASK_MM, offsetof(struct task_struct, mm)); |
35 | DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); | 31 | DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); |
36 | 32 | ||
@@ -45,6 +41,10 @@ int main(void) | |||
45 | DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl)); | 41 | DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl)); |
46 | DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate)); | 42 | DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate)); |
47 | 43 | ||
44 | /* offsets into the thread_info struct */ | ||
45 | DEFINE(TINFO_PREEMPT, offsetof(struct thread_info, preempt_count)); | ||
46 | DEFINE(TINFO_FLAGS, offsetof(struct thread_info, flags)); | ||
47 | |||
48 | /* offsets into the pt_regs */ | 48 | /* offsets into the pt_regs */ |
49 | DEFINE(PT_D0, offsetof(struct pt_regs, d0)); | 49 | DEFINE(PT_D0, offsetof(struct pt_regs, d0)); |
50 | DEFINE(PT_ORIG_D0, offsetof(struct pt_regs, orig_d0)); | 50 | DEFINE(PT_ORIG_D0, offsetof(struct pt_regs, orig_d0)); |
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index 23ca60a45552..320fde05dc63 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S | |||
@@ -44,9 +44,7 @@ | |||
44 | 44 | ||
45 | #include <asm/asm-offsets.h> | 45 | #include <asm/asm-offsets.h> |
46 | 46 | ||
47 | .globl system_call, buserr, trap | 47 | .globl system_call, buserr, trap, resume |
48 | .globl resume, ret_from_exception | ||
49 | .globl ret_from_signal | ||
50 | .globl inthandler, sys_call_table | 48 | .globl inthandler, sys_call_table |
51 | .globl sys_fork, sys_clone, sys_vfork | 49 | .globl sys_fork, sys_clone, sys_vfork |
52 | .globl ret_from_interrupt, bad_interrupt | 50 | .globl ret_from_interrupt, bad_interrupt |
@@ -58,7 +56,7 @@ ENTRY(buserr) | |||
58 | movel %sp,%sp@- | stack frame pointer argument | 56 | movel %sp,%sp@- | stack frame pointer argument |
59 | bsrl buserr_c | 57 | bsrl buserr_c |
60 | addql #4,%sp | 58 | addql #4,%sp |
61 | jra ret_from_exception | 59 | jra .Lret_from_exception |
62 | 60 | ||
63 | ENTRY(trap) | 61 | ENTRY(trap) |
64 | SAVE_ALL_INT | 62 | SAVE_ALL_INT |
@@ -66,7 +64,7 @@ ENTRY(trap) | |||
66 | movel %sp,%sp@- | stack frame pointer argument | 64 | movel %sp,%sp@- | stack frame pointer argument |
67 | bsrl trap_c | 65 | bsrl trap_c |
68 | addql #4,%sp | 66 | addql #4,%sp |
69 | jra ret_from_exception | 67 | jra .Lret_from_exception |
70 | 68 | ||
71 | | After a fork we jump here directly from resume, | 69 | | After a fork we jump here directly from resume, |
72 | | so that %d1 contains the previous task | 70 | | so that %d1 contains the previous task |
@@ -75,30 +73,31 @@ ENTRY(ret_from_fork) | |||
75 | movel %d1,%sp@- | 73 | movel %d1,%sp@- |
76 | jsr schedule_tail | 74 | jsr schedule_tail |
77 | addql #4,%sp | 75 | addql #4,%sp |
78 | jra ret_from_exception | 76 | jra .Lret_from_exception |
79 | 77 | ||
80 | badsys: | 78 | do_trace_entry: |
81 | movel #-ENOSYS,%sp@(PT_D0) | ||
82 | jra ret_from_exception | ||
83 | |||
84 | do_trace: | ||
85 | movel #-ENOSYS,%sp@(PT_D0) | needed for strace | 79 | movel #-ENOSYS,%sp@(PT_D0) | needed for strace |
86 | subql #4,%sp | 80 | subql #4,%sp |
87 | SAVE_SWITCH_STACK | 81 | SAVE_SWITCH_STACK |
88 | jbsr syscall_trace | 82 | jbsr syscall_trace |
89 | RESTORE_SWITCH_STACK | 83 | RESTORE_SWITCH_STACK |
90 | addql #4,%sp | 84 | addql #4,%sp |
91 | movel %sp@(PT_ORIG_D0),%d1 | 85 | movel %sp@(PT_ORIG_D0),%d0 |
92 | movel #-ENOSYS,%d0 | 86 | cmpl #NR_syscalls,%d0 |
93 | cmpl #NR_syscalls,%d1 | 87 | jcs syscall |
94 | jcc 1f | 88 | badsys: |
95 | jbsr @(sys_call_table,%d1:l:4)@(0) | 89 | movel #-ENOSYS,%sp@(PT_D0) |
96 | 1: movel %d0,%sp@(PT_D0) | save the return value | 90 | jra ret_from_syscall |
97 | subql #4,%sp | dummy return address | 91 | |
92 | do_trace_exit: | ||
93 | subql #4,%sp | ||
98 | SAVE_SWITCH_STACK | 94 | SAVE_SWITCH_STACK |
99 | jbsr syscall_trace | 95 | jbsr syscall_trace |
96 | RESTORE_SWITCH_STACK | ||
97 | addql #4,%sp | ||
98 | jra .Lret_from_exception | ||
100 | 99 | ||
101 | ret_from_signal: | 100 | ENTRY(ret_from_signal) |
102 | RESTORE_SWITCH_STACK | 101 | RESTORE_SWITCH_STACK |
103 | addql #4,%sp | 102 | addql #4,%sp |
104 | /* on 68040 complete pending writebacks if any */ | 103 | /* on 68040 complete pending writebacks if any */ |
@@ -111,7 +110,7 @@ ret_from_signal: | |||
111 | addql #4,%sp | 110 | addql #4,%sp |
112 | 1: | 111 | 1: |
113 | #endif | 112 | #endif |
114 | jra ret_from_exception | 113 | jra .Lret_from_exception |
115 | 114 | ||
116 | ENTRY(system_call) | 115 | ENTRY(system_call) |
117 | SAVE_ALL_SYS | 116 | SAVE_ALL_SYS |
@@ -120,30 +119,34 @@ ENTRY(system_call) | |||
120 | | save top of frame | 119 | | save top of frame |
121 | movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) | 120 | movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) |
122 | 121 | ||
123 | tstb %curptr@(TASK_SYSCALL_TRACE) | 122 | | syscall trace? |
124 | jne do_trace | 123 | tstb %curptr@(TASK_INFO+TINFO_FLAGS+2) |
124 | jmi do_trace_entry | ||
125 | cmpl #NR_syscalls,%d0 | 125 | cmpl #NR_syscalls,%d0 |
126 | jcc badsys | 126 | jcc badsys |
127 | syscall: | ||
127 | jbsr @(sys_call_table,%d0:l:4)@(0) | 128 | jbsr @(sys_call_table,%d0:l:4)@(0) |
128 | movel %d0,%sp@(PT_D0) | save the return value | 129 | movel %d0,%sp@(PT_D0) | save the return value |
129 | 130 | ret_from_syscall: | |
130 | |oriw #0x0700,%sr | 131 | |oriw #0x0700,%sr |
131 | movel %curptr@(TASK_WORK),%d0 | 132 | movew %curptr@(TASK_INFO+TINFO_FLAGS+2),%d0 |
132 | jne syscall_exit_work | 133 | jne syscall_exit_work |
133 | 1: RESTORE_ALL | 134 | 1: RESTORE_ALL |
134 | 135 | ||
135 | syscall_exit_work: | 136 | syscall_exit_work: |
136 | btst #5,%sp@(PT_SR) | check if returning to kernel | 137 | btst #5,%sp@(PT_SR) | check if returning to kernel |
137 | bnes 1b | if so, skip resched, signals | 138 | bnes 1b | if so, skip resched, signals |
138 | tstw %d0 | 139 | lslw #1,%d0 |
139 | jeq do_signal_return | 140 | jcs do_trace_exit |
140 | tstb %d0 | 141 | jmi do_delayed_trace |
141 | jne do_delayed_trace | 142 | lslw #8,%d0 |
142 | 143 | jmi do_signal_return | |
143 | pea resume_userspace | 144 | pea resume_userspace |
144 | jmp schedule | 145 | jra schedule |
146 | |||
145 | 147 | ||
146 | ret_from_exception: | 148 | ENTRY(ret_from_exception) |
149 | .Lret_from_exception: | ||
147 | btst #5,%sp@(PT_SR) | check if returning to kernel | 150 | btst #5,%sp@(PT_SR) | check if returning to kernel |
148 | bnes 1f | if so, skip resched, signals | 151 | bnes 1f | if so, skip resched, signals |
149 | | only allow interrupts when we are really the last one on the | 152 | | only allow interrupts when we are really the last one on the |
@@ -152,19 +155,18 @@ ret_from_exception: | |||
152 | andw #ALLOWINT,%sr | 155 | andw #ALLOWINT,%sr |
153 | 156 | ||
154 | resume_userspace: | 157 | resume_userspace: |
155 | movel %curptr@(TASK_WORK),%d0 | 158 | moveb %curptr@(TASK_INFO+TINFO_FLAGS+3),%d0 |
156 | lsrl #8,%d0 | ||
157 | jne exit_work | 159 | jne exit_work |
158 | 1: RESTORE_ALL | 160 | 1: RESTORE_ALL |
159 | 161 | ||
160 | exit_work: | 162 | exit_work: |
161 | | save top of frame | 163 | | save top of frame |
162 | movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) | 164 | movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) |
163 | tstb %d0 | 165 | lslb #1,%d0 |
164 | jeq do_signal_return | 166 | jmi do_signal_return |
165 | |||
166 | pea resume_userspace | 167 | pea resume_userspace |
167 | jmp schedule | 168 | jra schedule |
169 | |||
168 | 170 | ||
169 | do_signal_return: | 171 | do_signal_return: |
170 | |andw #ALLOWINT,%sr | 172 | |andw #ALLOWINT,%sr |
@@ -254,7 +256,7 @@ ret_from_interrupt: | |||
254 | 256 | ||
255 | /* check if we need to do software interrupts */ | 257 | /* check if we need to do software interrupts */ |
256 | tstl irq_stat+CPUSTAT_SOFTIRQ_PENDING | 258 | tstl irq_stat+CPUSTAT_SOFTIRQ_PENDING |
257 | jeq ret_from_exception | 259 | jeq .Lret_from_exception |
258 | pea ret_from_exception | 260 | pea ret_from_exception |
259 | jra do_softirq | 261 | jra do_softirq |
260 | 262 | ||
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c index 7e54422685cf..540638ca81f9 100644 --- a/arch/m68k/kernel/ptrace.c +++ b/arch/m68k/kernel/ptrace.c | |||
@@ -109,7 +109,7 @@ static inline void singlestep_disable(struct task_struct *child) | |||
109 | { | 109 | { |
110 | unsigned long tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); | 110 | unsigned long tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); |
111 | put_reg(child, PT_SR, tmp); | 111 | put_reg(child, PT_SR, tmp); |
112 | child->thread.work.delayed_trace = 0; | 112 | clear_tsk_thread_flag(child, TIF_DELAYED_TRACE); |
113 | } | 113 | } |
114 | 114 | ||
115 | /* | 115 | /* |
@@ -118,7 +118,7 @@ static inline void singlestep_disable(struct task_struct *child) | |||
118 | void ptrace_disable(struct task_struct *child) | 118 | void ptrace_disable(struct task_struct *child) |
119 | { | 119 | { |
120 | singlestep_disable(child); | 120 | singlestep_disable(child); |
121 | child->thread.work.syscall_trace = 0; | 121 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
122 | } | 122 | } |
123 | 123 | ||
124 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 124 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) |
@@ -198,9 +198,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
198 | goto out_eio; | 198 | goto out_eio; |
199 | 199 | ||
200 | if (request == PTRACE_SYSCALL) | 200 | if (request == PTRACE_SYSCALL) |
201 | child->thread.work.syscall_trace = ~0; | 201 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
202 | else | 202 | else |
203 | child->thread.work.syscall_trace = 0; | 203 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
204 | child->exit_code = data; | 204 | child->exit_code = data; |
205 | singlestep_disable(child); | 205 | singlestep_disable(child); |
206 | wake_up_process(child); | 206 | wake_up_process(child); |
@@ -223,10 +223,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
223 | if (!valid_signal(data)) | 223 | if (!valid_signal(data)) |
224 | goto out_eio; | 224 | goto out_eio; |
225 | 225 | ||
226 | child->thread.work.syscall_trace = 0; | 226 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
227 | tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16); | 227 | tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16); |
228 | put_reg(child, PT_SR, tmp); | 228 | put_reg(child, PT_SR, tmp); |
229 | child->thread.work.delayed_trace = 1; | 229 | set_tsk_thread_flag(child, TIF_DELAYED_TRACE); |
230 | 230 | ||
231 | child->exit_code = data; | 231 | child->exit_code = data; |
232 | /* give it a chance to run. */ | 232 | /* give it a chance to run. */ |
@@ -288,9 +288,6 @@ out_eio: | |||
288 | 288 | ||
289 | asmlinkage void syscall_trace(void) | 289 | asmlinkage void syscall_trace(void) |
290 | { | 290 | { |
291 | if (!current->thread.work.delayed_trace && | ||
292 | !current->thread.work.syscall_trace) | ||
293 | return; | ||
294 | ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) | 291 | ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) |
295 | ? 0x80 : 0)); | 292 | ? 0x80 : 0)); |
296 | /* | 293 | /* |
diff --git a/arch/mips/au1000/common/power.c b/arch/mips/au1000/common/power.c index f85093b8d54d..f4926315fb68 100644 --- a/arch/mips/au1000/common/power.c +++ b/arch/mips/au1000/common/power.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/config.h> | 32 | #include <linux/config.h> |
33 | #include <linux/init.h> | 33 | #include <linux/init.h> |
34 | #include <linux/pm.h> | 34 | #include <linux/pm.h> |
35 | #include <linux/pm_legacy.h> | ||
35 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
36 | #include <linux/sysctl.h> | 37 | #include <linux/sysctl.h> |
37 | #include <linux/jiffies.h> | 38 | #include <linux/jiffies.h> |
diff --git a/arch/mips/au1000/common/usbdev.c b/arch/mips/au1000/common/usbdev.c index 0b21bed7ee55..2cab7629702c 100644 --- a/arch/mips/au1000/common/usbdev.c +++ b/arch/mips/au1000/common/usbdev.c | |||
@@ -348,7 +348,7 @@ endpoint_stall(endpoint_t * ep) | |||
348 | { | 348 | { |
349 | u32 cs; | 349 | u32 cs; |
350 | 350 | ||
351 | warn(__FUNCTION__); | 351 | warn("%s", __FUNCTION__); |
352 | 352 | ||
353 | cs = au_readl(ep->reg->ctrl_stat) | USBDEV_CS_STALL; | 353 | cs = au_readl(ep->reg->ctrl_stat) | USBDEV_CS_STALL; |
354 | au_writel(cs, ep->reg->ctrl_stat); | 354 | au_writel(cs, ep->reg->ctrl_stat); |
@@ -360,7 +360,7 @@ endpoint_unstall(endpoint_t * ep) | |||
360 | { | 360 | { |
361 | u32 cs; | 361 | u32 cs; |
362 | 362 | ||
363 | warn(__FUNCTION__); | 363 | warn("%s", __FUNCTION__); |
364 | 364 | ||
365 | cs = au_readl(ep->reg->ctrl_stat) & ~USBDEV_CS_STALL; | 365 | cs = au_readl(ep->reg->ctrl_stat) & ~USBDEV_CS_STALL; |
366 | au_writel(cs, ep->reg->ctrl_stat); | 366 | au_writel(cs, ep->reg->ctrl_stat); |
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index c523029674e6..94df74bcc0ee 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -261,7 +261,7 @@ config PPC_ISERIES | |||
261 | 261 | ||
262 | config EMBEDDED6xx | 262 | config EMBEDDED6xx |
263 | bool "Embedded 6xx/7xx/7xxx-based board" | 263 | bool "Embedded 6xx/7xx/7xxx-based board" |
264 | depends on PPC32 | 264 | depends on PPC32 && BROKEN |
265 | 265 | ||
266 | config APUS | 266 | config APUS |
267 | bool "Amiga-APUS" | 267 | bool "Amiga-APUS" |
@@ -305,7 +305,7 @@ config PPC_PMAC64 | |||
305 | 305 | ||
306 | config PPC_PREP | 306 | config PPC_PREP |
307 | bool " PowerPC Reference Platform (PReP) based machines" | 307 | bool " PowerPC Reference Platform (PReP) based machines" |
308 | depends on PPC_MULTIPLATFORM && PPC32 | 308 | depends on PPC_MULTIPLATFORM && PPC32 && BROKEN |
309 | select PPC_I8259 | 309 | select PPC_I8259 |
310 | select PPC_INDIRECT_PCI | 310 | select PPC_INDIRECT_PCI |
311 | default y | 311 | default y |
@@ -932,6 +932,7 @@ source "arch/powerpc/oprofile/Kconfig" | |||
932 | 932 | ||
933 | config KPROBES | 933 | config KPROBES |
934 | bool "Kprobes (EXPERIMENTAL)" | 934 | bool "Kprobes (EXPERIMENTAL)" |
935 | depends on PPC64 | ||
935 | help | 936 | help |
936 | Kprobes allows you to trap at almost any kernel address and | 937 | Kprobes allows you to trap at almost any kernel address and |
937 | execute a callback function. register_kprobe() establishes | 938 | execute a callback function. register_kprobe() establishes |
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 5bc11bd36c1f..d41ad2e675db 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile | |||
@@ -187,7 +187,7 @@ archprepare: checkbin | |||
187 | 187 | ||
188 | # Temporary hack until we have migrated to asm-powerpc | 188 | # Temporary hack until we have migrated to asm-powerpc |
189 | include/asm: arch/$(ARCH)/include/asm | 189 | include/asm: arch/$(ARCH)/include/asm |
190 | arch/$(ARCH)/include/asm: | 190 | arch/$(ARCH)/include/asm: FORCE |
191 | $(Q)if [ ! -d arch/$(ARCH)/include ]; then mkdir -p arch/$(ARCH)/include; fi | 191 | $(Q)if [ ! -d arch/$(ARCH)/include ]; then mkdir -p arch/$(ARCH)/include; fi |
192 | $(Q)ln -fsn $(srctree)/include/asm-$(OLDARCH) arch/$(ARCH)/include/asm | 192 | $(Q)ln -fsn $(srctree)/include/asm-$(OLDARCH) arch/$(ARCH)/include/asm |
193 | 193 | ||
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig index 9f09dff9e11a..913962c1dae0 100644 --- a/arch/powerpc/configs/pseries_defconfig +++ b/arch/powerpc/configs/pseries_defconfig | |||
@@ -1,18 +1,33 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.14-rc4 | 3 | # Linux kernel version: 2.6.15-rc1 |
4 | # Thu Oct 20 08:32:17 2005 | 4 | # Mon Nov 14 15:27:00 2005 |
5 | # | 5 | # |
6 | CONFIG_PPC64=y | ||
6 | CONFIG_64BIT=y | 7 | CONFIG_64BIT=y |
8 | CONFIG_PPC_MERGE=y | ||
7 | CONFIG_MMU=y | 9 | CONFIG_MMU=y |
10 | CONFIG_GENERIC_HARDIRQS=y | ||
8 | CONFIG_RWSEM_XCHGADD_ALGORITHM=y | 11 | CONFIG_RWSEM_XCHGADD_ALGORITHM=y |
9 | CONFIG_GENERIC_CALIBRATE_DELAY=y | 12 | CONFIG_GENERIC_CALIBRATE_DELAY=y |
10 | CONFIG_GENERIC_ISA_DMA=y | 13 | CONFIG_PPC=y |
11 | CONFIG_EARLY_PRINTK=y | 14 | CONFIG_EARLY_PRINTK=y |
12 | CONFIG_COMPAT=y | 15 | CONFIG_COMPAT=y |
16 | CONFIG_SYSVIPC_COMPAT=y | ||
13 | CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y | 17 | CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y |
14 | CONFIG_ARCH_MAY_HAVE_PC_FDC=y | 18 | CONFIG_ARCH_MAY_HAVE_PC_FDC=y |
15 | CONFIG_FORCE_MAX_ZONEORDER=13 | 19 | |
20 | # | ||
21 | # Processor support | ||
22 | # | ||
23 | # CONFIG_POWER4_ONLY is not set | ||
24 | CONFIG_POWER3=y | ||
25 | CONFIG_POWER4=y | ||
26 | CONFIG_PPC_FPU=y | ||
27 | CONFIG_ALTIVEC=y | ||
28 | CONFIG_PPC_STD_MMU=y | ||
29 | CONFIG_SMP=y | ||
30 | CONFIG_NR_CPUS=128 | ||
16 | 31 | ||
17 | # | 32 | # |
18 | # Code maturity level options | 33 | # Code maturity level options |
@@ -68,75 +83,103 @@ CONFIG_MODVERSIONS=y | |||
68 | CONFIG_MODULE_SRCVERSION_ALL=y | 83 | CONFIG_MODULE_SRCVERSION_ALL=y |
69 | CONFIG_KMOD=y | 84 | CONFIG_KMOD=y |
70 | CONFIG_STOP_MACHINE=y | 85 | CONFIG_STOP_MACHINE=y |
71 | CONFIG_SYSVIPC_COMPAT=y | 86 | |
87 | # | ||
88 | # Block layer | ||
89 | # | ||
90 | |||
91 | # | ||
92 | # IO Schedulers | ||
93 | # | ||
94 | CONFIG_IOSCHED_NOOP=y | ||
95 | CONFIG_IOSCHED_AS=y | ||
96 | CONFIG_IOSCHED_DEADLINE=y | ||
97 | CONFIG_IOSCHED_CFQ=y | ||
98 | CONFIG_DEFAULT_AS=y | ||
99 | # CONFIG_DEFAULT_DEADLINE is not set | ||
100 | # CONFIG_DEFAULT_CFQ is not set | ||
101 | # CONFIG_DEFAULT_NOOP is not set | ||
102 | CONFIG_DEFAULT_IOSCHED="anticipatory" | ||
72 | 103 | ||
73 | # | 104 | # |
74 | # Platform support | 105 | # Platform support |
75 | # | 106 | # |
76 | # CONFIG_PPC_ISERIES is not set | ||
77 | CONFIG_PPC_MULTIPLATFORM=y | 107 | CONFIG_PPC_MULTIPLATFORM=y |
108 | # CONFIG_PPC_ISERIES is not set | ||
109 | # CONFIG_EMBEDDED6xx is not set | ||
110 | # CONFIG_APUS is not set | ||
78 | CONFIG_PPC_PSERIES=y | 111 | CONFIG_PPC_PSERIES=y |
79 | # CONFIG_PPC_BPA is not set | ||
80 | # CONFIG_PPC_PMAC is not set | 112 | # CONFIG_PPC_PMAC is not set |
81 | # CONFIG_PPC_MAPLE is not set | 113 | # CONFIG_PPC_MAPLE is not set |
82 | CONFIG_PPC=y | 114 | # CONFIG_PPC_CELL is not set |
83 | CONFIG_PPC64=y | ||
84 | CONFIG_PPC_OF=y | 115 | CONFIG_PPC_OF=y |
85 | CONFIG_XICS=y | 116 | CONFIG_XICS=y |
117 | # CONFIG_U3_DART is not set | ||
86 | CONFIG_MPIC=y | 118 | CONFIG_MPIC=y |
87 | CONFIG_ALTIVEC=y | 119 | CONFIG_PPC_RTAS=y |
88 | CONFIG_PPC_SPLPAR=y | 120 | CONFIG_RTAS_ERROR_LOGGING=y |
89 | CONFIG_KEXEC=y | 121 | CONFIG_RTAS_PROC=y |
122 | CONFIG_RTAS_FLASH=m | ||
123 | # CONFIG_MMIO_NVRAM is not set | ||
90 | CONFIG_IBMVIO=y | 124 | CONFIG_IBMVIO=y |
91 | # CONFIG_U3_DART is not set | 125 | # CONFIG_PPC_MPC106 is not set |
92 | # CONFIG_BOOTX_TEXT is not set | 126 | # CONFIG_GENERIC_TBSYNC is not set |
93 | # CONFIG_POWER4_ONLY is not set | 127 | # CONFIG_CPU_FREQ is not set |
128 | # CONFIG_WANT_EARLY_SERIAL is not set | ||
129 | |||
130 | # | ||
131 | # Kernel options | ||
132 | # | ||
133 | # CONFIG_HZ_100 is not set | ||
134 | CONFIG_HZ_250=y | ||
135 | # CONFIG_HZ_1000 is not set | ||
136 | CONFIG_HZ=250 | ||
137 | CONFIG_PREEMPT_NONE=y | ||
138 | # CONFIG_PREEMPT_VOLUNTARY is not set | ||
139 | # CONFIG_PREEMPT is not set | ||
140 | # CONFIG_PREEMPT_BKL is not set | ||
141 | CONFIG_BINFMT_ELF=y | ||
142 | # CONFIG_BINFMT_MISC is not set | ||
143 | CONFIG_FORCE_MAX_ZONEORDER=13 | ||
94 | CONFIG_IOMMU_VMERGE=y | 144 | CONFIG_IOMMU_VMERGE=y |
95 | CONFIG_SMP=y | 145 | CONFIG_HOTPLUG_CPU=y |
96 | CONFIG_NR_CPUS=128 | 146 | CONFIG_KEXEC=y |
147 | # CONFIG_IRQ_ALL_CPUS is not set | ||
148 | CONFIG_PPC_SPLPAR=y | ||
149 | CONFIG_EEH=y | ||
150 | CONFIG_SCANLOG=m | ||
151 | CONFIG_LPARCFG=y | ||
152 | CONFIG_NUMA=y | ||
97 | CONFIG_ARCH_SELECT_MEMORY_MODEL=y | 153 | CONFIG_ARCH_SELECT_MEMORY_MODEL=y |
98 | CONFIG_ARCH_FLATMEM_ENABLE=y | ||
99 | CONFIG_ARCH_DISCONTIGMEM_ENABLE=y | ||
100 | CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y | ||
101 | CONFIG_ARCH_SPARSEMEM_ENABLE=y | 154 | CONFIG_ARCH_SPARSEMEM_ENABLE=y |
155 | CONFIG_ARCH_SPARSEMEM_DEFAULT=y | ||
102 | CONFIG_SELECT_MEMORY_MODEL=y | 156 | CONFIG_SELECT_MEMORY_MODEL=y |
103 | # CONFIG_FLATMEM_MANUAL is not set | 157 | # CONFIG_FLATMEM_MANUAL is not set |
104 | CONFIG_DISCONTIGMEM_MANUAL=y | 158 | # CONFIG_DISCONTIGMEM_MANUAL is not set |
105 | # CONFIG_SPARSEMEM_MANUAL is not set | 159 | CONFIG_SPARSEMEM_MANUAL=y |
106 | CONFIG_DISCONTIGMEM=y | 160 | CONFIG_SPARSEMEM=y |
107 | CONFIG_FLAT_NODE_MEM_MAP=y | ||
108 | CONFIG_NEED_MULTIPLE_NODES=y | 161 | CONFIG_NEED_MULTIPLE_NODES=y |
162 | CONFIG_HAVE_MEMORY_PRESENT=y | ||
109 | # CONFIG_SPARSEMEM_STATIC is not set | 163 | # CONFIG_SPARSEMEM_STATIC is not set |
164 | CONFIG_SPARSEMEM_EXTREME=y | ||
165 | # CONFIG_MEMORY_HOTPLUG is not set | ||
166 | CONFIG_SPLIT_PTLOCK_CPUS=4096 | ||
110 | CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y | 167 | CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y |
111 | CONFIG_NODES_SPAN_OTHER_NODES=y | 168 | CONFIG_NODES_SPAN_OTHER_NODES=y |
112 | CONFIG_NUMA=y | 169 | # CONFIG_PPC_64K_PAGES is not set |
113 | CONFIG_SCHED_SMT=y | 170 | CONFIG_SCHED_SMT=y |
114 | CONFIG_PREEMPT_NONE=y | ||
115 | # CONFIG_PREEMPT_VOLUNTARY is not set | ||
116 | # CONFIG_PREEMPT is not set | ||
117 | # CONFIG_PREEMPT_BKL is not set | ||
118 | # CONFIG_HZ_100 is not set | ||
119 | CONFIG_HZ_250=y | ||
120 | # CONFIG_HZ_1000 is not set | ||
121 | CONFIG_HZ=250 | ||
122 | CONFIG_EEH=y | ||
123 | CONFIG_GENERIC_HARDIRQS=y | ||
124 | CONFIG_PPC_RTAS=y | ||
125 | CONFIG_RTAS_PROC=y | ||
126 | CONFIG_RTAS_FLASH=m | ||
127 | CONFIG_SCANLOG=m | ||
128 | CONFIG_LPARCFG=y | ||
129 | CONFIG_SECCOMP=y | ||
130 | CONFIG_BINFMT_ELF=y | ||
131 | # CONFIG_BINFMT_MISC is not set | ||
132 | CONFIG_HOTPLUG_CPU=y | ||
133 | CONFIG_PROC_DEVICETREE=y | 171 | CONFIG_PROC_DEVICETREE=y |
134 | # CONFIG_CMDLINE_BOOL is not set | 172 | # CONFIG_CMDLINE_BOOL is not set |
173 | # CONFIG_PM is not set | ||
174 | CONFIG_SECCOMP=y | ||
135 | CONFIG_ISA_DMA_API=y | 175 | CONFIG_ISA_DMA_API=y |
136 | 176 | ||
137 | # | 177 | # |
138 | # Bus Options | 178 | # Bus options |
139 | # | 179 | # |
180 | CONFIG_GENERIC_ISA_DMA=y | ||
181 | CONFIG_PPC_I8259=y | ||
182 | # CONFIG_PPC_INDIRECT_PCI is not set | ||
140 | CONFIG_PCI=y | 183 | CONFIG_PCI=y |
141 | CONFIG_PCI_DOMAINS=y | 184 | CONFIG_PCI_DOMAINS=y |
142 | CONFIG_PCI_LEGACY_PROC=y | 185 | CONFIG_PCI_LEGACY_PROC=y |
@@ -156,6 +199,7 @@ CONFIG_HOTPLUG_PCI=m | |||
156 | # CONFIG_HOTPLUG_PCI_SHPC is not set | 199 | # CONFIG_HOTPLUG_PCI_SHPC is not set |
157 | CONFIG_HOTPLUG_PCI_RPA=m | 200 | CONFIG_HOTPLUG_PCI_RPA=m |
158 | CONFIG_HOTPLUG_PCI_RPA_DLPAR=m | 201 | CONFIG_HOTPLUG_PCI_RPA_DLPAR=m |
202 | CONFIG_KERNEL_START=0xc000000000000000 | ||
159 | 203 | ||
160 | # | 204 | # |
161 | # Networking | 205 | # Networking |
@@ -197,6 +241,10 @@ CONFIG_TCP_CONG_BIC=y | |||
197 | # CONFIG_IPV6 is not set | 241 | # CONFIG_IPV6 is not set |
198 | CONFIG_NETFILTER=y | 242 | CONFIG_NETFILTER=y |
199 | # CONFIG_NETFILTER_DEBUG is not set | 243 | # CONFIG_NETFILTER_DEBUG is not set |
244 | |||
245 | # | ||
246 | # Core Netfilter Configuration | ||
247 | # | ||
200 | CONFIG_NETFILTER_NETLINK=y | 248 | CONFIG_NETFILTER_NETLINK=y |
201 | CONFIG_NETFILTER_NETLINK_QUEUE=m | 249 | CONFIG_NETFILTER_NETLINK_QUEUE=m |
202 | CONFIG_NETFILTER_NETLINK_LOG=m | 250 | CONFIG_NETFILTER_NETLINK_LOG=m |
@@ -299,6 +347,10 @@ CONFIG_LLC=y | |||
299 | # CONFIG_NET_DIVERT is not set | 347 | # CONFIG_NET_DIVERT is not set |
300 | # CONFIG_ECONET is not set | 348 | # CONFIG_ECONET is not set |
301 | # CONFIG_WAN_ROUTER is not set | 349 | # CONFIG_WAN_ROUTER is not set |
350 | |||
351 | # | ||
352 | # QoS and/or fair queueing | ||
353 | # | ||
302 | # CONFIG_NET_SCHED is not set | 354 | # CONFIG_NET_SCHED is not set |
303 | CONFIG_NET_CLS_ROUTE=y | 355 | CONFIG_NET_CLS_ROUTE=y |
304 | 356 | ||
@@ -368,14 +420,6 @@ CONFIG_BLK_DEV_RAM_COUNT=16 | |||
368 | CONFIG_BLK_DEV_RAM_SIZE=65536 | 420 | CONFIG_BLK_DEV_RAM_SIZE=65536 |
369 | CONFIG_BLK_DEV_INITRD=y | 421 | CONFIG_BLK_DEV_INITRD=y |
370 | # CONFIG_CDROM_PKTCDVD is not set | 422 | # CONFIG_CDROM_PKTCDVD is not set |
371 | |||
372 | # | ||
373 | # IO Schedulers | ||
374 | # | ||
375 | CONFIG_IOSCHED_NOOP=y | ||
376 | CONFIG_IOSCHED_AS=y | ||
377 | CONFIG_IOSCHED_DEADLINE=y | ||
378 | CONFIG_IOSCHED_CFQ=y | ||
379 | # CONFIG_ATA_OVER_ETH is not set | 423 | # CONFIG_ATA_OVER_ETH is not set |
380 | 424 | ||
381 | # | 425 | # |
@@ -473,6 +517,7 @@ CONFIG_SCSI_ISCSI_ATTRS=m | |||
473 | # | 517 | # |
474 | # SCSI low-level drivers | 518 | # SCSI low-level drivers |
475 | # | 519 | # |
520 | # CONFIG_ISCSI_TCP is not set | ||
476 | # CONFIG_BLK_DEV_3W_XXXX_RAID is not set | 521 | # CONFIG_BLK_DEV_3W_XXXX_RAID is not set |
477 | # CONFIG_SCSI_3W_9XXX is not set | 522 | # CONFIG_SCSI_3W_9XXX is not set |
478 | # CONFIG_SCSI_ACARD is not set | 523 | # CONFIG_SCSI_ACARD is not set |
@@ -559,6 +604,7 @@ CONFIG_DM_MULTIPATH_EMC=m | |||
559 | # | 604 | # |
560 | # Macintosh device drivers | 605 | # Macintosh device drivers |
561 | # | 606 | # |
607 | # CONFIG_WINDFARM is not set | ||
562 | 608 | ||
563 | # | 609 | # |
564 | # Network device support | 610 | # Network device support |
@@ -645,7 +691,6 @@ CONFIG_IXGB=m | |||
645 | # CONFIG_IXGB_NAPI is not set | 691 | # CONFIG_IXGB_NAPI is not set |
646 | CONFIG_S2IO=m | 692 | CONFIG_S2IO=m |
647 | # CONFIG_S2IO_NAPI is not set | 693 | # CONFIG_S2IO_NAPI is not set |
648 | # CONFIG_2BUFF_MODE is not set | ||
649 | 694 | ||
650 | # | 695 | # |
651 | # Token Ring devices | 696 | # Token Ring devices |
@@ -674,6 +719,7 @@ CONFIG_PPP_ASYNC=m | |||
674 | CONFIG_PPP_SYNC_TTY=m | 719 | CONFIG_PPP_SYNC_TTY=m |
675 | CONFIG_PPP_DEFLATE=m | 720 | CONFIG_PPP_DEFLATE=m |
676 | CONFIG_PPP_BSDCOMP=m | 721 | CONFIG_PPP_BSDCOMP=m |
722 | # CONFIG_PPP_MPPE is not set | ||
677 | CONFIG_PPPOE=m | 723 | CONFIG_PPPOE=m |
678 | # CONFIG_SLIP is not set | 724 | # CONFIG_SLIP is not set |
679 | # CONFIG_NET_FC is not set | 725 | # CONFIG_NET_FC is not set |
@@ -784,6 +830,8 @@ CONFIG_HVCS=m | |||
784 | # | 830 | # |
785 | # CONFIG_WATCHDOG is not set | 831 | # CONFIG_WATCHDOG is not set |
786 | # CONFIG_RTC is not set | 832 | # CONFIG_RTC is not set |
833 | CONFIG_GEN_RTC=y | ||
834 | # CONFIG_GEN_RTC_X is not set | ||
787 | # CONFIG_DTLK is not set | 835 | # CONFIG_DTLK is not set |
788 | # CONFIG_R3964 is not set | 836 | # CONFIG_R3964 is not set |
789 | # CONFIG_APPLICOM is not set | 837 | # CONFIG_APPLICOM is not set |
@@ -801,6 +849,7 @@ CONFIG_MAX_RAW_DEVS=1024 | |||
801 | # TPM devices | 849 | # TPM devices |
802 | # | 850 | # |
803 | # CONFIG_TCG_TPM is not set | 851 | # CONFIG_TCG_TPM is not set |
852 | # CONFIG_TELCLOCK is not set | ||
804 | 853 | ||
805 | # | 854 | # |
806 | # I2C support | 855 | # I2C support |
@@ -852,6 +901,7 @@ CONFIG_I2C_ALGOBIT=y | |||
852 | # CONFIG_SENSORS_PCF8591 is not set | 901 | # CONFIG_SENSORS_PCF8591 is not set |
853 | # CONFIG_SENSORS_RTC8564 is not set | 902 | # CONFIG_SENSORS_RTC8564 is not set |
854 | # CONFIG_SENSORS_MAX6875 is not set | 903 | # CONFIG_SENSORS_MAX6875 is not set |
904 | # CONFIG_RTC_X1205_I2C is not set | ||
855 | # CONFIG_I2C_DEBUG_CORE is not set | 905 | # CONFIG_I2C_DEBUG_CORE is not set |
856 | # CONFIG_I2C_DEBUG_ALGO is not set | 906 | # CONFIG_I2C_DEBUG_ALGO is not set |
857 | # CONFIG_I2C_DEBUG_BUS is not set | 907 | # CONFIG_I2C_DEBUG_BUS is not set |
@@ -893,7 +943,6 @@ CONFIG_FB=y | |||
893 | CONFIG_FB_CFB_FILLRECT=y | 943 | CONFIG_FB_CFB_FILLRECT=y |
894 | CONFIG_FB_CFB_COPYAREA=y | 944 | CONFIG_FB_CFB_COPYAREA=y |
895 | CONFIG_FB_CFB_IMAGEBLIT=y | 945 | CONFIG_FB_CFB_IMAGEBLIT=y |
896 | CONFIG_FB_SOFT_CURSOR=y | ||
897 | CONFIG_FB_MACMODES=y | 946 | CONFIG_FB_MACMODES=y |
898 | CONFIG_FB_MODE_HELPERS=y | 947 | CONFIG_FB_MODE_HELPERS=y |
899 | CONFIG_FB_TILEBLITTING=y | 948 | CONFIG_FB_TILEBLITTING=y |
@@ -905,6 +954,7 @@ CONFIG_FB_OF=y | |||
905 | # CONFIG_FB_ASILIANT is not set | 954 | # CONFIG_FB_ASILIANT is not set |
906 | # CONFIG_FB_IMSTT is not set | 955 | # CONFIG_FB_IMSTT is not set |
907 | # CONFIG_FB_VGA16 is not set | 956 | # CONFIG_FB_VGA16 is not set |
957 | # CONFIG_FB_S1D13XXX is not set | ||
908 | # CONFIG_FB_NVIDIA is not set | 958 | # CONFIG_FB_NVIDIA is not set |
909 | # CONFIG_FB_RIVA is not set | 959 | # CONFIG_FB_RIVA is not set |
910 | CONFIG_FB_MATROX=y | 960 | CONFIG_FB_MATROX=y |
@@ -927,7 +977,6 @@ CONFIG_FB_RADEON_I2C=y | |||
927 | # CONFIG_FB_VOODOO1 is not set | 977 | # CONFIG_FB_VOODOO1 is not set |
928 | # CONFIG_FB_CYBLA is not set | 978 | # CONFIG_FB_CYBLA is not set |
929 | # CONFIG_FB_TRIDENT is not set | 979 | # CONFIG_FB_TRIDENT is not set |
930 | # CONFIG_FB_S1D13XXX is not set | ||
931 | # CONFIG_FB_VIRTUAL is not set | 980 | # CONFIG_FB_VIRTUAL is not set |
932 | 981 | ||
933 | # | 982 | # |
@@ -936,6 +985,7 @@ CONFIG_FB_RADEON_I2C=y | |||
936 | # CONFIG_VGA_CONSOLE is not set | 985 | # CONFIG_VGA_CONSOLE is not set |
937 | CONFIG_DUMMY_CONSOLE=y | 986 | CONFIG_DUMMY_CONSOLE=y |
938 | CONFIG_FRAMEBUFFER_CONSOLE=y | 987 | CONFIG_FRAMEBUFFER_CONSOLE=y |
988 | # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set | ||
939 | # CONFIG_FONTS is not set | 989 | # CONFIG_FONTS is not set |
940 | CONFIG_FONT_8x8=y | 990 | CONFIG_FONT_8x8=y |
941 | CONFIG_FONT_8x16=y | 991 | CONFIG_FONT_8x16=y |
@@ -990,12 +1040,15 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y | |||
990 | # | 1040 | # |
991 | # USB Device Class drivers | 1041 | # USB Device Class drivers |
992 | # | 1042 | # |
993 | # CONFIG_USB_BLUETOOTH_TTY is not set | ||
994 | # CONFIG_USB_ACM is not set | 1043 | # CONFIG_USB_ACM is not set |
995 | # CONFIG_USB_PRINTER is not set | 1044 | # CONFIG_USB_PRINTER is not set |
996 | 1045 | ||
997 | # | 1046 | # |
998 | # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information | 1047 | # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' |
1048 | # | ||
1049 | |||
1050 | # | ||
1051 | # may also be needed; see USB_STORAGE Help for more information | ||
999 | # | 1052 | # |
1000 | CONFIG_USB_STORAGE=y | 1053 | CONFIG_USB_STORAGE=y |
1001 | # CONFIG_USB_STORAGE_DEBUG is not set | 1054 | # CONFIG_USB_STORAGE_DEBUG is not set |
@@ -1106,6 +1159,7 @@ CONFIG_INFINIBAND_MTHCA=m | |||
1106 | # CONFIG_INFINIBAND_MTHCA_DEBUG is not set | 1159 | # CONFIG_INFINIBAND_MTHCA_DEBUG is not set |
1107 | CONFIG_INFINIBAND_IPOIB=m | 1160 | CONFIG_INFINIBAND_IPOIB=m |
1108 | # CONFIG_INFINIBAND_IPOIB_DEBUG is not set | 1161 | # CONFIG_INFINIBAND_IPOIB_DEBUG is not set |
1162 | # CONFIG_INFINIBAND_SRP is not set | ||
1109 | 1163 | ||
1110 | # | 1164 | # |
1111 | # SN Devices | 1165 | # SN Devices |
@@ -1288,10 +1342,25 @@ CONFIG_NLS_ISO8859_1=y | |||
1288 | # CONFIG_NLS_UTF8 is not set | 1342 | # CONFIG_NLS_UTF8 is not set |
1289 | 1343 | ||
1290 | # | 1344 | # |
1291 | # Profiling support | 1345 | # Library routines |
1346 | # | ||
1347 | CONFIG_CRC_CCITT=m | ||
1348 | # CONFIG_CRC16 is not set | ||
1349 | CONFIG_CRC32=y | ||
1350 | CONFIG_LIBCRC32C=m | ||
1351 | CONFIG_ZLIB_INFLATE=y | ||
1352 | CONFIG_ZLIB_DEFLATE=m | ||
1353 | CONFIG_TEXTSEARCH=y | ||
1354 | CONFIG_TEXTSEARCH_KMP=m | ||
1355 | CONFIG_TEXTSEARCH_BM=m | ||
1356 | CONFIG_TEXTSEARCH_FSM=m | ||
1357 | |||
1358 | # | ||
1359 | # Instrumentation Support | ||
1292 | # | 1360 | # |
1293 | CONFIG_PROFILING=y | 1361 | CONFIG_PROFILING=y |
1294 | CONFIG_OPROFILE=y | 1362 | CONFIG_OPROFILE=y |
1363 | # CONFIG_KPROBES is not set | ||
1295 | 1364 | ||
1296 | # | 1365 | # |
1297 | # Kernel hacking | 1366 | # Kernel hacking |
@@ -1308,14 +1377,15 @@ CONFIG_DETECT_SOFTLOCKUP=y | |||
1308 | # CONFIG_DEBUG_KOBJECT is not set | 1377 | # CONFIG_DEBUG_KOBJECT is not set |
1309 | # CONFIG_DEBUG_INFO is not set | 1378 | # CONFIG_DEBUG_INFO is not set |
1310 | CONFIG_DEBUG_FS=y | 1379 | CONFIG_DEBUG_FS=y |
1380 | # CONFIG_DEBUG_VM is not set | ||
1381 | # CONFIG_RCU_TORTURE_TEST is not set | ||
1311 | CONFIG_DEBUG_STACKOVERFLOW=y | 1382 | CONFIG_DEBUG_STACKOVERFLOW=y |
1312 | # CONFIG_KPROBES is not set | ||
1313 | CONFIG_DEBUG_STACK_USAGE=y | 1383 | CONFIG_DEBUG_STACK_USAGE=y |
1314 | CONFIG_DEBUGGER=y | 1384 | CONFIG_DEBUGGER=y |
1315 | CONFIG_XMON=y | 1385 | CONFIG_XMON=y |
1316 | CONFIG_XMON_DEFAULT=y | 1386 | CONFIG_XMON_DEFAULT=y |
1317 | # CONFIG_PPCDBG is not set | ||
1318 | CONFIG_IRQSTACKS=y | 1387 | CONFIG_IRQSTACKS=y |
1388 | # CONFIG_BOOTX_TEXT is not set | ||
1319 | 1389 | ||
1320 | # | 1390 | # |
1321 | # Security options | 1391 | # Security options |
@@ -1355,17 +1425,3 @@ CONFIG_CRYPTO_TEST=m | |||
1355 | # | 1425 | # |
1356 | # Hardware crypto devices | 1426 | # Hardware crypto devices |
1357 | # | 1427 | # |
1358 | |||
1359 | # | ||
1360 | # Library routines | ||
1361 | # | ||
1362 | CONFIG_CRC_CCITT=m | ||
1363 | # CONFIG_CRC16 is not set | ||
1364 | CONFIG_CRC32=y | ||
1365 | CONFIG_LIBCRC32C=m | ||
1366 | CONFIG_ZLIB_INFLATE=y | ||
1367 | CONFIG_ZLIB_DEFLATE=m | ||
1368 | CONFIG_TEXTSEARCH=y | ||
1369 | CONFIG_TEXTSEARCH_KMP=m | ||
1370 | CONFIG_TEXTSEARCH_BM=m | ||
1371 | CONFIG_TEXTSEARCH_FSM=m | ||
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 9a74b7ab03a4..4970e3721a84 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -25,7 +25,7 @@ obj-$(CONFIG_PPC_OF) += of_device.o | |||
25 | procfs-$(CONFIG_PPC64) := proc_ppc64.o | 25 | procfs-$(CONFIG_PPC64) := proc_ppc64.o |
26 | obj-$(CONFIG_PROC_FS) += $(procfs-y) | 26 | obj-$(CONFIG_PROC_FS) += $(procfs-y) |
27 | rtaspci-$(CONFIG_PPC64) := rtas_pci.o | 27 | rtaspci-$(CONFIG_PPC64) := rtas_pci.o |
28 | obj-$(CONFIG_PPC_RTAS) += rtas.o $(rtaspci-y) | 28 | obj-$(CONFIG_PPC_RTAS) += rtas.o rtas-rtc.o $(rtaspci-y) |
29 | obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o | 29 | obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o |
30 | obj-$(CONFIG_RTAS_PROC) += rtas-proc.o | 30 | obj-$(CONFIG_RTAS_PROC) += rtas-proc.o |
31 | obj-$(CONFIG_LPARCFG) += lparcfg.o | 31 | obj-$(CONFIG_LPARCFG) += lparcfg.o |
@@ -49,12 +49,23 @@ extra-y += vmlinux.lds | |||
49 | obj-y += process.o init_task.o time.o \ | 49 | obj-y += process.o init_task.o time.o \ |
50 | prom.o traps.o setup-common.o | 50 | prom.o traps.o setup-common.o |
51 | obj-$(CONFIG_PPC32) += entry_32.o setup_32.o misc_32.o systbl.o | 51 | obj-$(CONFIG_PPC32) += entry_32.o setup_32.o misc_32.o systbl.o |
52 | obj-$(CONFIG_PPC64) += misc_64.o | 52 | obj-$(CONFIG_PPC64) += misc_64.o dma_64.o iommu.o |
53 | obj-$(CONFIG_PPC_OF) += prom_init.o | 53 | obj-$(CONFIG_PPC_OF) += prom_init.o |
54 | obj-$(CONFIG_MODULES) += ppc_ksyms.o | 54 | obj-$(CONFIG_MODULES) += ppc_ksyms.o |
55 | obj-$(CONFIG_BOOTX_TEXT) += btext.o | 55 | obj-$(CONFIG_BOOTX_TEXT) += btext.o |
56 | obj-$(CONFIG_6xx) += idle_6xx.o | 56 | obj-$(CONFIG_6xx) += idle_6xx.o |
57 | obj-$(CONFIG_SMP) += smp.o | 57 | obj-$(CONFIG_SMP) += smp.o |
58 | obj-$(CONFIG_KPROBES) += kprobes.o | ||
59 | |||
60 | module-$(CONFIG_PPC64) += module_64.o | ||
61 | obj-$(CONFIG_MODULES) += $(module-y) | ||
62 | |||
63 | pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o pci_iommu.o \ | ||
64 | pci_direct_iommu.o iomap.o | ||
65 | obj-$(CONFIG_PCI) += $(pci64-y) | ||
66 | |||
67 | kexec64-$(CONFIG_PPC64) += machine_kexec_64.o | ||
68 | obj-$(CONFIG_KEXEC) += $(kexec64-y) | ||
58 | 69 | ||
59 | ifeq ($(CONFIG_PPC_ISERIES),y) | 70 | ifeq ($(CONFIG_PPC_ISERIES),y) |
60 | $(obj)/head_64.o: $(obj)/lparmap.s | 71 | $(obj)/head_64.o: $(obj)/lparmap.s |
@@ -62,11 +73,8 @@ AFLAGS_head_64.o += -I$(obj) | |||
62 | endif | 73 | endif |
63 | 74 | ||
64 | else | 75 | else |
65 | # stuff used from here for ARCH=ppc or ARCH=ppc64 | 76 | # stuff used from here for ARCH=ppc |
66 | smpobj-$(CONFIG_SMP) += smp.o | 77 | smpobj-$(CONFIG_SMP) += smp.o |
67 | obj-$(CONFIG_PPC64) += traps.o process.o init_task.o time.o \ | ||
68 | setup-common.o $(smpobj-y) | ||
69 | |||
70 | 78 | ||
71 | endif | 79 | endif |
72 | 80 | ||
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 4550eb4f4fbd..91538d2445bf 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -270,13 +270,15 @@ int main(void) | |||
270 | DEFINE(TVAL64_TV_USEC, offsetof(struct timeval, tv_usec)); | 270 | DEFINE(TVAL64_TV_USEC, offsetof(struct timeval, tv_usec)); |
271 | DEFINE(TVAL32_TV_SEC, offsetof(struct compat_timeval, tv_sec)); | 271 | DEFINE(TVAL32_TV_SEC, offsetof(struct compat_timeval, tv_sec)); |
272 | DEFINE(TVAL32_TV_USEC, offsetof(struct compat_timeval, tv_usec)); | 272 | DEFINE(TVAL32_TV_USEC, offsetof(struct compat_timeval, tv_usec)); |
273 | DEFINE(TSPC64_TV_SEC, offsetof(struct timespec, tv_sec)); | ||
274 | DEFINE(TSPC64_TV_NSEC, offsetof(struct timespec, tv_nsec)); | ||
273 | DEFINE(TSPC32_TV_SEC, offsetof(struct compat_timespec, tv_sec)); | 275 | DEFINE(TSPC32_TV_SEC, offsetof(struct compat_timespec, tv_sec)); |
274 | DEFINE(TSPC32_TV_NSEC, offsetof(struct compat_timespec, tv_nsec)); | 276 | DEFINE(TSPC32_TV_NSEC, offsetof(struct compat_timespec, tv_nsec)); |
275 | #else | 277 | #else |
276 | DEFINE(TVAL32_TV_SEC, offsetof(struct timeval, tv_sec)); | 278 | DEFINE(TVAL32_TV_SEC, offsetof(struct timeval, tv_sec)); |
277 | DEFINE(TVAL32_TV_USEC, offsetof(struct timeval, tv_usec)); | 279 | DEFINE(TVAL32_TV_USEC, offsetof(struct timeval, tv_usec)); |
278 | DEFINE(TSPEC32_TV_SEC, offsetof(struct timespec, tv_sec)); | 280 | DEFINE(TSPC32_TV_SEC, offsetof(struct timespec, tv_sec)); |
279 | DEFINE(TSPEC32_TV_NSEC, offsetof(struct timespec, tv_nsec)); | 281 | DEFINE(TSPC32_TV_NSEC, offsetof(struct timespec, tv_nsec)); |
280 | #endif | 282 | #endif |
281 | /* timeval/timezone offsets for use by vdso */ | 283 | /* timeval/timezone offsets for use by vdso */ |
282 | DEFINE(TZONE_TZ_MINWEST, offsetof(struct timezone, tz_minuteswest)); | 284 | DEFINE(TZONE_TZ_MINWEST, offsetof(struct timezone, tz_minuteswest)); |
diff --git a/arch/ppc64/kernel/dma.c b/arch/powerpc/kernel/dma_64.c index 7c3419656ccc..7c3419656ccc 100644 --- a/arch/ppc64/kernel/dma.c +++ b/arch/powerpc/kernel/dma_64.c | |||
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 5063c603fad4..8d60fa99fc4b 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S | |||
@@ -24,7 +24,7 @@ | |||
24 | * Copyright 2002-2004 MontaVista Software, Inc. | 24 | * Copyright 2002-2004 MontaVista Software, Inc. |
25 | * PowerPC 44x support, Matt Porter <mporter@kernel.crashing.org> | 25 | * PowerPC 44x support, Matt Porter <mporter@kernel.crashing.org> |
26 | * Copyright 2004 Freescale Semiconductor, Inc | 26 | * Copyright 2004 Freescale Semiconductor, Inc |
27 | * PowerPC e500 modifications, Kumar Gala <kumar.gala@freescale.com> | 27 | * PowerPC e500 modifications, Kumar Gala <galak@kernel.crashing.org> |
28 | * | 28 | * |
29 | * This program is free software; you can redistribute it and/or modify it | 29 | * This program is free software; you can redistribute it and/or modify it |
30 | * under the terms of the GNU General Public License as published by the | 30 | * under the terms of the GNU General Public License as published by the |
diff --git a/arch/ppc64/kernel/iomap.c b/arch/powerpc/kernel/iomap.c index 6160c8dbb7c5..6160c8dbb7c5 100644 --- a/arch/ppc64/kernel/iomap.c +++ b/arch/powerpc/kernel/iomap.c | |||
diff --git a/arch/ppc64/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 4d9b4388918b..4d9b4388918b 100644 --- a/arch/ppc64/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c | |||
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 4b7940693f3d..5a71ed9612fe 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -71,6 +71,11 @@ | |||
71 | #include <asm/paca.h> | 71 | #include <asm/paca.h> |
72 | #endif | 72 | #endif |
73 | 73 | ||
74 | int __irq_offset_value; | ||
75 | #ifdef CONFIG_PPC32 | ||
76 | EXPORT_SYMBOL(__irq_offset_value); | ||
77 | #endif | ||
78 | |||
74 | static int ppc_spurious_interrupts; | 79 | static int ppc_spurious_interrupts; |
75 | 80 | ||
76 | #if defined(CONFIG_PPC_ISERIES) && defined(CONFIG_SMP) | 81 | #if defined(CONFIG_PPC_ISERIES) && defined(CONFIG_SMP) |
@@ -98,7 +103,6 @@ extern atomic_t ipi_sent; | |||
98 | EXPORT_SYMBOL(irq_desc); | 103 | EXPORT_SYMBOL(irq_desc); |
99 | 104 | ||
100 | int distribute_irqs = 1; | 105 | int distribute_irqs = 1; |
101 | int __irq_offset_value; | ||
102 | u64 ppc64_interrupt_controller; | 106 | u64 ppc64_interrupt_controller; |
103 | #endif /* CONFIG_PPC64 */ | 107 | #endif /* CONFIG_PPC64 */ |
104 | 108 | ||
@@ -311,7 +315,6 @@ void __init init_IRQ(void) | |||
311 | } | 315 | } |
312 | 316 | ||
313 | #ifdef CONFIG_PPC64 | 317 | #ifdef CONFIG_PPC64 |
314 | #ifndef CONFIG_PPC_ISERIES | ||
315 | /* | 318 | /* |
316 | * Virtual IRQ mapping code, used on systems with XICS interrupt controllers. | 319 | * Virtual IRQ mapping code, used on systems with XICS interrupt controllers. |
317 | */ | 320 | */ |
@@ -420,8 +423,6 @@ unsigned int real_irq_to_virt_slowpath(unsigned int real_irq) | |||
420 | 423 | ||
421 | } | 424 | } |
422 | 425 | ||
423 | #endif /* CONFIG_PPC_ISERIES */ | ||
424 | |||
425 | #ifdef CONFIG_IRQSTACKS | 426 | #ifdef CONFIG_IRQSTACKS |
426 | struct thread_info *softirq_ctx[NR_CPUS]; | 427 | struct thread_info *softirq_ctx[NR_CPUS]; |
427 | struct thread_info *hardirq_ctx[NR_CPUS]; | 428 | struct thread_info *hardirq_ctx[NR_CPUS]; |
diff --git a/arch/ppc64/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index 511af54e6230..511af54e6230 100644 --- a/arch/ppc64/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c | |||
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index 1b3ba8a440a6..9dda16ccde78 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c | |||
@@ -42,32 +42,6 @@ | |||
42 | 42 | ||
43 | /* #define LPARCFG_DEBUG */ | 43 | /* #define LPARCFG_DEBUG */ |
44 | 44 | ||
45 | /* find a better place for this function... */ | ||
46 | static void log_plpar_hcall_return(unsigned long rc, char *tag) | ||
47 | { | ||
48 | if (rc == 0) /* success, return */ | ||
49 | return; | ||
50 | /* check for null tag ? */ | ||
51 | if (rc == H_Hardware) | ||
52 | printk(KERN_INFO | ||
53 | "plpar-hcall (%s) failed with hardware fault\n", tag); | ||
54 | else if (rc == H_Function) | ||
55 | printk(KERN_INFO | ||
56 | "plpar-hcall (%s) failed; function not allowed\n", tag); | ||
57 | else if (rc == H_Authority) | ||
58 | printk(KERN_INFO | ||
59 | "plpar-hcall (%s) failed; not authorized to this function\n", | ||
60 | tag); | ||
61 | else if (rc == H_Parameter) | ||
62 | printk(KERN_INFO "plpar-hcall (%s) failed; Bad parameter(s)\n", | ||
63 | tag); | ||
64 | else | ||
65 | printk(KERN_INFO | ||
66 | "plpar-hcall (%s) failed with unexpected rc(0x%lx)\n", | ||
67 | tag, rc); | ||
68 | |||
69 | } | ||
70 | |||
71 | static struct proc_dir_entry *proc_ppc64_lparcfg; | 45 | static struct proc_dir_entry *proc_ppc64_lparcfg; |
72 | #define LPARCFG_BUFF_SIZE 4096 | 46 | #define LPARCFG_BUFF_SIZE 4096 |
73 | 47 | ||
@@ -172,6 +146,31 @@ static int lparcfg_data(struct seq_file *m, void *v) | |||
172 | /* | 146 | /* |
173 | * Methods used to fetch LPAR data when running on a pSeries platform. | 147 | * Methods used to fetch LPAR data when running on a pSeries platform. |
174 | */ | 148 | */ |
149 | /* find a better place for this function... */ | ||
150 | static void log_plpar_hcall_return(unsigned long rc, char *tag) | ||
151 | { | ||
152 | if (rc == 0) /* success, return */ | ||
153 | return; | ||
154 | /* check for null tag ? */ | ||
155 | if (rc == H_Hardware) | ||
156 | printk(KERN_INFO | ||
157 | "plpar-hcall (%s) failed with hardware fault\n", tag); | ||
158 | else if (rc == H_Function) | ||
159 | printk(KERN_INFO | ||
160 | "plpar-hcall (%s) failed; function not allowed\n", tag); | ||
161 | else if (rc == H_Authority) | ||
162 | printk(KERN_INFO | ||
163 | "plpar-hcall (%s) failed; not authorized to this function\n", | ||
164 | tag); | ||
165 | else if (rc == H_Parameter) | ||
166 | printk(KERN_INFO "plpar-hcall (%s) failed; Bad parameter(s)\n", | ||
167 | tag); | ||
168 | else | ||
169 | printk(KERN_INFO | ||
170 | "plpar-hcall (%s) failed with unexpected rc(0x%lx)\n", | ||
171 | tag, rc); | ||
172 | |||
173 | } | ||
175 | 174 | ||
176 | /* | 175 | /* |
177 | * H_GET_PPP hcall returns info in 4 parms. | 176 | * H_GET_PPP hcall returns info in 4 parms. |
diff --git a/arch/ppc64/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec_64.c index 07ea03598c00..97c51e452be7 100644 --- a/arch/ppc64/kernel/machine_kexec.c +++ b/arch/powerpc/kernel/machine_kexec_64.c | |||
@@ -185,8 +185,8 @@ void kexec_copy_flush(struct kimage *image) | |||
185 | */ | 185 | */ |
186 | void kexec_smp_down(void *arg) | 186 | void kexec_smp_down(void *arg) |
187 | { | 187 | { |
188 | if (ppc_md.cpu_irq_down) | 188 | if (ppc_md.kexec_cpu_down) |
189 | ppc_md.cpu_irq_down(1); | 189 | ppc_md.kexec_cpu_down(0, 1); |
190 | 190 | ||
191 | local_irq_disable(); | 191 | local_irq_disable(); |
192 | kexec_smp_wait(); | 192 | kexec_smp_wait(); |
@@ -233,8 +233,8 @@ static void kexec_prepare_cpus(void) | |||
233 | } | 233 | } |
234 | 234 | ||
235 | /* after we tell the others to go down */ | 235 | /* after we tell the others to go down */ |
236 | if (ppc_md.cpu_irq_down) | 236 | if (ppc_md.kexec_cpu_down) |
237 | ppc_md.cpu_irq_down(0); | 237 | ppc_md.kexec_cpu_down(0, 0); |
238 | 238 | ||
239 | put_cpu(); | 239 | put_cpu(); |
240 | 240 | ||
@@ -255,8 +255,8 @@ static void kexec_prepare_cpus(void) | |||
255 | * UP to an SMP kernel. | 255 | * UP to an SMP kernel. |
256 | */ | 256 | */ |
257 | smp_release_cpus(); | 257 | smp_release_cpus(); |
258 | if (ppc_md.cpu_irq_down) | 258 | if (ppc_md.kexec_cpu_down) |
259 | ppc_md.cpu_irq_down(0); | 259 | ppc_md.kexec_cpu_down(0, 0); |
260 | local_irq_disable(); | 260 | local_irq_disable(); |
261 | } | 261 | } |
262 | 262 | ||
@@ -305,3 +305,54 @@ void machine_kexec(struct kimage *image) | |||
305 | ppc_md.hpte_clear_all); | 305 | ppc_md.hpte_clear_all); |
306 | /* NOTREACHED */ | 306 | /* NOTREACHED */ |
307 | } | 307 | } |
308 | |||
309 | /* Values we need to export to the second kernel via the device tree. */ | ||
310 | static unsigned long htab_base, htab_size, kernel_end; | ||
311 | |||
312 | static struct property htab_base_prop = { | ||
313 | .name = "linux,htab-base", | ||
314 | .length = sizeof(unsigned long), | ||
315 | .value = (unsigned char *)&htab_base, | ||
316 | }; | ||
317 | |||
318 | static struct property htab_size_prop = { | ||
319 | .name = "linux,htab-size", | ||
320 | .length = sizeof(unsigned long), | ||
321 | .value = (unsigned char *)&htab_size, | ||
322 | }; | ||
323 | |||
324 | static struct property kernel_end_prop = { | ||
325 | .name = "linux,kernel-end", | ||
326 | .length = sizeof(unsigned long), | ||
327 | .value = (unsigned char *)&kernel_end, | ||
328 | }; | ||
329 | |||
330 | static void __init export_htab_values(void) | ||
331 | { | ||
332 | struct device_node *node; | ||
333 | |||
334 | node = of_find_node_by_path("/chosen"); | ||
335 | if (!node) | ||
336 | return; | ||
337 | |||
338 | kernel_end = __pa(_end); | ||
339 | prom_add_property(node, &kernel_end_prop); | ||
340 | |||
341 | /* On machines with no htab htab_address is NULL */ | ||
342 | if (NULL == htab_address) | ||
343 | goto out; | ||
344 | |||
345 | htab_base = __pa(htab_address); | ||
346 | prom_add_property(node, &htab_base_prop); | ||
347 | |||
348 | htab_size = 1UL << ppc64_pft_size; | ||
349 | prom_add_property(node, &htab_size_prop); | ||
350 | |||
351 | out: | ||
352 | of_node_put(node); | ||
353 | } | ||
354 | |||
355 | void __init kexec_setup(void) | ||
356 | { | ||
357 | export_htab_values(); | ||
358 | } | ||
diff --git a/arch/ppc64/kernel/module.c b/arch/powerpc/kernel/module_64.c index 928b8581fcb0..928b8581fcb0 100644 --- a/arch/ppc64/kernel/module.c +++ b/arch/powerpc/kernel/module_64.c | |||
diff --git a/arch/ppc64/kernel/pci.c b/arch/powerpc/kernel/pci_64.c index 3cef1b8f57f0..3cef1b8f57f0 100644 --- a/arch/ppc64/kernel/pci.c +++ b/arch/powerpc/kernel/pci_64.c | |||
diff --git a/arch/ppc64/kernel/pci_direct_iommu.c b/arch/powerpc/kernel/pci_direct_iommu.c index e1a32f802c0b..e1a32f802c0b 100644 --- a/arch/ppc64/kernel/pci_direct_iommu.c +++ b/arch/powerpc/kernel/pci_direct_iommu.c | |||
diff --git a/arch/ppc64/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c index 12c4c9e9bbc7..12c4c9e9bbc7 100644 --- a/arch/ppc64/kernel/pci_dn.c +++ b/arch/powerpc/kernel/pci_dn.c | |||
diff --git a/arch/ppc64/kernel/pci_iommu.c b/arch/powerpc/kernel/pci_iommu.c index bdf15dbbf4f0..bdf15dbbf4f0 100644 --- a/arch/ppc64/kernel/pci_iommu.c +++ b/arch/powerpc/kernel/pci_iommu.c | |||
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index 5dcf4ba05ee8..59846b40d521 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c | |||
@@ -105,6 +105,13 @@ EXPORT_SYMBOL(__clear_user); | |||
105 | EXPORT_SYMBOL(__strncpy_from_user); | 105 | EXPORT_SYMBOL(__strncpy_from_user); |
106 | EXPORT_SYMBOL(__strnlen_user); | 106 | EXPORT_SYMBOL(__strnlen_user); |
107 | 107 | ||
108 | #ifndef __powerpc64__ | ||
109 | EXPORT_SYMBOL(__ide_mm_insl); | ||
110 | EXPORT_SYMBOL(__ide_mm_outsw); | ||
111 | EXPORT_SYMBOL(__ide_mm_insw); | ||
112 | EXPORT_SYMBOL(__ide_mm_outsl); | ||
113 | #endif | ||
114 | |||
108 | EXPORT_SYMBOL(_insb); | 115 | EXPORT_SYMBOL(_insb); |
109 | EXPORT_SYMBOL(_outsb); | 116 | EXPORT_SYMBOL(_outsb); |
110 | EXPORT_SYMBOL(_insw); | 117 | EXPORT_SYMBOL(_insw); |
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 6a5b468edb4d..3bf968e74095 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -1368,6 +1368,7 @@ prom_n_addr_cells(struct device_node* np) | |||
1368 | /* No #address-cells property for the root node, default to 1 */ | 1368 | /* No #address-cells property for the root node, default to 1 */ |
1369 | return 1; | 1369 | return 1; |
1370 | } | 1370 | } |
1371 | EXPORT_SYMBOL(prom_n_addr_cells); | ||
1371 | 1372 | ||
1372 | int | 1373 | int |
1373 | prom_n_size_cells(struct device_node* np) | 1374 | prom_n_size_cells(struct device_node* np) |
@@ -1383,6 +1384,7 @@ prom_n_size_cells(struct device_node* np) | |||
1383 | /* No #size-cells property for the root node, default to 1 */ | 1384 | /* No #size-cells property for the root node, default to 1 */ |
1384 | return 1; | 1385 | return 1; |
1385 | } | 1386 | } |
1387 | EXPORT_SYMBOL(prom_n_size_cells); | ||
1386 | 1388 | ||
1387 | /** | 1389 | /** |
1388 | * Work out the sense (active-low level / active-high edge) | 1390 | * Work out the sense (active-low level / active-high edge) |
diff --git a/arch/powerpc/kernel/rtas-rtc.c b/arch/powerpc/kernel/rtas-rtc.c new file mode 100644 index 000000000000..7b948662704c --- /dev/null +++ b/arch/powerpc/kernel/rtas-rtc.c | |||
@@ -0,0 +1,105 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/time.h> | ||
3 | #include <linux/timer.h> | ||
4 | #include <linux/init.h> | ||
5 | #include <linux/rtc.h> | ||
6 | #include <linux/delay.h> | ||
7 | #include <asm/prom.h> | ||
8 | #include <asm/rtas.h> | ||
9 | #include <asm/time.h> | ||
10 | |||
11 | |||
12 | #define MAX_RTC_WAIT 5000 /* 5 sec */ | ||
13 | #define RTAS_CLOCK_BUSY (-2) | ||
14 | unsigned long __init rtas_get_boot_time(void) | ||
15 | { | ||
16 | int ret[8]; | ||
17 | int error, wait_time; | ||
18 | unsigned long max_wait_tb; | ||
19 | |||
20 | max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; | ||
21 | do { | ||
22 | error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); | ||
23 | if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { | ||
24 | wait_time = rtas_extended_busy_delay_time(error); | ||
25 | /* This is boot time so we spin. */ | ||
26 | udelay(wait_time*1000); | ||
27 | error = RTAS_CLOCK_BUSY; | ||
28 | } | ||
29 | } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb)); | ||
30 | |||
31 | if (error != 0 && printk_ratelimit()) { | ||
32 | printk(KERN_WARNING "error: reading the clock failed (%d)\n", | ||
33 | error); | ||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | return mktime(ret[0], ret[1], ret[2], ret[3], ret[4], ret[5]); | ||
38 | } | ||
39 | |||
40 | /* NOTE: get_rtc_time will get an error if executed in interrupt context | ||
41 | * and if a delay is needed to read the clock. In this case we just | ||
42 | * silently return without updating rtc_tm. | ||
43 | */ | ||
44 | void rtas_get_rtc_time(struct rtc_time *rtc_tm) | ||
45 | { | ||
46 | int ret[8]; | ||
47 | int error, wait_time; | ||
48 | unsigned long max_wait_tb; | ||
49 | |||
50 | max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; | ||
51 | do { | ||
52 | error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); | ||
53 | if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { | ||
54 | if (in_interrupt() && printk_ratelimit()) { | ||
55 | memset(&rtc_tm, 0, sizeof(struct rtc_time)); | ||
56 | printk(KERN_WARNING "error: reading clock" | ||
57 | " would delay interrupt\n"); | ||
58 | return; /* delay not allowed */ | ||
59 | } | ||
60 | wait_time = rtas_extended_busy_delay_time(error); | ||
61 | msleep(wait_time); | ||
62 | error = RTAS_CLOCK_BUSY; | ||
63 | } | ||
64 | } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb)); | ||
65 | |||
66 | if (error != 0 && printk_ratelimit()) { | ||
67 | printk(KERN_WARNING "error: reading the clock failed (%d)\n", | ||
68 | error); | ||
69 | return; | ||
70 | } | ||
71 | |||
72 | rtc_tm->tm_sec = ret[5]; | ||
73 | rtc_tm->tm_min = ret[4]; | ||
74 | rtc_tm->tm_hour = ret[3]; | ||
75 | rtc_tm->tm_mday = ret[2]; | ||
76 | rtc_tm->tm_mon = ret[1] - 1; | ||
77 | rtc_tm->tm_year = ret[0] - 1900; | ||
78 | } | ||
79 | |||
80 | int rtas_set_rtc_time(struct rtc_time *tm) | ||
81 | { | ||
82 | int error, wait_time; | ||
83 | unsigned long max_wait_tb; | ||
84 | |||
85 | max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; | ||
86 | do { | ||
87 | error = rtas_call(rtas_token("set-time-of-day"), 7, 1, NULL, | ||
88 | tm->tm_year + 1900, tm->tm_mon + 1, | ||
89 | tm->tm_mday, tm->tm_hour, tm->tm_min, | ||
90 | tm->tm_sec, 0); | ||
91 | if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { | ||
92 | if (in_interrupt()) | ||
93 | return 1; /* probably decrementer */ | ||
94 | wait_time = rtas_extended_busy_delay_time(error); | ||
95 | msleep(wait_time); | ||
96 | error = RTAS_CLOCK_BUSY; | ||
97 | } | ||
98 | } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb)); | ||
99 | |||
100 | if (error != 0 && printk_ratelimit()) | ||
101 | printk(KERN_WARNING "error: setting the clock failed (%d)\n", | ||
102 | error); | ||
103 | |||
104 | return 0; | ||
105 | } | ||
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index c98cfcc9cd9a..e5694335bf10 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c | |||
@@ -57,10 +57,6 @@ extern void power4_idle(void); | |||
57 | boot_infos_t *boot_infos; | 57 | boot_infos_t *boot_infos; |
58 | struct ide_machdep_calls ppc_ide_md; | 58 | struct ide_machdep_calls ppc_ide_md; |
59 | 59 | ||
60 | /* XXX should go elsewhere */ | ||
61 | int __irq_offset_value; | ||
62 | EXPORT_SYMBOL(__irq_offset_value); | ||
63 | |||
64 | int boot_cpuid; | 60 | int boot_cpuid; |
65 | EXPORT_SYMBOL_GPL(boot_cpuid); | 61 | EXPORT_SYMBOL_GPL(boot_cpuid); |
66 | int boot_cpuid_phys; | 62 | int boot_cpuid_phys; |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index fdbd9f9122f2..608fee7c7e20 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -59,6 +59,7 @@ | |||
59 | #include <asm/firmware.h> | 59 | #include <asm/firmware.h> |
60 | #include <asm/xmon.h> | 60 | #include <asm/xmon.h> |
61 | #include <asm/udbg.h> | 61 | #include <asm/udbg.h> |
62 | #include <asm/kexec.h> | ||
62 | 63 | ||
63 | #include "setup.h" | 64 | #include "setup.h" |
64 | 65 | ||
@@ -415,6 +416,10 @@ void __init setup_system(void) | |||
415 | */ | 416 | */ |
416 | unflatten_device_tree(); | 417 | unflatten_device_tree(); |
417 | 418 | ||
419 | #ifdef CONFIG_KEXEC | ||
420 | kexec_setup(); /* requires unflattened device tree. */ | ||
421 | #endif | ||
422 | |||
418 | /* | 423 | /* |
419 | * Fill the ppc64_caches & systemcfg structures with informations | 424 | * Fill the ppc64_caches & systemcfg structures with informations |
420 | * retreived from the device-tree. Need to be called before | 425 | * retreived from the device-tree. Need to be called before |
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 8bdf95b7e420..5a2eba60dd39 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
@@ -403,8 +403,6 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, | |||
403 | ELF_NFPREG * sizeof(double))) | 403 | ELF_NFPREG * sizeof(double))) |
404 | return 1; | 404 | return 1; |
405 | 405 | ||
406 | current->thread.fpscr.val = 0; /* turn off all fp exceptions */ | ||
407 | |||
408 | #ifdef CONFIG_ALTIVEC | 406 | #ifdef CONFIG_ALTIVEC |
409 | /* save altivec registers */ | 407 | /* save altivec registers */ |
410 | if (current->thread.used_vr) { | 408 | if (current->thread.used_vr) { |
@@ -818,6 +816,9 @@ static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka, | |||
818 | goto badframe; | 816 | goto badframe; |
819 | regs->link = (unsigned long) frame->tramp; | 817 | regs->link = (unsigned long) frame->tramp; |
820 | } | 818 | } |
819 | |||
820 | current->thread.fpscr.val = 0; /* turn off all fp exceptions */ | ||
821 | |||
821 | if (put_user(regs->gpr[1], (u32 __user *)newsp)) | 822 | if (put_user(regs->gpr[1], (u32 __user *)newsp)) |
822 | goto badframe; | 823 | goto badframe; |
823 | regs->gpr[1] = newsp; | 824 | regs->gpr[1] = newsp; |
@@ -1097,6 +1098,8 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka, | |||
1097 | regs->link = (unsigned long) frame->mctx.tramp; | 1098 | regs->link = (unsigned long) frame->mctx.tramp; |
1098 | } | 1099 | } |
1099 | 1100 | ||
1101 | current->thread.fpscr.val = 0; /* turn off all fp exceptions */ | ||
1102 | |||
1100 | if (put_user(regs->gpr[1], (u32 __user *)newsp)) | 1103 | if (put_user(regs->gpr[1], (u32 __user *)newsp)) |
1101 | goto badframe; | 1104 | goto badframe; |
1102 | regs->gpr[1] = newsp; | 1105 | regs->gpr[1] = newsp; |
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 58194e150711..1decf2785530 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c | |||
@@ -131,9 +131,6 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, | |||
131 | 131 | ||
132 | flush_fp_to_thread(current); | 132 | flush_fp_to_thread(current); |
133 | 133 | ||
134 | /* Make sure signal doesn't get spurrious FP exceptions */ | ||
135 | current->thread.fpscr.val = 0; | ||
136 | |||
137 | #ifdef CONFIG_ALTIVEC | 134 | #ifdef CONFIG_ALTIVEC |
138 | err |= __put_user(v_regs, &sc->v_regs); | 135 | err |= __put_user(v_regs, &sc->v_regs); |
139 | 136 | ||
@@ -423,6 +420,9 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, | |||
423 | if (err) | 420 | if (err) |
424 | goto badframe; | 421 | goto badframe; |
425 | 422 | ||
423 | /* Make sure signal handler doesn't get spurious FP exceptions */ | ||
424 | current->thread.fpscr.val = 0; | ||
425 | |||
426 | /* Set up to return from userspace. */ | 426 | /* Set up to return from userspace. */ |
427 | if (vdso64_rt_sigtramp && current->thread.vdso_base) { | 427 | if (vdso64_rt_sigtramp && current->thread.vdso_base) { |
428 | regs->link = current->thread.vdso_base + vdso64_rt_sigtramp; | 428 | regs->link = current->thread.vdso_base + vdso64_rt_sigtramp; |
diff --git a/arch/powerpc/kernel/vdso32/datapage.S b/arch/powerpc/kernel/vdso32/datapage.S index a08c26e87835..f6b38472318d 100644 --- a/arch/powerpc/kernel/vdso32/datapage.S +++ b/arch/powerpc/kernel/vdso32/datapage.S | |||
@@ -77,8 +77,9 @@ V_FUNCTION_BEGIN(__kernel_get_tbfreq) | |||
77 | mflr r12 | 77 | mflr r12 |
78 | .cfi_register lr,r12 | 78 | .cfi_register lr,r12 |
79 | bl __get_datapage@local | 79 | bl __get_datapage@local |
80 | lwz r3,CFG_TB_TICKS_PER_SEC(r3) | ||
81 | lwz r4,(CFG_TB_TICKS_PER_SEC + 4)(r3) | 80 | lwz r4,(CFG_TB_TICKS_PER_SEC + 4)(r3) |
81 | lwz r3,CFG_TB_TICKS_PER_SEC(r3) | ||
82 | mtlr r12 | 82 | mtlr r12 |
83 | blr | ||
83 | .cfi_endproc | 84 | .cfi_endproc |
84 | V_FUNCTION_END(__kernel_get_tbfreq) | 85 | V_FUNCTION_END(__kernel_get_tbfreq) |
diff --git a/arch/powerpc/kernel/vdso32/gettimeofday.S b/arch/powerpc/kernel/vdso32/gettimeofday.S index aeb5fc9b87b3..0a32a41d50b0 100644 --- a/arch/powerpc/kernel/vdso32/gettimeofday.S +++ b/arch/powerpc/kernel/vdso32/gettimeofday.S | |||
@@ -83,7 +83,7 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime) | |||
83 | /* Check for supported clock IDs */ | 83 | /* Check for supported clock IDs */ |
84 | cmpli cr0,r3,CLOCK_REALTIME | 84 | cmpli cr0,r3,CLOCK_REALTIME |
85 | cmpli cr1,r3,CLOCK_MONOTONIC | 85 | cmpli cr1,r3,CLOCK_MONOTONIC |
86 | cror cr0,cr0,cr1 | 86 | cror cr0*4+eq,cr0*4+eq,cr1*4+eq |
87 | bne cr0,99f | 87 | bne cr0,99f |
88 | 88 | ||
89 | mflr r12 /* r12 saves lr */ | 89 | mflr r12 /* r12 saves lr */ |
@@ -91,7 +91,7 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime) | |||
91 | mr r10,r3 /* r10 saves id */ | 91 | mr r10,r3 /* r10 saves id */ |
92 | mr r11,r4 /* r11 saves tp */ | 92 | mr r11,r4 /* r11 saves tp */ |
93 | bl __get_datapage@local /* get data page */ | 93 | bl __get_datapage@local /* get data page */ |
94 | mr r9, r3 /* datapage ptr in r9 */ | 94 | mr r9,r3 /* datapage ptr in r9 */ |
95 | beq cr1,50f /* if monotonic -> jump there */ | 95 | beq cr1,50f /* if monotonic -> jump there */ |
96 | 96 | ||
97 | /* | 97 | /* |
@@ -173,10 +173,14 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime) | |||
173 | add r4,r4,r7 | 173 | add r4,r4,r7 |
174 | lis r5,NSEC_PER_SEC@h | 174 | lis r5,NSEC_PER_SEC@h |
175 | ori r5,r5,NSEC_PER_SEC@l | 175 | ori r5,r5,NSEC_PER_SEC@l |
176 | cmpli cr0,r4,r5 | 176 | cmpl cr0,r4,r5 |
177 | cmpli cr1,r4,0 | ||
177 | blt 1f | 178 | blt 1f |
178 | subf r4,r5,r4 | 179 | subf r4,r5,r4 |
179 | addi r3,r3,1 | 180 | addi r3,r3,1 |
181 | 1: bge cr1,1f | ||
182 | addi r3,r3,-1 | ||
183 | add r4,r4,r5 | ||
180 | 1: stw r3,TSPC32_TV_SEC(r11) | 184 | 1: stw r3,TSPC32_TV_SEC(r11) |
181 | stw r4,TSPC32_TV_NSEC(r11) | 185 | stw r4,TSPC32_TV_NSEC(r11) |
182 | 186 | ||
@@ -210,7 +214,7 @@ V_FUNCTION_BEGIN(__kernel_clock_getres) | |||
210 | /* Check for supported clock IDs */ | 214 | /* Check for supported clock IDs */ |
211 | cmpwi cr0,r3,CLOCK_REALTIME | 215 | cmpwi cr0,r3,CLOCK_REALTIME |
212 | cmpwi cr1,r3,CLOCK_MONOTONIC | 216 | cmpwi cr1,r3,CLOCK_MONOTONIC |
213 | cror cr0,cr0,cr1 | 217 | cror cr0*4+eq,cr0*4+eq,cr1*4+eq |
214 | bne cr0,99f | 218 | bne cr0,99f |
215 | 219 | ||
216 | li r3,0 | 220 | li r3,0 |
diff --git a/arch/powerpc/kernel/vdso64/datapage.S b/arch/powerpc/kernel/vdso64/datapage.S index e67eda0f8cda..6393e4137bc7 100644 --- a/arch/powerpc/kernel/vdso64/datapage.S +++ b/arch/powerpc/kernel/vdso64/datapage.S | |||
@@ -80,5 +80,6 @@ V_FUNCTION_BEGIN(__kernel_get_tbfreq) | |||
80 | bl V_LOCAL_FUNC(__get_datapage) | 80 | bl V_LOCAL_FUNC(__get_datapage) |
81 | ld r3,CFG_TB_TICKS_PER_SEC(r3) | 81 | ld r3,CFG_TB_TICKS_PER_SEC(r3) |
82 | mtlr r12 | 82 | mtlr r12 |
83 | blr | ||
83 | .cfi_endproc | 84 | .cfi_endproc |
84 | V_FUNCTION_END(__kernel_get_tbfreq) | 85 | V_FUNCTION_END(__kernel_get_tbfreq) |
diff --git a/arch/powerpc/kernel/vdso64/gettimeofday.S b/arch/powerpc/kernel/vdso64/gettimeofday.S index d371c02a8c0e..1a89094715cc 100644 --- a/arch/powerpc/kernel/vdso64/gettimeofday.S +++ b/arch/powerpc/kernel/vdso64/gettimeofday.S | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | |
2 | /* | ||
2 | * Userland implementation of gettimeofday() for 64 bits processes in a | 3 | * Userland implementation of gettimeofday() for 64 bits processes in a |
3 | * ppc64 kernel for use in the vDSO | 4 | * ppc64 kernel for use in the vDSO |
4 | * | 5 | * |
@@ -68,7 +69,7 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime) | |||
68 | /* Check for supported clock IDs */ | 69 | /* Check for supported clock IDs */ |
69 | cmpwi cr0,r3,CLOCK_REALTIME | 70 | cmpwi cr0,r3,CLOCK_REALTIME |
70 | cmpwi cr1,r3,CLOCK_MONOTONIC | 71 | cmpwi cr1,r3,CLOCK_MONOTONIC |
71 | cror cr0,cr0,cr1 | 72 | cror cr0*4+eq,cr0*4+eq,cr1*4+eq |
72 | bne cr0,99f | 73 | bne cr0,99f |
73 | 74 | ||
74 | mflr r12 /* r12 saves lr */ | 75 | mflr r12 /* r12 saves lr */ |
@@ -84,16 +85,17 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime) | |||
84 | 85 | ||
85 | bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */ | 86 | bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */ |
86 | 87 | ||
87 | lis r7,0x3b9a /* r7 = 1000000000 = NSEC_PER_SEC */ | 88 | lis r7,15 /* r7 = 1000000 = USEC_PER_SEC */ |
88 | ori r7,r7,0xca00 | 89 | ori r7,r7,16960 |
89 | rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */ | 90 | rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */ |
90 | rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */ | 91 | rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */ |
91 | std r5,TSPC64_TV_SEC(r11) /* store sec in tv */ | 92 | std r5,TSPC64_TV_SEC(r11) /* store sec in tv */ |
92 | subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */ | 93 | subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */ |
93 | mulld r0,r0,r7 /* nsec = (xsec * NSEC_PER_SEC) / | 94 | mulld r0,r0,r7 /* usec = (xsec * USEC_PER_SEC) / |
94 | * XSEC_PER_SEC | 95 | * XSEC_PER_SEC |
95 | */ | 96 | */ |
96 | rldicl r0,r0,44,20 | 97 | rldicl r0,r0,44,20 |
98 | mulli r0,r0,1000 /* nsec = usec * 1000 */ | ||
97 | std r0,TSPC64_TV_NSEC(r11) /* store nsec in tp */ | 99 | std r0,TSPC64_TV_NSEC(r11) /* store nsec in tp */ |
98 | 100 | ||
99 | mtlr r12 | 101 | mtlr r12 |
@@ -106,15 +108,16 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime) | |||
106 | 108 | ||
107 | 50: bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */ | 109 | 50: bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */ |
108 | 110 | ||
109 | lis r7,0x3b9a /* r7 = 1000000000 = NSEC_PER_SEC */ | 111 | lis r7,15 /* r7 = 1000000 = USEC_PER_SEC */ |
110 | ori r7,r7,0xca00 | 112 | ori r7,r7,16960 |
111 | rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */ | 113 | rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */ |
112 | rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */ | 114 | rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */ |
113 | subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */ | 115 | subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */ |
114 | mulld r0,r0,r7 /* nsec = (xsec * NSEC_PER_SEC) / | 116 | mulld r0,r0,r7 /* usec = (xsec * USEC_PER_SEC) / |
115 | * XSEC_PER_SEC | 117 | * XSEC_PER_SEC |
116 | */ | 118 | */ |
117 | rldicl r6,r0,44,20 | 119 | rldicl r6,r0,44,20 |
120 | mulli r6,r6,1000 /* nsec = usec * 1000 */ | ||
118 | 121 | ||
119 | /* now we must fixup using wall to monotonic. We need to snapshot | 122 | /* now we must fixup using wall to monotonic. We need to snapshot |
120 | * that value and do the counter trick again. Fortunately, we still | 123 | * that value and do the counter trick again. Fortunately, we still |
@@ -123,8 +126,8 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime) | |||
123 | * can be used | 126 | * can be used |
124 | */ | 127 | */ |
125 | 128 | ||
126 | lwz r4,WTOM_CLOCK_SEC(r9) | 129 | lwa r4,WTOM_CLOCK_SEC(r3) |
127 | lwz r7,WTOM_CLOCK_NSEC(r9) | 130 | lwa r7,WTOM_CLOCK_NSEC(r3) |
128 | 131 | ||
129 | /* We now have our result in r4,r7. We create a fake dependency | 132 | /* We now have our result in r4,r7. We create a fake dependency |
130 | * on that result and re-check the counter | 133 | * on that result and re-check the counter |
@@ -144,10 +147,14 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime) | |||
144 | add r7,r7,r6 | 147 | add r7,r7,r6 |
145 | lis r9,NSEC_PER_SEC@h | 148 | lis r9,NSEC_PER_SEC@h |
146 | ori r9,r9,NSEC_PER_SEC@l | 149 | ori r9,r9,NSEC_PER_SEC@l |
147 | cmpli cr0,r7,r9 | 150 | cmpl cr0,r7,r9 |
151 | cmpli cr1,r7,0 | ||
148 | blt 1f | 152 | blt 1f |
149 | subf r7,r9,r7 | 153 | subf r7,r9,r7 |
150 | addi r4,r4,1 | 154 | addi r4,r4,1 |
155 | 1: bge cr1,1f | ||
156 | addi r4,r4,-1 | ||
157 | add r7,r7,r9 | ||
151 | 1: std r4,TSPC64_TV_SEC(r11) | 158 | 1: std r4,TSPC64_TV_SEC(r11) |
152 | std r7,TSPC64_TV_NSEC(r11) | 159 | std r7,TSPC64_TV_NSEC(r11) |
153 | 160 | ||
@@ -181,7 +188,7 @@ V_FUNCTION_BEGIN(__kernel_clock_getres) | |||
181 | /* Check for supported clock IDs */ | 188 | /* Check for supported clock IDs */ |
182 | cmpwi cr0,r3,CLOCK_REALTIME | 189 | cmpwi cr0,r3,CLOCK_REALTIME |
183 | cmpwi cr1,r3,CLOCK_MONOTONIC | 190 | cmpwi cr1,r3,CLOCK_MONOTONIC |
184 | cror cr0,cr0,cr1 | 191 | cror cr0*4+eq,cr0*4+eq,cr1*4+eq |
185 | bne cr0,99f | 192 | bne cr0,99f |
186 | 193 | ||
187 | li r3,0 | 194 | li r3,0 |
diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c index af9ca0eb6d55..5d581bb3aa12 100644 --- a/arch/powerpc/mm/fsl_booke_mmu.c +++ b/arch/powerpc/mm/fsl_booke_mmu.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Modifications by Kumar Gala (kumar.gala@freescale.com) to support | 2 | * Modifications by Kumar Gala (galak@kernel.crashing.org) to support |
3 | * E500 Book E processors. | 3 | * E500 Book E processors. |
4 | * | 4 | * |
5 | * Copyright 2004 Freescale Semiconductor, Inc | 5 | * Copyright 2004 Freescale Semiconductor, Inc |
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index e2c95fcb8055..4bd7b0a70996 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c | |||
@@ -200,6 +200,8 @@ void show_mem(void) | |||
200 | unsigned long flags; | 200 | unsigned long flags; |
201 | pgdat_resize_lock(pgdat, &flags); | 201 | pgdat_resize_lock(pgdat, &flags); |
202 | for (i = 0; i < pgdat->node_spanned_pages; i++) { | 202 | for (i = 0; i < pgdat->node_spanned_pages; i++) { |
203 | if (!pfn_valid(pgdat->node_start_pfn + i)) | ||
204 | continue; | ||
203 | page = pgdat_page_nr(pgdat, i); | 205 | page = pgdat_page_nr(pgdat, i); |
204 | total++; | 206 | total++; |
205 | if (PageHighMem(page)) | 207 | if (PageHighMem(page)) |
@@ -336,7 +338,7 @@ void __init mem_init(void) | |||
336 | struct page *page; | 338 | struct page *page; |
337 | unsigned long reservedpages = 0, codesize, initsize, datasize, bsssize; | 339 | unsigned long reservedpages = 0, codesize, initsize, datasize, bsssize; |
338 | 340 | ||
339 | num_physpages = max_pfn; /* RAM is assumed contiguous */ | 341 | num_physpages = lmb.memory.size >> PAGE_SHIFT; |
340 | high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); | 342 | high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); |
341 | 343 | ||
342 | #ifdef CONFIG_NEED_MULTIPLE_NODES | 344 | #ifdef CONFIG_NEED_MULTIPLE_NODES |
@@ -348,11 +350,13 @@ void __init mem_init(void) | |||
348 | } | 350 | } |
349 | } | 351 | } |
350 | #else | 352 | #else |
351 | max_mapnr = num_physpages; | 353 | max_mapnr = max_pfn; |
352 | totalram_pages += free_all_bootmem(); | 354 | totalram_pages += free_all_bootmem(); |
353 | #endif | 355 | #endif |
354 | for_each_pgdat(pgdat) { | 356 | for_each_pgdat(pgdat) { |
355 | for (i = 0; i < pgdat->node_spanned_pages; i++) { | 357 | for (i = 0; i < pgdat->node_spanned_pages; i++) { |
358 | if (!pfn_valid(pgdat->node_start_pfn + i)) | ||
359 | continue; | ||
356 | page = pgdat_page_nr(pgdat, i); | 360 | page = pgdat_page_nr(pgdat, i); |
357 | if (PageReserved(page)) | 361 | if (PageReserved(page)) |
358 | reservedpages++; | 362 | reservedpages++; |
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index bd2cf1336885..f72cf87364cb 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c | |||
@@ -483,6 +483,7 @@ static void __init setup_nonnuma(void) | |||
483 | { | 483 | { |
484 | unsigned long top_of_ram = lmb_end_of_DRAM(); | 484 | unsigned long top_of_ram = lmb_end_of_DRAM(); |
485 | unsigned long total_ram = lmb_phys_mem_size(); | 485 | unsigned long total_ram = lmb_phys_mem_size(); |
486 | unsigned int i; | ||
486 | 487 | ||
487 | printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n", | 488 | printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n", |
488 | top_of_ram, total_ram); | 489 | top_of_ram, total_ram); |
@@ -490,7 +491,9 @@ static void __init setup_nonnuma(void) | |||
490 | (top_of_ram - total_ram) >> 20); | 491 | (top_of_ram - total_ram) >> 20); |
491 | 492 | ||
492 | map_cpu_to_node(boot_cpuid, 0); | 493 | map_cpu_to_node(boot_cpuid, 0); |
493 | add_region(0, 0, lmb_end_of_DRAM() >> PAGE_SHIFT); | 494 | for (i = 0; i < lmb.memory.cnt; ++i) |
495 | add_region(0, lmb.memory.region[i].base >> PAGE_SHIFT, | ||
496 | lmb_size_pages(&lmb.memory, i)); | ||
494 | node_set_online(0); | 497 | node_set_online(0); |
495 | } | 498 | } |
496 | 499 | ||
diff --git a/arch/powerpc/oprofile/op_model_fsl_booke.c b/arch/powerpc/oprofile/op_model_fsl_booke.c index 86124a94c9af..26539cda6023 100644 --- a/arch/powerpc/oprofile/op_model_fsl_booke.c +++ b/arch/powerpc/oprofile/op_model_fsl_booke.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * Copyright (c) 2004 Freescale Semiconductor, Inc | 7 | * Copyright (c) 2004 Freescale Semiconductor, Inc |
8 | * | 8 | * |
9 | * Author: Andy Fleming | 9 | * Author: Andy Fleming |
10 | * Maintainer: Kumar Gala <Kumar.Gala@freescale.com> | 10 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or | 12 | * This program is free software; you can redistribute it and/or |
13 | * modify it under the terms of the GNU General Public License | 13 | * modify it under the terms of the GNU General Public License |
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index 01090e9ce0cf..a58daa153686 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c | |||
@@ -42,13 +42,6 @@ | |||
42 | #include "irq.h" | 42 | #include "irq.h" |
43 | #include "call_pci.h" | 43 | #include "call_pci.h" |
44 | 44 | ||
45 | /* This maps virtual irq numbers to real irqs */ | ||
46 | unsigned int virt_irq_to_real_map[NR_IRQS]; | ||
47 | |||
48 | /* The next available virtual irq number */ | ||
49 | /* Note: the pcnet32 driver assumes irq numbers < 2 aren't valid. :( */ | ||
50 | static int next_virtual_irq = 2; | ||
51 | |||
52 | static long Pci_Interrupt_Count; | 45 | static long Pci_Interrupt_Count; |
53 | static long Pci_Event_Count; | 46 | static long Pci_Event_Count; |
54 | 47 | ||
@@ -350,26 +343,14 @@ static hw_irq_controller iSeries_IRQ_handler = { | |||
350 | int __init iSeries_allocate_IRQ(HvBusNumber busNumber, | 343 | int __init iSeries_allocate_IRQ(HvBusNumber busNumber, |
351 | HvSubBusNumber subBusNumber, HvAgentId deviceId) | 344 | HvSubBusNumber subBusNumber, HvAgentId deviceId) |
352 | { | 345 | { |
353 | unsigned int realirq, virtirq; | 346 | int virtirq; |
347 | unsigned int realirq; | ||
354 | u8 idsel = (deviceId >> 4); | 348 | u8 idsel = (deviceId >> 4); |
355 | u8 function = deviceId & 7; | 349 | u8 function = deviceId & 7; |
356 | 350 | ||
357 | virtirq = next_virtual_irq++; | ||
358 | realirq = ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function; | 351 | realirq = ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function; |
359 | virt_irq_to_real_map[virtirq] = realirq; | 352 | virtirq = virt_irq_create_mapping(realirq); |
360 | 353 | ||
361 | irq_desc[virtirq].handler = &iSeries_IRQ_handler; | 354 | irq_desc[virtirq].handler = &iSeries_IRQ_handler; |
362 | return virtirq; | 355 | return virtirq; |
363 | } | 356 | } |
364 | |||
365 | int virt_irq_create_mapping(unsigned int real_irq) | ||
366 | { | ||
367 | BUG(); /* Don't call this on iSeries, yet */ | ||
368 | |||
369 | return 0; | ||
370 | } | ||
371 | |||
372 | void virt_irq_init(void) | ||
373 | { | ||
374 | return; | ||
375 | } | ||
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 6a29f301436b..da26639190db 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c | |||
@@ -39,7 +39,6 @@ | |||
39 | #include <asm/sections.h> | 39 | #include <asm/sections.h> |
40 | #include <asm/iommu.h> | 40 | #include <asm/iommu.h> |
41 | #include <asm/firmware.h> | 41 | #include <asm/firmware.h> |
42 | #include <asm/systemcfg.h> | ||
43 | #include <asm/system.h> | 42 | #include <asm/system.h> |
44 | #include <asm/time.h> | 43 | #include <asm/time.h> |
45 | #include <asm/paca.h> | 44 | #include <asm/paca.h> |
@@ -548,8 +547,6 @@ static unsigned long __init build_iSeries_Memory_Map(void) | |||
548 | */ | 547 | */ |
549 | static void __init iSeries_setup_arch(void) | 548 | static void __init iSeries_setup_arch(void) |
550 | { | 549 | { |
551 | unsigned procIx = get_paca()->lppaca.dyn_hv_phys_proc_index; | ||
552 | |||
553 | if (get_paca()->lppaca.shared_proc) { | 550 | if (get_paca()->lppaca.shared_proc) { |
554 | ppc_md.idle_loop = iseries_shared_idle; | 551 | ppc_md.idle_loop = iseries_shared_idle; |
555 | printk(KERN_INFO "Using shared processor idle loop\n"); | 552 | printk(KERN_INFO "Using shared processor idle loop\n"); |
@@ -565,9 +562,6 @@ static void __init iSeries_setup_arch(void) | |||
565 | itVpdAreas.xSlicMaxLogicalProcs); | 562 | itVpdAreas.xSlicMaxLogicalProcs); |
566 | printk("Max physical processors = %d\n", | 563 | printk("Max physical processors = %d\n", |
567 | itVpdAreas.xSlicMaxPhysicalProcs); | 564 | itVpdAreas.xSlicMaxPhysicalProcs); |
568 | |||
569 | _systemcfg->processor = xIoHriProcessorVpd[procIx].xPVR; | ||
570 | printk("Processor version = %x\n", _systemcfg->processor); | ||
571 | } | 565 | } |
572 | 566 | ||
573 | static void iSeries_show_cpuinfo(struct seq_file *m) | 567 | static void iSeries_show_cpuinfo(struct seq_file *m) |
diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c index 5947b21a8588..feb0a94e7819 100644 --- a/arch/powerpc/platforms/powermac/time.c +++ b/arch/powerpc/platforms/powermac/time.c | |||
@@ -102,7 +102,7 @@ static unsigned long from_rtc_time(struct rtc_time *tm) | |||
102 | static unsigned long cuda_get_time(void) | 102 | static unsigned long cuda_get_time(void) |
103 | { | 103 | { |
104 | struct adb_request req; | 104 | struct adb_request req; |
105 | unsigned long now; | 105 | unsigned int now; |
106 | 106 | ||
107 | if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) | 107 | if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) |
108 | return 0; | 108 | return 0; |
@@ -113,7 +113,7 @@ static unsigned long cuda_get_time(void) | |||
113 | req.reply_len); | 113 | req.reply_len); |
114 | now = (req.reply[3] << 24) + (req.reply[4] << 16) | 114 | now = (req.reply[3] << 24) + (req.reply[4] << 16) |
115 | + (req.reply[5] << 8) + req.reply[6]; | 115 | + (req.reply[5] << 8) + req.reply[6]; |
116 | return now - RTC_OFFSET; | 116 | return ((unsigned long)now) - RTC_OFFSET; |
117 | } | 117 | } |
118 | 118 | ||
119 | #define cuda_get_rtc_time(tm) to_rtc_time(cuda_get_time(), (tm)) | 119 | #define cuda_get_rtc_time(tm) to_rtc_time(cuda_get_time(), (tm)) |
@@ -146,7 +146,7 @@ static int cuda_set_rtc_time(struct rtc_time *tm) | |||
146 | static unsigned long pmu_get_time(void) | 146 | static unsigned long pmu_get_time(void) |
147 | { | 147 | { |
148 | struct adb_request req; | 148 | struct adb_request req; |
149 | unsigned long now; | 149 | unsigned int now; |
150 | 150 | ||
151 | if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) | 151 | if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) |
152 | return 0; | 152 | return 0; |
@@ -156,7 +156,7 @@ static unsigned long pmu_get_time(void) | |||
156 | req.reply_len); | 156 | req.reply_len); |
157 | now = (req.reply[0] << 24) + (req.reply[1] << 16) | 157 | now = (req.reply[0] << 24) + (req.reply[1] << 16) |
158 | + (req.reply[2] << 8) + req.reply[3]; | 158 | + (req.reply[2] << 8) + req.reply[3]; |
159 | return now - RTC_OFFSET; | 159 | return ((unsigned long)now) - RTC_OFFSET; |
160 | } | 160 | } |
161 | 161 | ||
162 | #define pmu_get_rtc_time(tm) to_rtc_time(pmu_get_time(), (tm)) | 162 | #define pmu_get_rtc_time(tm) to_rtc_time(pmu_get_time(), (tm)) |
@@ -199,6 +199,7 @@ static unsigned long smu_get_time(void) | |||
199 | #define smu_set_rtc_time(tm, spin) 0 | 199 | #define smu_set_rtc_time(tm, spin) 0 |
200 | #endif | 200 | #endif |
201 | 201 | ||
202 | /* Can't be __init, it's called when suspending and resuming */ | ||
202 | unsigned long pmac_get_boot_time(void) | 203 | unsigned long pmac_get_boot_time(void) |
203 | { | 204 | { |
204 | /* Get the time from the RTC, used only at boot time */ | 205 | /* Get the time from the RTC, used only at boot time */ |
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index e7ca5b1f591e..06d5ef501218 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile | |||
@@ -4,4 +4,7 @@ obj-$(CONFIG_SMP) += smp.o | |||
4 | obj-$(CONFIG_IBMVIO) += vio.o | 4 | obj-$(CONFIG_IBMVIO) += vio.o |
5 | obj-$(CONFIG_XICS) += xics.o | 5 | obj-$(CONFIG_XICS) += xics.o |
6 | obj-$(CONFIG_SCANLOG) += scanlog.o | 6 | obj-$(CONFIG_SCANLOG) += scanlog.o |
7 | obj-$(CONFIG_EEH) += eeh.o eeh_event.o | 7 | obj-$(CONFIG_EEH) += eeh.o eeh_event.o |
8 | |||
9 | obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o | ||
10 | obj-$(CONFIG_HVCS) += hvcserver.o | ||
diff --git a/arch/ppc64/kernel/hvconsole.c b/arch/powerpc/platforms/pseries/hvconsole.c index 138e128a3886..138e128a3886 100644 --- a/arch/ppc64/kernel/hvconsole.c +++ b/arch/powerpc/platforms/pseries/hvconsole.c | |||
diff --git a/arch/ppc64/kernel/hvcserver.c b/arch/powerpc/platforms/pseries/hvcserver.c index 4d584172055a..4d584172055a 100644 --- a/arch/ppc64/kernel/hvcserver.c +++ b/arch/powerpc/platforms/pseries/hvcserver.c | |||
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 31990829310c..b9d9732b2e06 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -200,14 +200,12 @@ static void __init pSeries_setup_arch(void) | |||
200 | if (ppc64_interrupt_controller == IC_OPEN_PIC) { | 200 | if (ppc64_interrupt_controller == IC_OPEN_PIC) { |
201 | ppc_md.init_IRQ = pSeries_init_mpic; | 201 | ppc_md.init_IRQ = pSeries_init_mpic; |
202 | ppc_md.get_irq = mpic_get_irq; | 202 | ppc_md.get_irq = mpic_get_irq; |
203 | ppc_md.cpu_irq_down = mpic_teardown_this_cpu; | ||
204 | /* Allocate the mpic now, so that find_and_init_phbs() can | 203 | /* Allocate the mpic now, so that find_and_init_phbs() can |
205 | * fill the ISUs */ | 204 | * fill the ISUs */ |
206 | pSeries_setup_mpic(); | 205 | pSeries_setup_mpic(); |
207 | } else { | 206 | } else { |
208 | ppc_md.init_IRQ = xics_init_IRQ; | 207 | ppc_md.init_IRQ = xics_init_IRQ; |
209 | ppc_md.get_irq = xics_get_irq; | 208 | ppc_md.get_irq = xics_get_irq; |
210 | ppc_md.cpu_irq_down = xics_teardown_cpu; | ||
211 | } | 209 | } |
212 | 210 | ||
213 | #ifdef CONFIG_SMP | 211 | #ifdef CONFIG_SMP |
@@ -595,6 +593,27 @@ static int pSeries_pci_probe_mode(struct pci_bus *bus) | |||
595 | return PCI_PROBE_NORMAL; | 593 | return PCI_PROBE_NORMAL; |
596 | } | 594 | } |
597 | 595 | ||
596 | #ifdef CONFIG_KEXEC | ||
597 | static void pseries_kexec_cpu_down(int crash_shutdown, int secondary) | ||
598 | { | ||
599 | /* Don't risk a hypervisor call if we're crashing */ | ||
600 | if (!crash_shutdown) { | ||
601 | unsigned long vpa = __pa(&get_paca()->lppaca); | ||
602 | |||
603 | if (unregister_vpa(hard_smp_processor_id(), vpa)) { | ||
604 | printk("VPA deregistration of cpu %u (hw_cpu_id %d) " | ||
605 | "failed\n", smp_processor_id(), | ||
606 | hard_smp_processor_id()); | ||
607 | } | ||
608 | } | ||
609 | |||
610 | if (ppc64_interrupt_controller == IC_OPEN_PIC) | ||
611 | mpic_teardown_this_cpu(secondary); | ||
612 | else | ||
613 | xics_teardown_cpu(secondary); | ||
614 | } | ||
615 | #endif | ||
616 | |||
598 | struct machdep_calls __initdata pSeries_md = { | 617 | struct machdep_calls __initdata pSeries_md = { |
599 | .probe = pSeries_probe, | 618 | .probe = pSeries_probe, |
600 | .setup_arch = pSeries_setup_arch, | 619 | .setup_arch = pSeries_setup_arch, |
@@ -617,4 +636,7 @@ struct machdep_calls __initdata pSeries_md = { | |||
617 | .check_legacy_ioport = pSeries_check_legacy_ioport, | 636 | .check_legacy_ioport = pSeries_check_legacy_ioport, |
618 | .system_reset_exception = pSeries_system_reset_exception, | 637 | .system_reset_exception = pSeries_system_reset_exception, |
619 | .machine_check_exception = pSeries_machine_check_exception, | 638 | .machine_check_exception = pSeries_machine_check_exception, |
639 | #ifdef CONFIG_KEXEC | ||
640 | .kexec_cpu_down = pseries_kexec_cpu_down, | ||
641 | #endif | ||
620 | }; | 642 | }; |
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index ef4356b29a97..c45a6ad5f3b7 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/cpumask.h> | 19 | #include <linux/cpumask.h> |
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/sysrq.h> | 21 | #include <linux/sysrq.h> |
22 | #include <linux/interrupt.h> | ||
22 | 23 | ||
23 | #include <asm/ptrace.h> | 24 | #include <asm/ptrace.h> |
24 | #include <asm/string.h> | 25 | #include <asm/string.h> |
diff --git a/arch/ppc/kernel/head_fsl_booke.S b/arch/ppc/kernel/head_fsl_booke.S index 5063c603fad4..8d60fa99fc4b 100644 --- a/arch/ppc/kernel/head_fsl_booke.S +++ b/arch/ppc/kernel/head_fsl_booke.S | |||
@@ -24,7 +24,7 @@ | |||
24 | * Copyright 2002-2004 MontaVista Software, Inc. | 24 | * Copyright 2002-2004 MontaVista Software, Inc. |
25 | * PowerPC 44x support, Matt Porter <mporter@kernel.crashing.org> | 25 | * PowerPC 44x support, Matt Porter <mporter@kernel.crashing.org> |
26 | * Copyright 2004 Freescale Semiconductor, Inc | 26 | * Copyright 2004 Freescale Semiconductor, Inc |
27 | * PowerPC e500 modifications, Kumar Gala <kumar.gala@freescale.com> | 27 | * PowerPC e500 modifications, Kumar Gala <galak@kernel.crashing.org> |
28 | * | 28 | * |
29 | * This program is free software; you can redistribute it and/or modify it | 29 | * This program is free software; you can redistribute it and/or modify it |
30 | * under the terms of the GNU General Public License as published by the | 30 | * under the terms of the GNU General Public License as published by the |
diff --git a/arch/ppc/mm/fsl_booke_mmu.c b/arch/ppc/mm/fsl_booke_mmu.c index af9ca0eb6d55..5d581bb3aa12 100644 --- a/arch/ppc/mm/fsl_booke_mmu.c +++ b/arch/ppc/mm/fsl_booke_mmu.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Modifications by Kumar Gala (kumar.gala@freescale.com) to support | 2 | * Modifications by Kumar Gala (galak@kernel.crashing.org) to support |
3 | * E500 Book E processors. | 3 | * E500 Book E processors. |
4 | * | 4 | * |
5 | * Copyright 2004 Freescale Semiconductor, Inc | 5 | * Copyright 2004 Freescale Semiconductor, Inc |
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c index 98edc75f4105..04bdc39bf47b 100644 --- a/arch/ppc/platforms/83xx/mpc834x_sys.c +++ b/arch/ppc/platforms/83xx/mpc834x_sys.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC834x SYS board specific routines | 4 | * MPC834x SYS board specific routines |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor Inc. | 8 | * Copyright 2005 Freescale Semiconductor Inc. |
9 | * | 9 | * |
@@ -73,12 +73,19 @@ mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | |||
73 | * A B C D | 73 | * A B C D |
74 | */ | 74 | */ |
75 | { | 75 | { |
76 | {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x11 */ | 76 | {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x11 */ |
77 | {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x12 */ | 77 | {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x12 */ |
78 | {PIRQD, PIRQA, PIRQB, PIRQC} /* idsel 0x13 */ | 78 | {PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x13 */ |
79 | {0, 0, 0, 0}, | ||
80 | {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x15 */ | ||
81 | {PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x16 */ | ||
82 | {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x17 */ | ||
83 | {PIRQB, PIRQC, PIRQD, PIRQA}, /* idsel 0x18 */ | ||
84 | {0, 0, 0, 0}, /* idsel 0x19 */ | ||
85 | {0, 0, 0, 0}, /* idsel 0x20 */ | ||
79 | }; | 86 | }; |
80 | 87 | ||
81 | const long min_idsel = 0x11, max_idsel = 0x13, irqs_per_slot = 4; | 88 | const long min_idsel = 0x11, max_idsel = 0x20, irqs_per_slot = 4; |
82 | return PCI_IRQ_TABLE_LOOKUP; | 89 | return PCI_IRQ_TABLE_LOOKUP; |
83 | } | 90 | } |
84 | 91 | ||
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.h b/arch/ppc/platforms/83xx/mpc834x_sys.h index 58e44c042535..2e514d316fb8 100644 --- a/arch/ppc/platforms/83xx/mpc834x_sys.h +++ b/arch/ppc/platforms/83xx/mpc834x_sys.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC834X SYS common board definitions | 4 | * MPC834X SYS common board definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor, Inc. | 8 | * Copyright 2005 Freescale Semiconductor, Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c index 7e952c1228cb..c5cde97c6ef0 100644 --- a/arch/ppc/platforms/85xx/mpc8540_ads.c +++ b/arch/ppc/platforms/85xx/mpc8540_ads.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC8540ADS board specific routines | 4 | * MPC8540ADS board specific routines |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.h b/arch/ppc/platforms/85xx/mpc8540_ads.h index 3d05d7c4a938..e48ca3a97397 100644 --- a/arch/ppc/platforms/85xx/mpc8540_ads.h +++ b/arch/ppc/platforms/85xx/mpc8540_ads.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC8540ADS board definitions | 4 | * MPC8540ADS board definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc8555_cds.h b/arch/ppc/platforms/85xx/mpc8555_cds.h index e0e75568bc57..1a8e6c67355d 100644 --- a/arch/ppc/platforms/85xx/mpc8555_cds.h +++ b/arch/ppc/platforms/85xx/mpc8555_cds.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC8555CDS board definitions | 4 | * MPC8555CDS board definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c index 208433f1e93a..8e39a5517092 100644 --- a/arch/ppc/platforms/85xx/mpc8560_ads.c +++ b/arch/ppc/platforms/85xx/mpc8560_ads.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC8560ADS board specific routines | 4 | * MPC8560ADS board specific routines |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.h b/arch/ppc/platforms/85xx/mpc8560_ads.h index 7df885d73e9d..143ae7eefa7c 100644 --- a/arch/ppc/platforms/85xx/mpc8560_ads.h +++ b/arch/ppc/platforms/85xx/mpc8560_ads.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC8540ADS board definitions | 4 | * MPC8540ADS board definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c index 16ad092d8a06..17ce48fe3503 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85xx ADS board common routines | 4 | * MPC85xx ADS board common routines |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.h b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h index 84acf6e8d45e..7b26bcc5d10d 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_ads_common.h +++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85XX ADS common board definitions | 4 | * MPC85XX ADS common board definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c index a21156967a5e..d8991b88dc9c 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85xx CDS board specific routines | 4 | * MPC85xx CDS board specific routines |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor, Inc | 8 | * Copyright 2004 Freescale Semiconductor, Inc |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.h b/arch/ppc/platforms/85xx/mpc85xx_cds_common.h index 12b292c6ae32..5b588cfd0e41 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.h +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85xx CDS board definitions | 4 | * MPC85xx CDS board definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor, Inc | 8 | * Copyright 2004 Freescale Semiconductor, Inc |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c index b4ee1707a836..45a5b81b4ed1 100644 --- a/arch/ppc/platforms/85xx/sbc8560.c +++ b/arch/ppc/platforms/85xx/sbc8560.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Wind River SBC8560 board specific routines | 4 | * Wind River SBC8560 board specific routines |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c index 58884a63ebdb..1e69b0593162 100644 --- a/arch/ppc/platforms/pmac_feature.c +++ b/arch/ppc/platforms/pmac_feature.c | |||
@@ -2317,6 +2317,14 @@ static struct pmac_mb_def pmac_mb_defs[] = { | |||
2317 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | 2317 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, |
2318 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | 2318 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, |
2319 | }, | 2319 | }, |
2320 | { "PowerBook5,8", "PowerBook G4 15\"", | ||
2321 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
2322 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
2323 | }, | ||
2324 | { "PowerBook5,9", "PowerBook G4 17\"", | ||
2325 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
2326 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
2327 | }, | ||
2320 | { "PowerBook6,1", "PowerBook G4 12\"", | 2328 | { "PowerBook6,1", "PowerBook G4 12\"", |
2321 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | 2329 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, |
2322 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | 2330 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, |
diff --git a/arch/ppc/platforms/pq2ads.c b/arch/ppc/platforms/pq2ads.c index 6a1475c1e128..71c9fca1fe9b 100644 --- a/arch/ppc/platforms/pq2ads.c +++ b/arch/ppc/platforms/pq2ads.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * PQ2ADS platform support | 4 | * PQ2ADS platform support |
5 | * | 5 | * |
6 | * Author: Kumar Gala <kumar.gala@freescale.com> | 6 | * Author: Kumar Gala <galak@kernel.crashing.org> |
7 | * Derived from: est8260_setup.c by Allen Curtis | 7 | * Derived from: est8260_setup.c by Allen Curtis |
8 | * | 8 | * |
9 | * Copyright 2004 Freescale Semiconductor, Inc. | 9 | * Copyright 2004 Freescale Semiconductor, Inc. |
diff --git a/arch/ppc/syslib/ipic.h b/arch/ppc/syslib/ipic.h index 2b56a4fcf373..a7ce7da8785c 100644 --- a/arch/ppc/syslib/ipic.h +++ b/arch/ppc/syslib/ipic.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * IPIC private definitions and structure. | 4 | * IPIC private definitions and structure. |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor, Inc | 8 | * Copyright 2005 Freescale Semiconductor, Inc |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c index f43fbf9a9389..847df4409982 100644 --- a/arch/ppc/syslib/mpc83xx_devices.c +++ b/arch/ppc/syslib/mpc83xx_devices.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC83xx Device descriptions | 4 | * MPC83xx Device descriptions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor Inc. | 8 | * Copyright 2005 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/mpc83xx_sys.c b/arch/ppc/syslib/mpc83xx_sys.c index da743446789b..a1523989aff4 100644 --- a/arch/ppc/syslib/mpc83xx_sys.c +++ b/arch/ppc/syslib/mpc83xx_sys.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC83xx System descriptions | 4 | * MPC83xx System descriptions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor Inc. | 8 | * Copyright 2005 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/mpc85xx_devices.c b/arch/ppc/syslib/mpc85xx_devices.c index 2ede677a0a53..69949d255658 100644 --- a/arch/ppc/syslib/mpc85xx_devices.c +++ b/arch/ppc/syslib/mpc85xx_devices.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85xx Device descriptions | 4 | * MPC85xx Device descriptions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor Inc. | 8 | * Copyright 2005 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/mpc85xx_sys.c b/arch/ppc/syslib/mpc85xx_sys.c index cb68d8c58348..397cfbcce5ea 100644 --- a/arch/ppc/syslib/mpc85xx_sys.c +++ b/arch/ppc/syslib/mpc85xx_sys.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85xx System descriptions | 4 | * MPC85xx System descriptions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor Inc. | 8 | * Copyright 2005 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/mpc8xx_devices.c b/arch/ppc/syslib/mpc8xx_devices.c index 2b5f0e701687..92dc98b36bde 100644 --- a/arch/ppc/syslib/mpc8xx_devices.c +++ b/arch/ppc/syslib/mpc8xx_devices.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC8xx Device descriptions | 4 | * MPC8xx Device descriptions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 MontaVista Software, Inc. by Vitaly Bordug<vbordug@ru.mvista.com> | 8 | * Copyright 2005 MontaVista Software, Inc. by Vitaly Bordug<vbordug@ru.mvista.com> |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/mpc8xx_sys.c b/arch/ppc/syslib/mpc8xx_sys.c index 3cc27d29e3af..d3c617521603 100644 --- a/arch/ppc/syslib/mpc8xx_sys.c +++ b/arch/ppc/syslib/mpc8xx_sys.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC8xx System descriptions | 4 | * MPC8xx System descriptions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 MontaVista Software, Inc. by Vitaly Bordug <vbordug@ru.mvista.com> | 8 | * Copyright 2005 MontaVista Software, Inc. by Vitaly Bordug <vbordug@ru.mvista.com> |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/ppc83xx_setup.c b/arch/ppc/syslib/ppc83xx_setup.c index 4da168a6ad03..1b5fe9e398d4 100644 --- a/arch/ppc/syslib/ppc83xx_setup.c +++ b/arch/ppc/syslib/ppc83xx_setup.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC83XX common board code | 4 | * MPC83XX common board code |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor Inc. | 8 | * Copyright 2005 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/ppc83xx_setup.h b/arch/ppc/syslib/ppc83xx_setup.h index c766c1a5f786..a122a7322e5e 100644 --- a/arch/ppc/syslib/ppc83xx_setup.h +++ b/arch/ppc/syslib/ppc83xx_setup.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC83XX common board definitions | 4 | * MPC83XX common board definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor Inc. | 8 | * Copyright 2005 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/ppc85xx_common.c b/arch/ppc/syslib/ppc85xx_common.c index da841dacdc13..19ad537225e4 100644 --- a/arch/ppc/syslib/ppc85xx_common.c +++ b/arch/ppc/syslib/ppc85xx_common.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85xx support routines | 4 | * MPC85xx support routines |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/ppc85xx_common.h b/arch/ppc/syslib/ppc85xx_common.h index 2c8f304441bf..94edf32151dd 100644 --- a/arch/ppc/syslib/ppc85xx_common.h +++ b/arch/ppc/syslib/ppc85xx_common.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85xx support routines | 4 | * MPC85xx support routines |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/ppc85xx_setup.c b/arch/ppc/syslib/ppc85xx_setup.c index de2f90576577..1a47ff4b831d 100644 --- a/arch/ppc/syslib/ppc85xx_setup.c +++ b/arch/ppc/syslib/ppc85xx_setup.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85XX common board code | 4 | * MPC85XX common board code |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/ppc85xx_setup.h b/arch/ppc/syslib/ppc85xx_setup.h index 6e6cfe162faf..e340b0545fb5 100644 --- a/arch/ppc/syslib/ppc85xx_setup.h +++ b/arch/ppc/syslib/ppc85xx_setup.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85XX common board definitions | 4 | * MPC85XX common board definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor Inc. | 8 | * Copyright 2004 Freescale Semiconductor Inc. |
9 | * | 9 | * |
diff --git a/arch/ppc/syslib/ppc_sys.c b/arch/ppc/syslib/ppc_sys.c index 603f01190816..c0b93c4191ee 100644 --- a/arch/ppc/syslib/ppc_sys.c +++ b/arch/ppc/syslib/ppc_sys.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * PPC System library functions | 4 | * PPC System library functions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor Inc. | 8 | * Copyright 2005 Freescale Semiconductor Inc. |
9 | * Copyright 2005 MontaVista, Inc. by Vitaly Bordug <vbordug@ru.mvista.com> | 9 | * Copyright 2005 MontaVista, Inc. by Vitaly Bordug <vbordug@ru.mvista.com> |
diff --git a/arch/ppc/syslib/pq2_devices.c b/arch/ppc/syslib/pq2_devices.c index e960fe935325..6ff3aab82fc3 100644 --- a/arch/ppc/syslib/pq2_devices.c +++ b/arch/ppc/syslib/pq2_devices.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * PQ2 Device descriptions | 4 | * PQ2 Device descriptions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * This file is licensed under the terms of the GNU General Public License | 8 | * This file is licensed under the terms of the GNU General Public License |
9 | * version 2. This program is licensed "as is" without any warranty of any | 9 | * version 2. This program is licensed "as is" without any warranty of any |
diff --git a/arch/ppc/syslib/pq2_sys.c b/arch/ppc/syslib/pq2_sys.c index 7b6c9ebdb9e3..36d6e2179940 100644 --- a/arch/ppc/syslib/pq2_sys.c +++ b/arch/ppc/syslib/pq2_sys.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * PQ2 System descriptions | 4 | * PQ2 System descriptions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * This file is licensed under the terms of the GNU General Public License | 8 | * This file is licensed under the terms of the GNU General Public License |
9 | * version 2. This program is licensed "as is" without any warranty of any | 9 | * version 2. This program is licensed "as is" without any warranty of any |
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig deleted file mode 100644 index 9d10c12e87fe..000000000000 --- a/arch/ppc64/Kconfig +++ /dev/null | |||
@@ -1,520 +0,0 @@ | |||
1 | # | ||
2 | # For a description of the syntax of this configuration file, | ||
3 | # see Documentation/kbuild/kconfig-language.txt. | ||
4 | # | ||
5 | |||
6 | config 64BIT | ||
7 | def_bool y | ||
8 | |||
9 | config MMU | ||
10 | bool | ||
11 | default y | ||
12 | |||
13 | config PPC_STD_MMU | ||
14 | def_bool y | ||
15 | |||
16 | config UID16 | ||
17 | bool | ||
18 | |||
19 | config RWSEM_GENERIC_SPINLOCK | ||
20 | bool | ||
21 | |||
22 | config RWSEM_XCHGADD_ALGORITHM | ||
23 | bool | ||
24 | default y | ||
25 | |||
26 | config GENERIC_CALIBRATE_DELAY | ||
27 | bool | ||
28 | default y | ||
29 | |||
30 | config GENERIC_ISA_DMA | ||
31 | bool | ||
32 | default y | ||
33 | |||
34 | config EARLY_PRINTK | ||
35 | bool | ||
36 | default y | ||
37 | |||
38 | config COMPAT | ||
39 | bool | ||
40 | default y | ||
41 | |||
42 | config SCHED_NO_NO_OMIT_FRAME_POINTER | ||
43 | bool | ||
44 | default y | ||
45 | |||
46 | config ARCH_MAY_HAVE_PC_FDC | ||
47 | bool | ||
48 | default y | ||
49 | |||
50 | config PPC_STD_MMU | ||
51 | bool | ||
52 | default y | ||
53 | |||
54 | # We optimistically allocate largepages from the VM, so make the limit | ||
55 | # large enough (16MB). This badly named config option is actually | ||
56 | # max order + 1 | ||
57 | config FORCE_MAX_ZONEORDER | ||
58 | int | ||
59 | default "9" if PPC_64K_PAGES | ||
60 | default "13" | ||
61 | |||
62 | source "init/Kconfig" | ||
63 | |||
64 | config SYSVIPC_COMPAT | ||
65 | bool | ||
66 | depends on COMPAT && SYSVIPC | ||
67 | default y | ||
68 | |||
69 | menu "Platform support" | ||
70 | |||
71 | choice | ||
72 | prompt "Platform Type" | ||
73 | default PPC_MULTIPLATFORM | ||
74 | |||
75 | config PPC_ISERIES | ||
76 | bool "IBM Legacy iSeries" | ||
77 | |||
78 | config PPC_MULTIPLATFORM | ||
79 | bool "Generic" | ||
80 | |||
81 | endchoice | ||
82 | |||
83 | config PPC_PSERIES | ||
84 | depends on PPC_MULTIPLATFORM | ||
85 | bool " IBM pSeries & new iSeries" | ||
86 | default y | ||
87 | |||
88 | config PPC_BPA | ||
89 | bool " Broadband Processor Architecture" | ||
90 | depends on PPC_MULTIPLATFORM | ||
91 | |||
92 | config PPC_PMAC | ||
93 | depends on PPC_MULTIPLATFORM | ||
94 | bool " Apple G5 based machines" | ||
95 | default y | ||
96 | select U3_DART | ||
97 | select GENERIC_TBSYNC | ||
98 | |||
99 | config PPC_MAPLE | ||
100 | depends on PPC_MULTIPLATFORM | ||
101 | bool " Maple 970FX Evaluation Board" | ||
102 | select U3_DART | ||
103 | select MPIC_BROKEN_U3 | ||
104 | select GENERIC_TBSYNC | ||
105 | default n | ||
106 | help | ||
107 | This option enables support for the Maple 970FX Evaluation Board. | ||
108 | For more informations, refer to <http://www.970eval.com> | ||
109 | |||
110 | config PPC | ||
111 | bool | ||
112 | default y | ||
113 | |||
114 | config PPC64 | ||
115 | bool | ||
116 | default y | ||
117 | |||
118 | config PPC_OF | ||
119 | depends on PPC_MULTIPLATFORM | ||
120 | bool | ||
121 | default y | ||
122 | |||
123 | config XICS | ||
124 | depends on PPC_PSERIES | ||
125 | bool | ||
126 | default y | ||
127 | |||
128 | config MPIC | ||
129 | depends on PPC_PSERIES || PPC_PMAC || PPC_MAPLE | ||
130 | bool | ||
131 | default y | ||
132 | |||
133 | config PPC_I8259 | ||
134 | depends on PPC_PSERIES | ||
135 | bool | ||
136 | default y | ||
137 | |||
138 | config BPA_IIC | ||
139 | depends on PPC_BPA | ||
140 | bool | ||
141 | default y | ||
142 | |||
143 | # VMX is pSeries only for now until somebody writes the iSeries | ||
144 | # exception vectors for it | ||
145 | config ALTIVEC | ||
146 | bool "Support for VMX (Altivec) vector unit" | ||
147 | depends on PPC_MULTIPLATFORM | ||
148 | default y | ||
149 | |||
150 | config PPC_SPLPAR | ||
151 | depends on PPC_PSERIES | ||
152 | bool "Support for shared-processor logical partitions" | ||
153 | default n | ||
154 | help | ||
155 | Enabling this option will make the kernel run more efficiently | ||
156 | on logically-partitioned pSeries systems which use shared | ||
157 | processors, that is, which share physical processors between | ||
158 | two or more partitions. | ||
159 | |||
160 | config KEXEC | ||
161 | bool "kexec system call (EXPERIMENTAL)" | ||
162 | depends on PPC_MULTIPLATFORM && EXPERIMENTAL | ||
163 | help | ||
164 | kexec is a system call that implements the ability to shutdown your | ||
165 | current kernel, and to start another kernel. It is like a reboot | ||
166 | but it is indepedent of the system firmware. And like a reboot | ||
167 | you can start any kernel with it, not just Linux. | ||
168 | |||
169 | The name comes from the similiarity to the exec system call. | ||
170 | |||
171 | It is an ongoing process to be certain the hardware in a machine | ||
172 | is properly shutdown, so do not be surprised if this code does not | ||
173 | initially work for you. It may help to enable device hotplugging | ||
174 | support. As of this writing the exact hardware interface is | ||
175 | strongly in flux, so no good recommendation can be made. | ||
176 | |||
177 | source "drivers/cpufreq/Kconfig" | ||
178 | |||
179 | config CPU_FREQ_PMAC64 | ||
180 | bool "Support for some Apple G5s" | ||
181 | depends on CPU_FREQ && PMAC_SMU && PPC64 | ||
182 | select CPU_FREQ_TABLE | ||
183 | help | ||
184 | This adds support for frequency switching on Apple iMac G5, | ||
185 | and some of the more recent desktop G5 machines as well. | ||
186 | |||
187 | config IBMVIO | ||
188 | depends on PPC_PSERIES || PPC_ISERIES | ||
189 | bool | ||
190 | default y | ||
191 | |||
192 | config U3_DART | ||
193 | bool | ||
194 | depends on PPC_MULTIPLATFORM | ||
195 | default n | ||
196 | |||
197 | config MPIC_BROKEN_U3 | ||
198 | bool | ||
199 | depends on PPC_MAPLE | ||
200 | default y | ||
201 | |||
202 | config GENERIC_TBSYNC | ||
203 | def_bool n | ||
204 | |||
205 | config PPC_PMAC64 | ||
206 | bool | ||
207 | depends on PPC_PMAC | ||
208 | default y | ||
209 | |||
210 | config BOOTX_TEXT | ||
211 | bool "Support for early boot text console" | ||
212 | depends PPC_OF | ||
213 | help | ||
214 | Say Y here to see progress messages from the boot firmware in text | ||
215 | mode. Requires an Open Firmware compatible video card. | ||
216 | |||
217 | config POWER4 | ||
218 | def_bool y | ||
219 | |||
220 | config PPC_FPU | ||
221 | def_bool y | ||
222 | |||
223 | config POWER4_ONLY | ||
224 | bool "Optimize for POWER4" | ||
225 | default n | ||
226 | ---help--- | ||
227 | Cause the compiler to optimize for POWER4 processors. The resulting | ||
228 | binary will not work on POWER3 or RS64 processors when compiled with | ||
229 | binutils 2.15 or later. | ||
230 | |||
231 | config IOMMU_VMERGE | ||
232 | bool "Enable IOMMU virtual merging (EXPERIMENTAL)" | ||
233 | depends on EXPERIMENTAL | ||
234 | default n | ||
235 | help | ||
236 | Cause IO segments sent to a device for DMA to be merged virtually | ||
237 | by the IOMMU when they happen to have been allocated contiguously. | ||
238 | This doesn't add pressure to the IOMMU allocator. However, some | ||
239 | drivers don't support getting large merged segments coming back | ||
240 | from *_map_sg(). Say Y if you know the drivers you are using are | ||
241 | properly handling this case. | ||
242 | |||
243 | config SMP | ||
244 | bool "Symmetric multi-processing support" | ||
245 | ---help--- | ||
246 | This enables support for systems with more than one CPU. If you have | ||
247 | a system with only one CPU, say N. If you have a system with more | ||
248 | than one CPU, say Y. | ||
249 | |||
250 | If you say N here, the kernel will run on single and multiprocessor | ||
251 | machines, but will use only one CPU of a multiprocessor machine. If | ||
252 | you say Y here, the kernel will run on single-processor machines. | ||
253 | On a single-processor machine, the kernel will run faster if you say | ||
254 | N here. | ||
255 | |||
256 | If you don't know what to do here, say Y. | ||
257 | |||
258 | config NR_CPUS | ||
259 | int "Maximum number of CPUs (2-128)" | ||
260 | range 2 128 | ||
261 | depends on SMP | ||
262 | default "32" | ||
263 | |||
264 | config HMT | ||
265 | bool "Hardware multithreading" | ||
266 | depends on SMP && PPC_PSERIES && BROKEN | ||
267 | help | ||
268 | This option enables hardware multithreading on RS64 cpus. | ||
269 | pSeries systems p620 and p660 have such a cpu type. | ||
270 | |||
271 | config NUMA | ||
272 | bool "NUMA support" | ||
273 | default y if SMP && PPC_PSERIES | ||
274 | |||
275 | config ARCH_SELECT_MEMORY_MODEL | ||
276 | def_bool y | ||
277 | |||
278 | config ARCH_FLATMEM_ENABLE | ||
279 | def_bool y | ||
280 | depends on !NUMA | ||
281 | |||
282 | config ARCH_SPARSEMEM_ENABLE | ||
283 | def_bool y | ||
284 | |||
285 | config ARCH_SPARSEMEM_DEFAULT | ||
286 | def_bool y | ||
287 | depends on NUMA | ||
288 | |||
289 | source "mm/Kconfig" | ||
290 | |||
291 | config HAVE_ARCH_EARLY_PFN_TO_NID | ||
292 | def_bool y | ||
293 | depends on NEED_MULTIPLE_NODES | ||
294 | |||
295 | config ARCH_MEMORY_PROBE | ||
296 | def_bool y | ||
297 | depends on MEMORY_HOTPLUG | ||
298 | |||
299 | # Some NUMA nodes have memory ranges that span | ||
300 | # other nodes. Even though a pfn is valid and | ||
301 | # between a node's start and end pfns, it may not | ||
302 | # reside on that node. | ||
303 | # | ||
304 | # This is a relatively temporary hack that should | ||
305 | # be able to go away when sparsemem is fully in | ||
306 | # place | ||
307 | config NODES_SPAN_OTHER_NODES | ||
308 | def_bool y | ||
309 | depends on NEED_MULTIPLE_NODES | ||
310 | |||
311 | config PPC_64K_PAGES | ||
312 | bool "64k page size" | ||
313 | help | ||
314 | This option changes the kernel logical page size to 64k. On machines | ||
315 | without processor support for 64k pages, the kernel will simulate | ||
316 | them by loading each individual 4k page on demand transparently, | ||
317 | while on hardware with such support, it will be used to map | ||
318 | normal application pages. | ||
319 | |||
320 | config SCHED_SMT | ||
321 | bool "SMT (Hyperthreading) scheduler support" | ||
322 | depends on SMP | ||
323 | default off | ||
324 | help | ||
325 | SMT scheduler support improves the CPU scheduler's decision making | ||
326 | when dealing with POWER5 cpus at a cost of slightly increased | ||
327 | overhead in some places. If unsure say N here. | ||
328 | |||
329 | source "kernel/Kconfig.preempt" | ||
330 | source kernel/Kconfig.hz | ||
331 | |||
332 | config EEH | ||
333 | bool "PCI Extended Error Handling (EEH)" if EMBEDDED | ||
334 | depends on PPC_PSERIES | ||
335 | default y if !EMBEDDED | ||
336 | |||
337 | # | ||
338 | # Use the generic interrupt handling code in kernel/irq/: | ||
339 | # | ||
340 | config GENERIC_HARDIRQS | ||
341 | bool | ||
342 | default y | ||
343 | |||
344 | config PPC_RTAS | ||
345 | bool | ||
346 | depends on PPC_PSERIES || PPC_BPA | ||
347 | default y | ||
348 | |||
349 | config RTAS_ERROR_LOGGING | ||
350 | bool | ||
351 | depends on PPC_RTAS | ||
352 | default y | ||
353 | |||
354 | config RTAS_PROC | ||
355 | bool "Proc interface to RTAS" | ||
356 | depends on PPC_RTAS | ||
357 | default y | ||
358 | |||
359 | config RTAS_FLASH | ||
360 | tristate "Firmware flash interface" | ||
361 | depends on RTAS_PROC | ||
362 | |||
363 | config SCANLOG | ||
364 | tristate "Scanlog dump interface" | ||
365 | depends on RTAS_PROC && PPC_PSERIES | ||
366 | |||
367 | config LPARCFG | ||
368 | tristate "LPAR Configuration Data" | ||
369 | depends on PPC_PSERIES || PPC_ISERIES | ||
370 | help | ||
371 | Provide system capacity information via human readable | ||
372 | <key word>=<value> pairs through a /proc/ppc64/lparcfg interface. | ||
373 | |||
374 | config SECCOMP | ||
375 | bool "Enable seccomp to safely compute untrusted bytecode" | ||
376 | depends on PROC_FS | ||
377 | default y | ||
378 | help | ||
379 | This kernel feature is useful for number crunching applications | ||
380 | that may need to compute untrusted bytecode during their | ||
381 | execution. By using pipes or other transports made available to | ||
382 | the process as file descriptors supporting the read/write | ||
383 | syscalls, it's possible to isolate those applications in | ||
384 | their own address space using seccomp. Once seccomp is | ||
385 | enabled via /proc/<pid>/seccomp, it cannot be disabled | ||
386 | and the task is only allowed to execute a few safe syscalls | ||
387 | defined by each seccomp mode. | ||
388 | |||
389 | If unsure, say Y. Only embedded should say N here. | ||
390 | |||
391 | source "fs/Kconfig.binfmt" | ||
392 | |||
393 | config HOTPLUG_CPU | ||
394 | bool "Support for hot-pluggable CPUs" | ||
395 | depends on SMP && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC) | ||
396 | select HOTPLUG | ||
397 | ---help--- | ||
398 | Say Y here to be able to turn CPUs off and on. | ||
399 | |||
400 | Say N if you are unsure. | ||
401 | |||
402 | config PROC_DEVICETREE | ||
403 | bool "Support for Open Firmware device tree in /proc" | ||
404 | help | ||
405 | This option adds a device-tree directory under /proc which contains | ||
406 | an image of the device tree that the kernel copies from Open | ||
407 | Firmware. If unsure, say Y here. | ||
408 | |||
409 | config CMDLINE_BOOL | ||
410 | bool "Default bootloader kernel arguments" | ||
411 | depends on !PPC_ISERIES | ||
412 | |||
413 | config CMDLINE | ||
414 | string "Initial kernel command string" | ||
415 | depends on CMDLINE_BOOL | ||
416 | default "console=ttyS0,9600 console=tty0 root=/dev/sda2" | ||
417 | help | ||
418 | On some platforms, there is currently no way for the boot loader to | ||
419 | pass arguments to the kernel. For these platforms, you can supply | ||
420 | some command-line options at build time by entering them here. In | ||
421 | most cases you will need to specify the root device here. | ||
422 | |||
423 | endmenu | ||
424 | |||
425 | config ISA_DMA_API | ||
426 | bool | ||
427 | default y | ||
428 | |||
429 | menu "Bus Options" | ||
430 | |||
431 | config ISA | ||
432 | bool | ||
433 | help | ||
434 | Find out whether you have ISA slots on your motherboard. ISA is the | ||
435 | name of a bus system, i.e. the way the CPU talks to the other stuff | ||
436 | inside your box. If you have an Apple machine, say N here; if you | ||
437 | have an IBM RS/6000 or pSeries machine or a PReP machine, say Y. If | ||
438 | you have an embedded board, consult your board documentation. | ||
439 | |||
440 | config SBUS | ||
441 | bool | ||
442 | |||
443 | config MCA | ||
444 | bool | ||
445 | |||
446 | config EISA | ||
447 | bool | ||
448 | |||
449 | config PCI | ||
450 | bool "support for PCI devices" if (EMBEDDED && PPC_ISERIES) | ||
451 | default y | ||
452 | help | ||
453 | Find out whether your system includes a PCI bus. PCI is the name of | ||
454 | a bus system, i.e. the way the CPU talks to the other stuff inside | ||
455 | your box. If you say Y here, the kernel will include drivers and | ||
456 | infrastructure code to support PCI bus devices. | ||
457 | |||
458 | config PCI_DOMAINS | ||
459 | bool | ||
460 | default PCI | ||
461 | |||
462 | source "drivers/pci/Kconfig" | ||
463 | |||
464 | source "drivers/pcmcia/Kconfig" | ||
465 | |||
466 | source "drivers/pci/hotplug/Kconfig" | ||
467 | |||
468 | endmenu | ||
469 | |||
470 | source "net/Kconfig" | ||
471 | |||
472 | source "drivers/Kconfig" | ||
473 | |||
474 | source "fs/Kconfig" | ||
475 | |||
476 | menu "iSeries device drivers" | ||
477 | depends on PPC_ISERIES | ||
478 | |||
479 | config VIOCONS | ||
480 | tristate "iSeries Virtual Console Support" | ||
481 | |||
482 | config VIODASD | ||
483 | tristate "iSeries Virtual I/O disk support" | ||
484 | help | ||
485 | If you are running on an iSeries system and you want to use | ||
486 | virtual disks created and managed by OS/400, say Y. | ||
487 | |||
488 | config VIOCD | ||
489 | tristate "iSeries Virtual I/O CD support" | ||
490 | help | ||
491 | If you are running Linux on an IBM iSeries system and you want to | ||
492 | read a CD drive owned by OS/400, say Y here. | ||
493 | |||
494 | config VIOTAPE | ||
495 | tristate "iSeries Virtual Tape Support" | ||
496 | help | ||
497 | If you are running Linux on an iSeries system and you want Linux | ||
498 | to read and/or write a tape drive owned by OS/400, say Y here. | ||
499 | |||
500 | endmenu | ||
501 | |||
502 | config VIOPATH | ||
503 | bool | ||
504 | depends on VIOCONS || VIODASD || VIOCD || VIOTAPE || VETH | ||
505 | default y | ||
506 | |||
507 | source "arch/powerpc/oprofile/Kconfig" | ||
508 | |||
509 | source "arch/ppc64/Kconfig.debug" | ||
510 | |||
511 | source "security/Kconfig" | ||
512 | |||
513 | config KEYS_COMPAT | ||
514 | bool | ||
515 | depends on COMPAT && KEYS | ||
516 | default y | ||
517 | |||
518 | source "crypto/Kconfig" | ||
519 | |||
520 | source "lib/Kconfig" | ||
diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile index dac4cc20fa93..e876c213f5ce 100644 --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile | |||
@@ -2,45 +2,6 @@ | |||
2 | # Makefile for the linux ppc64 kernel. | 2 | # Makefile for the linux ppc64 kernel. |
3 | # | 3 | # |
4 | 4 | ||
5 | ifneq ($(CONFIG_PPC_MERGE),y) | 5 | obj-y += idle.o align.o |
6 | |||
7 | EXTRA_CFLAGS += -mno-minimal-toc | ||
8 | extra-y := head.o vmlinux.lds | ||
9 | |||
10 | obj-y := misc.o prom.o | ||
11 | |||
12 | endif | ||
13 | |||
14 | obj-y += idle.o dma.o \ | ||
15 | align.o \ | ||
16 | rtc.o \ | ||
17 | iommu.o | ||
18 | |||
19 | pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += pci_dn.o pci_direct_iommu.o | ||
20 | |||
21 | obj-$(CONFIG_PCI) += pci.o pci_iommu.o iomap.o $(pci-obj-y) | ||
22 | 6 | ||
23 | obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o | 7 | obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o |
24 | ifneq ($(CONFIG_PPC_MERGE),y) | ||
25 | obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o | ||
26 | endif | ||
27 | |||
28 | obj-$(CONFIG_KEXEC) += machine_kexec.o | ||
29 | obj-$(CONFIG_MODULES) += module.o | ||
30 | ifneq ($(CONFIG_PPC_MERGE),y) | ||
31 | obj-$(CONFIG_MODULES) += ppc_ksyms.o | ||
32 | endif | ||
33 | obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o | ||
34 | ifneq ($(CONFIG_PPC_MERGE),y) | ||
35 | obj-$(CONFIG_BOOTX_TEXT) += btext.o | ||
36 | endif | ||
37 | obj-$(CONFIG_HVCS) += hvcserver.o | ||
38 | |||
39 | obj-$(CONFIG_KPROBES) += kprobes.o | ||
40 | |||
41 | ifneq ($(CONFIG_PPC_MERGE),y) | ||
42 | ifeq ($(CONFIG_PPC_ISERIES),y) | ||
43 | arch/ppc64/kernel/head.o: arch/powerpc/kernel/lparmap.s | ||
44 | AFLAGS_head.o += -Iarch/powerpc/kernel | ||
45 | endif | ||
46 | endif | ||
diff --git a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c deleted file mode 100644 index 84ab5c18ef52..000000000000 --- a/arch/ppc64/kernel/asm-offsets.c +++ /dev/null | |||
@@ -1,195 +0,0 @@ | |||
1 | /* | ||
2 | * This program is used to generate definitions needed by | ||
3 | * assembly language modules. | ||
4 | * | ||
5 | * We use the technique used in the OSF Mach kernel code: | ||
6 | * generate asm statements containing #defines, | ||
7 | * compile this file to assembler, and then extract the | ||
8 | * #defines from the assembly-language output. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * as published by the Free Software Foundation; either version | ||
13 | * 2 of the License, or (at your option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/config.h> | ||
17 | #include <linux/signal.h> | ||
18 | #include <linux/sched.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/errno.h> | ||
21 | #include <linux/string.h> | ||
22 | #include <linux/types.h> | ||
23 | #include <linux/mman.h> | ||
24 | #include <linux/mm.h> | ||
25 | #include <linux/time.h> | ||
26 | #include <linux/hardirq.h> | ||
27 | #include <asm/io.h> | ||
28 | #include <asm/page.h> | ||
29 | #include <asm/pgtable.h> | ||
30 | #include <asm/processor.h> | ||
31 | |||
32 | #include <asm/paca.h> | ||
33 | #include <asm/lppaca.h> | ||
34 | #include <asm/iseries/hv_lp_event.h> | ||
35 | #include <asm/rtas.h> | ||
36 | #include <asm/cputable.h> | ||
37 | #include <asm/cache.h> | ||
38 | #include <asm/systemcfg.h> | ||
39 | #include <asm/compat.h> | ||
40 | |||
41 | #define DEFINE(sym, val) \ | ||
42 | asm volatile("\n->" #sym " %0 " #val : : "i" (val)) | ||
43 | |||
44 | #define BLANK() asm volatile("\n->" : : ) | ||
45 | |||
46 | int main(void) | ||
47 | { | ||
48 | /* thread struct on stack */ | ||
49 | DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); | ||
50 | DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); | ||
51 | DEFINE(TI_SC_NOERR, offsetof(struct thread_info, syscall_noerror)); | ||
52 | |||
53 | /* task_struct->thread */ | ||
54 | DEFINE(THREAD, offsetof(struct task_struct, thread)); | ||
55 | DEFINE(PT_REGS, offsetof(struct thread_struct, regs)); | ||
56 | DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode)); | ||
57 | DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0])); | ||
58 | DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr)); | ||
59 | DEFINE(KSP, offsetof(struct thread_struct, ksp)); | ||
60 | DEFINE(KSP_VSID, offsetof(struct thread_struct, ksp_vsid)); | ||
61 | |||
62 | #ifdef CONFIG_ALTIVEC | ||
63 | DEFINE(THREAD_VR0, offsetof(struct thread_struct, vr[0])); | ||
64 | DEFINE(THREAD_VRSAVE, offsetof(struct thread_struct, vrsave)); | ||
65 | DEFINE(THREAD_VSCR, offsetof(struct thread_struct, vscr)); | ||
66 | DEFINE(THREAD_USED_VR, offsetof(struct thread_struct, used_vr)); | ||
67 | #endif /* CONFIG_ALTIVEC */ | ||
68 | DEFINE(MM, offsetof(struct task_struct, mm)); | ||
69 | DEFINE(AUDITCONTEXT, offsetof(struct task_struct, audit_context)); | ||
70 | |||
71 | DEFINE(DCACHEL1LINESIZE, offsetof(struct ppc64_caches, dline_size)); | ||
72 | DEFINE(DCACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_dline_size)); | ||
73 | DEFINE(DCACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, dlines_per_page)); | ||
74 | DEFINE(ICACHEL1LINESIZE, offsetof(struct ppc64_caches, iline_size)); | ||
75 | DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size)); | ||
76 | DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page)); | ||
77 | DEFINE(PLATFORM_LPAR, PLATFORM_LPAR); | ||
78 | |||
79 | /* paca */ | ||
80 | DEFINE(PACA_SIZE, sizeof(struct paca_struct)); | ||
81 | DEFINE(PACAPACAINDEX, offsetof(struct paca_struct, paca_index)); | ||
82 | DEFINE(PACAPROCSTART, offsetof(struct paca_struct, cpu_start)); | ||
83 | DEFINE(PACAKSAVE, offsetof(struct paca_struct, kstack)); | ||
84 | DEFINE(PACACURRENT, offsetof(struct paca_struct, __current)); | ||
85 | DEFINE(PACASAVEDMSR, offsetof(struct paca_struct, saved_msr)); | ||
86 | DEFINE(PACASTABREAL, offsetof(struct paca_struct, stab_real)); | ||
87 | DEFINE(PACASTABVIRT, offsetof(struct paca_struct, stab_addr)); | ||
88 | DEFINE(PACASTABRR, offsetof(struct paca_struct, stab_rr)); | ||
89 | DEFINE(PACAR1, offsetof(struct paca_struct, saved_r1)); | ||
90 | DEFINE(PACATOC, offsetof(struct paca_struct, kernel_toc)); | ||
91 | DEFINE(PACAPROCENABLED, offsetof(struct paca_struct, proc_enabled)); | ||
92 | DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); | ||
93 | DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); | ||
94 | DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); | ||
95 | #ifdef CONFIG_PPC_64K_PAGES | ||
96 | DEFINE(PACAPGDIR, offsetof(struct paca_struct, pgdir)); | ||
97 | #endif | ||
98 | #ifdef CONFIG_HUGETLB_PAGE | ||
99 | DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas)); | ||
100 | DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas)); | ||
101 | #endif /* CONFIG_HUGETLB_PAGE */ | ||
102 | DEFINE(PACADEFAULTDECR, offsetof(struct paca_struct, default_decr)); | ||
103 | DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen)); | ||
104 | DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc)); | ||
105 | DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb)); | ||
106 | DEFINE(PACA_EXDSI, offsetof(struct paca_struct, exdsi)); | ||
107 | DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp)); | ||
108 | DEFINE(PACALPPACA, offsetof(struct paca_struct, lppaca)); | ||
109 | DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); | ||
110 | DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0)); | ||
111 | DEFINE(LPPACASRR1, offsetof(struct lppaca, saved_srr1)); | ||
112 | DEFINE(LPPACAANYINT, offsetof(struct lppaca, int_dword.any_int)); | ||
113 | DEFINE(LPPACADECRINT, offsetof(struct lppaca, int_dword.fields.decr_int)); | ||
114 | |||
115 | /* RTAS */ | ||
116 | DEFINE(RTASBASE, offsetof(struct rtas_t, base)); | ||
117 | DEFINE(RTASENTRY, offsetof(struct rtas_t, entry)); | ||
118 | |||
119 | /* Interrupt register frame */ | ||
120 | DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD); | ||
121 | |||
122 | DEFINE(SWITCH_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs)); | ||
123 | |||
124 | /* 288 = # of volatile regs, int & fp, for leaf routines */ | ||
125 | /* which do not stack a frame. See the PPC64 ABI. */ | ||
126 | DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 288); | ||
127 | /* Create extra stack space for SRR0 and SRR1 when calling prom/rtas. */ | ||
128 | DEFINE(PROM_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16); | ||
129 | DEFINE(RTAS_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16); | ||
130 | DEFINE(GPR0, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[0])); | ||
131 | DEFINE(GPR1, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[1])); | ||
132 | DEFINE(GPR2, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[2])); | ||
133 | DEFINE(GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[3])); | ||
134 | DEFINE(GPR4, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[4])); | ||
135 | DEFINE(GPR5, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[5])); | ||
136 | DEFINE(GPR6, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[6])); | ||
137 | DEFINE(GPR7, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[7])); | ||
138 | DEFINE(GPR8, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[8])); | ||
139 | DEFINE(GPR9, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[9])); | ||
140 | DEFINE(GPR10, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[10])); | ||
141 | DEFINE(GPR11, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[11])); | ||
142 | DEFINE(GPR12, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[12])); | ||
143 | DEFINE(GPR13, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[13])); | ||
144 | /* | ||
145 | * Note: these symbols include _ because they overlap with special | ||
146 | * register names | ||
147 | */ | ||
148 | DEFINE(_NIP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, nip)); | ||
149 | DEFINE(_MSR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, msr)); | ||
150 | DEFINE(_CTR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, ctr)); | ||
151 | DEFINE(_LINK, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, link)); | ||
152 | DEFINE(_CCR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, ccr)); | ||
153 | DEFINE(_XER, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, xer)); | ||
154 | DEFINE(_DAR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dar)); | ||
155 | DEFINE(_DSISR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dsisr)); | ||
156 | DEFINE(ORIG_GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, orig_gpr3)); | ||
157 | DEFINE(RESULT, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, result)); | ||
158 | DEFINE(_TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap)); | ||
159 | DEFINE(SOFTE, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, softe)); | ||
160 | |||
161 | /* These _only_ to be used with {PROM,RTAS}_FRAME_SIZE!!! */ | ||
162 | DEFINE(_SRR0, STACK_FRAME_OVERHEAD+sizeof(struct pt_regs)); | ||
163 | DEFINE(_SRR1, STACK_FRAME_OVERHEAD+sizeof(struct pt_regs)+8); | ||
164 | |||
165 | DEFINE(CLONE_VM, CLONE_VM); | ||
166 | DEFINE(CLONE_UNTRACED, CLONE_UNTRACED); | ||
167 | |||
168 | /* About the CPU features table */ | ||
169 | DEFINE(CPU_SPEC_ENTRY_SIZE, sizeof(struct cpu_spec)); | ||
170 | DEFINE(CPU_SPEC_PVR_MASK, offsetof(struct cpu_spec, pvr_mask)); | ||
171 | DEFINE(CPU_SPEC_PVR_VALUE, offsetof(struct cpu_spec, pvr_value)); | ||
172 | DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features)); | ||
173 | DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup)); | ||
174 | |||
175 | /* systemcfg offsets for use by vdso */ | ||
176 | DEFINE(CFG_TB_ORIG_STAMP, offsetof(struct systemcfg, tb_orig_stamp)); | ||
177 | DEFINE(CFG_TB_TICKS_PER_SEC, offsetof(struct systemcfg, tb_ticks_per_sec)); | ||
178 | DEFINE(CFG_TB_TO_XS, offsetof(struct systemcfg, tb_to_xs)); | ||
179 | DEFINE(CFG_STAMP_XSEC, offsetof(struct systemcfg, stamp_xsec)); | ||
180 | DEFINE(CFG_TB_UPDATE_COUNT, offsetof(struct systemcfg, tb_update_count)); | ||
181 | DEFINE(CFG_TZ_MINUTEWEST, offsetof(struct systemcfg, tz_minuteswest)); | ||
182 | DEFINE(CFG_TZ_DSTTIME, offsetof(struct systemcfg, tz_dsttime)); | ||
183 | DEFINE(CFG_SYSCALL_MAP32, offsetof(struct systemcfg, syscall_map_32)); | ||
184 | DEFINE(CFG_SYSCALL_MAP64, offsetof(struct systemcfg, syscall_map_64)); | ||
185 | |||
186 | /* timeval/timezone offsets for use by vdso */ | ||
187 | DEFINE(TVAL64_TV_SEC, offsetof(struct timeval, tv_sec)); | ||
188 | DEFINE(TVAL64_TV_USEC, offsetof(struct timeval, tv_usec)); | ||
189 | DEFINE(TVAL32_TV_SEC, offsetof(struct compat_timeval, tv_sec)); | ||
190 | DEFINE(TVAL32_TV_USEC, offsetof(struct compat_timeval, tv_usec)); | ||
191 | DEFINE(TZONE_TZ_MINWEST, offsetof(struct timezone, tz_minuteswest)); | ||
192 | DEFINE(TZONE_TZ_DSTTIME, offsetof(struct timezone, tz_dsttime)); | ||
193 | |||
194 | return 0; | ||
195 | } | ||
diff --git a/arch/ppc64/kernel/btext.c b/arch/ppc64/kernel/btext.c deleted file mode 100644 index 506a37885c5c..000000000000 --- a/arch/ppc64/kernel/btext.c +++ /dev/null | |||
@@ -1,792 +0,0 @@ | |||
1 | /* | ||
2 | * Procedures for drawing on the screen early on in the boot process. | ||
3 | * | ||
4 | * Benjamin Herrenschmidt <benh@kernel.crashing.org> | ||
5 | */ | ||
6 | #include <linux/config.h> | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/string.h> | ||
9 | #include <linux/init.h> | ||
10 | |||
11 | #include <asm/sections.h> | ||
12 | #include <asm/prom.h> | ||
13 | #include <asm/btext.h> | ||
14 | #include <asm/prom.h> | ||
15 | #include <asm/page.h> | ||
16 | #include <asm/mmu.h> | ||
17 | #include <asm/pgtable.h> | ||
18 | #include <asm/io.h> | ||
19 | #include <asm/lmb.h> | ||
20 | #include <asm/processor.h> | ||
21 | #include <asm/udbg.h> | ||
22 | |||
23 | #undef NO_SCROLL | ||
24 | |||
25 | #ifndef NO_SCROLL | ||
26 | static void scrollscreen(void); | ||
27 | #endif | ||
28 | |||
29 | static void draw_byte(unsigned char c, long locX, long locY); | ||
30 | static void draw_byte_32(unsigned char *bits, unsigned int *base, int rb); | ||
31 | static void draw_byte_16(unsigned char *bits, unsigned int *base, int rb); | ||
32 | static void draw_byte_8(unsigned char *bits, unsigned int *base, int rb); | ||
33 | |||
34 | static int g_loc_X; | ||
35 | static int g_loc_Y; | ||
36 | static int g_max_loc_X; | ||
37 | static int g_max_loc_Y; | ||
38 | |||
39 | static int dispDeviceRowBytes; | ||
40 | static int dispDeviceDepth; | ||
41 | static int dispDeviceRect[4]; | ||
42 | static unsigned char *dispDeviceBase, *logicalDisplayBase; | ||
43 | |||
44 | unsigned long disp_BAT[2] __initdata = {0, 0}; | ||
45 | |||
46 | #define cmapsz (16*256) | ||
47 | |||
48 | static unsigned char vga_font[cmapsz]; | ||
49 | |||
50 | int boot_text_mapped; | ||
51 | int force_printk_to_btext = 0; | ||
52 | |||
53 | |||
54 | /* Here's a small text engine to use during early boot | ||
55 | * or for debugging purposes | ||
56 | * | ||
57 | * todo: | ||
58 | * | ||
59 | * - build some kind of vgacon with it to enable early printk | ||
60 | * - move to a separate file | ||
61 | * - add a few video driver hooks to keep in sync with display | ||
62 | * changes. | ||
63 | */ | ||
64 | |||
65 | void map_boot_text(void) | ||
66 | { | ||
67 | unsigned long base, offset, size; | ||
68 | unsigned char *vbase; | ||
69 | |||
70 | /* By default, we are no longer mapped */ | ||
71 | boot_text_mapped = 0; | ||
72 | if (dispDeviceBase == 0) | ||
73 | return; | ||
74 | base = ((unsigned long) dispDeviceBase) & 0xFFFFF000UL; | ||
75 | offset = ((unsigned long) dispDeviceBase) - base; | ||
76 | size = dispDeviceRowBytes * dispDeviceRect[3] + offset | ||
77 | + dispDeviceRect[0]; | ||
78 | vbase = __ioremap(base, size, _PAGE_NO_CACHE); | ||
79 | if (vbase == 0) | ||
80 | return; | ||
81 | logicalDisplayBase = vbase + offset; | ||
82 | boot_text_mapped = 1; | ||
83 | } | ||
84 | |||
85 | int btext_initialize(struct device_node *np) | ||
86 | { | ||
87 | unsigned int width, height, depth, pitch; | ||
88 | unsigned long address = 0; | ||
89 | u32 *prop; | ||
90 | |||
91 | prop = (u32 *)get_property(np, "width", NULL); | ||
92 | if (prop == NULL) | ||
93 | return -EINVAL; | ||
94 | width = *prop; | ||
95 | prop = (u32 *)get_property(np, "height", NULL); | ||
96 | if (prop == NULL) | ||
97 | return -EINVAL; | ||
98 | height = *prop; | ||
99 | prop = (u32 *)get_property(np, "depth", NULL); | ||
100 | if (prop == NULL) | ||
101 | return -EINVAL; | ||
102 | depth = *prop; | ||
103 | pitch = width * ((depth + 7) / 8); | ||
104 | prop = (u32 *)get_property(np, "linebytes", NULL); | ||
105 | if (prop) | ||
106 | pitch = *prop; | ||
107 | if (pitch == 1) | ||
108 | pitch = 0x1000; | ||
109 | prop = (u32 *)get_property(np, "address", NULL); | ||
110 | if (prop) | ||
111 | address = *prop; | ||
112 | |||
113 | /* FIXME: Add support for PCI reg properties */ | ||
114 | |||
115 | if (address == 0) | ||
116 | return -EINVAL; | ||
117 | |||
118 | g_loc_X = 0; | ||
119 | g_loc_Y = 0; | ||
120 | g_max_loc_X = width / 8; | ||
121 | g_max_loc_Y = height / 16; | ||
122 | logicalDisplayBase = (unsigned char *)address; | ||
123 | dispDeviceBase = (unsigned char *)address; | ||
124 | dispDeviceRowBytes = pitch; | ||
125 | dispDeviceDepth = depth; | ||
126 | dispDeviceRect[0] = dispDeviceRect[1] = 0; | ||
127 | dispDeviceRect[2] = width; | ||
128 | dispDeviceRect[3] = height; | ||
129 | |||
130 | map_boot_text(); | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static void btext_putc(unsigned char c) | ||
136 | { | ||
137 | btext_drawchar(c); | ||
138 | } | ||
139 | |||
140 | void __init init_boot_display(void) | ||
141 | { | ||
142 | char *name; | ||
143 | struct device_node *np = NULL; | ||
144 | int rc = -ENODEV; | ||
145 | |||
146 | printk("trying to initialize btext ...\n"); | ||
147 | |||
148 | name = (char *)get_property(of_chosen, "linux,stdout-path", NULL); | ||
149 | if (name != NULL) { | ||
150 | np = of_find_node_by_path(name); | ||
151 | if (np != NULL) { | ||
152 | if (strcmp(np->type, "display") != 0) { | ||
153 | printk("boot stdout isn't a display !\n"); | ||
154 | of_node_put(np); | ||
155 | np = NULL; | ||
156 | } | ||
157 | } | ||
158 | } | ||
159 | if (np) | ||
160 | rc = btext_initialize(np); | ||
161 | if (rc) { | ||
162 | for (np = NULL; (np = of_find_node_by_type(np, "display"));) { | ||
163 | if (get_property(np, "linux,opened", NULL)) { | ||
164 | printk("trying %s ...\n", np->full_name); | ||
165 | rc = btext_initialize(np); | ||
166 | printk("result: %d\n", rc); | ||
167 | } | ||
168 | if (rc == 0) | ||
169 | break; | ||
170 | } | ||
171 | } | ||
172 | if (rc == 0 && udbg_putc == NULL) | ||
173 | udbg_putc = btext_putc; | ||
174 | } | ||
175 | |||
176 | |||
177 | /* Calc the base address of a given point (x,y) */ | ||
178 | static unsigned char * calc_base(int x, int y) | ||
179 | { | ||
180 | unsigned char *base; | ||
181 | |||
182 | base = logicalDisplayBase; | ||
183 | if (base == 0) | ||
184 | base = dispDeviceBase; | ||
185 | base += (x + dispDeviceRect[0]) * (dispDeviceDepth >> 3); | ||
186 | base += (y + dispDeviceRect[1]) * dispDeviceRowBytes; | ||
187 | return base; | ||
188 | } | ||
189 | |||
190 | /* Adjust the display to a new resolution */ | ||
191 | void btext_update_display(unsigned long phys, int width, int height, | ||
192 | int depth, int pitch) | ||
193 | { | ||
194 | if (dispDeviceBase == 0) | ||
195 | return; | ||
196 | |||
197 | /* check it's the same frame buffer (within 256MB) */ | ||
198 | if ((phys ^ (unsigned long)dispDeviceBase) & 0xf0000000) | ||
199 | return; | ||
200 | |||
201 | dispDeviceBase = (__u8 *) phys; | ||
202 | dispDeviceRect[0] = 0; | ||
203 | dispDeviceRect[1] = 0; | ||
204 | dispDeviceRect[2] = width; | ||
205 | dispDeviceRect[3] = height; | ||
206 | dispDeviceDepth = depth; | ||
207 | dispDeviceRowBytes = pitch; | ||
208 | if (boot_text_mapped) { | ||
209 | iounmap(logicalDisplayBase); | ||
210 | boot_text_mapped = 0; | ||
211 | } | ||
212 | map_boot_text(); | ||
213 | g_loc_X = 0; | ||
214 | g_loc_Y = 0; | ||
215 | g_max_loc_X = width / 8; | ||
216 | g_max_loc_Y = height / 16; | ||
217 | } | ||
218 | |||
219 | void btext_clearscreen(void) | ||
220 | { | ||
221 | unsigned long *base = (unsigned long *)calc_base(0, 0); | ||
222 | unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) * | ||
223 | (dispDeviceDepth >> 3)) >> 3; | ||
224 | int i,j; | ||
225 | |||
226 | for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1]); i++) | ||
227 | { | ||
228 | unsigned long *ptr = base; | ||
229 | for(j=width; j; --j) | ||
230 | *(ptr++) = 0; | ||
231 | base += (dispDeviceRowBytes >> 3); | ||
232 | } | ||
233 | } | ||
234 | |||
235 | #ifndef NO_SCROLL | ||
236 | static void scrollscreen(void) | ||
237 | { | ||
238 | unsigned long *src = (unsigned long *)calc_base(0,16); | ||
239 | unsigned long *dst = (unsigned long *)calc_base(0,0); | ||
240 | unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) * | ||
241 | (dispDeviceDepth >> 3)) >> 3; | ||
242 | int i,j; | ||
243 | |||
244 | for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1] - 16); i++) | ||
245 | { | ||
246 | unsigned long *src_ptr = src; | ||
247 | unsigned long *dst_ptr = dst; | ||
248 | for(j=width; j; --j) | ||
249 | *(dst_ptr++) = *(src_ptr++); | ||
250 | src += (dispDeviceRowBytes >> 3); | ||
251 | dst += (dispDeviceRowBytes >> 3); | ||
252 | } | ||
253 | for (i=0; i<16; i++) | ||
254 | { | ||
255 | unsigned long *dst_ptr = dst; | ||
256 | for(j=width; j; --j) | ||
257 | *(dst_ptr++) = 0; | ||
258 | dst += (dispDeviceRowBytes >> 3); | ||
259 | } | ||
260 | } | ||
261 | #endif /* ndef NO_SCROLL */ | ||
262 | |||
263 | void btext_drawchar(char c) | ||
264 | { | ||
265 | int cline = 0; | ||
266 | #ifdef NO_SCROLL | ||
267 | int x; | ||
268 | #endif | ||
269 | if (!boot_text_mapped) | ||
270 | return; | ||
271 | |||
272 | switch (c) { | ||
273 | case '\b': | ||
274 | if (g_loc_X > 0) | ||
275 | --g_loc_X; | ||
276 | break; | ||
277 | case '\t': | ||
278 | g_loc_X = (g_loc_X & -8) + 8; | ||
279 | break; | ||
280 | case '\r': | ||
281 | g_loc_X = 0; | ||
282 | break; | ||
283 | case '\n': | ||
284 | g_loc_X = 0; | ||
285 | g_loc_Y++; | ||
286 | cline = 1; | ||
287 | break; | ||
288 | default: | ||
289 | draw_byte(c, g_loc_X++, g_loc_Y); | ||
290 | } | ||
291 | if (g_loc_X >= g_max_loc_X) { | ||
292 | g_loc_X = 0; | ||
293 | g_loc_Y++; | ||
294 | cline = 1; | ||
295 | } | ||
296 | #ifndef NO_SCROLL | ||
297 | while (g_loc_Y >= g_max_loc_Y) { | ||
298 | scrollscreen(); | ||
299 | g_loc_Y--; | ||
300 | } | ||
301 | #else | ||
302 | /* wrap around from bottom to top of screen so we don't | ||
303 | waste time scrolling each line. -- paulus. */ | ||
304 | if (g_loc_Y >= g_max_loc_Y) | ||
305 | g_loc_Y = 0; | ||
306 | if (cline) { | ||
307 | for (x = 0; x < g_max_loc_X; ++x) | ||
308 | draw_byte(' ', x, g_loc_Y); | ||
309 | } | ||
310 | #endif | ||
311 | } | ||
312 | |||
313 | void btext_drawstring(const char *c) | ||
314 | { | ||
315 | if (!boot_text_mapped) | ||
316 | return; | ||
317 | while (*c) | ||
318 | btext_drawchar(*c++); | ||
319 | } | ||
320 | |||
321 | void btext_drawhex(unsigned long v) | ||
322 | { | ||
323 | char *hex_table = "0123456789abcdef"; | ||
324 | |||
325 | if (!boot_text_mapped) | ||
326 | return; | ||
327 | btext_drawchar(hex_table[(v >> 60) & 0x0000000FUL]); | ||
328 | btext_drawchar(hex_table[(v >> 56) & 0x0000000FUL]); | ||
329 | btext_drawchar(hex_table[(v >> 52) & 0x0000000FUL]); | ||
330 | btext_drawchar(hex_table[(v >> 48) & 0x0000000FUL]); | ||
331 | btext_drawchar(hex_table[(v >> 44) & 0x0000000FUL]); | ||
332 | btext_drawchar(hex_table[(v >> 40) & 0x0000000FUL]); | ||
333 | btext_drawchar(hex_table[(v >> 36) & 0x0000000FUL]); | ||
334 | btext_drawchar(hex_table[(v >> 32) & 0x0000000FUL]); | ||
335 | btext_drawchar(hex_table[(v >> 28) & 0x0000000FUL]); | ||
336 | btext_drawchar(hex_table[(v >> 24) & 0x0000000FUL]); | ||
337 | btext_drawchar(hex_table[(v >> 20) & 0x0000000FUL]); | ||
338 | btext_drawchar(hex_table[(v >> 16) & 0x0000000FUL]); | ||
339 | btext_drawchar(hex_table[(v >> 12) & 0x0000000FUL]); | ||
340 | btext_drawchar(hex_table[(v >> 8) & 0x0000000FUL]); | ||
341 | btext_drawchar(hex_table[(v >> 4) & 0x0000000FUL]); | ||
342 | btext_drawchar(hex_table[(v >> 0) & 0x0000000FUL]); | ||
343 | btext_drawchar(' '); | ||
344 | } | ||
345 | |||
346 | static void draw_byte(unsigned char c, long locX, long locY) | ||
347 | { | ||
348 | unsigned char *base = calc_base(locX << 3, locY << 4); | ||
349 | unsigned char *font = &vga_font[((unsigned int)c) * 16]; | ||
350 | int rb = dispDeviceRowBytes; | ||
351 | |||
352 | switch(dispDeviceDepth) { | ||
353 | case 24: | ||
354 | case 32: | ||
355 | draw_byte_32(font, (unsigned int *)base, rb); | ||
356 | break; | ||
357 | case 15: | ||
358 | case 16: | ||
359 | draw_byte_16(font, (unsigned int *)base, rb); | ||
360 | break; | ||
361 | case 8: | ||
362 | draw_byte_8(font, (unsigned int *)base, rb); | ||
363 | break; | ||
364 | } | ||
365 | } | ||
366 | |||
367 | static unsigned int expand_bits_8[16] = { | ||
368 | 0x00000000, | ||
369 | 0x000000ff, | ||
370 | 0x0000ff00, | ||
371 | 0x0000ffff, | ||
372 | 0x00ff0000, | ||
373 | 0x00ff00ff, | ||
374 | 0x00ffff00, | ||
375 | 0x00ffffff, | ||
376 | 0xff000000, | ||
377 | 0xff0000ff, | ||
378 | 0xff00ff00, | ||
379 | 0xff00ffff, | ||
380 | 0xffff0000, | ||
381 | 0xffff00ff, | ||
382 | 0xffffff00, | ||
383 | 0xffffffff | ||
384 | }; | ||
385 | |||
386 | static unsigned int expand_bits_16[4] = { | ||
387 | 0x00000000, | ||
388 | 0x0000ffff, | ||
389 | 0xffff0000, | ||
390 | 0xffffffff | ||
391 | }; | ||
392 | |||
393 | |||
394 | static void draw_byte_32(unsigned char *font, unsigned int *base, int rb) | ||
395 | { | ||
396 | int l, bits; | ||
397 | int fg = 0xFFFFFFFFUL; | ||
398 | int bg = 0x00000000UL; | ||
399 | |||
400 | for (l = 0; l < 16; ++l) | ||
401 | { | ||
402 | bits = *font++; | ||
403 | base[0] = (-(bits >> 7) & fg) ^ bg; | ||
404 | base[1] = (-((bits >> 6) & 1) & fg) ^ bg; | ||
405 | base[2] = (-((bits >> 5) & 1) & fg) ^ bg; | ||
406 | base[3] = (-((bits >> 4) & 1) & fg) ^ bg; | ||
407 | base[4] = (-((bits >> 3) & 1) & fg) ^ bg; | ||
408 | base[5] = (-((bits >> 2) & 1) & fg) ^ bg; | ||
409 | base[6] = (-((bits >> 1) & 1) & fg) ^ bg; | ||
410 | base[7] = (-(bits & 1) & fg) ^ bg; | ||
411 | base = (unsigned int *) ((char *)base + rb); | ||
412 | } | ||
413 | } | ||
414 | |||
415 | static void draw_byte_16(unsigned char *font, unsigned int *base, int rb) | ||
416 | { | ||
417 | int l, bits; | ||
418 | int fg = 0xFFFFFFFFUL; | ||
419 | int bg = 0x00000000UL; | ||
420 | unsigned int *eb = (int *)expand_bits_16; | ||
421 | |||
422 | for (l = 0; l < 16; ++l) | ||
423 | { | ||
424 | bits = *font++; | ||
425 | base[0] = (eb[bits >> 6] & fg) ^ bg; | ||
426 | base[1] = (eb[(bits >> 4) & 3] & fg) ^ bg; | ||
427 | base[2] = (eb[(bits >> 2) & 3] & fg) ^ bg; | ||
428 | base[3] = (eb[bits & 3] & fg) ^ bg; | ||
429 | base = (unsigned int *) ((char *)base + rb); | ||
430 | } | ||
431 | } | ||
432 | |||
433 | static void draw_byte_8(unsigned char *font, unsigned int *base, int rb) | ||
434 | { | ||
435 | int l, bits; | ||
436 | int fg = 0x0F0F0F0FUL; | ||
437 | int bg = 0x00000000UL; | ||
438 | unsigned int *eb = (int *)expand_bits_8; | ||
439 | |||
440 | for (l = 0; l < 16; ++l) | ||
441 | { | ||
442 | bits = *font++; | ||
443 | base[0] = (eb[bits >> 4] & fg) ^ bg; | ||
444 | base[1] = (eb[bits & 0xf] & fg) ^ bg; | ||
445 | base = (unsigned int *) ((char *)base + rb); | ||
446 | } | ||
447 | } | ||
448 | |||
449 | static unsigned char vga_font[cmapsz] = { | ||
450 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
451 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, | ||
452 | 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, | ||
453 | 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, | ||
454 | 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, | ||
455 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, | ||
456 | 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, | ||
457 | 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, | ||
458 | 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, | ||
459 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, | ||
460 | 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, | ||
461 | 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
462 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, | ||
463 | 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, | ||
464 | 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e, | ||
465 | 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, | ||
466 | 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, | ||
467 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, | ||
468 | 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63, | ||
469 | 0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, | ||
470 | 0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, | ||
471 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, | ||
472 | 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e, | ||
473 | 0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, | ||
474 | 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, | ||
475 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, | ||
476 | 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb, | ||
477 | 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, | ||
478 | 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, | ||
479 | 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
480 | 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, | ||
481 | 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, | ||
482 | 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
483 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
484 | 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
485 | 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
486 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, | ||
487 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, | ||
488 | 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
489 | 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
490 | 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, | ||
491 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, | ||
492 | 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
493 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
494 | 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, | ||
495 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, | ||
496 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, | ||
497 | 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, | ||
498 | 0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, | ||
499 | 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, | ||
500 | 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, | ||
501 | 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, | ||
502 | 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
503 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, | ||
504 | 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, | ||
505 | 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, | ||
506 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, | ||
507 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, | ||
508 | 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
509 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, | ||
510 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, | ||
511 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
512 | 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
513 | 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, | ||
514 | 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c, | ||
515 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, | ||
516 | 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, | ||
517 | 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, | ||
518 | 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, | ||
519 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, | ||
520 | 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, | ||
521 | 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, | ||
522 | 0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, | ||
523 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, | ||
524 | 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, | ||
525 | 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, | ||
526 | 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, | ||
527 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, | ||
528 | 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
529 | 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, | ||
530 | 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, | ||
531 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, | ||
532 | 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, | ||
533 | 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, | ||
534 | 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, | ||
535 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde, | ||
536 | 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, | ||
537 | 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, | ||
538 | 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, | ||
539 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, | ||
540 | 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c, | ||
541 | 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, | ||
542 | 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, | ||
543 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, | ||
544 | 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, | ||
545 | 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, | ||
546 | 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, | ||
547 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
548 | 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, | ||
549 | 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, | ||
550 | 0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, | ||
551 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, | ||
552 | 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7, | ||
553 | 0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, | ||
554 | 0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, | ||
555 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, | ||
556 | 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, | ||
557 | 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, | ||
558 | 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, | ||
559 | 0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, | ||
560 | 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, | ||
561 | 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, | ||
562 | 0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, | ||
563 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, | ||
564 | 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, | ||
565 | 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, | ||
566 | 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, | ||
567 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, | ||
568 | 0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, | ||
569 | 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, | ||
570 | 0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, | ||
571 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, | ||
572 | 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, | ||
573 | 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, | ||
574 | 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, | ||
575 | 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, | ||
576 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
577 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, | ||
578 | 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
579 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, | ||
580 | 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60, | ||
581 | 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, | ||
582 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, | ||
583 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, | ||
584 | 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
585 | 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, | ||
586 | 0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, | ||
587 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, | ||
588 | 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60, | ||
589 | 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, | ||
590 | 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, | ||
591 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, | ||
592 | 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60, | ||
593 | 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, | ||
594 | 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, | ||
595 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, | ||
596 | 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
597 | 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, | ||
598 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, | ||
599 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, | ||
600 | 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
601 | 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, | ||
602 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, | ||
603 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, | ||
604 | 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, | ||
605 | 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, | ||
606 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, | ||
607 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, | ||
608 | 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
609 | 0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, | ||
610 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, | ||
611 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, | ||
612 | 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
613 | 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, | ||
614 | 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, | ||
615 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, | ||
616 | 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18, | ||
617 | 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, | ||
618 | 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
619 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, | ||
620 | 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, | ||
621 | 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, | ||
622 | 0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, | ||
623 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, | ||
624 | 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, | ||
625 | 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, | ||
626 | 0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, | ||
627 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, | ||
628 | 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, | ||
629 | 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, | ||
630 | 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, | ||
631 | 0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, | ||
632 | 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, | ||
633 | 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, | ||
634 | 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, | ||
635 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, | ||
636 | 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, | ||
637 | 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, | ||
638 | 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, | ||
639 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, | ||
640 | 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, | ||
641 | 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, | ||
642 | 0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, | ||
643 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, | ||
644 | 0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c, | ||
645 | 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, | ||
646 | 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, | ||
647 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, | ||
648 | 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, | ||
649 | 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, | ||
650 | 0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, | ||
651 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, | ||
652 | 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, | ||
653 | 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, | ||
654 | 0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, | ||
655 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, | ||
656 | 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, | ||
657 | 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, | ||
658 | 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, | ||
659 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, | ||
660 | 0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, | ||
661 | 0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, | ||
662 | 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
663 | 0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, | ||
664 | 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, | ||
665 | 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, | ||
666 | 0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, | ||
667 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, | ||
668 | 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, | ||
669 | 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, | ||
670 | 0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, | ||
671 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, | ||
672 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, | ||
673 | 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
674 | 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, | ||
675 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, | ||
676 | 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
677 | 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
678 | 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, | ||
679 | 0x0c, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, | ||
680 | 0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, | ||
681 | 0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, | ||
682 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, | ||
683 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, | ||
684 | 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44, | ||
685 | 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, | ||
686 | 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, | ||
687 | 0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, | ||
688 | 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18, | ||
689 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
690 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, | ||
691 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, | ||
692 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, | ||
693 | 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
694 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, | ||
695 | 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, | ||
696 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, | ||
697 | 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
698 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
699 | 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, | ||
700 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
701 | 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
702 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, | ||
703 | 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, | ||
704 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
705 | 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
706 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, | ||
707 | 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, | ||
708 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
709 | 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
710 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, | ||
711 | 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, | ||
712 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, | ||
713 | 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
714 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, | ||
715 | 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, | ||
716 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
717 | 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
718 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, | ||
719 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, | ||
720 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
721 | 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
722 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, | ||
723 | 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, | ||
724 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, | ||
725 | 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
726 | 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, | ||
727 | 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, | ||
728 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
729 | 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
730 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, | ||
731 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, | ||
732 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, | ||
733 | 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
734 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, | ||
735 | 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, | ||
736 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
737 | 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
738 | 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, | ||
739 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, | ||
740 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
741 | 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
742 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
743 | 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, | ||
744 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, | ||
745 | 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, | ||
746 | 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, | ||
747 | 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, | ||
748 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
749 | 0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, | ||
750 | 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, | ||
751 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, | ||
752 | 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
753 | 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, | ||
754 | 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, | ||
755 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, | ||
756 | 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
757 | 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, | ||
758 | 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
759 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, | ||
760 | 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, | ||
761 | 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, | ||
762 | 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, | ||
763 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, | ||
764 | 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
765 | 0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
766 | 0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, | ||
767 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, | ||
768 | 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, | ||
769 | 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, | ||
770 | 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, | ||
771 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, | ||
772 | 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, | ||
773 | 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, | ||
774 | 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, | ||
775 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18, | ||
776 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
777 | 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, | ||
778 | 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, | ||
779 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, | ||
780 | 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, | ||
781 | 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
782 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, | ||
783 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
784 | 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, | ||
785 | 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, | ||
786 | 0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
787 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, | ||
788 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
789 | 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
790 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
791 | 0x00, 0x00, 0x00, 0x00, | ||
792 | }; | ||
diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S deleted file mode 100644 index 1c869ea72d28..000000000000 --- a/arch/ppc64/kernel/head.S +++ /dev/null | |||
@@ -1,2007 +0,0 @@ | |||
1 | /* | ||
2 | * arch/ppc64/kernel/head.S | ||
3 | * | ||
4 | * PowerPC version | ||
5 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | ||
6 | * | ||
7 | * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP | ||
8 | * Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu> | ||
9 | * Adapted for Power Macintosh by Paul Mackerras. | ||
10 | * Low-level exception handlers and MMU support | ||
11 | * rewritten by Paul Mackerras. | ||
12 | * Copyright (C) 1996 Paul Mackerras. | ||
13 | * | ||
14 | * Adapted for 64bit PowerPC by Dave Engebretsen, Peter Bergner, and | ||
15 | * Mike Corrigan {engebret|bergner|mikejc}@us.ibm.com | ||
16 | * | ||
17 | * This file contains the low-level support and setup for the | ||
18 | * PowerPC-64 platform, including trap and interrupt dispatch. | ||
19 | * | ||
20 | * This program is free software; you can redistribute it and/or | ||
21 | * modify it under the terms of the GNU General Public License | ||
22 | * as published by the Free Software Foundation; either version | ||
23 | * 2 of the License, or (at your option) any later version. | ||
24 | */ | ||
25 | |||
26 | #include <linux/config.h> | ||
27 | #include <linux/threads.h> | ||
28 | #include <asm/processor.h> | ||
29 | #include <asm/page.h> | ||
30 | #include <asm/mmu.h> | ||
31 | #include <asm/ppc_asm.h> | ||
32 | #include <asm/asm-offsets.h> | ||
33 | #include <asm/bug.h> | ||
34 | #include <asm/cputable.h> | ||
35 | #include <asm/setup.h> | ||
36 | #include <asm/hvcall.h> | ||
37 | #include <asm/iseries/lpar_map.h> | ||
38 | #include <asm/thread_info.h> | ||
39 | |||
40 | #ifdef CONFIG_PPC_ISERIES | ||
41 | #define DO_SOFT_DISABLE | ||
42 | #endif | ||
43 | |||
44 | /* | ||
45 | * We layout physical memory as follows: | ||
46 | * 0x0000 - 0x00ff : Secondary processor spin code | ||
47 | * 0x0100 - 0x2fff : pSeries Interrupt prologs | ||
48 | * 0x3000 - 0x5fff : interrupt support, iSeries and common interrupt prologs | ||
49 | * 0x6000 - 0x6fff : Initial (CPU0) segment table | ||
50 | * 0x7000 - 0x7fff : FWNMI data area | ||
51 | * 0x8000 - : Early init and support code | ||
52 | */ | ||
53 | |||
54 | /* | ||
55 | * SPRG Usage | ||
56 | * | ||
57 | * Register Definition | ||
58 | * | ||
59 | * SPRG0 reserved for hypervisor | ||
60 | * SPRG1 temp - used to save gpr | ||
61 | * SPRG2 temp - used to save gpr | ||
62 | * SPRG3 virt addr of paca | ||
63 | */ | ||
64 | |||
65 | /* | ||
66 | * Entering into this code we make the following assumptions: | ||
67 | * For pSeries: | ||
68 | * 1. The MMU is off & open firmware is running in real mode. | ||
69 | * 2. The kernel is entered at __start | ||
70 | * | ||
71 | * For iSeries: | ||
72 | * 1. The MMU is on (as it always is for iSeries) | ||
73 | * 2. The kernel is entered at system_reset_iSeries | ||
74 | */ | ||
75 | |||
76 | .text | ||
77 | .globl _stext | ||
78 | _stext: | ||
79 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
80 | _GLOBAL(__start) | ||
81 | /* NOP this out unconditionally */ | ||
82 | BEGIN_FTR_SECTION | ||
83 | b .__start_initialization_multiplatform | ||
84 | END_FTR_SECTION(0, 1) | ||
85 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
86 | |||
87 | /* Catch branch to 0 in real mode */ | ||
88 | trap | ||
89 | |||
90 | #ifdef CONFIG_PPC_ISERIES | ||
91 | /* | ||
92 | * At offset 0x20, there is a pointer to iSeries LPAR data. | ||
93 | * This is required by the hypervisor | ||
94 | */ | ||
95 | . = 0x20 | ||
96 | .llong hvReleaseData-KERNELBASE | ||
97 | |||
98 | /* | ||
99 | * At offset 0x28 and 0x30 are offsets to the mschunks_map | ||
100 | * array (used by the iSeries LPAR debugger to do translation | ||
101 | * between physical addresses and absolute addresses) and | ||
102 | * to the pidhash table (also used by the debugger) | ||
103 | */ | ||
104 | .llong mschunks_map-KERNELBASE | ||
105 | .llong 0 /* pidhash-KERNELBASE SFRXXX */ | ||
106 | |||
107 | /* Offset 0x38 - Pointer to start of embedded System.map */ | ||
108 | .globl embedded_sysmap_start | ||
109 | embedded_sysmap_start: | ||
110 | .llong 0 | ||
111 | /* Offset 0x40 - Pointer to end of embedded System.map */ | ||
112 | .globl embedded_sysmap_end | ||
113 | embedded_sysmap_end: | ||
114 | .llong 0 | ||
115 | |||
116 | #endif /* CONFIG_PPC_ISERIES */ | ||
117 | |||
118 | /* Secondary processors spin on this value until it goes to 1. */ | ||
119 | .globl __secondary_hold_spinloop | ||
120 | __secondary_hold_spinloop: | ||
121 | .llong 0x0 | ||
122 | |||
123 | /* Secondary processors write this value with their cpu # */ | ||
124 | /* after they enter the spin loop immediately below. */ | ||
125 | .globl __secondary_hold_acknowledge | ||
126 | __secondary_hold_acknowledge: | ||
127 | .llong 0x0 | ||
128 | |||
129 | . = 0x60 | ||
130 | /* | ||
131 | * The following code is used on pSeries to hold secondary processors | ||
132 | * in a spin loop after they have been freed from OpenFirmware, but | ||
133 | * before the bulk of the kernel has been relocated. This code | ||
134 | * is relocated to physical address 0x60 before prom_init is run. | ||
135 | * All of it must fit below the first exception vector at 0x100. | ||
136 | */ | ||
137 | _GLOBAL(__secondary_hold) | ||
138 | mfmsr r24 | ||
139 | ori r24,r24,MSR_RI | ||
140 | mtmsrd r24 /* RI on */ | ||
141 | |||
142 | /* Grab our linux cpu number */ | ||
143 | mr r24,r3 | ||
144 | |||
145 | /* Tell the master cpu we're here */ | ||
146 | /* Relocation is off & we are located at an address less */ | ||
147 | /* than 0x100, so only need to grab low order offset. */ | ||
148 | std r24,__secondary_hold_acknowledge@l(0) | ||
149 | sync | ||
150 | |||
151 | /* All secondary cpus wait here until told to start. */ | ||
152 | 100: ld r4,__secondary_hold_spinloop@l(0) | ||
153 | cmpdi 0,r4,1 | ||
154 | bne 100b | ||
155 | |||
156 | #ifdef CONFIG_HMT | ||
157 | b .hmt_init | ||
158 | #else | ||
159 | #ifdef CONFIG_SMP | ||
160 | mr r3,r24 | ||
161 | b .pSeries_secondary_smp_init | ||
162 | #else | ||
163 | BUG_OPCODE | ||
164 | #endif | ||
165 | #endif | ||
166 | |||
167 | /* This value is used to mark exception frames on the stack. */ | ||
168 | .section ".toc","aw" | ||
169 | exception_marker: | ||
170 | .tc ID_72656773_68657265[TC],0x7265677368657265 | ||
171 | .text | ||
172 | |||
173 | /* | ||
174 | * The following macros define the code that appears as | ||
175 | * the prologue to each of the exception handlers. They | ||
176 | * are split into two parts to allow a single kernel binary | ||
177 | * to be used for pSeries and iSeries. | ||
178 | * LOL. One day... - paulus | ||
179 | */ | ||
180 | |||
181 | /* | ||
182 | * We make as much of the exception code common between native | ||
183 | * exception handlers (including pSeries LPAR) and iSeries LPAR | ||
184 | * implementations as possible. | ||
185 | */ | ||
186 | |||
187 | /* | ||
188 | * This is the start of the interrupt handlers for pSeries | ||
189 | * This code runs with relocation off. | ||
190 | */ | ||
191 | #define EX_R9 0 | ||
192 | #define EX_R10 8 | ||
193 | #define EX_R11 16 | ||
194 | #define EX_R12 24 | ||
195 | #define EX_R13 32 | ||
196 | #define EX_SRR0 40 | ||
197 | #define EX_DAR 48 | ||
198 | #define EX_DSISR 56 | ||
199 | #define EX_CCR 60 | ||
200 | #define EX_R3 64 | ||
201 | #define EX_LR 72 | ||
202 | |||
203 | #define EXCEPTION_PROLOG_PSERIES(area, label) \ | ||
204 | mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \ | ||
205 | std r9,area+EX_R9(r13); /* save r9 - r12 */ \ | ||
206 | std r10,area+EX_R10(r13); \ | ||
207 | std r11,area+EX_R11(r13); \ | ||
208 | std r12,area+EX_R12(r13); \ | ||
209 | mfspr r9,SPRN_SPRG1; \ | ||
210 | std r9,area+EX_R13(r13); \ | ||
211 | mfcr r9; \ | ||
212 | clrrdi r12,r13,32; /* get high part of &label */ \ | ||
213 | mfmsr r10; \ | ||
214 | mfspr r11,SPRN_SRR0; /* save SRR0 */ \ | ||
215 | ori r12,r12,(label)@l; /* virt addr of handler */ \ | ||
216 | ori r10,r10,MSR_IR|MSR_DR|MSR_RI; \ | ||
217 | mtspr SPRN_SRR0,r12; \ | ||
218 | mfspr r12,SPRN_SRR1; /* and SRR1 */ \ | ||
219 | mtspr SPRN_SRR1,r10; \ | ||
220 | rfid; \ | ||
221 | b . /* prevent speculative execution */ | ||
222 | |||
223 | /* | ||
224 | * This is the start of the interrupt handlers for iSeries | ||
225 | * This code runs with relocation on. | ||
226 | */ | ||
227 | #define EXCEPTION_PROLOG_ISERIES_1(area) \ | ||
228 | mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \ | ||
229 | std r9,area+EX_R9(r13); /* save r9 - r12 */ \ | ||
230 | std r10,area+EX_R10(r13); \ | ||
231 | std r11,area+EX_R11(r13); \ | ||
232 | std r12,area+EX_R12(r13); \ | ||
233 | mfspr r9,SPRN_SPRG1; \ | ||
234 | std r9,area+EX_R13(r13); \ | ||
235 | mfcr r9 | ||
236 | |||
237 | #define EXCEPTION_PROLOG_ISERIES_2 \ | ||
238 | mfmsr r10; \ | ||
239 | ld r11,PACALPPACA+LPPACASRR0(r13); \ | ||
240 | ld r12,PACALPPACA+LPPACASRR1(r13); \ | ||
241 | ori r10,r10,MSR_RI; \ | ||
242 | mtmsrd r10,1 | ||
243 | |||
244 | /* | ||
245 | * The common exception prolog is used for all except a few exceptions | ||
246 | * such as a segment miss on a kernel address. We have to be prepared | ||
247 | * to take another exception from the point where we first touch the | ||
248 | * kernel stack onwards. | ||
249 | * | ||
250 | * On entry r13 points to the paca, r9-r13 are saved in the paca, | ||
251 | * r9 contains the saved CR, r11 and r12 contain the saved SRR0 and | ||
252 | * SRR1, and relocation is on. | ||
253 | */ | ||
254 | #define EXCEPTION_PROLOG_COMMON(n, area) \ | ||
255 | andi. r10,r12,MSR_PR; /* See if coming from user */ \ | ||
256 | mr r10,r1; /* Save r1 */ \ | ||
257 | subi r1,r1,INT_FRAME_SIZE; /* alloc frame on kernel stack */ \ | ||
258 | beq- 1f; \ | ||
259 | ld r1,PACAKSAVE(r13); /* kernel stack to use */ \ | ||
260 | 1: cmpdi cr1,r1,0; /* check if r1 is in userspace */ \ | ||
261 | bge- cr1,bad_stack; /* abort if it is */ \ | ||
262 | std r9,_CCR(r1); /* save CR in stackframe */ \ | ||
263 | std r11,_NIP(r1); /* save SRR0 in stackframe */ \ | ||
264 | std r12,_MSR(r1); /* save SRR1 in stackframe */ \ | ||
265 | std r10,0(r1); /* make stack chain pointer */ \ | ||
266 | std r0,GPR0(r1); /* save r0 in stackframe */ \ | ||
267 | std r10,GPR1(r1); /* save r1 in stackframe */ \ | ||
268 | std r2,GPR2(r1); /* save r2 in stackframe */ \ | ||
269 | SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \ | ||
270 | SAVE_2GPRS(7, r1); /* save r7, r8 in stackframe */ \ | ||
271 | ld r9,area+EX_R9(r13); /* move r9, r10 to stackframe */ \ | ||
272 | ld r10,area+EX_R10(r13); \ | ||
273 | std r9,GPR9(r1); \ | ||
274 | std r10,GPR10(r1); \ | ||
275 | ld r9,area+EX_R11(r13); /* move r11 - r13 to stackframe */ \ | ||
276 | ld r10,area+EX_R12(r13); \ | ||
277 | ld r11,area+EX_R13(r13); \ | ||
278 | std r9,GPR11(r1); \ | ||
279 | std r10,GPR12(r1); \ | ||
280 | std r11,GPR13(r1); \ | ||
281 | ld r2,PACATOC(r13); /* get kernel TOC into r2 */ \ | ||
282 | mflr r9; /* save LR in stackframe */ \ | ||
283 | std r9,_LINK(r1); \ | ||
284 | mfctr r10; /* save CTR in stackframe */ \ | ||
285 | std r10,_CTR(r1); \ | ||
286 | mfspr r11,SPRN_XER; /* save XER in stackframe */ \ | ||
287 | std r11,_XER(r1); \ | ||
288 | li r9,(n)+1; \ | ||
289 | std r9,_TRAP(r1); /* set trap number */ \ | ||
290 | li r10,0; \ | ||
291 | ld r11,exception_marker@toc(r2); \ | ||
292 | std r10,RESULT(r1); /* clear regs->result */ \ | ||
293 | std r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame */ | ||
294 | |||
295 | /* | ||
296 | * Exception vectors. | ||
297 | */ | ||
298 | #define STD_EXCEPTION_PSERIES(n, label) \ | ||
299 | . = n; \ | ||
300 | .globl label##_pSeries; \ | ||
301 | label##_pSeries: \ | ||
302 | HMT_MEDIUM; \ | ||
303 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ | ||
304 | RUNLATCH_ON(r13); \ | ||
305 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) | ||
306 | |||
307 | #define STD_EXCEPTION_ISERIES(n, label, area) \ | ||
308 | .globl label##_iSeries; \ | ||
309 | label##_iSeries: \ | ||
310 | HMT_MEDIUM; \ | ||
311 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ | ||
312 | RUNLATCH_ON(r13); \ | ||
313 | EXCEPTION_PROLOG_ISERIES_1(area); \ | ||
314 | EXCEPTION_PROLOG_ISERIES_2; \ | ||
315 | b label##_common | ||
316 | |||
317 | #define MASKABLE_EXCEPTION_ISERIES(n, label) \ | ||
318 | .globl label##_iSeries; \ | ||
319 | label##_iSeries: \ | ||
320 | HMT_MEDIUM; \ | ||
321 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ | ||
322 | RUNLATCH_ON(r13); \ | ||
323 | EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN); \ | ||
324 | lbz r10,PACAPROCENABLED(r13); \ | ||
325 | cmpwi 0,r10,0; \ | ||
326 | beq- label##_iSeries_masked; \ | ||
327 | EXCEPTION_PROLOG_ISERIES_2; \ | ||
328 | b label##_common; \ | ||
329 | |||
330 | #ifdef DO_SOFT_DISABLE | ||
331 | #define DISABLE_INTS \ | ||
332 | lbz r10,PACAPROCENABLED(r13); \ | ||
333 | li r11,0; \ | ||
334 | std r10,SOFTE(r1); \ | ||
335 | mfmsr r10; \ | ||
336 | stb r11,PACAPROCENABLED(r13); \ | ||
337 | ori r10,r10,MSR_EE; \ | ||
338 | mtmsrd r10,1 | ||
339 | |||
340 | #define ENABLE_INTS \ | ||
341 | lbz r10,PACAPROCENABLED(r13); \ | ||
342 | mfmsr r11; \ | ||
343 | std r10,SOFTE(r1); \ | ||
344 | ori r11,r11,MSR_EE; \ | ||
345 | mtmsrd r11,1 | ||
346 | |||
347 | #else /* hard enable/disable interrupts */ | ||
348 | #define DISABLE_INTS | ||
349 | |||
350 | #define ENABLE_INTS \ | ||
351 | ld r12,_MSR(r1); \ | ||
352 | mfmsr r11; \ | ||
353 | rlwimi r11,r12,0,MSR_EE; \ | ||
354 | mtmsrd r11,1 | ||
355 | |||
356 | #endif | ||
357 | |||
358 | #define STD_EXCEPTION_COMMON(trap, label, hdlr) \ | ||
359 | .align 7; \ | ||
360 | .globl label##_common; \ | ||
361 | label##_common: \ | ||
362 | EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \ | ||
363 | DISABLE_INTS; \ | ||
364 | bl .save_nvgprs; \ | ||
365 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
366 | bl hdlr; \ | ||
367 | b .ret_from_except | ||
368 | |||
369 | #define STD_EXCEPTION_COMMON_LITE(trap, label, hdlr) \ | ||
370 | .align 7; \ | ||
371 | .globl label##_common; \ | ||
372 | label##_common: \ | ||
373 | EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \ | ||
374 | DISABLE_INTS; \ | ||
375 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
376 | bl hdlr; \ | ||
377 | b .ret_from_except_lite | ||
378 | |||
379 | /* | ||
380 | * Start of pSeries system interrupt routines | ||
381 | */ | ||
382 | . = 0x100 | ||
383 | .globl __start_interrupts | ||
384 | __start_interrupts: | ||
385 | |||
386 | STD_EXCEPTION_PSERIES(0x100, system_reset) | ||
387 | |||
388 | . = 0x200 | ||
389 | _machine_check_pSeries: | ||
390 | HMT_MEDIUM | ||
391 | mtspr SPRN_SPRG1,r13 /* save r13 */ | ||
392 | RUNLATCH_ON(r13) | ||
393 | EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) | ||
394 | |||
395 | . = 0x300 | ||
396 | .globl data_access_pSeries | ||
397 | data_access_pSeries: | ||
398 | HMT_MEDIUM | ||
399 | mtspr SPRN_SPRG1,r13 | ||
400 | BEGIN_FTR_SECTION | ||
401 | mtspr SPRN_SPRG2,r12 | ||
402 | mfspr r13,SPRN_DAR | ||
403 | mfspr r12,SPRN_DSISR | ||
404 | srdi r13,r13,60 | ||
405 | rlwimi r13,r12,16,0x20 | ||
406 | mfcr r12 | ||
407 | cmpwi r13,0x2c | ||
408 | beq .do_stab_bolted_pSeries | ||
409 | mtcrf 0x80,r12 | ||
410 | mfspr r12,SPRN_SPRG2 | ||
411 | END_FTR_SECTION_IFCLR(CPU_FTR_SLB) | ||
412 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common) | ||
413 | |||
414 | . = 0x380 | ||
415 | .globl data_access_slb_pSeries | ||
416 | data_access_slb_pSeries: | ||
417 | HMT_MEDIUM | ||
418 | mtspr SPRN_SPRG1,r13 | ||
419 | RUNLATCH_ON(r13) | ||
420 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ | ||
421 | std r3,PACA_EXSLB+EX_R3(r13) | ||
422 | mfspr r3,SPRN_DAR | ||
423 | std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ | ||
424 | mfcr r9 | ||
425 | #ifdef __DISABLED__ | ||
426 | /* Keep that around for when we re-implement dynamic VSIDs */ | ||
427 | cmpdi r3,0 | ||
428 | bge slb_miss_user_pseries | ||
429 | #endif /* __DISABLED__ */ | ||
430 | std r10,PACA_EXSLB+EX_R10(r13) | ||
431 | std r11,PACA_EXSLB+EX_R11(r13) | ||
432 | std r12,PACA_EXSLB+EX_R12(r13) | ||
433 | mfspr r10,SPRN_SPRG1 | ||
434 | std r10,PACA_EXSLB+EX_R13(r13) | ||
435 | mfspr r12,SPRN_SRR1 /* and SRR1 */ | ||
436 | b .slb_miss_realmode /* Rel. branch works in real mode */ | ||
437 | |||
438 | STD_EXCEPTION_PSERIES(0x400, instruction_access) | ||
439 | |||
440 | . = 0x480 | ||
441 | .globl instruction_access_slb_pSeries | ||
442 | instruction_access_slb_pSeries: | ||
443 | HMT_MEDIUM | ||
444 | mtspr SPRN_SPRG1,r13 | ||
445 | RUNLATCH_ON(r13) | ||
446 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ | ||
447 | std r3,PACA_EXSLB+EX_R3(r13) | ||
448 | mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ | ||
449 | std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ | ||
450 | mfcr r9 | ||
451 | #ifdef __DISABLED__ | ||
452 | /* Keep that around for when we re-implement dynamic VSIDs */ | ||
453 | cmpdi r3,0 | ||
454 | bge slb_miss_user_pseries | ||
455 | #endif /* __DISABLED__ */ | ||
456 | std r10,PACA_EXSLB+EX_R10(r13) | ||
457 | std r11,PACA_EXSLB+EX_R11(r13) | ||
458 | std r12,PACA_EXSLB+EX_R12(r13) | ||
459 | mfspr r10,SPRN_SPRG1 | ||
460 | std r10,PACA_EXSLB+EX_R13(r13) | ||
461 | mfspr r12,SPRN_SRR1 /* and SRR1 */ | ||
462 | b .slb_miss_realmode /* Rel. branch works in real mode */ | ||
463 | |||
464 | STD_EXCEPTION_PSERIES(0x500, hardware_interrupt) | ||
465 | STD_EXCEPTION_PSERIES(0x600, alignment) | ||
466 | STD_EXCEPTION_PSERIES(0x700, program_check) | ||
467 | STD_EXCEPTION_PSERIES(0x800, fp_unavailable) | ||
468 | STD_EXCEPTION_PSERIES(0x900, decrementer) | ||
469 | STD_EXCEPTION_PSERIES(0xa00, trap_0a) | ||
470 | STD_EXCEPTION_PSERIES(0xb00, trap_0b) | ||
471 | |||
472 | . = 0xc00 | ||
473 | .globl system_call_pSeries | ||
474 | system_call_pSeries: | ||
475 | HMT_MEDIUM | ||
476 | RUNLATCH_ON(r9) | ||
477 | mr r9,r13 | ||
478 | mfmsr r10 | ||
479 | mfspr r13,SPRN_SPRG3 | ||
480 | mfspr r11,SPRN_SRR0 | ||
481 | clrrdi r12,r13,32 | ||
482 | oris r12,r12,system_call_common@h | ||
483 | ori r12,r12,system_call_common@l | ||
484 | mtspr SPRN_SRR0,r12 | ||
485 | ori r10,r10,MSR_IR|MSR_DR|MSR_RI | ||
486 | mfspr r12,SPRN_SRR1 | ||
487 | mtspr SPRN_SRR1,r10 | ||
488 | rfid | ||
489 | b . /* prevent speculative execution */ | ||
490 | |||
491 | STD_EXCEPTION_PSERIES(0xd00, single_step) | ||
492 | STD_EXCEPTION_PSERIES(0xe00, trap_0e) | ||
493 | |||
494 | /* We need to deal with the Altivec unavailable exception | ||
495 | * here which is at 0xf20, thus in the middle of the | ||
496 | * prolog code of the PerformanceMonitor one. A little | ||
497 | * trickery is thus necessary | ||
498 | */ | ||
499 | . = 0xf00 | ||
500 | b performance_monitor_pSeries | ||
501 | |||
502 | STD_EXCEPTION_PSERIES(0xf20, altivec_unavailable) | ||
503 | |||
504 | STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint) | ||
505 | STD_EXCEPTION_PSERIES(0x1700, altivec_assist) | ||
506 | |||
507 | . = 0x3000 | ||
508 | |||
509 | /*** pSeries interrupt support ***/ | ||
510 | |||
511 | /* moved from 0xf00 */ | ||
512 | STD_EXCEPTION_PSERIES(., performance_monitor) | ||
513 | |||
514 | .align 7 | ||
515 | _GLOBAL(do_stab_bolted_pSeries) | ||
516 | mtcrf 0x80,r12 | ||
517 | mfspr r12,SPRN_SPRG2 | ||
518 | EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted) | ||
519 | |||
520 | /* | ||
521 | * We have some room here we use that to put | ||
522 | * the peries slb miss user trampoline code so it's reasonably | ||
523 | * away from slb_miss_user_common to avoid problems with rfid | ||
524 | * | ||
525 | * This is used for when the SLB miss handler has to go virtual, | ||
526 | * which doesn't happen for now anymore but will once we re-implement | ||
527 | * dynamic VSIDs for shared page tables | ||
528 | */ | ||
529 | #ifdef __DISABLED__ | ||
530 | slb_miss_user_pseries: | ||
531 | std r10,PACA_EXGEN+EX_R10(r13) | ||
532 | std r11,PACA_EXGEN+EX_R11(r13) | ||
533 | std r12,PACA_EXGEN+EX_R12(r13) | ||
534 | mfspr r10,SPRG1 | ||
535 | ld r11,PACA_EXSLB+EX_R9(r13) | ||
536 | ld r12,PACA_EXSLB+EX_R3(r13) | ||
537 | std r10,PACA_EXGEN+EX_R13(r13) | ||
538 | std r11,PACA_EXGEN+EX_R9(r13) | ||
539 | std r12,PACA_EXGEN+EX_R3(r13) | ||
540 | clrrdi r12,r13,32 | ||
541 | mfmsr r10 | ||
542 | mfspr r11,SRR0 /* save SRR0 */ | ||
543 | ori r12,r12,slb_miss_user_common@l /* virt addr of handler */ | ||
544 | ori r10,r10,MSR_IR|MSR_DR|MSR_RI | ||
545 | mtspr SRR0,r12 | ||
546 | mfspr r12,SRR1 /* and SRR1 */ | ||
547 | mtspr SRR1,r10 | ||
548 | rfid | ||
549 | b . /* prevent spec. execution */ | ||
550 | #endif /* __DISABLED__ */ | ||
551 | |||
552 | /* | ||
553 | * Vectors for the FWNMI option. Share common code. | ||
554 | */ | ||
555 | .globl system_reset_fwnmi | ||
556 | system_reset_fwnmi: | ||
557 | HMT_MEDIUM | ||
558 | mtspr SPRN_SPRG1,r13 /* save r13 */ | ||
559 | RUNLATCH_ON(r13) | ||
560 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common) | ||
561 | |||
562 | .globl machine_check_fwnmi | ||
563 | machine_check_fwnmi: | ||
564 | HMT_MEDIUM | ||
565 | mtspr SPRN_SPRG1,r13 /* save r13 */ | ||
566 | RUNLATCH_ON(r13) | ||
567 | EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) | ||
568 | |||
569 | #ifdef CONFIG_PPC_ISERIES | ||
570 | /*** ISeries-LPAR interrupt handlers ***/ | ||
571 | |||
572 | STD_EXCEPTION_ISERIES(0x200, machine_check, PACA_EXMC) | ||
573 | |||
574 | .globl data_access_iSeries | ||
575 | data_access_iSeries: | ||
576 | mtspr SPRN_SPRG1,r13 | ||
577 | BEGIN_FTR_SECTION | ||
578 | mtspr SPRN_SPRG2,r12 | ||
579 | mfspr r13,SPRN_DAR | ||
580 | mfspr r12,SPRN_DSISR | ||
581 | srdi r13,r13,60 | ||
582 | rlwimi r13,r12,16,0x20 | ||
583 | mfcr r12 | ||
584 | cmpwi r13,0x2c | ||
585 | beq .do_stab_bolted_iSeries | ||
586 | mtcrf 0x80,r12 | ||
587 | mfspr r12,SPRN_SPRG2 | ||
588 | END_FTR_SECTION_IFCLR(CPU_FTR_SLB) | ||
589 | EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN) | ||
590 | EXCEPTION_PROLOG_ISERIES_2 | ||
591 | b data_access_common | ||
592 | |||
593 | .do_stab_bolted_iSeries: | ||
594 | mtcrf 0x80,r12 | ||
595 | mfspr r12,SPRN_SPRG2 | ||
596 | EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB) | ||
597 | EXCEPTION_PROLOG_ISERIES_2 | ||
598 | b .do_stab_bolted | ||
599 | |||
600 | .globl data_access_slb_iSeries | ||
601 | data_access_slb_iSeries: | ||
602 | mtspr SPRN_SPRG1,r13 /* save r13 */ | ||
603 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ | ||
604 | std r3,PACA_EXSLB+EX_R3(r13) | ||
605 | mfspr r3,SPRN_DAR | ||
606 | std r9,PACA_EXSLB+EX_R9(r13) | ||
607 | mfcr r9 | ||
608 | #ifdef __DISABLED__ | ||
609 | cmpdi r3,0 | ||
610 | bge slb_miss_user_iseries | ||
611 | #endif | ||
612 | std r10,PACA_EXSLB+EX_R10(r13) | ||
613 | std r11,PACA_EXSLB+EX_R11(r13) | ||
614 | std r12,PACA_EXSLB+EX_R12(r13) | ||
615 | mfspr r10,SPRN_SPRG1 | ||
616 | std r10,PACA_EXSLB+EX_R13(r13) | ||
617 | ld r12,PACALPPACA+LPPACASRR1(r13); | ||
618 | b .slb_miss_realmode | ||
619 | |||
620 | STD_EXCEPTION_ISERIES(0x400, instruction_access, PACA_EXGEN) | ||
621 | |||
622 | .globl instruction_access_slb_iSeries | ||
623 | instruction_access_slb_iSeries: | ||
624 | mtspr SPRN_SPRG1,r13 /* save r13 */ | ||
625 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ | ||
626 | std r3,PACA_EXSLB+EX_R3(r13) | ||
627 | ld r3,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ | ||
628 | std r9,PACA_EXSLB+EX_R9(r13) | ||
629 | mfcr r9 | ||
630 | #ifdef __DISABLED__ | ||
631 | cmpdi r3,0 | ||
632 | bge .slb_miss_user_iseries | ||
633 | #endif | ||
634 | std r10,PACA_EXSLB+EX_R10(r13) | ||
635 | std r11,PACA_EXSLB+EX_R11(r13) | ||
636 | std r12,PACA_EXSLB+EX_R12(r13) | ||
637 | mfspr r10,SPRN_SPRG1 | ||
638 | std r10,PACA_EXSLB+EX_R13(r13) | ||
639 | ld r12,PACALPPACA+LPPACASRR1(r13); | ||
640 | b .slb_miss_realmode | ||
641 | |||
642 | #ifdef __DISABLED__ | ||
643 | slb_miss_user_iseries: | ||
644 | std r10,PACA_EXGEN+EX_R10(r13) | ||
645 | std r11,PACA_EXGEN+EX_R11(r13) | ||
646 | std r12,PACA_EXGEN+EX_R12(r13) | ||
647 | mfspr r10,SPRG1 | ||
648 | ld r11,PACA_EXSLB+EX_R9(r13) | ||
649 | ld r12,PACA_EXSLB+EX_R3(r13) | ||
650 | std r10,PACA_EXGEN+EX_R13(r13) | ||
651 | std r11,PACA_EXGEN+EX_R9(r13) | ||
652 | std r12,PACA_EXGEN+EX_R3(r13) | ||
653 | EXCEPTION_PROLOG_ISERIES_2 | ||
654 | b slb_miss_user_common | ||
655 | #endif | ||
656 | |||
657 | MASKABLE_EXCEPTION_ISERIES(0x500, hardware_interrupt) | ||
658 | STD_EXCEPTION_ISERIES(0x600, alignment, PACA_EXGEN) | ||
659 | STD_EXCEPTION_ISERIES(0x700, program_check, PACA_EXGEN) | ||
660 | STD_EXCEPTION_ISERIES(0x800, fp_unavailable, PACA_EXGEN) | ||
661 | MASKABLE_EXCEPTION_ISERIES(0x900, decrementer) | ||
662 | STD_EXCEPTION_ISERIES(0xa00, trap_0a, PACA_EXGEN) | ||
663 | STD_EXCEPTION_ISERIES(0xb00, trap_0b, PACA_EXGEN) | ||
664 | |||
665 | .globl system_call_iSeries | ||
666 | system_call_iSeries: | ||
667 | mr r9,r13 | ||
668 | mfspr r13,SPRN_SPRG3 | ||
669 | EXCEPTION_PROLOG_ISERIES_2 | ||
670 | b system_call_common | ||
671 | |||
672 | STD_EXCEPTION_ISERIES( 0xd00, single_step, PACA_EXGEN) | ||
673 | STD_EXCEPTION_ISERIES( 0xe00, trap_0e, PACA_EXGEN) | ||
674 | STD_EXCEPTION_ISERIES( 0xf00, performance_monitor, PACA_EXGEN) | ||
675 | |||
676 | .globl system_reset_iSeries | ||
677 | system_reset_iSeries: | ||
678 | mfspr r13,SPRN_SPRG3 /* Get paca address */ | ||
679 | mfmsr r24 | ||
680 | ori r24,r24,MSR_RI | ||
681 | mtmsrd r24 /* RI on */ | ||
682 | lhz r24,PACAPACAINDEX(r13) /* Get processor # */ | ||
683 | cmpwi 0,r24,0 /* Are we processor 0? */ | ||
684 | beq .__start_initialization_iSeries /* Start up the first processor */ | ||
685 | mfspr r4,SPRN_CTRLF | ||
686 | li r5,CTRL_RUNLATCH /* Turn off the run light */ | ||
687 | andc r4,r4,r5 | ||
688 | mtspr SPRN_CTRLT,r4 | ||
689 | |||
690 | 1: | ||
691 | HMT_LOW | ||
692 | #ifdef CONFIG_SMP | ||
693 | lbz r23,PACAPROCSTART(r13) /* Test if this processor | ||
694 | * should start */ | ||
695 | sync | ||
696 | LOADADDR(r3,current_set) | ||
697 | sldi r28,r24,3 /* get current_set[cpu#] */ | ||
698 | ldx r3,r3,r28 | ||
699 | addi r1,r3,THREAD_SIZE | ||
700 | subi r1,r1,STACK_FRAME_OVERHEAD | ||
701 | |||
702 | cmpwi 0,r23,0 | ||
703 | beq iSeries_secondary_smp_loop /* Loop until told to go */ | ||
704 | bne .__secondary_start /* Loop until told to go */ | ||
705 | iSeries_secondary_smp_loop: | ||
706 | /* Let the Hypervisor know we are alive */ | ||
707 | /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */ | ||
708 | lis r3,0x8002 | ||
709 | rldicr r3,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */ | ||
710 | #else /* CONFIG_SMP */ | ||
711 | /* Yield the processor. This is required for non-SMP kernels | ||
712 | which are running on multi-threaded machines. */ | ||
713 | lis r3,0x8000 | ||
714 | rldicr r3,r3,32,15 /* r3 = (r3 << 32) & 0xffff000000000000 */ | ||
715 | addi r3,r3,18 /* r3 = 0x8000000000000012 which is "yield" */ | ||
716 | li r4,0 /* "yield timed" */ | ||
717 | li r5,-1 /* "yield forever" */ | ||
718 | #endif /* CONFIG_SMP */ | ||
719 | li r0,-1 /* r0=-1 indicates a Hypervisor call */ | ||
720 | sc /* Invoke the hypervisor via a system call */ | ||
721 | mfspr r13,SPRN_SPRG3 /* Put r13 back ???? */ | ||
722 | b 1b /* If SMP not configured, secondaries | ||
723 | * loop forever */ | ||
724 | |||
725 | .globl decrementer_iSeries_masked | ||
726 | decrementer_iSeries_masked: | ||
727 | li r11,1 | ||
728 | stb r11,PACALPPACA+LPPACADECRINT(r13) | ||
729 | lwz r12,PACADEFAULTDECR(r13) | ||
730 | mtspr SPRN_DEC,r12 | ||
731 | /* fall through */ | ||
732 | |||
733 | .globl hardware_interrupt_iSeries_masked | ||
734 | hardware_interrupt_iSeries_masked: | ||
735 | mtcrf 0x80,r9 /* Restore regs */ | ||
736 | ld r11,PACALPPACA+LPPACASRR0(r13) | ||
737 | ld r12,PACALPPACA+LPPACASRR1(r13) | ||
738 | mtspr SPRN_SRR0,r11 | ||
739 | mtspr SPRN_SRR1,r12 | ||
740 | ld r9,PACA_EXGEN+EX_R9(r13) | ||
741 | ld r10,PACA_EXGEN+EX_R10(r13) | ||
742 | ld r11,PACA_EXGEN+EX_R11(r13) | ||
743 | ld r12,PACA_EXGEN+EX_R12(r13) | ||
744 | ld r13,PACA_EXGEN+EX_R13(r13) | ||
745 | rfid | ||
746 | b . /* prevent speculative execution */ | ||
747 | #endif /* CONFIG_PPC_ISERIES */ | ||
748 | |||
749 | /*** Common interrupt handlers ***/ | ||
750 | |||
751 | STD_EXCEPTION_COMMON(0x100, system_reset, .system_reset_exception) | ||
752 | |||
753 | /* | ||
754 | * Machine check is different because we use a different | ||
755 | * save area: PACA_EXMC instead of PACA_EXGEN. | ||
756 | */ | ||
757 | .align 7 | ||
758 | .globl machine_check_common | ||
759 | machine_check_common: | ||
760 | EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC) | ||
761 | DISABLE_INTS | ||
762 | bl .save_nvgprs | ||
763 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
764 | bl .machine_check_exception | ||
765 | b .ret_from_except | ||
766 | |||
767 | STD_EXCEPTION_COMMON_LITE(0x900, decrementer, .timer_interrupt) | ||
768 | STD_EXCEPTION_COMMON(0xa00, trap_0a, .unknown_exception) | ||
769 | STD_EXCEPTION_COMMON(0xb00, trap_0b, .unknown_exception) | ||
770 | STD_EXCEPTION_COMMON(0xd00, single_step, .single_step_exception) | ||
771 | STD_EXCEPTION_COMMON(0xe00, trap_0e, .unknown_exception) | ||
772 | STD_EXCEPTION_COMMON(0xf00, performance_monitor, .performance_monitor_exception) | ||
773 | STD_EXCEPTION_COMMON(0x1300, instruction_breakpoint, .instruction_breakpoint_exception) | ||
774 | #ifdef CONFIG_ALTIVEC | ||
775 | STD_EXCEPTION_COMMON(0x1700, altivec_assist, .altivec_assist_exception) | ||
776 | #else | ||
777 | STD_EXCEPTION_COMMON(0x1700, altivec_assist, .unknown_exception) | ||
778 | #endif | ||
779 | |||
780 | /* | ||
781 | * Here we have detected that the kernel stack pointer is bad. | ||
782 | * R9 contains the saved CR, r13 points to the paca, | ||
783 | * r10 contains the (bad) kernel stack pointer, | ||
784 | * r11 and r12 contain the saved SRR0 and SRR1. | ||
785 | * We switch to using an emergency stack, save the registers there, | ||
786 | * and call kernel_bad_stack(), which panics. | ||
787 | */ | ||
788 | bad_stack: | ||
789 | ld r1,PACAEMERGSP(r13) | ||
790 | subi r1,r1,64+INT_FRAME_SIZE | ||
791 | std r9,_CCR(r1) | ||
792 | std r10,GPR1(r1) | ||
793 | std r11,_NIP(r1) | ||
794 | std r12,_MSR(r1) | ||
795 | mfspr r11,SPRN_DAR | ||
796 | mfspr r12,SPRN_DSISR | ||
797 | std r11,_DAR(r1) | ||
798 | std r12,_DSISR(r1) | ||
799 | mflr r10 | ||
800 | mfctr r11 | ||
801 | mfxer r12 | ||
802 | std r10,_LINK(r1) | ||
803 | std r11,_CTR(r1) | ||
804 | std r12,_XER(r1) | ||
805 | SAVE_GPR(0,r1) | ||
806 | SAVE_GPR(2,r1) | ||
807 | SAVE_4GPRS(3,r1) | ||
808 | SAVE_2GPRS(7,r1) | ||
809 | SAVE_10GPRS(12,r1) | ||
810 | SAVE_10GPRS(22,r1) | ||
811 | addi r11,r1,INT_FRAME_SIZE | ||
812 | std r11,0(r1) | ||
813 | li r12,0 | ||
814 | std r12,0(r11) | ||
815 | ld r2,PACATOC(r13) | ||
816 | 1: addi r3,r1,STACK_FRAME_OVERHEAD | ||
817 | bl .kernel_bad_stack | ||
818 | b 1b | ||
819 | |||
820 | /* | ||
821 | * Return from an exception with minimal checks. | ||
822 | * The caller is assumed to have done EXCEPTION_PROLOG_COMMON. | ||
823 | * If interrupts have been enabled, or anything has been | ||
824 | * done that might have changed the scheduling status of | ||
825 | * any task or sent any task a signal, you should use | ||
826 | * ret_from_except or ret_from_except_lite instead of this. | ||
827 | */ | ||
828 | .globl fast_exception_return | ||
829 | fast_exception_return: | ||
830 | ld r12,_MSR(r1) | ||
831 | ld r11,_NIP(r1) | ||
832 | andi. r3,r12,MSR_RI /* check if RI is set */ | ||
833 | beq- unrecov_fer | ||
834 | ld r3,_CCR(r1) | ||
835 | ld r4,_LINK(r1) | ||
836 | ld r5,_CTR(r1) | ||
837 | ld r6,_XER(r1) | ||
838 | mtcr r3 | ||
839 | mtlr r4 | ||
840 | mtctr r5 | ||
841 | mtxer r6 | ||
842 | REST_GPR(0, r1) | ||
843 | REST_8GPRS(2, r1) | ||
844 | |||
845 | mfmsr r10 | ||
846 | clrrdi r10,r10,2 /* clear RI (LE is 0 already) */ | ||
847 | mtmsrd r10,1 | ||
848 | |||
849 | mtspr SPRN_SRR1,r12 | ||
850 | mtspr SPRN_SRR0,r11 | ||
851 | REST_4GPRS(10, r1) | ||
852 | ld r1,GPR1(r1) | ||
853 | rfid | ||
854 | b . /* prevent speculative execution */ | ||
855 | |||
856 | unrecov_fer: | ||
857 | bl .save_nvgprs | ||
858 | 1: addi r3,r1,STACK_FRAME_OVERHEAD | ||
859 | bl .unrecoverable_exception | ||
860 | b 1b | ||
861 | |||
862 | /* | ||
863 | * Here r13 points to the paca, r9 contains the saved CR, | ||
864 | * SRR0 and SRR1 are saved in r11 and r12, | ||
865 | * r9 - r13 are saved in paca->exgen. | ||
866 | */ | ||
867 | .align 7 | ||
868 | .globl data_access_common | ||
869 | data_access_common: | ||
870 | RUNLATCH_ON(r10) /* It wont fit in the 0x300 handler */ | ||
871 | mfspr r10,SPRN_DAR | ||
872 | std r10,PACA_EXGEN+EX_DAR(r13) | ||
873 | mfspr r10,SPRN_DSISR | ||
874 | stw r10,PACA_EXGEN+EX_DSISR(r13) | ||
875 | EXCEPTION_PROLOG_COMMON(0x300, PACA_EXGEN) | ||
876 | ld r3,PACA_EXGEN+EX_DAR(r13) | ||
877 | lwz r4,PACA_EXGEN+EX_DSISR(r13) | ||
878 | li r5,0x300 | ||
879 | b .do_hash_page /* Try to handle as hpte fault */ | ||
880 | |||
881 | .align 7 | ||
882 | .globl instruction_access_common | ||
883 | instruction_access_common: | ||
884 | EXCEPTION_PROLOG_COMMON(0x400, PACA_EXGEN) | ||
885 | ld r3,_NIP(r1) | ||
886 | andis. r4,r12,0x5820 | ||
887 | li r5,0x400 | ||
888 | b .do_hash_page /* Try to handle as hpte fault */ | ||
889 | |||
890 | /* | ||
891 | * Here is the common SLB miss user that is used when going to virtual | ||
892 | * mode for SLB misses, that is currently not used | ||
893 | */ | ||
894 | #ifdef __DISABLED__ | ||
895 | .align 7 | ||
896 | .globl slb_miss_user_common | ||
897 | slb_miss_user_common: | ||
898 | mflr r10 | ||
899 | std r3,PACA_EXGEN+EX_DAR(r13) | ||
900 | stw r9,PACA_EXGEN+EX_CCR(r13) | ||
901 | std r10,PACA_EXGEN+EX_LR(r13) | ||
902 | std r11,PACA_EXGEN+EX_SRR0(r13) | ||
903 | bl .slb_allocate_user | ||
904 | |||
905 | ld r10,PACA_EXGEN+EX_LR(r13) | ||
906 | ld r3,PACA_EXGEN+EX_R3(r13) | ||
907 | lwz r9,PACA_EXGEN+EX_CCR(r13) | ||
908 | ld r11,PACA_EXGEN+EX_SRR0(r13) | ||
909 | mtlr r10 | ||
910 | beq- slb_miss_fault | ||
911 | |||
912 | andi. r10,r12,MSR_RI /* check for unrecoverable exception */ | ||
913 | beq- unrecov_user_slb | ||
914 | mfmsr r10 | ||
915 | |||
916 | .machine push | ||
917 | .machine "power4" | ||
918 | mtcrf 0x80,r9 | ||
919 | .machine pop | ||
920 | |||
921 | clrrdi r10,r10,2 /* clear RI before setting SRR0/1 */ | ||
922 | mtmsrd r10,1 | ||
923 | |||
924 | mtspr SRR0,r11 | ||
925 | mtspr SRR1,r12 | ||
926 | |||
927 | ld r9,PACA_EXGEN+EX_R9(r13) | ||
928 | ld r10,PACA_EXGEN+EX_R10(r13) | ||
929 | ld r11,PACA_EXGEN+EX_R11(r13) | ||
930 | ld r12,PACA_EXGEN+EX_R12(r13) | ||
931 | ld r13,PACA_EXGEN+EX_R13(r13) | ||
932 | rfid | ||
933 | b . | ||
934 | |||
935 | slb_miss_fault: | ||
936 | EXCEPTION_PROLOG_COMMON(0x380, PACA_EXGEN) | ||
937 | ld r4,PACA_EXGEN+EX_DAR(r13) | ||
938 | li r5,0 | ||
939 | std r4,_DAR(r1) | ||
940 | std r5,_DSISR(r1) | ||
941 | b .handle_page_fault | ||
942 | |||
943 | unrecov_user_slb: | ||
944 | EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN) | ||
945 | DISABLE_INTS | ||
946 | bl .save_nvgprs | ||
947 | 1: addi r3,r1,STACK_FRAME_OVERHEAD | ||
948 | bl .unrecoverable_exception | ||
949 | b 1b | ||
950 | |||
951 | #endif /* __DISABLED__ */ | ||
952 | |||
953 | |||
954 | /* | ||
955 | * r13 points to the PACA, r9 contains the saved CR, | ||
956 | * r12 contain the saved SRR1, SRR0 is still ready for return | ||
957 | * r3 has the faulting address | ||
958 | * r9 - r13 are saved in paca->exslb. | ||
959 | * r3 is saved in paca->slb_r3 | ||
960 | * We assume we aren't going to take any exceptions during this procedure. | ||
961 | */ | ||
962 | _GLOBAL(slb_miss_realmode) | ||
963 | mflr r10 | ||
964 | |||
965 | stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */ | ||
966 | std r10,PACA_EXSLB+EX_LR(r13) /* save LR */ | ||
967 | |||
968 | bl .slb_allocate_realmode | ||
969 | |||
970 | /* All done -- return from exception. */ | ||
971 | |||
972 | ld r10,PACA_EXSLB+EX_LR(r13) | ||
973 | ld r3,PACA_EXSLB+EX_R3(r13) | ||
974 | lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ | ||
975 | #ifdef CONFIG_PPC_ISERIES | ||
976 | ld r11,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ | ||
977 | #endif /* CONFIG_PPC_ISERIES */ | ||
978 | |||
979 | mtlr r10 | ||
980 | |||
981 | andi. r10,r12,MSR_RI /* check for unrecoverable exception */ | ||
982 | beq- unrecov_slb | ||
983 | |||
984 | .machine push | ||
985 | .machine "power4" | ||
986 | mtcrf 0x80,r9 | ||
987 | mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */ | ||
988 | .machine pop | ||
989 | |||
990 | #ifdef CONFIG_PPC_ISERIES | ||
991 | mtspr SPRN_SRR0,r11 | ||
992 | mtspr SPRN_SRR1,r12 | ||
993 | #endif /* CONFIG_PPC_ISERIES */ | ||
994 | ld r9,PACA_EXSLB+EX_R9(r13) | ||
995 | ld r10,PACA_EXSLB+EX_R10(r13) | ||
996 | ld r11,PACA_EXSLB+EX_R11(r13) | ||
997 | ld r12,PACA_EXSLB+EX_R12(r13) | ||
998 | ld r13,PACA_EXSLB+EX_R13(r13) | ||
999 | rfid | ||
1000 | b . /* prevent speculative execution */ | ||
1001 | |||
1002 | unrecov_slb: | ||
1003 | EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB) | ||
1004 | DISABLE_INTS | ||
1005 | bl .save_nvgprs | ||
1006 | 1: addi r3,r1,STACK_FRAME_OVERHEAD | ||
1007 | bl .unrecoverable_exception | ||
1008 | b 1b | ||
1009 | |||
1010 | .align 7 | ||
1011 | .globl hardware_interrupt_common | ||
1012 | .globl hardware_interrupt_entry | ||
1013 | hardware_interrupt_common: | ||
1014 | EXCEPTION_PROLOG_COMMON(0x500, PACA_EXGEN) | ||
1015 | hardware_interrupt_entry: | ||
1016 | DISABLE_INTS | ||
1017 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1018 | bl .do_IRQ | ||
1019 | b .ret_from_except_lite | ||
1020 | |||
1021 | .align 7 | ||
1022 | .globl alignment_common | ||
1023 | alignment_common: | ||
1024 | mfspr r10,SPRN_DAR | ||
1025 | std r10,PACA_EXGEN+EX_DAR(r13) | ||
1026 | mfspr r10,SPRN_DSISR | ||
1027 | stw r10,PACA_EXGEN+EX_DSISR(r13) | ||
1028 | EXCEPTION_PROLOG_COMMON(0x600, PACA_EXGEN) | ||
1029 | ld r3,PACA_EXGEN+EX_DAR(r13) | ||
1030 | lwz r4,PACA_EXGEN+EX_DSISR(r13) | ||
1031 | std r3,_DAR(r1) | ||
1032 | std r4,_DSISR(r1) | ||
1033 | bl .save_nvgprs | ||
1034 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1035 | ENABLE_INTS | ||
1036 | bl .alignment_exception | ||
1037 | b .ret_from_except | ||
1038 | |||
1039 | .align 7 | ||
1040 | .globl program_check_common | ||
1041 | program_check_common: | ||
1042 | EXCEPTION_PROLOG_COMMON(0x700, PACA_EXGEN) | ||
1043 | bl .save_nvgprs | ||
1044 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1045 | ENABLE_INTS | ||
1046 | bl .program_check_exception | ||
1047 | b .ret_from_except | ||
1048 | |||
1049 | .align 7 | ||
1050 | .globl fp_unavailable_common | ||
1051 | fp_unavailable_common: | ||
1052 | EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN) | ||
1053 | bne .load_up_fpu /* if from user, just load it up */ | ||
1054 | bl .save_nvgprs | ||
1055 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1056 | ENABLE_INTS | ||
1057 | bl .kernel_fp_unavailable_exception | ||
1058 | BUG_OPCODE | ||
1059 | |||
1060 | .align 7 | ||
1061 | .globl altivec_unavailable_common | ||
1062 | altivec_unavailable_common: | ||
1063 | EXCEPTION_PROLOG_COMMON(0xf20, PACA_EXGEN) | ||
1064 | #ifdef CONFIG_ALTIVEC | ||
1065 | BEGIN_FTR_SECTION | ||
1066 | bne .load_up_altivec /* if from user, just load it up */ | ||
1067 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | ||
1068 | #endif | ||
1069 | bl .save_nvgprs | ||
1070 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1071 | ENABLE_INTS | ||
1072 | bl .altivec_unavailable_exception | ||
1073 | b .ret_from_except | ||
1074 | |||
1075 | #ifdef CONFIG_ALTIVEC | ||
1076 | /* | ||
1077 | * load_up_altivec(unused, unused, tsk) | ||
1078 | * Disable VMX for the task which had it previously, | ||
1079 | * and save its vector registers in its thread_struct. | ||
1080 | * Enables the VMX for use in the kernel on return. | ||
1081 | * On SMP we know the VMX is free, since we give it up every | ||
1082 | * switch (ie, no lazy save of the vector registers). | ||
1083 | * On entry: r13 == 'current' && last_task_used_altivec != 'current' | ||
1084 | */ | ||
1085 | _STATIC(load_up_altivec) | ||
1086 | mfmsr r5 /* grab the current MSR */ | ||
1087 | oris r5,r5,MSR_VEC@h | ||
1088 | mtmsrd r5 /* enable use of VMX now */ | ||
1089 | isync | ||
1090 | |||
1091 | /* | ||
1092 | * For SMP, we don't do lazy VMX switching because it just gets too | ||
1093 | * horrendously complex, especially when a task switches from one CPU | ||
1094 | * to another. Instead we call giveup_altvec in switch_to. | ||
1095 | * VRSAVE isn't dealt with here, that is done in the normal context | ||
1096 | * switch code. Note that we could rely on vrsave value to eventually | ||
1097 | * avoid saving all of the VREGs here... | ||
1098 | */ | ||
1099 | #ifndef CONFIG_SMP | ||
1100 | ld r3,last_task_used_altivec@got(r2) | ||
1101 | ld r4,0(r3) | ||
1102 | cmpdi 0,r4,0 | ||
1103 | beq 1f | ||
1104 | /* Save VMX state to last_task_used_altivec's THREAD struct */ | ||
1105 | addi r4,r4,THREAD | ||
1106 | SAVE_32VRS(0,r5,r4) | ||
1107 | mfvscr vr0 | ||
1108 | li r10,THREAD_VSCR | ||
1109 | stvx vr0,r10,r4 | ||
1110 | /* Disable VMX for last_task_used_altivec */ | ||
1111 | ld r5,PT_REGS(r4) | ||
1112 | ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
1113 | lis r6,MSR_VEC@h | ||
1114 | andc r4,r4,r6 | ||
1115 | std r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
1116 | 1: | ||
1117 | #endif /* CONFIG_SMP */ | ||
1118 | /* Hack: if we get an altivec unavailable trap with VRSAVE | ||
1119 | * set to all zeros, we assume this is a broken application | ||
1120 | * that fails to set it properly, and thus we switch it to | ||
1121 | * all 1's | ||
1122 | */ | ||
1123 | mfspr r4,SPRN_VRSAVE | ||
1124 | cmpdi 0,r4,0 | ||
1125 | bne+ 1f | ||
1126 | li r4,-1 | ||
1127 | mtspr SPRN_VRSAVE,r4 | ||
1128 | 1: | ||
1129 | /* enable use of VMX after return */ | ||
1130 | ld r4,PACACURRENT(r13) | ||
1131 | addi r5,r4,THREAD /* Get THREAD */ | ||
1132 | oris r12,r12,MSR_VEC@h | ||
1133 | std r12,_MSR(r1) | ||
1134 | li r4,1 | ||
1135 | li r10,THREAD_VSCR | ||
1136 | stw r4,THREAD_USED_VR(r5) | ||
1137 | lvx vr0,r10,r5 | ||
1138 | mtvscr vr0 | ||
1139 | REST_32VRS(0,r4,r5) | ||
1140 | #ifndef CONFIG_SMP | ||
1141 | /* Update last_task_used_math to 'current' */ | ||
1142 | subi r4,r5,THREAD /* Back to 'current' */ | ||
1143 | std r4,0(r3) | ||
1144 | #endif /* CONFIG_SMP */ | ||
1145 | /* restore registers and return */ | ||
1146 | b fast_exception_return | ||
1147 | #endif /* CONFIG_ALTIVEC */ | ||
1148 | |||
1149 | /* | ||
1150 | * Hash table stuff | ||
1151 | */ | ||
1152 | .align 7 | ||
1153 | _GLOBAL(do_hash_page) | ||
1154 | std r3,_DAR(r1) | ||
1155 | std r4,_DSISR(r1) | ||
1156 | |||
1157 | andis. r0,r4,0xa450 /* weird error? */ | ||
1158 | bne- .handle_page_fault /* if not, try to insert a HPTE */ | ||
1159 | BEGIN_FTR_SECTION | ||
1160 | andis. r0,r4,0x0020 /* Is it a segment table fault? */ | ||
1161 | bne- .do_ste_alloc /* If so handle it */ | ||
1162 | END_FTR_SECTION_IFCLR(CPU_FTR_SLB) | ||
1163 | |||
1164 | /* | ||
1165 | * We need to set the _PAGE_USER bit if MSR_PR is set or if we are | ||
1166 | * accessing a userspace segment (even from the kernel). We assume | ||
1167 | * kernel addresses always have the high bit set. | ||
1168 | */ | ||
1169 | rlwinm r4,r4,32-25+9,31-9,31-9 /* DSISR_STORE -> _PAGE_RW */ | ||
1170 | rotldi r0,r3,15 /* Move high bit into MSR_PR posn */ | ||
1171 | orc r0,r12,r0 /* MSR_PR | ~high_bit */ | ||
1172 | rlwimi r4,r0,32-13,30,30 /* becomes _PAGE_USER access bit */ | ||
1173 | ori r4,r4,1 /* add _PAGE_PRESENT */ | ||
1174 | rlwimi r4,r5,22+2,31-2,31-2 /* Set _PAGE_EXEC if trap is 0x400 */ | ||
1175 | |||
1176 | /* | ||
1177 | * On iSeries, we soft-disable interrupts here, then | ||
1178 | * hard-enable interrupts so that the hash_page code can spin on | ||
1179 | * the hash_table_lock without problems on a shared processor. | ||
1180 | */ | ||
1181 | DISABLE_INTS | ||
1182 | |||
1183 | /* | ||
1184 | * r3 contains the faulting address | ||
1185 | * r4 contains the required access permissions | ||
1186 | * r5 contains the trap number | ||
1187 | * | ||
1188 | * at return r3 = 0 for success | ||
1189 | */ | ||
1190 | bl .hash_page /* build HPTE if possible */ | ||
1191 | cmpdi r3,0 /* see if hash_page succeeded */ | ||
1192 | |||
1193 | #ifdef DO_SOFT_DISABLE | ||
1194 | /* | ||
1195 | * If we had interrupts soft-enabled at the point where the | ||
1196 | * DSI/ISI occurred, and an interrupt came in during hash_page, | ||
1197 | * handle it now. | ||
1198 | * We jump to ret_from_except_lite rather than fast_exception_return | ||
1199 | * because ret_from_except_lite will check for and handle pending | ||
1200 | * interrupts if necessary. | ||
1201 | */ | ||
1202 | beq .ret_from_except_lite | ||
1203 | /* For a hash failure, we don't bother re-enabling interrupts */ | ||
1204 | ble- 12f | ||
1205 | |||
1206 | /* | ||
1207 | * hash_page couldn't handle it, set soft interrupt enable back | ||
1208 | * to what it was before the trap. Note that .local_irq_restore | ||
1209 | * handles any interrupts pending at this point. | ||
1210 | */ | ||
1211 | ld r3,SOFTE(r1) | ||
1212 | bl .local_irq_restore | ||
1213 | b 11f | ||
1214 | #else | ||
1215 | beq fast_exception_return /* Return from exception on success */ | ||
1216 | ble- 12f /* Failure return from hash_page */ | ||
1217 | |||
1218 | /* fall through */ | ||
1219 | #endif | ||
1220 | |||
1221 | /* Here we have a page fault that hash_page can't handle. */ | ||
1222 | _GLOBAL(handle_page_fault) | ||
1223 | ENABLE_INTS | ||
1224 | 11: ld r4,_DAR(r1) | ||
1225 | ld r5,_DSISR(r1) | ||
1226 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1227 | bl .do_page_fault | ||
1228 | cmpdi r3,0 | ||
1229 | beq+ .ret_from_except_lite | ||
1230 | bl .save_nvgprs | ||
1231 | mr r5,r3 | ||
1232 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1233 | lwz r4,_DAR(r1) | ||
1234 | bl .bad_page_fault | ||
1235 | b .ret_from_except | ||
1236 | |||
1237 | /* We have a page fault that hash_page could handle but HV refused | ||
1238 | * the PTE insertion | ||
1239 | */ | ||
1240 | 12: bl .save_nvgprs | ||
1241 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1242 | lwz r4,_DAR(r1) | ||
1243 | bl .low_hash_fault | ||
1244 | b .ret_from_except | ||
1245 | |||
1246 | /* here we have a segment miss */ | ||
1247 | _GLOBAL(do_ste_alloc) | ||
1248 | bl .ste_allocate /* try to insert stab entry */ | ||
1249 | cmpdi r3,0 | ||
1250 | beq+ fast_exception_return | ||
1251 | b .handle_page_fault | ||
1252 | |||
1253 | /* | ||
1254 | * r13 points to the PACA, r9 contains the saved CR, | ||
1255 | * r11 and r12 contain the saved SRR0 and SRR1. | ||
1256 | * r9 - r13 are saved in paca->exslb. | ||
1257 | * We assume we aren't going to take any exceptions during this procedure. | ||
1258 | * We assume (DAR >> 60) == 0xc. | ||
1259 | */ | ||
1260 | .align 7 | ||
1261 | _GLOBAL(do_stab_bolted) | ||
1262 | stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */ | ||
1263 | std r11,PACA_EXSLB+EX_SRR0(r13) /* save SRR0 in exc. frame */ | ||
1264 | |||
1265 | /* Hash to the primary group */ | ||
1266 | ld r10,PACASTABVIRT(r13) | ||
1267 | mfspr r11,SPRN_DAR | ||
1268 | srdi r11,r11,28 | ||
1269 | rldimi r10,r11,7,52 /* r10 = first ste of the group */ | ||
1270 | |||
1271 | /* Calculate VSID */ | ||
1272 | /* This is a kernel address, so protovsid = ESID */ | ||
1273 | ASM_VSID_SCRAMBLE(r11, r9) | ||
1274 | rldic r9,r11,12,16 /* r9 = vsid << 12 */ | ||
1275 | |||
1276 | /* Search the primary group for a free entry */ | ||
1277 | 1: ld r11,0(r10) /* Test valid bit of the current ste */ | ||
1278 | andi. r11,r11,0x80 | ||
1279 | beq 2f | ||
1280 | addi r10,r10,16 | ||
1281 | andi. r11,r10,0x70 | ||
1282 | bne 1b | ||
1283 | |||
1284 | /* Stick for only searching the primary group for now. */ | ||
1285 | /* At least for now, we use a very simple random castout scheme */ | ||
1286 | /* Use the TB as a random number ; OR in 1 to avoid entry 0 */ | ||
1287 | mftb r11 | ||
1288 | rldic r11,r11,4,57 /* r11 = (r11 << 4) & 0x70 */ | ||
1289 | ori r11,r11,0x10 | ||
1290 | |||
1291 | /* r10 currently points to an ste one past the group of interest */ | ||
1292 | /* make it point to the randomly selected entry */ | ||
1293 | subi r10,r10,128 | ||
1294 | or r10,r10,r11 /* r10 is the entry to invalidate */ | ||
1295 | |||
1296 | isync /* mark the entry invalid */ | ||
1297 | ld r11,0(r10) | ||
1298 | rldicl r11,r11,56,1 /* clear the valid bit */ | ||
1299 | rotldi r11,r11,8 | ||
1300 | std r11,0(r10) | ||
1301 | sync | ||
1302 | |||
1303 | clrrdi r11,r11,28 /* Get the esid part of the ste */ | ||
1304 | slbie r11 | ||
1305 | |||
1306 | 2: std r9,8(r10) /* Store the vsid part of the ste */ | ||
1307 | eieio | ||
1308 | |||
1309 | mfspr r11,SPRN_DAR /* Get the new esid */ | ||
1310 | clrrdi r11,r11,28 /* Permits a full 32b of ESID */ | ||
1311 | ori r11,r11,0x90 /* Turn on valid and kp */ | ||
1312 | std r11,0(r10) /* Put new entry back into the stab */ | ||
1313 | |||
1314 | sync | ||
1315 | |||
1316 | /* All done -- return from exception. */ | ||
1317 | lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ | ||
1318 | ld r11,PACA_EXSLB+EX_SRR0(r13) /* get saved SRR0 */ | ||
1319 | |||
1320 | andi. r10,r12,MSR_RI | ||
1321 | beq- unrecov_slb | ||
1322 | |||
1323 | mtcrf 0x80,r9 /* restore CR */ | ||
1324 | |||
1325 | mfmsr r10 | ||
1326 | clrrdi r10,r10,2 | ||
1327 | mtmsrd r10,1 | ||
1328 | |||
1329 | mtspr SPRN_SRR0,r11 | ||
1330 | mtspr SPRN_SRR1,r12 | ||
1331 | ld r9,PACA_EXSLB+EX_R9(r13) | ||
1332 | ld r10,PACA_EXSLB+EX_R10(r13) | ||
1333 | ld r11,PACA_EXSLB+EX_R11(r13) | ||
1334 | ld r12,PACA_EXSLB+EX_R12(r13) | ||
1335 | ld r13,PACA_EXSLB+EX_R13(r13) | ||
1336 | rfid | ||
1337 | b . /* prevent speculative execution */ | ||
1338 | |||
1339 | /* | ||
1340 | * Space for CPU0's segment table. | ||
1341 | * | ||
1342 | * On iSeries, the hypervisor must fill in at least one entry before | ||
1343 | * we get control (with relocate on). The address is give to the hv | ||
1344 | * as a page number (see xLparMap in lpardata.c), so this must be at a | ||
1345 | * fixed address (the linker can't compute (u64)&initial_stab >> | ||
1346 | * PAGE_SHIFT). | ||
1347 | */ | ||
1348 | . = STAB0_PHYS_ADDR /* 0x6000 */ | ||
1349 | .globl initial_stab | ||
1350 | initial_stab: | ||
1351 | .space 4096 | ||
1352 | |||
1353 | /* | ||
1354 | * Data area reserved for FWNMI option. | ||
1355 | * This address (0x7000) is fixed by the RPA. | ||
1356 | */ | ||
1357 | .= 0x7000 | ||
1358 | .globl fwnmi_data_area | ||
1359 | fwnmi_data_area: | ||
1360 | |||
1361 | /* iSeries does not use the FWNMI stuff, so it is safe to put | ||
1362 | * this here, even if we later allow kernels that will boot on | ||
1363 | * both pSeries and iSeries */ | ||
1364 | #ifdef CONFIG_PPC_ISERIES | ||
1365 | . = LPARMAP_PHYS | ||
1366 | #include "lparmap.s" | ||
1367 | /* | ||
1368 | * This ".text" is here for old compilers that generate a trailing | ||
1369 | * .note section when compiling .c files to .s | ||
1370 | */ | ||
1371 | .text | ||
1372 | #endif /* CONFIG_PPC_ISERIES */ | ||
1373 | |||
1374 | . = 0x8000 | ||
1375 | |||
1376 | /* | ||
1377 | * On pSeries, secondary processors spin in the following code. | ||
1378 | * At entry, r3 = this processor's number (physical cpu id) | ||
1379 | */ | ||
1380 | _GLOBAL(pSeries_secondary_smp_init) | ||
1381 | mr r24,r3 | ||
1382 | |||
1383 | /* turn on 64-bit mode */ | ||
1384 | bl .enable_64b_mode | ||
1385 | isync | ||
1386 | |||
1387 | /* Copy some CPU settings from CPU 0 */ | ||
1388 | bl .__restore_cpu_setup | ||
1389 | |||
1390 | /* Set up a paca value for this processor. Since we have the | ||
1391 | * physical cpu id in r24, we need to search the pacas to find | ||
1392 | * which logical id maps to our physical one. | ||
1393 | */ | ||
1394 | LOADADDR(r13, paca) /* Get base vaddr of paca array */ | ||
1395 | li r5,0 /* logical cpu id */ | ||
1396 | 1: lhz r6,PACAHWCPUID(r13) /* Load HW procid from paca */ | ||
1397 | cmpw r6,r24 /* Compare to our id */ | ||
1398 | beq 2f | ||
1399 | addi r13,r13,PACA_SIZE /* Loop to next PACA on miss */ | ||
1400 | addi r5,r5,1 | ||
1401 | cmpwi r5,NR_CPUS | ||
1402 | blt 1b | ||
1403 | |||
1404 | mr r3,r24 /* not found, copy phys to r3 */ | ||
1405 | b .kexec_wait /* next kernel might do better */ | ||
1406 | |||
1407 | 2: mtspr SPRN_SPRG3,r13 /* Save vaddr of paca in SPRG3 */ | ||
1408 | /* From now on, r24 is expected to be logical cpuid */ | ||
1409 | mr r24,r5 | ||
1410 | 3: HMT_LOW | ||
1411 | lbz r23,PACAPROCSTART(r13) /* Test if this processor should */ | ||
1412 | /* start. */ | ||
1413 | sync | ||
1414 | |||
1415 | /* Create a temp kernel stack for use before relocation is on. */ | ||
1416 | ld r1,PACAEMERGSP(r13) | ||
1417 | subi r1,r1,STACK_FRAME_OVERHEAD | ||
1418 | |||
1419 | cmpwi 0,r23,0 | ||
1420 | #ifdef CONFIG_SMP | ||
1421 | bne .__secondary_start | ||
1422 | #endif | ||
1423 | b 3b /* Loop until told to go */ | ||
1424 | |||
1425 | #ifdef CONFIG_PPC_ISERIES | ||
1426 | _STATIC(__start_initialization_iSeries) | ||
1427 | /* Clear out the BSS */ | ||
1428 | LOADADDR(r11,__bss_stop) | ||
1429 | LOADADDR(r8,__bss_start) | ||
1430 | sub r11,r11,r8 /* bss size */ | ||
1431 | addi r11,r11,7 /* round up to an even double word */ | ||
1432 | rldicl. r11,r11,61,3 /* shift right by 3 */ | ||
1433 | beq 4f | ||
1434 | addi r8,r8,-8 | ||
1435 | li r0,0 | ||
1436 | mtctr r11 /* zero this many doublewords */ | ||
1437 | 3: stdu r0,8(r8) | ||
1438 | bdnz 3b | ||
1439 | 4: | ||
1440 | LOADADDR(r1,init_thread_union) | ||
1441 | addi r1,r1,THREAD_SIZE | ||
1442 | li r0,0 | ||
1443 | stdu r0,-STACK_FRAME_OVERHEAD(r1) | ||
1444 | |||
1445 | LOADADDR(r3,cpu_specs) | ||
1446 | LOADADDR(r4,cur_cpu_spec) | ||
1447 | li r5,0 | ||
1448 | bl .identify_cpu | ||
1449 | |||
1450 | LOADADDR(r2,__toc_start) | ||
1451 | addi r2,r2,0x4000 | ||
1452 | addi r2,r2,0x4000 | ||
1453 | |||
1454 | bl .iSeries_early_setup | ||
1455 | bl .early_setup | ||
1456 | |||
1457 | /* relocation is on at this point */ | ||
1458 | |||
1459 | b .start_here_common | ||
1460 | #endif /* CONFIG_PPC_ISERIES */ | ||
1461 | |||
1462 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
1463 | |||
1464 | _STATIC(__mmu_off) | ||
1465 | mfmsr r3 | ||
1466 | andi. r0,r3,MSR_IR|MSR_DR | ||
1467 | beqlr | ||
1468 | andc r3,r3,r0 | ||
1469 | mtspr SPRN_SRR0,r4 | ||
1470 | mtspr SPRN_SRR1,r3 | ||
1471 | sync | ||
1472 | rfid | ||
1473 | b . /* prevent speculative execution */ | ||
1474 | |||
1475 | |||
1476 | /* | ||
1477 | * Here is our main kernel entry point. We support currently 2 kind of entries | ||
1478 | * depending on the value of r5. | ||
1479 | * | ||
1480 | * r5 != NULL -> OF entry, we go to prom_init, "legacy" parameter content | ||
1481 | * in r3...r7 | ||
1482 | * | ||
1483 | * r5 == NULL -> kexec style entry. r3 is a physical pointer to the | ||
1484 | * DT block, r4 is a physical pointer to the kernel itself | ||
1485 | * | ||
1486 | */ | ||
1487 | _GLOBAL(__start_initialization_multiplatform) | ||
1488 | /* | ||
1489 | * Are we booted from a PROM Of-type client-interface ? | ||
1490 | */ | ||
1491 | cmpldi cr0,r5,0 | ||
1492 | bne .__boot_from_prom /* yes -> prom */ | ||
1493 | |||
1494 | /* Save parameters */ | ||
1495 | mr r31,r3 | ||
1496 | mr r30,r4 | ||
1497 | |||
1498 | /* Make sure we are running in 64 bits mode */ | ||
1499 | bl .enable_64b_mode | ||
1500 | |||
1501 | /* Setup some critical 970 SPRs before switching MMU off */ | ||
1502 | bl .__970_cpu_preinit | ||
1503 | |||
1504 | /* cpu # */ | ||
1505 | li r24,0 | ||
1506 | |||
1507 | /* Switch off MMU if not already */ | ||
1508 | LOADADDR(r4, .__after_prom_start - KERNELBASE) | ||
1509 | add r4,r4,r30 | ||
1510 | bl .__mmu_off | ||
1511 | b .__after_prom_start | ||
1512 | |||
1513 | _STATIC(__boot_from_prom) | ||
1514 | /* Save parameters */ | ||
1515 | mr r31,r3 | ||
1516 | mr r30,r4 | ||
1517 | mr r29,r5 | ||
1518 | mr r28,r6 | ||
1519 | mr r27,r7 | ||
1520 | |||
1521 | /* Make sure we are running in 64 bits mode */ | ||
1522 | bl .enable_64b_mode | ||
1523 | |||
1524 | /* put a relocation offset into r3 */ | ||
1525 | bl .reloc_offset | ||
1526 | |||
1527 | LOADADDR(r2,__toc_start) | ||
1528 | addi r2,r2,0x4000 | ||
1529 | addi r2,r2,0x4000 | ||
1530 | |||
1531 | /* Relocate the TOC from a virt addr to a real addr */ | ||
1532 | sub r2,r2,r3 | ||
1533 | |||
1534 | /* Restore parameters */ | ||
1535 | mr r3,r31 | ||
1536 | mr r4,r30 | ||
1537 | mr r5,r29 | ||
1538 | mr r6,r28 | ||
1539 | mr r7,r27 | ||
1540 | |||
1541 | /* Do all of the interaction with OF client interface */ | ||
1542 | bl .prom_init | ||
1543 | /* We never return */ | ||
1544 | trap | ||
1545 | |||
1546 | /* | ||
1547 | * At this point, r3 contains the physical address we are running at, | ||
1548 | * returned by prom_init() | ||
1549 | */ | ||
1550 | _STATIC(__after_prom_start) | ||
1551 | |||
1552 | /* | ||
1553 | * We need to run with __start at physical address 0. | ||
1554 | * This will leave some code in the first 256B of | ||
1555 | * real memory, which are reserved for software use. | ||
1556 | * The remainder of the first page is loaded with the fixed | ||
1557 | * interrupt vectors. The next two pages are filled with | ||
1558 | * unknown exception placeholders. | ||
1559 | * | ||
1560 | * Note: This process overwrites the OF exception vectors. | ||
1561 | * r26 == relocation offset | ||
1562 | * r27 == KERNELBASE | ||
1563 | */ | ||
1564 | bl .reloc_offset | ||
1565 | mr r26,r3 | ||
1566 | SET_REG_TO_CONST(r27,KERNELBASE) | ||
1567 | |||
1568 | li r3,0 /* target addr */ | ||
1569 | |||
1570 | // XXX FIXME: Use phys returned by OF (r30) | ||
1571 | sub r4,r27,r26 /* source addr */ | ||
1572 | /* current address of _start */ | ||
1573 | /* i.e. where we are running */ | ||
1574 | /* the source addr */ | ||
1575 | |||
1576 | LOADADDR(r5,copy_to_here) /* # bytes of memory to copy */ | ||
1577 | sub r5,r5,r27 | ||
1578 | |||
1579 | li r6,0x100 /* Start offset, the first 0x100 */ | ||
1580 | /* bytes were copied earlier. */ | ||
1581 | |||
1582 | bl .copy_and_flush /* copy the first n bytes */ | ||
1583 | /* this includes the code being */ | ||
1584 | /* executed here. */ | ||
1585 | |||
1586 | LOADADDR(r0, 4f) /* Jump to the copy of this code */ | ||
1587 | mtctr r0 /* that we just made/relocated */ | ||
1588 | bctr | ||
1589 | |||
1590 | 4: LOADADDR(r5,klimit) | ||
1591 | sub r5,r5,r26 | ||
1592 | ld r5,0(r5) /* get the value of klimit */ | ||
1593 | sub r5,r5,r27 | ||
1594 | bl .copy_and_flush /* copy the rest */ | ||
1595 | b .start_here_multiplatform | ||
1596 | |||
1597 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
1598 | |||
1599 | /* | ||
1600 | * Copy routine used to copy the kernel to start at physical address 0 | ||
1601 | * and flush and invalidate the caches as needed. | ||
1602 | * r3 = dest addr, r4 = source addr, r5 = copy limit, r6 = start offset | ||
1603 | * on exit, r3, r4, r5 are unchanged, r6 is updated to be >= r5. | ||
1604 | * | ||
1605 | * Note: this routine *only* clobbers r0, r6 and lr | ||
1606 | */ | ||
1607 | _GLOBAL(copy_and_flush) | ||
1608 | addi r5,r5,-8 | ||
1609 | addi r6,r6,-8 | ||
1610 | 4: li r0,16 /* Use the least common */ | ||
1611 | /* denominator cache line */ | ||
1612 | /* size. This results in */ | ||
1613 | /* extra cache line flushes */ | ||
1614 | /* but operation is correct. */ | ||
1615 | /* Can't get cache line size */ | ||
1616 | /* from NACA as it is being */ | ||
1617 | /* moved too. */ | ||
1618 | |||
1619 | mtctr r0 /* put # words/line in ctr */ | ||
1620 | 3: addi r6,r6,8 /* copy a cache line */ | ||
1621 | ldx r0,r6,r4 | ||
1622 | stdx r0,r6,r3 | ||
1623 | bdnz 3b | ||
1624 | dcbst r6,r3 /* write it to memory */ | ||
1625 | sync | ||
1626 | icbi r6,r3 /* flush the icache line */ | ||
1627 | cmpld 0,r6,r5 | ||
1628 | blt 4b | ||
1629 | sync | ||
1630 | addi r5,r5,8 | ||
1631 | addi r6,r6,8 | ||
1632 | blr | ||
1633 | |||
1634 | .align 8 | ||
1635 | copy_to_here: | ||
1636 | |||
1637 | #ifdef CONFIG_SMP | ||
1638 | #ifdef CONFIG_PPC_PMAC | ||
1639 | /* | ||
1640 | * On PowerMac, secondary processors starts from the reset vector, which | ||
1641 | * is temporarily turned into a call to one of the functions below. | ||
1642 | */ | ||
1643 | .section ".text"; | ||
1644 | .align 2 ; | ||
1645 | |||
1646 | .globl __secondary_start_pmac_0 | ||
1647 | __secondary_start_pmac_0: | ||
1648 | /* NB the entries for cpus 0, 1, 2 must each occupy 8 bytes. */ | ||
1649 | li r24,0 | ||
1650 | b 1f | ||
1651 | li r24,1 | ||
1652 | b 1f | ||
1653 | li r24,2 | ||
1654 | b 1f | ||
1655 | li r24,3 | ||
1656 | 1: | ||
1657 | |||
1658 | _GLOBAL(pmac_secondary_start) | ||
1659 | /* turn on 64-bit mode */ | ||
1660 | bl .enable_64b_mode | ||
1661 | isync | ||
1662 | |||
1663 | /* Copy some CPU settings from CPU 0 */ | ||
1664 | bl .__restore_cpu_setup | ||
1665 | |||
1666 | /* pSeries do that early though I don't think we really need it */ | ||
1667 | mfmsr r3 | ||
1668 | ori r3,r3,MSR_RI | ||
1669 | mtmsrd r3 /* RI on */ | ||
1670 | |||
1671 | /* Set up a paca value for this processor. */ | ||
1672 | LOADADDR(r4, paca) /* Get base vaddr of paca array */ | ||
1673 | mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */ | ||
1674 | add r13,r13,r4 /* for this processor. */ | ||
1675 | mtspr SPRN_SPRG3,r13 /* Save vaddr of paca in SPRG3 */ | ||
1676 | |||
1677 | /* Create a temp kernel stack for use before relocation is on. */ | ||
1678 | ld r1,PACAEMERGSP(r13) | ||
1679 | subi r1,r1,STACK_FRAME_OVERHEAD | ||
1680 | |||
1681 | b .__secondary_start | ||
1682 | |||
1683 | #endif /* CONFIG_PPC_PMAC */ | ||
1684 | |||
1685 | /* | ||
1686 | * This function is called after the master CPU has released the | ||
1687 | * secondary processors. The execution environment is relocation off. | ||
1688 | * The paca for this processor has the following fields initialized at | ||
1689 | * this point: | ||
1690 | * 1. Processor number | ||
1691 | * 2. Segment table pointer (virtual address) | ||
1692 | * On entry the following are set: | ||
1693 | * r1 = stack pointer. vaddr for iSeries, raddr (temp stack) for pSeries | ||
1694 | * r24 = cpu# (in Linux terms) | ||
1695 | * r13 = paca virtual address | ||
1696 | * SPRG3 = paca virtual address | ||
1697 | */ | ||
1698 | _GLOBAL(__secondary_start) | ||
1699 | |||
1700 | HMT_MEDIUM /* Set thread priority to MEDIUM */ | ||
1701 | |||
1702 | ld r2,PACATOC(r13) | ||
1703 | |||
1704 | /* Do early setup for that CPU */ | ||
1705 | bl .early_setup_secondary | ||
1706 | |||
1707 | /* Initialize the kernel stack. Just a repeat for iSeries. */ | ||
1708 | LOADADDR(r3,current_set) | ||
1709 | sldi r28,r24,3 /* get current_set[cpu#] */ | ||
1710 | ldx r1,r3,r28 | ||
1711 | addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD | ||
1712 | std r1,PACAKSAVE(r13) | ||
1713 | |||
1714 | li r7,0 | ||
1715 | mtlr r7 | ||
1716 | |||
1717 | /* enable MMU and jump to start_secondary */ | ||
1718 | LOADADDR(r3,.start_secondary_prolog) | ||
1719 | SET_REG_TO_CONST(r4, MSR_KERNEL) | ||
1720 | #ifdef DO_SOFT_DISABLE | ||
1721 | ori r4,r4,MSR_EE | ||
1722 | #endif | ||
1723 | mtspr SPRN_SRR0,r3 | ||
1724 | mtspr SPRN_SRR1,r4 | ||
1725 | rfid | ||
1726 | b . /* prevent speculative execution */ | ||
1727 | |||
1728 | /* | ||
1729 | * Running with relocation on at this point. All we want to do is | ||
1730 | * zero the stack back-chain pointer before going into C code. | ||
1731 | */ | ||
1732 | _GLOBAL(start_secondary_prolog) | ||
1733 | li r3,0 | ||
1734 | std r3,0(r1) /* Zero the stack frame pointer */ | ||
1735 | bl .start_secondary | ||
1736 | #endif | ||
1737 | |||
1738 | /* | ||
1739 | * This subroutine clobbers r11 and r12 | ||
1740 | */ | ||
1741 | _GLOBAL(enable_64b_mode) | ||
1742 | mfmsr r11 /* grab the current MSR */ | ||
1743 | li r12,1 | ||
1744 | rldicr r12,r12,MSR_SF_LG,(63-MSR_SF_LG) | ||
1745 | or r11,r11,r12 | ||
1746 | li r12,1 | ||
1747 | rldicr r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG) | ||
1748 | or r11,r11,r12 | ||
1749 | mtmsrd r11 | ||
1750 | isync | ||
1751 | blr | ||
1752 | |||
1753 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
1754 | /* | ||
1755 | * This is where the main kernel code starts. | ||
1756 | */ | ||
1757 | _STATIC(start_here_multiplatform) | ||
1758 | /* get a new offset, now that the kernel has moved. */ | ||
1759 | bl .reloc_offset | ||
1760 | mr r26,r3 | ||
1761 | |||
1762 | /* Clear out the BSS. It may have been done in prom_init, | ||
1763 | * already but that's irrelevant since prom_init will soon | ||
1764 | * be detached from the kernel completely. Besides, we need | ||
1765 | * to clear it now for kexec-style entry. | ||
1766 | */ | ||
1767 | LOADADDR(r11,__bss_stop) | ||
1768 | LOADADDR(r8,__bss_start) | ||
1769 | sub r11,r11,r8 /* bss size */ | ||
1770 | addi r11,r11,7 /* round up to an even double word */ | ||
1771 | rldicl. r11,r11,61,3 /* shift right by 3 */ | ||
1772 | beq 4f | ||
1773 | addi r8,r8,-8 | ||
1774 | li r0,0 | ||
1775 | mtctr r11 /* zero this many doublewords */ | ||
1776 | 3: stdu r0,8(r8) | ||
1777 | bdnz 3b | ||
1778 | 4: | ||
1779 | |||
1780 | mfmsr r6 | ||
1781 | ori r6,r6,MSR_RI | ||
1782 | mtmsrd r6 /* RI on */ | ||
1783 | |||
1784 | #ifdef CONFIG_HMT | ||
1785 | /* Start up the second thread on cpu 0 */ | ||
1786 | mfspr r3,SPRN_PVR | ||
1787 | srwi r3,r3,16 | ||
1788 | cmpwi r3,0x34 /* Pulsar */ | ||
1789 | beq 90f | ||
1790 | cmpwi r3,0x36 /* Icestar */ | ||
1791 | beq 90f | ||
1792 | cmpwi r3,0x37 /* SStar */ | ||
1793 | beq 90f | ||
1794 | b 91f /* HMT not supported */ | ||
1795 | 90: li r3,0 | ||
1796 | bl .hmt_start_secondary | ||
1797 | 91: | ||
1798 | #endif | ||
1799 | |||
1800 | /* The following gets the stack and TOC set up with the regs */ | ||
1801 | /* pointing to the real addr of the kernel stack. This is */ | ||
1802 | /* all done to support the C function call below which sets */ | ||
1803 | /* up the htab. This is done because we have relocated the */ | ||
1804 | /* kernel but are still running in real mode. */ | ||
1805 | |||
1806 | LOADADDR(r3,init_thread_union) | ||
1807 | sub r3,r3,r26 | ||
1808 | |||
1809 | /* set up a stack pointer (physical address) */ | ||
1810 | addi r1,r3,THREAD_SIZE | ||
1811 | li r0,0 | ||
1812 | stdu r0,-STACK_FRAME_OVERHEAD(r1) | ||
1813 | |||
1814 | /* set up the TOC (physical address) */ | ||
1815 | LOADADDR(r2,__toc_start) | ||
1816 | addi r2,r2,0x4000 | ||
1817 | addi r2,r2,0x4000 | ||
1818 | sub r2,r2,r26 | ||
1819 | |||
1820 | LOADADDR(r3,cpu_specs) | ||
1821 | sub r3,r3,r26 | ||
1822 | LOADADDR(r4,cur_cpu_spec) | ||
1823 | sub r4,r4,r26 | ||
1824 | mr r5,r26 | ||
1825 | bl .identify_cpu | ||
1826 | |||
1827 | /* Save some low level config HIDs of CPU0 to be copied to | ||
1828 | * other CPUs later on, or used for suspend/resume | ||
1829 | */ | ||
1830 | bl .__save_cpu_setup | ||
1831 | sync | ||
1832 | |||
1833 | /* Setup a valid physical PACA pointer in SPRG3 for early_setup | ||
1834 | * note that boot_cpuid can always be 0 nowadays since there is | ||
1835 | * nowhere it can be initialized differently before we reach this | ||
1836 | * code | ||
1837 | */ | ||
1838 | LOADADDR(r27, boot_cpuid) | ||
1839 | sub r27,r27,r26 | ||
1840 | lwz r27,0(r27) | ||
1841 | |||
1842 | LOADADDR(r24, paca) /* Get base vaddr of paca array */ | ||
1843 | mulli r13,r27,PACA_SIZE /* Calculate vaddr of right paca */ | ||
1844 | add r13,r13,r24 /* for this processor. */ | ||
1845 | sub r13,r13,r26 /* convert to physical addr */ | ||
1846 | mtspr SPRN_SPRG3,r13 /* PPPBBB: Temp... -Peter */ | ||
1847 | |||
1848 | /* Do very early kernel initializations, including initial hash table, | ||
1849 | * stab and slb setup before we turn on relocation. */ | ||
1850 | |||
1851 | /* Restore parameters passed from prom_init/kexec */ | ||
1852 | mr r3,r31 | ||
1853 | bl .early_setup | ||
1854 | |||
1855 | LOADADDR(r3,.start_here_common) | ||
1856 | SET_REG_TO_CONST(r4, MSR_KERNEL) | ||
1857 | mtspr SPRN_SRR0,r3 | ||
1858 | mtspr SPRN_SRR1,r4 | ||
1859 | rfid | ||
1860 | b . /* prevent speculative execution */ | ||
1861 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
1862 | |||
1863 | /* This is where all platforms converge execution */ | ||
1864 | _STATIC(start_here_common) | ||
1865 | /* relocation is on at this point */ | ||
1866 | |||
1867 | /* The following code sets up the SP and TOC now that we are */ | ||
1868 | /* running with translation enabled. */ | ||
1869 | |||
1870 | LOADADDR(r3,init_thread_union) | ||
1871 | |||
1872 | /* set up the stack */ | ||
1873 | addi r1,r3,THREAD_SIZE | ||
1874 | li r0,0 | ||
1875 | stdu r0,-STACK_FRAME_OVERHEAD(r1) | ||
1876 | |||
1877 | /* Apply the CPUs-specific fixups (nop out sections not relevant | ||
1878 | * to this CPU | ||
1879 | */ | ||
1880 | li r3,0 | ||
1881 | bl .do_cpu_ftr_fixups | ||
1882 | |||
1883 | LOADADDR(r26, boot_cpuid) | ||
1884 | lwz r26,0(r26) | ||
1885 | |||
1886 | LOADADDR(r24, paca) /* Get base vaddr of paca array */ | ||
1887 | mulli r13,r26,PACA_SIZE /* Calculate vaddr of right paca */ | ||
1888 | add r13,r13,r24 /* for this processor. */ | ||
1889 | mtspr SPRN_SPRG3,r13 | ||
1890 | |||
1891 | /* ptr to current */ | ||
1892 | LOADADDR(r4,init_task) | ||
1893 | std r4,PACACURRENT(r13) | ||
1894 | |||
1895 | /* Load the TOC */ | ||
1896 | ld r2,PACATOC(r13) | ||
1897 | std r1,PACAKSAVE(r13) | ||
1898 | |||
1899 | bl .setup_system | ||
1900 | |||
1901 | /* Load up the kernel context */ | ||
1902 | 5: | ||
1903 | #ifdef DO_SOFT_DISABLE | ||
1904 | li r5,0 | ||
1905 | stb r5,PACAPROCENABLED(r13) /* Soft Disabled */ | ||
1906 | mfmsr r5 | ||
1907 | ori r5,r5,MSR_EE /* Hard Enabled */ | ||
1908 | mtmsrd r5 | ||
1909 | #endif | ||
1910 | |||
1911 | bl .start_kernel | ||
1912 | |||
1913 | _GLOBAL(hmt_init) | ||
1914 | #ifdef CONFIG_HMT | ||
1915 | LOADADDR(r5, hmt_thread_data) | ||
1916 | mfspr r7,SPRN_PVR | ||
1917 | srwi r7,r7,16 | ||
1918 | cmpwi r7,0x34 /* Pulsar */ | ||
1919 | beq 90f | ||
1920 | cmpwi r7,0x36 /* Icestar */ | ||
1921 | beq 91f | ||
1922 | cmpwi r7,0x37 /* SStar */ | ||
1923 | beq 91f | ||
1924 | b 101f | ||
1925 | 90: mfspr r6,SPRN_PIR | ||
1926 | andi. r6,r6,0x1f | ||
1927 | b 92f | ||
1928 | 91: mfspr r6,SPRN_PIR | ||
1929 | andi. r6,r6,0x3ff | ||
1930 | 92: sldi r4,r24,3 | ||
1931 | stwx r6,r5,r4 | ||
1932 | bl .hmt_start_secondary | ||
1933 | b 101f | ||
1934 | |||
1935 | __hmt_secondary_hold: | ||
1936 | LOADADDR(r5, hmt_thread_data) | ||
1937 | clrldi r5,r5,4 | ||
1938 | li r7,0 | ||
1939 | mfspr r6,SPRN_PIR | ||
1940 | mfspr r8,SPRN_PVR | ||
1941 | srwi r8,r8,16 | ||
1942 | cmpwi r8,0x34 | ||
1943 | bne 93f | ||
1944 | andi. r6,r6,0x1f | ||
1945 | b 103f | ||
1946 | 93: andi. r6,r6,0x3f | ||
1947 | |||
1948 | 103: lwzx r8,r5,r7 | ||
1949 | cmpw r8,r6 | ||
1950 | beq 104f | ||
1951 | addi r7,r7,8 | ||
1952 | b 103b | ||
1953 | |||
1954 | 104: addi r7,r7,4 | ||
1955 | lwzx r9,r5,r7 | ||
1956 | mr r24,r9 | ||
1957 | 101: | ||
1958 | #endif | ||
1959 | mr r3,r24 | ||
1960 | b .pSeries_secondary_smp_init | ||
1961 | |||
1962 | #ifdef CONFIG_HMT | ||
1963 | _GLOBAL(hmt_start_secondary) | ||
1964 | LOADADDR(r4,__hmt_secondary_hold) | ||
1965 | clrldi r4,r4,4 | ||
1966 | mtspr SPRN_NIADORM, r4 | ||
1967 | mfspr r4, SPRN_MSRDORM | ||
1968 | li r5, -65 | ||
1969 | and r4, r4, r5 | ||
1970 | mtspr SPRN_MSRDORM, r4 | ||
1971 | lis r4,0xffef | ||
1972 | ori r4,r4,0x7403 | ||
1973 | mtspr SPRN_TSC, r4 | ||
1974 | li r4,0x1f4 | ||
1975 | mtspr SPRN_TST, r4 | ||
1976 | mfspr r4, SPRN_HID0 | ||
1977 | ori r4, r4, 0x1 | ||
1978 | mtspr SPRN_HID0, r4 | ||
1979 | mfspr r4, SPRN_CTRLF | ||
1980 | oris r4, r4, 0x40 | ||
1981 | mtspr SPRN_CTRLT, r4 | ||
1982 | blr | ||
1983 | #endif | ||
1984 | |||
1985 | /* | ||
1986 | * We put a few things here that have to be page-aligned. | ||
1987 | * This stuff goes at the beginning of the bss, which is page-aligned. | ||
1988 | */ | ||
1989 | .section ".bss" | ||
1990 | |||
1991 | .align PAGE_SHIFT | ||
1992 | |||
1993 | .globl empty_zero_page | ||
1994 | empty_zero_page: | ||
1995 | .space PAGE_SIZE | ||
1996 | |||
1997 | .globl swapper_pg_dir | ||
1998 | swapper_pg_dir: | ||
1999 | .space PAGE_SIZE | ||
2000 | |||
2001 | /* | ||
2002 | * This space gets a copy of optional info passed to us by the bootstrap | ||
2003 | * Used to pass parameters into the kernel like root=/dev/sda1, etc. | ||
2004 | */ | ||
2005 | .globl cmd_line | ||
2006 | cmd_line: | ||
2007 | .space COMMAND_LINE_SIZE | ||
diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S deleted file mode 100644 index 5e089deb0a2b..000000000000 --- a/arch/ppc64/kernel/misc.S +++ /dev/null | |||
@@ -1,940 +0,0 @@ | |||
1 | /* | ||
2 | * arch/ppc/kernel/misc.S | ||
3 | * | ||
4 | * | ||
5 | * | ||
6 | * This file contains miscellaneous low-level functions. | ||
7 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | ||
8 | * | ||
9 | * Largely rewritten by Cort Dougan (cort@cs.nmt.edu) | ||
10 | * and Paul Mackerras. | ||
11 | * Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com) | ||
12 | * PPC64 updates by Dave Engebretsen (engebret@us.ibm.com) | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or | ||
15 | * modify it under the terms of the GNU General Public License | ||
16 | * as published by the Free Software Foundation; either version | ||
17 | * 2 of the License, or (at your option) any later version. | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #include <linux/config.h> | ||
22 | #include <linux/sys.h> | ||
23 | #include <asm/unistd.h> | ||
24 | #include <asm/errno.h> | ||
25 | #include <asm/processor.h> | ||
26 | #include <asm/page.h> | ||
27 | #include <asm/cache.h> | ||
28 | #include <asm/ppc_asm.h> | ||
29 | #include <asm/asm-offsets.h> | ||
30 | #include <asm/cputable.h> | ||
31 | #include <asm/thread_info.h> | ||
32 | |||
33 | .text | ||
34 | |||
35 | /* | ||
36 | * Returns (address we were linked at) - (address we are running at) | ||
37 | * for use before the text and data are mapped to KERNELBASE. | ||
38 | */ | ||
39 | |||
40 | _GLOBAL(reloc_offset) | ||
41 | mflr r0 | ||
42 | bl 1f | ||
43 | 1: mflr r3 | ||
44 | LOADADDR(r4,1b) | ||
45 | sub r3,r4,r3 | ||
46 | mtlr r0 | ||
47 | blr | ||
48 | |||
49 | _GLOBAL(get_msr) | ||
50 | mfmsr r3 | ||
51 | blr | ||
52 | |||
53 | _GLOBAL(get_dar) | ||
54 | mfdar r3 | ||
55 | blr | ||
56 | |||
57 | _GLOBAL(get_srr0) | ||
58 | mfsrr0 r3 | ||
59 | blr | ||
60 | |||
61 | _GLOBAL(get_srr1) | ||
62 | mfsrr1 r3 | ||
63 | blr | ||
64 | |||
65 | _GLOBAL(get_sp) | ||
66 | mr r3,r1 | ||
67 | blr | ||
68 | |||
69 | #ifdef CONFIG_IRQSTACKS | ||
70 | _GLOBAL(call_do_softirq) | ||
71 | mflr r0 | ||
72 | std r0,16(r1) | ||
73 | stdu r1,THREAD_SIZE-112(r3) | ||
74 | mr r1,r3 | ||
75 | bl .__do_softirq | ||
76 | ld r1,0(r1) | ||
77 | ld r0,16(r1) | ||
78 | mtlr r0 | ||
79 | blr | ||
80 | |||
81 | _GLOBAL(call___do_IRQ) | ||
82 | mflr r0 | ||
83 | std r0,16(r1) | ||
84 | stdu r1,THREAD_SIZE-112(r5) | ||
85 | mr r1,r5 | ||
86 | bl .__do_IRQ | ||
87 | ld r1,0(r1) | ||
88 | ld r0,16(r1) | ||
89 | mtlr r0 | ||
90 | blr | ||
91 | #endif /* CONFIG_IRQSTACKS */ | ||
92 | |||
93 | /* | ||
94 | * To be called by C code which needs to do some operations with MMU | ||
95 | * disabled. Note that interrupts have to be disabled by the caller | ||
96 | * prior to calling us. The code called _MUST_ be in the RMO of course | ||
97 | * and part of the linear mapping as we don't attempt to translate the | ||
98 | * stack pointer at all. The function is called with the stack switched | ||
99 | * to this CPU emergency stack | ||
100 | * | ||
101 | * prototype is void *call_with_mmu_off(void *func, void *data); | ||
102 | * | ||
103 | * the called function is expected to be of the form | ||
104 | * | ||
105 | * void *called(void *data); | ||
106 | */ | ||
107 | _GLOBAL(call_with_mmu_off) | ||
108 | mflr r0 /* get link, save it on stackframe */ | ||
109 | std r0,16(r1) | ||
110 | mr r1,r5 /* save old stack ptr */ | ||
111 | ld r1,PACAEMERGSP(r13) /* get emerg. stack */ | ||
112 | subi r1,r1,STACK_FRAME_OVERHEAD | ||
113 | std r0,16(r1) /* save link on emerg. stack */ | ||
114 | std r5,0(r1) /* save old stack ptr in backchain */ | ||
115 | ld r3,0(r3) /* get to real function ptr (assume same TOC) */ | ||
116 | bl 2f /* we need LR to return, continue at label 2 */ | ||
117 | |||
118 | ld r0,16(r1) /* we return here from the call, get LR and */ | ||
119 | ld r1,0(r1) /* .. old stack ptr */ | ||
120 | mtspr SPRN_SRR0,r0 /* and get back to virtual mode with these */ | ||
121 | mfmsr r4 | ||
122 | ori r4,r4,MSR_IR|MSR_DR | ||
123 | mtspr SPRN_SRR1,r4 | ||
124 | rfid | ||
125 | |||
126 | 2: mtspr SPRN_SRR0,r3 /* coming from above, enter real mode */ | ||
127 | mr r3,r4 /* get parameter */ | ||
128 | mfmsr r0 | ||
129 | ori r0,r0,MSR_IR|MSR_DR | ||
130 | xori r0,r0,MSR_IR|MSR_DR | ||
131 | mtspr SPRN_SRR1,r0 | ||
132 | rfid | ||
133 | |||
134 | |||
135 | .section ".toc","aw" | ||
136 | PPC64_CACHES: | ||
137 | .tc ppc64_caches[TC],ppc64_caches | ||
138 | .section ".text" | ||
139 | |||
140 | /* | ||
141 | * Write any modified data cache blocks out to memory | ||
142 | * and invalidate the corresponding instruction cache blocks. | ||
143 | * | ||
144 | * flush_icache_range(unsigned long start, unsigned long stop) | ||
145 | * | ||
146 | * flush all bytes from start through stop-1 inclusive | ||
147 | */ | ||
148 | |||
149 | _KPROBE(__flush_icache_range) | ||
150 | |||
151 | /* | ||
152 | * Flush the data cache to memory | ||
153 | * | ||
154 | * Different systems have different cache line sizes | ||
155 | * and in some cases i-cache and d-cache line sizes differ from | ||
156 | * each other. | ||
157 | */ | ||
158 | ld r10,PPC64_CACHES@toc(r2) | ||
159 | lwz r7,DCACHEL1LINESIZE(r10)/* Get cache line size */ | ||
160 | addi r5,r7,-1 | ||
161 | andc r6,r3,r5 /* round low to line bdy */ | ||
162 | subf r8,r6,r4 /* compute length */ | ||
163 | add r8,r8,r5 /* ensure we get enough */ | ||
164 | lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of cache line size */ | ||
165 | srw. r8,r8,r9 /* compute line count */ | ||
166 | beqlr /* nothing to do? */ | ||
167 | mtctr r8 | ||
168 | 1: dcbst 0,r6 | ||
169 | add r6,r6,r7 | ||
170 | bdnz 1b | ||
171 | sync | ||
172 | |||
173 | /* Now invalidate the instruction cache */ | ||
174 | |||
175 | lwz r7,ICACHEL1LINESIZE(r10) /* Get Icache line size */ | ||
176 | addi r5,r7,-1 | ||
177 | andc r6,r3,r5 /* round low to line bdy */ | ||
178 | subf r8,r6,r4 /* compute length */ | ||
179 | add r8,r8,r5 | ||
180 | lwz r9,ICACHEL1LOGLINESIZE(r10) /* Get log-2 of Icache line size */ | ||
181 | srw. r8,r8,r9 /* compute line count */ | ||
182 | beqlr /* nothing to do? */ | ||
183 | mtctr r8 | ||
184 | 2: icbi 0,r6 | ||
185 | add r6,r6,r7 | ||
186 | bdnz 2b | ||
187 | isync | ||
188 | blr | ||
189 | |||
190 | .text | ||
191 | /* | ||
192 | * Like above, but only do the D-cache. | ||
193 | * | ||
194 | * flush_dcache_range(unsigned long start, unsigned long stop) | ||
195 | * | ||
196 | * flush all bytes from start to stop-1 inclusive | ||
197 | */ | ||
198 | _GLOBAL(flush_dcache_range) | ||
199 | |||
200 | /* | ||
201 | * Flush the data cache to memory | ||
202 | * | ||
203 | * Different systems have different cache line sizes | ||
204 | */ | ||
205 | ld r10,PPC64_CACHES@toc(r2) | ||
206 | lwz r7,DCACHEL1LINESIZE(r10) /* Get dcache line size */ | ||
207 | addi r5,r7,-1 | ||
208 | andc r6,r3,r5 /* round low to line bdy */ | ||
209 | subf r8,r6,r4 /* compute length */ | ||
210 | add r8,r8,r5 /* ensure we get enough */ | ||
211 | lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of dcache line size */ | ||
212 | srw. r8,r8,r9 /* compute line count */ | ||
213 | beqlr /* nothing to do? */ | ||
214 | mtctr r8 | ||
215 | 0: dcbst 0,r6 | ||
216 | add r6,r6,r7 | ||
217 | bdnz 0b | ||
218 | sync | ||
219 | blr | ||
220 | |||
221 | /* | ||
222 | * Like above, but works on non-mapped physical addresses. | ||
223 | * Use only for non-LPAR setups ! It also assumes real mode | ||
224 | * is cacheable. Used for flushing out the DART before using | ||
225 | * it as uncacheable memory | ||
226 | * | ||
227 | * flush_dcache_phys_range(unsigned long start, unsigned long stop) | ||
228 | * | ||
229 | * flush all bytes from start to stop-1 inclusive | ||
230 | */ | ||
231 | _GLOBAL(flush_dcache_phys_range) | ||
232 | ld r10,PPC64_CACHES@toc(r2) | ||
233 | lwz r7,DCACHEL1LINESIZE(r10) /* Get dcache line size */ | ||
234 | addi r5,r7,-1 | ||
235 | andc r6,r3,r5 /* round low to line bdy */ | ||
236 | subf r8,r6,r4 /* compute length */ | ||
237 | add r8,r8,r5 /* ensure we get enough */ | ||
238 | lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of dcache line size */ | ||
239 | srw. r8,r8,r9 /* compute line count */ | ||
240 | beqlr /* nothing to do? */ | ||
241 | mfmsr r5 /* Disable MMU Data Relocation */ | ||
242 | ori r0,r5,MSR_DR | ||
243 | xori r0,r0,MSR_DR | ||
244 | sync | ||
245 | mtmsr r0 | ||
246 | sync | ||
247 | isync | ||
248 | mtctr r8 | ||
249 | 0: dcbst 0,r6 | ||
250 | add r6,r6,r7 | ||
251 | bdnz 0b | ||
252 | sync | ||
253 | isync | ||
254 | mtmsr r5 /* Re-enable MMU Data Relocation */ | ||
255 | sync | ||
256 | isync | ||
257 | blr | ||
258 | |||
259 | _GLOBAL(flush_inval_dcache_range) | ||
260 | ld r10,PPC64_CACHES@toc(r2) | ||
261 | lwz r7,DCACHEL1LINESIZE(r10) /* Get dcache line size */ | ||
262 | addi r5,r7,-1 | ||
263 | andc r6,r3,r5 /* round low to line bdy */ | ||
264 | subf r8,r6,r4 /* compute length */ | ||
265 | add r8,r8,r5 /* ensure we get enough */ | ||
266 | lwz r9,DCACHEL1LOGLINESIZE(r10)/* Get log-2 of dcache line size */ | ||
267 | srw. r8,r8,r9 /* compute line count */ | ||
268 | beqlr /* nothing to do? */ | ||
269 | sync | ||
270 | isync | ||
271 | mtctr r8 | ||
272 | 0: dcbf 0,r6 | ||
273 | add r6,r6,r7 | ||
274 | bdnz 0b | ||
275 | sync | ||
276 | isync | ||
277 | blr | ||
278 | |||
279 | |||
280 | /* | ||
281 | * Flush a particular page from the data cache to RAM. | ||
282 | * Note: this is necessary because the instruction cache does *not* | ||
283 | * snoop from the data cache. | ||
284 | * | ||
285 | * void __flush_dcache_icache(void *page) | ||
286 | */ | ||
287 | _GLOBAL(__flush_dcache_icache) | ||
288 | /* | ||
289 | * Flush the data cache to memory | ||
290 | * | ||
291 | * Different systems have different cache line sizes | ||
292 | */ | ||
293 | |||
294 | /* Flush the dcache */ | ||
295 | ld r7,PPC64_CACHES@toc(r2) | ||
296 | clrrdi r3,r3,PAGE_SHIFT /* Page align */ | ||
297 | lwz r4,DCACHEL1LINESPERPAGE(r7) /* Get # dcache lines per page */ | ||
298 | lwz r5,DCACHEL1LINESIZE(r7) /* Get dcache line size */ | ||
299 | mr r6,r3 | ||
300 | mtctr r4 | ||
301 | 0: dcbst 0,r6 | ||
302 | add r6,r6,r5 | ||
303 | bdnz 0b | ||
304 | sync | ||
305 | |||
306 | /* Now invalidate the icache */ | ||
307 | |||
308 | lwz r4,ICACHEL1LINESPERPAGE(r7) /* Get # icache lines per page */ | ||
309 | lwz r5,ICACHEL1LINESIZE(r7) /* Get icache line size */ | ||
310 | mtctr r4 | ||
311 | 1: icbi 0,r3 | ||
312 | add r3,r3,r5 | ||
313 | bdnz 1b | ||
314 | isync | ||
315 | blr | ||
316 | |||
317 | /* | ||
318 | * I/O string operations | ||
319 | * | ||
320 | * insb(port, buf, len) | ||
321 | * outsb(port, buf, len) | ||
322 | * insw(port, buf, len) | ||
323 | * outsw(port, buf, len) | ||
324 | * insl(port, buf, len) | ||
325 | * outsl(port, buf, len) | ||
326 | * insw_ns(port, buf, len) | ||
327 | * outsw_ns(port, buf, len) | ||
328 | * insl_ns(port, buf, len) | ||
329 | * outsl_ns(port, buf, len) | ||
330 | * | ||
331 | * The *_ns versions don't do byte-swapping. | ||
332 | */ | ||
333 | _GLOBAL(_insb) | ||
334 | cmpwi 0,r5,0 | ||
335 | mtctr r5 | ||
336 | subi r4,r4,1 | ||
337 | blelr- | ||
338 | 00: lbz r5,0(r3) | ||
339 | eieio | ||
340 | stbu r5,1(r4) | ||
341 | bdnz 00b | ||
342 | twi 0,r5,0 | ||
343 | isync | ||
344 | blr | ||
345 | |||
346 | _GLOBAL(_outsb) | ||
347 | cmpwi 0,r5,0 | ||
348 | mtctr r5 | ||
349 | subi r4,r4,1 | ||
350 | blelr- | ||
351 | 00: lbzu r5,1(r4) | ||
352 | stb r5,0(r3) | ||
353 | bdnz 00b | ||
354 | sync | ||
355 | blr | ||
356 | |||
357 | _GLOBAL(_insw) | ||
358 | cmpwi 0,r5,0 | ||
359 | mtctr r5 | ||
360 | subi r4,r4,2 | ||
361 | blelr- | ||
362 | 00: lhbrx r5,0,r3 | ||
363 | eieio | ||
364 | sthu r5,2(r4) | ||
365 | bdnz 00b | ||
366 | twi 0,r5,0 | ||
367 | isync | ||
368 | blr | ||
369 | |||
370 | _GLOBAL(_outsw) | ||
371 | cmpwi 0,r5,0 | ||
372 | mtctr r5 | ||
373 | subi r4,r4,2 | ||
374 | blelr- | ||
375 | 00: lhzu r5,2(r4) | ||
376 | sthbrx r5,0,r3 | ||
377 | bdnz 00b | ||
378 | sync | ||
379 | blr | ||
380 | |||
381 | _GLOBAL(_insl) | ||
382 | cmpwi 0,r5,0 | ||
383 | mtctr r5 | ||
384 | subi r4,r4,4 | ||
385 | blelr- | ||
386 | 00: lwbrx r5,0,r3 | ||
387 | eieio | ||
388 | stwu r5,4(r4) | ||
389 | bdnz 00b | ||
390 | twi 0,r5,0 | ||
391 | isync | ||
392 | blr | ||
393 | |||
394 | _GLOBAL(_outsl) | ||
395 | cmpwi 0,r5,0 | ||
396 | mtctr r5 | ||
397 | subi r4,r4,4 | ||
398 | blelr- | ||
399 | 00: lwzu r5,4(r4) | ||
400 | stwbrx r5,0,r3 | ||
401 | bdnz 00b | ||
402 | sync | ||
403 | blr | ||
404 | |||
405 | /* _GLOBAL(ide_insw) now in drivers/ide/ide-iops.c */ | ||
406 | _GLOBAL(_insw_ns) | ||
407 | cmpwi 0,r5,0 | ||
408 | mtctr r5 | ||
409 | subi r4,r4,2 | ||
410 | blelr- | ||
411 | 00: lhz r5,0(r3) | ||
412 | eieio | ||
413 | sthu r5,2(r4) | ||
414 | bdnz 00b | ||
415 | twi 0,r5,0 | ||
416 | isync | ||
417 | blr | ||
418 | |||
419 | /* _GLOBAL(ide_outsw) now in drivers/ide/ide-iops.c */ | ||
420 | _GLOBAL(_outsw_ns) | ||
421 | cmpwi 0,r5,0 | ||
422 | mtctr r5 | ||
423 | subi r4,r4,2 | ||
424 | blelr- | ||
425 | 00: lhzu r5,2(r4) | ||
426 | sth r5,0(r3) | ||
427 | bdnz 00b | ||
428 | sync | ||
429 | blr | ||
430 | |||
431 | _GLOBAL(_insl_ns) | ||
432 | cmpwi 0,r5,0 | ||
433 | mtctr r5 | ||
434 | subi r4,r4,4 | ||
435 | blelr- | ||
436 | 00: lwz r5,0(r3) | ||
437 | eieio | ||
438 | stwu r5,4(r4) | ||
439 | bdnz 00b | ||
440 | twi 0,r5,0 | ||
441 | isync | ||
442 | blr | ||
443 | |||
444 | _GLOBAL(_outsl_ns) | ||
445 | cmpwi 0,r5,0 | ||
446 | mtctr r5 | ||
447 | subi r4,r4,4 | ||
448 | blelr- | ||
449 | 00: lwzu r5,4(r4) | ||
450 | stw r5,0(r3) | ||
451 | bdnz 00b | ||
452 | sync | ||
453 | blr | ||
454 | |||
455 | /* | ||
456 | * identify_cpu and calls setup_cpu | ||
457 | * In: r3 = base of the cpu_specs array | ||
458 | * r4 = address of cur_cpu_spec | ||
459 | * r5 = relocation offset | ||
460 | */ | ||
461 | _GLOBAL(identify_cpu) | ||
462 | mfpvr r7 | ||
463 | 1: | ||
464 | lwz r8,CPU_SPEC_PVR_MASK(r3) | ||
465 | and r8,r8,r7 | ||
466 | lwz r9,CPU_SPEC_PVR_VALUE(r3) | ||
467 | cmplw 0,r9,r8 | ||
468 | beq 1f | ||
469 | addi r3,r3,CPU_SPEC_ENTRY_SIZE | ||
470 | b 1b | ||
471 | 1: | ||
472 | add r0,r3,r5 | ||
473 | std r0,0(r4) | ||
474 | ld r4,CPU_SPEC_SETUP(r3) | ||
475 | sub r4,r4,r5 | ||
476 | ld r4,0(r4) | ||
477 | sub r4,r4,r5 | ||
478 | mtctr r4 | ||
479 | /* Calling convention for cpu setup is r3=offset, r4=cur_cpu_spec */ | ||
480 | mr r4,r3 | ||
481 | mr r3,r5 | ||
482 | bctr | ||
483 | |||
484 | /* | ||
485 | * do_cpu_ftr_fixups - goes through the list of CPU feature fixups | ||
486 | * and writes nop's over sections of code that don't apply for this cpu. | ||
487 | * r3 = data offset (not changed) | ||
488 | */ | ||
489 | _GLOBAL(do_cpu_ftr_fixups) | ||
490 | /* Get CPU 0 features */ | ||
491 | LOADADDR(r6,cur_cpu_spec) | ||
492 | sub r6,r6,r3 | ||
493 | ld r4,0(r6) | ||
494 | sub r4,r4,r3 | ||
495 | ld r4,CPU_SPEC_FEATURES(r4) | ||
496 | /* Get the fixup table */ | ||
497 | LOADADDR(r6,__start___ftr_fixup) | ||
498 | sub r6,r6,r3 | ||
499 | LOADADDR(r7,__stop___ftr_fixup) | ||
500 | sub r7,r7,r3 | ||
501 | /* Do the fixup */ | ||
502 | 1: cmpld r6,r7 | ||
503 | bgelr | ||
504 | addi r6,r6,32 | ||
505 | ld r8,-32(r6) /* mask */ | ||
506 | and r8,r8,r4 | ||
507 | ld r9,-24(r6) /* value */ | ||
508 | cmpld r8,r9 | ||
509 | beq 1b | ||
510 | ld r8,-16(r6) /* section begin */ | ||
511 | ld r9,-8(r6) /* section end */ | ||
512 | subf. r9,r8,r9 | ||
513 | beq 1b | ||
514 | /* write nops over the section of code */ | ||
515 | /* todo: if large section, add a branch at the start of it */ | ||
516 | srwi r9,r9,2 | ||
517 | mtctr r9 | ||
518 | sub r8,r8,r3 | ||
519 | lis r0,0x60000000@h /* nop */ | ||
520 | 3: stw r0,0(r8) | ||
521 | andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE@l | ||
522 | beq 2f | ||
523 | dcbst 0,r8 /* suboptimal, but simpler */ | ||
524 | sync | ||
525 | icbi 0,r8 | ||
526 | 2: addi r8,r8,4 | ||
527 | bdnz 3b | ||
528 | sync /* additional sync needed on g4 */ | ||
529 | isync | ||
530 | b 1b | ||
531 | |||
532 | #if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) | ||
533 | /* | ||
534 | * Do an IO access in real mode | ||
535 | */ | ||
536 | _GLOBAL(real_readb) | ||
537 | mfmsr r7 | ||
538 | ori r0,r7,MSR_DR | ||
539 | xori r0,r0,MSR_DR | ||
540 | sync | ||
541 | mtmsrd r0 | ||
542 | sync | ||
543 | isync | ||
544 | mfspr r6,SPRN_HID4 | ||
545 | rldicl r5,r6,32,0 | ||
546 | ori r5,r5,0x100 | ||
547 | rldicl r5,r5,32,0 | ||
548 | sync | ||
549 | mtspr SPRN_HID4,r5 | ||
550 | isync | ||
551 | slbia | ||
552 | isync | ||
553 | lbz r3,0(r3) | ||
554 | sync | ||
555 | mtspr SPRN_HID4,r6 | ||
556 | isync | ||
557 | slbia | ||
558 | isync | ||
559 | mtmsrd r7 | ||
560 | sync | ||
561 | isync | ||
562 | blr | ||
563 | |||
564 | /* | ||
565 | * Do an IO access in real mode | ||
566 | */ | ||
567 | _GLOBAL(real_writeb) | ||
568 | mfmsr r7 | ||
569 | ori r0,r7,MSR_DR | ||
570 | xori r0,r0,MSR_DR | ||
571 | sync | ||
572 | mtmsrd r0 | ||
573 | sync | ||
574 | isync | ||
575 | mfspr r6,SPRN_HID4 | ||
576 | rldicl r5,r6,32,0 | ||
577 | ori r5,r5,0x100 | ||
578 | rldicl r5,r5,32,0 | ||
579 | sync | ||
580 | mtspr SPRN_HID4,r5 | ||
581 | isync | ||
582 | slbia | ||
583 | isync | ||
584 | stb r3,0(r4) | ||
585 | sync | ||
586 | mtspr SPRN_HID4,r6 | ||
587 | isync | ||
588 | slbia | ||
589 | isync | ||
590 | mtmsrd r7 | ||
591 | sync | ||
592 | isync | ||
593 | blr | ||
594 | #endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */ | ||
595 | |||
596 | /* | ||
597 | * SCOM access functions for 970 (FX only for now) | ||
598 | * | ||
599 | * unsigned long scom970_read(unsigned int address); | ||
600 | * void scom970_write(unsigned int address, unsigned long value); | ||
601 | * | ||
602 | * The address passed in is the 24 bits register address. This code | ||
603 | * is 970 specific and will not check the status bits, so you should | ||
604 | * know what you are doing. | ||
605 | */ | ||
606 | _GLOBAL(scom970_read) | ||
607 | /* interrupts off */ | ||
608 | mfmsr r4 | ||
609 | ori r0,r4,MSR_EE | ||
610 | xori r0,r0,MSR_EE | ||
611 | mtmsrd r0,1 | ||
612 | |||
613 | /* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits | ||
614 | * (including parity). On current CPUs they must be 0'd, | ||
615 | * and finally or in RW bit | ||
616 | */ | ||
617 | rlwinm r3,r3,8,0,15 | ||
618 | ori r3,r3,0x8000 | ||
619 | |||
620 | /* do the actual scom read */ | ||
621 | sync | ||
622 | mtspr SPRN_SCOMC,r3 | ||
623 | isync | ||
624 | mfspr r3,SPRN_SCOMD | ||
625 | isync | ||
626 | mfspr r0,SPRN_SCOMC | ||
627 | isync | ||
628 | |||
629 | /* XXX: fixup result on some buggy 970's (ouch ! we lost a bit, bah | ||
630 | * that's the best we can do). Not implemented yet as we don't use | ||
631 | * the scom on any of the bogus CPUs yet, but may have to be done | ||
632 | * ultimately | ||
633 | */ | ||
634 | |||
635 | /* restore interrupts */ | ||
636 | mtmsrd r4,1 | ||
637 | blr | ||
638 | |||
639 | |||
640 | _GLOBAL(scom970_write) | ||
641 | /* interrupts off */ | ||
642 | mfmsr r5 | ||
643 | ori r0,r5,MSR_EE | ||
644 | xori r0,r0,MSR_EE | ||
645 | mtmsrd r0,1 | ||
646 | |||
647 | /* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits | ||
648 | * (including parity). On current CPUs they must be 0'd. | ||
649 | */ | ||
650 | |||
651 | rlwinm r3,r3,8,0,15 | ||
652 | |||
653 | sync | ||
654 | mtspr SPRN_SCOMD,r4 /* write data */ | ||
655 | isync | ||
656 | mtspr SPRN_SCOMC,r3 /* write command */ | ||
657 | isync | ||
658 | mfspr 3,SPRN_SCOMC | ||
659 | isync | ||
660 | |||
661 | /* restore interrupts */ | ||
662 | mtmsrd r5,1 | ||
663 | blr | ||
664 | |||
665 | |||
666 | /* | ||
667 | * Create a kernel thread | ||
668 | * kernel_thread(fn, arg, flags) | ||
669 | */ | ||
670 | _GLOBAL(kernel_thread) | ||
671 | std r29,-24(r1) | ||
672 | std r30,-16(r1) | ||
673 | stdu r1,-STACK_FRAME_OVERHEAD(r1) | ||
674 | mr r29,r3 | ||
675 | mr r30,r4 | ||
676 | ori r3,r5,CLONE_VM /* flags */ | ||
677 | oris r3,r3,(CLONE_UNTRACED>>16) | ||
678 | li r4,0 /* new sp (unused) */ | ||
679 | li r0,__NR_clone | ||
680 | sc | ||
681 | cmpdi 0,r3,0 /* parent or child? */ | ||
682 | bne 1f /* return if parent */ | ||
683 | li r0,0 | ||
684 | stdu r0,-STACK_FRAME_OVERHEAD(r1) | ||
685 | ld r2,8(r29) | ||
686 | ld r29,0(r29) | ||
687 | mtlr r29 /* fn addr in lr */ | ||
688 | mr r3,r30 /* load arg and call fn */ | ||
689 | blrl | ||
690 | li r0,__NR_exit /* exit after child exits */ | ||
691 | li r3,0 | ||
692 | sc | ||
693 | 1: addi r1,r1,STACK_FRAME_OVERHEAD | ||
694 | ld r29,-24(r1) | ||
695 | ld r30,-16(r1) | ||
696 | blr | ||
697 | |||
698 | /* | ||
699 | * disable_kernel_fp() | ||
700 | * Disable the FPU. | ||
701 | */ | ||
702 | _GLOBAL(disable_kernel_fp) | ||
703 | mfmsr r3 | ||
704 | rldicl r0,r3,(63-MSR_FP_LG),1 | ||
705 | rldicl r3,r0,(MSR_FP_LG+1),0 | ||
706 | mtmsrd r3 /* disable use of fpu now */ | ||
707 | isync | ||
708 | blr | ||
709 | |||
710 | #ifdef CONFIG_ALTIVEC | ||
711 | |||
712 | #if 0 /* this has no callers for now */ | ||
713 | /* | ||
714 | * disable_kernel_altivec() | ||
715 | * Disable the VMX. | ||
716 | */ | ||
717 | _GLOBAL(disable_kernel_altivec) | ||
718 | mfmsr r3 | ||
719 | rldicl r0,r3,(63-MSR_VEC_LG),1 | ||
720 | rldicl r3,r0,(MSR_VEC_LG+1),0 | ||
721 | mtmsrd r3 /* disable use of VMX now */ | ||
722 | isync | ||
723 | blr | ||
724 | #endif /* 0 */ | ||
725 | |||
726 | /* | ||
727 | * giveup_altivec(tsk) | ||
728 | * Disable VMX for the task given as the argument, | ||
729 | * and save the vector registers in its thread_struct. | ||
730 | * Enables the VMX for use in the kernel on return. | ||
731 | */ | ||
732 | _GLOBAL(giveup_altivec) | ||
733 | mfmsr r5 | ||
734 | oris r5,r5,MSR_VEC@h | ||
735 | mtmsrd r5 /* enable use of VMX now */ | ||
736 | isync | ||
737 | cmpdi 0,r3,0 | ||
738 | beqlr- /* if no previous owner, done */ | ||
739 | addi r3,r3,THREAD /* want THREAD of task */ | ||
740 | ld r5,PT_REGS(r3) | ||
741 | cmpdi 0,r5,0 | ||
742 | SAVE_32VRS(0,r4,r3) | ||
743 | mfvscr vr0 | ||
744 | li r4,THREAD_VSCR | ||
745 | stvx vr0,r4,r3 | ||
746 | beq 1f | ||
747 | ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
748 | lis r3,MSR_VEC@h | ||
749 | andc r4,r4,r3 /* disable FP for previous task */ | ||
750 | std r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
751 | 1: | ||
752 | #ifndef CONFIG_SMP | ||
753 | li r5,0 | ||
754 | ld r4,last_task_used_altivec@got(r2) | ||
755 | std r5,0(r4) | ||
756 | #endif /* CONFIG_SMP */ | ||
757 | blr | ||
758 | |||
759 | #endif /* CONFIG_ALTIVEC */ | ||
760 | |||
761 | _GLOBAL(__setup_cpu_power3) | ||
762 | blr | ||
763 | |||
764 | _GLOBAL(execve) | ||
765 | li r0,__NR_execve | ||
766 | sc | ||
767 | bnslr | ||
768 | neg r3,r3 | ||
769 | blr | ||
770 | |||
771 | /* kexec_wait(phys_cpu) | ||
772 | * | ||
773 | * wait for the flag to change, indicating this kernel is going away but | ||
774 | * the slave code for the next one is at addresses 0 to 100. | ||
775 | * | ||
776 | * This is used by all slaves. | ||
777 | * | ||
778 | * Physical (hardware) cpu id should be in r3. | ||
779 | */ | ||
780 | _GLOBAL(kexec_wait) | ||
781 | bl 1f | ||
782 | 1: mflr r5 | ||
783 | addi r5,r5,kexec_flag-1b | ||
784 | |||
785 | 99: HMT_LOW | ||
786 | #ifdef CONFIG_KEXEC /* use no memory without kexec */ | ||
787 | lwz r4,0(r5) | ||
788 | cmpwi 0,r4,0 | ||
789 | bnea 0x60 | ||
790 | #endif | ||
791 | b 99b | ||
792 | |||
793 | /* this can be in text because we won't change it until we are | ||
794 | * running in real anyways | ||
795 | */ | ||
796 | kexec_flag: | ||
797 | .long 0 | ||
798 | |||
799 | |||
800 | #ifdef CONFIG_KEXEC | ||
801 | |||
802 | /* kexec_smp_wait(void) | ||
803 | * | ||
804 | * call with interrupts off | ||
805 | * note: this is a terminal routine, it does not save lr | ||
806 | * | ||
807 | * get phys id from paca | ||
808 | * set paca id to -1 to say we got here | ||
809 | * switch to real mode | ||
810 | * join other cpus in kexec_wait(phys_id) | ||
811 | */ | ||
812 | _GLOBAL(kexec_smp_wait) | ||
813 | lhz r3,PACAHWCPUID(r13) | ||
814 | li r4,-1 | ||
815 | sth r4,PACAHWCPUID(r13) /* let others know we left */ | ||
816 | bl real_mode | ||
817 | b .kexec_wait | ||
818 | |||
819 | /* | ||
820 | * switch to real mode (turn mmu off) | ||
821 | * we use the early kernel trick that the hardware ignores bits | ||
822 | * 0 and 1 (big endian) of the effective address in real mode | ||
823 | * | ||
824 | * don't overwrite r3 here, it is live for kexec_wait above. | ||
825 | */ | ||
826 | real_mode: /* assume normal blr return */ | ||
827 | 1: li r9,MSR_RI | ||
828 | li r10,MSR_DR|MSR_IR | ||
829 | mflr r11 /* return address to SRR0 */ | ||
830 | mfmsr r12 | ||
831 | andc r9,r12,r9 | ||
832 | andc r10,r12,r10 | ||
833 | |||
834 | mtmsrd r9,1 | ||
835 | mtspr SPRN_SRR1,r10 | ||
836 | mtspr SPRN_SRR0,r11 | ||
837 | rfid | ||
838 | |||
839 | |||
840 | /* | ||
841 | * kexec_sequence(newstack, start, image, control, clear_all()) | ||
842 | * | ||
843 | * does the grungy work with stack switching and real mode switches | ||
844 | * also does simple calls to other code | ||
845 | */ | ||
846 | |||
847 | _GLOBAL(kexec_sequence) | ||
848 | mflr r0 | ||
849 | std r0,16(r1) | ||
850 | |||
851 | /* switch stacks to newstack -- &kexec_stack.stack */ | ||
852 | stdu r1,THREAD_SIZE-112(r3) | ||
853 | mr r1,r3 | ||
854 | |||
855 | li r0,0 | ||
856 | std r0,16(r1) | ||
857 | |||
858 | /* save regs for local vars on new stack. | ||
859 | * yes, we won't go back, but ... | ||
860 | */ | ||
861 | std r31,-8(r1) | ||
862 | std r30,-16(r1) | ||
863 | std r29,-24(r1) | ||
864 | std r28,-32(r1) | ||
865 | std r27,-40(r1) | ||
866 | std r26,-48(r1) | ||
867 | std r25,-56(r1) | ||
868 | |||
869 | stdu r1,-112-64(r1) | ||
870 | |||
871 | /* save args into preserved regs */ | ||
872 | mr r31,r3 /* newstack (both) */ | ||
873 | mr r30,r4 /* start (real) */ | ||
874 | mr r29,r5 /* image (virt) */ | ||
875 | mr r28,r6 /* control, unused */ | ||
876 | mr r27,r7 /* clear_all() fn desc */ | ||
877 | mr r26,r8 /* spare */ | ||
878 | lhz r25,PACAHWCPUID(r13) /* get our phys cpu from paca */ | ||
879 | |||
880 | /* disable interrupts, we are overwriting kernel data next */ | ||
881 | mfmsr r3 | ||
882 | rlwinm r3,r3,0,17,15 | ||
883 | mtmsrd r3,1 | ||
884 | |||
885 | /* copy dest pages, flush whole dest image */ | ||
886 | mr r3,r29 | ||
887 | bl .kexec_copy_flush /* (image) */ | ||
888 | |||
889 | /* turn off mmu */ | ||
890 | bl real_mode | ||
891 | |||
892 | /* clear out hardware hash page table and tlb */ | ||
893 | ld r5,0(r27) /* deref function descriptor */ | ||
894 | mtctr r5 | ||
895 | bctrl /* ppc_md.hash_clear_all(void); */ | ||
896 | |||
897 | /* | ||
898 | * kexec image calling is: | ||
899 | * the first 0x100 bytes of the entry point are copied to 0 | ||
900 | * | ||
901 | * all slaves branch to slave = 0x60 (absolute) | ||
902 | * slave(phys_cpu_id); | ||
903 | * | ||
904 | * master goes to start = entry point | ||
905 | * start(phys_cpu_id, start, 0); | ||
906 | * | ||
907 | * | ||
908 | * a wrapper is needed to call existing kernels, here is an approximate | ||
909 | * description of one method: | ||
910 | * | ||
911 | * v2: (2.6.10) | ||
912 | * start will be near the boot_block (maybe 0x100 bytes before it?) | ||
913 | * it will have a 0x60, which will b to boot_block, where it will wait | ||
914 | * and 0 will store phys into struct boot-block and load r3 from there, | ||
915 | * copy kernel 0-0x100 and tell slaves to back down to 0x60 again | ||
916 | * | ||
917 | * v1: (2.6.9) | ||
918 | * boot block will have all cpus scanning device tree to see if they | ||
919 | * are the boot cpu ????? | ||
920 | * other device tree differences (prop sizes, va vs pa, etc)... | ||
921 | */ | ||
922 | |||
923 | /* copy 0x100 bytes starting at start to 0 */ | ||
924 | li r3,0 | ||
925 | mr r4,r30 | ||
926 | li r5,0x100 | ||
927 | li r6,0 | ||
928 | bl .copy_and_flush /* (dest, src, copy limit, start offset) */ | ||
929 | 1: /* assume normal blr return */ | ||
930 | |||
931 | /* release other cpus to the new kernel secondary start at 0x60 */ | ||
932 | mflr r5 | ||
933 | li r6,1 | ||
934 | stw r6,kexec_flag-1b(5) | ||
935 | mr r3,r25 # my phys cpu | ||
936 | mr r4,r30 # start, aka phys mem offset | ||
937 | mtlr 4 | ||
938 | li r5,0 | ||
939 | blr /* image->start(physid, image->start, 0); */ | ||
940 | #endif /* CONFIG_KEXEC */ | ||
diff --git a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c deleted file mode 100644 index 84006e26342c..000000000000 --- a/arch/ppc64/kernel/ppc_ksyms.c +++ /dev/null | |||
@@ -1,76 +0,0 @@ | |||
1 | /* | ||
2 | * c 2001 PPC 64 Team, IBM Corp | ||
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 | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | #include <linux/config.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/string.h> | ||
12 | #include <linux/console.h> | ||
13 | #include <net/checksum.h> | ||
14 | |||
15 | #include <asm/processor.h> | ||
16 | #include <asm/uaccess.h> | ||
17 | #include <asm/io.h> | ||
18 | #include <asm/system.h> | ||
19 | #include <asm/hw_irq.h> | ||
20 | #include <asm/abs_addr.h> | ||
21 | #include <asm/cacheflush.h> | ||
22 | |||
23 | EXPORT_SYMBOL(strcpy); | ||
24 | EXPORT_SYMBOL(strncpy); | ||
25 | EXPORT_SYMBOL(strcat); | ||
26 | EXPORT_SYMBOL(strncat); | ||
27 | EXPORT_SYMBOL(strchr); | ||
28 | EXPORT_SYMBOL(strrchr); | ||
29 | EXPORT_SYMBOL(strpbrk); | ||
30 | EXPORT_SYMBOL(strstr); | ||
31 | EXPORT_SYMBOL(strlen); | ||
32 | EXPORT_SYMBOL(strnlen); | ||
33 | EXPORT_SYMBOL(strcmp); | ||
34 | EXPORT_SYMBOL(strncmp); | ||
35 | |||
36 | EXPORT_SYMBOL(csum_partial); | ||
37 | EXPORT_SYMBOL(csum_partial_copy_generic); | ||
38 | EXPORT_SYMBOL(ip_fast_csum); | ||
39 | EXPORT_SYMBOL(csum_tcpudp_magic); | ||
40 | |||
41 | EXPORT_SYMBOL(__copy_tofrom_user); | ||
42 | EXPORT_SYMBOL(__clear_user); | ||
43 | EXPORT_SYMBOL(__strncpy_from_user); | ||
44 | EXPORT_SYMBOL(__strnlen_user); | ||
45 | |||
46 | EXPORT_SYMBOL(reloc_offset); | ||
47 | |||
48 | EXPORT_SYMBOL(_insb); | ||
49 | EXPORT_SYMBOL(_outsb); | ||
50 | EXPORT_SYMBOL(_insw); | ||
51 | EXPORT_SYMBOL(_outsw); | ||
52 | EXPORT_SYMBOL(_insl); | ||
53 | EXPORT_SYMBOL(_outsl); | ||
54 | EXPORT_SYMBOL(_insw_ns); | ||
55 | EXPORT_SYMBOL(_outsw_ns); | ||
56 | EXPORT_SYMBOL(_insl_ns); | ||
57 | EXPORT_SYMBOL(_outsl_ns); | ||
58 | |||
59 | EXPORT_SYMBOL(kernel_thread); | ||
60 | |||
61 | EXPORT_SYMBOL(giveup_fpu); | ||
62 | #ifdef CONFIG_ALTIVEC | ||
63 | EXPORT_SYMBOL(giveup_altivec); | ||
64 | #endif | ||
65 | EXPORT_SYMBOL(__flush_icache_range); | ||
66 | EXPORT_SYMBOL(flush_dcache_range); | ||
67 | |||
68 | EXPORT_SYMBOL(memcpy); | ||
69 | EXPORT_SYMBOL(memset); | ||
70 | EXPORT_SYMBOL(memmove); | ||
71 | EXPORT_SYMBOL(memscan); | ||
72 | EXPORT_SYMBOL(memcmp); | ||
73 | EXPORT_SYMBOL(memchr); | ||
74 | |||
75 | EXPORT_SYMBOL(timer_interrupt); | ||
76 | EXPORT_SYMBOL(console_drivers); | ||
diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c deleted file mode 100644 index fbad2c360784..000000000000 --- a/arch/ppc64/kernel/prom.c +++ /dev/null | |||
@@ -1,1954 +0,0 @@ | |||
1 | /* | ||
2 | * | ||
3 | * | ||
4 | * Procedures for interfacing to Open Firmware. | ||
5 | * | ||
6 | * Paul Mackerras August 1996. | ||
7 | * Copyright (C) 1996 Paul Mackerras. | ||
8 | * | ||
9 | * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. | ||
10 | * {engebret|bergner}@us.ibm.com | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version | ||
15 | * 2 of the License, or (at your option) any later version. | ||
16 | */ | ||
17 | |||
18 | #undef DEBUG | ||
19 | |||
20 | #include <stdarg.h> | ||
21 | #include <linux/config.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/string.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/threads.h> | ||
26 | #include <linux/spinlock.h> | ||
27 | #include <linux/types.h> | ||
28 | #include <linux/pci.h> | ||
29 | #include <linux/stringify.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/initrd.h> | ||
32 | #include <linux/bitops.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/module.h> | ||
35 | |||
36 | #include <asm/prom.h> | ||
37 | #include <asm/rtas.h> | ||
38 | #include <asm/lmb.h> | ||
39 | #include <asm/abs_addr.h> | ||
40 | #include <asm/page.h> | ||
41 | #include <asm/processor.h> | ||
42 | #include <asm/irq.h> | ||
43 | #include <asm/io.h> | ||
44 | #include <asm/smp.h> | ||
45 | #include <asm/system.h> | ||
46 | #include <asm/mmu.h> | ||
47 | #include <asm/pgtable.h> | ||
48 | #include <asm/pci.h> | ||
49 | #include <asm/iommu.h> | ||
50 | #include <asm/btext.h> | ||
51 | #include <asm/sections.h> | ||
52 | #include <asm/machdep.h> | ||
53 | #include <asm/pSeries_reconfig.h> | ||
54 | |||
55 | #ifdef DEBUG | ||
56 | #define DBG(fmt...) udbg_printf(fmt) | ||
57 | #else | ||
58 | #define DBG(fmt...) | ||
59 | #endif | ||
60 | |||
61 | struct pci_reg_property { | ||
62 | struct pci_address addr; | ||
63 | u32 size_hi; | ||
64 | u32 size_lo; | ||
65 | }; | ||
66 | |||
67 | struct isa_reg_property { | ||
68 | u32 space; | ||
69 | u32 address; | ||
70 | u32 size; | ||
71 | }; | ||
72 | |||
73 | |||
74 | typedef int interpret_func(struct device_node *, unsigned long *, | ||
75 | int, int, int); | ||
76 | |||
77 | extern struct rtas_t rtas; | ||
78 | extern struct lmb lmb; | ||
79 | extern unsigned long klimit; | ||
80 | extern unsigned long memory_limit; | ||
81 | |||
82 | static int __initdata dt_root_addr_cells; | ||
83 | static int __initdata dt_root_size_cells; | ||
84 | static int __initdata iommu_is_off; | ||
85 | int __initdata iommu_force_on; | ||
86 | unsigned long tce_alloc_start, tce_alloc_end; | ||
87 | |||
88 | typedef u32 cell_t; | ||
89 | |||
90 | #if 0 | ||
91 | static struct boot_param_header *initial_boot_params __initdata; | ||
92 | #else | ||
93 | struct boot_param_header *initial_boot_params; | ||
94 | #endif | ||
95 | |||
96 | static struct device_node *allnodes = NULL; | ||
97 | |||
98 | /* use when traversing tree through the allnext, child, sibling, | ||
99 | * or parent members of struct device_node. | ||
100 | */ | ||
101 | static DEFINE_RWLOCK(devtree_lock); | ||
102 | |||
103 | /* export that to outside world */ | ||
104 | struct device_node *of_chosen; | ||
105 | |||
106 | /* | ||
107 | * Wrapper for allocating memory for various data that needs to be | ||
108 | * attached to device nodes as they are processed at boot or when | ||
109 | * added to the device tree later (e.g. DLPAR). At boot there is | ||
110 | * already a region reserved so we just increment *mem_start by size; | ||
111 | * otherwise we call kmalloc. | ||
112 | */ | ||
113 | static void * prom_alloc(unsigned long size, unsigned long *mem_start) | ||
114 | { | ||
115 | unsigned long tmp; | ||
116 | |||
117 | if (!mem_start) | ||
118 | return kmalloc(size, GFP_KERNEL); | ||
119 | |||
120 | tmp = *mem_start; | ||
121 | *mem_start += size; | ||
122 | return (void *)tmp; | ||
123 | } | ||
124 | |||
125 | /* | ||
126 | * Find the device_node with a given phandle. | ||
127 | */ | ||
128 | static struct device_node * find_phandle(phandle ph) | ||
129 | { | ||
130 | struct device_node *np; | ||
131 | |||
132 | for (np = allnodes; np != 0; np = np->allnext) | ||
133 | if (np->linux_phandle == ph) | ||
134 | return np; | ||
135 | return NULL; | ||
136 | } | ||
137 | |||
138 | /* | ||
139 | * Find the interrupt parent of a node. | ||
140 | */ | ||
141 | static struct device_node * __devinit intr_parent(struct device_node *p) | ||
142 | { | ||
143 | phandle *parp; | ||
144 | |||
145 | parp = (phandle *) get_property(p, "interrupt-parent", NULL); | ||
146 | if (parp == NULL) | ||
147 | return p->parent; | ||
148 | return find_phandle(*parp); | ||
149 | } | ||
150 | |||
151 | /* | ||
152 | * Find out the size of each entry of the interrupts property | ||
153 | * for a node. | ||
154 | */ | ||
155 | int __devinit prom_n_intr_cells(struct device_node *np) | ||
156 | { | ||
157 | struct device_node *p; | ||
158 | unsigned int *icp; | ||
159 | |||
160 | for (p = np; (p = intr_parent(p)) != NULL; ) { | ||
161 | icp = (unsigned int *) | ||
162 | get_property(p, "#interrupt-cells", NULL); | ||
163 | if (icp != NULL) | ||
164 | return *icp; | ||
165 | if (get_property(p, "interrupt-controller", NULL) != NULL | ||
166 | || get_property(p, "interrupt-map", NULL) != NULL) { | ||
167 | printk("oops, node %s doesn't have #interrupt-cells\n", | ||
168 | p->full_name); | ||
169 | return 1; | ||
170 | } | ||
171 | } | ||
172 | #ifdef DEBUG_IRQ | ||
173 | printk("prom_n_intr_cells failed for %s\n", np->full_name); | ||
174 | #endif | ||
175 | return 1; | ||
176 | } | ||
177 | |||
178 | /* | ||
179 | * Map an interrupt from a device up to the platform interrupt | ||
180 | * descriptor. | ||
181 | */ | ||
182 | static int __devinit map_interrupt(unsigned int **irq, struct device_node **ictrler, | ||
183 | struct device_node *np, unsigned int *ints, | ||
184 | int nintrc) | ||
185 | { | ||
186 | struct device_node *p, *ipar; | ||
187 | unsigned int *imap, *imask, *ip; | ||
188 | int i, imaplen, match; | ||
189 | int newintrc = 0, newaddrc = 0; | ||
190 | unsigned int *reg; | ||
191 | int naddrc; | ||
192 | |||
193 | reg = (unsigned int *) get_property(np, "reg", NULL); | ||
194 | naddrc = prom_n_addr_cells(np); | ||
195 | p = intr_parent(np); | ||
196 | while (p != NULL) { | ||
197 | if (get_property(p, "interrupt-controller", NULL) != NULL) | ||
198 | /* this node is an interrupt controller, stop here */ | ||
199 | break; | ||
200 | imap = (unsigned int *) | ||
201 | get_property(p, "interrupt-map", &imaplen); | ||
202 | if (imap == NULL) { | ||
203 | p = intr_parent(p); | ||
204 | continue; | ||
205 | } | ||
206 | imask = (unsigned int *) | ||
207 | get_property(p, "interrupt-map-mask", NULL); | ||
208 | if (imask == NULL) { | ||
209 | printk("oops, %s has interrupt-map but no mask\n", | ||
210 | p->full_name); | ||
211 | return 0; | ||
212 | } | ||
213 | imaplen /= sizeof(unsigned int); | ||
214 | match = 0; | ||
215 | ipar = NULL; | ||
216 | while (imaplen > 0 && !match) { | ||
217 | /* check the child-interrupt field */ | ||
218 | match = 1; | ||
219 | for (i = 0; i < naddrc && match; ++i) | ||
220 | match = ((reg[i] ^ imap[i]) & imask[i]) == 0; | ||
221 | for (; i < naddrc + nintrc && match; ++i) | ||
222 | match = ((ints[i-naddrc] ^ imap[i]) & imask[i]) == 0; | ||
223 | imap += naddrc + nintrc; | ||
224 | imaplen -= naddrc + nintrc; | ||
225 | /* grab the interrupt parent */ | ||
226 | ipar = find_phandle((phandle) *imap++); | ||
227 | --imaplen; | ||
228 | if (ipar == NULL) { | ||
229 | printk("oops, no int parent %x in map of %s\n", | ||
230 | imap[-1], p->full_name); | ||
231 | return 0; | ||
232 | } | ||
233 | /* find the parent's # addr and intr cells */ | ||
234 | ip = (unsigned int *) | ||
235 | get_property(ipar, "#interrupt-cells", NULL); | ||
236 | if (ip == NULL) { | ||
237 | printk("oops, no #interrupt-cells on %s\n", | ||
238 | ipar->full_name); | ||
239 | return 0; | ||
240 | } | ||
241 | newintrc = *ip; | ||
242 | ip = (unsigned int *) | ||
243 | get_property(ipar, "#address-cells", NULL); | ||
244 | newaddrc = (ip == NULL)? 0: *ip; | ||
245 | imap += newaddrc + newintrc; | ||
246 | imaplen -= newaddrc + newintrc; | ||
247 | } | ||
248 | if (imaplen < 0) { | ||
249 | printk("oops, error decoding int-map on %s, len=%d\n", | ||
250 | p->full_name, imaplen); | ||
251 | return 0; | ||
252 | } | ||
253 | if (!match) { | ||
254 | #ifdef DEBUG_IRQ | ||
255 | printk("oops, no match in %s int-map for %s\n", | ||
256 | p->full_name, np->full_name); | ||
257 | #endif | ||
258 | return 0; | ||
259 | } | ||
260 | p = ipar; | ||
261 | naddrc = newaddrc; | ||
262 | nintrc = newintrc; | ||
263 | ints = imap - nintrc; | ||
264 | reg = ints - naddrc; | ||
265 | } | ||
266 | if (p == NULL) { | ||
267 | #ifdef DEBUG_IRQ | ||
268 | printk("hmmm, int tree for %s doesn't have ctrler\n", | ||
269 | np->full_name); | ||
270 | #endif | ||
271 | return 0; | ||
272 | } | ||
273 | *irq = ints; | ||
274 | *ictrler = p; | ||
275 | return nintrc; | ||
276 | } | ||
277 | |||
278 | static int __devinit finish_node_interrupts(struct device_node *np, | ||
279 | unsigned long *mem_start, | ||
280 | int measure_only) | ||
281 | { | ||
282 | unsigned int *ints; | ||
283 | int intlen, intrcells, intrcount; | ||
284 | int i, j, n; | ||
285 | unsigned int *irq, virq; | ||
286 | struct device_node *ic; | ||
287 | |||
288 | ints = (unsigned int *) get_property(np, "interrupts", &intlen); | ||
289 | if (ints == NULL) | ||
290 | return 0; | ||
291 | intrcells = prom_n_intr_cells(np); | ||
292 | intlen /= intrcells * sizeof(unsigned int); | ||
293 | |||
294 | np->intrs = prom_alloc(intlen * sizeof(*(np->intrs)), mem_start); | ||
295 | if (!np->intrs) | ||
296 | return -ENOMEM; | ||
297 | |||
298 | if (measure_only) | ||
299 | return 0; | ||
300 | |||
301 | intrcount = 0; | ||
302 | for (i = 0; i < intlen; ++i, ints += intrcells) { | ||
303 | n = map_interrupt(&irq, &ic, np, ints, intrcells); | ||
304 | if (n <= 0) | ||
305 | continue; | ||
306 | |||
307 | /* don't map IRQ numbers under a cascaded 8259 controller */ | ||
308 | if (ic && device_is_compatible(ic, "chrp,iic")) { | ||
309 | np->intrs[intrcount].line = irq[0]; | ||
310 | } else { | ||
311 | virq = virt_irq_create_mapping(irq[0]); | ||
312 | if (virq == NO_IRQ) { | ||
313 | printk(KERN_CRIT "Could not allocate interrupt" | ||
314 | " number for %s\n", np->full_name); | ||
315 | continue; | ||
316 | } | ||
317 | np->intrs[intrcount].line = irq_offset_up(virq); | ||
318 | } | ||
319 | |||
320 | /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ | ||
321 | if (_machine == PLATFORM_POWERMAC && ic && ic->parent) { | ||
322 | char *name = get_property(ic->parent, "name", NULL); | ||
323 | if (name && !strcmp(name, "u3")) | ||
324 | np->intrs[intrcount].line += 128; | ||
325 | else if (!(name && !strcmp(name, "mac-io"))) | ||
326 | /* ignore other cascaded controllers, such as | ||
327 | the k2-sata-root */ | ||
328 | break; | ||
329 | } | ||
330 | np->intrs[intrcount].sense = 1; | ||
331 | if (n > 1) | ||
332 | np->intrs[intrcount].sense = irq[1]; | ||
333 | if (n > 2) { | ||
334 | printk("hmmm, got %d intr cells for %s:", n, | ||
335 | np->full_name); | ||
336 | for (j = 0; j < n; ++j) | ||
337 | printk(" %d", irq[j]); | ||
338 | printk("\n"); | ||
339 | } | ||
340 | ++intrcount; | ||
341 | } | ||
342 | np->n_intrs = intrcount; | ||
343 | |||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | static int __devinit interpret_pci_props(struct device_node *np, | ||
348 | unsigned long *mem_start, | ||
349 | int naddrc, int nsizec, | ||
350 | int measure_only) | ||
351 | { | ||
352 | struct address_range *adr; | ||
353 | struct pci_reg_property *pci_addrs; | ||
354 | int i, l, n_addrs; | ||
355 | |||
356 | pci_addrs = (struct pci_reg_property *) | ||
357 | get_property(np, "assigned-addresses", &l); | ||
358 | if (!pci_addrs) | ||
359 | return 0; | ||
360 | |||
361 | n_addrs = l / sizeof(*pci_addrs); | ||
362 | |||
363 | adr = prom_alloc(n_addrs * sizeof(*adr), mem_start); | ||
364 | if (!adr) | ||
365 | return -ENOMEM; | ||
366 | |||
367 | if (measure_only) | ||
368 | return 0; | ||
369 | |||
370 | np->addrs = adr; | ||
371 | np->n_addrs = n_addrs; | ||
372 | |||
373 | for (i = 0; i < n_addrs; i++) { | ||
374 | adr[i].space = pci_addrs[i].addr.a_hi; | ||
375 | adr[i].address = pci_addrs[i].addr.a_lo | | ||
376 | ((u64)pci_addrs[i].addr.a_mid << 32); | ||
377 | adr[i].size = pci_addrs[i].size_lo; | ||
378 | } | ||
379 | |||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | static int __init interpret_dbdma_props(struct device_node *np, | ||
384 | unsigned long *mem_start, | ||
385 | int naddrc, int nsizec, | ||
386 | int measure_only) | ||
387 | { | ||
388 | struct reg_property32 *rp; | ||
389 | struct address_range *adr; | ||
390 | unsigned long base_address; | ||
391 | int i, l; | ||
392 | struct device_node *db; | ||
393 | |||
394 | base_address = 0; | ||
395 | if (!measure_only) { | ||
396 | for (db = np->parent; db != NULL; db = db->parent) { | ||
397 | if (!strcmp(db->type, "dbdma") && db->n_addrs != 0) { | ||
398 | base_address = db->addrs[0].address; | ||
399 | break; | ||
400 | } | ||
401 | } | ||
402 | } | ||
403 | |||
404 | rp = (struct reg_property32 *) get_property(np, "reg", &l); | ||
405 | if (rp != 0 && l >= sizeof(struct reg_property32)) { | ||
406 | i = 0; | ||
407 | adr = (struct address_range *) (*mem_start); | ||
408 | while ((l -= sizeof(struct reg_property32)) >= 0) { | ||
409 | if (!measure_only) { | ||
410 | adr[i].space = 2; | ||
411 | adr[i].address = rp[i].address + base_address; | ||
412 | adr[i].size = rp[i].size; | ||
413 | } | ||
414 | ++i; | ||
415 | } | ||
416 | np->addrs = adr; | ||
417 | np->n_addrs = i; | ||
418 | (*mem_start) += i * sizeof(struct address_range); | ||
419 | } | ||
420 | |||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | static int __init interpret_macio_props(struct device_node *np, | ||
425 | unsigned long *mem_start, | ||
426 | int naddrc, int nsizec, | ||
427 | int measure_only) | ||
428 | { | ||
429 | struct reg_property32 *rp; | ||
430 | struct address_range *adr; | ||
431 | unsigned long base_address; | ||
432 | int i, l; | ||
433 | struct device_node *db; | ||
434 | |||
435 | base_address = 0; | ||
436 | if (!measure_only) { | ||
437 | for (db = np->parent; db != NULL; db = db->parent) { | ||
438 | if (!strcmp(db->type, "mac-io") && db->n_addrs != 0) { | ||
439 | base_address = db->addrs[0].address; | ||
440 | break; | ||
441 | } | ||
442 | } | ||
443 | } | ||
444 | |||
445 | rp = (struct reg_property32 *) get_property(np, "reg", &l); | ||
446 | if (rp != 0 && l >= sizeof(struct reg_property32)) { | ||
447 | i = 0; | ||
448 | adr = (struct address_range *) (*mem_start); | ||
449 | while ((l -= sizeof(struct reg_property32)) >= 0) { | ||
450 | if (!measure_only) { | ||
451 | adr[i].space = 2; | ||
452 | adr[i].address = rp[i].address + base_address; | ||
453 | adr[i].size = rp[i].size; | ||
454 | } | ||
455 | ++i; | ||
456 | } | ||
457 | np->addrs = adr; | ||
458 | np->n_addrs = i; | ||
459 | (*mem_start) += i * sizeof(struct address_range); | ||
460 | } | ||
461 | |||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | static int __init interpret_isa_props(struct device_node *np, | ||
466 | unsigned long *mem_start, | ||
467 | int naddrc, int nsizec, | ||
468 | int measure_only) | ||
469 | { | ||
470 | struct isa_reg_property *rp; | ||
471 | struct address_range *adr; | ||
472 | int i, l; | ||
473 | |||
474 | rp = (struct isa_reg_property *) get_property(np, "reg", &l); | ||
475 | if (rp != 0 && l >= sizeof(struct isa_reg_property)) { | ||
476 | i = 0; | ||
477 | adr = (struct address_range *) (*mem_start); | ||
478 | while ((l -= sizeof(struct isa_reg_property)) >= 0) { | ||
479 | if (!measure_only) { | ||
480 | adr[i].space = rp[i].space; | ||
481 | adr[i].address = rp[i].address; | ||
482 | adr[i].size = rp[i].size; | ||
483 | } | ||
484 | ++i; | ||
485 | } | ||
486 | np->addrs = adr; | ||
487 | np->n_addrs = i; | ||
488 | (*mem_start) += i * sizeof(struct address_range); | ||
489 | } | ||
490 | |||
491 | return 0; | ||
492 | } | ||
493 | |||
494 | static int __init interpret_root_props(struct device_node *np, | ||
495 | unsigned long *mem_start, | ||
496 | int naddrc, int nsizec, | ||
497 | int measure_only) | ||
498 | { | ||
499 | struct address_range *adr; | ||
500 | int i, l; | ||
501 | unsigned int *rp; | ||
502 | int rpsize = (naddrc + nsizec) * sizeof(unsigned int); | ||
503 | |||
504 | rp = (unsigned int *) get_property(np, "reg", &l); | ||
505 | if (rp != 0 && l >= rpsize) { | ||
506 | i = 0; | ||
507 | adr = (struct address_range *) (*mem_start); | ||
508 | while ((l -= rpsize) >= 0) { | ||
509 | if (!measure_only) { | ||
510 | adr[i].space = 0; | ||
511 | adr[i].address = rp[naddrc - 1]; | ||
512 | adr[i].size = rp[naddrc + nsizec - 1]; | ||
513 | } | ||
514 | ++i; | ||
515 | rp += naddrc + nsizec; | ||
516 | } | ||
517 | np->addrs = adr; | ||
518 | np->n_addrs = i; | ||
519 | (*mem_start) += i * sizeof(struct address_range); | ||
520 | } | ||
521 | |||
522 | return 0; | ||
523 | } | ||
524 | |||
525 | static int __devinit finish_node(struct device_node *np, | ||
526 | unsigned long *mem_start, | ||
527 | interpret_func *ifunc, | ||
528 | int naddrc, int nsizec, | ||
529 | int measure_only) | ||
530 | { | ||
531 | struct device_node *child; | ||
532 | int *ip, rc = 0; | ||
533 | |||
534 | /* get the device addresses and interrupts */ | ||
535 | if (ifunc != NULL) | ||
536 | rc = ifunc(np, mem_start, naddrc, nsizec, measure_only); | ||
537 | if (rc) | ||
538 | goto out; | ||
539 | |||
540 | rc = finish_node_interrupts(np, mem_start, measure_only); | ||
541 | if (rc) | ||
542 | goto out; | ||
543 | |||
544 | /* Look for #address-cells and #size-cells properties. */ | ||
545 | ip = (int *) get_property(np, "#address-cells", NULL); | ||
546 | if (ip != NULL) | ||
547 | naddrc = *ip; | ||
548 | ip = (int *) get_property(np, "#size-cells", NULL); | ||
549 | if (ip != NULL) | ||
550 | nsizec = *ip; | ||
551 | |||
552 | if (!strcmp(np->name, "device-tree") || np->parent == NULL) | ||
553 | ifunc = interpret_root_props; | ||
554 | else if (np->type == 0) | ||
555 | ifunc = NULL; | ||
556 | else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci")) | ||
557 | ifunc = interpret_pci_props; | ||
558 | else if (!strcmp(np->type, "dbdma")) | ||
559 | ifunc = interpret_dbdma_props; | ||
560 | else if (!strcmp(np->type, "mac-io") || ifunc == interpret_macio_props) | ||
561 | ifunc = interpret_macio_props; | ||
562 | else if (!strcmp(np->type, "isa")) | ||
563 | ifunc = interpret_isa_props; | ||
564 | else if (!strcmp(np->name, "uni-n") || !strcmp(np->name, "u3")) | ||
565 | ifunc = interpret_root_props; | ||
566 | else if (!((ifunc == interpret_dbdma_props | ||
567 | || ifunc == interpret_macio_props) | ||
568 | && (!strcmp(np->type, "escc") | ||
569 | || !strcmp(np->type, "media-bay")))) | ||
570 | ifunc = NULL; | ||
571 | |||
572 | for (child = np->child; child != NULL; child = child->sibling) { | ||
573 | rc = finish_node(child, mem_start, ifunc, | ||
574 | naddrc, nsizec, measure_only); | ||
575 | if (rc) | ||
576 | goto out; | ||
577 | } | ||
578 | out: | ||
579 | return rc; | ||
580 | } | ||
581 | |||
582 | /** | ||
583 | * finish_device_tree is called once things are running normally | ||
584 | * (i.e. with text and data mapped to the address they were linked at). | ||
585 | * It traverses the device tree and fills in some of the additional, | ||
586 | * fields in each node like {n_}addrs and {n_}intrs, the virt interrupt | ||
587 | * mapping is also initialized at this point. | ||
588 | */ | ||
589 | void __init finish_device_tree(void) | ||
590 | { | ||
591 | unsigned long start, end, size = 0; | ||
592 | |||
593 | DBG(" -> finish_device_tree\n"); | ||
594 | |||
595 | if (ppc64_interrupt_controller == IC_INVALID) { | ||
596 | DBG("failed to configure interrupt controller type\n"); | ||
597 | panic("failed to configure interrupt controller type\n"); | ||
598 | } | ||
599 | |||
600 | /* Initialize virtual IRQ map */ | ||
601 | virt_irq_init(); | ||
602 | |||
603 | /* | ||
604 | * Finish device-tree (pre-parsing some properties etc...) | ||
605 | * We do this in 2 passes. One with "measure_only" set, which | ||
606 | * will only measure the amount of memory needed, then we can | ||
607 | * allocate that memory, and call finish_node again. However, | ||
608 | * we must be careful as most routines will fail nowadays when | ||
609 | * prom_alloc() returns 0, so we must make sure our first pass | ||
610 | * doesn't start at 0. We pre-initialize size to 16 for that | ||
611 | * reason and then remove those additional 16 bytes | ||
612 | */ | ||
613 | size = 16; | ||
614 | finish_node(allnodes, &size, NULL, 0, 0, 1); | ||
615 | size -= 16; | ||
616 | end = start = (unsigned long)abs_to_virt(lmb_alloc(size, 128)); | ||
617 | finish_node(allnodes, &end, NULL, 0, 0, 0); | ||
618 | BUG_ON(end != start + size); | ||
619 | |||
620 | DBG(" <- finish_device_tree\n"); | ||
621 | } | ||
622 | |||
623 | #ifdef DEBUG | ||
624 | #define printk udbg_printf | ||
625 | #endif | ||
626 | |||
627 | static inline char *find_flat_dt_string(u32 offset) | ||
628 | { | ||
629 | return ((char *)initial_boot_params) + | ||
630 | initial_boot_params->off_dt_strings + offset; | ||
631 | } | ||
632 | |||
633 | /** | ||
634 | * This function is used to scan the flattened device-tree, it is | ||
635 | * used to extract the memory informations at boot before we can | ||
636 | * unflatten the tree | ||
637 | */ | ||
638 | int __init of_scan_flat_dt(int (*it)(unsigned long node, | ||
639 | const char *uname, int depth, | ||
640 | void *data), | ||
641 | void *data) | ||
642 | { | ||
643 | unsigned long p = ((unsigned long)initial_boot_params) + | ||
644 | initial_boot_params->off_dt_struct; | ||
645 | int rc = 0; | ||
646 | int depth = -1; | ||
647 | |||
648 | do { | ||
649 | u32 tag = *((u32 *)p); | ||
650 | char *pathp; | ||
651 | |||
652 | p += 4; | ||
653 | if (tag == OF_DT_END_NODE) { | ||
654 | depth --; | ||
655 | continue; | ||
656 | } | ||
657 | if (tag == OF_DT_NOP) | ||
658 | continue; | ||
659 | if (tag == OF_DT_END) | ||
660 | break; | ||
661 | if (tag == OF_DT_PROP) { | ||
662 | u32 sz = *((u32 *)p); | ||
663 | p += 8; | ||
664 | if (initial_boot_params->version < 0x10) | ||
665 | p = _ALIGN(p, sz >= 8 ? 8 : 4); | ||
666 | p += sz; | ||
667 | p = _ALIGN(p, 4); | ||
668 | continue; | ||
669 | } | ||
670 | if (tag != OF_DT_BEGIN_NODE) { | ||
671 | printk(KERN_WARNING "Invalid tag %x scanning flattened" | ||
672 | " device tree !\n", tag); | ||
673 | return -EINVAL; | ||
674 | } | ||
675 | depth++; | ||
676 | pathp = (char *)p; | ||
677 | p = _ALIGN(p + strlen(pathp) + 1, 4); | ||
678 | if ((*pathp) == '/') { | ||
679 | char *lp, *np; | ||
680 | for (lp = NULL, np = pathp; *np; np++) | ||
681 | if ((*np) == '/') | ||
682 | lp = np+1; | ||
683 | if (lp != NULL) | ||
684 | pathp = lp; | ||
685 | } | ||
686 | rc = it(p, pathp, depth, data); | ||
687 | if (rc != 0) | ||
688 | break; | ||
689 | } while(1); | ||
690 | |||
691 | return rc; | ||
692 | } | ||
693 | |||
694 | /** | ||
695 | * This function can be used within scan_flattened_dt callback to get | ||
696 | * access to properties | ||
697 | */ | ||
698 | void* __init of_get_flat_dt_prop(unsigned long node, const char *name, | ||
699 | unsigned long *size) | ||
700 | { | ||
701 | unsigned long p = node; | ||
702 | |||
703 | do { | ||
704 | u32 tag = *((u32 *)p); | ||
705 | u32 sz, noff; | ||
706 | const char *nstr; | ||
707 | |||
708 | p += 4; | ||
709 | if (tag == OF_DT_NOP) | ||
710 | continue; | ||
711 | if (tag != OF_DT_PROP) | ||
712 | return NULL; | ||
713 | |||
714 | sz = *((u32 *)p); | ||
715 | noff = *((u32 *)(p + 4)); | ||
716 | p += 8; | ||
717 | if (initial_boot_params->version < 0x10) | ||
718 | p = _ALIGN(p, sz >= 8 ? 8 : 4); | ||
719 | |||
720 | nstr = find_flat_dt_string(noff); | ||
721 | if (nstr == NULL) { | ||
722 | printk(KERN_WARNING "Can't find property index" | ||
723 | " name !\n"); | ||
724 | return NULL; | ||
725 | } | ||
726 | if (strcmp(name, nstr) == 0) { | ||
727 | if (size) | ||
728 | *size = sz; | ||
729 | return (void *)p; | ||
730 | } | ||
731 | p += sz; | ||
732 | p = _ALIGN(p, 4); | ||
733 | } while(1); | ||
734 | } | ||
735 | |||
736 | static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, | ||
737 | unsigned long align) | ||
738 | { | ||
739 | void *res; | ||
740 | |||
741 | *mem = _ALIGN(*mem, align); | ||
742 | res = (void *)*mem; | ||
743 | *mem += size; | ||
744 | |||
745 | return res; | ||
746 | } | ||
747 | |||
748 | static unsigned long __init unflatten_dt_node(unsigned long mem, | ||
749 | unsigned long *p, | ||
750 | struct device_node *dad, | ||
751 | struct device_node ***allnextpp, | ||
752 | unsigned long fpsize) | ||
753 | { | ||
754 | struct device_node *np; | ||
755 | struct property *pp, **prev_pp = NULL; | ||
756 | char *pathp; | ||
757 | u32 tag; | ||
758 | unsigned int l, allocl; | ||
759 | int has_name = 0; | ||
760 | int new_format = 0; | ||
761 | |||
762 | tag = *((u32 *)(*p)); | ||
763 | if (tag != OF_DT_BEGIN_NODE) { | ||
764 | printk("Weird tag at start of node: %x\n", tag); | ||
765 | return mem; | ||
766 | } | ||
767 | *p += 4; | ||
768 | pathp = (char *)*p; | ||
769 | l = allocl = strlen(pathp) + 1; | ||
770 | *p = _ALIGN(*p + l, 4); | ||
771 | |||
772 | /* version 0x10 has a more compact unit name here instead of the full | ||
773 | * path. we accumulate the full path size using "fpsize", we'll rebuild | ||
774 | * it later. We detect this because the first character of the name is | ||
775 | * not '/'. | ||
776 | */ | ||
777 | if ((*pathp) != '/') { | ||
778 | new_format = 1; | ||
779 | if (fpsize == 0) { | ||
780 | /* root node: special case. fpsize accounts for path | ||
781 | * plus terminating zero. root node only has '/', so | ||
782 | * fpsize should be 2, but we want to avoid the first | ||
783 | * level nodes to have two '/' so we use fpsize 1 here | ||
784 | */ | ||
785 | fpsize = 1; | ||
786 | allocl = 2; | ||
787 | } else { | ||
788 | /* account for '/' and path size minus terminal 0 | ||
789 | * already in 'l' | ||
790 | */ | ||
791 | fpsize += l; | ||
792 | allocl = fpsize; | ||
793 | } | ||
794 | } | ||
795 | |||
796 | |||
797 | np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl, | ||
798 | __alignof__(struct device_node)); | ||
799 | if (allnextpp) { | ||
800 | memset(np, 0, sizeof(*np)); | ||
801 | np->full_name = ((char*)np) + sizeof(struct device_node); | ||
802 | if (new_format) { | ||
803 | char *p = np->full_name; | ||
804 | /* rebuild full path for new format */ | ||
805 | if (dad && dad->parent) { | ||
806 | strcpy(p, dad->full_name); | ||
807 | #ifdef DEBUG | ||
808 | if ((strlen(p) + l + 1) != allocl) { | ||
809 | DBG("%s: p: %d, l: %d, a: %d\n", | ||
810 | pathp, strlen(p), l, allocl); | ||
811 | } | ||
812 | #endif | ||
813 | p += strlen(p); | ||
814 | } | ||
815 | *(p++) = '/'; | ||
816 | memcpy(p, pathp, l); | ||
817 | } else | ||
818 | memcpy(np->full_name, pathp, l); | ||
819 | prev_pp = &np->properties; | ||
820 | **allnextpp = np; | ||
821 | *allnextpp = &np->allnext; | ||
822 | if (dad != NULL) { | ||
823 | np->parent = dad; | ||
824 | /* we temporarily use the next field as `last_child'*/ | ||
825 | if (dad->next == 0) | ||
826 | dad->child = np; | ||
827 | else | ||
828 | dad->next->sibling = np; | ||
829 | dad->next = np; | ||
830 | } | ||
831 | kref_init(&np->kref); | ||
832 | } | ||
833 | while(1) { | ||
834 | u32 sz, noff; | ||
835 | char *pname; | ||
836 | |||
837 | tag = *((u32 *)(*p)); | ||
838 | if (tag == OF_DT_NOP) { | ||
839 | *p += 4; | ||
840 | continue; | ||
841 | } | ||
842 | if (tag != OF_DT_PROP) | ||
843 | break; | ||
844 | *p += 4; | ||
845 | sz = *((u32 *)(*p)); | ||
846 | noff = *((u32 *)((*p) + 4)); | ||
847 | *p += 8; | ||
848 | if (initial_boot_params->version < 0x10) | ||
849 | *p = _ALIGN(*p, sz >= 8 ? 8 : 4); | ||
850 | |||
851 | pname = find_flat_dt_string(noff); | ||
852 | if (pname == NULL) { | ||
853 | printk("Can't find property name in list !\n"); | ||
854 | break; | ||
855 | } | ||
856 | if (strcmp(pname, "name") == 0) | ||
857 | has_name = 1; | ||
858 | l = strlen(pname) + 1; | ||
859 | pp = unflatten_dt_alloc(&mem, sizeof(struct property), | ||
860 | __alignof__(struct property)); | ||
861 | if (allnextpp) { | ||
862 | if (strcmp(pname, "linux,phandle") == 0) { | ||
863 | np->node = *((u32 *)*p); | ||
864 | if (np->linux_phandle == 0) | ||
865 | np->linux_phandle = np->node; | ||
866 | } | ||
867 | if (strcmp(pname, "ibm,phandle") == 0) | ||
868 | np->linux_phandle = *((u32 *)*p); | ||
869 | pp->name = pname; | ||
870 | pp->length = sz; | ||
871 | pp->value = (void *)*p; | ||
872 | *prev_pp = pp; | ||
873 | prev_pp = &pp->next; | ||
874 | } | ||
875 | *p = _ALIGN((*p) + sz, 4); | ||
876 | } | ||
877 | /* with version 0x10 we may not have the name property, recreate | ||
878 | * it here from the unit name if absent | ||
879 | */ | ||
880 | if (!has_name) { | ||
881 | char *p = pathp, *ps = pathp, *pa = NULL; | ||
882 | int sz; | ||
883 | |||
884 | while (*p) { | ||
885 | if ((*p) == '@') | ||
886 | pa = p; | ||
887 | if ((*p) == '/') | ||
888 | ps = p + 1; | ||
889 | p++; | ||
890 | } | ||
891 | if (pa < ps) | ||
892 | pa = p; | ||
893 | sz = (pa - ps) + 1; | ||
894 | pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz, | ||
895 | __alignof__(struct property)); | ||
896 | if (allnextpp) { | ||
897 | pp->name = "name"; | ||
898 | pp->length = sz; | ||
899 | pp->value = (unsigned char *)(pp + 1); | ||
900 | *prev_pp = pp; | ||
901 | prev_pp = &pp->next; | ||
902 | memcpy(pp->value, ps, sz - 1); | ||
903 | ((char *)pp->value)[sz - 1] = 0; | ||
904 | DBG("fixed up name for %s -> %s\n", pathp, pp->value); | ||
905 | } | ||
906 | } | ||
907 | if (allnextpp) { | ||
908 | *prev_pp = NULL; | ||
909 | np->name = get_property(np, "name", NULL); | ||
910 | np->type = get_property(np, "device_type", NULL); | ||
911 | |||
912 | if (!np->name) | ||
913 | np->name = "<NULL>"; | ||
914 | if (!np->type) | ||
915 | np->type = "<NULL>"; | ||
916 | } | ||
917 | while (tag == OF_DT_BEGIN_NODE) { | ||
918 | mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize); | ||
919 | tag = *((u32 *)(*p)); | ||
920 | } | ||
921 | if (tag != OF_DT_END_NODE) { | ||
922 | printk("Weird tag at end of node: %x\n", tag); | ||
923 | return mem; | ||
924 | } | ||
925 | *p += 4; | ||
926 | return mem; | ||
927 | } | ||
928 | |||
929 | |||
930 | /** | ||
931 | * unflattens the device-tree passed by the firmware, creating the | ||
932 | * tree of struct device_node. It also fills the "name" and "type" | ||
933 | * pointers of the nodes so the normal device-tree walking functions | ||
934 | * can be used (this used to be done by finish_device_tree) | ||
935 | */ | ||
936 | void __init unflatten_device_tree(void) | ||
937 | { | ||
938 | unsigned long start, mem, size; | ||
939 | struct device_node **allnextp = &allnodes; | ||
940 | char *p = NULL; | ||
941 | int l = 0; | ||
942 | |||
943 | DBG(" -> unflatten_device_tree()\n"); | ||
944 | |||
945 | /* First pass, scan for size */ | ||
946 | start = ((unsigned long)initial_boot_params) + | ||
947 | initial_boot_params->off_dt_struct; | ||
948 | size = unflatten_dt_node(0, &start, NULL, NULL, 0); | ||
949 | size = (size | 3) + 1; | ||
950 | |||
951 | DBG(" size is %lx, allocating...\n", size); | ||
952 | |||
953 | /* Allocate memory for the expanded device tree */ | ||
954 | mem = lmb_alloc(size + 4, __alignof__(struct device_node)); | ||
955 | if (!mem) { | ||
956 | DBG("Couldn't allocate memory with lmb_alloc()!\n"); | ||
957 | panic("Couldn't allocate memory with lmb_alloc()!\n"); | ||
958 | } | ||
959 | mem = (unsigned long)abs_to_virt(mem); | ||
960 | |||
961 | ((u32 *)mem)[size / 4] = 0xdeadbeef; | ||
962 | |||
963 | DBG(" unflattening...\n", mem); | ||
964 | |||
965 | /* Second pass, do actual unflattening */ | ||
966 | start = ((unsigned long)initial_boot_params) + | ||
967 | initial_boot_params->off_dt_struct; | ||
968 | unflatten_dt_node(mem, &start, NULL, &allnextp, 0); | ||
969 | if (*((u32 *)start) != OF_DT_END) | ||
970 | printk(KERN_WARNING "Weird tag at end of tree: %08x\n", *((u32 *)start)); | ||
971 | if (((u32 *)mem)[size / 4] != 0xdeadbeef) | ||
972 | printk(KERN_WARNING "End of tree marker overwritten: %08x\n", | ||
973 | ((u32 *)mem)[size / 4] ); | ||
974 | *allnextp = NULL; | ||
975 | |||
976 | /* Get pointer to OF "/chosen" node for use everywhere */ | ||
977 | of_chosen = of_find_node_by_path("/chosen"); | ||
978 | |||
979 | /* Retreive command line */ | ||
980 | if (of_chosen != NULL) { | ||
981 | p = (char *)get_property(of_chosen, "bootargs", &l); | ||
982 | if (p != NULL && l > 0) | ||
983 | strlcpy(cmd_line, p, min(l, COMMAND_LINE_SIZE)); | ||
984 | } | ||
985 | #ifdef CONFIG_CMDLINE | ||
986 | if (l == 0 || (l == 1 && (*p) == 0)) | ||
987 | strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); | ||
988 | #endif /* CONFIG_CMDLINE */ | ||
989 | |||
990 | DBG("Command line is: %s\n", cmd_line); | ||
991 | |||
992 | DBG(" <- unflatten_device_tree()\n"); | ||
993 | } | ||
994 | |||
995 | |||
996 | static int __init early_init_dt_scan_cpus(unsigned long node, | ||
997 | const char *uname, int depth, void *data) | ||
998 | { | ||
999 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); | ||
1000 | u32 *prop; | ||
1001 | unsigned long size; | ||
1002 | |||
1003 | /* We are scanning "cpu" nodes only */ | ||
1004 | if (type == NULL || strcmp(type, "cpu") != 0) | ||
1005 | return 0; | ||
1006 | |||
1007 | if (initial_boot_params && initial_boot_params->version >= 2) { | ||
1008 | /* version 2 of the kexec param format adds the phys cpuid | ||
1009 | * of booted proc. | ||
1010 | */ | ||
1011 | boot_cpuid_phys = initial_boot_params->boot_cpuid_phys; | ||
1012 | boot_cpuid = 0; | ||
1013 | } else { | ||
1014 | /* Check if it's the boot-cpu, set it's hw index in paca now */ | ||
1015 | if (of_get_flat_dt_prop(node, "linux,boot-cpu", NULL) | ||
1016 | != NULL) { | ||
1017 | u32 *prop = of_get_flat_dt_prop(node, "reg", NULL); | ||
1018 | set_hard_smp_processor_id(0, prop == NULL ? 0 : *prop); | ||
1019 | boot_cpuid_phys = get_hard_smp_processor_id(0); | ||
1020 | } | ||
1021 | } | ||
1022 | |||
1023 | #ifdef CONFIG_ALTIVEC | ||
1024 | /* Check if we have a VMX and eventually update CPU features */ | ||
1025 | prop = (u32 *)of_get_flat_dt_prop(node, "ibm,vmx", NULL); | ||
1026 | if (prop && (*prop) > 0) { | ||
1027 | cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; | ||
1028 | cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; | ||
1029 | } | ||
1030 | |||
1031 | /* Same goes for Apple's "altivec" property */ | ||
1032 | prop = (u32 *)of_get_flat_dt_prop(node, "altivec", NULL); | ||
1033 | if (prop) { | ||
1034 | cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; | ||
1035 | cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; | ||
1036 | } | ||
1037 | #endif /* CONFIG_ALTIVEC */ | ||
1038 | |||
1039 | /* | ||
1040 | * Check for an SMT capable CPU and set the CPU feature. We do | ||
1041 | * this by looking at the size of the ibm,ppc-interrupt-server#s | ||
1042 | * property | ||
1043 | */ | ||
1044 | prop = (u32 *)of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", | ||
1045 | &size); | ||
1046 | cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT; | ||
1047 | if (prop && ((size / sizeof(u32)) > 1)) | ||
1048 | cur_cpu_spec->cpu_features |= CPU_FTR_SMT; | ||
1049 | |||
1050 | return 0; | ||
1051 | } | ||
1052 | |||
1053 | static int __init early_init_dt_scan_chosen(unsigned long node, | ||
1054 | const char *uname, int depth, void *data) | ||
1055 | { | ||
1056 | u32 *prop; | ||
1057 | u64 *prop64; | ||
1058 | |||
1059 | DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname); | ||
1060 | |||
1061 | if (depth != 1 || strcmp(uname, "chosen") != 0) | ||
1062 | return 0; | ||
1063 | |||
1064 | /* get platform type */ | ||
1065 | prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL); | ||
1066 | if (prop == NULL) | ||
1067 | return 0; | ||
1068 | _machine = *prop; | ||
1069 | |||
1070 | /* check if iommu is forced on or off */ | ||
1071 | if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) | ||
1072 | iommu_is_off = 1; | ||
1073 | if (of_get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL) | ||
1074 | iommu_force_on = 1; | ||
1075 | |||
1076 | prop64 = (u64*)of_get_flat_dt_prop(node, "linux,memory-limit", NULL); | ||
1077 | if (prop64) | ||
1078 | memory_limit = *prop64; | ||
1079 | |||
1080 | prop64 = (u64*)of_get_flat_dt_prop(node, "linux,tce-alloc-start",NULL); | ||
1081 | if (prop64) | ||
1082 | tce_alloc_start = *prop64; | ||
1083 | |||
1084 | prop64 = (u64*)of_get_flat_dt_prop(node, "linux,tce-alloc-end", NULL); | ||
1085 | if (prop64) | ||
1086 | tce_alloc_end = *prop64; | ||
1087 | |||
1088 | #ifdef CONFIG_PPC_RTAS | ||
1089 | /* To help early debugging via the front panel, we retreive a minimal | ||
1090 | * set of RTAS infos now if available | ||
1091 | */ | ||
1092 | { | ||
1093 | u64 *basep, *entryp; | ||
1094 | |||
1095 | basep = (u64*)of_get_flat_dt_prop(node, | ||
1096 | "linux,rtas-base", NULL); | ||
1097 | entryp = (u64*)of_get_flat_dt_prop(node, | ||
1098 | "linux,rtas-entry", NULL); | ||
1099 | prop = (u32*)of_get_flat_dt_prop(node, | ||
1100 | "linux,rtas-size", NULL); | ||
1101 | if (basep && entryp && prop) { | ||
1102 | rtas.base = *basep; | ||
1103 | rtas.entry = *entryp; | ||
1104 | rtas.size = *prop; | ||
1105 | } | ||
1106 | } | ||
1107 | #endif /* CONFIG_PPC_RTAS */ | ||
1108 | |||
1109 | /* break now */ | ||
1110 | return 1; | ||
1111 | } | ||
1112 | |||
1113 | static int __init early_init_dt_scan_root(unsigned long node, | ||
1114 | const char *uname, int depth, void *data) | ||
1115 | { | ||
1116 | u32 *prop; | ||
1117 | |||
1118 | if (depth != 0) | ||
1119 | return 0; | ||
1120 | |||
1121 | prop = (u32 *)of_get_flat_dt_prop(node, "#size-cells", NULL); | ||
1122 | dt_root_size_cells = (prop == NULL) ? 1 : *prop; | ||
1123 | DBG("dt_root_size_cells = %x\n", dt_root_size_cells); | ||
1124 | |||
1125 | prop = (u32 *)of_get_flat_dt_prop(node, "#address-cells", NULL); | ||
1126 | dt_root_addr_cells = (prop == NULL) ? 2 : *prop; | ||
1127 | DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells); | ||
1128 | |||
1129 | /* break now */ | ||
1130 | return 1; | ||
1131 | } | ||
1132 | |||
1133 | static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp) | ||
1134 | { | ||
1135 | cell_t *p = *cellp; | ||
1136 | unsigned long r = 0; | ||
1137 | |||
1138 | /* Ignore more than 2 cells */ | ||
1139 | while (s > 2) { | ||
1140 | p++; | ||
1141 | s--; | ||
1142 | } | ||
1143 | while (s) { | ||
1144 | r <<= 32; | ||
1145 | r |= *(p++); | ||
1146 | s--; | ||
1147 | } | ||
1148 | |||
1149 | *cellp = p; | ||
1150 | return r; | ||
1151 | } | ||
1152 | |||
1153 | |||
1154 | static int __init early_init_dt_scan_memory(unsigned long node, | ||
1155 | const char *uname, int depth, void *data) | ||
1156 | { | ||
1157 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); | ||
1158 | cell_t *reg, *endp; | ||
1159 | unsigned long l; | ||
1160 | |||
1161 | /* We are scanning "memory" nodes only */ | ||
1162 | if (type == NULL || strcmp(type, "memory") != 0) | ||
1163 | return 0; | ||
1164 | |||
1165 | reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l); | ||
1166 | if (reg == NULL) | ||
1167 | return 0; | ||
1168 | |||
1169 | endp = reg + (l / sizeof(cell_t)); | ||
1170 | |||
1171 | DBG("memory scan node %s ..., reg size %ld, data: %x %x %x %x, ...\n", | ||
1172 | uname, l, reg[0], reg[1], reg[2], reg[3]); | ||
1173 | |||
1174 | while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) { | ||
1175 | unsigned long base, size; | ||
1176 | |||
1177 | base = dt_mem_next_cell(dt_root_addr_cells, ®); | ||
1178 | size = dt_mem_next_cell(dt_root_size_cells, ®); | ||
1179 | |||
1180 | if (size == 0) | ||
1181 | continue; | ||
1182 | DBG(" - %lx , %lx\n", base, size); | ||
1183 | if (iommu_is_off) { | ||
1184 | if (base >= 0x80000000ul) | ||
1185 | continue; | ||
1186 | if ((base + size) > 0x80000000ul) | ||
1187 | size = 0x80000000ul - base; | ||
1188 | } | ||
1189 | lmb_add(base, size); | ||
1190 | } | ||
1191 | return 0; | ||
1192 | } | ||
1193 | |||
1194 | static void __init early_reserve_mem(void) | ||
1195 | { | ||
1196 | u64 base, size; | ||
1197 | u64 *reserve_map = (u64 *)(((unsigned long)initial_boot_params) + | ||
1198 | initial_boot_params->off_mem_rsvmap); | ||
1199 | while (1) { | ||
1200 | base = *(reserve_map++); | ||
1201 | size = *(reserve_map++); | ||
1202 | if (size == 0) | ||
1203 | break; | ||
1204 | DBG("reserving: %lx -> %lx\n", base, size); | ||
1205 | lmb_reserve(base, size); | ||
1206 | } | ||
1207 | |||
1208 | #if 0 | ||
1209 | DBG("memory reserved, lmbs :\n"); | ||
1210 | lmb_dump_all(); | ||
1211 | #endif | ||
1212 | } | ||
1213 | |||
1214 | void __init early_init_devtree(void *params) | ||
1215 | { | ||
1216 | DBG(" -> early_init_devtree()\n"); | ||
1217 | |||
1218 | /* Setup flat device-tree pointer */ | ||
1219 | initial_boot_params = params; | ||
1220 | |||
1221 | /* Retreive various informations from the /chosen node of the | ||
1222 | * device-tree, including the platform type, initrd location and | ||
1223 | * size, TCE reserve, and more ... | ||
1224 | */ | ||
1225 | of_scan_flat_dt(early_init_dt_scan_chosen, NULL); | ||
1226 | |||
1227 | /* Scan memory nodes and rebuild LMBs */ | ||
1228 | lmb_init(); | ||
1229 | of_scan_flat_dt(early_init_dt_scan_root, NULL); | ||
1230 | of_scan_flat_dt(early_init_dt_scan_memory, NULL); | ||
1231 | lmb_enforce_memory_limit(memory_limit); | ||
1232 | lmb_analyze(); | ||
1233 | lmb_reserve(0, __pa(klimit)); | ||
1234 | |||
1235 | /* Reserve LMB regions used by kernel, initrd, dt, etc... */ | ||
1236 | early_reserve_mem(); | ||
1237 | |||
1238 | DBG("Scanning CPUs ...\n"); | ||
1239 | |||
1240 | /* Retreive hash table size from flattened tree plus other | ||
1241 | * CPU related informations (altivec support, boot CPU ID, ...) | ||
1242 | */ | ||
1243 | of_scan_flat_dt(early_init_dt_scan_cpus, NULL); | ||
1244 | |||
1245 | DBG(" <- early_init_devtree()\n"); | ||
1246 | } | ||
1247 | |||
1248 | #undef printk | ||
1249 | |||
1250 | int | ||
1251 | prom_n_addr_cells(struct device_node* np) | ||
1252 | { | ||
1253 | int* ip; | ||
1254 | do { | ||
1255 | if (np->parent) | ||
1256 | np = np->parent; | ||
1257 | ip = (int *) get_property(np, "#address-cells", NULL); | ||
1258 | if (ip != NULL) | ||
1259 | return *ip; | ||
1260 | } while (np->parent); | ||
1261 | /* No #address-cells property for the root node, default to 1 */ | ||
1262 | return 1; | ||
1263 | } | ||
1264 | |||
1265 | int | ||
1266 | prom_n_size_cells(struct device_node* np) | ||
1267 | { | ||
1268 | int* ip; | ||
1269 | do { | ||
1270 | if (np->parent) | ||
1271 | np = np->parent; | ||
1272 | ip = (int *) get_property(np, "#size-cells", NULL); | ||
1273 | if (ip != NULL) | ||
1274 | return *ip; | ||
1275 | } while (np->parent); | ||
1276 | /* No #size-cells property for the root node, default to 1 */ | ||
1277 | return 1; | ||
1278 | } | ||
1279 | |||
1280 | /** | ||
1281 | * Work out the sense (active-low level / active-high edge) | ||
1282 | * of each interrupt from the device tree. | ||
1283 | */ | ||
1284 | void __init prom_get_irq_senses(unsigned char *senses, int off, int max) | ||
1285 | { | ||
1286 | struct device_node *np; | ||
1287 | int i, j; | ||
1288 | |||
1289 | /* default to level-triggered */ | ||
1290 | memset(senses, 1, max - off); | ||
1291 | |||
1292 | for (np = allnodes; np != 0; np = np->allnext) { | ||
1293 | for (j = 0; j < np->n_intrs; j++) { | ||
1294 | i = np->intrs[j].line; | ||
1295 | if (i >= off && i < max) | ||
1296 | senses[i-off] = np->intrs[j].sense ? | ||
1297 | IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE : | ||
1298 | IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE; | ||
1299 | } | ||
1300 | } | ||
1301 | } | ||
1302 | |||
1303 | /** | ||
1304 | * Construct and return a list of the device_nodes with a given name. | ||
1305 | */ | ||
1306 | struct device_node * | ||
1307 | find_devices(const char *name) | ||
1308 | { | ||
1309 | struct device_node *head, **prevp, *np; | ||
1310 | |||
1311 | prevp = &head; | ||
1312 | for (np = allnodes; np != 0; np = np->allnext) { | ||
1313 | if (np->name != 0 && strcasecmp(np->name, name) == 0) { | ||
1314 | *prevp = np; | ||
1315 | prevp = &np->next; | ||
1316 | } | ||
1317 | } | ||
1318 | *prevp = NULL; | ||
1319 | return head; | ||
1320 | } | ||
1321 | EXPORT_SYMBOL(find_devices); | ||
1322 | |||
1323 | /** | ||
1324 | * Construct and return a list of the device_nodes with a given type. | ||
1325 | */ | ||
1326 | struct device_node * | ||
1327 | find_type_devices(const char *type) | ||
1328 | { | ||
1329 | struct device_node *head, **prevp, *np; | ||
1330 | |||
1331 | prevp = &head; | ||
1332 | for (np = allnodes; np != 0; np = np->allnext) { | ||
1333 | if (np->type != 0 && strcasecmp(np->type, type) == 0) { | ||
1334 | *prevp = np; | ||
1335 | prevp = &np->next; | ||
1336 | } | ||
1337 | } | ||
1338 | *prevp = NULL; | ||
1339 | return head; | ||
1340 | } | ||
1341 | EXPORT_SYMBOL(find_type_devices); | ||
1342 | |||
1343 | /** | ||
1344 | * Returns all nodes linked together | ||
1345 | */ | ||
1346 | struct device_node * | ||
1347 | find_all_nodes(void) | ||
1348 | { | ||
1349 | struct device_node *head, **prevp, *np; | ||
1350 | |||
1351 | prevp = &head; | ||
1352 | for (np = allnodes; np != 0; np = np->allnext) { | ||
1353 | *prevp = np; | ||
1354 | prevp = &np->next; | ||
1355 | } | ||
1356 | *prevp = NULL; | ||
1357 | return head; | ||
1358 | } | ||
1359 | EXPORT_SYMBOL(find_all_nodes); | ||
1360 | |||
1361 | /** Checks if the given "compat" string matches one of the strings in | ||
1362 | * the device's "compatible" property | ||
1363 | */ | ||
1364 | int | ||
1365 | device_is_compatible(struct device_node *device, const char *compat) | ||
1366 | { | ||
1367 | const char* cp; | ||
1368 | int cplen, l; | ||
1369 | |||
1370 | cp = (char *) get_property(device, "compatible", &cplen); | ||
1371 | if (cp == NULL) | ||
1372 | return 0; | ||
1373 | while (cplen > 0) { | ||
1374 | if (strncasecmp(cp, compat, strlen(compat)) == 0) | ||
1375 | return 1; | ||
1376 | l = strlen(cp) + 1; | ||
1377 | cp += l; | ||
1378 | cplen -= l; | ||
1379 | } | ||
1380 | |||
1381 | return 0; | ||
1382 | } | ||
1383 | EXPORT_SYMBOL(device_is_compatible); | ||
1384 | |||
1385 | |||
1386 | /** | ||
1387 | * Indicates whether the root node has a given value in its | ||
1388 | * compatible property. | ||
1389 | */ | ||
1390 | int | ||
1391 | machine_is_compatible(const char *compat) | ||
1392 | { | ||
1393 | struct device_node *root; | ||
1394 | int rc = 0; | ||
1395 | |||
1396 | root = of_find_node_by_path("/"); | ||
1397 | if (root) { | ||
1398 | rc = device_is_compatible(root, compat); | ||
1399 | of_node_put(root); | ||
1400 | } | ||
1401 | return rc; | ||
1402 | } | ||
1403 | EXPORT_SYMBOL(machine_is_compatible); | ||
1404 | |||
1405 | /** | ||
1406 | * Construct and return a list of the device_nodes with a given type | ||
1407 | * and compatible property. | ||
1408 | */ | ||
1409 | struct device_node * | ||
1410 | find_compatible_devices(const char *type, const char *compat) | ||
1411 | { | ||
1412 | struct device_node *head, **prevp, *np; | ||
1413 | |||
1414 | prevp = &head; | ||
1415 | for (np = allnodes; np != 0; np = np->allnext) { | ||
1416 | if (type != NULL | ||
1417 | && !(np->type != 0 && strcasecmp(np->type, type) == 0)) | ||
1418 | continue; | ||
1419 | if (device_is_compatible(np, compat)) { | ||
1420 | *prevp = np; | ||
1421 | prevp = &np->next; | ||
1422 | } | ||
1423 | } | ||
1424 | *prevp = NULL; | ||
1425 | return head; | ||
1426 | } | ||
1427 | EXPORT_SYMBOL(find_compatible_devices); | ||
1428 | |||
1429 | /** | ||
1430 | * Find the device_node with a given full_name. | ||
1431 | */ | ||
1432 | struct device_node * | ||
1433 | find_path_device(const char *path) | ||
1434 | { | ||
1435 | struct device_node *np; | ||
1436 | |||
1437 | for (np = allnodes; np != 0; np = np->allnext) | ||
1438 | if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0) | ||
1439 | return np; | ||
1440 | return NULL; | ||
1441 | } | ||
1442 | EXPORT_SYMBOL(find_path_device); | ||
1443 | |||
1444 | /******* | ||
1445 | * | ||
1446 | * New implementation of the OF "find" APIs, return a refcounted | ||
1447 | * object, call of_node_put() when done. The device tree and list | ||
1448 | * are protected by a rw_lock. | ||
1449 | * | ||
1450 | * Note that property management will need some locking as well, | ||
1451 | * this isn't dealt with yet. | ||
1452 | * | ||
1453 | *******/ | ||
1454 | |||
1455 | /** | ||
1456 | * of_find_node_by_name - Find a node by its "name" property | ||
1457 | * @from: The node to start searching from or NULL, the node | ||
1458 | * you pass will not be searched, only the next one | ||
1459 | * will; typically, you pass what the previous call | ||
1460 | * returned. of_node_put() will be called on it | ||
1461 | * @name: The name string to match against | ||
1462 | * | ||
1463 | * Returns a node pointer with refcount incremented, use | ||
1464 | * of_node_put() on it when done. | ||
1465 | */ | ||
1466 | struct device_node *of_find_node_by_name(struct device_node *from, | ||
1467 | const char *name) | ||
1468 | { | ||
1469 | struct device_node *np; | ||
1470 | |||
1471 | read_lock(&devtree_lock); | ||
1472 | np = from ? from->allnext : allnodes; | ||
1473 | for (; np != 0; np = np->allnext) | ||
1474 | if (np->name != 0 && strcasecmp(np->name, name) == 0 | ||
1475 | && of_node_get(np)) | ||
1476 | break; | ||
1477 | if (from) | ||
1478 | of_node_put(from); | ||
1479 | read_unlock(&devtree_lock); | ||
1480 | return np; | ||
1481 | } | ||
1482 | EXPORT_SYMBOL(of_find_node_by_name); | ||
1483 | |||
1484 | /** | ||
1485 | * of_find_node_by_type - Find a node by its "device_type" property | ||
1486 | * @from: The node to start searching from or NULL, the node | ||
1487 | * you pass will not be searched, only the next one | ||
1488 | * will; typically, you pass what the previous call | ||
1489 | * returned. of_node_put() will be called on it | ||
1490 | * @name: The type string to match against | ||
1491 | * | ||
1492 | * Returns a node pointer with refcount incremented, use | ||
1493 | * of_node_put() on it when done. | ||
1494 | */ | ||
1495 | struct device_node *of_find_node_by_type(struct device_node *from, | ||
1496 | const char *type) | ||
1497 | { | ||
1498 | struct device_node *np; | ||
1499 | |||
1500 | read_lock(&devtree_lock); | ||
1501 | np = from ? from->allnext : allnodes; | ||
1502 | for (; np != 0; np = np->allnext) | ||
1503 | if (np->type != 0 && strcasecmp(np->type, type) == 0 | ||
1504 | && of_node_get(np)) | ||
1505 | break; | ||
1506 | if (from) | ||
1507 | of_node_put(from); | ||
1508 | read_unlock(&devtree_lock); | ||
1509 | return np; | ||
1510 | } | ||
1511 | EXPORT_SYMBOL(of_find_node_by_type); | ||
1512 | |||
1513 | /** | ||
1514 | * of_find_compatible_node - Find a node based on type and one of the | ||
1515 | * tokens in its "compatible" property | ||
1516 | * @from: The node to start searching from or NULL, the node | ||
1517 | * you pass will not be searched, only the next one | ||
1518 | * will; typically, you pass what the previous call | ||
1519 | * returned. of_node_put() will be called on it | ||
1520 | * @type: The type string to match "device_type" or NULL to ignore | ||
1521 | * @compatible: The string to match to one of the tokens in the device | ||
1522 | * "compatible" list. | ||
1523 | * | ||
1524 | * Returns a node pointer with refcount incremented, use | ||
1525 | * of_node_put() on it when done. | ||
1526 | */ | ||
1527 | struct device_node *of_find_compatible_node(struct device_node *from, | ||
1528 | const char *type, const char *compatible) | ||
1529 | { | ||
1530 | struct device_node *np; | ||
1531 | |||
1532 | read_lock(&devtree_lock); | ||
1533 | np = from ? from->allnext : allnodes; | ||
1534 | for (; np != 0; np = np->allnext) { | ||
1535 | if (type != NULL | ||
1536 | && !(np->type != 0 && strcasecmp(np->type, type) == 0)) | ||
1537 | continue; | ||
1538 | if (device_is_compatible(np, compatible) && of_node_get(np)) | ||
1539 | break; | ||
1540 | } | ||
1541 | if (from) | ||
1542 | of_node_put(from); | ||
1543 | read_unlock(&devtree_lock); | ||
1544 | return np; | ||
1545 | } | ||
1546 | EXPORT_SYMBOL(of_find_compatible_node); | ||
1547 | |||
1548 | /** | ||
1549 | * of_find_node_by_path - Find a node matching a full OF path | ||
1550 | * @path: The full path to match | ||
1551 | * | ||
1552 | * Returns a node pointer with refcount incremented, use | ||
1553 | * of_node_put() on it when done. | ||
1554 | */ | ||
1555 | struct device_node *of_find_node_by_path(const char *path) | ||
1556 | { | ||
1557 | struct device_node *np = allnodes; | ||
1558 | |||
1559 | read_lock(&devtree_lock); | ||
1560 | for (; np != 0; np = np->allnext) { | ||
1561 | if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0 | ||
1562 | && of_node_get(np)) | ||
1563 | break; | ||
1564 | } | ||
1565 | read_unlock(&devtree_lock); | ||
1566 | return np; | ||
1567 | } | ||
1568 | EXPORT_SYMBOL(of_find_node_by_path); | ||
1569 | |||
1570 | /** | ||
1571 | * of_find_node_by_phandle - Find a node given a phandle | ||
1572 | * @handle: phandle of the node to find | ||
1573 | * | ||
1574 | * Returns a node pointer with refcount incremented, use | ||
1575 | * of_node_put() on it when done. | ||
1576 | */ | ||
1577 | struct device_node *of_find_node_by_phandle(phandle handle) | ||
1578 | { | ||
1579 | struct device_node *np; | ||
1580 | |||
1581 | read_lock(&devtree_lock); | ||
1582 | for (np = allnodes; np != 0; np = np->allnext) | ||
1583 | if (np->linux_phandle == handle) | ||
1584 | break; | ||
1585 | if (np) | ||
1586 | of_node_get(np); | ||
1587 | read_unlock(&devtree_lock); | ||
1588 | return np; | ||
1589 | } | ||
1590 | EXPORT_SYMBOL(of_find_node_by_phandle); | ||
1591 | |||
1592 | /** | ||
1593 | * of_find_all_nodes - Get next node in global list | ||
1594 | * @prev: Previous node or NULL to start iteration | ||
1595 | * of_node_put() will be called on it | ||
1596 | * | ||
1597 | * Returns a node pointer with refcount incremented, use | ||
1598 | * of_node_put() on it when done. | ||
1599 | */ | ||
1600 | struct device_node *of_find_all_nodes(struct device_node *prev) | ||
1601 | { | ||
1602 | struct device_node *np; | ||
1603 | |||
1604 | read_lock(&devtree_lock); | ||
1605 | np = prev ? prev->allnext : allnodes; | ||
1606 | for (; np != 0; np = np->allnext) | ||
1607 | if (of_node_get(np)) | ||
1608 | break; | ||
1609 | if (prev) | ||
1610 | of_node_put(prev); | ||
1611 | read_unlock(&devtree_lock); | ||
1612 | return np; | ||
1613 | } | ||
1614 | EXPORT_SYMBOL(of_find_all_nodes); | ||
1615 | |||
1616 | /** | ||
1617 | * of_get_parent - Get a node's parent if any | ||
1618 | * @node: Node to get parent | ||
1619 | * | ||
1620 | * Returns a node pointer with refcount incremented, use | ||
1621 | * of_node_put() on it when done. | ||
1622 | */ | ||
1623 | struct device_node *of_get_parent(const struct device_node *node) | ||
1624 | { | ||
1625 | struct device_node *np; | ||
1626 | |||
1627 | if (!node) | ||
1628 | return NULL; | ||
1629 | |||
1630 | read_lock(&devtree_lock); | ||
1631 | np = of_node_get(node->parent); | ||
1632 | read_unlock(&devtree_lock); | ||
1633 | return np; | ||
1634 | } | ||
1635 | EXPORT_SYMBOL(of_get_parent); | ||
1636 | |||
1637 | /** | ||
1638 | * of_get_next_child - Iterate a node childs | ||
1639 | * @node: parent node | ||
1640 | * @prev: previous child of the parent node, or NULL to get first | ||
1641 | * | ||
1642 | * Returns a node pointer with refcount incremented, use | ||
1643 | * of_node_put() on it when done. | ||
1644 | */ | ||
1645 | struct device_node *of_get_next_child(const struct device_node *node, | ||
1646 | struct device_node *prev) | ||
1647 | { | ||
1648 | struct device_node *next; | ||
1649 | |||
1650 | read_lock(&devtree_lock); | ||
1651 | next = prev ? prev->sibling : node->child; | ||
1652 | for (; next != 0; next = next->sibling) | ||
1653 | if (of_node_get(next)) | ||
1654 | break; | ||
1655 | if (prev) | ||
1656 | of_node_put(prev); | ||
1657 | read_unlock(&devtree_lock); | ||
1658 | return next; | ||
1659 | } | ||
1660 | EXPORT_SYMBOL(of_get_next_child); | ||
1661 | |||
1662 | /** | ||
1663 | * of_node_get - Increment refcount of a node | ||
1664 | * @node: Node to inc refcount, NULL is supported to | ||
1665 | * simplify writing of callers | ||
1666 | * | ||
1667 | * Returns node. | ||
1668 | */ | ||
1669 | struct device_node *of_node_get(struct device_node *node) | ||
1670 | { | ||
1671 | if (node) | ||
1672 | kref_get(&node->kref); | ||
1673 | return node; | ||
1674 | } | ||
1675 | EXPORT_SYMBOL(of_node_get); | ||
1676 | |||
1677 | static inline struct device_node * kref_to_device_node(struct kref *kref) | ||
1678 | { | ||
1679 | return container_of(kref, struct device_node, kref); | ||
1680 | } | ||
1681 | |||
1682 | /** | ||
1683 | * of_node_release - release a dynamically allocated node | ||
1684 | * @kref: kref element of the node to be released | ||
1685 | * | ||
1686 | * In of_node_put() this function is passed to kref_put() | ||
1687 | * as the destructor. | ||
1688 | */ | ||
1689 | static void of_node_release(struct kref *kref) | ||
1690 | { | ||
1691 | struct device_node *node = kref_to_device_node(kref); | ||
1692 | struct property *prop = node->properties; | ||
1693 | |||
1694 | if (!OF_IS_DYNAMIC(node)) | ||
1695 | return; | ||
1696 | while (prop) { | ||
1697 | struct property *next = prop->next; | ||
1698 | kfree(prop->name); | ||
1699 | kfree(prop->value); | ||
1700 | kfree(prop); | ||
1701 | prop = next; | ||
1702 | } | ||
1703 | kfree(node->intrs); | ||
1704 | kfree(node->addrs); | ||
1705 | kfree(node->full_name); | ||
1706 | kfree(node->data); | ||
1707 | kfree(node); | ||
1708 | } | ||
1709 | |||
1710 | /** | ||
1711 | * of_node_put - Decrement refcount of a node | ||
1712 | * @node: Node to dec refcount, NULL is supported to | ||
1713 | * simplify writing of callers | ||
1714 | * | ||
1715 | */ | ||
1716 | void of_node_put(struct device_node *node) | ||
1717 | { | ||
1718 | if (node) | ||
1719 | kref_put(&node->kref, of_node_release); | ||
1720 | } | ||
1721 | EXPORT_SYMBOL(of_node_put); | ||
1722 | |||
1723 | /* | ||
1724 | * Fix up the uninitialized fields in a new device node: | ||
1725 | * name, type, n_addrs, addrs, n_intrs, intrs, and pci-specific fields | ||
1726 | * | ||
1727 | * A lot of boot-time code is duplicated here, because functions such | ||
1728 | * as finish_node_interrupts, interpret_pci_props, etc. cannot use the | ||
1729 | * slab allocator. | ||
1730 | * | ||
1731 | * This should probably be split up into smaller chunks. | ||
1732 | */ | ||
1733 | |||
1734 | static int of_finish_dynamic_node(struct device_node *node, | ||
1735 | unsigned long *unused1, int unused2, | ||
1736 | int unused3, int unused4) | ||
1737 | { | ||
1738 | struct device_node *parent = of_get_parent(node); | ||
1739 | int err = 0; | ||
1740 | phandle *ibm_phandle; | ||
1741 | |||
1742 | node->name = get_property(node, "name", NULL); | ||
1743 | node->type = get_property(node, "device_type", NULL); | ||
1744 | |||
1745 | if (!parent) { | ||
1746 | err = -ENODEV; | ||
1747 | goto out; | ||
1748 | } | ||
1749 | |||
1750 | /* We don't support that function on PowerMac, at least | ||
1751 | * not yet | ||
1752 | */ | ||
1753 | if (_machine == PLATFORM_POWERMAC) | ||
1754 | return -ENODEV; | ||
1755 | |||
1756 | /* fix up new node's linux_phandle field */ | ||
1757 | if ((ibm_phandle = (unsigned int *)get_property(node, "ibm,phandle", NULL))) | ||
1758 | node->linux_phandle = *ibm_phandle; | ||
1759 | |||
1760 | out: | ||
1761 | of_node_put(parent); | ||
1762 | return err; | ||
1763 | } | ||
1764 | |||
1765 | /* | ||
1766 | * Plug a device node into the tree and global list. | ||
1767 | */ | ||
1768 | void of_attach_node(struct device_node *np) | ||
1769 | { | ||
1770 | write_lock(&devtree_lock); | ||
1771 | np->sibling = np->parent->child; | ||
1772 | np->allnext = allnodes; | ||
1773 | np->parent->child = np; | ||
1774 | allnodes = np; | ||
1775 | write_unlock(&devtree_lock); | ||
1776 | } | ||
1777 | |||
1778 | /* | ||
1779 | * "Unplug" a node from the device tree. The caller must hold | ||
1780 | * a reference to the node. The memory associated with the node | ||
1781 | * is not freed until its refcount goes to zero. | ||
1782 | */ | ||
1783 | void of_detach_node(const struct device_node *np) | ||
1784 | { | ||
1785 | struct device_node *parent; | ||
1786 | |||
1787 | write_lock(&devtree_lock); | ||
1788 | |||
1789 | parent = np->parent; | ||
1790 | |||
1791 | if (allnodes == np) | ||
1792 | allnodes = np->allnext; | ||
1793 | else { | ||
1794 | struct device_node *prev; | ||
1795 | for (prev = allnodes; | ||
1796 | prev->allnext != np; | ||
1797 | prev = prev->allnext) | ||
1798 | ; | ||
1799 | prev->allnext = np->allnext; | ||
1800 | } | ||
1801 | |||
1802 | if (parent->child == np) | ||
1803 | parent->child = np->sibling; | ||
1804 | else { | ||
1805 | struct device_node *prevsib; | ||
1806 | for (prevsib = np->parent->child; | ||
1807 | prevsib->sibling != np; | ||
1808 | prevsib = prevsib->sibling) | ||
1809 | ; | ||
1810 | prevsib->sibling = np->sibling; | ||
1811 | } | ||
1812 | |||
1813 | write_unlock(&devtree_lock); | ||
1814 | } | ||
1815 | |||
1816 | static int prom_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node) | ||
1817 | { | ||
1818 | int err; | ||
1819 | |||
1820 | switch (action) { | ||
1821 | case PSERIES_RECONFIG_ADD: | ||
1822 | err = finish_node(node, NULL, of_finish_dynamic_node, 0, 0, 0); | ||
1823 | if (err < 0) { | ||
1824 | printk(KERN_ERR "finish_node returned %d\n", err); | ||
1825 | err = NOTIFY_BAD; | ||
1826 | } | ||
1827 | break; | ||
1828 | default: | ||
1829 | err = NOTIFY_DONE; | ||
1830 | break; | ||
1831 | } | ||
1832 | return err; | ||
1833 | } | ||
1834 | |||
1835 | static struct notifier_block prom_reconfig_nb = { | ||
1836 | .notifier_call = prom_reconfig_notifier, | ||
1837 | .priority = 10, /* This one needs to run first */ | ||
1838 | }; | ||
1839 | |||
1840 | static int __init prom_reconfig_setup(void) | ||
1841 | { | ||
1842 | return pSeries_reconfig_notifier_register(&prom_reconfig_nb); | ||
1843 | } | ||
1844 | __initcall(prom_reconfig_setup); | ||
1845 | |||
1846 | /* | ||
1847 | * Find a property with a given name for a given node | ||
1848 | * and return the value. | ||
1849 | */ | ||
1850 | unsigned char * | ||
1851 | get_property(struct device_node *np, const char *name, int *lenp) | ||
1852 | { | ||
1853 | struct property *pp; | ||
1854 | |||
1855 | for (pp = np->properties; pp != 0; pp = pp->next) | ||
1856 | if (strcmp(pp->name, name) == 0) { | ||
1857 | if (lenp != 0) | ||
1858 | *lenp = pp->length; | ||
1859 | return pp->value; | ||
1860 | } | ||
1861 | return NULL; | ||
1862 | } | ||
1863 | EXPORT_SYMBOL(get_property); | ||
1864 | |||
1865 | /* | ||
1866 | * Add a property to a node. | ||
1867 | */ | ||
1868 | int | ||
1869 | prom_add_property(struct device_node* np, struct property* prop) | ||
1870 | { | ||
1871 | struct property **next; | ||
1872 | |||
1873 | prop->next = NULL; | ||
1874 | write_lock(&devtree_lock); | ||
1875 | next = &np->properties; | ||
1876 | while (*next) { | ||
1877 | if (strcmp(prop->name, (*next)->name) == 0) { | ||
1878 | /* duplicate ! don't insert it */ | ||
1879 | write_unlock(&devtree_lock); | ||
1880 | return -1; | ||
1881 | } | ||
1882 | next = &(*next)->next; | ||
1883 | } | ||
1884 | *next = prop; | ||
1885 | write_unlock(&devtree_lock); | ||
1886 | |||
1887 | /* try to add to proc as well if it was initialized */ | ||
1888 | if (np->pde) | ||
1889 | proc_device_tree_add_prop(np->pde, prop); | ||
1890 | |||
1891 | return 0; | ||
1892 | } | ||
1893 | |||
1894 | #if 0 | ||
1895 | void | ||
1896 | print_properties(struct device_node *np) | ||
1897 | { | ||
1898 | struct property *pp; | ||
1899 | char *cp; | ||
1900 | int i, n; | ||
1901 | |||
1902 | for (pp = np->properties; pp != 0; pp = pp->next) { | ||
1903 | printk(KERN_INFO "%s", pp->name); | ||
1904 | for (i = strlen(pp->name); i < 16; ++i) | ||
1905 | printk(" "); | ||
1906 | cp = (char *) pp->value; | ||
1907 | for (i = pp->length; i > 0; --i, ++cp) | ||
1908 | if ((i > 1 && (*cp < 0x20 || *cp > 0x7e)) | ||
1909 | || (i == 1 && *cp != 0)) | ||
1910 | break; | ||
1911 | if (i == 0 && pp->length > 1) { | ||
1912 | /* looks like a string */ | ||
1913 | printk(" %s\n", (char *) pp->value); | ||
1914 | } else { | ||
1915 | /* dump it in hex */ | ||
1916 | n = pp->length; | ||
1917 | if (n > 64) | ||
1918 | n = 64; | ||
1919 | if (pp->length % 4 == 0) { | ||
1920 | unsigned int *p = (unsigned int *) pp->value; | ||
1921 | |||
1922 | n /= 4; | ||
1923 | for (i = 0; i < n; ++i) { | ||
1924 | if (i != 0 && (i % 4) == 0) | ||
1925 | printk("\n "); | ||
1926 | printk(" %08x", *p++); | ||
1927 | } | ||
1928 | } else { | ||
1929 | unsigned char *bp = pp->value; | ||
1930 | |||
1931 | for (i = 0; i < n; ++i) { | ||
1932 | if (i != 0 && (i % 16) == 0) | ||
1933 | printk("\n "); | ||
1934 | printk(" %02x", *bp++); | ||
1935 | } | ||
1936 | } | ||
1937 | printk("\n"); | ||
1938 | if (pp->length > 64) | ||
1939 | printk(" ... (length = %d)\n", | ||
1940 | pp->length); | ||
1941 | } | ||
1942 | } | ||
1943 | } | ||
1944 | #endif | ||
1945 | |||
1946 | |||
1947 | |||
1948 | |||
1949 | |||
1950 | |||
1951 | |||
1952 | |||
1953 | |||
1954 | |||
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c deleted file mode 100644 index 6375f40b23db..000000000000 --- a/arch/ppc64/kernel/prom_init.c +++ /dev/null | |||
@@ -1,2051 +0,0 @@ | |||
1 | /* | ||
2 | * | ||
3 | * | ||
4 | * Procedures for interfacing to Open Firmware. | ||
5 | * | ||
6 | * Paul Mackerras August 1996. | ||
7 | * Copyright (C) 1996 Paul Mackerras. | ||
8 | * | ||
9 | * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. | ||
10 | * {engebret|bergner}@us.ibm.com | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version | ||
15 | * 2 of the License, or (at your option) any later version. | ||
16 | */ | ||
17 | |||
18 | #undef DEBUG_PROM | ||
19 | |||
20 | #include <stdarg.h> | ||
21 | #include <linux/config.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/string.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/threads.h> | ||
26 | #include <linux/spinlock.h> | ||
27 | #include <linux/types.h> | ||
28 | #include <linux/pci.h> | ||
29 | #include <linux/proc_fs.h> | ||
30 | #include <linux/stringify.h> | ||
31 | #include <linux/delay.h> | ||
32 | #include <linux/initrd.h> | ||
33 | #include <linux/bitops.h> | ||
34 | #include <asm/prom.h> | ||
35 | #include <asm/rtas.h> | ||
36 | #include <asm/abs_addr.h> | ||
37 | #include <asm/page.h> | ||
38 | #include <asm/processor.h> | ||
39 | #include <asm/irq.h> | ||
40 | #include <asm/io.h> | ||
41 | #include <asm/smp.h> | ||
42 | #include <asm/system.h> | ||
43 | #include <asm/mmu.h> | ||
44 | #include <asm/pgtable.h> | ||
45 | #include <asm/pci.h> | ||
46 | #include <asm/iommu.h> | ||
47 | #include <asm/btext.h> | ||
48 | #include <asm/sections.h> | ||
49 | #include <asm/machdep.h> | ||
50 | |||
51 | #ifdef CONFIG_LOGO_LINUX_CLUT224 | ||
52 | #include <linux/linux_logo.h> | ||
53 | extern const struct linux_logo logo_linux_clut224; | ||
54 | #endif | ||
55 | |||
56 | /* | ||
57 | * Properties whose value is longer than this get excluded from our | ||
58 | * copy of the device tree. This value does need to be big enough to | ||
59 | * ensure that we don't lose things like the interrupt-map property | ||
60 | * on a PCI-PCI bridge. | ||
61 | */ | ||
62 | #define MAX_PROPERTY_LENGTH (1UL * 1024 * 1024) | ||
63 | |||
64 | /* | ||
65 | * Eventually bump that one up | ||
66 | */ | ||
67 | #define DEVTREE_CHUNK_SIZE 0x100000 | ||
68 | |||
69 | /* | ||
70 | * This is the size of the local memory reserve map that gets copied | ||
71 | * into the boot params passed to the kernel. That size is totally | ||
72 | * flexible as the kernel just reads the list until it encounters an | ||
73 | * entry with size 0, so it can be changed without breaking binary | ||
74 | * compatibility | ||
75 | */ | ||
76 | #define MEM_RESERVE_MAP_SIZE 8 | ||
77 | |||
78 | /* | ||
79 | * prom_init() is called very early on, before the kernel text | ||
80 | * and data have been mapped to KERNELBASE. At this point the code | ||
81 | * is running at whatever address it has been loaded at, so | ||
82 | * references to extern and static variables must be relocated | ||
83 | * explicitly. The procedure reloc_offset() returns the address | ||
84 | * we're currently running at minus the address we were linked at. | ||
85 | * (Note that strings count as static variables.) | ||
86 | * | ||
87 | * Because OF may have mapped I/O devices into the area starting at | ||
88 | * KERNELBASE, particularly on CHRP machines, we can't safely call | ||
89 | * OF once the kernel has been mapped to KERNELBASE. Therefore all | ||
90 | * OF calls should be done within prom_init(), and prom_init() | ||
91 | * and all routines called within it must be careful to relocate | ||
92 | * references as necessary. | ||
93 | * | ||
94 | * Note that the bss is cleared *after* prom_init runs, so we have | ||
95 | * to make sure that any static or extern variables it accesses | ||
96 | * are put in the data segment. | ||
97 | */ | ||
98 | |||
99 | |||
100 | #define PROM_BUG() do { \ | ||
101 | prom_printf("kernel BUG at %s line 0x%x!\n", \ | ||
102 | RELOC(__FILE__), __LINE__); \ | ||
103 | __asm__ __volatile__(".long " BUG_ILLEGAL_INSTR); \ | ||
104 | } while (0) | ||
105 | |||
106 | #ifdef DEBUG_PROM | ||
107 | #define prom_debug(x...) prom_printf(x) | ||
108 | #else | ||
109 | #define prom_debug(x...) | ||
110 | #endif | ||
111 | |||
112 | |||
113 | typedef u32 prom_arg_t; | ||
114 | |||
115 | struct prom_args { | ||
116 | u32 service; | ||
117 | u32 nargs; | ||
118 | u32 nret; | ||
119 | prom_arg_t args[10]; | ||
120 | prom_arg_t *rets; /* Pointer to return values in args[16]. */ | ||
121 | }; | ||
122 | |||
123 | struct prom_t { | ||
124 | unsigned long entry; | ||
125 | ihandle root; | ||
126 | ihandle chosen; | ||
127 | int cpu; | ||
128 | ihandle stdout; | ||
129 | ihandle disp_node; | ||
130 | struct prom_args args; | ||
131 | unsigned long version; | ||
132 | unsigned long root_size_cells; | ||
133 | unsigned long root_addr_cells; | ||
134 | }; | ||
135 | |||
136 | struct pci_reg_property { | ||
137 | struct pci_address addr; | ||
138 | u32 size_hi; | ||
139 | u32 size_lo; | ||
140 | }; | ||
141 | |||
142 | struct mem_map_entry { | ||
143 | u64 base; | ||
144 | u64 size; | ||
145 | }; | ||
146 | |||
147 | typedef u32 cell_t; | ||
148 | |||
149 | extern void __start(unsigned long r3, unsigned long r4, unsigned long r5); | ||
150 | |||
151 | extern void enter_prom(struct prom_args *args, unsigned long entry); | ||
152 | extern void copy_and_flush(unsigned long dest, unsigned long src, | ||
153 | unsigned long size, unsigned long offset); | ||
154 | |||
155 | extern unsigned long klimit; | ||
156 | |||
157 | /* prom structure */ | ||
158 | static struct prom_t __initdata prom; | ||
159 | |||
160 | #define PROM_SCRATCH_SIZE 256 | ||
161 | |||
162 | static char __initdata of_stdout_device[256]; | ||
163 | static char __initdata prom_scratch[PROM_SCRATCH_SIZE]; | ||
164 | |||
165 | static unsigned long __initdata dt_header_start; | ||
166 | static unsigned long __initdata dt_struct_start, dt_struct_end; | ||
167 | static unsigned long __initdata dt_string_start, dt_string_end; | ||
168 | |||
169 | static unsigned long __initdata prom_initrd_start, prom_initrd_end; | ||
170 | |||
171 | static int __initdata iommu_force_on; | ||
172 | static int __initdata ppc64_iommu_off; | ||
173 | static int __initdata of_platform; | ||
174 | |||
175 | static char __initdata prom_cmd_line[COMMAND_LINE_SIZE]; | ||
176 | |||
177 | static unsigned long __initdata prom_memory_limit; | ||
178 | static unsigned long __initdata prom_tce_alloc_start; | ||
179 | static unsigned long __initdata prom_tce_alloc_end; | ||
180 | |||
181 | static unsigned long __initdata alloc_top; | ||
182 | static unsigned long __initdata alloc_top_high; | ||
183 | static unsigned long __initdata alloc_bottom; | ||
184 | static unsigned long __initdata rmo_top; | ||
185 | static unsigned long __initdata ram_top; | ||
186 | |||
187 | static struct mem_map_entry __initdata mem_reserve_map[MEM_RESERVE_MAP_SIZE]; | ||
188 | static int __initdata mem_reserve_cnt; | ||
189 | |||
190 | static cell_t __initdata regbuf[1024]; | ||
191 | |||
192 | |||
193 | #define MAX_CPU_THREADS 2 | ||
194 | |||
195 | /* TO GO */ | ||
196 | #ifdef CONFIG_HMT | ||
197 | struct { | ||
198 | unsigned int pir; | ||
199 | unsigned int threadid; | ||
200 | } hmt_thread_data[NR_CPUS]; | ||
201 | #endif /* CONFIG_HMT */ | ||
202 | |||
203 | /* | ||
204 | * This are used in calls to call_prom. The 4th and following | ||
205 | * arguments to call_prom should be 32-bit values. 64 bit values | ||
206 | * are truncated to 32 bits (and fortunately don't get interpreted | ||
207 | * as two arguments). | ||
208 | */ | ||
209 | #define ADDR(x) (u32) ((unsigned long)(x) - offset) | ||
210 | |||
211 | /* | ||
212 | * Error results ... some OF calls will return "-1" on error, some | ||
213 | * will return 0, some will return either. To simplify, here are | ||
214 | * macros to use with any ihandle or phandle return value to check if | ||
215 | * it is valid | ||
216 | */ | ||
217 | |||
218 | #define PROM_ERROR (-1u) | ||
219 | #define PHANDLE_VALID(p) ((p) != 0 && (p) != PROM_ERROR) | ||
220 | #define IHANDLE_VALID(i) ((i) != 0 && (i) != PROM_ERROR) | ||
221 | |||
222 | |||
223 | /* This is the one and *ONLY* place where we actually call open | ||
224 | * firmware from, since we need to make sure we're running in 32b | ||
225 | * mode when we do. We switch back to 64b mode upon return. | ||
226 | */ | ||
227 | |||
228 | static int __init call_prom(const char *service, int nargs, int nret, ...) | ||
229 | { | ||
230 | int i; | ||
231 | unsigned long offset = reloc_offset(); | ||
232 | struct prom_t *_prom = PTRRELOC(&prom); | ||
233 | va_list list; | ||
234 | |||
235 | _prom->args.service = ADDR(service); | ||
236 | _prom->args.nargs = nargs; | ||
237 | _prom->args.nret = nret; | ||
238 | _prom->args.rets = (prom_arg_t *)&(_prom->args.args[nargs]); | ||
239 | |||
240 | va_start(list, nret); | ||
241 | for (i=0; i < nargs; i++) | ||
242 | _prom->args.args[i] = va_arg(list, prom_arg_t); | ||
243 | va_end(list); | ||
244 | |||
245 | for (i=0; i < nret ;i++) | ||
246 | _prom->args.rets[i] = 0; | ||
247 | |||
248 | enter_prom(&_prom->args, _prom->entry); | ||
249 | |||
250 | return (nret > 0) ? _prom->args.rets[0] : 0; | ||
251 | } | ||
252 | |||
253 | |||
254 | static unsigned int __init prom_claim(unsigned long virt, unsigned long size, | ||
255 | unsigned long align) | ||
256 | { | ||
257 | return (unsigned int)call_prom("claim", 3, 1, | ||
258 | (prom_arg_t)virt, (prom_arg_t)size, | ||
259 | (prom_arg_t)align); | ||
260 | } | ||
261 | |||
262 | static void __init prom_print(const char *msg) | ||
263 | { | ||
264 | const char *p, *q; | ||
265 | unsigned long offset = reloc_offset(); | ||
266 | struct prom_t *_prom = PTRRELOC(&prom); | ||
267 | |||
268 | if (_prom->stdout == 0) | ||
269 | return; | ||
270 | |||
271 | for (p = msg; *p != 0; p = q) { | ||
272 | for (q = p; *q != 0 && *q != '\n'; ++q) | ||
273 | ; | ||
274 | if (q > p) | ||
275 | call_prom("write", 3, 1, _prom->stdout, p, q - p); | ||
276 | if (*q == 0) | ||
277 | break; | ||
278 | ++q; | ||
279 | call_prom("write", 3, 1, _prom->stdout, ADDR("\r\n"), 2); | ||
280 | } | ||
281 | } | ||
282 | |||
283 | |||
284 | static void __init prom_print_hex(unsigned long val) | ||
285 | { | ||
286 | unsigned long offset = reloc_offset(); | ||
287 | int i, nibbles = sizeof(val)*2; | ||
288 | char buf[sizeof(val)*2+1]; | ||
289 | struct prom_t *_prom = PTRRELOC(&prom); | ||
290 | |||
291 | for (i = nibbles-1; i >= 0; i--) { | ||
292 | buf[i] = (val & 0xf) + '0'; | ||
293 | if (buf[i] > '9') | ||
294 | buf[i] += ('a'-'0'-10); | ||
295 | val >>= 4; | ||
296 | } | ||
297 | buf[nibbles] = '\0'; | ||
298 | call_prom("write", 3, 1, _prom->stdout, buf, nibbles); | ||
299 | } | ||
300 | |||
301 | |||
302 | static void __init prom_printf(const char *format, ...) | ||
303 | { | ||
304 | unsigned long offset = reloc_offset(); | ||
305 | const char *p, *q, *s; | ||
306 | va_list args; | ||
307 | unsigned long v; | ||
308 | struct prom_t *_prom = PTRRELOC(&prom); | ||
309 | |||
310 | va_start(args, format); | ||
311 | for (p = PTRRELOC(format); *p != 0; p = q) { | ||
312 | for (q = p; *q != 0 && *q != '\n' && *q != '%'; ++q) | ||
313 | ; | ||
314 | if (q > p) | ||
315 | call_prom("write", 3, 1, _prom->stdout, p, q - p); | ||
316 | if (*q == 0) | ||
317 | break; | ||
318 | if (*q == '\n') { | ||
319 | ++q; | ||
320 | call_prom("write", 3, 1, _prom->stdout, | ||
321 | ADDR("\r\n"), 2); | ||
322 | continue; | ||
323 | } | ||
324 | ++q; | ||
325 | if (*q == 0) | ||
326 | break; | ||
327 | switch (*q) { | ||
328 | case 's': | ||
329 | ++q; | ||
330 | s = va_arg(args, const char *); | ||
331 | prom_print(s); | ||
332 | break; | ||
333 | case 'x': | ||
334 | ++q; | ||
335 | v = va_arg(args, unsigned long); | ||
336 | prom_print_hex(v); | ||
337 | break; | ||
338 | } | ||
339 | } | ||
340 | } | ||
341 | |||
342 | |||
343 | static void __init __attribute__((noreturn)) prom_panic(const char *reason) | ||
344 | { | ||
345 | unsigned long offset = reloc_offset(); | ||
346 | |||
347 | prom_print(PTRRELOC(reason)); | ||
348 | /* ToDo: should put up an SRC here */ | ||
349 | call_prom("exit", 0, 0); | ||
350 | |||
351 | for (;;) /* should never get here */ | ||
352 | ; | ||
353 | } | ||
354 | |||
355 | |||
356 | static int __init prom_next_node(phandle *nodep) | ||
357 | { | ||
358 | phandle node; | ||
359 | |||
360 | if ((node = *nodep) != 0 | ||
361 | && (*nodep = call_prom("child", 1, 1, node)) != 0) | ||
362 | return 1; | ||
363 | if ((*nodep = call_prom("peer", 1, 1, node)) != 0) | ||
364 | return 1; | ||
365 | for (;;) { | ||
366 | if ((node = call_prom("parent", 1, 1, node)) == 0) | ||
367 | return 0; | ||
368 | if ((*nodep = call_prom("peer", 1, 1, node)) != 0) | ||
369 | return 1; | ||
370 | } | ||
371 | } | ||
372 | |||
373 | static int __init prom_getprop(phandle node, const char *pname, | ||
374 | void *value, size_t valuelen) | ||
375 | { | ||
376 | unsigned long offset = reloc_offset(); | ||
377 | |||
378 | return call_prom("getprop", 4, 1, node, ADDR(pname), | ||
379 | (u32)(unsigned long) value, (u32) valuelen); | ||
380 | } | ||
381 | |||
382 | static int __init prom_getproplen(phandle node, const char *pname) | ||
383 | { | ||
384 | unsigned long offset = reloc_offset(); | ||
385 | |||
386 | return call_prom("getproplen", 2, 1, node, ADDR(pname)); | ||
387 | } | ||
388 | |||
389 | static int __init prom_setprop(phandle node, const char *pname, | ||
390 | void *value, size_t valuelen) | ||
391 | { | ||
392 | unsigned long offset = reloc_offset(); | ||
393 | |||
394 | return call_prom("setprop", 4, 1, node, ADDR(pname), | ||
395 | (u32)(unsigned long) value, (u32) valuelen); | ||
396 | } | ||
397 | |||
398 | /* We can't use the standard versions because of RELOC headaches. */ | ||
399 | #define isxdigit(c) (('0' <= (c) && (c) <= '9') \ | ||
400 | || ('a' <= (c) && (c) <= 'f') \ | ||
401 | || ('A' <= (c) && (c) <= 'F')) | ||
402 | |||
403 | #define isdigit(c) ('0' <= (c) && (c) <= '9') | ||
404 | #define islower(c) ('a' <= (c) && (c) <= 'z') | ||
405 | #define toupper(c) (islower(c) ? ((c) - 'a' + 'A') : (c)) | ||
406 | |||
407 | unsigned long prom_strtoul(const char *cp, const char **endp) | ||
408 | { | ||
409 | unsigned long result = 0, base = 10, value; | ||
410 | |||
411 | if (*cp == '0') { | ||
412 | base = 8; | ||
413 | cp++; | ||
414 | if (toupper(*cp) == 'X') { | ||
415 | cp++; | ||
416 | base = 16; | ||
417 | } | ||
418 | } | ||
419 | |||
420 | while (isxdigit(*cp) && | ||
421 | (value = isdigit(*cp) ? *cp - '0' : toupper(*cp) - 'A' + 10) < base) { | ||
422 | result = result * base + value; | ||
423 | cp++; | ||
424 | } | ||
425 | |||
426 | if (endp) | ||
427 | *endp = cp; | ||
428 | |||
429 | return result; | ||
430 | } | ||
431 | |||
432 | unsigned long prom_memparse(const char *ptr, const char **retptr) | ||
433 | { | ||
434 | unsigned long ret = prom_strtoul(ptr, retptr); | ||
435 | int shift = 0; | ||
436 | |||
437 | /* | ||
438 | * We can't use a switch here because GCC *may* generate a | ||
439 | * jump table which won't work, because we're not running at | ||
440 | * the address we're linked at. | ||
441 | */ | ||
442 | if ('G' == **retptr || 'g' == **retptr) | ||
443 | shift = 30; | ||
444 | |||
445 | if ('M' == **retptr || 'm' == **retptr) | ||
446 | shift = 20; | ||
447 | |||
448 | if ('K' == **retptr || 'k' == **retptr) | ||
449 | shift = 10; | ||
450 | |||
451 | if (shift) { | ||
452 | ret <<= shift; | ||
453 | (*retptr)++; | ||
454 | } | ||
455 | |||
456 | return ret; | ||
457 | } | ||
458 | |||
459 | /* | ||
460 | * Early parsing of the command line passed to the kernel, used for | ||
461 | * "mem=x" and the options that affect the iommu | ||
462 | */ | ||
463 | static void __init early_cmdline_parse(void) | ||
464 | { | ||
465 | unsigned long offset = reloc_offset(); | ||
466 | struct prom_t *_prom = PTRRELOC(&prom); | ||
467 | char *opt, *p; | ||
468 | int l = 0; | ||
469 | |||
470 | RELOC(prom_cmd_line[0]) = 0; | ||
471 | p = RELOC(prom_cmd_line); | ||
472 | if ((long)_prom->chosen > 0) | ||
473 | l = prom_getprop(_prom->chosen, "bootargs", p, COMMAND_LINE_SIZE-1); | ||
474 | #ifdef CONFIG_CMDLINE | ||
475 | if (l == 0) /* dbl check */ | ||
476 | strlcpy(RELOC(prom_cmd_line), | ||
477 | RELOC(CONFIG_CMDLINE), sizeof(prom_cmd_line)); | ||
478 | #endif /* CONFIG_CMDLINE */ | ||
479 | prom_printf("command line: %s\n", RELOC(prom_cmd_line)); | ||
480 | |||
481 | opt = strstr(RELOC(prom_cmd_line), RELOC("iommu=")); | ||
482 | if (opt) { | ||
483 | prom_printf("iommu opt is: %s\n", opt); | ||
484 | opt += 6; | ||
485 | while (*opt && *opt == ' ') | ||
486 | opt++; | ||
487 | if (!strncmp(opt, RELOC("off"), 3)) | ||
488 | RELOC(ppc64_iommu_off) = 1; | ||
489 | else if (!strncmp(opt, RELOC("force"), 5)) | ||
490 | RELOC(iommu_force_on) = 1; | ||
491 | } | ||
492 | |||
493 | opt = strstr(RELOC(prom_cmd_line), RELOC("mem=")); | ||
494 | if (opt) { | ||
495 | opt += 4; | ||
496 | RELOC(prom_memory_limit) = prom_memparse(opt, (const char **)&opt); | ||
497 | /* Align to 16 MB == size of large page */ | ||
498 | RELOC(prom_memory_limit) = ALIGN(RELOC(prom_memory_limit), 0x1000000); | ||
499 | } | ||
500 | } | ||
501 | |||
502 | /* | ||
503 | * To tell the firmware what our capabilities are, we have to pass | ||
504 | * it a fake 32-bit ELF header containing a couple of PT_NOTE sections | ||
505 | * that contain structures that contain the actual values. | ||
506 | */ | ||
507 | static struct fake_elf { | ||
508 | Elf32_Ehdr elfhdr; | ||
509 | Elf32_Phdr phdr[2]; | ||
510 | struct chrpnote { | ||
511 | u32 namesz; | ||
512 | u32 descsz; | ||
513 | u32 type; | ||
514 | char name[8]; /* "PowerPC" */ | ||
515 | struct chrpdesc { | ||
516 | u32 real_mode; | ||
517 | u32 real_base; | ||
518 | u32 real_size; | ||
519 | u32 virt_base; | ||
520 | u32 virt_size; | ||
521 | u32 load_base; | ||
522 | } chrpdesc; | ||
523 | } chrpnote; | ||
524 | struct rpanote { | ||
525 | u32 namesz; | ||
526 | u32 descsz; | ||
527 | u32 type; | ||
528 | char name[24]; /* "IBM,RPA-Client-Config" */ | ||
529 | struct rpadesc { | ||
530 | u32 lpar_affinity; | ||
531 | u32 min_rmo_size; | ||
532 | u32 min_rmo_percent; | ||
533 | u32 max_pft_size; | ||
534 | u32 splpar; | ||
535 | u32 min_load; | ||
536 | u32 new_mem_def; | ||
537 | u32 ignore_me; | ||
538 | } rpadesc; | ||
539 | } rpanote; | ||
540 | } fake_elf = { | ||
541 | .elfhdr = { | ||
542 | .e_ident = { 0x7f, 'E', 'L', 'F', | ||
543 | ELFCLASS32, ELFDATA2MSB, EV_CURRENT }, | ||
544 | .e_type = ET_EXEC, /* yeah right */ | ||
545 | .e_machine = EM_PPC, | ||
546 | .e_version = EV_CURRENT, | ||
547 | .e_phoff = offsetof(struct fake_elf, phdr), | ||
548 | .e_phentsize = sizeof(Elf32_Phdr), | ||
549 | .e_phnum = 2 | ||
550 | }, | ||
551 | .phdr = { | ||
552 | [0] = { | ||
553 | .p_type = PT_NOTE, | ||
554 | .p_offset = offsetof(struct fake_elf, chrpnote), | ||
555 | .p_filesz = sizeof(struct chrpnote) | ||
556 | }, [1] = { | ||
557 | .p_type = PT_NOTE, | ||
558 | .p_offset = offsetof(struct fake_elf, rpanote), | ||
559 | .p_filesz = sizeof(struct rpanote) | ||
560 | } | ||
561 | }, | ||
562 | .chrpnote = { | ||
563 | .namesz = sizeof("PowerPC"), | ||
564 | .descsz = sizeof(struct chrpdesc), | ||
565 | .type = 0x1275, | ||
566 | .name = "PowerPC", | ||
567 | .chrpdesc = { | ||
568 | .real_mode = ~0U, /* ~0 means "don't care" */ | ||
569 | .real_base = ~0U, | ||
570 | .real_size = ~0U, | ||
571 | .virt_base = ~0U, | ||
572 | .virt_size = ~0U, | ||
573 | .load_base = ~0U | ||
574 | }, | ||
575 | }, | ||
576 | .rpanote = { | ||
577 | .namesz = sizeof("IBM,RPA-Client-Config"), | ||
578 | .descsz = sizeof(struct rpadesc), | ||
579 | .type = 0x12759999, | ||
580 | .name = "IBM,RPA-Client-Config", | ||
581 | .rpadesc = { | ||
582 | .lpar_affinity = 0, | ||
583 | .min_rmo_size = 64, /* in megabytes */ | ||
584 | .min_rmo_percent = 0, | ||
585 | .max_pft_size = 48, /* 2^48 bytes max PFT size */ | ||
586 | .splpar = 1, | ||
587 | .min_load = ~0U, | ||
588 | .new_mem_def = 0 | ||
589 | } | ||
590 | } | ||
591 | }; | ||
592 | |||
593 | static void __init prom_send_capabilities(void) | ||
594 | { | ||
595 | unsigned long offset = reloc_offset(); | ||
596 | ihandle elfloader; | ||
597 | |||
598 | elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader")); | ||
599 | if (elfloader == 0) { | ||
600 | prom_printf("couldn't open /packages/elf-loader\n"); | ||
601 | return; | ||
602 | } | ||
603 | call_prom("call-method", 3, 1, ADDR("process-elf-header"), | ||
604 | elfloader, ADDR(&fake_elf)); | ||
605 | call_prom("close", 1, 0, elfloader); | ||
606 | } | ||
607 | |||
608 | /* | ||
609 | * Memory allocation strategy... our layout is normally: | ||
610 | * | ||
611 | * at 14Mb or more we vmlinux, then a gap and initrd. In some rare cases, initrd | ||
612 | * might end up beeing before the kernel though. We assume this won't override | ||
613 | * the final kernel at 0, we have no provision to handle that in this version, | ||
614 | * but it should hopefully never happen. | ||
615 | * | ||
616 | * alloc_top is set to the top of RMO, eventually shrink down if the TCEs overlap | ||
617 | * alloc_bottom is set to the top of kernel/initrd | ||
618 | * | ||
619 | * from there, allocations are done that way : rtas is allocated topmost, and | ||
620 | * the device-tree is allocated from the bottom. We try to grow the device-tree | ||
621 | * allocation as we progress. If we can't, then we fail, we don't currently have | ||
622 | * a facility to restart elsewhere, but that shouldn't be necessary neither | ||
623 | * | ||
624 | * Note that calls to reserve_mem have to be done explicitely, memory allocated | ||
625 | * with either alloc_up or alloc_down isn't automatically reserved. | ||
626 | */ | ||
627 | |||
628 | |||
629 | /* | ||
630 | * Allocates memory in the RMO upward from the kernel/initrd | ||
631 | * | ||
632 | * When align is 0, this is a special case, it means to allocate in place | ||
633 | * at the current location of alloc_bottom or fail (that is basically | ||
634 | * extending the previous allocation). Used for the device-tree flattening | ||
635 | */ | ||
636 | static unsigned long __init alloc_up(unsigned long size, unsigned long align) | ||
637 | { | ||
638 | unsigned long offset = reloc_offset(); | ||
639 | unsigned long base = _ALIGN_UP(RELOC(alloc_bottom), align); | ||
640 | unsigned long addr = 0; | ||
641 | |||
642 | prom_debug("alloc_up(%x, %x)\n", size, align); | ||
643 | if (RELOC(ram_top) == 0) | ||
644 | prom_panic("alloc_up() called with mem not initialized\n"); | ||
645 | |||
646 | if (align) | ||
647 | base = _ALIGN_UP(RELOC(alloc_bottom), align); | ||
648 | else | ||
649 | base = RELOC(alloc_bottom); | ||
650 | |||
651 | for(; (base + size) <= RELOC(alloc_top); | ||
652 | base = _ALIGN_UP(base + 0x100000, align)) { | ||
653 | prom_debug(" trying: 0x%x\n\r", base); | ||
654 | addr = (unsigned long)prom_claim(base, size, 0); | ||
655 | if (addr != PROM_ERROR) | ||
656 | break; | ||
657 | addr = 0; | ||
658 | if (align == 0) | ||
659 | break; | ||
660 | } | ||
661 | if (addr == 0) | ||
662 | return 0; | ||
663 | RELOC(alloc_bottom) = addr; | ||
664 | |||
665 | prom_debug(" -> %x\n", addr); | ||
666 | prom_debug(" alloc_bottom : %x\n", RELOC(alloc_bottom)); | ||
667 | prom_debug(" alloc_top : %x\n", RELOC(alloc_top)); | ||
668 | prom_debug(" alloc_top_hi : %x\n", RELOC(alloc_top_high)); | ||
669 | prom_debug(" rmo_top : %x\n", RELOC(rmo_top)); | ||
670 | prom_debug(" ram_top : %x\n", RELOC(ram_top)); | ||
671 | |||
672 | return addr; | ||
673 | } | ||
674 | |||
675 | /* | ||
676 | * Allocates memory downard, either from top of RMO, or if highmem | ||
677 | * is set, from the top of RAM. Note that this one doesn't handle | ||
678 | * failures. In does claim memory if highmem is not set. | ||
679 | */ | ||
680 | static unsigned long __init alloc_down(unsigned long size, unsigned long align, | ||
681 | int highmem) | ||
682 | { | ||
683 | unsigned long offset = reloc_offset(); | ||
684 | unsigned long base, addr = 0; | ||
685 | |||
686 | prom_debug("alloc_down(%x, %x, %s)\n", size, align, | ||
687 | highmem ? RELOC("(high)") : RELOC("(low)")); | ||
688 | if (RELOC(ram_top) == 0) | ||
689 | prom_panic("alloc_down() called with mem not initialized\n"); | ||
690 | |||
691 | if (highmem) { | ||
692 | /* Carve out storage for the TCE table. */ | ||
693 | addr = _ALIGN_DOWN(RELOC(alloc_top_high) - size, align); | ||
694 | if (addr <= RELOC(alloc_bottom)) | ||
695 | return 0; | ||
696 | else { | ||
697 | /* Will we bump into the RMO ? If yes, check out that we | ||
698 | * didn't overlap existing allocations there, if we did, | ||
699 | * we are dead, we must be the first in town ! | ||
700 | */ | ||
701 | if (addr < RELOC(rmo_top)) { | ||
702 | /* Good, we are first */ | ||
703 | if (RELOC(alloc_top) == RELOC(rmo_top)) | ||
704 | RELOC(alloc_top) = RELOC(rmo_top) = addr; | ||
705 | else | ||
706 | return 0; | ||
707 | } | ||
708 | RELOC(alloc_top_high) = addr; | ||
709 | } | ||
710 | goto bail; | ||
711 | } | ||
712 | |||
713 | base = _ALIGN_DOWN(RELOC(alloc_top) - size, align); | ||
714 | for(; base > RELOC(alloc_bottom); base = _ALIGN_DOWN(base - 0x100000, align)) { | ||
715 | prom_debug(" trying: 0x%x\n\r", base); | ||
716 | addr = (unsigned long)prom_claim(base, size, 0); | ||
717 | if (addr != PROM_ERROR) | ||
718 | break; | ||
719 | addr = 0; | ||
720 | } | ||
721 | if (addr == 0) | ||
722 | return 0; | ||
723 | RELOC(alloc_top) = addr; | ||
724 | |||
725 | bail: | ||
726 | prom_debug(" -> %x\n", addr); | ||
727 | prom_debug(" alloc_bottom : %x\n", RELOC(alloc_bottom)); | ||
728 | prom_debug(" alloc_top : %x\n", RELOC(alloc_top)); | ||
729 | prom_debug(" alloc_top_hi : %x\n", RELOC(alloc_top_high)); | ||
730 | prom_debug(" rmo_top : %x\n", RELOC(rmo_top)); | ||
731 | prom_debug(" ram_top : %x\n", RELOC(ram_top)); | ||
732 | |||
733 | return addr; | ||
734 | } | ||
735 | |||
736 | /* | ||
737 | * Parse a "reg" cell | ||
738 | */ | ||
739 | static unsigned long __init prom_next_cell(int s, cell_t **cellp) | ||
740 | { | ||
741 | cell_t *p = *cellp; | ||
742 | unsigned long r = 0; | ||
743 | |||
744 | /* Ignore more than 2 cells */ | ||
745 | while (s > 2) { | ||
746 | p++; | ||
747 | s--; | ||
748 | } | ||
749 | while (s) { | ||
750 | r <<= 32; | ||
751 | r |= *(p++); | ||
752 | s--; | ||
753 | } | ||
754 | |||
755 | *cellp = p; | ||
756 | return r; | ||
757 | } | ||
758 | |||
759 | /* | ||
760 | * Very dumb function for adding to the memory reserve list, but | ||
761 | * we don't need anything smarter at this point | ||
762 | * | ||
763 | * XXX Eventually check for collisions. They should NEVER happen | ||
764 | * if problems seem to show up, it would be a good start to track | ||
765 | * them down. | ||
766 | */ | ||
767 | static void reserve_mem(unsigned long base, unsigned long size) | ||
768 | { | ||
769 | unsigned long offset = reloc_offset(); | ||
770 | unsigned long top = base + size; | ||
771 | unsigned long cnt = RELOC(mem_reserve_cnt); | ||
772 | |||
773 | if (size == 0) | ||
774 | return; | ||
775 | |||
776 | /* We need to always keep one empty entry so that we | ||
777 | * have our terminator with "size" set to 0 since we are | ||
778 | * dumb and just copy this entire array to the boot params | ||
779 | */ | ||
780 | base = _ALIGN_DOWN(base, PAGE_SIZE); | ||
781 | top = _ALIGN_UP(top, PAGE_SIZE); | ||
782 | size = top - base; | ||
783 | |||
784 | if (cnt >= (MEM_RESERVE_MAP_SIZE - 1)) | ||
785 | prom_panic("Memory reserve map exhausted !\n"); | ||
786 | RELOC(mem_reserve_map)[cnt].base = base; | ||
787 | RELOC(mem_reserve_map)[cnt].size = size; | ||
788 | RELOC(mem_reserve_cnt) = cnt + 1; | ||
789 | } | ||
790 | |||
791 | /* | ||
792 | * Initialize memory allocation mecanism, parse "memory" nodes and | ||
793 | * obtain that way the top of memory and RMO to setup out local allocator | ||
794 | */ | ||
795 | static void __init prom_init_mem(void) | ||
796 | { | ||
797 | phandle node; | ||
798 | char *path, type[64]; | ||
799 | unsigned int plen; | ||
800 | cell_t *p, *endp; | ||
801 | unsigned long offset = reloc_offset(); | ||
802 | struct prom_t *_prom = PTRRELOC(&prom); | ||
803 | |||
804 | /* | ||
805 | * We iterate the memory nodes to find | ||
806 | * 1) top of RMO (first node) | ||
807 | * 2) top of memory | ||
808 | */ | ||
809 | prom_debug("root_addr_cells: %x\n", (long)_prom->root_addr_cells); | ||
810 | prom_debug("root_size_cells: %x\n", (long)_prom->root_size_cells); | ||
811 | |||
812 | prom_debug("scanning memory:\n"); | ||
813 | path = RELOC(prom_scratch); | ||
814 | |||
815 | for (node = 0; prom_next_node(&node); ) { | ||
816 | type[0] = 0; | ||
817 | prom_getprop(node, "device_type", type, sizeof(type)); | ||
818 | |||
819 | if (strcmp(type, RELOC("memory"))) | ||
820 | continue; | ||
821 | |||
822 | plen = prom_getprop(node, "reg", RELOC(regbuf), sizeof(regbuf)); | ||
823 | if (plen > sizeof(regbuf)) { | ||
824 | prom_printf("memory node too large for buffer !\n"); | ||
825 | plen = sizeof(regbuf); | ||
826 | } | ||
827 | p = RELOC(regbuf); | ||
828 | endp = p + (plen / sizeof(cell_t)); | ||
829 | |||
830 | #ifdef DEBUG_PROM | ||
831 | memset(path, 0, PROM_SCRATCH_SIZE); | ||
832 | call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1); | ||
833 | prom_debug(" node %s :\n", path); | ||
834 | #endif /* DEBUG_PROM */ | ||
835 | |||
836 | while ((endp - p) >= (_prom->root_addr_cells + _prom->root_size_cells)) { | ||
837 | unsigned long base, size; | ||
838 | |||
839 | base = prom_next_cell(_prom->root_addr_cells, &p); | ||
840 | size = prom_next_cell(_prom->root_size_cells, &p); | ||
841 | |||
842 | if (size == 0) | ||
843 | continue; | ||
844 | prom_debug(" %x %x\n", base, size); | ||
845 | if (base == 0) | ||
846 | RELOC(rmo_top) = size; | ||
847 | if ((base + size) > RELOC(ram_top)) | ||
848 | RELOC(ram_top) = base + size; | ||
849 | } | ||
850 | } | ||
851 | |||
852 | RELOC(alloc_bottom) = PAGE_ALIGN(RELOC(klimit) - offset + 0x4000); | ||
853 | |||
854 | /* Check if we have an initrd after the kernel, if we do move our bottom | ||
855 | * point to after it | ||
856 | */ | ||
857 | if (RELOC(prom_initrd_start)) { | ||
858 | if (RELOC(prom_initrd_end) > RELOC(alloc_bottom)) | ||
859 | RELOC(alloc_bottom) = PAGE_ALIGN(RELOC(prom_initrd_end)); | ||
860 | } | ||
861 | |||
862 | /* | ||
863 | * If prom_memory_limit is set we reduce the upper limits *except* for | ||
864 | * alloc_top_high. This must be the real top of RAM so we can put | ||
865 | * TCE's up there. | ||
866 | */ | ||
867 | |||
868 | RELOC(alloc_top_high) = RELOC(ram_top); | ||
869 | |||
870 | if (RELOC(prom_memory_limit)) { | ||
871 | if (RELOC(prom_memory_limit) <= RELOC(alloc_bottom)) { | ||
872 | prom_printf("Ignoring mem=%x <= alloc_bottom.\n", | ||
873 | RELOC(prom_memory_limit)); | ||
874 | RELOC(prom_memory_limit) = 0; | ||
875 | } else if (RELOC(prom_memory_limit) >= RELOC(ram_top)) { | ||
876 | prom_printf("Ignoring mem=%x >= ram_top.\n", | ||
877 | RELOC(prom_memory_limit)); | ||
878 | RELOC(prom_memory_limit) = 0; | ||
879 | } else { | ||
880 | RELOC(ram_top) = RELOC(prom_memory_limit); | ||
881 | RELOC(rmo_top) = min(RELOC(rmo_top), RELOC(prom_memory_limit)); | ||
882 | } | ||
883 | } | ||
884 | |||
885 | /* | ||
886 | * Setup our top alloc point, that is top of RMO or top of | ||
887 | * segment 0 when running non-LPAR. | ||
888 | */ | ||
889 | if ( RELOC(of_platform) == PLATFORM_PSERIES_LPAR ) | ||
890 | RELOC(alloc_top) = RELOC(rmo_top); | ||
891 | else | ||
892 | /* Some RS64 machines have buggy firmware where claims up at 1GB | ||
893 | * fails. Cap at 768MB as a workaround. Still plenty of room. | ||
894 | */ | ||
895 | RELOC(alloc_top) = RELOC(rmo_top) = min(0x30000000ul, RELOC(ram_top)); | ||
896 | |||
897 | prom_printf("memory layout at init:\n"); | ||
898 | prom_printf(" memory_limit : %x (16 MB aligned)\n", RELOC(prom_memory_limit)); | ||
899 | prom_printf(" alloc_bottom : %x\n", RELOC(alloc_bottom)); | ||
900 | prom_printf(" alloc_top : %x\n", RELOC(alloc_top)); | ||
901 | prom_printf(" alloc_top_hi : %x\n", RELOC(alloc_top_high)); | ||
902 | prom_printf(" rmo_top : %x\n", RELOC(rmo_top)); | ||
903 | prom_printf(" ram_top : %x\n", RELOC(ram_top)); | ||
904 | } | ||
905 | |||
906 | |||
907 | /* | ||
908 | * Allocate room for and instanciate RTAS | ||
909 | */ | ||
910 | static void __init prom_instantiate_rtas(void) | ||
911 | { | ||
912 | unsigned long offset = reloc_offset(); | ||
913 | struct prom_t *_prom = PTRRELOC(&prom); | ||
914 | phandle rtas_node; | ||
915 | ihandle rtas_inst; | ||
916 | u32 base, entry = 0; | ||
917 | u32 size = 0; | ||
918 | |||
919 | prom_debug("prom_instantiate_rtas: start...\n"); | ||
920 | |||
921 | rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas")); | ||
922 | prom_debug("rtas_node: %x\n", rtas_node); | ||
923 | if (!PHANDLE_VALID(rtas_node)) | ||
924 | return; | ||
925 | |||
926 | prom_getprop(rtas_node, "rtas-size", &size, sizeof(size)); | ||
927 | if (size == 0) | ||
928 | return; | ||
929 | |||
930 | base = alloc_down(size, PAGE_SIZE, 0); | ||
931 | if (base == 0) { | ||
932 | prom_printf("RTAS allocation failed !\n"); | ||
933 | return; | ||
934 | } | ||
935 | |||
936 | rtas_inst = call_prom("open", 1, 1, ADDR("/rtas")); | ||
937 | if (!IHANDLE_VALID(rtas_inst)) { | ||
938 | prom_printf("opening rtas package failed"); | ||
939 | return; | ||
940 | } | ||
941 | |||
942 | prom_printf("instantiating rtas at 0x%x ...", base); | ||
943 | |||
944 | if (call_prom("call-method", 3, 2, | ||
945 | ADDR("instantiate-rtas"), | ||
946 | rtas_inst, base) != PROM_ERROR) { | ||
947 | entry = (long)_prom->args.rets[1]; | ||
948 | } | ||
949 | if (entry == 0) { | ||
950 | prom_printf(" failed\n"); | ||
951 | return; | ||
952 | } | ||
953 | prom_printf(" done\n"); | ||
954 | |||
955 | reserve_mem(base, size); | ||
956 | |||
957 | prom_setprop(rtas_node, "linux,rtas-base", &base, sizeof(base)); | ||
958 | prom_setprop(rtas_node, "linux,rtas-entry", &entry, sizeof(entry)); | ||
959 | |||
960 | prom_debug("rtas base = 0x%x\n", base); | ||
961 | prom_debug("rtas entry = 0x%x\n", entry); | ||
962 | prom_debug("rtas size = 0x%x\n", (long)size); | ||
963 | |||
964 | prom_debug("prom_instantiate_rtas: end...\n"); | ||
965 | } | ||
966 | |||
967 | |||
968 | /* | ||
969 | * Allocate room for and initialize TCE tables | ||
970 | */ | ||
971 | static void __init prom_initialize_tce_table(void) | ||
972 | { | ||
973 | phandle node; | ||
974 | ihandle phb_node; | ||
975 | unsigned long offset = reloc_offset(); | ||
976 | char compatible[64], type[64], model[64]; | ||
977 | char *path = RELOC(prom_scratch); | ||
978 | u64 base, align; | ||
979 | u32 minalign, minsize; | ||
980 | u64 tce_entry, *tce_entryp; | ||
981 | u64 local_alloc_top, local_alloc_bottom; | ||
982 | u64 i; | ||
983 | |||
984 | if (RELOC(ppc64_iommu_off)) | ||
985 | return; | ||
986 | |||
987 | prom_debug("starting prom_initialize_tce_table\n"); | ||
988 | |||
989 | /* Cache current top of allocs so we reserve a single block */ | ||
990 | local_alloc_top = RELOC(alloc_top_high); | ||
991 | local_alloc_bottom = local_alloc_top; | ||
992 | |||
993 | /* Search all nodes looking for PHBs. */ | ||
994 | for (node = 0; prom_next_node(&node); ) { | ||
995 | compatible[0] = 0; | ||
996 | type[0] = 0; | ||
997 | model[0] = 0; | ||
998 | prom_getprop(node, "compatible", | ||
999 | compatible, sizeof(compatible)); | ||
1000 | prom_getprop(node, "device_type", type, sizeof(type)); | ||
1001 | prom_getprop(node, "model", model, sizeof(model)); | ||
1002 | |||
1003 | if ((type[0] == 0) || (strstr(type, RELOC("pci")) == NULL)) | ||
1004 | continue; | ||
1005 | |||
1006 | /* Keep the old logic in tack to avoid regression. */ | ||
1007 | if (compatible[0] != 0) { | ||
1008 | if ((strstr(compatible, RELOC("python")) == NULL) && | ||
1009 | (strstr(compatible, RELOC("Speedwagon")) == NULL) && | ||
1010 | (strstr(compatible, RELOC("Winnipeg")) == NULL)) | ||
1011 | continue; | ||
1012 | } else if (model[0] != 0) { | ||
1013 | if ((strstr(model, RELOC("ython")) == NULL) && | ||
1014 | (strstr(model, RELOC("peedwagon")) == NULL) && | ||
1015 | (strstr(model, RELOC("innipeg")) == NULL)) | ||
1016 | continue; | ||
1017 | } | ||
1018 | |||
1019 | if (prom_getprop(node, "tce-table-minalign", &minalign, | ||
1020 | sizeof(minalign)) == PROM_ERROR) | ||
1021 | minalign = 0; | ||
1022 | if (prom_getprop(node, "tce-table-minsize", &minsize, | ||
1023 | sizeof(minsize)) == PROM_ERROR) | ||
1024 | minsize = 4UL << 20; | ||
1025 | |||
1026 | /* | ||
1027 | * Even though we read what OF wants, we just set the table | ||
1028 | * size to 4 MB. This is enough to map 2GB of PCI DMA space. | ||
1029 | * By doing this, we avoid the pitfalls of trying to DMA to | ||
1030 | * MMIO space and the DMA alias hole. | ||
1031 | * | ||
1032 | * On POWER4, firmware sets the TCE region by assuming | ||
1033 | * each TCE table is 8MB. Using this memory for anything | ||
1034 | * else will impact performance, so we always allocate 8MB. | ||
1035 | * Anton | ||
1036 | */ | ||
1037 | if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p)) | ||
1038 | minsize = 8UL << 20; | ||
1039 | else | ||
1040 | minsize = 4UL << 20; | ||
1041 | |||
1042 | /* Align to the greater of the align or size */ | ||
1043 | align = max(minalign, minsize); | ||
1044 | base = alloc_down(minsize, align, 1); | ||
1045 | if (base == 0) | ||
1046 | prom_panic("ERROR, cannot find space for TCE table.\n"); | ||
1047 | if (base < local_alloc_bottom) | ||
1048 | local_alloc_bottom = base; | ||
1049 | |||
1050 | /* Save away the TCE table attributes for later use. */ | ||
1051 | prom_setprop(node, "linux,tce-base", &base, sizeof(base)); | ||
1052 | prom_setprop(node, "linux,tce-size", &minsize, sizeof(minsize)); | ||
1053 | |||
1054 | /* It seems OF doesn't null-terminate the path :-( */ | ||
1055 | memset(path, 0, sizeof(path)); | ||
1056 | /* Call OF to setup the TCE hardware */ | ||
1057 | if (call_prom("package-to-path", 3, 1, node, | ||
1058 | path, PROM_SCRATCH_SIZE-1) == PROM_ERROR) { | ||
1059 | prom_printf("package-to-path failed\n"); | ||
1060 | } | ||
1061 | |||
1062 | prom_debug("TCE table: %s\n", path); | ||
1063 | prom_debug("\tnode = 0x%x\n", node); | ||
1064 | prom_debug("\tbase = 0x%x\n", base); | ||
1065 | prom_debug("\tsize = 0x%x\n", minsize); | ||
1066 | |||
1067 | /* Initialize the table to have a one-to-one mapping | ||
1068 | * over the allocated size. | ||
1069 | */ | ||
1070 | tce_entryp = (unsigned long *)base; | ||
1071 | for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) { | ||
1072 | tce_entry = (i << PAGE_SHIFT); | ||
1073 | tce_entry |= 0x3; | ||
1074 | *tce_entryp = tce_entry; | ||
1075 | } | ||
1076 | |||
1077 | prom_printf("opening PHB %s", path); | ||
1078 | phb_node = call_prom("open", 1, 1, path); | ||
1079 | if (phb_node == 0) | ||
1080 | prom_printf("... failed\n"); | ||
1081 | else | ||
1082 | prom_printf("... done\n"); | ||
1083 | |||
1084 | call_prom("call-method", 6, 0, ADDR("set-64-bit-addressing"), | ||
1085 | phb_node, -1, minsize, | ||
1086 | (u32) base, (u32) (base >> 32)); | ||
1087 | call_prom("close", 1, 0, phb_node); | ||
1088 | } | ||
1089 | |||
1090 | reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom); | ||
1091 | |||
1092 | if (RELOC(prom_memory_limit)) { | ||
1093 | /* | ||
1094 | * We align the start to a 16MB boundary so we can map the TCE area | ||
1095 | * using large pages if possible. The end should be the top of RAM | ||
1096 | * so no need to align it. | ||
1097 | */ | ||
1098 | RELOC(prom_tce_alloc_start) = _ALIGN_DOWN(local_alloc_bottom, 0x1000000); | ||
1099 | RELOC(prom_tce_alloc_end) = local_alloc_top; | ||
1100 | } | ||
1101 | |||
1102 | /* Flag the first invalid entry */ | ||
1103 | prom_debug("ending prom_initialize_tce_table\n"); | ||
1104 | } | ||
1105 | |||
1106 | /* | ||
1107 | * With CHRP SMP we need to use the OF to start the other | ||
1108 | * processors so we can't wait until smp_boot_cpus (the OF is | ||
1109 | * trashed by then) so we have to put the processors into | ||
1110 | * a holding pattern controlled by the kernel (not OF) before | ||
1111 | * we destroy the OF. | ||
1112 | * | ||
1113 | * This uses a chunk of low memory, puts some holding pattern | ||
1114 | * code there and sends the other processors off to there until | ||
1115 | * smp_boot_cpus tells them to do something. The holding pattern | ||
1116 | * checks that address until its cpu # is there, when it is that | ||
1117 | * cpu jumps to __secondary_start(). smp_boot_cpus() takes care | ||
1118 | * of setting those values. | ||
1119 | * | ||
1120 | * We also use physical address 0x4 here to tell when a cpu | ||
1121 | * is in its holding pattern code. | ||
1122 | * | ||
1123 | * Fixup comment... DRENG / PPPBBB - Peter | ||
1124 | * | ||
1125 | * -- Cort | ||
1126 | */ | ||
1127 | static void __init prom_hold_cpus(void) | ||
1128 | { | ||
1129 | unsigned long i; | ||
1130 | unsigned int reg; | ||
1131 | phandle node; | ||
1132 | unsigned long offset = reloc_offset(); | ||
1133 | char type[64]; | ||
1134 | int cpuid = 0; | ||
1135 | unsigned int interrupt_server[MAX_CPU_THREADS]; | ||
1136 | unsigned int cpu_threads, hw_cpu_num; | ||
1137 | int propsize; | ||
1138 | extern void __secondary_hold(void); | ||
1139 | extern unsigned long __secondary_hold_spinloop; | ||
1140 | extern unsigned long __secondary_hold_acknowledge; | ||
1141 | unsigned long *spinloop | ||
1142 | = (void *)virt_to_abs(&__secondary_hold_spinloop); | ||
1143 | unsigned long *acknowledge | ||
1144 | = (void *)virt_to_abs(&__secondary_hold_acknowledge); | ||
1145 | unsigned long secondary_hold | ||
1146 | = virt_to_abs(*PTRRELOC((unsigned long *)__secondary_hold)); | ||
1147 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1148 | |||
1149 | prom_debug("prom_hold_cpus: start...\n"); | ||
1150 | prom_debug(" 1) spinloop = 0x%x\n", (unsigned long)spinloop); | ||
1151 | prom_debug(" 1) *spinloop = 0x%x\n", *spinloop); | ||
1152 | prom_debug(" 1) acknowledge = 0x%x\n", | ||
1153 | (unsigned long)acknowledge); | ||
1154 | prom_debug(" 1) *acknowledge = 0x%x\n", *acknowledge); | ||
1155 | prom_debug(" 1) secondary_hold = 0x%x\n", secondary_hold); | ||
1156 | |||
1157 | /* Set the common spinloop variable, so all of the secondary cpus | ||
1158 | * will block when they are awakened from their OF spinloop. | ||
1159 | * This must occur for both SMP and non SMP kernels, since OF will | ||
1160 | * be trashed when we move the kernel. | ||
1161 | */ | ||
1162 | *spinloop = 0; | ||
1163 | |||
1164 | #ifdef CONFIG_HMT | ||
1165 | for (i=0; i < NR_CPUS; i++) { | ||
1166 | RELOC(hmt_thread_data)[i].pir = 0xdeadbeef; | ||
1167 | } | ||
1168 | #endif | ||
1169 | /* look for cpus */ | ||
1170 | for (node = 0; prom_next_node(&node); ) { | ||
1171 | type[0] = 0; | ||
1172 | prom_getprop(node, "device_type", type, sizeof(type)); | ||
1173 | if (strcmp(type, RELOC("cpu")) != 0) | ||
1174 | continue; | ||
1175 | |||
1176 | /* Skip non-configured cpus. */ | ||
1177 | if (prom_getprop(node, "status", type, sizeof(type)) > 0) | ||
1178 | if (strcmp(type, RELOC("okay")) != 0) | ||
1179 | continue; | ||
1180 | |||
1181 | reg = -1; | ||
1182 | prom_getprop(node, "reg", ®, sizeof(reg)); | ||
1183 | |||
1184 | prom_debug("\ncpuid = 0x%x\n", cpuid); | ||
1185 | prom_debug("cpu hw idx = 0x%x\n", reg); | ||
1186 | |||
1187 | /* Init the acknowledge var which will be reset by | ||
1188 | * the secondary cpu when it awakens from its OF | ||
1189 | * spinloop. | ||
1190 | */ | ||
1191 | *acknowledge = (unsigned long)-1; | ||
1192 | |||
1193 | propsize = prom_getprop(node, "ibm,ppc-interrupt-server#s", | ||
1194 | &interrupt_server, | ||
1195 | sizeof(interrupt_server)); | ||
1196 | if (propsize < 0) { | ||
1197 | /* no property. old hardware has no SMT */ | ||
1198 | cpu_threads = 1; | ||
1199 | interrupt_server[0] = reg; /* fake it with phys id */ | ||
1200 | } else { | ||
1201 | /* We have a threaded processor */ | ||
1202 | cpu_threads = propsize / sizeof(u32); | ||
1203 | if (cpu_threads > MAX_CPU_THREADS) { | ||
1204 | prom_printf("SMT: too many threads!\n" | ||
1205 | "SMT: found %x, max is %x\n", | ||
1206 | cpu_threads, MAX_CPU_THREADS); | ||
1207 | cpu_threads = 1; /* ToDo: panic? */ | ||
1208 | } | ||
1209 | } | ||
1210 | |||
1211 | hw_cpu_num = interrupt_server[0]; | ||
1212 | if (hw_cpu_num != _prom->cpu) { | ||
1213 | /* Primary Thread of non-boot cpu */ | ||
1214 | prom_printf("%x : starting cpu hw idx %x... ", cpuid, reg); | ||
1215 | call_prom("start-cpu", 3, 0, node, | ||
1216 | secondary_hold, reg); | ||
1217 | |||
1218 | for ( i = 0 ; (i < 100000000) && | ||
1219 | (*acknowledge == ((unsigned long)-1)); i++ ) | ||
1220 | mb(); | ||
1221 | |||
1222 | if (*acknowledge == reg) { | ||
1223 | prom_printf("done\n"); | ||
1224 | /* We have to get every CPU out of OF, | ||
1225 | * even if we never start it. */ | ||
1226 | if (cpuid >= NR_CPUS) | ||
1227 | goto next; | ||
1228 | } else { | ||
1229 | prom_printf("failed: %x\n", *acknowledge); | ||
1230 | } | ||
1231 | } | ||
1232 | #ifdef CONFIG_SMP | ||
1233 | else | ||
1234 | prom_printf("%x : boot cpu %x\n", cpuid, reg); | ||
1235 | #endif | ||
1236 | next: | ||
1237 | #ifdef CONFIG_SMP | ||
1238 | /* Init paca for secondary threads. They start later. */ | ||
1239 | for (i=1; i < cpu_threads; i++) { | ||
1240 | cpuid++; | ||
1241 | if (cpuid >= NR_CPUS) | ||
1242 | continue; | ||
1243 | } | ||
1244 | #endif /* CONFIG_SMP */ | ||
1245 | cpuid++; | ||
1246 | } | ||
1247 | #ifdef CONFIG_HMT | ||
1248 | /* Only enable HMT on processors that provide support. */ | ||
1249 | if (__is_processor(PV_PULSAR) || | ||
1250 | __is_processor(PV_ICESTAR) || | ||
1251 | __is_processor(PV_SSTAR)) { | ||
1252 | prom_printf(" starting secondary threads\n"); | ||
1253 | |||
1254 | for (i = 0; i < NR_CPUS; i += 2) { | ||
1255 | if (!cpu_online(i)) | ||
1256 | continue; | ||
1257 | |||
1258 | if (i == 0) { | ||
1259 | unsigned long pir = mfspr(SPRN_PIR); | ||
1260 | if (__is_processor(PV_PULSAR)) { | ||
1261 | RELOC(hmt_thread_data)[i].pir = | ||
1262 | pir & 0x1f; | ||
1263 | } else { | ||
1264 | RELOC(hmt_thread_data)[i].pir = | ||
1265 | pir & 0x3ff; | ||
1266 | } | ||
1267 | } | ||
1268 | } | ||
1269 | } else { | ||
1270 | prom_printf("Processor is not HMT capable\n"); | ||
1271 | } | ||
1272 | #endif | ||
1273 | |||
1274 | if (cpuid > NR_CPUS) | ||
1275 | prom_printf("WARNING: maximum CPUs (" __stringify(NR_CPUS) | ||
1276 | ") exceeded: ignoring extras\n"); | ||
1277 | |||
1278 | prom_debug("prom_hold_cpus: end...\n"); | ||
1279 | } | ||
1280 | |||
1281 | |||
1282 | static void __init prom_init_client_services(unsigned long pp) | ||
1283 | { | ||
1284 | unsigned long offset = reloc_offset(); | ||
1285 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1286 | |||
1287 | /* Get a handle to the prom entry point before anything else */ | ||
1288 | _prom->entry = pp; | ||
1289 | |||
1290 | /* Init default value for phys size */ | ||
1291 | _prom->root_size_cells = 1; | ||
1292 | _prom->root_addr_cells = 2; | ||
1293 | |||
1294 | /* get a handle for the stdout device */ | ||
1295 | _prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen")); | ||
1296 | if (!PHANDLE_VALID(_prom->chosen)) | ||
1297 | prom_panic("cannot find chosen"); /* msg won't be printed :( */ | ||
1298 | |||
1299 | /* get device tree root */ | ||
1300 | _prom->root = call_prom("finddevice", 1, 1, ADDR("/")); | ||
1301 | if (!PHANDLE_VALID(_prom->root)) | ||
1302 | prom_panic("cannot find device tree root"); /* msg won't be printed :( */ | ||
1303 | } | ||
1304 | |||
1305 | static void __init prom_init_stdout(void) | ||
1306 | { | ||
1307 | unsigned long offset = reloc_offset(); | ||
1308 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1309 | char *path = RELOC(of_stdout_device); | ||
1310 | char type[16]; | ||
1311 | u32 val; | ||
1312 | |||
1313 | if (prom_getprop(_prom->chosen, "stdout", &val, sizeof(val)) <= 0) | ||
1314 | prom_panic("cannot find stdout"); | ||
1315 | |||
1316 | _prom->stdout = val; | ||
1317 | |||
1318 | /* Get the full OF pathname of the stdout device */ | ||
1319 | memset(path, 0, 256); | ||
1320 | call_prom("instance-to-path", 3, 1, _prom->stdout, path, 255); | ||
1321 | val = call_prom("instance-to-package", 1, 1, _prom->stdout); | ||
1322 | prom_setprop(_prom->chosen, "linux,stdout-package", &val, sizeof(val)); | ||
1323 | prom_printf("OF stdout device is: %s\n", RELOC(of_stdout_device)); | ||
1324 | prom_setprop(_prom->chosen, "linux,stdout-path", | ||
1325 | RELOC(of_stdout_device), strlen(RELOC(of_stdout_device))+1); | ||
1326 | |||
1327 | /* If it's a display, note it */ | ||
1328 | memset(type, 0, sizeof(type)); | ||
1329 | prom_getprop(val, "device_type", type, sizeof(type)); | ||
1330 | if (strcmp(type, RELOC("display")) == 0) { | ||
1331 | _prom->disp_node = val; | ||
1332 | prom_setprop(val, "linux,boot-display", NULL, 0); | ||
1333 | } | ||
1334 | } | ||
1335 | |||
1336 | static void __init prom_close_stdin(void) | ||
1337 | { | ||
1338 | unsigned long offset = reloc_offset(); | ||
1339 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1340 | ihandle val; | ||
1341 | |||
1342 | if (prom_getprop(_prom->chosen, "stdin", &val, sizeof(val)) > 0) | ||
1343 | call_prom("close", 1, 0, val); | ||
1344 | } | ||
1345 | |||
1346 | static int __init prom_find_machine_type(void) | ||
1347 | { | ||
1348 | unsigned long offset = reloc_offset(); | ||
1349 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1350 | char compat[256]; | ||
1351 | int len, i = 0; | ||
1352 | phandle rtas; | ||
1353 | |||
1354 | len = prom_getprop(_prom->root, "compatible", | ||
1355 | compat, sizeof(compat)-1); | ||
1356 | if (len > 0) { | ||
1357 | compat[len] = 0; | ||
1358 | while (i < len) { | ||
1359 | char *p = &compat[i]; | ||
1360 | int sl = strlen(p); | ||
1361 | if (sl == 0) | ||
1362 | break; | ||
1363 | if (strstr(p, RELOC("Power Macintosh")) || | ||
1364 | strstr(p, RELOC("MacRISC4"))) | ||
1365 | return PLATFORM_POWERMAC; | ||
1366 | if (strstr(p, RELOC("Momentum,Maple"))) | ||
1367 | return PLATFORM_MAPLE; | ||
1368 | i += sl + 1; | ||
1369 | } | ||
1370 | } | ||
1371 | /* Default to pSeries. We need to know if we are running LPAR */ | ||
1372 | rtas = call_prom("finddevice", 1, 1, ADDR("/rtas")); | ||
1373 | if (PHANDLE_VALID(rtas)) { | ||
1374 | int x = prom_getproplen(rtas, "ibm,hypertas-functions"); | ||
1375 | if (x != PROM_ERROR) { | ||
1376 | prom_printf("Hypertas detected, assuming LPAR !\n"); | ||
1377 | return PLATFORM_PSERIES_LPAR; | ||
1378 | } | ||
1379 | } | ||
1380 | return PLATFORM_PSERIES; | ||
1381 | } | ||
1382 | |||
1383 | static int __init prom_set_color(ihandle ih, int i, int r, int g, int b) | ||
1384 | { | ||
1385 | unsigned long offset = reloc_offset(); | ||
1386 | |||
1387 | return call_prom("call-method", 6, 1, ADDR("color!"), ih, i, b, g, r); | ||
1388 | } | ||
1389 | |||
1390 | /* | ||
1391 | * If we have a display that we don't know how to drive, | ||
1392 | * we will want to try to execute OF's open method for it | ||
1393 | * later. However, OF will probably fall over if we do that | ||
1394 | * we've taken over the MMU. | ||
1395 | * So we check whether we will need to open the display, | ||
1396 | * and if so, open it now. | ||
1397 | */ | ||
1398 | static void __init prom_check_displays(void) | ||
1399 | { | ||
1400 | unsigned long offset = reloc_offset(); | ||
1401 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1402 | char type[16], *path; | ||
1403 | phandle node; | ||
1404 | ihandle ih; | ||
1405 | int i; | ||
1406 | |||
1407 | static unsigned char default_colors[] = { | ||
1408 | 0x00, 0x00, 0x00, | ||
1409 | 0x00, 0x00, 0xaa, | ||
1410 | 0x00, 0xaa, 0x00, | ||
1411 | 0x00, 0xaa, 0xaa, | ||
1412 | 0xaa, 0x00, 0x00, | ||
1413 | 0xaa, 0x00, 0xaa, | ||
1414 | 0xaa, 0xaa, 0x00, | ||
1415 | 0xaa, 0xaa, 0xaa, | ||
1416 | 0x55, 0x55, 0x55, | ||
1417 | 0x55, 0x55, 0xff, | ||
1418 | 0x55, 0xff, 0x55, | ||
1419 | 0x55, 0xff, 0xff, | ||
1420 | 0xff, 0x55, 0x55, | ||
1421 | 0xff, 0x55, 0xff, | ||
1422 | 0xff, 0xff, 0x55, | ||
1423 | 0xff, 0xff, 0xff | ||
1424 | }; | ||
1425 | const unsigned char *clut; | ||
1426 | |||
1427 | prom_printf("Looking for displays\n"); | ||
1428 | for (node = 0; prom_next_node(&node); ) { | ||
1429 | memset(type, 0, sizeof(type)); | ||
1430 | prom_getprop(node, "device_type", type, sizeof(type)); | ||
1431 | if (strcmp(type, RELOC("display")) != 0) | ||
1432 | continue; | ||
1433 | |||
1434 | /* It seems OF doesn't null-terminate the path :-( */ | ||
1435 | path = RELOC(prom_scratch); | ||
1436 | memset(path, 0, PROM_SCRATCH_SIZE); | ||
1437 | |||
1438 | /* | ||
1439 | * leave some room at the end of the path for appending extra | ||
1440 | * arguments | ||
1441 | */ | ||
1442 | if (call_prom("package-to-path", 3, 1, node, path, | ||
1443 | PROM_SCRATCH_SIZE-10) == PROM_ERROR) | ||
1444 | continue; | ||
1445 | prom_printf("found display : %s, opening ... ", path); | ||
1446 | |||
1447 | ih = call_prom("open", 1, 1, path); | ||
1448 | if (ih == 0) { | ||
1449 | prom_printf("failed\n"); | ||
1450 | continue; | ||
1451 | } | ||
1452 | |||
1453 | /* Success */ | ||
1454 | prom_printf("done\n"); | ||
1455 | prom_setprop(node, "linux,opened", NULL, 0); | ||
1456 | |||
1457 | /* | ||
1458 | * stdout wasn't a display node, pick the first we can find | ||
1459 | * for btext | ||
1460 | */ | ||
1461 | if (_prom->disp_node == 0) | ||
1462 | _prom->disp_node = node; | ||
1463 | |||
1464 | /* Setup a useable color table when the appropriate | ||
1465 | * method is available. Should update this to set-colors */ | ||
1466 | clut = RELOC(default_colors); | ||
1467 | for (i = 0; i < 32; i++, clut += 3) | ||
1468 | if (prom_set_color(ih, i, clut[0], clut[1], | ||
1469 | clut[2]) != 0) | ||
1470 | break; | ||
1471 | |||
1472 | #ifdef CONFIG_LOGO_LINUX_CLUT224 | ||
1473 | clut = PTRRELOC(RELOC(logo_linux_clut224.clut)); | ||
1474 | for (i = 0; i < RELOC(logo_linux_clut224.clutsize); i++, clut += 3) | ||
1475 | if (prom_set_color(ih, i + 32, clut[0], clut[1], | ||
1476 | clut[2]) != 0) | ||
1477 | break; | ||
1478 | #endif /* CONFIG_LOGO_LINUX_CLUT224 */ | ||
1479 | } | ||
1480 | } | ||
1481 | |||
1482 | |||
1483 | /* Return (relocated) pointer to this much memory: moves initrd if reqd. */ | ||
1484 | static void __init *make_room(unsigned long *mem_start, unsigned long *mem_end, | ||
1485 | unsigned long needed, unsigned long align) | ||
1486 | { | ||
1487 | unsigned long offset = reloc_offset(); | ||
1488 | void *ret; | ||
1489 | |||
1490 | *mem_start = _ALIGN(*mem_start, align); | ||
1491 | while ((*mem_start + needed) > *mem_end) { | ||
1492 | unsigned long room, chunk; | ||
1493 | |||
1494 | prom_debug("Chunk exhausted, claiming more at %x...\n", | ||
1495 | RELOC(alloc_bottom)); | ||
1496 | room = RELOC(alloc_top) - RELOC(alloc_bottom); | ||
1497 | if (room > DEVTREE_CHUNK_SIZE) | ||
1498 | room = DEVTREE_CHUNK_SIZE; | ||
1499 | if (room < PAGE_SIZE) | ||
1500 | prom_panic("No memory for flatten_device_tree (no room)"); | ||
1501 | chunk = alloc_up(room, 0); | ||
1502 | if (chunk == 0) | ||
1503 | prom_panic("No memory for flatten_device_tree (claim failed)"); | ||
1504 | *mem_end = RELOC(alloc_top); | ||
1505 | } | ||
1506 | |||
1507 | ret = (void *)*mem_start; | ||
1508 | *mem_start += needed; | ||
1509 | |||
1510 | return ret; | ||
1511 | } | ||
1512 | |||
1513 | #define dt_push_token(token, mem_start, mem_end) \ | ||
1514 | do { *((u32 *)make_room(mem_start, mem_end, 4, 4)) = token; } while(0) | ||
1515 | |||
1516 | static unsigned long __init dt_find_string(char *str) | ||
1517 | { | ||
1518 | unsigned long offset = reloc_offset(); | ||
1519 | char *s, *os; | ||
1520 | |||
1521 | s = os = (char *)RELOC(dt_string_start); | ||
1522 | s += 4; | ||
1523 | while (s < (char *)RELOC(dt_string_end)) { | ||
1524 | if (strcmp(s, str) == 0) | ||
1525 | return s - os; | ||
1526 | s += strlen(s) + 1; | ||
1527 | } | ||
1528 | return 0; | ||
1529 | } | ||
1530 | |||
1531 | /* | ||
1532 | * The Open Firmware 1275 specification states properties must be 31 bytes or | ||
1533 | * less, however not all firmwares obey this. Make it 64 bytes to be safe. | ||
1534 | */ | ||
1535 | #define MAX_PROPERTY_NAME 64 | ||
1536 | |||
1537 | static void __init scan_dt_build_strings(phandle node, | ||
1538 | unsigned long *mem_start, | ||
1539 | unsigned long *mem_end) | ||
1540 | { | ||
1541 | unsigned long offset = reloc_offset(); | ||
1542 | char *prev_name, *namep, *sstart; | ||
1543 | unsigned long soff; | ||
1544 | phandle child; | ||
1545 | |||
1546 | sstart = (char *)RELOC(dt_string_start); | ||
1547 | |||
1548 | /* get and store all property names */ | ||
1549 | prev_name = RELOC(""); | ||
1550 | for (;;) { | ||
1551 | /* 64 is max len of name including nul. */ | ||
1552 | namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1); | ||
1553 | if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) { | ||
1554 | /* No more nodes: unwind alloc */ | ||
1555 | *mem_start = (unsigned long)namep; | ||
1556 | break; | ||
1557 | } | ||
1558 | |||
1559 | /* skip "name" */ | ||
1560 | if (strcmp(namep, RELOC("name")) == 0) { | ||
1561 | *mem_start = (unsigned long)namep; | ||
1562 | prev_name = RELOC("name"); | ||
1563 | continue; | ||
1564 | } | ||
1565 | /* get/create string entry */ | ||
1566 | soff = dt_find_string(namep); | ||
1567 | if (soff != 0) { | ||
1568 | *mem_start = (unsigned long)namep; | ||
1569 | namep = sstart + soff; | ||
1570 | } else { | ||
1571 | /* Trim off some if we can */ | ||
1572 | *mem_start = (unsigned long)namep + strlen(namep) + 1; | ||
1573 | RELOC(dt_string_end) = *mem_start; | ||
1574 | } | ||
1575 | prev_name = namep; | ||
1576 | } | ||
1577 | |||
1578 | /* do all our children */ | ||
1579 | child = call_prom("child", 1, 1, node); | ||
1580 | while (child != 0) { | ||
1581 | scan_dt_build_strings(child, mem_start, mem_end); | ||
1582 | child = call_prom("peer", 1, 1, child); | ||
1583 | } | ||
1584 | } | ||
1585 | |||
1586 | static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, | ||
1587 | unsigned long *mem_end) | ||
1588 | { | ||
1589 | phandle child; | ||
1590 | char *namep, *prev_name, *sstart, *p, *ep, *lp, *path; | ||
1591 | unsigned long soff; | ||
1592 | unsigned char *valp; | ||
1593 | unsigned long offset = reloc_offset(); | ||
1594 | static char pname[MAX_PROPERTY_NAME]; | ||
1595 | int l; | ||
1596 | |||
1597 | dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end); | ||
1598 | |||
1599 | /* get the node's full name */ | ||
1600 | namep = (char *)*mem_start; | ||
1601 | l = call_prom("package-to-path", 3, 1, node, | ||
1602 | namep, *mem_end - *mem_start); | ||
1603 | if (l >= 0) { | ||
1604 | /* Didn't fit? Get more room. */ | ||
1605 | if ((l+1) > (*mem_end - *mem_start)) { | ||
1606 | namep = make_room(mem_start, mem_end, l+1, 1); | ||
1607 | call_prom("package-to-path", 3, 1, node, namep, l); | ||
1608 | } | ||
1609 | namep[l] = '\0'; | ||
1610 | |||
1611 | /* Fixup an Apple bug where they have bogus \0 chars in the | ||
1612 | * middle of the path in some properties | ||
1613 | */ | ||
1614 | for (p = namep, ep = namep + l; p < ep; p++) | ||
1615 | if (*p == '\0') { | ||
1616 | memmove(p, p+1, ep - p); | ||
1617 | ep--; l--; p--; | ||
1618 | } | ||
1619 | |||
1620 | /* now try to extract the unit name in that mess */ | ||
1621 | for (p = namep, lp = NULL; *p; p++) | ||
1622 | if (*p == '/') | ||
1623 | lp = p + 1; | ||
1624 | if (lp != NULL) | ||
1625 | memmove(namep, lp, strlen(lp) + 1); | ||
1626 | *mem_start = _ALIGN(((unsigned long) namep) + | ||
1627 | strlen(namep) + 1, 4); | ||
1628 | } | ||
1629 | |||
1630 | /* get it again for debugging */ | ||
1631 | path = RELOC(prom_scratch); | ||
1632 | memset(path, 0, PROM_SCRATCH_SIZE); | ||
1633 | call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1); | ||
1634 | |||
1635 | /* get and store all properties */ | ||
1636 | prev_name = RELOC(""); | ||
1637 | sstart = (char *)RELOC(dt_string_start); | ||
1638 | for (;;) { | ||
1639 | if (call_prom("nextprop", 3, 1, node, prev_name, | ||
1640 | RELOC(pname)) != 1) | ||
1641 | break; | ||
1642 | |||
1643 | /* skip "name" */ | ||
1644 | if (strcmp(RELOC(pname), RELOC("name")) == 0) { | ||
1645 | prev_name = RELOC("name"); | ||
1646 | continue; | ||
1647 | } | ||
1648 | |||
1649 | /* find string offset */ | ||
1650 | soff = dt_find_string(RELOC(pname)); | ||
1651 | if (soff == 0) { | ||
1652 | prom_printf("WARNING: Can't find string index for" | ||
1653 | " <%s>, node %s\n", RELOC(pname), path); | ||
1654 | break; | ||
1655 | } | ||
1656 | prev_name = sstart + soff; | ||
1657 | |||
1658 | /* get length */ | ||
1659 | l = call_prom("getproplen", 2, 1, node, RELOC(pname)); | ||
1660 | |||
1661 | /* sanity checks */ | ||
1662 | if (l == PROM_ERROR) | ||
1663 | continue; | ||
1664 | if (l > MAX_PROPERTY_LENGTH) { | ||
1665 | prom_printf("WARNING: ignoring large property "); | ||
1666 | /* It seems OF doesn't null-terminate the path :-( */ | ||
1667 | prom_printf("[%s] ", path); | ||
1668 | prom_printf("%s length 0x%x\n", RELOC(pname), l); | ||
1669 | continue; | ||
1670 | } | ||
1671 | |||
1672 | /* push property head */ | ||
1673 | dt_push_token(OF_DT_PROP, mem_start, mem_end); | ||
1674 | dt_push_token(l, mem_start, mem_end); | ||
1675 | dt_push_token(soff, mem_start, mem_end); | ||
1676 | |||
1677 | /* push property content */ | ||
1678 | valp = make_room(mem_start, mem_end, l, 4); | ||
1679 | call_prom("getprop", 4, 1, node, RELOC(pname), valp, l); | ||
1680 | *mem_start = _ALIGN(*mem_start, 4); | ||
1681 | } | ||
1682 | |||
1683 | /* Add a "linux,phandle" property. */ | ||
1684 | soff = dt_find_string(RELOC("linux,phandle")); | ||
1685 | if (soff == 0) | ||
1686 | prom_printf("WARNING: Can't find string index for" | ||
1687 | " <linux-phandle> node %s\n", path); | ||
1688 | else { | ||
1689 | dt_push_token(OF_DT_PROP, mem_start, mem_end); | ||
1690 | dt_push_token(4, mem_start, mem_end); | ||
1691 | dt_push_token(soff, mem_start, mem_end); | ||
1692 | valp = make_room(mem_start, mem_end, 4, 4); | ||
1693 | *(u32 *)valp = node; | ||
1694 | } | ||
1695 | |||
1696 | /* do all our children */ | ||
1697 | child = call_prom("child", 1, 1, node); | ||
1698 | while (child != 0) { | ||
1699 | scan_dt_build_struct(child, mem_start, mem_end); | ||
1700 | child = call_prom("peer", 1, 1, child); | ||
1701 | } | ||
1702 | |||
1703 | dt_push_token(OF_DT_END_NODE, mem_start, mem_end); | ||
1704 | } | ||
1705 | |||
1706 | static void __init flatten_device_tree(void) | ||
1707 | { | ||
1708 | phandle root; | ||
1709 | unsigned long offset = reloc_offset(); | ||
1710 | unsigned long mem_start, mem_end, room; | ||
1711 | struct boot_param_header *hdr; | ||
1712 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1713 | char *namep; | ||
1714 | u64 *rsvmap; | ||
1715 | |||
1716 | /* | ||
1717 | * Check how much room we have between alloc top & bottom (+/- a | ||
1718 | * few pages), crop to 4Mb, as this is our "chuck" size | ||
1719 | */ | ||
1720 | room = RELOC(alloc_top) - RELOC(alloc_bottom) - 0x4000; | ||
1721 | if (room > DEVTREE_CHUNK_SIZE) | ||
1722 | room = DEVTREE_CHUNK_SIZE; | ||
1723 | prom_debug("starting device tree allocs at %x\n", RELOC(alloc_bottom)); | ||
1724 | |||
1725 | /* Now try to claim that */ | ||
1726 | mem_start = (unsigned long)alloc_up(room, PAGE_SIZE); | ||
1727 | if (mem_start == 0) | ||
1728 | prom_panic("Can't allocate initial device-tree chunk\n"); | ||
1729 | mem_end = RELOC(alloc_top); | ||
1730 | |||
1731 | /* Get root of tree */ | ||
1732 | root = call_prom("peer", 1, 1, (phandle)0); | ||
1733 | if (root == (phandle)0) | ||
1734 | prom_panic ("couldn't get device tree root\n"); | ||
1735 | |||
1736 | /* Build header and make room for mem rsv map */ | ||
1737 | mem_start = _ALIGN(mem_start, 4); | ||
1738 | hdr = make_room(&mem_start, &mem_end, | ||
1739 | sizeof(struct boot_param_header), 4); | ||
1740 | RELOC(dt_header_start) = (unsigned long)hdr; | ||
1741 | rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8); | ||
1742 | |||
1743 | /* Start of strings */ | ||
1744 | mem_start = PAGE_ALIGN(mem_start); | ||
1745 | RELOC(dt_string_start) = mem_start; | ||
1746 | mem_start += 4; /* hole */ | ||
1747 | |||
1748 | /* Add "linux,phandle" in there, we'll need it */ | ||
1749 | namep = make_room(&mem_start, &mem_end, 16, 1); | ||
1750 | strcpy(namep, RELOC("linux,phandle")); | ||
1751 | mem_start = (unsigned long)namep + strlen(namep) + 1; | ||
1752 | |||
1753 | /* Build string array */ | ||
1754 | prom_printf("Building dt strings...\n"); | ||
1755 | scan_dt_build_strings(root, &mem_start, &mem_end); | ||
1756 | RELOC(dt_string_end) = mem_start; | ||
1757 | |||
1758 | /* Build structure */ | ||
1759 | mem_start = PAGE_ALIGN(mem_start); | ||
1760 | RELOC(dt_struct_start) = mem_start; | ||
1761 | prom_printf("Building dt structure...\n"); | ||
1762 | scan_dt_build_struct(root, &mem_start, &mem_end); | ||
1763 | dt_push_token(OF_DT_END, &mem_start, &mem_end); | ||
1764 | RELOC(dt_struct_end) = PAGE_ALIGN(mem_start); | ||
1765 | |||
1766 | /* Finish header */ | ||
1767 | hdr->boot_cpuid_phys = _prom->cpu; | ||
1768 | hdr->magic = OF_DT_HEADER; | ||
1769 | hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start); | ||
1770 | hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start); | ||
1771 | hdr->off_dt_strings = RELOC(dt_string_start) - RELOC(dt_header_start); | ||
1772 | hdr->dt_strings_size = RELOC(dt_string_end) - RELOC(dt_string_start); | ||
1773 | hdr->off_mem_rsvmap = ((unsigned long)rsvmap) - RELOC(dt_header_start); | ||
1774 | hdr->version = OF_DT_VERSION; | ||
1775 | /* Version 16 is not backward compatible */ | ||
1776 | hdr->last_comp_version = 0x10; | ||
1777 | |||
1778 | /* Reserve the whole thing and copy the reserve map in, we | ||
1779 | * also bump mem_reserve_cnt to cause further reservations to | ||
1780 | * fail since it's too late. | ||
1781 | */ | ||
1782 | reserve_mem(RELOC(dt_header_start), hdr->totalsize); | ||
1783 | memcpy(rsvmap, RELOC(mem_reserve_map), sizeof(mem_reserve_map)); | ||
1784 | |||
1785 | #ifdef DEBUG_PROM | ||
1786 | { | ||
1787 | int i; | ||
1788 | prom_printf("reserved memory map:\n"); | ||
1789 | for (i = 0; i < RELOC(mem_reserve_cnt); i++) | ||
1790 | prom_printf(" %x - %x\n", RELOC(mem_reserve_map)[i].base, | ||
1791 | RELOC(mem_reserve_map)[i].size); | ||
1792 | } | ||
1793 | #endif | ||
1794 | RELOC(mem_reserve_cnt) = MEM_RESERVE_MAP_SIZE; | ||
1795 | |||
1796 | prom_printf("Device tree strings 0x%x -> 0x%x\n", | ||
1797 | RELOC(dt_string_start), RELOC(dt_string_end)); | ||
1798 | prom_printf("Device tree struct 0x%x -> 0x%x\n", | ||
1799 | RELOC(dt_struct_start), RELOC(dt_struct_end)); | ||
1800 | |||
1801 | } | ||
1802 | |||
1803 | |||
1804 | static void __init fixup_device_tree(void) | ||
1805 | { | ||
1806 | unsigned long offset = reloc_offset(); | ||
1807 | phandle u3, i2c, mpic; | ||
1808 | u32 u3_rev; | ||
1809 | u32 interrupts[2]; | ||
1810 | u32 parent; | ||
1811 | |||
1812 | /* Some G5s have a missing interrupt definition, fix it up here */ | ||
1813 | u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000")); | ||
1814 | if (!PHANDLE_VALID(u3)) | ||
1815 | return; | ||
1816 | i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000")); | ||
1817 | if (!PHANDLE_VALID(i2c)) | ||
1818 | return; | ||
1819 | mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000")); | ||
1820 | if (!PHANDLE_VALID(mpic)) | ||
1821 | return; | ||
1822 | |||
1823 | /* check if proper rev of u3 */ | ||
1824 | if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) | ||
1825 | == PROM_ERROR) | ||
1826 | return; | ||
1827 | if (u3_rev < 0x35 || u3_rev > 0x39) | ||
1828 | return; | ||
1829 | /* does it need fixup ? */ | ||
1830 | if (prom_getproplen(i2c, "interrupts") > 0) | ||
1831 | return; | ||
1832 | |||
1833 | prom_printf("fixing up bogus interrupts for u3 i2c...\n"); | ||
1834 | |||
1835 | /* interrupt on this revision of u3 is number 0 and level */ | ||
1836 | interrupts[0] = 0; | ||
1837 | interrupts[1] = 1; | ||
1838 | prom_setprop(i2c, "interrupts", &interrupts, sizeof(interrupts)); | ||
1839 | parent = (u32)mpic; | ||
1840 | prom_setprop(i2c, "interrupt-parent", &parent, sizeof(parent)); | ||
1841 | } | ||
1842 | |||
1843 | |||
1844 | static void __init prom_find_boot_cpu(void) | ||
1845 | { | ||
1846 | unsigned long offset = reloc_offset(); | ||
1847 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1848 | u32 getprop_rval; | ||
1849 | ihandle prom_cpu; | ||
1850 | phandle cpu_pkg; | ||
1851 | |||
1852 | if (prom_getprop(_prom->chosen, "cpu", &prom_cpu, sizeof(prom_cpu)) <= 0) | ||
1853 | prom_panic("cannot find boot cpu"); | ||
1854 | |||
1855 | cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu); | ||
1856 | |||
1857 | prom_getprop(cpu_pkg, "reg", &getprop_rval, sizeof(getprop_rval)); | ||
1858 | _prom->cpu = getprop_rval; | ||
1859 | |||
1860 | prom_debug("Booting CPU hw index = 0x%x\n", _prom->cpu); | ||
1861 | } | ||
1862 | |||
1863 | static void __init prom_check_initrd(unsigned long r3, unsigned long r4) | ||
1864 | { | ||
1865 | #ifdef CONFIG_BLK_DEV_INITRD | ||
1866 | unsigned long offset = reloc_offset(); | ||
1867 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1868 | |||
1869 | if ( r3 && r4 && r4 != 0xdeadbeef) { | ||
1870 | u64 val; | ||
1871 | |||
1872 | RELOC(prom_initrd_start) = (r3 >= KERNELBASE) ? __pa(r3) : r3; | ||
1873 | RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4; | ||
1874 | |||
1875 | val = (u64)RELOC(prom_initrd_start); | ||
1876 | prom_setprop(_prom->chosen, "linux,initrd-start", &val, sizeof(val)); | ||
1877 | val = (u64)RELOC(prom_initrd_end); | ||
1878 | prom_setprop(_prom->chosen, "linux,initrd-end", &val, sizeof(val)); | ||
1879 | |||
1880 | reserve_mem(RELOC(prom_initrd_start), | ||
1881 | RELOC(prom_initrd_end) - RELOC(prom_initrd_start)); | ||
1882 | |||
1883 | prom_debug("initrd_start=0x%x\n", RELOC(prom_initrd_start)); | ||
1884 | prom_debug("initrd_end=0x%x\n", RELOC(prom_initrd_end)); | ||
1885 | } | ||
1886 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
1887 | } | ||
1888 | |||
1889 | /* | ||
1890 | * We enter here early on, when the Open Firmware prom is still | ||
1891 | * handling exceptions and the MMU hash table for us. | ||
1892 | */ | ||
1893 | |||
1894 | unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long pp, | ||
1895 | unsigned long r6, unsigned long r7) | ||
1896 | { | ||
1897 | unsigned long offset = reloc_offset(); | ||
1898 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1899 | unsigned long phys = KERNELBASE - offset; | ||
1900 | u32 getprop_rval; | ||
1901 | |||
1902 | /* | ||
1903 | * First zero the BSS | ||
1904 | */ | ||
1905 | memset(PTRRELOC(&__bss_start), 0, __bss_stop - __bss_start); | ||
1906 | |||
1907 | /* | ||
1908 | * Init interface to Open Firmware, get some node references, | ||
1909 | * like /chosen | ||
1910 | */ | ||
1911 | prom_init_client_services(pp); | ||
1912 | |||
1913 | /* | ||
1914 | * Init prom stdout device | ||
1915 | */ | ||
1916 | prom_init_stdout(); | ||
1917 | prom_debug("klimit=0x%x\n", RELOC(klimit)); | ||
1918 | prom_debug("offset=0x%x\n", offset); | ||
1919 | |||
1920 | /* | ||
1921 | * Check for an initrd | ||
1922 | */ | ||
1923 | prom_check_initrd(r3, r4); | ||
1924 | |||
1925 | /* | ||
1926 | * Get default machine type. At this point, we do not differenciate | ||
1927 | * between pSeries SMP and pSeries LPAR | ||
1928 | */ | ||
1929 | RELOC(of_platform) = prom_find_machine_type(); | ||
1930 | getprop_rval = RELOC(of_platform); | ||
1931 | prom_setprop(_prom->chosen, "linux,platform", | ||
1932 | &getprop_rval, sizeof(getprop_rval)); | ||
1933 | |||
1934 | /* | ||
1935 | * On pSeries, inform the firmware about our capabilities | ||
1936 | */ | ||
1937 | if (RELOC(of_platform) == PLATFORM_PSERIES || | ||
1938 | RELOC(of_platform) == PLATFORM_PSERIES_LPAR) | ||
1939 | prom_send_capabilities(); | ||
1940 | |||
1941 | /* | ||
1942 | * On pSeries and Cell, copy the CPU hold code | ||
1943 | */ | ||
1944 | if (RELOC(of_platform) & (PLATFORM_PSERIES | PLATFORM_CELL)) | ||
1945 | copy_and_flush(0, KERNELBASE - offset, 0x100, 0); | ||
1946 | |||
1947 | /* | ||
1948 | * Get memory cells format | ||
1949 | */ | ||
1950 | getprop_rval = 1; | ||
1951 | prom_getprop(_prom->root, "#size-cells", | ||
1952 | &getprop_rval, sizeof(getprop_rval)); | ||
1953 | _prom->root_size_cells = getprop_rval; | ||
1954 | getprop_rval = 2; | ||
1955 | prom_getprop(_prom->root, "#address-cells", | ||
1956 | &getprop_rval, sizeof(getprop_rval)); | ||
1957 | _prom->root_addr_cells = getprop_rval; | ||
1958 | |||
1959 | /* | ||
1960 | * Do early parsing of command line | ||
1961 | */ | ||
1962 | early_cmdline_parse(); | ||
1963 | |||
1964 | /* | ||
1965 | * Initialize memory management within prom_init | ||
1966 | */ | ||
1967 | prom_init_mem(); | ||
1968 | |||
1969 | /* | ||
1970 | * Determine which cpu is actually running right _now_ | ||
1971 | */ | ||
1972 | prom_find_boot_cpu(); | ||
1973 | |||
1974 | /* | ||
1975 | * Initialize display devices | ||
1976 | */ | ||
1977 | prom_check_displays(); | ||
1978 | |||
1979 | /* | ||
1980 | * Initialize IOMMU (TCE tables) on pSeries. Do that before anything else | ||
1981 | * that uses the allocator, we need to make sure we get the top of memory | ||
1982 | * available for us here... | ||
1983 | */ | ||
1984 | if (RELOC(of_platform) == PLATFORM_PSERIES) | ||
1985 | prom_initialize_tce_table(); | ||
1986 | |||
1987 | /* | ||
1988 | * On non-powermacs, try to instantiate RTAS and puts all CPUs | ||
1989 | * in spin-loops. PowerMacs don't have a working RTAS and use | ||
1990 | * a different way to spin CPUs | ||
1991 | */ | ||
1992 | if (RELOC(of_platform) != PLATFORM_POWERMAC) { | ||
1993 | prom_instantiate_rtas(); | ||
1994 | prom_hold_cpus(); | ||
1995 | } | ||
1996 | |||
1997 | /* | ||
1998 | * Fill in some infos for use by the kernel later on | ||
1999 | */ | ||
2000 | if (RELOC(ppc64_iommu_off)) | ||
2001 | prom_setprop(_prom->chosen, "linux,iommu-off", NULL, 0); | ||
2002 | |||
2003 | if (RELOC(iommu_force_on)) | ||
2004 | prom_setprop(_prom->chosen, "linux,iommu-force-on", NULL, 0); | ||
2005 | |||
2006 | if (RELOC(prom_memory_limit)) | ||
2007 | prom_setprop(_prom->chosen, "linux,memory-limit", | ||
2008 | PTRRELOC(&prom_memory_limit), sizeof(RELOC(prom_memory_limit))); | ||
2009 | |||
2010 | if (RELOC(prom_tce_alloc_start)) { | ||
2011 | prom_setprop(_prom->chosen, "linux,tce-alloc-start", | ||
2012 | PTRRELOC(&prom_tce_alloc_start), sizeof(RELOC(prom_tce_alloc_start))); | ||
2013 | prom_setprop(_prom->chosen, "linux,tce-alloc-end", | ||
2014 | PTRRELOC(&prom_tce_alloc_end), sizeof(RELOC(prom_tce_alloc_end))); | ||
2015 | } | ||
2016 | |||
2017 | /* | ||
2018 | * Fixup any known bugs in the device-tree | ||
2019 | */ | ||
2020 | fixup_device_tree(); | ||
2021 | |||
2022 | /* | ||
2023 | * Now finally create the flattened device-tree | ||
2024 | */ | ||
2025 | prom_printf("copying OF device tree ...\n"); | ||
2026 | flatten_device_tree(); | ||
2027 | |||
2028 | /* in case stdin is USB and still active on IBM machines... */ | ||
2029 | prom_close_stdin(); | ||
2030 | |||
2031 | /* | ||
2032 | * Call OF "quiesce" method to shut down pending DMA's from | ||
2033 | * devices etc... | ||
2034 | */ | ||
2035 | prom_printf("Calling quiesce ...\n"); | ||
2036 | call_prom("quiesce", 0, 0); | ||
2037 | |||
2038 | /* | ||
2039 | * And finally, call the kernel passing it the flattened device | ||
2040 | * tree and NULL as r5, thus triggering the new entry point which | ||
2041 | * is common to us and kexec | ||
2042 | */ | ||
2043 | prom_printf("returning from prom_init\n"); | ||
2044 | prom_debug("->dt_header_start=0x%x\n", RELOC(dt_header_start)); | ||
2045 | prom_debug("->phys=0x%x\n", phys); | ||
2046 | |||
2047 | __start(RELOC(dt_header_start), phys, 0); | ||
2048 | |||
2049 | return 0; | ||
2050 | } | ||
2051 | |||
diff --git a/arch/ppc64/kernel/rtc.c b/arch/ppc64/kernel/rtc.c deleted file mode 100644 index 79e7ed2858dd..000000000000 --- a/arch/ppc64/kernel/rtc.c +++ /dev/null | |||
@@ -1,358 +0,0 @@ | |||
1 | /* | ||
2 | * Real Time Clock interface for PPC64. | ||
3 | * | ||
4 | * Based on rtc.c by Paul Gortmaker | ||
5 | * | ||
6 | * This driver allows use of the real time clock | ||
7 | * from user space. It exports the /dev/rtc | ||
8 | * interface supporting various ioctl() and also the | ||
9 | * /proc/driver/rtc pseudo-file for status information. | ||
10 | * | ||
11 | * Interface does not support RTC interrupts nor an alarm. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * as published by the Free Software Foundation; either version | ||
16 | * 2 of the License, or (at your option) any later version. | ||
17 | * | ||
18 | * 1.0 Mike Corrigan: IBM iSeries rtc support | ||
19 | * 1.1 Dave Engebretsen: IBM pSeries rtc support | ||
20 | */ | ||
21 | |||
22 | #define RTC_VERSION "1.1" | ||
23 | |||
24 | #include <linux/config.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/types.h> | ||
28 | #include <linux/miscdevice.h> | ||
29 | #include <linux/ioport.h> | ||
30 | #include <linux/fcntl.h> | ||
31 | #include <linux/mc146818rtc.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/poll.h> | ||
34 | #include <linux/proc_fs.h> | ||
35 | #include <linux/spinlock.h> | ||
36 | #include <linux/bcd.h> | ||
37 | #include <linux/interrupt.h> | ||
38 | #include <linux/delay.h> | ||
39 | |||
40 | #include <asm/io.h> | ||
41 | #include <asm/uaccess.h> | ||
42 | #include <asm/system.h> | ||
43 | #include <asm/time.h> | ||
44 | #include <asm/rtas.h> | ||
45 | |||
46 | #include <asm/machdep.h> | ||
47 | |||
48 | /* | ||
49 | * We sponge a minor off of the misc major. No need slurping | ||
50 | * up another valuable major dev number for this. If you add | ||
51 | * an ioctl, make sure you don't conflict with SPARC's RTC | ||
52 | * ioctls. | ||
53 | */ | ||
54 | |||
55 | static ssize_t rtc_read(struct file *file, char __user *buf, | ||
56 | size_t count, loff_t *ppos); | ||
57 | |||
58 | static int rtc_ioctl(struct inode *inode, struct file *file, | ||
59 | unsigned int cmd, unsigned long arg); | ||
60 | |||
61 | static int rtc_read_proc(char *page, char **start, off_t off, | ||
62 | int count, int *eof, void *data); | ||
63 | |||
64 | /* | ||
65 | * If this driver ever becomes modularised, it will be really nice | ||
66 | * to make the epoch retain its value across module reload... | ||
67 | */ | ||
68 | |||
69 | static unsigned long epoch = 1900; /* year corresponding to 0x00 */ | ||
70 | |||
71 | static const unsigned char days_in_mo[] = | ||
72 | {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; | ||
73 | |||
74 | /* | ||
75 | * Now all the various file operations that we export. | ||
76 | */ | ||
77 | |||
78 | static ssize_t rtc_read(struct file *file, char __user *buf, | ||
79 | size_t count, loff_t *ppos) | ||
80 | { | ||
81 | return -EIO; | ||
82 | } | ||
83 | |||
84 | static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | ||
85 | unsigned long arg) | ||
86 | { | ||
87 | struct rtc_time wtime; | ||
88 | |||
89 | switch (cmd) { | ||
90 | case RTC_RD_TIME: /* Read the time/date from RTC */ | ||
91 | { | ||
92 | memset(&wtime, 0, sizeof(struct rtc_time)); | ||
93 | ppc_md.get_rtc_time(&wtime); | ||
94 | break; | ||
95 | } | ||
96 | case RTC_SET_TIME: /* Set the RTC */ | ||
97 | { | ||
98 | struct rtc_time rtc_tm; | ||
99 | unsigned char mon, day, hrs, min, sec, leap_yr; | ||
100 | unsigned int yrs; | ||
101 | |||
102 | if (!capable(CAP_SYS_TIME)) | ||
103 | return -EACCES; | ||
104 | |||
105 | if (copy_from_user(&rtc_tm, (struct rtc_time __user *)arg, | ||
106 | sizeof(struct rtc_time))) | ||
107 | return -EFAULT; | ||
108 | |||
109 | yrs = rtc_tm.tm_year; | ||
110 | mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */ | ||
111 | day = rtc_tm.tm_mday; | ||
112 | hrs = rtc_tm.tm_hour; | ||
113 | min = rtc_tm.tm_min; | ||
114 | sec = rtc_tm.tm_sec; | ||
115 | |||
116 | if (yrs < 70) | ||
117 | return -EINVAL; | ||
118 | |||
119 | leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400)); | ||
120 | |||
121 | if ((mon > 12) || (day == 0)) | ||
122 | return -EINVAL; | ||
123 | |||
124 | if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr))) | ||
125 | return -EINVAL; | ||
126 | |||
127 | if ((hrs >= 24) || (min >= 60) || (sec >= 60)) | ||
128 | return -EINVAL; | ||
129 | |||
130 | if ( yrs > 169 ) | ||
131 | return -EINVAL; | ||
132 | |||
133 | ppc_md.set_rtc_time(&rtc_tm); | ||
134 | |||
135 | return 0; | ||
136 | } | ||
137 | case RTC_EPOCH_READ: /* Read the epoch. */ | ||
138 | { | ||
139 | return put_user (epoch, (unsigned long __user *)arg); | ||
140 | } | ||
141 | case RTC_EPOCH_SET: /* Set the epoch. */ | ||
142 | { | ||
143 | /* | ||
144 | * There were no RTC clocks before 1900. | ||
145 | */ | ||
146 | if (arg < 1900) | ||
147 | return -EINVAL; | ||
148 | |||
149 | if (!capable(CAP_SYS_TIME)) | ||
150 | return -EACCES; | ||
151 | |||
152 | epoch = arg; | ||
153 | return 0; | ||
154 | } | ||
155 | default: | ||
156 | return -EINVAL; | ||
157 | } | ||
158 | return copy_to_user((void __user *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; | ||
159 | } | ||
160 | |||
161 | static int rtc_open(struct inode *inode, struct file *file) | ||
162 | { | ||
163 | nonseekable_open(inode, file); | ||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | static int rtc_release(struct inode *inode, struct file *file) | ||
168 | { | ||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | /* | ||
173 | * The various file operations we support. | ||
174 | */ | ||
175 | static struct file_operations rtc_fops = { | ||
176 | .owner = THIS_MODULE, | ||
177 | .llseek = no_llseek, | ||
178 | .read = rtc_read, | ||
179 | .ioctl = rtc_ioctl, | ||
180 | .open = rtc_open, | ||
181 | .release = rtc_release, | ||
182 | }; | ||
183 | |||
184 | static struct miscdevice rtc_dev = { | ||
185 | .minor = RTC_MINOR, | ||
186 | .name = "rtc", | ||
187 | .fops = &rtc_fops | ||
188 | }; | ||
189 | |||
190 | static int __init rtc_init(void) | ||
191 | { | ||
192 | int retval; | ||
193 | |||
194 | retval = misc_register(&rtc_dev); | ||
195 | if(retval < 0) | ||
196 | return retval; | ||
197 | |||
198 | #ifdef CONFIG_PROC_FS | ||
199 | if (create_proc_read_entry("driver/rtc", 0, NULL, rtc_read_proc, NULL) | ||
200 | == NULL) { | ||
201 | misc_deregister(&rtc_dev); | ||
202 | return -ENOMEM; | ||
203 | } | ||
204 | #endif | ||
205 | |||
206 | printk(KERN_INFO "i/pSeries Real Time Clock Driver v" RTC_VERSION "\n"); | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | static void __exit rtc_exit (void) | ||
212 | { | ||
213 | remove_proc_entry ("driver/rtc", NULL); | ||
214 | misc_deregister(&rtc_dev); | ||
215 | } | ||
216 | |||
217 | module_init(rtc_init); | ||
218 | module_exit(rtc_exit); | ||
219 | |||
220 | /* | ||
221 | * Info exported via "/proc/driver/rtc". | ||
222 | */ | ||
223 | |||
224 | static int rtc_proc_output (char *buf) | ||
225 | { | ||
226 | |||
227 | char *p; | ||
228 | struct rtc_time tm; | ||
229 | |||
230 | p = buf; | ||
231 | |||
232 | ppc_md.get_rtc_time(&tm); | ||
233 | |||
234 | /* | ||
235 | * There is no way to tell if the luser has the RTC set for local | ||
236 | * time or for Universal Standard Time (GMT). Probably local though. | ||
237 | */ | ||
238 | p += sprintf(p, | ||
239 | "rtc_time\t: %02d:%02d:%02d\n" | ||
240 | "rtc_date\t: %04d-%02d-%02d\n" | ||
241 | "rtc_epoch\t: %04lu\n", | ||
242 | tm.tm_hour, tm.tm_min, tm.tm_sec, | ||
243 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, epoch); | ||
244 | |||
245 | p += sprintf(p, | ||
246 | "DST_enable\t: no\n" | ||
247 | "BCD\t\t: yes\n" | ||
248 | "24hr\t\t: yes\n" ); | ||
249 | |||
250 | return p - buf; | ||
251 | } | ||
252 | |||
253 | static int rtc_read_proc(char *page, char **start, off_t off, | ||
254 | int count, int *eof, void *data) | ||
255 | { | ||
256 | int len = rtc_proc_output (page); | ||
257 | if (len <= off+count) *eof = 1; | ||
258 | *start = page + off; | ||
259 | len -= off; | ||
260 | if (len>count) len = count; | ||
261 | if (len<0) len = 0; | ||
262 | return len; | ||
263 | } | ||
264 | |||
265 | #ifdef CONFIG_PPC_RTAS | ||
266 | #define MAX_RTC_WAIT 5000 /* 5 sec */ | ||
267 | #define RTAS_CLOCK_BUSY (-2) | ||
268 | unsigned long rtas_get_boot_time(void) | ||
269 | { | ||
270 | int ret[8]; | ||
271 | int error, wait_time; | ||
272 | unsigned long max_wait_tb; | ||
273 | |||
274 | max_wait_tb = __get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; | ||
275 | do { | ||
276 | error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); | ||
277 | if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { | ||
278 | wait_time = rtas_extended_busy_delay_time(error); | ||
279 | /* This is boot time so we spin. */ | ||
280 | udelay(wait_time*1000); | ||
281 | error = RTAS_CLOCK_BUSY; | ||
282 | } | ||
283 | } while (error == RTAS_CLOCK_BUSY && (__get_tb() < max_wait_tb)); | ||
284 | |||
285 | if (error != 0 && printk_ratelimit()) { | ||
286 | printk(KERN_WARNING "error: reading the clock failed (%d)\n", | ||
287 | error); | ||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | return mktime(ret[0], ret[1], ret[2], ret[3], ret[4], ret[5]); | ||
292 | } | ||
293 | |||
294 | /* NOTE: get_rtc_time will get an error if executed in interrupt context | ||
295 | * and if a delay is needed to read the clock. In this case we just | ||
296 | * silently return without updating rtc_tm. | ||
297 | */ | ||
298 | void rtas_get_rtc_time(struct rtc_time *rtc_tm) | ||
299 | { | ||
300 | int ret[8]; | ||
301 | int error, wait_time; | ||
302 | unsigned long max_wait_tb; | ||
303 | |||
304 | max_wait_tb = __get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; | ||
305 | do { | ||
306 | error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); | ||
307 | if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { | ||
308 | if (in_interrupt() && printk_ratelimit()) { | ||
309 | printk(KERN_WARNING "error: reading clock would delay interrupt\n"); | ||
310 | return; /* delay not allowed */ | ||
311 | } | ||
312 | wait_time = rtas_extended_busy_delay_time(error); | ||
313 | msleep_interruptible(wait_time); | ||
314 | error = RTAS_CLOCK_BUSY; | ||
315 | } | ||
316 | } while (error == RTAS_CLOCK_BUSY && (__get_tb() < max_wait_tb)); | ||
317 | |||
318 | if (error != 0 && printk_ratelimit()) { | ||
319 | printk(KERN_WARNING "error: reading the clock failed (%d)\n", | ||
320 | error); | ||
321 | return; | ||
322 | } | ||
323 | |||
324 | rtc_tm->tm_sec = ret[5]; | ||
325 | rtc_tm->tm_min = ret[4]; | ||
326 | rtc_tm->tm_hour = ret[3]; | ||
327 | rtc_tm->tm_mday = ret[2]; | ||
328 | rtc_tm->tm_mon = ret[1] - 1; | ||
329 | rtc_tm->tm_year = ret[0] - 1900; | ||
330 | } | ||
331 | |||
332 | int rtas_set_rtc_time(struct rtc_time *tm) | ||
333 | { | ||
334 | int error, wait_time; | ||
335 | unsigned long max_wait_tb; | ||
336 | |||
337 | max_wait_tb = __get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; | ||
338 | do { | ||
339 | error = rtas_call(rtas_token("set-time-of-day"), 7, 1, NULL, | ||
340 | tm->tm_year + 1900, tm->tm_mon + 1, | ||
341 | tm->tm_mday, tm->tm_hour, tm->tm_min, | ||
342 | tm->tm_sec, 0); | ||
343 | if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { | ||
344 | if (in_interrupt()) | ||
345 | return 1; /* probably decrementer */ | ||
346 | wait_time = rtas_extended_busy_delay_time(error); | ||
347 | msleep_interruptible(wait_time); | ||
348 | error = RTAS_CLOCK_BUSY; | ||
349 | } | ||
350 | } while (error == RTAS_CLOCK_BUSY && (__get_tb() < max_wait_tb)); | ||
351 | |||
352 | if (error != 0 && printk_ratelimit()) | ||
353 | printk(KERN_WARNING "error: setting the clock failed (%d)\n", | ||
354 | error); | ||
355 | |||
356 | return 0; | ||
357 | } | ||
358 | #endif | ||
diff --git a/arch/ppc64/kernel/semaphore.c b/arch/ppc64/kernel/semaphore.c deleted file mode 100644 index a1c1db573e9c..000000000000 --- a/arch/ppc64/kernel/semaphore.c +++ /dev/null | |||
@@ -1,136 +0,0 @@ | |||
1 | /* | ||
2 | * | ||
3 | * | ||
4 | * PowerPC-specific semaphore code. | ||
5 | * | ||
6 | * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu> | ||
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 | * April 2001 - Reworked by Paul Mackerras <paulus@samba.org> | ||
14 | * to eliminate the SMP races in the old version between the updates | ||
15 | * of `count' and `waking'. Now we use negative `count' values to | ||
16 | * indicate that some process(es) are waiting for the semaphore. | ||
17 | */ | ||
18 | |||
19 | #include <linux/sched.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/module.h> | ||
22 | |||
23 | #include <asm/atomic.h> | ||
24 | #include <asm/semaphore.h> | ||
25 | #include <asm/errno.h> | ||
26 | |||
27 | /* | ||
28 | * Atomically update sem->count. | ||
29 | * This does the equivalent of the following: | ||
30 | * | ||
31 | * old_count = sem->count; | ||
32 | * tmp = MAX(old_count, 0) + incr; | ||
33 | * sem->count = tmp; | ||
34 | * return old_count; | ||
35 | */ | ||
36 | static inline int __sem_update_count(struct semaphore *sem, int incr) | ||
37 | { | ||
38 | int old_count, tmp; | ||
39 | |||
40 | __asm__ __volatile__("\n" | ||
41 | "1: lwarx %0,0,%3\n" | ||
42 | " srawi %1,%0,31\n" | ||
43 | " andc %1,%0,%1\n" | ||
44 | " add %1,%1,%4\n" | ||
45 | " stwcx. %1,0,%3\n" | ||
46 | " bne 1b" | ||
47 | : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count) | ||
48 | : "r" (&sem->count), "r" (incr), "m" (sem->count) | ||
49 | : "cc"); | ||
50 | |||
51 | return old_count; | ||
52 | } | ||
53 | |||
54 | void __up(struct semaphore *sem) | ||
55 | { | ||
56 | /* | ||
57 | * Note that we incremented count in up() before we came here, | ||
58 | * but that was ineffective since the result was <= 0, and | ||
59 | * any negative value of count is equivalent to 0. | ||
60 | * This ends up setting count to 1, unless count is now > 0 | ||
61 | * (i.e. because some other cpu has called up() in the meantime), | ||
62 | * in which case we just increment count. | ||
63 | */ | ||
64 | __sem_update_count(sem, 1); | ||
65 | wake_up(&sem->wait); | ||
66 | } | ||
67 | EXPORT_SYMBOL(__up); | ||
68 | |||
69 | /* | ||
70 | * Note that when we come in to __down or __down_interruptible, | ||
71 | * we have already decremented count, but that decrement was | ||
72 | * ineffective since the result was < 0, and any negative value | ||
73 | * of count is equivalent to 0. | ||
74 | * Thus it is only when we decrement count from some value > 0 | ||
75 | * that we have actually got the semaphore. | ||
76 | */ | ||
77 | void __sched __down(struct semaphore *sem) | ||
78 | { | ||
79 | struct task_struct *tsk = current; | ||
80 | DECLARE_WAITQUEUE(wait, tsk); | ||
81 | |||
82 | __set_task_state(tsk, TASK_UNINTERRUPTIBLE); | ||
83 | add_wait_queue_exclusive(&sem->wait, &wait); | ||
84 | |||
85 | /* | ||
86 | * Try to get the semaphore. If the count is > 0, then we've | ||
87 | * got the semaphore; we decrement count and exit the loop. | ||
88 | * If the count is 0 or negative, we set it to -1, indicating | ||
89 | * that we are asleep, and then sleep. | ||
90 | */ | ||
91 | while (__sem_update_count(sem, -1) <= 0) { | ||
92 | schedule(); | ||
93 | set_task_state(tsk, TASK_UNINTERRUPTIBLE); | ||
94 | } | ||
95 | remove_wait_queue(&sem->wait, &wait); | ||
96 | __set_task_state(tsk, TASK_RUNNING); | ||
97 | |||
98 | /* | ||
99 | * If there are any more sleepers, wake one of them up so | ||
100 | * that it can either get the semaphore, or set count to -1 | ||
101 | * indicating that there are still processes sleeping. | ||
102 | */ | ||
103 | wake_up(&sem->wait); | ||
104 | } | ||
105 | EXPORT_SYMBOL(__down); | ||
106 | |||
107 | int __sched __down_interruptible(struct semaphore * sem) | ||
108 | { | ||
109 | int retval = 0; | ||
110 | struct task_struct *tsk = current; | ||
111 | DECLARE_WAITQUEUE(wait, tsk); | ||
112 | |||
113 | __set_task_state(tsk, TASK_INTERRUPTIBLE); | ||
114 | add_wait_queue_exclusive(&sem->wait, &wait); | ||
115 | |||
116 | while (__sem_update_count(sem, -1) <= 0) { | ||
117 | if (signal_pending(current)) { | ||
118 | /* | ||
119 | * A signal is pending - give up trying. | ||
120 | * Set sem->count to 0 if it is negative, | ||
121 | * since we are no longer sleeping. | ||
122 | */ | ||
123 | __sem_update_count(sem, 0); | ||
124 | retval = -EINTR; | ||
125 | break; | ||
126 | } | ||
127 | schedule(); | ||
128 | set_task_state(tsk, TASK_INTERRUPTIBLE); | ||
129 | } | ||
130 | remove_wait_queue(&sem->wait, &wait); | ||
131 | __set_task_state(tsk, TASK_RUNNING); | ||
132 | |||
133 | wake_up(&sem->wait); | ||
134 | return retval; | ||
135 | } | ||
136 | EXPORT_SYMBOL(__down_interruptible); | ||
diff --git a/arch/ppc64/kernel/vdso.c b/arch/ppc64/kernel/vdso.c deleted file mode 100644 index 1bbacac44988..000000000000 --- a/arch/ppc64/kernel/vdso.c +++ /dev/null | |||
@@ -1,625 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/ppc64/kernel/vdso.c | ||
3 | * | ||
4 | * Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp. | ||
5 | * <benh@kernel.crashing.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version | ||
10 | * 2 of the License, or (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/config.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/sched.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/mm.h> | ||
19 | #include <linux/smp.h> | ||
20 | #include <linux/smp_lock.h> | ||
21 | #include <linux/stddef.h> | ||
22 | #include <linux/unistd.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/user.h> | ||
25 | #include <linux/elf.h> | ||
26 | #include <linux/security.h> | ||
27 | #include <linux/bootmem.h> | ||
28 | |||
29 | #include <asm/pgtable.h> | ||
30 | #include <asm/system.h> | ||
31 | #include <asm/processor.h> | ||
32 | #include <asm/mmu.h> | ||
33 | #include <asm/mmu_context.h> | ||
34 | #include <asm/machdep.h> | ||
35 | #include <asm/cputable.h> | ||
36 | #include <asm/sections.h> | ||
37 | #include <asm/systemcfg.h> | ||
38 | #include <asm/vdso.h> | ||
39 | |||
40 | #undef DEBUG | ||
41 | |||
42 | #ifdef DEBUG | ||
43 | #define DBG(fmt...) printk(fmt) | ||
44 | #else | ||
45 | #define DBG(fmt...) | ||
46 | #endif | ||
47 | |||
48 | |||
49 | /* | ||
50 | * The vDSOs themselves are here | ||
51 | */ | ||
52 | extern char vdso64_start, vdso64_end; | ||
53 | extern char vdso32_start, vdso32_end; | ||
54 | |||
55 | static void *vdso64_kbase = &vdso64_start; | ||
56 | static void *vdso32_kbase = &vdso32_start; | ||
57 | |||
58 | unsigned int vdso64_pages; | ||
59 | unsigned int vdso32_pages; | ||
60 | |||
61 | /* Signal trampolines user addresses */ | ||
62 | |||
63 | unsigned long vdso64_rt_sigtramp; | ||
64 | unsigned long vdso32_sigtramp; | ||
65 | unsigned long vdso32_rt_sigtramp; | ||
66 | |||
67 | /* Format of the patch table */ | ||
68 | struct vdso_patch_def | ||
69 | { | ||
70 | u32 pvr_mask, pvr_value; | ||
71 | const char *gen_name; | ||
72 | const char *fix_name; | ||
73 | }; | ||
74 | |||
75 | /* Table of functions to patch based on the CPU type/revision | ||
76 | * | ||
77 | * TODO: Improve by adding whole lists for each entry | ||
78 | */ | ||
79 | static struct vdso_patch_def vdso_patches[] = { | ||
80 | { | ||
81 | 0xffff0000, 0x003a0000, /* POWER5 */ | ||
82 | "__kernel_sync_dicache", "__kernel_sync_dicache_p5" | ||
83 | }, | ||
84 | { | ||
85 | 0xffff0000, 0x003b0000, /* POWER5 */ | ||
86 | "__kernel_sync_dicache", "__kernel_sync_dicache_p5" | ||
87 | }, | ||
88 | }; | ||
89 | |||
90 | /* | ||
91 | * Some infos carried around for each of them during parsing at | ||
92 | * boot time. | ||
93 | */ | ||
94 | struct lib32_elfinfo | ||
95 | { | ||
96 | Elf32_Ehdr *hdr; /* ptr to ELF */ | ||
97 | Elf32_Sym *dynsym; /* ptr to .dynsym section */ | ||
98 | unsigned long dynsymsize; /* size of .dynsym section */ | ||
99 | char *dynstr; /* ptr to .dynstr section */ | ||
100 | unsigned long text; /* offset of .text section in .so */ | ||
101 | }; | ||
102 | |||
103 | struct lib64_elfinfo | ||
104 | { | ||
105 | Elf64_Ehdr *hdr; | ||
106 | Elf64_Sym *dynsym; | ||
107 | unsigned long dynsymsize; | ||
108 | char *dynstr; | ||
109 | unsigned long text; | ||
110 | }; | ||
111 | |||
112 | |||
113 | #ifdef __DEBUG | ||
114 | static void dump_one_vdso_page(struct page *pg, struct page *upg) | ||
115 | { | ||
116 | printk("kpg: %p (c:%d,f:%08lx)", __va(page_to_pfn(pg) << PAGE_SHIFT), | ||
117 | page_count(pg), | ||
118 | pg->flags); | ||
119 | if (upg/* && pg != upg*/) { | ||
120 | printk(" upg: %p (c:%d,f:%08lx)", __va(page_to_pfn(upg) << PAGE_SHIFT), | ||
121 | page_count(upg), | ||
122 | upg->flags); | ||
123 | } | ||
124 | printk("\n"); | ||
125 | } | ||
126 | |||
127 | static void dump_vdso_pages(struct vm_area_struct * vma) | ||
128 | { | ||
129 | int i; | ||
130 | |||
131 | if (!vma || test_thread_flag(TIF_32BIT)) { | ||
132 | printk("vDSO32 @ %016lx:\n", (unsigned long)vdso32_kbase); | ||
133 | for (i=0; i<vdso32_pages; i++) { | ||
134 | struct page *pg = virt_to_page(vdso32_kbase + i*PAGE_SIZE); | ||
135 | struct page *upg = (vma && vma->vm_mm) ? | ||
136 | follow_page(vma->vm_mm, vma->vm_start + i*PAGE_SIZE, 0) | ||
137 | : NULL; | ||
138 | dump_one_vdso_page(pg, upg); | ||
139 | } | ||
140 | } | ||
141 | if (!vma || !test_thread_flag(TIF_32BIT)) { | ||
142 | printk("vDSO64 @ %016lx:\n", (unsigned long)vdso64_kbase); | ||
143 | for (i=0; i<vdso64_pages; i++) { | ||
144 | struct page *pg = virt_to_page(vdso64_kbase + i*PAGE_SIZE); | ||
145 | struct page *upg = (vma && vma->vm_mm) ? | ||
146 | follow_page(vma->vm_mm, vma->vm_start + i*PAGE_SIZE, 0) | ||
147 | : NULL; | ||
148 | dump_one_vdso_page(pg, upg); | ||
149 | } | ||
150 | } | ||
151 | } | ||
152 | #endif /* DEBUG */ | ||
153 | |||
154 | /* | ||
155 | * Keep a dummy vma_close for now, it will prevent VMA merging. | ||
156 | */ | ||
157 | static void vdso_vma_close(struct vm_area_struct * vma) | ||
158 | { | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * Our nopage() function, maps in the actual vDSO kernel pages, they will | ||
163 | * be mapped read-only by do_no_page(), and eventually COW'ed, either | ||
164 | * right away for an initial write access, or by do_wp_page(). | ||
165 | */ | ||
166 | static struct page * vdso_vma_nopage(struct vm_area_struct * vma, | ||
167 | unsigned long address, int *type) | ||
168 | { | ||
169 | unsigned long offset = address - vma->vm_start; | ||
170 | struct page *pg; | ||
171 | void *vbase = test_thread_flag(TIF_32BIT) ? vdso32_kbase : vdso64_kbase; | ||
172 | |||
173 | DBG("vdso_vma_nopage(current: %s, address: %016lx, off: %lx)\n", | ||
174 | current->comm, address, offset); | ||
175 | |||
176 | if (address < vma->vm_start || address > vma->vm_end) | ||
177 | return NOPAGE_SIGBUS; | ||
178 | |||
179 | /* | ||
180 | * Last page is systemcfg. | ||
181 | */ | ||
182 | if ((vma->vm_end - address) <= PAGE_SIZE) | ||
183 | pg = virt_to_page(_systemcfg); | ||
184 | else | ||
185 | pg = virt_to_page(vbase + offset); | ||
186 | |||
187 | get_page(pg); | ||
188 | DBG(" ->page count: %d\n", page_count(pg)); | ||
189 | |||
190 | return pg; | ||
191 | } | ||
192 | |||
193 | static struct vm_operations_struct vdso_vmops = { | ||
194 | .close = vdso_vma_close, | ||
195 | .nopage = vdso_vma_nopage, | ||
196 | }; | ||
197 | |||
198 | /* | ||
199 | * This is called from binfmt_elf, we create the special vma for the | ||
200 | * vDSO and insert it into the mm struct tree | ||
201 | */ | ||
202 | int arch_setup_additional_pages(struct linux_binprm *bprm, int executable_stack) | ||
203 | { | ||
204 | struct mm_struct *mm = current->mm; | ||
205 | struct vm_area_struct *vma; | ||
206 | unsigned long vdso_pages; | ||
207 | unsigned long vdso_base; | ||
208 | |||
209 | if (test_thread_flag(TIF_32BIT)) { | ||
210 | vdso_pages = vdso32_pages; | ||
211 | vdso_base = VDSO32_MBASE; | ||
212 | } else { | ||
213 | vdso_pages = vdso64_pages; | ||
214 | vdso_base = VDSO64_MBASE; | ||
215 | } | ||
216 | |||
217 | current->thread.vdso_base = 0; | ||
218 | |||
219 | /* vDSO has a problem and was disabled, just don't "enable" it for the | ||
220 | * process | ||
221 | */ | ||
222 | if (vdso_pages == 0) | ||
223 | return 0; | ||
224 | |||
225 | vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); | ||
226 | if (vma == NULL) | ||
227 | return -ENOMEM; | ||
228 | |||
229 | memset(vma, 0, sizeof(*vma)); | ||
230 | |||
231 | /* | ||
232 | * pick a base address for the vDSO in process space. We try to put it | ||
233 | * at vdso_base which is the "natural" base for it, but we might fail | ||
234 | * and end up putting it elsewhere. | ||
235 | */ | ||
236 | vdso_base = get_unmapped_area(NULL, vdso_base, | ||
237 | vdso_pages << PAGE_SHIFT, 0, 0); | ||
238 | if (vdso_base & ~PAGE_MASK) { | ||
239 | kmem_cache_free(vm_area_cachep, vma); | ||
240 | return (int)vdso_base; | ||
241 | } | ||
242 | |||
243 | current->thread.vdso_base = vdso_base; | ||
244 | |||
245 | vma->vm_mm = mm; | ||
246 | vma->vm_start = current->thread.vdso_base; | ||
247 | |||
248 | /* | ||
249 | * the VMA size is one page more than the vDSO since systemcfg | ||
250 | * is mapped in the last one | ||
251 | */ | ||
252 | vma->vm_end = vma->vm_start + ((vdso_pages + 1) << PAGE_SHIFT); | ||
253 | |||
254 | /* | ||
255 | * our vma flags don't have VM_WRITE so by default, the process isn't allowed | ||
256 | * to write those pages. | ||
257 | * gdb can break that with ptrace interface, and thus trigger COW on those | ||
258 | * pages but it's then your responsibility to never do that on the "data" page | ||
259 | * of the vDSO or you'll stop getting kernel updates and your nice userland | ||
260 | * gettimeofday will be totally dead. It's fine to use that for setting | ||
261 | * breakpoints in the vDSO code pages though | ||
262 | */ | ||
263 | vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC | VM_RESERVED; | ||
264 | vma->vm_flags |= mm->def_flags; | ||
265 | vma->vm_page_prot = protection_map[vma->vm_flags & 0x7]; | ||
266 | vma->vm_ops = &vdso_vmops; | ||
267 | |||
268 | down_write(&mm->mmap_sem); | ||
269 | if (insert_vm_struct(mm, vma)) { | ||
270 | up_write(&mm->mmap_sem); | ||
271 | kmem_cache_free(vm_area_cachep, vma); | ||
272 | return -ENOMEM; | ||
273 | } | ||
274 | mm->total_vm += (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; | ||
275 | up_write(&mm->mmap_sem); | ||
276 | |||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | static void * __init find_section32(Elf32_Ehdr *ehdr, const char *secname, | ||
281 | unsigned long *size) | ||
282 | { | ||
283 | Elf32_Shdr *sechdrs; | ||
284 | unsigned int i; | ||
285 | char *secnames; | ||
286 | |||
287 | /* Grab section headers and strings so we can tell who is who */ | ||
288 | sechdrs = (void *)ehdr + ehdr->e_shoff; | ||
289 | secnames = (void *)ehdr + sechdrs[ehdr->e_shstrndx].sh_offset; | ||
290 | |||
291 | /* Find the section they want */ | ||
292 | for (i = 1; i < ehdr->e_shnum; i++) { | ||
293 | if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) { | ||
294 | if (size) | ||
295 | *size = sechdrs[i].sh_size; | ||
296 | return (void *)ehdr + sechdrs[i].sh_offset; | ||
297 | } | ||
298 | } | ||
299 | *size = 0; | ||
300 | return NULL; | ||
301 | } | ||
302 | |||
303 | static void * __init find_section64(Elf64_Ehdr *ehdr, const char *secname, | ||
304 | unsigned long *size) | ||
305 | { | ||
306 | Elf64_Shdr *sechdrs; | ||
307 | unsigned int i; | ||
308 | char *secnames; | ||
309 | |||
310 | /* Grab section headers and strings so we can tell who is who */ | ||
311 | sechdrs = (void *)ehdr + ehdr->e_shoff; | ||
312 | secnames = (void *)ehdr + sechdrs[ehdr->e_shstrndx].sh_offset; | ||
313 | |||
314 | /* Find the section they want */ | ||
315 | for (i = 1; i < ehdr->e_shnum; i++) { | ||
316 | if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) { | ||
317 | if (size) | ||
318 | *size = sechdrs[i].sh_size; | ||
319 | return (void *)ehdr + sechdrs[i].sh_offset; | ||
320 | } | ||
321 | } | ||
322 | if (size) | ||
323 | *size = 0; | ||
324 | return NULL; | ||
325 | } | ||
326 | |||
327 | static Elf32_Sym * __init find_symbol32(struct lib32_elfinfo *lib, const char *symname) | ||
328 | { | ||
329 | unsigned int i; | ||
330 | char name[32], *c; | ||
331 | |||
332 | for (i = 0; i < (lib->dynsymsize / sizeof(Elf32_Sym)); i++) { | ||
333 | if (lib->dynsym[i].st_name == 0) | ||
334 | continue; | ||
335 | strlcpy(name, lib->dynstr + lib->dynsym[i].st_name, 32); | ||
336 | c = strchr(name, '@'); | ||
337 | if (c) | ||
338 | *c = 0; | ||
339 | if (strcmp(symname, name) == 0) | ||
340 | return &lib->dynsym[i]; | ||
341 | } | ||
342 | return NULL; | ||
343 | } | ||
344 | |||
345 | static Elf64_Sym * __init find_symbol64(struct lib64_elfinfo *lib, const char *symname) | ||
346 | { | ||
347 | unsigned int i; | ||
348 | char name[32], *c; | ||
349 | |||
350 | for (i = 0; i < (lib->dynsymsize / sizeof(Elf64_Sym)); i++) { | ||
351 | if (lib->dynsym[i].st_name == 0) | ||
352 | continue; | ||
353 | strlcpy(name, lib->dynstr + lib->dynsym[i].st_name, 32); | ||
354 | c = strchr(name, '@'); | ||
355 | if (c) | ||
356 | *c = 0; | ||
357 | if (strcmp(symname, name) == 0) | ||
358 | return &lib->dynsym[i]; | ||
359 | } | ||
360 | return NULL; | ||
361 | } | ||
362 | |||
363 | /* Note that we assume the section is .text and the symbol is relative to | ||
364 | * the library base | ||
365 | */ | ||
366 | static unsigned long __init find_function32(struct lib32_elfinfo *lib, const char *symname) | ||
367 | { | ||
368 | Elf32_Sym *sym = find_symbol32(lib, symname); | ||
369 | |||
370 | if (sym == NULL) { | ||
371 | printk(KERN_WARNING "vDSO32: function %s not found !\n", symname); | ||
372 | return 0; | ||
373 | } | ||
374 | return sym->st_value - VDSO32_LBASE; | ||
375 | } | ||
376 | |||
377 | /* Note that we assume the section is .text and the symbol is relative to | ||
378 | * the library base | ||
379 | */ | ||
380 | static unsigned long __init find_function64(struct lib64_elfinfo *lib, const char *symname) | ||
381 | { | ||
382 | Elf64_Sym *sym = find_symbol64(lib, symname); | ||
383 | |||
384 | if (sym == NULL) { | ||
385 | printk(KERN_WARNING "vDSO64: function %s not found !\n", symname); | ||
386 | return 0; | ||
387 | } | ||
388 | #ifdef VDS64_HAS_DESCRIPTORS | ||
389 | return *((u64 *)(vdso64_kbase + sym->st_value - VDSO64_LBASE)) - VDSO64_LBASE; | ||
390 | #else | ||
391 | return sym->st_value - VDSO64_LBASE; | ||
392 | #endif | ||
393 | } | ||
394 | |||
395 | |||
396 | static __init int vdso_do_find_sections(struct lib32_elfinfo *v32, | ||
397 | struct lib64_elfinfo *v64) | ||
398 | { | ||
399 | void *sect; | ||
400 | |||
401 | /* | ||
402 | * Locate symbol tables & text section | ||
403 | */ | ||
404 | |||
405 | v32->dynsym = find_section32(v32->hdr, ".dynsym", &v32->dynsymsize); | ||
406 | v32->dynstr = find_section32(v32->hdr, ".dynstr", NULL); | ||
407 | if (v32->dynsym == NULL || v32->dynstr == NULL) { | ||
408 | printk(KERN_ERR "vDSO32: a required symbol section was not found\n"); | ||
409 | return -1; | ||
410 | } | ||
411 | sect = find_section32(v32->hdr, ".text", NULL); | ||
412 | if (sect == NULL) { | ||
413 | printk(KERN_ERR "vDSO32: the .text section was not found\n"); | ||
414 | return -1; | ||
415 | } | ||
416 | v32->text = sect - vdso32_kbase; | ||
417 | |||
418 | v64->dynsym = find_section64(v64->hdr, ".dynsym", &v64->dynsymsize); | ||
419 | v64->dynstr = find_section64(v64->hdr, ".dynstr", NULL); | ||
420 | if (v64->dynsym == NULL || v64->dynstr == NULL) { | ||
421 | printk(KERN_ERR "vDSO64: a required symbol section was not found\n"); | ||
422 | return -1; | ||
423 | } | ||
424 | sect = find_section64(v64->hdr, ".text", NULL); | ||
425 | if (sect == NULL) { | ||
426 | printk(KERN_ERR "vDSO64: the .text section was not found\n"); | ||
427 | return -1; | ||
428 | } | ||
429 | v64->text = sect - vdso64_kbase; | ||
430 | |||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | static __init void vdso_setup_trampolines(struct lib32_elfinfo *v32, | ||
435 | struct lib64_elfinfo *v64) | ||
436 | { | ||
437 | /* | ||
438 | * Find signal trampolines | ||
439 | */ | ||
440 | |||
441 | vdso64_rt_sigtramp = find_function64(v64, "__kernel_sigtramp_rt64"); | ||
442 | vdso32_sigtramp = find_function32(v32, "__kernel_sigtramp32"); | ||
443 | vdso32_rt_sigtramp = find_function32(v32, "__kernel_sigtramp_rt32"); | ||
444 | } | ||
445 | |||
446 | static __init int vdso_fixup_datapage(struct lib32_elfinfo *v32, | ||
447 | struct lib64_elfinfo *v64) | ||
448 | { | ||
449 | Elf32_Sym *sym32; | ||
450 | Elf64_Sym *sym64; | ||
451 | |||
452 | sym32 = find_symbol32(v32, "__kernel_datapage_offset"); | ||
453 | if (sym32 == NULL) { | ||
454 | printk(KERN_ERR "vDSO32: Can't find symbol __kernel_datapage_offset !\n"); | ||
455 | return -1; | ||
456 | } | ||
457 | *((int *)(vdso32_kbase + (sym32->st_value - VDSO32_LBASE))) = | ||
458 | (vdso32_pages << PAGE_SHIFT) - (sym32->st_value - VDSO32_LBASE); | ||
459 | |||
460 | sym64 = find_symbol64(v64, "__kernel_datapage_offset"); | ||
461 | if (sym64 == NULL) { | ||
462 | printk(KERN_ERR "vDSO64: Can't find symbol __kernel_datapage_offset !\n"); | ||
463 | return -1; | ||
464 | } | ||
465 | *((int *)(vdso64_kbase + sym64->st_value - VDSO64_LBASE)) = | ||
466 | (vdso64_pages << PAGE_SHIFT) - (sym64->st_value - VDSO64_LBASE); | ||
467 | |||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | static int vdso_do_func_patch32(struct lib32_elfinfo *v32, | ||
472 | struct lib64_elfinfo *v64, | ||
473 | const char *orig, const char *fix) | ||
474 | { | ||
475 | Elf32_Sym *sym32_gen, *sym32_fix; | ||
476 | |||
477 | sym32_gen = find_symbol32(v32, orig); | ||
478 | if (sym32_gen == NULL) { | ||
479 | printk(KERN_ERR "vDSO32: Can't find symbol %s !\n", orig); | ||
480 | return -1; | ||
481 | } | ||
482 | sym32_fix = find_symbol32(v32, fix); | ||
483 | if (sym32_fix == NULL) { | ||
484 | printk(KERN_ERR "vDSO32: Can't find symbol %s !\n", fix); | ||
485 | return -1; | ||
486 | } | ||
487 | sym32_gen->st_value = sym32_fix->st_value; | ||
488 | sym32_gen->st_size = sym32_fix->st_size; | ||
489 | sym32_gen->st_info = sym32_fix->st_info; | ||
490 | sym32_gen->st_other = sym32_fix->st_other; | ||
491 | sym32_gen->st_shndx = sym32_fix->st_shndx; | ||
492 | |||
493 | return 0; | ||
494 | } | ||
495 | |||
496 | static int vdso_do_func_patch64(struct lib32_elfinfo *v32, | ||
497 | struct lib64_elfinfo *v64, | ||
498 | const char *orig, const char *fix) | ||
499 | { | ||
500 | Elf64_Sym *sym64_gen, *sym64_fix; | ||
501 | |||
502 | sym64_gen = find_symbol64(v64, orig); | ||
503 | if (sym64_gen == NULL) { | ||
504 | printk(KERN_ERR "vDSO64: Can't find symbol %s !\n", orig); | ||
505 | return -1; | ||
506 | } | ||
507 | sym64_fix = find_symbol64(v64, fix); | ||
508 | if (sym64_fix == NULL) { | ||
509 | printk(KERN_ERR "vDSO64: Can't find symbol %s !\n", fix); | ||
510 | return -1; | ||
511 | } | ||
512 | sym64_gen->st_value = sym64_fix->st_value; | ||
513 | sym64_gen->st_size = sym64_fix->st_size; | ||
514 | sym64_gen->st_info = sym64_fix->st_info; | ||
515 | sym64_gen->st_other = sym64_fix->st_other; | ||
516 | sym64_gen->st_shndx = sym64_fix->st_shndx; | ||
517 | |||
518 | return 0; | ||
519 | } | ||
520 | |||
521 | static __init int vdso_fixup_alt_funcs(struct lib32_elfinfo *v32, | ||
522 | struct lib64_elfinfo *v64) | ||
523 | { | ||
524 | u32 pvr; | ||
525 | int i; | ||
526 | |||
527 | pvr = mfspr(SPRN_PVR); | ||
528 | for (i = 0; i < ARRAY_SIZE(vdso_patches); i++) { | ||
529 | struct vdso_patch_def *patch = &vdso_patches[i]; | ||
530 | int match = (pvr & patch->pvr_mask) == patch->pvr_value; | ||
531 | |||
532 | DBG("patch %d (mask: %x, pvr: %x) : %s\n", | ||
533 | i, patch->pvr_mask, patch->pvr_value, match ? "match" : "skip"); | ||
534 | |||
535 | if (!match) | ||
536 | continue; | ||
537 | |||
538 | DBG("replacing %s with %s...\n", patch->gen_name, patch->fix_name); | ||
539 | |||
540 | /* | ||
541 | * Patch the 32 bits and 64 bits symbols. Note that we do not patch | ||
542 | * the "." symbol on 64 bits. It would be easy to do, but doesn't | ||
543 | * seem to be necessary, patching the OPD symbol is enough. | ||
544 | */ | ||
545 | vdso_do_func_patch32(v32, v64, patch->gen_name, patch->fix_name); | ||
546 | vdso_do_func_patch64(v32, v64, patch->gen_name, patch->fix_name); | ||
547 | } | ||
548 | |||
549 | return 0; | ||
550 | } | ||
551 | |||
552 | |||
553 | static __init int vdso_setup(void) | ||
554 | { | ||
555 | struct lib32_elfinfo v32; | ||
556 | struct lib64_elfinfo v64; | ||
557 | |||
558 | v32.hdr = vdso32_kbase; | ||
559 | v64.hdr = vdso64_kbase; | ||
560 | |||
561 | if (vdso_do_find_sections(&v32, &v64)) | ||
562 | return -1; | ||
563 | |||
564 | if (vdso_fixup_datapage(&v32, &v64)) | ||
565 | return -1; | ||
566 | |||
567 | if (vdso_fixup_alt_funcs(&v32, &v64)) | ||
568 | return -1; | ||
569 | |||
570 | vdso_setup_trampolines(&v32, &v64); | ||
571 | |||
572 | return 0; | ||
573 | } | ||
574 | |||
575 | void __init vdso_init(void) | ||
576 | { | ||
577 | int i; | ||
578 | |||
579 | vdso64_pages = (&vdso64_end - &vdso64_start) >> PAGE_SHIFT; | ||
580 | vdso32_pages = (&vdso32_end - &vdso32_start) >> PAGE_SHIFT; | ||
581 | |||
582 | DBG("vdso64_kbase: %p, 0x%x pages, vdso32_kbase: %p, 0x%x pages\n", | ||
583 | vdso64_kbase, vdso64_pages, vdso32_kbase, vdso32_pages); | ||
584 | |||
585 | /* | ||
586 | * Initialize the vDSO images in memory, that is do necessary | ||
587 | * fixups of vDSO symbols, locate trampolines, etc... | ||
588 | */ | ||
589 | if (vdso_setup()) { | ||
590 | printk(KERN_ERR "vDSO setup failure, not enabled !\n"); | ||
591 | /* XXX should free pages here ? */ | ||
592 | vdso64_pages = vdso32_pages = 0; | ||
593 | return; | ||
594 | } | ||
595 | |||
596 | /* Make sure pages are in the correct state */ | ||
597 | for (i = 0; i < vdso64_pages; i++) { | ||
598 | struct page *pg = virt_to_page(vdso64_kbase + i*PAGE_SIZE); | ||
599 | ClearPageReserved(pg); | ||
600 | get_page(pg); | ||
601 | } | ||
602 | for (i = 0; i < vdso32_pages; i++) { | ||
603 | struct page *pg = virt_to_page(vdso32_kbase + i*PAGE_SIZE); | ||
604 | ClearPageReserved(pg); | ||
605 | get_page(pg); | ||
606 | } | ||
607 | |||
608 | get_page(virt_to_page(_systemcfg)); | ||
609 | } | ||
610 | |||
611 | int in_gate_area_no_task(unsigned long addr) | ||
612 | { | ||
613 | return 0; | ||
614 | } | ||
615 | |||
616 | int in_gate_area(struct task_struct *task, unsigned long addr) | ||
617 | { | ||
618 | return 0; | ||
619 | } | ||
620 | |||
621 | struct vm_area_struct *get_gate_vma(struct task_struct *tsk) | ||
622 | { | ||
623 | return NULL; | ||
624 | } | ||
625 | |||
diff --git a/arch/ppc64/kernel/vmlinux.lds.S b/arch/ppc64/kernel/vmlinux.lds.S deleted file mode 100644 index 022f220e772f..000000000000 --- a/arch/ppc64/kernel/vmlinux.lds.S +++ /dev/null | |||
@@ -1,151 +0,0 @@ | |||
1 | #include <asm/page.h> | ||
2 | #include <asm-generic/vmlinux.lds.h> | ||
3 | |||
4 | OUTPUT_ARCH(powerpc:common64) | ||
5 | jiffies = jiffies_64; | ||
6 | SECTIONS | ||
7 | { | ||
8 | /* Sections to be discarded. */ | ||
9 | /DISCARD/ : { | ||
10 | *(.exitcall.exit) | ||
11 | } | ||
12 | |||
13 | |||
14 | /* Read-only sections, merged into text segment: */ | ||
15 | .text : { | ||
16 | *(.text .text.*) | ||
17 | SCHED_TEXT | ||
18 | LOCK_TEXT | ||
19 | KPROBES_TEXT | ||
20 | *(.fixup) | ||
21 | . = ALIGN(PAGE_SIZE); | ||
22 | _etext = .; | ||
23 | } | ||
24 | |||
25 | __ex_table : { | ||
26 | __start___ex_table = .; | ||
27 | *(__ex_table) | ||
28 | __stop___ex_table = .; | ||
29 | } | ||
30 | |||
31 | __bug_table : { | ||
32 | __start___bug_table = .; | ||
33 | *(__bug_table) | ||
34 | __stop___bug_table = .; | ||
35 | } | ||
36 | |||
37 | __ftr_fixup : { | ||
38 | __start___ftr_fixup = .; | ||
39 | *(__ftr_fixup) | ||
40 | __stop___ftr_fixup = .; | ||
41 | } | ||
42 | |||
43 | RODATA | ||
44 | |||
45 | |||
46 | /* will be freed after init */ | ||
47 | . = ALIGN(PAGE_SIZE); | ||
48 | __init_begin = .; | ||
49 | |||
50 | .init.text : { | ||
51 | _sinittext = .; | ||
52 | *(.init.text) | ||
53 | _einittext = .; | ||
54 | } | ||
55 | |||
56 | .init.data : { | ||
57 | *(.init.data) | ||
58 | } | ||
59 | |||
60 | . = ALIGN(16); | ||
61 | .init.setup : { | ||
62 | __setup_start = .; | ||
63 | *(.init.setup) | ||
64 | __setup_end = .; | ||
65 | } | ||
66 | |||
67 | .initcall.init : { | ||
68 | __initcall_start = .; | ||
69 | *(.initcall1.init) | ||
70 | *(.initcall2.init) | ||
71 | *(.initcall3.init) | ||
72 | *(.initcall4.init) | ||
73 | *(.initcall5.init) | ||
74 | *(.initcall6.init) | ||
75 | *(.initcall7.init) | ||
76 | __initcall_end = .; | ||
77 | } | ||
78 | |||
79 | .con_initcall.init : { | ||
80 | __con_initcall_start = .; | ||
81 | *(.con_initcall.init) | ||
82 | __con_initcall_end = .; | ||
83 | } | ||
84 | |||
85 | SECURITY_INIT | ||
86 | |||
87 | . = ALIGN(PAGE_SIZE); | ||
88 | .init.ramfs : { | ||
89 | __initramfs_start = .; | ||
90 | *(.init.ramfs) | ||
91 | __initramfs_end = .; | ||
92 | } | ||
93 | |||
94 | .data.percpu : { | ||
95 | __per_cpu_start = .; | ||
96 | *(.data.percpu) | ||
97 | __per_cpu_end = .; | ||
98 | } | ||
99 | |||
100 | . = ALIGN(PAGE_SIZE); | ||
101 | . = ALIGN(16384); | ||
102 | __init_end = .; | ||
103 | /* freed after init ends here */ | ||
104 | |||
105 | |||
106 | /* Read/write sections */ | ||
107 | . = ALIGN(PAGE_SIZE); | ||
108 | . = ALIGN(16384); | ||
109 | _sdata = .; | ||
110 | /* The initial task and kernel stack */ | ||
111 | .data.init_task : { | ||
112 | *(.data.init_task) | ||
113 | } | ||
114 | |||
115 | . = ALIGN(PAGE_SIZE); | ||
116 | .data.page_aligned : { | ||
117 | *(.data.page_aligned) | ||
118 | } | ||
119 | |||
120 | .data.cacheline_aligned : { | ||
121 | *(.data.cacheline_aligned) | ||
122 | } | ||
123 | |||
124 | .data : { | ||
125 | *(.data .data.rel* .toc1) | ||
126 | *(.branch_lt) | ||
127 | } | ||
128 | |||
129 | .opd : { | ||
130 | *(.opd) | ||
131 | } | ||
132 | |||
133 | .got : { | ||
134 | __toc_start = .; | ||
135 | *(.got) | ||
136 | *(.toc) | ||
137 | . = ALIGN(PAGE_SIZE); | ||
138 | _edata = .; | ||
139 | } | ||
140 | |||
141 | |||
142 | . = ALIGN(PAGE_SIZE); | ||
143 | .bss : { | ||
144 | __bss_start = .; | ||
145 | *(.bss) | ||
146 | __bss_stop = .; | ||
147 | } | ||
148 | |||
149 | . = ALIGN(PAGE_SIZE); | ||
150 | _end = . ; | ||
151 | } | ||
diff --git a/arch/ppc64/xmon/privinst.h b/arch/ppc64/xmon/privinst.h deleted file mode 100644 index 02eb40dac0b3..000000000000 --- a/arch/ppc64/xmon/privinst.h +++ /dev/null | |||
@@ -1,64 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1996 Paul Mackerras. | ||
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 | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #define GETREG(reg) \ | ||
11 | static inline unsigned long get_ ## reg (void) \ | ||
12 | { unsigned long ret; asm volatile ("mf" #reg " %0" : "=r" (ret) :); return ret; } | ||
13 | |||
14 | #define SETREG(reg) \ | ||
15 | static inline void set_ ## reg (unsigned long val) \ | ||
16 | { asm volatile ("mt" #reg " %0" : : "r" (val)); } | ||
17 | |||
18 | GETREG(msr) | ||
19 | SETREG(msrd) | ||
20 | GETREG(cr) | ||
21 | |||
22 | #define GSETSPR(n, name) \ | ||
23 | static inline long get_ ## name (void) \ | ||
24 | { long ret; asm volatile ("mfspr %0," #n : "=r" (ret) : ); return ret; } \ | ||
25 | static inline void set_ ## name (long val) \ | ||
26 | { asm volatile ("mtspr " #n ",%0" : : "r" (val)); } | ||
27 | |||
28 | GSETSPR(0, mq) | ||
29 | GSETSPR(1, xer) | ||
30 | GSETSPR(4, rtcu) | ||
31 | GSETSPR(5, rtcl) | ||
32 | GSETSPR(8, lr) | ||
33 | GSETSPR(9, ctr) | ||
34 | GSETSPR(18, dsisr) | ||
35 | GSETSPR(19, dar) | ||
36 | GSETSPR(22, dec) | ||
37 | GSETSPR(25, sdr1) | ||
38 | GSETSPR(26, srr0) | ||
39 | GSETSPR(27, srr1) | ||
40 | GSETSPR(272, sprg0) | ||
41 | GSETSPR(273, sprg1) | ||
42 | GSETSPR(274, sprg2) | ||
43 | GSETSPR(275, sprg3) | ||
44 | GSETSPR(282, ear) | ||
45 | GSETSPR(287, pvr) | ||
46 | GSETSPR(1008, hid0) | ||
47 | GSETSPR(1009, hid1) | ||
48 | GSETSPR(1010, iabr) | ||
49 | GSETSPR(1023, pir) | ||
50 | |||
51 | static inline void store_inst(void *p) | ||
52 | { | ||
53 | asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p)); | ||
54 | } | ||
55 | |||
56 | static inline void cflush(void *p) | ||
57 | { | ||
58 | asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p)); | ||
59 | } | ||
60 | |||
61 | static inline void cinval(void *p) | ||
62 | { | ||
63 | asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p)); | ||
64 | } | ||
diff --git a/arch/sparc/lib/atomic32.c b/arch/sparc/lib/atomic32.c index 2e64e8c3e8e5..cb3cf0f22822 100644 --- a/arch/sparc/lib/atomic32.c +++ b/arch/sparc/lib/atomic32.c | |||
@@ -37,17 +37,43 @@ int __atomic_add_return(int i, atomic_t *v) | |||
37 | spin_unlock_irqrestore(ATOMIC_HASH(v), flags); | 37 | spin_unlock_irqrestore(ATOMIC_HASH(v), flags); |
38 | return ret; | 38 | return ret; |
39 | } | 39 | } |
40 | EXPORT_SYMBOL(__atomic_add_return); | ||
40 | 41 | ||
41 | void atomic_set(atomic_t *v, int i) | 42 | int atomic_cmpxchg(atomic_t *v, int old, int new) |
42 | { | 43 | { |
44 | int ret; | ||
43 | unsigned long flags; | 45 | unsigned long flags; |
46 | |||
44 | spin_lock_irqsave(ATOMIC_HASH(v), flags); | 47 | spin_lock_irqsave(ATOMIC_HASH(v), flags); |
48 | ret = v->counter; | ||
49 | if (likely(ret == old)) | ||
50 | v->counter = new; | ||
45 | 51 | ||
46 | v->counter = i; | 52 | spin_unlock_irqrestore(ATOMIC_HASH(v), flags); |
53 | return ret; | ||
54 | } | ||
55 | |||
56 | int atomic_add_unless(atomic_t *v, int a, int u) | ||
57 | { | ||
58 | int ret; | ||
59 | unsigned long flags; | ||
47 | 60 | ||
61 | spin_lock_irqsave(ATOMIC_HASH(v), flags); | ||
62 | ret = v->counter; | ||
63 | if (ret != u) | ||
64 | v->counter += a; | ||
48 | spin_unlock_irqrestore(ATOMIC_HASH(v), flags); | 65 | spin_unlock_irqrestore(ATOMIC_HASH(v), flags); |
66 | return ret != u; | ||
49 | } | 67 | } |
50 | 68 | ||
51 | EXPORT_SYMBOL(__atomic_add_return); | 69 | static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) |
52 | EXPORT_SYMBOL(atomic_set); | 70 | /* Atomic operations are already serializing */ |
71 | void atomic_set(atomic_t *v, int i) | ||
72 | { | ||
73 | unsigned long flags; | ||
53 | 74 | ||
75 | spin_lock_irqsave(ATOMIC_HASH(v), flags); | ||
76 | v->counter = i; | ||
77 | spin_unlock_irqrestore(ATOMIC_HASH(v), flags); | ||
78 | } | ||
79 | EXPORT_SYMBOL(atomic_set); | ||
diff --git a/arch/sparc/lib/bitext.c b/arch/sparc/lib/bitext.c index 94b05e8c906c..2e168d16547f 100644 --- a/arch/sparc/lib/bitext.c +++ b/arch/sparc/lib/bitext.c | |||
@@ -10,6 +10,7 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/smp_lock.h> | 12 | #include <linux/smp_lock.h> |
13 | #include <linux/string.h> | ||
13 | #include <linux/bitops.h> | 14 | #include <linux/bitops.h> |
14 | 15 | ||
15 | #include <asm/bitext.h> | 16 | #include <asm/bitext.h> |
diff --git a/arch/um/Kconfig b/arch/um/Kconfig index 3b5f47c46907..563301fe5df8 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig | |||
@@ -7,7 +7,6 @@ config UML | |||
7 | bool | 7 | bool |
8 | default y | 8 | default y |
9 | 9 | ||
10 | # XXX: does UM have a mmu/swap? | ||
11 | config MMU | 10 | config MMU |
12 | bool | 11 | bool |
13 | default y | 12 | default y |
@@ -36,12 +35,6 @@ config IRQ_RELEASE_METHOD | |||
36 | bool | 35 | bool |
37 | default y | 36 | default y |
38 | 37 | ||
39 | menu "Host processor type and features" | ||
40 | |||
41 | source "arch/i386/Kconfig.cpu" | ||
42 | |||
43 | endmenu | ||
44 | |||
45 | menu "UML-specific options" | 38 | menu "UML-specific options" |
46 | 39 | ||
47 | config MODE_TT | 40 | config MODE_TT |
@@ -209,7 +202,8 @@ config MAGIC_SYSRQ | |||
209 | config SMP | 202 | config SMP |
210 | bool "Symmetric multi-processing support (EXPERIMENTAL)" | 203 | bool "Symmetric multi-processing support (EXPERIMENTAL)" |
211 | default n | 204 | default n |
212 | depends on (MODE_TT && EXPERIMENTAL && !SMP_BROKEN) || (BROKEN && SMP_BROKEN) | 205 | #SMP_BROKEN is for x86_64. |
206 | depends on MODE_TT && EXPERIMENTAL && (!SMP_BROKEN || (BROKEN && SMP_BROKEN)) | ||
213 | help | 207 | help |
214 | This option enables UML SMP support. | 208 | This option enables UML SMP support. |
215 | It is NOT related to having a real SMP box. Not directly, at least. | 209 | It is NOT related to having a real SMP box. Not directly, at least. |
diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386 index 5d92cacd56c6..c71b39a677aa 100644 --- a/arch/um/Kconfig.i386 +++ b/arch/um/Kconfig.i386 | |||
@@ -1,3 +1,9 @@ | |||
1 | menu "Host processor type and features" | ||
2 | |||
3 | source "arch/i386/Kconfig.cpu" | ||
4 | |||
5 | endmenu | ||
6 | |||
1 | config UML_X86 | 7 | config UML_X86 |
2 | bool | 8 | bool |
3 | default y | 9 | default y |
@@ -42,7 +48,3 @@ config ARCH_HAS_SC_SIGNALS | |||
42 | config ARCH_REUSE_HOST_VSYSCALL_AREA | 48 | config ARCH_REUSE_HOST_VSYSCALL_AREA |
43 | bool | 49 | bool |
44 | default y | 50 | default y |
45 | |||
46 | config X86_CMPXCHG | ||
47 | bool | ||
48 | default y | ||
diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386 index 1f7dcb064aee..7a0e04e34bf9 100644 --- a/arch/um/Makefile-i386 +++ b/arch/um/Makefile-i386 | |||
@@ -35,4 +35,3 @@ cflags-y += $(call cc-option,-mpreferred-stack-boundary=2) | |||
35 | 35 | ||
36 | CFLAGS += $(cflags-y) | 36 | CFLAGS += $(cflags-y) |
37 | USER_CFLAGS += $(cflags-y) | 37 | USER_CFLAGS += $(cflags-y) |
38 | |||
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 16e7dc89f61d..5b58fad45290 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c | |||
@@ -89,8 +89,7 @@ static int not_configged_write(int fd, const char *buf, int len, void *data) | |||
89 | return(-EIO); | 89 | return(-EIO); |
90 | } | 90 | } |
91 | 91 | ||
92 | static int not_configged_console_write(int fd, const char *buf, int len, | 92 | static int not_configged_console_write(int fd, const char *buf, int len) |
93 | void *data) | ||
94 | { | 93 | { |
95 | my_puts("Using a channel type which is configured out of " | 94 | my_puts("Using a channel type which is configured out of " |
96 | "UML\n"); | 95 | "UML\n"); |
@@ -299,7 +298,7 @@ int console_write_chan(struct list_head *chans, const char *buf, int len) | |||
299 | chan = list_entry(ele, struct chan, list); | 298 | chan = list_entry(ele, struct chan, list); |
300 | if(!chan->output || (chan->ops->console_write == NULL)) | 299 | if(!chan->output || (chan->ops->console_write == NULL)) |
301 | continue; | 300 | continue; |
302 | n = chan->ops->console_write(chan->fd, buf, len, chan->data); | 301 | n = chan->ops->console_write(chan->fd, buf, len); |
303 | if(chan->primary) ret = n; | 302 | if(chan->primary) ret = n; |
304 | } | 303 | } |
305 | return(ret); | 304 | return(ret); |
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c index 1c55d5802489..5d50d4a44abf 100644 --- a/arch/um/drivers/chan_user.c +++ b/arch/um/drivers/chan_user.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include "choose-mode.h" | 20 | #include "choose-mode.h" |
21 | #include "mode.h" | 21 | #include "mode.h" |
22 | 22 | ||
23 | int generic_console_write(int fd, const char *buf, int n, void *unused) | 23 | int generic_console_write(int fd, const char *buf, int n) |
24 | { | 24 | { |
25 | struct termios save, new; | 25 | struct termios save, new; |
26 | int err; | 26 | int err; |
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c index c1b03f7c1daa..1bb085b2824d 100644 --- a/arch/um/drivers/daemon_user.c +++ b/arch/um/drivers/daemon_user.c | |||
@@ -98,7 +98,7 @@ static int connect_to_switch(struct daemon_data *pri) | |||
98 | printk("daemon_open : control setup request failed, err = %d\n", | 98 | printk("daemon_open : control setup request failed, err = %d\n", |
99 | -n); | 99 | -n); |
100 | err = -ENOTCONN; | 100 | err = -ENOTCONN; |
101 | goto out; | 101 | goto out_free; |
102 | } | 102 | } |
103 | 103 | ||
104 | n = os_read_file(pri->control, sun, sizeof(*sun)); | 104 | n = os_read_file(pri->control, sun, sizeof(*sun)); |
@@ -106,12 +106,14 @@ static int connect_to_switch(struct daemon_data *pri) | |||
106 | printk("daemon_open : read of data socket failed, err = %d\n", | 106 | printk("daemon_open : read of data socket failed, err = %d\n", |
107 | -n); | 107 | -n); |
108 | err = -ENOTCONN; | 108 | err = -ENOTCONN; |
109 | goto out_close; | 109 | goto out_free; |
110 | } | 110 | } |
111 | 111 | ||
112 | pri->data_addr = sun; | 112 | pri->data_addr = sun; |
113 | return(fd); | 113 | return(fd); |
114 | 114 | ||
115 | out_free: | ||
116 | kfree(sun); | ||
115 | out_close: | 117 | out_close: |
116 | os_close_file(fd); | 118 | os_close_file(fd); |
117 | out: | 119 | out: |
diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c index f0b888f66e05..3296e86a03a5 100644 --- a/arch/um/drivers/fd.c +++ b/arch/um/drivers/fd.c | |||
@@ -76,13 +76,6 @@ static void fd_close(int fd, void *d) | |||
76 | } | 76 | } |
77 | } | 77 | } |
78 | 78 | ||
79 | static int fd_console_write(int fd, const char *buf, int n, void *d) | ||
80 | { | ||
81 | struct fd_chan *data = d; | ||
82 | |||
83 | return(generic_console_write(fd, buf, n, &data->tt)); | ||
84 | } | ||
85 | |||
86 | struct chan_ops fd_ops = { | 79 | struct chan_ops fd_ops = { |
87 | .type = "fd", | 80 | .type = "fd", |
88 | .init = fd_init, | 81 | .init = fd_init, |
@@ -90,7 +83,7 @@ struct chan_ops fd_ops = { | |||
90 | .close = fd_close, | 83 | .close = fd_close, |
91 | .read = generic_read, | 84 | .read = generic_read, |
92 | .write = generic_write, | 85 | .write = generic_write, |
93 | .console_write = fd_console_write, | 86 | .console_write = generic_console_write, |
94 | .window_size = generic_window_size, | 87 | .window_size = generic_window_size, |
95 | .free = generic_free, | 88 | .free = generic_free, |
96 | .winch = 1, | 89 | .winch = 1, |
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c index 5db136e2651c..afe85bfa66e0 100644 --- a/arch/um/drivers/mcast_user.c +++ b/arch/um/drivers/mcast_user.c | |||
@@ -54,7 +54,7 @@ static int mcast_open(void *data) | |||
54 | struct mcast_data *pri = data; | 54 | struct mcast_data *pri = data; |
55 | struct sockaddr_in *sin = pri->mcast_addr; | 55 | struct sockaddr_in *sin = pri->mcast_addr; |
56 | struct ip_mreq mreq; | 56 | struct ip_mreq mreq; |
57 | int fd, yes = 1, err = 0; | 57 | int fd, yes = 1, err = -EINVAL; |
58 | 58 | ||
59 | 59 | ||
60 | if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) | 60 | if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) |
@@ -63,40 +63,40 @@ static int mcast_open(void *data) | |||
63 | fd = socket(AF_INET, SOCK_DGRAM, 0); | 63 | fd = socket(AF_INET, SOCK_DGRAM, 0); |
64 | 64 | ||
65 | if (fd < 0){ | 65 | if (fd < 0){ |
66 | err = -errno; | ||
66 | printk("mcast_open : data socket failed, errno = %d\n", | 67 | printk("mcast_open : data socket failed, errno = %d\n", |
67 | errno); | 68 | errno); |
68 | err = -errno; | ||
69 | goto out; | 69 | goto out; |
70 | } | 70 | } |
71 | 71 | ||
72 | if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { | 72 | if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { |
73 | err = -errno; | ||
73 | printk("mcast_open: SO_REUSEADDR failed, errno = %d\n", | 74 | printk("mcast_open: SO_REUSEADDR failed, errno = %d\n", |
74 | errno); | 75 | errno); |
75 | err = -errno; | ||
76 | goto out_close; | 76 | goto out_close; |
77 | } | 77 | } |
78 | 78 | ||
79 | /* set ttl according to config */ | 79 | /* set ttl according to config */ |
80 | if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl, | 80 | if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl, |
81 | sizeof(pri->ttl)) < 0) { | 81 | sizeof(pri->ttl)) < 0) { |
82 | err = -errno; | ||
82 | printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n", | 83 | printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n", |
83 | errno); | 84 | errno); |
84 | err = -errno; | ||
85 | goto out_close; | 85 | goto out_close; |
86 | } | 86 | } |
87 | 87 | ||
88 | /* set LOOP, so data does get fed back to local sockets */ | 88 | /* set LOOP, so data does get fed back to local sockets */ |
89 | if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { | 89 | if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { |
90 | err = -errno; | ||
90 | printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n", | 91 | printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n", |
91 | errno); | 92 | errno); |
92 | err = -errno; | ||
93 | goto out_close; | 93 | goto out_close; |
94 | } | 94 | } |
95 | 95 | ||
96 | /* bind socket to mcast address */ | 96 | /* bind socket to mcast address */ |
97 | if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { | 97 | if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { |
98 | printk("mcast_open : data bind failed, errno = %d\n", errno); | ||
99 | err = -errno; | 98 | err = -errno; |
99 | printk("mcast_open : data bind failed, errno = %d\n", errno); | ||
100 | goto out_close; | 100 | goto out_close; |
101 | } | 101 | } |
102 | 102 | ||
@@ -105,22 +105,22 @@ static int mcast_open(void *data) | |||
105 | mreq.imr_interface.s_addr = 0; | 105 | mreq.imr_interface.s_addr = 0; |
106 | if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, | 106 | if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, |
107 | &mreq, sizeof(mreq)) < 0) { | 107 | &mreq, sizeof(mreq)) < 0) { |
108 | err = -errno; | ||
108 | printk("mcast_open: IP_ADD_MEMBERSHIP failed, error = %d\n", | 109 | printk("mcast_open: IP_ADD_MEMBERSHIP failed, error = %d\n", |
109 | errno); | 110 | errno); |
110 | printk("There appears not to be a multicast-capable network " | 111 | printk("There appears not to be a multicast-capable network " |
111 | "interface on the host.\n"); | 112 | "interface on the host.\n"); |
112 | printk("eth0 should be configured in order to use the " | 113 | printk("eth0 should be configured in order to use the " |
113 | "multicast transport.\n"); | 114 | "multicast transport.\n"); |
114 | err = -errno; | 115 | goto out_close; |
115 | goto out_close; | ||
116 | } | 116 | } |
117 | 117 | ||
118 | return fd; | 118 | return fd; |
119 | 119 | ||
120 | out_close: | 120 | out_close: |
121 | os_close_file(fd); | 121 | os_close_file(fd); |
122 | out: | 122 | out: |
123 | return err; | 123 | return err; |
124 | } | 124 | } |
125 | 125 | ||
126 | static void mcast_close(int fd, void *data) | 126 | static void mcast_close(int fd, void *data) |
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c index ed4a1a6c5d83..c43e8bb32502 100644 --- a/arch/um/drivers/port_user.c +++ b/arch/um/drivers/port_user.c | |||
@@ -100,13 +100,6 @@ static void port_close(int fd, void *d) | |||
100 | os_close_file(fd); | 100 | os_close_file(fd); |
101 | } | 101 | } |
102 | 102 | ||
103 | static int port_console_write(int fd, const char *buf, int n, void *d) | ||
104 | { | ||
105 | struct port_chan *data = d; | ||
106 | |||
107 | return(generic_console_write(fd, buf, n, &data->tt)); | ||
108 | } | ||
109 | |||
110 | struct chan_ops port_ops = { | 103 | struct chan_ops port_ops = { |
111 | .type = "port", | 104 | .type = "port", |
112 | .init = port_init, | 105 | .init = port_init, |
@@ -114,7 +107,7 @@ struct chan_ops port_ops = { | |||
114 | .close = port_close, | 107 | .close = port_close, |
115 | .read = generic_read, | 108 | .read = generic_read, |
116 | .write = generic_write, | 109 | .write = generic_write, |
117 | .console_write = port_console_write, | 110 | .console_write = generic_console_write, |
118 | .window_size = generic_window_size, | 111 | .window_size = generic_window_size, |
119 | .free = port_free, | 112 | .free = port_free, |
120 | .winch = 1, | 113 | .winch = 1, |
diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c index 0306a1b215b7..1c555c38de4d 100644 --- a/arch/um/drivers/pty.c +++ b/arch/um/drivers/pty.c | |||
@@ -118,13 +118,6 @@ static int pty_open(int input, int output, int primary, void *d, | |||
118 | return(fd); | 118 | return(fd); |
119 | } | 119 | } |
120 | 120 | ||
121 | static int pty_console_write(int fd, const char *buf, int n, void *d) | ||
122 | { | ||
123 | struct pty_chan *data = d; | ||
124 | |||
125 | return(generic_console_write(fd, buf, n, &data->tt)); | ||
126 | } | ||
127 | |||
128 | struct chan_ops pty_ops = { | 121 | struct chan_ops pty_ops = { |
129 | .type = "pty", | 122 | .type = "pty", |
130 | .init = pty_chan_init, | 123 | .init = pty_chan_init, |
@@ -132,7 +125,7 @@ struct chan_ops pty_ops = { | |||
132 | .close = generic_close, | 125 | .close = generic_close, |
133 | .read = generic_read, | 126 | .read = generic_read, |
134 | .write = generic_write, | 127 | .write = generic_write, |
135 | .console_write = pty_console_write, | 128 | .console_write = generic_console_write, |
136 | .window_size = generic_window_size, | 129 | .window_size = generic_window_size, |
137 | .free = generic_free, | 130 | .free = generic_free, |
138 | .winch = 0, | 131 | .winch = 0, |
@@ -145,7 +138,7 @@ struct chan_ops pts_ops = { | |||
145 | .close = generic_close, | 138 | .close = generic_close, |
146 | .read = generic_read, | 139 | .read = generic_read, |
147 | .write = generic_write, | 140 | .write = generic_write, |
148 | .console_write = pty_console_write, | 141 | .console_write = generic_console_write, |
149 | .window_size = generic_window_size, | 142 | .window_size = generic_window_size, |
150 | .free = generic_free, | 143 | .free = generic_free, |
151 | .winch = 0, | 144 | .winch = 0, |
diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c index 6fbb670ee274..94c9265a4f2c 100644 --- a/arch/um/drivers/tty.c +++ b/arch/um/drivers/tty.c | |||
@@ -60,13 +60,6 @@ static int tty_open(int input, int output, int primary, void *d, | |||
60 | return(fd); | 60 | return(fd); |
61 | } | 61 | } |
62 | 62 | ||
63 | static int tty_console_write(int fd, const char *buf, int n, void *d) | ||
64 | { | ||
65 | struct tty_chan *data = d; | ||
66 | |||
67 | return(generic_console_write(fd, buf, n, &data->tt)); | ||
68 | } | ||
69 | |||
70 | struct chan_ops tty_ops = { | 63 | struct chan_ops tty_ops = { |
71 | .type = "tty", | 64 | .type = "tty", |
72 | .init = tty_chan_init, | 65 | .init = tty_chan_init, |
@@ -74,7 +67,7 @@ struct chan_ops tty_ops = { | |||
74 | .close = generic_close, | 67 | .close = generic_close, |
75 | .read = generic_read, | 68 | .read = generic_read, |
76 | .write = generic_write, | 69 | .write = generic_write, |
77 | .console_write = tty_console_write, | 70 | .console_write = generic_console_write, |
78 | .window_size = generic_window_size, | 71 | .window_size = generic_window_size, |
79 | .free = generic_free, | 72 | .free = generic_free, |
80 | .winch = 0, | 73 | .winch = 0, |
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c index b530f1a6540d..aaa636661043 100644 --- a/arch/um/drivers/xterm.c +++ b/arch/um/drivers/xterm.c | |||
@@ -194,13 +194,6 @@ static void xterm_free(void *d) | |||
194 | free(d); | 194 | free(d); |
195 | } | 195 | } |
196 | 196 | ||
197 | static int xterm_console_write(int fd, const char *buf, int n, void *d) | ||
198 | { | ||
199 | struct xterm_chan *data = d; | ||
200 | |||
201 | return(generic_console_write(fd, buf, n, &data->tt)); | ||
202 | } | ||
203 | |||
204 | struct chan_ops xterm_ops = { | 197 | struct chan_ops xterm_ops = { |
205 | .type = "xterm", | 198 | .type = "xterm", |
206 | .init = xterm_init, | 199 | .init = xterm_init, |
@@ -208,7 +201,7 @@ struct chan_ops xterm_ops = { | |||
208 | .close = xterm_close, | 201 | .close = xterm_close, |
209 | .read = generic_read, | 202 | .read = generic_read, |
210 | .write = generic_write, | 203 | .write = generic_write, |
211 | .console_write = xterm_console_write, | 204 | .console_write = generic_console_write, |
212 | .window_size = generic_window_size, | 205 | .window_size = generic_window_size, |
213 | .free = xterm_free, | 206 | .free = xterm_free, |
214 | .winch = 1, | 207 | .winch = 1, |
diff --git a/arch/um/include/chan_user.h b/arch/um/include/chan_user.h index f77d9aa4c164..659bb3cac32f 100644 --- a/arch/um/include/chan_user.h +++ b/arch/um/include/chan_user.h | |||
@@ -25,7 +25,7 @@ struct chan_ops { | |||
25 | void (*close)(int, void *); | 25 | void (*close)(int, void *); |
26 | int (*read)(int, char *, void *); | 26 | int (*read)(int, char *, void *); |
27 | int (*write)(int, const char *, int, void *); | 27 | int (*write)(int, const char *, int, void *); |
28 | int (*console_write)(int, const char *, int, void *); | 28 | int (*console_write)(int, const char *, int); |
29 | int (*window_size)(int, void *, unsigned short *, unsigned short *); | 29 | int (*window_size)(int, void *, unsigned short *, unsigned short *); |
30 | void (*free)(void *); | 30 | void (*free)(void *); |
31 | int winch; | 31 | int winch; |
@@ -37,7 +37,7 @@ extern struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops, tty_ops, | |||
37 | extern void generic_close(int fd, void *unused); | 37 | extern void generic_close(int fd, void *unused); |
38 | extern int generic_read(int fd, char *c_out, void *unused); | 38 | extern int generic_read(int fd, char *c_out, void *unused); |
39 | extern int generic_write(int fd, const char *buf, int n, void *unused); | 39 | extern int generic_write(int fd, const char *buf, int n, void *unused); |
40 | extern int generic_console_write(int fd, const char *buf, int n, void *state); | 40 | extern int generic_console_write(int fd, const char *buf, int n); |
41 | extern int generic_window_size(int fd, void *unused, unsigned short *rows_out, | 41 | extern int generic_window_size(int fd, void *unused, unsigned short *rows_out, |
42 | unsigned short *cols_out); | 42 | unsigned short *cols_out); |
43 | extern void generic_free(void *data); | 43 | extern void generic_free(void *data); |
diff --git a/arch/um/include/um_uaccess.h b/arch/um/include/um_uaccess.h index 84c0868cd561..f8760a3f43b0 100644 --- a/arch/um/include/um_uaccess.h +++ b/arch/um/include/um_uaccess.h | |||
@@ -17,8 +17,25 @@ | |||
17 | #include "uaccess-skas.h" | 17 | #include "uaccess-skas.h" |
18 | #endif | 18 | #endif |
19 | 19 | ||
20 | #define __under_task_size(addr, size) \ | ||
21 | (((unsigned long) (addr) < TASK_SIZE) && \ | ||
22 | (((unsigned long) (addr) + (size)) < TASK_SIZE)) | ||
23 | |||
24 | #define __access_ok_vsyscall(type, addr, size) \ | ||
25 | ((type == VERIFY_READ) && \ | ||
26 | ((unsigned long) (addr) >= FIXADDR_USER_START) && \ | ||
27 | ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \ | ||
28 | ((unsigned long) (addr) + (size) >= (unsigned long)(addr))) | ||
29 | |||
30 | #define __addr_range_nowrap(addr, size) \ | ||
31 | ((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) | ||
32 | |||
20 | #define access_ok(type, addr, size) \ | 33 | #define access_ok(type, addr, size) \ |
21 | CHOOSE_MODE_PROC(access_ok_tt, access_ok_skas, type, addr, size) | 34 | (__addr_range_nowrap(addr, size) && \ |
35 | (__under_task_size(addr, size) || \ | ||
36 | __access_ok_vsyscall(type, addr, size) || \ | ||
37 | segment_eq(get_fs(), KERNEL_DS) || \ | ||
38 | CHOOSE_MODE_PROC(access_ok_tt, access_ok_skas, type, addr, size))) | ||
22 | 39 | ||
23 | static inline int copy_from_user(void *to, const void __user *from, int n) | 40 | static inline int copy_from_user(void *to, const void __user *from, int n) |
24 | { | 41 | { |
diff --git a/arch/um/kernel/skas/include/uaccess-skas.h b/arch/um/kernel/skas/include/uaccess-skas.h index 7da0c2def0ef..f611f83ad4ff 100644 --- a/arch/um/kernel/skas/include/uaccess-skas.h +++ b/arch/um/kernel/skas/include/uaccess-skas.h | |||
@@ -9,14 +9,8 @@ | |||
9 | #include "asm/errno.h" | 9 | #include "asm/errno.h" |
10 | #include "asm/fixmap.h" | 10 | #include "asm/fixmap.h" |
11 | 11 | ||
12 | #define access_ok_skas(type, addr, size) \ | 12 | /* No SKAS-specific checking. */ |
13 | ((segment_eq(get_fs(), KERNEL_DS)) || \ | 13 | #define access_ok_skas(type, addr, size) 0 |
14 | (((unsigned long) (addr) < TASK_SIZE) && \ | ||
15 | ((unsigned long) (addr) + (size) <= TASK_SIZE)) || \ | ||
16 | ((type == VERIFY_READ ) && \ | ||
17 | ((unsigned long) (addr) >= FIXADDR_USER_START) && \ | ||
18 | ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \ | ||
19 | ((unsigned long) (addr) + (size) >= (unsigned long)(addr)))) | ||
20 | 14 | ||
21 | extern int copy_from_user_skas(void *to, const void __user *from, int n); | 15 | extern int copy_from_user_skas(void *to, const void __user *from, int n); |
22 | extern int copy_to_user_skas(void __user *to, const void *from, int n); | 16 | extern int copy_to_user_skas(void __user *to, const void *from, int n); |
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c index 75195281081e..a5a47528dec7 100644 --- a/arch/um/kernel/skas/uaccess.c +++ b/arch/um/kernel/skas/uaccess.c | |||
@@ -143,7 +143,7 @@ int copy_from_user_skas(void *to, const void __user *from, int n) | |||
143 | return(0); | 143 | return(0); |
144 | } | 144 | } |
145 | 145 | ||
146 | return(access_ok_skas(VERIFY_READ, from, n) ? | 146 | return(access_ok(VERIFY_READ, from, n) ? |
147 | buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to): | 147 | buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to): |
148 | n); | 148 | n); |
149 | } | 149 | } |
@@ -164,7 +164,7 @@ int copy_to_user_skas(void __user *to, const void *from, int n) | |||
164 | return(0); | 164 | return(0); |
165 | } | 165 | } |
166 | 166 | ||
167 | return(access_ok_skas(VERIFY_WRITE, to, n) ? | 167 | return(access_ok(VERIFY_WRITE, to, n) ? |
168 | buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) : | 168 | buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) : |
169 | n); | 169 | n); |
170 | } | 170 | } |
@@ -193,7 +193,7 @@ int strncpy_from_user_skas(char *dst, const char __user *src, int count) | |||
193 | return(strnlen(dst, count)); | 193 | return(strnlen(dst, count)); |
194 | } | 194 | } |
195 | 195 | ||
196 | if(!access_ok_skas(VERIFY_READ, src, 1)) | 196 | if(!access_ok(VERIFY_READ, src, 1)) |
197 | return(-EFAULT); | 197 | return(-EFAULT); |
198 | 198 | ||
199 | n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user, | 199 | n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user, |
@@ -221,7 +221,7 @@ int clear_user_skas(void __user *mem, int len) | |||
221 | return(0); | 221 | return(0); |
222 | } | 222 | } |
223 | 223 | ||
224 | return(access_ok_skas(VERIFY_WRITE, mem, len) ? | 224 | return(access_ok(VERIFY_WRITE, mem, len) ? |
225 | buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len); | 225 | buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len); |
226 | } | 226 | } |
227 | 227 | ||
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c index 95c8f8733baf..0d4c10a73607 100644 --- a/arch/um/kernel/trap_kern.c +++ b/arch/um/kernel/trap_kern.c | |||
@@ -95,7 +95,16 @@ survive: | |||
95 | pte = pte_offset_kernel(pmd, address); | 95 | pte = pte_offset_kernel(pmd, address); |
96 | } while(!pte_present(*pte)); | 96 | } while(!pte_present(*pte)); |
97 | err = 0; | 97 | err = 0; |
98 | /* The below warning was added in place of | ||
99 | * pte_mkyoung(); if (is_write) pte_mkdirty(); | ||
100 | * If it's triggered, we'd see normally a hang here (a clean pte is | ||
101 | * marked read-only to emulate the dirty bit). | ||
102 | * However, the generic code can mark a PTE writable but clean on a | ||
103 | * concurrent read fault, triggering this harmlessly. So comment it out. | ||
104 | */ | ||
105 | #if 0 | ||
98 | WARN_ON(!pte_young(*pte) || (is_write && !pte_dirty(*pte))); | 106 | WARN_ON(!pte_young(*pte) || (is_write && !pte_dirty(*pte))); |
107 | #endif | ||
99 | flush_tlb_page(vma, address); | 108 | flush_tlb_page(vma, address); |
100 | out: | 109 | out: |
101 | up_read(&mm->mmap_sem); | 110 | up_read(&mm->mmap_sem); |
diff --git a/arch/um/kernel/tt/include/uaccess-tt.h b/arch/um/kernel/tt/include/uaccess-tt.h index dc2ebfa8c54f..b9bfe9c481c4 100644 --- a/arch/um/kernel/tt/include/uaccess-tt.h +++ b/arch/um/kernel/tt/include/uaccess-tt.h | |||
@@ -19,19 +19,13 @@ | |||
19 | extern unsigned long end_vm; | 19 | extern unsigned long end_vm; |
20 | extern unsigned long uml_physmem; | 20 | extern unsigned long uml_physmem; |
21 | 21 | ||
22 | #define under_task_size(addr, size) \ | ||
23 | (((unsigned long) (addr) < TASK_SIZE) && \ | ||
24 | (((unsigned long) (addr) + (size)) < TASK_SIZE)) | ||
25 | |||
26 | #define is_stack(addr, size) \ | 22 | #define is_stack(addr, size) \ |
27 | (((unsigned long) (addr) < STACK_TOP) && \ | 23 | (((unsigned long) (addr) < STACK_TOP) && \ |
28 | ((unsigned long) (addr) >= STACK_TOP - ABOVE_KMEM) && \ | 24 | ((unsigned long) (addr) >= STACK_TOP - ABOVE_KMEM) && \ |
29 | (((unsigned long) (addr) + (size)) <= STACK_TOP)) | 25 | (((unsigned long) (addr) + (size)) <= STACK_TOP)) |
30 | 26 | ||
31 | #define access_ok_tt(type, addr, size) \ | 27 | #define access_ok_tt(type, addr, size) \ |
32 | ((type == VERIFY_READ) || (segment_eq(get_fs(), KERNEL_DS)) || \ | 28 | (is_stack(addr, size)) |
33 | (((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) && \ | ||
34 | (under_task_size(addr, size) || is_stack(addr, size)))) | ||
35 | 29 | ||
36 | extern unsigned long get_fault_addr(void); | 30 | extern unsigned long get_fault_addr(void); |
37 | 31 | ||
diff --git a/arch/um/kernel/tt/uaccess.c b/arch/um/kernel/tt/uaccess.c index a72aa632972f..1cb60726567e 100644 --- a/arch/um/kernel/tt/uaccess.c +++ b/arch/um/kernel/tt/uaccess.c | |||
@@ -8,7 +8,7 @@ | |||
8 | 8 | ||
9 | int copy_from_user_tt(void *to, const void __user *from, int n) | 9 | int copy_from_user_tt(void *to, const void __user *from, int n) |
10 | { | 10 | { |
11 | if(!access_ok_tt(VERIFY_READ, from, n)) | 11 | if(!access_ok(VERIFY_READ, from, n)) |
12 | return(n); | 12 | return(n); |
13 | 13 | ||
14 | return(__do_copy_from_user(to, from, n, ¤t->thread.fault_addr, | 14 | return(__do_copy_from_user(to, from, n, ¤t->thread.fault_addr, |
@@ -17,7 +17,7 @@ int copy_from_user_tt(void *to, const void __user *from, int n) | |||
17 | 17 | ||
18 | int copy_to_user_tt(void __user *to, const void *from, int n) | 18 | int copy_to_user_tt(void __user *to, const void *from, int n) |
19 | { | 19 | { |
20 | if(!access_ok_tt(VERIFY_WRITE, to, n)) | 20 | if(!access_ok(VERIFY_WRITE, to, n)) |
21 | return(n); | 21 | return(n); |
22 | 22 | ||
23 | return(__do_copy_to_user(to, from, n, ¤t->thread.fault_addr, | 23 | return(__do_copy_to_user(to, from, n, ¤t->thread.fault_addr, |
@@ -28,7 +28,7 @@ int strncpy_from_user_tt(char *dst, const char __user *src, int count) | |||
28 | { | 28 | { |
29 | int n; | 29 | int n; |
30 | 30 | ||
31 | if(!access_ok_tt(VERIFY_READ, src, 1)) | 31 | if(!access_ok(VERIFY_READ, src, 1)) |
32 | return(-EFAULT); | 32 | return(-EFAULT); |
33 | 33 | ||
34 | n = __do_strncpy_from_user(dst, src, count, | 34 | n = __do_strncpy_from_user(dst, src, count, |
@@ -47,7 +47,7 @@ int __clear_user_tt(void __user *mem, int len) | |||
47 | 47 | ||
48 | int clear_user_tt(void __user *mem, int len) | 48 | int clear_user_tt(void __user *mem, int len) |
49 | { | 49 | { |
50 | if(!access_ok_tt(VERIFY_WRITE, mem, len)) | 50 | if(!access_ok(VERIFY_WRITE, mem, len)) |
51 | return(len); | 51 | return(len); |
52 | 52 | ||
53 | return(__do_clear_user(mem, len, ¤t->thread.fault_addr, | 53 | return(__do_clear_user(mem, len, ¤t->thread.fault_addr, |
diff --git a/arch/v850/Kconfig b/arch/v850/Kconfig index 89c053b6c2c4..310865903234 100644 --- a/arch/v850/Kconfig +++ b/arch/v850/Kconfig | |||
@@ -23,6 +23,14 @@ config GENERIC_CALIBRATE_DELAY | |||
23 | bool | 23 | bool |
24 | default y | 24 | default y |
25 | 25 | ||
26 | config GENERIC_HARDIRQS | ||
27 | bool | ||
28 | default y | ||
29 | |||
30 | config GENERIC_IRQ_PROBE | ||
31 | bool | ||
32 | default y | ||
33 | |||
26 | # Turn off some random 386 crap that can affect device config | 34 | # Turn off some random 386 crap that can affect device config |
27 | config ISA | 35 | config ISA |
28 | bool | 36 | bool |
diff --git a/arch/v850/kernel/irq.c b/arch/v850/kernel/irq.c index 9e85969ba976..7a151c26f82e 100644 --- a/arch/v850/kernel/irq.c +++ b/arch/v850/kernel/irq.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * arch/v850/kernel/irq.c -- High-level interrupt handling | 2 | * arch/v850/kernel/irq.c -- High-level interrupt handling |
3 | * | 3 | * |
4 | * Copyright (C) 2001,02,03,04 NEC Electronics Corporation | 4 | * Copyright (C) 2001,02,03,04,05 NEC Electronics Corporation |
5 | * Copyright (C) 2001,02,03,04 Miles Bader <miles@gnu.org> | 5 | * Copyright (C) 2001,02,03,04,05 Miles Bader <miles@gnu.org> |
6 | * Copyright (C) 1994-2000 Ralf Baechle | 6 | * Copyright (C) 1994-2000 Ralf Baechle |
7 | * Copyright (C) 1992 Linus Torvalds | 7 | * Copyright (C) 1992 Linus Torvalds |
8 | * | 8 | * |
@@ -27,55 +27,15 @@ | |||
27 | #include <asm/system.h> | 27 | #include <asm/system.h> |
28 | 28 | ||
29 | /* | 29 | /* |
30 | * Controller mappings for all interrupt sources: | 30 | * 'what should we do if we get a hw irq event on an illegal vector'. |
31 | * each architecture has to answer this themselves, it doesn't deserve | ||
32 | * a generic callback i think. | ||
31 | */ | 33 | */ |
32 | irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { | 34 | void ack_bad_irq(unsigned int irq) |
33 | [0 ... NR_IRQS-1] = { | ||
34 | .handler = &no_irq_type, | ||
35 | .lock = SPIN_LOCK_UNLOCKED | ||
36 | } | ||
37 | }; | ||
38 | |||
39 | /* | ||
40 | * Special irq handlers. | ||
41 | */ | ||
42 | |||
43 | irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs) | ||
44 | { | ||
45 | return IRQ_NONE; | ||
46 | } | ||
47 | |||
48 | /* | ||
49 | * Generic no controller code | ||
50 | */ | ||
51 | |||
52 | static void enable_none(unsigned int irq) { } | ||
53 | static unsigned int startup_none(unsigned int irq) { return 0; } | ||
54 | static void disable_none(unsigned int irq) { } | ||
55 | static void ack_none(unsigned int irq) | ||
56 | { | 35 | { |
57 | /* | ||
58 | * 'what should we do if we get a hw irq event on an illegal vector'. | ||
59 | * each architecture has to answer this themselves, it doesn't deserve | ||
60 | * a generic callback i think. | ||
61 | */ | ||
62 | printk("received IRQ %d with unknown interrupt type\n", irq); | 36 | printk("received IRQ %d with unknown interrupt type\n", irq); |
63 | } | 37 | } |
64 | 38 | ||
65 | /* startup is the same as "enable", shutdown is same as "disable" */ | ||
66 | #define shutdown_none disable_none | ||
67 | #define end_none enable_none | ||
68 | |||
69 | struct hw_interrupt_type no_irq_type = { | ||
70 | .typename = "none", | ||
71 | .startup = startup_none, | ||
72 | .shutdown = shutdown_none, | ||
73 | .enable = enable_none, | ||
74 | .disable = disable_none, | ||
75 | .ack = ack_none, | ||
76 | .end = end_none | ||
77 | }; | ||
78 | |||
79 | volatile unsigned long irq_err_count, spurious_count; | 39 | volatile unsigned long irq_err_count, spurious_count; |
80 | 40 | ||
81 | /* | 41 | /* |
@@ -84,643 +44,68 @@ volatile unsigned long irq_err_count, spurious_count; | |||
84 | 44 | ||
85 | int show_interrupts(struct seq_file *p, void *v) | 45 | int show_interrupts(struct seq_file *p, void *v) |
86 | { | 46 | { |
87 | int i = *(loff_t *) v; | 47 | int irq = *(loff_t *) v; |
88 | struct irqaction * action; | ||
89 | unsigned long flags; | ||
90 | 48 | ||
91 | if (i == 0) { | 49 | if (irq == 0) { |
50 | int cpu; | ||
92 | seq_puts(p, " "); | 51 | seq_puts(p, " "); |
93 | for (i=0; i < 1 /*smp_num_cpus*/; i++) | 52 | for (cpu=0; cpu < 1 /*smp_num_cpus*/; cpu++) |
94 | seq_printf(p, "CPU%d ", i); | 53 | seq_printf(p, "CPU%d ", cpu); |
95 | seq_putc(p, '\n'); | 54 | seq_putc(p, '\n'); |
96 | } | 55 | } |
97 | 56 | ||
98 | if (i < NR_IRQS) { | 57 | if (irq < NR_IRQS) { |
99 | int j, count, num; | 58 | unsigned long flags; |
100 | const char *type_name = irq_desc[i].handler->typename; | 59 | struct irqaction *action; |
101 | spin_lock_irqsave(&irq_desc[j].lock, flags); | ||
102 | action = irq_desc[i].action; | ||
103 | if (!action) | ||
104 | goto skip; | ||
105 | 60 | ||
106 | count = 0; | 61 | spin_lock_irqsave(&irq_desc[irq].lock, flags); |
107 | num = -1; | ||
108 | for (j = 0; j < NR_IRQS; j++) | ||
109 | if (irq_desc[j].handler->typename == type_name) { | ||
110 | if (i == j) | ||
111 | num = count; | ||
112 | count++; | ||
113 | } | ||
114 | 62 | ||
115 | seq_printf(p, "%3d: ",i); | 63 | action = irq_desc[irq].action; |
116 | seq_printf(p, "%10u ", kstat_irqs(i)); | 64 | if (action) { |
117 | if (count > 1) { | 65 | int j; |
118 | int prec = (num >= 100 ? 3 : num >= 10 ? 2 : 1); | 66 | int count = 0; |
119 | seq_printf(p, " %*s%d", 14 - prec, type_name, num); | 67 | int num = -1; |
120 | } else | 68 | const char *type_name = irq_desc[irq].handler->typename; |
121 | seq_printf(p, " %14s", type_name); | 69 | |
70 | for (j = 0; j < NR_IRQS; j++) | ||
71 | if (irq_desc[j].handler->typename == type_name){ | ||
72 | if (irq == j) | ||
73 | num = count; | ||
74 | count++; | ||
75 | } | ||
76 | |||
77 | seq_printf(p, "%3d: ",irq); | ||
78 | seq_printf(p, "%10u ", kstat_irqs(irq)); | ||
79 | if (count > 1) { | ||
80 | int prec = (num >= 100 ? 3 : num >= 10 ? 2 : 1); | ||
81 | seq_printf(p, " %*s%d", 14 - prec, | ||
82 | type_name, num); | ||
83 | } else | ||
84 | seq_printf(p, " %14s", type_name); | ||
122 | 85 | ||
123 | seq_printf(p, " %s", action->name); | 86 | seq_printf(p, " %s", action->name); |
124 | for (action=action->next; action; action = action->next) | 87 | for (action=action->next; action; action = action->next) |
125 | seq_printf(p, ", %s", action->name); | 88 | seq_printf(p, ", %s", action->name); |
126 | seq_putc(p, '\n'); | 89 | seq_putc(p, '\n'); |
127 | skip: | 90 | } |
128 | spin_unlock_irqrestore(&irq_desc[j].lock, flags); | ||
129 | } else if (i == NR_IRQS) | ||
130 | seq_printf(p, "ERR: %10lu\n", irq_err_count); | ||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | * This should really return information about whether | ||
136 | * we should do bottom half handling etc. Right now we | ||
137 | * end up _always_ checking the bottom half, which is a | ||
138 | * waste of time and is not what some drivers would | ||
139 | * prefer. | ||
140 | */ | ||
141 | int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action) | ||
142 | { | ||
143 | int status = 1; /* Force the "do bottom halves" bit */ | ||
144 | int ret; | ||
145 | |||
146 | if (!(action->flags & SA_INTERRUPT)) | ||
147 | local_irq_enable(); | ||
148 | |||
149 | do { | ||
150 | ret = action->handler(irq, action->dev_id, regs); | ||
151 | if (ret == IRQ_HANDLED) | ||
152 | status |= action->flags; | ||
153 | action = action->next; | ||
154 | } while (action); | ||
155 | if (status & SA_SAMPLE_RANDOM) | ||
156 | add_interrupt_randomness(irq); | ||
157 | local_irq_disable(); | ||
158 | |||
159 | return status; | ||
160 | } | ||
161 | |||
162 | /* | ||
163 | * Generic enable/disable code: this just calls | ||
164 | * down into the PIC-specific version for the actual | ||
165 | * hardware disable after having gotten the irq | ||
166 | * controller lock. | ||
167 | */ | ||
168 | |||
169 | /** | ||
170 | * disable_irq_nosync - disable an irq without waiting | ||
171 | * @irq: Interrupt to disable | ||
172 | * | ||
173 | * Disable the selected interrupt line. Disables of an interrupt | ||
174 | * stack. Unlike disable_irq(), this function does not ensure existing | ||
175 | * instances of the IRQ handler have completed before returning. | ||
176 | * | ||
177 | * This function may be called from IRQ context. | ||
178 | */ | ||
179 | |||
180 | void inline disable_irq_nosync(unsigned int irq) | ||
181 | { | ||
182 | irq_desc_t *desc = irq_desc + irq; | ||
183 | unsigned long flags; | ||
184 | |||
185 | spin_lock_irqsave(&desc->lock, flags); | ||
186 | if (!desc->depth++) { | ||
187 | desc->status |= IRQ_DISABLED; | ||
188 | desc->handler->disable(irq); | ||
189 | } | ||
190 | spin_unlock_irqrestore(&desc->lock, flags); | ||
191 | } | ||
192 | |||
193 | /** | ||
194 | * disable_irq - disable an irq and wait for completion | ||
195 | * @irq: Interrupt to disable | ||
196 | * | ||
197 | * Disable the selected interrupt line. Disables of an interrupt | ||
198 | * stack. That is for two disables you need two enables. This | ||
199 | * function waits for any pending IRQ handlers for this interrupt | ||
200 | * to complete before returning. If you use this function while | ||
201 | * holding a resource the IRQ handler may need you will deadlock. | ||
202 | * | ||
203 | * This function may be called - with care - from IRQ context. | ||
204 | */ | ||
205 | |||
206 | void disable_irq(unsigned int irq) | ||
207 | { | ||
208 | disable_irq_nosync(irq); | ||
209 | synchronize_irq(irq); | ||
210 | } | ||
211 | 91 | ||
212 | /** | 92 | spin_unlock_irqrestore(&irq_desc[irq].lock, flags); |
213 | * enable_irq - enable interrupt handling on an irq | 93 | } else if (irq == NR_IRQS) |
214 | * @irq: Interrupt to enable | 94 | seq_printf(p, "ERR: %10lu\n", irq_err_count); |
215 | * | ||
216 | * Re-enables the processing of interrupts on this IRQ line | ||
217 | * providing no disable_irq calls are now in effect. | ||
218 | * | ||
219 | * This function may be called from IRQ context. | ||
220 | */ | ||
221 | |||
222 | void enable_irq(unsigned int irq) | ||
223 | { | ||
224 | irq_desc_t *desc = irq_desc + irq; | ||
225 | unsigned long flags; | ||
226 | 95 | ||
227 | spin_lock_irqsave(&desc->lock, flags); | 96 | return 0; |
228 | switch (desc->depth) { | ||
229 | case 1: { | ||
230 | unsigned int status = desc->status & ~IRQ_DISABLED; | ||
231 | desc->status = status; | ||
232 | if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { | ||
233 | desc->status = status | IRQ_REPLAY; | ||
234 | hw_resend_irq(desc->handler,irq); | ||
235 | } | ||
236 | desc->handler->enable(irq); | ||
237 | /* fall-through */ | ||
238 | } | ||
239 | default: | ||
240 | desc->depth--; | ||
241 | break; | ||
242 | case 0: | ||
243 | printk("enable_irq(%u) unbalanced from %p\n", irq, | ||
244 | __builtin_return_address(0)); | ||
245 | } | ||
246 | spin_unlock_irqrestore(&desc->lock, flags); | ||
247 | } | 97 | } |
248 | 98 | ||
249 | /* Handle interrupt IRQ. REGS are the registers at the time of ther | 99 | /* Handle interrupt IRQ. REGS are the registers at the time of ther |
250 | interrupt. */ | 100 | interrupt. */ |
251 | unsigned int handle_irq (int irq, struct pt_regs *regs) | 101 | unsigned int handle_irq (int irq, struct pt_regs *regs) |
252 | { | 102 | { |
253 | /* | ||
254 | * We ack quickly, we don't want the irq controller | ||
255 | * thinking we're snobs just because some other CPU has | ||
256 | * disabled global interrupts (we have already done the | ||
257 | * INT_ACK cycles, it's too late to try to pretend to the | ||
258 | * controller that we aren't taking the interrupt). | ||
259 | * | ||
260 | * 0 return value means that this irq is already being | ||
261 | * handled by some other CPU. (or is disabled) | ||
262 | */ | ||
263 | int cpu = smp_processor_id(); | ||
264 | irq_desc_t *desc = irq_desc + irq; | ||
265 | struct irqaction * action; | ||
266 | unsigned int status; | ||
267 | |||
268 | irq_enter(); | 103 | irq_enter(); |
269 | kstat_cpu(cpu).irqs[irq]++; | 104 | __do_IRQ(irq, regs); |
270 | spin_lock(&desc->lock); | ||
271 | desc->handler->ack(irq); | ||
272 | /* | ||
273 | REPLAY is when Linux resends an IRQ that was dropped earlier | ||
274 | WAITING is used by probe to mark irqs that are being tested | ||
275 | */ | ||
276 | status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING); | ||
277 | status |= IRQ_PENDING; /* we _want_ to handle it */ | ||
278 | |||
279 | /* | ||
280 | * If the IRQ is disabled for whatever reason, we cannot | ||
281 | * use the action we have. | ||
282 | */ | ||
283 | action = NULL; | ||
284 | if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) { | ||
285 | action = desc->action; | ||
286 | status &= ~IRQ_PENDING; /* we commit to handling */ | ||
287 | status |= IRQ_INPROGRESS; /* we are handling it */ | ||
288 | } | ||
289 | desc->status = status; | ||
290 | |||
291 | /* | ||
292 | * If there is no IRQ handler or it was disabled, exit early. | ||
293 | Since we set PENDING, if another processor is handling | ||
294 | a different instance of this same irq, the other processor | ||
295 | will take care of it. | ||
296 | */ | ||
297 | if (unlikely(!action)) | ||
298 | goto out; | ||
299 | |||
300 | /* | ||
301 | * Edge triggered interrupts need to remember | ||
302 | * pending events. | ||
303 | * This applies to any hw interrupts that allow a second | ||
304 | * instance of the same irq to arrive while we are in handle_irq | ||
305 | * or in the handler. But the code here only handles the _second_ | ||
306 | * instance of the irq, not the third or fourth. So it is mostly | ||
307 | * useful for irq hardware that does not mask cleanly in an | ||
308 | * SMP environment. | ||
309 | */ | ||
310 | for (;;) { | ||
311 | spin_unlock(&desc->lock); | ||
312 | handle_IRQ_event(irq, regs, action); | ||
313 | spin_lock(&desc->lock); | ||
314 | |||
315 | if (likely(!(desc->status & IRQ_PENDING))) | ||
316 | break; | ||
317 | desc->status &= ~IRQ_PENDING; | ||
318 | } | ||
319 | desc->status &= ~IRQ_INPROGRESS; | ||
320 | |||
321 | out: | ||
322 | /* | ||
323 | * The ->end() handler has to deal with interrupts which got | ||
324 | * disabled while the handler was running. | ||
325 | */ | ||
326 | desc->handler->end(irq); | ||
327 | spin_unlock(&desc->lock); | ||
328 | |||
329 | irq_exit(); | 105 | irq_exit(); |
330 | |||
331 | return 1; | 106 | return 1; |
332 | } | 107 | } |
333 | 108 | ||
334 | /** | ||
335 | * request_irq - allocate an interrupt line | ||
336 | * @irq: Interrupt line to allocate | ||
337 | * @handler: Function to be called when the IRQ occurs | ||
338 | * @irqflags: Interrupt type flags | ||
339 | * @devname: An ascii name for the claiming device | ||
340 | * @dev_id: A cookie passed back to the handler function | ||
341 | * | ||
342 | * This call allocates interrupt resources and enables the | ||
343 | * interrupt line and IRQ handling. From the point this | ||
344 | * call is made your handler function may be invoked. Since | ||
345 | * your handler function must clear any interrupt the board | ||
346 | * raises, you must take care both to initialise your hardware | ||
347 | * and to set up the interrupt handler in the right order. | ||
348 | * | ||
349 | * Dev_id must be globally unique. Normally the address of the | ||
350 | * device data structure is used as the cookie. Since the handler | ||
351 | * receives this value it makes sense to use it. | ||
352 | * | ||
353 | * If your interrupt is shared you must pass a non NULL dev_id | ||
354 | * as this is required when freeing the interrupt. | ||
355 | * | ||
356 | * Flags: | ||
357 | * | ||
358 | * SA_SHIRQ Interrupt is shared | ||
359 | * | ||
360 | * SA_INTERRUPT Disable local interrupts while processing | ||
361 | * | ||
362 | * SA_SAMPLE_RANDOM The interrupt can be used for entropy | ||
363 | * | ||
364 | */ | ||
365 | |||
366 | int request_irq(unsigned int irq, | ||
367 | irqreturn_t (*handler)(int, void *, struct pt_regs *), | ||
368 | unsigned long irqflags, | ||
369 | const char * devname, | ||
370 | void *dev_id) | ||
371 | { | ||
372 | int retval; | ||
373 | struct irqaction * action; | ||
374 | |||
375 | #if 1 | ||
376 | /* | ||
377 | * Sanity-check: shared interrupts should REALLY pass in | ||
378 | * a real dev-ID, otherwise we'll have trouble later trying | ||
379 | * to figure out which interrupt is which (messes up the | ||
380 | * interrupt freeing logic etc). | ||
381 | */ | ||
382 | if (irqflags & SA_SHIRQ) { | ||
383 | if (!dev_id) | ||
384 | printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", devname, (&irq)[-1]); | ||
385 | } | ||
386 | #endif | ||
387 | |||
388 | if (irq >= NR_IRQS) | ||
389 | return -EINVAL; | ||
390 | if (!handler) | ||
391 | return -EINVAL; | ||
392 | |||
393 | action = (struct irqaction *) | ||
394 | kmalloc(sizeof(struct irqaction), GFP_KERNEL); | ||
395 | if (!action) | ||
396 | return -ENOMEM; | ||
397 | |||
398 | action->handler = handler; | ||
399 | action->flags = irqflags; | ||
400 | cpus_clear(action->mask); | ||
401 | action->name = devname; | ||
402 | action->next = NULL; | ||
403 | action->dev_id = dev_id; | ||
404 | |||
405 | retval = setup_irq(irq, action); | ||
406 | if (retval) | ||
407 | kfree(action); | ||
408 | return retval; | ||
409 | } | ||
410 | |||
411 | EXPORT_SYMBOL(request_irq); | ||
412 | |||
413 | /** | ||
414 | * free_irq - free an interrupt | ||
415 | * @irq: Interrupt line to free | ||
416 | * @dev_id: Device identity to free | ||
417 | * | ||
418 | * Remove an interrupt handler. The handler is removed and if the | ||
419 | * interrupt line is no longer in use by any driver it is disabled. | ||
420 | * On a shared IRQ the caller must ensure the interrupt is disabled | ||
421 | * on the card it drives before calling this function. The function | ||
422 | * does not return until any executing interrupts for this IRQ | ||
423 | * have completed. | ||
424 | * | ||
425 | * This function may be called from interrupt context. | ||
426 | * | ||
427 | * Bugs: Attempting to free an irq in a handler for the same irq hangs | ||
428 | * the machine. | ||
429 | */ | ||
430 | |||
431 | void free_irq(unsigned int irq, void *dev_id) | ||
432 | { | ||
433 | irq_desc_t *desc; | ||
434 | struct irqaction **p; | ||
435 | unsigned long flags; | ||
436 | |||
437 | if (irq >= NR_IRQS) | ||
438 | return; | ||
439 | |||
440 | desc = irq_desc + irq; | ||
441 | spin_lock_irqsave(&desc->lock,flags); | ||
442 | p = &desc->action; | ||
443 | for (;;) { | ||
444 | struct irqaction * action = *p; | ||
445 | if (action) { | ||
446 | struct irqaction **pp = p; | ||
447 | p = &action->next; | ||
448 | if (action->dev_id != dev_id) | ||
449 | continue; | ||
450 | |||
451 | /* Found it - now remove it from the list of entries */ | ||
452 | *pp = action->next; | ||
453 | if (!desc->action) { | ||
454 | desc->status |= IRQ_DISABLED; | ||
455 | desc->handler->shutdown(irq); | ||
456 | } | ||
457 | spin_unlock_irqrestore(&desc->lock,flags); | ||
458 | |||
459 | synchronize_irq(irq); | ||
460 | kfree(action); | ||
461 | return; | ||
462 | } | ||
463 | printk("Trying to free free IRQ%d\n",irq); | ||
464 | spin_unlock_irqrestore(&desc->lock,flags); | ||
465 | return; | ||
466 | } | ||
467 | } | ||
468 | |||
469 | EXPORT_SYMBOL(free_irq); | ||
470 | |||
471 | /* | ||
472 | * IRQ autodetection code.. | ||
473 | * | ||
474 | * This depends on the fact that any interrupt that | ||
475 | * comes in on to an unassigned handler will get stuck | ||
476 | * with "IRQ_WAITING" cleared and the interrupt | ||
477 | * disabled. | ||
478 | */ | ||
479 | |||
480 | static DECLARE_MUTEX(probe_sem); | ||
481 | |||
482 | /** | ||
483 | * probe_irq_on - begin an interrupt autodetect | ||
484 | * | ||
485 | * Commence probing for an interrupt. The interrupts are scanned | ||
486 | * and a mask of potential interrupt lines is returned. | ||
487 | * | ||
488 | */ | ||
489 | |||
490 | unsigned long probe_irq_on(void) | ||
491 | { | ||
492 | unsigned int i; | ||
493 | irq_desc_t *desc; | ||
494 | unsigned long val; | ||
495 | unsigned long delay; | ||
496 | |||
497 | down(&probe_sem); | ||
498 | /* | ||
499 | * something may have generated an irq long ago and we want to | ||
500 | * flush such a longstanding irq before considering it as spurious. | ||
501 | */ | ||
502 | for (i = NR_IRQS-1; i > 0; i--) { | ||
503 | desc = irq_desc + i; | ||
504 | |||
505 | spin_lock_irq(&desc->lock); | ||
506 | if (!irq_desc[i].action) | ||
507 | irq_desc[i].handler->startup(i); | ||
508 | spin_unlock_irq(&desc->lock); | ||
509 | } | ||
510 | |||
511 | /* Wait for longstanding interrupts to trigger. */ | ||
512 | for (delay = jiffies + HZ/50; time_after(delay, jiffies); ) | ||
513 | /* about 20ms delay */ barrier(); | ||
514 | |||
515 | /* | ||
516 | * enable any unassigned irqs | ||
517 | * (we must startup again here because if a longstanding irq | ||
518 | * happened in the previous stage, it may have masked itself) | ||
519 | */ | ||
520 | for (i = NR_IRQS-1; i > 0; i--) { | ||
521 | desc = irq_desc + i; | ||
522 | |||
523 | spin_lock_irq(&desc->lock); | ||
524 | if (!desc->action) { | ||
525 | desc->status |= IRQ_AUTODETECT | IRQ_WAITING; | ||
526 | if (desc->handler->startup(i)) | ||
527 | desc->status |= IRQ_PENDING; | ||
528 | } | ||
529 | spin_unlock_irq(&desc->lock); | ||
530 | } | ||
531 | |||
532 | /* | ||
533 | * Wait for spurious interrupts to trigger | ||
534 | */ | ||
535 | for (delay = jiffies + HZ/10; time_after(delay, jiffies); ) | ||
536 | /* about 100ms delay */ barrier(); | ||
537 | |||
538 | /* | ||
539 | * Now filter out any obviously spurious interrupts | ||
540 | */ | ||
541 | val = 0; | ||
542 | for (i = 0; i < NR_IRQS; i++) { | ||
543 | irq_desc_t *desc = irq_desc + i; | ||
544 | unsigned int status; | ||
545 | |||
546 | spin_lock_irq(&desc->lock); | ||
547 | status = desc->status; | ||
548 | |||
549 | if (status & IRQ_AUTODETECT) { | ||
550 | /* It triggered already - consider it spurious. */ | ||
551 | if (!(status & IRQ_WAITING)) { | ||
552 | desc->status = status & ~IRQ_AUTODETECT; | ||
553 | desc->handler->shutdown(i); | ||
554 | } else | ||
555 | if (i < 32) | ||
556 | val |= 1 << i; | ||
557 | } | ||
558 | spin_unlock_irq(&desc->lock); | ||
559 | } | ||
560 | |||
561 | return val; | ||
562 | } | ||
563 | |||
564 | EXPORT_SYMBOL(probe_irq_on); | ||
565 | |||
566 | /* | ||
567 | * Return a mask of triggered interrupts (this | ||
568 | * can handle only legacy ISA interrupts). | ||
569 | */ | ||
570 | |||
571 | /** | ||
572 | * probe_irq_mask - scan a bitmap of interrupt lines | ||
573 | * @val: mask of interrupts to consider | ||
574 | * | ||
575 | * Scan the ISA bus interrupt lines and return a bitmap of | ||
576 | * active interrupts. The interrupt probe logic state is then | ||
577 | * returned to its previous value. | ||
578 | * | ||
579 | * Note: we need to scan all the irq's even though we will | ||
580 | * only return ISA irq numbers - just so that we reset them | ||
581 | * all to a known state. | ||
582 | */ | ||
583 | unsigned int probe_irq_mask(unsigned long val) | ||
584 | { | ||
585 | int i; | ||
586 | unsigned int mask; | ||
587 | |||
588 | mask = 0; | ||
589 | for (i = 0; i < NR_IRQS; i++) { | ||
590 | irq_desc_t *desc = irq_desc + i; | ||
591 | unsigned int status; | ||
592 | |||
593 | spin_lock_irq(&desc->lock); | ||
594 | status = desc->status; | ||
595 | |||
596 | if (status & IRQ_AUTODETECT) { | ||
597 | if (i < 16 && !(status & IRQ_WAITING)) | ||
598 | mask |= 1 << i; | ||
599 | |||
600 | desc->status = status & ~IRQ_AUTODETECT; | ||
601 | desc->handler->shutdown(i); | ||
602 | } | ||
603 | spin_unlock_irq(&desc->lock); | ||
604 | } | ||
605 | up(&probe_sem); | ||
606 | |||
607 | return mask & val; | ||
608 | } | ||
609 | |||
610 | /* | ||
611 | * Return the one interrupt that triggered (this can | ||
612 | * handle any interrupt source). | ||
613 | */ | ||
614 | |||
615 | /** | ||
616 | * probe_irq_off - end an interrupt autodetect | ||
617 | * @val: mask of potential interrupts (unused) | ||
618 | * | ||
619 | * Scans the unused interrupt lines and returns the line which | ||
620 | * appears to have triggered the interrupt. If no interrupt was | ||
621 | * found then zero is returned. If more than one interrupt is | ||
622 | * found then minus the first candidate is returned to indicate | ||
623 | * their is doubt. | ||
624 | * | ||
625 | * The interrupt probe logic state is returned to its previous | ||
626 | * value. | ||
627 | * | ||
628 | * BUGS: When used in a module (which arguably shouldnt happen) | ||
629 | * nothing prevents two IRQ probe callers from overlapping. The | ||
630 | * results of this are non-optimal. | ||
631 | */ | ||
632 | |||
633 | int probe_irq_off(unsigned long val) | ||
634 | { | ||
635 | int i, irq_found, nr_irqs; | ||
636 | |||
637 | nr_irqs = 0; | ||
638 | irq_found = 0; | ||
639 | for (i = 0; i < NR_IRQS; i++) { | ||
640 | irq_desc_t *desc = irq_desc + i; | ||
641 | unsigned int status; | ||
642 | |||
643 | spin_lock_irq(&desc->lock); | ||
644 | status = desc->status; | ||
645 | |||
646 | if (status & IRQ_AUTODETECT) { | ||
647 | if (!(status & IRQ_WAITING)) { | ||
648 | if (!nr_irqs) | ||
649 | irq_found = i; | ||
650 | nr_irqs++; | ||
651 | } | ||
652 | desc->status = status & ~IRQ_AUTODETECT; | ||
653 | desc->handler->shutdown(i); | ||
654 | } | ||
655 | spin_unlock_irq(&desc->lock); | ||
656 | } | ||
657 | up(&probe_sem); | ||
658 | |||
659 | if (nr_irqs > 1) | ||
660 | irq_found = -irq_found; | ||
661 | return irq_found; | ||
662 | } | ||
663 | |||
664 | EXPORT_SYMBOL(probe_irq_off); | ||
665 | |||
666 | /* this was setup_x86_irq but it seems pretty generic */ | ||
667 | int setup_irq(unsigned int irq, struct irqaction * new) | ||
668 | { | ||
669 | int shared = 0; | ||
670 | unsigned long flags; | ||
671 | struct irqaction *old, **p; | ||
672 | irq_desc_t *desc = irq_desc + irq; | ||
673 | |||
674 | /* | ||
675 | * Some drivers like serial.c use request_irq() heavily, | ||
676 | * so we have to be careful not to interfere with a | ||
677 | * running system. | ||
678 | */ | ||
679 | if (new->flags & SA_SAMPLE_RANDOM) { | ||
680 | /* | ||
681 | * This function might sleep, we want to call it first, | ||
682 | * outside of the atomic block. | ||
683 | * Yes, this might clear the entropy pool if the wrong | ||
684 | * driver is attempted to be loaded, without actually | ||
685 | * installing a new handler, but is this really a problem, | ||
686 | * only the sysadmin is able to do this. | ||
687 | */ | ||
688 | rand_initialize_irq(irq); | ||
689 | } | ||
690 | |||
691 | /* | ||
692 | * The following block of code has to be executed atomically | ||
693 | */ | ||
694 | spin_lock_irqsave(&desc->lock,flags); | ||
695 | p = &desc->action; | ||
696 | if ((old = *p) != NULL) { | ||
697 | /* Can't share interrupts unless both agree to */ | ||
698 | if (!(old->flags & new->flags & SA_SHIRQ)) { | ||
699 | spin_unlock_irqrestore(&desc->lock,flags); | ||
700 | return -EBUSY; | ||
701 | } | ||
702 | |||
703 | /* add new interrupt at end of irq queue */ | ||
704 | do { | ||
705 | p = &old->next; | ||
706 | old = *p; | ||
707 | } while (old); | ||
708 | shared = 1; | ||
709 | } | ||
710 | |||
711 | *p = new; | ||
712 | |||
713 | if (!shared) { | ||
714 | desc->depth = 0; | ||
715 | desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); | ||
716 | desc->handler->startup(irq); | ||
717 | } | ||
718 | spin_unlock_irqrestore(&desc->lock,flags); | ||
719 | |||
720 | /* register_irq_proc(irq); */ | ||
721 | return 0; | ||
722 | } | ||
723 | |||
724 | /* Initialize irq handling for IRQs. | 109 | /* Initialize irq handling for IRQs. |
725 | BASE_IRQ, BASE_IRQ+INTERVAL, ..., BASE_IRQ+NUM*INTERVAL | 110 | BASE_IRQ, BASE_IRQ+INTERVAL, ..., BASE_IRQ+NUM*INTERVAL |
726 | to IRQ_TYPE. An IRQ_TYPE of 0 means to use a generic interrupt type. */ | 111 | to IRQ_TYPE. An IRQ_TYPE of 0 means to use a generic interrupt type. */ |
@@ -736,9 +121,3 @@ init_irq_handlers (int base_irq, int num, int interval, | |||
736 | base_irq += interval; | 121 | base_irq += interval; |
737 | } | 122 | } |
738 | } | 123 | } |
739 | |||
740 | #if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL) | ||
741 | void init_irq_proc(void) | ||
742 | { | ||
743 | } | ||
744 | #endif /* CONFIG_PROC_FS && CONFIG_SYSCTL */ | ||
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 4cce2f6f170c..6ece645e4dbe 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig | |||
@@ -226,22 +226,42 @@ config SCHED_SMT | |||
226 | 226 | ||
227 | source "kernel/Kconfig.preempt" | 227 | source "kernel/Kconfig.preempt" |
228 | 228 | ||
229 | config K8_NUMA | 229 | config NUMA |
230 | bool "K8 NUMA support" | 230 | bool "Non Uniform Memory Access (NUMA) Support" |
231 | select NUMA | ||
232 | depends on SMP | 231 | depends on SMP |
233 | help | 232 | help |
234 | Enable NUMA (Non Unified Memory Architecture) support for | 233 | Enable NUMA (Non Uniform Memory Access) support. The kernel |
235 | AMD Opteron Multiprocessor systems. The kernel will try to allocate | 234 | will try to allocate memory used by a CPU on the local memory |
236 | memory used by a CPU on the local memory controller of the CPU | 235 | controller of the CPU and add some more NUMA awareness to the kernel. |
237 | and add some more NUMA awareness to the kernel. | 236 | This code is recommended on all multiprocessor Opteron systems. |
238 | This code is recommended on all multiprocessor Opteron systems | 237 | If the system is EM64T, you should say N unless your system is EM64T |
239 | and normally doesn't hurt on others. | 238 | NUMA. |
239 | |||
240 | config K8_NUMA | ||
241 | bool "Old style AMD Opteron NUMA detection" | ||
242 | depends on NUMA | ||
243 | default y | ||
244 | help | ||
245 | Enable K8 NUMA node topology detection. You should say Y here if | ||
246 | you have a multi processor AMD K8 system. This uses an old | ||
247 | method to read the NUMA configurtion directly from the builtin | ||
248 | Northbridge of Opteron. It is recommended to use X86_64_ACPI_NUMA | ||
249 | instead, which also takes priority if both are compiled in. | ||
250 | |||
251 | # Dummy CONFIG option to select ACPI_NUMA from drivers/acpi/Kconfig. | ||
252 | |||
253 | config X86_64_ACPI_NUMA | ||
254 | bool "ACPI NUMA detection" | ||
255 | depends on NUMA | ||
256 | select ACPI | ||
257 | select ACPI_NUMA | ||
258 | default y | ||
259 | help | ||
260 | Enable ACPI SRAT based node topology detection. | ||
240 | 261 | ||
241 | config NUMA_EMU | 262 | config NUMA_EMU |
242 | bool "NUMA emulation support" | 263 | bool "NUMA emulation" |
243 | select NUMA | 264 | depends on NUMA |
244 | depends on SMP | ||
245 | help | 265 | help |
246 | Enable NUMA emulation. A flat machine will be split | 266 | Enable NUMA emulation. A flat machine will be split |
247 | into virtual nodes when booted with "numa=fake=N", where N is the | 267 | into virtual nodes when booted with "numa=fake=N", where N is the |
@@ -252,9 +272,6 @@ config ARCH_DISCONTIGMEM_ENABLE | |||
252 | depends on NUMA | 272 | depends on NUMA |
253 | default y | 273 | default y |
254 | 274 | ||
255 | config NUMA | ||
256 | bool | ||
257 | default n | ||
258 | 275 | ||
259 | config ARCH_DISCONTIGMEM_ENABLE | 276 | config ARCH_DISCONTIGMEM_ENABLE |
260 | def_bool y | 277 | def_bool y |
@@ -374,6 +391,14 @@ config X86_MCE_INTEL | |||
374 | Additional support for intel specific MCE features such as | 391 | Additional support for intel specific MCE features such as |
375 | the thermal monitor. | 392 | the thermal monitor. |
376 | 393 | ||
394 | config X86_MCE_AMD | ||
395 | bool "AMD MCE features" | ||
396 | depends on X86_MCE && X86_LOCAL_APIC | ||
397 | default y | ||
398 | help | ||
399 | Additional support for AMD specific MCE features such as | ||
400 | the DRAM Error Threshold. | ||
401 | |||
377 | config PHYSICAL_START | 402 | config PHYSICAL_START |
378 | hex "Physical address where the kernel is loaded" if EMBEDDED | 403 | hex "Physical address where the kernel is loaded" if EMBEDDED |
379 | default "0x100000" | 404 | default "0x100000" |
@@ -502,7 +527,7 @@ config IA32_EMULATION | |||
502 | left. | 527 | left. |
503 | 528 | ||
504 | config IA32_AOUT | 529 | config IA32_AOUT |
505 | bool "IA32 a.out support" | 530 | tristate "IA32 a.out support" |
506 | depends on IA32_EMULATION | 531 | depends on IA32_EMULATION |
507 | help | 532 | help |
508 | Support old a.out binaries in the 32bit emulation. | 533 | Support old a.out binaries in the 32bit emulation. |
diff --git a/arch/x86_64/Kconfig.debug b/arch/x86_64/Kconfig.debug index d584ecc27ea1..e2c6e64a85ec 100644 --- a/arch/x86_64/Kconfig.debug +++ b/arch/x86_64/Kconfig.debug | |||
@@ -2,15 +2,6 @@ menu "Kernel hacking" | |||
2 | 2 | ||
3 | source "lib/Kconfig.debug" | 3 | source "lib/Kconfig.debug" |
4 | 4 | ||
5 | # !SMP for now because the context switch early causes GPF in segment reloading | ||
6 | # and the GS base checking does the wrong thing then, causing a hang. | ||
7 | config CHECKING | ||
8 | bool "Additional run-time checks" | ||
9 | depends on DEBUG_KERNEL && !SMP | ||
10 | help | ||
11 | Enables some internal consistency checks for kernel debugging. | ||
12 | You should normally say N. | ||
13 | |||
14 | config INIT_DEBUG | 5 | config INIT_DEBUG |
15 | bool "Debug __init statements" | 6 | bool "Debug __init statements" |
16 | depends on DEBUG_KERNEL | 7 | depends on DEBUG_KERNEL |
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig index f8db7e500fbf..5d56542fb68f 100644 --- a/arch/x86_64/defconfig +++ b/arch/x86_64/defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.13-git11 | 3 | # Linux kernel version: 2.6.14-git7 |
4 | # Mon Sep 12 16:16:16 2005 | 4 | # Sat Nov 5 15:55:50 2005 |
5 | # | 5 | # |
6 | CONFIG_X86_64=y | 6 | CONFIG_X86_64=y |
7 | CONFIG_64BIT=y | 7 | CONFIG_64BIT=y |
@@ -35,7 +35,7 @@ CONFIG_POSIX_MQUEUE=y | |||
35 | # CONFIG_BSD_PROCESS_ACCT is not set | 35 | # CONFIG_BSD_PROCESS_ACCT is not set |
36 | CONFIG_SYSCTL=y | 36 | CONFIG_SYSCTL=y |
37 | # CONFIG_AUDIT is not set | 37 | # CONFIG_AUDIT is not set |
38 | # CONFIG_HOTPLUG is not set | 38 | CONFIG_HOTPLUG=y |
39 | CONFIG_KOBJECT_UEVENT=y | 39 | CONFIG_KOBJECT_UEVENT=y |
40 | CONFIG_IKCONFIG=y | 40 | CONFIG_IKCONFIG=y |
41 | CONFIG_IKCONFIG_PROC=y | 41 | CONFIG_IKCONFIG_PROC=y |
@@ -93,10 +93,11 @@ CONFIG_PREEMPT_NONE=y | |||
93 | # CONFIG_PREEMPT_VOLUNTARY is not set | 93 | # CONFIG_PREEMPT_VOLUNTARY is not set |
94 | # CONFIG_PREEMPT is not set | 94 | # CONFIG_PREEMPT is not set |
95 | CONFIG_PREEMPT_BKL=y | 95 | CONFIG_PREEMPT_BKL=y |
96 | CONFIG_NUMA=y | ||
96 | CONFIG_K8_NUMA=y | 97 | CONFIG_K8_NUMA=y |
98 | CONFIG_X86_64_ACPI_NUMA=y | ||
97 | # CONFIG_NUMA_EMU is not set | 99 | # CONFIG_NUMA_EMU is not set |
98 | CONFIG_ARCH_DISCONTIGMEM_ENABLE=y | 100 | CONFIG_ARCH_DISCONTIGMEM_ENABLE=y |
99 | CONFIG_NUMA=y | ||
100 | CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y | 101 | CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y |
101 | CONFIG_ARCH_SPARSEMEM_ENABLE=y | 102 | CONFIG_ARCH_SPARSEMEM_ENABLE=y |
102 | CONFIG_SELECT_MEMORY_MODEL=y | 103 | CONFIG_SELECT_MEMORY_MODEL=y |
@@ -107,9 +108,10 @@ CONFIG_DISCONTIGMEM=y | |||
107 | CONFIG_FLAT_NODE_MEM_MAP=y | 108 | CONFIG_FLAT_NODE_MEM_MAP=y |
108 | CONFIG_NEED_MULTIPLE_NODES=y | 109 | CONFIG_NEED_MULTIPLE_NODES=y |
109 | # CONFIG_SPARSEMEM_STATIC is not set | 110 | # CONFIG_SPARSEMEM_STATIC is not set |
111 | CONFIG_SPLIT_PTLOCK_CPUS=4 | ||
110 | CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y | 112 | CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y |
111 | CONFIG_HAVE_DEC_LOCK=y | ||
112 | CONFIG_NR_CPUS=32 | 113 | CONFIG_NR_CPUS=32 |
114 | CONFIG_HOTPLUG_CPU=y | ||
113 | CONFIG_HPET_TIMER=y | 115 | CONFIG_HPET_TIMER=y |
114 | CONFIG_X86_PM_TIMER=y | 116 | CONFIG_X86_PM_TIMER=y |
115 | CONFIG_HPET_EMULATE_RTC=y | 117 | CONFIG_HPET_EMULATE_RTC=y |
@@ -117,6 +119,7 @@ CONFIG_GART_IOMMU=y | |||
117 | CONFIG_SWIOTLB=y | 119 | CONFIG_SWIOTLB=y |
118 | CONFIG_X86_MCE=y | 120 | CONFIG_X86_MCE=y |
119 | CONFIG_X86_MCE_INTEL=y | 121 | CONFIG_X86_MCE_INTEL=y |
122 | CONFIG_X86_MCE_AMD=y | ||
120 | CONFIG_PHYSICAL_START=0x100000 | 123 | CONFIG_PHYSICAL_START=0x100000 |
121 | # CONFIG_KEXEC is not set | 124 | # CONFIG_KEXEC is not set |
122 | CONFIG_SECCOMP=y | 125 | CONFIG_SECCOMP=y |
@@ -136,11 +139,15 @@ CONFIG_PM=y | |||
136 | # CONFIG_PM_DEBUG is not set | 139 | # CONFIG_PM_DEBUG is not set |
137 | CONFIG_SOFTWARE_SUSPEND=y | 140 | CONFIG_SOFTWARE_SUSPEND=y |
138 | CONFIG_PM_STD_PARTITION="" | 141 | CONFIG_PM_STD_PARTITION="" |
142 | CONFIG_SUSPEND_SMP=y | ||
139 | 143 | ||
140 | # | 144 | # |
141 | # ACPI (Advanced Configuration and Power Interface) Support | 145 | # ACPI (Advanced Configuration and Power Interface) Support |
142 | # | 146 | # |
143 | CONFIG_ACPI=y | 147 | CONFIG_ACPI=y |
148 | CONFIG_ACPI_SLEEP=y | ||
149 | CONFIG_ACPI_SLEEP_PROC_FS=y | ||
150 | CONFIG_ACPI_SLEEP_PROC_SLEEP=y | ||
144 | CONFIG_ACPI_AC=y | 151 | CONFIG_ACPI_AC=y |
145 | CONFIG_ACPI_BATTERY=y | 152 | CONFIG_ACPI_BATTERY=y |
146 | CONFIG_ACPI_BUTTON=y | 153 | CONFIG_ACPI_BUTTON=y |
@@ -148,6 +155,7 @@ CONFIG_ACPI_BUTTON=y | |||
148 | CONFIG_ACPI_HOTKEY=m | 155 | CONFIG_ACPI_HOTKEY=m |
149 | CONFIG_ACPI_FAN=y | 156 | CONFIG_ACPI_FAN=y |
150 | CONFIG_ACPI_PROCESSOR=y | 157 | CONFIG_ACPI_PROCESSOR=y |
158 | CONFIG_ACPI_HOTPLUG_CPU=y | ||
151 | CONFIG_ACPI_THERMAL=y | 159 | CONFIG_ACPI_THERMAL=y |
152 | CONFIG_ACPI_NUMA=y | 160 | CONFIG_ACPI_NUMA=y |
153 | # CONFIG_ACPI_ASUS is not set | 161 | # CONFIG_ACPI_ASUS is not set |
@@ -158,7 +166,7 @@ CONFIG_ACPI_BLACKLIST_YEAR=2001 | |||
158 | CONFIG_ACPI_EC=y | 166 | CONFIG_ACPI_EC=y |
159 | CONFIG_ACPI_POWER=y | 167 | CONFIG_ACPI_POWER=y |
160 | CONFIG_ACPI_SYSTEM=y | 168 | CONFIG_ACPI_SYSTEM=y |
161 | # CONFIG_ACPI_CONTAINER is not set | 169 | CONFIG_ACPI_CONTAINER=y |
162 | 170 | ||
163 | # | 171 | # |
164 | # CPU Frequency scaling | 172 | # CPU Frequency scaling |
@@ -293,7 +301,6 @@ CONFIG_IPV6=y | |||
293 | # Network testing | 301 | # Network testing |
294 | # | 302 | # |
295 | # CONFIG_NET_PKTGEN is not set | 303 | # CONFIG_NET_PKTGEN is not set |
296 | # CONFIG_NETFILTER_NETLINK is not set | ||
297 | # CONFIG_HAMRADIO is not set | 304 | # CONFIG_HAMRADIO is not set |
298 | # CONFIG_IRDA is not set | 305 | # CONFIG_IRDA is not set |
299 | # CONFIG_BT is not set | 306 | # CONFIG_BT is not set |
@@ -312,6 +319,11 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y | |||
312 | # CONFIG_DEBUG_DRIVER is not set | 319 | # CONFIG_DEBUG_DRIVER is not set |
313 | 320 | ||
314 | # | 321 | # |
322 | # Connector - unified userspace <-> kernelspace linker | ||
323 | # | ||
324 | # CONFIG_CONNECTOR is not set | ||
325 | |||
326 | # | ||
315 | # Memory Technology Devices (MTD) | 327 | # Memory Technology Devices (MTD) |
316 | # | 328 | # |
317 | # CONFIG_MTD is not set | 329 | # CONFIG_MTD is not set |
@@ -354,6 +366,11 @@ CONFIG_IOSCHED_NOOP=y | |||
354 | # CONFIG_IOSCHED_AS is not set | 366 | # CONFIG_IOSCHED_AS is not set |
355 | CONFIG_IOSCHED_DEADLINE=y | 367 | CONFIG_IOSCHED_DEADLINE=y |
356 | CONFIG_IOSCHED_CFQ=y | 368 | CONFIG_IOSCHED_CFQ=y |
369 | # CONFIG_DEFAULT_AS is not set | ||
370 | CONFIG_DEFAULT_DEADLINE=y | ||
371 | # CONFIG_DEFAULT_CFQ is not set | ||
372 | # CONFIG_DEFAULT_NOOP is not set | ||
373 | CONFIG_DEFAULT_IOSCHED="cfq" | ||
357 | # CONFIG_ATA_OVER_ETH is not set | 374 | # CONFIG_ATA_OVER_ETH is not set |
358 | 375 | ||
359 | # | 376 | # |
@@ -450,6 +467,7 @@ CONFIG_BLK_DEV_SD=y | |||
450 | CONFIG_SCSI_SPI_ATTRS=y | 467 | CONFIG_SCSI_SPI_ATTRS=y |
451 | # CONFIG_SCSI_FC_ATTRS is not set | 468 | # CONFIG_SCSI_FC_ATTRS is not set |
452 | # CONFIG_SCSI_ISCSI_ATTRS is not set | 469 | # CONFIG_SCSI_ISCSI_ATTRS is not set |
470 | # CONFIG_SCSI_SAS_ATTRS is not set | ||
453 | 471 | ||
454 | # | 472 | # |
455 | # SCSI low-level drivers | 473 | # SCSI low-level drivers |
@@ -469,20 +487,24 @@ CONFIG_AIC79XX_DEBUG_MASK=0 | |||
469 | # CONFIG_AIC79XX_REG_PRETTY_PRINT is not set | 487 | # CONFIG_AIC79XX_REG_PRETTY_PRINT is not set |
470 | # CONFIG_MEGARAID_NEWGEN is not set | 488 | # CONFIG_MEGARAID_NEWGEN is not set |
471 | # CONFIG_MEGARAID_LEGACY is not set | 489 | # CONFIG_MEGARAID_LEGACY is not set |
490 | # CONFIG_MEGARAID_SAS is not set | ||
472 | CONFIG_SCSI_SATA=y | 491 | CONFIG_SCSI_SATA=y |
473 | # CONFIG_SCSI_SATA_AHCI is not set | 492 | # CONFIG_SCSI_SATA_AHCI is not set |
474 | # CONFIG_SCSI_SATA_SVW is not set | 493 | # CONFIG_SCSI_SATA_SVW is not set |
475 | CONFIG_SCSI_ATA_PIIX=y | 494 | CONFIG_SCSI_ATA_PIIX=y |
476 | # CONFIG_SCSI_SATA_MV is not set | 495 | # CONFIG_SCSI_SATA_MV is not set |
477 | # CONFIG_SCSI_SATA_NV is not set | 496 | CONFIG_SCSI_SATA_NV=y |
478 | # CONFIG_SCSI_SATA_PROMISE is not set | 497 | # CONFIG_SCSI_PDC_ADMA is not set |
479 | # CONFIG_SCSI_SATA_QSTOR is not set | 498 | # CONFIG_SCSI_SATA_QSTOR is not set |
499 | # CONFIG_SCSI_SATA_PROMISE is not set | ||
480 | # CONFIG_SCSI_SATA_SX4 is not set | 500 | # CONFIG_SCSI_SATA_SX4 is not set |
481 | # CONFIG_SCSI_SATA_SIL is not set | 501 | # CONFIG_SCSI_SATA_SIL is not set |
502 | # CONFIG_SCSI_SATA_SIL24 is not set | ||
482 | # CONFIG_SCSI_SATA_SIS is not set | 503 | # CONFIG_SCSI_SATA_SIS is not set |
483 | # CONFIG_SCSI_SATA_ULI is not set | 504 | # CONFIG_SCSI_SATA_ULI is not set |
484 | CONFIG_SCSI_SATA_VIA=y | 505 | CONFIG_SCSI_SATA_VIA=y |
485 | # CONFIG_SCSI_SATA_VITESSE is not set | 506 | # CONFIG_SCSI_SATA_VITESSE is not set |
507 | CONFIG_SCSI_SATA_INTEL_COMBINED=y | ||
486 | # CONFIG_SCSI_BUSLOGIC is not set | 508 | # CONFIG_SCSI_BUSLOGIC is not set |
487 | # CONFIG_SCSI_DMX3191D is not set | 509 | # CONFIG_SCSI_DMX3191D is not set |
488 | # CONFIG_SCSI_EATA is not set | 510 | # CONFIG_SCSI_EATA is not set |
@@ -525,6 +547,7 @@ CONFIG_BLK_DEV_DM=y | |||
525 | CONFIG_FUSION=y | 547 | CONFIG_FUSION=y |
526 | CONFIG_FUSION_SPI=y | 548 | CONFIG_FUSION_SPI=y |
527 | # CONFIG_FUSION_FC is not set | 549 | # CONFIG_FUSION_FC is not set |
550 | # CONFIG_FUSION_SAS is not set | ||
528 | CONFIG_FUSION_MAX_SGE=128 | 551 | CONFIG_FUSION_MAX_SGE=128 |
529 | # CONFIG_FUSION_CTL is not set | 552 | # CONFIG_FUSION_CTL is not set |
530 | 553 | ||
@@ -564,6 +587,7 @@ CONFIG_NET_ETHERNET=y | |||
564 | CONFIG_MII=y | 587 | CONFIG_MII=y |
565 | # CONFIG_HAPPYMEAL is not set | 588 | # CONFIG_HAPPYMEAL is not set |
566 | # CONFIG_SUNGEM is not set | 589 | # CONFIG_SUNGEM is not set |
590 | # CONFIG_CASSINI is not set | ||
567 | CONFIG_NET_VENDOR_3COM=y | 591 | CONFIG_NET_VENDOR_3COM=y |
568 | CONFIG_VORTEX=y | 592 | CONFIG_VORTEX=y |
569 | # CONFIG_TYPHOON is not set | 593 | # CONFIG_TYPHOON is not set |
@@ -740,7 +764,43 @@ CONFIG_LEGACY_PTY_COUNT=256 | |||
740 | # | 764 | # |
741 | # Watchdog Cards | 765 | # Watchdog Cards |
742 | # | 766 | # |
743 | # CONFIG_WATCHDOG is not set | 767 | CONFIG_WATCHDOG=y |
768 | # CONFIG_WATCHDOG_NOWAYOUT is not set | ||
769 | |||
770 | # | ||
771 | # Watchdog Device Drivers | ||
772 | # | ||
773 | CONFIG_SOFT_WATCHDOG=y | ||
774 | # CONFIG_ACQUIRE_WDT is not set | ||
775 | # CONFIG_ADVANTECH_WDT is not set | ||
776 | # CONFIG_ALIM1535_WDT is not set | ||
777 | # CONFIG_ALIM7101_WDT is not set | ||
778 | # CONFIG_SC520_WDT is not set | ||
779 | # CONFIG_EUROTECH_WDT is not set | ||
780 | # CONFIG_IB700_WDT is not set | ||
781 | # CONFIG_IBMASR is not set | ||
782 | # CONFIG_WAFER_WDT is not set | ||
783 | # CONFIG_I6300ESB_WDT is not set | ||
784 | # CONFIG_I8XX_TCO is not set | ||
785 | # CONFIG_SC1200_WDT is not set | ||
786 | # CONFIG_60XX_WDT is not set | ||
787 | # CONFIG_SBC8360_WDT is not set | ||
788 | # CONFIG_CPU5_WDT is not set | ||
789 | # CONFIG_W83627HF_WDT is not set | ||
790 | # CONFIG_W83877F_WDT is not set | ||
791 | # CONFIG_W83977F_WDT is not set | ||
792 | # CONFIG_MACHZ_WDT is not set | ||
793 | |||
794 | # | ||
795 | # PCI-based Watchdog Cards | ||
796 | # | ||
797 | # CONFIG_PCIPCWATCHDOG is not set | ||
798 | # CONFIG_WDTPCI is not set | ||
799 | |||
800 | # | ||
801 | # USB-based Watchdog Cards | ||
802 | # | ||
803 | # CONFIG_USBPCWATCHDOG is not set | ||
744 | CONFIG_HW_RANDOM=y | 804 | CONFIG_HW_RANDOM=y |
745 | # CONFIG_NVRAM is not set | 805 | # CONFIG_NVRAM is not set |
746 | CONFIG_RTC=y | 806 | CONFIG_RTC=y |
@@ -767,6 +827,7 @@ CONFIG_MAX_RAW_DEVS=256 | |||
767 | # TPM devices | 827 | # TPM devices |
768 | # | 828 | # |
769 | # CONFIG_TCG_TPM is not set | 829 | # CONFIG_TCG_TPM is not set |
830 | # CONFIG_TELCLOCK is not set | ||
770 | 831 | ||
771 | # | 832 | # |
772 | # I2C support | 833 | # I2C support |
@@ -783,6 +844,7 @@ CONFIG_MAX_RAW_DEVS=256 | |||
783 | # | 844 | # |
784 | CONFIG_HWMON=y | 845 | CONFIG_HWMON=y |
785 | # CONFIG_HWMON_VID is not set | 846 | # CONFIG_HWMON_VID is not set |
847 | # CONFIG_SENSORS_HDAPS is not set | ||
786 | # CONFIG_HWMON_DEBUG_CHIP is not set | 848 | # CONFIG_HWMON_DEBUG_CHIP is not set |
787 | 849 | ||
788 | # | 850 | # |
@@ -886,12 +948,15 @@ CONFIG_USB_UHCI_HCD=y | |||
886 | # USB Device Class drivers | 948 | # USB Device Class drivers |
887 | # | 949 | # |
888 | # CONFIG_OBSOLETE_OSS_USB_DRIVER is not set | 950 | # CONFIG_OBSOLETE_OSS_USB_DRIVER is not set |
889 | # CONFIG_USB_BLUETOOTH_TTY is not set | ||
890 | # CONFIG_USB_ACM is not set | 951 | # CONFIG_USB_ACM is not set |
891 | CONFIG_USB_PRINTER=y | 952 | CONFIG_USB_PRINTER=y |
892 | 953 | ||
893 | # | 954 | # |
894 | # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information | 955 | # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' |
956 | # | ||
957 | |||
958 | # | ||
959 | # may also be needed; see USB_STORAGE Help for more information | ||
895 | # | 960 | # |
896 | CONFIG_USB_STORAGE=y | 961 | CONFIG_USB_STORAGE=y |
897 | # CONFIG_USB_STORAGE_DEBUG is not set | 962 | # CONFIG_USB_STORAGE_DEBUG is not set |
@@ -924,6 +989,7 @@ CONFIG_USB_HIDINPUT=y | |||
924 | # CONFIG_USB_XPAD is not set | 989 | # CONFIG_USB_XPAD is not set |
925 | # CONFIG_USB_ATI_REMOTE is not set | 990 | # CONFIG_USB_ATI_REMOTE is not set |
926 | # CONFIG_USB_KEYSPAN_REMOTE is not set | 991 | # CONFIG_USB_KEYSPAN_REMOTE is not set |
992 | # CONFIG_USB_APPLETOUCH is not set | ||
927 | 993 | ||
928 | # | 994 | # |
929 | # USB Imaging devices | 995 | # USB Imaging devices |
@@ -1005,7 +1071,7 @@ CONFIG_USB_MON=y | |||
1005 | # | 1071 | # |
1006 | # CONFIG_EDD is not set | 1072 | # CONFIG_EDD is not set |
1007 | # CONFIG_DELL_RBU is not set | 1073 | # CONFIG_DELL_RBU is not set |
1008 | CONFIG_DCDBAS=m | 1074 | # CONFIG_DCDBAS is not set |
1009 | 1075 | ||
1010 | # | 1076 | # |
1011 | # File systems | 1077 | # File systems |
@@ -1037,7 +1103,7 @@ CONFIG_INOTIFY=y | |||
1037 | # CONFIG_QUOTA is not set | 1103 | # CONFIG_QUOTA is not set |
1038 | CONFIG_DNOTIFY=y | 1104 | CONFIG_DNOTIFY=y |
1039 | CONFIG_AUTOFS_FS=y | 1105 | CONFIG_AUTOFS_FS=y |
1040 | # CONFIG_AUTOFS4_FS is not set | 1106 | CONFIG_AUTOFS4_FS=y |
1041 | # CONFIG_FUSE_FS is not set | 1107 | # CONFIG_FUSE_FS is not set |
1042 | 1108 | ||
1043 | # | 1109 | # |
@@ -1068,7 +1134,7 @@ CONFIG_TMPFS=y | |||
1068 | CONFIG_HUGETLBFS=y | 1134 | CONFIG_HUGETLBFS=y |
1069 | CONFIG_HUGETLB_PAGE=y | 1135 | CONFIG_HUGETLB_PAGE=y |
1070 | CONFIG_RAMFS=y | 1136 | CONFIG_RAMFS=y |
1071 | # CONFIG_RELAYFS_FS is not set | 1137 | CONFIG_RELAYFS_FS=y |
1072 | 1138 | ||
1073 | # | 1139 | # |
1074 | # Miscellaneous filesystems | 1140 | # Miscellaneous filesystems |
@@ -1186,7 +1252,9 @@ CONFIG_DETECT_SOFTLOCKUP=y | |||
1186 | # CONFIG_DEBUG_KOBJECT is not set | 1252 | # CONFIG_DEBUG_KOBJECT is not set |
1187 | # CONFIG_DEBUG_INFO is not set | 1253 | # CONFIG_DEBUG_INFO is not set |
1188 | CONFIG_DEBUG_FS=y | 1254 | CONFIG_DEBUG_FS=y |
1255 | # CONFIG_DEBUG_VM is not set | ||
1189 | # CONFIG_FRAME_POINTER is not set | 1256 | # CONFIG_FRAME_POINTER is not set |
1257 | # CONFIG_RCU_TORTURE_TEST is not set | ||
1190 | CONFIG_INIT_DEBUG=y | 1258 | CONFIG_INIT_DEBUG=y |
1191 | # CONFIG_IOMMU_DEBUG is not set | 1259 | # CONFIG_IOMMU_DEBUG is not set |
1192 | CONFIG_KPROBES=y | 1260 | CONFIG_KPROBES=y |
diff --git a/arch/x86_64/ia32/ia32_aout.c b/arch/x86_64/ia32/ia32_aout.c index 93c60f4aa47a..3bf58af98936 100644 --- a/arch/x86_64/ia32/ia32_aout.c +++ b/arch/x86_64/ia32/ia32_aout.c | |||
@@ -36,9 +36,6 @@ | |||
36 | #undef WARN_OLD | 36 | #undef WARN_OLD |
37 | #undef CORE_DUMP /* probably broken */ | 37 | #undef CORE_DUMP /* probably broken */ |
38 | 38 | ||
39 | extern int ia32_setup_arg_pages(struct linux_binprm *bprm, | ||
40 | unsigned long stack_top, int exec_stack); | ||
41 | |||
42 | static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs); | 39 | static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs); |
43 | static int load_aout_library(struct file*); | 40 | static int load_aout_library(struct file*); |
44 | 41 | ||
diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c index d9161e395978..830feb272eca 100644 --- a/arch/x86_64/ia32/ia32_binfmt.c +++ b/arch/x86_64/ia32/ia32_binfmt.c | |||
@@ -335,7 +335,8 @@ static void elf32_init(struct pt_regs *regs) | |||
335 | me->thread.es = __USER_DS; | 335 | me->thread.es = __USER_DS; |
336 | } | 336 | } |
337 | 337 | ||
338 | int setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top, int executable_stack) | 338 | int ia32_setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top, |
339 | int executable_stack) | ||
339 | { | 340 | { |
340 | unsigned long stack_base; | 341 | unsigned long stack_base; |
341 | struct vm_area_struct *mpnt; | 342 | struct vm_area_struct *mpnt; |
@@ -389,6 +390,7 @@ int setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top, int exec | |||
389 | 390 | ||
390 | return 0; | 391 | return 0; |
391 | } | 392 | } |
393 | EXPORT_SYMBOL(ia32_setup_arg_pages); | ||
392 | 394 | ||
393 | static unsigned long | 395 | static unsigned long |
394 | elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type) | 396 | elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type) |
diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile index 14328cab5d3a..fe4cbd1c4b2f 100644 --- a/arch/x86_64/kernel/Makefile +++ b/arch/x86_64/kernel/Makefile | |||
@@ -11,6 +11,7 @@ obj-y := process.o signal.o entry.o traps.o irq.o \ | |||
11 | 11 | ||
12 | obj-$(CONFIG_X86_MCE) += mce.o | 12 | obj-$(CONFIG_X86_MCE) += mce.o |
13 | obj-$(CONFIG_X86_MCE_INTEL) += mce_intel.o | 13 | obj-$(CONFIG_X86_MCE_INTEL) += mce_intel.o |
14 | obj-$(CONFIG_X86_MCE_AMD) += mce_amd.o | ||
14 | obj-$(CONFIG_MTRR) += ../../i386/kernel/cpu/mtrr/ | 15 | obj-$(CONFIG_MTRR) += ../../i386/kernel/cpu/mtrr/ |
15 | obj-$(CONFIG_ACPI) += acpi/ | 16 | obj-$(CONFIG_ACPI) += acpi/ |
16 | obj-$(CONFIG_X86_MSR) += msr.o | 17 | obj-$(CONFIG_X86_MSR) += msr.o |
diff --git a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c index 962ad4823b6a..c7f4fdd20f05 100644 --- a/arch/x86_64/kernel/aperture.c +++ b/arch/x86_64/kernel/aperture.c | |||
@@ -196,7 +196,7 @@ static __u32 __init search_agp_bridge(u32 *order, int *valid_agp) | |||
196 | void __init iommu_hole_init(void) | 196 | void __init iommu_hole_init(void) |
197 | { | 197 | { |
198 | int fix, num; | 198 | int fix, num; |
199 | u32 aper_size, aper_alloc = 0, aper_order, last_aper_order = 0; | 199 | u32 aper_size, aper_alloc = 0, aper_order = 0, last_aper_order = 0; |
200 | u64 aper_base, last_aper_base = 0; | 200 | u64 aper_base, last_aper_base = 0; |
201 | int valid_agp = 0; | 201 | int valid_agp = 0; |
202 | 202 | ||
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c index b6e7715d877f..18691ce4c759 100644 --- a/arch/x86_64/kernel/apic.c +++ b/arch/x86_64/kernel/apic.c | |||
@@ -833,6 +833,16 @@ int setup_profiling_timer(unsigned int multiplier) | |||
833 | return 0; | 833 | return 0; |
834 | } | 834 | } |
835 | 835 | ||
836 | #ifdef CONFIG_X86_MCE_AMD | ||
837 | void setup_threshold_lvt(unsigned long lvt_off) | ||
838 | { | ||
839 | unsigned int v = 0; | ||
840 | unsigned long reg = (lvt_off << 4) + 0x500; | ||
841 | v |= THRESHOLD_APIC_VECTOR; | ||
842 | apic_write(reg, v); | ||
843 | } | ||
844 | #endif /* CONFIG_X86_MCE_AMD */ | ||
845 | |||
836 | #undef APIC_DIVISOR | 846 | #undef APIC_DIVISOR |
837 | 847 | ||
838 | /* | 848 | /* |
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c index ab3f87aaff70..17579a1a174b 100644 --- a/arch/x86_64/kernel/e820.c +++ b/arch/x86_64/kernel/e820.c | |||
@@ -23,8 +23,7 @@ | |||
23 | #include <asm/e820.h> | 23 | #include <asm/e820.h> |
24 | #include <asm/proto.h> | 24 | #include <asm/proto.h> |
25 | #include <asm/bootsetup.h> | 25 | #include <asm/bootsetup.h> |
26 | 26 | #include <asm/sections.h> | |
27 | extern char _end[]; | ||
28 | 27 | ||
29 | /* | 28 | /* |
30 | * PFN of last memory page. | 29 | * PFN of last memory page. |
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S index 7937971d1853..9ff42041bb6b 100644 --- a/arch/x86_64/kernel/entry.S +++ b/arch/x86_64/kernel/entry.S | |||
@@ -612,6 +612,9 @@ retint_kernel: | |||
612 | ENTRY(thermal_interrupt) | 612 | ENTRY(thermal_interrupt) |
613 | apicinterrupt THERMAL_APIC_VECTOR,smp_thermal_interrupt | 613 | apicinterrupt THERMAL_APIC_VECTOR,smp_thermal_interrupt |
614 | 614 | ||
615 | ENTRY(threshold_interrupt) | ||
616 | apicinterrupt THRESHOLD_APIC_VECTOR,mce_threshold_interrupt | ||
617 | |||
615 | #ifdef CONFIG_SMP | 618 | #ifdef CONFIG_SMP |
616 | ENTRY(reschedule_interrupt) | 619 | ENTRY(reschedule_interrupt) |
617 | apicinterrupt RESCHEDULE_VECTOR,smp_reschedule_interrupt | 620 | apicinterrupt RESCHEDULE_VECTOR,smp_reschedule_interrupt |
diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S index b92e5f45ed46..15290968e49d 100644 --- a/arch/x86_64/kernel/head.S +++ b/arch/x86_64/kernel/head.S | |||
@@ -12,6 +12,7 @@ | |||
12 | 12 | ||
13 | #include <linux/linkage.h> | 13 | #include <linux/linkage.h> |
14 | #include <linux/threads.h> | 14 | #include <linux/threads.h> |
15 | #include <linux/init.h> | ||
15 | #include <asm/desc.h> | 16 | #include <asm/desc.h> |
16 | #include <asm/segment.h> | 17 | #include <asm/segment.h> |
17 | #include <asm/page.h> | 18 | #include <asm/page.h> |
@@ -70,7 +71,7 @@ startup_32: | |||
70 | movl %eax, %cr4 | 71 | movl %eax, %cr4 |
71 | 72 | ||
72 | /* Setup early boot stage 4 level pagetables */ | 73 | /* Setup early boot stage 4 level pagetables */ |
73 | movl $(init_level4_pgt - __START_KERNEL_map), %eax | 74 | movl $(boot_level4_pgt - __START_KERNEL_map), %eax |
74 | movl %eax, %cr3 | 75 | movl %eax, %cr3 |
75 | 76 | ||
76 | /* Setup EFER (Extended Feature Enable Register) */ | 77 | /* Setup EFER (Extended Feature Enable Register) */ |
@@ -113,7 +114,7 @@ startup_64: | |||
113 | movq %rax, %cr4 | 114 | movq %rax, %cr4 |
114 | 115 | ||
115 | /* Setup early boot stage 4 level pagetables. */ | 116 | /* Setup early boot stage 4 level pagetables. */ |
116 | movq $(init_level4_pgt - __START_KERNEL_map), %rax | 117 | movq $(boot_level4_pgt - __START_KERNEL_map), %rax |
117 | movq %rax, %cr3 | 118 | movq %rax, %cr3 |
118 | 119 | ||
119 | /* Check if nx is implemented */ | 120 | /* Check if nx is implemented */ |
@@ -240,20 +241,10 @@ ljumpvector: | |||
240 | ENTRY(stext) | 241 | ENTRY(stext) |
241 | ENTRY(_stext) | 242 | ENTRY(_stext) |
242 | 243 | ||
243 | /* | ||
244 | * This default setting generates an ident mapping at address 0x100000 | ||
245 | * and a mapping for the kernel that precisely maps virtual address | ||
246 | * 0xffffffff80000000 to physical address 0x000000. (always using | ||
247 | * 2Mbyte large pages provided by PAE mode) | ||
248 | */ | ||
249 | .org 0x1000 | 244 | .org 0x1000 |
250 | ENTRY(init_level4_pgt) | 245 | ENTRY(init_level4_pgt) |
251 | .quad 0x0000000000002007 + __PHYSICAL_START /* -> level3_ident_pgt */ | 246 | /* This gets initialized in x86_64_start_kernel */ |
252 | .fill 255,8,0 | 247 | .fill 512,8,0 |
253 | .quad 0x000000000000a007 + __PHYSICAL_START | ||
254 | .fill 254,8,0 | ||
255 | /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */ | ||
256 | .quad 0x0000000000003007 + __PHYSICAL_START /* -> level3_kernel_pgt */ | ||
257 | 248 | ||
258 | .org 0x2000 | 249 | .org 0x2000 |
259 | ENTRY(level3_ident_pgt) | 250 | ENTRY(level3_ident_pgt) |
@@ -350,6 +341,24 @@ ENTRY(wakeup_level4_pgt) | |||
350 | .quad 0x0000000000003007 + __PHYSICAL_START /* -> level3_kernel_pgt */ | 341 | .quad 0x0000000000003007 + __PHYSICAL_START /* -> level3_kernel_pgt */ |
351 | #endif | 342 | #endif |
352 | 343 | ||
344 | #ifndef CONFIG_HOTPLUG_CPU | ||
345 | __INITDATA | ||
346 | #endif | ||
347 | /* | ||
348 | * This default setting generates an ident mapping at address 0x100000 | ||
349 | * and a mapping for the kernel that precisely maps virtual address | ||
350 | * 0xffffffff80000000 to physical address 0x000000. (always using | ||
351 | * 2Mbyte large pages provided by PAE mode) | ||
352 | */ | ||
353 | .align PAGE_SIZE | ||
354 | ENTRY(boot_level4_pgt) | ||
355 | .quad 0x0000000000002007 + __PHYSICAL_START /* -> level3_ident_pgt */ | ||
356 | .fill 255,8,0 | ||
357 | .quad 0x000000000000a007 + __PHYSICAL_START | ||
358 | .fill 254,8,0 | ||
359 | /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */ | ||
360 | .quad 0x0000000000003007 + __PHYSICAL_START /* -> level3_kernel_pgt */ | ||
361 | |||
353 | .data | 362 | .data |
354 | 363 | ||
355 | .align 16 | 364 | .align 16 |
diff --git a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c index cf6ab147a2a5..b675c5add01e 100644 --- a/arch/x86_64/kernel/head64.c +++ b/arch/x86_64/kernel/head64.c | |||
@@ -19,14 +19,15 @@ | |||
19 | #include <asm/bootsetup.h> | 19 | #include <asm/bootsetup.h> |
20 | #include <asm/setup.h> | 20 | #include <asm/setup.h> |
21 | #include <asm/desc.h> | 21 | #include <asm/desc.h> |
22 | #include <asm/pgtable.h> | ||
23 | #include <asm/sections.h> | ||
22 | 24 | ||
23 | /* Don't add a printk in there. printk relies on the PDA which is not initialized | 25 | /* Don't add a printk in there. printk relies on the PDA which is not initialized |
24 | yet. */ | 26 | yet. */ |
25 | static void __init clear_bss(void) | 27 | static void __init clear_bss(void) |
26 | { | 28 | { |
27 | extern char __bss_start[], __bss_end[]; | ||
28 | memset(__bss_start, 0, | 29 | memset(__bss_start, 0, |
29 | (unsigned long) __bss_end - (unsigned long) __bss_start); | 30 | (unsigned long) __bss_stop - (unsigned long) __bss_start); |
30 | } | 31 | } |
31 | 32 | ||
32 | #define NEW_CL_POINTER 0x228 /* Relative to real mode data */ | 33 | #define NEW_CL_POINTER 0x228 /* Relative to real mode data */ |
@@ -75,8 +76,6 @@ static void __init setup_boot_cpu_data(void) | |||
75 | boot_cpu_data.x86_mask = eax & 0xf; | 76 | boot_cpu_data.x86_mask = eax & 0xf; |
76 | } | 77 | } |
77 | 78 | ||
78 | extern char _end[]; | ||
79 | |||
80 | void __init x86_64_start_kernel(char * real_mode_data) | 79 | void __init x86_64_start_kernel(char * real_mode_data) |
81 | { | 80 | { |
82 | char *s; | 81 | char *s; |
@@ -86,6 +85,13 @@ void __init x86_64_start_kernel(char * real_mode_data) | |||
86 | set_intr_gate(i, early_idt_handler); | 85 | set_intr_gate(i, early_idt_handler); |
87 | asm volatile("lidt %0" :: "m" (idt_descr)); | 86 | asm volatile("lidt %0" :: "m" (idt_descr)); |
88 | clear_bss(); | 87 | clear_bss(); |
88 | |||
89 | /* | ||
90 | * switch to init_level4_pgt from boot_level4_pgt | ||
91 | */ | ||
92 | memcpy(init_level4_pgt, boot_level4_pgt, PTRS_PER_PGD*sizeof(pgd_t)); | ||
93 | asm volatile("movq %0,%%cr3" :: "r" (__pa_symbol(&init_level4_pgt))); | ||
94 | |||
89 | pda_init(0); | 95 | pda_init(0); |
90 | copy_bootdata(real_mode_data); | 96 | copy_bootdata(real_mode_data); |
91 | #ifdef CONFIG_SMP | 97 | #ifdef CONFIG_SMP |
diff --git a/arch/x86_64/kernel/i8259.c b/arch/x86_64/kernel/i8259.c index c6c9791d77c1..6e5101ad3d1a 100644 --- a/arch/x86_64/kernel/i8259.c +++ b/arch/x86_64/kernel/i8259.c | |||
@@ -492,6 +492,7 @@ void invalidate_interrupt5(void); | |||
492 | void invalidate_interrupt6(void); | 492 | void invalidate_interrupt6(void); |
493 | void invalidate_interrupt7(void); | 493 | void invalidate_interrupt7(void); |
494 | void thermal_interrupt(void); | 494 | void thermal_interrupt(void); |
495 | void threshold_interrupt(void); | ||
495 | void i8254_timer_resume(void); | 496 | void i8254_timer_resume(void); |
496 | 497 | ||
497 | static void setup_timer_hardware(void) | 498 | static void setup_timer_hardware(void) |
@@ -515,7 +516,7 @@ void i8254_timer_resume(void) | |||
515 | } | 516 | } |
516 | 517 | ||
517 | static struct sysdev_class timer_sysclass = { | 518 | static struct sysdev_class timer_sysclass = { |
518 | set_kset_name("timer"), | 519 | set_kset_name("timer_pit"), |
519 | .resume = timer_resume, | 520 | .resume = timer_resume, |
520 | }; | 521 | }; |
521 | 522 | ||
@@ -580,6 +581,7 @@ void __init init_IRQ(void) | |||
580 | set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt); | 581 | set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt); |
581 | #endif | 582 | #endif |
582 | set_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt); | 583 | set_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt); |
584 | set_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt); | ||
583 | 585 | ||
584 | #ifdef CONFIG_X86_LOCAL_APIC | 586 | #ifdef CONFIG_X86_LOCAL_APIC |
585 | /* self generated IPI for local APIC timer */ | 587 | /* self generated IPI for local APIC timer */ |
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index c8eee20cd519..97154ab058b4 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c | |||
@@ -57,7 +57,7 @@ int nr_ioapic_registers[MAX_IO_APICS]; | |||
57 | * Rough estimation of how many shared IRQs there are, can | 57 | * Rough estimation of how many shared IRQs there are, can |
58 | * be changed anytime. | 58 | * be changed anytime. |
59 | */ | 59 | */ |
60 | #define MAX_PLUS_SHARED_IRQS NR_IRQS | 60 | #define MAX_PLUS_SHARED_IRQS NR_IRQ_VECTORS |
61 | #define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS) | 61 | #define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS) |
62 | 62 | ||
63 | /* | 63 | /* |
@@ -85,6 +85,7 @@ int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1}; | |||
85 | int pin; \ | 85 | int pin; \ |
86 | struct irq_pin_list *entry = irq_2_pin + irq; \ | 86 | struct irq_pin_list *entry = irq_2_pin + irq; \ |
87 | \ | 87 | \ |
88 | BUG_ON(irq >= NR_IRQS); \ | ||
88 | for (;;) { \ | 89 | for (;;) { \ |
89 | unsigned int reg; \ | 90 | unsigned int reg; \ |
90 | pin = entry->pin; \ | 91 | pin = entry->pin; \ |
@@ -127,6 +128,8 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask) | |||
127 | } | 128 | } |
128 | #endif | 129 | #endif |
129 | 130 | ||
131 | static u8 gsi_2_irq[NR_IRQ_VECTORS] = { [0 ... NR_IRQ_VECTORS-1] = 0xFF }; | ||
132 | |||
130 | /* | 133 | /* |
131 | * The common case is 1:1 IRQ<->pin mappings. Sometimes there are | 134 | * The common case is 1:1 IRQ<->pin mappings. Sometimes there are |
132 | * shared ISA-space IRQs, so we have to support them. We are super | 135 | * shared ISA-space IRQs, so we have to support them. We are super |
@@ -137,6 +140,7 @@ static void add_pin_to_irq(unsigned int irq, int apic, int pin) | |||
137 | static int first_free_entry = NR_IRQS; | 140 | static int first_free_entry = NR_IRQS; |
138 | struct irq_pin_list *entry = irq_2_pin + irq; | 141 | struct irq_pin_list *entry = irq_2_pin + irq; |
139 | 142 | ||
143 | BUG_ON(irq >= NR_IRQS); | ||
140 | while (entry->next) | 144 | while (entry->next) |
141 | entry = irq_2_pin + entry->next; | 145 | entry = irq_2_pin + entry->next; |
142 | 146 | ||
@@ -144,7 +148,7 @@ static void add_pin_to_irq(unsigned int irq, int apic, int pin) | |||
144 | entry->next = first_free_entry; | 148 | entry->next = first_free_entry; |
145 | entry = irq_2_pin + entry->next; | 149 | entry = irq_2_pin + entry->next; |
146 | if (++first_free_entry >= PIN_MAP_SIZE) | 150 | if (++first_free_entry >= PIN_MAP_SIZE) |
147 | panic("io_apic.c: whoops"); | 151 | panic("io_apic.c: ran out of irq_2_pin entries!"); |
148 | } | 152 | } |
149 | entry->apic = apic; | 153 | entry->apic = apic; |
150 | entry->pin = pin; | 154 | entry->pin = pin; |
@@ -420,6 +424,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin) | |||
420 | best_guess = irq; | 424 | best_guess = irq; |
421 | } | 425 | } |
422 | } | 426 | } |
427 | BUG_ON(best_guess >= NR_IRQS); | ||
423 | return best_guess; | 428 | return best_guess; |
424 | } | 429 | } |
425 | 430 | ||
@@ -610,6 +615,64 @@ static inline int irq_trigger(int idx) | |||
610 | return MPBIOS_trigger(idx); | 615 | return MPBIOS_trigger(idx); |
611 | } | 616 | } |
612 | 617 | ||
618 | static int next_irq = 16; | ||
619 | |||
620 | /* | ||
621 | * gsi_irq_sharing -- Name overload! "irq" can be either a legacy IRQ | ||
622 | * in the range 0-15, a linux IRQ in the range 0-223, or a GSI number | ||
623 | * from ACPI, which can reach 800 in large boxen. | ||
624 | * | ||
625 | * Compact the sparse GSI space into a sequential IRQ series and reuse | ||
626 | * vectors if possible. | ||
627 | */ | ||
628 | int gsi_irq_sharing(int gsi) | ||
629 | { | ||
630 | int i, tries, vector; | ||
631 | |||
632 | BUG_ON(gsi >= NR_IRQ_VECTORS); | ||
633 | |||
634 | if (platform_legacy_irq(gsi)) | ||
635 | return gsi; | ||
636 | |||
637 | if (gsi_2_irq[gsi] != 0xFF) | ||
638 | return (int)gsi_2_irq[gsi]; | ||
639 | |||
640 | tries = NR_IRQS; | ||
641 | try_again: | ||
642 | vector = assign_irq_vector(gsi); | ||
643 | |||
644 | /* | ||
645 | * Sharing vectors means sharing IRQs, so scan irq_vectors for previous | ||
646 | * use of vector and if found, return that IRQ. However, we never want | ||
647 | * to share legacy IRQs, which usually have a different trigger mode | ||
648 | * than PCI. | ||
649 | */ | ||
650 | for (i = 0; i < NR_IRQS; i++) | ||
651 | if (IO_APIC_VECTOR(i) == vector) | ||
652 | break; | ||
653 | if (platform_legacy_irq(i)) { | ||
654 | if (--tries >= 0) { | ||
655 | IO_APIC_VECTOR(i) = 0; | ||
656 | goto try_again; | ||
657 | } | ||
658 | panic("gsi_irq_sharing: didn't find an IRQ using vector 0x%02X for GSI %d", vector, gsi); | ||
659 | } | ||
660 | if (i < NR_IRQS) { | ||
661 | gsi_2_irq[gsi] = i; | ||
662 | printk(KERN_INFO "GSI %d sharing vector 0x%02X and IRQ %d\n", | ||
663 | gsi, vector, i); | ||
664 | return i; | ||
665 | } | ||
666 | |||
667 | i = next_irq++; | ||
668 | BUG_ON(i >= NR_IRQS); | ||
669 | gsi_2_irq[gsi] = i; | ||
670 | IO_APIC_VECTOR(i) = vector; | ||
671 | printk(KERN_INFO "GSI %d assigned vector 0x%02X and IRQ %d\n", | ||
672 | gsi, vector, i); | ||
673 | return i; | ||
674 | } | ||
675 | |||
613 | static int pin_2_irq(int idx, int apic, int pin) | 676 | static int pin_2_irq(int idx, int apic, int pin) |
614 | { | 677 | { |
615 | int irq, i; | 678 | int irq, i; |
@@ -639,6 +702,7 @@ static int pin_2_irq(int idx, int apic, int pin) | |||
639 | while (i < apic) | 702 | while (i < apic) |
640 | irq += nr_ioapic_registers[i++]; | 703 | irq += nr_ioapic_registers[i++]; |
641 | irq += pin; | 704 | irq += pin; |
705 | irq = gsi_irq_sharing(irq); | ||
642 | break; | 706 | break; |
643 | } | 707 | } |
644 | default: | 708 | default: |
@@ -648,6 +712,7 @@ static int pin_2_irq(int idx, int apic, int pin) | |||
648 | break; | 712 | break; |
649 | } | 713 | } |
650 | } | 714 | } |
715 | BUG_ON(irq >= NR_IRQS); | ||
651 | 716 | ||
652 | /* | 717 | /* |
653 | * PCI IRQ command line redirection. Yes, limits are hardcoded. | 718 | * PCI IRQ command line redirection. Yes, limits are hardcoded. |
@@ -663,6 +728,7 @@ static int pin_2_irq(int idx, int apic, int pin) | |||
663 | } | 728 | } |
664 | } | 729 | } |
665 | } | 730 | } |
731 | BUG_ON(irq >= NR_IRQS); | ||
666 | return irq; | 732 | return irq; |
667 | } | 733 | } |
668 | 734 | ||
@@ -690,8 +756,8 @@ int assign_irq_vector(int irq) | |||
690 | { | 756 | { |
691 | static int current_vector = FIRST_DEVICE_VECTOR, offset = 0; | 757 | static int current_vector = FIRST_DEVICE_VECTOR, offset = 0; |
692 | 758 | ||
693 | BUG_ON(irq >= NR_IRQ_VECTORS); | 759 | BUG_ON(irq != AUTO_ASSIGN && (unsigned)irq >= NR_IRQ_VECTORS); |
694 | if (IO_APIC_VECTOR(irq) > 0) | 760 | if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) |
695 | return IO_APIC_VECTOR(irq); | 761 | return IO_APIC_VECTOR(irq); |
696 | next: | 762 | next: |
697 | current_vector += 8; | 763 | current_vector += 8; |
@@ -699,9 +765,8 @@ next: | |||
699 | goto next; | 765 | goto next; |
700 | 766 | ||
701 | if (current_vector >= FIRST_SYSTEM_VECTOR) { | 767 | if (current_vector >= FIRST_SYSTEM_VECTOR) { |
702 | offset++; | 768 | /* If we run out of vectors on large boxen, must share them. */ |
703 | if (!(offset%8)) | 769 | offset = (offset + 1) % 8; |
704 | return -ENOSPC; | ||
705 | current_vector = FIRST_DEVICE_VECTOR + offset; | 770 | current_vector = FIRST_DEVICE_VECTOR + offset; |
706 | } | 771 | } |
707 | 772 | ||
@@ -1917,6 +1982,7 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a | |||
1917 | entry.polarity = active_high_low; | 1982 | entry.polarity = active_high_low; |
1918 | entry.mask = 1; /* Disabled (masked) */ | 1983 | entry.mask = 1; /* Disabled (masked) */ |
1919 | 1984 | ||
1985 | irq = gsi_irq_sharing(irq); | ||
1920 | /* | 1986 | /* |
1921 | * IRQs < 16 are already in the irq_2_pin[] map | 1987 | * IRQs < 16 are already in the irq_2_pin[] map |
1922 | */ | 1988 | */ |
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c index 69541db5ff2c..183dc6105429 100644 --- a/arch/x86_64/kernel/mce.c +++ b/arch/x86_64/kernel/mce.c | |||
@@ -37,7 +37,7 @@ static unsigned long bank[NR_BANKS] = { [0 ... NR_BANKS-1] = ~0UL }; | |||
37 | static unsigned long console_logged; | 37 | static unsigned long console_logged; |
38 | static int notify_user; | 38 | static int notify_user; |
39 | static int rip_msr; | 39 | static int rip_msr; |
40 | static int mce_bootlog; | 40 | static int mce_bootlog = 1; |
41 | 41 | ||
42 | /* | 42 | /* |
43 | * Lockless MCE logging infrastructure. | 43 | * Lockless MCE logging infrastructure. |
@@ -347,7 +347,11 @@ static void __cpuinit mce_cpu_quirks(struct cpuinfo_x86 *c) | |||
347 | /* disable GART TBL walk error reporting, which trips off | 347 | /* disable GART TBL walk error reporting, which trips off |
348 | incorrectly with the IOMMU & 3ware & Cerberus. */ | 348 | incorrectly with the IOMMU & 3ware & Cerberus. */ |
349 | clear_bit(10, &bank[4]); | 349 | clear_bit(10, &bank[4]); |
350 | /* Lots of broken BIOS around that don't clear them | ||
351 | by default and leave crap in there. Don't log. */ | ||
352 | mce_bootlog = 0; | ||
350 | } | 353 | } |
354 | |||
351 | } | 355 | } |
352 | 356 | ||
353 | static void __cpuinit mce_cpu_features(struct cpuinfo_x86 *c) | 357 | static void __cpuinit mce_cpu_features(struct cpuinfo_x86 *c) |
@@ -356,6 +360,9 @@ static void __cpuinit mce_cpu_features(struct cpuinfo_x86 *c) | |||
356 | case X86_VENDOR_INTEL: | 360 | case X86_VENDOR_INTEL: |
357 | mce_intel_feature_init(c); | 361 | mce_intel_feature_init(c); |
358 | break; | 362 | break; |
363 | case X86_VENDOR_AMD: | ||
364 | mce_amd_feature_init(c); | ||
365 | break; | ||
359 | default: | 366 | default: |
360 | break; | 367 | break; |
361 | } | 368 | } |
@@ -495,16 +502,16 @@ static int __init mcheck_disable(char *str) | |||
495 | /* mce=off disables machine check. Note you can reenable it later | 502 | /* mce=off disables machine check. Note you can reenable it later |
496 | using sysfs. | 503 | using sysfs. |
497 | mce=TOLERANCELEVEL (number, see above) | 504 | mce=TOLERANCELEVEL (number, see above) |
498 | mce=bootlog Log MCEs from before booting. Disabled by default to work | 505 | mce=bootlog Log MCEs from before booting. Disabled by default on AMD. |
499 | around buggy BIOS that leave bogus MCEs. */ | 506 | mce=nobootlog Don't log MCEs from before booting. */ |
500 | static int __init mcheck_enable(char *str) | 507 | static int __init mcheck_enable(char *str) |
501 | { | 508 | { |
502 | if (*str == '=') | 509 | if (*str == '=') |
503 | str++; | 510 | str++; |
504 | if (!strcmp(str, "off")) | 511 | if (!strcmp(str, "off")) |
505 | mce_dont_init = 1; | 512 | mce_dont_init = 1; |
506 | else if (!strcmp(str, "bootlog")) | 513 | else if (!strcmp(str, "bootlog") || !strcmp(str,"nobootlog")) |
507 | mce_bootlog = 1; | 514 | mce_bootlog = str[0] == 'b'; |
508 | else if (isdigit(str[0])) | 515 | else if (isdigit(str[0])) |
509 | get_option(&str, &tolerant); | 516 | get_option(&str, &tolerant); |
510 | else | 517 | else |
diff --git a/arch/x86_64/kernel/mce_amd.c b/arch/x86_64/kernel/mce_amd.c new file mode 100644 index 000000000000..1f76175ace02 --- /dev/null +++ b/arch/x86_64/kernel/mce_amd.c | |||
@@ -0,0 +1,538 @@ | |||
1 | /* | ||
2 | * (c) 2005 Advanced Micro Devices, Inc. | ||
3 | * Your use of this code is subject to the terms and conditions of the | ||
4 | * GNU general public license version 2. See "COPYING" or | ||
5 | * http://www.gnu.org/licenses/gpl.html | ||
6 | * | ||
7 | * Written by Jacob Shin - AMD, Inc. | ||
8 | * | ||
9 | * Support : jacob.shin@amd.com | ||
10 | * | ||
11 | * MC4_MISC0 DRAM ECC Error Threshold available under AMD K8 Rev F. | ||
12 | * MC4_MISC0 exists per physical processor. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/cpu.h> | ||
17 | #include <linux/errno.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/kobject.h> | ||
21 | #include <linux/notifier.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/smp.h> | ||
24 | #include <linux/sysdev.h> | ||
25 | #include <linux/sysfs.h> | ||
26 | #include <asm/apic.h> | ||
27 | #include <asm/mce.h> | ||
28 | #include <asm/msr.h> | ||
29 | #include <asm/percpu.h> | ||
30 | |||
31 | #define PFX "mce_threshold: " | ||
32 | #define VERSION "version 1.00.9" | ||
33 | #define NR_BANKS 5 | ||
34 | #define THRESHOLD_MAX 0xFFF | ||
35 | #define INT_TYPE_APIC 0x00020000 | ||
36 | #define MASK_VALID_HI 0x80000000 | ||
37 | #define MASK_LVTOFF_HI 0x00F00000 | ||
38 | #define MASK_COUNT_EN_HI 0x00080000 | ||
39 | #define MASK_INT_TYPE_HI 0x00060000 | ||
40 | #define MASK_OVERFLOW_HI 0x00010000 | ||
41 | #define MASK_ERR_COUNT_HI 0x00000FFF | ||
42 | #define MASK_OVERFLOW 0x0001000000000000L | ||
43 | |||
44 | struct threshold_bank { | ||
45 | unsigned int cpu; | ||
46 | u8 bank; | ||
47 | u8 interrupt_enable; | ||
48 | u16 threshold_limit; | ||
49 | struct kobject kobj; | ||
50 | }; | ||
51 | |||
52 | static struct threshold_bank threshold_defaults = { | ||
53 | .interrupt_enable = 0, | ||
54 | .threshold_limit = THRESHOLD_MAX, | ||
55 | }; | ||
56 | |||
57 | #ifdef CONFIG_SMP | ||
58 | static unsigned char shared_bank[NR_BANKS] = { | ||
59 | 0, 0, 0, 0, 1 | ||
60 | }; | ||
61 | #endif | ||
62 | |||
63 | static DEFINE_PER_CPU(unsigned char, bank_map); /* see which banks are on */ | ||
64 | |||
65 | /* | ||
66 | * CPU Initialization | ||
67 | */ | ||
68 | |||
69 | /* must be called with correct cpu affinity */ | ||
70 | static void threshold_restart_bank(struct threshold_bank *b, | ||
71 | int reset, u16 old_limit) | ||
72 | { | ||
73 | u32 mci_misc_hi, mci_misc_lo; | ||
74 | |||
75 | rdmsr(MSR_IA32_MC0_MISC + b->bank * 4, mci_misc_lo, mci_misc_hi); | ||
76 | |||
77 | if (b->threshold_limit < (mci_misc_hi & THRESHOLD_MAX)) | ||
78 | reset = 1; /* limit cannot be lower than err count */ | ||
79 | |||
80 | if (reset) { /* reset err count and overflow bit */ | ||
81 | mci_misc_hi = | ||
82 | (mci_misc_hi & ~(MASK_ERR_COUNT_HI | MASK_OVERFLOW_HI)) | | ||
83 | (THRESHOLD_MAX - b->threshold_limit); | ||
84 | } else if (old_limit) { /* change limit w/o reset */ | ||
85 | int new_count = (mci_misc_hi & THRESHOLD_MAX) + | ||
86 | (old_limit - b->threshold_limit); | ||
87 | mci_misc_hi = (mci_misc_hi & ~MASK_ERR_COUNT_HI) | | ||
88 | (new_count & THRESHOLD_MAX); | ||
89 | } | ||
90 | |||
91 | b->interrupt_enable ? | ||
92 | (mci_misc_hi = (mci_misc_hi & ~MASK_INT_TYPE_HI) | INT_TYPE_APIC) : | ||
93 | (mci_misc_hi &= ~MASK_INT_TYPE_HI); | ||
94 | |||
95 | mci_misc_hi |= MASK_COUNT_EN_HI; | ||
96 | wrmsr(MSR_IA32_MC0_MISC + b->bank * 4, mci_misc_lo, mci_misc_hi); | ||
97 | } | ||
98 | |||
99 | void __cpuinit mce_amd_feature_init(struct cpuinfo_x86 *c) | ||
100 | { | ||
101 | int bank; | ||
102 | u32 mci_misc_lo, mci_misc_hi; | ||
103 | unsigned int cpu = smp_processor_id(); | ||
104 | |||
105 | for (bank = 0; bank < NR_BANKS; ++bank) { | ||
106 | rdmsr(MSR_IA32_MC0_MISC + bank * 4, mci_misc_lo, mci_misc_hi); | ||
107 | |||
108 | /* !valid, !counter present, bios locked */ | ||
109 | if (!(mci_misc_hi & MASK_VALID_HI) || | ||
110 | !(mci_misc_hi & MASK_VALID_HI >> 1) || | ||
111 | (mci_misc_hi & MASK_VALID_HI >> 2)) | ||
112 | continue; | ||
113 | |||
114 | per_cpu(bank_map, cpu) |= (1 << bank); | ||
115 | |||
116 | #ifdef CONFIG_SMP | ||
117 | if (shared_bank[bank] && cpu_core_id[cpu]) | ||
118 | continue; | ||
119 | #endif | ||
120 | |||
121 | setup_threshold_lvt((mci_misc_hi & MASK_LVTOFF_HI) >> 20); | ||
122 | threshold_defaults.cpu = cpu; | ||
123 | threshold_defaults.bank = bank; | ||
124 | threshold_restart_bank(&threshold_defaults, 0, 0); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | /* | ||
129 | * APIC Interrupt Handler | ||
130 | */ | ||
131 | |||
132 | /* | ||
133 | * threshold interrupt handler will service THRESHOLD_APIC_VECTOR. | ||
134 | * the interrupt goes off when error_count reaches threshold_limit. | ||
135 | * the handler will simply log mcelog w/ software defined bank number. | ||
136 | */ | ||
137 | asmlinkage void mce_threshold_interrupt(void) | ||
138 | { | ||
139 | int bank; | ||
140 | struct mce m; | ||
141 | |||
142 | ack_APIC_irq(); | ||
143 | irq_enter(); | ||
144 | |||
145 | memset(&m, 0, sizeof(m)); | ||
146 | rdtscll(m.tsc); | ||
147 | m.cpu = smp_processor_id(); | ||
148 | |||
149 | /* assume first bank caused it */ | ||
150 | for (bank = 0; bank < NR_BANKS; ++bank) { | ||
151 | m.bank = MCE_THRESHOLD_BASE + bank; | ||
152 | rdmsrl(MSR_IA32_MC0_MISC + bank * 4, m.misc); | ||
153 | |||
154 | if (m.misc & MASK_OVERFLOW) { | ||
155 | mce_log(&m); | ||
156 | goto out; | ||
157 | } | ||
158 | } | ||
159 | out: | ||
160 | irq_exit(); | ||
161 | } | ||
162 | |||
163 | /* | ||
164 | * Sysfs Interface | ||
165 | */ | ||
166 | |||
167 | static struct sysdev_class threshold_sysclass = { | ||
168 | set_kset_name("threshold"), | ||
169 | }; | ||
170 | |||
171 | static DEFINE_PER_CPU(struct sys_device, device_threshold); | ||
172 | |||
173 | struct threshold_attr { | ||
174 | struct attribute attr; | ||
175 | ssize_t(*show) (struct threshold_bank *, char *); | ||
176 | ssize_t(*store) (struct threshold_bank *, const char *, size_t count); | ||
177 | }; | ||
178 | |||
179 | static DEFINE_PER_CPU(struct threshold_bank *, threshold_banks[NR_BANKS]); | ||
180 | |||
181 | static cpumask_t affinity_set(unsigned int cpu) | ||
182 | { | ||
183 | cpumask_t oldmask = current->cpus_allowed; | ||
184 | cpumask_t newmask = CPU_MASK_NONE; | ||
185 | cpu_set(cpu, newmask); | ||
186 | set_cpus_allowed(current, newmask); | ||
187 | return oldmask; | ||
188 | } | ||
189 | |||
190 | static void affinity_restore(cpumask_t oldmask) | ||
191 | { | ||
192 | set_cpus_allowed(current, oldmask); | ||
193 | } | ||
194 | |||
195 | #define SHOW_FIELDS(name) \ | ||
196 | static ssize_t show_ ## name(struct threshold_bank * b, char *buf) \ | ||
197 | { \ | ||
198 | return sprintf(buf, "%lx\n", (unsigned long) b->name); \ | ||
199 | } | ||
200 | SHOW_FIELDS(interrupt_enable) | ||
201 | SHOW_FIELDS(threshold_limit) | ||
202 | |||
203 | static ssize_t store_interrupt_enable(struct threshold_bank *b, | ||
204 | const char *buf, size_t count) | ||
205 | { | ||
206 | char *end; | ||
207 | cpumask_t oldmask; | ||
208 | unsigned long new = simple_strtoul(buf, &end, 0); | ||
209 | if (end == buf) | ||
210 | return -EINVAL; | ||
211 | b->interrupt_enable = !!new; | ||
212 | |||
213 | oldmask = affinity_set(b->cpu); | ||
214 | threshold_restart_bank(b, 0, 0); | ||
215 | affinity_restore(oldmask); | ||
216 | |||
217 | return end - buf; | ||
218 | } | ||
219 | |||
220 | static ssize_t store_threshold_limit(struct threshold_bank *b, | ||
221 | const char *buf, size_t count) | ||
222 | { | ||
223 | char *end; | ||
224 | cpumask_t oldmask; | ||
225 | u16 old; | ||
226 | unsigned long new = simple_strtoul(buf, &end, 0); | ||
227 | if (end == buf) | ||
228 | return -EINVAL; | ||
229 | if (new > THRESHOLD_MAX) | ||
230 | new = THRESHOLD_MAX; | ||
231 | if (new < 1) | ||
232 | new = 1; | ||
233 | old = b->threshold_limit; | ||
234 | b->threshold_limit = new; | ||
235 | |||
236 | oldmask = affinity_set(b->cpu); | ||
237 | threshold_restart_bank(b, 0, old); | ||
238 | affinity_restore(oldmask); | ||
239 | |||
240 | return end - buf; | ||
241 | } | ||
242 | |||
243 | static ssize_t show_error_count(struct threshold_bank *b, char *buf) | ||
244 | { | ||
245 | u32 high, low; | ||
246 | cpumask_t oldmask; | ||
247 | oldmask = affinity_set(b->cpu); | ||
248 | rdmsr(MSR_IA32_MC0_MISC + b->bank * 4, low, high); /* ignore low 32 */ | ||
249 | affinity_restore(oldmask); | ||
250 | return sprintf(buf, "%x\n", | ||
251 | (high & 0xFFF) - (THRESHOLD_MAX - b->threshold_limit)); | ||
252 | } | ||
253 | |||
254 | static ssize_t store_error_count(struct threshold_bank *b, | ||
255 | const char *buf, size_t count) | ||
256 | { | ||
257 | cpumask_t oldmask; | ||
258 | oldmask = affinity_set(b->cpu); | ||
259 | threshold_restart_bank(b, 1, 0); | ||
260 | affinity_restore(oldmask); | ||
261 | return 1; | ||
262 | } | ||
263 | |||
264 | #define THRESHOLD_ATTR(_name,_mode,_show,_store) { \ | ||
265 | .attr = {.name = __stringify(_name), .mode = _mode }, \ | ||
266 | .show = _show, \ | ||
267 | .store = _store, \ | ||
268 | }; | ||
269 | |||
270 | #define ATTR_FIELDS(name) \ | ||
271 | static struct threshold_attr name = \ | ||
272 | THRESHOLD_ATTR(name, 0644, show_## name, store_## name) | ||
273 | |||
274 | ATTR_FIELDS(interrupt_enable); | ||
275 | ATTR_FIELDS(threshold_limit); | ||
276 | ATTR_FIELDS(error_count); | ||
277 | |||
278 | static struct attribute *default_attrs[] = { | ||
279 | &interrupt_enable.attr, | ||
280 | &threshold_limit.attr, | ||
281 | &error_count.attr, | ||
282 | NULL | ||
283 | }; | ||
284 | |||
285 | #define to_bank(k) container_of(k,struct threshold_bank,kobj) | ||
286 | #define to_attr(a) container_of(a,struct threshold_attr,attr) | ||
287 | |||
288 | static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf) | ||
289 | { | ||
290 | struct threshold_bank *b = to_bank(kobj); | ||
291 | struct threshold_attr *a = to_attr(attr); | ||
292 | ssize_t ret; | ||
293 | ret = a->show ? a->show(b, buf) : -EIO; | ||
294 | return ret; | ||
295 | } | ||
296 | |||
297 | static ssize_t store(struct kobject *kobj, struct attribute *attr, | ||
298 | const char *buf, size_t count) | ||
299 | { | ||
300 | struct threshold_bank *b = to_bank(kobj); | ||
301 | struct threshold_attr *a = to_attr(attr); | ||
302 | ssize_t ret; | ||
303 | ret = a->store ? a->store(b, buf, count) : -EIO; | ||
304 | return ret; | ||
305 | } | ||
306 | |||
307 | static struct sysfs_ops threshold_ops = { | ||
308 | .show = show, | ||
309 | .store = store, | ||
310 | }; | ||
311 | |||
312 | static struct kobj_type threshold_ktype = { | ||
313 | .sysfs_ops = &threshold_ops, | ||
314 | .default_attrs = default_attrs, | ||
315 | }; | ||
316 | |||
317 | /* symlinks sibling shared banks to first core. first core owns dir/files. */ | ||
318 | static __cpuinit int threshold_create_bank(unsigned int cpu, int bank) | ||
319 | { | ||
320 | int err = 0; | ||
321 | struct threshold_bank *b = 0; | ||
322 | |||
323 | #ifdef CONFIG_SMP | ||
324 | if (cpu_core_id[cpu] && shared_bank[bank]) { /* symlink */ | ||
325 | char name[16]; | ||
326 | unsigned lcpu = first_cpu(cpu_core_map[cpu]); | ||
327 | if (cpu_core_id[lcpu]) | ||
328 | goto out; /* first core not up yet */ | ||
329 | |||
330 | b = per_cpu(threshold_banks, lcpu)[bank]; | ||
331 | if (!b) | ||
332 | goto out; | ||
333 | sprintf(name, "bank%i", bank); | ||
334 | err = sysfs_create_link(&per_cpu(device_threshold, cpu).kobj, | ||
335 | &b->kobj, name); | ||
336 | if (err) | ||
337 | goto out; | ||
338 | per_cpu(threshold_banks, cpu)[bank] = b; | ||
339 | goto out; | ||
340 | } | ||
341 | #endif | ||
342 | |||
343 | b = kmalloc(sizeof(struct threshold_bank), GFP_KERNEL); | ||
344 | if (!b) { | ||
345 | err = -ENOMEM; | ||
346 | goto out; | ||
347 | } | ||
348 | memset(b, 0, sizeof(struct threshold_bank)); | ||
349 | |||
350 | b->cpu = cpu; | ||
351 | b->bank = bank; | ||
352 | b->interrupt_enable = 0; | ||
353 | b->threshold_limit = THRESHOLD_MAX; | ||
354 | kobject_set_name(&b->kobj, "bank%i", bank); | ||
355 | b->kobj.parent = &per_cpu(device_threshold, cpu).kobj; | ||
356 | b->kobj.ktype = &threshold_ktype; | ||
357 | |||
358 | err = kobject_register(&b->kobj); | ||
359 | if (err) { | ||
360 | kfree(b); | ||
361 | goto out; | ||
362 | } | ||
363 | per_cpu(threshold_banks, cpu)[bank] = b; | ||
364 | out: | ||
365 | return err; | ||
366 | } | ||
367 | |||
368 | /* create dir/files for all valid threshold banks */ | ||
369 | static __cpuinit int threshold_create_device(unsigned int cpu) | ||
370 | { | ||
371 | int bank; | ||
372 | int err = 0; | ||
373 | |||
374 | per_cpu(device_threshold, cpu).id = cpu; | ||
375 | per_cpu(device_threshold, cpu).cls = &threshold_sysclass; | ||
376 | err = sysdev_register(&per_cpu(device_threshold, cpu)); | ||
377 | if (err) | ||
378 | goto out; | ||
379 | |||
380 | for (bank = 0; bank < NR_BANKS; ++bank) { | ||
381 | if (!(per_cpu(bank_map, cpu) & 1 << bank)) | ||
382 | continue; | ||
383 | err = threshold_create_bank(cpu, bank); | ||
384 | if (err) | ||
385 | goto out; | ||
386 | } | ||
387 | out: | ||
388 | return err; | ||
389 | } | ||
390 | |||
391 | #ifdef CONFIG_HOTPLUG_CPU | ||
392 | /* | ||
393 | * let's be hotplug friendly. | ||
394 | * in case of multiple core processors, the first core always takes ownership | ||
395 | * of shared sysfs dir/files, and rest of the cores will be symlinked to it. | ||
396 | */ | ||
397 | |||
398 | /* cpu hotplug call removes all symlinks before first core dies */ | ||
399 | static __cpuinit void threshold_remove_bank(unsigned int cpu, int bank) | ||
400 | { | ||
401 | struct threshold_bank *b; | ||
402 | char name[16]; | ||
403 | |||
404 | b = per_cpu(threshold_banks, cpu)[bank]; | ||
405 | if (!b) | ||
406 | return; | ||
407 | if (shared_bank[bank] && atomic_read(&b->kobj.kref.refcount) > 2) { | ||
408 | sprintf(name, "bank%i", bank); | ||
409 | sysfs_remove_link(&per_cpu(device_threshold, cpu).kobj, name); | ||
410 | per_cpu(threshold_banks, cpu)[bank] = 0; | ||
411 | } else { | ||
412 | kobject_unregister(&b->kobj); | ||
413 | kfree(per_cpu(threshold_banks, cpu)[bank]); | ||
414 | } | ||
415 | } | ||
416 | |||
417 | static __cpuinit void threshold_remove_device(unsigned int cpu) | ||
418 | { | ||
419 | int bank; | ||
420 | |||
421 | for (bank = 0; bank < NR_BANKS; ++bank) { | ||
422 | if (!(per_cpu(bank_map, cpu) & 1 << bank)) | ||
423 | continue; | ||
424 | threshold_remove_bank(cpu, bank); | ||
425 | } | ||
426 | sysdev_unregister(&per_cpu(device_threshold, cpu)); | ||
427 | } | ||
428 | |||
429 | /* link all existing siblings when first core comes up */ | ||
430 | static __cpuinit int threshold_create_symlinks(unsigned int cpu) | ||
431 | { | ||
432 | int bank, err = 0; | ||
433 | unsigned int lcpu = 0; | ||
434 | |||
435 | if (cpu_core_id[cpu]) | ||
436 | return 0; | ||
437 | for_each_cpu_mask(lcpu, cpu_core_map[cpu]) { | ||
438 | if (lcpu == cpu) | ||
439 | continue; | ||
440 | for (bank = 0; bank < NR_BANKS; ++bank) { | ||
441 | if (!(per_cpu(bank_map, cpu) & 1 << bank)) | ||
442 | continue; | ||
443 | if (!shared_bank[bank]) | ||
444 | continue; | ||
445 | err = threshold_create_bank(lcpu, bank); | ||
446 | } | ||
447 | } | ||
448 | return err; | ||
449 | } | ||
450 | |||
451 | /* remove all symlinks before first core dies. */ | ||
452 | static __cpuinit void threshold_remove_symlinks(unsigned int cpu) | ||
453 | { | ||
454 | int bank; | ||
455 | unsigned int lcpu = 0; | ||
456 | if (cpu_core_id[cpu]) | ||
457 | return; | ||
458 | for_each_cpu_mask(lcpu, cpu_core_map[cpu]) { | ||
459 | if (lcpu == cpu) | ||
460 | continue; | ||
461 | for (bank = 0; bank < NR_BANKS; ++bank) { | ||
462 | if (!(per_cpu(bank_map, cpu) & 1 << bank)) | ||
463 | continue; | ||
464 | if (!shared_bank[bank]) | ||
465 | continue; | ||
466 | threshold_remove_bank(lcpu, bank); | ||
467 | } | ||
468 | } | ||
469 | } | ||
470 | #else /* !CONFIG_HOTPLUG_CPU */ | ||
471 | static __cpuinit void threshold_create_symlinks(unsigned int cpu) | ||
472 | { | ||
473 | } | ||
474 | static __cpuinit void threshold_remove_symlinks(unsigned int cpu) | ||
475 | { | ||
476 | } | ||
477 | static void threshold_remove_device(unsigned int cpu) | ||
478 | { | ||
479 | } | ||
480 | #endif | ||
481 | |||
482 | /* get notified when a cpu comes on/off */ | ||
483 | static __cpuinit int threshold_cpu_callback(struct notifier_block *nfb, | ||
484 | unsigned long action, void *hcpu) | ||
485 | { | ||
486 | /* cpu was unsigned int to begin with */ | ||
487 | unsigned int cpu = (unsigned long)hcpu; | ||
488 | |||
489 | if (cpu >= NR_CPUS) | ||
490 | goto out; | ||
491 | |||
492 | switch (action) { | ||
493 | case CPU_ONLINE: | ||
494 | threshold_create_device(cpu); | ||
495 | threshold_create_symlinks(cpu); | ||
496 | break; | ||
497 | case CPU_DOWN_PREPARE: | ||
498 | threshold_remove_symlinks(cpu); | ||
499 | break; | ||
500 | case CPU_DOWN_FAILED: | ||
501 | threshold_create_symlinks(cpu); | ||
502 | break; | ||
503 | case CPU_DEAD: | ||
504 | threshold_remove_device(cpu); | ||
505 | break; | ||
506 | default: | ||
507 | break; | ||
508 | } | ||
509 | out: | ||
510 | return NOTIFY_OK; | ||
511 | } | ||
512 | |||
513 | static struct notifier_block threshold_cpu_notifier = { | ||
514 | .notifier_call = threshold_cpu_callback, | ||
515 | }; | ||
516 | |||
517 | static __init int threshold_init_device(void) | ||
518 | { | ||
519 | int err; | ||
520 | int lcpu = 0; | ||
521 | |||
522 | err = sysdev_class_register(&threshold_sysclass); | ||
523 | if (err) | ||
524 | goto out; | ||
525 | |||
526 | /* to hit CPUs online before the notifier is up */ | ||
527 | for_each_online_cpu(lcpu) { | ||
528 | err = threshold_create_device(lcpu); | ||
529 | if (err) | ||
530 | goto out; | ||
531 | } | ||
532 | register_cpu_notifier(&threshold_cpu_notifier); | ||
533 | |||
534 | out: | ||
535 | return err; | ||
536 | } | ||
537 | |||
538 | device_initcall(threshold_init_device); | ||
diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c index f16d38d09daf..1105250bf02c 100644 --- a/arch/x86_64/kernel/mpparse.c +++ b/arch/x86_64/kernel/mpparse.c | |||
@@ -42,7 +42,7 @@ int acpi_found_madt; | |||
42 | * Various Linux-internal data structures created from the | 42 | * Various Linux-internal data structures created from the |
43 | * MP-table. | 43 | * MP-table. |
44 | */ | 44 | */ |
45 | int apic_version [MAX_APICS]; | 45 | unsigned char apic_version [MAX_APICS]; |
46 | unsigned char mp_bus_id_to_type [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 }; | 46 | unsigned char mp_bus_id_to_type [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 }; |
47 | int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 }; | 47 | int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 }; |
48 | 48 | ||
@@ -65,7 +65,9 @@ unsigned long mp_lapic_addr = 0; | |||
65 | /* Processor that is doing the boot up */ | 65 | /* Processor that is doing the boot up */ |
66 | unsigned int boot_cpu_id = -1U; | 66 | unsigned int boot_cpu_id = -1U; |
67 | /* Internal processor count */ | 67 | /* Internal processor count */ |
68 | static unsigned int num_processors = 0; | 68 | unsigned int num_processors __initdata = 0; |
69 | |||
70 | unsigned disabled_cpus __initdata; | ||
69 | 71 | ||
70 | /* Bitmask of physically existing CPUs */ | 72 | /* Bitmask of physically existing CPUs */ |
71 | physid_mask_t phys_cpu_present_map = PHYSID_MASK_NONE; | 73 | physid_mask_t phys_cpu_present_map = PHYSID_MASK_NONE; |
@@ -106,11 +108,14 @@ static int __init mpf_checksum(unsigned char *mp, int len) | |||
106 | 108 | ||
107 | static void __init MP_processor_info (struct mpc_config_processor *m) | 109 | static void __init MP_processor_info (struct mpc_config_processor *m) |
108 | { | 110 | { |
109 | int ver, cpu; | 111 | int cpu; |
112 | unsigned char ver; | ||
110 | static int found_bsp=0; | 113 | static int found_bsp=0; |
111 | 114 | ||
112 | if (!(m->mpc_cpuflag & CPU_ENABLED)) | 115 | if (!(m->mpc_cpuflag & CPU_ENABLED)) { |
116 | disabled_cpus++; | ||
113 | return; | 117 | return; |
118 | } | ||
114 | 119 | ||
115 | printk(KERN_INFO "Processor #%d %d:%d APIC version %d\n", | 120 | printk(KERN_INFO "Processor #%d %d:%d APIC version %d\n", |
116 | m->mpc_apicid, | 121 | m->mpc_apicid, |
@@ -129,12 +134,14 @@ static void __init MP_processor_info (struct mpc_config_processor *m) | |||
129 | } | 134 | } |
130 | 135 | ||
131 | cpu = num_processors++; | 136 | cpu = num_processors++; |
132 | 137 | ||
133 | if (m->mpc_apicid > MAX_APICS) { | 138 | #if MAX_APICS < 255 |
139 | if ((int)m->mpc_apicid > MAX_APICS) { | ||
134 | printk(KERN_ERR "Processor #%d INVALID. (Max ID: %d).\n", | 140 | printk(KERN_ERR "Processor #%d INVALID. (Max ID: %d).\n", |
135 | m->mpc_apicid, MAX_APICS); | 141 | m->mpc_apicid, MAX_APICS); |
136 | return; | 142 | return; |
137 | } | 143 | } |
144 | #endif | ||
138 | ver = m->mpc_apicver; | 145 | ver = m->mpc_apicver; |
139 | 146 | ||
140 | physid_set(m->mpc_apicid, phys_cpu_present_map); | 147 | physid_set(m->mpc_apicid, phys_cpu_present_map); |
@@ -218,7 +225,7 @@ static void __init MP_intsrc_info (struct mpc_config_intsrc *m) | |||
218 | m->mpc_irqtype, m->mpc_irqflag & 3, | 225 | m->mpc_irqtype, m->mpc_irqflag & 3, |
219 | (m->mpc_irqflag >> 2) & 3, m->mpc_srcbus, | 226 | (m->mpc_irqflag >> 2) & 3, m->mpc_srcbus, |
220 | m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq); | 227 | m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq); |
221 | if (++mp_irq_entries == MAX_IRQ_SOURCES) | 228 | if (++mp_irq_entries >= MAX_IRQ_SOURCES) |
222 | panic("Max # of irq sources exceeded!!\n"); | 229 | panic("Max # of irq sources exceeded!!\n"); |
223 | } | 230 | } |
224 | 231 | ||
@@ -549,7 +556,7 @@ void __init get_smp_config (void) | |||
549 | * Read the physical hardware table. Anything here will | 556 | * Read the physical hardware table. Anything here will |
550 | * override the defaults. | 557 | * override the defaults. |
551 | */ | 558 | */ |
552 | if (!smp_read_mpc((void *)(unsigned long)mpf->mpf_physptr)) { | 559 | if (!smp_read_mpc(phys_to_virt(mpf->mpf_physptr))) { |
553 | smp_found_config = 0; | 560 | smp_found_config = 0; |
554 | printk(KERN_ERR "BIOS bug, MP table errors detected!...\n"); | 561 | printk(KERN_ERR "BIOS bug, MP table errors detected!...\n"); |
555 | printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n"); | 562 | printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n"); |
diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c index 88be97c96987..2e28e855ec3c 100644 --- a/arch/x86_64/kernel/pci-gart.c +++ b/arch/x86_64/kernel/pci-gart.c | |||
@@ -220,6 +220,12 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, | |||
220 | uses the normal dma_mask for alloc_coherent. */ | 220 | uses the normal dma_mask for alloc_coherent. */ |
221 | dma_mask &= *dev->dma_mask; | 221 | dma_mask &= *dev->dma_mask; |
222 | 222 | ||
223 | /* Why <=? Even when the mask is smaller than 4GB it is often larger | ||
224 | than 16MB and in this case we have a chance of finding fitting memory | ||
225 | in the next higher zone first. If not retry with true GFP_DMA. -AK */ | ||
226 | if (dma_mask <= 0xffffffff) | ||
227 | gfp |= GFP_DMA32; | ||
228 | |||
223 | again: | 229 | again: |
224 | memory = dma_alloc_pages(dev, gfp, get_order(size)); | 230 | memory = dma_alloc_pages(dev, gfp, get_order(size)); |
225 | if (memory == NULL) | 231 | if (memory == NULL) |
@@ -245,7 +251,7 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, | |||
245 | } | 251 | } |
246 | 252 | ||
247 | if (!(gfp & GFP_DMA)) { | 253 | if (!(gfp & GFP_DMA)) { |
248 | gfp |= GFP_DMA; | 254 | gfp = (gfp & ~GFP_DMA32) | GFP_DMA; |
249 | goto again; | 255 | goto again; |
250 | } | 256 | } |
251 | return NULL; | 257 | return NULL; |
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index 59be85d9a4bc..5afd63e8cef7 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c | |||
@@ -144,7 +144,8 @@ void cpu_idle_wait(void) | |||
144 | do { | 144 | do { |
145 | ssleep(1); | 145 | ssleep(1); |
146 | for_each_online_cpu(cpu) { | 146 | for_each_online_cpu(cpu) { |
147 | if (cpu_isset(cpu, map) && !per_cpu(cpu_idle_state, cpu)) | 147 | if (cpu_isset(cpu, map) && |
148 | !per_cpu(cpu_idle_state, cpu)) | ||
148 | cpu_clear(cpu, map); | 149 | cpu_clear(cpu, map); |
149 | } | 150 | } |
150 | cpus_and(map, map, cpu_online_map); | 151 | cpus_and(map, map, cpu_online_map); |
@@ -275,7 +276,8 @@ void __show_regs(struct pt_regs * regs) | |||
275 | system_utsname.version); | 276 | system_utsname.version); |
276 | printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->rip); | 277 | printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->rip); |
277 | printk_address(regs->rip); | 278 | printk_address(regs->rip); |
278 | printk("\nRSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, regs->rsp, regs->eflags); | 279 | printk("\nRSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, regs->rsp, |
280 | regs->eflags); | ||
279 | printk("RAX: %016lx RBX: %016lx RCX: %016lx\n", | 281 | printk("RAX: %016lx RBX: %016lx RCX: %016lx\n", |
280 | regs->rax, regs->rbx, regs->rcx); | 282 | regs->rax, regs->rbx, regs->rcx); |
281 | printk("RDX: %016lx RSI: %016lx RDI: %016lx\n", | 283 | printk("RDX: %016lx RSI: %016lx RDI: %016lx\n", |
@@ -427,15 +429,14 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, | |||
427 | struct pt_regs * childregs; | 429 | struct pt_regs * childregs; |
428 | struct task_struct *me = current; | 430 | struct task_struct *me = current; |
429 | 431 | ||
430 | childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1; | 432 | childregs = ((struct pt_regs *) |
431 | 433 | (THREAD_SIZE + (unsigned long) p->thread_info)) - 1; | |
432 | *childregs = *regs; | 434 | *childregs = *regs; |
433 | 435 | ||
434 | childregs->rax = 0; | 436 | childregs->rax = 0; |
435 | childregs->rsp = rsp; | 437 | childregs->rsp = rsp; |
436 | if (rsp == ~0UL) { | 438 | if (rsp == ~0UL) |
437 | childregs->rsp = (unsigned long)childregs; | 439 | childregs->rsp = (unsigned long)childregs; |
438 | } | ||
439 | 440 | ||
440 | p->thread.rsp = (unsigned long) childregs; | 441 | p->thread.rsp = (unsigned long) childregs; |
441 | p->thread.rsp0 = (unsigned long) (childregs+1); | 442 | p->thread.rsp0 = (unsigned long) (childregs+1); |
@@ -457,7 +458,8 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, | |||
457 | p->thread.io_bitmap_max = 0; | 458 | p->thread.io_bitmap_max = 0; |
458 | return -ENOMEM; | 459 | return -ENOMEM; |
459 | } | 460 | } |
460 | memcpy(p->thread.io_bitmap_ptr, me->thread.io_bitmap_ptr, IO_BITMAP_BYTES); | 461 | memcpy(p->thread.io_bitmap_ptr, me->thread.io_bitmap_ptr, |
462 | IO_BITMAP_BYTES); | ||
461 | } | 463 | } |
462 | 464 | ||
463 | /* | 465 | /* |
@@ -494,7 +496,8 @@ out: | |||
494 | * - fold all the options into a flag word and test it with a single test. | 496 | * - fold all the options into a flag word and test it with a single test. |
495 | * - could test fs/gs bitsliced | 497 | * - could test fs/gs bitsliced |
496 | */ | 498 | */ |
497 | struct task_struct *__switch_to(struct task_struct *prev_p, struct task_struct *next_p) | 499 | struct task_struct * |
500 | __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | ||
498 | { | 501 | { |
499 | struct thread_struct *prev = &prev_p->thread, | 502 | struct thread_struct *prev = &prev_p->thread, |
500 | *next = &next_p->thread; | 503 | *next = &next_p->thread; |
@@ -565,7 +568,8 @@ struct task_struct *__switch_to(struct task_struct *prev_p, struct task_struct * | |||
565 | prev->userrsp = read_pda(oldrsp); | 568 | prev->userrsp = read_pda(oldrsp); |
566 | write_pda(oldrsp, next->userrsp); | 569 | write_pda(oldrsp, next->userrsp); |
567 | write_pda(pcurrent, next_p); | 570 | write_pda(pcurrent, next_p); |
568 | write_pda(kernelstack, (unsigned long)next_p->thread_info + THREAD_SIZE - PDA_STACKOFFSET); | 571 | write_pda(kernelstack, |
572 | (unsigned long)next_p->thread_info + THREAD_SIZE - PDA_STACKOFFSET); | ||
569 | 573 | ||
570 | /* | 574 | /* |
571 | * Now maybe reload the debug registers | 575 | * Now maybe reload the debug registers |
@@ -646,7 +650,9 @@ asmlinkage long sys_fork(struct pt_regs *regs) | |||
646 | return do_fork(SIGCHLD, regs->rsp, regs, 0, NULL, NULL); | 650 | return do_fork(SIGCHLD, regs->rsp, regs, 0, NULL, NULL); |
647 | } | 651 | } |
648 | 652 | ||
649 | asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, void __user *parent_tid, void __user *child_tid, struct pt_regs *regs) | 653 | asmlinkage long |
654 | sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
655 | void __user *parent_tid, void __user *child_tid, struct pt_regs *regs) | ||
650 | { | 656 | { |
651 | if (!newsp) | 657 | if (!newsp) |
652 | newsp = regs->rsp; | 658 | newsp = regs->rsp; |
@@ -682,7 +688,8 @@ unsigned long get_wchan(struct task_struct *p) | |||
682 | return 0; | 688 | return 0; |
683 | fp = *(u64 *)(p->thread.rsp); | 689 | fp = *(u64 *)(p->thread.rsp); |
684 | do { | 690 | do { |
685 | if (fp < (unsigned long)stack || fp > (unsigned long)stack+THREAD_SIZE) | 691 | if (fp < (unsigned long)stack || |
692 | fp > (unsigned long)stack+THREAD_SIZE) | ||
686 | return 0; | 693 | return 0; |
687 | rip = *(u64 *)(fp+8); | 694 | rip = *(u64 *)(fp+8); |
688 | if (!in_sched_functions(rip)) | 695 | if (!in_sched_functions(rip)) |
@@ -717,8 +724,8 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) | |||
717 | task->thread.gsindex = 0; | 724 | task->thread.gsindex = 0; |
718 | task->thread.gs = addr; | 725 | task->thread.gs = addr; |
719 | if (doit) { | 726 | if (doit) { |
720 | load_gs_index(0); | 727 | load_gs_index(0); |
721 | ret = checking_wrmsrl(MSR_KERNEL_GS_BASE, addr); | 728 | ret = checking_wrmsrl(MSR_KERNEL_GS_BASE, addr); |
722 | } | 729 | } |
723 | } | 730 | } |
724 | put_cpu(); | 731 | put_cpu(); |
@@ -735,7 +742,7 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) | |||
735 | set_32bit_tls(task, FS_TLS, addr); | 742 | set_32bit_tls(task, FS_TLS, addr); |
736 | if (doit) { | 743 | if (doit) { |
737 | load_TLS(&task->thread, cpu); | 744 | load_TLS(&task->thread, cpu); |
738 | asm volatile("movl %0,%%fs" :: "r" (FS_TLS_SEL)); | 745 | asm volatile("movl %0,%%fs" :: "r"(FS_TLS_SEL)); |
739 | } | 746 | } |
740 | task->thread.fsindex = FS_TLS_SEL; | 747 | task->thread.fsindex = FS_TLS_SEL; |
741 | task->thread.fs = 0; | 748 | task->thread.fs = 0; |
@@ -745,8 +752,8 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) | |||
745 | if (doit) { | 752 | if (doit) { |
746 | /* set the selector to 0 to not confuse | 753 | /* set the selector to 0 to not confuse |
747 | __switch_to */ | 754 | __switch_to */ |
748 | asm volatile("movl %0,%%fs" :: "r" (0)); | 755 | asm volatile("movl %0,%%fs" :: "r" (0)); |
749 | ret = checking_wrmsrl(MSR_FS_BASE, addr); | 756 | ret = checking_wrmsrl(MSR_FS_BASE, addr); |
750 | } | 757 | } |
751 | } | 758 | } |
752 | put_cpu(); | 759 | put_cpu(); |
@@ -755,9 +762,9 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) | |||
755 | unsigned long base; | 762 | unsigned long base; |
756 | if (task->thread.fsindex == FS_TLS_SEL) | 763 | if (task->thread.fsindex == FS_TLS_SEL) |
757 | base = read_32bit_tls(task, FS_TLS); | 764 | base = read_32bit_tls(task, FS_TLS); |
758 | else if (doit) { | 765 | else if (doit) |
759 | rdmsrl(MSR_FS_BASE, base); | 766 | rdmsrl(MSR_FS_BASE, base); |
760 | } else | 767 | else |
761 | base = task->thread.fs; | 768 | base = task->thread.fs; |
762 | ret = put_user(base, (unsigned long __user *)addr); | 769 | ret = put_user(base, (unsigned long __user *)addr); |
763 | break; | 770 | break; |
@@ -766,9 +773,9 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) | |||
766 | unsigned long base; | 773 | unsigned long base; |
767 | if (task->thread.gsindex == GS_TLS_SEL) | 774 | if (task->thread.gsindex == GS_TLS_SEL) |
768 | base = read_32bit_tls(task, GS_TLS); | 775 | base = read_32bit_tls(task, GS_TLS); |
769 | else if (doit) { | 776 | else if (doit) |
770 | rdmsrl(MSR_KERNEL_GS_BASE, base); | 777 | rdmsrl(MSR_KERNEL_GS_BASE, base); |
771 | } else | 778 | else |
772 | base = task->thread.gs; | 779 | base = task->thread.gs; |
773 | ret = put_user(base, (unsigned long __user *)addr); | 780 | ret = put_user(base, (unsigned long __user *)addr); |
774 | break; | 781 | break; |
diff --git a/arch/x86_64/kernel/reboot.c b/arch/x86_64/kernel/reboot.c index 47f95687905f..75235ed2b31b 100644 --- a/arch/x86_64/kernel/reboot.c +++ b/arch/x86_64/kernel/reboot.c | |||
@@ -77,6 +77,7 @@ static inline void kb_wait(void) | |||
77 | 77 | ||
78 | void machine_shutdown(void) | 78 | void machine_shutdown(void) |
79 | { | 79 | { |
80 | unsigned long flags; | ||
80 | /* Stop the cpus and apics */ | 81 | /* Stop the cpus and apics */ |
81 | #ifdef CONFIG_SMP | 82 | #ifdef CONFIG_SMP |
82 | int reboot_cpu_id; | 83 | int reboot_cpu_id; |
@@ -98,7 +99,7 @@ void machine_shutdown(void) | |||
98 | smp_send_stop(); | 99 | smp_send_stop(); |
99 | #endif | 100 | #endif |
100 | 101 | ||
101 | local_irq_disable(); | 102 | local_irq_save(flags); |
102 | 103 | ||
103 | #ifndef CONFIG_SMP | 104 | #ifndef CONFIG_SMP |
104 | disable_local_APIC(); | 105 | disable_local_APIC(); |
@@ -106,7 +107,7 @@ void machine_shutdown(void) | |||
106 | 107 | ||
107 | disable_IO_APIC(); | 108 | disable_IO_APIC(); |
108 | 109 | ||
109 | local_irq_enable(); | 110 | local_irq_restore(flags); |
110 | } | 111 | } |
111 | 112 | ||
112 | void machine_emergency_restart(void) | 113 | void machine_emergency_restart(void) |
@@ -120,7 +121,7 @@ void machine_emergency_restart(void) | |||
120 | /* Could also try the reset bit in the Hammer NB */ | 121 | /* Could also try the reset bit in the Hammer NB */ |
121 | switch (reboot_type) { | 122 | switch (reboot_type) { |
122 | case BOOT_KBD: | 123 | case BOOT_KBD: |
123 | for (i=0; i<100; i++) { | 124 | for (i=0; i<10; i++) { |
124 | kb_wait(); | 125 | kb_wait(); |
125 | udelay(50); | 126 | udelay(50); |
126 | outb(0xfe,0x64); /* pulse reset low */ | 127 | outb(0xfe,0x64); /* pulse reset low */ |
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index da0bc3e7bdf5..750e01dcbdf4 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c | |||
@@ -60,6 +60,7 @@ | |||
60 | #include <asm/setup.h> | 60 | #include <asm/setup.h> |
61 | #include <asm/mach_apic.h> | 61 | #include <asm/mach_apic.h> |
62 | #include <asm/numa.h> | 62 | #include <asm/numa.h> |
63 | #include <asm/sections.h> | ||
63 | 64 | ||
64 | /* | 65 | /* |
65 | * Machine setup.. | 66 | * Machine setup.. |
@@ -103,7 +104,6 @@ struct edid_info edid_info; | |||
103 | struct e820map e820; | 104 | struct e820map e820; |
104 | 105 | ||
105 | extern int root_mountflags; | 106 | extern int root_mountflags; |
106 | extern char _text, _etext, _edata, _end; | ||
107 | 107 | ||
108 | char command_line[COMMAND_LINE_SIZE]; | 108 | char command_line[COMMAND_LINE_SIZE]; |
109 | 109 | ||
@@ -412,7 +412,6 @@ contig_initmem_init(unsigned long start_pfn, unsigned long end_pfn) | |||
412 | { | 412 | { |
413 | unsigned long bootmap_size, bootmap; | 413 | unsigned long bootmap_size, bootmap; |
414 | 414 | ||
415 | memory_present(0, start_pfn, end_pfn); | ||
416 | bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT; | 415 | bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT; |
417 | bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size); | 416 | bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size); |
418 | if (bootmap == -1L) | 417 | if (bootmap == -1L) |
@@ -571,6 +570,8 @@ void __init setup_arch(char **cmdline_p) | |||
571 | 570 | ||
572 | init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT)); | 571 | init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT)); |
573 | 572 | ||
573 | zap_low_mappings(0); | ||
574 | |||
574 | #ifdef CONFIG_ACPI | 575 | #ifdef CONFIG_ACPI |
575 | /* | 576 | /* |
576 | * Initialize the ACPI boot-time table parser (gets the RSDP and SDT). | 577 | * Initialize the ACPI boot-time table parser (gets the RSDP and SDT). |
@@ -657,8 +658,6 @@ void __init setup_arch(char **cmdline_p) | |||
657 | } | 658 | } |
658 | #endif | 659 | #endif |
659 | 660 | ||
660 | sparse_init(); | ||
661 | |||
662 | paging_init(); | 661 | paging_init(); |
663 | 662 | ||
664 | check_ioapic(); | 663 | check_ioapic(); |
@@ -793,7 +792,7 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c) | |||
793 | #endif | 792 | #endif |
794 | 793 | ||
795 | bits = 0; | 794 | bits = 0; |
796 | while ((1 << bits) < c->x86_num_cores) | 795 | while ((1 << bits) < c->x86_max_cores) |
797 | bits++; | 796 | bits++; |
798 | 797 | ||
799 | /* Low order bits define the core id (index of core in socket) */ | 798 | /* Low order bits define the core id (index of core in socket) */ |
@@ -823,10 +822,10 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c) | |||
823 | if (!node_online(node)) | 822 | if (!node_online(node)) |
824 | node = nearby_node(apicid); | 823 | node = nearby_node(apicid); |
825 | } | 824 | } |
826 | cpu_to_node[cpu] = node; | 825 | numa_set_node(cpu, node); |
827 | 826 | ||
828 | printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n", | 827 | printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n", |
829 | cpu, c->x86_num_cores, node, cpu_core_id[cpu]); | 828 | cpu, c->x86_max_cores, node, cpu_core_id[cpu]); |
830 | #endif | 829 | #endif |
831 | #endif | 830 | #endif |
832 | } | 831 | } |
@@ -875,9 +874,9 @@ static int __init init_amd(struct cpuinfo_x86 *c) | |||
875 | display_cacheinfo(c); | 874 | display_cacheinfo(c); |
876 | 875 | ||
877 | if (c->extended_cpuid_level >= 0x80000008) { | 876 | if (c->extended_cpuid_level >= 0x80000008) { |
878 | c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1; | 877 | c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1; |
879 | if (c->x86_num_cores & (c->x86_num_cores - 1)) | 878 | if (c->x86_max_cores & (c->x86_max_cores - 1)) |
880 | c->x86_num_cores = 1; | 879 | c->x86_max_cores = 1; |
881 | 880 | ||
882 | amd_detect_cmp(c); | 881 | amd_detect_cmp(c); |
883 | } | 882 | } |
@@ -889,54 +888,44 @@ static void __cpuinit detect_ht(struct cpuinfo_x86 *c) | |||
889 | { | 888 | { |
890 | #ifdef CONFIG_SMP | 889 | #ifdef CONFIG_SMP |
891 | u32 eax, ebx, ecx, edx; | 890 | u32 eax, ebx, ecx, edx; |
892 | int index_msb, tmp; | 891 | int index_msb, core_bits; |
893 | int cpu = smp_processor_id(); | 892 | int cpu = smp_processor_id(); |
894 | 893 | ||
894 | cpuid(1, &eax, &ebx, &ecx, &edx); | ||
895 | |||
896 | c->apicid = phys_pkg_id(0); | ||
897 | |||
895 | if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY)) | 898 | if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY)) |
896 | return; | 899 | return; |
897 | 900 | ||
898 | cpuid(1, &eax, &ebx, &ecx, &edx); | ||
899 | smp_num_siblings = (ebx & 0xff0000) >> 16; | 901 | smp_num_siblings = (ebx & 0xff0000) >> 16; |
900 | 902 | ||
901 | if (smp_num_siblings == 1) { | 903 | if (smp_num_siblings == 1) { |
902 | printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); | 904 | printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); |
903 | } else if (smp_num_siblings > 1) { | 905 | } else if (smp_num_siblings > 1 ) { |
904 | index_msb = 31; | 906 | |
905 | /* | ||
906 | * At this point we only support two siblings per | ||
907 | * processor package. | ||
908 | */ | ||
909 | if (smp_num_siblings > NR_CPUS) { | 907 | if (smp_num_siblings > NR_CPUS) { |
910 | printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings); | 908 | printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings); |
911 | smp_num_siblings = 1; | 909 | smp_num_siblings = 1; |
912 | return; | 910 | return; |
913 | } | 911 | } |
914 | tmp = smp_num_siblings; | 912 | |
915 | while ((tmp & 0x80000000 ) == 0) { | 913 | index_msb = get_count_order(smp_num_siblings); |
916 | tmp <<=1 ; | ||
917 | index_msb--; | ||
918 | } | ||
919 | if (smp_num_siblings & (smp_num_siblings - 1)) | ||
920 | index_msb++; | ||
921 | phys_proc_id[cpu] = phys_pkg_id(index_msb); | 914 | phys_proc_id[cpu] = phys_pkg_id(index_msb); |
922 | 915 | ||
923 | printk(KERN_INFO "CPU: Physical Processor ID: %d\n", | 916 | printk(KERN_INFO "CPU: Physical Processor ID: %d\n", |
924 | phys_proc_id[cpu]); | 917 | phys_proc_id[cpu]); |
925 | 918 | ||
926 | smp_num_siblings = smp_num_siblings / c->x86_num_cores; | 919 | smp_num_siblings = smp_num_siblings / c->x86_max_cores; |
927 | 920 | ||
928 | tmp = smp_num_siblings; | 921 | index_msb = get_count_order(smp_num_siblings) ; |
929 | index_msb = 31; | ||
930 | while ((tmp & 0x80000000) == 0) { | ||
931 | tmp <<=1 ; | ||
932 | index_msb--; | ||
933 | } | ||
934 | if (smp_num_siblings & (smp_num_siblings - 1)) | ||
935 | index_msb++; | ||
936 | 922 | ||
937 | cpu_core_id[cpu] = phys_pkg_id(index_msb); | 923 | core_bits = get_count_order(c->x86_max_cores); |
938 | 924 | ||
939 | if (c->x86_num_cores > 1) | 925 | cpu_core_id[cpu] = phys_pkg_id(index_msb) & |
926 | ((1 << core_bits) - 1); | ||
927 | |||
928 | if (c->x86_max_cores > 1) | ||
940 | printk(KERN_INFO "CPU: Processor Core ID: %d\n", | 929 | printk(KERN_INFO "CPU: Processor Core ID: %d\n", |
941 | cpu_core_id[cpu]); | 930 | cpu_core_id[cpu]); |
942 | } | 931 | } |
@@ -975,7 +964,7 @@ static void srat_detect_node(void) | |||
975 | node = apicid_to_node[hard_smp_processor_id()]; | 964 | node = apicid_to_node[hard_smp_processor_id()]; |
976 | if (node == NUMA_NO_NODE) | 965 | if (node == NUMA_NO_NODE) |
977 | node = 0; | 966 | node = 0; |
978 | cpu_to_node[cpu] = node; | 967 | numa_set_node(cpu, node); |
979 | 968 | ||
980 | if (acpi_numa > 0) | 969 | if (acpi_numa > 0) |
981 | printk(KERN_INFO "CPU %d -> Node %d\n", cpu, node); | 970 | printk(KERN_INFO "CPU %d -> Node %d\n", cpu, node); |
@@ -993,13 +982,18 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) | |||
993 | unsigned eax = cpuid_eax(0x80000008); | 982 | unsigned eax = cpuid_eax(0x80000008); |
994 | c->x86_virt_bits = (eax >> 8) & 0xff; | 983 | c->x86_virt_bits = (eax >> 8) & 0xff; |
995 | c->x86_phys_bits = eax & 0xff; | 984 | c->x86_phys_bits = eax & 0xff; |
985 | /* CPUID workaround for Intel 0F34 CPU */ | ||
986 | if (c->x86_vendor == X86_VENDOR_INTEL && | ||
987 | c->x86 == 0xF && c->x86_model == 0x3 && | ||
988 | c->x86_mask == 0x4) | ||
989 | c->x86_phys_bits = 36; | ||
996 | } | 990 | } |
997 | 991 | ||
998 | if (c->x86 == 15) | 992 | if (c->x86 == 15) |
999 | c->x86_cache_alignment = c->x86_clflush_size * 2; | 993 | c->x86_cache_alignment = c->x86_clflush_size * 2; |
1000 | if (c->x86 >= 15) | 994 | if (c->x86 >= 15) |
1001 | set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability); | 995 | set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability); |
1002 | c->x86_num_cores = intel_num_cpu_cores(c); | 996 | c->x86_max_cores = intel_num_cpu_cores(c); |
1003 | 997 | ||
1004 | srat_detect_node(); | 998 | srat_detect_node(); |
1005 | } | 999 | } |
@@ -1037,7 +1031,7 @@ void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c) | |||
1037 | c->x86_model_id[0] = '\0'; /* Unset */ | 1031 | c->x86_model_id[0] = '\0'; /* Unset */ |
1038 | c->x86_clflush_size = 64; | 1032 | c->x86_clflush_size = 64; |
1039 | c->x86_cache_alignment = c->x86_clflush_size; | 1033 | c->x86_cache_alignment = c->x86_clflush_size; |
1040 | c->x86_num_cores = 1; | 1034 | c->x86_max_cores = 1; |
1041 | c->extended_cpuid_level = 0; | 1035 | c->extended_cpuid_level = 0; |
1042 | memset(&c->x86_capability, 0, sizeof c->x86_capability); | 1036 | memset(&c->x86_capability, 0, sizeof c->x86_capability); |
1043 | 1037 | ||
@@ -1060,10 +1054,10 @@ void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c) | |||
1060 | c->x86 = (tfms >> 8) & 0xf; | 1054 | c->x86 = (tfms >> 8) & 0xf; |
1061 | c->x86_model = (tfms >> 4) & 0xf; | 1055 | c->x86_model = (tfms >> 4) & 0xf; |
1062 | c->x86_mask = tfms & 0xf; | 1056 | c->x86_mask = tfms & 0xf; |
1063 | if (c->x86 == 0xf) { | 1057 | if (c->x86 == 0xf) |
1064 | c->x86 += (tfms >> 20) & 0xff; | 1058 | c->x86 += (tfms >> 20) & 0xff; |
1059 | if (c->x86 >= 0x6) | ||
1065 | c->x86_model += ((tfms >> 16) & 0xF) << 4; | 1060 | c->x86_model += ((tfms >> 16) & 0xF) << 4; |
1066 | } | ||
1067 | if (c->x86_capability[0] & (1<<19)) | 1061 | if (c->x86_capability[0] & (1<<19)) |
1068 | c->x86_clflush_size = ((misc >> 8) & 0xff) * 8; | 1062 | c->x86_clflush_size = ((misc >> 8) & 0xff) * 8; |
1069 | } else { | 1063 | } else { |
@@ -1271,13 +1265,12 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
1271 | seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); | 1265 | seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); |
1272 | 1266 | ||
1273 | #ifdef CONFIG_SMP | 1267 | #ifdef CONFIG_SMP |
1274 | if (smp_num_siblings * c->x86_num_cores > 1) { | 1268 | if (smp_num_siblings * c->x86_max_cores > 1) { |
1275 | int cpu = c - cpu_data; | 1269 | int cpu = c - cpu_data; |
1276 | seq_printf(m, "physical id\t: %d\n", phys_proc_id[cpu]); | 1270 | seq_printf(m, "physical id\t: %d\n", phys_proc_id[cpu]); |
1277 | seq_printf(m, "siblings\t: %d\n", | 1271 | seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[cpu])); |
1278 | c->x86_num_cores * smp_num_siblings); | ||
1279 | seq_printf(m, "core id\t\t: %d\n", cpu_core_id[cpu]); | 1272 | seq_printf(m, "core id\t\t: %d\n", cpu_core_id[cpu]); |
1280 | seq_printf(m, "cpu cores\t: %d\n", c->x86_num_cores); | 1273 | seq_printf(m, "cpu cores\t: %d\n", c->booted_cores); |
1281 | } | 1274 | } |
1282 | #endif | 1275 | #endif |
1283 | 1276 | ||
diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c index 79190891fbc5..06dc354375c3 100644 --- a/arch/x86_64/kernel/setup64.c +++ b/arch/x86_64/kernel/setup64.c | |||
@@ -141,7 +141,6 @@ void pda_init(int cpu) | |||
141 | panic("cannot allocate irqstack for cpu %d", cpu); | 141 | panic("cannot allocate irqstack for cpu %d", cpu); |
142 | } | 142 | } |
143 | 143 | ||
144 | asm volatile("movq %0,%%cr3" :: "r" (__pa_symbol(&init_level4_pgt))); | ||
145 | 144 | ||
146 | pda->irqstackptr += IRQSTACKSIZE-64; | 145 | pda->irqstackptr += IRQSTACKSIZE-64; |
147 | } | 146 | } |
@@ -197,6 +196,7 @@ void __cpuinit cpu_init (void) | |||
197 | /* CPU 0 is initialised in head64.c */ | 196 | /* CPU 0 is initialised in head64.c */ |
198 | if (cpu != 0) { | 197 | if (cpu != 0) { |
199 | pda_init(cpu); | 198 | pda_init(cpu); |
199 | zap_low_mappings(cpu); | ||
200 | } else | 200 | } else |
201 | estacks = boot_exception_stacks; | 201 | estacks = boot_exception_stacks; |
202 | 202 | ||
diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c index d642fbf3da29..5876df116c92 100644 --- a/arch/x86_64/kernel/signal.c +++ b/arch/x86_64/kernel/signal.c | |||
@@ -110,6 +110,15 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned | |||
110 | COPY(r14); | 110 | COPY(r14); |
111 | COPY(r15); | 111 | COPY(r15); |
112 | 112 | ||
113 | /* Kernel saves and restores only the CS segment register on signals, | ||
114 | * which is the bare minimum needed to allow mixed 32/64-bit code. | ||
115 | * App's signal handler can save/restore other segments if needed. */ | ||
116 | { | ||
117 | unsigned cs; | ||
118 | err |= __get_user(cs, &sc->cs); | ||
119 | regs->cs = cs | 3; /* Force into user mode */ | ||
120 | } | ||
121 | |||
113 | { | 122 | { |
114 | unsigned int tmpflags; | 123 | unsigned int tmpflags; |
115 | err |= __get_user(tmpflags, &sc->eflags); | 124 | err |= __get_user(tmpflags, &sc->eflags); |
@@ -187,6 +196,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned lo | |||
187 | { | 196 | { |
188 | int err = 0; | 197 | int err = 0; |
189 | 198 | ||
199 | err |= __put_user(regs->cs, &sc->cs); | ||
190 | err |= __put_user(0, &sc->gs); | 200 | err |= __put_user(0, &sc->gs); |
191 | err |= __put_user(0, &sc->fs); | 201 | err |= __put_user(0, &sc->fs); |
192 | 202 | ||
@@ -318,7 +328,14 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
318 | 328 | ||
319 | regs->rsp = (unsigned long)frame; | 329 | regs->rsp = (unsigned long)frame; |
320 | 330 | ||
331 | /* Set up the CS register to run signal handlers in 64-bit mode, | ||
332 | even if the handler happens to be interrupting 32-bit code. */ | ||
333 | regs->cs = __USER_CS; | ||
334 | |||
335 | /* This, by contrast, has nothing to do with segment registers - | ||
336 | see include/asm-x86_64/uaccess.h for details. */ | ||
321 | set_fs(USER_DS); | 337 | set_fs(USER_DS); |
338 | |||
322 | regs->eflags &= ~TF_MASK; | 339 | regs->eflags &= ~TF_MASK; |
323 | if (test_thread_flag(TIF_SINGLESTEP)) | 340 | if (test_thread_flag(TIF_SINGLESTEP)) |
324 | ptrace_notify(SIGTRAP); | 341 | ptrace_notify(SIGTRAP); |
diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c index 9db9dda161b4..cfc3d9dccbd9 100644 --- a/arch/x86_64/kernel/smp.c +++ b/arch/x86_64/kernel/smp.c | |||
@@ -28,8 +28,6 @@ | |||
28 | #include <asm/proto.h> | 28 | #include <asm/proto.h> |
29 | #include <asm/apicdef.h> | 29 | #include <asm/apicdef.h> |
30 | 30 | ||
31 | #define __cpuinit __init | ||
32 | |||
33 | /* | 31 | /* |
34 | * Smarter SMP flushing macros. | 32 | * Smarter SMP flushing macros. |
35 | * c/o Linus Torvalds. | 33 | * c/o Linus Torvalds. |
@@ -452,13 +450,14 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic, | |||
452 | 450 | ||
453 | void smp_stop_cpu(void) | 451 | void smp_stop_cpu(void) |
454 | { | 452 | { |
453 | unsigned long flags; | ||
455 | /* | 454 | /* |
456 | * Remove this CPU: | 455 | * Remove this CPU: |
457 | */ | 456 | */ |
458 | cpu_clear(smp_processor_id(), cpu_online_map); | 457 | cpu_clear(smp_processor_id(), cpu_online_map); |
459 | local_irq_disable(); | 458 | local_irq_save(flags); |
460 | disable_local_APIC(); | 459 | disable_local_APIC(); |
461 | local_irq_enable(); | 460 | local_irq_restore(flags); |
462 | } | 461 | } |
463 | 462 | ||
464 | static void smp_really_stop_cpu(void *dummy) | 463 | static void smp_really_stop_cpu(void *dummy) |
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index c4e59bbdc187..683c33f7b967 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c | |||
@@ -64,6 +64,7 @@ | |||
64 | int smp_num_siblings = 1; | 64 | int smp_num_siblings = 1; |
65 | /* Package ID of each logical CPU */ | 65 | /* Package ID of each logical CPU */ |
66 | u8 phys_proc_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID }; | 66 | u8 phys_proc_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID }; |
67 | /* core ID of each logical CPU */ | ||
67 | u8 cpu_core_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID }; | 68 | u8 cpu_core_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID }; |
68 | 69 | ||
69 | /* Bitmask of currently online CPUs */ | 70 | /* Bitmask of currently online CPUs */ |
@@ -87,7 +88,10 @@ struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned; | |||
87 | /* Set when the idlers are all forked */ | 88 | /* Set when the idlers are all forked */ |
88 | int smp_threads_ready; | 89 | int smp_threads_ready; |
89 | 90 | ||
91 | /* representing HT siblings of each logical CPU */ | ||
90 | cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; | 92 | cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; |
93 | |||
94 | /* representing HT and core siblings of each logical CPU */ | ||
91 | cpumask_t cpu_core_map[NR_CPUS] __read_mostly; | 95 | cpumask_t cpu_core_map[NR_CPUS] __read_mostly; |
92 | EXPORT_SYMBOL(cpu_core_map); | 96 | EXPORT_SYMBOL(cpu_core_map); |
93 | 97 | ||
@@ -434,30 +438,59 @@ void __cpuinit smp_callin(void) | |||
434 | cpu_set(cpuid, cpu_callin_map); | 438 | cpu_set(cpuid, cpu_callin_map); |
435 | } | 439 | } |
436 | 440 | ||
441 | /* representing cpus for which sibling maps can be computed */ | ||
442 | static cpumask_t cpu_sibling_setup_map; | ||
443 | |||
437 | static inline void set_cpu_sibling_map(int cpu) | 444 | static inline void set_cpu_sibling_map(int cpu) |
438 | { | 445 | { |
439 | int i; | 446 | int i; |
447 | struct cpuinfo_x86 *c = cpu_data; | ||
448 | |||
449 | cpu_set(cpu, cpu_sibling_setup_map); | ||
440 | 450 | ||
441 | if (smp_num_siblings > 1) { | 451 | if (smp_num_siblings > 1) { |
442 | for_each_cpu(i) { | 452 | for_each_cpu_mask(i, cpu_sibling_setup_map) { |
443 | if (cpu_core_id[cpu] == cpu_core_id[i]) { | 453 | if (phys_proc_id[cpu] == phys_proc_id[i] && |
454 | cpu_core_id[cpu] == cpu_core_id[i]) { | ||
444 | cpu_set(i, cpu_sibling_map[cpu]); | 455 | cpu_set(i, cpu_sibling_map[cpu]); |
445 | cpu_set(cpu, cpu_sibling_map[i]); | 456 | cpu_set(cpu, cpu_sibling_map[i]); |
457 | cpu_set(i, cpu_core_map[cpu]); | ||
458 | cpu_set(cpu, cpu_core_map[i]); | ||
446 | } | 459 | } |
447 | } | 460 | } |
448 | } else { | 461 | } else { |
449 | cpu_set(cpu, cpu_sibling_map[cpu]); | 462 | cpu_set(cpu, cpu_sibling_map[cpu]); |
450 | } | 463 | } |
451 | 464 | ||
452 | if (current_cpu_data.x86_num_cores > 1) { | 465 | if (current_cpu_data.x86_max_cores == 1) { |
453 | for_each_cpu(i) { | ||
454 | if (phys_proc_id[cpu] == phys_proc_id[i]) { | ||
455 | cpu_set(i, cpu_core_map[cpu]); | ||
456 | cpu_set(cpu, cpu_core_map[i]); | ||
457 | } | ||
458 | } | ||
459 | } else { | ||
460 | cpu_core_map[cpu] = cpu_sibling_map[cpu]; | 466 | cpu_core_map[cpu] = cpu_sibling_map[cpu]; |
467 | c[cpu].booted_cores = 1; | ||
468 | return; | ||
469 | } | ||
470 | |||
471 | for_each_cpu_mask(i, cpu_sibling_setup_map) { | ||
472 | if (phys_proc_id[cpu] == phys_proc_id[i]) { | ||
473 | cpu_set(i, cpu_core_map[cpu]); | ||
474 | cpu_set(cpu, cpu_core_map[i]); | ||
475 | /* | ||
476 | * Does this new cpu bringup a new core? | ||
477 | */ | ||
478 | if (cpus_weight(cpu_sibling_map[cpu]) == 1) { | ||
479 | /* | ||
480 | * for each core in package, increment | ||
481 | * the booted_cores for this new cpu | ||
482 | */ | ||
483 | if (first_cpu(cpu_sibling_map[i]) == i) | ||
484 | c[cpu].booted_cores++; | ||
485 | /* | ||
486 | * increment the core count for all | ||
487 | * the other cpus in this package | ||
488 | */ | ||
489 | if (i != cpu) | ||
490 | c[i].booted_cores++; | ||
491 | } else if (i != cpu && !c[cpu].booted_cores) | ||
492 | c[cpu].booted_cores = c[i].booted_cores; | ||
493 | } | ||
461 | } | 494 | } |
462 | } | 495 | } |
463 | 496 | ||
@@ -879,6 +912,9 @@ static __init void disable_smp(void) | |||
879 | } | 912 | } |
880 | 913 | ||
881 | #ifdef CONFIG_HOTPLUG_CPU | 914 | #ifdef CONFIG_HOTPLUG_CPU |
915 | |||
916 | int additional_cpus __initdata = -1; | ||
917 | |||
882 | /* | 918 | /* |
883 | * cpu_possible_map should be static, it cannot change as cpu's | 919 | * cpu_possible_map should be static, it cannot change as cpu's |
884 | * are onlined, or offlined. The reason is per-cpu data-structures | 920 | * are onlined, or offlined. The reason is per-cpu data-structures |
@@ -887,14 +923,38 @@ static __init void disable_smp(void) | |||
887 | * cpu_present_map on the other hand can change dynamically. | 923 | * cpu_present_map on the other hand can change dynamically. |
888 | * In case when cpu_hotplug is not compiled, then we resort to current | 924 | * In case when cpu_hotplug is not compiled, then we resort to current |
889 | * behaviour, which is cpu_possible == cpu_present. | 925 | * behaviour, which is cpu_possible == cpu_present. |
890 | * If cpu-hotplug is supported, then we need to preallocate for all | ||
891 | * those NR_CPUS, hence cpu_possible_map represents entire NR_CPUS range. | ||
892 | * - Ashok Raj | 926 | * - Ashok Raj |
927 | * | ||
928 | * Three ways to find out the number of additional hotplug CPUs: | ||
929 | * - If the BIOS specified disabled CPUs in ACPI/mptables use that. | ||
930 | * - otherwise use half of the available CPUs or 2, whatever is more. | ||
931 | * - The user can overwrite it with additional_cpus=NUM | ||
932 | * We do this because additional CPUs waste a lot of memory. | ||
933 | * -AK | ||
893 | */ | 934 | */ |
894 | __init void prefill_possible_map(void) | 935 | __init void prefill_possible_map(void) |
895 | { | 936 | { |
896 | int i; | 937 | int i; |
897 | for (i = 0; i < NR_CPUS; i++) | 938 | int possible; |
939 | |||
940 | if (additional_cpus == -1) { | ||
941 | if (disabled_cpus > 0) { | ||
942 | additional_cpus = disabled_cpus; | ||
943 | } else { | ||
944 | additional_cpus = num_processors / 2; | ||
945 | if (additional_cpus == 0) | ||
946 | additional_cpus = 2; | ||
947 | } | ||
948 | } | ||
949 | possible = num_processors + additional_cpus; | ||
950 | if (possible > NR_CPUS) | ||
951 | possible = NR_CPUS; | ||
952 | |||
953 | printk(KERN_INFO "SMP: Allowing %d CPUs, %d hotplug CPUs\n", | ||
954 | possible, | ||
955 | max_t(int, possible - num_processors, 0)); | ||
956 | |||
957 | for (i = 0; i < possible; i++) | ||
898 | cpu_set(i, cpu_possible_map); | 958 | cpu_set(i, cpu_possible_map); |
899 | } | 959 | } |
900 | #endif | 960 | #endif |
@@ -965,6 +1025,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
965 | nmi_watchdog_default(); | 1025 | nmi_watchdog_default(); |
966 | current_cpu_data = boot_cpu_data; | 1026 | current_cpu_data = boot_cpu_data; |
967 | current_thread_info()->cpu = 0; /* needed? */ | 1027 | current_thread_info()->cpu = 0; /* needed? */ |
1028 | set_cpu_sibling_map(0); | ||
968 | 1029 | ||
969 | if (smp_sanity_check(max_cpus) < 0) { | 1030 | if (smp_sanity_check(max_cpus) < 0) { |
970 | printk(KERN_INFO "SMP disabled\n"); | 1031 | printk(KERN_INFO "SMP disabled\n"); |
@@ -1008,8 +1069,6 @@ void __init smp_prepare_boot_cpu(void) | |||
1008 | int me = smp_processor_id(); | 1069 | int me = smp_processor_id(); |
1009 | cpu_set(me, cpu_online_map); | 1070 | cpu_set(me, cpu_online_map); |
1010 | cpu_set(me, cpu_callout_map); | 1071 | cpu_set(me, cpu_callout_map); |
1011 | cpu_set(0, cpu_sibling_map[0]); | ||
1012 | cpu_set(0, cpu_core_map[0]); | ||
1013 | per_cpu(cpu_state, me) = CPU_ONLINE; | 1072 | per_cpu(cpu_state, me) = CPU_ONLINE; |
1014 | } | 1073 | } |
1015 | 1074 | ||
@@ -1062,9 +1121,6 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
1062 | */ | 1121 | */ |
1063 | void __init smp_cpus_done(unsigned int max_cpus) | 1122 | void __init smp_cpus_done(unsigned int max_cpus) |
1064 | { | 1123 | { |
1065 | #ifndef CONFIG_HOTPLUG_CPU | ||
1066 | zap_low_mappings(); | ||
1067 | #endif | ||
1068 | smp_cleanup_boot(); | 1124 | smp_cleanup_boot(); |
1069 | 1125 | ||
1070 | #ifdef CONFIG_X86_IO_APIC | 1126 | #ifdef CONFIG_X86_IO_APIC |
@@ -1081,15 +1137,24 @@ void __init smp_cpus_done(unsigned int max_cpus) | |||
1081 | static void remove_siblinginfo(int cpu) | 1137 | static void remove_siblinginfo(int cpu) |
1082 | { | 1138 | { |
1083 | int sibling; | 1139 | int sibling; |
1140 | struct cpuinfo_x86 *c = cpu_data; | ||
1084 | 1141 | ||
1142 | for_each_cpu_mask(sibling, cpu_core_map[cpu]) { | ||
1143 | cpu_clear(cpu, cpu_core_map[sibling]); | ||
1144 | /* | ||
1145 | * last thread sibling in this cpu core going down | ||
1146 | */ | ||
1147 | if (cpus_weight(cpu_sibling_map[cpu]) == 1) | ||
1148 | c[sibling].booted_cores--; | ||
1149 | } | ||
1150 | |||
1085 | for_each_cpu_mask(sibling, cpu_sibling_map[cpu]) | 1151 | for_each_cpu_mask(sibling, cpu_sibling_map[cpu]) |
1086 | cpu_clear(cpu, cpu_sibling_map[sibling]); | 1152 | cpu_clear(cpu, cpu_sibling_map[sibling]); |
1087 | for_each_cpu_mask(sibling, cpu_core_map[cpu]) | ||
1088 | cpu_clear(cpu, cpu_core_map[sibling]); | ||
1089 | cpus_clear(cpu_sibling_map[cpu]); | 1153 | cpus_clear(cpu_sibling_map[cpu]); |
1090 | cpus_clear(cpu_core_map[cpu]); | 1154 | cpus_clear(cpu_core_map[cpu]); |
1091 | phys_proc_id[cpu] = BAD_APICID; | 1155 | phys_proc_id[cpu] = BAD_APICID; |
1092 | cpu_core_id[cpu] = BAD_APICID; | 1156 | cpu_core_id[cpu] = BAD_APICID; |
1157 | cpu_clear(cpu, cpu_sibling_setup_map); | ||
1093 | } | 1158 | } |
1094 | 1159 | ||
1095 | void remove_cpu_from_maps(void) | 1160 | void remove_cpu_from_maps(void) |
@@ -1153,6 +1218,12 @@ void __cpu_die(unsigned int cpu) | |||
1153 | printk(KERN_ERR "CPU %u didn't die...\n", cpu); | 1218 | printk(KERN_ERR "CPU %u didn't die...\n", cpu); |
1154 | } | 1219 | } |
1155 | 1220 | ||
1221 | static __init int setup_additional_cpus(char *s) | ||
1222 | { | ||
1223 | return get_option(&s, &additional_cpus); | ||
1224 | } | ||
1225 | __setup("additional_cpus=", setup_additional_cpus); | ||
1226 | |||
1156 | #else /* ... !CONFIG_HOTPLUG_CPU */ | 1227 | #else /* ... !CONFIG_HOTPLUG_CPU */ |
1157 | 1228 | ||
1158 | int __cpu_disable(void) | 1229 | int __cpu_disable(void) |
diff --git a/arch/x86_64/kernel/sys_x86_64.c b/arch/x86_64/kernel/sys_x86_64.c index cc7821c68851..6449ea8fe756 100644 --- a/arch/x86_64/kernel/sys_x86_64.c +++ b/arch/x86_64/kernel/sys_x86_64.c | |||
@@ -154,17 +154,3 @@ asmlinkage long sys_uname(struct new_utsname __user * name) | |||
154 | err |= copy_to_user(&name->machine, "i686", 5); | 154 | err |= copy_to_user(&name->machine, "i686", 5); |
155 | return err ? -EFAULT : 0; | 155 | return err ? -EFAULT : 0; |
156 | } | 156 | } |
157 | |||
158 | asmlinkage long sys_time64(long __user * tloc) | ||
159 | { | ||
160 | struct timeval now; | ||
161 | int i; | ||
162 | |||
163 | do_gettimeofday(&now); | ||
164 | i = now.tv_sec; | ||
165 | if (tloc) { | ||
166 | if (put_user(i,tloc)) | ||
167 | i = -EFAULT; | ||
168 | } | ||
169 | return i; | ||
170 | } | ||
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index b5e09e6b5536..bf337f493189 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c | |||
@@ -428,19 +428,6 @@ static void __kprobes do_trap(int trapnr, int signr, char *str, | |||
428 | { | 428 | { |
429 | conditional_sti(regs); | 429 | conditional_sti(regs); |
430 | 430 | ||
431 | #ifdef CONFIG_CHECKING | ||
432 | { | ||
433 | unsigned long gs; | ||
434 | struct x8664_pda *pda = cpu_pda + safe_smp_processor_id(); | ||
435 | rdmsrl(MSR_GS_BASE, gs); | ||
436 | if (gs != (unsigned long)pda) { | ||
437 | wrmsrl(MSR_GS_BASE, pda); | ||
438 | printk("%s: wrong gs %lx expected %p rip %lx\n", str, gs, pda, | ||
439 | regs->rip); | ||
440 | } | ||
441 | } | ||
442 | #endif | ||
443 | |||
444 | if (user_mode(regs)) { | 431 | if (user_mode(regs)) { |
445 | struct task_struct *tsk = current; | 432 | struct task_struct *tsk = current; |
446 | 433 | ||
@@ -513,20 +500,6 @@ asmlinkage void __kprobes do_general_protection(struct pt_regs * regs, | |||
513 | { | 500 | { |
514 | conditional_sti(regs); | 501 | conditional_sti(regs); |
515 | 502 | ||
516 | #ifdef CONFIG_CHECKING | ||
517 | { | ||
518 | unsigned long gs; | ||
519 | struct x8664_pda *pda = cpu_pda + safe_smp_processor_id(); | ||
520 | rdmsrl(MSR_GS_BASE, gs); | ||
521 | if (gs != (unsigned long)pda) { | ||
522 | wrmsrl(MSR_GS_BASE, pda); | ||
523 | oops_in_progress++; | ||
524 | printk("general protection handler: wrong gs %lx expected %p\n", gs, pda); | ||
525 | oops_in_progress--; | ||
526 | } | ||
527 | } | ||
528 | #endif | ||
529 | |||
530 | if (user_mode(regs)) { | 503 | if (user_mode(regs)) { |
531 | struct task_struct *tsk = current; | 504 | struct task_struct *tsk = current; |
532 | 505 | ||
@@ -665,19 +638,6 @@ asmlinkage void __kprobes do_debug(struct pt_regs * regs, | |||
665 | struct task_struct *tsk = current; | 638 | struct task_struct *tsk = current; |
666 | siginfo_t info; | 639 | siginfo_t info; |
667 | 640 | ||
668 | #ifdef CONFIG_CHECKING | ||
669 | { | ||
670 | /* RED-PEN interaction with debugger - could destroy gs */ | ||
671 | unsigned long gs; | ||
672 | struct x8664_pda *pda = cpu_pda + safe_smp_processor_id(); | ||
673 | rdmsrl(MSR_GS_BASE, gs); | ||
674 | if (gs != (unsigned long)pda) { | ||
675 | wrmsrl(MSR_GS_BASE, pda); | ||
676 | printk("debug handler: wrong gs %lx expected %p\n", gs, pda); | ||
677 | } | ||
678 | } | ||
679 | #endif | ||
680 | |||
681 | get_debugreg(condition, 6); | 641 | get_debugreg(condition, 6); |
682 | 642 | ||
683 | if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code, | 643 | if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code, |
@@ -888,6 +848,10 @@ asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void) | |||
888 | { | 848 | { |
889 | } | 849 | } |
890 | 850 | ||
851 | asmlinkage void __attribute__((weak)) mce_threshold_interrupt(void) | ||
852 | { | ||
853 | } | ||
854 | |||
891 | /* | 855 | /* |
892 | * 'math_state_restore()' saves the current math information in the | 856 | * 'math_state_restore()' saves the current math information in the |
893 | * old math state array, and gets the new ones from the current task | 857 | * old math state array, and gets the new ones from the current task |
diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S index 6dd642cad2ef..58b19215b4b3 100644 --- a/arch/x86_64/kernel/vmlinux.lds.S +++ b/arch/x86_64/kernel/vmlinux.lds.S | |||
@@ -50,7 +50,7 @@ SECTIONS | |||
50 | *(.bss.page_aligned) | 50 | *(.bss.page_aligned) |
51 | *(.bss) | 51 | *(.bss) |
52 | } | 52 | } |
53 | __bss_end = .; | 53 | __bss_stop = .; |
54 | 54 | ||
55 | . = ALIGN(PAGE_SIZE); | 55 | . = ALIGN(PAGE_SIZE); |
56 | . = ALIGN(CONFIG_X86_L1_CACHE_BYTES); | 56 | . = ALIGN(CONFIG_X86_L1_CACHE_BYTES); |
diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c index fd99ddd009bc..4a54221e10bc 100644 --- a/arch/x86_64/kernel/x8664_ksyms.c +++ b/arch/x86_64/kernel/x8664_ksyms.c | |||
@@ -203,3 +203,6 @@ EXPORT_SYMBOL(flush_tlb_page); | |||
203 | #endif | 203 | #endif |
204 | 204 | ||
205 | EXPORT_SYMBOL(cpu_khz); | 205 | EXPORT_SYMBOL(cpu_khz); |
206 | |||
207 | EXPORT_SYMBOL(load_gs_index); | ||
208 | |||
diff --git a/arch/x86_64/lib/clear_page.S b/arch/x86_64/lib/clear_page.S index 30a9da458c15..43d9fa136180 100644 --- a/arch/x86_64/lib/clear_page.S +++ b/arch/x86_64/lib/clear_page.S | |||
@@ -5,46 +5,8 @@ | |||
5 | .globl clear_page | 5 | .globl clear_page |
6 | .p2align 4 | 6 | .p2align 4 |
7 | clear_page: | 7 | clear_page: |
8 | xorl %eax,%eax | ||
9 | movl $4096/64,%ecx | ||
10 | .p2align 4 | ||
11 | .Lloop: | ||
12 | decl %ecx | ||
13 | #define PUT(x) movq %rax,x*8(%rdi) | ||
14 | movq %rax,(%rdi) | ||
15 | PUT(1) | ||
16 | PUT(2) | ||
17 | PUT(3) | ||
18 | PUT(4) | ||
19 | PUT(5) | ||
20 | PUT(6) | ||
21 | PUT(7) | ||
22 | leaq 64(%rdi),%rdi | ||
23 | jnz .Lloop | ||
24 | nop | ||
25 | ret | ||
26 | clear_page_end: | ||
27 | |||
28 | /* C stepping K8 run faster using the string instructions. | ||
29 | It is also a lot simpler. Use this when possible */ | ||
30 | |||
31 | #include <asm/cpufeature.h> | ||
32 | |||
33 | .section .altinstructions,"a" | ||
34 | .align 8 | ||
35 | .quad clear_page | ||
36 | .quad clear_page_c | ||
37 | .byte X86_FEATURE_K8_C | ||
38 | .byte clear_page_end-clear_page | ||
39 | .byte clear_page_c_end-clear_page_c | ||
40 | .previous | ||
41 | |||
42 | .section .altinstr_replacement,"ax" | ||
43 | clear_page_c: | ||
44 | movl $4096/8,%ecx | 8 | movl $4096/8,%ecx |
45 | xorl %eax,%eax | 9 | xorl %eax,%eax |
46 | rep | 10 | rep |
47 | stosq | 11 | stosq |
48 | ret | 12 | ret |
49 | clear_page_c_end: | ||
50 | .previous | ||
diff --git a/arch/x86_64/lib/copy_page.S b/arch/x86_64/lib/copy_page.S index dd3aa47b6bf5..621a19769406 100644 --- a/arch/x86_64/lib/copy_page.S +++ b/arch/x86_64/lib/copy_page.S | |||
@@ -8,94 +8,7 @@ | |||
8 | .globl copy_page | 8 | .globl copy_page |
9 | .p2align 4 | 9 | .p2align 4 |
10 | copy_page: | 10 | copy_page: |
11 | subq $3*8,%rsp | ||
12 | movq %rbx,(%rsp) | ||
13 | movq %r12,1*8(%rsp) | ||
14 | movq %r13,2*8(%rsp) | ||
15 | |||
16 | movl $(4096/64)-5,%ecx | ||
17 | .p2align 4 | ||
18 | .Loop64: | ||
19 | dec %rcx | ||
20 | |||
21 | movq (%rsi), %rax | ||
22 | movq 8 (%rsi), %rbx | ||
23 | movq 16 (%rsi), %rdx | ||
24 | movq 24 (%rsi), %r8 | ||
25 | movq 32 (%rsi), %r9 | ||
26 | movq 40 (%rsi), %r10 | ||
27 | movq 48 (%rsi), %r11 | ||
28 | movq 56 (%rsi), %r12 | ||
29 | |||
30 | prefetcht0 5*64(%rsi) | ||
31 | |||
32 | movq %rax, (%rdi) | ||
33 | movq %rbx, 8 (%rdi) | ||
34 | movq %rdx, 16 (%rdi) | ||
35 | movq %r8, 24 (%rdi) | ||
36 | movq %r9, 32 (%rdi) | ||
37 | movq %r10, 40 (%rdi) | ||
38 | movq %r11, 48 (%rdi) | ||
39 | movq %r12, 56 (%rdi) | ||
40 | |||
41 | leaq 64 (%rsi), %rsi | ||
42 | leaq 64 (%rdi), %rdi | ||
43 | |||
44 | jnz .Loop64 | ||
45 | |||
46 | movl $5,%ecx | ||
47 | .p2align 4 | ||
48 | .Loop2: | ||
49 | decl %ecx | ||
50 | |||
51 | movq (%rsi), %rax | ||
52 | movq 8 (%rsi), %rbx | ||
53 | movq 16 (%rsi), %rdx | ||
54 | movq 24 (%rsi), %r8 | ||
55 | movq 32 (%rsi), %r9 | ||
56 | movq 40 (%rsi), %r10 | ||
57 | movq 48 (%rsi), %r11 | ||
58 | movq 56 (%rsi), %r12 | ||
59 | |||
60 | movq %rax, (%rdi) | ||
61 | movq %rbx, 8 (%rdi) | ||
62 | movq %rdx, 16 (%rdi) | ||
63 | movq %r8, 24 (%rdi) | ||
64 | movq %r9, 32 (%rdi) | ||
65 | movq %r10, 40 (%rdi) | ||
66 | movq %r11, 48 (%rdi) | ||
67 | movq %r12, 56 (%rdi) | ||
68 | |||
69 | leaq 64(%rdi),%rdi | ||
70 | leaq 64(%rsi),%rsi | ||
71 | |||
72 | jnz .Loop2 | ||
73 | |||
74 | movq (%rsp),%rbx | ||
75 | movq 1*8(%rsp),%r12 | ||
76 | movq 2*8(%rsp),%r13 | ||
77 | addq $3*8,%rsp | ||
78 | ret | ||
79 | |||
80 | /* C stepping K8 run faster using the string copy instructions. | ||
81 | It is also a lot simpler. Use this when possible */ | ||
82 | |||
83 | #include <asm/cpufeature.h> | ||
84 | |||
85 | .section .altinstructions,"a" | ||
86 | .align 8 | ||
87 | .quad copy_page | ||
88 | .quad copy_page_c | ||
89 | .byte X86_FEATURE_K8_C | ||
90 | .byte copy_page_c_end-copy_page_c | ||
91 | .byte copy_page_c_end-copy_page_c | ||
92 | .previous | ||
93 | |||
94 | .section .altinstr_replacement,"ax" | ||
95 | copy_page_c: | ||
96 | movl $4096/8,%ecx | 11 | movl $4096/8,%ecx |
97 | rep | 12 | rep |
98 | movsq | 13 | movsq |
99 | ret | 14 | ret |
100 | copy_page_c_end: | ||
101 | .previous | ||
diff --git a/arch/x86_64/lib/memcpy.S b/arch/x86_64/lib/memcpy.S index c6c46494fef5..92dd80544602 100644 --- a/arch/x86_64/lib/memcpy.S +++ b/arch/x86_64/lib/memcpy.S | |||
@@ -11,6 +11,8 @@ | |||
11 | * | 11 | * |
12 | * Output: | 12 | * Output: |
13 | * rax original destination | 13 | * rax original destination |
14 | * | ||
15 | * TODO: check best memcpy for PSC | ||
14 | */ | 16 | */ |
15 | 17 | ||
16 | .globl __memcpy | 18 | .globl __memcpy |
@@ -18,95 +20,6 @@ | |||
18 | .p2align 4 | 20 | .p2align 4 |
19 | __memcpy: | 21 | __memcpy: |
20 | memcpy: | 22 | memcpy: |
21 | pushq %rbx | ||
22 | movq %rdi,%rax | ||
23 | |||
24 | movl %edx,%ecx | ||
25 | shrl $6,%ecx | ||
26 | jz .Lhandle_tail | ||
27 | |||
28 | .p2align 4 | ||
29 | .Lloop_64: | ||
30 | decl %ecx | ||
31 | |||
32 | movq (%rsi),%r11 | ||
33 | movq 8(%rsi),%r8 | ||
34 | |||
35 | movq %r11,(%rdi) | ||
36 | movq %r8,1*8(%rdi) | ||
37 | |||
38 | movq 2*8(%rsi),%r9 | ||
39 | movq 3*8(%rsi),%r10 | ||
40 | |||
41 | movq %r9,2*8(%rdi) | ||
42 | movq %r10,3*8(%rdi) | ||
43 | |||
44 | movq 4*8(%rsi),%r11 | ||
45 | movq 5*8(%rsi),%r8 | ||
46 | |||
47 | movq %r11,4*8(%rdi) | ||
48 | movq %r8,5*8(%rdi) | ||
49 | |||
50 | movq 6*8(%rsi),%r9 | ||
51 | movq 7*8(%rsi),%r10 | ||
52 | |||
53 | movq %r9,6*8(%rdi) | ||
54 | movq %r10,7*8(%rdi) | ||
55 | |||
56 | leaq 64(%rsi),%rsi | ||
57 | leaq 64(%rdi),%rdi | ||
58 | jnz .Lloop_64 | ||
59 | |||
60 | .Lhandle_tail: | ||
61 | movl %edx,%ecx | ||
62 | andl $63,%ecx | ||
63 | shrl $3,%ecx | ||
64 | jz .Lhandle_7 | ||
65 | .p2align 4 | ||
66 | .Lloop_8: | ||
67 | decl %ecx | ||
68 | movq (%rsi),%r8 | ||
69 | movq %r8,(%rdi) | ||
70 | leaq 8(%rdi),%rdi | ||
71 | leaq 8(%rsi),%rsi | ||
72 | jnz .Lloop_8 | ||
73 | |||
74 | .Lhandle_7: | ||
75 | movl %edx,%ecx | ||
76 | andl $7,%ecx | ||
77 | jz .Lende | ||
78 | .p2align 4 | ||
79 | .Lloop_1: | ||
80 | movb (%rsi),%r8b | ||
81 | movb %r8b,(%rdi) | ||
82 | incq %rdi | ||
83 | incq %rsi | ||
84 | decl %ecx | ||
85 | jnz .Lloop_1 | ||
86 | |||
87 | .Lende: | ||
88 | popq %rbx | ||
89 | ret | ||
90 | .Lfinal: | ||
91 | |||
92 | /* C stepping K8 run faster using the string copy instructions. | ||
93 | It is also a lot simpler. Use this when possible */ | ||
94 | |||
95 | .section .altinstructions,"a" | ||
96 | .align 8 | ||
97 | .quad memcpy | ||
98 | .quad memcpy_c | ||
99 | .byte X86_FEATURE_K8_C | ||
100 | .byte .Lfinal-memcpy | ||
101 | .byte memcpy_c_end-memcpy_c | ||
102 | .previous | ||
103 | |||
104 | .section .altinstr_replacement,"ax" | ||
105 | /* rdi destination | ||
106 | * rsi source | ||
107 | * rdx count | ||
108 | */ | ||
109 | memcpy_c: | ||
110 | movq %rdi,%rax | 23 | movq %rdi,%rax |
111 | movl %edx,%ecx | 24 | movl %edx,%ecx |
112 | shrl $3,%ecx | 25 | shrl $3,%ecx |
@@ -117,5 +30,3 @@ memcpy_c: | |||
117 | rep | 30 | rep |
118 | movsb | 31 | movsb |
119 | ret | 32 | ret |
120 | memcpy_c_end: | ||
121 | .previous | ||
diff --git a/arch/x86_64/lib/memset.S b/arch/x86_64/lib/memset.S index 4b4c40638640..2aa48f24ed1e 100644 --- a/arch/x86_64/lib/memset.S +++ b/arch/x86_64/lib/memset.S | |||
@@ -13,98 +13,6 @@ | |||
13 | .p2align 4 | 13 | .p2align 4 |
14 | memset: | 14 | memset: |
15 | __memset: | 15 | __memset: |
16 | movq %rdi,%r10 | ||
17 | movq %rdx,%r11 | ||
18 | |||
19 | /* expand byte value */ | ||
20 | movzbl %sil,%ecx | ||
21 | movabs $0x0101010101010101,%rax | ||
22 | mul %rcx /* with rax, clobbers rdx */ | ||
23 | |||
24 | /* align dst */ | ||
25 | movl %edi,%r9d | ||
26 | andl $7,%r9d | ||
27 | jnz .Lbad_alignment | ||
28 | .Lafter_bad_alignment: | ||
29 | |||
30 | movl %r11d,%ecx | ||
31 | shrl $6,%ecx | ||
32 | jz .Lhandle_tail | ||
33 | |||
34 | .p2align 4 | ||
35 | .Lloop_64: | ||
36 | decl %ecx | ||
37 | movq %rax,(%rdi) | ||
38 | movq %rax,8(%rdi) | ||
39 | movq %rax,16(%rdi) | ||
40 | movq %rax,24(%rdi) | ||
41 | movq %rax,32(%rdi) | ||
42 | movq %rax,40(%rdi) | ||
43 | movq %rax,48(%rdi) | ||
44 | movq %rax,56(%rdi) | ||
45 | leaq 64(%rdi),%rdi | ||
46 | jnz .Lloop_64 | ||
47 | |||
48 | /* Handle tail in loops. The loops should be faster than hard | ||
49 | to predict jump tables. */ | ||
50 | .p2align 4 | ||
51 | .Lhandle_tail: | ||
52 | movl %r11d,%ecx | ||
53 | andl $63&(~7),%ecx | ||
54 | jz .Lhandle_7 | ||
55 | shrl $3,%ecx | ||
56 | .p2align 4 | ||
57 | .Lloop_8: | ||
58 | decl %ecx | ||
59 | movq %rax,(%rdi) | ||
60 | leaq 8(%rdi),%rdi | ||
61 | jnz .Lloop_8 | ||
62 | |||
63 | .Lhandle_7: | ||
64 | movl %r11d,%ecx | ||
65 | andl $7,%ecx | ||
66 | jz .Lende | ||
67 | .p2align 4 | ||
68 | .Lloop_1: | ||
69 | decl %ecx | ||
70 | movb %al,(%rdi) | ||
71 | leaq 1(%rdi),%rdi | ||
72 | jnz .Lloop_1 | ||
73 | |||
74 | .Lende: | ||
75 | movq %r10,%rax | ||
76 | ret | ||
77 | |||
78 | .Lbad_alignment: | ||
79 | cmpq $7,%r11 | ||
80 | jbe .Lhandle_7 | ||
81 | movq %rax,(%rdi) /* unaligned store */ | ||
82 | movq $8,%r8 | ||
83 | subq %r9,%r8 | ||
84 | addq %r8,%rdi | ||
85 | subq %r8,%r11 | ||
86 | jmp .Lafter_bad_alignment | ||
87 | |||
88 | /* C stepping K8 run faster using the string instructions. | ||
89 | It is also a lot simpler. Use this when possible */ | ||
90 | |||
91 | #include <asm/cpufeature.h> | ||
92 | |||
93 | .section .altinstructions,"a" | ||
94 | .align 8 | ||
95 | .quad memset | ||
96 | .quad memset_c | ||
97 | .byte X86_FEATURE_K8_C | ||
98 | .byte memset_c_end-memset_c | ||
99 | .byte memset_c_end-memset_c | ||
100 | .previous | ||
101 | |||
102 | .section .altinstr_replacement,"ax" | ||
103 | /* rdi destination | ||
104 | * rsi value | ||
105 | * rdx count | ||
106 | */ | ||
107 | memset_c: | ||
108 | movq %rdi,%r9 | 16 | movq %rdi,%r9 |
109 | movl %edx,%r8d | 17 | movl %edx,%r8d |
110 | andl $7,%r8d | 18 | andl $7,%r8d |
@@ -121,5 +29,3 @@ memset_c: | |||
121 | stosb | 29 | stosb |
122 | movq %r9,%rax | 30 | movq %r9,%rax |
123 | ret | 31 | ret |
124 | memset_c_end: | ||
125 | .previous | ||
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c index b75b872ec154..3a63707a698b 100644 --- a/arch/x86_64/mm/fault.c +++ b/arch/x86_64/mm/fault.c | |||
@@ -308,18 +308,6 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, | |||
308 | unsigned long flags; | 308 | unsigned long flags; |
309 | siginfo_t info; | 309 | siginfo_t info; |
310 | 310 | ||
311 | #ifdef CONFIG_CHECKING | ||
312 | { | ||
313 | unsigned long gs; | ||
314 | struct x8664_pda *pda = cpu_pda + stack_smp_processor_id(); | ||
315 | rdmsrl(MSR_GS_BASE, gs); | ||
316 | if (gs != (unsigned long)pda) { | ||
317 | wrmsrl(MSR_GS_BASE, pda); | ||
318 | printk("page_fault: wrong gs %lx expected %p\n", gs, pda); | ||
319 | } | ||
320 | } | ||
321 | #endif | ||
322 | |||
323 | /* get the address */ | 311 | /* get the address */ |
324 | __asm__("movq %%cr2,%0":"=r" (address)); | 312 | __asm__("movq %%cr2,%0":"=r" (address)); |
325 | if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, | 313 | if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, |
@@ -571,3 +559,10 @@ do_sigbus: | |||
571 | force_sig_info(SIGBUS, &info, tsk); | 559 | force_sig_info(SIGBUS, &info, tsk); |
572 | return; | 560 | return; |
573 | } | 561 | } |
562 | |||
563 | static int __init enable_pagefaulttrace(char *str) | ||
564 | { | ||
565 | page_fault_trace = 1; | ||
566 | return 0; | ||
567 | } | ||
568 | __setup("pagefaulttrace", enable_pagefaulttrace); | ||
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c index e60a1a848de8..286f6a624c3a 100644 --- a/arch/x86_64/mm/init.c +++ b/arch/x86_64/mm/init.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/pagemap.h> | 22 | #include <linux/pagemap.h> |
23 | #include <linux/bootmem.h> | 23 | #include <linux/bootmem.h> |
24 | #include <linux/proc_fs.h> | 24 | #include <linux/proc_fs.h> |
25 | #include <linux/pci.h> | ||
25 | 26 | ||
26 | #include <asm/processor.h> | 27 | #include <asm/processor.h> |
27 | #include <asm/system.h> | 28 | #include <asm/system.h> |
@@ -36,16 +37,13 @@ | |||
36 | #include <asm/mmu_context.h> | 37 | #include <asm/mmu_context.h> |
37 | #include <asm/proto.h> | 38 | #include <asm/proto.h> |
38 | #include <asm/smp.h> | 39 | #include <asm/smp.h> |
40 | #include <asm/sections.h> | ||
39 | 41 | ||
40 | #ifndef Dprintk | 42 | #ifndef Dprintk |
41 | #define Dprintk(x...) | 43 | #define Dprintk(x...) |
42 | #endif | 44 | #endif |
43 | 45 | ||
44 | #ifdef CONFIG_GART_IOMMU | 46 | static unsigned long dma_reserve __initdata; |
45 | extern int swiotlb; | ||
46 | #endif | ||
47 | |||
48 | extern char _stext[]; | ||
49 | 47 | ||
50 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | 48 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); |
51 | 49 | ||
@@ -86,9 +84,6 @@ void show_mem(void) | |||
86 | 84 | ||
87 | /* References to section boundaries */ | 85 | /* References to section boundaries */ |
88 | 86 | ||
89 | extern char _text, _etext, _edata, __bss_start, _end[]; | ||
90 | extern char __init_begin, __init_end; | ||
91 | |||
92 | int after_bootmem; | 87 | int after_bootmem; |
93 | 88 | ||
94 | static void *spp_getpage(void) | 89 | static void *spp_getpage(void) |
@@ -308,42 +303,81 @@ void __init init_memory_mapping(unsigned long start, unsigned long end) | |||
308 | table_end<<PAGE_SHIFT); | 303 | table_end<<PAGE_SHIFT); |
309 | } | 304 | } |
310 | 305 | ||
311 | extern struct x8664_pda cpu_pda[NR_CPUS]; | 306 | void __cpuinit zap_low_mappings(int cpu) |
307 | { | ||
308 | if (cpu == 0) { | ||
309 | pgd_t *pgd = pgd_offset_k(0UL); | ||
310 | pgd_clear(pgd); | ||
311 | } else { | ||
312 | /* | ||
313 | * For AP's, zap the low identity mappings by changing the cr3 | ||
314 | * to init_level4_pgt and doing local flush tlb all | ||
315 | */ | ||
316 | asm volatile("movq %0,%%cr3" :: "r" (__pa_symbol(&init_level4_pgt))); | ||
317 | } | ||
318 | __flush_tlb_all(); | ||
319 | } | ||
312 | 320 | ||
313 | /* Assumes all CPUs still execute in init_mm */ | 321 | /* Compute zone sizes for the DMA and DMA32 zones in a node. */ |
314 | void zap_low_mappings(void) | 322 | __init void |
323 | size_zones(unsigned long *z, unsigned long *h, | ||
324 | unsigned long start_pfn, unsigned long end_pfn) | ||
315 | { | 325 | { |
316 | pgd_t *pgd = pgd_offset_k(0UL); | 326 | int i; |
317 | pgd_clear(pgd); | 327 | unsigned long w; |
318 | flush_tlb_all(); | 328 | |
329 | for (i = 0; i < MAX_NR_ZONES; i++) | ||
330 | z[i] = 0; | ||
331 | |||
332 | if (start_pfn < MAX_DMA_PFN) | ||
333 | z[ZONE_DMA] = MAX_DMA_PFN - start_pfn; | ||
334 | if (start_pfn < MAX_DMA32_PFN) { | ||
335 | unsigned long dma32_pfn = MAX_DMA32_PFN; | ||
336 | if (dma32_pfn > end_pfn) | ||
337 | dma32_pfn = end_pfn; | ||
338 | z[ZONE_DMA32] = dma32_pfn - start_pfn; | ||
339 | } | ||
340 | z[ZONE_NORMAL] = end_pfn - start_pfn; | ||
341 | |||
342 | /* Remove lower zones from higher ones. */ | ||
343 | w = 0; | ||
344 | for (i = 0; i < MAX_NR_ZONES; i++) { | ||
345 | if (z[i]) | ||
346 | z[i] -= w; | ||
347 | w += z[i]; | ||
348 | } | ||
349 | |||
350 | /* Compute holes */ | ||
351 | w = 0; | ||
352 | for (i = 0; i < MAX_NR_ZONES; i++) { | ||
353 | unsigned long s = w; | ||
354 | w += z[i]; | ||
355 | h[i] = e820_hole_size(s, w); | ||
356 | } | ||
357 | |||
358 | /* Add the space pace needed for mem_map to the holes too. */ | ||
359 | for (i = 0; i < MAX_NR_ZONES; i++) | ||
360 | h[i] += (z[i] * sizeof(struct page)) / PAGE_SIZE; | ||
361 | |||
362 | /* The 16MB DMA zone has the kernel and other misc mappings. | ||
363 | Account them too */ | ||
364 | if (h[ZONE_DMA]) { | ||
365 | h[ZONE_DMA] += dma_reserve; | ||
366 | if (h[ZONE_DMA] >= z[ZONE_DMA]) { | ||
367 | printk(KERN_WARNING | ||
368 | "Kernel too large and filling up ZONE_DMA?\n"); | ||
369 | h[ZONE_DMA] = z[ZONE_DMA]; | ||
370 | } | ||
371 | } | ||
319 | } | 372 | } |
320 | 373 | ||
321 | #ifndef CONFIG_NUMA | 374 | #ifndef CONFIG_NUMA |
322 | void __init paging_init(void) | 375 | void __init paging_init(void) |
323 | { | 376 | { |
324 | { | 377 | unsigned long zones[MAX_NR_ZONES], holes[MAX_NR_ZONES]; |
325 | unsigned long zones_size[MAX_NR_ZONES]; | 378 | size_zones(zones, holes, 0, end_pfn); |
326 | unsigned long holes[MAX_NR_ZONES]; | 379 | free_area_init_node(0, NODE_DATA(0), zones, |
327 | unsigned int max_dma; | 380 | __pa(PAGE_OFFSET) >> PAGE_SHIFT, holes); |
328 | |||
329 | memset(zones_size, 0, sizeof(zones_size)); | ||
330 | memset(holes, 0, sizeof(holes)); | ||
331 | |||
332 | max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; | ||
333 | |||
334 | if (end_pfn < max_dma) { | ||
335 | zones_size[ZONE_DMA] = end_pfn; | ||
336 | holes[ZONE_DMA] = e820_hole_size(0, end_pfn); | ||
337 | } else { | ||
338 | zones_size[ZONE_DMA] = max_dma; | ||
339 | holes[ZONE_DMA] = e820_hole_size(0, max_dma); | ||
340 | zones_size[ZONE_NORMAL] = end_pfn - max_dma; | ||
341 | holes[ZONE_NORMAL] = e820_hole_size(max_dma, end_pfn); | ||
342 | } | ||
343 | free_area_init_node(0, NODE_DATA(0), zones_size, | ||
344 | __pa(PAGE_OFFSET) >> PAGE_SHIFT, holes); | ||
345 | } | ||
346 | return; | ||
347 | } | 381 | } |
348 | #endif | 382 | #endif |
349 | 383 | ||
@@ -438,19 +472,16 @@ void __init mem_init(void) | |||
438 | datasize >> 10, | 472 | datasize >> 10, |
439 | initsize >> 10); | 473 | initsize >> 10); |
440 | 474 | ||
475 | #ifdef CONFIG_SMP | ||
441 | /* | 476 | /* |
442 | * Subtle. SMP is doing its boot stuff late (because it has to | 477 | * Sync boot_level4_pgt mappings with the init_level4_pgt |
443 | * fork idle threads) - but it also needs low mappings for the | 478 | * except for the low identity mappings which are already zapped |
444 | * protected-mode entry to work. We zap these entries only after | 479 | * in init_level4_pgt. This sync-up is essential for AP's bringup |
445 | * the WP-bit has been tested. | ||
446 | */ | 480 | */ |
447 | #ifndef CONFIG_SMP | 481 | memcpy(boot_level4_pgt+1, init_level4_pgt+1, (PTRS_PER_PGD-1)*sizeof(pgd_t)); |
448 | zap_low_mappings(); | ||
449 | #endif | 482 | #endif |
450 | } | 483 | } |
451 | 484 | ||
452 | extern char __initdata_begin[], __initdata_end[]; | ||
453 | |||
454 | void free_initmem(void) | 485 | void free_initmem(void) |
455 | { | 486 | { |
456 | unsigned long addr; | 487 | unsigned long addr; |
@@ -464,7 +495,7 @@ void free_initmem(void) | |||
464 | totalram_pages++; | 495 | totalram_pages++; |
465 | } | 496 | } |
466 | memset(__initdata_begin, 0xba, __initdata_end - __initdata_begin); | 497 | memset(__initdata_begin, 0xba, __initdata_end - __initdata_begin); |
467 | printk ("Freeing unused kernel memory: %luk freed\n", (&__init_end - &__init_begin) >> 10); | 498 | printk ("Freeing unused kernel memory: %luk freed\n", (__init_end - __init_begin) >> 10); |
468 | } | 499 | } |
469 | 500 | ||
470 | #ifdef CONFIG_BLK_DEV_INITRD | 501 | #ifdef CONFIG_BLK_DEV_INITRD |
@@ -491,6 +522,8 @@ void __init reserve_bootmem_generic(unsigned long phys, unsigned len) | |||
491 | #else | 522 | #else |
492 | reserve_bootmem(phys, len); | 523 | reserve_bootmem(phys, len); |
493 | #endif | 524 | #endif |
525 | if (phys+len <= MAX_DMA_PFN*PAGE_SIZE) | ||
526 | dma_reserve += len / PAGE_SIZE; | ||
494 | } | 527 | } |
495 | 528 | ||
496 | int kern_addr_valid(unsigned long addr) | 529 | int kern_addr_valid(unsigned long addr) |
@@ -532,10 +565,6 @@ extern int exception_trace, page_fault_trace; | |||
532 | static ctl_table debug_table2[] = { | 565 | static ctl_table debug_table2[] = { |
533 | { 99, "exception-trace", &exception_trace, sizeof(int), 0644, NULL, | 566 | { 99, "exception-trace", &exception_trace, sizeof(int), 0644, NULL, |
534 | proc_dointvec }, | 567 | proc_dointvec }, |
535 | #ifdef CONFIG_CHECKING | ||
536 | { 100, "page-fault-trace", &page_fault_trace, sizeof(int), 0644, NULL, | ||
537 | proc_dointvec }, | ||
538 | #endif | ||
539 | { 0, } | 568 | { 0, } |
540 | }; | 569 | }; |
541 | 570 | ||
diff --git a/arch/x86_64/mm/k8topology.c b/arch/x86_64/mm/k8topology.c index 65417b040c1b..a5663e0bb01c 100644 --- a/arch/x86_64/mm/k8topology.c +++ b/arch/x86_64/mm/k8topology.c | |||
@@ -108,6 +108,7 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) | |||
108 | limit >>= 16; | 108 | limit >>= 16; |
109 | limit <<= 24; | 109 | limit <<= 24; |
110 | limit |= (1<<24)-1; | 110 | limit |= (1<<24)-1; |
111 | limit++; | ||
111 | 112 | ||
112 | if (limit > end_pfn << PAGE_SHIFT) | 113 | if (limit > end_pfn << PAGE_SHIFT) |
113 | limit = end_pfn << PAGE_SHIFT; | 114 | limit = end_pfn << PAGE_SHIFT; |
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c index 214803821001..a828a01739cc 100644 --- a/arch/x86_64/mm/numa.c +++ b/arch/x86_64/mm/numa.c | |||
@@ -38,38 +38,57 @@ cpumask_t node_to_cpumask[MAX_NUMNODES] __read_mostly; | |||
38 | 38 | ||
39 | int numa_off __initdata; | 39 | int numa_off __initdata; |
40 | 40 | ||
41 | int __init compute_hash_shift(struct node *nodes, int numnodes) | 41 | |
42 | /* | ||
43 | * Given a shift value, try to populate memnodemap[] | ||
44 | * Returns : | ||
45 | * 1 if OK | ||
46 | * 0 if memnodmap[] too small (of shift too small) | ||
47 | * -1 if node overlap or lost ram (shift too big) | ||
48 | */ | ||
49 | static int __init populate_memnodemap( | ||
50 | const struct node *nodes, int numnodes, int shift) | ||
42 | { | 51 | { |
43 | int i; | 52 | int i; |
44 | int shift = 20; | 53 | int res = -1; |
45 | unsigned long addr,maxend=0; | 54 | unsigned long addr, end; |
46 | |||
47 | for (i = 0; i < numnodes; i++) | ||
48 | if ((nodes[i].start != nodes[i].end) && (nodes[i].end > maxend)) | ||
49 | maxend = nodes[i].end; | ||
50 | 55 | ||
51 | while ((1UL << shift) < (maxend / NODEMAPSIZE)) | 56 | memset(memnodemap, 0xff, sizeof(memnodemap)); |
52 | shift++; | ||
53 | |||
54 | printk (KERN_DEBUG"Using %d for the hash shift. Max adder is %lx \n", | ||
55 | shift,maxend); | ||
56 | memset(memnodemap,0xff,sizeof(*memnodemap) * NODEMAPSIZE); | ||
57 | for (i = 0; i < numnodes; i++) { | 57 | for (i = 0; i < numnodes; i++) { |
58 | if (nodes[i].start == nodes[i].end) | 58 | addr = nodes[i].start; |
59 | end = nodes[i].end; | ||
60 | if (addr >= end) | ||
59 | continue; | 61 | continue; |
60 | for (addr = nodes[i].start; | 62 | if ((end >> shift) >= NODEMAPSIZE) |
61 | addr < nodes[i].end; | 63 | return 0; |
62 | addr += (1UL << shift)) { | 64 | do { |
63 | if (memnodemap[addr >> shift] != 0xff) { | 65 | if (memnodemap[addr >> shift] != 0xff) |
64 | printk(KERN_INFO | ||
65 | "Your memory is not aligned you need to rebuild your kernel " | ||
66 | "with a bigger NODEMAPSIZE shift=%d adder=%lu\n", | ||
67 | shift,addr); | ||
68 | return -1; | 66 | return -1; |
69 | } | ||
70 | memnodemap[addr >> shift] = i; | 67 | memnodemap[addr >> shift] = i; |
71 | } | 68 | addr += (1 << shift); |
69 | } while (addr < end); | ||
70 | res = 1; | ||
72 | } | 71 | } |
72 | return res; | ||
73 | } | ||
74 | |||
75 | int __init compute_hash_shift(struct node *nodes, int numnodes) | ||
76 | { | ||
77 | int shift = 20; | ||
78 | |||
79 | while (populate_memnodemap(nodes, numnodes, shift + 1) >= 0) | ||
80 | shift++; | ||
81 | |||
82 | printk(KERN_DEBUG "Using %d for the hash shift.\n", | ||
83 | shift); | ||
84 | |||
85 | if (populate_memnodemap(nodes, numnodes, shift) != 1) { | ||
86 | printk(KERN_INFO | ||
87 | "Your memory is not aligned you need to rebuild your kernel " | ||
88 | "with a bigger NODEMAPSIZE shift=%d\n", | ||
89 | shift); | ||
90 | return -1; | ||
91 | } | ||
73 | return shift; | 92 | return shift; |
74 | } | 93 | } |
75 | 94 | ||
@@ -94,7 +113,6 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en | |||
94 | start_pfn = start >> PAGE_SHIFT; | 113 | start_pfn = start >> PAGE_SHIFT; |
95 | end_pfn = end >> PAGE_SHIFT; | 114 | end_pfn = end >> PAGE_SHIFT; |
96 | 115 | ||
97 | memory_present(nodeid, start_pfn, end_pfn); | ||
98 | nodedata_phys = find_e820_area(start, end, pgdat_size); | 116 | nodedata_phys = find_e820_area(start, end, pgdat_size); |
99 | if (nodedata_phys == -1L) | 117 | if (nodedata_phys == -1L) |
100 | panic("Cannot find memory pgdat in node %d\n", nodeid); | 118 | panic("Cannot find memory pgdat in node %d\n", nodeid); |
@@ -132,29 +150,14 @@ void __init setup_node_zones(int nodeid) | |||
132 | unsigned long start_pfn, end_pfn; | 150 | unsigned long start_pfn, end_pfn; |
133 | unsigned long zones[MAX_NR_ZONES]; | 151 | unsigned long zones[MAX_NR_ZONES]; |
134 | unsigned long holes[MAX_NR_ZONES]; | 152 | unsigned long holes[MAX_NR_ZONES]; |
135 | unsigned long dma_end_pfn; | ||
136 | 153 | ||
137 | memset(zones, 0, sizeof(unsigned long) * MAX_NR_ZONES); | 154 | start_pfn = node_start_pfn(nodeid); |
138 | memset(holes, 0, sizeof(unsigned long) * MAX_NR_ZONES); | 155 | end_pfn = node_end_pfn(nodeid); |
139 | 156 | ||
140 | start_pfn = node_start_pfn(nodeid); | 157 | Dprintk(KERN_INFO "setting up node %d %lx-%lx\n", |
141 | end_pfn = node_end_pfn(nodeid); | 158 | nodeid, start_pfn, end_pfn); |
142 | 159 | ||
143 | Dprintk(KERN_INFO "setting up node %d %lx-%lx\n", nodeid, start_pfn, end_pfn); | 160 | size_zones(zones, holes, start_pfn, end_pfn); |
144 | |||
145 | /* All nodes > 0 have a zero length zone DMA */ | ||
146 | dma_end_pfn = __pa(MAX_DMA_ADDRESS) >> PAGE_SHIFT; | ||
147 | if (start_pfn < dma_end_pfn) { | ||
148 | zones[ZONE_DMA] = dma_end_pfn - start_pfn; | ||
149 | holes[ZONE_DMA] = e820_hole_size(start_pfn, dma_end_pfn); | ||
150 | zones[ZONE_NORMAL] = end_pfn - dma_end_pfn; | ||
151 | holes[ZONE_NORMAL] = e820_hole_size(dma_end_pfn, end_pfn); | ||
152 | |||
153 | } else { | ||
154 | zones[ZONE_NORMAL] = end_pfn - start_pfn; | ||
155 | holes[ZONE_NORMAL] = e820_hole_size(start_pfn, end_pfn); | ||
156 | } | ||
157 | |||
158 | free_area_init_node(nodeid, NODE_DATA(nodeid), zones, | 161 | free_area_init_node(nodeid, NODE_DATA(nodeid), zones, |
159 | start_pfn, holes); | 162 | start_pfn, holes); |
160 | } | 163 | } |
@@ -171,7 +174,7 @@ void __init numa_init_array(void) | |||
171 | for (i = 0; i < NR_CPUS; i++) { | 174 | for (i = 0; i < NR_CPUS; i++) { |
172 | if (cpu_to_node[i] != NUMA_NO_NODE) | 175 | if (cpu_to_node[i] != NUMA_NO_NODE) |
173 | continue; | 176 | continue; |
174 | cpu_to_node[i] = rr; | 177 | numa_set_node(i, rr); |
175 | rr = next_node(rr, node_online_map); | 178 | rr = next_node(rr, node_online_map); |
176 | if (rr == MAX_NUMNODES) | 179 | if (rr == MAX_NUMNODES) |
177 | rr = first_node(node_online_map); | 180 | rr = first_node(node_online_map); |
@@ -205,8 +208,6 @@ static int numa_emulation(unsigned long start_pfn, unsigned long end_pfn) | |||
205 | if (i == numa_fake-1) | 208 | if (i == numa_fake-1) |
206 | sz = (end_pfn<<PAGE_SHIFT) - nodes[i].start; | 209 | sz = (end_pfn<<PAGE_SHIFT) - nodes[i].start; |
207 | nodes[i].end = nodes[i].start + sz; | 210 | nodes[i].end = nodes[i].start + sz; |
208 | if (i != numa_fake-1) | ||
209 | nodes[i].end--; | ||
210 | printk(KERN_INFO "Faking node %d at %016Lx-%016Lx (%LuMB)\n", | 211 | printk(KERN_INFO "Faking node %d at %016Lx-%016Lx (%LuMB)\n", |
211 | i, | 212 | i, |
212 | nodes[i].start, nodes[i].end, | 213 | nodes[i].start, nodes[i].end, |
@@ -257,7 +258,7 @@ void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn) | |||
257 | nodes_clear(node_online_map); | 258 | nodes_clear(node_online_map); |
258 | node_set_online(0); | 259 | node_set_online(0); |
259 | for (i = 0; i < NR_CPUS; i++) | 260 | for (i = 0; i < NR_CPUS; i++) |
260 | cpu_to_node[i] = 0; | 261 | numa_set_node(i, 0); |
261 | node_to_cpumask[0] = cpumask_of_cpu(0); | 262 | node_to_cpumask[0] = cpumask_of_cpu(0); |
262 | setup_node_bootmem(0, start_pfn << PAGE_SHIFT, end_pfn << PAGE_SHIFT); | 263 | setup_node_bootmem(0, start_pfn << PAGE_SHIFT, end_pfn << PAGE_SHIFT); |
263 | } | 264 | } |
@@ -267,6 +268,12 @@ __cpuinit void numa_add_cpu(int cpu) | |||
267 | set_bit(cpu, &node_to_cpumask[cpu_to_node(cpu)]); | 268 | set_bit(cpu, &node_to_cpumask[cpu_to_node(cpu)]); |
268 | } | 269 | } |
269 | 270 | ||
271 | void __cpuinit numa_set_node(int cpu, int node) | ||
272 | { | ||
273 | cpu_pda[cpu].nodenumber = node; | ||
274 | cpu_to_node[cpu] = node; | ||
275 | } | ||
276 | |||
270 | unsigned long __init numa_free_all_bootmem(void) | 277 | unsigned long __init numa_free_all_bootmem(void) |
271 | { | 278 | { |
272 | int i; | 279 | int i; |
@@ -277,9 +284,26 @@ unsigned long __init numa_free_all_bootmem(void) | |||
277 | return pages; | 284 | return pages; |
278 | } | 285 | } |
279 | 286 | ||
287 | #ifdef CONFIG_SPARSEMEM | ||
288 | static void __init arch_sparse_init(void) | ||
289 | { | ||
290 | int i; | ||
291 | |||
292 | for_each_online_node(i) | ||
293 | memory_present(i, node_start_pfn(i), node_end_pfn(i)); | ||
294 | |||
295 | sparse_init(); | ||
296 | } | ||
297 | #else | ||
298 | #define arch_sparse_init() do {} while (0) | ||
299 | #endif | ||
300 | |||
280 | void __init paging_init(void) | 301 | void __init paging_init(void) |
281 | { | 302 | { |
282 | int i; | 303 | int i; |
304 | |||
305 | arch_sparse_init(); | ||
306 | |||
283 | for_each_online_node(i) { | 307 | for_each_online_node(i) { |
284 | setup_node_zones(i); | 308 | setup_node_zones(i); |
285 | } | 309 | } |
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c index 4b2e844c15a7..33340bd1e328 100644 --- a/arch/x86_64/mm/srat.c +++ b/arch/x86_64/mm/srat.c | |||
@@ -71,8 +71,6 @@ static __init void cutoff_node(int i, unsigned long start, unsigned long end) | |||
71 | nd->start = nd->end; | 71 | nd->start = nd->end; |
72 | } | 72 | } |
73 | if (nd->end > end) { | 73 | if (nd->end > end) { |
74 | if (!(end & 0xfff)) | ||
75 | end--; | ||
76 | nd->end = end; | 74 | nd->end = end; |
77 | if (nd->start > nd->end) | 75 | if (nd->start > nd->end) |
78 | nd->start = nd->end; | 76 | nd->start = nd->end; |
@@ -166,8 +164,6 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma) | |||
166 | if (nd->end < end) | 164 | if (nd->end < end) |
167 | nd->end = end; | 165 | nd->end = end; |
168 | } | 166 | } |
169 | if (!(nd->end & 0xfff)) | ||
170 | nd->end--; | ||
171 | printk(KERN_INFO "SRAT: Node %u PXM %u %Lx-%Lx\n", node, pxm, | 167 | printk(KERN_INFO "SRAT: Node %u PXM %u %Lx-%Lx\n", node, pxm, |
172 | nd->start, nd->end); | 168 | nd->start, nd->end); |
173 | } | 169 | } |
@@ -203,7 +199,7 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end) | |||
203 | if (cpu_to_node[i] == NUMA_NO_NODE) | 199 | if (cpu_to_node[i] == NUMA_NO_NODE) |
204 | continue; | 200 | continue; |
205 | if (!node_isset(cpu_to_node[i], nodes_parsed)) | 201 | if (!node_isset(cpu_to_node[i], nodes_parsed)) |
206 | cpu_to_node[i] = NUMA_NO_NODE; | 202 | numa_set_node(i, NUMA_NO_NODE); |
207 | } | 203 | } |
208 | numa_init_array(); | 204 | numa_init_array(); |
209 | return 0; | 205 | return 0; |
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 6a4da417c16b..606f8733a776 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/list.h> | 28 | #include <linux/list.h> |
29 | #include <linux/sched.h> | 29 | #include <linux/sched.h> |
30 | #include <linux/pm.h> | 30 | #include <linux/pm.h> |
31 | #include <linux/pm_legacy.h> | ||
31 | #include <linux/device.h> | 32 | #include <linux/device.h> |
32 | #include <linux/proc_fs.h> | 33 | #include <linux/proc_fs.h> |
33 | #ifdef CONFIG_X86 | 34 | #ifdef CONFIG_X86 |
@@ -754,7 +755,7 @@ static int __init acpi_init(void) | |||
754 | result = acpi_bus_init(); | 755 | result = acpi_bus_init(); |
755 | 756 | ||
756 | if (!result) { | 757 | if (!result) { |
757 | #ifdef CONFIG_PM | 758 | #ifdef CONFIG_PM_LEGACY |
758 | if (!PM_IS_ACTIVE()) | 759 | if (!PM_IS_ACTIVE()) |
759 | pm_active = 1; | 760 | pm_active = 1; |
760 | else { | 761 | else { |
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 98f6c02d6790..59dacb6552c0 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -526,18 +526,23 @@ request_firmware_work_func(void *arg) | |||
526 | { | 526 | { |
527 | struct firmware_work *fw_work = arg; | 527 | struct firmware_work *fw_work = arg; |
528 | const struct firmware *fw; | 528 | const struct firmware *fw; |
529 | int ret; | ||
529 | if (!arg) { | 530 | if (!arg) { |
530 | WARN_ON(1); | 531 | WARN_ON(1); |
531 | return 0; | 532 | return 0; |
532 | } | 533 | } |
533 | daemonize("%s/%s", "firmware", fw_work->name); | 534 | daemonize("%s/%s", "firmware", fw_work->name); |
534 | _request_firmware(&fw, fw_work->name, fw_work->device, | 535 | ret = _request_firmware(&fw, fw_work->name, fw_work->device, |
535 | fw_work->hotplug); | 536 | fw_work->hotplug); |
536 | fw_work->cont(fw, fw_work->context); | 537 | if (ret < 0) |
537 | release_firmware(fw); | 538 | fw_work->cont(NULL, fw_work->context); |
539 | else { | ||
540 | fw_work->cont(fw, fw_work->context); | ||
541 | release_firmware(fw); | ||
542 | } | ||
538 | module_put(fw_work->module); | 543 | module_put(fw_work->module); |
539 | kfree(fw_work); | 544 | kfree(fw_work); |
540 | return 0; | 545 | return ret; |
541 | } | 546 | } |
542 | 547 | ||
543 | /** | 548 | /** |
@@ -586,6 +591,8 @@ request_firmware_nowait( | |||
586 | 591 | ||
587 | if (ret < 0) { | 592 | if (ret < 0) { |
588 | fw_work->cont(NULL, fw_work->context); | 593 | fw_work->cont(NULL, fw_work->context); |
594 | module_put(fw_work->module); | ||
595 | kfree(fw_work); | ||
589 | return ret; | 596 | return ret; |
590 | } | 597 | } |
591 | return 0; | 598 | return 0; |
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index 3226aa11c6ef..2942d32280a5 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c | |||
@@ -255,7 +255,7 @@ scsi_cmd_stack_free(int ctlr) | |||
255 | #define DEVICETYPE(n) (n<0 || n>MAX_SCSI_DEVICE_CODE) ? \ | 255 | #define DEVICETYPE(n) (n<0 || n>MAX_SCSI_DEVICE_CODE) ? \ |
256 | "Unknown" : scsi_device_types[n] | 256 | "Unknown" : scsi_device_types[n] |
257 | 257 | ||
258 | #if 1 | 258 | #if 0 |
259 | static int xmargin=8; | 259 | static int xmargin=8; |
260 | static int amargin=60; | 260 | static int amargin=60; |
261 | 261 | ||
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 59e5982a5db3..c0233efabeba 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c | |||
@@ -1188,7 +1188,7 @@ static void pkt_count_states(struct pktcdvd_device *pd, int *states) | |||
1188 | struct packet_data *pkt; | 1188 | struct packet_data *pkt; |
1189 | int i; | 1189 | int i; |
1190 | 1190 | ||
1191 | for (i = 0; i <= PACKET_NUM_STATES; i++) | 1191 | for (i = 0; i < PACKET_NUM_STATES; i++) |
1192 | states[i] = 0; | 1192 | states[i] = 0; |
1193 | 1193 | ||
1194 | spin_lock(&pd->cdrw.active_list_lock); | 1194 | spin_lock(&pd->cdrw.active_list_lock); |
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index fdf4370db994..970f70d498f4 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -735,7 +735,7 @@ config SGI_IP27_RTC | |||
735 | 735 | ||
736 | config GEN_RTC | 736 | config GEN_RTC |
737 | tristate "Generic /dev/rtc emulation" | 737 | tristate "Generic /dev/rtc emulation" |
738 | depends on RTC!=y && !IA64 && !ARM && !PPC64 && !M32R && !SPARC32 && !SPARC64 | 738 | depends on RTC!=y && !IA64 && !ARM && !M32R && !SPARC32 && !SPARC64 |
739 | ---help--- | 739 | ---help--- |
740 | If you say Y here and create a character special file /dev/rtc with | 740 | If you say Y here and create a character special file /dev/rtc with |
741 | major number 10 and minor number 135 using mknod ("man mknod"), you | 741 | major number 10 and minor number 135 using mknod ("man mknod"), you |
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 78ce98a69f37..76589782adcb 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c | |||
@@ -57,9 +57,8 @@ static int nr_garts; | |||
57 | static struct pci_dev * hammers[MAX_HAMMER_GARTS]; | 57 | static struct pci_dev * hammers[MAX_HAMMER_GARTS]; |
58 | 58 | ||
59 | static struct resource *aperture_resource; | 59 | static struct resource *aperture_resource; |
60 | static int __initdata agp_try_unsupported; | 60 | static int __initdata agp_try_unsupported = 1; |
61 | 61 | ||
62 | static int gart_iterator; | ||
63 | #define for_each_nb() for(gart_iterator=0;gart_iterator<nr_garts;gart_iterator++) | 62 | #define for_each_nb() for(gart_iterator=0;gart_iterator<nr_garts;gart_iterator++) |
64 | 63 | ||
65 | static void flush_amd64_tlb(struct pci_dev *dev) | 64 | static void flush_amd64_tlb(struct pci_dev *dev) |
@@ -73,6 +72,7 @@ static void flush_amd64_tlb(struct pci_dev *dev) | |||
73 | 72 | ||
74 | static void amd64_tlbflush(struct agp_memory *temp) | 73 | static void amd64_tlbflush(struct agp_memory *temp) |
75 | { | 74 | { |
75 | int gart_iterator; | ||
76 | for_each_nb() | 76 | for_each_nb() |
77 | flush_amd64_tlb(hammers[gart_iterator]); | 77 | flush_amd64_tlb(hammers[gart_iterator]); |
78 | } | 78 | } |
@@ -222,6 +222,7 @@ static struct aper_size_info_32 amd_8151_sizes[7] = | |||
222 | static int amd_8151_configure(void) | 222 | static int amd_8151_configure(void) |
223 | { | 223 | { |
224 | unsigned long gatt_bus = virt_to_gart(agp_bridge->gatt_table_real); | 224 | unsigned long gatt_bus = virt_to_gart(agp_bridge->gatt_table_real); |
225 | int gart_iterator; | ||
225 | 226 | ||
226 | /* Configure AGP regs in each x86-64 host bridge. */ | 227 | /* Configure AGP regs in each x86-64 host bridge. */ |
227 | for_each_nb() { | 228 | for_each_nb() { |
@@ -235,7 +236,7 @@ static int amd_8151_configure(void) | |||
235 | static void amd64_cleanup(void) | 236 | static void amd64_cleanup(void) |
236 | { | 237 | { |
237 | u32 tmp; | 238 | u32 tmp; |
238 | 239 | int gart_iterator; | |
239 | for_each_nb() { | 240 | for_each_nb() { |
240 | /* disable gart translation */ | 241 | /* disable gart translation */ |
241 | pci_read_config_dword (hammers[gart_iterator], AMD64_GARTAPERTURECTL, &tmp); | 242 | pci_read_config_dword (hammers[gart_iterator], AMD64_GARTAPERTURECTL, &tmp); |
@@ -697,6 +698,16 @@ static struct pci_device_id agp_amd64_pci_table[] = { | |||
697 | .subvendor = PCI_ANY_ID, | 698 | .subvendor = PCI_ANY_ID, |
698 | .subdevice = PCI_ANY_ID, | 699 | .subdevice = PCI_ANY_ID, |
699 | }, | 700 | }, |
701 | /* ALI/ULI M1695 */ | ||
702 | { | ||
703 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
704 | .class_mask = ~0, | ||
705 | .vendor = PCI_VENDOR_ID_AL, | ||
706 | .device = 0x1689, | ||
707 | .subvendor = PCI_ANY_ID, | ||
708 | .subdevice = PCI_ANY_ID, | ||
709 | }, | ||
710 | |||
700 | { } | 711 | { } |
701 | }; | 712 | }; |
702 | 713 | ||
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index c8255312b8c1..50947e38501a 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c | |||
@@ -557,6 +557,10 @@ static struct agp_device_ids uninorth_agp_device_ids[] __devinitdata = { | |||
557 | .device_id = PCI_DEVICE_ID_APPLE_U3H_AGP, | 557 | .device_id = PCI_DEVICE_ID_APPLE_U3H_AGP, |
558 | .chipset_name = "U3H", | 558 | .chipset_name = "U3H", |
559 | }, | 559 | }, |
560 | { | ||
561 | .device_id = PCI_DEVICE_ID_APPLE_IPID2_AGP, | ||
562 | .chipset_name = "UniNorth/Intrepid2", | ||
563 | }, | ||
560 | }; | 564 | }; |
561 | 565 | ||
562 | static int __devinit agp_uninorth_probe(struct pci_dev *pdev, | 566 | static int __devinit agp_uninorth_probe(struct pci_dev *pdev, |
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index d16bd4b5c117..6b302a930e5f 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -48,7 +48,7 @@ | |||
48 | 48 | ||
49 | #define PFX "IPMI message handler: " | 49 | #define PFX "IPMI message handler: " |
50 | 50 | ||
51 | #define IPMI_DRIVER_VERSION "36.0" | 51 | #define IPMI_DRIVER_VERSION "38.0" |
52 | 52 | ||
53 | static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void); | 53 | static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void); |
54 | static int ipmi_init_msghandler(void); | 54 | static int ipmi_init_msghandler(void); |
diff --git a/drivers/char/pcmcia/Kconfig b/drivers/char/pcmcia/Kconfig index d22bfdc13563..27c1179ee527 100644 --- a/drivers/char/pcmcia/Kconfig +++ b/drivers/char/pcmcia/Kconfig | |||
@@ -18,5 +18,29 @@ config SYNCLINK_CS | |||
18 | The module will be called synclinkmp. If you want to do that, say M | 18 | The module will be called synclinkmp. If you want to do that, say M |
19 | here. | 19 | here. |
20 | 20 | ||
21 | config CARDMAN_4000 | ||
22 | tristate "Omnikey Cardman 4000 support" | ||
23 | depends on PCMCIA | ||
24 | help | ||
25 | Enable support for the Omnikey Cardman 4000 PCMCIA Smartcard | ||
26 | reader. | ||
27 | |||
28 | This kernel driver requires additional userspace support, either | ||
29 | by the vendor-provided PC/SC ifd_handler (http://www.omnikey.com/), | ||
30 | or via the cm4000 backend of OpenCT (http://www.opensc.com/). | ||
31 | |||
32 | config CARDMAN_4040 | ||
33 | tristate "Omnikey CardMan 4040 support" | ||
34 | depends on PCMCIA | ||
35 | help | ||
36 | Enable support for the Omnikey CardMan 4040 PCMCIA Smartcard | ||
37 | reader. | ||
38 | |||
39 | This card is basically a USB CCID device connected to a FIFO | ||
40 | in I/O space. To use the kernel driver, you will need either the | ||
41 | PC/SC ifdhandler provided from the Omnikey homepage | ||
42 | (http://www.omnikey.com/), or a current development version of OpenCT | ||
43 | (http://www.opensc.org/). | ||
44 | |||
21 | endmenu | 45 | endmenu |
22 | 46 | ||
diff --git a/drivers/char/pcmcia/Makefile b/drivers/char/pcmcia/Makefile index 1fcd4c591958..0aae20985d57 100644 --- a/drivers/char/pcmcia/Makefile +++ b/drivers/char/pcmcia/Makefile | |||
@@ -5,3 +5,5 @@ | |||
5 | # | 5 | # |
6 | 6 | ||
7 | obj-$(CONFIG_SYNCLINK_CS) += synclink_cs.o | 7 | obj-$(CONFIG_SYNCLINK_CS) += synclink_cs.o |
8 | obj-$(CONFIG_CARDMAN_4000) += cm4000_cs.o | ||
9 | obj-$(CONFIG_CARDMAN_4040) += cm4040_cs.o | ||
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c new file mode 100644 index 000000000000..ef011ef5dc46 --- /dev/null +++ b/drivers/char/pcmcia/cm4000_cs.c | |||
@@ -0,0 +1,2078 @@ | |||
1 | /* | ||
2 | * A driver for the PCMCIA Smartcard Reader "Omnikey CardMan Mobile 4000" | ||
3 | * | ||
4 | * cm4000_cs.c support.linux@omnikey.com | ||
5 | * | ||
6 | * Tue Oct 23 11:32:43 GMT 2001 herp - cleaned up header files | ||
7 | * Sun Jan 20 10:11:15 MET 2002 herp - added modversion header files | ||
8 | * Thu Nov 14 16:34:11 GMT 2002 mh - added PPS functionality | ||
9 | * Tue Nov 19 16:36:27 GMT 2002 mh - added SUSPEND/RESUME functionailty | ||
10 | * Wed Jul 28 12:55:01 CEST 2004 mh - kernel 2.6 adjustments | ||
11 | * | ||
12 | * current version: 2.4.0gm4 | ||
13 | * | ||
14 | * (C) 2000,2001,2002,2003,2004 Omnikey AG | ||
15 | * | ||
16 | * (C) 2005 Harald Welte <laforge@gnumonks.org> | ||
17 | * - Adhere to Kernel CodingStyle | ||
18 | * - Port to 2.6.13 "new" style PCMCIA | ||
19 | * - Check for copy_{from,to}_user return values | ||
20 | * - Use nonseekable_open() | ||
21 | * | ||
22 | * All rights reserved. Licensed under dual BSD/GPL license. | ||
23 | */ | ||
24 | |||
25 | /* #define PCMCIA_DEBUG 6 */ | ||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/fs.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <asm/uaccess.h> | ||
34 | #include <asm/io.h> | ||
35 | |||
36 | #include <pcmcia/cs_types.h> | ||
37 | #include <pcmcia/cs.h> | ||
38 | #include <pcmcia/cistpl.h> | ||
39 | #include <pcmcia/cisreg.h> | ||
40 | #include <pcmcia/ciscode.h> | ||
41 | #include <pcmcia/ds.h> | ||
42 | |||
43 | #include <linux/cm4000_cs.h> | ||
44 | |||
45 | /* #define ATR_CSUM */ | ||
46 | |||
47 | #ifdef PCMCIA_DEBUG | ||
48 | #define reader_to_dev(x) (&handle_to_dev(x->link.handle)) | ||
49 | static int pc_debug = PCMCIA_DEBUG; | ||
50 | module_param(pc_debug, int, 0600); | ||
51 | #define DEBUGP(n, rdr, x, args...) do { \ | ||
52 | if (pc_debug >= (n)) \ | ||
53 | dev_printk(KERN_DEBUG, reader_to_dev(rdr), "%s:" x, \ | ||
54 | __FUNCTION__ , ## args); \ | ||
55 | } while (0) | ||
56 | #else | ||
57 | #define DEBUGP(n, rdr, x, args...) | ||
58 | #endif | ||
59 | static char *version = "cm4000_cs.c v2.4.0gm5 - All bugs added by Harald Welte"; | ||
60 | |||
61 | #define T_1SEC (HZ) | ||
62 | #define T_10MSEC msecs_to_jiffies(10) | ||
63 | #define T_20MSEC msecs_to_jiffies(20) | ||
64 | #define T_40MSEC msecs_to_jiffies(40) | ||
65 | #define T_50MSEC msecs_to_jiffies(50) | ||
66 | #define T_100MSEC msecs_to_jiffies(100) | ||
67 | #define T_500MSEC msecs_to_jiffies(500) | ||
68 | |||
69 | static void cm4000_detach(dev_link_t *link); | ||
70 | static void cm4000_release(dev_link_t *link); | ||
71 | |||
72 | static int major; /* major number we get from the kernel */ | ||
73 | |||
74 | /* note: the first state has to have number 0 always */ | ||
75 | |||
76 | #define M_FETCH_ATR 0 | ||
77 | #define M_TIMEOUT_WAIT 1 | ||
78 | #define M_READ_ATR_LEN 2 | ||
79 | #define M_READ_ATR 3 | ||
80 | #define M_ATR_PRESENT 4 | ||
81 | #define M_BAD_CARD 5 | ||
82 | #define M_CARDOFF 6 | ||
83 | |||
84 | #define LOCK_IO 0 | ||
85 | #define LOCK_MONITOR 1 | ||
86 | |||
87 | #define IS_AUTOPPS_ACT 6 | ||
88 | #define IS_PROCBYTE_PRESENT 7 | ||
89 | #define IS_INVREV 8 | ||
90 | #define IS_ANY_T0 9 | ||
91 | #define IS_ANY_T1 10 | ||
92 | #define IS_ATR_PRESENT 11 | ||
93 | #define IS_ATR_VALID 12 | ||
94 | #define IS_CMM_ABSENT 13 | ||
95 | #define IS_BAD_LENGTH 14 | ||
96 | #define IS_BAD_CSUM 15 | ||
97 | #define IS_BAD_CARD 16 | ||
98 | |||
99 | #define REG_FLAGS0(x) (x + 0) | ||
100 | #define REG_FLAGS1(x) (x + 1) | ||
101 | #define REG_NUM_BYTES(x) (x + 2) | ||
102 | #define REG_BUF_ADDR(x) (x + 3) | ||
103 | #define REG_BUF_DATA(x) (x + 4) | ||
104 | #define REG_NUM_SEND(x) (x + 5) | ||
105 | #define REG_BAUDRATE(x) (x + 6) | ||
106 | #define REG_STOPBITS(x) (x + 7) | ||
107 | |||
108 | struct cm4000_dev { | ||
109 | dev_link_t link; /* pcmcia link */ | ||
110 | dev_node_t node; /* OS node (major,minor) */ | ||
111 | |||
112 | unsigned char atr[MAX_ATR]; | ||
113 | unsigned char rbuf[512]; | ||
114 | unsigned char sbuf[512]; | ||
115 | |||
116 | wait_queue_head_t devq; /* when removing cardman must not be | ||
117 | zeroed! */ | ||
118 | |||
119 | wait_queue_head_t ioq; /* if IO is locked, wait on this Q */ | ||
120 | wait_queue_head_t atrq; /* wait for ATR valid */ | ||
121 | wait_queue_head_t readq; /* used by write to wake blk.read */ | ||
122 | |||
123 | /* warning: do not move this fields. | ||
124 | * initialising to zero depends on it - see ZERO_DEV below. */ | ||
125 | unsigned char atr_csum; | ||
126 | unsigned char atr_len_retry; | ||
127 | unsigned short atr_len; | ||
128 | unsigned short rlen; /* bytes avail. after write */ | ||
129 | unsigned short rpos; /* latest read pos. write zeroes */ | ||
130 | unsigned char procbyte; /* T=0 procedure byte */ | ||
131 | unsigned char mstate; /* state of card monitor */ | ||
132 | unsigned char cwarn; /* slow down warning */ | ||
133 | unsigned char flags0; /* cardman IO-flags 0 */ | ||
134 | unsigned char flags1; /* cardman IO-flags 1 */ | ||
135 | unsigned int mdelay; /* variable monitor speeds, in jiffies */ | ||
136 | |||
137 | unsigned int baudv; /* baud value for speed */ | ||
138 | unsigned char ta1; | ||
139 | unsigned char proto; /* T=0, T=1, ... */ | ||
140 | unsigned long flags; /* lock+flags (MONITOR,IO,ATR) * for concurrent | ||
141 | access */ | ||
142 | |||
143 | unsigned char pts[4]; | ||
144 | |||
145 | struct timer_list timer; /* used to keep monitor running */ | ||
146 | int monitor_running; | ||
147 | }; | ||
148 | |||
149 | #define ZERO_DEV(dev) \ | ||
150 | memset(&dev->atr_csum,0, \ | ||
151 | sizeof(struct cm4000_dev) - \ | ||
152 | /*link*/ sizeof(dev_link_t) - \ | ||
153 | /*node*/ sizeof(dev_node_t) - \ | ||
154 | /*atr*/ MAX_ATR*sizeof(char) - \ | ||
155 | /*rbuf*/ 512*sizeof(char) - \ | ||
156 | /*sbuf*/ 512*sizeof(char) - \ | ||
157 | /*queue*/ 4*sizeof(wait_queue_head_t)) | ||
158 | |||
159 | static dev_info_t dev_info = MODULE_NAME; | ||
160 | static dev_link_t *dev_table[CM4000_MAX_DEV]; | ||
161 | |||
162 | /* This table doesn't use spaces after the comma between fields and thus | ||
163 | * violates CodingStyle. However, I don't really think wrapping it around will | ||
164 | * make it any clearer to read -HW */ | ||
165 | static unsigned char fi_di_table[10][14] = { | ||
166 | /*FI 00 01 02 03 04 05 06 07 08 09 10 11 12 13 */ | ||
167 | /*DI */ | ||
168 | /* 0 */ {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, | ||
169 | /* 1 */ {0x01,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x91,0x11,0x11,0x11,0x11}, | ||
170 | /* 2 */ {0x02,0x12,0x22,0x32,0x11,0x11,0x11,0x11,0x11,0x92,0xA2,0xB2,0x11,0x11}, | ||
171 | /* 3 */ {0x03,0x13,0x23,0x33,0x43,0x53,0x63,0x11,0x11,0x93,0xA3,0xB3,0xC3,0xD3}, | ||
172 | /* 4 */ {0x04,0x14,0x24,0x34,0x44,0x54,0x64,0x11,0x11,0x94,0xA4,0xB4,0xC4,0xD4}, | ||
173 | /* 5 */ {0x00,0x15,0x25,0x35,0x45,0x55,0x65,0x11,0x11,0x95,0xA5,0xB5,0xC5,0xD5}, | ||
174 | /* 6 */ {0x06,0x16,0x26,0x36,0x46,0x56,0x66,0x11,0x11,0x96,0xA6,0xB6,0xC6,0xD6}, | ||
175 | /* 7 */ {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, | ||
176 | /* 8 */ {0x08,0x11,0x28,0x38,0x48,0x58,0x68,0x11,0x11,0x98,0xA8,0xB8,0xC8,0xD8}, | ||
177 | /* 9 */ {0x09,0x19,0x29,0x39,0x49,0x59,0x69,0x11,0x11,0x99,0xA9,0xB9,0xC9,0xD9} | ||
178 | }; | ||
179 | |||
180 | #ifndef PCMCIA_DEBUG | ||
181 | #define xoutb outb | ||
182 | #define xinb inb | ||
183 | #else | ||
184 | static inline void xoutb(unsigned char val, unsigned short port) | ||
185 | { | ||
186 | if (pc_debug >= 7) | ||
187 | printk(KERN_DEBUG "outb(val=%.2x,port=%.4x)\n", val, port); | ||
188 | outb(val, port); | ||
189 | } | ||
190 | static inline unsigned char xinb(unsigned short port) | ||
191 | { | ||
192 | unsigned char val; | ||
193 | |||
194 | val = inb(port); | ||
195 | if (pc_debug >= 7) | ||
196 | printk(KERN_DEBUG "%.2x=inb(%.4x)\n", val, port); | ||
197 | |||
198 | return val; | ||
199 | } | ||
200 | #endif | ||
201 | |||
202 | #define b_0000 15 | ||
203 | #define b_0001 14 | ||
204 | #define b_0010 13 | ||
205 | #define b_0011 12 | ||
206 | #define b_0100 11 | ||
207 | #define b_0101 10 | ||
208 | #define b_0110 9 | ||
209 | #define b_0111 8 | ||
210 | #define b_1000 7 | ||
211 | #define b_1001 6 | ||
212 | #define b_1010 5 | ||
213 | #define b_1011 4 | ||
214 | #define b_1100 3 | ||
215 | #define b_1101 2 | ||
216 | #define b_1110 1 | ||
217 | #define b_1111 0 | ||
218 | |||
219 | static unsigned char irtab[16] = { | ||
220 | b_0000, b_1000, b_0100, b_1100, | ||
221 | b_0010, b_1010, b_0110, b_1110, | ||
222 | b_0001, b_1001, b_0101, b_1101, | ||
223 | b_0011, b_1011, b_0111, b_1111 | ||
224 | }; | ||
225 | |||
226 | static void str_invert_revert(unsigned char *b, int len) | ||
227 | { | ||
228 | int i; | ||
229 | |||
230 | for (i = 0; i < len; i++) | ||
231 | b[i] = (irtab[b[i] & 0x0f] << 4) | irtab[b[i] >> 4]; | ||
232 | } | ||
233 | |||
234 | static unsigned char invert_revert(unsigned char ch) | ||
235 | { | ||
236 | return (irtab[ch & 0x0f] << 4) | irtab[ch >> 4]; | ||
237 | } | ||
238 | |||
239 | #define ATRLENCK(dev,pos) \ | ||
240 | if (pos>=dev->atr_len || pos>=MAX_ATR) \ | ||
241 | goto return_0; | ||
242 | |||
243 | static unsigned int calc_baudv(unsigned char fidi) | ||
244 | { | ||
245 | unsigned int wcrcf, wbrcf, fi_rfu, di_rfu; | ||
246 | |||
247 | fi_rfu = 372; | ||
248 | di_rfu = 1; | ||
249 | |||
250 | /* FI */ | ||
251 | switch ((fidi >> 4) & 0x0F) { | ||
252 | case 0x00: | ||
253 | wcrcf = 372; | ||
254 | break; | ||
255 | case 0x01: | ||
256 | wcrcf = 372; | ||
257 | break; | ||
258 | case 0x02: | ||
259 | wcrcf = 558; | ||
260 | break; | ||
261 | case 0x03: | ||
262 | wcrcf = 744; | ||
263 | break; | ||
264 | case 0x04: | ||
265 | wcrcf = 1116; | ||
266 | break; | ||
267 | case 0x05: | ||
268 | wcrcf = 1488; | ||
269 | break; | ||
270 | case 0x06: | ||
271 | wcrcf = 1860; | ||
272 | break; | ||
273 | case 0x07: | ||
274 | wcrcf = fi_rfu; | ||
275 | break; | ||
276 | case 0x08: | ||
277 | wcrcf = fi_rfu; | ||
278 | break; | ||
279 | case 0x09: | ||
280 | wcrcf = 512; | ||
281 | break; | ||
282 | case 0x0A: | ||
283 | wcrcf = 768; | ||
284 | break; | ||
285 | case 0x0B: | ||
286 | wcrcf = 1024; | ||
287 | break; | ||
288 | case 0x0C: | ||
289 | wcrcf = 1536; | ||
290 | break; | ||
291 | case 0x0D: | ||
292 | wcrcf = 2048; | ||
293 | break; | ||
294 | default: | ||
295 | wcrcf = fi_rfu; | ||
296 | break; | ||
297 | } | ||
298 | |||
299 | /* DI */ | ||
300 | switch (fidi & 0x0F) { | ||
301 | case 0x00: | ||
302 | wbrcf = di_rfu; | ||
303 | break; | ||
304 | case 0x01: | ||
305 | wbrcf = 1; | ||
306 | break; | ||
307 | case 0x02: | ||
308 | wbrcf = 2; | ||
309 | break; | ||
310 | case 0x03: | ||
311 | wbrcf = 4; | ||
312 | break; | ||
313 | case 0x04: | ||
314 | wbrcf = 8; | ||
315 | break; | ||
316 | case 0x05: | ||
317 | wbrcf = 16; | ||
318 | break; | ||
319 | case 0x06: | ||
320 | wbrcf = 32; | ||
321 | break; | ||
322 | case 0x07: | ||
323 | wbrcf = di_rfu; | ||
324 | break; | ||
325 | case 0x08: | ||
326 | wbrcf = 12; | ||
327 | break; | ||
328 | case 0x09: | ||
329 | wbrcf = 20; | ||
330 | break; | ||
331 | default: | ||
332 | wbrcf = di_rfu; | ||
333 | break; | ||
334 | } | ||
335 | |||
336 | return (wcrcf / wbrcf); | ||
337 | } | ||
338 | |||
339 | static unsigned short io_read_num_rec_bytes(ioaddr_t iobase, unsigned short *s) | ||
340 | { | ||
341 | unsigned short tmp; | ||
342 | |||
343 | tmp = *s = 0; | ||
344 | do { | ||
345 | *s = tmp; | ||
346 | tmp = inb(REG_NUM_BYTES(iobase)) | | ||
347 | (inb(REG_FLAGS0(iobase)) & 4 ? 0x100 : 0); | ||
348 | } while (tmp != *s); | ||
349 | |||
350 | return *s; | ||
351 | } | ||
352 | |||
353 | static int parse_atr(struct cm4000_dev *dev) | ||
354 | { | ||
355 | unsigned char any_t1, any_t0; | ||
356 | unsigned char ch, ifno; | ||
357 | int ix, done; | ||
358 | |||
359 | DEBUGP(3, dev, "-> parse_atr: dev->atr_len = %i\n", dev->atr_len); | ||
360 | |||
361 | if (dev->atr_len < 3) { | ||
362 | DEBUGP(5, dev, "parse_atr: atr_len < 3\n"); | ||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | if (dev->atr[0] == 0x3f) | ||
367 | set_bit(IS_INVREV, &dev->flags); | ||
368 | else | ||
369 | clear_bit(IS_INVREV, &dev->flags); | ||
370 | ix = 1; | ||
371 | ifno = 1; | ||
372 | ch = dev->atr[1]; | ||
373 | dev->proto = 0; /* XXX PROTO */ | ||
374 | any_t1 = any_t0 = done = 0; | ||
375 | dev->ta1 = 0x11; /* defaults to 9600 baud */ | ||
376 | do { | ||
377 | if (ifno == 1 && (ch & 0x10)) { | ||
378 | /* read first interface byte and TA1 is present */ | ||
379 | dev->ta1 = dev->atr[2]; | ||
380 | DEBUGP(5, dev, "Card says FiDi is 0x%.2x\n", dev->ta1); | ||
381 | ifno++; | ||
382 | } else if ((ifno == 2) && (ch & 0x10)) { /* TA(2) */ | ||
383 | dev->ta1 = 0x11; | ||
384 | ifno++; | ||
385 | } | ||
386 | |||
387 | DEBUGP(5, dev, "Yi=%.2x\n", ch & 0xf0); | ||
388 | ix += ((ch & 0x10) >> 4) /* no of int.face chars */ | ||
389 | +((ch & 0x20) >> 5) | ||
390 | + ((ch & 0x40) >> 6) | ||
391 | + ((ch & 0x80) >> 7); | ||
392 | /* ATRLENCK(dev,ix); */ | ||
393 | if (ch & 0x80) { /* TDi */ | ||
394 | ch = dev->atr[ix]; | ||
395 | if ((ch & 0x0f)) { | ||
396 | any_t1 = 1; | ||
397 | DEBUGP(5, dev, "card is capable of T=1\n"); | ||
398 | } else { | ||
399 | any_t0 = 1; | ||
400 | DEBUGP(5, dev, "card is capable of T=0\n"); | ||
401 | } | ||
402 | } else | ||
403 | done = 1; | ||
404 | } while (!done); | ||
405 | |||
406 | DEBUGP(5, dev, "ix=%d noHist=%d any_t1=%d\n", | ||
407 | ix, dev->atr[1] & 15, any_t1); | ||
408 | if (ix + 1 + (dev->atr[1] & 0x0f) + any_t1 != dev->atr_len) { | ||
409 | DEBUGP(5, dev, "length error\n"); | ||
410 | return 0; | ||
411 | } | ||
412 | if (any_t0) | ||
413 | set_bit(IS_ANY_T0, &dev->flags); | ||
414 | |||
415 | if (any_t1) { /* compute csum */ | ||
416 | dev->atr_csum = 0; | ||
417 | #ifdef ATR_CSUM | ||
418 | for (i = 1; i < dev->atr_len; i++) | ||
419 | dev->atr_csum ^= dev->atr[i]; | ||
420 | if (dev->atr_csum) { | ||
421 | set_bit(IS_BAD_CSUM, &dev->flags); | ||
422 | DEBUGP(5, dev, "bad checksum\n"); | ||
423 | goto return_0; | ||
424 | } | ||
425 | #endif | ||
426 | if (any_t0 == 0) | ||
427 | dev->proto = 1; /* XXX PROTO */ | ||
428 | set_bit(IS_ANY_T1, &dev->flags); | ||
429 | } | ||
430 | |||
431 | return 1; | ||
432 | } | ||
433 | |||
434 | struct card_fixup { | ||
435 | char atr[12]; | ||
436 | u_int8_t atr_len; | ||
437 | u_int8_t stopbits; | ||
438 | }; | ||
439 | |||
440 | static struct card_fixup card_fixups[] = { | ||
441 | { /* ACOS */ | ||
442 | .atr = { 0x3b, 0xb3, 0x11, 0x00, 0x00, 0x41, 0x01 }, | ||
443 | .atr_len = 7, | ||
444 | .stopbits = 0x03, | ||
445 | }, | ||
446 | { /* Motorola */ | ||
447 | .atr = {0x3b, 0x76, 0x13, 0x00, 0x00, 0x80, 0x62, 0x07, | ||
448 | 0x41, 0x81, 0x81 }, | ||
449 | .atr_len = 11, | ||
450 | .stopbits = 0x04, | ||
451 | }, | ||
452 | }; | ||
453 | |||
454 | static void set_cardparameter(struct cm4000_dev *dev) | ||
455 | { | ||
456 | int i; | ||
457 | ioaddr_t iobase = dev->link.io.BasePort1; | ||
458 | u_int8_t stopbits = 0x02; /* ISO default */ | ||
459 | |||
460 | DEBUGP(3, dev, "-> set_cardparameter\n"); | ||
461 | |||
462 | dev->flags1 = dev->flags1 | (((dev->baudv - 1) & 0x0100) >> 8); | ||
463 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
464 | DEBUGP(5, dev, "flags1 = 0x%02x\n", dev->flags1); | ||
465 | |||
466 | /* set baudrate */ | ||
467 | xoutb((unsigned char)((dev->baudv - 1) & 0xFF), REG_BAUDRATE(iobase)); | ||
468 | |||
469 | DEBUGP(5, dev, "baudv = %i -> write 0x%02x\n", dev->baudv, | ||
470 | ((dev->baudv - 1) & 0xFF)); | ||
471 | |||
472 | /* set stopbits */ | ||
473 | for (i = 0; i < ARRAY_SIZE(card_fixups); i++) { | ||
474 | if (!memcmp(dev->atr, card_fixups[i].atr, | ||
475 | card_fixups[i].atr_len)) | ||
476 | stopbits = card_fixups[i].stopbits; | ||
477 | } | ||
478 | xoutb(stopbits, REG_STOPBITS(iobase)); | ||
479 | |||
480 | DEBUGP(3, dev, "<- set_cardparameter\n"); | ||
481 | } | ||
482 | |||
483 | static int set_protocol(struct cm4000_dev *dev, struct ptsreq *ptsreq) | ||
484 | { | ||
485 | |||
486 | unsigned long tmp, i; | ||
487 | unsigned short num_bytes_read; | ||
488 | unsigned char pts_reply[4]; | ||
489 | ssize_t rc; | ||
490 | ioaddr_t iobase = dev->link.io.BasePort1; | ||
491 | |||
492 | rc = 0; | ||
493 | |||
494 | DEBUGP(3, dev, "-> set_protocol\n"); | ||
495 | DEBUGP(5, dev, "ptsreq->Protocol = 0x%.8x, ptsreq->Flags=0x%.8x, " | ||
496 | "ptsreq->pts1=0x%.2x, ptsreq->pts2=0x%.2x, " | ||
497 | "ptsreq->pts3=0x%.2x\n", (unsigned int)ptsreq->protocol, | ||
498 | (unsigned int)ptsreq->flags, ptsreq->pts1, ptsreq->pts2, | ||
499 | ptsreq->pts3); | ||
500 | |||
501 | /* Fill PTS structure */ | ||
502 | dev->pts[0] = 0xff; | ||
503 | dev->pts[1] = 0x00; | ||
504 | tmp = ptsreq->protocol; | ||
505 | while ((tmp = (tmp >> 1)) > 0) | ||
506 | dev->pts[1]++; | ||
507 | dev->proto = dev->pts[1]; /* Set new protocol */ | ||
508 | dev->pts[1] = (0x01 << 4) | (dev->pts[1]); | ||
509 | |||
510 | /* Correct Fi/Di according to CM4000 Fi/Di table */ | ||
511 | DEBUGP(5, dev, "Ta(1) from ATR is 0x%.2x\n", dev->ta1); | ||
512 | /* set Fi/Di according to ATR TA(1) */ | ||
513 | dev->pts[2] = fi_di_table[dev->ta1 & 0x0F][(dev->ta1 >> 4) & 0x0F]; | ||
514 | |||
515 | /* Calculate PCK character */ | ||
516 | dev->pts[3] = dev->pts[0] ^ dev->pts[1] ^ dev->pts[2]; | ||
517 | |||
518 | DEBUGP(5, dev, "pts0=%.2x, pts1=%.2x, pts2=%.2x, pts3=%.2x\n", | ||
519 | dev->pts[0], dev->pts[1], dev->pts[2], dev->pts[3]); | ||
520 | |||
521 | /* check card convention */ | ||
522 | if (test_bit(IS_INVREV, &dev->flags)) | ||
523 | str_invert_revert(dev->pts, 4); | ||
524 | |||
525 | /* reset SM */ | ||
526 | xoutb(0x80, REG_FLAGS0(iobase)); | ||
527 | |||
528 | /* Enable access to the message buffer */ | ||
529 | DEBUGP(5, dev, "Enable access to the messages buffer\n"); | ||
530 | dev->flags1 = 0x20 /* T_Active */ | ||
531 | | (test_bit(IS_INVREV, &dev->flags) ? 0x02 : 0x00) /* inv parity */ | ||
532 | | ((dev->baudv >> 8) & 0x01); /* MSB-baud */ | ||
533 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
534 | |||
535 | DEBUGP(5, dev, "Enable message buffer -> flags1 = 0x%.2x\n", | ||
536 | dev->flags1); | ||
537 | |||
538 | /* write challenge to the buffer */ | ||
539 | DEBUGP(5, dev, "Write challenge to buffer: "); | ||
540 | for (i = 0; i < 4; i++) { | ||
541 | xoutb(i, REG_BUF_ADDR(iobase)); | ||
542 | xoutb(dev->pts[i], REG_BUF_DATA(iobase)); /* buf data */ | ||
543 | #ifdef PCMCIA_DEBUG | ||
544 | if (pc_debug >= 5) | ||
545 | printk("0x%.2x ", dev->pts[i]); | ||
546 | } | ||
547 | if (pc_debug >= 5) | ||
548 | printk("\n"); | ||
549 | #else | ||
550 | } | ||
551 | #endif | ||
552 | |||
553 | /* set number of bytes to write */ | ||
554 | DEBUGP(5, dev, "Set number of bytes to write\n"); | ||
555 | xoutb(0x04, REG_NUM_SEND(iobase)); | ||
556 | |||
557 | /* Trigger CARDMAN CONTROLLER */ | ||
558 | xoutb(0x50, REG_FLAGS0(iobase)); | ||
559 | |||
560 | /* Monitor progress */ | ||
561 | /* wait for xmit done */ | ||
562 | DEBUGP(5, dev, "Waiting for NumRecBytes getting valid\n"); | ||
563 | |||
564 | for (i = 0; i < 100; i++) { | ||
565 | if (inb(REG_FLAGS0(iobase)) & 0x08) { | ||
566 | DEBUGP(5, dev, "NumRecBytes is valid\n"); | ||
567 | break; | ||
568 | } | ||
569 | mdelay(10); | ||
570 | } | ||
571 | if (i == 100) { | ||
572 | DEBUGP(5, dev, "Timeout waiting for NumRecBytes getting " | ||
573 | "valid\n"); | ||
574 | rc = -EIO; | ||
575 | goto exit_setprotocol; | ||
576 | } | ||
577 | |||
578 | DEBUGP(5, dev, "Reading NumRecBytes\n"); | ||
579 | for (i = 0; i < 100; i++) { | ||
580 | io_read_num_rec_bytes(iobase, &num_bytes_read); | ||
581 | if (num_bytes_read >= 4) { | ||
582 | DEBUGP(2, dev, "NumRecBytes = %i\n", num_bytes_read); | ||
583 | break; | ||
584 | } | ||
585 | mdelay(10); | ||
586 | } | ||
587 | |||
588 | /* check whether it is a short PTS reply? */ | ||
589 | if (num_bytes_read == 3) | ||
590 | i = 0; | ||
591 | |||
592 | if (i == 100) { | ||
593 | DEBUGP(5, dev, "Timeout reading num_bytes_read\n"); | ||
594 | rc = -EIO; | ||
595 | goto exit_setprotocol; | ||
596 | } | ||
597 | |||
598 | DEBUGP(5, dev, "Reset the CARDMAN CONTROLLER\n"); | ||
599 | xoutb(0x80, REG_FLAGS0(iobase)); | ||
600 | |||
601 | /* Read PPS reply */ | ||
602 | DEBUGP(5, dev, "Read PPS reply\n"); | ||
603 | for (i = 0; i < num_bytes_read; i++) { | ||
604 | xoutb(i, REG_BUF_ADDR(iobase)); | ||
605 | pts_reply[i] = inb(REG_BUF_DATA(iobase)); | ||
606 | } | ||
607 | |||
608 | #ifdef PCMCIA_DEBUG | ||
609 | DEBUGP(2, dev, "PTSreply: "); | ||
610 | for (i = 0; i < num_bytes_read; i++) { | ||
611 | if (pc_debug >= 5) | ||
612 | printk("0x%.2x ", pts_reply[i]); | ||
613 | } | ||
614 | printk("\n"); | ||
615 | #endif /* PCMCIA_DEBUG */ | ||
616 | |||
617 | DEBUGP(5, dev, "Clear Tactive in Flags1\n"); | ||
618 | xoutb(0x20, REG_FLAGS1(iobase)); | ||
619 | |||
620 | /* Compare ptsreq and ptsreply */ | ||
621 | if ((dev->pts[0] == pts_reply[0]) && | ||
622 | (dev->pts[1] == pts_reply[1]) && | ||
623 | (dev->pts[2] == pts_reply[2]) && (dev->pts[3] == pts_reply[3])) { | ||
624 | /* setcardparameter according to PPS */ | ||
625 | dev->baudv = calc_baudv(dev->pts[2]); | ||
626 | set_cardparameter(dev); | ||
627 | } else if ((dev->pts[0] == pts_reply[0]) && | ||
628 | ((dev->pts[1] & 0xef) == pts_reply[1]) && | ||
629 | ((pts_reply[0] ^ pts_reply[1]) == pts_reply[2])) { | ||
630 | /* short PTS reply, set card parameter to default values */ | ||
631 | dev->baudv = calc_baudv(0x11); | ||
632 | set_cardparameter(dev); | ||
633 | } else | ||
634 | rc = -EIO; | ||
635 | |||
636 | exit_setprotocol: | ||
637 | DEBUGP(3, dev, "<- set_protocol\n"); | ||
638 | return rc; | ||
639 | } | ||
640 | |||
641 | static int io_detect_cm4000(ioaddr_t iobase, struct cm4000_dev *dev) | ||
642 | { | ||
643 | |||
644 | /* note: statemachine is assumed to be reset */ | ||
645 | if (inb(REG_FLAGS0(iobase)) & 8) { | ||
646 | clear_bit(IS_ATR_VALID, &dev->flags); | ||
647 | set_bit(IS_CMM_ABSENT, &dev->flags); | ||
648 | return 0; /* detect CMM = 1 -> failure */ | ||
649 | } | ||
650 | /* xoutb(0x40, REG_FLAGS1(iobase)); detectCMM */ | ||
651 | xoutb(dev->flags1 | 0x40, REG_FLAGS1(iobase)); | ||
652 | if ((inb(REG_FLAGS0(iobase)) & 8) == 0) { | ||
653 | clear_bit(IS_ATR_VALID, &dev->flags); | ||
654 | set_bit(IS_CMM_ABSENT, &dev->flags); | ||
655 | return 0; /* detect CMM=0 -> failure */ | ||
656 | } | ||
657 | /* clear detectCMM again by restoring original flags1 */ | ||
658 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
659 | return 1; | ||
660 | } | ||
661 | |||
662 | static void terminate_monitor(struct cm4000_dev *dev) | ||
663 | { | ||
664 | |||
665 | /* tell the monitor to stop and wait until | ||
666 | * it terminates. | ||
667 | */ | ||
668 | DEBUGP(3, dev, "-> terminate_monitor\n"); | ||
669 | wait_event_interruptible(dev->devq, | ||
670 | test_and_set_bit(LOCK_MONITOR, | ||
671 | (void *)&dev->flags)); | ||
672 | |||
673 | /* now, LOCK_MONITOR has been set. | ||
674 | * allow a last cycle in the monitor. | ||
675 | * the monitor will indicate that it has | ||
676 | * finished by clearing this bit. | ||
677 | */ | ||
678 | DEBUGP(5, dev, "Now allow last cycle of monitor!\n"); | ||
679 | while (test_bit(LOCK_MONITOR, (void *)&dev->flags)) | ||
680 | msleep(25); | ||
681 | |||
682 | DEBUGP(5, dev, "Delete timer\n"); | ||
683 | del_timer_sync(&dev->timer); | ||
684 | #ifdef PCMCIA_DEBUG | ||
685 | dev->monitor_running = 0; | ||
686 | #endif | ||
687 | |||
688 | DEBUGP(3, dev, "<- terminate_monitor\n"); | ||
689 | } | ||
690 | |||
691 | /* | ||
692 | * monitor the card every 50msec. as a side-effect, retrieve the | ||
693 | * atr once a card is inserted. another side-effect of retrieving the | ||
694 | * atr is that the card will be powered on, so there is no need to | ||
695 | * power on the card explictely from the application: the driver | ||
696 | * is already doing that for you. | ||
697 | */ | ||
698 | |||
699 | static void monitor_card(unsigned long p) | ||
700 | { | ||
701 | struct cm4000_dev *dev = (struct cm4000_dev *) p; | ||
702 | ioaddr_t iobase = dev->link.io.BasePort1; | ||
703 | unsigned short s; | ||
704 | struct ptsreq ptsreq; | ||
705 | int i, atrc; | ||
706 | |||
707 | DEBUGP(7, dev, "-> monitor_card\n"); | ||
708 | |||
709 | /* if someone has set the lock for us: we're done! */ | ||
710 | if (test_and_set_bit(LOCK_MONITOR, &dev->flags)) { | ||
711 | DEBUGP(4, dev, "About to stop monitor\n"); | ||
712 | /* no */ | ||
713 | dev->rlen = | ||
714 | dev->rpos = | ||
715 | dev->atr_csum = dev->atr_len_retry = dev->cwarn = 0; | ||
716 | dev->mstate = M_FETCH_ATR; | ||
717 | clear_bit(LOCK_MONITOR, &dev->flags); | ||
718 | /* close et al. are sleeping on devq, so wake it */ | ||
719 | wake_up_interruptible(&dev->devq); | ||
720 | DEBUGP(2, dev, "<- monitor_card (we are done now)\n"); | ||
721 | return; | ||
722 | } | ||
723 | |||
724 | /* try to lock io: if it is already locked, just add another timer */ | ||
725 | if (test_and_set_bit(LOCK_IO, (void *)&dev->flags)) { | ||
726 | DEBUGP(4, dev, "Couldn't get IO lock\n"); | ||
727 | goto return_with_timer; | ||
728 | } | ||
729 | |||
730 | /* is a card/a reader inserted at all ? */ | ||
731 | dev->flags0 = xinb(REG_FLAGS0(iobase)); | ||
732 | DEBUGP(7, dev, "dev->flags0 = 0x%2x\n", dev->flags0); | ||
733 | DEBUGP(7, dev, "smartcard present: %s\n", | ||
734 | dev->flags0 & 1 ? "yes" : "no"); | ||
735 | DEBUGP(7, dev, "cardman present: %s\n", | ||
736 | dev->flags0 == 0xff ? "no" : "yes"); | ||
737 | |||
738 | if ((dev->flags0 & 1) == 0 /* no smartcard inserted */ | ||
739 | || dev->flags0 == 0xff) { /* no cardman inserted */ | ||
740 | /* no */ | ||
741 | dev->rlen = | ||
742 | dev->rpos = | ||
743 | dev->atr_csum = dev->atr_len_retry = dev->cwarn = 0; | ||
744 | dev->mstate = M_FETCH_ATR; | ||
745 | |||
746 | dev->flags &= 0x000000ff; /* only keep IO and MONITOR locks */ | ||
747 | |||
748 | if (dev->flags0 == 0xff) { | ||
749 | DEBUGP(4, dev, "set IS_CMM_ABSENT bit\n"); | ||
750 | set_bit(IS_CMM_ABSENT, &dev->flags); | ||
751 | } else if (test_bit(IS_CMM_ABSENT, &dev->flags)) { | ||
752 | DEBUGP(4, dev, "clear IS_CMM_ABSENT bit " | ||
753 | "(card is removed)\n"); | ||
754 | clear_bit(IS_CMM_ABSENT, &dev->flags); | ||
755 | } | ||
756 | |||
757 | goto release_io; | ||
758 | } else if ((dev->flags0 & 1) && test_bit(IS_CMM_ABSENT, &dev->flags)) { | ||
759 | /* cardman and card present but cardman was absent before | ||
760 | * (after suspend with inserted card) */ | ||
761 | DEBUGP(4, dev, "clear IS_CMM_ABSENT bit (card is inserted)\n"); | ||
762 | clear_bit(IS_CMM_ABSENT, &dev->flags); | ||
763 | } | ||
764 | |||
765 | if (test_bit(IS_ATR_VALID, &dev->flags) == 1) { | ||
766 | DEBUGP(7, dev, "believe ATR is already valid (do nothing)\n"); | ||
767 | goto release_io; | ||
768 | } | ||
769 | |||
770 | switch (dev->mstate) { | ||
771 | unsigned char flags0; | ||
772 | case M_CARDOFF: | ||
773 | DEBUGP(4, dev, "M_CARDOFF\n"); | ||
774 | flags0 = inb(REG_FLAGS0(iobase)); | ||
775 | if (flags0 & 0x02) { | ||
776 | /* wait until Flags0 indicate power is off */ | ||
777 | dev->mdelay = T_10MSEC; | ||
778 | } else { | ||
779 | /* Flags0 indicate power off and no card inserted now; | ||
780 | * Reset CARDMAN CONTROLLER */ | ||
781 | xoutb(0x80, REG_FLAGS0(iobase)); | ||
782 | |||
783 | /* prepare for fetching ATR again: after card off ATR | ||
784 | * is read again automatically */ | ||
785 | dev->rlen = | ||
786 | dev->rpos = | ||
787 | dev->atr_csum = | ||
788 | dev->atr_len_retry = dev->cwarn = 0; | ||
789 | dev->mstate = M_FETCH_ATR; | ||
790 | |||
791 | /* minimal gap between CARDOFF and read ATR is 50msec */ | ||
792 | dev->mdelay = T_50MSEC; | ||
793 | } | ||
794 | break; | ||
795 | case M_FETCH_ATR: | ||
796 | DEBUGP(4, dev, "M_FETCH_ATR\n"); | ||
797 | xoutb(0x80, REG_FLAGS0(iobase)); | ||
798 | DEBUGP(4, dev, "Reset BAUDV to 9600\n"); | ||
799 | dev->baudv = 0x173; /* 9600 */ | ||
800 | xoutb(0x02, REG_STOPBITS(iobase)); /* stopbits=2 */ | ||
801 | xoutb(0x73, REG_BAUDRATE(iobase)); /* baud value */ | ||
802 | xoutb(0x21, REG_FLAGS1(iobase)); /* T_Active=1, baud | ||
803 | value */ | ||
804 | /* warm start vs. power on: */ | ||
805 | xoutb(dev->flags0 & 2 ? 0x46 : 0x44, REG_FLAGS0(iobase)); | ||
806 | dev->mdelay = T_40MSEC; | ||
807 | dev->mstate = M_TIMEOUT_WAIT; | ||
808 | break; | ||
809 | case M_TIMEOUT_WAIT: | ||
810 | DEBUGP(4, dev, "M_TIMEOUT_WAIT\n"); | ||
811 | /* numRecBytes */ | ||
812 | io_read_num_rec_bytes(iobase, &dev->atr_len); | ||
813 | dev->mdelay = T_10MSEC; | ||
814 | dev->mstate = M_READ_ATR_LEN; | ||
815 | break; | ||
816 | case M_READ_ATR_LEN: | ||
817 | DEBUGP(4, dev, "M_READ_ATR_LEN\n"); | ||
818 | /* infinite loop possible, since there is no timeout */ | ||
819 | |||
820 | #define MAX_ATR_LEN_RETRY 100 | ||
821 | |||
822 | if (dev->atr_len == io_read_num_rec_bytes(iobase, &s)) { | ||
823 | if (dev->atr_len_retry++ >= MAX_ATR_LEN_RETRY) { /* + XX msec */ | ||
824 | dev->mdelay = T_10MSEC; | ||
825 | dev->mstate = M_READ_ATR; | ||
826 | } | ||
827 | } else { | ||
828 | dev->atr_len = s; | ||
829 | dev->atr_len_retry = 0; /* set new timeout */ | ||
830 | } | ||
831 | |||
832 | DEBUGP(4, dev, "Current ATR_LEN = %i\n", dev->atr_len); | ||
833 | break; | ||
834 | case M_READ_ATR: | ||
835 | DEBUGP(4, dev, "M_READ_ATR\n"); | ||
836 | xoutb(0x80, REG_FLAGS0(iobase)); /* reset SM */ | ||
837 | for (i = 0; i < dev->atr_len; i++) { | ||
838 | xoutb(i, REG_BUF_ADDR(iobase)); | ||
839 | dev->atr[i] = inb(REG_BUF_DATA(iobase)); | ||
840 | } | ||
841 | /* Deactivate T_Active flags */ | ||
842 | DEBUGP(4, dev, "Deactivate T_Active flags\n"); | ||
843 | dev->flags1 = 0x01; | ||
844 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
845 | |||
846 | /* atr is present (which doesnt mean it's valid) */ | ||
847 | set_bit(IS_ATR_PRESENT, &dev->flags); | ||
848 | if (dev->atr[0] == 0x03) | ||
849 | str_invert_revert(dev->atr, dev->atr_len); | ||
850 | atrc = parse_atr(dev); | ||
851 | if (atrc == 0) { /* atr invalid */ | ||
852 | dev->mdelay = 0; | ||
853 | dev->mstate = M_BAD_CARD; | ||
854 | } else { | ||
855 | dev->mdelay = T_50MSEC; | ||
856 | dev->mstate = M_ATR_PRESENT; | ||
857 | set_bit(IS_ATR_VALID, &dev->flags); | ||
858 | } | ||
859 | |||
860 | if (test_bit(IS_ATR_VALID, &dev->flags) == 1) { | ||
861 | DEBUGP(4, dev, "monitor_card: ATR valid\n"); | ||
862 | /* if ta1 == 0x11, no PPS necessary (default values) */ | ||
863 | /* do not do PPS with multi protocol cards */ | ||
864 | if ((test_bit(IS_AUTOPPS_ACT, &dev->flags) == 0) && | ||
865 | (dev->ta1 != 0x11) && | ||
866 | !(test_bit(IS_ANY_T0, &dev->flags) && | ||
867 | test_bit(IS_ANY_T1, &dev->flags))) { | ||
868 | DEBUGP(4, dev, "Perform AUTOPPS\n"); | ||
869 | set_bit(IS_AUTOPPS_ACT, &dev->flags); | ||
870 | ptsreq.protocol = ptsreq.protocol = | ||
871 | (0x01 << dev->proto); | ||
872 | ptsreq.flags = 0x01; | ||
873 | ptsreq.pts1 = 0x00; | ||
874 | ptsreq.pts2 = 0x00; | ||
875 | ptsreq.pts3 = 0x00; | ||
876 | if (set_protocol(dev, &ptsreq) == 0) { | ||
877 | DEBUGP(4, dev, "AUTOPPS ret SUCC\n"); | ||
878 | clear_bit(IS_AUTOPPS_ACT, &dev->flags); | ||
879 | wake_up_interruptible(&dev->atrq); | ||
880 | } else { | ||
881 | DEBUGP(4, dev, "AUTOPPS failed: " | ||
882 | "repower using defaults\n"); | ||
883 | /* prepare for repowering */ | ||
884 | clear_bit(IS_ATR_PRESENT, &dev->flags); | ||
885 | clear_bit(IS_ATR_VALID, &dev->flags); | ||
886 | dev->rlen = | ||
887 | dev->rpos = | ||
888 | dev->atr_csum = | ||
889 | dev->atr_len_retry = dev->cwarn = 0; | ||
890 | dev->mstate = M_FETCH_ATR; | ||
891 | |||
892 | dev->mdelay = T_50MSEC; | ||
893 | } | ||
894 | } else { | ||
895 | /* for cards which use slightly different | ||
896 | * params (extra guard time) */ | ||
897 | set_cardparameter(dev); | ||
898 | if (test_bit(IS_AUTOPPS_ACT, &dev->flags) == 1) | ||
899 | DEBUGP(4, dev, "AUTOPPS already active " | ||
900 | "2nd try:use default values\n"); | ||
901 | if (dev->ta1 == 0x11) | ||
902 | DEBUGP(4, dev, "No AUTOPPS necessary " | ||
903 | "TA(1)==0x11\n"); | ||
904 | if (test_bit(IS_ANY_T0, &dev->flags) | ||
905 | && test_bit(IS_ANY_T1, &dev->flags)) | ||
906 | DEBUGP(4, dev, "Do NOT perform AUTOPPS " | ||
907 | "with multiprotocol cards\n"); | ||
908 | clear_bit(IS_AUTOPPS_ACT, &dev->flags); | ||
909 | wake_up_interruptible(&dev->atrq); | ||
910 | } | ||
911 | } else { | ||
912 | DEBUGP(4, dev, "ATR invalid\n"); | ||
913 | wake_up_interruptible(&dev->atrq); | ||
914 | } | ||
915 | break; | ||
916 | case M_BAD_CARD: | ||
917 | DEBUGP(4, dev, "M_BAD_CARD\n"); | ||
918 | /* slow down warning, but prompt immediately after insertion */ | ||
919 | if (dev->cwarn == 0 || dev->cwarn == 10) { | ||
920 | set_bit(IS_BAD_CARD, &dev->flags); | ||
921 | printk(KERN_WARNING MODULE_NAME ": device %s: ", | ||
922 | dev->node.dev_name); | ||
923 | if (test_bit(IS_BAD_CSUM, &dev->flags)) { | ||
924 | DEBUGP(4, dev, "ATR checksum (0x%.2x, should " | ||
925 | "be zero) failed\n", dev->atr_csum); | ||
926 | } | ||
927 | #ifdef PCMCIA_DEBUG | ||
928 | else if (test_bit(IS_BAD_LENGTH, &dev->flags)) { | ||
929 | DEBUGP(4, dev, "ATR length error\n"); | ||
930 | } else { | ||
931 | DEBUGP(4, dev, "card damaged or wrong way " | ||
932 | "inserted\n"); | ||
933 | } | ||
934 | #endif | ||
935 | dev->cwarn = 0; | ||
936 | wake_up_interruptible(&dev->atrq); /* wake open */ | ||
937 | } | ||
938 | dev->cwarn++; | ||
939 | dev->mdelay = T_100MSEC; | ||
940 | dev->mstate = M_FETCH_ATR; | ||
941 | break; | ||
942 | default: | ||
943 | DEBUGP(7, dev, "Unknown action\n"); | ||
944 | break; /* nothing */ | ||
945 | } | ||
946 | |||
947 | release_io: | ||
948 | DEBUGP(7, dev, "release_io\n"); | ||
949 | clear_bit(LOCK_IO, &dev->flags); | ||
950 | wake_up_interruptible(&dev->ioq); /* whoever needs IO */ | ||
951 | |||
952 | return_with_timer: | ||
953 | DEBUGP(7, dev, "<- monitor_card (returns with timer)\n"); | ||
954 | dev->timer.expires = jiffies + dev->mdelay; | ||
955 | add_timer(&dev->timer); | ||
956 | clear_bit(LOCK_MONITOR, &dev->flags); | ||
957 | } | ||
958 | |||
959 | /* Interface to userland (file_operations) */ | ||
960 | |||
961 | static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count, | ||
962 | loff_t *ppos) | ||
963 | { | ||
964 | struct cm4000_dev *dev = filp->private_data; | ||
965 | ioaddr_t iobase = dev->link.io.BasePort1; | ||
966 | ssize_t rc; | ||
967 | int i, j, k; | ||
968 | |||
969 | DEBUGP(2, dev, "-> cmm_read(%s,%d)\n", current->comm, current->pid); | ||
970 | |||
971 | if (count == 0) /* according to manpage */ | ||
972 | return 0; | ||
973 | |||
974 | if ((dev->link.state & DEV_PRESENT) == 0 || /* socket removed */ | ||
975 | test_bit(IS_CMM_ABSENT, &dev->flags)) | ||
976 | return -ENODEV; | ||
977 | |||
978 | if (test_bit(IS_BAD_CSUM, &dev->flags)) | ||
979 | return -EIO; | ||
980 | |||
981 | /* also see the note about this in cmm_write */ | ||
982 | if (wait_event_interruptible | ||
983 | (dev->atrq, | ||
984 | ((filp->f_flags & O_NONBLOCK) | ||
985 | || (test_bit(IS_ATR_PRESENT, (void *)&dev->flags) != 0)))) { | ||
986 | if (filp->f_flags & O_NONBLOCK) | ||
987 | return -EAGAIN; | ||
988 | return -ERESTARTSYS; | ||
989 | } | ||
990 | |||
991 | if (test_bit(IS_ATR_VALID, &dev->flags) == 0) | ||
992 | return -EIO; | ||
993 | |||
994 | /* this one implements blocking IO */ | ||
995 | if (wait_event_interruptible | ||
996 | (dev->readq, | ||
997 | ((filp->f_flags & O_NONBLOCK) || (dev->rpos < dev->rlen)))) { | ||
998 | if (filp->f_flags & O_NONBLOCK) | ||
999 | return -EAGAIN; | ||
1000 | return -ERESTARTSYS; | ||
1001 | } | ||
1002 | |||
1003 | /* lock io */ | ||
1004 | if (wait_event_interruptible | ||
1005 | (dev->ioq, | ||
1006 | ((filp->f_flags & O_NONBLOCK) | ||
1007 | || (test_and_set_bit(LOCK_IO, (void *)&dev->flags) == 0)))) { | ||
1008 | if (filp->f_flags & O_NONBLOCK) | ||
1009 | return -EAGAIN; | ||
1010 | return -ERESTARTSYS; | ||
1011 | } | ||
1012 | |||
1013 | rc = 0; | ||
1014 | dev->flags0 = inb(REG_FLAGS0(iobase)); | ||
1015 | if ((dev->flags0 & 1) == 0 /* no smartcard inserted */ | ||
1016 | || dev->flags0 == 0xff) { /* no cardman inserted */ | ||
1017 | clear_bit(IS_ATR_VALID, &dev->flags); | ||
1018 | if (dev->flags0 & 1) { | ||
1019 | set_bit(IS_CMM_ABSENT, &dev->flags); | ||
1020 | rc = -ENODEV; | ||
1021 | } | ||
1022 | rc = -EIO; | ||
1023 | goto release_io; | ||
1024 | } | ||
1025 | |||
1026 | DEBUGP(4, dev, "begin read answer\n"); | ||
1027 | j = min(count, (size_t)(dev->rlen - dev->rpos)); | ||
1028 | k = dev->rpos; | ||
1029 | if (k + j > 255) | ||
1030 | j = 256 - k; | ||
1031 | DEBUGP(4, dev, "read1 j=%d\n", j); | ||
1032 | for (i = 0; i < j; i++) { | ||
1033 | xoutb(k++, REG_BUF_ADDR(iobase)); | ||
1034 | dev->rbuf[i] = xinb(REG_BUF_DATA(iobase)); | ||
1035 | } | ||
1036 | j = min(count, (size_t)(dev->rlen - dev->rpos)); | ||
1037 | if (k + j > 255) { | ||
1038 | DEBUGP(4, dev, "read2 j=%d\n", j); | ||
1039 | dev->flags1 |= 0x10; /* MSB buf addr set */ | ||
1040 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
1041 | for (; i < j; i++) { | ||
1042 | xoutb(k++, REG_BUF_ADDR(iobase)); | ||
1043 | dev->rbuf[i] = xinb(REG_BUF_DATA(iobase)); | ||
1044 | } | ||
1045 | } | ||
1046 | |||
1047 | if (dev->proto == 0 && count > dev->rlen - dev->rpos) { | ||
1048 | DEBUGP(4, dev, "T=0 and count > buffer\n"); | ||
1049 | dev->rbuf[i] = dev->rbuf[i - 1]; | ||
1050 | dev->rbuf[i - 1] = dev->procbyte; | ||
1051 | j++; | ||
1052 | } | ||
1053 | count = j; | ||
1054 | |||
1055 | dev->rpos = dev->rlen + 1; | ||
1056 | |||
1057 | /* Clear T1Active */ | ||
1058 | DEBUGP(4, dev, "Clear T1Active\n"); | ||
1059 | dev->flags1 &= 0xdf; | ||
1060 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
1061 | |||
1062 | xoutb(0, REG_FLAGS1(iobase)); /* clear detectCMM */ | ||
1063 | /* last check before exit */ | ||
1064 | if (!io_detect_cm4000(iobase, dev)) | ||
1065 | count = -ENODEV; | ||
1066 | |||
1067 | if (test_bit(IS_INVREV, &dev->flags) && count > 0) | ||
1068 | str_invert_revert(dev->rbuf, count); | ||
1069 | |||
1070 | if (copy_to_user(buf, dev->rbuf, count)) | ||
1071 | return -EFAULT; | ||
1072 | |||
1073 | release_io: | ||
1074 | clear_bit(LOCK_IO, &dev->flags); | ||
1075 | wake_up_interruptible(&dev->ioq); | ||
1076 | |||
1077 | DEBUGP(2, dev, "<- cmm_read returns: rc = %Zi\n", | ||
1078 | (rc < 0 ? rc : count)); | ||
1079 | return rc < 0 ? rc : count; | ||
1080 | } | ||
1081 | |||
1082 | static ssize_t cmm_write(struct file *filp, const char __user *buf, | ||
1083 | size_t count, loff_t *ppos) | ||
1084 | { | ||
1085 | struct cm4000_dev *dev = (struct cm4000_dev *) filp->private_data; | ||
1086 | ioaddr_t iobase = dev->link.io.BasePort1; | ||
1087 | unsigned short s; | ||
1088 | unsigned char tmp; | ||
1089 | unsigned char infolen; | ||
1090 | unsigned char sendT0; | ||
1091 | unsigned short nsend; | ||
1092 | unsigned short nr; | ||
1093 | ssize_t rc; | ||
1094 | int i; | ||
1095 | |||
1096 | DEBUGP(2, dev, "-> cmm_write(%s,%d)\n", current->comm, current->pid); | ||
1097 | |||
1098 | if (count == 0) /* according to manpage */ | ||
1099 | return 0; | ||
1100 | |||
1101 | if (dev->proto == 0 && count < 4) { | ||
1102 | /* T0 must have at least 4 bytes */ | ||
1103 | DEBUGP(4, dev, "T0 short write\n"); | ||
1104 | return -EIO; | ||
1105 | } | ||
1106 | |||
1107 | nr = count & 0x1ff; /* max bytes to write */ | ||
1108 | |||
1109 | sendT0 = dev->proto ? 0 : nr > 5 ? 0x08 : 0; | ||
1110 | |||
1111 | if ((dev->link.state & DEV_PRESENT) == 0 || /* socket removed */ | ||
1112 | test_bit(IS_CMM_ABSENT, &dev->flags)) | ||
1113 | return -ENODEV; | ||
1114 | |||
1115 | if (test_bit(IS_BAD_CSUM, &dev->flags)) { | ||
1116 | DEBUGP(4, dev, "bad csum\n"); | ||
1117 | return -EIO; | ||
1118 | } | ||
1119 | |||
1120 | /* | ||
1121 | * wait for atr to become valid. | ||
1122 | * note: it is important to lock this code. if we dont, the monitor | ||
1123 | * could be run between test_bit and the the call the sleep on the | ||
1124 | * atr-queue. if *then* the monitor detects atr valid, it will wake up | ||
1125 | * any process on the atr-queue, *but* since we have been interrupted, | ||
1126 | * we do not yet sleep on this queue. this would result in a missed | ||
1127 | * wake_up and the calling process would sleep forever (until | ||
1128 | * interrupted). also, do *not* restore_flags before sleep_on, because | ||
1129 | * this could result in the same situation! | ||
1130 | */ | ||
1131 | if (wait_event_interruptible | ||
1132 | (dev->atrq, | ||
1133 | ((filp->f_flags & O_NONBLOCK) | ||
1134 | || (test_bit(IS_ATR_PRESENT, (void *)&dev->flags) != 0)))) { | ||
1135 | if (filp->f_flags & O_NONBLOCK) | ||
1136 | return -EAGAIN; | ||
1137 | return -ERESTARTSYS; | ||
1138 | } | ||
1139 | |||
1140 | if (test_bit(IS_ATR_VALID, &dev->flags) == 0) { /* invalid atr */ | ||
1141 | DEBUGP(4, dev, "invalid ATR\n"); | ||
1142 | return -EIO; | ||
1143 | } | ||
1144 | |||
1145 | /* lock io */ | ||
1146 | if (wait_event_interruptible | ||
1147 | (dev->ioq, | ||
1148 | ((filp->f_flags & O_NONBLOCK) | ||
1149 | || (test_and_set_bit(LOCK_IO, (void *)&dev->flags) == 0)))) { | ||
1150 | if (filp->f_flags & O_NONBLOCK) | ||
1151 | return -EAGAIN; | ||
1152 | return -ERESTARTSYS; | ||
1153 | } | ||
1154 | |||
1155 | if (copy_from_user(dev->sbuf, buf, ((count > 512) ? 512 : count))) | ||
1156 | return -EFAULT; | ||
1157 | |||
1158 | rc = 0; | ||
1159 | dev->flags0 = inb(REG_FLAGS0(iobase)); | ||
1160 | if ((dev->flags0 & 1) == 0 /* no smartcard inserted */ | ||
1161 | || dev->flags0 == 0xff) { /* no cardman inserted */ | ||
1162 | clear_bit(IS_ATR_VALID, &dev->flags); | ||
1163 | if (dev->flags0 & 1) { | ||
1164 | set_bit(IS_CMM_ABSENT, &dev->flags); | ||
1165 | rc = -ENODEV; | ||
1166 | } else { | ||
1167 | DEBUGP(4, dev, "IO error\n"); | ||
1168 | rc = -EIO; | ||
1169 | } | ||
1170 | goto release_io; | ||
1171 | } | ||
1172 | |||
1173 | xoutb(0x80, REG_FLAGS0(iobase)); /* reset SM */ | ||
1174 | |||
1175 | if (!io_detect_cm4000(iobase, dev)) { | ||
1176 | rc = -ENODEV; | ||
1177 | goto release_io; | ||
1178 | } | ||
1179 | |||
1180 | /* reflect T=0 send/read mode in flags1 */ | ||
1181 | dev->flags1 |= (sendT0); | ||
1182 | |||
1183 | set_cardparameter(dev); | ||
1184 | |||
1185 | /* dummy read, reset flag procedure received */ | ||
1186 | tmp = inb(REG_FLAGS1(iobase)); | ||
1187 | |||
1188 | dev->flags1 = 0x20 /* T_Active */ | ||
1189 | | (sendT0) | ||
1190 | | (test_bit(IS_INVREV, &dev->flags) ? 2 : 0)/* inverse parity */ | ||
1191 | | (((dev->baudv - 1) & 0x0100) >> 8); /* MSB-Baud */ | ||
1192 | DEBUGP(1, dev, "set dev->flags1 = 0x%.2x\n", dev->flags1); | ||
1193 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
1194 | |||
1195 | /* xmit data */ | ||
1196 | DEBUGP(4, dev, "Xmit data\n"); | ||
1197 | for (i = 0; i < nr; i++) { | ||
1198 | if (i >= 256) { | ||
1199 | dev->flags1 = 0x20 /* T_Active */ | ||
1200 | | (sendT0) /* SendT0 */ | ||
1201 | /* inverse parity: */ | ||
1202 | | (test_bit(IS_INVREV, &dev->flags) ? 2 : 0) | ||
1203 | | (((dev->baudv - 1) & 0x0100) >> 8) /* MSB-Baud */ | ||
1204 | | 0x10; /* set address high */ | ||
1205 | DEBUGP(4, dev, "dev->flags = 0x%.2x - set address " | ||
1206 | "high\n", dev->flags1); | ||
1207 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
1208 | } | ||
1209 | if (test_bit(IS_INVREV, &dev->flags)) { | ||
1210 | DEBUGP(4, dev, "Apply inverse convention for 0x%.2x " | ||
1211 | "-> 0x%.2x\n", (unsigned char)dev->sbuf[i], | ||
1212 | invert_revert(dev->sbuf[i])); | ||
1213 | xoutb(i, REG_BUF_ADDR(iobase)); | ||
1214 | xoutb(invert_revert(dev->sbuf[i]), | ||
1215 | REG_BUF_DATA(iobase)); | ||
1216 | } else { | ||
1217 | xoutb(i, REG_BUF_ADDR(iobase)); | ||
1218 | xoutb(dev->sbuf[i], REG_BUF_DATA(iobase)); | ||
1219 | } | ||
1220 | } | ||
1221 | DEBUGP(4, dev, "Xmit done\n"); | ||
1222 | |||
1223 | if (dev->proto == 0) { | ||
1224 | /* T=0 proto: 0 byte reply */ | ||
1225 | if (nr == 4) { | ||
1226 | DEBUGP(4, dev, "T=0 assumes 0 byte reply\n"); | ||
1227 | xoutb(i, REG_BUF_ADDR(iobase)); | ||
1228 | if (test_bit(IS_INVREV, &dev->flags)) | ||
1229 | xoutb(0xff, REG_BUF_DATA(iobase)); | ||
1230 | else | ||
1231 | xoutb(0x00, REG_BUF_DATA(iobase)); | ||
1232 | } | ||
1233 | |||
1234 | /* numSendBytes */ | ||
1235 | if (sendT0) | ||
1236 | nsend = nr; | ||
1237 | else { | ||
1238 | if (nr == 4) | ||
1239 | nsend = 5; | ||
1240 | else { | ||
1241 | nsend = 5 + (unsigned char)dev->sbuf[4]; | ||
1242 | if (dev->sbuf[4] == 0) | ||
1243 | nsend += 0x100; | ||
1244 | } | ||
1245 | } | ||
1246 | } else | ||
1247 | nsend = nr; | ||
1248 | |||
1249 | /* T0: output procedure byte */ | ||
1250 | if (test_bit(IS_INVREV, &dev->flags)) { | ||
1251 | DEBUGP(4, dev, "T=0 set Procedure byte (inverse-reverse) " | ||
1252 | "0x%.2x\n", invert_revert(dev->sbuf[1])); | ||
1253 | xoutb(invert_revert(dev->sbuf[1]), REG_NUM_BYTES(iobase)); | ||
1254 | } else { | ||
1255 | DEBUGP(4, dev, "T=0 set Procedure byte 0x%.2x\n", dev->sbuf[1]); | ||
1256 | xoutb(dev->sbuf[1], REG_NUM_BYTES(iobase)); | ||
1257 | } | ||
1258 | |||
1259 | DEBUGP(1, dev, "set NumSendBytes = 0x%.2x\n", | ||
1260 | (unsigned char)(nsend & 0xff)); | ||
1261 | xoutb((unsigned char)(nsend & 0xff), REG_NUM_SEND(iobase)); | ||
1262 | |||
1263 | DEBUGP(1, dev, "Trigger CARDMAN CONTROLLER (0x%.2x)\n", | ||
1264 | 0x40 /* SM_Active */ | ||
1265 | | (dev->flags0 & 2 ? 0 : 4) /* power on if needed */ | ||
1266 | |(dev->proto ? 0x10 : 0x08) /* T=1/T=0 */ | ||
1267 | |(nsend & 0x100) >> 8 /* MSB numSendBytes */ ); | ||
1268 | xoutb(0x40 /* SM_Active */ | ||
1269 | | (dev->flags0 & 2 ? 0 : 4) /* power on if needed */ | ||
1270 | |(dev->proto ? 0x10 : 0x08) /* T=1/T=0 */ | ||
1271 | |(nsend & 0x100) >> 8, /* MSB numSendBytes */ | ||
1272 | REG_FLAGS0(iobase)); | ||
1273 | |||
1274 | /* wait for xmit done */ | ||
1275 | if (dev->proto == 1) { | ||
1276 | DEBUGP(4, dev, "Wait for xmit done\n"); | ||
1277 | for (i = 0; i < 1000; i++) { | ||
1278 | if (inb(REG_FLAGS0(iobase)) & 0x08) | ||
1279 | break; | ||
1280 | msleep_interruptible(10); | ||
1281 | } | ||
1282 | if (i == 1000) { | ||
1283 | DEBUGP(4, dev, "timeout waiting for xmit done\n"); | ||
1284 | rc = -EIO; | ||
1285 | goto release_io; | ||
1286 | } | ||
1287 | } | ||
1288 | |||
1289 | /* T=1: wait for infoLen */ | ||
1290 | |||
1291 | infolen = 0; | ||
1292 | if (dev->proto) { | ||
1293 | /* wait until infoLen is valid */ | ||
1294 | for (i = 0; i < 6000; i++) { /* max waiting time of 1 min */ | ||
1295 | io_read_num_rec_bytes(iobase, &s); | ||
1296 | if (s >= 3) { | ||
1297 | infolen = inb(REG_FLAGS1(iobase)); | ||
1298 | DEBUGP(4, dev, "infolen=%d\n", infolen); | ||
1299 | break; | ||
1300 | } | ||
1301 | msleep_interruptible(10); | ||
1302 | } | ||
1303 | if (i == 6000) { | ||
1304 | DEBUGP(4, dev, "timeout waiting for infoLen\n"); | ||
1305 | rc = -EIO; | ||
1306 | goto release_io; | ||
1307 | } | ||
1308 | } else | ||
1309 | clear_bit(IS_PROCBYTE_PRESENT, &dev->flags); | ||
1310 | |||
1311 | /* numRecBytes | bit9 of numRecytes */ | ||
1312 | io_read_num_rec_bytes(iobase, &dev->rlen); | ||
1313 | for (i = 0; i < 600; i++) { /* max waiting time of 2 sec */ | ||
1314 | if (dev->proto) { | ||
1315 | if (dev->rlen >= infolen + 4) | ||
1316 | break; | ||
1317 | } | ||
1318 | msleep_interruptible(10); | ||
1319 | /* numRecBytes | bit9 of numRecytes */ | ||
1320 | io_read_num_rec_bytes(iobase, &s); | ||
1321 | if (s > dev->rlen) { | ||
1322 | DEBUGP(1, dev, "NumRecBytes inc (reset timeout)\n"); | ||
1323 | i = 0; /* reset timeout */ | ||
1324 | dev->rlen = s; | ||
1325 | } | ||
1326 | /* T=0: we are done when numRecBytes doesn't | ||
1327 | * increment any more and NoProcedureByte | ||
1328 | * is set and numRecBytes == bytes sent + 6 | ||
1329 | * (header bytes + data + 1 for sw2) | ||
1330 | * except when the card replies an error | ||
1331 | * which means, no data will be sent back. | ||
1332 | */ | ||
1333 | else if (dev->proto == 0) { | ||
1334 | if ((inb(REG_BUF_ADDR(iobase)) & 0x80)) { | ||
1335 | /* no procedure byte received since last read */ | ||
1336 | DEBUGP(1, dev, "NoProcedure byte set\n"); | ||
1337 | /* i=0; */ | ||
1338 | } else { | ||
1339 | /* procedure byte received since last read */ | ||
1340 | DEBUGP(1, dev, "NoProcedure byte unset " | ||
1341 | "(reset timeout)\n"); | ||
1342 | dev->procbyte = inb(REG_FLAGS1(iobase)); | ||
1343 | DEBUGP(1, dev, "Read procedure byte 0x%.2x\n", | ||
1344 | dev->procbyte); | ||
1345 | i = 0; /* resettimeout */ | ||
1346 | } | ||
1347 | if (inb(REG_FLAGS0(iobase)) & 0x08) { | ||
1348 | DEBUGP(1, dev, "T0Done flag (read reply)\n"); | ||
1349 | break; | ||
1350 | } | ||
1351 | } | ||
1352 | if (dev->proto) | ||
1353 | infolen = inb(REG_FLAGS1(iobase)); | ||
1354 | } | ||
1355 | if (i == 600) { | ||
1356 | DEBUGP(1, dev, "timeout waiting for numRecBytes\n"); | ||
1357 | rc = -EIO; | ||
1358 | goto release_io; | ||
1359 | } else { | ||
1360 | if (dev->proto == 0) { | ||
1361 | DEBUGP(1, dev, "Wait for T0Done bit to be set\n"); | ||
1362 | for (i = 0; i < 1000; i++) { | ||
1363 | if (inb(REG_FLAGS0(iobase)) & 0x08) | ||
1364 | break; | ||
1365 | msleep_interruptible(10); | ||
1366 | } | ||
1367 | if (i == 1000) { | ||
1368 | DEBUGP(1, dev, "timeout waiting for T0Done\n"); | ||
1369 | rc = -EIO; | ||
1370 | goto release_io; | ||
1371 | } | ||
1372 | |||
1373 | dev->procbyte = inb(REG_FLAGS1(iobase)); | ||
1374 | DEBUGP(4, dev, "Read procedure byte 0x%.2x\n", | ||
1375 | dev->procbyte); | ||
1376 | |||
1377 | io_read_num_rec_bytes(iobase, &dev->rlen); | ||
1378 | DEBUGP(4, dev, "Read NumRecBytes = %i\n", dev->rlen); | ||
1379 | |||
1380 | } | ||
1381 | } | ||
1382 | /* T=1: read offset=zero, T=0: read offset=after challenge */ | ||
1383 | dev->rpos = dev->proto ? 0 : nr == 4 ? 5 : nr > dev->rlen ? 5 : nr; | ||
1384 | DEBUGP(4, dev, "dev->rlen = %i, dev->rpos = %i, nr = %i\n", | ||
1385 | dev->rlen, dev->rpos, nr); | ||
1386 | |||
1387 | release_io: | ||
1388 | DEBUGP(4, dev, "Reset SM\n"); | ||
1389 | xoutb(0x80, REG_FLAGS0(iobase)); /* reset SM */ | ||
1390 | |||
1391 | if (rc < 0) { | ||
1392 | DEBUGP(4, dev, "Write failed but clear T_Active\n"); | ||
1393 | dev->flags1 &= 0xdf; | ||
1394 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
1395 | } | ||
1396 | |||
1397 | clear_bit(LOCK_IO, &dev->flags); | ||
1398 | wake_up_interruptible(&dev->ioq); | ||
1399 | wake_up_interruptible(&dev->readq); /* tell read we have data */ | ||
1400 | |||
1401 | /* ITSEC E2: clear write buffer */ | ||
1402 | memset((char *)dev->sbuf, 0, 512); | ||
1403 | |||
1404 | /* return error or actually written bytes */ | ||
1405 | DEBUGP(2, dev, "<- cmm_write\n"); | ||
1406 | return rc < 0 ? rc : nr; | ||
1407 | } | ||
1408 | |||
1409 | static void start_monitor(struct cm4000_dev *dev) | ||
1410 | { | ||
1411 | DEBUGP(3, dev, "-> start_monitor\n"); | ||
1412 | if (!dev->monitor_running) { | ||
1413 | DEBUGP(5, dev, "create, init and add timer\n"); | ||
1414 | init_timer(&dev->timer); | ||
1415 | dev->monitor_running = 1; | ||
1416 | dev->timer.expires = jiffies; | ||
1417 | dev->timer.data = (unsigned long) dev; | ||
1418 | dev->timer.function = monitor_card; | ||
1419 | add_timer(&dev->timer); | ||
1420 | } else | ||
1421 | DEBUGP(5, dev, "monitor already running\n"); | ||
1422 | DEBUGP(3, dev, "<- start_monitor\n"); | ||
1423 | } | ||
1424 | |||
1425 | static void stop_monitor(struct cm4000_dev *dev) | ||
1426 | { | ||
1427 | DEBUGP(3, dev, "-> stop_monitor\n"); | ||
1428 | if (dev->monitor_running) { | ||
1429 | DEBUGP(5, dev, "stopping monitor\n"); | ||
1430 | terminate_monitor(dev); | ||
1431 | /* reset monitor SM */ | ||
1432 | clear_bit(IS_ATR_VALID, &dev->flags); | ||
1433 | clear_bit(IS_ATR_PRESENT, &dev->flags); | ||
1434 | } else | ||
1435 | DEBUGP(5, dev, "monitor already stopped\n"); | ||
1436 | DEBUGP(3, dev, "<- stop_monitor\n"); | ||
1437 | } | ||
1438 | |||
1439 | static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | ||
1440 | unsigned long arg) | ||
1441 | { | ||
1442 | struct cm4000_dev *dev = filp->private_data; | ||
1443 | ioaddr_t iobase = dev->link.io.BasePort1; | ||
1444 | dev_link_t *link; | ||
1445 | int size; | ||
1446 | int rc; | ||
1447 | #ifdef PCMCIA_DEBUG | ||
1448 | char *ioctl_names[CM_IOC_MAXNR + 1] = { | ||
1449 | [_IOC_NR(CM_IOCGSTATUS)] "CM_IOCGSTATUS", | ||
1450 | [_IOC_NR(CM_IOCGATR)] "CM_IOCGATR", | ||
1451 | [_IOC_NR(CM_IOCARDOFF)] "CM_IOCARDOFF", | ||
1452 | [_IOC_NR(CM_IOCSPTS)] "CM_IOCSPTS", | ||
1453 | [_IOC_NR(CM_IOSDBGLVL)] "CM4000_DBGLVL", | ||
1454 | }; | ||
1455 | #endif | ||
1456 | DEBUGP(3, dev, "cmm_ioctl(device=%d.%d) %s\n", imajor(inode), | ||
1457 | iminor(inode), ioctl_names[_IOC_NR(cmd)]); | ||
1458 | |||
1459 | link = dev_table[iminor(inode)]; | ||
1460 | if (!(DEV_OK(link))) { | ||
1461 | DEBUGP(4, dev, "DEV_OK false\n"); | ||
1462 | return -ENODEV; | ||
1463 | } | ||
1464 | |||
1465 | if (test_bit(IS_CMM_ABSENT, &dev->flags)) { | ||
1466 | DEBUGP(4, dev, "CMM_ABSENT flag set\n"); | ||
1467 | return -ENODEV; | ||
1468 | } | ||
1469 | |||
1470 | if (_IOC_TYPE(cmd) != CM_IOC_MAGIC) { | ||
1471 | DEBUGP(4, dev, "ioctype mismatch\n"); | ||
1472 | return -EINVAL; | ||
1473 | } | ||
1474 | if (_IOC_NR(cmd) > CM_IOC_MAXNR) { | ||
1475 | DEBUGP(4, dev, "iocnr mismatch\n"); | ||
1476 | return -EINVAL; | ||
1477 | } | ||
1478 | size = _IOC_SIZE(cmd); | ||
1479 | rc = 0; | ||
1480 | DEBUGP(4, dev, "iocdir=%.4x iocr=%.4x iocw=%.4x iocsize=%d cmd=%.4x\n", | ||
1481 | _IOC_DIR(cmd), _IOC_READ, _IOC_WRITE, size, cmd); | ||
1482 | |||
1483 | if (_IOC_DIR(cmd) & _IOC_READ) { | ||
1484 | if (!access_ok(VERIFY_WRITE, (void *)arg, size)) | ||
1485 | return -EFAULT; | ||
1486 | } | ||
1487 | if (_IOC_DIR(cmd) & _IOC_WRITE) { | ||
1488 | if (!access_ok(VERIFY_READ, (void *)arg, size)) | ||
1489 | return -EFAULT; | ||
1490 | } | ||
1491 | |||
1492 | switch (cmd) { | ||
1493 | case CM_IOCGSTATUS: | ||
1494 | DEBUGP(4, dev, " ... in CM_IOCGSTATUS\n"); | ||
1495 | { | ||
1496 | int status; | ||
1497 | |||
1498 | /* clear other bits, but leave inserted & powered as | ||
1499 | * they are */ | ||
1500 | status = dev->flags0 & 3; | ||
1501 | if (test_bit(IS_ATR_PRESENT, &dev->flags)) | ||
1502 | status |= CM_ATR_PRESENT; | ||
1503 | if (test_bit(IS_ATR_VALID, &dev->flags)) | ||
1504 | status |= CM_ATR_VALID; | ||
1505 | if (test_bit(IS_CMM_ABSENT, &dev->flags)) | ||
1506 | status |= CM_NO_READER; | ||
1507 | if (test_bit(IS_BAD_CARD, &dev->flags)) | ||
1508 | status |= CM_BAD_CARD; | ||
1509 | if (copy_to_user((int *)arg, &status, sizeof(int))) | ||
1510 | return -EFAULT; | ||
1511 | } | ||
1512 | return 0; | ||
1513 | case CM_IOCGATR: | ||
1514 | DEBUGP(4, dev, "... in CM_IOCGATR\n"); | ||
1515 | { | ||
1516 | struct atreq *atreq = (struct atreq *) arg; | ||
1517 | int tmp; | ||
1518 | /* allow nonblocking io and being interrupted */ | ||
1519 | if (wait_event_interruptible | ||
1520 | (dev->atrq, | ||
1521 | ((filp->f_flags & O_NONBLOCK) | ||
1522 | || (test_bit(IS_ATR_PRESENT, (void *)&dev->flags) | ||
1523 | != 0)))) { | ||
1524 | if (filp->f_flags & O_NONBLOCK) | ||
1525 | return -EAGAIN; | ||
1526 | return -ERESTARTSYS; | ||
1527 | } | ||
1528 | |||
1529 | if (test_bit(IS_ATR_VALID, &dev->flags) == 0) { | ||
1530 | tmp = -1; | ||
1531 | if (copy_to_user(&(atreq->atr_len), &tmp, | ||
1532 | sizeof(int))) | ||
1533 | return -EFAULT; | ||
1534 | } else { | ||
1535 | if (copy_to_user(atreq->atr, dev->atr, | ||
1536 | dev->atr_len)) | ||
1537 | return -EFAULT; | ||
1538 | |||
1539 | tmp = dev->atr_len; | ||
1540 | if (copy_to_user(&(atreq->atr_len), &tmp, sizeof(int))) | ||
1541 | return -EFAULT; | ||
1542 | } | ||
1543 | return 0; | ||
1544 | } | ||
1545 | case CM_IOCARDOFF: | ||
1546 | |||
1547 | #ifdef PCMCIA_DEBUG | ||
1548 | DEBUGP(4, dev, "... in CM_IOCARDOFF\n"); | ||
1549 | if (dev->flags0 & 0x01) { | ||
1550 | DEBUGP(4, dev, " Card inserted\n"); | ||
1551 | } else { | ||
1552 | DEBUGP(2, dev, " No card inserted\n"); | ||
1553 | } | ||
1554 | if (dev->flags0 & 0x02) { | ||
1555 | DEBUGP(4, dev, " Card powered\n"); | ||
1556 | } else { | ||
1557 | DEBUGP(2, dev, " Card not powered\n"); | ||
1558 | } | ||
1559 | #endif | ||
1560 | |||
1561 | /* is a card inserted and powered? */ | ||
1562 | if ((dev->flags0 & 0x01) && (dev->flags0 & 0x02)) { | ||
1563 | |||
1564 | /* get IO lock */ | ||
1565 | if (wait_event_interruptible | ||
1566 | (dev->ioq, | ||
1567 | ((filp->f_flags & O_NONBLOCK) | ||
1568 | || (test_and_set_bit(LOCK_IO, (void *)&dev->flags) | ||
1569 | == 0)))) { | ||
1570 | if (filp->f_flags & O_NONBLOCK) | ||
1571 | return -EAGAIN; | ||
1572 | return -ERESTARTSYS; | ||
1573 | } | ||
1574 | /* Set Flags0 = 0x42 */ | ||
1575 | DEBUGP(4, dev, "Set Flags0=0x42 \n"); | ||
1576 | xoutb(0x42, REG_FLAGS0(iobase)); | ||
1577 | clear_bit(IS_ATR_PRESENT, &dev->flags); | ||
1578 | clear_bit(IS_ATR_VALID, &dev->flags); | ||
1579 | dev->mstate = M_CARDOFF; | ||
1580 | clear_bit(LOCK_IO, &dev->flags); | ||
1581 | if (wait_event_interruptible | ||
1582 | (dev->atrq, | ||
1583 | ((filp->f_flags & O_NONBLOCK) | ||
1584 | || (test_bit(IS_ATR_VALID, (void *)&dev->flags) != | ||
1585 | 0)))) { | ||
1586 | if (filp->f_flags & O_NONBLOCK) | ||
1587 | return -EAGAIN; | ||
1588 | return -ERESTARTSYS; | ||
1589 | } | ||
1590 | } | ||
1591 | /* release lock */ | ||
1592 | clear_bit(LOCK_IO, &dev->flags); | ||
1593 | wake_up_interruptible(&dev->ioq); | ||
1594 | |||
1595 | return 0; | ||
1596 | case CM_IOCSPTS: | ||
1597 | { | ||
1598 | struct ptsreq krnptsreq; | ||
1599 | |||
1600 | if (copy_from_user(&krnptsreq, (struct ptsreq *) arg, | ||
1601 | sizeof(struct ptsreq))) | ||
1602 | return -EFAULT; | ||
1603 | |||
1604 | rc = 0; | ||
1605 | DEBUGP(4, dev, "... in CM_IOCSPTS\n"); | ||
1606 | /* wait for ATR to get valid */ | ||
1607 | if (wait_event_interruptible | ||
1608 | (dev->atrq, | ||
1609 | ((filp->f_flags & O_NONBLOCK) | ||
1610 | || (test_bit(IS_ATR_PRESENT, (void *)&dev->flags) | ||
1611 | != 0)))) { | ||
1612 | if (filp->f_flags & O_NONBLOCK) | ||
1613 | return -EAGAIN; | ||
1614 | return -ERESTARTSYS; | ||
1615 | } | ||
1616 | /* get IO lock */ | ||
1617 | if (wait_event_interruptible | ||
1618 | (dev->ioq, | ||
1619 | ((filp->f_flags & O_NONBLOCK) | ||
1620 | || (test_and_set_bit(LOCK_IO, (void *)&dev->flags) | ||
1621 | == 0)))) { | ||
1622 | if (filp->f_flags & O_NONBLOCK) | ||
1623 | return -EAGAIN; | ||
1624 | return -ERESTARTSYS; | ||
1625 | } | ||
1626 | |||
1627 | if ((rc = set_protocol(dev, &krnptsreq)) != 0) { | ||
1628 | /* auto power_on again */ | ||
1629 | dev->mstate = M_FETCH_ATR; | ||
1630 | clear_bit(IS_ATR_VALID, &dev->flags); | ||
1631 | } | ||
1632 | /* release lock */ | ||
1633 | clear_bit(LOCK_IO, &dev->flags); | ||
1634 | wake_up_interruptible(&dev->ioq); | ||
1635 | |||
1636 | } | ||
1637 | return rc; | ||
1638 | #ifdef PCMCIA_DEBUG | ||
1639 | case CM_IOSDBGLVL: /* set debug log level */ | ||
1640 | { | ||
1641 | int old_pc_debug = 0; | ||
1642 | |||
1643 | old_pc_debug = pc_debug; | ||
1644 | if (copy_from_user(&pc_debug, (int *)arg, sizeof(int))) | ||
1645 | return -EFAULT; | ||
1646 | |||
1647 | if (old_pc_debug != pc_debug) | ||
1648 | DEBUGP(0, dev, "Changed debug log level " | ||
1649 | "to %i\n", pc_debug); | ||
1650 | } | ||
1651 | return rc; | ||
1652 | #endif | ||
1653 | default: | ||
1654 | DEBUGP(4, dev, "... in default (unknown IOCTL code)\n"); | ||
1655 | return -EINVAL; | ||
1656 | } | ||
1657 | } | ||
1658 | |||
1659 | static int cmm_open(struct inode *inode, struct file *filp) | ||
1660 | { | ||
1661 | struct cm4000_dev *dev; | ||
1662 | dev_link_t *link; | ||
1663 | int rc, minor = iminor(inode); | ||
1664 | |||
1665 | if (minor >= CM4000_MAX_DEV) | ||
1666 | return -ENODEV; | ||
1667 | |||
1668 | link = dev_table[minor]; | ||
1669 | if (link == NULL || !(DEV_OK(link))) | ||
1670 | return -ENODEV; | ||
1671 | |||
1672 | if (link->open) | ||
1673 | return -EBUSY; | ||
1674 | |||
1675 | dev = link->priv; | ||
1676 | filp->private_data = dev; | ||
1677 | |||
1678 | DEBUGP(2, dev, "-> cmm_open(device=%d.%d process=%s,%d)\n", | ||
1679 | imajor(inode), minor, current->comm, current->pid); | ||
1680 | |||
1681 | /* init device variables, they may be "polluted" after close | ||
1682 | * or, the device may never have been closed (i.e. open failed) | ||
1683 | */ | ||
1684 | |||
1685 | ZERO_DEV(dev); | ||
1686 | |||
1687 | /* opening will always block since the | ||
1688 | * monitor will be started by open, which | ||
1689 | * means we have to wait for ATR becoming | ||
1690 | * vaild = block until valid (or card | ||
1691 | * inserted) | ||
1692 | */ | ||
1693 | if (filp->f_flags & O_NONBLOCK) | ||
1694 | return -EAGAIN; | ||
1695 | |||
1696 | dev->mdelay = T_50MSEC; | ||
1697 | |||
1698 | /* start monitoring the cardstatus */ | ||
1699 | start_monitor(dev); | ||
1700 | |||
1701 | link->open = 1; /* only one open per device */ | ||
1702 | rc = 0; | ||
1703 | |||
1704 | DEBUGP(2, dev, "<- cmm_open\n"); | ||
1705 | return nonseekable_open(inode, filp); | ||
1706 | } | ||
1707 | |||
1708 | static int cmm_close(struct inode *inode, struct file *filp) | ||
1709 | { | ||
1710 | struct cm4000_dev *dev; | ||
1711 | dev_link_t *link; | ||
1712 | int minor = iminor(inode); | ||
1713 | |||
1714 | if (minor >= CM4000_MAX_DEV) | ||
1715 | return -ENODEV; | ||
1716 | |||
1717 | link = dev_table[minor]; | ||
1718 | if (link == NULL) | ||
1719 | return -ENODEV; | ||
1720 | |||
1721 | dev = link->priv; | ||
1722 | |||
1723 | DEBUGP(2, dev, "-> cmm_close(maj/min=%d.%d)\n", | ||
1724 | imajor(inode), minor); | ||
1725 | |||
1726 | stop_monitor(dev); | ||
1727 | |||
1728 | ZERO_DEV(dev); | ||
1729 | |||
1730 | link->open = 0; /* only one open per device */ | ||
1731 | wake_up(&dev->devq); /* socket removed? */ | ||
1732 | |||
1733 | DEBUGP(2, dev, "cmm_close\n"); | ||
1734 | return 0; | ||
1735 | } | ||
1736 | |||
1737 | static void cmm_cm4000_release(dev_link_t * link) | ||
1738 | { | ||
1739 | struct cm4000_dev *dev = link->priv; | ||
1740 | |||
1741 | /* dont terminate the monitor, rather rely on | ||
1742 | * close doing that for us. | ||
1743 | */ | ||
1744 | DEBUGP(3, dev, "-> cmm_cm4000_release\n"); | ||
1745 | while (link->open) { | ||
1746 | printk(KERN_INFO MODULE_NAME ": delaying release until " | ||
1747 | "process has terminated\n"); | ||
1748 | /* note: don't interrupt us: | ||
1749 | * close the applications which own | ||
1750 | * the devices _first_ ! | ||
1751 | */ | ||
1752 | wait_event(dev->devq, (link->open == 0)); | ||
1753 | } | ||
1754 | /* dev->devq=NULL; this cannot be zeroed earlier */ | ||
1755 | DEBUGP(3, dev, "<- cmm_cm4000_release\n"); | ||
1756 | return; | ||
1757 | } | ||
1758 | |||
1759 | /*==== Interface to PCMCIA Layer =======================================*/ | ||
1760 | |||
1761 | static void cm4000_config(dev_link_t * link, int devno) | ||
1762 | { | ||
1763 | client_handle_t handle = link->handle; | ||
1764 | struct cm4000_dev *dev; | ||
1765 | tuple_t tuple; | ||
1766 | cisparse_t parse; | ||
1767 | config_info_t conf; | ||
1768 | u_char buf[64]; | ||
1769 | int fail_fn, fail_rc; | ||
1770 | int rc; | ||
1771 | |||
1772 | /* read the config-tuples */ | ||
1773 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
1774 | tuple.Attributes = 0; | ||
1775 | tuple.TupleData = buf; | ||
1776 | tuple.TupleDataMax = sizeof(buf); | ||
1777 | tuple.TupleOffset = 0; | ||
1778 | |||
1779 | if ((fail_rc = pcmcia_get_first_tuple(handle, &tuple)) != CS_SUCCESS) { | ||
1780 | fail_fn = GetFirstTuple; | ||
1781 | goto cs_failed; | ||
1782 | } | ||
1783 | if ((fail_rc = pcmcia_get_tuple_data(handle, &tuple)) != CS_SUCCESS) { | ||
1784 | fail_fn = GetTupleData; | ||
1785 | goto cs_failed; | ||
1786 | } | ||
1787 | if ((fail_rc = | ||
1788 | pcmcia_parse_tuple(handle, &tuple, &parse)) != CS_SUCCESS) { | ||
1789 | fail_fn = ParseTuple; | ||
1790 | goto cs_failed; | ||
1791 | } | ||
1792 | if ((fail_rc = | ||
1793 | pcmcia_get_configuration_info(handle, &conf)) != CS_SUCCESS) { | ||
1794 | fail_fn = GetConfigurationInfo; | ||
1795 | goto cs_failed; | ||
1796 | } | ||
1797 | |||
1798 | link->state |= DEV_CONFIG; | ||
1799 | link->conf.ConfigBase = parse.config.base; | ||
1800 | link->conf.Present = parse.config.rmask[0]; | ||
1801 | link->conf.Vcc = conf.Vcc; | ||
1802 | |||
1803 | link->io.BasePort2 = 0; | ||
1804 | link->io.NumPorts2 = 0; | ||
1805 | link->io.Attributes2 = 0; | ||
1806 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
1807 | for (rc = pcmcia_get_first_tuple(handle, &tuple); | ||
1808 | rc == CS_SUCCESS; rc = pcmcia_get_next_tuple(handle, &tuple)) { | ||
1809 | |||
1810 | rc = pcmcia_get_tuple_data(handle, &tuple); | ||
1811 | if (rc != CS_SUCCESS) | ||
1812 | continue; | ||
1813 | rc = pcmcia_parse_tuple(handle, &tuple, &parse); | ||
1814 | if (rc != CS_SUCCESS) | ||
1815 | continue; | ||
1816 | |||
1817 | link->conf.ConfigIndex = parse.cftable_entry.index; | ||
1818 | |||
1819 | if (!parse.cftable_entry.io.nwin) | ||
1820 | continue; | ||
1821 | |||
1822 | /* Get the IOaddr */ | ||
1823 | link->io.BasePort1 = parse.cftable_entry.io.win[0].base; | ||
1824 | link->io.NumPorts1 = parse.cftable_entry.io.win[0].len; | ||
1825 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
1826 | if (!(parse.cftable_entry.io.flags & CISTPL_IO_8BIT)) | ||
1827 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
1828 | if (!(parse.cftable_entry.io.flags & CISTPL_IO_16BIT)) | ||
1829 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
1830 | link->io.IOAddrLines = parse.cftable_entry.io.flags | ||
1831 | & CISTPL_IO_LINES_MASK; | ||
1832 | |||
1833 | rc = pcmcia_request_io(handle, &link->io); | ||
1834 | if (rc == CS_SUCCESS) | ||
1835 | break; /* we are done */ | ||
1836 | } | ||
1837 | if (rc != CS_SUCCESS) | ||
1838 | goto cs_release; | ||
1839 | |||
1840 | link->conf.IntType = 00000002; | ||
1841 | |||
1842 | if ((fail_rc = | ||
1843 | pcmcia_request_configuration(handle, &link->conf)) != CS_SUCCESS) { | ||
1844 | fail_fn = RequestConfiguration; | ||
1845 | goto cs_release; | ||
1846 | } | ||
1847 | |||
1848 | dev = link->priv; | ||
1849 | sprintf(dev->node.dev_name, DEVICE_NAME "%d", devno); | ||
1850 | dev->node.major = major; | ||
1851 | dev->node.minor = devno; | ||
1852 | dev->node.next = NULL; | ||
1853 | link->dev = &dev->node; | ||
1854 | link->state &= ~DEV_CONFIG_PENDING; | ||
1855 | |||
1856 | return; | ||
1857 | |||
1858 | cs_failed: | ||
1859 | cs_error(handle, fail_fn, fail_rc); | ||
1860 | cs_release: | ||
1861 | cm4000_release(link); | ||
1862 | |||
1863 | link->state &= ~DEV_CONFIG_PENDING; | ||
1864 | } | ||
1865 | |||
1866 | static int cm4000_event(event_t event, int priority, | ||
1867 | event_callback_args_t *args) | ||
1868 | { | ||
1869 | dev_link_t *link; | ||
1870 | struct cm4000_dev *dev; | ||
1871 | int devno; | ||
1872 | |||
1873 | link = args->client_data; | ||
1874 | dev = link->priv; | ||
1875 | |||
1876 | DEBUGP(3, dev, "-> cm4000_event\n"); | ||
1877 | for (devno = 0; devno < CM4000_MAX_DEV; devno++) | ||
1878 | if (dev_table[devno] == link) | ||
1879 | break; | ||
1880 | |||
1881 | if (devno == CM4000_MAX_DEV) | ||
1882 | return CS_BAD_ADAPTER; | ||
1883 | |||
1884 | switch (event) { | ||
1885 | case CS_EVENT_CARD_INSERTION: | ||
1886 | DEBUGP(5, dev, "CS_EVENT_CARD_INSERTION\n"); | ||
1887 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
1888 | cm4000_config(link, devno); | ||
1889 | break; | ||
1890 | case CS_EVENT_CARD_REMOVAL: | ||
1891 | DEBUGP(5, dev, "CS_EVENT_CARD_REMOVAL\n"); | ||
1892 | link->state &= ~DEV_PRESENT; | ||
1893 | stop_monitor(dev); | ||
1894 | break; | ||
1895 | case CS_EVENT_PM_SUSPEND: | ||
1896 | DEBUGP(5, dev, "CS_EVENT_PM_SUSPEND " | ||
1897 | "(fall-through to CS_EVENT_RESET_PHYSICAL)\n"); | ||
1898 | link->state |= DEV_SUSPEND; | ||
1899 | /* fall-through */ | ||
1900 | case CS_EVENT_RESET_PHYSICAL: | ||
1901 | DEBUGP(5, dev, "CS_EVENT_RESET_PHYSICAL\n"); | ||
1902 | if (link->state & DEV_CONFIG) { | ||
1903 | DEBUGP(5, dev, "ReleaseConfiguration\n"); | ||
1904 | pcmcia_release_configuration(link->handle); | ||
1905 | } | ||
1906 | stop_monitor(dev); | ||
1907 | break; | ||
1908 | case CS_EVENT_PM_RESUME: | ||
1909 | DEBUGP(5, dev, "CS_EVENT_PM_RESUME " | ||
1910 | "(fall-through to CS_EVENT_CARD_RESET)\n"); | ||
1911 | link->state &= ~DEV_SUSPEND; | ||
1912 | /* fall-through */ | ||
1913 | case CS_EVENT_CARD_RESET: | ||
1914 | DEBUGP(5, dev, "CS_EVENT_CARD_RESET\n"); | ||
1915 | if ((link->state & DEV_CONFIG)) { | ||
1916 | DEBUGP(5, dev, "RequestConfiguration\n"); | ||
1917 | pcmcia_request_configuration(link->handle, &link->conf); | ||
1918 | } | ||
1919 | if (link->open) | ||
1920 | start_monitor(dev); | ||
1921 | break; | ||
1922 | default: | ||
1923 | DEBUGP(5, dev, "unknown event %.2x\n", event); | ||
1924 | break; | ||
1925 | } | ||
1926 | DEBUGP(3, dev, "<- cm4000_event\n"); | ||
1927 | return CS_SUCCESS; | ||
1928 | } | ||
1929 | |||
1930 | static void cm4000_release(dev_link_t *link) | ||
1931 | { | ||
1932 | cmm_cm4000_release(link->priv); /* delay release until device closed */ | ||
1933 | pcmcia_release_configuration(link->handle); | ||
1934 | pcmcia_release_io(link->handle, &link->io); | ||
1935 | } | ||
1936 | |||
1937 | static dev_link_t *cm4000_attach(void) | ||
1938 | { | ||
1939 | struct cm4000_dev *dev; | ||
1940 | dev_link_t *link; | ||
1941 | client_reg_t client_reg; | ||
1942 | int i; | ||
1943 | |||
1944 | for (i = 0; i < CM4000_MAX_DEV; i++) | ||
1945 | if (dev_table[i] == NULL) | ||
1946 | break; | ||
1947 | |||
1948 | if (i == CM4000_MAX_DEV) { | ||
1949 | printk(KERN_NOTICE MODULE_NAME ": all devices in use\n"); | ||
1950 | return NULL; | ||
1951 | } | ||
1952 | |||
1953 | /* create a new cm4000_cs device */ | ||
1954 | dev = kzalloc(sizeof(struct cm4000_dev), GFP_KERNEL); | ||
1955 | if (dev == NULL) | ||
1956 | return NULL; | ||
1957 | |||
1958 | link = &dev->link; | ||
1959 | link->priv = dev; | ||
1960 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
1961 | dev_table[i] = link; | ||
1962 | |||
1963 | /* register with card services */ | ||
1964 | client_reg.dev_info = &dev_info; | ||
1965 | client_reg.EventMask = | ||
1966 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | | ||
1967 | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | | ||
1968 | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; | ||
1969 | client_reg.Version = 0x0210; | ||
1970 | client_reg.event_callback_args.client_data = link; | ||
1971 | |||
1972 | i = pcmcia_register_client(&link->handle, &client_reg); | ||
1973 | if (i) { | ||
1974 | cs_error(link->handle, RegisterClient, i); | ||
1975 | cm4000_detach(link); | ||
1976 | return NULL; | ||
1977 | } | ||
1978 | |||
1979 | init_waitqueue_head(&dev->devq); | ||
1980 | init_waitqueue_head(&dev->ioq); | ||
1981 | init_waitqueue_head(&dev->atrq); | ||
1982 | init_waitqueue_head(&dev->readq); | ||
1983 | |||
1984 | return link; | ||
1985 | } | ||
1986 | |||
1987 | static void cm4000_detach_by_devno(int devno, dev_link_t * link) | ||
1988 | { | ||
1989 | struct cm4000_dev *dev = link->priv; | ||
1990 | |||
1991 | DEBUGP(3, dev, "-> detach_by_devno(devno=%d)\n", devno); | ||
1992 | |||
1993 | if (link->state & DEV_CONFIG) { | ||
1994 | DEBUGP(5, dev, "device still configured (try to release it)\n"); | ||
1995 | cm4000_release(link); | ||
1996 | } | ||
1997 | |||
1998 | if (link->handle) { | ||
1999 | pcmcia_deregister_client(link->handle); | ||
2000 | } | ||
2001 | |||
2002 | dev_table[devno] = NULL; | ||
2003 | kfree(dev); | ||
2004 | return; | ||
2005 | } | ||
2006 | |||
2007 | static void cm4000_detach(dev_link_t * link) | ||
2008 | { | ||
2009 | int i; | ||
2010 | |||
2011 | /* find device */ | ||
2012 | for (i = 0; i < CM4000_MAX_DEV; i++) | ||
2013 | if (dev_table[i] == link) | ||
2014 | break; | ||
2015 | |||
2016 | if (i == CM4000_MAX_DEV) | ||
2017 | return; | ||
2018 | |||
2019 | cm4000_detach_by_devno(i, link); | ||
2020 | return; | ||
2021 | } | ||
2022 | |||
2023 | static struct file_operations cm4000_fops = { | ||
2024 | .owner = THIS_MODULE, | ||
2025 | .read = cmm_read, | ||
2026 | .write = cmm_write, | ||
2027 | .ioctl = cmm_ioctl, | ||
2028 | .open = cmm_open, | ||
2029 | .release= cmm_close, | ||
2030 | }; | ||
2031 | |||
2032 | static struct pcmcia_device_id cm4000_ids[] = { | ||
2033 | PCMCIA_DEVICE_MANF_CARD(0x0223, 0x0002), | ||
2034 | PCMCIA_DEVICE_PROD_ID12("CardMan", "4000", 0x2FB368CA, 0xA2BD8C39), | ||
2035 | PCMCIA_DEVICE_NULL, | ||
2036 | }; | ||
2037 | MODULE_DEVICE_TABLE(pcmcia, cm4000_ids); | ||
2038 | |||
2039 | static struct pcmcia_driver cm4000_driver = { | ||
2040 | .owner = THIS_MODULE, | ||
2041 | .drv = { | ||
2042 | .name = "cm4000_cs", | ||
2043 | }, | ||
2044 | .attach = cm4000_attach, | ||
2045 | .detach = cm4000_detach, | ||
2046 | .event = cm4000_event, | ||
2047 | .id_table = cm4000_ids, | ||
2048 | }; | ||
2049 | |||
2050 | static int __init cmm_init(void) | ||
2051 | { | ||
2052 | printk(KERN_INFO "%s\n", version); | ||
2053 | pcmcia_register_driver(&cm4000_driver); | ||
2054 | major = register_chrdev(0, DEVICE_NAME, &cm4000_fops); | ||
2055 | if (major < 0) { | ||
2056 | printk(KERN_WARNING MODULE_NAME | ||
2057 | ": could not get major number\n"); | ||
2058 | return -1; | ||
2059 | } | ||
2060 | |||
2061 | return 0; | ||
2062 | } | ||
2063 | |||
2064 | static void __exit cmm_exit(void) | ||
2065 | { | ||
2066 | int i; | ||
2067 | |||
2068 | printk(KERN_INFO MODULE_NAME ": unloading\n"); | ||
2069 | pcmcia_unregister_driver(&cm4000_driver); | ||
2070 | for (i = 0; i < CM4000_MAX_DEV; i++) | ||
2071 | if (dev_table[i]) | ||
2072 | cm4000_detach_by_devno(i, dev_table[i]); | ||
2073 | unregister_chrdev(major, DEVICE_NAME); | ||
2074 | }; | ||
2075 | |||
2076 | module_init(cmm_init); | ||
2077 | module_exit(cmm_exit); | ||
2078 | MODULE_LICENSE("Dual BSD/GPL"); | ||
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c new file mode 100644 index 000000000000..4c698d908ffa --- /dev/null +++ b/drivers/char/pcmcia/cm4040_cs.c | |||
@@ -0,0 +1,841 @@ | |||
1 | /* | ||
2 | * A driver for the Omnikey PCMCIA smartcard reader CardMan 4040 | ||
3 | * | ||
4 | * (c) 2000-2004 Omnikey AG (http://www.omnikey.com/) | ||
5 | * | ||
6 | * (C) 2005 Harald Welte <laforge@gnumonks.org> | ||
7 | * - add support for poll() | ||
8 | * - driver cleanup | ||
9 | * - add waitqueues | ||
10 | * - adhere to linux kernel coding style and policies | ||
11 | * - support 2.6.13 "new style" pcmcia interface | ||
12 | * | ||
13 | * The device basically is a USB CCID compliant device that has been | ||
14 | * attached to an I/O-Mapped FIFO. | ||
15 | * | ||
16 | * All rights reserved, Dual BSD/GPL Licensed. | ||
17 | */ | ||
18 | |||
19 | /* #define PCMCIA_DEBUG 6 */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/fs.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/poll.h> | ||
28 | #include <linux/wait.h> | ||
29 | #include <asm/uaccess.h> | ||
30 | #include <asm/io.h> | ||
31 | |||
32 | #include <pcmcia/cs_types.h> | ||
33 | #include <pcmcia/cs.h> | ||
34 | #include <pcmcia/cistpl.h> | ||
35 | #include <pcmcia/cisreg.h> | ||
36 | #include <pcmcia/ciscode.h> | ||
37 | #include <pcmcia/ds.h> | ||
38 | |||
39 | #include "cm4040_cs.h" | ||
40 | |||
41 | |||
42 | #ifdef PCMCIA_DEBUG | ||
43 | #define reader_to_dev(x) (&handle_to_dev(x->link.handle)) | ||
44 | static int pc_debug = PCMCIA_DEBUG; | ||
45 | module_param(pc_debug, int, 0600); | ||
46 | #define DEBUGP(n, rdr, x, args...) do { \ | ||
47 | if (pc_debug >= (n)) \ | ||
48 | dev_printk(KERN_DEBUG, reader_to_dev(rdr), "%s:" x, \ | ||
49 | __FUNCTION__ , ##args); \ | ||
50 | } while (0) | ||
51 | #else | ||
52 | #define DEBUGP(n, rdr, x, args...) | ||
53 | #endif | ||
54 | |||
55 | static char *version = | ||
56 | "OMNIKEY CardMan 4040 v1.1.0gm4 - All bugs added by Harald Welte"; | ||
57 | |||
58 | #define CCID_DRIVER_BULK_DEFAULT_TIMEOUT (150*HZ) | ||
59 | #define CCID_DRIVER_ASYNC_POWERUP_TIMEOUT (35*HZ) | ||
60 | #define CCID_DRIVER_MINIMUM_TIMEOUT (3*HZ) | ||
61 | #define READ_WRITE_BUFFER_SIZE 512 | ||
62 | #define POLL_LOOP_COUNT 1000 | ||
63 | |||
64 | /* how often to poll for fifo status change */ | ||
65 | #define POLL_PERIOD msecs_to_jiffies(10) | ||
66 | |||
67 | static void reader_release(dev_link_t *link); | ||
68 | static void reader_detach(dev_link_t *link); | ||
69 | |||
70 | static int major; | ||
71 | |||
72 | #define BS_READABLE 0x01 | ||
73 | #define BS_WRITABLE 0x02 | ||
74 | |||
75 | struct reader_dev { | ||
76 | dev_link_t link; | ||
77 | dev_node_t node; | ||
78 | wait_queue_head_t devq; | ||
79 | wait_queue_head_t poll_wait; | ||
80 | wait_queue_head_t read_wait; | ||
81 | wait_queue_head_t write_wait; | ||
82 | unsigned long buffer_status; | ||
83 | unsigned long timeout; | ||
84 | unsigned char s_buf[READ_WRITE_BUFFER_SIZE]; | ||
85 | unsigned char r_buf[READ_WRITE_BUFFER_SIZE]; | ||
86 | struct timer_list poll_timer; | ||
87 | }; | ||
88 | |||
89 | static dev_info_t dev_info = MODULE_NAME; | ||
90 | static dev_link_t *dev_table[CM_MAX_DEV]; | ||
91 | |||
92 | #ifndef PCMCIA_DEBUG | ||
93 | #define xoutb outb | ||
94 | #define xinb inb | ||
95 | #else | ||
96 | static inline void xoutb(unsigned char val, unsigned short port) | ||
97 | { | ||
98 | if (pc_debug >= 7) | ||
99 | printk(KERN_DEBUG "outb(val=%.2x,port=%.4x)\n", val, port); | ||
100 | outb(val, port); | ||
101 | } | ||
102 | |||
103 | static inline unsigned char xinb(unsigned short port) | ||
104 | { | ||
105 | unsigned char val; | ||
106 | |||
107 | val = inb(port); | ||
108 | if (pc_debug >= 7) | ||
109 | printk(KERN_DEBUG "%.2x=inb(%.4x)\n", val, port); | ||
110 | return val; | ||
111 | } | ||
112 | #endif | ||
113 | |||
114 | /* poll the device fifo status register. not to be confused with | ||
115 | * the poll syscall. */ | ||
116 | static void cm4040_do_poll(unsigned long dummy) | ||
117 | { | ||
118 | struct reader_dev *dev = (struct reader_dev *) dummy; | ||
119 | unsigned int obs = xinb(dev->link.io.BasePort1 | ||
120 | + REG_OFFSET_BUFFER_STATUS); | ||
121 | |||
122 | if ((obs & BSR_BULK_IN_FULL)) { | ||
123 | set_bit(BS_READABLE, &dev->buffer_status); | ||
124 | DEBUGP(4, dev, "waking up read_wait\n"); | ||
125 | wake_up_interruptible(&dev->read_wait); | ||
126 | } else | ||
127 | clear_bit(BS_READABLE, &dev->buffer_status); | ||
128 | |||
129 | if (!(obs & BSR_BULK_OUT_FULL)) { | ||
130 | set_bit(BS_WRITABLE, &dev->buffer_status); | ||
131 | DEBUGP(4, dev, "waking up write_wait\n"); | ||
132 | wake_up_interruptible(&dev->write_wait); | ||
133 | } else | ||
134 | clear_bit(BS_WRITABLE, &dev->buffer_status); | ||
135 | |||
136 | if (dev->buffer_status) | ||
137 | wake_up_interruptible(&dev->poll_wait); | ||
138 | |||
139 | mod_timer(&dev->poll_timer, jiffies + POLL_PERIOD); | ||
140 | } | ||
141 | |||
142 | static void cm4040_stop_poll(struct reader_dev *dev) | ||
143 | { | ||
144 | del_timer_sync(&dev->poll_timer); | ||
145 | } | ||
146 | |||
147 | static int wait_for_bulk_out_ready(struct reader_dev *dev) | ||
148 | { | ||
149 | int i, rc; | ||
150 | int iobase = dev->link.io.BasePort1; | ||
151 | |||
152 | for (i = 0; i < POLL_LOOP_COUNT; i++) { | ||
153 | if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS) | ||
154 | & BSR_BULK_OUT_FULL) == 0) { | ||
155 | DEBUGP(4, dev, "BulkOut empty (i=%d)\n", i); | ||
156 | return 1; | ||
157 | } | ||
158 | } | ||
159 | |||
160 | DEBUGP(4, dev, "wait_event_interruptible_timeout(timeout=%ld\n", | ||
161 | dev->timeout); | ||
162 | rc = wait_event_interruptible_timeout(dev->write_wait, | ||
163 | test_and_clear_bit(BS_WRITABLE, | ||
164 | &dev->buffer_status), | ||
165 | dev->timeout); | ||
166 | |||
167 | if (rc > 0) | ||
168 | DEBUGP(4, dev, "woke up: BulkOut empty\n"); | ||
169 | else if (rc == 0) | ||
170 | DEBUGP(4, dev, "woke up: BulkOut full, returning 0 :(\n"); | ||
171 | else if (rc < 0) | ||
172 | DEBUGP(4, dev, "woke up: signal arrived\n"); | ||
173 | |||
174 | return rc; | ||
175 | } | ||
176 | |||
177 | /* Write to Sync Control Register */ | ||
178 | static int write_sync_reg(unsigned char val, struct reader_dev *dev) | ||
179 | { | ||
180 | int iobase = dev->link.io.BasePort1; | ||
181 | int rc; | ||
182 | |||
183 | rc = wait_for_bulk_out_ready(dev); | ||
184 | if (rc <= 0) | ||
185 | return rc; | ||
186 | |||
187 | xoutb(val, iobase + REG_OFFSET_SYNC_CONTROL); | ||
188 | rc = wait_for_bulk_out_ready(dev); | ||
189 | if (rc <= 0) | ||
190 | return rc; | ||
191 | |||
192 | return 1; | ||
193 | } | ||
194 | |||
195 | static int wait_for_bulk_in_ready(struct reader_dev *dev) | ||
196 | { | ||
197 | int i, rc; | ||
198 | int iobase = dev->link.io.BasePort1; | ||
199 | |||
200 | for (i = 0; i < POLL_LOOP_COUNT; i++) { | ||
201 | if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS) | ||
202 | & BSR_BULK_IN_FULL) == BSR_BULK_IN_FULL) { | ||
203 | DEBUGP(3, dev, "BulkIn full (i=%d)\n", i); | ||
204 | return 1; | ||
205 | } | ||
206 | } | ||
207 | |||
208 | DEBUGP(4, dev, "wait_event_interruptible_timeout(timeout=%ld\n", | ||
209 | dev->timeout); | ||
210 | rc = wait_event_interruptible_timeout(dev->read_wait, | ||
211 | test_and_clear_bit(BS_READABLE, | ||
212 | &dev->buffer_status), | ||
213 | dev->timeout); | ||
214 | if (rc > 0) | ||
215 | DEBUGP(4, dev, "woke up: BulkIn full\n"); | ||
216 | else if (rc == 0) | ||
217 | DEBUGP(4, dev, "woke up: BulkIn not full, returning 0 :(\n"); | ||
218 | else if (rc < 0) | ||
219 | DEBUGP(4, dev, "woke up: signal arrived\n"); | ||
220 | |||
221 | return rc; | ||
222 | } | ||
223 | |||
224 | static ssize_t cm4040_read(struct file *filp, char __user *buf, | ||
225 | size_t count, loff_t *ppos) | ||
226 | { | ||
227 | struct reader_dev *dev = filp->private_data; | ||
228 | int iobase = dev->link.io.BasePort1; | ||
229 | size_t bytes_to_read; | ||
230 | unsigned long i; | ||
231 | size_t min_bytes_to_read; | ||
232 | int rc; | ||
233 | unsigned char uc; | ||
234 | |||
235 | DEBUGP(2, dev, "-> cm4040_read(%s,%d)\n", current->comm, current->pid); | ||
236 | |||
237 | if (count == 0) | ||
238 | return 0; | ||
239 | |||
240 | if (count < 10) | ||
241 | return -EFAULT; | ||
242 | |||
243 | if (filp->f_flags & O_NONBLOCK) { | ||
244 | DEBUGP(4, dev, "filep->f_flags O_NONBLOCK set\n"); | ||
245 | DEBUGP(2, dev, "<- cm4040_read (failure)\n"); | ||
246 | return -EAGAIN; | ||
247 | } | ||
248 | |||
249 | if ((dev->link.state & DEV_PRESENT)==0) | ||
250 | return -ENODEV; | ||
251 | |||
252 | for (i = 0; i < 5; i++) { | ||
253 | rc = wait_for_bulk_in_ready(dev); | ||
254 | if (rc <= 0) { | ||
255 | DEBUGP(5, dev, "wait_for_bulk_in_ready rc=%.2x\n", rc); | ||
256 | DEBUGP(2, dev, "<- cm4040_read (failed)\n"); | ||
257 | if (rc == -ERESTARTSYS) | ||
258 | return rc; | ||
259 | return -EIO; | ||
260 | } | ||
261 | dev->r_buf[i] = xinb(iobase + REG_OFFSET_BULK_IN); | ||
262 | #ifdef PCMCIA_DEBUG | ||
263 | if (pc_debug >= 6) | ||
264 | printk(KERN_DEBUG "%lu:%2x ", i, dev->r_buf[i]); | ||
265 | } | ||
266 | printk("\n"); | ||
267 | #else | ||
268 | } | ||
269 | #endif | ||
270 | |||
271 | bytes_to_read = 5 + le32_to_cpu(*(__le32 *)&dev->r_buf[1]); | ||
272 | |||
273 | DEBUGP(6, dev, "BytesToRead=%lu\n", bytes_to_read); | ||
274 | |||
275 | min_bytes_to_read = min(count, bytes_to_read + 5); | ||
276 | |||
277 | DEBUGP(6, dev, "Min=%lu\n", min_bytes_to_read); | ||
278 | |||
279 | for (i = 0; i < (min_bytes_to_read-5); i++) { | ||
280 | rc = wait_for_bulk_in_ready(dev); | ||
281 | if (rc <= 0) { | ||
282 | DEBUGP(5, dev, "wait_for_bulk_in_ready rc=%.2x\n", rc); | ||
283 | DEBUGP(2, dev, "<- cm4040_read (failed)\n"); | ||
284 | if (rc == -ERESTARTSYS) | ||
285 | return rc; | ||
286 | return -EIO; | ||
287 | } | ||
288 | dev->r_buf[i+5] = xinb(iobase + REG_OFFSET_BULK_IN); | ||
289 | #ifdef PCMCIA_DEBUG | ||
290 | if (pc_debug >= 6) | ||
291 | printk(KERN_DEBUG "%lu:%2x ", i, dev->r_buf[i]); | ||
292 | } | ||
293 | printk("\n"); | ||
294 | #else | ||
295 | } | ||
296 | #endif | ||
297 | |||
298 | *ppos = min_bytes_to_read; | ||
299 | if (copy_to_user(buf, dev->r_buf, min_bytes_to_read)) | ||
300 | return -EFAULT; | ||
301 | |||
302 | rc = wait_for_bulk_in_ready(dev); | ||
303 | if (rc <= 0) { | ||
304 | DEBUGP(5, dev, "wait_for_bulk_in_ready rc=%.2x\n", rc); | ||
305 | DEBUGP(2, dev, "<- cm4040_read (failed)\n"); | ||
306 | if (rc == -ERESTARTSYS) | ||
307 | return rc; | ||
308 | return -EIO; | ||
309 | } | ||
310 | |||
311 | rc = write_sync_reg(SCR_READER_TO_HOST_DONE, dev); | ||
312 | if (rc <= 0) { | ||
313 | DEBUGP(5, dev, "write_sync_reg c=%.2x\n", rc); | ||
314 | DEBUGP(2, dev, "<- cm4040_read (failed)\n"); | ||
315 | if (rc == -ERESTARTSYS) | ||
316 | return rc; | ||
317 | else | ||
318 | return -EIO; | ||
319 | } | ||
320 | |||
321 | uc = xinb(iobase + REG_OFFSET_BULK_IN); | ||
322 | |||
323 | DEBUGP(2, dev, "<- cm4040_read (successfully)\n"); | ||
324 | return min_bytes_to_read; | ||
325 | } | ||
326 | |||
327 | static ssize_t cm4040_write(struct file *filp, const char __user *buf, | ||
328 | size_t count, loff_t *ppos) | ||
329 | { | ||
330 | struct reader_dev *dev = filp->private_data; | ||
331 | int iobase = dev->link.io.BasePort1; | ||
332 | ssize_t rc; | ||
333 | int i; | ||
334 | unsigned int bytes_to_write; | ||
335 | |||
336 | DEBUGP(2, dev, "-> cm4040_write(%s,%d)\n", current->comm, current->pid); | ||
337 | |||
338 | if (count == 0) { | ||
339 | DEBUGP(2, dev, "<- cm4040_write empty read (successfully)\n"); | ||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | if (count < 5) { | ||
344 | DEBUGP(2, dev, "<- cm4040_write buffersize=%Zd < 5\n", count); | ||
345 | return -EIO; | ||
346 | } | ||
347 | |||
348 | if (filp->f_flags & O_NONBLOCK) { | ||
349 | DEBUGP(4, dev, "filep->f_flags O_NONBLOCK set\n"); | ||
350 | DEBUGP(4, dev, "<- cm4040_write (failure)\n"); | ||
351 | return -EAGAIN; | ||
352 | } | ||
353 | |||
354 | if ((dev->link.state & DEV_PRESENT) == 0) | ||
355 | return -ENODEV; | ||
356 | |||
357 | bytes_to_write = count; | ||
358 | if (copy_from_user(dev->s_buf, buf, bytes_to_write)) | ||
359 | return -EFAULT; | ||
360 | |||
361 | switch (dev->s_buf[0]) { | ||
362 | case CMD_PC_TO_RDR_XFRBLOCK: | ||
363 | case CMD_PC_TO_RDR_SECURE: | ||
364 | case CMD_PC_TO_RDR_TEST_SECURE: | ||
365 | case CMD_PC_TO_RDR_OK_SECURE: | ||
366 | dev->timeout = CCID_DRIVER_BULK_DEFAULT_TIMEOUT; | ||
367 | break; | ||
368 | |||
369 | case CMD_PC_TO_RDR_ICCPOWERON: | ||
370 | dev->timeout = CCID_DRIVER_ASYNC_POWERUP_TIMEOUT; | ||
371 | break; | ||
372 | |||
373 | case CMD_PC_TO_RDR_GETSLOTSTATUS: | ||
374 | case CMD_PC_TO_RDR_ICCPOWEROFF: | ||
375 | case CMD_PC_TO_RDR_GETPARAMETERS: | ||
376 | case CMD_PC_TO_RDR_RESETPARAMETERS: | ||
377 | case CMD_PC_TO_RDR_SETPARAMETERS: | ||
378 | case CMD_PC_TO_RDR_ESCAPE: | ||
379 | case CMD_PC_TO_RDR_ICCCLOCK: | ||
380 | default: | ||
381 | dev->timeout = CCID_DRIVER_MINIMUM_TIMEOUT; | ||
382 | break; | ||
383 | } | ||
384 | |||
385 | rc = write_sync_reg(SCR_HOST_TO_READER_START, dev); | ||
386 | if (rc <= 0) { | ||
387 | DEBUGP(5, dev, "write_sync_reg c=%.2Zx\n", rc); | ||
388 | DEBUGP(2, dev, "<- cm4040_write (failed)\n"); | ||
389 | if (rc == -ERESTARTSYS) | ||
390 | return rc; | ||
391 | else | ||
392 | return -EIO; | ||
393 | } | ||
394 | |||
395 | DEBUGP(4, dev, "start \n"); | ||
396 | |||
397 | for (i = 0; i < bytes_to_write; i++) { | ||
398 | rc = wait_for_bulk_out_ready(dev); | ||
399 | if (rc <= 0) { | ||
400 | DEBUGP(5, dev, "wait_for_bulk_out_ready rc=%.2Zx\n", | ||
401 | rc); | ||
402 | DEBUGP(2, dev, "<- cm4040_write (failed)\n"); | ||
403 | if (rc == -ERESTARTSYS) | ||
404 | return rc; | ||
405 | else | ||
406 | return -EIO; | ||
407 | } | ||
408 | |||
409 | xoutb(dev->s_buf[i],iobase + REG_OFFSET_BULK_OUT); | ||
410 | } | ||
411 | DEBUGP(4, dev, "end\n"); | ||
412 | |||
413 | rc = write_sync_reg(SCR_HOST_TO_READER_DONE, dev); | ||
414 | |||
415 | if (rc <= 0) { | ||
416 | DEBUGP(5, dev, "write_sync_reg c=%.2Zx\n", rc); | ||
417 | DEBUGP(2, dev, "<- cm4040_write (failed)\n"); | ||
418 | if (rc == -ERESTARTSYS) | ||
419 | return rc; | ||
420 | else | ||
421 | return -EIO; | ||
422 | } | ||
423 | |||
424 | DEBUGP(2, dev, "<- cm4040_write (successfully)\n"); | ||
425 | return count; | ||
426 | } | ||
427 | |||
428 | static unsigned int cm4040_poll(struct file *filp, poll_table *wait) | ||
429 | { | ||
430 | struct reader_dev *dev = filp->private_data; | ||
431 | unsigned int mask = 0; | ||
432 | |||
433 | poll_wait(filp, &dev->poll_wait, wait); | ||
434 | |||
435 | if (test_and_clear_bit(BS_READABLE, &dev->buffer_status)) | ||
436 | mask |= POLLIN | POLLRDNORM; | ||
437 | if (test_and_clear_bit(BS_WRITABLE, &dev->buffer_status)) | ||
438 | mask |= POLLOUT | POLLWRNORM; | ||
439 | |||
440 | DEBUGP(2, dev, "<- cm4040_poll(%u)\n", mask); | ||
441 | |||
442 | return mask; | ||
443 | } | ||
444 | |||
445 | static int cm4040_open(struct inode *inode, struct file *filp) | ||
446 | { | ||
447 | struct reader_dev *dev; | ||
448 | dev_link_t *link; | ||
449 | int minor = iminor(inode); | ||
450 | |||
451 | if (minor >= CM_MAX_DEV) | ||
452 | return -ENODEV; | ||
453 | |||
454 | link = dev_table[minor]; | ||
455 | if (link == NULL || !(DEV_OK(link))) | ||
456 | return -ENODEV; | ||
457 | |||
458 | if (link->open) | ||
459 | return -EBUSY; | ||
460 | |||
461 | dev = link->priv; | ||
462 | filp->private_data = dev; | ||
463 | |||
464 | if (filp->f_flags & O_NONBLOCK) { | ||
465 | DEBUGP(4, dev, "filep->f_flags O_NONBLOCK set\n"); | ||
466 | return -EAGAIN; | ||
467 | } | ||
468 | |||
469 | link->open = 1; | ||
470 | |||
471 | dev->poll_timer.data = (unsigned long) dev; | ||
472 | mod_timer(&dev->poll_timer, jiffies + POLL_PERIOD); | ||
473 | |||
474 | DEBUGP(2, dev, "<- cm4040_open (successfully)\n"); | ||
475 | return nonseekable_open(inode, filp); | ||
476 | } | ||
477 | |||
478 | static int cm4040_close(struct inode *inode, struct file *filp) | ||
479 | { | ||
480 | struct reader_dev *dev = filp->private_data; | ||
481 | dev_link_t *link; | ||
482 | int minor = iminor(inode); | ||
483 | |||
484 | DEBUGP(2, dev, "-> cm4040_close(maj/min=%d.%d)\n", imajor(inode), | ||
485 | iminor(inode)); | ||
486 | |||
487 | if (minor >= CM_MAX_DEV) | ||
488 | return -ENODEV; | ||
489 | |||
490 | link = dev_table[minor]; | ||
491 | if (link == NULL) | ||
492 | return -ENODEV; | ||
493 | |||
494 | cm4040_stop_poll(dev); | ||
495 | |||
496 | link->open = 0; | ||
497 | wake_up(&dev->devq); | ||
498 | |||
499 | DEBUGP(2, dev, "<- cm4040_close\n"); | ||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | static void cm4040_reader_release(dev_link_t *link) | ||
504 | { | ||
505 | struct reader_dev *dev = link->priv; | ||
506 | |||
507 | DEBUGP(3, dev, "-> cm4040_reader_release\n"); | ||
508 | while (link->open) { | ||
509 | DEBUGP(3, dev, KERN_INFO MODULE_NAME ": delaying release " | ||
510 | "until process has terminated\n"); | ||
511 | wait_event(dev->devq, (link->open == 0)); | ||
512 | } | ||
513 | DEBUGP(3, dev, "<- cm4040_reader_release\n"); | ||
514 | return; | ||
515 | } | ||
516 | |||
517 | static void reader_config(dev_link_t *link, int devno) | ||
518 | { | ||
519 | client_handle_t handle; | ||
520 | struct reader_dev *dev; | ||
521 | tuple_t tuple; | ||
522 | cisparse_t parse; | ||
523 | config_info_t conf; | ||
524 | u_char buf[64]; | ||
525 | int fail_fn, fail_rc; | ||
526 | int rc; | ||
527 | |||
528 | handle = link->handle; | ||
529 | |||
530 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
531 | tuple.Attributes = 0; | ||
532 | tuple.TupleData = buf; | ||
533 | tuple.TupleDataMax = sizeof(buf); | ||
534 | tuple.TupleOffset = 0; | ||
535 | |||
536 | if ((fail_rc = pcmcia_get_first_tuple(handle, &tuple)) != CS_SUCCESS) { | ||
537 | fail_fn = GetFirstTuple; | ||
538 | goto cs_failed; | ||
539 | } | ||
540 | if ((fail_rc = pcmcia_get_tuple_data(handle, &tuple)) != CS_SUCCESS) { | ||
541 | fail_fn = GetTupleData; | ||
542 | goto cs_failed; | ||
543 | } | ||
544 | if ((fail_rc = pcmcia_parse_tuple(handle, &tuple, &parse)) | ||
545 | != CS_SUCCESS) { | ||
546 | fail_fn = ParseTuple; | ||
547 | goto cs_failed; | ||
548 | } | ||
549 | if ((fail_rc = pcmcia_get_configuration_info(handle, &conf)) | ||
550 | != CS_SUCCESS) { | ||
551 | fail_fn = GetConfigurationInfo; | ||
552 | goto cs_failed; | ||
553 | } | ||
554 | |||
555 | link->state |= DEV_CONFIG; | ||
556 | link->conf.ConfigBase = parse.config.base; | ||
557 | link->conf.Present = parse.config.rmask[0]; | ||
558 | link->conf.Vcc = conf.Vcc; | ||
559 | |||
560 | link->io.BasePort2 = 0; | ||
561 | link->io.NumPorts2 = 0; | ||
562 | link->io.Attributes2 = 0; | ||
563 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
564 | for (rc = pcmcia_get_first_tuple(handle, &tuple); | ||
565 | rc == CS_SUCCESS; | ||
566 | rc = pcmcia_get_next_tuple(handle, &tuple)) { | ||
567 | rc = pcmcia_get_tuple_data(handle, &tuple); | ||
568 | if (rc != CS_SUCCESS) | ||
569 | continue; | ||
570 | rc = pcmcia_parse_tuple(handle, &tuple, &parse); | ||
571 | if (rc != CS_SUCCESS) | ||
572 | continue; | ||
573 | |||
574 | link->conf.ConfigIndex = parse.cftable_entry.index; | ||
575 | |||
576 | if (!parse.cftable_entry.io.nwin) | ||
577 | continue; | ||
578 | |||
579 | link->io.BasePort1 = parse.cftable_entry.io.win[0].base; | ||
580 | link->io.NumPorts1 = parse.cftable_entry.io.win[0].len; | ||
581 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
582 | if (!(parse.cftable_entry.io.flags & CISTPL_IO_8BIT)) | ||
583 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
584 | if (!(parse.cftable_entry.io.flags & CISTPL_IO_16BIT)) | ||
585 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
586 | link->io.IOAddrLines = parse.cftable_entry.io.flags | ||
587 | & CISTPL_IO_LINES_MASK; | ||
588 | rc = pcmcia_request_io(handle, &link->io); | ||
589 | |||
590 | dev_printk(KERN_INFO, &handle_to_dev(handle), "foo"); | ||
591 | if (rc == CS_SUCCESS) | ||
592 | break; | ||
593 | else | ||
594 | dev_printk(KERN_INFO, &handle_to_dev(handle), | ||
595 | "pcmcia_request_io failed 0x%x\n", rc); | ||
596 | } | ||
597 | if (rc != CS_SUCCESS) | ||
598 | goto cs_release; | ||
599 | |||
600 | link->conf.IntType = 00000002; | ||
601 | |||
602 | if ((fail_rc = pcmcia_request_configuration(handle,&link->conf)) | ||
603 | !=CS_SUCCESS) { | ||
604 | fail_fn = RequestConfiguration; | ||
605 | dev_printk(KERN_INFO, &handle_to_dev(handle), | ||
606 | "pcmcia_request_configuration failed 0x%x\n", | ||
607 | fail_rc); | ||
608 | goto cs_release; | ||
609 | } | ||
610 | |||
611 | dev = link->priv; | ||
612 | sprintf(dev->node.dev_name, DEVICE_NAME "%d", devno); | ||
613 | dev->node.major = major; | ||
614 | dev->node.minor = devno; | ||
615 | dev->node.next = NULL; | ||
616 | link->dev = &dev->node; | ||
617 | link->state &= ~DEV_CONFIG_PENDING; | ||
618 | |||
619 | DEBUGP(2, dev, "device " DEVICE_NAME "%d at 0x%.4x-0x%.4x\n", devno, | ||
620 | link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1); | ||
621 | DEBUGP(2, dev, "<- reader_config (succ)\n"); | ||
622 | |||
623 | return; | ||
624 | |||
625 | cs_failed: | ||
626 | cs_error(handle, fail_fn, fail_rc); | ||
627 | cs_release: | ||
628 | reader_release(link); | ||
629 | link->state &= ~DEV_CONFIG_PENDING; | ||
630 | } | ||
631 | |||
632 | static int reader_event(event_t event, int priority, | ||
633 | event_callback_args_t *args) | ||
634 | { | ||
635 | dev_link_t *link; | ||
636 | struct reader_dev *dev; | ||
637 | int devno; | ||
638 | |||
639 | link = args->client_data; | ||
640 | dev = link->priv; | ||
641 | DEBUGP(3, dev, "-> reader_event\n"); | ||
642 | for (devno = 0; devno < CM_MAX_DEV; devno++) { | ||
643 | if (dev_table[devno] == link) | ||
644 | break; | ||
645 | } | ||
646 | if (devno == CM_MAX_DEV) | ||
647 | return CS_BAD_ADAPTER; | ||
648 | |||
649 | switch (event) { | ||
650 | case CS_EVENT_CARD_INSERTION: | ||
651 | DEBUGP(5, dev, "CS_EVENT_CARD_INSERTION\n"); | ||
652 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
653 | reader_config(link, devno); | ||
654 | break; | ||
655 | case CS_EVENT_CARD_REMOVAL: | ||
656 | DEBUGP(5, dev, "CS_EVENT_CARD_REMOVAL\n"); | ||
657 | link->state &= ~DEV_PRESENT; | ||
658 | break; | ||
659 | case CS_EVENT_PM_SUSPEND: | ||
660 | DEBUGP(5, dev, "CS_EVENT_PM_SUSPEND " | ||
661 | "(fall-through to CS_EVENT_RESET_PHYSICAL)\n"); | ||
662 | link->state |= DEV_SUSPEND; | ||
663 | |||
664 | case CS_EVENT_RESET_PHYSICAL: | ||
665 | DEBUGP(5, dev, "CS_EVENT_RESET_PHYSICAL\n"); | ||
666 | if (link->state & DEV_CONFIG) { | ||
667 | DEBUGP(5, dev, "ReleaseConfiguration\n"); | ||
668 | pcmcia_release_configuration(link->handle); | ||
669 | } | ||
670 | break; | ||
671 | case CS_EVENT_PM_RESUME: | ||
672 | DEBUGP(5, dev, "CS_EVENT_PM_RESUME " | ||
673 | "(fall-through to CS_EVENT_CARD_RESET)\n"); | ||
674 | link->state &= ~DEV_SUSPEND; | ||
675 | |||
676 | case CS_EVENT_CARD_RESET: | ||
677 | DEBUGP(5, dev, "CS_EVENT_CARD_RESET\n"); | ||
678 | if ((link->state & DEV_CONFIG)) { | ||
679 | DEBUGP(5, dev, "RequestConfiguration\n"); | ||
680 | pcmcia_request_configuration(link->handle, | ||
681 | &link->conf); | ||
682 | } | ||
683 | break; | ||
684 | default: | ||
685 | DEBUGP(5, dev, "reader_event: unknown event %.2x\n", | ||
686 | event); | ||
687 | break; | ||
688 | } | ||
689 | DEBUGP(3, dev, "<- reader_event\n"); | ||
690 | return CS_SUCCESS; | ||
691 | } | ||
692 | |||
693 | static void reader_release(dev_link_t *link) | ||
694 | { | ||
695 | cm4040_reader_release(link->priv); | ||
696 | pcmcia_release_configuration(link->handle); | ||
697 | pcmcia_release_io(link->handle, &link->io); | ||
698 | } | ||
699 | |||
700 | static dev_link_t *reader_attach(void) | ||
701 | { | ||
702 | struct reader_dev *dev; | ||
703 | dev_link_t *link; | ||
704 | client_reg_t client_reg; | ||
705 | int i; | ||
706 | |||
707 | for (i = 0; i < CM_MAX_DEV; i++) { | ||
708 | if (dev_table[i] == NULL) | ||
709 | break; | ||
710 | } | ||
711 | |||
712 | if (i == CM_MAX_DEV) | ||
713 | return NULL; | ||
714 | |||
715 | dev = kzalloc(sizeof(struct reader_dev), GFP_KERNEL); | ||
716 | if (dev == NULL) | ||
717 | return NULL; | ||
718 | |||
719 | dev->timeout = CCID_DRIVER_MINIMUM_TIMEOUT; | ||
720 | dev->buffer_status = 0; | ||
721 | |||
722 | link = &dev->link; | ||
723 | link->priv = dev; | ||
724 | |||
725 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
726 | dev_table[i] = link; | ||
727 | |||
728 | client_reg.dev_info = &dev_info; | ||
729 | client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; | ||
730 | client_reg.EventMask= | ||
731 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | | ||
732 | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | | ||
733 | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; | ||
734 | client_reg.Version = 0x0210; | ||
735 | client_reg.event_callback_args.client_data = link; | ||
736 | i = pcmcia_register_client(&link->handle, &client_reg); | ||
737 | if (i) { | ||
738 | cs_error(link->handle, RegisterClient, i); | ||
739 | reader_detach(link); | ||
740 | return NULL; | ||
741 | } | ||
742 | init_waitqueue_head(&dev->devq); | ||
743 | init_waitqueue_head(&dev->poll_wait); | ||
744 | init_waitqueue_head(&dev->read_wait); | ||
745 | init_waitqueue_head(&dev->write_wait); | ||
746 | init_timer(&dev->poll_timer); | ||
747 | dev->poll_timer.function = &cm4040_do_poll; | ||
748 | |||
749 | return link; | ||
750 | } | ||
751 | |||
752 | static void reader_detach_by_devno(int devno, dev_link_t *link) | ||
753 | { | ||
754 | struct reader_dev *dev = link->priv; | ||
755 | |||
756 | if (link->state & DEV_CONFIG) { | ||
757 | DEBUGP(5, dev, "device still configured (try to release it)\n"); | ||
758 | reader_release(link); | ||
759 | } | ||
760 | |||
761 | pcmcia_deregister_client(link->handle); | ||
762 | dev_table[devno] = NULL; | ||
763 | DEBUGP(5, dev, "freeing dev=%p\n", dev); | ||
764 | cm4040_stop_poll(dev); | ||
765 | kfree(dev); | ||
766 | return; | ||
767 | } | ||
768 | |||
769 | static void reader_detach(dev_link_t *link) | ||
770 | { | ||
771 | int i; | ||
772 | |||
773 | /* find device */ | ||
774 | for (i = 0; i < CM_MAX_DEV; i++) { | ||
775 | if (dev_table[i] == link) | ||
776 | break; | ||
777 | } | ||
778 | if (i == CM_MAX_DEV) | ||
779 | return; | ||
780 | |||
781 | reader_detach_by_devno(i, link); | ||
782 | return; | ||
783 | } | ||
784 | |||
785 | static struct file_operations reader_fops = { | ||
786 | .owner = THIS_MODULE, | ||
787 | .read = cm4040_read, | ||
788 | .write = cm4040_write, | ||
789 | .open = cm4040_open, | ||
790 | .release = cm4040_close, | ||
791 | .poll = cm4040_poll, | ||
792 | }; | ||
793 | |||
794 | static struct pcmcia_device_id cm4040_ids[] = { | ||
795 | PCMCIA_DEVICE_MANF_CARD(0x0223, 0x0200), | ||
796 | PCMCIA_DEVICE_PROD_ID12("OMNIKEY", "CardMan 4040", | ||
797 | 0xE32CDD8C, 0x8F23318B), | ||
798 | PCMCIA_DEVICE_NULL, | ||
799 | }; | ||
800 | MODULE_DEVICE_TABLE(pcmcia, cm4040_ids); | ||
801 | |||
802 | static struct pcmcia_driver reader_driver = { | ||
803 | .owner = THIS_MODULE, | ||
804 | .drv = { | ||
805 | .name = "cm4040_cs", | ||
806 | }, | ||
807 | .attach = reader_attach, | ||
808 | .detach = reader_detach, | ||
809 | .event = reader_event, | ||
810 | .id_table = cm4040_ids, | ||
811 | }; | ||
812 | |||
813 | static int __init cm4040_init(void) | ||
814 | { | ||
815 | printk(KERN_INFO "%s\n", version); | ||
816 | pcmcia_register_driver(&reader_driver); | ||
817 | major = register_chrdev(0, DEVICE_NAME, &reader_fops); | ||
818 | if (major < 0) { | ||
819 | printk(KERN_WARNING MODULE_NAME | ||
820 | ": could not get major number\n"); | ||
821 | return -1; | ||
822 | } | ||
823 | return 0; | ||
824 | } | ||
825 | |||
826 | static void __exit cm4040_exit(void) | ||
827 | { | ||
828 | int i; | ||
829 | |||
830 | printk(KERN_INFO MODULE_NAME ": unloading\n"); | ||
831 | pcmcia_unregister_driver(&reader_driver); | ||
832 | for (i = 0; i < CM_MAX_DEV; i++) { | ||
833 | if (dev_table[i]) | ||
834 | reader_detach_by_devno(i, dev_table[i]); | ||
835 | } | ||
836 | unregister_chrdev(major, DEVICE_NAME); | ||
837 | } | ||
838 | |||
839 | module_init(cm4040_init); | ||
840 | module_exit(cm4040_exit); | ||
841 | MODULE_LICENSE("Dual BSD/GPL"); | ||
diff --git a/drivers/char/pcmcia/cm4040_cs.h b/drivers/char/pcmcia/cm4040_cs.h new file mode 100644 index 000000000000..9a8b805c5095 --- /dev/null +++ b/drivers/char/pcmcia/cm4040_cs.h | |||
@@ -0,0 +1,47 @@ | |||
1 | #ifndef _CM4040_H_ | ||
2 | #define _CM4040_H_ | ||
3 | |||
4 | #define CM_MAX_DEV 4 | ||
5 | |||
6 | #define DEVICE_NAME "cmx" | ||
7 | #define MODULE_NAME "cm4040_cs" | ||
8 | |||
9 | #define REG_OFFSET_BULK_OUT 0 | ||
10 | #define REG_OFFSET_BULK_IN 0 | ||
11 | #define REG_OFFSET_BUFFER_STATUS 1 | ||
12 | #define REG_OFFSET_SYNC_CONTROL 2 | ||
13 | |||
14 | #define BSR_BULK_IN_FULL 0x02 | ||
15 | #define BSR_BULK_OUT_FULL 0x01 | ||
16 | |||
17 | #define SCR_HOST_TO_READER_START 0x80 | ||
18 | #define SCR_ABORT 0x40 | ||
19 | #define SCR_EN_NOTIFY 0x20 | ||
20 | #define SCR_ACK_NOTIFY 0x10 | ||
21 | #define SCR_READER_TO_HOST_DONE 0x08 | ||
22 | #define SCR_HOST_TO_READER_DONE 0x04 | ||
23 | #define SCR_PULSE_INTERRUPT 0x02 | ||
24 | #define SCR_POWER_DOWN 0x01 | ||
25 | |||
26 | |||
27 | #define CMD_PC_TO_RDR_ICCPOWERON 0x62 | ||
28 | #define CMD_PC_TO_RDR_GETSLOTSTATUS 0x65 | ||
29 | #define CMD_PC_TO_RDR_ICCPOWEROFF 0x63 | ||
30 | #define CMD_PC_TO_RDR_SECURE 0x69 | ||
31 | #define CMD_PC_TO_RDR_GETPARAMETERS 0x6C | ||
32 | #define CMD_PC_TO_RDR_RESETPARAMETERS 0x6D | ||
33 | #define CMD_PC_TO_RDR_SETPARAMETERS 0x61 | ||
34 | #define CMD_PC_TO_RDR_XFRBLOCK 0x6F | ||
35 | #define CMD_PC_TO_RDR_ESCAPE 0x6B | ||
36 | #define CMD_PC_TO_RDR_ICCCLOCK 0x6E | ||
37 | #define CMD_PC_TO_RDR_TEST_SECURE 0x74 | ||
38 | #define CMD_PC_TO_RDR_OK_SECURE 0x89 | ||
39 | |||
40 | |||
41 | #define CMD_RDR_TO_PC_SLOTSTATUS 0x81 | ||
42 | #define CMD_RDR_TO_PC_DATABLOCK 0x80 | ||
43 | #define CMD_RDR_TO_PC_PARAMETERS 0x82 | ||
44 | #define CMD_RDR_TO_PC_ESCAPE 0x83 | ||
45 | #define CMD_RDR_TO_PC_OK_SECURE 0x89 | ||
46 | |||
47 | #endif /* _CM4040_H_ */ | ||
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 82c6abde68df..62aa0e534a6d 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/char/synclink.c | 2 | * linux/drivers/char/synclink.c |
3 | * | 3 | * |
4 | * $Id: synclink.c,v 4.37 2005/09/07 13:13:19 paulkf Exp $ | 4 | * $Id: synclink.c,v 4.38 2005/11/07 16:30:34 paulkf Exp $ |
5 | * | 5 | * |
6 | * Device driver for Microgate SyncLink ISA and PCI | 6 | * Device driver for Microgate SyncLink ISA and PCI |
7 | * high speed multiprotocol serial adapters. | 7 | * high speed multiprotocol serial adapters. |
@@ -101,6 +101,7 @@ | |||
101 | #include <linux/termios.h> | 101 | #include <linux/termios.h> |
102 | #include <linux/workqueue.h> | 102 | #include <linux/workqueue.h> |
103 | #include <linux/hdlc.h> | 103 | #include <linux/hdlc.h> |
104 | #include <linux/dma-mapping.h> | ||
104 | 105 | ||
105 | #ifdef CONFIG_HDLC_MODULE | 106 | #ifdef CONFIG_HDLC_MODULE |
106 | #define CONFIG_HDLC 1 | 107 | #define CONFIG_HDLC 1 |
@@ -148,6 +149,7 @@ typedef struct _DMABUFFERENTRY | |||
148 | u32 link; /* 32-bit flat link to next buffer entry */ | 149 | u32 link; /* 32-bit flat link to next buffer entry */ |
149 | char *virt_addr; /* virtual address of data buffer */ | 150 | char *virt_addr; /* virtual address of data buffer */ |
150 | u32 phys_entry; /* physical address of this buffer entry */ | 151 | u32 phys_entry; /* physical address of this buffer entry */ |
152 | dma_addr_t dma_addr; | ||
151 | } DMABUFFERENTRY, *DMAPBUFFERENTRY; | 153 | } DMABUFFERENTRY, *DMAPBUFFERENTRY; |
152 | 154 | ||
153 | /* The queue of BH actions to be performed */ | 155 | /* The queue of BH actions to be performed */ |
@@ -233,7 +235,8 @@ struct mgsl_struct { | |||
233 | int ri_chkcount; | 235 | int ri_chkcount; |
234 | 236 | ||
235 | char *buffer_list; /* virtual address of Rx & Tx buffer lists */ | 237 | char *buffer_list; /* virtual address of Rx & Tx buffer lists */ |
236 | unsigned long buffer_list_phys; | 238 | u32 buffer_list_phys; |
239 | dma_addr_t buffer_list_dma_addr; | ||
237 | 240 | ||
238 | unsigned int rx_buffer_count; /* count of total allocated Rx buffers */ | 241 | unsigned int rx_buffer_count; /* count of total allocated Rx buffers */ |
239 | DMABUFFERENTRY *rx_buffer_list; /* list of receive buffer entries */ | 242 | DMABUFFERENTRY *rx_buffer_list; /* list of receive buffer entries */ |
@@ -896,7 +899,7 @@ module_param_array(txdmabufs, int, NULL, 0); | |||
896 | module_param_array(txholdbufs, int, NULL, 0); | 899 | module_param_array(txholdbufs, int, NULL, 0); |
897 | 900 | ||
898 | static char *driver_name = "SyncLink serial driver"; | 901 | static char *driver_name = "SyncLink serial driver"; |
899 | static char *driver_version = "$Revision: 4.37 $"; | 902 | static char *driver_version = "$Revision: 4.38 $"; |
900 | 903 | ||
901 | static int synclink_init_one (struct pci_dev *dev, | 904 | static int synclink_init_one (struct pci_dev *dev, |
902 | const struct pci_device_id *ent); | 905 | const struct pci_device_id *ent); |
@@ -3811,11 +3814,10 @@ static int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info ) | |||
3811 | /* inspect portions of the buffer while other portions are being */ | 3814 | /* inspect portions of the buffer while other portions are being */ |
3812 | /* updated by the adapter using Bus Master DMA. */ | 3815 | /* updated by the adapter using Bus Master DMA. */ |
3813 | 3816 | ||
3814 | info->buffer_list = kmalloc(BUFFERLISTSIZE, GFP_KERNEL | GFP_DMA); | 3817 | info->buffer_list = dma_alloc_coherent(NULL, BUFFERLISTSIZE, &info->buffer_list_dma_addr, GFP_KERNEL); |
3815 | if ( info->buffer_list == NULL ) | 3818 | if (info->buffer_list == NULL) |
3816 | return -ENOMEM; | 3819 | return -ENOMEM; |
3817 | 3820 | info->buffer_list_phys = (u32)(info->buffer_list_dma_addr); | |
3818 | info->buffer_list_phys = isa_virt_to_bus(info->buffer_list); | ||
3819 | } | 3821 | } |
3820 | 3822 | ||
3821 | /* We got the memory for the buffer entry lists. */ | 3823 | /* We got the memory for the buffer entry lists. */ |
@@ -3882,8 +3884,8 @@ static int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info ) | |||
3882 | */ | 3884 | */ |
3883 | static void mgsl_free_buffer_list_memory( struct mgsl_struct *info ) | 3885 | static void mgsl_free_buffer_list_memory( struct mgsl_struct *info ) |
3884 | { | 3886 | { |
3885 | if ( info->buffer_list && info->bus_type != MGSL_BUS_TYPE_PCI ) | 3887 | if (info->buffer_list && info->bus_type != MGSL_BUS_TYPE_PCI) |
3886 | kfree(info->buffer_list); | 3888 | dma_free_coherent(NULL, BUFFERLISTSIZE, info->buffer_list, info->buffer_list_dma_addr); |
3887 | 3889 | ||
3888 | info->buffer_list = NULL; | 3890 | info->buffer_list = NULL; |
3889 | info->rx_buffer_list = NULL; | 3891 | info->rx_buffer_list = NULL; |
@@ -3910,7 +3912,7 @@ static void mgsl_free_buffer_list_memory( struct mgsl_struct *info ) | |||
3910 | static int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList,int Buffercount) | 3912 | static int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList,int Buffercount) |
3911 | { | 3913 | { |
3912 | int i; | 3914 | int i; |
3913 | unsigned long phys_addr; | 3915 | u32 phys_addr; |
3914 | 3916 | ||
3915 | /* Allocate page sized buffers for the receive buffer list */ | 3917 | /* Allocate page sized buffers for the receive buffer list */ |
3916 | 3918 | ||
@@ -3922,11 +3924,10 @@ static int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *Buff | |||
3922 | info->last_mem_alloc += DMABUFFERSIZE; | 3924 | info->last_mem_alloc += DMABUFFERSIZE; |
3923 | } else { | 3925 | } else { |
3924 | /* ISA adapter uses system memory. */ | 3926 | /* ISA adapter uses system memory. */ |
3925 | BufferList[i].virt_addr = | 3927 | BufferList[i].virt_addr = dma_alloc_coherent(NULL, DMABUFFERSIZE, &BufferList[i].dma_addr, GFP_KERNEL); |
3926 | kmalloc(DMABUFFERSIZE, GFP_KERNEL | GFP_DMA); | 3928 | if (BufferList[i].virt_addr == NULL) |
3927 | if ( BufferList[i].virt_addr == NULL ) | ||
3928 | return -ENOMEM; | 3929 | return -ENOMEM; |
3929 | phys_addr = isa_virt_to_bus(BufferList[i].virt_addr); | 3930 | phys_addr = (u32)(BufferList[i].dma_addr); |
3930 | } | 3931 | } |
3931 | BufferList[i].phys_addr = phys_addr; | 3932 | BufferList[i].phys_addr = phys_addr; |
3932 | } | 3933 | } |
@@ -3957,7 +3958,7 @@ static void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *Buf | |||
3957 | for ( i = 0 ; i < Buffercount ; i++ ) { | 3958 | for ( i = 0 ; i < Buffercount ; i++ ) { |
3958 | if ( BufferList[i].virt_addr ) { | 3959 | if ( BufferList[i].virt_addr ) { |
3959 | if ( info->bus_type != MGSL_BUS_TYPE_PCI ) | 3960 | if ( info->bus_type != MGSL_BUS_TYPE_PCI ) |
3960 | kfree(BufferList[i].virt_addr); | 3961 | dma_free_coherent(NULL, DMABUFFERSIZE, BufferList[i].virt_addr, BufferList[i].dma_addr); |
3961 | BufferList[i].virt_addr = NULL; | 3962 | BufferList[i].virt_addr = NULL; |
3962 | } | 3963 | } |
3963 | } | 3964 | } |
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 303f15880466..0b283d246730 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -43,6 +43,13 @@ static void user_reader_timeout(unsigned long ptr) | |||
43 | { | 43 | { |
44 | struct tpm_chip *chip = (struct tpm_chip *) ptr; | 44 | struct tpm_chip *chip = (struct tpm_chip *) ptr; |
45 | 45 | ||
46 | schedule_work(&chip->work); | ||
47 | } | ||
48 | |||
49 | static void timeout_work(void * ptr) | ||
50 | { | ||
51 | struct tpm_chip *chip = ptr; | ||
52 | |||
46 | down(&chip->buffer_mutex); | 53 | down(&chip->buffer_mutex); |
47 | atomic_set(&chip->data_pending, 0); | 54 | atomic_set(&chip->data_pending, 0); |
48 | memset(chip->data_buffer, 0, TPM_BUFSIZE); | 55 | memset(chip->data_buffer, 0, TPM_BUFSIZE); |
@@ -428,8 +435,7 @@ ssize_t tpm_read(struct file * file, char __user *buf, | |||
428 | ret_size = size; | 435 | ret_size = size; |
429 | 436 | ||
430 | down(&chip->buffer_mutex); | 437 | down(&chip->buffer_mutex); |
431 | if (copy_to_user | 438 | if (copy_to_user(buf, chip->data_buffer, ret_size)) |
432 | ((void __user *) buf, chip->data_buffer, ret_size)) | ||
433 | ret_size = -EFAULT; | 439 | ret_size = -EFAULT; |
434 | up(&chip->buffer_mutex); | 440 | up(&chip->buffer_mutex); |
435 | } | 441 | } |
@@ -460,7 +466,7 @@ void tpm_remove_hardware(struct device *dev) | |||
460 | sysfs_remove_group(&dev->kobj, chip->vendor->attr_group); | 466 | sysfs_remove_group(&dev->kobj, chip->vendor->attr_group); |
461 | 467 | ||
462 | dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= | 468 | dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= |
463 | !(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES)); | 469 | ~(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES)); |
464 | 470 | ||
465 | kfree(chip); | 471 | kfree(chip); |
466 | 472 | ||
@@ -528,6 +534,8 @@ int tpm_register_hardware(struct device *dev, struct tpm_vendor_specific *entry) | |||
528 | init_MUTEX(&chip->tpm_mutex); | 534 | init_MUTEX(&chip->tpm_mutex); |
529 | INIT_LIST_HEAD(&chip->list); | 535 | INIT_LIST_HEAD(&chip->list); |
530 | 536 | ||
537 | INIT_WORK(&chip->work, timeout_work, chip); | ||
538 | |||
531 | init_timer(&chip->user_read_timer); | 539 | init_timer(&chip->user_read_timer); |
532 | chip->user_read_timer.function = user_reader_timeout; | 540 | chip->user_read_timer.function = user_reader_timeout; |
533 | chip->user_read_timer.data = (unsigned long) chip; | 541 | chip->user_read_timer.data = (unsigned long) chip; |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 9293bcc4dc62..159882ca69dd 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -50,7 +50,11 @@ struct tpm_vendor_specific { | |||
50 | u8 req_complete_mask; | 50 | u8 req_complete_mask; |
51 | u8 req_complete_val; | 51 | u8 req_complete_val; |
52 | u8 req_canceled; | 52 | u8 req_canceled; |
53 | u16 base; /* TPM base address */ | 53 | void __iomem *iobase; /* ioremapped address */ |
54 | unsigned long base; /* TPM base address */ | ||
55 | |||
56 | int region_size; | ||
57 | int have_region; | ||
54 | 58 | ||
55 | int (*recv) (struct tpm_chip *, u8 *, size_t); | 59 | int (*recv) (struct tpm_chip *, u8 *, size_t); |
56 | int (*send) (struct tpm_chip *, u8 *, size_t); | 60 | int (*send) (struct tpm_chip *, u8 *, size_t); |
@@ -73,6 +77,7 @@ struct tpm_chip { | |||
73 | struct semaphore buffer_mutex; | 77 | struct semaphore buffer_mutex; |
74 | 78 | ||
75 | struct timer_list user_read_timer; /* user needs to claim result */ | 79 | struct timer_list user_read_timer; /* user needs to claim result */ |
80 | struct work_struct work; | ||
76 | struct semaphore tpm_mutex; /* tpm is processing */ | 81 | struct semaphore tpm_mutex; /* tpm is processing */ |
77 | 82 | ||
78 | struct tpm_vendor_specific *vendor; | 83 | struct tpm_vendor_specific *vendor; |
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c index 32e01450c425..deb4b5c80914 100644 --- a/drivers/char/tpm/tpm_atmel.c +++ b/drivers/char/tpm/tpm_atmel.c | |||
@@ -19,14 +19,8 @@ | |||
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/platform_device.h> | ||
23 | #include "tpm.h" | 22 | #include "tpm.h" |
24 | 23 | #include "tpm_atmel.h" | |
25 | /* Atmel definitions */ | ||
26 | enum tpm_atmel_addr { | ||
27 | TPM_ATMEL_BASE_ADDR_LO = 0x08, | ||
28 | TPM_ATMEL_BASE_ADDR_HI = 0x09 | ||
29 | }; | ||
30 | 24 | ||
31 | /* write status bits */ | 25 | /* write status bits */ |
32 | enum tpm_atmel_write_status { | 26 | enum tpm_atmel_write_status { |
@@ -53,13 +47,13 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
53 | return -EIO; | 47 | return -EIO; |
54 | 48 | ||
55 | for (i = 0; i < 6; i++) { | 49 | for (i = 0; i < 6; i++) { |
56 | status = inb(chip->vendor->base + 1); | 50 | status = atmel_getb(chip, 1); |
57 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { | 51 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { |
58 | dev_err(chip->dev, | 52 | dev_err(chip->dev, |
59 | "error reading header\n"); | 53 | "error reading header\n"); |
60 | return -EIO; | 54 | return -EIO; |
61 | } | 55 | } |
62 | *buf++ = inb(chip->vendor->base); | 56 | *buf++ = atmel_getb(chip, 0); |
63 | } | 57 | } |
64 | 58 | ||
65 | /* size of the data received */ | 59 | /* size of the data received */ |
@@ -70,7 +64,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
70 | dev_err(chip->dev, | 64 | dev_err(chip->dev, |
71 | "Recv size(%d) less than available space\n", size); | 65 | "Recv size(%d) less than available space\n", size); |
72 | for (; i < size; i++) { /* clear the waiting data anyway */ | 66 | for (; i < size; i++) { /* clear the waiting data anyway */ |
73 | status = inb(chip->vendor->base + 1); | 67 | status = atmel_getb(chip, 1); |
74 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { | 68 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { |
75 | dev_err(chip->dev, | 69 | dev_err(chip->dev, |
76 | "error reading data\n"); | 70 | "error reading data\n"); |
@@ -82,17 +76,17 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
82 | 76 | ||
83 | /* read all the data available */ | 77 | /* read all the data available */ |
84 | for (; i < size; i++) { | 78 | for (; i < size; i++) { |
85 | status = inb(chip->vendor->base + 1); | 79 | status = atmel_getb(chip, 1); |
86 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { | 80 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { |
87 | dev_err(chip->dev, | 81 | dev_err(chip->dev, |
88 | "error reading data\n"); | 82 | "error reading data\n"); |
89 | return -EIO; | 83 | return -EIO; |
90 | } | 84 | } |
91 | *buf++ = inb(chip->vendor->base); | 85 | *buf++ = atmel_getb(chip, 0); |
92 | } | 86 | } |
93 | 87 | ||
94 | /* make sure data available is gone */ | 88 | /* make sure data available is gone */ |
95 | status = inb(chip->vendor->base + 1); | 89 | status = atmel_getb(chip, 1); |
96 | if (status & ATML_STATUS_DATA_AVAIL) { | 90 | if (status & ATML_STATUS_DATA_AVAIL) { |
97 | dev_err(chip->dev, "data available is stuck\n"); | 91 | dev_err(chip->dev, "data available is stuck\n"); |
98 | return -EIO; | 92 | return -EIO; |
@@ -108,7 +102,7 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count) | |||
108 | dev_dbg(chip->dev, "tpm_atml_send:\n"); | 102 | dev_dbg(chip->dev, "tpm_atml_send:\n"); |
109 | for (i = 0; i < count; i++) { | 103 | for (i = 0; i < count; i++) { |
110 | dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); | 104 | dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); |
111 | outb(buf[i], chip->vendor->base); | 105 | atmel_putb(buf[i], chip, 0); |
112 | } | 106 | } |
113 | 107 | ||
114 | return count; | 108 | return count; |
@@ -116,12 +110,12 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count) | |||
116 | 110 | ||
117 | static void tpm_atml_cancel(struct tpm_chip *chip) | 111 | static void tpm_atml_cancel(struct tpm_chip *chip) |
118 | { | 112 | { |
119 | outb(ATML_STATUS_ABORT, chip->vendor->base + 1); | 113 | atmel_putb(ATML_STATUS_ABORT, chip, 1); |
120 | } | 114 | } |
121 | 115 | ||
122 | static u8 tpm_atml_status(struct tpm_chip *chip) | 116 | static u8 tpm_atml_status(struct tpm_chip *chip) |
123 | { | 117 | { |
124 | return inb(chip->vendor->base + 1); | 118 | return atmel_getb(chip, 1); |
125 | } | 119 | } |
126 | 120 | ||
127 | static struct file_operations atmel_ops = { | 121 | static struct file_operations atmel_ops = { |
@@ -162,12 +156,16 @@ static struct tpm_vendor_specific tpm_atmel = { | |||
162 | 156 | ||
163 | static struct platform_device *pdev; | 157 | static struct platform_device *pdev; |
164 | 158 | ||
165 | static void __devexit tpm_atml_remove(struct device *dev) | 159 | static void atml_plat_remove(void) |
166 | { | 160 | { |
167 | struct tpm_chip *chip = dev_get_drvdata(dev); | 161 | struct tpm_chip *chip = dev_get_drvdata(&pdev->dev); |
162 | |||
168 | if (chip) { | 163 | if (chip) { |
169 | release_region(chip->vendor->base, 2); | 164 | if (chip->vendor->have_region) |
165 | atmel_release_region(chip->vendor->base, chip->vendor->region_size); | ||
166 | atmel_put_base_addr(chip->vendor); | ||
170 | tpm_remove_hardware(chip->dev); | 167 | tpm_remove_hardware(chip->dev); |
168 | platform_device_unregister(pdev); | ||
171 | } | 169 | } |
172 | } | 170 | } |
173 | 171 | ||
@@ -182,72 +180,40 @@ static struct device_driver atml_drv = { | |||
182 | static int __init init_atmel(void) | 180 | static int __init init_atmel(void) |
183 | { | 181 | { |
184 | int rc = 0; | 182 | int rc = 0; |
185 | int lo, hi; | ||
186 | 183 | ||
187 | driver_register(&atml_drv); | 184 | driver_register(&atml_drv); |
188 | 185 | ||
189 | lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO); | 186 | if (atmel_get_base_addr(&tpm_atmel) != 0) { |
190 | hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI); | 187 | rc = -ENODEV; |
191 | 188 | goto err_unreg_drv; | |
192 | tpm_atmel.base = (hi<<8)|lo; | ||
193 | |||
194 | /* verify that it is an Atmel part */ | ||
195 | if (tpm_read_index(TPM_ADDR, 4) != 'A' || tpm_read_index(TPM_ADDR, 5) != 'T' | ||
196 | || tpm_read_index(TPM_ADDR, 6) != 'M' || tpm_read_index(TPM_ADDR, 7) != 'L') { | ||
197 | return -ENODEV; | ||
198 | } | ||
199 | |||
200 | /* verify chip version number is 1.1 */ | ||
201 | if ( (tpm_read_index(TPM_ADDR, 0x00) != 0x01) || | ||
202 | (tpm_read_index(TPM_ADDR, 0x01) != 0x01 )) | ||
203 | return -ENODEV; | ||
204 | |||
205 | pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL); | ||
206 | if ( !pdev ) | ||
207 | return -ENOMEM; | ||
208 | |||
209 | pdev->name = "tpm_atmel0"; | ||
210 | pdev->id = -1; | ||
211 | pdev->num_resources = 0; | ||
212 | pdev->dev.release = tpm_atml_remove; | ||
213 | pdev->dev.driver = &atml_drv; | ||
214 | |||
215 | if ((rc = platform_device_register(pdev)) < 0) { | ||
216 | kfree(pdev); | ||
217 | pdev = NULL; | ||
218 | return rc; | ||
219 | } | 189 | } |
220 | 190 | ||
221 | if (request_region(tpm_atmel.base, 2, "tpm_atmel0") == NULL ) { | 191 | tpm_atmel.have_region = (atmel_request_region( tpm_atmel.base, tpm_atmel.region_size, "tpm_atmel0") == NULL) ? 0 : 1; |
222 | platform_device_unregister(pdev); | ||
223 | kfree(pdev); | ||
224 | pdev = NULL; | ||
225 | return -EBUSY; | ||
226 | } | ||
227 | 192 | ||
228 | if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0) { | 193 | if (IS_ERR(pdev = platform_device_register_simple("tpm_atmel", -1, NULL, 0 ))) { |
229 | release_region(tpm_atmel.base, 2); | 194 | rc = PTR_ERR(pdev); |
230 | platform_device_unregister(pdev); | 195 | goto err_rel_reg; |
231 | kfree(pdev); | ||
232 | pdev = NULL; | ||
233 | return rc; | ||
234 | } | 196 | } |
235 | 197 | ||
236 | dev_info(&pdev->dev, "Atmel TPM 1.1, Base Address: 0x%x\n", | 198 | if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0) |
237 | tpm_atmel.base); | 199 | goto err_unreg_dev; |
238 | return 0; | 200 | return 0; |
201 | |||
202 | err_unreg_dev: | ||
203 | platform_device_unregister(pdev); | ||
204 | err_rel_reg: | ||
205 | if (tpm_atmel.have_region) | ||
206 | atmel_release_region(tpm_atmel.base, tpm_atmel.region_size); | ||
207 | atmel_put_base_addr(&tpm_atmel); | ||
208 | err_unreg_drv: | ||
209 | driver_unregister(&atml_drv); | ||
210 | return rc; | ||
239 | } | 211 | } |
240 | 212 | ||
241 | static void __exit cleanup_atmel(void) | 213 | static void __exit cleanup_atmel(void) |
242 | { | 214 | { |
243 | if (pdev) { | ||
244 | tpm_atml_remove(&pdev->dev); | ||
245 | platform_device_unregister(pdev); | ||
246 | kfree(pdev); | ||
247 | pdev = NULL; | ||
248 | } | ||
249 | |||
250 | driver_unregister(&atml_drv); | 215 | driver_unregister(&atml_drv); |
216 | atml_plat_remove(); | ||
251 | } | 217 | } |
252 | 218 | ||
253 | module_init(init_atmel); | 219 | module_init(init_atmel); |
diff --git a/drivers/char/tpm/tpm_atmel.h b/drivers/char/tpm/tpm_atmel.h new file mode 100644 index 000000000000..3c5b9a8d1c49 --- /dev/null +++ b/drivers/char/tpm/tpm_atmel.h | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005 IBM Corporation | ||
3 | * | ||
4 | * Authors: | ||
5 | * Kylene Hall <kjhall@us.ibm.com> | ||
6 | * | ||
7 | * Maintained by: <tpmdd_devel@lists.sourceforge.net> | ||
8 | * | ||
9 | * Device driver for TCG/TCPA TPM (trusted platform module). | ||
10 | * Specifications at www.trustedcomputinggroup.org | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License as | ||
14 | * published by the Free Software Foundation, version 2 of the | ||
15 | * License. | ||
16 | * | ||
17 | * These difference are required on power because the device must be | ||
18 | * discovered through the device tree and iomap must be used to get | ||
19 | * around the need for holes in the io_page_mask. This does not happen | ||
20 | * automatically because the tpm is not a normal pci device and lives | ||
21 | * under the root node. | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifdef CONFIG_PPC64 | ||
26 | #define atmel_getb(chip, offset) readb(chip->vendor->iobase + offset); | ||
27 | #define atmel_putb(val, chip, offset) writeb(val, chip->vendor->iobase + offset) | ||
28 | #define atmel_request_region request_mem_region | ||
29 | #define atmel_release_region release_mem_region | ||
30 | static inline void atmel_put_base_addr(struct tpm_vendor_specific *vendor) | ||
31 | { | ||
32 | iounmap(vendor->iobase); | ||
33 | } | ||
34 | |||
35 | static int atmel_get_base_addr(struct tpm_vendor_specific *vendor) | ||
36 | { | ||
37 | struct device_node *dn; | ||
38 | unsigned long address, size; | ||
39 | unsigned int *reg; | ||
40 | int reglen; | ||
41 | int naddrc; | ||
42 | int nsizec; | ||
43 | |||
44 | dn = of_find_node_by_name(NULL, "tpm"); | ||
45 | |||
46 | if (!dn) | ||
47 | return 1; | ||
48 | |||
49 | if (!device_is_compatible(dn, "AT97SC3201")) { | ||
50 | of_node_put(dn); | ||
51 | return 1; | ||
52 | } | ||
53 | |||
54 | reg = (unsigned int *) get_property(dn, "reg", ®len); | ||
55 | naddrc = prom_n_addr_cells(dn); | ||
56 | nsizec = prom_n_size_cells(dn); | ||
57 | |||
58 | of_node_put(dn); | ||
59 | |||
60 | |||
61 | if (naddrc == 2) | ||
62 | address = ((unsigned long) reg[0] << 32) | reg[1]; | ||
63 | else | ||
64 | address = reg[0]; | ||
65 | |||
66 | if (nsizec == 2) | ||
67 | size = | ||
68 | ((unsigned long) reg[naddrc] << 32) | reg[naddrc + 1]; | ||
69 | else | ||
70 | size = reg[naddrc]; | ||
71 | |||
72 | vendor->base = address; | ||
73 | vendor->region_size = size; | ||
74 | vendor->iobase = ioremap(address, size); | ||
75 | return 0; | ||
76 | } | ||
77 | #else | ||
78 | #define atmel_getb(chip, offset) inb(chip->vendor->base + offset) | ||
79 | #define atmel_putb(val, chip, offset) outb(val, chip->vendor->base + offset) | ||
80 | #define atmel_request_region request_region | ||
81 | #define atmel_release_region release_region | ||
82 | /* Atmel definitions */ | ||
83 | enum tpm_atmel_addr { | ||
84 | TPM_ATMEL_BASE_ADDR_LO = 0x08, | ||
85 | TPM_ATMEL_BASE_ADDR_HI = 0x09 | ||
86 | }; | ||
87 | |||
88 | /* Verify this is a 1.1 Atmel TPM */ | ||
89 | static int atmel_verify_tpm11(void) | ||
90 | { | ||
91 | |||
92 | /* verify that it is an Atmel part */ | ||
93 | if (tpm_read_index(TPM_ADDR, 4) != 'A' || | ||
94 | tpm_read_index(TPM_ADDR, 5) != 'T' || | ||
95 | tpm_read_index(TPM_ADDR, 6) != 'M' || | ||
96 | tpm_read_index(TPM_ADDR, 7) != 'L') | ||
97 | return 1; | ||
98 | |||
99 | /* query chip for its version number */ | ||
100 | if (tpm_read_index(TPM_ADDR, 0x00) != 1 || | ||
101 | tpm_read_index(TPM_ADDR, 0x01) != 1) | ||
102 | return 1; | ||
103 | |||
104 | /* This is an atmel supported part */ | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static inline void atmel_put_base_addr(struct tpm_vendor_specific *vendor) | ||
109 | { | ||
110 | } | ||
111 | |||
112 | /* Determine where to talk to device */ | ||
113 | static unsigned long atmel_get_base_addr(struct tpm_vendor_specific | ||
114 | *vendor) | ||
115 | { | ||
116 | int lo, hi; | ||
117 | |||
118 | if (atmel_verify_tpm11() != 0) | ||
119 | return 1; | ||
120 | |||
121 | lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO); | ||
122 | hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI); | ||
123 | |||
124 | vendor->base = (hi << 8) | lo; | ||
125 | vendor->region_size = 2; | ||
126 | |||
127 | return 0; | ||
128 | } | ||
129 | #endif | ||
diff --git a/drivers/char/watchdog/booke_wdt.c b/drivers/char/watchdog/booke_wdt.c index abc30cca6645..65830ec71042 100644 --- a/drivers/char/watchdog/booke_wdt.c +++ b/drivers/char/watchdog/booke_wdt.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Watchdog timer for PowerPC Book-E systems | 4 | * Watchdog timer for PowerPC Book-E systems |
5 | * | 5 | * |
6 | * Author: Matthew McClintock | 6 | * Author: Matthew McClintock |
7 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 7 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
8 | * | 8 | * |
9 | * Copyright 2005 Freescale Semiconductor Inc. | 9 | * Copyright 2005 Freescale Semiconductor Inc. |
10 | * | 10 | * |
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c index ea0806c82be0..8a5c7b286b2b 100644 --- a/drivers/ide/pci/sl82c105.c +++ b/drivers/ide/pci/sl82c105.c | |||
@@ -399,34 +399,6 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c | |||
399 | return dev->irq; | 399 | return dev->irq; |
400 | } | 400 | } |
401 | 401 | ||
402 | static void __devinit init_dma_sl82c105(ide_hwif_t *hwif, unsigned long dma_base) | ||
403 | { | ||
404 | unsigned int rev; | ||
405 | u8 dma_state; | ||
406 | |||
407 | DBG(("init_dma_sl82c105(hwif: ide%d, dma_base: 0x%08x)\n", hwif->index, dma_base)); | ||
408 | |||
409 | hwif->autodma = 0; | ||
410 | |||
411 | if (!dma_base) | ||
412 | return; | ||
413 | |||
414 | dma_state = hwif->INB(dma_base + 2); | ||
415 | rev = sl82c105_bridge_revision(hwif->pci_dev); | ||
416 | if (rev <= 5) { | ||
417 | printk(" %s: Winbond 553 bridge revision %d, BM-DMA disabled\n", | ||
418 | hwif->name, rev); | ||
419 | dma_state &= ~0x60; | ||
420 | } else { | ||
421 | dma_state |= 0x60; | ||
422 | if (!noautodma) | ||
423 | hwif->autodma = 1; | ||
424 | } | ||
425 | hwif->OUTB(dma_state, dma_base + 2); | ||
426 | |||
427 | ide_setup_dma(hwif, dma_base, 8); | ||
428 | } | ||
429 | |||
430 | /* | 402 | /* |
431 | * Initialise the chip | 403 | * Initialise the chip |
432 | */ | 404 | */ |
@@ -434,6 +406,8 @@ static void __devinit init_dma_sl82c105(ide_hwif_t *hwif, unsigned long dma_base | |||
434 | static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) | 406 | static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) |
435 | { | 407 | { |
436 | struct pci_dev *dev = hwif->pci_dev; | 408 | struct pci_dev *dev = hwif->pci_dev; |
409 | unsigned int rev; | ||
410 | u8 dma_state; | ||
437 | u32 val; | 411 | u32 val; |
438 | 412 | ||
439 | DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index)); | 413 | DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index)); |
@@ -455,33 +429,54 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) | |||
455 | pci_read_config_dword(dev, 0x40, &val); | 429 | pci_read_config_dword(dev, 0x40, &val); |
456 | *((u32 *)&hwif->hwif_data) = val; | 430 | *((u32 *)&hwif->hwif_data) = val; |
457 | 431 | ||
432 | hwif->atapi_dma = 0; | ||
433 | hwif->mwdma_mask = 0; | ||
434 | hwif->swdma_mask = 0; | ||
435 | hwif->autodma = 0; | ||
436 | |||
458 | if (!hwif->dma_base) | 437 | if (!hwif->dma_base) |
459 | return; | 438 | return; |
460 | 439 | ||
461 | hwif->atapi_dma = 1; | 440 | dma_state = hwif->INB(hwif->dma_base + 2) & ~0x60; |
462 | hwif->mwdma_mask = 0x07; | 441 | rev = sl82c105_bridge_revision(hwif->pci_dev); |
463 | hwif->swdma_mask = 0x07; | 442 | if (rev <= 5) { |
464 | 443 | /* | |
444 | * Never ever EVER under any circumstances enable | ||
445 | * DMA when the bridge is this old. | ||
446 | */ | ||
447 | printk(" %s: Winbond 553 bridge revision %d, BM-DMA disabled\n", | ||
448 | hwif->name, rev); | ||
449 | } else { | ||
465 | #ifdef CONFIG_BLK_DEV_IDEDMA | 450 | #ifdef CONFIG_BLK_DEV_IDEDMA |
466 | hwif->ide_dma_check = &sl82c105_check_drive; | 451 | dma_state |= 0x60; |
467 | hwif->ide_dma_on = &sl82c105_ide_dma_on; | 452 | |
468 | hwif->ide_dma_off_quietly = &sl82c105_ide_dma_off_quietly; | 453 | hwif->atapi_dma = 1; |
469 | hwif->ide_dma_lostirq = &sl82c105_ide_dma_lost_irq; | 454 | hwif->mwdma_mask = 0x07; |
470 | hwif->dma_start = &sl82c105_ide_dma_start; | 455 | hwif->swdma_mask = 0x07; |
471 | hwif->ide_dma_timeout = &sl82c105_ide_dma_timeout; | 456 | |
472 | 457 | hwif->ide_dma_check = &sl82c105_check_drive; | |
473 | if (!noautodma) | 458 | hwif->ide_dma_on = &sl82c105_ide_dma_on; |
474 | hwif->autodma = 1; | 459 | hwif->ide_dma_off_quietly = &sl82c105_ide_dma_off_quietly; |
475 | hwif->drives[0].autodma = hwif->autodma; | 460 | hwif->ide_dma_lostirq = &sl82c105_ide_dma_lost_irq; |
476 | hwif->drives[1].autodma = hwif->autodma; | 461 | hwif->dma_start = &sl82c105_ide_dma_start; |
462 | hwif->ide_dma_timeout = &sl82c105_ide_dma_timeout; | ||
463 | |||
464 | if (!noautodma) | ||
465 | hwif->autodma = 1; | ||
466 | hwif->drives[0].autodma = hwif->autodma; | ||
467 | hwif->drives[1].autodma = hwif->autodma; | ||
468 | |||
469 | if (hwif->mate) | ||
470 | hwif->serialized = hwif->mate->serialized = 1; | ||
477 | #endif /* CONFIG_BLK_DEV_IDEDMA */ | 471 | #endif /* CONFIG_BLK_DEV_IDEDMA */ |
472 | } | ||
473 | hwif->OUTB(dma_state, hwif->dma_base + 2); | ||
478 | } | 474 | } |
479 | 475 | ||
480 | static ide_pci_device_t sl82c105_chipset __devinitdata = { | 476 | static ide_pci_device_t sl82c105_chipset __devinitdata = { |
481 | .name = "W82C105", | 477 | .name = "W82C105", |
482 | .init_chipset = init_chipset_sl82c105, | 478 | .init_chipset = init_chipset_sl82c105, |
483 | .init_hwif = init_hwif_sl82c105, | 479 | .init_hwif = init_hwif_sl82c105, |
484 | .init_dma = init_dma_sl82c105, | ||
485 | .channels = 2, | 480 | .channels = 2, |
486 | .autodma = NOAUTODMA, | 481 | .autodma = NOAUTODMA, |
487 | .enablebits = {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, | 482 | .enablebits = {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, |
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index b3e65a65d202..136911a86e84 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c | |||
@@ -1667,11 +1667,16 @@ static struct macio_driver pmac_ide_macio_driver = | |||
1667 | }; | 1667 | }; |
1668 | 1668 | ||
1669 | static struct pci_device_id pmac_ide_pci_match[] = { | 1669 | static struct pci_device_id pmac_ide_pci_match[] = { |
1670 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_ATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 1670 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_ATA, |
1671 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 1671 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
1672 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 1672 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100, |
1673 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
1674 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100, | ||
1675 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
1673 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_SH_ATA, | 1676 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_SH_ATA, |
1674 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 1677 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
1678 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID2_ATA, | ||
1679 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
1675 | }; | 1680 | }; |
1676 | 1681 | ||
1677 | static struct pci_driver pmac_ide_pci_driver = { | 1682 | static struct pci_driver pmac_ide_pci_driver = { |
diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c index 32bf0d5d0f9a..f8457ef48826 100644 --- a/drivers/isdn/hisax/hfc_usb.c +++ b/drivers/isdn/hisax/hfc_usb.c | |||
@@ -71,78 +71,68 @@ typedef struct { | |||
71 | /****************************************/ | 71 | /****************************************/ |
72 | static struct usb_device_id hfcusb_idtab[] = { | 72 | static struct usb_device_id hfcusb_idtab[] = { |
73 | { | 73 | { |
74 | .idVendor = 0x0959, | 74 | USB_DEVICE(0x0959, 0x2bd0), |
75 | .idProduct = 0x2bd0, | ||
76 | .driver_info = (unsigned long) &((hfcsusb_vdata) | 75 | .driver_info = (unsigned long) &((hfcsusb_vdata) |
77 | {LED_OFF, {4, 0, 2, 1}, | 76 | {LED_OFF, {4, 0, 2, 1}, |
78 | "ISDN USB TA (Cologne Chip HFC-S USB based)"}), | 77 | "ISDN USB TA (Cologne Chip HFC-S USB based)"}), |
79 | }, | 78 | }, |
80 | { | 79 | { |
81 | .idVendor = 0x0675, | 80 | USB_DEVICE(0x0675, 0x1688), |
82 | .idProduct = 0x1688, | ||
83 | .driver_info = (unsigned long) &((hfcsusb_vdata) | 81 | .driver_info = (unsigned long) &((hfcsusb_vdata) |
84 | {LED_SCHEME1, {1, 2, 0, 0}, | 82 | {LED_SCHEME1, {1, 2, 0, 0}, |
85 | "DrayTek miniVigor 128 USB ISDN TA"}), | 83 | "DrayTek miniVigor 128 USB ISDN TA"}), |
86 | }, | 84 | }, |
87 | { | 85 | { |
88 | .idVendor = 0x07b0, | 86 | USB_DEVICE(0x07b0, 0x0007), |
89 | .idProduct = 0x0007, | ||
90 | .driver_info = (unsigned long) &((hfcsusb_vdata) | 87 | .driver_info = (unsigned long) &((hfcsusb_vdata) |
91 | {LED_SCHEME1, {0x80, -64, -32, -16}, | 88 | {LED_SCHEME1, {0x80, -64, -32, -16}, |
92 | "Billion tiny USB ISDN TA 128"}), | 89 | "Billion tiny USB ISDN TA 128"}), |
93 | }, | 90 | }, |
94 | { | 91 | { |
95 | .idVendor = 0x0742, | 92 | USB_DEVICE(0x0742, 0x2008), |
96 | .idProduct = 0x2008, | ||
97 | .driver_info = (unsigned long) &((hfcsusb_vdata) | 93 | .driver_info = (unsigned long) &((hfcsusb_vdata) |
98 | {LED_SCHEME1, {4, 0, 2, 1}, | 94 | {LED_SCHEME1, {4, 0, 2, 1}, |
99 | "Stollmann USB TA"}), | 95 | "Stollmann USB TA"}), |
100 | }, | 96 | }, |
101 | { | 97 | { |
102 | .idVendor = 0x0742, | 98 | USB_DEVICE(0x0742, 0x2009), |
103 | .idProduct = 0x2009, | ||
104 | .driver_info = (unsigned long) &((hfcsusb_vdata) | 99 | .driver_info = (unsigned long) &((hfcsusb_vdata) |
105 | {LED_SCHEME1, {4, 0, 2, 1}, | 100 | {LED_SCHEME1, {4, 0, 2, 1}, |
106 | "Aceex USB ISDN TA"}), | 101 | "Aceex USB ISDN TA"}), |
107 | }, | 102 | }, |
108 | { | 103 | { |
109 | .idVendor = 0x0742, | 104 | USB_DEVICE(0x0742, 0x200A), |
110 | .idProduct = 0x200A, | ||
111 | .driver_info = (unsigned long) &((hfcsusb_vdata) | 105 | .driver_info = (unsigned long) &((hfcsusb_vdata) |
112 | {LED_SCHEME1, {4, 0, 2, 1}, | 106 | {LED_SCHEME1, {4, 0, 2, 1}, |
113 | "OEM USB ISDN TA"}), | 107 | "OEM USB ISDN TA"}), |
114 | }, | 108 | }, |
115 | { | 109 | { |
116 | .idVendor = 0x08e3, | 110 | USB_DEVICE(0x08e3, 0x0301), |
117 | .idProduct = 0x0301, | ||
118 | .driver_info = (unsigned long) &((hfcsusb_vdata) | 111 | .driver_info = (unsigned long) &((hfcsusb_vdata) |
119 | {LED_SCHEME1, {2, 0, 1, 4}, | 112 | {LED_SCHEME1, {2, 0, 1, 4}, |
120 | "Olitec USB RNIS"}), | 113 | "Olitec USB RNIS"}), |
121 | }, | 114 | }, |
122 | { | 115 | { |
123 | .idVendor = 0x07fa, | 116 | USB_DEVICE(0x07fa, 0x0846), |
124 | .idProduct = 0x0846, | ||
125 | .driver_info = (unsigned long) &((hfcsusb_vdata) | 117 | .driver_info = (unsigned long) &((hfcsusb_vdata) |
126 | {LED_SCHEME1, {0x80, -64, -32, -16}, | 118 | {LED_SCHEME1, {0x80, -64, -32, -16}, |
127 | "Bewan Modem RNIS USB"}), | 119 | "Bewan Modem RNIS USB"}), |
128 | }, | 120 | }, |
129 | { | 121 | { |
130 | .idVendor = 0x07fa, | 122 | USB_DEVICE(0x07fa, 0x0847), |
131 | .idProduct = 0x0847, | ||
132 | .driver_info = (unsigned long) &((hfcsusb_vdata) | 123 | .driver_info = (unsigned long) &((hfcsusb_vdata) |
133 | {LED_SCHEME1, {0x80, -64, -32, -16}, | 124 | {LED_SCHEME1, {0x80, -64, -32, -16}, |
134 | "Djinn Numeris USB"}), | 125 | "Djinn Numeris USB"}), |
135 | }, | 126 | }, |
136 | { | 127 | { |
137 | .idVendor = 0x07b0, | 128 | USB_DEVICE(0x07b0, 0x0006), |
138 | .idProduct = 0x0006, | ||
139 | .driver_info = (unsigned long) &((hfcsusb_vdata) | 129 | .driver_info = (unsigned long) &((hfcsusb_vdata) |
140 | {LED_SCHEME1, {0x80, -64, -32, -16}, | 130 | {LED_SCHEME1, {0x80, -64, -32, -16}, |
141 | "Twister ISDN TA"}), | 131 | "Twister ISDN TA"}), |
142 | }, | 132 | }, |
133 | { } | ||
143 | }; | 134 | }; |
144 | 135 | ||
145 | |||
146 | /***************************************************************/ | 136 | /***************************************************************/ |
147 | /* structure defining input+output fifos (interrupt/bulk mode) */ | 137 | /* structure defining input+output fifos (interrupt/bulk mode) */ |
148 | /***************************************************************/ | 138 | /***************************************************************/ |
diff --git a/drivers/md/md.c b/drivers/md/md.c index adf960d8a7c9..f3fed662f32e 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -3156,7 +3156,7 @@ static int md_ioctl(struct inode *inode, struct file *file, | |||
3156 | if (cnt > 0 ) { | 3156 | if (cnt > 0 ) { |
3157 | printk(KERN_WARNING | 3157 | printk(KERN_WARNING |
3158 | "md: %s(pid %d) used deprecated START_ARRAY ioctl. " | 3158 | "md: %s(pid %d) used deprecated START_ARRAY ioctl. " |
3159 | "This will not be supported beyond 2.6\n", | 3159 | "This will not be supported beyond July 2006\n", |
3160 | current->comm, current->pid); | 3160 | current->comm, current->pid); |
3161 | cnt--; | 3161 | cnt--; |
3162 | } | 3162 | } |
@@ -3437,10 +3437,19 @@ static int md_thread(void * arg) | |||
3437 | allow_signal(SIGKILL); | 3437 | allow_signal(SIGKILL); |
3438 | while (!kthread_should_stop()) { | 3438 | while (!kthread_should_stop()) { |
3439 | 3439 | ||
3440 | wait_event_timeout(thread->wqueue, | 3440 | /* We need to wait INTERRUPTIBLE so that |
3441 | test_bit(THREAD_WAKEUP, &thread->flags) | 3441 | * we don't add to the load-average. |
3442 | || kthread_should_stop(), | 3442 | * That means we need to be sure no signals are |
3443 | thread->timeout); | 3443 | * pending |
3444 | */ | ||
3445 | if (signal_pending(current)) | ||
3446 | flush_signals(current); | ||
3447 | |||
3448 | wait_event_interruptible_timeout | ||
3449 | (thread->wqueue, | ||
3450 | test_bit(THREAD_WAKEUP, &thread->flags) | ||
3451 | || kthread_should_stop(), | ||
3452 | thread->timeout); | ||
3444 | try_to_freeze(); | 3453 | try_to_freeze(); |
3445 | 3454 | ||
3446 | clear_bit(THREAD_WAKEUP, &thread->flags); | 3455 | clear_bit(THREAD_WAKEUP, &thread->flags); |
diff --git a/drivers/media/common/ir-common.c b/drivers/media/common/ir-common.c index 4b71fd6f7aed..7972c73bc14e 100644 --- a/drivers/media/common/ir-common.c +++ b/drivers/media/common/ir-common.c | |||
@@ -126,6 +126,66 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { | |||
126 | }; | 126 | }; |
127 | EXPORT_SYMBOL_GPL(ir_codes_winfast); | 127 | EXPORT_SYMBOL_GPL(ir_codes_winfast); |
128 | 128 | ||
129 | IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = { | ||
130 | [ 0x59 ] = KEY_MUTE, | ||
131 | [ 0x4a ] = KEY_POWER, | ||
132 | |||
133 | [ 0x18 ] = KEY_TEXT, | ||
134 | [ 0x26 ] = KEY_TV, | ||
135 | [ 0x3d ] = KEY_PRINT, | ||
136 | |||
137 | [ 0x48 ] = KEY_RED, | ||
138 | [ 0x04 ] = KEY_GREEN, | ||
139 | [ 0x11 ] = KEY_YELLOW, | ||
140 | [ 0x00 ] = KEY_BLUE, | ||
141 | |||
142 | [ 0x2d ] = KEY_VOLUMEUP, | ||
143 | [ 0x1e ] = KEY_VOLUMEDOWN, | ||
144 | |||
145 | [ 0x49 ] = KEY_MENU, | ||
146 | |||
147 | [ 0x16 ] = KEY_CHANNELUP, | ||
148 | [ 0x17 ] = KEY_CHANNELDOWN, | ||
149 | |||
150 | [ 0x20 ] = KEY_UP, | ||
151 | [ 0x21 ] = KEY_DOWN, | ||
152 | [ 0x22 ] = KEY_LEFT, | ||
153 | [ 0x23 ] = KEY_RIGHT, | ||
154 | [ 0x0d ] = KEY_SELECT, | ||
155 | |||
156 | |||
157 | |||
158 | [ 0x08 ] = KEY_BACK, | ||
159 | [ 0x07 ] = KEY_REFRESH, | ||
160 | |||
161 | [ 0x2f ] = KEY_ZOOM, | ||
162 | [ 0x29 ] = KEY_RECORD, | ||
163 | |||
164 | [ 0x4b ] = KEY_PAUSE, | ||
165 | [ 0x4d ] = KEY_REWIND, | ||
166 | [ 0x2e ] = KEY_PLAY, | ||
167 | [ 0x4e ] = KEY_FORWARD, | ||
168 | [ 0x53 ] = KEY_PREVIOUS, | ||
169 | [ 0x4c ] = KEY_STOP, | ||
170 | [ 0x54 ] = KEY_NEXT, | ||
171 | |||
172 | [ 0x69 ] = KEY_KP0, | ||
173 | [ 0x6a ] = KEY_KP1, | ||
174 | [ 0x6b ] = KEY_KP2, | ||
175 | [ 0x6c ] = KEY_KP3, | ||
176 | [ 0x6d ] = KEY_KP4, | ||
177 | [ 0x6e ] = KEY_KP5, | ||
178 | [ 0x6f ] = KEY_KP6, | ||
179 | [ 0x70 ] = KEY_KP7, | ||
180 | [ 0x71 ] = KEY_KP8, | ||
181 | [ 0x72 ] = KEY_KP9, | ||
182 | |||
183 | [ 0x74 ] = KEY_CHANNEL, | ||
184 | [ 0x0a ] = KEY_BACKSPACE, | ||
185 | }; | ||
186 | |||
187 | EXPORT_SYMBOL_GPL(ir_codes_pinnacle); | ||
188 | |||
129 | /* empty keytable, can be used as placeholder for not-yet created keytables */ | 189 | /* empty keytable, can be used as placeholder for not-yet created keytables */ |
130 | IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE] = { | 190 | IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE] = { |
131 | [ 42 ] = KEY_COFFEE, | 191 | [ 42 ] = KEY_COFFEE, |
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 199b01188858..1a3b3c7e5e99 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -333,4 +333,18 @@ config VIDEO_M32R_AR_M64278 | |||
333 | Say Y here to use the Renesas M64278E-800 camera module, | 333 | Say Y here to use the Renesas M64278E-800 camera module, |
334 | which supports VGA(640x480 pixcels) size of images. | 334 | which supports VGA(640x480 pixcels) size of images. |
335 | 335 | ||
336 | config VIDEO_AUDIO_DECODER | ||
337 | tristate "Add support for additional audio chipsets" | ||
338 | depends on VIDEO_DEV && I2C && EXPERIMENTAL | ||
339 | ---help--- | ||
340 | Say Y here to compile drivers for WM8775 and CS53L32A audio | ||
341 | decoders. | ||
342 | |||
343 | config VIDEO_DECODER | ||
344 | tristate "Add support for additional video chipsets" | ||
345 | depends on VIDEO_DEV && I2C && EXPERIMENTAL | ||
346 | ---help--- | ||
347 | Say Y here to compile drivers for SAA7115, SAA7127 and CX25840 | ||
348 | video decoders. | ||
349 | |||
336 | endmenu | 350 | endmenu |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 3ac465992400..82060f9909d8 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
@@ -36,10 +36,11 @@ obj-$(CONFIG_VIDEO_CPIA) += cpia.o | |||
36 | obj-$(CONFIG_VIDEO_CPIA_PP) += cpia_pp.o | 36 | obj-$(CONFIG_VIDEO_CPIA_PP) += cpia_pp.o |
37 | obj-$(CONFIG_VIDEO_CPIA_USB) += cpia_usb.o | 37 | obj-$(CONFIG_VIDEO_CPIA_USB) += cpia_usb.o |
38 | obj-$(CONFIG_VIDEO_MEYE) += meye.o | 38 | obj-$(CONFIG_VIDEO_MEYE) += meye.o |
39 | obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ | 39 | obj-$(CONFIG_VIDEO_SAA7134) += ir-kbd-i2c.o saa7134/ |
40 | obj-$(CONFIG_VIDEO_CX88) += cx88/ | 40 | obj-$(CONFIG_VIDEO_CX88) += cx88/ |
41 | obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ | 41 | obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ |
42 | obj-$(CONFIG_VIDEO_EM28XX) += saa711x.o tvp5150.o | 42 | obj-$(CONFIG_VIDEO_EM28XX) += saa711x.o tvp5150.o |
43 | obj-$(CONFIG_VIDEO_AUDIO_DECODER) += wm8775.o cs53l32a.o | ||
43 | obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/ | 44 | obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/ |
44 | obj-$(CONFIG_VIDEO_MXB) += saa7111.o tuner.o tda9840.o tea6415c.o tea6420.o mxb.o | 45 | obj-$(CONFIG_VIDEO_MXB) += saa7111.o tuner.o tda9840.o tea6415c.o tea6420.o mxb.o |
45 | obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o | 46 | obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o |
@@ -55,4 +56,6 @@ obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o | |||
55 | 56 | ||
56 | obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o | 57 | obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o |
57 | 58 | ||
59 | obj-$(CONFIG_VIDEO_DECODER) += saa7115.o cx25840/ saa7127.o | ||
60 | |||
58 | EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core | 61 | EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core |
diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 3413bace443a..e31ebb11c468 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c | |||
@@ -2133,7 +2133,10 @@ struct tvcard bttv_tvcards[] = { | |||
2133 | .tuner_addr = ADDR_UNSET, | 2133 | .tuner_addr = ADDR_UNSET, |
2134 | .radio_addr = ADDR_UNSET, | 2134 | .radio_addr = ADDR_UNSET, |
2135 | .has_dvb = 1, | 2135 | .has_dvb = 1, |
2136 | .has_remote = 1, | ||
2137 | .gpiomask = 0x1b, | ||
2136 | .no_gpioirq = 1, | 2138 | .no_gpioirq = 1, |
2139 | .any_irq = 1, | ||
2137 | }, | 2140 | }, |
2138 | [BTTV_BOARD_PV143] = { | 2141 | [BTTV_BOARD_PV143] = { |
2139 | /* Jorge Boncompte - DTI2 <jorge@dti2.net> */ | 2142 | /* Jorge Boncompte - DTI2 <jorge@dti2.net> */ |
@@ -2796,7 +2799,24 @@ struct tvcard bttv_tvcards[] = { | |||
2796 | .tuner_addr = ADDR_UNSET, | 2799 | .tuner_addr = ADDR_UNSET, |
2797 | .radio_addr = ADDR_UNSET, | 2800 | .radio_addr = ADDR_UNSET, |
2798 | }, | 2801 | }, |
2799 | 2802 | /* ---- card 0x8e ---------------------------------- */ | |
2803 | [BTTV_BOARD_SABRENT_TVFM] = { | ||
2804 | .name = "Sabrent TV-FM (bttv version)", | ||
2805 | .video_inputs = 3, | ||
2806 | .audio_inputs = 1, | ||
2807 | .tuner = 0, | ||
2808 | .svhs = 2, | ||
2809 | .gpiomask = 0x108007, | ||
2810 | .muxsel = { 2, 3, 1, 1}, | ||
2811 | .audiomux = { 100000, 100002, 100002, 100000}, | ||
2812 | .no_msp34xx = 1, | ||
2813 | .no_tda9875 = 1, | ||
2814 | .no_tda7432 = 1, | ||
2815 | .pll = PLL_28, | ||
2816 | .tuner_type = TUNER_TNF_5335MF, | ||
2817 | .tuner_addr = ADDR_UNSET, | ||
2818 | .has_radio = 1, | ||
2819 | }, | ||
2800 | }; | 2820 | }; |
2801 | 2821 | ||
2802 | static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); | 2822 | static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); |
@@ -3367,6 +3387,8 @@ void __devinit bttv_init_card2(struct bttv *btv) | |||
3367 | btv->has_remote=1; | 3387 | btv->has_remote=1; |
3368 | if (!bttv_tvcards[btv->c.type].no_gpioirq) | 3388 | if (!bttv_tvcards[btv->c.type].no_gpioirq) |
3369 | btv->gpioirq=1; | 3389 | btv->gpioirq=1; |
3390 | if (bttv_tvcards[btv->c.type].any_irq) | ||
3391 | btv->any_irq = 1; | ||
3370 | if (bttv_tvcards[btv->c.type].audio_hook) | 3392 | if (bttv_tvcards[btv->c.type].audio_hook) |
3371 | btv->audio_hook=bttv_tvcards[btv->c.type].audio_hook; | 3393 | btv->audio_hook=bttv_tvcards[btv->c.type].audio_hook; |
3372 | 3394 | ||
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index 0005741d5514..709099f03bd2 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c | |||
@@ -3667,6 +3667,10 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs) | |||
3667 | int handled = 0; | 3667 | int handled = 0; |
3668 | 3668 | ||
3669 | btv=(struct bttv *)dev_id; | 3669 | btv=(struct bttv *)dev_id; |
3670 | |||
3671 | if (btv->any_irq) | ||
3672 | handled = bttv_any_irq(&btv->c); | ||
3673 | |||
3670 | count=0; | 3674 | count=0; |
3671 | while (1) { | 3675 | while (1) { |
3672 | /* get/clear interrupt status bits */ | 3676 | /* get/clear interrupt status bits */ |
diff --git a/drivers/media/video/bttv-gpio.c b/drivers/media/video/bttv-gpio.c index 575ce8b8e714..616a5b7e510c 100644 --- a/drivers/media/video/bttv-gpio.c +++ b/drivers/media/video/bttv-gpio.c | |||
@@ -113,6 +113,24 @@ void bttv_gpio_irq(struct bttv_core *core) | |||
113 | } | 113 | } |
114 | } | 114 | } |
115 | 115 | ||
116 | int bttv_any_irq(struct bttv_core *core) | ||
117 | { | ||
118 | struct bttv_sub_driver *drv; | ||
119 | struct bttv_sub_device *dev; | ||
120 | struct list_head *item; | ||
121 | int handled = 0; | ||
122 | |||
123 | list_for_each(item,&core->subs) { | ||
124 | dev = list_entry(item,struct bttv_sub_device,list); | ||
125 | drv = to_bttv_sub_drv(dev->dev.driver); | ||
126 | if (drv && drv->any_irq) { | ||
127 | if (drv->any_irq(dev)) | ||
128 | handled = 1; | ||
129 | } | ||
130 | } | ||
131 | return handled; | ||
132 | } | ||
133 | |||
116 | /* ----------------------------------------------------------------------- */ | 134 | /* ----------------------------------------------------------------------- */ |
117 | /* external: sub-driver register/unregister */ | 135 | /* external: sub-driver register/unregister */ |
118 | 136 | ||
diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h index 124ea41dada4..93298f06e019 100644 --- a/drivers/media/video/bttv.h +++ b/drivers/media/video/bttv.h | |||
@@ -162,6 +162,7 @@ | |||
162 | #define BTTV_BOARD_PV_M4900 0x8b | 162 | #define BTTV_BOARD_PV_M4900 0x8b |
163 | #define BTTV_BOARD_OSPREY440 0x8c | 163 | #define BTTV_BOARD_OSPREY440 0x8c |
164 | #define BTTV_BOARD_ASOUND_SKYEYE 0x8d | 164 | #define BTTV_BOARD_ASOUND_SKYEYE 0x8d |
165 | #define BTTV_BOARD_SABRENT_TVFM 0x8e | ||
165 | 166 | ||
166 | /* i2c address list */ | 167 | /* i2c address list */ |
167 | #define I2C_TSA5522 0xc2 | 168 | #define I2C_TSA5522 0xc2 |
@@ -234,6 +235,7 @@ struct tvcard | |||
234 | unsigned int has_dvb:1; | 235 | unsigned int has_dvb:1; |
235 | unsigned int has_remote:1; | 236 | unsigned int has_remote:1; |
236 | unsigned int no_gpioirq:1; | 237 | unsigned int no_gpioirq:1; |
238 | unsigned int any_irq:1; | ||
237 | 239 | ||
238 | /* other settings */ | 240 | /* other settings */ |
239 | unsigned int pll; | 241 | unsigned int pll; |
@@ -333,6 +335,7 @@ struct bttv_sub_driver { | |||
333 | struct device_driver drv; | 335 | struct device_driver drv; |
334 | char wanted[BUS_ID_SIZE]; | 336 | char wanted[BUS_ID_SIZE]; |
335 | void (*gpio_irq)(struct bttv_sub_device *sub); | 337 | void (*gpio_irq)(struct bttv_sub_device *sub); |
338 | int (*any_irq)(struct bttv_sub_device *sub); | ||
336 | }; | 339 | }; |
337 | #define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) | 340 | #define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) |
338 | 341 | ||
diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h index 386f546f7d11..3aa9c6e4fc33 100644 --- a/drivers/media/video/bttvp.h +++ b/drivers/media/video/bttvp.h | |||
@@ -208,6 +208,7 @@ extern struct bus_type bttv_sub_bus_type; | |||
208 | int bttv_sub_add_device(struct bttv_core *core, char *name); | 208 | int bttv_sub_add_device(struct bttv_core *core, char *name); |
209 | int bttv_sub_del_devices(struct bttv_core *core); | 209 | int bttv_sub_del_devices(struct bttv_core *core); |
210 | void bttv_gpio_irq(struct bttv_core *core); | 210 | void bttv_gpio_irq(struct bttv_core *core); |
211 | int bttv_any_irq(struct bttv_core *core); | ||
211 | 212 | ||
212 | 213 | ||
213 | /* ---------------------------------------------------------- */ | 214 | /* ---------------------------------------------------------- */ |
@@ -273,6 +274,7 @@ struct bttv { | |||
273 | struct bttv_pll_info pll; | 274 | struct bttv_pll_info pll; |
274 | int triton1; | 275 | int triton1; |
275 | int gpioirq; | 276 | int gpioirq; |
277 | int any_irq; | ||
276 | int use_i2c_hw; | 278 | int use_i2c_hw; |
277 | 279 | ||
278 | /* old gpio interface */ | 280 | /* old gpio interface */ |
diff --git a/drivers/media/video/cx25840/Makefile b/drivers/media/video/cx25840/Makefile new file mode 100644 index 000000000000..543ebacdc9d7 --- /dev/null +++ b/drivers/media/video/cx25840/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | cx25840-objs := cx25840-core.o cx25840-audio.o cx25840-firmware.o \ | ||
2 | cx25840-vbi.o | ||
3 | |||
4 | obj-$(CONFIG_VIDEO_DECODER) += cx25840.o | ||
5 | |||
6 | EXTRA_CFLAGS += -I$(src)/.. | ||
diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c new file mode 100644 index 000000000000..740908f8027d --- /dev/null +++ b/drivers/media/video/cx25840/cx25840-audio.c | |||
@@ -0,0 +1,368 @@ | |||
1 | /* cx25840 audio functions | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or | ||
4 | * modify it under the terms of the GNU General Public License | ||
5 | * as published by the Free Software Foundation; either version 2 | ||
6 | * of the License, or (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | |||
19 | #include <linux/videodev2.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <media/audiochip.h> | ||
22 | #include <media/v4l2-common.h> | ||
23 | |||
24 | #include "cx25840.h" | ||
25 | |||
26 | inline static int set_audclk_freq(struct i2c_client *client, | ||
27 | enum v4l2_audio_clock_freq freq) | ||
28 | { | ||
29 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
30 | |||
31 | /* assert soft reset */ | ||
32 | cx25840_and_or(client, 0x810, ~0x1, 0x01); | ||
33 | |||
34 | /* common for all inputs and rates */ | ||
35 | /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */ | ||
36 | cx25840_write(client, 0x127, 0x50); | ||
37 | |||
38 | switch (state->audio_input) { | ||
39 | case AUDIO_TUNER: | ||
40 | switch (freq) { | ||
41 | case V4L2_AUDCLK_32_KHZ: | ||
42 | /* VID_PLL and AUX_PLL */ | ||
43 | cx25840_write4(client, 0x108, 0x0f040610); | ||
44 | |||
45 | /* AUX_PLL_FRAC */ | ||
46 | cx25840_write4(client, 0x110, 0xee39bb01); | ||
47 | |||
48 | /* src3/4/6_ctl = 0x0801f77f */ | ||
49 | cx25840_write4(client, 0x900, 0x7ff70108); | ||
50 | cx25840_write4(client, 0x904, 0x7ff70108); | ||
51 | cx25840_write4(client, 0x90c, 0x7ff70108); | ||
52 | break; | ||
53 | |||
54 | case V4L2_AUDCLK_441_KHZ: | ||
55 | /* VID_PLL and AUX_PLL */ | ||
56 | cx25840_write4(client, 0x108, 0x0f040910); | ||
57 | |||
58 | /* AUX_PLL_FRAC */ | ||
59 | cx25840_write4(client, 0x110, 0xd66bec00); | ||
60 | |||
61 | /* src3/4/6_ctl = 0x08016d59 */ | ||
62 | cx25840_write4(client, 0x900, 0x596d0108); | ||
63 | cx25840_write4(client, 0x904, 0x596d0108); | ||
64 | cx25840_write4(client, 0x90c, 0x596d0108); | ||
65 | break; | ||
66 | |||
67 | case V4L2_AUDCLK_48_KHZ: | ||
68 | /* VID_PLL and AUX_PLL */ | ||
69 | cx25840_write4(client, 0x108, 0x0f040a10); | ||
70 | |||
71 | /* AUX_PLL_FRAC */ | ||
72 | cx25840_write4(client, 0x110, 0xe5d69800); | ||
73 | |||
74 | /* src3/4/6_ctl = 0x08014faa */ | ||
75 | cx25840_write4(client, 0x900, 0xaa4f0108); | ||
76 | cx25840_write4(client, 0x904, 0xaa4f0108); | ||
77 | cx25840_write4(client, 0x90c, 0xaa4f0108); | ||
78 | break; | ||
79 | } | ||
80 | break; | ||
81 | |||
82 | case AUDIO_EXTERN_1: | ||
83 | case AUDIO_EXTERN_2: | ||
84 | case AUDIO_INTERN: | ||
85 | case AUDIO_RADIO: | ||
86 | switch (freq) { | ||
87 | case V4L2_AUDCLK_32_KHZ: | ||
88 | /* VID_PLL and AUX_PLL */ | ||
89 | cx25840_write4(client, 0x108, 0x0f04081e); | ||
90 | |||
91 | /* AUX_PLL_FRAC */ | ||
92 | cx25840_write4(client, 0x110, 0x69082a01); | ||
93 | |||
94 | /* src1_ctl = 0x08010000 */ | ||
95 | cx25840_write4(client, 0x8f8, 0x00000108); | ||
96 | |||
97 | /* src3/4/6_ctl = 0x08020000 */ | ||
98 | cx25840_write4(client, 0x900, 0x00000208); | ||
99 | cx25840_write4(client, 0x904, 0x00000208); | ||
100 | cx25840_write4(client, 0x90c, 0x00000208); | ||
101 | |||
102 | /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */ | ||
103 | cx25840_write(client, 0x127, 0x54); | ||
104 | break; | ||
105 | |||
106 | case V4L2_AUDCLK_441_KHZ: | ||
107 | /* VID_PLL and AUX_PLL */ | ||
108 | cx25840_write4(client, 0x108, 0x0f040918); | ||
109 | |||
110 | /* AUX_PLL_FRAC */ | ||
111 | cx25840_write4(client, 0x110, 0xd66bec00); | ||
112 | |||
113 | /* src1_ctl = 0x08010000 */ | ||
114 | cx25840_write4(client, 0x8f8, 0xcd600108); | ||
115 | |||
116 | /* src3/4/6_ctl = 0x08020000 */ | ||
117 | cx25840_write4(client, 0x900, 0x85730108); | ||
118 | cx25840_write4(client, 0x904, 0x85730108); | ||
119 | cx25840_write4(client, 0x90c, 0x85730108); | ||
120 | break; | ||
121 | |||
122 | case V4L2_AUDCLK_48_KHZ: | ||
123 | /* VID_PLL and AUX_PLL */ | ||
124 | cx25840_write4(client, 0x108, 0x0f040a18); | ||
125 | |||
126 | /* AUX_PLL_FRAC */ | ||
127 | cx25840_write4(client, 0x110, 0xe5d69800); | ||
128 | |||
129 | /* src1_ctl = 0x08010000 */ | ||
130 | cx25840_write4(client, 0x8f8, 0x00800108); | ||
131 | |||
132 | /* src3/4/6_ctl = 0x08020000 */ | ||
133 | cx25840_write4(client, 0x900, 0x55550108); | ||
134 | cx25840_write4(client, 0x904, 0x55550108); | ||
135 | cx25840_write4(client, 0x90c, 0x55550108); | ||
136 | break; | ||
137 | } | ||
138 | break; | ||
139 | } | ||
140 | |||
141 | /* deassert soft reset */ | ||
142 | cx25840_and_or(client, 0x810, ~0x1, 0x00); | ||
143 | |||
144 | state->audclk_freq = freq; | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static int set_input(struct i2c_client *client, int audio_input) | ||
150 | { | ||
151 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
152 | |||
153 | cx25840_dbg("set audio input (%d)\n", audio_input); | ||
154 | |||
155 | /* stop microcontroller */ | ||
156 | cx25840_and_or(client, 0x803, ~0x10, 0); | ||
157 | |||
158 | /* Mute everything to prevent the PFFT! */ | ||
159 | cx25840_write(client, 0x8d3, 0x1f); | ||
160 | |||
161 | switch (audio_input) { | ||
162 | case AUDIO_TUNER: | ||
163 | /* Set Path1 to Analog Demod Main Channel */ | ||
164 | cx25840_write4(client, 0x8d0, 0x7038061f); | ||
165 | |||
166 | /* When the microcontroller detects the | ||
167 | * audio format, it will unmute the lines */ | ||
168 | cx25840_and_or(client, 0x803, ~0x10, 0x10); | ||
169 | break; | ||
170 | |||
171 | case AUDIO_EXTERN_1: | ||
172 | case AUDIO_EXTERN_2: | ||
173 | case AUDIO_INTERN: | ||
174 | case AUDIO_RADIO: | ||
175 | /* Set Path1 to Serial Audio Input */ | ||
176 | cx25840_write4(client, 0x8d0, 0x12100101); | ||
177 | |||
178 | /* The microcontroller should not be started for the | ||
179 | * non-tuner inputs: autodetection is specific for | ||
180 | * TV audio. */ | ||
181 | break; | ||
182 | |||
183 | default: | ||
184 | cx25840_dbg("Invalid audio input selection %d\n", audio_input); | ||
185 | return -EINVAL; | ||
186 | } | ||
187 | |||
188 | state->audio_input = audio_input; | ||
189 | |||
190 | return set_audclk_freq(client, state->audclk_freq); | ||
191 | } | ||
192 | |||
193 | inline static int get_volume(struct i2c_client *client) | ||
194 | { | ||
195 | /* Volume runs +18dB to -96dB in 1/2dB steps | ||
196 | * change to fit the msp3400 -114dB to +12dB range */ | ||
197 | |||
198 | /* check PATH1_VOLUME */ | ||
199 | int vol = 228 - cx25840_read(client, 0x8d4); | ||
200 | vol = (vol / 2) + 23; | ||
201 | return vol << 9; | ||
202 | } | ||
203 | |||
204 | inline static void set_volume(struct i2c_client *client, int volume) | ||
205 | { | ||
206 | /* First convert the volume to msp3400 values (0-127) */ | ||
207 | int vol = volume >> 9; | ||
208 | /* now scale it up to cx25840 values | ||
209 | * -114dB to -96dB maps to 0 | ||
210 | * this should be 19, but in my testing that was 4dB too loud */ | ||
211 | if (vol <= 23) { | ||
212 | vol = 0; | ||
213 | } else { | ||
214 | vol -= 23; | ||
215 | } | ||
216 | |||
217 | /* PATH1_VOLUME */ | ||
218 | cx25840_write(client, 0x8d4, 228 - (vol * 2)); | ||
219 | } | ||
220 | |||
221 | inline static int get_bass(struct i2c_client *client) | ||
222 | { | ||
223 | /* bass is 49 steps +12dB to -12dB */ | ||
224 | |||
225 | /* check PATH1_EQ_BASS_VOL */ | ||
226 | int bass = cx25840_read(client, 0x8d9) & 0x3f; | ||
227 | bass = (((48 - bass) * 0xffff) + 47) / 48; | ||
228 | return bass; | ||
229 | } | ||
230 | |||
231 | inline static void set_bass(struct i2c_client *client, int bass) | ||
232 | { | ||
233 | /* PATH1_EQ_BASS_VOL */ | ||
234 | cx25840_and_or(client, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff)); | ||
235 | } | ||
236 | |||
237 | inline static int get_treble(struct i2c_client *client) | ||
238 | { | ||
239 | /* treble is 49 steps +12dB to -12dB */ | ||
240 | |||
241 | /* check PATH1_EQ_TREBLE_VOL */ | ||
242 | int treble = cx25840_read(client, 0x8db) & 0x3f; | ||
243 | treble = (((48 - treble) * 0xffff) + 47) / 48; | ||
244 | return treble; | ||
245 | } | ||
246 | |||
247 | inline static void set_treble(struct i2c_client *client, int treble) | ||
248 | { | ||
249 | /* PATH1_EQ_TREBLE_VOL */ | ||
250 | cx25840_and_or(client, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff)); | ||
251 | } | ||
252 | |||
253 | inline static int get_balance(struct i2c_client *client) | ||
254 | { | ||
255 | /* balance is 7 bit, 0 to -96dB */ | ||
256 | |||
257 | /* check PATH1_BAL_LEVEL */ | ||
258 | int balance = cx25840_read(client, 0x8d5) & 0x7f; | ||
259 | /* check PATH1_BAL_LEFT */ | ||
260 | if ((cx25840_read(client, 0x8d5) & 0x80) == 0) | ||
261 | balance = 0x80 - balance; | ||
262 | else | ||
263 | balance = 0x80 + balance; | ||
264 | return balance << 8; | ||
265 | } | ||
266 | |||
267 | inline static void set_balance(struct i2c_client *client, int balance) | ||
268 | { | ||
269 | int bal = balance >> 8; | ||
270 | if (bal > 0x80) { | ||
271 | /* PATH1_BAL_LEFT */ | ||
272 | cx25840_and_or(client, 0x8d5, 0x7f, 0x80); | ||
273 | /* PATH1_BAL_LEVEL */ | ||
274 | cx25840_and_or(client, 0x8d5, ~0x7f, bal & 0x7f); | ||
275 | } else { | ||
276 | /* PATH1_BAL_LEFT */ | ||
277 | cx25840_and_or(client, 0x8d5, 0x7f, 0x00); | ||
278 | /* PATH1_BAL_LEVEL */ | ||
279 | cx25840_and_or(client, 0x8d5, ~0x7f, 0x80 - bal); | ||
280 | } | ||
281 | } | ||
282 | |||
283 | inline static int get_mute(struct i2c_client *client) | ||
284 | { | ||
285 | /* check SRC1_MUTE_EN */ | ||
286 | return cx25840_read(client, 0x8d3) & 0x2 ? 1 : 0; | ||
287 | } | ||
288 | |||
289 | inline static void set_mute(struct i2c_client *client, int mute) | ||
290 | { | ||
291 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
292 | |||
293 | if (state->audio_input == AUDIO_TUNER) { | ||
294 | /* Must turn off microcontroller in order to mute sound. | ||
295 | * Not sure if this is the best method, but it does work. | ||
296 | * If the microcontroller is running, then it will undo any | ||
297 | * changes to the mute register. */ | ||
298 | if (mute) { | ||
299 | /* disable microcontroller */ | ||
300 | cx25840_and_or(client, 0x803, ~0x10, 0x00); | ||
301 | cx25840_write(client, 0x8d3, 0x1f); | ||
302 | } else { | ||
303 | /* enable microcontroller */ | ||
304 | cx25840_and_or(client, 0x803, ~0x10, 0x10); | ||
305 | } | ||
306 | } else { | ||
307 | /* SRC1_MUTE_EN */ | ||
308 | cx25840_and_or(client, 0x8d3, ~0x2, mute ? 0x02 : 0x00); | ||
309 | } | ||
310 | } | ||
311 | |||
312 | int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg) | ||
313 | { | ||
314 | struct v4l2_control *ctrl = arg; | ||
315 | |||
316 | switch (cmd) { | ||
317 | case AUDC_SET_INPUT: | ||
318 | return set_input(client, *(int *)arg); | ||
319 | case VIDIOC_INT_AUDIO_CLOCK_FREQ: | ||
320 | return set_audclk_freq(client, *(enum v4l2_audio_clock_freq *)arg); | ||
321 | case VIDIOC_G_CTRL: | ||
322 | switch (ctrl->id) { | ||
323 | case V4L2_CID_AUDIO_VOLUME: | ||
324 | ctrl->value = get_volume(client); | ||
325 | break; | ||
326 | case V4L2_CID_AUDIO_BASS: | ||
327 | ctrl->value = get_bass(client); | ||
328 | break; | ||
329 | case V4L2_CID_AUDIO_TREBLE: | ||
330 | ctrl->value = get_treble(client); | ||
331 | break; | ||
332 | case V4L2_CID_AUDIO_BALANCE: | ||
333 | ctrl->value = get_balance(client); | ||
334 | break; | ||
335 | case V4L2_CID_AUDIO_MUTE: | ||
336 | ctrl->value = get_mute(client); | ||
337 | break; | ||
338 | default: | ||
339 | return -EINVAL; | ||
340 | } | ||
341 | break; | ||
342 | case VIDIOC_S_CTRL: | ||
343 | switch (ctrl->id) { | ||
344 | case V4L2_CID_AUDIO_VOLUME: | ||
345 | set_volume(client, ctrl->value); | ||
346 | break; | ||
347 | case V4L2_CID_AUDIO_BASS: | ||
348 | set_bass(client, ctrl->value); | ||
349 | break; | ||
350 | case V4L2_CID_AUDIO_TREBLE: | ||
351 | set_treble(client, ctrl->value); | ||
352 | break; | ||
353 | case V4L2_CID_AUDIO_BALANCE: | ||
354 | set_balance(client, ctrl->value); | ||
355 | break; | ||
356 | case V4L2_CID_AUDIO_MUTE: | ||
357 | set_mute(client, ctrl->value); | ||
358 | break; | ||
359 | default: | ||
360 | return -EINVAL; | ||
361 | } | ||
362 | break; | ||
363 | default: | ||
364 | return -EINVAL; | ||
365 | } | ||
366 | |||
367 | return 0; | ||
368 | } | ||
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c new file mode 100644 index 000000000000..f6afeec499c5 --- /dev/null +++ b/drivers/media/video/cx25840/cx25840-core.c | |||
@@ -0,0 +1,1020 @@ | |||
1 | /* cx25840 - Conexant CX25840 audio/video decoder driver | ||
2 | * | ||
3 | * Copyright (C) 2004 Ulf Eklund | ||
4 | * | ||
5 | * Based on the saa7115 driver and on the first verison of Chris Kennedy's | ||
6 | * cx25840 driver. | ||
7 | * | ||
8 | * Changes by Tyler Trafford <tatrafford@comcast.net> | ||
9 | * - cleanup/rewrite for V4L2 API (2005) | ||
10 | * | ||
11 | * VBI support by Hans Verkuil <hverkuil@xs4all.nl>. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * as published by the Free Software Foundation; either version 2 | ||
16 | * of the License, or (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
26 | */ | ||
27 | |||
28 | |||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <linux/videodev2.h> | ||
33 | #include <linux/i2c.h> | ||
34 | #include <media/audiochip.h> | ||
35 | #include <media/v4l2-common.h> | ||
36 | |||
37 | #include "cx25840.h" | ||
38 | |||
39 | MODULE_DESCRIPTION("Conexant CX25840 audio/video decoder driver"); | ||
40 | MODULE_AUTHOR("Ulf Eklund, Chris Kennedy, Hans Verkuil, Tyler Trafford"); | ||
41 | MODULE_LICENSE("GPL"); | ||
42 | |||
43 | static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; | ||
44 | |||
45 | |||
46 | int cx25840_debug = 0; | ||
47 | |||
48 | module_param(cx25840_debug, bool, 0644); | ||
49 | |||
50 | MODULE_PARM_DESC(cx25840_debug, "Debugging messages [0=Off (default) 1=On]"); | ||
51 | |||
52 | I2C_CLIENT_INSMOD; | ||
53 | |||
54 | /* ----------------------------------------------------------------------- */ | ||
55 | |||
56 | int cx25840_write(struct i2c_client *client, u16 addr, u8 value) | ||
57 | { | ||
58 | u8 buffer[3]; | ||
59 | buffer[0] = addr >> 8; | ||
60 | buffer[1] = addr & 0xff; | ||
61 | buffer[2] = value; | ||
62 | return i2c_master_send(client, buffer, 3); | ||
63 | } | ||
64 | |||
65 | int cx25840_write4(struct i2c_client *client, u16 addr, u32 value) | ||
66 | { | ||
67 | u8 buffer[6]; | ||
68 | buffer[0] = addr >> 8; | ||
69 | buffer[1] = addr & 0xff; | ||
70 | buffer[2] = value >> 24; | ||
71 | buffer[3] = (value >> 16) & 0xff; | ||
72 | buffer[4] = (value >> 8) & 0xff; | ||
73 | buffer[5] = value & 0xff; | ||
74 | return i2c_master_send(client, buffer, 6); | ||
75 | } | ||
76 | |||
77 | u8 cx25840_read(struct i2c_client * client, u16 addr) | ||
78 | { | ||
79 | u8 buffer[2]; | ||
80 | buffer[0] = addr >> 8; | ||
81 | buffer[1] = addr & 0xff; | ||
82 | |||
83 | if (i2c_master_send(client, buffer, 2) < 2) | ||
84 | return 0; | ||
85 | |||
86 | if (i2c_master_recv(client, buffer, 1) < 1) | ||
87 | return 0; | ||
88 | |||
89 | return buffer[0]; | ||
90 | } | ||
91 | |||
92 | u32 cx25840_read4(struct i2c_client * client, u16 addr) | ||
93 | { | ||
94 | u8 buffer[4]; | ||
95 | buffer[0] = addr >> 8; | ||
96 | buffer[1] = addr & 0xff; | ||
97 | |||
98 | if (i2c_master_send(client, buffer, 2) < 2) | ||
99 | return 0; | ||
100 | |||
101 | if (i2c_master_recv(client, buffer, 4) < 4) | ||
102 | return 0; | ||
103 | |||
104 | return (buffer[0] << 24) | (buffer[1] << 16) | | ||
105 | (buffer[2] << 8) | buffer[3]; | ||
106 | } | ||
107 | |||
108 | int cx25840_and_or(struct i2c_client *client, u16 addr, u8 and_mask, | ||
109 | u8 or_value) | ||
110 | { | ||
111 | return cx25840_write(client, addr, | ||
112 | (cx25840_read(client, addr) & and_mask) | | ||
113 | or_value); | ||
114 | } | ||
115 | |||
116 | /* ----------------------------------------------------------------------- */ | ||
117 | |||
118 | static int set_input(struct i2c_client *, enum cx25840_input); | ||
119 | static void input_change(struct i2c_client *); | ||
120 | static void log_status(struct i2c_client *client); | ||
121 | |||
122 | /* ----------------------------------------------------------------------- */ | ||
123 | |||
124 | static inline void init_dll1(struct i2c_client *client) | ||
125 | { | ||
126 | /* This is the Hauppauge sequence used to | ||
127 | * initialize the Delay Lock Loop 1 (ADC DLL). */ | ||
128 | cx25840_write(client, 0x159, 0x23); | ||
129 | cx25840_write(client, 0x15a, 0x87); | ||
130 | cx25840_write(client, 0x15b, 0x06); | ||
131 | cx25840_write(client, 0x159, 0xe1); | ||
132 | cx25840_write(client, 0x15a, 0x86); | ||
133 | cx25840_write(client, 0x159, 0xe0); | ||
134 | cx25840_write(client, 0x159, 0xe1); | ||
135 | cx25840_write(client, 0x15b, 0x10); | ||
136 | } | ||
137 | |||
138 | static inline void init_dll2(struct i2c_client *client) | ||
139 | { | ||
140 | /* This is the Hauppauge sequence used to | ||
141 | * initialize the Delay Lock Loop 2 (ADC DLL). */ | ||
142 | cx25840_write(client, 0x15d, 0xe3); | ||
143 | cx25840_write(client, 0x15e, 0x86); | ||
144 | cx25840_write(client, 0x15f, 0x06); | ||
145 | cx25840_write(client, 0x15d, 0xe1); | ||
146 | cx25840_write(client, 0x15d, 0xe0); | ||
147 | cx25840_write(client, 0x15d, 0xe1); | ||
148 | } | ||
149 | |||
150 | static void cx25840_initialize(struct i2c_client *client, int loadfw) | ||
151 | { | ||
152 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
153 | |||
154 | /* datasheet startup in numbered steps, refer to page 3-77 */ | ||
155 | /* 2. */ | ||
156 | cx25840_and_or(client, 0x803, ~0x10, 0x00); | ||
157 | /* The default of this register should be 4, but I get 0 instead. | ||
158 | * Set this register to 4 manually. */ | ||
159 | cx25840_write(client, 0x000, 0x04); | ||
160 | /* 3. */ | ||
161 | init_dll1(client); | ||
162 | init_dll2(client); | ||
163 | cx25840_write(client, 0x136, 0x0a); | ||
164 | /* 4. */ | ||
165 | cx25840_write(client, 0x13c, 0x01); | ||
166 | cx25840_write(client, 0x13c, 0x00); | ||
167 | /* 5. */ | ||
168 | if (loadfw) | ||
169 | cx25840_loadfw(client); | ||
170 | /* 6. */ | ||
171 | cx25840_write(client, 0x115, 0x8c); | ||
172 | cx25840_write(client, 0x116, 0x07); | ||
173 | cx25840_write(client, 0x118, 0x02); | ||
174 | /* 7. */ | ||
175 | cx25840_write(client, 0x4a5, 0x80); | ||
176 | cx25840_write(client, 0x4a5, 0x00); | ||
177 | cx25840_write(client, 0x402, 0x00); | ||
178 | /* 8. */ | ||
179 | cx25840_write(client, 0x401, 0x18); | ||
180 | cx25840_write(client, 0x4a2, 0x10); | ||
181 | cx25840_write(client, 0x402, 0x04); | ||
182 | /* 10. */ | ||
183 | cx25840_write(client, 0x8d3, 0x1f); | ||
184 | cx25840_write(client, 0x8e3, 0x03); | ||
185 | |||
186 | cx25840_vbi_setup(client); | ||
187 | |||
188 | /* trial and error says these are needed to get audio */ | ||
189 | cx25840_write(client, 0x914, 0xa0); | ||
190 | cx25840_write(client, 0x918, 0xa0); | ||
191 | cx25840_write(client, 0x919, 0x01); | ||
192 | |||
193 | /* stereo prefered */ | ||
194 | cx25840_write(client, 0x809, 0x04); | ||
195 | /* AC97 shift */ | ||
196 | cx25840_write(client, 0x8cf, 0x0f); | ||
197 | |||
198 | /* (re)set video input */ | ||
199 | set_input(client, state->input); | ||
200 | /* (re)set audio input */ | ||
201 | cx25840_audio(client, AUDC_SET_INPUT, &state->audio_input); | ||
202 | |||
203 | /* start microcontroller */ | ||
204 | cx25840_and_or(client, 0x803, ~0x10, 0x10); | ||
205 | } | ||
206 | |||
207 | /* ----------------------------------------------------------------------- */ | ||
208 | |||
209 | static void input_change(struct i2c_client *client) | ||
210 | { | ||
211 | v4l2_std_id std = cx25840_get_v4lstd(client); | ||
212 | |||
213 | if (std & V4L2_STD_PAL) { | ||
214 | /* Follow tuner change procedure for PAL */ | ||
215 | cx25840_write(client, 0x808, 0xff); | ||
216 | cx25840_write(client, 0x80b, 0x10); | ||
217 | } else if (std & V4L2_STD_SECAM) { | ||
218 | /* Select autodetect for SECAM */ | ||
219 | cx25840_write(client, 0x808, 0xff); | ||
220 | cx25840_write(client, 0x80b, 0x10); | ||
221 | } else if (std & V4L2_STD_NTSC) { | ||
222 | /* NTSC */ | ||
223 | cx25840_write(client, 0x808, 0xf6); | ||
224 | cx25840_write(client, 0x80b, 0x00); | ||
225 | } | ||
226 | |||
227 | if (cx25840_read(client, 0x803) & 0x10) { | ||
228 | /* restart audio decoder microcontroller */ | ||
229 | cx25840_and_or(client, 0x803, ~0x10, 0x00); | ||
230 | cx25840_and_or(client, 0x803, ~0x10, 0x10); | ||
231 | } | ||
232 | } | ||
233 | |||
234 | static int set_input(struct i2c_client *client, enum cx25840_input input) | ||
235 | { | ||
236 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
237 | |||
238 | cx25840_dbg("decoder set input (%d)\n", input); | ||
239 | |||
240 | switch (input) { | ||
241 | case CX25840_TUNER: | ||
242 | cx25840_dbg("now setting Tuner input\n"); | ||
243 | |||
244 | if (state->cardtype == CARDTYPE_PVR150) { | ||
245 | /* CH_SEL_ADC2=1 */ | ||
246 | cx25840_and_or(client, 0x102, ~0x2, 0x02); | ||
247 | } | ||
248 | |||
249 | /* Video Input Control */ | ||
250 | if (state->cardtype == CARDTYPE_PG600) { | ||
251 | cx25840_write(client, 0x103, 0x11); | ||
252 | } else { | ||
253 | cx25840_write(client, 0x103, 0x46); | ||
254 | } | ||
255 | |||
256 | /* INPUT_MODE=0 */ | ||
257 | cx25840_and_or(client, 0x401, ~0x6, 0x00); | ||
258 | break; | ||
259 | |||
260 | case CX25840_COMPOSITE0: | ||
261 | case CX25840_COMPOSITE1: | ||
262 | cx25840_dbg("now setting Composite input\n"); | ||
263 | |||
264 | /* Video Input Control */ | ||
265 | if (state->cardtype == CARDTYPE_PG600) { | ||
266 | cx25840_write(client, 0x103, 0x00); | ||
267 | } else { | ||
268 | cx25840_write(client, 0x103, 0x02); | ||
269 | } | ||
270 | |||
271 | /* INPUT_MODE=0 */ | ||
272 | cx25840_and_or(client, 0x401, ~0x6, 0x00); | ||
273 | break; | ||
274 | |||
275 | case CX25840_SVIDEO0: | ||
276 | case CX25840_SVIDEO1: | ||
277 | cx25840_dbg("now setting S-Video input\n"); | ||
278 | |||
279 | /* CH_SEL_ADC2=0 */ | ||
280 | cx25840_and_or(client, 0x102, ~0x2, 0x00); | ||
281 | |||
282 | /* Video Input Control */ | ||
283 | if (state->cardtype == CARDTYPE_PG600) { | ||
284 | cx25840_write(client, 0x103, 0x02); | ||
285 | } else { | ||
286 | cx25840_write(client, 0x103, 0x10); | ||
287 | } | ||
288 | |||
289 | /* INPUT_MODE=1 */ | ||
290 | cx25840_and_or(client, 0x401, ~0x6, 0x02); | ||
291 | break; | ||
292 | |||
293 | default: | ||
294 | cx25840_err("%d is not a valid input!\n", input); | ||
295 | return -EINVAL; | ||
296 | } | ||
297 | |||
298 | state->input = input; | ||
299 | input_change(client); | ||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | /* ----------------------------------------------------------------------- */ | ||
304 | |||
305 | static int set_v4lstd(struct i2c_client *client, v4l2_std_id std) | ||
306 | { | ||
307 | u8 fmt; | ||
308 | |||
309 | switch (std) { | ||
310 | /* zero is autodetect */ | ||
311 | case 0: fmt = 0x0; break; | ||
312 | /* default ntsc to ntsc-m */ | ||
313 | case V4L2_STD_NTSC: | ||
314 | case V4L2_STD_NTSC_M: fmt = 0x1; break; | ||
315 | case V4L2_STD_NTSC_M_JP: fmt = 0x2; break; | ||
316 | case V4L2_STD_NTSC_443: fmt = 0x3; break; | ||
317 | case V4L2_STD_PAL: fmt = 0x4; break; | ||
318 | case V4L2_STD_PAL_M: fmt = 0x5; break; | ||
319 | case V4L2_STD_PAL_N: fmt = 0x6; break; | ||
320 | case V4L2_STD_PAL_Nc: fmt = 0x7; break; | ||
321 | case V4L2_STD_PAL_60: fmt = 0x8; break; | ||
322 | case V4L2_STD_SECAM: fmt = 0xc; break; | ||
323 | default: | ||
324 | return -ERANGE; | ||
325 | } | ||
326 | |||
327 | cx25840_and_or(client, 0x400, ~0xf, fmt); | ||
328 | cx25840_vbi_setup(client); | ||
329 | return 0; | ||
330 | } | ||
331 | |||
332 | v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client) | ||
333 | { | ||
334 | /* check VID_FMT_SEL first */ | ||
335 | u8 fmt = cx25840_read(client, 0x400) & 0xf; | ||
336 | |||
337 | if (!fmt) { | ||
338 | /* check AFD_FMT_STAT if set to autodetect */ | ||
339 | fmt = cx25840_read(client, 0x40d) & 0xf; | ||
340 | } | ||
341 | |||
342 | switch (fmt) { | ||
343 | case 0x1: return V4L2_STD_NTSC_M; | ||
344 | case 0x2: return V4L2_STD_NTSC_M_JP; | ||
345 | case 0x3: return V4L2_STD_NTSC_443; | ||
346 | case 0x4: return V4L2_STD_PAL; | ||
347 | case 0x5: return V4L2_STD_PAL_M; | ||
348 | case 0x6: return V4L2_STD_PAL_N; | ||
349 | case 0x7: return V4L2_STD_PAL_Nc; | ||
350 | case 0x8: return V4L2_STD_PAL_60; | ||
351 | case 0xc: return V4L2_STD_SECAM; | ||
352 | default: return V4L2_STD_UNKNOWN; | ||
353 | } | ||
354 | } | ||
355 | |||
356 | /* ----------------------------------------------------------------------- */ | ||
357 | |||
358 | static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) | ||
359 | { | ||
360 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
361 | |||
362 | switch (ctrl->id) { | ||
363 | case CX25840_CID_CARDTYPE: | ||
364 | switch (ctrl->value) { | ||
365 | case CARDTYPE_PVR150: | ||
366 | case CARDTYPE_PG600: | ||
367 | state->cardtype = ctrl->value; | ||
368 | break; | ||
369 | default: | ||
370 | return -ERANGE; | ||
371 | } | ||
372 | |||
373 | set_input(client, state->input); | ||
374 | break; | ||
375 | |||
376 | case V4L2_CID_BRIGHTNESS: | ||
377 | if (ctrl->value < 0 || ctrl->value > 255) { | ||
378 | cx25840_err("invalid brightness setting %d\n", | ||
379 | ctrl->value); | ||
380 | return -ERANGE; | ||
381 | } | ||
382 | |||
383 | cx25840_write(client, 0x414, ctrl->value - 128); | ||
384 | break; | ||
385 | |||
386 | case V4L2_CID_CONTRAST: | ||
387 | if (ctrl->value < 0 || ctrl->value > 127) { | ||
388 | cx25840_err("invalid contrast setting %d\n", | ||
389 | ctrl->value); | ||
390 | return -ERANGE; | ||
391 | } | ||
392 | |||
393 | cx25840_write(client, 0x415, ctrl->value << 1); | ||
394 | break; | ||
395 | |||
396 | case V4L2_CID_SATURATION: | ||
397 | if (ctrl->value < 0 || ctrl->value > 127) { | ||
398 | cx25840_err("invalid saturation setting %d\n", | ||
399 | ctrl->value); | ||
400 | return -ERANGE; | ||
401 | } | ||
402 | |||
403 | cx25840_write(client, 0x420, ctrl->value << 1); | ||
404 | cx25840_write(client, 0x421, ctrl->value << 1); | ||
405 | break; | ||
406 | |||
407 | case V4L2_CID_HUE: | ||
408 | if (ctrl->value < -127 || ctrl->value > 127) { | ||
409 | cx25840_err("invalid hue setting %d\n", ctrl->value); | ||
410 | return -ERANGE; | ||
411 | } | ||
412 | |||
413 | cx25840_write(client, 0x422, ctrl->value); | ||
414 | break; | ||
415 | |||
416 | case V4L2_CID_AUDIO_VOLUME: | ||
417 | case V4L2_CID_AUDIO_BASS: | ||
418 | case V4L2_CID_AUDIO_TREBLE: | ||
419 | case V4L2_CID_AUDIO_BALANCE: | ||
420 | case V4L2_CID_AUDIO_MUTE: | ||
421 | return cx25840_audio(client, VIDIOC_S_CTRL, ctrl); | ||
422 | } | ||
423 | |||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | static int get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) | ||
428 | { | ||
429 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
430 | |||
431 | switch (ctrl->id) { | ||
432 | case CX25840_CID_CARDTYPE: | ||
433 | ctrl->value = state->cardtype; | ||
434 | break; | ||
435 | case V4L2_CID_BRIGHTNESS: | ||
436 | ctrl->value = cx25840_read(client, 0x414) + 128; | ||
437 | break; | ||
438 | case V4L2_CID_CONTRAST: | ||
439 | ctrl->value = cx25840_read(client, 0x415) >> 1; | ||
440 | break; | ||
441 | case V4L2_CID_SATURATION: | ||
442 | ctrl->value = cx25840_read(client, 0x420) >> 1; | ||
443 | break; | ||
444 | case V4L2_CID_HUE: | ||
445 | ctrl->value = cx25840_read(client, 0x422); | ||
446 | break; | ||
447 | case V4L2_CID_AUDIO_VOLUME: | ||
448 | case V4L2_CID_AUDIO_BASS: | ||
449 | case V4L2_CID_AUDIO_TREBLE: | ||
450 | case V4L2_CID_AUDIO_BALANCE: | ||
451 | case V4L2_CID_AUDIO_MUTE: | ||
452 | return cx25840_audio(client, VIDIOC_G_CTRL, ctrl); | ||
453 | default: | ||
454 | return -EINVAL; | ||
455 | } | ||
456 | |||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | /* ----------------------------------------------------------------------- */ | ||
461 | |||
462 | static int get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) | ||
463 | { | ||
464 | switch (fmt->type) { | ||
465 | case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: | ||
466 | return cx25840_vbi(client, VIDIOC_G_FMT, fmt); | ||
467 | default: | ||
468 | return -EINVAL; | ||
469 | } | ||
470 | |||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) | ||
475 | { | ||
476 | struct v4l2_pix_format *pix; | ||
477 | int HSC, VSC, Vsrc, Hsrc, filter, Vlines; | ||
478 | int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_NTSC); | ||
479 | |||
480 | switch (fmt->type) { | ||
481 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
482 | pix = &(fmt->fmt.pix); | ||
483 | |||
484 | Vsrc = (cx25840_read(client, 0x476) & 0x3f) << 4; | ||
485 | Vsrc |= (cx25840_read(client, 0x475) & 0xf0) >> 4; | ||
486 | |||
487 | Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4; | ||
488 | Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4; | ||
489 | |||
490 | Vlines = pix->height + (is_pal ? 4 : 7); | ||
491 | |||
492 | if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) || | ||
493 | (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) { | ||
494 | cx25840_err("%dx%d is not a valid size!\n", | ||
495 | pix->width, pix->height); | ||
496 | return -ERANGE; | ||
497 | } | ||
498 | |||
499 | HSC = (Hsrc * (1 << 20)) / pix->width - (1 << 20); | ||
500 | VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9)); | ||
501 | VSC &= 0x1fff; | ||
502 | |||
503 | if (pix->width >= 385) | ||
504 | filter = 0; | ||
505 | else if (pix->width > 192) | ||
506 | filter = 1; | ||
507 | else if (pix->width > 96) | ||
508 | filter = 2; | ||
509 | else | ||
510 | filter = 3; | ||
511 | |||
512 | cx25840_dbg("decoder set size %dx%d -> scale %ux%u\n", | ||
513 | pix->width, pix->height, HSC, VSC); | ||
514 | |||
515 | /* HSCALE=HSC */ | ||
516 | cx25840_write(client, 0x418, HSC & 0xff); | ||
517 | cx25840_write(client, 0x419, (HSC >> 8) & 0xff); | ||
518 | cx25840_write(client, 0x41a, HSC >> 16); | ||
519 | /* VSCALE=VSC */ | ||
520 | cx25840_write(client, 0x41c, VSC & 0xff); | ||
521 | cx25840_write(client, 0x41d, VSC >> 8); | ||
522 | /* VS_INTRLACE=1 VFILT=filter */ | ||
523 | cx25840_write(client, 0x41e, 0x8 | filter); | ||
524 | break; | ||
525 | |||
526 | case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: | ||
527 | return cx25840_vbi(client, VIDIOC_S_FMT, fmt); | ||
528 | |||
529 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
530 | return cx25840_vbi(client, VIDIOC_S_FMT, fmt); | ||
531 | |||
532 | default: | ||
533 | return -EINVAL; | ||
534 | } | ||
535 | |||
536 | return 0; | ||
537 | } | ||
538 | |||
539 | /* ----------------------------------------------------------------------- */ | ||
540 | |||
541 | static int cx25840_command(struct i2c_client *client, unsigned int cmd, | ||
542 | void *arg) | ||
543 | { | ||
544 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
545 | struct v4l2_tuner *vt = arg; | ||
546 | int result = 0; | ||
547 | |||
548 | switch (cmd) { | ||
549 | case 0: | ||
550 | break; | ||
551 | |||
552 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
553 | /* ioctls to allow direct access to the | ||
554 | * cx25840 registers for testing */ | ||
555 | case VIDIOC_INT_G_REGISTER: | ||
556 | { | ||
557 | struct v4l2_register *reg = arg; | ||
558 | |||
559 | if (reg->i2c_id != I2C_DRIVERID_CX25840) | ||
560 | return -EINVAL; | ||
561 | reg->val = cx25840_read(client, reg->reg & 0x0fff); | ||
562 | break; | ||
563 | } | ||
564 | |||
565 | case VIDIOC_INT_S_REGISTER: | ||
566 | { | ||
567 | struct v4l2_register *reg = arg; | ||
568 | |||
569 | if (reg->i2c_id != I2C_DRIVERID_CX25840) | ||
570 | return -EINVAL; | ||
571 | if (!capable(CAP_SYS_ADMIN)) | ||
572 | return -EPERM; | ||
573 | cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff); | ||
574 | break; | ||
575 | } | ||
576 | #endif | ||
577 | |||
578 | case VIDIOC_INT_DECODE_VBI_LINE: | ||
579 | return cx25840_vbi(client, cmd, arg); | ||
580 | |||
581 | case VIDIOC_INT_AUDIO_CLOCK_FREQ: | ||
582 | case AUDC_SET_INPUT: | ||
583 | result = cx25840_audio(client, cmd, arg); | ||
584 | break; | ||
585 | |||
586 | case VIDIOC_STREAMON: | ||
587 | cx25840_dbg("enable output\n"); | ||
588 | cx25840_write(client, 0x115, 0x8c); | ||
589 | cx25840_write(client, 0x116, 0x07); | ||
590 | break; | ||
591 | |||
592 | case VIDIOC_STREAMOFF: | ||
593 | cx25840_dbg("disable output\n"); | ||
594 | cx25840_write(client, 0x115, 0x00); | ||
595 | cx25840_write(client, 0x116, 0x00); | ||
596 | break; | ||
597 | |||
598 | case VIDIOC_LOG_STATUS: | ||
599 | log_status(client); | ||
600 | break; | ||
601 | |||
602 | case VIDIOC_G_CTRL: | ||
603 | result = get_v4lctrl(client, (struct v4l2_control *)arg); | ||
604 | break; | ||
605 | |||
606 | case VIDIOC_S_CTRL: | ||
607 | result = set_v4lctrl(client, (struct v4l2_control *)arg); | ||
608 | break; | ||
609 | |||
610 | case VIDIOC_G_STD: | ||
611 | *(v4l2_std_id *)arg = cx25840_get_v4lstd(client); | ||
612 | break; | ||
613 | |||
614 | case VIDIOC_S_STD: | ||
615 | result = set_v4lstd(client, *(v4l2_std_id *)arg); | ||
616 | break; | ||
617 | |||
618 | case VIDIOC_G_INPUT: | ||
619 | *(int *)arg = state->input; | ||
620 | break; | ||
621 | |||
622 | case VIDIOC_S_INPUT: | ||
623 | result = set_input(client, *(int *)arg); | ||
624 | break; | ||
625 | |||
626 | case VIDIOC_S_FREQUENCY: | ||
627 | input_change(client); | ||
628 | break; | ||
629 | |||
630 | case VIDIOC_G_TUNER: | ||
631 | { | ||
632 | u8 mode = cx25840_read(client, 0x804); | ||
633 | u8 pref = cx25840_read(client, 0x809) & 0xf; | ||
634 | u8 vpres = cx25840_read(client, 0x80a) & 0x10; | ||
635 | int val = 0; | ||
636 | |||
637 | vt->capability |= | ||
638 | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | | ||
639 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; | ||
640 | |||
641 | vt->signal = vpres ? 0xffff : 0x0; | ||
642 | |||
643 | /* get rxsubchans and audmode */ | ||
644 | if ((mode & 0xf) == 1) | ||
645 | val |= V4L2_TUNER_SUB_STEREO; | ||
646 | else | ||
647 | val |= V4L2_TUNER_SUB_MONO; | ||
648 | |||
649 | if (mode == 2 || mode == 4) | ||
650 | val |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; | ||
651 | |||
652 | if (mode & 0x10) | ||
653 | val |= V4L2_TUNER_SUB_SAP; | ||
654 | |||
655 | vt->rxsubchans = val; | ||
656 | |||
657 | switch (pref) { | ||
658 | case 0: | ||
659 | vt->audmode = V4L2_TUNER_MODE_MONO; | ||
660 | break; | ||
661 | case 1: | ||
662 | case 2: | ||
663 | vt->audmode = V4L2_TUNER_MODE_LANG2; | ||
664 | break; | ||
665 | case 4: | ||
666 | default: | ||
667 | vt->audmode = V4L2_TUNER_MODE_STEREO; | ||
668 | } | ||
669 | break; | ||
670 | } | ||
671 | |||
672 | case VIDIOC_S_TUNER: | ||
673 | switch (vt->audmode) { | ||
674 | case V4L2_TUNER_MODE_MONO: | ||
675 | case V4L2_TUNER_MODE_LANG1: | ||
676 | /* Force PREF_MODE to MONO */ | ||
677 | cx25840_and_or(client, 0x809, ~0xf, 0x00); | ||
678 | break; | ||
679 | case V4L2_TUNER_MODE_STEREO: | ||
680 | /* Force PREF_MODE to STEREO */ | ||
681 | cx25840_and_or(client, 0x809, ~0xf, 0x04); | ||
682 | break; | ||
683 | case V4L2_TUNER_MODE_LANG2: | ||
684 | /* Force PREF_MODE to LANG2 */ | ||
685 | cx25840_and_or(client, 0x809, ~0xf, 0x01); | ||
686 | break; | ||
687 | } | ||
688 | break; | ||
689 | |||
690 | case VIDIOC_G_FMT: | ||
691 | result = get_v4lfmt(client, (struct v4l2_format *)arg); | ||
692 | break; | ||
693 | |||
694 | case VIDIOC_S_FMT: | ||
695 | result = set_v4lfmt(client, (struct v4l2_format *)arg); | ||
696 | break; | ||
697 | |||
698 | case VIDIOC_INT_RESET: | ||
699 | cx25840_initialize(client, 0); | ||
700 | break; | ||
701 | |||
702 | case VIDIOC_INT_G_CHIP_IDENT: | ||
703 | *(enum v4l2_chip_ident *)arg = | ||
704 | V4L2_IDENT_CX25840 + ((cx25840_read(client, 0x100) >> 4) & 0xf); | ||
705 | break; | ||
706 | |||
707 | default: | ||
708 | cx25840_err("invalid ioctl %x\n", cmd); | ||
709 | return -EINVAL; | ||
710 | } | ||
711 | |||
712 | return result; | ||
713 | } | ||
714 | |||
715 | /* ----------------------------------------------------------------------- */ | ||
716 | |||
717 | struct i2c_driver i2c_driver_cx25840; | ||
718 | |||
719 | static int cx25840_detect_client(struct i2c_adapter *adapter, int address, | ||
720 | int kind) | ||
721 | { | ||
722 | struct i2c_client *client; | ||
723 | struct cx25840_state *state; | ||
724 | u16 device_id; | ||
725 | |||
726 | /* Check if the adapter supports the needed features | ||
727 | * Not until kernel version 2.6.11 did the bit-algo | ||
728 | * correctly report that it would do an I2C-level xfer */ | ||
729 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) | ||
730 | return 0; | ||
731 | |||
732 | client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
733 | if (client == 0) | ||
734 | return -ENOMEM; | ||
735 | |||
736 | memset(client, 0, sizeof(struct i2c_client)); | ||
737 | client->addr = address; | ||
738 | client->adapter = adapter; | ||
739 | client->driver = &i2c_driver_cx25840; | ||
740 | client->flags = I2C_CLIENT_ALLOW_USE; | ||
741 | snprintf(client->name, sizeof(client->name) - 1, "cx25840"); | ||
742 | |||
743 | cx25840_dbg("detecting cx25840 client on address 0x%x\n", address << 1); | ||
744 | |||
745 | device_id = cx25840_read(client, 0x101) << 8; | ||
746 | device_id |= cx25840_read(client, 0x100); | ||
747 | |||
748 | /* The high byte of the device ID should be | ||
749 | * 0x84 if chip is present */ | ||
750 | if ((device_id & 0xff00) != 0x8400) { | ||
751 | cx25840_dbg("cx25840 not found\n"); | ||
752 | kfree(client); | ||
753 | return 0; | ||
754 | } | ||
755 | |||
756 | cx25840_info("cx25%3x-2%x found @ 0x%x (%s)\n", | ||
757 | (device_id & 0xfff0) >> 4, | ||
758 | (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : 3, | ||
759 | address << 1, adapter->name); | ||
760 | |||
761 | state = kmalloc(sizeof(struct cx25840_state), GFP_KERNEL); | ||
762 | if (state == NULL) { | ||
763 | kfree(client); | ||
764 | return -ENOMEM; | ||
765 | } | ||
766 | |||
767 | i2c_set_clientdata(client, state); | ||
768 | memset(state, 0, sizeof(struct cx25840_state)); | ||
769 | state->input = CX25840_TUNER; | ||
770 | state->audclk_freq = V4L2_AUDCLK_48_KHZ; | ||
771 | state->audio_input = AUDIO_TUNER; | ||
772 | state->cardtype = CARDTYPE_PVR150; | ||
773 | |||
774 | cx25840_initialize(client, 1); | ||
775 | |||
776 | i2c_attach_client(client); | ||
777 | |||
778 | return 0; | ||
779 | } | ||
780 | |||
781 | static int cx25840_attach_adapter(struct i2c_adapter *adapter) | ||
782 | { | ||
783 | #ifdef I2C_CLASS_TV_ANALOG | ||
784 | if (adapter->class & I2C_CLASS_TV_ANALOG) | ||
785 | #else | ||
786 | if (adapter->id == I2C_HW_B_BT848) | ||
787 | #endif | ||
788 | return i2c_probe(adapter, &addr_data, &cx25840_detect_client); | ||
789 | return 0; | ||
790 | } | ||
791 | |||
792 | static int cx25840_detach_client(struct i2c_client *client) | ||
793 | { | ||
794 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
795 | int err; | ||
796 | |||
797 | err = i2c_detach_client(client); | ||
798 | if (err) { | ||
799 | return err; | ||
800 | } | ||
801 | |||
802 | kfree(state); | ||
803 | kfree(client); | ||
804 | |||
805 | return 0; | ||
806 | } | ||
807 | |||
808 | /* ----------------------------------------------------------------------- */ | ||
809 | |||
810 | struct i2c_driver i2c_driver_cx25840 = { | ||
811 | .name = "cx25840", | ||
812 | |||
813 | .id = I2C_DRIVERID_CX25840, | ||
814 | .flags = I2C_DF_NOTIFY, | ||
815 | |||
816 | .attach_adapter = cx25840_attach_adapter, | ||
817 | .detach_client = cx25840_detach_client, | ||
818 | .command = cx25840_command, | ||
819 | .owner = THIS_MODULE, | ||
820 | }; | ||
821 | |||
822 | |||
823 | static int __init m__init(void) | ||
824 | { | ||
825 | return i2c_add_driver(&i2c_driver_cx25840); | ||
826 | } | ||
827 | |||
828 | static void __exit m__exit(void) | ||
829 | { | ||
830 | i2c_del_driver(&i2c_driver_cx25840); | ||
831 | } | ||
832 | |||
833 | module_init(m__init); | ||
834 | module_exit(m__exit); | ||
835 | |||
836 | /* ----------------------------------------------------------------------- */ | ||
837 | |||
838 | static void log_status(struct i2c_client *client) | ||
839 | { | ||
840 | static const char *const fmt_strs[] = { | ||
841 | "0x0", | ||
842 | "NTSC-M", "NTSC-J", "NTSC-4.43", | ||
843 | "PAL-BDGHI", "PAL-M", "PAL-N", "PAL-Nc", "PAL-60", | ||
844 | "0x9", "0xA", "0xB", | ||
845 | "SECAM", | ||
846 | "0xD", "0xE", "0xF" | ||
847 | }; | ||
848 | |||
849 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
850 | u8 microctrl_vidfmt = cx25840_read(client, 0x80a); | ||
851 | u8 vidfmt_sel = cx25840_read(client, 0x400) & 0xf; | ||
852 | u8 gen_stat1 = cx25840_read(client, 0x40d); | ||
853 | u8 download_ctl = cx25840_read(client, 0x803); | ||
854 | u8 mod_det_stat0 = cx25840_read(client, 0x804); | ||
855 | u8 mod_det_stat1 = cx25840_read(client, 0x805); | ||
856 | u8 audio_config = cx25840_read(client, 0x808); | ||
857 | u8 pref_mode = cx25840_read(client, 0x809); | ||
858 | u8 afc0 = cx25840_read(client, 0x80b); | ||
859 | u8 mute_ctl = cx25840_read(client, 0x8d3); | ||
860 | char *p; | ||
861 | |||
862 | cx25840_info("Video signal: %spresent\n", | ||
863 | (microctrl_vidfmt & 0x10) ? "" : "not "); | ||
864 | cx25840_info("Detected format: %s\n", | ||
865 | fmt_strs[gen_stat1 & 0xf]); | ||
866 | |||
867 | switch (mod_det_stat0) { | ||
868 | case 0x00: p = "mono"; break; | ||
869 | case 0x01: p = "stereo"; break; | ||
870 | case 0x02: p = "dual"; break; | ||
871 | case 0x04: p = "tri"; break; | ||
872 | case 0x10: p = "mono with SAP"; break; | ||
873 | case 0x11: p = "stereo with SAP"; break; | ||
874 | case 0x12: p = "dual with SAP"; break; | ||
875 | case 0x14: p = "tri with SAP"; break; | ||
876 | case 0xfe: p = "forced mode"; break; | ||
877 | default: p = "not defined"; | ||
878 | } | ||
879 | cx25840_info("Detected audio mode: %s\n", p); | ||
880 | |||
881 | switch (mod_det_stat1) { | ||
882 | case 0x00: p = "not defined"; break; | ||
883 | case 0x01: p = "EIAJ"; break; | ||
884 | case 0x02: p = "A2-M"; break; | ||
885 | case 0x03: p = "A2-BG"; break; | ||
886 | case 0x04: p = "A2-DK1"; break; | ||
887 | case 0x05: p = "A2-DK2"; break; | ||
888 | case 0x06: p = "A2-DK3"; break; | ||
889 | case 0x07: p = "A1 (6.0 MHz FM Mono)"; break; | ||
890 | case 0x08: p = "AM-L"; break; | ||
891 | case 0x09: p = "NICAM-BG"; break; | ||
892 | case 0x0a: p = "NICAM-DK"; break; | ||
893 | case 0x0b: p = "NICAM-I"; break; | ||
894 | case 0x0c: p = "NICAM-L"; break; | ||
895 | case 0x0d: p = "BTSC/EIAJ/A2-M Mono (4.5 MHz FMMono)"; break; | ||
896 | case 0x0e: p = "IF FM Radio"; break; | ||
897 | case 0x0f: p = "BTSC"; break; | ||
898 | case 0x10: p = "high-deviation FM"; break; | ||
899 | case 0x11: p = "very high-deviation FM"; break; | ||
900 | case 0xfd: p = "unknown audio standard"; break; | ||
901 | case 0xfe: p = "forced audio standard"; break; | ||
902 | case 0xff: p = "no detected audio standard"; break; | ||
903 | default: p = "not defined"; | ||
904 | } | ||
905 | cx25840_info("Detected audio standard: %s\n", p); | ||
906 | cx25840_info("Audio muted: %s\n", | ||
907 | (mute_ctl & 0x2) ? "yes" : "no"); | ||
908 | cx25840_info("Audio microcontroller: %s\n", | ||
909 | (download_ctl & 0x10) ? "running" : "stopped"); | ||
910 | |||
911 | switch (audio_config >> 4) { | ||
912 | case 0x00: p = "undefined"; break; | ||
913 | case 0x01: p = "BTSC"; break; | ||
914 | case 0x02: p = "EIAJ"; break; | ||
915 | case 0x03: p = "A2-M"; break; | ||
916 | case 0x04: p = "A2-BG"; break; | ||
917 | case 0x05: p = "A2-DK1"; break; | ||
918 | case 0x06: p = "A2-DK2"; break; | ||
919 | case 0x07: p = "A2-DK3"; break; | ||
920 | case 0x08: p = "A1 (6.0 MHz FM Mono)"; break; | ||
921 | case 0x09: p = "AM-L"; break; | ||
922 | case 0x0a: p = "NICAM-BG"; break; | ||
923 | case 0x0b: p = "NICAM-DK"; break; | ||
924 | case 0x0c: p = "NICAM-I"; break; | ||
925 | case 0x0d: p = "NICAM-L"; break; | ||
926 | case 0x0e: p = "FM radio"; break; | ||
927 | case 0x0f: p = "automatic detection"; break; | ||
928 | default: p = "undefined"; | ||
929 | } | ||
930 | cx25840_info("Configured audio standard: %s\n", p); | ||
931 | |||
932 | if ((audio_config >> 4) < 0xF) { | ||
933 | switch (audio_config & 0xF) { | ||
934 | case 0x00: p = "MONO1 (LANGUAGE A/Mono L+R channel for BTSC, EIAJ, A2)"; break; | ||
935 | case 0x01: p = "MONO2 (LANGUAGE B)"; break; | ||
936 | case 0x02: p = "MONO3 (STEREO forced MONO)"; break; | ||
937 | case 0x03: p = "MONO4 (NICAM ANALOG-Language C/Analog Fallback)"; break; | ||
938 | case 0x04: p = "STEREO"; break; | ||
939 | case 0x05: p = "DUAL1 (AB)"; break; | ||
940 | case 0x06: p = "DUAL2 (AC) (FM)"; break; | ||
941 | case 0x07: p = "DUAL3 (BC) (FM)"; break; | ||
942 | case 0x08: p = "DUAL4 (AC) (AM)"; break; | ||
943 | case 0x09: p = "DUAL5 (BC) (AM)"; break; | ||
944 | case 0x0a: p = "SAP"; break; | ||
945 | default: p = "undefined"; | ||
946 | } | ||
947 | cx25840_info("Configured audio mode: %s\n", p); | ||
948 | } else { | ||
949 | switch (audio_config & 0xF) { | ||
950 | case 0x00: p = "BG"; break; | ||
951 | case 0x01: p = "DK1"; break; | ||
952 | case 0x02: p = "DK2"; break; | ||
953 | case 0x03: p = "DK3"; break; | ||
954 | case 0x04: p = "I"; break; | ||
955 | case 0x05: p = "L"; break; | ||
956 | case 0x06: p = "BTSC"; break; | ||
957 | case 0x07: p = "EIAJ"; break; | ||
958 | case 0x08: p = "A2-M"; break; | ||
959 | case 0x09: p = "FM Radio"; break; | ||
960 | case 0x0f: p = "automatic standard and mode detection"; break; | ||
961 | default: p = "undefined"; | ||
962 | } | ||
963 | cx25840_info("Configured audio system: %s\n", p); | ||
964 | } | ||
965 | |||
966 | cx25840_info("Specified standard: %s\n", | ||
967 | vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection"); | ||
968 | |||
969 | switch (state->input) { | ||
970 | case CX25840_COMPOSITE0: p = "Composite 0"; break; | ||
971 | case CX25840_COMPOSITE1: p = "Composite 1"; break; | ||
972 | case CX25840_SVIDEO0: p = "S-Video 0"; break; | ||
973 | case CX25840_SVIDEO1: p = "S-Video 1"; break; | ||
974 | case CX25840_TUNER: p = "Tuner"; break; | ||
975 | } | ||
976 | cx25840_info("Specified input: %s\n", p); | ||
977 | cx25840_info("Specified audio input: %s\n", | ||
978 | state->audio_input == 0 ? "Tuner" : "External"); | ||
979 | |||
980 | switch (state->audclk_freq) { | ||
981 | case V4L2_AUDCLK_441_KHZ: p = "44.1 kHz"; break; | ||
982 | case V4L2_AUDCLK_48_KHZ: p = "48 kHz"; break; | ||
983 | case V4L2_AUDCLK_32_KHZ: p = "32 kHz"; break; | ||
984 | default: p = "undefined"; | ||
985 | } | ||
986 | cx25840_info("Specified audioclock freq: %s\n", p); | ||
987 | |||
988 | switch (pref_mode & 0xf) { | ||
989 | case 0: p = "mono/language A"; break; | ||
990 | case 1: p = "language B"; break; | ||
991 | case 2: p = "language C"; break; | ||
992 | case 3: p = "analog fallback"; break; | ||
993 | case 4: p = "stereo"; break; | ||
994 | case 5: p = "language AC"; break; | ||
995 | case 6: p = "language BC"; break; | ||
996 | case 7: p = "language AB"; break; | ||
997 | default: p = "undefined"; | ||
998 | } | ||
999 | cx25840_info("Preferred audio mode: %s\n", p); | ||
1000 | |||
1001 | if ((audio_config & 0xf) == 0xf) { | ||
1002 | switch ((afc0 >> 3) & 0x3) { | ||
1003 | case 0: p = "system DK"; break; | ||
1004 | case 1: p = "system L"; break; | ||
1005 | case 2: p = "autodetect"; break; | ||
1006 | default: p = "undefined"; | ||
1007 | } | ||
1008 | cx25840_info("Selected 65 MHz format: %s\n", p); | ||
1009 | |||
1010 | switch (afc0 & 0x7) { | ||
1011 | case 0: p = "chroma"; break; | ||
1012 | case 1: p = "BTSC"; break; | ||
1013 | case 2: p = "EIAJ"; break; | ||
1014 | case 3: p = "A2-M"; break; | ||
1015 | case 4: p = "autodetect"; break; | ||
1016 | default: p = "undefined"; | ||
1017 | } | ||
1018 | cx25840_info("Selected 45 MHz format: %s\n", p); | ||
1019 | } | ||
1020 | } | ||
diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/video/cx25840/cx25840-firmware.c new file mode 100644 index 000000000000..df9d50a75542 --- /dev/null +++ b/drivers/media/video/cx25840/cx25840-firmware.c | |||
@@ -0,0 +1,167 @@ | |||
1 | /* cx25840 firmware functions | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or | ||
4 | * modify it under the terms of the GNU General Public License | ||
5 | * as published by the Free Software Foundation; either version 2 | ||
6 | * of the License, or (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/i2c-algo-bit.h> | ||
22 | #include <linux/firmware.h> | ||
23 | #include <media/v4l2-common.h> | ||
24 | |||
25 | #include "cx25840.h" | ||
26 | |||
27 | #define FWFILE "v4l-cx25840.fw" | ||
28 | #define FWSEND 1024 | ||
29 | |||
30 | #define FWDEV(x) &((x)->adapter->dev) | ||
31 | |||
32 | static int fastfw = 1; | ||
33 | static char *firmware = FWFILE; | ||
34 | |||
35 | module_param(fastfw, bool, 0444); | ||
36 | module_param(firmware, charp, 0444); | ||
37 | |||
38 | MODULE_PARM_DESC(fastfw, "Load firmware fast [0=100MHz 1=333MHz (default)]"); | ||
39 | MODULE_PARM_DESC(firmware, "Firmware image [default: " FWFILE "]"); | ||
40 | |||
41 | static inline void set_i2c_delay(struct i2c_client *client, int delay) | ||
42 | { | ||
43 | struct i2c_algo_bit_data *algod = client->adapter->algo_data; | ||
44 | |||
45 | /* We aren't guaranteed to be using algo_bit, | ||
46 | * so avoid the null pointer dereference | ||
47 | * and disable the 'fast firmware load' */ | ||
48 | if (algod) { | ||
49 | algod->udelay = delay; | ||
50 | } else { | ||
51 | fastfw = 0; | ||
52 | } | ||
53 | } | ||
54 | |||
55 | static inline void start_fw_load(struct i2c_client *client) | ||
56 | { | ||
57 | /* DL_ADDR_LB=0 DL_ADDR_HB=0 */ | ||
58 | cx25840_write(client, 0x800, 0x00); | ||
59 | cx25840_write(client, 0x801, 0x00); | ||
60 | // DL_MAP=3 DL_AUTO_INC=0 DL_ENABLE=1 | ||
61 | cx25840_write(client, 0x803, 0x0b); | ||
62 | /* AUTO_INC_DIS=1 */ | ||
63 | cx25840_write(client, 0x000, 0x20); | ||
64 | |||
65 | if (fastfw) | ||
66 | set_i2c_delay(client, 3); | ||
67 | } | ||
68 | |||
69 | static inline void end_fw_load(struct i2c_client *client) | ||
70 | { | ||
71 | if (fastfw) | ||
72 | set_i2c_delay(client, 10); | ||
73 | |||
74 | /* AUTO_INC_DIS=0 */ | ||
75 | cx25840_write(client, 0x000, 0x00); | ||
76 | /* DL_ENABLE=0 */ | ||
77 | cx25840_write(client, 0x803, 0x03); | ||
78 | } | ||
79 | |||
80 | static inline int check_fw_load(struct i2c_client *client, int size) | ||
81 | { | ||
82 | /* DL_ADDR_HB DL_ADDR_LB */ | ||
83 | int s = cx25840_read(client, 0x801) << 8; | ||
84 | s |= cx25840_read(client, 0x800); | ||
85 | |||
86 | if (size != s) { | ||
87 | cx25840_err("firmware %s load failed\n", firmware); | ||
88 | return -EINVAL; | ||
89 | } | ||
90 | |||
91 | cx25840_info("loaded %s firmware (%d bytes)\n", firmware, size); | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | static inline int fw_write(struct i2c_client *client, u8 * data, int size) | ||
96 | { | ||
97 | if (i2c_master_send(client, data, size) < size) { | ||
98 | |||
99 | if (fastfw) { | ||
100 | cx25840_err("333MHz i2c firmware load failed\n"); | ||
101 | fastfw = 0; | ||
102 | set_i2c_delay(client, 10); | ||
103 | |||
104 | if (i2c_master_send(client, data, size) < size) { | ||
105 | cx25840_err | ||
106 | ("100MHz i2c firmware load failed\n"); | ||
107 | return -ENOSYS; | ||
108 | } | ||
109 | |||
110 | } else { | ||
111 | cx25840_err("firmware load i2c failure\n"); | ||
112 | return -ENOSYS; | ||
113 | } | ||
114 | |||
115 | } | ||
116 | |||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | int cx25840_loadfw(struct i2c_client *client) | ||
121 | { | ||
122 | const struct firmware *fw = NULL; | ||
123 | u8 buffer[4], *ptr; | ||
124 | int size, send, retval; | ||
125 | |||
126 | if (request_firmware(&fw, firmware, FWDEV(client)) != 0) { | ||
127 | cx25840_err("unable to open firmware %s\n", firmware); | ||
128 | return -EINVAL; | ||
129 | } | ||
130 | |||
131 | start_fw_load(client); | ||
132 | |||
133 | buffer[0] = 0x08; | ||
134 | buffer[1] = 0x02; | ||
135 | buffer[2] = fw->data[0]; | ||
136 | buffer[3] = fw->data[1]; | ||
137 | retval = fw_write(client, buffer, 4); | ||
138 | |||
139 | if (retval < 0) { | ||
140 | release_firmware(fw); | ||
141 | return retval; | ||
142 | } | ||
143 | |||
144 | size = fw->size - 2; | ||
145 | ptr = fw->data; | ||
146 | while (size > 0) { | ||
147 | ptr[0] = 0x08; | ||
148 | ptr[1] = 0x02; | ||
149 | send = size > (FWSEND - 2) ? FWSEND : size + 2; | ||
150 | retval = fw_write(client, ptr, send); | ||
151 | |||
152 | if (retval < 0) { | ||
153 | release_firmware(fw); | ||
154 | return retval; | ||
155 | } | ||
156 | |||
157 | size -= FWSEND - 2; | ||
158 | ptr += FWSEND - 2; | ||
159 | } | ||
160 | |||
161 | end_fw_load(client); | ||
162 | |||
163 | size = fw->size; | ||
164 | release_firmware(fw); | ||
165 | |||
166 | return check_fw_load(client, size); | ||
167 | } | ||
diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c new file mode 100644 index 000000000000..13ba4e15ddea --- /dev/null +++ b/drivers/media/video/cx25840/cx25840-vbi.c | |||
@@ -0,0 +1,315 @@ | |||
1 | /* cx25840 VBI functions | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or | ||
4 | * modify it under the terms of the GNU General Public License | ||
5 | * as published by the Free Software Foundation; either version 2 | ||
6 | * of the License, or (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | |||
19 | #include <linux/videodev2.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <media/v4l2-common.h> | ||
22 | |||
23 | #include "cx25840.h" | ||
24 | |||
25 | static inline int odd_parity(u8 c) | ||
26 | { | ||
27 | c ^= (c >> 4); | ||
28 | c ^= (c >> 2); | ||
29 | c ^= (c >> 1); | ||
30 | |||
31 | return c & 1; | ||
32 | } | ||
33 | |||
34 | static inline int decode_vps(u8 * dst, u8 * p) | ||
35 | { | ||
36 | static const u8 biphase_tbl[] = { | ||
37 | 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, | ||
38 | 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0, | ||
39 | 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96, | ||
40 | 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2, | ||
41 | 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94, | ||
42 | 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0, | ||
43 | 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, | ||
44 | 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0, | ||
45 | 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5, | ||
46 | 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1, | ||
47 | 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87, | ||
48 | 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3, | ||
49 | 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85, | ||
50 | 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1, | ||
51 | 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5, | ||
52 | 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1, | ||
53 | 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4, | ||
54 | 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0, | ||
55 | 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86, | ||
56 | 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2, | ||
57 | 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84, | ||
58 | 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0, | ||
59 | 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4, | ||
60 | 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0, | ||
61 | 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, | ||
62 | 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0, | ||
63 | 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96, | ||
64 | 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2, | ||
65 | 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94, | ||
66 | 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0, | ||
67 | 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, | ||
68 | 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0, | ||
69 | }; | ||
70 | |||
71 | u8 c, err = 0; | ||
72 | int i; | ||
73 | |||
74 | for (i = 0; i < 2 * 13; i += 2) { | ||
75 | err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]]; | ||
76 | c = (biphase_tbl[p[i + 1]] & 0xf) | | ||
77 | ((biphase_tbl[p[i]] & 0xf) << 4); | ||
78 | dst[i / 2] = c; | ||
79 | } | ||
80 | |||
81 | return err & 0xf0; | ||
82 | } | ||
83 | |||
84 | void cx25840_vbi_setup(struct i2c_client *client) | ||
85 | { | ||
86 | v4l2_std_id std = cx25840_get_v4lstd(client); | ||
87 | |||
88 | if (std & ~V4L2_STD_NTSC) { | ||
89 | /* datasheet startup, step 8d */ | ||
90 | cx25840_write(client, 0x49f, 0x11); | ||
91 | |||
92 | cx25840_write(client, 0x470, 0x84); | ||
93 | cx25840_write(client, 0x471, 0x00); | ||
94 | cx25840_write(client, 0x472, 0x2d); | ||
95 | cx25840_write(client, 0x473, 0x5d); | ||
96 | |||
97 | cx25840_write(client, 0x474, 0x24); | ||
98 | cx25840_write(client, 0x475, 0x40); | ||
99 | cx25840_write(client, 0x476, 0x24); | ||
100 | cx25840_write(client, 0x477, 0x28); | ||
101 | |||
102 | cx25840_write(client, 0x478, 0x1f); | ||
103 | cx25840_write(client, 0x479, 0x02); | ||
104 | |||
105 | if (std & V4L2_STD_SECAM) { | ||
106 | cx25840_write(client, 0x47a, 0x80); | ||
107 | cx25840_write(client, 0x47b, 0x00); | ||
108 | cx25840_write(client, 0x47c, 0x5f); | ||
109 | cx25840_write(client, 0x47d, 0x42); | ||
110 | } else { | ||
111 | cx25840_write(client, 0x47a, 0x90); | ||
112 | cx25840_write(client, 0x47b, 0x20); | ||
113 | cx25840_write(client, 0x47c, 0x63); | ||
114 | cx25840_write(client, 0x47d, 0x82); | ||
115 | } | ||
116 | |||
117 | cx25840_write(client, 0x47e, 0x0a); | ||
118 | cx25840_write(client, 0x47f, 0x01); | ||
119 | } else { | ||
120 | /* datasheet startup, step 8d */ | ||
121 | cx25840_write(client, 0x49f, 0x14); | ||
122 | |||
123 | cx25840_write(client, 0x470, 0x7a); | ||
124 | cx25840_write(client, 0x471, 0x00); | ||
125 | cx25840_write(client, 0x472, 0x2d); | ||
126 | cx25840_write(client, 0x473, 0x5b); | ||
127 | |||
128 | cx25840_write(client, 0x474, 0x1a); | ||
129 | cx25840_write(client, 0x475, 0x70); | ||
130 | cx25840_write(client, 0x476, 0x1e); | ||
131 | cx25840_write(client, 0x477, 0x1e); | ||
132 | |||
133 | cx25840_write(client, 0x478, 0x1f); | ||
134 | cx25840_write(client, 0x479, 0x02); | ||
135 | cx25840_write(client, 0x47a, 0x50); | ||
136 | cx25840_write(client, 0x47b, 0x66); | ||
137 | |||
138 | cx25840_write(client, 0x47c, 0x1f); | ||
139 | cx25840_write(client, 0x47d, 0x7c); | ||
140 | cx25840_write(client, 0x47e, 0x08); | ||
141 | cx25840_write(client, 0x47f, 0x00); | ||
142 | } | ||
143 | } | ||
144 | |||
145 | int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) | ||
146 | { | ||
147 | struct v4l2_format *fmt; | ||
148 | struct v4l2_sliced_vbi_format *svbi; | ||
149 | |||
150 | switch (cmd) { | ||
151 | case VIDIOC_G_FMT: | ||
152 | { | ||
153 | static u16 lcr2vbi[] = { | ||
154 | 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ | ||
155 | 0, V4L2_SLICED_WSS_625, 0, /* 4 */ | ||
156 | V4L2_SLICED_CAPTION_525, /* 6 */ | ||
157 | 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */ | ||
158 | 0, 0, 0, 0 | ||
159 | }; | ||
160 | int i; | ||
161 | |||
162 | fmt = arg; | ||
163 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) | ||
164 | return -EINVAL; | ||
165 | svbi = &fmt->fmt.sliced; | ||
166 | memset(svbi, 0, sizeof(*svbi)); | ||
167 | /* we're done if raw VBI is active */ | ||
168 | if ((cx25840_read(client, 0x404) & 0x10) == 0) | ||
169 | break; | ||
170 | |||
171 | for (i = 7; i <= 23; i++) { | ||
172 | u8 v = cx25840_read(client, 0x424 + i - 7); | ||
173 | |||
174 | svbi->service_lines[0][i] = lcr2vbi[v >> 4]; | ||
175 | svbi->service_lines[1][i] = lcr2vbi[v & 0xf]; | ||
176 | svbi->service_set |= | ||
177 | svbi->service_lines[0][i] | svbi->service_lines[1][i]; | ||
178 | } | ||
179 | break; | ||
180 | } | ||
181 | |||
182 | case VIDIOC_S_FMT: | ||
183 | { | ||
184 | int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_NTSC); | ||
185 | int vbi_offset = is_pal ? 1 : 0; | ||
186 | int i, x; | ||
187 | u8 lcr[24]; | ||
188 | |||
189 | fmt = arg; | ||
190 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) | ||
191 | return -EINVAL; | ||
192 | svbi = &fmt->fmt.sliced; | ||
193 | if (svbi->service_set == 0) { | ||
194 | /* raw VBI */ | ||
195 | memset(svbi, 0, sizeof(*svbi)); | ||
196 | |||
197 | /* Setup VBI */ | ||
198 | cx25840_vbi_setup(client); | ||
199 | |||
200 | /* VBI Offset */ | ||
201 | cx25840_write(client, 0x47f, vbi_offset); | ||
202 | cx25840_write(client, 0x404, 0x2e); | ||
203 | break; | ||
204 | } | ||
205 | |||
206 | for (x = 0; x <= 23; x++) | ||
207 | lcr[x] = 0x00; | ||
208 | |||
209 | /* Setup VBI */ | ||
210 | cx25840_vbi_setup(client); | ||
211 | |||
212 | /* Sliced VBI */ | ||
213 | cx25840_write(client, 0x404, 0x36); /* Ancillery data */ | ||
214 | cx25840_write(client, 0x406, 0x13); | ||
215 | cx25840_write(client, 0x47f, vbi_offset); | ||
216 | |||
217 | if (is_pal) { | ||
218 | for (i = 0; i <= 6; i++) | ||
219 | svbi->service_lines[0][i] = | ||
220 | svbi->service_lines[1][i] = 0; | ||
221 | } else { | ||
222 | for (i = 0; i <= 9; i++) | ||
223 | svbi->service_lines[0][i] = | ||
224 | svbi->service_lines[1][i] = 0; | ||
225 | |||
226 | for (i = 22; i <= 23; i++) | ||
227 | svbi->service_lines[0][i] = | ||
228 | svbi->service_lines[1][i] = 0; | ||
229 | } | ||
230 | |||
231 | for (i = 7; i <= 23; i++) { | ||
232 | for (x = 0; x <= 1; x++) { | ||
233 | switch (svbi->service_lines[1-x][i]) { | ||
234 | case V4L2_SLICED_TELETEXT_B: | ||
235 | lcr[i] |= 1 << (4 * x); | ||
236 | break; | ||
237 | case V4L2_SLICED_WSS_625: | ||
238 | lcr[i] |= 4 << (4 * x); | ||
239 | break; | ||
240 | case V4L2_SLICED_CAPTION_525: | ||
241 | lcr[i] |= 6 << (4 * x); | ||
242 | break; | ||
243 | case V4L2_SLICED_VPS: | ||
244 | lcr[i] |= 9 << (4 * x); | ||
245 | break; | ||
246 | } | ||
247 | } | ||
248 | } | ||
249 | |||
250 | for (x = 1, i = 0x424; i <= 0x434; i++, x++) { | ||
251 | cx25840_write(client, i, lcr[6 + x]); | ||
252 | } | ||
253 | |||
254 | cx25840_write(client, 0x43c, 0x16); | ||
255 | |||
256 | if (is_pal) { | ||
257 | cx25840_write(client, 0x474, 0x2a); | ||
258 | } else { | ||
259 | cx25840_write(client, 0x474, 0x1a + 6); | ||
260 | } | ||
261 | break; | ||
262 | } | ||
263 | |||
264 | case VIDIOC_INT_DECODE_VBI_LINE: | ||
265 | { | ||
266 | struct v4l2_decode_vbi_line *vbi = arg; | ||
267 | u8 *p = vbi->p; | ||
268 | int id1, id2, l, err = 0; | ||
269 | |||
270 | if (p[0] || p[1] != 0xff || p[2] != 0xff || | ||
271 | (p[3] != 0x55 && p[3] != 0x91)) { | ||
272 | vbi->line = vbi->type = 0; | ||
273 | break; | ||
274 | } | ||
275 | |||
276 | p += 4; | ||
277 | id1 = p[-1]; | ||
278 | id2 = p[0] & 0xf; | ||
279 | l = p[2] & 0x3f; | ||
280 | l += 5; | ||
281 | p += 4; | ||
282 | |||
283 | switch (id2) { | ||
284 | case 1: | ||
285 | id2 = V4L2_SLICED_TELETEXT_B; | ||
286 | break; | ||
287 | case 4: | ||
288 | id2 = V4L2_SLICED_WSS_625; | ||
289 | break; | ||
290 | case 6: | ||
291 | id2 = V4L2_SLICED_CAPTION_525; | ||
292 | err = !odd_parity(p[0]) || !odd_parity(p[1]); | ||
293 | break; | ||
294 | case 9: | ||
295 | id2 = V4L2_SLICED_VPS; | ||
296 | if (decode_vps(p, p) != 0) { | ||
297 | err = 1; | ||
298 | } | ||
299 | break; | ||
300 | default: | ||
301 | id2 = 0; | ||
302 | err = 1; | ||
303 | break; | ||
304 | } | ||
305 | |||
306 | vbi->type = err ? 0 : id2; | ||
307 | vbi->line = err ? 0 : l; | ||
308 | vbi->is_second_field = err ? 0 : (id1 == 0x55); | ||
309 | vbi->p = p; | ||
310 | break; | ||
311 | } | ||
312 | } | ||
313 | |||
314 | return 0; | ||
315 | } | ||
diff --git a/drivers/media/video/cx25840/cx25840.h b/drivers/media/video/cx25840/cx25840.h new file mode 100644 index 000000000000..5c3f0639fb77 --- /dev/null +++ b/drivers/media/video/cx25840/cx25840.h | |||
@@ -0,0 +1,85 @@ | |||
1 | /* cx25840 API header | ||
2 | * | ||
3 | * Copyright (C) 2003-2004 Chris Kennedy | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License | ||
7 | * as published by the Free Software Foundation; either version 2 | ||
8 | * of the License, or (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
18 | */ | ||
19 | |||
20 | #ifndef _CX25840_H_ | ||
21 | #define _CX25840_H_ | ||
22 | |||
23 | |||
24 | #include <linux/videodev2.h> | ||
25 | #include <linux/i2c.h> | ||
26 | |||
27 | extern int cx25840_debug; | ||
28 | |||
29 | #define cx25840_dbg(fmt, arg...) do { if (cx25840_debug) \ | ||
30 | printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \ | ||
31 | i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) | ||
32 | |||
33 | #define cx25840_err(fmt, arg...) do { \ | ||
34 | printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \ | ||
35 | i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) | ||
36 | |||
37 | #define cx25840_info(fmt, arg...) do { \ | ||
38 | printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \ | ||
39 | i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) | ||
40 | |||
41 | #define CX25840_CID_CARDTYPE (V4L2_CID_PRIVATE_BASE+0) | ||
42 | |||
43 | enum cx25840_cardtype { | ||
44 | CARDTYPE_PVR150, | ||
45 | CARDTYPE_PG600 | ||
46 | }; | ||
47 | |||
48 | enum cx25840_input { | ||
49 | CX25840_TUNER, | ||
50 | CX25840_COMPOSITE0, | ||
51 | CX25840_COMPOSITE1, | ||
52 | CX25840_SVIDEO0, | ||
53 | CX25840_SVIDEO1 | ||
54 | }; | ||
55 | |||
56 | struct cx25840_state { | ||
57 | enum cx25840_cardtype cardtype; | ||
58 | enum cx25840_input input; | ||
59 | int audio_input; | ||
60 | enum v4l2_audio_clock_freq audclk_freq; | ||
61 | }; | ||
62 | |||
63 | /* ----------------------------------------------------------------------- */ | ||
64 | /* cx25850-core.c */ | ||
65 | int cx25840_write(struct i2c_client *client, u16 addr, u8 value); | ||
66 | int cx25840_write4(struct i2c_client *client, u16 addr, u32 value); | ||
67 | u8 cx25840_read(struct i2c_client *client, u16 addr); | ||
68 | u32 cx25840_read4(struct i2c_client *client, u16 addr); | ||
69 | int cx25840_and_or(struct i2c_client *client, u16 addr, u8 mask, u8 value); | ||
70 | v4l2_std_id cx25840_get_v4lstd(struct i2c_client *client); | ||
71 | |||
72 | /* ----------------------------------------------------------------------- */ | ||
73 | /* cx25850-firmware.c */ | ||
74 | int cx25840_loadfw(struct i2c_client *client); | ||
75 | |||
76 | /* ----------------------------------------------------------------------- */ | ||
77 | /* cx25850-audio.c */ | ||
78 | int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg); | ||
79 | |||
80 | /* ----------------------------------------------------------------------- */ | ||
81 | /* cx25850-vbi.c */ | ||
82 | void cx25840_vbi_setup(struct i2c_client *client); | ||
83 | int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg); | ||
84 | |||
85 | #endif | ||
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 9cce91ec334b..99ea955f5987 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
@@ -439,9 +439,6 @@ static int dvb_register(struct cx8802_dev *dev) | |||
439 | /* Put the analog decoder in standby to keep it quiet */ | 439 | /* Put the analog decoder in standby to keep it quiet */ |
440 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | 440 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); |
441 | 441 | ||
442 | /* Put the analog decoder in standby to keep it quiet */ | ||
443 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | ||
444 | |||
445 | /* register everything */ | 442 | /* register everything */ |
446 | return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev); | 443 | return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev); |
447 | } | 444 | } |
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 32c49df58adc..9b94f77d6fd7 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c | |||
@@ -120,9 +120,6 @@ static int get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | |||
120 | if (buf[1]==0xff) | 120 | if (buf[1]==0xff) |
121 | return 0; | 121 | return 0; |
122 | 122 | ||
123 | /* avoid fast reapeating */ | ||
124 | if (buf[1]==ir->old) | ||
125 | return 0; | ||
126 | ir->old=buf[1]; | 123 | ir->old=buf[1]; |
127 | 124 | ||
128 | /* Rearranges bits to the right order */ | 125 | /* Rearranges bits to the right order */ |
diff --git a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/ir-kbd-gpio.c index ed81934ef3cd..5abfc0fbf6de 100644 --- a/drivers/media/video/ir-kbd-gpio.c +++ b/drivers/media/video/ir-kbd-gpio.c | |||
@@ -221,24 +221,99 @@ static IR_KEYTAB_TYPE ir_codes_conceptronic[IR_KEYTAB_SIZE] = { | |||
221 | [ 24 ] = KEY_MUTE // mute/unmute | 221 | [ 24 ] = KEY_MUTE // mute/unmute |
222 | }; | 222 | }; |
223 | 223 | ||
224 | static IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE] = { | ||
225 | [0x00] = KEY_KP0, | ||
226 | [0x01] = KEY_KP1, | ||
227 | [0x02] = KEY_KP2, | ||
228 | [0x03] = KEY_KP3, | ||
229 | [0x04] = KEY_KP4, | ||
230 | [0x05] = KEY_KP5, | ||
231 | [0x06] = KEY_KP6, | ||
232 | [0x07] = KEY_KP7, | ||
233 | [0x08] = KEY_KP8, | ||
234 | [0x09] = KEY_KP9, | ||
235 | [0x0a] = KEY_TV, | ||
236 | [0x0b] = KEY_AUX, | ||
237 | [0x0c] = KEY_DVD, | ||
238 | [0x0d] = KEY_POWER, | ||
239 | [0x0e] = KEY_MHP, /* labelled 'Picture' */ | ||
240 | [0x0f] = KEY_AUDIO, | ||
241 | [0x10] = KEY_INFO, | ||
242 | [0x11] = KEY_F13, /* 16:9 */ | ||
243 | [0x12] = KEY_F14, /* 14:9 */ | ||
244 | [0x13] = KEY_EPG, | ||
245 | [0x14] = KEY_EXIT, | ||
246 | [0x15] = KEY_MENU, | ||
247 | [0x16] = KEY_UP, | ||
248 | [0x17] = KEY_DOWN, | ||
249 | [0x18] = KEY_LEFT, | ||
250 | [0x19] = KEY_RIGHT, | ||
251 | [0x1a] = KEY_ENTER, | ||
252 | [0x1b] = KEY_CHANNELUP, | ||
253 | [0x1c] = KEY_CHANNELDOWN, | ||
254 | [0x1d] = KEY_VOLUMEUP, | ||
255 | [0x1e] = KEY_VOLUMEDOWN, | ||
256 | [0x1f] = KEY_RED, | ||
257 | [0x20] = KEY_GREEN, | ||
258 | [0x21] = KEY_YELLOW, | ||
259 | [0x22] = KEY_BLUE, | ||
260 | [0x23] = KEY_SUBTITLE, | ||
261 | [0x24] = KEY_F15, /* AD */ | ||
262 | [0x25] = KEY_TEXT, | ||
263 | [0x26] = KEY_MUTE, | ||
264 | [0x27] = KEY_REWIND, | ||
265 | [0x28] = KEY_STOP, | ||
266 | [0x29] = KEY_PLAY, | ||
267 | [0x2a] = KEY_FASTFORWARD, | ||
268 | [0x2b] = KEY_F16, /* chapter */ | ||
269 | [0x2c] = KEY_PAUSE, | ||
270 | [0x2d] = KEY_PLAY, | ||
271 | [0x2e] = KEY_RECORD, | ||
272 | [0x2f] = KEY_F17, /* picture in picture */ | ||
273 | [0x30] = KEY_KPPLUS, /* zoom in */ | ||
274 | [0x31] = KEY_KPMINUS, /* zoom out */ | ||
275 | [0x32] = KEY_F18, /* capture */ | ||
276 | [0x33] = KEY_F19, /* web */ | ||
277 | [0x34] = KEY_EMAIL, | ||
278 | [0x35] = KEY_PHONE, | ||
279 | [0x36] = KEY_PC | ||
280 | }; | ||
281 | |||
224 | struct IR { | 282 | struct IR { |
225 | struct bttv_sub_device *sub; | 283 | struct bttv_sub_device *sub; |
226 | struct input_dev *input; | 284 | struct input_dev *input; |
227 | struct ir_input_state ir; | 285 | struct ir_input_state ir; |
228 | char name[32]; | 286 | char name[32]; |
229 | char phys[32]; | 287 | char phys[32]; |
288 | |||
289 | /* Usual gpio signalling */ | ||
290 | |||
230 | u32 mask_keycode; | 291 | u32 mask_keycode; |
231 | u32 mask_keydown; | 292 | u32 mask_keydown; |
232 | u32 mask_keyup; | 293 | u32 mask_keyup; |
233 | 294 | u32 polling; | |
234 | int polling; | ||
235 | u32 last_gpio; | 295 | u32 last_gpio; |
236 | struct work_struct work; | 296 | struct work_struct work; |
237 | struct timer_list timer; | 297 | struct timer_list timer; |
298 | |||
299 | /* RC5 gpio */ | ||
300 | |||
301 | u32 rc5_gpio; | ||
302 | struct timer_list timer_end; /* timer_end for code completion */ | ||
303 | struct timer_list timer_keyup; /* timer_end for key release */ | ||
304 | u32 last_rc5; /* last good rc5 code */ | ||
305 | u32 last_bit; /* last raw bit seen */ | ||
306 | u32 code; /* raw code under construction */ | ||
307 | struct timeval base_time; /* time of last seen code */ | ||
308 | int active; /* building raw code */ | ||
238 | }; | 309 | }; |
239 | 310 | ||
240 | static int debug; | 311 | static int debug; |
241 | module_param(debug, int, 0644); /* debug level (0,1,2) */ | 312 | module_param(debug, int, 0644); /* debug level (0,1,2) */ |
313 | static int repeat_delay = 500; | ||
314 | module_param(repeat_delay, int, 0644); | ||
315 | static int repeat_period = 33; | ||
316 | module_param(repeat_period, int, 0644); | ||
242 | 317 | ||
243 | #define DEVNAME "ir-kbd-gpio" | 318 | #define DEVNAME "ir-kbd-gpio" |
244 | #define dprintk(fmt, arg...) if (debug) \ | 319 | #define dprintk(fmt, arg...) if (debug) \ |
@@ -254,7 +329,7 @@ static struct bttv_sub_driver driver = { | |||
254 | .probe = ir_probe, | 329 | .probe = ir_probe, |
255 | .remove = ir_remove, | 330 | .remove = ir_remove, |
256 | }, | 331 | }, |
257 | .gpio_irq = ir_irq, | 332 | .gpio_irq = ir_irq, |
258 | }; | 333 | }; |
259 | 334 | ||
260 | /* ---------------------------------------------------------------------- */ | 335 | /* ---------------------------------------------------------------------- */ |
@@ -327,6 +402,173 @@ static void ir_work(void *data) | |||
327 | mod_timer(&ir->timer, timeout); | 402 | mod_timer(&ir->timer, timeout); |
328 | } | 403 | } |
329 | 404 | ||
405 | /* ---------------------------------------------------------------*/ | ||
406 | |||
407 | static int rc5_remote_gap = 885; | ||
408 | module_param(rc5_remote_gap, int, 0644); | ||
409 | static int rc5_key_timeout = 200; | ||
410 | module_param(rc5_key_timeout, int, 0644); | ||
411 | |||
412 | #define RC5_START(x) (((x)>>12)&3) | ||
413 | #define RC5_TOGGLE(x) (((x)>>11)&1) | ||
414 | #define RC5_ADDR(x) (((x)>>6)&31) | ||
415 | #define RC5_INSTR(x) ((x)&63) | ||
416 | |||
417 | /* decode raw bit pattern to RC5 code */ | ||
418 | static u32 rc5_decode(unsigned int code) | ||
419 | { | ||
420 | unsigned int org_code = code; | ||
421 | unsigned int pair; | ||
422 | unsigned int rc5 = 0; | ||
423 | int i; | ||
424 | |||
425 | code = (code << 1) | 1; | ||
426 | for (i = 0; i < 14; ++i) { | ||
427 | pair = code & 0x3; | ||
428 | code >>= 2; | ||
429 | |||
430 | rc5 <<= 1; | ||
431 | switch (pair) { | ||
432 | case 0: | ||
433 | case 2: | ||
434 | break; | ||
435 | case 1: | ||
436 | rc5 |= 1; | ||
437 | break; | ||
438 | case 3: | ||
439 | dprintk("bad code: %x\n", org_code); | ||
440 | return 0; | ||
441 | } | ||
442 | } | ||
443 | dprintk("code=%x, rc5=%x, start=%x, toggle=%x, address=%x, " | ||
444 | "instr=%x\n", rc5, org_code, RC5_START(rc5), | ||
445 | RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5)); | ||
446 | return rc5; | ||
447 | } | ||
448 | |||
449 | static int ir_rc5_irq(struct bttv_sub_device *sub) | ||
450 | { | ||
451 | struct IR *ir = dev_get_drvdata(&sub->dev); | ||
452 | struct timeval tv; | ||
453 | u32 gpio; | ||
454 | u32 gap; | ||
455 | unsigned long current_jiffies, timeout; | ||
456 | |||
457 | /* read gpio port */ | ||
458 | gpio = bttv_gpio_read(ir->sub->core); | ||
459 | |||
460 | /* remote IRQ? */ | ||
461 | if (!(gpio & 0x20)) | ||
462 | return 0; | ||
463 | |||
464 | /* get time of bit */ | ||
465 | current_jiffies = jiffies; | ||
466 | do_gettimeofday(&tv); | ||
467 | |||
468 | /* avoid overflow with gap >1s */ | ||
469 | if (tv.tv_sec - ir->base_time.tv_sec > 1) { | ||
470 | gap = 200000; | ||
471 | } else { | ||
472 | gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + | ||
473 | tv.tv_usec - ir->base_time.tv_usec; | ||
474 | } | ||
475 | |||
476 | /* active code => add bit */ | ||
477 | if (ir->active) { | ||
478 | /* only if in the code (otherwise spurious IRQ or timer | ||
479 | late) */ | ||
480 | if (ir->last_bit < 28) { | ||
481 | ir->last_bit = (gap - rc5_remote_gap / 2) / | ||
482 | rc5_remote_gap; | ||
483 | ir->code |= 1 << ir->last_bit; | ||
484 | } | ||
485 | /* starting new code */ | ||
486 | } else { | ||
487 | ir->active = 1; | ||
488 | ir->code = 0; | ||
489 | ir->base_time = tv; | ||
490 | ir->last_bit = 0; | ||
491 | |||
492 | timeout = current_jiffies + (500 + 30 * HZ) / 1000; | ||
493 | mod_timer(&ir->timer_end, timeout); | ||
494 | } | ||
495 | |||
496 | /* toggle GPIO pin 4 to reset the irq */ | ||
497 | bttv_gpio_write(ir->sub->core, gpio & ~(1 << 4)); | ||
498 | bttv_gpio_write(ir->sub->core, gpio | (1 << 4)); | ||
499 | return 1; | ||
500 | } | ||
501 | |||
502 | static void ir_rc5_timer_end(unsigned long data) | ||
503 | { | ||
504 | struct IR *ir = (struct IR *)data; | ||
505 | struct timeval tv; | ||
506 | unsigned long current_jiffies, timeout; | ||
507 | u32 gap; | ||
508 | |||
509 | /* get time */ | ||
510 | current_jiffies = jiffies; | ||
511 | do_gettimeofday(&tv); | ||
512 | |||
513 | /* avoid overflow with gap >1s */ | ||
514 | if (tv.tv_sec - ir->base_time.tv_sec > 1) { | ||
515 | gap = 200000; | ||
516 | } else { | ||
517 | gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + | ||
518 | tv.tv_usec - ir->base_time.tv_usec; | ||
519 | } | ||
520 | |||
521 | /* Allow some timmer jitter (RC5 is ~24ms anyway so this is ok) */ | ||
522 | if (gap < 28000) { | ||
523 | dprintk("spurious timer_end\n"); | ||
524 | return; | ||
525 | } | ||
526 | |||
527 | ir->active = 0; | ||
528 | if (ir->last_bit < 20) { | ||
529 | /* ignore spurious codes (caused by light/other remotes) */ | ||
530 | dprintk("short code: %x\n", ir->code); | ||
531 | } else { | ||
532 | u32 rc5 = rc5_decode(ir->code); | ||
533 | |||
534 | /* two start bits? */ | ||
535 | if (RC5_START(rc5) != 3) { | ||
536 | dprintk("rc5 start bits invalid: %u\n", RC5_START(rc5)); | ||
537 | |||
538 | /* right address? */ | ||
539 | } else if (RC5_ADDR(rc5) == 0x0) { | ||
540 | u32 toggle = RC5_TOGGLE(rc5); | ||
541 | u32 instr = RC5_INSTR(rc5); | ||
542 | |||
543 | /* Good code, decide if repeat/repress */ | ||
544 | if (toggle != RC5_TOGGLE(ir->last_rc5) || | ||
545 | instr != RC5_INSTR(ir->last_rc5)) { | ||
546 | dprintk("instruction %x, toggle %x\n", instr, | ||
547 | toggle); | ||
548 | ir_input_nokey(ir->input, &ir->ir); | ||
549 | ir_input_keydown(ir->input, &ir->ir, instr, | ||
550 | instr); | ||
551 | } | ||
552 | |||
553 | /* Set/reset key-up timer */ | ||
554 | timeout = current_jiffies + (500 + rc5_key_timeout | ||
555 | * HZ) / 1000; | ||
556 | mod_timer(&ir->timer_keyup, timeout); | ||
557 | |||
558 | /* Save code for repeat test */ | ||
559 | ir->last_rc5 = rc5; | ||
560 | } | ||
561 | } | ||
562 | } | ||
563 | |||
564 | static void ir_rc5_timer_keyup(unsigned long data) | ||
565 | { | ||
566 | struct IR *ir = (struct IR *)data; | ||
567 | |||
568 | dprintk("key released\n"); | ||
569 | ir_input_nokey(ir->input, &ir->ir); | ||
570 | } | ||
571 | |||
330 | /* ---------------------------------------------------------------------- */ | 572 | /* ---------------------------------------------------------------------- */ |
331 | 573 | ||
332 | static int ir_probe(struct device *dev) | 574 | static int ir_probe(struct device *dev) |
@@ -400,6 +642,12 @@ static int ir_probe(struct device *dev) | |||
400 | ir->mask_keyup = 0x006000; | 642 | ir->mask_keyup = 0x006000; |
401 | ir->polling = 50; // ms | 643 | ir->polling = 50; // ms |
402 | break; | 644 | break; |
645 | case BTTV_BOARD_NEBULA_DIGITV: | ||
646 | ir_codes = ir_codes_nebula; | ||
647 | driver.any_irq = ir_rc5_irq; | ||
648 | driver.gpio_irq = NULL; | ||
649 | ir->rc5_gpio = 1; | ||
650 | break; | ||
403 | } | 651 | } |
404 | if (NULL == ir_codes) { | 652 | if (NULL == ir_codes) { |
405 | kfree(ir); | 653 | kfree(ir); |
@@ -407,9 +655,17 @@ static int ir_probe(struct device *dev) | |||
407 | return -ENODEV; | 655 | return -ENODEV; |
408 | } | 656 | } |
409 | 657 | ||
410 | /* init hardware-specific stuff */ | 658 | if (ir->rc5_gpio) { |
411 | bttv_gpio_inout(sub->core, ir->mask_keycode | ir->mask_keydown, 0); | 659 | u32 gpio; |
412 | ir->sub = sub; | 660 | /* enable remote irq */ |
661 | bttv_gpio_inout(sub->core, (1 << 4), 1 << 4); | ||
662 | gpio = bttv_gpio_read(sub->core); | ||
663 | bttv_gpio_write(sub->core, gpio & ~(1 << 4)); | ||
664 | bttv_gpio_write(sub->core, gpio | (1 << 4)); | ||
665 | } else { | ||
666 | /* init hardware-specific stuff */ | ||
667 | bttv_gpio_inout(sub->core, ir->mask_keycode | ir->mask_keydown, 0); | ||
668 | } | ||
413 | 669 | ||
414 | /* init input device */ | 670 | /* init input device */ |
415 | snprintf(ir->name, sizeof(ir->name), "bttv IR (card=%d)", | 671 | snprintf(ir->name, sizeof(ir->name), "bttv IR (card=%d)", |
@@ -417,6 +673,7 @@ static int ir_probe(struct device *dev) | |||
417 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", | 673 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", |
418 | pci_name(sub->core->pci)); | 674 | pci_name(sub->core->pci)); |
419 | 675 | ||
676 | ir->sub = sub; | ||
420 | ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); | 677 | ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); |
421 | input_dev->name = ir->name; | 678 | input_dev->name = ir->name; |
422 | input_dev->phys = ir->phys; | 679 | input_dev->phys = ir->phys; |
@@ -437,11 +694,25 @@ static int ir_probe(struct device *dev) | |||
437 | ir->timer.function = ir_timer; | 694 | ir->timer.function = ir_timer; |
438 | ir->timer.data = (unsigned long)ir; | 695 | ir->timer.data = (unsigned long)ir; |
439 | schedule_work(&ir->work); | 696 | schedule_work(&ir->work); |
697 | } else if (ir->rc5_gpio) { | ||
698 | /* set timer_end for code completion */ | ||
699 | init_timer(&ir->timer_end); | ||
700 | ir->timer_end.function = ir_rc5_timer_end; | ||
701 | ir->timer_end.data = (unsigned long)ir; | ||
702 | |||
703 | init_timer(&ir->timer_keyup); | ||
704 | ir->timer_keyup.function = ir_rc5_timer_keyup; | ||
705 | ir->timer_keyup.data = (unsigned long)ir; | ||
440 | } | 706 | } |
441 | 707 | ||
442 | /* all done */ | 708 | /* all done */ |
443 | dev_set_drvdata(dev, ir); | 709 | dev_set_drvdata(dev, ir); |
444 | input_register_device(ir->input); | 710 | input_register_device(ir->input); |
711 | printk(DEVNAME ": %s detected at %s\n",ir->name,ir->phys); | ||
712 | |||
713 | /* the remote isn't as bouncy as a keyboard */ | ||
714 | ir->input->rep[REP_DELAY] = repeat_delay; | ||
715 | ir->input->rep[REP_PERIOD] = repeat_period; | ||
445 | 716 | ||
446 | return 0; | 717 | return 0; |
447 | } | 718 | } |
@@ -454,6 +725,15 @@ static int ir_remove(struct device *dev) | |||
454 | del_timer(&ir->timer); | 725 | del_timer(&ir->timer); |
455 | flush_scheduled_work(); | 726 | flush_scheduled_work(); |
456 | } | 727 | } |
728 | if (ir->rc5_gpio) { | ||
729 | u32 gpio; | ||
730 | |||
731 | del_timer(&ir->timer_end); | ||
732 | flush_scheduled_work(); | ||
733 | |||
734 | gpio = bttv_gpio_read(ir->sub->core); | ||
735 | bttv_gpio_write(ir->sub->core, gpio & ~(1 << 4)); | ||
736 | } | ||
457 | 737 | ||
458 | input_unregister_device(ir->input); | 738 | input_unregister_device(ir->input); |
459 | kfree(ir); | 739 | kfree(ir); |
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 0085567a1421..801c736e9328 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c | |||
@@ -183,6 +183,58 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | |||
183 | return 1; | 183 | return 1; |
184 | } | 184 | } |
185 | 185 | ||
186 | /* The new pinnacle PCTV remote (with the colored buttons) | ||
187 | * | ||
188 | * Ricardo Cerqueira <v4l@cerqueira.org> | ||
189 | */ | ||
190 | |||
191 | int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | ||
192 | { | ||
193 | unsigned char b[4]; | ||
194 | unsigned int start = 0,parity = 0,code = 0; | ||
195 | |||
196 | /* poll IR chip */ | ||
197 | if (4 != i2c_master_recv(&ir->c,b,4)) { | ||
198 | dprintk(2,"read error\n"); | ||
199 | return -EIO; | ||
200 | } | ||
201 | |||
202 | for (start = 0; start<4; start++) { | ||
203 | if (b[start] == 0x80) { | ||
204 | code=b[(start+3)%4]; | ||
205 | parity=b[(start+2)%4]; | ||
206 | } | ||
207 | } | ||
208 | |||
209 | /* Empty Request */ | ||
210 | if (parity==0) | ||
211 | return 0; | ||
212 | |||
213 | /* Repeating... */ | ||
214 | if (ir->old == parity) | ||
215 | return 0; | ||
216 | |||
217 | |||
218 | ir->old = parity; | ||
219 | |||
220 | /* Reduce code value to fit inside IR_KEYTAB_SIZE | ||
221 | * | ||
222 | * this is the only value that results in 42 unique | ||
223 | * codes < 128 | ||
224 | */ | ||
225 | |||
226 | code %= 0x88; | ||
227 | |||
228 | *ir_raw = code; | ||
229 | *ir_key = code; | ||
230 | |||
231 | dprintk(1,"Pinnacle PCTV key %02x\n", code); | ||
232 | |||
233 | return 1; | ||
234 | } | ||
235 | |||
236 | EXPORT_SYMBOL_GPL(get_key_pinnacle); | ||
237 | |||
186 | /* ----------------------------------------------------------------------- */ | 238 | /* ----------------------------------------------------------------------- */ |
187 | 239 | ||
188 | static void ir_key_poll(struct IR_i2c *ir) | 240 | static void ir_key_poll(struct IR_i2c *ir) |
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c new file mode 100644 index 000000000000..0235cef07b31 --- /dev/null +++ b/drivers/media/video/saa7115.c | |||
@@ -0,0 +1,1376 @@ | |||
1 | /* saa7115 - Philips SAA7114/SAA7115 video decoder driver | ||
2 | * | ||
3 | * Based on saa7114 driver by Maxim Yevtyushkin, which is based on | ||
4 | * the saa7111 driver by Dave Perks. | ||
5 | * | ||
6 | * Copyright (C) 1998 Dave Perks <dperks@ibm.net> | ||
7 | * Copyright (C) 2002 Maxim Yevtyushkin <max@linuxmedialabs.com> | ||
8 | * | ||
9 | * Slight changes for video timing and attachment output by | ||
10 | * Wolfgang Scherr <scherr@net4you.net> | ||
11 | * | ||
12 | * Moved over to the linux >= 2.4.x i2c protocol (1/1/2003) | ||
13 | * by Ronald Bultje <rbultje@ronald.bitfreak.net> | ||
14 | * | ||
15 | * Added saa7115 support by Kevin Thayer <nufan_wfk at yahoo.com> | ||
16 | * (2/17/2003) | ||
17 | * | ||
18 | * VBI support (2004) and cleanups (2005) by Hans Verkuil <hverkuil@xs4all.nl> | ||
19 | * | ||
20 | * This program is free software; you can redistribute it and/or | ||
21 | * modify it under the terms of the GNU General Public License | ||
22 | * as published by the Free Software Foundation; either version 2 | ||
23 | * of the License, or (at your option) any later version. | ||
24 | * | ||
25 | * This program is distributed in the hope that it will be useful, | ||
26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
28 | * GNU General Public License for more details. | ||
29 | * | ||
30 | * You should have received a copy of the GNU General Public License | ||
31 | * along with this program; if not, write to the Free Software | ||
32 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
33 | */ | ||
34 | |||
35 | |||
36 | #include <linux/kernel.h> | ||
37 | #include <linux/module.h> | ||
38 | #include <linux/slab.h> | ||
39 | #include <linux/i2c.h> | ||
40 | #include <linux/videodev2.h> | ||
41 | #include <media/v4l2-common.h> | ||
42 | |||
43 | MODULE_DESCRIPTION("Philips SAA7114/SAA7115 video decoder driver"); | ||
44 | MODULE_AUTHOR("Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, Hans Verkuil"); | ||
45 | MODULE_LICENSE("GPL"); | ||
46 | |||
47 | static int debug = 0; | ||
48 | module_param(debug, int, 0644); | ||
49 | |||
50 | MODULE_PARM_DESC(debug, "Debug level (0-1)"); | ||
51 | |||
52 | #define saa7115_dbg(fmt,arg...) \ | ||
53 | do { \ | ||
54 | if (debug) \ | ||
55 | printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \ | ||
56 | i2c_adapter_id(client->adapter), client->addr , ## arg); \ | ||
57 | } while (0) | ||
58 | |||
59 | #define saa7115_err(fmt, arg...) do { \ | ||
60 | printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \ | ||
61 | i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) | ||
62 | #define saa7115_info(fmt, arg...) do { \ | ||
63 | printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \ | ||
64 | i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) | ||
65 | |||
66 | static unsigned short normal_i2c[] = { 0x42 >> 1, 0x40 >> 1, I2C_CLIENT_END }; | ||
67 | |||
68 | |||
69 | I2C_CLIENT_INSMOD; | ||
70 | |||
71 | struct saa7115_state { | ||
72 | v4l2_std_id std; | ||
73 | int input; | ||
74 | int enable; | ||
75 | int bright; | ||
76 | int contrast; | ||
77 | int hue; | ||
78 | int sat; | ||
79 | enum v4l2_chip_ident ident; | ||
80 | enum v4l2_audio_clock_freq audclk_freq; | ||
81 | }; | ||
82 | |||
83 | /* ----------------------------------------------------------------------- */ | ||
84 | |||
85 | static inline int saa7115_write(struct i2c_client *client, u8 reg, u8 value) | ||
86 | { | ||
87 | return i2c_smbus_write_byte_data(client, reg, value); | ||
88 | } | ||
89 | |||
90 | static int saa7115_writeregs(struct i2c_client *client, const unsigned char *regs) | ||
91 | { | ||
92 | unsigned char reg, data; | ||
93 | |||
94 | while (*regs != 0x00) { | ||
95 | reg = *(regs++); | ||
96 | data = *(regs++); | ||
97 | if (saa7115_write(client, reg, data) < 0) | ||
98 | return -1; | ||
99 | } | ||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static inline int saa7115_read(struct i2c_client *client, u8 reg) | ||
104 | { | ||
105 | return i2c_smbus_read_byte_data(client, reg); | ||
106 | } | ||
107 | |||
108 | /* ----------------------------------------------------------------------- */ | ||
109 | |||
110 | /* If a value differs from the Hauppauge driver values, then the comment starts with | ||
111 | 'was 0xXX' to denote the Hauppauge value. Otherwise the value is identical to what the | ||
112 | Hauppauge driver sets. */ | ||
113 | |||
114 | static const unsigned char saa7115_init_auto_input[] = { | ||
115 | 0x01, 0x48, /* white peak control disabled */ | ||
116 | 0x03, 0x20, /* was 0x30. 0x20: long vertical blanking */ | ||
117 | 0x04, 0x90, /* analog gain set to 0 */ | ||
118 | 0x05, 0x90, /* analog gain set to 0 */ | ||
119 | 0x06, 0xeb, /* horiz sync begin = -21 */ | ||
120 | 0x07, 0xe0, /* horiz sync stop = -17 */ | ||
121 | 0x0a, 0x80, /* was 0x88. decoder brightness, 0x80 is itu standard */ | ||
122 | 0x0b, 0x44, /* was 0x48. decoder contrast, 0x44 is itu standard */ | ||
123 | 0x0c, 0x40, /* was 0x47. decoder saturation, 0x40 is itu standard */ | ||
124 | 0x0d, 0x00, /* chrominance hue control */ | ||
125 | 0x0f, 0x00, /* chrominance gain control: use automicatic mode */ | ||
126 | 0x10, 0x06, /* chrominance/luminance control: active adaptive combfilter */ | ||
127 | 0x11, 0x00, /* delay control */ | ||
128 | 0x12, 0x9d, /* RTS0 output control: VGATE */ | ||
129 | 0x13, 0x80, /* X-port output control: ITU656 standard mode, RTCO output enable RTCE */ | ||
130 | 0x14, 0x00, /* analog/ADC/auto compatibility control */ | ||
131 | 0x18, 0x40, /* raw data gain 0x00 = nominal */ | ||
132 | 0x19, 0x80, /* raw data offset 0x80 = 0 LSB */ | ||
133 | 0x1a, 0x77, /* color killer level control 0x77 = recommended */ | ||
134 | 0x1b, 0x42, /* misc chroma control 0x42 = recommended */ | ||
135 | 0x1c, 0xa9, /* combfilter control 0xA9 = recommended */ | ||
136 | 0x1d, 0x01, /* combfilter control 0x01 = recommended */ | ||
137 | 0x88, 0xd0, /* reset device */ | ||
138 | 0x88, 0xf0, /* set device programmed, all in operational mode */ | ||
139 | 0x00, 0x00 | ||
140 | }; | ||
141 | |||
142 | static const unsigned char saa7115_cfg_reset_scaler[] = { | ||
143 | 0x87, 0x00, /* disable I-port output */ | ||
144 | 0x88, 0xd0, /* reset scaler */ | ||
145 | 0x88, 0xf0, /* activate scaler */ | ||
146 | 0x87, 0x01, /* enable I-port output */ | ||
147 | 0x00, 0x00 | ||
148 | }; | ||
149 | |||
150 | /* ============== SAA7715 VIDEO templates ============= */ | ||
151 | |||
152 | static const unsigned char saa7115_cfg_60hz_fullres_x[] = { | ||
153 | 0xcc, 0xd0, /* hsize low (output), hor. output window size = 0x2d0 = 720 */ | ||
154 | 0xcd, 0x02, /* hsize hi (output) */ | ||
155 | |||
156 | /* Why not in 60hz-Land, too? */ | ||
157 | 0xd0, 0x01, /* downscale = 1 */ | ||
158 | 0xd8, 0x00, /* hor lum scaling 0x0400 = 1 */ | ||
159 | 0xd9, 0x04, | ||
160 | 0xdc, 0x00, /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */ | ||
161 | 0xdd, 0x02, /* H-scaling incr chroma */ | ||
162 | |||
163 | 0x00, 0x00 | ||
164 | }; | ||
165 | static const unsigned char saa7115_cfg_60hz_fullres_y[] = { | ||
166 | 0xce, 0xf8, /* vsize low (output), ver. output window size = 248 (but 60hz is 240?) */ | ||
167 | 0xcf, 0x00, /* vsize hi (output) */ | ||
168 | |||
169 | /* Why not in 60hz-Land, too? */ | ||
170 | 0xd5, 0x40, /* Lum contrast, nominal value = 0x40 */ | ||
171 | 0xd6, 0x40, /* Chroma satur. nominal value = 0x80 */ | ||
172 | |||
173 | 0xe0, 0x00, /* V-scaling incr luma low */ | ||
174 | 0xe1, 0x04, /* " hi */ | ||
175 | 0xe2, 0x00, /* V-scaling incr chroma low */ | ||
176 | 0xe3, 0x04, /* " hi */ | ||
177 | |||
178 | 0x00, 0x00 | ||
179 | }; | ||
180 | |||
181 | static const unsigned char saa7115_cfg_60hz_video[] = { | ||
182 | 0x80, 0x00, /* reset tasks */ | ||
183 | 0x88, 0xd0, /* reset scaler */ | ||
184 | |||
185 | 0x15, 0x03, /* VGATE pulse start */ | ||
186 | 0x16, 0x11, /* VGATE pulse stop */ | ||
187 | 0x17, 0x9c, /* VGATE MSB and other values */ | ||
188 | |||
189 | 0x08, 0x68, /* 0xBO: auto detection, 0x68 = NTSC */ | ||
190 | 0x0e, 0x07, /* lots of different stuff... video autodetection is on */ | ||
191 | |||
192 | 0x5a, 0x06, /* Vertical offset, standard 60hz value for ITU656 line counting */ | ||
193 | |||
194 | /* Task A */ | ||
195 | 0x90, 0x80, /* Task Handling Control */ | ||
196 | 0x91, 0x48, /* X-port formats/config */ | ||
197 | 0x92, 0x40, /* Input Ref. signal Def. */ | ||
198 | 0x93, 0x84, /* I-port config */ | ||
199 | 0x94, 0x01, /* hoffset low (input), 0x0002 is minimum */ | ||
200 | 0x95, 0x00, /* hoffset hi (input) */ | ||
201 | 0x96, 0xd0, /* hsize low (input), 0x02d0 = 720 */ | ||
202 | 0x97, 0x02, /* hsize hi (input) */ | ||
203 | 0x98, 0x05, /* voffset low (input) */ | ||
204 | 0x99, 0x00, /* voffset hi (input) */ | ||
205 | 0x9a, 0x0c, /* vsize low (input), 0x0c = 12 */ | ||
206 | 0x9b, 0x00, /* vsize hi (input) */ | ||
207 | 0x9c, 0xa0, /* hsize low (output), 0x05a0 = 1440 */ | ||
208 | 0x9d, 0x05, /* hsize hi (output) */ | ||
209 | 0x9e, 0x0c, /* vsize low (output), 0x0c = 12 */ | ||
210 | 0x9f, 0x00, /* vsize hi (output) */ | ||
211 | |||
212 | /* Task B */ | ||
213 | 0xc0, 0x00, /* Task Handling Control */ | ||
214 | 0xc1, 0x08, /* X-port formats/config */ | ||
215 | 0xc2, 0x00, /* Input Ref. signal Def. */ | ||
216 | 0xc3, 0x80, /* I-port config */ | ||
217 | 0xc4, 0x02, /* hoffset low (input), 0x0002 is minimum */ | ||
218 | 0xc5, 0x00, /* hoffset hi (input) */ | ||
219 | 0xc6, 0xd0, /* hsize low (input), 0x02d0 = 720 */ | ||
220 | 0xc7, 0x02, /* hsize hi (input) */ | ||
221 | 0xc8, 0x12, /* voffset low (input), 0x12 = 18 */ | ||
222 | 0xc9, 0x00, /* voffset hi (input) */ | ||
223 | 0xca, 0xf8, /* vsize low (input), 0xf8 = 248 */ | ||
224 | 0xcb, 0x00, /* vsize hi (input) */ | ||
225 | 0xcc, 0xd0, /* hsize low (output), 0x02d0 = 720 */ | ||
226 | 0xcd, 0x02, /* hsize hi (output) */ | ||
227 | |||
228 | 0xf0, 0xad, /* Set PLL Register. 60hz 525 lines per frame, 27 MHz */ | ||
229 | 0xf1, 0x05, /* low bit with 0xF0 */ | ||
230 | 0xf5, 0xad, /* Set pulse generator register */ | ||
231 | 0xf6, 0x01, | ||
232 | |||
233 | 0x87, 0x00, /* Disable I-port output */ | ||
234 | 0x88, 0xd0, /* reset scaler */ | ||
235 | 0x80, 0x20, /* Activate only task "B", continuous mode (was 0xA0) */ | ||
236 | 0x88, 0xf0, /* activate scaler */ | ||
237 | 0x87, 0x01, /* Enable I-port output */ | ||
238 | 0x00, 0x00 | ||
239 | }; | ||
240 | |||
241 | static const unsigned char saa7115_cfg_50hz_fullres_x[] = { | ||
242 | 0xcc, 0xd0, /* hsize low (output), 720 same as 60hz */ | ||
243 | 0xcd, 0x02, /* hsize hi (output) */ | ||
244 | |||
245 | 0xd0, 0x01, /* down scale = 1 */ | ||
246 | 0xd8, 0x00, /* hor lum scaling 0x0400 = 1 */ | ||
247 | 0xd9, 0x04, | ||
248 | 0xdc, 0x00, /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */ | ||
249 | 0xdd, 0x02, /* H-scaling incr chroma */ | ||
250 | |||
251 | 0x00, 0x00 | ||
252 | }; | ||
253 | static const unsigned char saa7115_cfg_50hz_fullres_y[] = { | ||
254 | 0xce, 0x20, /* vsize low (output), 0x0120 = 288 */ | ||
255 | 0xcf, 0x01, /* vsize hi (output) */ | ||
256 | |||
257 | 0xd5, 0x40, /* Lum contrast, nominal value = 0x40 */ | ||
258 | 0xd6, 0x40, /* Chroma satur. nominal value = 0x80 */ | ||
259 | |||
260 | 0xe0, 0x00, /* V-scaling incr luma low */ | ||
261 | 0xe1, 0x04, /* " hi */ | ||
262 | 0xe2, 0x00, /* V-scaling incr chroma low */ | ||
263 | 0xe3, 0x04, /* " hi */ | ||
264 | |||
265 | 0x00, 0x00 | ||
266 | }; | ||
267 | |||
268 | static const unsigned char saa7115_cfg_50hz_video[] = { | ||
269 | 0x80, 0x00, /* reset tasks */ | ||
270 | 0x88, 0xd0, /* reset scaler */ | ||
271 | |||
272 | 0x15, 0x37, /* VGATE start */ | ||
273 | 0x16, 0x16, /* VGATE stop */ | ||
274 | 0x17, 0x99, /* VGATE MSB and other values */ | ||
275 | |||
276 | 0x08, 0x28, /* 0x28 = PAL */ | ||
277 | 0x0e, 0x07, /* chrominance control 1 */ | ||
278 | |||
279 | 0x5a, 0x03, /* Vertical offset, standard 50hz value */ | ||
280 | |||
281 | /* Task A */ | ||
282 | 0x90, 0x81, /* Task Handling Control */ | ||
283 | 0x91, 0x48, /* X-port formats/config */ | ||
284 | 0x92, 0x40, /* Input Ref. signal Def. */ | ||
285 | 0x93, 0x84, /* I-port config */ | ||
286 | /* This is weird: the datasheet says that you should use 2 as the minimum value, */ | ||
287 | /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */ | ||
288 | 0x94, 0x00, /* hoffset low (input), 0x0002 is minimum */ | ||
289 | 0x95, 0x00, /* hoffset hi (input) */ | ||
290 | 0x96, 0xd0, /* hsize low (input), 0x02d0 = 720 */ | ||
291 | 0x97, 0x02, /* hsize hi (input) */ | ||
292 | 0x98, 0x03, /* voffset low (input) */ | ||
293 | 0x99, 0x00, /* voffset hi (input) */ | ||
294 | 0x9a, 0x12, /* vsize low (input), 0x12 = 18 */ | ||
295 | 0x9b, 0x00, /* vsize hi (input) */ | ||
296 | 0x9c, 0xa0, /* hsize low (output), 0x05a0 = 1440 */ | ||
297 | 0x9d, 0x05, /* hsize hi (output) */ | ||
298 | 0x9e, 0x12, /* vsize low (output), 0x12 = 18 */ | ||
299 | 0x9f, 0x00, /* vsize hi (output) */ | ||
300 | |||
301 | /* Task B */ | ||
302 | 0xc0, 0x00, /* Task Handling Control */ | ||
303 | 0xc1, 0x08, /* X-port formats/config */ | ||
304 | 0xc2, 0x00, /* Input Ref. signal Def. */ | ||
305 | 0xc3, 0x80, /* I-port config */ | ||
306 | 0xc4, 0x00, /* hoffset low (input), 0x0002 is minimum. See comment at 0x94 above. */ | ||
307 | 0xc5, 0x00, /* hoffset hi (input) */ | ||
308 | 0xc6, 0xd0, /* hsize low (input), 0x02d0 = 720 */ | ||
309 | 0xc7, 0x02, /* hsize hi (input) */ | ||
310 | 0xc8, 0x16, /* voffset low (input), 0x16 = 22 */ | ||
311 | 0xc9, 0x00, /* voffset hi (input) */ | ||
312 | 0xca, 0x20, /* vsize low (input), 0x0120 = 288 */ | ||
313 | 0xcb, 0x01, /* vsize hi (input) */ | ||
314 | 0xcc, 0xd0, /* hsize low (output), 0x02d0 = 720 */ | ||
315 | 0xcd, 0x02, /* hsize hi (output) */ | ||
316 | 0xce, 0x20, /* vsize low (output), 0x0120 = 288 */ | ||
317 | 0xcf, 0x01, /* vsize hi (output) */ | ||
318 | |||
319 | 0xf0, 0xb0, /* Set PLL Register. 50hz 625 lines per frame, 27 MHz */ | ||
320 | 0xf1, 0x05, /* low bit with 0xF0, (was 0x05) */ | ||
321 | 0xf5, 0xb0, /* Set pulse generator register */ | ||
322 | 0xf6, 0x01, | ||
323 | |||
324 | 0x87, 0x00, /* Disable I-port output */ | ||
325 | 0x88, 0xd0, /* reset scaler (was 0xD0) */ | ||
326 | 0x80, 0x20, /* Activate only task "B" */ | ||
327 | 0x88, 0xf0, /* activate scaler */ | ||
328 | 0x87, 0x01, /* Enable I-port output */ | ||
329 | 0x00, 0x00 | ||
330 | }; | ||
331 | |||
332 | /* ============== SAA7715 VIDEO templates (end) ======= */ | ||
333 | |||
334 | static const unsigned char saa7115_cfg_vbi_on[] = { | ||
335 | 0x80, 0x00, /* reset tasks */ | ||
336 | 0x88, 0xd0, /* reset scaler */ | ||
337 | 0x80, 0x30, /* Activate both tasks */ | ||
338 | 0x88, 0xf0, /* activate scaler */ | ||
339 | 0x87, 0x01, /* Enable I-port output */ | ||
340 | 0x00, 0x00 | ||
341 | }; | ||
342 | |||
343 | static const unsigned char saa7115_cfg_vbi_off[] = { | ||
344 | 0x80, 0x00, /* reset tasks */ | ||
345 | 0x88, 0xd0, /* reset scaler */ | ||
346 | 0x80, 0x20, /* Activate only task "B" */ | ||
347 | 0x88, 0xf0, /* activate scaler */ | ||
348 | 0x87, 0x01, /* Enable I-port output */ | ||
349 | 0x00, 0x00 | ||
350 | }; | ||
351 | |||
352 | static const unsigned char saa7115_init_misc[] = { | ||
353 | 0x38, 0x03, /* audio stuff */ | ||
354 | 0x39, 0x10, | ||
355 | 0x3a, 0x08, | ||
356 | |||
357 | 0x81, 0x01, /* reg 0x15,0x16 define blanking window */ | ||
358 | 0x82, 0x00, | ||
359 | 0x83, 0x01, /* I port settings */ | ||
360 | 0x84, 0x20, | ||
361 | 0x85, 0x21, | ||
362 | 0x86, 0xc5, | ||
363 | 0x87, 0x01, | ||
364 | |||
365 | /* Task A */ | ||
366 | 0xa0, 0x01, /* down scale = 1 */ | ||
367 | 0xa1, 0x00, /* prescale accumulation length = 1 */ | ||
368 | 0xa2, 0x00, /* dc gain and fir prefilter control */ | ||
369 | 0xa4, 0x80, /* Lum Brightness, nominal value = 0x80 */ | ||
370 | 0xa5, 0x40, /* Lum contrast, nominal value = 0x40 */ | ||
371 | 0xa6, 0x40, /* Chroma satur. nominal value = 0x80 */ | ||
372 | 0xa8, 0x00, /* hor lum scaling 0x0200 = 2 zoom */ | ||
373 | 0xa9, 0x02, /* note: 2 x zoom ensures that VBI lines have same length as video lines. */ | ||
374 | 0xaa, 0x00, /* H-phase offset Luma = 0 */ | ||
375 | 0xac, 0x00, /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */ | ||
376 | 0xad, 0x01, /* H-scaling incr chroma */ | ||
377 | 0xae, 0x00, /* H-phase offset chroma. must be offset luma / 2 */ | ||
378 | |||
379 | 0xb0, 0x00, /* V-scaling incr luma low */ | ||
380 | 0xb1, 0x04, /* " hi */ | ||
381 | 0xb2, 0x00, /* V-scaling incr chroma low */ | ||
382 | 0xb3, 0x04, /* " hi */ | ||
383 | 0xb4, 0x01, /* V-scaling mode control */ | ||
384 | 0xb8, 0x00, /* V-phase offset chroma 00 */ | ||
385 | 0xb9, 0x00, /* V-phase offset chroma 01 */ | ||
386 | 0xba, 0x00, /* V-phase offset chroma 10 */ | ||
387 | 0xbb, 0x00, /* V-phase offset chroma 11 */ | ||
388 | 0xbc, 0x00, /* V-phase offset luma 00 */ | ||
389 | 0xbd, 0x00, /* V-phase offset luma 01 */ | ||
390 | 0xbe, 0x00, /* V-phase offset luma 10 */ | ||
391 | 0xbf, 0x00, /* V-phase offset luma 11 */ | ||
392 | |||
393 | /* Task B */ | ||
394 | 0xd0, 0x01, /* down scale = 1 */ | ||
395 | 0xd1, 0x00, /* prescale accumulation length = 1 */ | ||
396 | 0xd2, 0x00, /* dc gain and fir prefilter control */ | ||
397 | 0xd4, 0x80, /* Lum Brightness, nominal value = 0x80 */ | ||
398 | 0xd5, 0x40, /* Lum contrast, nominal value = 0x40 */ | ||
399 | 0xd6, 0x40, /* Chroma satur. nominal value = 0x80 */ | ||
400 | 0xd8, 0x00, /* hor lum scaling 0x0400 = 1 */ | ||
401 | 0xd9, 0x04, | ||
402 | 0xda, 0x00, /* H-phase offset Luma = 0 */ | ||
403 | 0xdc, 0x00, /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */ | ||
404 | 0xdd, 0x02, /* H-scaling incr chroma */ | ||
405 | 0xde, 0x00, /* H-phase offset chroma. must be offset luma / 2 */ | ||
406 | |||
407 | 0xe0, 0x00, /* V-scaling incr luma low */ | ||
408 | 0xe1, 0x04, /* " hi */ | ||
409 | 0xe2, 0x00, /* V-scaling incr chroma low */ | ||
410 | 0xe3, 0x04, /* " hi */ | ||
411 | 0xe4, 0x01, /* V-scaling mode control */ | ||
412 | 0xe8, 0x00, /* V-phase offset chroma 00 */ | ||
413 | 0xe9, 0x00, /* V-phase offset chroma 01 */ | ||
414 | 0xea, 0x00, /* V-phase offset chroma 10 */ | ||
415 | 0xeb, 0x00, /* V-phase offset chroma 11 */ | ||
416 | 0xec, 0x00, /* V-phase offset luma 00 */ | ||
417 | 0xed, 0x00, /* V-phase offset luma 01 */ | ||
418 | 0xee, 0x00, /* V-phase offset luma 10 */ | ||
419 | 0xef, 0x00, /* V-phase offset luma 11 */ | ||
420 | |||
421 | 0xf2, 0x50, /* crystal clock = 24.576 MHz, target = 27MHz */ | ||
422 | 0xf3, 0x46, | ||
423 | 0xf4, 0x00, | ||
424 | 0xf7, 0x4b, /* not the recommended settings! */ | ||
425 | 0xf8, 0x00, | ||
426 | 0xf9, 0x4b, | ||
427 | 0xfa, 0x00, | ||
428 | 0xfb, 0x4b, | ||
429 | 0xff, 0x88, /* PLL2 lock detection settings: 71 lines 50% phase error */ | ||
430 | |||
431 | /* Turn off VBI */ | ||
432 | 0x40, 0x20, /* No framing code errors allowed. */ | ||
433 | 0x41, 0xff, | ||
434 | 0x42, 0xff, | ||
435 | 0x43, 0xff, | ||
436 | 0x44, 0xff, | ||
437 | 0x45, 0xff, | ||
438 | 0x46, 0xff, | ||
439 | 0x47, 0xff, | ||
440 | 0x48, 0xff, | ||
441 | 0x49, 0xff, | ||
442 | 0x4a, 0xff, | ||
443 | 0x4b, 0xff, | ||
444 | 0x4c, 0xff, | ||
445 | 0x4d, 0xff, | ||
446 | 0x4e, 0xff, | ||
447 | 0x4f, 0xff, | ||
448 | 0x50, 0xff, | ||
449 | 0x51, 0xff, | ||
450 | 0x52, 0xff, | ||
451 | 0x53, 0xff, | ||
452 | 0x54, 0xff, | ||
453 | 0x55, 0xff, | ||
454 | 0x56, 0xff, | ||
455 | 0x57, 0xff, | ||
456 | 0x58, 0x40, | ||
457 | 0x59, 0x47, | ||
458 | 0x5b, 0x83, | ||
459 | 0x5d, 0xbd, | ||
460 | 0x5e, 0x35, | ||
461 | |||
462 | 0x02, 0x84, /* input tuner -> input 4, amplifier active */ | ||
463 | 0x09, 0x53, /* 0x53, was 0x56 for 60hz. luminance control */ | ||
464 | |||
465 | 0x80, 0x20, /* enable task B */ | ||
466 | 0x88, 0xd0, | ||
467 | 0x88, 0xf0, | ||
468 | 0x00, 0x00 | ||
469 | }; | ||
470 | |||
471 | /* ============== SAA7715 AUDIO settings ============= */ | ||
472 | |||
473 | /* 48.0 kHz */ | ||
474 | static const unsigned char saa7115_cfg_48_audio[] = { | ||
475 | 0x34, 0xce, | ||
476 | 0x35, 0xfb, | ||
477 | 0x36, 0x30, | ||
478 | 0x00, 0x00 | ||
479 | }; | ||
480 | |||
481 | /* 44.1 kHz */ | ||
482 | static const unsigned char saa7115_cfg_441_audio[] = { | ||
483 | 0x34, 0xf2, | ||
484 | 0x35, 0x00, | ||
485 | 0x36, 0x2d, | ||
486 | 0x00, 0x00 | ||
487 | }; | ||
488 | |||
489 | /* 32.0 kHz */ | ||
490 | static const unsigned char saa7115_cfg_32_audio[] = { | ||
491 | 0x34, 0xdf, | ||
492 | 0x35, 0xa7, | ||
493 | 0x36, 0x20, | ||
494 | 0x00, 0x00 | ||
495 | }; | ||
496 | |||
497 | /* 48.0 kHz 60hz */ | ||
498 | static const unsigned char saa7115_cfg_60hz_48_audio[] = { | ||
499 | 0x30, 0xcd, | ||
500 | 0x31, 0x20, | ||
501 | 0x32, 0x03, | ||
502 | 0x00, 0x00 | ||
503 | }; | ||
504 | |||
505 | /* 48.0 kHz 50hz */ | ||
506 | static const unsigned char saa7115_cfg_50hz_48_audio[] = { | ||
507 | 0x30, 0x00, | ||
508 | 0x31, 0xc0, | ||
509 | 0x32, 0x03, | ||
510 | 0x00, 0x00 | ||
511 | }; | ||
512 | |||
513 | /* 44.1 kHz 60hz */ | ||
514 | static const unsigned char saa7115_cfg_60hz_441_audio[] = { | ||
515 | 0x30, 0xbc, | ||
516 | 0x31, 0xdf, | ||
517 | 0x32, 0x02, | ||
518 | 0x00, 0x00 | ||
519 | }; | ||
520 | |||
521 | /* 44.1 kHz 50hz */ | ||
522 | static const unsigned char saa7115_cfg_50hz_441_audio[] = { | ||
523 | 0x30, 0x00, | ||
524 | 0x31, 0x72, | ||
525 | 0x32, 0x03, | ||
526 | 0x00, 0x00 | ||
527 | }; | ||
528 | |||
529 | /* 32.0 kHz 60hz */ | ||
530 | static const unsigned char saa7115_cfg_60hz_32_audio[] = { | ||
531 | 0x30, 0xde, | ||
532 | 0x31, 0x15, | ||
533 | 0x32, 0x02, | ||
534 | 0x00, 0x00 | ||
535 | }; | ||
536 | |||
537 | /* 32.0 kHz 50hz */ | ||
538 | static const unsigned char saa7115_cfg_50hz_32_audio[] = { | ||
539 | 0x30, 0x00, | ||
540 | 0x31, 0x80, | ||
541 | 0x32, 0x02, | ||
542 | 0x00, 0x00 | ||
543 | }; | ||
544 | |||
545 | static int saa7115_odd_parity(u8 c) | ||
546 | { | ||
547 | c ^= (c >> 4); | ||
548 | c ^= (c >> 2); | ||
549 | c ^= (c >> 1); | ||
550 | |||
551 | return c & 1; | ||
552 | } | ||
553 | |||
554 | static int saa7115_decode_vps(u8 * dst, u8 * p) | ||
555 | { | ||
556 | static const u8 biphase_tbl[] = { | ||
557 | 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, | ||
558 | 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0, | ||
559 | 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96, | ||
560 | 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2, | ||
561 | 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94, | ||
562 | 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0, | ||
563 | 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, | ||
564 | 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0, | ||
565 | 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5, | ||
566 | 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1, | ||
567 | 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87, | ||
568 | 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3, | ||
569 | 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85, | ||
570 | 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1, | ||
571 | 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5, | ||
572 | 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1, | ||
573 | 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4, | ||
574 | 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0, | ||
575 | 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86, | ||
576 | 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2, | ||
577 | 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84, | ||
578 | 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0, | ||
579 | 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4, | ||
580 | 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0, | ||
581 | 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, | ||
582 | 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0, | ||
583 | 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96, | ||
584 | 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2, | ||
585 | 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94, | ||
586 | 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0, | ||
587 | 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, | ||
588 | 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0, | ||
589 | }; | ||
590 | int i; | ||
591 | u8 c, err = 0; | ||
592 | |||
593 | for (i = 0; i < 2 * 13; i += 2) { | ||
594 | err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]]; | ||
595 | c = (biphase_tbl[p[i + 1]] & 0xf) | ((biphase_tbl[p[i]] & 0xf) << 4); | ||
596 | dst[i / 2] = c; | ||
597 | } | ||
598 | return err & 0xf0; | ||
599 | } | ||
600 | |||
601 | static int saa7115_decode_wss(u8 * p) | ||
602 | { | ||
603 | static const int wss_bits[8] = { | ||
604 | 0, 0, 0, 1, 0, 1, 1, 1 | ||
605 | }; | ||
606 | unsigned char parity; | ||
607 | int wss = 0; | ||
608 | int i; | ||
609 | |||
610 | for (i = 0; i < 16; i++) { | ||
611 | int b1 = wss_bits[p[i] & 7]; | ||
612 | int b2 = wss_bits[(p[i] >> 3) & 7]; | ||
613 | |||
614 | if (b1 == b2) | ||
615 | return -1; | ||
616 | wss |= b2 << i; | ||
617 | } | ||
618 | parity = wss & 15; | ||
619 | parity ^= parity >> 2; | ||
620 | parity ^= parity >> 1; | ||
621 | |||
622 | if (!(parity & 1)) | ||
623 | return -1; | ||
624 | |||
625 | return wss; | ||
626 | } | ||
627 | |||
628 | |||
629 | static int saa7115_set_audio_clock_freq(struct i2c_client *client, enum v4l2_audio_clock_freq freq) | ||
630 | { | ||
631 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
632 | |||
633 | saa7115_dbg("set audio clock freq: %d\n", freq); | ||
634 | switch (freq) { | ||
635 | case V4L2_AUDCLK_32_KHZ: | ||
636 | saa7115_writeregs(client, saa7115_cfg_32_audio); | ||
637 | if (state->std & V4L2_STD_525_60) { | ||
638 | saa7115_writeregs(client, saa7115_cfg_60hz_32_audio); | ||
639 | } else { | ||
640 | saa7115_writeregs(client, saa7115_cfg_50hz_32_audio); | ||
641 | } | ||
642 | break; | ||
643 | case V4L2_AUDCLK_441_KHZ: | ||
644 | saa7115_writeregs(client, saa7115_cfg_441_audio); | ||
645 | if (state->std & V4L2_STD_525_60) { | ||
646 | saa7115_writeregs(client, saa7115_cfg_60hz_441_audio); | ||
647 | } else { | ||
648 | saa7115_writeregs(client, saa7115_cfg_50hz_441_audio); | ||
649 | } | ||
650 | break; | ||
651 | case V4L2_AUDCLK_48_KHZ: | ||
652 | saa7115_writeregs(client, saa7115_cfg_48_audio); | ||
653 | if (state->std & V4L2_STD_525_60) { | ||
654 | saa7115_writeregs(client, saa7115_cfg_60hz_48_audio); | ||
655 | } else { | ||
656 | saa7115_writeregs(client, saa7115_cfg_50hz_48_audio); | ||
657 | } | ||
658 | break; | ||
659 | default: | ||
660 | saa7115_dbg("invalid audio setting %d\n", freq); | ||
661 | return -EINVAL; | ||
662 | } | ||
663 | state->audclk_freq = freq; | ||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) | ||
668 | { | ||
669 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
670 | |||
671 | switch (ctrl->id) { | ||
672 | case V4L2_CID_BRIGHTNESS: | ||
673 | if (ctrl->value < 0 || ctrl->value > 255) { | ||
674 | saa7115_err("invalid brightness setting %d\n", ctrl->value); | ||
675 | return -ERANGE; | ||
676 | } | ||
677 | |||
678 | state->bright = ctrl->value; | ||
679 | saa7115_write(client, 0x0a, state->bright); | ||
680 | break; | ||
681 | |||
682 | case V4L2_CID_CONTRAST: | ||
683 | if (ctrl->value < 0 || ctrl->value > 127) { | ||
684 | saa7115_err("invalid contrast setting %d\n", ctrl->value); | ||
685 | return -ERANGE; | ||
686 | } | ||
687 | |||
688 | state->contrast = ctrl->value; | ||
689 | saa7115_write(client, 0x0b, state->contrast); | ||
690 | break; | ||
691 | |||
692 | case V4L2_CID_SATURATION: | ||
693 | if (ctrl->value < 0 || ctrl->value > 127) { | ||
694 | saa7115_err("invalid saturation setting %d\n", ctrl->value); | ||
695 | return -ERANGE; | ||
696 | } | ||
697 | |||
698 | state->sat = ctrl->value; | ||
699 | saa7115_write(client, 0x0c, state->sat); | ||
700 | break; | ||
701 | |||
702 | case V4L2_CID_HUE: | ||
703 | if (ctrl->value < -127 || ctrl->value > 127) { | ||
704 | saa7115_err("invalid hue setting %d\n", ctrl->value); | ||
705 | return -ERANGE; | ||
706 | } | ||
707 | |||
708 | state->hue = ctrl->value; | ||
709 | saa7115_write(client, 0x0d, state->hue); | ||
710 | break; | ||
711 | } | ||
712 | |||
713 | return 0; | ||
714 | } | ||
715 | |||
716 | static int saa7115_get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) | ||
717 | { | ||
718 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
719 | |||
720 | switch (ctrl->id) { | ||
721 | case V4L2_CID_BRIGHTNESS: | ||
722 | ctrl->value = state->bright; | ||
723 | break; | ||
724 | case V4L2_CID_CONTRAST: | ||
725 | ctrl->value = state->contrast; | ||
726 | break; | ||
727 | case V4L2_CID_SATURATION: | ||
728 | ctrl->value = state->sat; | ||
729 | break; | ||
730 | case V4L2_CID_HUE: | ||
731 | ctrl->value = state->hue; | ||
732 | break; | ||
733 | default: | ||
734 | return -EINVAL; | ||
735 | } | ||
736 | |||
737 | return 0; | ||
738 | } | ||
739 | |||
740 | static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std) | ||
741 | { | ||
742 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
743 | int taskb = saa7115_read(client, 0x80) & 0x10; | ||
744 | |||
745 | // This works for NTSC-M, SECAM-L and the 50Hz PAL variants. | ||
746 | if (std & V4L2_STD_525_60) { | ||
747 | saa7115_dbg("decoder set standard 60 Hz\n"); | ||
748 | saa7115_writeregs(client, saa7115_cfg_60hz_video); | ||
749 | } else { | ||
750 | saa7115_dbg("decoder set standard 50 Hz\n"); | ||
751 | saa7115_writeregs(client, saa7115_cfg_50hz_video); | ||
752 | } | ||
753 | |||
754 | state->std = std; | ||
755 | |||
756 | /* restart task B if needed */ | ||
757 | if (taskb && state->ident == V4L2_IDENT_SAA7114) { | ||
758 | saa7115_writeregs(client, saa7115_cfg_vbi_on); | ||
759 | } | ||
760 | |||
761 | /* switch audio mode too! */ | ||
762 | saa7115_set_audio_clock_freq(client, state->audclk_freq); | ||
763 | } | ||
764 | |||
765 | static v4l2_std_id saa7115_get_v4lstd(struct i2c_client *client) | ||
766 | { | ||
767 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
768 | |||
769 | return state->std; | ||
770 | } | ||
771 | |||
772 | static void saa7115_log_status(struct i2c_client *client) | ||
773 | { | ||
774 | static const char * const audclk_freq_strs[] = { | ||
775 | "44.1 kHz", | ||
776 | "48 kHz", | ||
777 | "32 kHz" | ||
778 | }; | ||
779 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
780 | int reg1e, reg1f; | ||
781 | int signalOk; | ||
782 | int vcr; | ||
783 | |||
784 | saa7115_info("Audio frequency: %s\n", audclk_freq_strs[state->audclk_freq]); | ||
785 | if (client->name[6] == '4') { | ||
786 | /* status for the saa7114 */ | ||
787 | reg1f = saa7115_read(client, 0x1f); | ||
788 | signalOk = (reg1f & 0xc1) == 0x81; | ||
789 | saa7115_info("Video signal: %s\n", signalOk ? "ok" : "bad"); | ||
790 | saa7115_info("Frequency: %s\n", (reg1f & 0x20) ? "60Hz" : "50Hz"); | ||
791 | return; | ||
792 | } | ||
793 | |||
794 | /* status for the saa7115 */ | ||
795 | reg1e = saa7115_read(client, 0x1e); | ||
796 | reg1f = saa7115_read(client, 0x1f); | ||
797 | |||
798 | signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80; | ||
799 | vcr = !(reg1f & 0x10); | ||
800 | |||
801 | saa7115_info("Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad"); | ||
802 | saa7115_info("Frequency: %s\n", (reg1f & 0x20) ? "60Hz" : "50Hz"); | ||
803 | |||
804 | switch (reg1e & 0x03) { | ||
805 | case 1: | ||
806 | saa7115_info("Detected format: NTSC\n"); | ||
807 | break; | ||
808 | case 2: | ||
809 | saa7115_info("Detected format: PAL\n"); | ||
810 | break; | ||
811 | case 3: | ||
812 | saa7115_info("Detected format: SECAM\n"); | ||
813 | break; | ||
814 | default: | ||
815 | saa7115_info("Detected format: BW/No color\n"); | ||
816 | break; | ||
817 | } | ||
818 | } | ||
819 | |||
820 | /* setup the sliced VBI lcr registers according to the sliced VBI format */ | ||
821 | static void saa7115_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_format *fmt) | ||
822 | { | ||
823 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
824 | int is_50hz = (state->std & V4L2_STD_625_50); | ||
825 | u8 lcr[24]; | ||
826 | int i, x; | ||
827 | |||
828 | /* saa7114 doesn't yet support VBI */ | ||
829 | if (state->ident == V4L2_IDENT_SAA7114) | ||
830 | return; | ||
831 | |||
832 | for (i = 0; i <= 23; i++) | ||
833 | lcr[i] = 0xff; | ||
834 | |||
835 | if (fmt->service_set == 0) { | ||
836 | /* raw VBI */ | ||
837 | if (is_50hz) | ||
838 | for (i = 6; i <= 23; i++) | ||
839 | lcr[i] = 0xdd; | ||
840 | else | ||
841 | for (i = 10; i <= 21; i++) | ||
842 | lcr[i] = 0xdd; | ||
843 | } else { | ||
844 | /* sliced VBI */ | ||
845 | /* first clear lines that cannot be captured */ | ||
846 | if (is_50hz) { | ||
847 | for (i = 0; i <= 5; i++) | ||
848 | fmt->service_lines[0][i] = | ||
849 | fmt->service_lines[1][i] = 0; | ||
850 | } | ||
851 | else { | ||
852 | for (i = 0; i <= 9; i++) | ||
853 | fmt->service_lines[0][i] = | ||
854 | fmt->service_lines[1][i] = 0; | ||
855 | for (i = 22; i <= 23; i++) | ||
856 | fmt->service_lines[0][i] = | ||
857 | fmt->service_lines[1][i] = 0; | ||
858 | } | ||
859 | |||
860 | /* Now set the lcr values according to the specified service */ | ||
861 | for (i = 6; i <= 23; i++) { | ||
862 | lcr[i] = 0; | ||
863 | for (x = 0; x <= 1; x++) { | ||
864 | switch (fmt->service_lines[1-x][i]) { | ||
865 | case 0: | ||
866 | lcr[i] |= 0xf << (4 * x); | ||
867 | break; | ||
868 | case V4L2_SLICED_TELETEXT_B: | ||
869 | lcr[i] |= 1 << (4 * x); | ||
870 | break; | ||
871 | case V4L2_SLICED_CAPTION_525: | ||
872 | lcr[i] |= 4 << (4 * x); | ||
873 | break; | ||
874 | case V4L2_SLICED_WSS_625: | ||
875 | lcr[i] |= 5 << (4 * x); | ||
876 | break; | ||
877 | case V4L2_SLICED_VPS: | ||
878 | lcr[i] |= 7 << (4 * x); | ||
879 | break; | ||
880 | } | ||
881 | } | ||
882 | } | ||
883 | } | ||
884 | |||
885 | /* write the lcr registers */ | ||
886 | for (i = 2; i <= 23; i++) { | ||
887 | saa7115_write(client, i - 2 + 0x41, lcr[i]); | ||
888 | } | ||
889 | |||
890 | /* enable/disable raw VBI capturing */ | ||
891 | saa7115_writeregs(client, fmt->service_set == 0 ? saa7115_cfg_vbi_on : saa7115_cfg_vbi_off); | ||
892 | } | ||
893 | |||
894 | static int saa7115_get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) | ||
895 | { | ||
896 | static u16 lcr2vbi[] = { | ||
897 | 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ | ||
898 | 0, V4L2_SLICED_CAPTION_525, /* 4 */ | ||
899 | V4L2_SLICED_WSS_625, 0, /* 5 */ | ||
900 | V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 */ | ||
901 | 0, 0, 0, 0 | ||
902 | }; | ||
903 | struct v4l2_sliced_vbi_format *sliced = &fmt->fmt.sliced; | ||
904 | int i; | ||
905 | |||
906 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) | ||
907 | return -EINVAL; | ||
908 | memset(sliced, 0, sizeof(*sliced)); | ||
909 | /* done if using raw VBI */ | ||
910 | if (saa7115_read(client, 0x80) & 0x10) | ||
911 | return 0; | ||
912 | for (i = 2; i <= 23; i++) { | ||
913 | u8 v = saa7115_read(client, i - 2 + 0x41); | ||
914 | |||
915 | sliced->service_lines[0][i] = lcr2vbi[v >> 4]; | ||
916 | sliced->service_lines[1][i] = lcr2vbi[v & 0xf]; | ||
917 | sliced->service_set |= | ||
918 | sliced->service_lines[0][i] | sliced->service_lines[1][i]; | ||
919 | } | ||
920 | return 0; | ||
921 | } | ||
922 | |||
923 | static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) | ||
924 | { | ||
925 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
926 | struct v4l2_pix_format *pix; | ||
927 | int HPSC, HFSC; | ||
928 | int VSCY, Vsrc; | ||
929 | int is_50hz = state->std & V4L2_STD_625_50; | ||
930 | |||
931 | if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { | ||
932 | saa7115_set_lcr(client, &fmt->fmt.sliced); | ||
933 | return 0; | ||
934 | } | ||
935 | if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
936 | return -EINVAL; | ||
937 | |||
938 | pix = &(fmt->fmt.pix); | ||
939 | |||
940 | saa7115_dbg("decoder set size\n"); | ||
941 | |||
942 | /* FIXME need better bounds checking here */ | ||
943 | if ((pix->width < 1) || (pix->width > 1440)) | ||
944 | return -EINVAL; | ||
945 | if ((pix->height < 1) || (pix->height > 960)) | ||
946 | return -EINVAL; | ||
947 | |||
948 | /* probably have a valid size, let's set it */ | ||
949 | /* Set output width/height */ | ||
950 | /* width */ | ||
951 | saa7115_write(client, 0xcc, (u8) (pix->width & 0xff)); | ||
952 | saa7115_write(client, 0xcd, (u8) ((pix->width >> 8) & 0xff)); | ||
953 | /* height */ | ||
954 | saa7115_write(client, 0xce, (u8) (pix->height & 0xff)); | ||
955 | saa7115_write(client, 0xcf, (u8) ((pix->height >> 8) & 0xff)); | ||
956 | |||
957 | /* Scaling settings */ | ||
958 | /* Hprescaler is floor(inres/outres) */ | ||
959 | /* FIXME hardcoding input res */ | ||
960 | if (pix->width != 720) { | ||
961 | HPSC = (int)(720 / pix->width); | ||
962 | /* 0 is not allowed (div. by zero) */ | ||
963 | HPSC = HPSC ? HPSC : 1; | ||
964 | HFSC = (int)((1024 * 720) / (HPSC * pix->width)); | ||
965 | |||
966 | saa7115_dbg("Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC); | ||
967 | /* FIXME hardcodes to "Task B" | ||
968 | * write H prescaler integer */ | ||
969 | saa7115_write(client, 0xd0, (u8) (HPSC & 0x3f)); | ||
970 | |||
971 | /* write H fine-scaling (luminance) */ | ||
972 | saa7115_write(client, 0xd8, (u8) (HFSC & 0xff)); | ||
973 | saa7115_write(client, 0xd9, (u8) ((HFSC >> 8) & 0xff)); | ||
974 | /* write H fine-scaling (chrominance) | ||
975 | * must be lum/2, so i'll just bitshift :) */ | ||
976 | saa7115_write(client, 0xDC, (u8) ((HFSC >> 1) & 0xff)); | ||
977 | saa7115_write(client, 0xDD, (u8) ((HFSC >> 9) & 0xff)); | ||
978 | } else { | ||
979 | if (is_50hz) { | ||
980 | saa7115_dbg("Setting full 50hz width\n"); | ||
981 | saa7115_writeregs(client, saa7115_cfg_50hz_fullres_x); | ||
982 | } else { | ||
983 | saa7115_dbg("Setting full 60hz width\n"); | ||
984 | saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x); | ||
985 | } | ||
986 | } | ||
987 | |||
988 | Vsrc = is_50hz ? 576 : 480; | ||
989 | |||
990 | if (pix->height != Vsrc) { | ||
991 | VSCY = (int)((1024 * Vsrc) / pix->height); | ||
992 | saa7115_dbg("Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY); | ||
993 | |||
994 | /* Correct Contrast and Luminance */ | ||
995 | saa7115_write(client, 0xd5, (u8) (64 * 1024 / VSCY)); | ||
996 | saa7115_write(client, 0xd6, (u8) (64 * 1024 / VSCY)); | ||
997 | |||
998 | /* write V fine-scaling (luminance) */ | ||
999 | saa7115_write(client, 0xe0, (u8) (VSCY & 0xff)); | ||
1000 | saa7115_write(client, 0xe1, (u8) ((VSCY >> 8) & 0xff)); | ||
1001 | /* write V fine-scaling (chrominance) */ | ||
1002 | saa7115_write(client, 0xe2, (u8) (VSCY & 0xff)); | ||
1003 | saa7115_write(client, 0xe3, (u8) ((VSCY >> 8) & 0xff)); | ||
1004 | } else { | ||
1005 | if (is_50hz) { | ||
1006 | saa7115_dbg("Setting full 50Hz height\n"); | ||
1007 | saa7115_writeregs(client, saa7115_cfg_50hz_fullres_y); | ||
1008 | } else { | ||
1009 | saa7115_dbg("Setting full 60hz height\n"); | ||
1010 | saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y); | ||
1011 | } | ||
1012 | } | ||
1013 | |||
1014 | saa7115_writeregs(client, saa7115_cfg_reset_scaler); | ||
1015 | return 0; | ||
1016 | } | ||
1017 | |||
1018 | /* Decode the sliced VBI data stream as created by the saa7115. | ||
1019 | The format is described in the saa7115 datasheet in Tables 25 and 26 | ||
1020 | and in Figure 33. | ||
1021 | The current implementation uses SAV/EAV codes and not the ancillary data | ||
1022 | headers. The vbi->p pointer points to the SDID byte right after the SAV | ||
1023 | code. */ | ||
1024 | static void saa7115_decode_vbi_line(struct i2c_client *client, | ||
1025 | struct v4l2_decode_vbi_line *vbi) | ||
1026 | { | ||
1027 | static const char vbi_no_data_pattern[] = { | ||
1028 | 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0 | ||
1029 | }; | ||
1030 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
1031 | u8 *p = vbi->p; | ||
1032 | u32 wss; | ||
1033 | int id1, id2; /* the ID1 and ID2 bytes from the internal header */ | ||
1034 | |||
1035 | vbi->type = 0; /* mark result as a failure */ | ||
1036 | id1 = p[2]; | ||
1037 | id2 = p[3]; | ||
1038 | /* Note: the field bit is inverted for 60 Hz video */ | ||
1039 | if (state->std & V4L2_STD_525_60) | ||
1040 | id1 ^= 0x40; | ||
1041 | |||
1042 | /* Skip internal header, p now points to the start of the payload */ | ||
1043 | p += 4; | ||
1044 | vbi->p = p; | ||
1045 | |||
1046 | /* calculate field and line number of the VBI packet (1-23) */ | ||
1047 | vbi->is_second_field = ((id1 & 0x40) != 0); | ||
1048 | vbi->line = (id1 & 0x3f) << 3; | ||
1049 | vbi->line |= (id2 & 0x70) >> 4; | ||
1050 | |||
1051 | /* Obtain data type */ | ||
1052 | id2 &= 0xf; | ||
1053 | |||
1054 | /* If the VBI slicer does not detect any signal it will fill up | ||
1055 | the payload buffer with 0xa0 bytes. */ | ||
1056 | if (!memcmp(p, vbi_no_data_pattern, sizeof(vbi_no_data_pattern))) | ||
1057 | return; | ||
1058 | |||
1059 | /* decode payloads */ | ||
1060 | switch (id2) { | ||
1061 | case 1: | ||
1062 | vbi->type = V4L2_SLICED_TELETEXT_B; | ||
1063 | break; | ||
1064 | case 4: | ||
1065 | if (!saa7115_odd_parity(p[0]) || !saa7115_odd_parity(p[1])) | ||
1066 | return; | ||
1067 | vbi->type = V4L2_SLICED_CAPTION_525; | ||
1068 | break; | ||
1069 | case 5: | ||
1070 | wss = saa7115_decode_wss(p); | ||
1071 | if (wss == -1) | ||
1072 | return; | ||
1073 | p[0] = wss & 0xff; | ||
1074 | p[1] = wss >> 8; | ||
1075 | vbi->type = V4L2_SLICED_WSS_625; | ||
1076 | break; | ||
1077 | case 7: | ||
1078 | if (saa7115_decode_vps(p, p) != 0) | ||
1079 | return; | ||
1080 | vbi->type = V4L2_SLICED_VPS; | ||
1081 | break; | ||
1082 | default: | ||
1083 | return; | ||
1084 | } | ||
1085 | } | ||
1086 | |||
1087 | /* ============ SAA7115 AUDIO settings (end) ============= */ | ||
1088 | |||
1089 | static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *arg) | ||
1090 | { | ||
1091 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
1092 | int *iarg = arg; | ||
1093 | |||
1094 | /* ioctls to allow direct access to the saa7115 registers for testing */ | ||
1095 | switch (cmd) { | ||
1096 | case VIDIOC_S_FMT: | ||
1097 | return saa7115_set_v4lfmt(client, (struct v4l2_format *)arg); | ||
1098 | |||
1099 | case VIDIOC_G_FMT: | ||
1100 | return saa7115_get_v4lfmt(client, (struct v4l2_format *)arg); | ||
1101 | |||
1102 | case VIDIOC_INT_AUDIO_CLOCK_FREQ: | ||
1103 | return saa7115_set_audio_clock_freq(client, *(enum v4l2_audio_clock_freq *)arg); | ||
1104 | |||
1105 | case VIDIOC_G_TUNER: | ||
1106 | { | ||
1107 | struct v4l2_tuner *vt = arg; | ||
1108 | int status; | ||
1109 | |||
1110 | status = saa7115_read(client, 0x1f); | ||
1111 | |||
1112 | saa7115_dbg("status: 0x%02x\n", status); | ||
1113 | vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0; | ||
1114 | break; | ||
1115 | } | ||
1116 | |||
1117 | case VIDIOC_LOG_STATUS: | ||
1118 | saa7115_log_status(client); | ||
1119 | break; | ||
1120 | |||
1121 | case VIDIOC_G_CTRL: | ||
1122 | return saa7115_get_v4lctrl(client, (struct v4l2_control *)arg); | ||
1123 | |||
1124 | case VIDIOC_S_CTRL: | ||
1125 | return saa7115_set_v4lctrl(client, (struct v4l2_control *)arg); | ||
1126 | |||
1127 | case VIDIOC_G_STD: | ||
1128 | *(v4l2_std_id *)arg = saa7115_get_v4lstd(client); | ||
1129 | break; | ||
1130 | |||
1131 | case VIDIOC_S_STD: | ||
1132 | saa7115_set_v4lstd(client, *(v4l2_std_id *)arg); | ||
1133 | break; | ||
1134 | |||
1135 | case VIDIOC_G_INPUT: | ||
1136 | *(int *)arg = state->input; | ||
1137 | break; | ||
1138 | |||
1139 | case VIDIOC_S_INPUT: | ||
1140 | saa7115_dbg("decoder set input %d\n", *iarg); | ||
1141 | /* inputs from 0-9 are available */ | ||
1142 | if (*iarg < 0 || *iarg > 9) { | ||
1143 | return -EINVAL; | ||
1144 | } | ||
1145 | |||
1146 | if (state->input == *iarg) | ||
1147 | break; | ||
1148 | saa7115_dbg("now setting %s input\n", | ||
1149 | *iarg >= 6 ? "S-Video" : "Composite"); | ||
1150 | state->input = *iarg; | ||
1151 | |||
1152 | /* select mode */ | ||
1153 | saa7115_write(client, 0x02, | ||
1154 | (saa7115_read(client, 0x02) & 0xf0) | | ||
1155 | state->input); | ||
1156 | |||
1157 | /* bypass chrominance trap for modes 6..9 */ | ||
1158 | saa7115_write(client, 0x09, | ||
1159 | (saa7115_read(client, 0x09) & 0x7f) | | ||
1160 | (state->input < 6 ? 0x0 : 0x80)); | ||
1161 | break; | ||
1162 | |||
1163 | case VIDIOC_STREAMON: | ||
1164 | case VIDIOC_STREAMOFF: | ||
1165 | saa7115_dbg("%s output\n", | ||
1166 | (cmd == VIDIOC_STREAMON) ? "enable" : "disable"); | ||
1167 | |||
1168 | if (state->enable != (cmd == VIDIOC_STREAMON)) { | ||
1169 | state->enable = (cmd == VIDIOC_STREAMON); | ||
1170 | saa7115_write(client, 0x87, state->enable); | ||
1171 | } | ||
1172 | break; | ||
1173 | |||
1174 | case VIDIOC_INT_DECODE_VBI_LINE: | ||
1175 | saa7115_decode_vbi_line(client, arg); | ||
1176 | break; | ||
1177 | |||
1178 | case VIDIOC_INT_RESET: | ||
1179 | saa7115_dbg("decoder RESET\n"); | ||
1180 | saa7115_writeregs(client, saa7115_cfg_reset_scaler); | ||
1181 | break; | ||
1182 | |||
1183 | case VIDIOC_INT_G_VBI_DATA: | ||
1184 | { | ||
1185 | struct v4l2_sliced_vbi_data *data = arg; | ||
1186 | |||
1187 | switch (data->id) { | ||
1188 | case V4L2_SLICED_WSS_625: | ||
1189 | if (saa7115_read(client, 0x6b) & 0xc0) | ||
1190 | return -EIO; | ||
1191 | data->data[0] = saa7115_read(client, 0x6c); | ||
1192 | data->data[1] = saa7115_read(client, 0x6d); | ||
1193 | return 0; | ||
1194 | case V4L2_SLICED_CAPTION_525: | ||
1195 | if (data->field == 0) { | ||
1196 | /* CC */ | ||
1197 | if (saa7115_read(client, 0x66) & 0xc0) | ||
1198 | return -EIO; | ||
1199 | data->data[0] = saa7115_read(client, 0x67); | ||
1200 | data->data[1] = saa7115_read(client, 0x68); | ||
1201 | return 0; | ||
1202 | } | ||
1203 | /* XDS */ | ||
1204 | if (saa7115_read(client, 0x66) & 0x30) | ||
1205 | return -EIO; | ||
1206 | data->data[0] = saa7115_read(client, 0x69); | ||
1207 | data->data[1] = saa7115_read(client, 0x6a); | ||
1208 | return 0; | ||
1209 | default: | ||
1210 | return -EINVAL; | ||
1211 | } | ||
1212 | break; | ||
1213 | } | ||
1214 | |||
1215 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1216 | case VIDIOC_INT_G_REGISTER: | ||
1217 | { | ||
1218 | struct v4l2_register *reg = arg; | ||
1219 | |||
1220 | if (reg->i2c_id != I2C_DRIVERID_SAA711X) | ||
1221 | return -EINVAL; | ||
1222 | reg->val = saa7115_read(client, reg->reg & 0xff); | ||
1223 | break; | ||
1224 | } | ||
1225 | |||
1226 | case VIDIOC_INT_S_REGISTER: | ||
1227 | { | ||
1228 | struct v4l2_register *reg = arg; | ||
1229 | |||
1230 | if (reg->i2c_id != I2C_DRIVERID_SAA711X) | ||
1231 | return -EINVAL; | ||
1232 | if (!capable(CAP_SYS_ADMIN)) | ||
1233 | return -EPERM; | ||
1234 | saa7115_write(client, reg->reg & 0xff, reg->val & 0xff); | ||
1235 | break; | ||
1236 | } | ||
1237 | #endif | ||
1238 | |||
1239 | case VIDIOC_INT_G_CHIP_IDENT: | ||
1240 | *iarg = state->ident; | ||
1241 | break; | ||
1242 | |||
1243 | default: | ||
1244 | return -EINVAL; | ||
1245 | } | ||
1246 | |||
1247 | return 0; | ||
1248 | } | ||
1249 | |||
1250 | /* ----------------------------------------------------------------------- */ | ||
1251 | |||
1252 | static struct i2c_driver i2c_driver_saa7115; | ||
1253 | |||
1254 | static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind) | ||
1255 | { | ||
1256 | struct i2c_client *client; | ||
1257 | struct saa7115_state *state; | ||
1258 | u8 chip_id; | ||
1259 | |||
1260 | /* Check if the adapter supports the needed features */ | ||
1261 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
1262 | return 0; | ||
1263 | |||
1264 | client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
1265 | if (client == 0) | ||
1266 | return -ENOMEM; | ||
1267 | memset(client, 0, sizeof(struct i2c_client)); | ||
1268 | client->addr = address; | ||
1269 | client->adapter = adapter; | ||
1270 | client->driver = &i2c_driver_saa7115; | ||
1271 | client->flags = I2C_CLIENT_ALLOW_USE; | ||
1272 | snprintf(client->name, sizeof(client->name) - 1, "saa7115"); | ||
1273 | |||
1274 | saa7115_dbg("detecting saa7115 client on address 0x%x\n", address << 1); | ||
1275 | |||
1276 | saa7115_write(client, 0, 5); | ||
1277 | chip_id = saa7115_read(client, 0) & 0x0f; | ||
1278 | if (chip_id != 4 && chip_id != 5) { | ||
1279 | saa7115_dbg("saa7115 not found\n"); | ||
1280 | kfree(client); | ||
1281 | return 0; | ||
1282 | } | ||
1283 | if (chip_id == 4) { | ||
1284 | snprintf(client->name, sizeof(client->name) - 1, "saa7114"); | ||
1285 | } | ||
1286 | saa7115_info("saa711%d found @ 0x%x (%s)\n", chip_id, address << 1, adapter->name); | ||
1287 | |||
1288 | state = kmalloc(sizeof(struct saa7115_state), GFP_KERNEL); | ||
1289 | i2c_set_clientdata(client, state); | ||
1290 | if (state == NULL) { | ||
1291 | kfree(client); | ||
1292 | return -ENOMEM; | ||
1293 | } | ||
1294 | memset(state, 0, sizeof(struct saa7115_state)); | ||
1295 | state->std = V4L2_STD_NTSC; | ||
1296 | state->input = -1; | ||
1297 | state->enable = 1; | ||
1298 | state->bright = 128; | ||
1299 | state->contrast = 64; | ||
1300 | state->hue = 0; | ||
1301 | state->sat = 64; | ||
1302 | state->ident = (chip_id == 4) ? V4L2_IDENT_SAA7114 : V4L2_IDENT_SAA7115; | ||
1303 | state->audclk_freq = V4L2_AUDCLK_48_KHZ; | ||
1304 | |||
1305 | saa7115_dbg("writing init values\n"); | ||
1306 | |||
1307 | /* init to 60hz/48khz */ | ||
1308 | saa7115_writeregs(client, saa7115_init_auto_input); | ||
1309 | saa7115_writeregs(client, saa7115_init_misc); | ||
1310 | saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x); | ||
1311 | saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y); | ||
1312 | saa7115_writeregs(client, saa7115_cfg_60hz_video); | ||
1313 | saa7115_writeregs(client, saa7115_cfg_48_audio); | ||
1314 | saa7115_writeregs(client, saa7115_cfg_60hz_48_audio); | ||
1315 | saa7115_writeregs(client, saa7115_cfg_reset_scaler); | ||
1316 | |||
1317 | i2c_attach_client(client); | ||
1318 | |||
1319 | saa7115_dbg("status: (1E) 0x%02x, (1F) 0x%02x\n", | ||
1320 | saa7115_read(client, 0x1e), saa7115_read(client, 0x1f)); | ||
1321 | |||
1322 | return 0; | ||
1323 | } | ||
1324 | |||
1325 | static int saa7115_probe(struct i2c_adapter *adapter) | ||
1326 | { | ||
1327 | #ifdef I2C_CLASS_TV_ANALOG | ||
1328 | if (adapter->class & I2C_CLASS_TV_ANALOG) | ||
1329 | #else | ||
1330 | if (adapter->id == I2C_HW_B_BT848) | ||
1331 | #endif | ||
1332 | return i2c_probe(adapter, &addr_data, &saa7115_attach); | ||
1333 | return 0; | ||
1334 | } | ||
1335 | |||
1336 | static int saa7115_detach(struct i2c_client *client) | ||
1337 | { | ||
1338 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
1339 | int err; | ||
1340 | |||
1341 | err = i2c_detach_client(client); | ||
1342 | if (err) { | ||
1343 | return err; | ||
1344 | } | ||
1345 | |||
1346 | kfree(state); | ||
1347 | kfree(client); | ||
1348 | return 0; | ||
1349 | } | ||
1350 | |||
1351 | /* ----------------------------------------------------------------------- */ | ||
1352 | |||
1353 | /* i2c implementation */ | ||
1354 | static struct i2c_driver i2c_driver_saa7115 = { | ||
1355 | .name = "saa7115", | ||
1356 | .id = I2C_DRIVERID_SAA711X, | ||
1357 | .flags = I2C_DF_NOTIFY, | ||
1358 | .attach_adapter = saa7115_probe, | ||
1359 | .detach_client = saa7115_detach, | ||
1360 | .command = saa7115_command, | ||
1361 | .owner = THIS_MODULE, | ||
1362 | }; | ||
1363 | |||
1364 | |||
1365 | static int __init saa7115_init_module(void) | ||
1366 | { | ||
1367 | return i2c_add_driver(&i2c_driver_saa7115); | ||
1368 | } | ||
1369 | |||
1370 | static void __exit saa7115_cleanup_module(void) | ||
1371 | { | ||
1372 | i2c_del_driver(&i2c_driver_saa7115); | ||
1373 | } | ||
1374 | |||
1375 | module_init(saa7115_init_module); | ||
1376 | module_exit(saa7115_cleanup_module); | ||
diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c index 9aa8827de2c3..25b30f352d84 100644 --- a/drivers/media/video/saa711x.c +++ b/drivers/media/video/saa711x.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #include <asm/pgtable.h> | 36 | #include <asm/pgtable.h> |
37 | #include <asm/page.h> | 37 | #include <asm/page.h> |
38 | #include <linux/sched.h> | 38 | #include <linux/sched.h> |
39 | #include <asm/segment.h> | ||
40 | #include <linux/types.h> | 39 | #include <linux/types.h> |
41 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
42 | #include <linux/videodev.h> | 41 | #include <linux/videodev.h> |
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c new file mode 100644 index 000000000000..843431f10e3b --- /dev/null +++ b/drivers/media/video/saa7127.c | |||
@@ -0,0 +1,849 @@ | |||
1 | /* | ||
2 | * saa7127 - Philips SAA7127/SAA7129 video encoder driver | ||
3 | * | ||
4 | * Copyright (C) 2003 Roy Bulter <rbulter@hetnet.nl> | ||
5 | * | ||
6 | * Based on SAA7126 video encoder driver by Gillem & Andreas Oberritter | ||
7 | * | ||
8 | * Copyright (C) 2000-2001 Gillem <htoa@gmx.net> | ||
9 | * Copyright (C) 2002 Andreas Oberritter <obi@saftware.de> | ||
10 | * | ||
11 | * Based on Stadis 4:2:2 MPEG-2 Decoder Driver by Nathan Laredo | ||
12 | * | ||
13 | * Copyright (C) 1999 Nathan Laredo <laredo@gnu.org> | ||
14 | * | ||
15 | * This driver is designed for the Hauppauge 250/350 Linux driver | ||
16 | * from the ivtv Project | ||
17 | * | ||
18 | * Copyright (C) 2003 Kevin Thayer <nufan_wfk@yahoo.com> | ||
19 | * | ||
20 | * Dual output support: | ||
21 | * Copyright (C) 2004 Eric Varsanyi | ||
22 | * | ||
23 | * NTSC Tuning and 7.5 IRE Setup | ||
24 | * Copyright (C) 2004 Chris Kennedy <c@groovy.org> | ||
25 | * | ||
26 | * VBI additions & cleanup: | ||
27 | * Copyright (C) 2004, 2005 Hans Verkuil <hverkuil@xs4all.nl> | ||
28 | * | ||
29 | * Note: the saa7126 is identical to the saa7127, and the saa7128 is | ||
30 | * identical to the saa7129, except that the saa7126 and saa7128 have | ||
31 | * macrovision anti-taping support. This driver will almost certainly | ||
32 | * work find for those chips, except of course for the missing anti-taping | ||
33 | * support. | ||
34 | * | ||
35 | * This program is free software; you can redistribute it and/or modify | ||
36 | * it under the terms of the GNU General Public License as published by | ||
37 | * the Free Software Foundation; either version 2 of the License, or | ||
38 | * (at your option) any later version. | ||
39 | * | ||
40 | * This program is distributed in the hope that it will be useful, | ||
41 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
42 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
43 | * GNU General Public License for more details. | ||
44 | * | ||
45 | * You should have received a copy of the GNU General Public License | ||
46 | * along with this program; if not, write to the Free Software | ||
47 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
48 | */ | ||
49 | |||
50 | |||
51 | #include <linux/kernel.h> | ||
52 | #include <linux/module.h> | ||
53 | #include <linux/slab.h> | ||
54 | #include <linux/i2c.h> | ||
55 | #include <linux/videodev2.h> | ||
56 | #include <media/v4l2-common.h> | ||
57 | |||
58 | static int debug = 0; | ||
59 | static int test_image = 0; | ||
60 | |||
61 | MODULE_DESCRIPTION("Philips SAA7127/9 video encoder driver"); | ||
62 | MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil"); | ||
63 | MODULE_LICENSE("GPL"); | ||
64 | module_param(debug, int, 0644); | ||
65 | module_param(test_image, int, 0644); | ||
66 | MODULE_PARM_DESC(debug, "debug level (0-2)"); | ||
67 | MODULE_PARM_DESC(test_image, "test_image (0-1)"); | ||
68 | |||
69 | #define saa7127_dbg(fmt, arg...) \ | ||
70 | do { \ | ||
71 | if (debug >= 1) \ | ||
72 | printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \ | ||
73 | i2c_adapter_id(client->adapter), client->addr , ## arg); \ | ||
74 | } while (0) | ||
75 | |||
76 | /* High volume debug. Use with care. */ | ||
77 | #define saa7127_dbg_highvol(fmt, arg...) \ | ||
78 | do { \ | ||
79 | if (debug == 2) \ | ||
80 | printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \ | ||
81 | i2c_adapter_id(client->adapter), client->addr , ## arg); \ | ||
82 | } while (0) | ||
83 | |||
84 | #define saa7127_err(fmt, arg...) do { \ | ||
85 | printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \ | ||
86 | i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) | ||
87 | #define saa7127_info(fmt, arg...) do { \ | ||
88 | printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \ | ||
89 | i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) | ||
90 | |||
91 | static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; | ||
92 | |||
93 | |||
94 | I2C_CLIENT_INSMOD; | ||
95 | |||
96 | /* | ||
97 | * SAA7127 registers | ||
98 | */ | ||
99 | |||
100 | #define SAA7127_REG_STATUS 0x00 | ||
101 | #define SAA7127_REG_WIDESCREEN_CONFIG 0x26 | ||
102 | #define SAA7127_REG_WIDESCREEN_ENABLE 0x27 | ||
103 | #define SAA7127_REG_BURST_START 0x28 | ||
104 | #define SAA7127_REG_BURST_END 0x29 | ||
105 | #define SAA7127_REG_COPYGEN_0 0x2a | ||
106 | #define SAA7127_REG_COPYGEN_1 0x2b | ||
107 | #define SAA7127_REG_COPYGEN_2 0x2c | ||
108 | #define SAA7127_REG_OUTPUT_PORT_CONTROL 0x2d | ||
109 | #define SAA7127_REG_GAIN_LUMINANCE_RGB 0x38 | ||
110 | #define SAA7127_REG_GAIN_COLORDIFF_RGB 0x39 | ||
111 | #define SAA7127_REG_INPUT_PORT_CONTROL_1 0x3a | ||
112 | #define SAA7129_REG_FADE_KEY_COL2 0x4f | ||
113 | #define SAA7127_REG_CHROMA_PHASE 0x5a | ||
114 | #define SAA7127_REG_GAINU 0x5b | ||
115 | #define SAA7127_REG_GAINV 0x5c | ||
116 | #define SAA7127_REG_BLACK_LEVEL 0x5d | ||
117 | #define SAA7127_REG_BLANKING_LEVEL 0x5e | ||
118 | #define SAA7127_REG_VBI_BLANKING 0x5f | ||
119 | #define SAA7127_REG_DAC_CONTROL 0x61 | ||
120 | #define SAA7127_REG_BURST_AMP 0x62 | ||
121 | #define SAA7127_REG_SUBC3 0x63 | ||
122 | #define SAA7127_REG_SUBC2 0x64 | ||
123 | #define SAA7127_REG_SUBC1 0x65 | ||
124 | #define SAA7127_REG_SUBC0 0x66 | ||
125 | #define SAA7127_REG_LINE_21_ODD_0 0x67 | ||
126 | #define SAA7127_REG_LINE_21_ODD_1 0x68 | ||
127 | #define SAA7127_REG_LINE_21_EVEN_0 0x69 | ||
128 | #define SAA7127_REG_LINE_21_EVEN_1 0x6a | ||
129 | #define SAA7127_REG_RCV_PORT_CONTROL 0x6b | ||
130 | #define SAA7127_REG_VTRIG 0x6c | ||
131 | #define SAA7127_REG_HTRIG_HI 0x6d | ||
132 | #define SAA7127_REG_MULTI 0x6e | ||
133 | #define SAA7127_REG_CLOSED_CAPTION 0x6f | ||
134 | #define SAA7127_REG_RCV2_OUTPUT_START 0x70 | ||
135 | #define SAA7127_REG_RCV2_OUTPUT_END 0x71 | ||
136 | #define SAA7127_REG_RCV2_OUTPUT_MSBS 0x72 | ||
137 | #define SAA7127_REG_TTX_REQUEST_H_START 0x73 | ||
138 | #define SAA7127_REG_TTX_REQUEST_H_DELAY_LENGTH 0x74 | ||
139 | #define SAA7127_REG_CSYNC_ADVANCE_VSYNC_SHIFT 0x75 | ||
140 | #define SAA7127_REG_TTX_ODD_REQ_VERT_START 0x76 | ||
141 | #define SAA7127_REG_TTX_ODD_REQ_VERT_END 0x77 | ||
142 | #define SAA7127_REG_TTX_EVEN_REQ_VERT_START 0x78 | ||
143 | #define SAA7127_REG_TTX_EVEN_REQ_VERT_END 0x79 | ||
144 | #define SAA7127_REG_FIRST_ACTIVE 0x7a | ||
145 | #define SAA7127_REG_LAST_ACTIVE 0x7b | ||
146 | #define SAA7127_REG_MSB_VERTICAL 0x7c | ||
147 | #define SAA7127_REG_DISABLE_TTX_LINE_LO_0 0x7e | ||
148 | #define SAA7127_REG_DISABLE_TTX_LINE_LO_1 0x7f | ||
149 | |||
150 | /* | ||
151 | ********************************************************************** | ||
152 | * | ||
153 | * Arrays with configuration parameters for the SAA7127 | ||
154 | * | ||
155 | ********************************************************************** | ||
156 | */ | ||
157 | |||
158 | struct i2c_reg_value { | ||
159 | unsigned char reg; | ||
160 | unsigned char value; | ||
161 | }; | ||
162 | |||
163 | static const struct i2c_reg_value saa7129_init_config_extra[] = { | ||
164 | { SAA7127_REG_OUTPUT_PORT_CONTROL, 0x38 }, | ||
165 | { SAA7127_REG_VTRIG, 0xfa }, | ||
166 | }; | ||
167 | |||
168 | static const struct i2c_reg_value saa7127_init_config_common[] = { | ||
169 | { SAA7127_REG_WIDESCREEN_CONFIG, 0x0d }, | ||
170 | { SAA7127_REG_WIDESCREEN_ENABLE, 0x00 }, | ||
171 | { SAA7127_REG_COPYGEN_0, 0x77 }, | ||
172 | { SAA7127_REG_COPYGEN_1, 0x41 }, | ||
173 | { SAA7127_REG_COPYGEN_2, 0x00 }, /* Macrovision enable/disable */ | ||
174 | { SAA7127_REG_OUTPUT_PORT_CONTROL, 0x9e }, | ||
175 | { SAA7127_REG_GAIN_LUMINANCE_RGB, 0x00 }, | ||
176 | { SAA7127_REG_GAIN_COLORDIFF_RGB, 0x00 }, | ||
177 | { SAA7127_REG_INPUT_PORT_CONTROL_1, 0x80 }, /* for color bars */ | ||
178 | { SAA7127_REG_LINE_21_ODD_0, 0x77 }, | ||
179 | { SAA7127_REG_LINE_21_ODD_1, 0x41 }, | ||
180 | { SAA7127_REG_LINE_21_EVEN_0, 0x88 }, | ||
181 | { SAA7127_REG_LINE_21_EVEN_1, 0x41 }, | ||
182 | { SAA7127_REG_RCV_PORT_CONTROL, 0x12 }, | ||
183 | { SAA7127_REG_VTRIG, 0xf9 }, | ||
184 | { SAA7127_REG_HTRIG_HI, 0x00 }, | ||
185 | { SAA7127_REG_RCV2_OUTPUT_START, 0x41 }, | ||
186 | { SAA7127_REG_RCV2_OUTPUT_END, 0xc3 }, | ||
187 | { SAA7127_REG_RCV2_OUTPUT_MSBS, 0x00 }, | ||
188 | { SAA7127_REG_TTX_REQUEST_H_START, 0x3e }, | ||
189 | { SAA7127_REG_TTX_REQUEST_H_DELAY_LENGTH, 0xb8 }, | ||
190 | { SAA7127_REG_CSYNC_ADVANCE_VSYNC_SHIFT, 0x03 }, | ||
191 | { SAA7127_REG_TTX_ODD_REQ_VERT_START, 0x15 }, | ||
192 | { SAA7127_REG_TTX_ODD_REQ_VERT_END, 0x16 }, | ||
193 | { SAA7127_REG_TTX_EVEN_REQ_VERT_START, 0x15 }, | ||
194 | { SAA7127_REG_TTX_EVEN_REQ_VERT_END, 0x16 }, | ||
195 | { SAA7127_REG_FIRST_ACTIVE, 0x1a }, | ||
196 | { SAA7127_REG_LAST_ACTIVE, 0x01 }, | ||
197 | { SAA7127_REG_MSB_VERTICAL, 0xc0 }, | ||
198 | { SAA7127_REG_DISABLE_TTX_LINE_LO_0, 0x00 }, | ||
199 | { SAA7127_REG_DISABLE_TTX_LINE_LO_1, 0x00 }, | ||
200 | { 0, 0 } | ||
201 | }; | ||
202 | |||
203 | #define SAA7127_60HZ_DAC_CONTROL 0x15 | ||
204 | static const struct i2c_reg_value saa7127_init_config_60hz[] = { | ||
205 | { SAA7127_REG_BURST_START, 0x19 }, | ||
206 | /* BURST_END is also used as a chip ID in saa7127_detect_client */ | ||
207 | { SAA7127_REG_BURST_END, 0x1d }, | ||
208 | { SAA7127_REG_CHROMA_PHASE, 0xa3 }, | ||
209 | { SAA7127_REG_GAINU, 0x98 }, | ||
210 | { SAA7127_REG_GAINV, 0xd3 }, | ||
211 | { SAA7127_REG_BLACK_LEVEL, 0x39 }, | ||
212 | { SAA7127_REG_BLANKING_LEVEL, 0x2e }, | ||
213 | { SAA7127_REG_VBI_BLANKING, 0x2e }, | ||
214 | { SAA7127_REG_DAC_CONTROL, 0x15 }, | ||
215 | { SAA7127_REG_BURST_AMP, 0x4d }, | ||
216 | { SAA7127_REG_SUBC3, 0x1f }, | ||
217 | { SAA7127_REG_SUBC2, 0x7c }, | ||
218 | { SAA7127_REG_SUBC1, 0xf0 }, | ||
219 | { SAA7127_REG_SUBC0, 0x21 }, | ||
220 | { SAA7127_REG_MULTI, 0x90 }, | ||
221 | { SAA7127_REG_CLOSED_CAPTION, 0x11 }, | ||
222 | { 0, 0 } | ||
223 | }; | ||
224 | |||
225 | #define SAA7127_50HZ_DAC_CONTROL 0x02 | ||
226 | struct i2c_reg_value saa7127_init_config_50hz[] = { | ||
227 | { SAA7127_REG_BURST_START, 0x21 }, | ||
228 | /* BURST_END is also used as a chip ID in saa7127_detect_client */ | ||
229 | { SAA7127_REG_BURST_END, 0x1d }, | ||
230 | { SAA7127_REG_CHROMA_PHASE, 0x3f }, | ||
231 | { SAA7127_REG_GAINU, 0x7d }, | ||
232 | { SAA7127_REG_GAINV, 0xaf }, | ||
233 | { SAA7127_REG_BLACK_LEVEL, 0x33 }, | ||
234 | { SAA7127_REG_BLANKING_LEVEL, 0x35 }, | ||
235 | { SAA7127_REG_VBI_BLANKING, 0x35 }, | ||
236 | { SAA7127_REG_DAC_CONTROL, 0x02 }, | ||
237 | { SAA7127_REG_BURST_AMP, 0x2f }, | ||
238 | { SAA7127_REG_SUBC3, 0xcb }, | ||
239 | { SAA7127_REG_SUBC2, 0x8a }, | ||
240 | { SAA7127_REG_SUBC1, 0x09 }, | ||
241 | { SAA7127_REG_SUBC0, 0x2a }, | ||
242 | { SAA7127_REG_MULTI, 0xa0 }, | ||
243 | { SAA7127_REG_CLOSED_CAPTION, 0x00 }, | ||
244 | { 0, 0 } | ||
245 | }; | ||
246 | |||
247 | /* Enumeration for the Supported input types */ | ||
248 | enum saa7127_input_type { | ||
249 | SAA7127_INPUT_TYPE_NORMAL, | ||
250 | SAA7127_INPUT_TYPE_TEST_IMAGE | ||
251 | }; | ||
252 | |||
253 | /* Enumeration for the Supported Output signal types */ | ||
254 | enum saa7127_output_type { | ||
255 | SAA7127_OUTPUT_TYPE_BOTH, | ||
256 | SAA7127_OUTPUT_TYPE_COMPOSITE, | ||
257 | SAA7127_OUTPUT_TYPE_SVIDEO, | ||
258 | SAA7127_OUTPUT_TYPE_RGB, | ||
259 | SAA7127_OUTPUT_TYPE_YUV_C, | ||
260 | SAA7127_OUTPUT_TYPE_YUV_V | ||
261 | }; | ||
262 | |||
263 | /* | ||
264 | ********************************************************************** | ||
265 | * | ||
266 | * Encoder Struct, holds the configuration state of the encoder | ||
267 | * | ||
268 | ********************************************************************** | ||
269 | */ | ||
270 | |||
271 | struct saa7127_state { | ||
272 | v4l2_std_id std; | ||
273 | enum v4l2_chip_ident ident; | ||
274 | enum saa7127_input_type input_type; | ||
275 | enum saa7127_output_type output_type; | ||
276 | int video_enable; | ||
277 | int wss_enable; | ||
278 | u16 wss_mode; | ||
279 | int cc_enable; | ||
280 | u16 cc_data; | ||
281 | int xds_enable; | ||
282 | u16 xds_data; | ||
283 | int vps_enable; | ||
284 | u8 vps_data[5]; | ||
285 | u8 reg_2d; | ||
286 | u8 reg_3a; | ||
287 | u8 reg_3a_cb; /* colorbar bit */ | ||
288 | u8 reg_61; | ||
289 | }; | ||
290 | |||
291 | static const char * const output_strs[] = | ||
292 | { | ||
293 | "S-Video + Composite", | ||
294 | "Composite", | ||
295 | "S-Video", | ||
296 | "RGB", | ||
297 | "YUV C", | ||
298 | "YUV V" | ||
299 | }; | ||
300 | |||
301 | static const char * const wss_strs[] = { | ||
302 | "invalid", | ||
303 | "letterbox 14:9 center", | ||
304 | "letterbox 14:9 top", | ||
305 | "invalid", | ||
306 | "letterbox 16:9 top", | ||
307 | "invalid", | ||
308 | "invalid", | ||
309 | "16:9 full format anamorphic" | ||
310 | "4:3 full format", | ||
311 | "invalid", | ||
312 | "invalid", | ||
313 | "letterbox 16:9 center", | ||
314 | "invalid", | ||
315 | "letterbox >16:9 center", | ||
316 | "14:9 full format center", | ||
317 | "invalid", | ||
318 | }; | ||
319 | |||
320 | /* ----------------------------------------------------------------------- */ | ||
321 | |||
322 | static int saa7127_read(struct i2c_client *client, u8 reg) | ||
323 | { | ||
324 | return i2c_smbus_read_byte_data(client, reg); | ||
325 | } | ||
326 | |||
327 | /* ----------------------------------------------------------------------- */ | ||
328 | |||
329 | static int saa7127_write(struct i2c_client *client, u8 reg, u8 val) | ||
330 | { | ||
331 | int i; | ||
332 | |||
333 | for (i = 0; i < 3; i++) { | ||
334 | if (i2c_smbus_write_byte_data(client, reg, val) == 0) | ||
335 | return 0; | ||
336 | } | ||
337 | saa7127_err("I2C Write Problem\n"); | ||
338 | return -1; | ||
339 | } | ||
340 | |||
341 | /* ----------------------------------------------------------------------- */ | ||
342 | |||
343 | static int saa7127_write_inittab(struct i2c_client *client, | ||
344 | const struct i2c_reg_value *regs) | ||
345 | { | ||
346 | while (regs->reg != 0) { | ||
347 | saa7127_write(client, regs->reg, regs->value); | ||
348 | regs++; | ||
349 | } | ||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | /* ----------------------------------------------------------------------- */ | ||
354 | |||
355 | static int saa7127_set_vps(struct i2c_client *client, struct v4l2_sliced_vbi_data *data) | ||
356 | { | ||
357 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
358 | int enable = (data->line != 0); | ||
359 | |||
360 | if (enable && (data->field != 0 || data->line != 16)) | ||
361 | return -EINVAL; | ||
362 | if (state->vps_enable != enable) { | ||
363 | saa7127_dbg("Turn VPS Signal %s\n", enable ? "on" : "off"); | ||
364 | saa7127_write(client, 0x54, enable << 7); | ||
365 | state->vps_enable = enable; | ||
366 | } | ||
367 | if (!enable) | ||
368 | return 0; | ||
369 | |||
370 | state->vps_data[0] = data->data[4]; | ||
371 | state->vps_data[1] = data->data[10]; | ||
372 | state->vps_data[2] = data->data[11]; | ||
373 | state->vps_data[3] = data->data[12]; | ||
374 | state->vps_data[4] = data->data[13]; | ||
375 | saa7127_dbg("Set VPS data %02x %02x %02x %02x %02x\n", | ||
376 | state->vps_data[0], state->vps_data[1], | ||
377 | state->vps_data[2], state->vps_data[3], | ||
378 | state->vps_data[4]); | ||
379 | saa7127_write(client, 0x55, state->vps_data[0]); | ||
380 | saa7127_write(client, 0x56, state->vps_data[1]); | ||
381 | saa7127_write(client, 0x57, state->vps_data[2]); | ||
382 | saa7127_write(client, 0x58, state->vps_data[3]); | ||
383 | saa7127_write(client, 0x59, state->vps_data[4]); | ||
384 | return 0; | ||
385 | } | ||
386 | |||
387 | /* ----------------------------------------------------------------------- */ | ||
388 | |||
389 | static int saa7127_set_cc(struct i2c_client *client, struct v4l2_sliced_vbi_data *data) | ||
390 | { | ||
391 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
392 | u16 cc = data->data[0] << 8 | data->data[1]; | ||
393 | int enable = (data->line != 0); | ||
394 | |||
395 | if (enable && (data->field != 0 || data->line != 21)) | ||
396 | return -EINVAL; | ||
397 | if (state->cc_enable != enable) { | ||
398 | saa7127_dbg("Turn CC %s\n", enable ? "on" : "off"); | ||
399 | saa7127_write(client, SAA7127_REG_CLOSED_CAPTION, | ||
400 | (enable << 6) | 0x11); | ||
401 | state->cc_enable = enable; | ||
402 | } | ||
403 | if (!enable) | ||
404 | return 0; | ||
405 | |||
406 | saa7127_dbg_highvol("CC data: %04x\n", cc); | ||
407 | saa7127_write(client, SAA7127_REG_LINE_21_ODD_0, cc & 0xff); | ||
408 | saa7127_write(client, SAA7127_REG_LINE_21_ODD_1, cc >> 8); | ||
409 | state->cc_data = cc; | ||
410 | return 0; | ||
411 | } | ||
412 | |||
413 | /* ----------------------------------------------------------------------- */ | ||
414 | |||
415 | static int saa7127_set_xds(struct i2c_client *client, struct v4l2_sliced_vbi_data *data) | ||
416 | { | ||
417 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
418 | u16 xds = data->data[1] << 8 | data->data[0]; | ||
419 | int enable = (data->line != 0); | ||
420 | |||
421 | if (enable && (data->field != 1 || data->line != 21)) | ||
422 | return -EINVAL; | ||
423 | if (state->xds_enable != enable) { | ||
424 | saa7127_dbg("Turn XDS %s\n", enable ? "on" : "off"); | ||
425 | saa7127_write(client, SAA7127_REG_CLOSED_CAPTION, | ||
426 | (enable << 7) | 0x11); | ||
427 | state->xds_enable = enable; | ||
428 | } | ||
429 | if (!enable) | ||
430 | return 0; | ||
431 | |||
432 | saa7127_dbg_highvol("XDS data: %04x\n", xds); | ||
433 | saa7127_write(client, SAA7127_REG_LINE_21_EVEN_0, xds & 0xff); | ||
434 | saa7127_write(client, SAA7127_REG_LINE_21_EVEN_1, xds >> 8); | ||
435 | state->xds_data = xds; | ||
436 | return 0; | ||
437 | } | ||
438 | |||
439 | /* ----------------------------------------------------------------------- */ | ||
440 | |||
441 | static int saa7127_set_wss(struct i2c_client *client, struct v4l2_sliced_vbi_data *data) | ||
442 | { | ||
443 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
444 | int enable = (data->line != 0); | ||
445 | |||
446 | if (enable && (data->field != 0 || data->line != 23)) | ||
447 | return -EINVAL; | ||
448 | if (state->wss_enable != enable) { | ||
449 | saa7127_dbg("Turn WSS %s\n", enable ? "on" : "off"); | ||
450 | saa7127_write(client, 0x27, enable << 7); | ||
451 | state->wss_enable = enable; | ||
452 | } | ||
453 | if (!enable) | ||
454 | return 0; | ||
455 | |||
456 | saa7127_write(client, 0x26, data->data[0]); | ||
457 | saa7127_write(client, 0x27, 0x80 | (data->data[1] & 0x3f)); | ||
458 | saa7127_dbg("WSS mode: %s\n", wss_strs[data->data[0] & 0xf]); | ||
459 | state->wss_mode = (data->data[1] & 0x3f) << 8 | data->data[0]; | ||
460 | return 0; | ||
461 | } | ||
462 | |||
463 | /* ----------------------------------------------------------------------- */ | ||
464 | |||
465 | static int saa7127_set_video_enable(struct i2c_client *client, int enable) | ||
466 | { | ||
467 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
468 | |||
469 | if (enable) { | ||
470 | saa7127_dbg("Enable Video Output\n"); | ||
471 | saa7127_write(client, 0x2d, state->reg_2d); | ||
472 | saa7127_write(client, 0x61, state->reg_61); | ||
473 | } else { | ||
474 | saa7127_dbg("Disable Video Output\n"); | ||
475 | saa7127_write(client, 0x2d, (state->reg_2d & 0xf0)); | ||
476 | saa7127_write(client, 0x61, (state->reg_61 | 0xc0)); | ||
477 | } | ||
478 | state->video_enable = enable; | ||
479 | return 0; | ||
480 | } | ||
481 | |||
482 | /* ----------------------------------------------------------------------- */ | ||
483 | |||
484 | static int saa7127_set_std(struct i2c_client *client, v4l2_std_id std) | ||
485 | { | ||
486 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
487 | const struct i2c_reg_value *inittab; | ||
488 | |||
489 | if (std & V4L2_STD_525_60) { | ||
490 | saa7127_dbg("Selecting 60 Hz video Standard\n"); | ||
491 | inittab = saa7127_init_config_60hz; | ||
492 | state->reg_61 = SAA7127_60HZ_DAC_CONTROL; | ||
493 | } else { | ||
494 | saa7127_dbg("Selecting 50 Hz video Standard\n"); | ||
495 | inittab = saa7127_init_config_50hz; | ||
496 | state->reg_61 = SAA7127_50HZ_DAC_CONTROL; | ||
497 | } | ||
498 | |||
499 | /* Write Table */ | ||
500 | saa7127_write_inittab(client, inittab); | ||
501 | state->std = std; | ||
502 | return 0; | ||
503 | } | ||
504 | |||
505 | /* ----------------------------------------------------------------------- */ | ||
506 | |||
507 | static int saa7127_set_output_type(struct i2c_client *client, int output) | ||
508 | { | ||
509 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
510 | |||
511 | switch (output) { | ||
512 | case SAA7127_OUTPUT_TYPE_RGB: | ||
513 | state->reg_2d = 0x0f; /* RGB + CVBS (for sync) */ | ||
514 | state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */ | ||
515 | break; | ||
516 | |||
517 | case SAA7127_OUTPUT_TYPE_COMPOSITE: | ||
518 | state->reg_2d = 0x08; /* 00001000 CVBS only, RGB DAC's off (high impedance mode) */ | ||
519 | state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */ | ||
520 | break; | ||
521 | |||
522 | case SAA7127_OUTPUT_TYPE_SVIDEO: | ||
523 | state->reg_2d = 0xff; /* 11111111 croma -> R, luma -> CVBS + G + B */ | ||
524 | state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */ | ||
525 | break; | ||
526 | |||
527 | case SAA7127_OUTPUT_TYPE_YUV_V: | ||
528 | state->reg_2d = 0x4f; /* reg 2D = 01001111, all DAC's on, RGB + VBS */ | ||
529 | state->reg_3a = 0x0b; /* reg 3A = 00001011, bypass RGB-matrix */ | ||
530 | break; | ||
531 | |||
532 | case SAA7127_OUTPUT_TYPE_YUV_C: | ||
533 | state->reg_2d = 0x0f; /* reg 2D = 00001111, all DAC's on, RGB + CVBS */ | ||
534 | state->reg_3a = 0x0b; /* reg 3A = 00001011, bypass RGB-matrix */ | ||
535 | break; | ||
536 | |||
537 | case SAA7127_OUTPUT_TYPE_BOTH: | ||
538 | state->reg_2d = 0xbf; | ||
539 | state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */ | ||
540 | break; | ||
541 | |||
542 | default: | ||
543 | return -EINVAL; | ||
544 | } | ||
545 | saa7127_dbg("Selecting %s output type\n", output_strs[output]); | ||
546 | |||
547 | /* Configure Encoder */ | ||
548 | saa7127_write(client, 0x2d, state->reg_2d); | ||
549 | saa7127_write(client, 0x3a, state->reg_3a | state->reg_3a_cb); | ||
550 | state->output_type = output; | ||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | /* ----------------------------------------------------------------------- */ | ||
555 | |||
556 | static int saa7127_set_input_type(struct i2c_client *client, int input) | ||
557 | { | ||
558 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
559 | |||
560 | switch (input) { | ||
561 | case SAA7127_INPUT_TYPE_NORMAL: /* avia */ | ||
562 | saa7127_dbg("Selecting Normal Encoder Input\n"); | ||
563 | state->reg_3a_cb = 0; | ||
564 | break; | ||
565 | |||
566 | case SAA7127_INPUT_TYPE_TEST_IMAGE: /* color bar */ | ||
567 | saa7127_dbg("Selecting Color Bar generator\n"); | ||
568 | state->reg_3a_cb = 0x80; | ||
569 | break; | ||
570 | |||
571 | default: | ||
572 | return -EINVAL; | ||
573 | } | ||
574 | saa7127_write(client, 0x3a, state->reg_3a | state->reg_3a_cb); | ||
575 | state->input_type = input; | ||
576 | return 0; | ||
577 | } | ||
578 | |||
579 | /* ----------------------------------------------------------------------- */ | ||
580 | |||
581 | static int saa7127_command(struct i2c_client *client, | ||
582 | unsigned int cmd, void *arg) | ||
583 | { | ||
584 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
585 | struct v4l2_format *fmt = arg; | ||
586 | int *iarg = arg; | ||
587 | |||
588 | switch (cmd) { | ||
589 | case VIDIOC_S_STD: | ||
590 | if (state->std == *(v4l2_std_id *)arg) | ||
591 | break; | ||
592 | return saa7127_set_std(client, *(v4l2_std_id *)arg); | ||
593 | |||
594 | case VIDIOC_G_STD: | ||
595 | *(v4l2_std_id *)arg = state->std; | ||
596 | break; | ||
597 | |||
598 | case VIDIOC_S_INPUT: | ||
599 | if (state->input_type == *iarg) | ||
600 | break; | ||
601 | return saa7127_set_input_type(client, *iarg); | ||
602 | |||
603 | case VIDIOC_S_OUTPUT: | ||
604 | if (state->output_type == *iarg) | ||
605 | break; | ||
606 | return saa7127_set_output_type(client, *iarg); | ||
607 | |||
608 | case VIDIOC_STREAMON: | ||
609 | case VIDIOC_STREAMOFF: | ||
610 | if (state->video_enable == (cmd == VIDIOC_STREAMON)) | ||
611 | break; | ||
612 | return saa7127_set_video_enable(client, cmd == VIDIOC_STREAMON); | ||
613 | |||
614 | case VIDIOC_G_FMT: | ||
615 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) | ||
616 | return -EINVAL; | ||
617 | |||
618 | memset(&fmt->fmt.sliced, 0, sizeof(fmt->fmt.sliced)); | ||
619 | if (state->vps_enable) | ||
620 | fmt->fmt.sliced.service_lines[0][16] = V4L2_SLICED_VPS; | ||
621 | if (state->wss_enable) | ||
622 | fmt->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625; | ||
623 | if (state->cc_enable) { | ||
624 | fmt->fmt.sliced.service_lines[0][21] = V4L2_SLICED_CAPTION_525; | ||
625 | fmt->fmt.sliced.service_lines[1][21] = V4L2_SLICED_CAPTION_525; | ||
626 | } | ||
627 | fmt->fmt.sliced.service_set = | ||
628 | (state->vps_enable ? V4L2_SLICED_VPS : 0) | | ||
629 | (state->wss_enable ? V4L2_SLICED_WSS_625 : 0) | | ||
630 | (state->cc_enable ? V4L2_SLICED_CAPTION_525 : 0); | ||
631 | break; | ||
632 | |||
633 | case VIDIOC_LOG_STATUS: | ||
634 | saa7127_info("Standard: %s\n", (state->std & V4L2_STD_525_60) ? "60 Hz" : "50 Hz"); | ||
635 | saa7127_info("Input: %s\n", state->input_type ? "color bars" : "normal"); | ||
636 | saa7127_info("Output: %s\n", state->video_enable ? | ||
637 | output_strs[state->output_type] : "disabled"); | ||
638 | saa7127_info("WSS: %s\n", state->wss_enable ? | ||
639 | wss_strs[state->wss_mode] : "disabled"); | ||
640 | saa7127_info("VPS: %s\n", state->vps_enable ? "enabled" : "disabled"); | ||
641 | saa7127_info("CC: %s\n", state->cc_enable ? "enabled" : "disabled"); | ||
642 | break; | ||
643 | |||
644 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
645 | case VIDIOC_INT_G_REGISTER: | ||
646 | { | ||
647 | struct v4l2_register *reg = arg; | ||
648 | |||
649 | if (reg->i2c_id != I2C_DRIVERID_SAA7127) | ||
650 | return -EINVAL; | ||
651 | reg->val = saa7127_read(client, reg->reg & 0xff); | ||
652 | break; | ||
653 | } | ||
654 | |||
655 | case VIDIOC_INT_S_REGISTER: | ||
656 | { | ||
657 | struct v4l2_register *reg = arg; | ||
658 | |||
659 | if (reg->i2c_id != I2C_DRIVERID_SAA7127) | ||
660 | return -EINVAL; | ||
661 | if (!capable(CAP_SYS_ADMIN)) | ||
662 | return -EPERM; | ||
663 | saa7127_write(client, reg->reg & 0xff, reg->val & 0xff); | ||
664 | break; | ||
665 | } | ||
666 | #endif | ||
667 | |||
668 | case VIDIOC_INT_S_VBI_DATA: | ||
669 | { | ||
670 | struct v4l2_sliced_vbi_data *data = arg; | ||
671 | |||
672 | switch (data->id) { | ||
673 | case V4L2_SLICED_WSS_625: | ||
674 | return saa7127_set_wss(client, data); | ||
675 | case V4L2_SLICED_VPS: | ||
676 | return saa7127_set_vps(client, data); | ||
677 | case V4L2_SLICED_CAPTION_525: | ||
678 | if (data->field == 0) | ||
679 | return saa7127_set_cc(client, data); | ||
680 | return saa7127_set_xds(client, data); | ||
681 | default: | ||
682 | return -EINVAL; | ||
683 | } | ||
684 | break; | ||
685 | } | ||
686 | |||
687 | case VIDIOC_INT_G_CHIP_IDENT: | ||
688 | *(enum v4l2_chip_ident *)arg = state->ident; | ||
689 | break; | ||
690 | |||
691 | default: | ||
692 | return -EINVAL; | ||
693 | } | ||
694 | return 0; | ||
695 | } | ||
696 | |||
697 | /* ----------------------------------------------------------------------- */ | ||
698 | |||
699 | struct i2c_driver i2c_driver_saa7127; | ||
700 | |||
701 | /* ----------------------------------------------------------------------- */ | ||
702 | |||
703 | static int saa7127_attach(struct i2c_adapter *adapter, int address, int kind) | ||
704 | { | ||
705 | struct i2c_client *client; | ||
706 | struct saa7127_state *state; | ||
707 | struct v4l2_sliced_vbi_data vbi = { 0, 0, 0, 0 }; /* set to disabled */ | ||
708 | int read_result = 0; | ||
709 | |||
710 | /* Check if the adapter supports the needed features */ | ||
711 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
712 | return 0; | ||
713 | |||
714 | client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
715 | if (client == 0) | ||
716 | return -ENOMEM; | ||
717 | |||
718 | memset(client, 0, sizeof(struct i2c_client)); | ||
719 | client->addr = address; | ||
720 | client->adapter = adapter; | ||
721 | client->driver = &i2c_driver_saa7127; | ||
722 | client->flags = I2C_CLIENT_ALLOW_USE; | ||
723 | snprintf(client->name, sizeof(client->name) - 1, "saa7127"); | ||
724 | |||
725 | saa7127_dbg("detecting saa7127 client on address 0x%x\n", address << 1); | ||
726 | |||
727 | /* First test register 0: Bits 5-7 are a version ID (should be 0), | ||
728 | and bit 2 should also be 0. | ||
729 | This is rather general, so the second test is more specific and | ||
730 | looks at the 'ending point of burst in clock cycles' which is | ||
731 | 0x1d after a reset and not expected to ever change. */ | ||
732 | if ((saa7127_read(client, 0) & 0xe4) != 0 || | ||
733 | (saa7127_read(client, 0x29) & 0x3f) != 0x1d) { | ||
734 | saa7127_dbg("saa7127 not found\n"); | ||
735 | kfree(client); | ||
736 | return 0; | ||
737 | } | ||
738 | state = kmalloc(sizeof(struct saa7127_state), GFP_KERNEL); | ||
739 | |||
740 | if (state == NULL) { | ||
741 | kfree(client); | ||
742 | return (-ENOMEM); | ||
743 | } | ||
744 | |||
745 | i2c_set_clientdata(client, state); | ||
746 | memset(state, 0, sizeof(struct saa7127_state)); | ||
747 | |||
748 | /* Configure Encoder */ | ||
749 | |||
750 | saa7127_dbg("Configuring encoder\n"); | ||
751 | saa7127_write_inittab(client, saa7127_init_config_common); | ||
752 | saa7127_set_std(client, V4L2_STD_NTSC); | ||
753 | saa7127_set_output_type(client, SAA7127_OUTPUT_TYPE_BOTH); | ||
754 | saa7127_set_vps(client, &vbi); | ||
755 | saa7127_set_wss(client, &vbi); | ||
756 | saa7127_set_cc(client, &vbi); | ||
757 | saa7127_set_xds(client, &vbi); | ||
758 | if (test_image == 1) { | ||
759 | /* The Encoder has an internal Colorbar generator */ | ||
760 | /* This can be used for debugging */ | ||
761 | saa7127_set_input_type(client, SAA7127_INPUT_TYPE_TEST_IMAGE); | ||
762 | } else { | ||
763 | saa7127_set_input_type(client, SAA7127_INPUT_TYPE_NORMAL); | ||
764 | } | ||
765 | saa7127_set_video_enable(client, 1); | ||
766 | |||
767 | /* Detect if it's an saa7129 */ | ||
768 | read_result = saa7127_read(client, SAA7129_REG_FADE_KEY_COL2); | ||
769 | saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, 0xaa); | ||
770 | if (saa7127_read(client, SAA7129_REG_FADE_KEY_COL2) == 0xaa) { | ||
771 | saa7127_info("saa7129 found @ 0x%x (%s)\n", address << 1, adapter->name); | ||
772 | saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, read_result); | ||
773 | saa7127_write_inittab(client, saa7129_init_config_extra); | ||
774 | state->ident = V4L2_IDENT_SAA7129; | ||
775 | } else { | ||
776 | saa7127_info("saa7127 found @ 0x%x (%s)\n", address << 1, adapter->name); | ||
777 | state->ident = V4L2_IDENT_SAA7127; | ||
778 | } | ||
779 | |||
780 | i2c_attach_client(client); | ||
781 | |||
782 | return 0; | ||
783 | } | ||
784 | |||
785 | /* ----------------------------------------------------------------------- */ | ||
786 | |||
787 | static int saa7127_probe(struct i2c_adapter *adapter) | ||
788 | { | ||
789 | #ifdef I2C_CLASS_TV_ANALOG | ||
790 | if (adapter->class & I2C_CLASS_TV_ANALOG) | ||
791 | #else | ||
792 | if (adapter->id == I2C_HW_B_BT848) | ||
793 | #endif | ||
794 | return i2c_probe(adapter, &addr_data, saa7127_attach); | ||
795 | return 0; | ||
796 | } | ||
797 | |||
798 | /* ----------------------------------------------------------------------- */ | ||
799 | |||
800 | static int saa7127_detach(struct i2c_client *client) | ||
801 | { | ||
802 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
803 | int err; | ||
804 | |||
805 | /* Turn off TV output */ | ||
806 | saa7127_set_video_enable(client, 0); | ||
807 | |||
808 | err = i2c_detach_client(client); | ||
809 | |||
810 | if (err) { | ||
811 | return err; | ||
812 | } | ||
813 | |||
814 | kfree(state); | ||
815 | kfree(client); | ||
816 | return 0; | ||
817 | } | ||
818 | |||
819 | /* ----------------------------------------------------------------------- */ | ||
820 | |||
821 | struct i2c_driver i2c_driver_saa7127 = { | ||
822 | .name = "saa7127", | ||
823 | .id = I2C_DRIVERID_SAA7127, | ||
824 | .flags = I2C_DF_NOTIFY, | ||
825 | .attach_adapter = saa7127_probe, | ||
826 | .detach_client = saa7127_detach, | ||
827 | .command = saa7127_command, | ||
828 | .owner = THIS_MODULE, | ||
829 | }; | ||
830 | |||
831 | |||
832 | /* ----------------------------------------------------------------------- */ | ||
833 | |||
834 | static int __init saa7127_init_module(void) | ||
835 | { | ||
836 | return i2c_add_driver(&i2c_driver_saa7127); | ||
837 | } | ||
838 | |||
839 | /* ----------------------------------------------------------------------- */ | ||
840 | |||
841 | static void __exit saa7127_cleanup_module(void) | ||
842 | { | ||
843 | i2c_del_driver(&i2c_driver_saa7127); | ||
844 | } | ||
845 | |||
846 | /* ----------------------------------------------------------------------- */ | ||
847 | |||
848 | module_init(saa7127_init_module); | ||
849 | module_exit(saa7127_cleanup_module); | ||
diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig index 624e8808a517..7bdeabe638ca 100644 --- a/drivers/media/video/saa7134/Kconfig +++ b/drivers/media/video/saa7134/Kconfig | |||
@@ -1,10 +1,11 @@ | |||
1 | config VIDEO_SAA7134 | 1 | config VIDEO_SAA7134 |
2 | tristate "Philips SAA7134 support" | 2 | tristate "Philips SAA7134 support" |
3 | depends on VIDEO_DEV && PCI && I2C && SOUND | 3 | depends on VIDEO_DEV && PCI && I2C && SOUND && SND |
4 | select VIDEO_BUF | 4 | select VIDEO_BUF |
5 | select VIDEO_IR | 5 | select VIDEO_IR |
6 | select VIDEO_TUNER | 6 | select VIDEO_TUNER |
7 | select CRC32 | 7 | select CRC32 |
8 | select SND_PCM_OSS | ||
8 | ---help--- | 9 | ---help--- |
9 | This is a video4linux driver for Philips SAA713x based | 10 | This is a video4linux driver for Philips SAA713x based |
10 | TV cards. | 11 | TV cards. |
diff --git a/drivers/media/video/saa7134/Makefile b/drivers/media/video/saa7134/Makefile index e0b28f0533af..4226b61cc613 100644 --- a/drivers/media/video/saa7134/Makefile +++ b/drivers/media/video/saa7134/Makefile | |||
@@ -1,10 +1,11 @@ | |||
1 | 1 | ||
2 | saa7134-objs := saa7134-cards.o saa7134-core.o saa7134-i2c.o \ | 2 | saa7134-objs := saa7134-cards.o saa7134-core.o saa7134-i2c.o \ |
3 | saa7134-oss.o saa7134-ts.o saa7134-tvaudio.o \ | 3 | saa7134-ts.o saa7134-tvaudio.o saa7134-vbi.o \ |
4 | saa7134-vbi.o saa7134-video.o saa7134-input.o | 4 | saa7134-video.o saa7134-input.o |
5 | 5 | ||
6 | obj-$(CONFIG_VIDEO_SAA7134) += saa7134.o saa7134-empress.o \ | 6 | obj-$(CONFIG_VIDEO_SAA7134) += saa7134.o saa7134-empress.o \ |
7 | saa6752hs.o saa7134-alsa.o | 7 | saa6752hs.o saa7134-alsa.o \ |
8 | saa7134-oss.o | ||
8 | obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o | 9 | obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o |
9 | 10 | ||
10 | EXTRA_CFLAGS += -I$(src)/.. | 11 | EXTRA_CFLAGS += -I$(src)/.. |
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 4f3c42354329..5707c666660b 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c | |||
@@ -30,7 +30,9 @@ | |||
30 | #include <sound/core.h> | 30 | #include <sound/core.h> |
31 | #include <sound/control.h> | 31 | #include <sound/control.h> |
32 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
33 | #include <sound/pcm_params.h> | ||
33 | #include <sound/initval.h> | 34 | #include <sound/initval.h> |
35 | #include <linux/interrupt.h> | ||
34 | 36 | ||
35 | #include "saa7134.h" | 37 | #include "saa7134.h" |
36 | #include "saa7134-reg.h" | 38 | #include "saa7134-reg.h" |
@@ -56,6 +58,8 @@ static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; | |||
56 | module_param_array(index, int, NULL, 0444); | 58 | module_param_array(index, int, NULL, 0444); |
57 | MODULE_PARM_DESC(index, "Index value for SAA7134 capture interface(s)."); | 59 | MODULE_PARM_DESC(index, "Index value for SAA7134 capture interface(s)."); |
58 | 60 | ||
61 | int position; | ||
62 | |||
59 | #define dprintk(fmt, arg...) if (debug) \ | 63 | #define dprintk(fmt, arg...) if (debug) \ |
60 | printk(KERN_DEBUG "%s/alsa: " fmt, dev->name , ## arg) | 64 | printk(KERN_DEBUG "%s/alsa: " fmt, dev->name , ## arg) |
61 | 65 | ||
@@ -68,7 +72,7 @@ typedef struct snd_card_saa7134 { | |||
68 | int mixer_volume[MIXER_ADDR_LAST+1][2]; | 72 | int mixer_volume[MIXER_ADDR_LAST+1][2]; |
69 | int capture_source[MIXER_ADDR_LAST+1][2]; | 73 | int capture_source[MIXER_ADDR_LAST+1][2]; |
70 | struct pci_dev *pci; | 74 | struct pci_dev *pci; |
71 | struct saa7134_dev *saadev; | 75 | struct saa7134_dev *dev; |
72 | 76 | ||
73 | unsigned long iobase; | 77 | unsigned long iobase; |
74 | int irq; | 78 | int irq; |
@@ -83,12 +87,10 @@ typedef struct snd_card_saa7134 { | |||
83 | */ | 87 | */ |
84 | 88 | ||
85 | typedef struct snd_card_saa7134_pcm { | 89 | typedef struct snd_card_saa7134_pcm { |
86 | struct saa7134_dev *saadev; | 90 | struct saa7134_dev *dev; |
87 | 91 | ||
88 | spinlock_t lock; | 92 | spinlock_t lock; |
89 | unsigned int pcm_size; /* buffer size */ | 93 | |
90 | unsigned int pcm_count; /* bytes per period */ | ||
91 | unsigned int pcm_bps; /* bytes per second */ | ||
92 | snd_pcm_substream_t *substream; | 94 | snd_pcm_substream_t *substream; |
93 | } snd_card_saa7134_pcm_t; | 95 | } snd_card_saa7134_pcm_t; |
94 | 96 | ||
@@ -100,13 +102,11 @@ static snd_card_t *snd_saa7134_cards[SNDRV_CARDS]; | |||
100 | * | 102 | * |
101 | * Called when the capture device is released or the buffer overflows | 103 | * Called when the capture device is released or the buffer overflows |
102 | * | 104 | * |
103 | * - Copied verbatim from saa7134-oss's dsp_dma_stop. Can be dropped | 105 | * - Copied verbatim from saa7134-oss's dsp_dma_stop. |
104 | * if we just share dsp_dma_stop and use it here | ||
105 | * | 106 | * |
106 | */ | 107 | */ |
107 | 108 | ||
108 | static void saa7134_dma_stop(struct saa7134_dev *dev) | 109 | static void saa7134_dma_stop(struct saa7134_dev *dev) |
109 | |||
110 | { | 110 | { |
111 | dev->dmasound.dma_blk = -1; | 111 | dev->dmasound.dma_blk = -1; |
112 | dev->dmasound.dma_running = 0; | 112 | dev->dmasound.dma_running = 0; |
@@ -118,8 +118,7 @@ static void saa7134_dma_stop(struct saa7134_dev *dev) | |||
118 | * | 118 | * |
119 | * Called when preparing the capture device for use | 119 | * Called when preparing the capture device for use |
120 | * | 120 | * |
121 | * - Copied verbatim from saa7134-oss's dsp_dma_start. Can be dropped | 121 | * - Copied verbatim from saa7134-oss's dsp_dma_start. |
122 | * if we just share dsp_dma_start and use it here | ||
123 | * | 122 | * |
124 | */ | 123 | */ |
125 | 124 | ||
@@ -170,9 +169,9 @@ void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status) | |||
170 | if (dev->dmasound.read_count >= dev->dmasound.blksize * (dev->dmasound.blocks-2)) { | 169 | if (dev->dmasound.read_count >= dev->dmasound.blksize * (dev->dmasound.blocks-2)) { |
171 | dprintk("irq: overrun [full=%d/%d] - Blocks in %d\n",dev->dmasound.read_count, | 170 | dprintk("irq: overrun [full=%d/%d] - Blocks in %d\n",dev->dmasound.read_count, |
172 | dev->dmasound.bufsize, dev->dmasound.blocks); | 171 | dev->dmasound.bufsize, dev->dmasound.blocks); |
172 | spin_unlock(&dev->slock); | ||
173 | snd_pcm_stop(dev->dmasound.substream,SNDRV_PCM_STATE_XRUN); | 173 | snd_pcm_stop(dev->dmasound.substream,SNDRV_PCM_STATE_XRUN); |
174 | saa7134_dma_stop(dev); | 174 | return; |
175 | goto done; | ||
176 | } | 175 | } |
177 | 176 | ||
178 | /* next block addr */ | 177 | /* next block addr */ |
@@ -194,6 +193,7 @@ void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status) | |||
194 | snd_pcm_period_elapsed(dev->dmasound.substream); | 193 | snd_pcm_period_elapsed(dev->dmasound.substream); |
195 | spin_lock(&dev->slock); | 194 | spin_lock(&dev->slock); |
196 | } | 195 | } |
196 | |||
197 | done: | 197 | done: |
198 | spin_unlock(&dev->slock); | 198 | spin_unlock(&dev->slock); |
199 | 199 | ||
@@ -209,7 +209,9 @@ void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status) | |||
209 | 209 | ||
210 | static irqreturn_t saa7134_alsa_irq(int irq, void *dev_id, struct pt_regs *regs) | 210 | static irqreturn_t saa7134_alsa_irq(int irq, void *dev_id, struct pt_regs *regs) |
211 | { | 211 | { |
212 | struct saa7134_dev *dev = (struct saa7134_dev*) dev_id; | 212 | struct saa7134_dmasound *dmasound = dev_id; |
213 | struct saa7134_dev *dev = dmasound->priv_data; | ||
214 | |||
213 | unsigned long report, status; | 215 | unsigned long report, status; |
214 | int loop, handled = 0; | 216 | int loop, handled = 0; |
215 | 217 | ||
@@ -248,56 +250,23 @@ static int snd_card_saa7134_capture_trigger(snd_pcm_substream_t * substream, | |||
248 | int cmd) | 250 | int cmd) |
249 | { | 251 | { |
250 | snd_pcm_runtime_t *runtime = substream->runtime; | 252 | snd_pcm_runtime_t *runtime = substream->runtime; |
251 | snd_card_saa7134_pcm_t *saapcm = runtime->private_data; | 253 | snd_card_saa7134_pcm_t *pcm = runtime->private_data; |
252 | struct saa7134_dev *dev=saapcm->saadev; | 254 | struct saa7134_dev *dev=pcm->dev; |
253 | int err = 0; | 255 | int err = 0; |
254 | 256 | ||
255 | spin_lock_irq(&dev->slock); | 257 | spin_lock(&dev->slock); |
256 | if (cmd == SNDRV_PCM_TRIGGER_START) { | 258 | if (cmd == SNDRV_PCM_TRIGGER_START) { |
257 | /* start dma */ | 259 | /* start dma */ |
258 | saa7134_dma_start(dev); | 260 | saa7134_dma_start(dev); |
259 | } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { | 261 | } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { |
260 | /* stop dma */ | 262 | /* stop dma */ |
261 | saa7134_dma_stop(dev); | 263 | saa7134_dma_stop(dev); |
262 | } else { | 264 | } else { |
263 | err = -EINVAL; | 265 | err = -EINVAL; |
264 | } | 266 | } |
265 | spin_unlock_irq(&dev->slock); | 267 | spin_unlock(&dev->slock); |
266 | |||
267 | return err; | ||
268 | } | ||
269 | |||
270 | /* | ||
271 | * DMA buffer config | ||
272 | * | ||
273 | * Sets the values that will later be used as the size of the buffer, | ||
274 | * size of the fragments, and total number of fragments. | ||
275 | * Must be called during the preparation stage, before memory is | ||
276 | * allocated | ||
277 | * | ||
278 | * - Copied verbatim from saa7134-oss. Can be dropped | ||
279 | * if we just share dsp_buffer_conf from OSS. | ||
280 | */ | ||
281 | 268 | ||
282 | static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) | 269 | return err; |
283 | { | ||
284 | if (blksize < 0x100) | ||
285 | blksize = 0x100; | ||
286 | if (blksize > 0x10000) | ||
287 | blksize = 0x10000; | ||
288 | |||
289 | if (blocks < 2) | ||
290 | blocks = 2; | ||
291 | if ((blksize * blocks) > 1024*1024) | ||
292 | blocks = 1024*1024 / blksize; | ||
293 | |||
294 | dev->dmasound.blocks = blocks; | ||
295 | dev->dmasound.blksize = blksize; | ||
296 | dev->dmasound.bufsize = blksize * blocks; | ||
297 | |||
298 | dprintk("buffer config: %d blocks / %d bytes, %d kB total\n", | ||
299 | blocks,blksize,blksize * blocks / 1024); | ||
300 | return 0; | ||
301 | } | 270 | } |
302 | 271 | ||
303 | /* | 272 | /* |
@@ -307,16 +276,16 @@ static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) | |||
307 | * ALSA, but I was unable to use ALSA's own DMA, and had to force the | 276 | * ALSA, but I was unable to use ALSA's own DMA, and had to force the |
308 | * usage of V4L's | 277 | * usage of V4L's |
309 | * | 278 | * |
310 | * - Copied verbatim from saa7134-oss. Can be dropped | 279 | * - Copied verbatim from saa7134-oss. |
311 | * if we just share dsp_buffer_init from OSS. | 280 | * |
312 | */ | 281 | */ |
313 | 282 | ||
314 | static int dsp_buffer_init(struct saa7134_dev *dev) | 283 | static int dsp_buffer_init(struct saa7134_dev *dev) |
315 | { | 284 | { |
316 | int err; | 285 | int err; |
317 | 286 | ||
318 | if (!dev->dmasound.bufsize) | 287 | BUG_ON(!dev->dmasound.bufsize); |
319 | BUG(); | 288 | |
320 | videobuf_dma_init(&dev->dmasound.dma); | 289 | videobuf_dma_init(&dev->dmasound.dma); |
321 | err = videobuf_dma_init_kernel(&dev->dmasound.dma, PCI_DMA_FROMDEVICE, | 290 | err = videobuf_dma_init_kernel(&dev->dmasound.dma, PCI_DMA_FROMDEVICE, |
322 | (dev->dmasound.bufsize + PAGE_SIZE) >> PAGE_SHIFT); | 291 | (dev->dmasound.bufsize + PAGE_SIZE) >> PAGE_SHIFT); |
@@ -326,6 +295,28 @@ static int dsp_buffer_init(struct saa7134_dev *dev) | |||
326 | } | 295 | } |
327 | 296 | ||
328 | /* | 297 | /* |
298 | * DMA buffer release | ||
299 | * | ||
300 | * Called after closing the device, during snd_card_saa7134_capture_close | ||
301 | * | ||
302 | */ | ||
303 | |||
304 | static int dsp_buffer_free(struct saa7134_dev *dev) | ||
305 | { | ||
306 | if (!dev->dmasound.blksize) | ||
307 | BUG(); | ||
308 | |||
309 | videobuf_dma_free(&dev->dmasound.dma); | ||
310 | |||
311 | dev->dmasound.blocks = 0; | ||
312 | dev->dmasound.blksize = 0; | ||
313 | dev->dmasound.bufsize = 0; | ||
314 | |||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | |||
319 | /* | ||
329 | * ALSA PCM preparation | 320 | * ALSA PCM preparation |
330 | * | 321 | * |
331 | * - One of the ALSA capture callbacks. | 322 | * - One of the ALSA capture callbacks. |
@@ -340,84 +331,30 @@ static int dsp_buffer_init(struct saa7134_dev *dev) | |||
340 | static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) | 331 | static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) |
341 | { | 332 | { |
342 | snd_pcm_runtime_t *runtime = substream->runtime; | 333 | snd_pcm_runtime_t *runtime = substream->runtime; |
343 | int err, bswap, sign; | 334 | int bswap, sign; |
344 | u32 fmt, control; | 335 | u32 fmt, control; |
345 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); | 336 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); |
346 | struct saa7134_dev *dev; | 337 | struct saa7134_dev *dev; |
347 | snd_card_saa7134_pcm_t *saapcm = runtime->private_data; | 338 | snd_card_saa7134_pcm_t *pcm = runtime->private_data; |
348 | unsigned int bps; | ||
349 | unsigned long size; | ||
350 | unsigned count; | ||
351 | |||
352 | size = snd_pcm_lib_buffer_bytes(substream); | ||
353 | count = snd_pcm_lib_period_bytes(substream); | ||
354 | |||
355 | saapcm->saadev->dmasound.substream = substream; | ||
356 | bps = runtime->rate * runtime->channels; | ||
357 | bps *= snd_pcm_format_width(runtime->format); | ||
358 | bps /= 8; | ||
359 | if (bps <= 0) | ||
360 | return -EINVAL; | ||
361 | saapcm->pcm_bps = bps; | ||
362 | saapcm->pcm_size = snd_pcm_lib_buffer_bytes(substream); | ||
363 | saapcm->pcm_count = snd_pcm_lib_period_bytes(substream); | ||
364 | |||
365 | 339 | ||
366 | dev=saa7134->saadev; | 340 | pcm->dev->dmasound.substream = substream; |
367 | 341 | ||
368 | dsp_buffer_conf(dev,saapcm->pcm_count,(saapcm->pcm_size/saapcm->pcm_count)); | 342 | dev = saa7134->dev; |
369 | 343 | ||
370 | err = dsp_buffer_init(dev); | 344 | if (snd_pcm_format_width(runtime->format) == 8) |
371 | if (0 != err) | ||
372 | goto fail2; | ||
373 | |||
374 | /* prepare buffer */ | ||
375 | if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->dmasound.dma))) | ||
376 | return err; | ||
377 | if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) | ||
378 | goto fail1; | ||
379 | if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->dmasound.pt, | ||
380 | dev->dmasound.dma.sglist, | ||
381 | dev->dmasound.dma.sglen, | ||
382 | 0))) | ||
383 | goto fail2; | ||
384 | |||
385 | |||
386 | |||
387 | switch (runtime->format) { | ||
388 | case SNDRV_PCM_FORMAT_U8: | ||
389 | case SNDRV_PCM_FORMAT_S8: | ||
390 | fmt = 0x00; | 345 | fmt = 0x00; |
391 | break; | 346 | else |
392 | case SNDRV_PCM_FORMAT_U16_LE: | ||
393 | case SNDRV_PCM_FORMAT_U16_BE: | ||
394 | case SNDRV_PCM_FORMAT_S16_LE: | ||
395 | case SNDRV_PCM_FORMAT_S16_BE: | ||
396 | fmt = 0x01; | 347 | fmt = 0x01; |
397 | break; | ||
398 | default: | ||
399 | err = -EINVAL; | ||
400 | return 1; | ||
401 | } | ||
402 | 348 | ||
403 | switch (runtime->format) { | 349 | if (snd_pcm_format_signed(runtime->format)) |
404 | case SNDRV_PCM_FORMAT_S8: | ||
405 | case SNDRV_PCM_FORMAT_S16_LE: | ||
406 | case SNDRV_PCM_FORMAT_S16_BE: | ||
407 | sign = 1; | 350 | sign = 1; |
408 | break; | 351 | else |
409 | default: | ||
410 | sign = 0; | 352 | sign = 0; |
411 | break; | ||
412 | } | ||
413 | 353 | ||
414 | switch (runtime->format) { | 354 | if (snd_pcm_format_big_endian(runtime->format)) |
415 | case SNDRV_PCM_FORMAT_U16_BE: | 355 | bswap = 1; |
416 | case SNDRV_PCM_FORMAT_S16_BE: | 356 | else |
417 | bswap = 1; break; | 357 | bswap = 0; |
418 | default: | ||
419 | bswap = 0; break; | ||
420 | } | ||
421 | 358 | ||
422 | switch (dev->pci->device) { | 359 | switch (dev->pci->device) { |
423 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | 360 | case PCI_DEVICE_ID_PHILIPS_SAA7134: |
@@ -445,7 +382,6 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) | |||
445 | fmt |= 0x04; | 382 | fmt |= 0x04; |
446 | saa_writel(SAA7133_NUM_SAMPLES, dev->dmasound.blksize -1); | 383 | saa_writel(SAA7133_NUM_SAMPLES, dev->dmasound.blksize -1); |
447 | saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24)); | 384 | saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24)); |
448 | //saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210); | ||
449 | break; | 385 | break; |
450 | } | 386 | } |
451 | 387 | ||
@@ -459,12 +395,6 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) | |||
459 | if (bswap) | 395 | if (bswap) |
460 | control |= SAA7134_RS_CONTROL_BSWAP; | 396 | control |= SAA7134_RS_CONTROL_BSWAP; |
461 | 397 | ||
462 | /* I should be able to use runtime->dma_addr in the control | ||
463 | byte, but it doesn't work. So I allocate the DMA using the | ||
464 | V4L functions, and force ALSA to use that as the DMA area */ | ||
465 | |||
466 | runtime->dma_area = dev->dmasound.dma.vmalloc; | ||
467 | |||
468 | saa_writel(SAA7134_RS_BA1(6),0); | 398 | saa_writel(SAA7134_RS_BA1(6),0); |
469 | saa_writel(SAA7134_RS_BA2(6),dev->dmasound.blksize); | 399 | saa_writel(SAA7134_RS_BA2(6),dev->dmasound.blksize); |
470 | saa_writel(SAA7134_RS_PITCH(6),0); | 400 | saa_writel(SAA7134_RS_PITCH(6),0); |
@@ -473,12 +403,6 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) | |||
473 | dev->dmasound.rate = runtime->rate; | 403 | dev->dmasound.rate = runtime->rate; |
474 | 404 | ||
475 | return 0; | 405 | return 0; |
476 | fail2: | ||
477 | saa7134_pgtable_free(dev->pci,&dev->dmasound.pt); | ||
478 | fail1: | ||
479 | videobuf_dma_pci_unmap(dev->pci,&dev->dmasound.dma); | ||
480 | return err; | ||
481 | |||
482 | 406 | ||
483 | } | 407 | } |
484 | 408 | ||
@@ -496,10 +420,8 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) | |||
496 | static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * substream) | 420 | static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * substream) |
497 | { | 421 | { |
498 | snd_pcm_runtime_t *runtime = substream->runtime; | 422 | snd_pcm_runtime_t *runtime = substream->runtime; |
499 | snd_card_saa7134_pcm_t *saapcm = runtime->private_data; | 423 | snd_card_saa7134_pcm_t *pcm = runtime->private_data; |
500 | struct saa7134_dev *dev=saapcm->saadev; | 424 | struct saa7134_dev *dev=pcm->dev; |
501 | |||
502 | |||
503 | 425 | ||
504 | if (dev->dmasound.read_count) { | 426 | if (dev->dmasound.read_count) { |
505 | dev->dmasound.read_count -= snd_pcm_lib_period_bytes(substream); | 427 | dev->dmasound.read_count -= snd_pcm_lib_period_bytes(substream); |
@@ -540,9 +462,9 @@ static snd_pcm_hardware_t snd_card_saa7134_capture = | |||
540 | 462 | ||
541 | static void snd_card_saa7134_runtime_free(snd_pcm_runtime_t *runtime) | 463 | static void snd_card_saa7134_runtime_free(snd_pcm_runtime_t *runtime) |
542 | { | 464 | { |
543 | snd_card_saa7134_pcm_t *saapcm = runtime->private_data; | 465 | snd_card_saa7134_pcm_t *pcm = runtime->private_data; |
544 | 466 | ||
545 | kfree(saapcm); | 467 | kfree(pcm); |
546 | } | 468 | } |
547 | 469 | ||
548 | 470 | ||
@@ -552,17 +474,76 @@ static void snd_card_saa7134_runtime_free(snd_pcm_runtime_t *runtime) | |||
552 | * - One of the ALSA capture callbacks. | 474 | * - One of the ALSA capture callbacks. |
553 | * | 475 | * |
554 | * Called on initialization, right before the PCM preparation | 476 | * Called on initialization, right before the PCM preparation |
555 | * Usually used in ALSA to allocate the DMA, but since we don't use the | ||
556 | * ALSA DMA it does nothing | ||
557 | * | 477 | * |
558 | */ | 478 | */ |
559 | 479 | ||
560 | static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream, | 480 | static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream, |
561 | snd_pcm_hw_params_t * hw_params) | 481 | snd_pcm_hw_params_t * hw_params) |
562 | { | 482 | { |
483 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); | ||
484 | struct saa7134_dev *dev; | ||
485 | unsigned int period_size, periods; | ||
486 | int err; | ||
563 | 487 | ||
564 | return 0; | 488 | period_size = params_period_bytes(hw_params); |
489 | periods = params_periods(hw_params); | ||
490 | |||
491 | snd_assert(period_size >= 0x100 && period_size <= 0x10000, | ||
492 | return -EINVAL); | ||
493 | snd_assert(periods >= 2, return -EINVAL); | ||
494 | snd_assert(period_size * periods <= 1024 * 1024, return -EINVAL); | ||
565 | 495 | ||
496 | dev = saa7134->dev; | ||
497 | |||
498 | if (dev->dmasound.blocks == periods && | ||
499 | dev->dmasound.blksize == period_size) | ||
500 | return 0; | ||
501 | |||
502 | /* release the old buffer */ | ||
503 | if (substream->runtime->dma_area) { | ||
504 | saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); | ||
505 | videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma); | ||
506 | dsp_buffer_free(dev); | ||
507 | substream->runtime->dma_area = NULL; | ||
508 | } | ||
509 | dev->dmasound.blocks = periods; | ||
510 | dev->dmasound.blksize = period_size; | ||
511 | dev->dmasound.bufsize = period_size * periods; | ||
512 | |||
513 | err = dsp_buffer_init(dev); | ||
514 | if (0 != err) { | ||
515 | dev->dmasound.blocks = 0; | ||
516 | dev->dmasound.blksize = 0; | ||
517 | dev->dmasound.bufsize = 0; | ||
518 | return err; | ||
519 | } | ||
520 | |||
521 | if (0 != (err = videobuf_dma_pci_map(dev->pci, &dev->dmasound.dma))) { | ||
522 | dsp_buffer_free(dev); | ||
523 | return err; | ||
524 | } | ||
525 | if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) { | ||
526 | videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma); | ||
527 | dsp_buffer_free(dev); | ||
528 | return err; | ||
529 | } | ||
530 | if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->dmasound.pt, | ||
531 | dev->dmasound.dma.sglist, | ||
532 | dev->dmasound.dma.sglen, | ||
533 | 0))) { | ||
534 | saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); | ||
535 | videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma); | ||
536 | dsp_buffer_free(dev); | ||
537 | return err; | ||
538 | } | ||
539 | |||
540 | /* I should be able to use runtime->dma_addr in the control | ||
541 | byte, but it doesn't work. So I allocate the DMA using the | ||
542 | V4L functions, and force ALSA to use that as the DMA area */ | ||
543 | |||
544 | substream->runtime->dma_area = dev->dmasound.dma.vmalloc; | ||
545 | |||
546 | return 1; | ||
566 | 547 | ||
567 | } | 548 | } |
568 | 549 | ||
@@ -572,33 +553,23 @@ static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream, | |||
572 | * - One of the ALSA capture callbacks. | 553 | * - One of the ALSA capture callbacks. |
573 | * | 554 | * |
574 | * Called after closing the device, but before snd_card_saa7134_capture_close | 555 | * Called after closing the device, but before snd_card_saa7134_capture_close |
575 | * Usually used in ALSA to free the DMA, but since we don't use the | 556 | * It stops the DMA audio and releases the buffers. |
576 | * ALSA DMA I'm almost sure this isn't necessary. | ||
577 | * | 557 | * |
578 | */ | 558 | */ |
579 | 559 | ||
580 | static int snd_card_saa7134_hw_free(snd_pcm_substream_t * substream) | 560 | static int snd_card_saa7134_hw_free(snd_pcm_substream_t * substream) |
581 | { | 561 | { |
582 | return 0; | 562 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); |
583 | } | 563 | struct saa7134_dev *dev; |
584 | |||
585 | /* | ||
586 | * DMA buffer release | ||
587 | * | ||
588 | * Called after closing the device, during snd_card_saa7134_capture_close | ||
589 | * | ||
590 | */ | ||
591 | |||
592 | static int dsp_buffer_free(struct saa7134_dev *dev) | ||
593 | { | ||
594 | if (!dev->dmasound.blksize) | ||
595 | BUG(); | ||
596 | 564 | ||
597 | videobuf_dma_free(&dev->dmasound.dma); | 565 | dev = saa7134->dev; |
598 | 566 | ||
599 | dev->dmasound.blocks = 0; | 567 | if (substream->runtime->dma_area) { |
600 | dev->dmasound.blksize = 0; | 568 | saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); |
601 | dev->dmasound.bufsize = 0; | 569 | videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma); |
570 | dsp_buffer_free(dev); | ||
571 | substream->runtime->dma_area = NULL; | ||
572 | } | ||
602 | 573 | ||
603 | return 0; | 574 | return 0; |
604 | } | 575 | } |
@@ -608,21 +579,12 @@ static int dsp_buffer_free(struct saa7134_dev *dev) | |||
608 | * | 579 | * |
609 | * - One of the ALSA capture callbacks. | 580 | * - One of the ALSA capture callbacks. |
610 | * | 581 | * |
611 | * Called after closing the device. It stops the DMA audio and releases | 582 | * Called after closing the device. |
612 | * the buffers | ||
613 | * | 583 | * |
614 | */ | 584 | */ |
615 | 585 | ||
616 | static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream) | 586 | static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream) |
617 | { | 587 | { |
618 | snd_card_saa7134_t *chip = snd_pcm_substream_chip(substream); | ||
619 | struct saa7134_dev *dev = chip->saadev; | ||
620 | |||
621 | /* unlock buffer */ | ||
622 | saa7134_pgtable_free(dev->pci,&dev->dmasound.pt); | ||
623 | videobuf_dma_pci_unmap(dev->pci,&dev->dmasound.dma); | ||
624 | |||
625 | dsp_buffer_free(dev); | ||
626 | return 0; | 588 | return 0; |
627 | } | 589 | } |
628 | 590 | ||
@@ -639,29 +601,28 @@ static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream) | |||
639 | static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream) | 601 | static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream) |
640 | { | 602 | { |
641 | snd_pcm_runtime_t *runtime = substream->runtime; | 603 | snd_pcm_runtime_t *runtime = substream->runtime; |
642 | snd_card_saa7134_pcm_t *saapcm; | 604 | snd_card_saa7134_pcm_t *pcm; |
643 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); | 605 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); |
644 | struct saa7134_dev *dev = saa7134->saadev; | 606 | struct saa7134_dev *dev = saa7134->dev; |
645 | int err; | 607 | int err; |
646 | 608 | ||
647 | down(&dev->dmasound.lock); | 609 | down(&dev->dmasound.lock); |
648 | 610 | ||
649 | dev->dmasound.afmt = SNDRV_PCM_FORMAT_U8; | ||
650 | dev->dmasound.channels = 2; | ||
651 | dev->dmasound.read_count = 0; | 611 | dev->dmasound.read_count = 0; |
652 | dev->dmasound.read_offset = 0; | 612 | dev->dmasound.read_offset = 0; |
653 | 613 | ||
654 | up(&dev->dmasound.lock); | 614 | up(&dev->dmasound.lock); |
655 | 615 | ||
656 | saapcm = kzalloc(sizeof(*saapcm), GFP_KERNEL); | 616 | pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); |
657 | if (saapcm == NULL) | 617 | if (pcm == NULL) |
658 | return -ENOMEM; | 618 | return -ENOMEM; |
659 | saapcm->saadev=saa7134->saadev; | ||
660 | 619 | ||
661 | spin_lock_init(&saapcm->lock); | 620 | pcm->dev=saa7134->dev; |
662 | 621 | ||
663 | saapcm->substream = substream; | 622 | spin_lock_init(&pcm->lock); |
664 | runtime->private_data = saapcm; | 623 | |
624 | pcm->substream = substream; | ||
625 | runtime->private_data = pcm; | ||
665 | runtime->private_free = snd_card_saa7134_runtime_free; | 626 | runtime->private_free = snd_card_saa7134_runtime_free; |
666 | runtime->hw = snd_card_saa7134_capture; | 627 | runtime->hw = snd_card_saa7134_capture; |
667 | 628 | ||
@@ -736,7 +697,6 @@ static int snd_saa7134_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ | |||
736 | static int snd_saa7134_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | 697 | static int snd_saa7134_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) |
737 | { | 698 | { |
738 | snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); | 699 | snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); |
739 | unsigned long flags; | ||
740 | int change, addr = kcontrol->private_value; | 700 | int change, addr = kcontrol->private_value; |
741 | int left, right; | 701 | int left, right; |
742 | 702 | ||
@@ -750,12 +710,12 @@ static int snd_saa7134_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ | |||
750 | right = 0; | 710 | right = 0; |
751 | if (right > 20) | 711 | if (right > 20) |
752 | right = 20; | 712 | right = 20; |
753 | spin_lock_irqsave(&chip->mixer_lock, flags); | 713 | spin_lock_irq(&chip->mixer_lock); |
754 | change = chip->mixer_volume[addr][0] != left || | 714 | change = chip->mixer_volume[addr][0] != left || |
755 | chip->mixer_volume[addr][1] != right; | 715 | chip->mixer_volume[addr][1] != right; |
756 | chip->mixer_volume[addr][0] = left; | 716 | chip->mixer_volume[addr][0] = left; |
757 | chip->mixer_volume[addr][1] = right; | 717 | chip->mixer_volume[addr][1] = right; |
758 | spin_unlock_irqrestore(&chip->mixer_lock, flags); | 718 | spin_unlock_irq(&chip->mixer_lock); |
759 | return change; | 719 | return change; |
760 | } | 720 | } |
761 | 721 | ||
@@ -777,38 +737,37 @@ static int snd_saa7134_capsrc_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_ | |||
777 | static int snd_saa7134_capsrc_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | 737 | static int snd_saa7134_capsrc_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) |
778 | { | 738 | { |
779 | snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); | 739 | snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); |
780 | unsigned long flags; | ||
781 | int addr = kcontrol->private_value; | 740 | int addr = kcontrol->private_value; |
782 | 741 | ||
783 | spin_lock_irqsave(&chip->mixer_lock, flags); | 742 | spin_lock_irq(&chip->mixer_lock); |
784 | ucontrol->value.integer.value[0] = chip->capture_source[addr][0]; | 743 | ucontrol->value.integer.value[0] = chip->capture_source[addr][0]; |
785 | ucontrol->value.integer.value[1] = chip->capture_source[addr][1]; | 744 | ucontrol->value.integer.value[1] = chip->capture_source[addr][1]; |
786 | spin_unlock_irqrestore(&chip->mixer_lock, flags); | 745 | spin_unlock_irq(&chip->mixer_lock); |
746 | |||
787 | return 0; | 747 | return 0; |
788 | } | 748 | } |
789 | 749 | ||
790 | static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | 750 | static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) |
791 | { | 751 | { |
792 | snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); | 752 | snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); |
793 | unsigned long flags; | ||
794 | int change, addr = kcontrol->private_value; | 753 | int change, addr = kcontrol->private_value; |
795 | int left, right; | 754 | int left, right; |
796 | u32 anabar, xbarin; | 755 | u32 anabar, xbarin; |
797 | int analog_io, rate; | 756 | int analog_io, rate; |
798 | struct saa7134_dev *dev; | 757 | struct saa7134_dev *dev; |
799 | 758 | ||
800 | dev = chip->saadev; | 759 | dev = chip->dev; |
801 | 760 | ||
802 | left = ucontrol->value.integer.value[0] & 1; | 761 | left = ucontrol->value.integer.value[0] & 1; |
803 | right = ucontrol->value.integer.value[1] & 1; | 762 | right = ucontrol->value.integer.value[1] & 1; |
804 | spin_lock_irqsave(&chip->mixer_lock, flags); | 763 | spin_lock_irq(&chip->mixer_lock); |
805 | 764 | ||
806 | change = chip->capture_source[addr][0] != left || | 765 | change = chip->capture_source[addr][0] != left || |
807 | chip->capture_source[addr][1] != right; | 766 | chip->capture_source[addr][1] != right; |
808 | chip->capture_source[addr][0] = left; | 767 | chip->capture_source[addr][0] = left; |
809 | chip->capture_source[addr][1] = right; | 768 | chip->capture_source[addr][1] = right; |
810 | dev->dmasound.input=addr; | 769 | dev->dmasound.input=addr; |
811 | spin_unlock_irqrestore(&chip->mixer_lock, flags); | 770 | spin_unlock_irq(&chip->mixer_lock); |
812 | 771 | ||
813 | 772 | ||
814 | if (change) { | 773 | if (change) { |
@@ -898,43 +857,44 @@ static int snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip) | |||
898 | return 0; | 857 | return 0; |
899 | } | 858 | } |
900 | 859 | ||
901 | static int snd_saa7134_free(snd_card_saa7134_t *chip) | 860 | static void snd_saa7134_free(snd_card_t * card) |
902 | { | 861 | { |
903 | return 0; | 862 | snd_card_saa7134_t *chip = card->private_data; |
904 | } | 863 | |
864 | if (chip->dev->dmasound.priv_data == NULL) | ||
865 | return; | ||
866 | |||
867 | if (chip->irq >= 0) { | ||
868 | synchronize_irq(chip->irq); | ||
869 | free_irq(chip->irq, &chip->dev->dmasound); | ||
870 | } | ||
871 | |||
872 | chip->dev->dmasound.priv_data = NULL; | ||
905 | 873 | ||
906 | static int snd_saa7134_dev_free(snd_device_t *device) | ||
907 | { | ||
908 | snd_card_saa7134_t *chip = device->device_data; | ||
909 | return snd_saa7134_free(chip); | ||
910 | } | 874 | } |
911 | 875 | ||
912 | /* | 876 | /* |
913 | * ALSA initialization | 877 | * ALSA initialization |
914 | * | 878 | * |
915 | * Called by saa7134-core, it creates the basic structures and registers | 879 | * Called by the init routine, once for each saa7134 device present, |
916 | * the ALSA devices | 880 | * it creates the basic structures and registers the ALSA devices |
917 | * | 881 | * |
918 | */ | 882 | */ |
919 | 883 | ||
920 | int alsa_card_saa7134_create (struct saa7134_dev *saadev) | 884 | int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum) |
921 | { | 885 | { |
922 | static int dev; | ||
923 | 886 | ||
924 | snd_card_t *card; | 887 | snd_card_t *card; |
925 | snd_card_saa7134_t *chip; | 888 | snd_card_saa7134_t *chip; |
926 | int err; | 889 | int err; |
927 | static snd_device_ops_t ops = { | ||
928 | .dev_free = snd_saa7134_dev_free, | ||
929 | }; | ||
930 | 890 | ||
931 | 891 | ||
932 | if (dev >= SNDRV_CARDS) | 892 | if (devnum >= SNDRV_CARDS) |
933 | return -ENODEV; | 893 | return -ENODEV; |
934 | if (!enable[dev]) | 894 | if (!enable[devnum]) |
935 | return -ENODEV; | 895 | return -ENODEV; |
936 | 896 | ||
937 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 897 | card = snd_card_new(index[devnum], id[devnum], THIS_MODULE, sizeof(snd_card_saa7134_t)); |
938 | 898 | ||
939 | if (card == NULL) | 899 | if (card == NULL) |
940 | return -ENOMEM; | 900 | return -ENOMEM; |
@@ -943,34 +903,33 @@ int alsa_card_saa7134_create (struct saa7134_dev *saadev) | |||
943 | 903 | ||
944 | /* Card "creation" */ | 904 | /* Card "creation" */ |
945 | 905 | ||
946 | chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); | 906 | card->private_free = snd_saa7134_free; |
947 | if (chip == NULL) { | 907 | chip = (snd_card_saa7134_t *) card->private_data; |
948 | return -ENOMEM; | ||
949 | } | ||
950 | 908 | ||
951 | spin_lock_init(&chip->lock); | 909 | spin_lock_init(&chip->lock); |
952 | spin_lock_init(&chip->mixer_lock); | 910 | spin_lock_init(&chip->mixer_lock); |
953 | 911 | ||
954 | chip->saadev = saadev; | 912 | chip->dev = dev; |
955 | 913 | ||
956 | chip->card = card; | 914 | chip->card = card; |
957 | 915 | ||
958 | chip->pci = saadev->pci; | 916 | chip->pci = dev->pci; |
959 | chip->irq = saadev->pci->irq; | 917 | chip->iobase = pci_resource_start(dev->pci, 0); |
960 | chip->iobase = pci_resource_start(saadev->pci, 0); | ||
961 | 918 | ||
962 | err = request_irq(saadev->pci->irq, saa7134_alsa_irq, | 919 | |
963 | SA_SHIRQ | SA_INTERRUPT, saadev->name, saadev); | 920 | err = request_irq(dev->pci->irq, saa7134_alsa_irq, |
921 | SA_SHIRQ | SA_INTERRUPT, dev->name, | ||
922 | (void*) &dev->dmasound); | ||
964 | 923 | ||
965 | if (err < 0) { | 924 | if (err < 0) { |
966 | printk(KERN_ERR "%s: can't get IRQ %d for ALSA\n", | 925 | printk(KERN_ERR "%s: can't get IRQ %d for ALSA\n", |
967 | saadev->name, saadev->pci->irq); | 926 | dev->name, dev->pci->irq); |
968 | goto __nodev; | 927 | goto __nodev; |
969 | } | 928 | } |
970 | 929 | ||
971 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { | 930 | chip->irq = dev->pci->irq; |
972 | goto __nodev; | 931 | |
973 | } | 932 | init_MUTEX(&dev->dmasound.lock); |
974 | 933 | ||
975 | if ((err = snd_card_saa7134_new_mixer(chip)) < 0) | 934 | if ((err = snd_card_saa7134_new_mixer(chip)) < 0) |
976 | goto __nodev; | 935 | goto __nodev; |
@@ -984,16 +943,15 @@ int alsa_card_saa7134_create (struct saa7134_dev *saadev) | |||
984 | 943 | ||
985 | strcpy(card->shortname, "SAA7134"); | 944 | strcpy(card->shortname, "SAA7134"); |
986 | sprintf(card->longname, "%s at 0x%lx irq %d", | 945 | sprintf(card->longname, "%s at 0x%lx irq %d", |
987 | chip->saadev->name, chip->iobase, chip->irq); | 946 | chip->dev->name, chip->iobase, chip->irq); |
988 | 947 | ||
989 | if ((err = snd_card_register(card)) == 0) { | 948 | if ((err = snd_card_register(card)) == 0) { |
990 | snd_saa7134_cards[dev] = card; | 949 | snd_saa7134_cards[devnum] = card; |
991 | return 0; | 950 | return 0; |
992 | } | 951 | } |
993 | 952 | ||
994 | __nodev: | 953 | __nodev: |
995 | snd_card_free(card); | 954 | snd_card_free(card); |
996 | kfree(chip); | ||
997 | return err; | 955 | return err; |
998 | } | 956 | } |
999 | 957 | ||
@@ -1007,21 +965,29 @@ __nodev: | |||
1007 | 965 | ||
1008 | static int saa7134_alsa_init(void) | 966 | static int saa7134_alsa_init(void) |
1009 | { | 967 | { |
1010 | struct saa7134_dev *saadev = NULL; | 968 | struct saa7134_dev *dev = NULL; |
1011 | struct list_head *list; | 969 | struct list_head *list; |
1012 | 970 | ||
1013 | printk(KERN_INFO "saa7134 ALSA driver for DMA sound loaded\n"); | 971 | position = 0; |
1014 | 972 | ||
1015 | list_for_each(list,&saa7134_devlist) { | 973 | printk(KERN_INFO "saa7134 ALSA driver for DMA sound loaded\n"); |
1016 | saadev = list_entry(list, struct saa7134_dev, devlist); | ||
1017 | alsa_card_saa7134_create(saadev); | ||
1018 | } | ||
1019 | 974 | ||
1020 | if (saadev == NULL) | 975 | list_for_each(list,&saa7134_devlist) { |
976 | dev = list_entry(list, struct saa7134_dev, devlist); | ||
977 | if (dev->dmasound.priv_data == NULL) { | ||
978 | dev->dmasound.priv_data = dev; | ||
979 | alsa_card_saa7134_create(dev,position); | ||
980 | position++; | ||
981 | } else { | ||
982 | printk(KERN_ERR "saa7134 ALSA: DMA sound is being handled by OSS. ignoring %s\n",dev->name); | ||
983 | return -EBUSY; | ||
984 | } | ||
985 | } | ||
986 | |||
987 | if (dev == NULL) | ||
1021 | printk(KERN_INFO "saa7134 ALSA: no saa7134 cards found\n"); | 988 | printk(KERN_INFO "saa7134 ALSA: no saa7134 cards found\n"); |
1022 | 989 | ||
1023 | return 0; | 990 | return 0; |
1024 | |||
1025 | } | 991 | } |
1026 | 992 | ||
1027 | /* | 993 | /* |
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 663d03e5bc67..75abc20b0ccd 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c | |||
@@ -2529,6 +2529,32 @@ struct saa7134_board saa7134_boards[] = { | |||
2529 | .amux = LINE1, | 2529 | .amux = LINE1, |
2530 | }}, | 2530 | }}, |
2531 | }, | 2531 | }, |
2532 | [SAA7134_BOARD_MSI_TVATANYWHERE_PLUS] = { | ||
2533 | .name = "MSI TV@Anywhere plus", | ||
2534 | .audio_clock = 0x00187de7, | ||
2535 | .tuner_type = TUNER_PHILIPS_TDA8290, | ||
2536 | .radio_type = UNSET, | ||
2537 | .tuner_addr = ADDR_UNSET, | ||
2538 | .radio_addr = ADDR_UNSET, | ||
2539 | .inputs = {{ | ||
2540 | .name = name_tv, | ||
2541 | .vmux = 1, | ||
2542 | .amux = TV, | ||
2543 | .tv = 1, | ||
2544 | },{ | ||
2545 | .name = name_comp1, | ||
2546 | .vmux = 3, | ||
2547 | .amux = LINE1, | ||
2548 | },{ | ||
2549 | .name = name_svideo, | ||
2550 | .vmux = 0, | ||
2551 | .amux = LINE1, | ||
2552 | }}, | ||
2553 | .radio = { | ||
2554 | .name = name_radio, | ||
2555 | .amux = LINE1, | ||
2556 | }, | ||
2557 | }, | ||
2532 | }; | 2558 | }; |
2533 | 2559 | ||
2534 | const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); | 2560 | const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); |
@@ -2970,6 +2996,12 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
2970 | .subdevice = 0x2018, | 2996 | .subdevice = 0x2018, |
2971 | .driver_data = SAA7134_BOARD_PHILIPS_TIGER, | 2997 | .driver_data = SAA7134_BOARD_PHILIPS_TIGER, |
2972 | },{ | 2998 | },{ |
2999 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
3000 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
3001 | .subvendor = 0x1462, | ||
3002 | .subdevice = 0x6231, | ||
3003 | .driver_data = SAA7134_BOARD_MSI_TVATANYWHERE_PLUS, | ||
3004 | },{ | ||
2973 | /* --- boards without eeprom + subsystem ID --- */ | 3005 | /* --- boards without eeprom + subsystem ID --- */ |
2974 | .vendor = PCI_VENDOR_ID_PHILIPS, | 3006 | .vendor = PCI_VENDOR_ID_PHILIPS, |
2975 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, | 3007 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, |
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 19b88744fb31..4275d2ddb864 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c | |||
@@ -53,13 +53,13 @@ static unsigned int gpio_tracking = 0; | |||
53 | module_param(gpio_tracking, int, 0644); | 53 | module_param(gpio_tracking, int, 0644); |
54 | MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]"); | 54 | MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]"); |
55 | 55 | ||
56 | static unsigned int oss = 0; | ||
57 | module_param(oss, int, 0444); | ||
58 | MODULE_PARM_DESC(oss,"register oss devices (default: no)"); | ||
59 | |||
60 | static unsigned int alsa = 0; | 56 | static unsigned int alsa = 0; |
61 | module_param(alsa, int, 0444); | 57 | module_param(alsa, int, 0644); |
62 | MODULE_PARM_DESC(alsa,"register alsa devices (default: no)"); | 58 | MODULE_PARM_DESC(alsa,"enable ALSA DMA sound [dmasound]"); |
59 | |||
60 | static unsigned int oss = 0; | ||
61 | module_param(oss, int, 0644); | ||
62 | MODULE_PARM_DESC(oss,"enable OSS DMA sound [dmasound]"); | ||
63 | 63 | ||
64 | static unsigned int latency = UNSET; | 64 | static unsigned int latency = UNSET; |
65 | module_param(latency, int, 0444); | 65 | module_param(latency, int, 0444); |
@@ -68,24 +68,18 @@ MODULE_PARM_DESC(latency,"pci latency timer"); | |||
68 | static unsigned int video_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; | 68 | static unsigned int video_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; |
69 | static unsigned int vbi_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; | 69 | static unsigned int vbi_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; |
70 | static unsigned int radio_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; | 70 | static unsigned int radio_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; |
71 | static unsigned int dsp_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; | ||
72 | static unsigned int mixer_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; | ||
73 | static unsigned int tuner[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; | 71 | static unsigned int tuner[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; |
74 | static unsigned int card[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; | 72 | static unsigned int card[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; |
75 | 73 | ||
76 | module_param_array(video_nr, int, NULL, 0444); | 74 | module_param_array(video_nr, int, NULL, 0444); |
77 | module_param_array(vbi_nr, int, NULL, 0444); | 75 | module_param_array(vbi_nr, int, NULL, 0444); |
78 | module_param_array(radio_nr, int, NULL, 0444); | 76 | module_param_array(radio_nr, int, NULL, 0444); |
79 | module_param_array(dsp_nr, int, NULL, 0444); | ||
80 | module_param_array(mixer_nr, int, NULL, 0444); | ||
81 | module_param_array(tuner, int, NULL, 0444); | 77 | module_param_array(tuner, int, NULL, 0444); |
82 | module_param_array(card, int, NULL, 0444); | 78 | module_param_array(card, int, NULL, 0444); |
83 | 79 | ||
84 | MODULE_PARM_DESC(video_nr, "video device number"); | 80 | MODULE_PARM_DESC(video_nr, "video device number"); |
85 | MODULE_PARM_DESC(vbi_nr, "vbi device number"); | 81 | MODULE_PARM_DESC(vbi_nr, "vbi device number"); |
86 | MODULE_PARM_DESC(radio_nr, "radio device number"); | 82 | MODULE_PARM_DESC(radio_nr, "radio device number"); |
87 | MODULE_PARM_DESC(dsp_nr, "oss dsp device number"); | ||
88 | MODULE_PARM_DESC(mixer_nr, "oss mixer device number"); | ||
89 | MODULE_PARM_DESC(tuner, "tuner type"); | 83 | MODULE_PARM_DESC(tuner, "tuner type"); |
90 | MODULE_PARM_DESC(card, "card type"); | 84 | MODULE_PARM_DESC(card, "card type"); |
91 | 85 | ||
@@ -195,6 +189,7 @@ void saa7134_track_gpio(struct saa7134_dev *dev, char *msg) | |||
195 | static int need_empress; | 189 | static int need_empress; |
196 | static int need_dvb; | 190 | static int need_dvb; |
197 | static int need_alsa; | 191 | static int need_alsa; |
192 | static int need_oss; | ||
198 | 193 | ||
199 | static int pending_call(struct notifier_block *self, unsigned long state, | 194 | static int pending_call(struct notifier_block *self, unsigned long state, |
200 | void *module) | 195 | void *module) |
@@ -208,6 +203,8 @@ static int pending_call(struct notifier_block *self, unsigned long state, | |||
208 | request_module("saa7134-dvb"); | 203 | request_module("saa7134-dvb"); |
209 | if (need_alsa) | 204 | if (need_alsa) |
210 | request_module("saa7134-alsa"); | 205 | request_module("saa7134-alsa"); |
206 | if (need_oss) | ||
207 | request_module("saa7134-oss"); | ||
211 | return NOTIFY_DONE; | 208 | return NOTIFY_DONE; |
212 | } | 209 | } |
213 | 210 | ||
@@ -218,10 +215,11 @@ static struct notifier_block pending_notifier = { | |||
218 | 215 | ||
219 | static void request_module_depend(char *name, int *flag) | 216 | static void request_module_depend(char *name, int *flag) |
220 | { | 217 | { |
218 | int err; | ||
221 | switch (THIS_MODULE->state) { | 219 | switch (THIS_MODULE->state) { |
222 | case MODULE_STATE_COMING: | 220 | case MODULE_STATE_COMING: |
223 | if (!pending_registered) { | 221 | if (!pending_registered) { |
224 | register_module_notifier(&pending_notifier); | 222 | err = register_module_notifier(&pending_notifier); |
225 | pending_registered = 1; | 223 | pending_registered = 1; |
226 | } | 224 | } |
227 | *flag = 1; | 225 | *flag = 1; |
@@ -578,12 +576,14 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs) | |||
578 | goto out; | 576 | goto out; |
579 | } | 577 | } |
580 | 578 | ||
581 | /* If alsa support is active and we get a sound report, exit | 579 | /* If dmasound support is active and we get a sound report, exit |
582 | and let the saa7134-alsa module deal with it */ | 580 | and let the saa7134-alsa/oss module deal with it */ |
583 | 581 | ||
584 | if ((report & SAA7134_IRQ_REPORT_DONE_RA3) && alsa) { | 582 | if ((report & SAA7134_IRQ_REPORT_DONE_RA3) && |
583 | (dev->dmasound.priv_data != NULL) ) | ||
584 | { | ||
585 | if (irq_debug > 1) | 585 | if (irq_debug > 1) |
586 | printk(KERN_DEBUG "%s/irq: ignoring interrupt for ALSA\n", | 586 | printk(KERN_DEBUG "%s/irq: ignoring interrupt for DMA sound\n", |
587 | dev->name); | 587 | dev->name); |
588 | goto out; | 588 | goto out; |
589 | } | 589 | } |
@@ -609,12 +609,6 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs) | |||
609 | card_has_mpeg(dev)) | 609 | card_has_mpeg(dev)) |
610 | saa7134_irq_ts_done(dev,status); | 610 | saa7134_irq_ts_done(dev,status); |
611 | 611 | ||
612 | if ((report & SAA7134_IRQ_REPORT_DONE_RA3)) { | ||
613 | if (oss) { | ||
614 | saa7134_irq_oss_done(dev,status); | ||
615 | } | ||
616 | } | ||
617 | |||
618 | if ((report & (SAA7134_IRQ_REPORT_GPIO16 | | 612 | if ((report & (SAA7134_IRQ_REPORT_GPIO16 | |
619 | SAA7134_IRQ_REPORT_GPIO18)) && | 613 | SAA7134_IRQ_REPORT_GPIO18)) && |
620 | dev->remote) | 614 | dev->remote) |
@@ -689,14 +683,6 @@ static int saa7134_hwinit1(struct saa7134_dev *dev) | |||
689 | * audio will not work. | 683 | * audio will not work. |
690 | */ | 684 | */ |
691 | 685 | ||
692 | switch (dev->pci->device) { | ||
693 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | ||
694 | case PCI_DEVICE_ID_PHILIPS_SAA7133: | ||
695 | case PCI_DEVICE_ID_PHILIPS_SAA7135: | ||
696 | saa7134_oss_init1(dev); | ||
697 | break; | ||
698 | } | ||
699 | |||
700 | /* enable peripheral devices */ | 686 | /* enable peripheral devices */ |
701 | saa_writeb(SAA7134_SPECIAL_MODE, 0x01); | 687 | saa_writeb(SAA7134_SPECIAL_MODE, 0x01); |
702 | 688 | ||
@@ -728,8 +714,6 @@ static int saa7134_hwinit2(struct saa7134_dev *dev) | |||
728 | irq2_mask |= (SAA7134_IRQ2_INTE_GPIO18 | | 714 | irq2_mask |= (SAA7134_IRQ2_INTE_GPIO18 | |
729 | SAA7134_IRQ2_INTE_GPIO18A | | 715 | SAA7134_IRQ2_INTE_GPIO18A | |
730 | SAA7134_IRQ2_INTE_GPIO16 ); | 716 | SAA7134_IRQ2_INTE_GPIO16 ); |
731 | else if (dev->has_remote == SAA7134_REMOTE_I2C) | ||
732 | request_module("ir-kbd-i2c"); | ||
733 | 717 | ||
734 | saa_writel(SAA7134_IRQ1, 0); | 718 | saa_writel(SAA7134_IRQ1, 0); |
735 | saa_writel(SAA7134_IRQ2, irq2_mask); | 719 | saa_writel(SAA7134_IRQ2, irq2_mask); |
@@ -742,13 +726,6 @@ static int saa7134_hwfini(struct saa7134_dev *dev) | |||
742 | { | 726 | { |
743 | dprintk("hwfini\n"); | 727 | dprintk("hwfini\n"); |
744 | 728 | ||
745 | switch (dev->pci->device) { | ||
746 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | ||
747 | case PCI_DEVICE_ID_PHILIPS_SAA7133: | ||
748 | case PCI_DEVICE_ID_PHILIPS_SAA7135: | ||
749 | saa7134_oss_fini(dev); | ||
750 | break; | ||
751 | } | ||
752 | if (card_has_mpeg(dev)) | 729 | if (card_has_mpeg(dev)) |
753 | saa7134_ts_fini(dev); | 730 | saa7134_ts_fini(dev); |
754 | saa7134_input_fini(dev); | 731 | saa7134_input_fini(dev); |
@@ -986,11 +963,12 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, | |||
986 | if (card_is_dvb(dev)) | 963 | if (card_is_dvb(dev)) |
987 | request_module_depend("saa7134-dvb",&need_dvb); | 964 | request_module_depend("saa7134-dvb",&need_dvb); |
988 | 965 | ||
989 | if (!oss && alsa) { | 966 | |
990 | dprintk("Requesting ALSA module\n"); | 967 | if (alsa) |
991 | request_module_depend("saa7134-alsa",&need_alsa); | 968 | request_module_depend("saa7134-alsa",&need_alsa); |
992 | } | ||
993 | 969 | ||
970 | if (oss) | ||
971 | request_module_depend("saa7134-oss",&need_oss); | ||
994 | 972 | ||
995 | v4l2_prio_init(&dev->prio); | 973 | v4l2_prio_init(&dev->prio); |
996 | 974 | ||
@@ -1024,32 +1002,6 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, | |||
1024 | dev->name,dev->radio_dev->minor & 0x1f); | 1002 | dev->name,dev->radio_dev->minor & 0x1f); |
1025 | } | 1003 | } |
1026 | 1004 | ||
1027 | /* register oss devices */ | ||
1028 | switch (dev->pci->device) { | ||
1029 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | ||
1030 | case PCI_DEVICE_ID_PHILIPS_SAA7133: | ||
1031 | case PCI_DEVICE_ID_PHILIPS_SAA7135: | ||
1032 | if (oss) { | ||
1033 | err = dev->dmasound.minor_dsp = | ||
1034 | register_sound_dsp(&saa7134_dsp_fops, | ||
1035 | dsp_nr[dev->nr]); | ||
1036 | if (err < 0) { | ||
1037 | goto fail4; | ||
1038 | } | ||
1039 | printk(KERN_INFO "%s: registered device dsp%d\n", | ||
1040 | dev->name,dev->dmasound.minor_dsp >> 4); | ||
1041 | |||
1042 | err = dev->dmasound.minor_mixer = | ||
1043 | register_sound_mixer(&saa7134_mixer_fops, | ||
1044 | mixer_nr[dev->nr]); | ||
1045 | if (err < 0) | ||
1046 | goto fail5; | ||
1047 | printk(KERN_INFO "%s: registered device mixer%d\n", | ||
1048 | dev->name,dev->dmasound.minor_mixer >> 4); | ||
1049 | } | ||
1050 | break; | ||
1051 | } | ||
1052 | |||
1053 | /* everything worked */ | 1005 | /* everything worked */ |
1054 | pci_set_drvdata(pci_dev,dev); | 1006 | pci_set_drvdata(pci_dev,dev); |
1055 | saa7134_devcount++; | 1007 | saa7134_devcount++; |
@@ -1064,17 +1016,9 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, | |||
1064 | 1016 | ||
1065 | /* check for signal */ | 1017 | /* check for signal */ |
1066 | saa7134_irq_video_intl(dev); | 1018 | saa7134_irq_video_intl(dev); |
1019 | |||
1067 | return 0; | 1020 | return 0; |
1068 | 1021 | ||
1069 | fail5: | ||
1070 | switch (dev->pci->device) { | ||
1071 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | ||
1072 | case PCI_DEVICE_ID_PHILIPS_SAA7133: | ||
1073 | case PCI_DEVICE_ID_PHILIPS_SAA7135: | ||
1074 | if (oss) | ||
1075 | unregister_sound_dsp(dev->dmasound.minor_dsp); | ||
1076 | break; | ||
1077 | } | ||
1078 | fail4: | 1022 | fail4: |
1079 | saa7134_unregister_video(dev); | 1023 | saa7134_unregister_video(dev); |
1080 | saa7134_i2c_unregister(dev); | 1024 | saa7134_i2c_unregister(dev); |
@@ -1125,19 +1069,16 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) | |||
1125 | saa7134_devcount--; | 1069 | saa7134_devcount--; |
1126 | 1070 | ||
1127 | saa7134_i2c_unregister(dev); | 1071 | saa7134_i2c_unregister(dev); |
1128 | switch (dev->pci->device) { | ||
1129 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | ||
1130 | case PCI_DEVICE_ID_PHILIPS_SAA7133: | ||
1131 | case PCI_DEVICE_ID_PHILIPS_SAA7135: | ||
1132 | if (oss) { | ||
1133 | unregister_sound_mixer(dev->dmasound.minor_mixer); | ||
1134 | unregister_sound_dsp(dev->dmasound.minor_dsp); | ||
1135 | } | ||
1136 | break; | ||
1137 | } | ||
1138 | saa7134_unregister_video(dev); | 1072 | saa7134_unregister_video(dev); |
1139 | 1073 | ||
1140 | /* release ressources */ | 1074 | /* the DMA sound modules should be unloaded before reaching |
1075 | this, but just in case they are still present... */ | ||
1076 | if (dev->dmasound.priv_data != NULL) { | ||
1077 | free_irq(pci_dev->irq, &dev->dmasound); | ||
1078 | dev->dmasound.priv_data = NULL; | ||
1079 | } | ||
1080 | |||
1081 | /* release resources */ | ||
1141 | free_irq(pci_dev->irq, dev); | 1082 | free_irq(pci_dev->irq, dev); |
1142 | iounmap(dev->lmmio); | 1083 | iounmap(dev->lmmio); |
1143 | release_mem_region(pci_resource_start(pci_dev,0), | 1084 | release_mem_region(pci_resource_start(pci_dev,0), |
@@ -1225,7 +1166,7 @@ EXPORT_SYMBOL(saa7134_i2c_call_clients); | |||
1225 | EXPORT_SYMBOL(saa7134_devlist); | 1166 | EXPORT_SYMBOL(saa7134_devlist); |
1226 | EXPORT_SYMBOL(saa7134_boards); | 1167 | EXPORT_SYMBOL(saa7134_boards); |
1227 | 1168 | ||
1228 | /* ----------------- For ALSA -------------------------------- */ | 1169 | /* ----------------- for the DMA sound modules --------------- */ |
1229 | 1170 | ||
1230 | EXPORT_SYMBOL(saa7134_pgtable_free); | 1171 | EXPORT_SYMBOL(saa7134_pgtable_free); |
1231 | EXPORT_SYMBOL(saa7134_pgtable_build); | 1172 | EXPORT_SYMBOL(saa7134_pgtable_build); |
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 329accda6d45..e648cc3bc96d 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
@@ -485,64 +485,6 @@ static IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { | |||
485 | 485 | ||
486 | }; | 486 | }; |
487 | 487 | ||
488 | static IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = { | ||
489 | [ 0x59 ] = KEY_MUTE, | ||
490 | [ 0x4a ] = KEY_POWER, | ||
491 | |||
492 | [ 0x18 ] = KEY_TEXT, | ||
493 | [ 0x26 ] = KEY_TV, | ||
494 | [ 0x3d ] = KEY_PRINT, | ||
495 | |||
496 | [ 0x48 ] = KEY_RED, | ||
497 | [ 0x04 ] = KEY_GREEN, | ||
498 | [ 0x11 ] = KEY_YELLOW, | ||
499 | [ 0x00 ] = KEY_BLUE, | ||
500 | |||
501 | [ 0x2d ] = KEY_VOLUMEUP, | ||
502 | [ 0x1e ] = KEY_VOLUMEDOWN, | ||
503 | |||
504 | [ 0x49 ] = KEY_MENU, | ||
505 | |||
506 | [ 0x16 ] = KEY_CHANNELUP, | ||
507 | [ 0x17 ] = KEY_CHANNELDOWN, | ||
508 | |||
509 | [ 0x20 ] = KEY_UP, | ||
510 | [ 0x21 ] = KEY_DOWN, | ||
511 | [ 0x22 ] = KEY_LEFT, | ||
512 | [ 0x23 ] = KEY_RIGHT, | ||
513 | [ 0x0d ] = KEY_SELECT, | ||
514 | |||
515 | |||
516 | |||
517 | [ 0x08 ] = KEY_BACK, | ||
518 | [ 0x07 ] = KEY_REFRESH, | ||
519 | |||
520 | [ 0x2f ] = KEY_ZOOM, | ||
521 | [ 0x29 ] = KEY_RECORD, | ||
522 | |||
523 | [ 0x4b ] = KEY_PAUSE, | ||
524 | [ 0x4d ] = KEY_REWIND, | ||
525 | [ 0x2e ] = KEY_PLAY, | ||
526 | [ 0x4e ] = KEY_FORWARD, | ||
527 | [ 0x53 ] = KEY_PREVIOUS, | ||
528 | [ 0x4c ] = KEY_STOP, | ||
529 | [ 0x54 ] = KEY_NEXT, | ||
530 | |||
531 | [ 0x69 ] = KEY_KP0, | ||
532 | [ 0x6a ] = KEY_KP1, | ||
533 | [ 0x6b ] = KEY_KP2, | ||
534 | [ 0x6c ] = KEY_KP3, | ||
535 | [ 0x6d ] = KEY_KP4, | ||
536 | [ 0x6e ] = KEY_KP5, | ||
537 | [ 0x6f ] = KEY_KP6, | ||
538 | [ 0x70 ] = KEY_KP7, | ||
539 | [ 0x71 ] = KEY_KP8, | ||
540 | [ 0x72 ] = KEY_KP9, | ||
541 | |||
542 | [ 0x74 ] = KEY_CHANNEL, | ||
543 | [ 0x0a ] = KEY_BACKSPACE, | ||
544 | }; | ||
545 | |||
546 | /* Mapping for the 28 key remote control as seen at | 488 | /* Mapping for the 28 key remote control as seen at |
547 | http://www.sednacomputer.com/photo/cardbus-tv.jpg | 489 | http://www.sednacomputer.com/photo/cardbus-tv.jpg |
548 | Pavel Mihaylov <bin@bash.info> */ | 490 | Pavel Mihaylov <bin@bash.info> */ |
@@ -635,57 +577,6 @@ static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | |||
635 | return 1; | 577 | return 1; |
636 | } | 578 | } |
637 | 579 | ||
638 | /* The new pinnacle PCTV remote (with the colored buttons) | ||
639 | * | ||
640 | * Ricardo Cerqueira <v4l@cerqueira.org> | ||
641 | */ | ||
642 | |||
643 | static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | ||
644 | { | ||
645 | unsigned char b[4]; | ||
646 | unsigned int start = 0,parity = 0,code = 0; | ||
647 | |||
648 | /* poll IR chip */ | ||
649 | if (4 != i2c_master_recv(&ir->c,b,4)) { | ||
650 | i2cdprintk("read error\n"); | ||
651 | return -EIO; | ||
652 | } | ||
653 | |||
654 | for (start = 0; start<4; start++) { | ||
655 | if (b[start] == 0x80) { | ||
656 | code=b[(start+3)%4]; | ||
657 | parity=b[(start+2)%4]; | ||
658 | } | ||
659 | } | ||
660 | |||
661 | /* Empty Request */ | ||
662 | if (parity==0) | ||
663 | return 0; | ||
664 | |||
665 | /* Repeating... */ | ||
666 | if (ir->old == parity) | ||
667 | return 0; | ||
668 | |||
669 | |||
670 | ir->old = parity; | ||
671 | |||
672 | /* Reduce code value to fit inside IR_KEYTAB_SIZE | ||
673 | * | ||
674 | * this is the only value that results in 42 unique | ||
675 | * codes < 128 | ||
676 | */ | ||
677 | |||
678 | code %= 0x88; | ||
679 | |||
680 | *ir_raw = code; | ||
681 | *ir_key = code; | ||
682 | |||
683 | i2cdprintk("Pinnacle PCTV key %02x\n", code); | ||
684 | |||
685 | return 1; | ||
686 | } | ||
687 | |||
688 | |||
689 | void saa7134_input_irq(struct saa7134_dev *dev) | 580 | void saa7134_input_irq(struct saa7134_dev *dev) |
690 | { | 581 | { |
691 | struct saa7134_ir *ir = dev->remote; | 582 | struct saa7134_ir *ir = dev->remote; |
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c index fd53dfcc1644..fd9ed11ab1e2 100644 --- a/drivers/media/video/saa7134/saa7134-oss.c +++ b/drivers/media/video/saa7134/saa7134-oss.c | |||
@@ -4,6 +4,8 @@ | |||
4 | * oss dsp interface | 4 | * oss dsp interface |
5 | * | 5 | * |
6 | * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] | 6 | * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] |
7 | * 2005 conversion to standalone module: | ||
8 | * Ricardo Cerqueira <v4l@cerqueira.org> | ||
7 | * | 9 | * |
8 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License as published by |
@@ -25,7 +27,9 @@ | |||
25 | #include <linux/module.h> | 27 | #include <linux/module.h> |
26 | #include <linux/moduleparam.h> | 28 | #include <linux/moduleparam.h> |
27 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
30 | #include <linux/interrupt.h> | ||
28 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
32 | #include <linux/sound.h> | ||
29 | #include <linux/soundcard.h> | 33 | #include <linux/soundcard.h> |
30 | 34 | ||
31 | #include "saa7134-reg.h" | 35 | #include "saa7134-reg.h" |
@@ -33,15 +37,23 @@ | |||
33 | 37 | ||
34 | /* ------------------------------------------------------------------ */ | 38 | /* ------------------------------------------------------------------ */ |
35 | 39 | ||
36 | static unsigned int oss_debug = 0; | 40 | static unsigned int debug = 0; |
37 | module_param(oss_debug, int, 0644); | 41 | module_param(debug, int, 0644); |
38 | MODULE_PARM_DESC(oss_debug,"enable debug messages [oss]"); | 42 | MODULE_PARM_DESC(debug,"enable debug messages [oss]"); |
39 | 43 | ||
40 | static unsigned int oss_rate = 0; | 44 | static unsigned int rate = 0; |
41 | module_param(oss_rate, int, 0444); | 45 | module_param(rate, int, 0444); |
42 | MODULE_PARM_DESC(oss_rate,"sample rate (valid are: 32000,48000)"); | 46 | MODULE_PARM_DESC(rate,"sample rate (valid are: 32000,48000)"); |
43 | 47 | ||
44 | #define dprintk(fmt, arg...) if (oss_debug) \ | 48 | static unsigned int dsp_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; |
49 | MODULE_PARM_DESC(dsp_nr, "device numbers for SAA7134 capture interface(s)."); | ||
50 | module_param_array(dsp_nr, int, NULL, 0444); | ||
51 | |||
52 | static unsigned int mixer_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; | ||
53 | MODULE_PARM_DESC(mixer_nr, "mixer numbers for SAA7134 capture interface(s)."); | ||
54 | module_param_array(mixer_nr, int, NULL, 0444); | ||
55 | |||
56 | #define dprintk(fmt, arg...) if (debug) \ | ||
45 | printk(KERN_DEBUG "%s/oss: " fmt, dev->name , ## arg) | 57 | printk(KERN_DEBUG "%s/oss: " fmt, dev->name , ## arg) |
46 | 58 | ||
47 | 59 | ||
@@ -369,7 +381,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file, | |||
369 | int __user *p = argp; | 381 | int __user *p = argp; |
370 | int val = 0; | 382 | int val = 0; |
371 | 383 | ||
372 | if (oss_debug > 1) | 384 | if (debug > 1) |
373 | saa7134_print_ioctl(dev->name,cmd); | 385 | saa7134_print_ioctl(dev->name,cmd); |
374 | switch (cmd) { | 386 | switch (cmd) { |
375 | case OSS_GETVERSION: | 387 | case OSS_GETVERSION: |
@@ -665,7 +677,7 @@ static int mixer_ioctl(struct inode *inode, struct file *file, | |||
665 | void __user *argp = (void __user *) arg; | 677 | void __user *argp = (void __user *) arg; |
666 | int __user *p = argp; | 678 | int __user *p = argp; |
667 | 679 | ||
668 | if (oss_debug > 1) | 680 | if (debug > 1) |
669 | saa7134_print_ioctl(dev->name,cmd); | 681 | saa7134_print_ioctl(dev->name,cmd); |
670 | switch (cmd) { | 682 | switch (cmd) { |
671 | case OSS_GETVERSION: | 683 | case OSS_GETVERSION: |
@@ -768,8 +780,41 @@ struct file_operations saa7134_mixer_fops = { | |||
768 | 780 | ||
769 | /* ------------------------------------------------------------------ */ | 781 | /* ------------------------------------------------------------------ */ |
770 | 782 | ||
783 | static irqreturn_t saa7134_oss_irq(int irq, void *dev_id, struct pt_regs *regs) | ||
784 | { | ||
785 | struct saa7134_dmasound *dmasound = dev_id; | ||
786 | struct saa7134_dev *dev = dmasound->priv_data; | ||
787 | unsigned long report, status; | ||
788 | int loop, handled = 0; | ||
789 | |||
790 | for (loop = 0; loop < 10; loop++) { | ||
791 | report = saa_readl(SAA7134_IRQ_REPORT); | ||
792 | status = saa_readl(SAA7134_IRQ_STATUS); | ||
793 | |||
794 | if (report & SAA7134_IRQ_REPORT_DONE_RA3) { | ||
795 | handled = 1; | ||
796 | saa_writel(SAA7134_IRQ_REPORT,report); | ||
797 | saa7134_irq_oss_done(dev, status); | ||
798 | } else { | ||
799 | goto out; | ||
800 | } | ||
801 | } | ||
802 | |||
803 | if (loop == 10) { | ||
804 | dprintk("error! looping IRQ!"); | ||
805 | } | ||
806 | out: | ||
807 | return IRQ_RETVAL(handled); | ||
808 | } | ||
809 | |||
771 | int saa7134_oss_init1(struct saa7134_dev *dev) | 810 | int saa7134_oss_init1(struct saa7134_dev *dev) |
772 | { | 811 | { |
812 | |||
813 | if ((request_irq(dev->pci->irq, saa7134_oss_irq, | ||
814 | SA_SHIRQ | SA_INTERRUPT, dev->name, | ||
815 | (void*) &dev->dmasound)) < 0) | ||
816 | return -1; | ||
817 | |||
773 | /* general */ | 818 | /* general */ |
774 | init_MUTEX(&dev->dmasound.lock); | 819 | init_MUTEX(&dev->dmasound.lock); |
775 | init_waitqueue_head(&dev->dmasound.wq); | 820 | init_waitqueue_head(&dev->dmasound.wq); |
@@ -785,8 +830,8 @@ int saa7134_oss_init1(struct saa7134_dev *dev) | |||
785 | 830 | ||
786 | /* dsp */ | 831 | /* dsp */ |
787 | dev->dmasound.rate = 32000; | 832 | dev->dmasound.rate = 32000; |
788 | if (oss_rate) | 833 | if (rate) |
789 | dev->dmasound.rate = oss_rate; | 834 | dev->dmasound.rate = rate; |
790 | dev->dmasound.rate = (dev->dmasound.rate > 40000) ? 48000 : 32000; | 835 | dev->dmasound.rate = (dev->dmasound.rate > 40000) ? 48000 : 32000; |
791 | 836 | ||
792 | /* mixer */ | 837 | /* mixer */ |
@@ -840,7 +885,7 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status) | |||
840 | /* next block addr */ | 885 | /* next block addr */ |
841 | next_blk = (dev->dmasound.dma_blk + 2) % dev->dmasound.blocks; | 886 | next_blk = (dev->dmasound.dma_blk + 2) % dev->dmasound.blocks; |
842 | saa_writel(reg,next_blk * dev->dmasound.blksize); | 887 | saa_writel(reg,next_blk * dev->dmasound.blksize); |
843 | if (oss_debug > 2) | 888 | if (debug > 2) |
844 | dprintk("irq: ok, %s, next_blk=%d, addr=%x\n", | 889 | dprintk("irq: ok, %s, next_blk=%d, addr=%x\n", |
845 | (status & 0x10000000) ? "even" : "odd ", next_blk, | 890 | (status & 0x10000000) ? "even" : "odd ", next_blk, |
846 | next_blk * dev->dmasound.blksize); | 891 | next_blk * dev->dmasound.blksize); |
@@ -854,6 +899,98 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status) | |||
854 | spin_unlock(&dev->slock); | 899 | spin_unlock(&dev->slock); |
855 | } | 900 | } |
856 | 901 | ||
902 | int saa7134_dsp_create(struct saa7134_dev *dev) | ||
903 | { | ||
904 | int err; | ||
905 | |||
906 | err = dev->dmasound.minor_dsp = | ||
907 | register_sound_dsp(&saa7134_dsp_fops, | ||
908 | dsp_nr[dev->nr]); | ||
909 | if (err < 0) { | ||
910 | goto fail; | ||
911 | } | ||
912 | printk(KERN_INFO "%s: registered device dsp%d\n", | ||
913 | dev->name,dev->dmasound.minor_dsp >> 4); | ||
914 | |||
915 | err = dev->dmasound.minor_mixer = | ||
916 | register_sound_mixer(&saa7134_mixer_fops, | ||
917 | mixer_nr[dev->nr]); | ||
918 | if (err < 0) | ||
919 | goto fail; | ||
920 | printk(KERN_INFO "%s: registered device mixer%d\n", | ||
921 | dev->name,dev->dmasound.minor_mixer >> 4); | ||
922 | |||
923 | return 0; | ||
924 | |||
925 | fail: | ||
926 | unregister_sound_dsp(dev->dmasound.minor_dsp); | ||
927 | return 0; | ||
928 | |||
929 | |||
930 | } | ||
931 | |||
932 | static int saa7134_oss_init(void) | ||
933 | { | ||
934 | struct saa7134_dev *dev = NULL; | ||
935 | struct list_head *list; | ||
936 | |||
937 | printk(KERN_INFO "saa7134 OSS driver for DMA sound loaded\n"); | ||
938 | |||
939 | list_for_each(list,&saa7134_devlist) { | ||
940 | dev = list_entry(list, struct saa7134_dev, devlist); | ||
941 | if (dev->dmasound.priv_data == NULL) { | ||
942 | dev->dmasound.priv_data = dev; | ||
943 | saa7134_oss_init1(dev); | ||
944 | saa7134_dsp_create(dev); | ||
945 | } else { | ||
946 | printk(KERN_ERR "saa7134 OSS: DMA sound is being handled by ALSA, ignoring %s\n",dev->name); | ||
947 | return -EBUSY; | ||
948 | } | ||
949 | } | ||
950 | |||
951 | if (dev == NULL) | ||
952 | printk(KERN_INFO "saa7134 OSS: no saa7134 cards found\n"); | ||
953 | |||
954 | return 0; | ||
955 | |||
956 | } | ||
957 | |||
958 | void saa7134_oss_exit(void) | ||
959 | { | ||
960 | struct saa7134_dev *dev = NULL; | ||
961 | struct list_head *list; | ||
962 | |||
963 | list_for_each(list,&saa7134_devlist) { | ||
964 | dev = list_entry(list, struct saa7134_dev, devlist); | ||
965 | |||
966 | /* Device isn't registered by OSS, probably ALSA's */ | ||
967 | if (!dev->dmasound.minor_dsp) | ||
968 | continue; | ||
969 | |||
970 | unregister_sound_mixer(dev->dmasound.minor_mixer); | ||
971 | unregister_sound_dsp(dev->dmasound.minor_dsp); | ||
972 | |||
973 | saa7134_oss_fini(dev); | ||
974 | |||
975 | if (dev->pci->irq > 0) { | ||
976 | synchronize_irq(dev->pci->irq); | ||
977 | free_irq(dev->pci->irq,&dev->dmasound); | ||
978 | } | ||
979 | |||
980 | dev->dmasound.priv_data = NULL; | ||
981 | |||
982 | } | ||
983 | |||
984 | printk(KERN_INFO "saa7134 OSS driver for DMA sound unloaded\n"); | ||
985 | |||
986 | return; | ||
987 | } | ||
988 | |||
989 | module_init(saa7134_oss_init); | ||
990 | module_exit(saa7134_oss_exit); | ||
991 | MODULE_LICENSE("GPL"); | ||
992 | MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); | ||
993 | |||
857 | /* ----------------------------------------------------------- */ | 994 | /* ----------------------------------------------------------- */ |
858 | /* | 995 | /* |
859 | * Local variables: | 996 | * Local variables: |
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index fb9727471661..244e1973081c 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h | |||
@@ -208,6 +208,7 @@ struct saa7134_format { | |||
208 | #define SAA7134_BOARD_SEDNA_PC_TV_CARDBUS 79 | 208 | #define SAA7134_BOARD_SEDNA_PC_TV_CARDBUS 79 |
209 | #define SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV 80 | 209 | #define SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV 80 |
210 | #define SAA7134_BOARD_PHILIPS_TIGER 81 | 210 | #define SAA7134_BOARD_PHILIPS_TIGER 81 |
211 | #define SAA7134_BOARD_MSI_TVATANYWHERE_PLUS 82 | ||
211 | 212 | ||
212 | #define SAA7134_MAXBOARDS 8 | 213 | #define SAA7134_MAXBOARDS 8 |
213 | #define SAA7134_INPUT_MAX 8 | 214 | #define SAA7134_INPUT_MAX 8 |
@@ -383,6 +384,7 @@ struct saa7134_dmasound { | |||
383 | unsigned int dma_blk; | 384 | unsigned int dma_blk; |
384 | unsigned int read_offset; | 385 | unsigned int read_offset; |
385 | unsigned int read_count; | 386 | unsigned int read_count; |
387 | void * priv_data; | ||
386 | snd_pcm_substream_t *substream; | 388 | snd_pcm_substream_t *substream; |
387 | }; | 389 | }; |
388 | 390 | ||
diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index b2dfe07e9f9d..61d94ddaff41 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c | |||
@@ -437,6 +437,10 @@ static void set_audio(struct tuner *t) | |||
437 | t->sgIF = 124; | 437 | t->sgIF = 124; |
438 | t->tda8290_easy_mode = 0x20; | 438 | t->tda8290_easy_mode = 0x20; |
439 | mode = "L"; | 439 | mode = "L"; |
440 | } else if (t->std & V4L2_STD_SECAM_LC) { | ||
441 | t->sgIF = 20; | ||
442 | t->tda8290_easy_mode = 0x40; | ||
443 | mode = "LC"; | ||
440 | } | 444 | } |
441 | tuner_dbg("setting tda8290 to system %s\n", mode); | 445 | tuner_dbg("setting tda8290 to system %s\n", mode); |
442 | } | 446 | } |
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 73c4041c35d7..e58abdfcaab8 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c | |||
@@ -251,7 +251,7 @@ static inline int check_mode(struct tuner *t, char *cmd) | |||
251 | 251 | ||
252 | static char pal[] = "-"; | 252 | static char pal[] = "-"; |
253 | module_param_string(pal, pal, sizeof(pal), 0644); | 253 | module_param_string(pal, pal, sizeof(pal), 0644); |
254 | static char secam[] = "-"; | 254 | static char secam[] = "--"; |
255 | module_param_string(secam, secam, sizeof(secam), 0644); | 255 | module_param_string(secam, secam, sizeof(secam), 0644); |
256 | 256 | ||
257 | /* get more precise norm info from insmod option */ | 257 | /* get more precise norm info from insmod option */ |
@@ -307,8 +307,13 @@ static int tuner_fixup_std(struct tuner *t) | |||
307 | break; | 307 | break; |
308 | case 'l': | 308 | case 'l': |
309 | case 'L': | 309 | case 'L': |
310 | tuner_dbg ("insmod fixup: SECAM => SECAM-L\n"); | 310 | if ((secam[1]=='C')||(secam[1]=='c')) { |
311 | t->std = V4L2_STD_SECAM_L; | 311 | tuner_dbg ("insmod fixup: SECAM => SECAM-L'\n"); |
312 | t->std = V4L2_STD_SECAM_LC; | ||
313 | } else { | ||
314 | tuner_dbg ("insmod fixup: SECAM => SECAM-L\n"); | ||
315 | t->std = V4L2_STD_SECAM_L; | ||
316 | } | ||
312 | break; | 317 | break; |
313 | case '-': | 318 | case '-': |
314 | /* default parameter, do nothing */ | 319 | /* default parameter, do nothing */ |
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index d832205818f2..e0c9fdb9914a 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c | |||
@@ -233,7 +233,7 @@ static struct tunertype tuners[] = { | |||
233 | { "Ymec TVision TVF-5533MF", Philips, NTSC, | 233 | { "Ymec TVision TVF-5533MF", Philips, NTSC, |
234 | 16*160.00,16*454.00,0x01,0x02,0x04,0x8e,732}, | 234 | 16*160.00,16*454.00,0x01,0x02,0x04,0x8e,732}, |
235 | 235 | ||
236 | /* 60-68 */ | 236 | /* 60-69 */ |
237 | { "Thomson DDT 7611 (ATSC/NTSC)", THOMSON, ATSC, | 237 | { "Thomson DDT 7611 (ATSC/NTSC)", THOMSON, ATSC, |
238 | 16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732}, | 238 | 16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732}, |
239 | { "Tena TNF9533-D/IF/TNF9533-B/DF", Philips, PAL, | 239 | { "Tena TNF9533-D/IF/TNF9533-B/DF", Philips, PAL, |
@@ -252,6 +252,8 @@ static struct tunertype tuners[] = { | |||
252 | 16*160.00,16*442.00,0xa1,0xa2,0xa4,0xc8,623 }, | 252 | 16*160.00,16*442.00,0xa1,0xa2,0xa4,0xc8,623 }, |
253 | { "Philips TUV1236D ATSC/NTSC dual in", Philips, ATSC, | 253 | { "Philips TUV1236D ATSC/NTSC dual in", Philips, ATSC, |
254 | 16*157.25,16*454.00,0x01,0x02,0x04,0xce,732 }, | 254 | 16*157.25,16*454.00,0x01,0x02,0x04,0xce,732 }, |
255 | { "Tena TNF 5335 MF", Philips, NTSC, | ||
256 | 16*157.25,16*454.00,0x01,0x02,0x04,0x8e,732 }, | ||
255 | }; | 257 | }; |
256 | 258 | ||
257 | unsigned const int tuner_count = ARRAY_SIZE(tuners); | 259 | unsigned const int tuner_count = ARRAY_SIZE(tuners); |
diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c index 22f286222004..a6936ad74fcf 100644 --- a/drivers/media/video/wm8775.c +++ b/drivers/media/video/wm8775.c | |||
@@ -5,6 +5,11 @@ | |||
5 | * | 5 | * |
6 | * Based on saa7115 driver | 6 | * Based on saa7115 driver |
7 | * | 7 | * |
8 | * Copyright (C) 2005 Hans Verkuil <hverkuil@xs4all.nl> | ||
9 | * - Cleanup | ||
10 | * - V4L2 API update | ||
11 | * - sound fixes | ||
12 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 14 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation; either version 2 of the License, or | 15 | * the Free Software Foundation; either version 2 of the License, or |
@@ -31,7 +36,7 @@ | |||
31 | #include <media/audiochip.h> | 36 | #include <media/audiochip.h> |
32 | 37 | ||
33 | MODULE_DESCRIPTION("wm8775 driver"); | 38 | MODULE_DESCRIPTION("wm8775 driver"); |
34 | MODULE_AUTHOR("Ulf Eklund"); | 39 | MODULE_AUTHOR("Ulf Eklund, Hans Verkuil"); |
35 | MODULE_LICENSE("GPL"); | 40 | MODULE_LICENSE("GPL"); |
36 | 41 | ||
37 | #define wm8775_err(fmt, arg...) do { \ | 42 | #define wm8775_err(fmt, arg...) do { \ |
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c index 1e6bdba26756..166c9b0ad04e 100644 --- a/drivers/mmc/mmci.c +++ b/drivers/mmc/mmci.c | |||
@@ -22,7 +22,6 @@ | |||
22 | 22 | ||
23 | #include <asm/div64.h> | 23 | #include <asm/div64.h> |
24 | #include <asm/io.h> | 24 | #include <asm/io.h> |
25 | #include <asm/irq.h> | ||
26 | #include <asm/scatterlist.h> | 25 | #include <asm/scatterlist.h> |
27 | #include <asm/sizes.h> | 26 | #include <asm/sizes.h> |
28 | #include <asm/hardware/amba.h> | 27 | #include <asm/hardware/amba.h> |
diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index 977935a3d898..824e430486c2 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c | |||
@@ -84,6 +84,7 @@ static int max_interrupt_work = 10; | |||
84 | #include <linux/netdevice.h> | 84 | #include <linux/netdevice.h> |
85 | #include <linux/etherdevice.h> | 85 | #include <linux/etherdevice.h> |
86 | #include <linux/pm.h> | 86 | #include <linux/pm.h> |
87 | #include <linux/pm_legacy.h> | ||
87 | #include <linux/skbuff.h> | 88 | #include <linux/skbuff.h> |
88 | #include <linux/delay.h> /* for udelay() */ | 89 | #include <linux/delay.h> /* for udelay() */ |
89 | #include <linux/spinlock.h> | 90 | #include <linux/spinlock.h> |
@@ -173,7 +174,7 @@ struct el3_private { | |||
173 | /* skb send-queue */ | 174 | /* skb send-queue */ |
174 | int head, size; | 175 | int head, size; |
175 | struct sk_buff *queue[SKB_QUEUE_SIZE]; | 176 | struct sk_buff *queue[SKB_QUEUE_SIZE]; |
176 | #ifdef CONFIG_PM | 177 | #ifdef CONFIG_PM_LEGACY |
177 | struct pm_dev *pmdev; | 178 | struct pm_dev *pmdev; |
178 | #endif | 179 | #endif |
179 | enum { | 180 | enum { |
@@ -200,7 +201,7 @@ static void el3_tx_timeout (struct net_device *dev); | |||
200 | static void el3_down(struct net_device *dev); | 201 | static void el3_down(struct net_device *dev); |
201 | static void el3_up(struct net_device *dev); | 202 | static void el3_up(struct net_device *dev); |
202 | static struct ethtool_ops ethtool_ops; | 203 | static struct ethtool_ops ethtool_ops; |
203 | #ifdef CONFIG_PM | 204 | #ifdef CONFIG_PM_LEGACY |
204 | static int el3_suspend(struct pm_dev *pdev); | 205 | static int el3_suspend(struct pm_dev *pdev); |
205 | static int el3_resume(struct pm_dev *pdev); | 206 | static int el3_resume(struct pm_dev *pdev); |
206 | static int el3_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data); | 207 | static int el3_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data); |
@@ -361,7 +362,7 @@ static void el3_common_remove (struct net_device *dev) | |||
361 | struct el3_private *lp = netdev_priv(dev); | 362 | struct el3_private *lp = netdev_priv(dev); |
362 | 363 | ||
363 | (void) lp; /* Keep gcc quiet... */ | 364 | (void) lp; /* Keep gcc quiet... */ |
364 | #ifdef CONFIG_PM | 365 | #ifdef CONFIG_PM_LEGACY |
365 | if (lp->pmdev) | 366 | if (lp->pmdev) |
366 | pm_unregister(lp->pmdev); | 367 | pm_unregister(lp->pmdev); |
367 | #endif | 368 | #endif |
@@ -571,7 +572,7 @@ no_pnp: | |||
571 | if (err) | 572 | if (err) |
572 | goto out1; | 573 | goto out1; |
573 | 574 | ||
574 | #ifdef CONFIG_PM | 575 | #ifdef CONFIG_PM_LEGACY |
575 | /* register power management */ | 576 | /* register power management */ |
576 | lp->pmdev = pm_register(PM_ISA_DEV, card_idx, el3_pm_callback); | 577 | lp->pmdev = pm_register(PM_ISA_DEV, card_idx, el3_pm_callback); |
577 | if (lp->pmdev) { | 578 | if (lp->pmdev) { |
@@ -1479,7 +1480,7 @@ el3_up(struct net_device *dev) | |||
1479 | } | 1480 | } |
1480 | 1481 | ||
1481 | /* Power Management support functions */ | 1482 | /* Power Management support functions */ |
1482 | #ifdef CONFIG_PM | 1483 | #ifdef CONFIG_PM_LEGACY |
1483 | 1484 | ||
1484 | static int | 1485 | static int |
1485 | el3_suspend(struct pm_dev *pdev) | 1486 | el3_suspend(struct pm_dev *pdev) |
@@ -1548,7 +1549,7 @@ el3_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data) | |||
1548 | return 0; | 1549 | return 0; |
1549 | } | 1550 | } |
1550 | 1551 | ||
1551 | #endif /* CONFIG_PM */ | 1552 | #endif /* CONFIG_PM_LEGACY */ |
1552 | 1553 | ||
1553 | /* Parameters that may be passed into the module. */ | 1554 | /* Parameters that may be passed into the module. */ |
1554 | static int debug = -1; | 1555 | static int debug = -1; |
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index e3a329539f1c..0f030b73cbb3 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * Based on 8260_io/fcc_enet.c | 6 | * Based on 8260_io/fcc_enet.c |
7 | * | 7 | * |
8 | * Author: Andy Fleming | 8 | * Author: Andy Fleming |
9 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) | 9 | * Maintainer: Kumar Gala |
10 | * | 10 | * |
11 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. | 11 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. |
12 | * | 12 | * |
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 220084e53341..5065ba82cb76 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h | |||
@@ -6,7 +6,7 @@ | |||
6 | * Based on 8260_io/fcc_enet.c | 6 | * Based on 8260_io/fcc_enet.c |
7 | * | 7 | * |
8 | * Author: Andy Fleming | 8 | * Author: Andy Fleming |
9 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) | 9 | * Maintainer: Kumar Gala |
10 | * | 10 | * |
11 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. | 11 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. |
12 | * | 12 | * |
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index 5a2d810ce575..cfa3cd7c91a0 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * Based on e1000 ethtool support | 6 | * Based on e1000 ethtool support |
7 | * | 7 | * |
8 | * Author: Andy Fleming | 8 | * Author: Andy Fleming |
9 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) | 9 | * Maintainer: Kumar Gala |
10 | * | 10 | * |
11 | * Copyright (c) 2003,2004 Freescale Semiconductor, Inc. | 11 | * Copyright (c) 2003,2004 Freescale Semiconductor, Inc. |
12 | * | 12 | * |
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c index 9544279e8bcd..04a462c2a5b7 100644 --- a/drivers/net/gianfar_mii.c +++ b/drivers/net/gianfar_mii.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * Provides Bus interface for MIIM regs | 5 | * Provides Bus interface for MIIM regs |
6 | * | 6 | * |
7 | * Author: Andy Fleming | 7 | * Author: Andy Fleming |
8 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) | 8 | * Maintainer: Kumar Gala |
9 | * | 9 | * |
10 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. | 10 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. |
11 | * | 11 | * |
diff --git a/drivers/net/gianfar_mii.h b/drivers/net/gianfar_mii.h index 56e5665d5c9b..e85eb216fb5b 100644 --- a/drivers/net/gianfar_mii.h +++ b/drivers/net/gianfar_mii.h | |||
@@ -5,7 +5,7 @@ | |||
5 | * Driver for the MDIO bus controller in the Gianfar register space | 5 | * Driver for the MDIO bus controller in the Gianfar register space |
6 | * | 6 | * |
7 | * Author: Andy Fleming | 7 | * Author: Andy Fleming |
8 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) | 8 | * Maintainer: Kumar Gala |
9 | * | 9 | * |
10 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. | 10 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. |
11 | * | 11 | * |
diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c index 9bf34681d3df..2e7882eb7d6f 100644 --- a/drivers/net/irda/ali-ircc.c +++ b/drivers/net/irda/ali-ircc.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <asm/byteorder.h> | 40 | #include <asm/byteorder.h> |
41 | 41 | ||
42 | #include <linux/pm.h> | 42 | #include <linux/pm.h> |
43 | #include <linux/pm_legacy.h> | ||
43 | 44 | ||
44 | #include <net/irda/wrapper.h> | 45 | #include <net/irda/wrapper.h> |
45 | #include <net/irda/irda.h> | 46 | #include <net/irda/irda.h> |
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c index 805714ec9a8a..ee717d0e939e 100644 --- a/drivers/net/irda/nsc-ircc.c +++ b/drivers/net/irda/nsc-ircc.c | |||
@@ -59,6 +59,7 @@ | |||
59 | #include <asm/byteorder.h> | 59 | #include <asm/byteorder.h> |
60 | 60 | ||
61 | #include <linux/pm.h> | 61 | #include <linux/pm.h> |
62 | #include <linux/pm_legacy.h> | ||
62 | 63 | ||
63 | #include <net/irda/wrapper.h> | 64 | #include <net/irda/wrapper.h> |
64 | #include <net/irda/irda.h> | 65 | #include <net/irda/irda.h> |
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index a10cd184d597..5c2824be4ee6 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h | |||
@@ -100,14 +100,14 @@ | |||
100 | #define SMC_IO_SHIFT 0 | 100 | #define SMC_IO_SHIFT 0 |
101 | #define SMC_NOWAIT 1 | 101 | #define SMC_NOWAIT 1 |
102 | 102 | ||
103 | #define SMC_inb(a, r) inb((a) + (r)) | 103 | #define SMC_inb(a, r) readb((a) + (r)) |
104 | #define SMC_insb(a, r, p, l) insb((a) + (r), p, (l)) | 104 | #define SMC_insb(a, r, p, l) readsb((a) + (r), p, (l)) |
105 | #define SMC_inw(a, r) inw((a) + (r)) | 105 | #define SMC_inw(a, r) readw((a) + (r)) |
106 | #define SMC_insw(a, r, p, l) insw((a) + (r), p, l) | 106 | #define SMC_insw(a, r, p, l) readsw((a) + (r), p, l) |
107 | #define SMC_outb(v, a, r) outb(v, (a) + (r)) | 107 | #define SMC_outb(v, a, r) writeb(v, (a) + (r)) |
108 | #define SMC_outsb(a, r, p, l) outsb((a) + (r), p, (l)) | 108 | #define SMC_outsb(a, r, p, l) writesb((a) + (r), p, (l)) |
109 | #define SMC_outw(v, a, r) outw(v, (a) + (r)) | 109 | #define SMC_outw(v, a, r) writew(v, (a) + (r)) |
110 | #define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l) | 110 | #define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l) |
111 | 111 | ||
112 | #define set_irq_type(irq, type) do {} while (0) | 112 | #define set_irq_type(irq, type) do {} while (0) |
113 | 113 | ||
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index de399563a9db..081717d01374 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c | |||
@@ -128,6 +128,8 @@ static struct pci_device_id gem_pci_tbl[] = { | |||
128 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | 128 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, |
129 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_SH_SUNGEM, | 129 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_SH_SUNGEM, |
130 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | 130 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, |
131 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID2_GMAC, | ||
132 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | ||
131 | {0, } | 133 | {0, } |
132 | }; | 134 | }; |
133 | 135 | ||
diff --git a/drivers/net/wan/sdladrv.c b/drivers/net/wan/sdladrv.c index 7c2cf2e76300..032c0f81928e 100644 --- a/drivers/net/wan/sdladrv.c +++ b/drivers/net/wan/sdladrv.c | |||
@@ -1994,7 +1994,7 @@ static int detect_s514 (sdlahw_t* hw) | |||
1994 | modname, hw->irq); | 1994 | modname, hw->irq); |
1995 | 1995 | ||
1996 | /* map the physical PCI memory to virtual memory */ | 1996 | /* map the physical PCI memory to virtual memory */ |
1997 | (void *)hw->dpmbase = ioremap((unsigned long)S514_mem_base_addr, | 1997 | hw->dpmbase = ioremap((unsigned long)S514_mem_base_addr, |
1998 | (unsigned long)MAX_SIZEOF_S514_MEMORY); | 1998 | (unsigned long)MAX_SIZEOF_S514_MEMORY); |
1999 | /* map the physical control register memory to virtual memory */ | 1999 | /* map the physical control register memory to virtual memory */ |
2000 | hw->vector = (unsigned long)ioremap( | 2000 | hw->vector = (unsigned long)ioremap( |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 4a3cecca012c..2387e75da0fe 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
34 | #include <linux/interrupt.h> | ||
35 | |||
34 | #include "../pci.h" | 36 | #include "../pci.h" |
35 | #include "pciehp.h" | 37 | #include "pciehp.h" |
36 | 38 | ||
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index a7859a84d1ae..4b35097b3d9f 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c | |||
@@ -253,7 +253,7 @@ rpaphp_pci_config_slot(struct pci_bus *bus) | |||
253 | if (!dn || !dn->child) | 253 | if (!dn || !dn->child) |
254 | return NULL; | 254 | return NULL; |
255 | 255 | ||
256 | if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { | 256 | if (_machine == PLATFORM_PSERIES_LPAR) { |
257 | of_scan_bus(dn, bus); | 257 | of_scan_bus(dn, bus); |
258 | if (list_empty(&bus->devices)) { | 258 | if (list_empty(&bus->devices)) { |
259 | err("%s: No new device found\n", __FUNCTION__); | 259 | err("%s: No new device found\n", __FUNCTION__); |
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 40905a6c8094..9987a6fd65b8 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
34 | #include <linux/interrupt.h> | ||
35 | |||
34 | #include "shpchp.h" | 36 | #include "shpchp.h" |
35 | 37 | ||
36 | #ifdef DEBUG | 38 | #ifdef DEBUG |
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 234cdca6fe13..a30aa74304a2 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c | |||
@@ -513,6 +513,11 @@ static int socket_insert(struct pcmcia_socket *skt) | |||
513 | ret = socket_setup(skt, setup_delay); | 513 | ret = socket_setup(skt, setup_delay); |
514 | if (ret == CS_SUCCESS) { | 514 | if (ret == CS_SUCCESS) { |
515 | skt->state |= SOCKET_PRESENT; | 515 | skt->state |= SOCKET_PRESENT; |
516 | |||
517 | printk(KERN_NOTICE "pccard: %s card inserted into slot %d\n", | ||
518 | (skt->state & SOCKET_CARDBUS) ? "CardBus" : "PCMCIA", | ||
519 | skt->sock); | ||
520 | |||
516 | #ifdef CONFIG_CARDBUS | 521 | #ifdef CONFIG_CARDBUS |
517 | if (skt->state & SOCKET_CARDBUS) { | 522 | if (skt->state & SOCKET_CARDBUS) { |
518 | cb_alloc(skt); | 523 | cb_alloc(skt); |
@@ -598,6 +603,7 @@ static int socket_resume(struct pcmcia_socket *skt) | |||
598 | 603 | ||
599 | static void socket_remove(struct pcmcia_socket *skt) | 604 | static void socket_remove(struct pcmcia_socket *skt) |
600 | { | 605 | { |
606 | printk(KERN_NOTICE "pccard: card ejected from slot %d\n", skt->sock); | ||
601 | socket_shutdown(skt); | 607 | socket_shutdown(skt); |
602 | cs_socket_put(skt); | 608 | cs_socket_put(skt); |
603 | } | 609 | } |
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 39d096b52926..7f8219f3fd9e 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -544,6 +544,9 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f | |||
544 | list_add_tail(&p_dev->socket_device_list, &s->devices_list); | 544 | list_add_tail(&p_dev->socket_device_list, &s->devices_list); |
545 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | 545 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); |
546 | 546 | ||
547 | printk(KERN_NOTICE "pcmcia: registering new device %s\n", | ||
548 | p_dev->devname); | ||
549 | |||
547 | pcmcia_device_query(p_dev); | 550 | pcmcia_device_query(p_dev); |
548 | 551 | ||
549 | if (device_register(&p_dev->dev)) { | 552 | if (device_register(&p_dev->dev)) { |
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c index 4ddd76239b34..4d56bc9926d6 100644 --- a/drivers/pcmcia/i82365.c +++ b/drivers/pcmcia/i82365.c | |||
@@ -1339,10 +1339,7 @@ static struct device_driver i82365_driver = { | |||
1339 | .resume = pcmcia_socket_dev_resume, | 1339 | .resume = pcmcia_socket_dev_resume, |
1340 | }; | 1340 | }; |
1341 | 1341 | ||
1342 | static struct platform_device i82365_device = { | 1342 | static struct platform_device *i82365_device; |
1343 | .name = "i82365", | ||
1344 | .id = 0, | ||
1345 | }; | ||
1346 | 1343 | ||
1347 | static int __init init_i82365(void) | 1344 | static int __init init_i82365(void) |
1348 | { | 1345 | { |
@@ -1352,7 +1349,14 @@ static int __init init_i82365(void) | |||
1352 | if (ret) | 1349 | if (ret) |
1353 | return ret; | 1350 | return ret; |
1354 | 1351 | ||
1355 | ret = platform_device_register(&i82365_device); | 1352 | i82365_device = platform_device_alloc("i82365", 0); |
1353 | if (i82365_device) { | ||
1354 | ret = platform_device_add(i82365_device); | ||
1355 | if (ret) | ||
1356 | platform_device_put(i82365_device); | ||
1357 | } else | ||
1358 | ret = -ENOMEM; | ||
1359 | |||
1356 | if (ret) { | 1360 | if (ret) { |
1357 | driver_unregister(&i82365_driver); | 1361 | driver_unregister(&i82365_driver); |
1358 | return ret; | 1362 | return ret; |
@@ -1365,7 +1369,7 @@ static int __init init_i82365(void) | |||
1365 | 1369 | ||
1366 | if (sockets == 0) { | 1370 | if (sockets == 0) { |
1367 | printk("not found.\n"); | 1371 | printk("not found.\n"); |
1368 | platform_device_unregister(&i82365_device); | 1372 | platform_device_unregister(i82365_device); |
1369 | release_region(i365_base, 2); | 1373 | release_region(i365_base, 2); |
1370 | driver_unregister(&i82365_driver); | 1374 | driver_unregister(&i82365_driver); |
1371 | return -ENODEV; | 1375 | return -ENODEV; |
@@ -1377,7 +1381,7 @@ static int __init init_i82365(void) | |||
1377 | 1381 | ||
1378 | /* register sockets with the pcmcia core */ | 1382 | /* register sockets with the pcmcia core */ |
1379 | for (i = 0; i < sockets; i++) { | 1383 | for (i = 0; i < sockets; i++) { |
1380 | socket[i].socket.dev.dev = &i82365_device.dev; | 1384 | socket[i].socket.dev.dev = &i82365_device->dev; |
1381 | socket[i].socket.ops = &pcic_operations; | 1385 | socket[i].socket.ops = &pcic_operations; |
1382 | socket[i].socket.resource_ops = &pccard_nonstatic_ops; | 1386 | socket[i].socket.resource_ops = &pccard_nonstatic_ops; |
1383 | socket[i].socket.owner = THIS_MODULE; | 1387 | socket[i].socket.owner = THIS_MODULE; |
@@ -1415,7 +1419,7 @@ static void __exit exit_i82365(void) | |||
1415 | if (socket[i].flags & IS_REGISTERED) | 1419 | if (socket[i].flags & IS_REGISTERED) |
1416 | pcmcia_unregister_socket(&socket[i].socket); | 1420 | pcmcia_unregister_socket(&socket[i].socket); |
1417 | } | 1421 | } |
1418 | platform_device_unregister(&i82365_device); | 1422 | platform_device_unregister(i82365_device); |
1419 | if (poll_interval != 0) | 1423 | if (poll_interval != 0) |
1420 | del_timer_sync(&poll_timer); | 1424 | del_timer_sync(&poll_timer); |
1421 | if (grab_irq != 0) | 1425 | if (grab_irq != 0) |
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index 2efb317153ce..67e9afa000c1 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/keyboard.h> | 34 | #include <linux/keyboard.h> |
35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
36 | #include <linux/pm.h> | 36 | #include <linux/pm.h> |
37 | #include <linux/pm_legacy.h> | ||
37 | #include <linux/bitops.h> | 38 | #include <linux/bitops.h> |
38 | #include <linux/delay.h> | 39 | #include <linux/delay.h> |
39 | 40 | ||
@@ -1343,7 +1344,7 @@ static void show_serial_version(void) | |||
1343 | printk("MC68328 serial driver version 1.00\n"); | 1344 | printk("MC68328 serial driver version 1.00\n"); |
1344 | } | 1345 | } |
1345 | 1346 | ||
1346 | #ifdef CONFIG_PM | 1347 | #ifdef CONFIG_PM_LEGACY |
1347 | /* Serial Power management | 1348 | /* Serial Power management |
1348 | * The console (currently fixed at line 0) is a special case for power | 1349 | * The console (currently fixed at line 0) is a special case for power |
1349 | * management because the kernel is so chatty. The console will be | 1350 | * management because the kernel is so chatty. The console will be |
@@ -1393,7 +1394,7 @@ void startup_console(void) | |||
1393 | struct m68k_serial *info = &m68k_soft[0]; | 1394 | struct m68k_serial *info = &m68k_soft[0]; |
1394 | startup(info); | 1395 | startup(info); |
1395 | } | 1396 | } |
1396 | #endif | 1397 | #endif /* CONFIG_PM_LEGACY */ |
1397 | 1398 | ||
1398 | 1399 | ||
1399 | static struct tty_operations rs_ops = { | 1400 | static struct tty_operations rs_ops = { |
@@ -1486,7 +1487,7 @@ rs68328_init(void) | |||
1486 | IRQ_FLG_STD, | 1487 | IRQ_FLG_STD, |
1487 | "M68328_UART", NULL)) | 1488 | "M68328_UART", NULL)) |
1488 | panic("Unable to attach 68328 serial interrupt\n"); | 1489 | panic("Unable to attach 68328 serial interrupt\n"); |
1489 | #ifdef CONFIG_PM | 1490 | #ifdef CONFIG_PM_LEGACY |
1490 | serial_pm[i] = pm_register(PM_SYS_DEV, PM_SYS_COM, serial_pm_callback); | 1491 | serial_pm[i] = pm_register(PM_SYS_DEV, PM_SYS_COM, serial_pm_callback); |
1491 | if (serial_pm[i]) | 1492 | if (serial_pm[i]) |
1492 | serial_pm[i]->data = info; | 1493 | serial_pm[i]->data = info; |
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 3742753241ee..e08510d09ff6 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -999,7 +999,10 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) | |||
999 | serial_outp(up, UART_MCR, save_mcr); | 999 | serial_outp(up, UART_MCR, save_mcr); |
1000 | serial8250_clear_fifos(up); | 1000 | serial8250_clear_fifos(up); |
1001 | (void)serial_in(up, UART_RX); | 1001 | (void)serial_in(up, UART_RX); |
1002 | serial_outp(up, UART_IER, 0); | 1002 | if (up->capabilities & UART_CAP_UUE) |
1003 | serial_outp(up, UART_IER, UART_IER_UUE); | ||
1004 | else | ||
1005 | serial_outp(up, UART_IER, 0); | ||
1003 | 1006 | ||
1004 | out: | 1007 | out: |
1005 | spin_unlock_irqrestore(&up->port.lock, flags); | 1008 | spin_unlock_irqrestore(&up->port.lock, flags); |
diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c index 5d8660a42b77..b79ed0665d51 100644 --- a/drivers/serial/8250_pnp.c +++ b/drivers/serial/8250_pnp.c | |||
@@ -323,6 +323,8 @@ static const struct pnp_device_id pnp_dev_table[] = { | |||
323 | { "USR9180", 0 }, | 323 | { "USR9180", 0 }, |
324 | /* U.S. Robotics 56K Voice INT PnP*/ | 324 | /* U.S. Robotics 56K Voice INT PnP*/ |
325 | { "USR9190", 0 }, | 325 | { "USR9190", 0 }, |
326 | /* HP Compaq Tablet PC tc1100 Wacom tablet */ | ||
327 | { "WACF005", 0 }, | ||
326 | /* Rockwell's (PORALiNK) 33600 INT PNP */ | 328 | /* Rockwell's (PORALiNK) 33600 INT PNP */ |
327 | { "WCI0003", 0 }, | 329 | { "WCI0003", 0 }, |
328 | /* Unkown PnP modems */ | 330 | /* Unkown PnP modems */ |
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 25825f2aba22..987d22b53c22 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * Based on ppc8xx.c by Thomas Gleixner | 7 | * Based on ppc8xx.c by Thomas Gleixner |
8 | * Based on drivers/serial/amba.c by Russell King | 8 | * Based on drivers/serial/amba.c by Russell King |
9 | * | 9 | * |
10 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2) | 10 | * Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2) |
11 | * Pantelis Antoniou (panto@intracom.gr) (CPM1) | 11 | * Pantelis Antoniou (panto@intracom.gr) (CPM1) |
12 | * | 12 | * |
13 | * Copyright (C) 2004 Freescale Semiconductor, Inc. | 13 | * Copyright (C) 2004 Freescale Semiconductor, Inc. |
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c index 4b0786e7eb7f..d789ee55cbb7 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Driver for CPM (SCC/SMC) serial ports; CPM1 definitions | 4 | * Driver for CPM (SCC/SMC) serial ports; CPM1 definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2) | 6 | * Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2) |
7 | * Pantelis Antoniou (panto@intracom.gr) (CPM1) | 7 | * Pantelis Antoniou (panto@intracom.gr) (CPM1) |
8 | * | 8 | * |
9 | * Copyright (C) 2004 Freescale Semiconductor, Inc. | 9 | * Copyright (C) 2004 Freescale Semiconductor, Inc. |
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c index 15ad58d94889..fd9e53ed3feb 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Driver for CPM (SCC/SMC) serial ports; CPM2 definitions | 4 | * Driver for CPM (SCC/SMC) serial ports; CPM2 definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2) | 6 | * Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2) |
7 | * Pantelis Antoniou (panto@intracom.gr) (CPM1) | 7 | * Pantelis Antoniou (panto@intracom.gr) (CPM1) |
8 | * | 8 | * |
9 | * Copyright (C) 2004 Freescale Semiconductor, Inc. | 9 | * Copyright (C) 2004 Freescale Semiconductor, Inc. |
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c index e63b9dffc8d7..4d8516d1bb71 100644 --- a/drivers/serial/dz.c +++ b/drivers/serial/dz.c | |||
@@ -1,9 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * dz.c: Serial port driver for DECStations equiped | 2 | * dz.c: Serial port driver for DECStations equiped |
3 | * with the DZ chipset. | 3 | * with the DZ chipset. |
4 | * | 4 | * |
5 | * Copyright (C) 1998 Olivier A. D. Lebaillif | 5 | * Copyright (C) 1998 Olivier A. D. Lebaillif |
6 | * | 6 | * |
7 | * Email: olivier.lebaillif@ifrsys.com | 7 | * Email: olivier.lebaillif@ifrsys.com |
8 | * | 8 | * |
9 | * [31-AUG-98] triemer | 9 | * [31-AUG-98] triemer |
@@ -11,14 +11,14 @@ | |||
11 | * removed base_addr code - moving address assignment to setup.c | 11 | * removed base_addr code - moving address assignment to setup.c |
12 | * Changed name of dz_init to rs_init to be consistent with tc code | 12 | * Changed name of dz_init to rs_init to be consistent with tc code |
13 | * [13-NOV-98] triemer fixed code to receive characters | 13 | * [13-NOV-98] triemer fixed code to receive characters |
14 | * after patches by harald to irq code. | 14 | * after patches by harald to irq code. |
15 | * [09-JAN-99] triemer minor fix for schedule - due to removal of timeout | 15 | * [09-JAN-99] triemer minor fix for schedule - due to removal of timeout |
16 | * field from "current" - somewhere between 2.1.121 and 2.1.131 | 16 | * field from "current" - somewhere between 2.1.121 and 2.1.131 |
17 | Qua Jun 27 15:02:26 BRT 2001 | 17 | Qua Jun 27 15:02:26 BRT 2001 |
18 | * [27-JUN-2001] Arnaldo Carvalho de Melo <acme@conectiva.com.br> - cleanups | 18 | * [27-JUN-2001] Arnaldo Carvalho de Melo <acme@conectiva.com.br> - cleanups |
19 | * | 19 | * |
20 | * Parts (C) 1999 David Airlie, airlied@linux.ie | 20 | * Parts (C) 1999 David Airlie, airlied@linux.ie |
21 | * [07-SEP-99] Bugfixes | 21 | * [07-SEP-99] Bugfixes |
22 | * | 22 | * |
23 | * [06-Jan-2002] Russell King <rmk@arm.linux.org.uk> | 23 | * [06-Jan-2002] Russell King <rmk@arm.linux.org.uk> |
24 | * Converted to new serial core | 24 | * Converted to new serial core |
@@ -64,7 +64,7 @@ static struct dz_port dz_ports[DZ_NB_PORT]; | |||
64 | 64 | ||
65 | #ifdef DEBUG_DZ | 65 | #ifdef DEBUG_DZ |
66 | /* | 66 | /* |
67 | * debugging code to send out chars via prom | 67 | * debugging code to send out chars via prom |
68 | */ | 68 | */ |
69 | static void debug_console(const char *s, int count) | 69 | static void debug_console(const char *s, int count) |
70 | { | 70 | { |
@@ -82,7 +82,7 @@ static void debug_console(const char *s, int count) | |||
82 | * ------------------------------------------------------------ | 82 | * ------------------------------------------------------------ |
83 | * dz_in () and dz_out () | 83 | * dz_in () and dz_out () |
84 | * | 84 | * |
85 | * These routines are used to access the registers of the DZ | 85 | * These routines are used to access the registers of the DZ |
86 | * chip, hiding relocation differences between implementation. | 86 | * chip, hiding relocation differences between implementation. |
87 | * ------------------------------------------------------------ | 87 | * ------------------------------------------------------------ |
88 | */ | 88 | */ |
@@ -106,8 +106,8 @@ static inline void dz_out(struct dz_port *dport, unsigned offset, | |||
106 | * ------------------------------------------------------------ | 106 | * ------------------------------------------------------------ |
107 | * rs_stop () and rs_start () | 107 | * rs_stop () and rs_start () |
108 | * | 108 | * |
109 | * These routines are called before setting or resetting | 109 | * These routines are called before setting or resetting |
110 | * tty->stopped. They enable or disable transmitter interrupts, | 110 | * tty->stopped. They enable or disable transmitter interrupts, |
111 | * as necessary. | 111 | * as necessary. |
112 | * ------------------------------------------------------------ | 112 | * ------------------------------------------------------------ |
113 | */ | 113 | */ |
@@ -156,17 +156,17 @@ static void dz_enable_ms(struct uart_port *port) | |||
156 | 156 | ||
157 | /* | 157 | /* |
158 | * ------------------------------------------------------------ | 158 | * ------------------------------------------------------------ |
159 | * Here starts the interrupt handling routines. All of the | 159 | * Here starts the interrupt handling routines. All of the |
160 | * following subroutines are declared as inline and are folded | 160 | * following subroutines are declared as inline and are folded |
161 | * into dz_interrupt. They were separated out for readability's | 161 | * into dz_interrupt. They were separated out for readability's |
162 | * sake. | 162 | * sake. |
163 | * | 163 | * |
164 | * Note: rs_interrupt() is a "fast" interrupt, which means that it | 164 | * Note: rs_interrupt() is a "fast" interrupt, which means that it |
165 | * runs with interrupts turned off. People who may want to modify | 165 | * runs with interrupts turned off. People who may want to modify |
166 | * rs_interrupt() should try to keep the interrupt handler as fast as | 166 | * rs_interrupt() should try to keep the interrupt handler as fast as |
167 | * possible. After you are done making modifications, it is not a bad | 167 | * possible. After you are done making modifications, it is not a bad |
168 | * idea to do: | 168 | * idea to do: |
169 | * | 169 | * |
170 | * make drivers/serial/dz.s | 170 | * make drivers/serial/dz.s |
171 | * | 171 | * |
172 | * and look at the resulting assemble code in dz.s. | 172 | * and look at the resulting assemble code in dz.s. |
@@ -403,7 +403,7 @@ static void dz_set_mctrl(struct uart_port *uport, unsigned int mctrl) | |||
403 | * startup () | 403 | * startup () |
404 | * | 404 | * |
405 | * various initialization tasks | 405 | * various initialization tasks |
406 | * ------------------------------------------------------------------- | 406 | * ------------------------------------------------------------------- |
407 | */ | 407 | */ |
408 | static int dz_startup(struct uart_port *uport) | 408 | static int dz_startup(struct uart_port *uport) |
409 | { | 409 | { |
@@ -430,13 +430,13 @@ static int dz_startup(struct uart_port *uport) | |||
430 | return 0; | 430 | return 0; |
431 | } | 431 | } |
432 | 432 | ||
433 | /* | 433 | /* |
434 | * ------------------------------------------------------------------- | 434 | * ------------------------------------------------------------------- |
435 | * shutdown () | 435 | * shutdown () |
436 | * | 436 | * |
437 | * This routine will shutdown a serial port; interrupts are disabled, and | 437 | * This routine will shutdown a serial port; interrupts are disabled, and |
438 | * DTR is dropped if the hangup on close termio flag is on. | 438 | * DTR is dropped if the hangup on close termio flag is on. |
439 | * ------------------------------------------------------------------- | 439 | * ------------------------------------------------------------------- |
440 | */ | 440 | */ |
441 | static void dz_shutdown(struct uart_port *uport) | 441 | static void dz_shutdown(struct uart_port *uport) |
442 | { | 442 | { |
@@ -451,7 +451,7 @@ static void dz_shutdown(struct uart_port *uport) | |||
451 | * release the bus after transmitting. This must be done when | 451 | * release the bus after transmitting. This must be done when |
452 | * the transmit shift register is empty, not be done when the | 452 | * the transmit shift register is empty, not be done when the |
453 | * transmit holding register is empty. This functionality | 453 | * transmit holding register is empty. This functionality |
454 | * allows an RS485 driver to be written in user space. | 454 | * allows an RS485 driver to be written in user space. |
455 | */ | 455 | */ |
456 | static unsigned int dz_tx_empty(struct uart_port *uport) | 456 | static unsigned int dz_tx_empty(struct uart_port *uport) |
457 | { | 457 | { |
@@ -645,9 +645,9 @@ static void __init dz_init_ports(void) | |||
645 | 645 | ||
646 | if (mips_machtype == MACH_DS23100 || | 646 | if (mips_machtype == MACH_DS23100 || |
647 | mips_machtype == MACH_DS5100) | 647 | mips_machtype == MACH_DS5100) |
648 | base = (unsigned long) KN01_DZ11_BASE; | 648 | base = CKSEG1ADDR(KN01_SLOT_BASE + KN01_DZ11); |
649 | else | 649 | else |
650 | base = (unsigned long) KN02_DZ11_BASE; | 650 | base = CKSEG1ADDR(KN02_SLOT_BASE + KN02_DZ11); |
651 | 651 | ||
652 | for (i = 0, dport = dz_ports; i < DZ_NB_PORT; i++, dport++) { | 652 | for (i = 0, dport = dz_ports; i < DZ_NB_PORT; i++, dport++) { |
653 | spin_lock_init(&dport->port.lock); | 653 | spin_lock_init(&dport->port.lock); |
@@ -695,13 +695,13 @@ static void dz_console_put_char(struct dz_port *dport, unsigned char ch) | |||
695 | 695 | ||
696 | spin_unlock_irqrestore(&dport->port.lock, flags); | 696 | spin_unlock_irqrestore(&dport->port.lock, flags); |
697 | } | 697 | } |
698 | /* | 698 | /* |
699 | * ------------------------------------------------------------------- | 699 | * ------------------------------------------------------------------- |
700 | * dz_console_print () | 700 | * dz_console_print () |
701 | * | 701 | * |
702 | * dz_console_print is registered for printk. | 702 | * dz_console_print is registered for printk. |
703 | * The console must be locked when we get here. | 703 | * The console must be locked when we get here. |
704 | * ------------------------------------------------------------------- | 704 | * ------------------------------------------------------------------- |
705 | */ | 705 | */ |
706 | static void dz_console_print(struct console *cons, | 706 | static void dz_console_print(struct console *cons, |
707 | const char *str, | 707 | const char *str, |
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 5d3cb8486447..b8727d9bf690 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c | |||
@@ -725,7 +725,7 @@ mpc52xx_uart_probe(struct platform_device *dev) | |||
725 | int i, idx, ret; | 725 | int i, idx, ret; |
726 | 726 | ||
727 | /* Check validity & presence */ | 727 | /* Check validity & presence */ |
728 | idx = pdev->id; | 728 | idx = dev->id; |
729 | if (idx < 0 || idx >= MPC52xx_PSC_MAXNUM) | 729 | if (idx < 0 || idx >= MPC52xx_PSC_MAXNUM) |
730 | return -EINVAL; | 730 | return -EINVAL; |
731 | 731 | ||
@@ -748,7 +748,7 @@ mpc52xx_uart_probe(struct platform_device *dev) | |||
748 | port->ops = &mpc52xx_uart_ops; | 748 | port->ops = &mpc52xx_uart_ops; |
749 | 749 | ||
750 | /* Search for IRQ and mapbase */ | 750 | /* Search for IRQ and mapbase */ |
751 | for (i=0 ; i<pdev->num_resources ; i++, res++) { | 751 | for (i=0 ; i<dev->num_resources ; i++, res++) { |
752 | if (res->flags & IORESOURCE_MEM) | 752 | if (res->flags & IORESOURCE_MEM) |
753 | port->mapbase = res->start; | 753 | port->mapbase = res->start; |
754 | else if (res->flags & IORESOURCE_IRQ) | 754 | else if (res->flags & IORESOURCE_IRQ) |
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c index fd9deee20e05..0e3daf6d7b50 100644 --- a/drivers/serial/sa1100.c +++ b/drivers/serial/sa1100.c | |||
@@ -156,7 +156,7 @@ static void sa1100_stop_tx(struct uart_port *port) | |||
156 | } | 156 | } |
157 | 157 | ||
158 | /* | 158 | /* |
159 | * interrupts may not be disabled on entry | 159 | * port locked and interrupts disabled |
160 | */ | 160 | */ |
161 | static void sa1100_start_tx(struct uart_port *port) | 161 | static void sa1100_start_tx(struct uart_port *port) |
162 | { | 162 | { |
@@ -164,11 +164,9 @@ static void sa1100_start_tx(struct uart_port *port) | |||
164 | unsigned long flags; | 164 | unsigned long flags; |
165 | u32 utcr3; | 165 | u32 utcr3; |
166 | 166 | ||
167 | spin_lock_irqsave(&sport->port.lock, flags); | ||
168 | utcr3 = UART_GET_UTCR3(sport); | 167 | utcr3 = UART_GET_UTCR3(sport); |
169 | sport->port.read_status_mask |= UTSR0_TO_SM(UTSR0_TFS); | 168 | sport->port.read_status_mask |= UTSR0_TO_SM(UTSR0_TFS); |
170 | UART_PUT_UTCR3(sport, utcr3 | UTCR3_TIE); | 169 | UART_PUT_UTCR3(sport, utcr3 | UTCR3_TIE); |
171 | spin_unlock_irqrestore(&sport->port.lock, flags); | ||
172 | } | 170 | } |
173 | 171 | ||
174 | /* | 172 | /* |
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 427a23858076..2331296e1e17 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c | |||
@@ -209,33 +209,45 @@ static void uart_shutdown(struct uart_state *state) | |||
209 | struct uart_info *info = state->info; | 209 | struct uart_info *info = state->info; |
210 | struct uart_port *port = state->port; | 210 | struct uart_port *port = state->port; |
211 | 211 | ||
212 | if (!(info->flags & UIF_INITIALIZED)) | ||
213 | return; | ||
214 | |||
215 | /* | 212 | /* |
216 | * Turn off DTR and RTS early. | 213 | * Set the TTY IO error marker |
217 | */ | 214 | */ |
218 | if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) | 215 | if (info->tty) |
219 | uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); | 216 | set_bit(TTY_IO_ERROR, &info->tty->flags); |
220 | 217 | ||
221 | /* | 218 | if (info->flags & UIF_INITIALIZED) { |
222 | * clear delta_msr_wait queue to avoid mem leaks: we may free | 219 | info->flags &= ~UIF_INITIALIZED; |
223 | * the irq here so the queue might never be woken up. Note | ||
224 | * that we won't end up waiting on delta_msr_wait again since | ||
225 | * any outstanding file descriptors should be pointing at | ||
226 | * hung_up_tty_fops now. | ||
227 | */ | ||
228 | wake_up_interruptible(&info->delta_msr_wait); | ||
229 | 220 | ||
230 | /* | 221 | /* |
231 | * Free the IRQ and disable the port. | 222 | * Turn off DTR and RTS early. |
232 | */ | 223 | */ |
233 | port->ops->shutdown(port); | 224 | if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) |
225 | uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); | ||
226 | |||
227 | /* | ||
228 | * clear delta_msr_wait queue to avoid mem leaks: we may free | ||
229 | * the irq here so the queue might never be woken up. Note | ||
230 | * that we won't end up waiting on delta_msr_wait again since | ||
231 | * any outstanding file descriptors should be pointing at | ||
232 | * hung_up_tty_fops now. | ||
233 | */ | ||
234 | wake_up_interruptible(&info->delta_msr_wait); | ||
235 | |||
236 | /* | ||
237 | * Free the IRQ and disable the port. | ||
238 | */ | ||
239 | port->ops->shutdown(port); | ||
240 | |||
241 | /* | ||
242 | * Ensure that the IRQ handler isn't running on another CPU. | ||
243 | */ | ||
244 | synchronize_irq(port->irq); | ||
245 | } | ||
234 | 246 | ||
235 | /* | 247 | /* |
236 | * Ensure that the IRQ handler isn't running on another CPU. | 248 | * kill off our tasklet |
237 | */ | 249 | */ |
238 | synchronize_irq(port->irq); | 250 | tasklet_kill(&info->tlet); |
239 | 251 | ||
240 | /* | 252 | /* |
241 | * Free the transmit buffer page. | 253 | * Free the transmit buffer page. |
@@ -244,15 +256,6 @@ static void uart_shutdown(struct uart_state *state) | |||
244 | free_page((unsigned long)info->xmit.buf); | 256 | free_page((unsigned long)info->xmit.buf); |
245 | info->xmit.buf = NULL; | 257 | info->xmit.buf = NULL; |
246 | } | 258 | } |
247 | |||
248 | /* | ||
249 | * kill off our tasklet | ||
250 | */ | ||
251 | tasklet_kill(&info->tlet); | ||
252 | if (info->tty) | ||
253 | set_bit(TTY_IO_ERROR, &info->tty->flags); | ||
254 | |||
255 | info->flags &= ~UIF_INITIALIZED; | ||
256 | } | 259 | } |
257 | 260 | ||
258 | /** | 261 | /** |
@@ -1928,14 +1931,25 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) | |||
1928 | 1931 | ||
1929 | if (state->info && state->info->flags & UIF_INITIALIZED) { | 1932 | if (state->info && state->info->flags & UIF_INITIALIZED) { |
1930 | struct uart_ops *ops = port->ops; | 1933 | struct uart_ops *ops = port->ops; |
1934 | int ret; | ||
1931 | 1935 | ||
1932 | ops->set_mctrl(port, 0); | 1936 | ops->set_mctrl(port, 0); |
1933 | ops->startup(port); | 1937 | ret = ops->startup(port); |
1934 | uart_change_speed(state, NULL); | 1938 | if (ret == 0) { |
1935 | spin_lock_irq(&port->lock); | 1939 | uart_change_speed(state, NULL); |
1936 | ops->set_mctrl(port, port->mctrl); | 1940 | spin_lock_irq(&port->lock); |
1937 | ops->start_tx(port); | 1941 | ops->set_mctrl(port, port->mctrl); |
1938 | spin_unlock_irq(&port->lock); | 1942 | ops->start_tx(port); |
1943 | spin_unlock_irq(&port->lock); | ||
1944 | } else { | ||
1945 | /* | ||
1946 | * Failed to resume - maybe hardware went away? | ||
1947 | * Clear the "initialized" flag so we won't try | ||
1948 | * to call the low level drivers shutdown method. | ||
1949 | */ | ||
1950 | state->info->flags &= ~UIF_INITIALIZED; | ||
1951 | uart_shutdown(state); | ||
1952 | } | ||
1939 | } | 1953 | } |
1940 | 1954 | ||
1941 | up(&state->sem); | 1955 | up(&state->sem); |
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index e7802ffe549a..bcea87c3cc06 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c | |||
@@ -106,8 +106,7 @@ enum { | |||
106 | FBCON_LOGO_DONTSHOW = -3 /* do not show the logo */ | 106 | FBCON_LOGO_DONTSHOW = -3 /* do not show the logo */ |
107 | }; | 107 | }; |
108 | 108 | ||
109 | struct display fb_display[MAX_NR_CONSOLES]; | 109 | static struct display fb_display[MAX_NR_CONSOLES]; |
110 | EXPORT_SYMBOL(fb_display); | ||
111 | 110 | ||
112 | static signed char con2fb_map[MAX_NR_CONSOLES]; | 111 | static signed char con2fb_map[MAX_NR_CONSOLES]; |
113 | static signed char con2fb_map_boot[MAX_NR_CONSOLES]; | 112 | static signed char con2fb_map_boot[MAX_NR_CONSOLES]; |
@@ -653,13 +652,12 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info, | |||
653 | { | 652 | { |
654 | struct fbcon_ops *ops = info->fbcon_par; | 653 | struct fbcon_ops *ops = info->fbcon_par; |
655 | 654 | ||
655 | ops->p = (p) ? p : &fb_display[vc->vc_num]; | ||
656 | |||
656 | if ((info->flags & FBINFO_MISC_TILEBLITTING)) | 657 | if ((info->flags & FBINFO_MISC_TILEBLITTING)) |
657 | fbcon_set_tileops(vc, info, p, ops); | 658 | fbcon_set_tileops(vc, info, p, ops); |
658 | else { | 659 | else { |
659 | struct display *disp; | 660 | fbcon_set_rotation(info, ops->p); |
660 | |||
661 | disp = (p) ? p : &fb_display[vc->vc_num]; | ||
662 | fbcon_set_rotation(info, disp); | ||
663 | fbcon_set_bitops(ops); | 661 | fbcon_set_bitops(ops); |
664 | } | 662 | } |
665 | } | 663 | } |
@@ -668,11 +666,10 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info, | |||
668 | struct display *p) | 666 | struct display *p) |
669 | { | 667 | { |
670 | struct fbcon_ops *ops = info->fbcon_par; | 668 | struct fbcon_ops *ops = info->fbcon_par; |
671 | struct display *disp; | ||
672 | 669 | ||
673 | info->flags &= ~FBINFO_MISC_TILEBLITTING; | 670 | info->flags &= ~FBINFO_MISC_TILEBLITTING; |
674 | disp = (p) ? p : &fb_display[vc->vc_num]; | 671 | ops->p = (p) ? p : &fb_display[vc->vc_num]; |
675 | fbcon_set_rotation(info, disp); | 672 | fbcon_set_rotation(info, ops->p); |
676 | fbcon_set_bitops(ops); | 673 | fbcon_set_bitops(ops); |
677 | } | 674 | } |
678 | #endif /* CONFIG_MISC_TILEBLITTING */ | 675 | #endif /* CONFIG_MISC_TILEBLITTING */ |
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h index accfd7bd8e93..6892e7ff34de 100644 --- a/drivers/video/console/fbcon.h +++ b/drivers/video/console/fbcon.h | |||
@@ -52,8 +52,6 @@ struct display { | |||
52 | struct fb_videomode *mode; | 52 | struct fb_videomode *mode; |
53 | }; | 53 | }; |
54 | 54 | ||
55 | extern struct display fb_display[]; | ||
56 | |||
57 | struct fbcon_ops { | 55 | struct fbcon_ops { |
58 | void (*bmove)(struct vc_data *vc, struct fb_info *info, int sy, | 56 | void (*bmove)(struct vc_data *vc, struct fb_info *info, int sy, |
59 | int sx, int dy, int dx, int height, int width); | 57 | int sx, int dy, int dx, int height, int width); |
@@ -73,6 +71,7 @@ struct fbcon_ops { | |||
73 | struct fb_var_screeninfo var; /* copy of the current fb_var_screeninfo */ | 71 | struct fb_var_screeninfo var; /* copy of the current fb_var_screeninfo */ |
74 | struct timer_list cursor_timer; /* Cursor timer */ | 72 | struct timer_list cursor_timer; /* Cursor timer */ |
75 | struct fb_cursor cursor_state; | 73 | struct fb_cursor cursor_state; |
74 | struct display *p; | ||
76 | int currcon; /* Current VC. */ | 75 | int currcon; /* Current VC. */ |
77 | int cursor_flash; | 76 | int cursor_flash; |
78 | int cursor_reset; | 77 | int cursor_reset; |
diff --git a/drivers/video/console/fbcon_ccw.c b/drivers/video/console/fbcon_ccw.c index 680aabab73c5..3afd1eeb1ade 100644 --- a/drivers/video/console/fbcon_ccw.c +++ b/drivers/video/console/fbcon_ccw.c | |||
@@ -63,9 +63,9 @@ static inline void ccw_update_attr(u8 *dst, u8 *src, int attribute, | |||
63 | static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy, | 63 | static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy, |
64 | int sx, int dy, int dx, int height, int width) | 64 | int sx, int dy, int dx, int height, int width) |
65 | { | 65 | { |
66 | struct display *p = &fb_display[vc->vc_num]; | 66 | struct fbcon_ops *ops = info->fbcon_par; |
67 | struct fb_copyarea area; | 67 | struct fb_copyarea area; |
68 | u32 vyres = GETVYRES(p->scrollmode, info); | 68 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
69 | 69 | ||
70 | area.sx = sy * vc->vc_font.height; | 70 | area.sx = sy * vc->vc_font.height; |
71 | area.sy = vyres - ((sx + width) * vc->vc_font.width); | 71 | area.sy = vyres - ((sx + width) * vc->vc_font.width); |
@@ -80,10 +80,10 @@ static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy, | |||
80 | static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy, | 80 | static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy, |
81 | int sx, int height, int width) | 81 | int sx, int height, int width) |
82 | { | 82 | { |
83 | struct display *p = &fb_display[vc->vc_num]; | 83 | struct fbcon_ops *ops = info->fbcon_par; |
84 | struct fb_fillrect region; | 84 | struct fb_fillrect region; |
85 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 85 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
86 | u32 vyres = GETVYRES(p->scrollmode, info); | 86 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
87 | 87 | ||
88 | region.color = attr_bgcol_ec(bgshift,vc); | 88 | region.color = attr_bgcol_ec(bgshift,vc); |
89 | region.dx = sy * vc->vc_font.height; | 89 | region.dx = sy * vc->vc_font.height; |
@@ -131,7 +131,6 @@ static void ccw_putcs(struct vc_data *vc, struct fb_info *info, | |||
131 | int fg, int bg) | 131 | int fg, int bg) |
132 | { | 132 | { |
133 | struct fb_image image; | 133 | struct fb_image image; |
134 | struct display *p = &fb_display[vc->vc_num]; | ||
135 | struct fbcon_ops *ops = info->fbcon_par; | 134 | struct fbcon_ops *ops = info->fbcon_par; |
136 | u32 width = (vc->vc_font.height + 7)/8; | 135 | u32 width = (vc->vc_font.height + 7)/8; |
137 | u32 cellsize = width * vc->vc_font.width; | 136 | u32 cellsize = width * vc->vc_font.width; |
@@ -141,7 +140,7 @@ static void ccw_putcs(struct vc_data *vc, struct fb_info *info, | |||
141 | u32 cnt, pitch, size; | 140 | u32 cnt, pitch, size; |
142 | u32 attribute = get_attribute(info, scr_readw(s)); | 141 | u32 attribute = get_attribute(info, scr_readw(s)); |
143 | u8 *dst, *buf = NULL; | 142 | u8 *dst, *buf = NULL; |
144 | u32 vyres = GETVYRES(p->scrollmode, info); | 143 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
145 | 144 | ||
146 | if (!ops->fontbuffer) | 145 | if (!ops->fontbuffer) |
147 | return; | 146 | return; |
@@ -397,9 +396,8 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, | |||
397 | int ccw_update_start(struct fb_info *info) | 396 | int ccw_update_start(struct fb_info *info) |
398 | { | 397 | { |
399 | struct fbcon_ops *ops = info->fbcon_par; | 398 | struct fbcon_ops *ops = info->fbcon_par; |
400 | struct display *p = &fb_display[ops->currcon]; | ||
401 | u32 yoffset; | 399 | u32 yoffset; |
402 | u32 vyres = GETVYRES(p->scrollmode, info); | 400 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
403 | int err; | 401 | int err; |
404 | 402 | ||
405 | yoffset = (vyres - info->var.yres) - ops->var.xoffset; | 403 | yoffset = (vyres - info->var.yres) - ops->var.xoffset; |
diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c index 6c6f3b6dd175..6d92b8456206 100644 --- a/drivers/video/console/fbcon_cw.c +++ b/drivers/video/console/fbcon_cw.c | |||
@@ -49,9 +49,9 @@ static inline void cw_update_attr(u8 *dst, u8 *src, int attribute, | |||
49 | static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy, | 49 | static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy, |
50 | int sx, int dy, int dx, int height, int width) | 50 | int sx, int dy, int dx, int height, int width) |
51 | { | 51 | { |
52 | struct display *p = &fb_display[vc->vc_num]; | 52 | struct fbcon_ops *ops = info->fbcon_par; |
53 | struct fb_copyarea area; | 53 | struct fb_copyarea area; |
54 | u32 vxres = GETVXRES(p->scrollmode, info); | 54 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
55 | 55 | ||
56 | area.sx = vxres - ((sy + height) * vc->vc_font.height); | 56 | area.sx = vxres - ((sy + height) * vc->vc_font.height); |
57 | area.sy = sx * vc->vc_font.width; | 57 | area.sy = sx * vc->vc_font.width; |
@@ -66,10 +66,10 @@ static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy, | |||
66 | static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy, | 66 | static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy, |
67 | int sx, int height, int width) | 67 | int sx, int height, int width) |
68 | { | 68 | { |
69 | struct display *p = &fb_display[vc->vc_num]; | 69 | struct fbcon_ops *ops = info->fbcon_par; |
70 | struct fb_fillrect region; | 70 | struct fb_fillrect region; |
71 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 71 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
72 | u32 vxres = GETVXRES(p->scrollmode, info); | 72 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
73 | 73 | ||
74 | region.color = attr_bgcol_ec(bgshift,vc); | 74 | region.color = attr_bgcol_ec(bgshift,vc); |
75 | region.dx = vxres - ((sy + height) * vc->vc_font.height); | 75 | region.dx = vxres - ((sy + height) * vc->vc_font.height); |
@@ -117,7 +117,6 @@ static void cw_putcs(struct vc_data *vc, struct fb_info *info, | |||
117 | int fg, int bg) | 117 | int fg, int bg) |
118 | { | 118 | { |
119 | struct fb_image image; | 119 | struct fb_image image; |
120 | struct display *p = &fb_display[vc->vc_num]; | ||
121 | struct fbcon_ops *ops = info->fbcon_par; | 120 | struct fbcon_ops *ops = info->fbcon_par; |
122 | u32 width = (vc->vc_font.height + 7)/8; | 121 | u32 width = (vc->vc_font.height + 7)/8; |
123 | u32 cellsize = width * vc->vc_font.width; | 122 | u32 cellsize = width * vc->vc_font.width; |
@@ -127,7 +126,7 @@ static void cw_putcs(struct vc_data *vc, struct fb_info *info, | |||
127 | u32 cnt, pitch, size; | 126 | u32 cnt, pitch, size; |
128 | u32 attribute = get_attribute(info, scr_readw(s)); | 127 | u32 attribute = get_attribute(info, scr_readw(s)); |
129 | u8 *dst, *buf = NULL; | 128 | u8 *dst, *buf = NULL; |
130 | u32 vxres = GETVXRES(p->scrollmode, info); | 129 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
131 | 130 | ||
132 | if (!ops->fontbuffer) | 131 | if (!ops->fontbuffer) |
133 | return; | 132 | return; |
@@ -381,8 +380,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, | |||
381 | int cw_update_start(struct fb_info *info) | 380 | int cw_update_start(struct fb_info *info) |
382 | { | 381 | { |
383 | struct fbcon_ops *ops = info->fbcon_par; | 382 | struct fbcon_ops *ops = info->fbcon_par; |
384 | struct display *p = &fb_display[ops->currcon]; | 383 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
385 | u32 vxres = GETVXRES(p->scrollmode, info); | ||
386 | u32 xoffset; | 384 | u32 xoffset; |
387 | int err; | 385 | int err; |
388 | 386 | ||
diff --git a/drivers/video/console/fbcon_ud.c b/drivers/video/console/fbcon_ud.c index 2e1d9d4249cd..c4d7c89212b4 100644 --- a/drivers/video/console/fbcon_ud.c +++ b/drivers/video/console/fbcon_ud.c | |||
@@ -48,10 +48,10 @@ static inline void ud_update_attr(u8 *dst, u8 *src, int attribute, | |||
48 | static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy, | 48 | static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy, |
49 | int sx, int dy, int dx, int height, int width) | 49 | int sx, int dy, int dx, int height, int width) |
50 | { | 50 | { |
51 | struct display *p = &fb_display[vc->vc_num]; | 51 | struct fbcon_ops *ops = info->fbcon_par; |
52 | struct fb_copyarea area; | 52 | struct fb_copyarea area; |
53 | u32 vyres = GETVYRES(p->scrollmode, info); | 53 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
54 | u32 vxres = GETVXRES(p->scrollmode, info); | 54 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
55 | 55 | ||
56 | area.sy = vyres - ((sy + height) * vc->vc_font.height); | 56 | area.sy = vyres - ((sy + height) * vc->vc_font.height); |
57 | area.sx = vxres - ((sx + width) * vc->vc_font.width); | 57 | area.sx = vxres - ((sx + width) * vc->vc_font.width); |
@@ -66,11 +66,11 @@ static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy, | |||
66 | static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy, | 66 | static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy, |
67 | int sx, int height, int width) | 67 | int sx, int height, int width) |
68 | { | 68 | { |
69 | struct display *p = &fb_display[vc->vc_num]; | 69 | struct fbcon_ops *ops = info->fbcon_par; |
70 | struct fb_fillrect region; | 70 | struct fb_fillrect region; |
71 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 71 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
72 | u32 vyres = GETVYRES(p->scrollmode, info); | 72 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
73 | u32 vxres = GETVXRES(p->scrollmode, info); | 73 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
74 | 74 | ||
75 | region.color = attr_bgcol_ec(bgshift,vc); | 75 | region.color = attr_bgcol_ec(bgshift,vc); |
76 | region.dy = vyres - ((sy + height) * vc->vc_font.height); | 76 | region.dy = vyres - ((sy + height) * vc->vc_font.height); |
@@ -153,7 +153,6 @@ static void ud_putcs(struct vc_data *vc, struct fb_info *info, | |||
153 | int fg, int bg) | 153 | int fg, int bg) |
154 | { | 154 | { |
155 | struct fb_image image; | 155 | struct fb_image image; |
156 | struct display *p = &fb_display[vc->vc_num]; | ||
157 | struct fbcon_ops *ops = info->fbcon_par; | 156 | struct fbcon_ops *ops = info->fbcon_par; |
158 | u32 width = (vc->vc_font.width + 7)/8; | 157 | u32 width = (vc->vc_font.width + 7)/8; |
159 | u32 cellsize = width * vc->vc_font.height; | 158 | u32 cellsize = width * vc->vc_font.height; |
@@ -163,8 +162,8 @@ static void ud_putcs(struct vc_data *vc, struct fb_info *info, | |||
163 | u32 mod = vc->vc_font.width % 8, cnt, pitch, size; | 162 | u32 mod = vc->vc_font.width % 8, cnt, pitch, size; |
164 | u32 attribute = get_attribute(info, scr_readw(s)); | 163 | u32 attribute = get_attribute(info, scr_readw(s)); |
165 | u8 *dst, *buf = NULL; | 164 | u8 *dst, *buf = NULL; |
166 | u32 vyres = GETVYRES(p->scrollmode, info); | 165 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
167 | u32 vxres = GETVXRES(p->scrollmode, info); | 166 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
168 | 167 | ||
169 | if (!ops->fontbuffer) | 168 | if (!ops->fontbuffer) |
170 | return; | 169 | return; |
@@ -421,10 +420,9 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, | |||
421 | int ud_update_start(struct fb_info *info) | 420 | int ud_update_start(struct fb_info *info) |
422 | { | 421 | { |
423 | struct fbcon_ops *ops = info->fbcon_par; | 422 | struct fbcon_ops *ops = info->fbcon_par; |
424 | struct display *p = &fb_display[ops->currcon]; | ||
425 | u32 xoffset, yoffset; | 423 | u32 xoffset, yoffset; |
426 | u32 vyres = GETVYRES(p->scrollmode, info); | 424 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
427 | u32 vxres = GETVXRES(p->scrollmode, info); | 425 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
428 | int err; | 426 | int err; |
429 | 427 | ||
430 | xoffset = (vxres - info->var.xres) - ops->var.xoffset; | 428 | xoffset = (vxres - info->var.xres) - ops->var.xoffset; |
diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h index f60b1f432270..3353103e8b0b 100644 --- a/drivers/video/nvidia/nv_proto.h +++ b/drivers/video/nvidia/nv_proto.h | |||
@@ -42,7 +42,7 @@ int nvidia_probe_i2c_connector(struct fb_info *info, int conn, | |||
42 | #define nvidia_probe_i2c_connector(p, c, edid) (-1) | 42 | #define nvidia_probe_i2c_connector(p, c, edid) (-1) |
43 | #endif | 43 | #endif |
44 | 44 | ||
45 | #ifdef CONFIG_FB_OF | 45 | #ifdef CONFIG_PPC_OF |
46 | int nvidia_probe_of_connector(struct fb_info *info, int conn, | 46 | int nvidia_probe_of_connector(struct fb_info *info, int conn, |
47 | u8 ** out_edid); | 47 | u8 ** out_edid); |
48 | #else | 48 | #else |
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index 0b40a2a721c1..bee09c6e48f6 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c | |||
@@ -1301,7 +1301,7 @@ static int nvidiafb_pan_display(struct fb_var_screeninfo *var, | |||
1301 | struct nvidia_par *par = info->par; | 1301 | struct nvidia_par *par = info->par; |
1302 | u32 total; | 1302 | u32 total; |
1303 | 1303 | ||
1304 | total = info->var.yoffset * info->fix.line_length + info->var.xoffset; | 1304 | total = var->yoffset * info->fix.line_length + var->xoffset; |
1305 | 1305 | ||
1306 | NVSetStartAddress(par, total); | 1306 | NVSetStartAddress(par, total); |
1307 | 1307 | ||
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index 2c3aa2fcfd91..3e58ddc2bc38 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c | |||
@@ -413,6 +413,7 @@ static int __init vesafb_probe(struct platform_device *dev) | |||
413 | * region already (FIXME) */ | 413 | * region already (FIXME) */ |
414 | request_region(0x3c0, 32, "vesafb"); | 414 | request_region(0x3c0, 32, "vesafb"); |
415 | 415 | ||
416 | #ifdef CONFIG_MTRR | ||
416 | if (mtrr) { | 417 | if (mtrr) { |
417 | unsigned int temp_size = size_total; | 418 | unsigned int temp_size = size_total; |
418 | unsigned int type = 0; | 419 | unsigned int type = 0; |
@@ -450,6 +451,7 @@ static int __init vesafb_probe(struct platform_device *dev) | |||
450 | } while (temp_size >= PAGE_SIZE && rc == -EINVAL); | 451 | } while (temp_size >= PAGE_SIZE && rc == -EINVAL); |
451 | } | 452 | } |
452 | } | 453 | } |
454 | #endif | ||
453 | 455 | ||
454 | info->fbops = &vesafb_ops; | 456 | info->fbops = &vesafb_ops; |
455 | info->var = vesafb_defined; | 457 | info->var = vesafb_defined; |
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index daa46051f55d..f6e24ee85f07 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c | |||
@@ -514,7 +514,7 @@ int __init w100fb_probe(struct platform_device *pdev) | |||
514 | if (remapped_fbuf == NULL) | 514 | if (remapped_fbuf == NULL) |
515 | goto out; | 515 | goto out; |
516 | 516 | ||
517 | info=framebuffer_alloc(sizeof(struct w100fb_par), dev); | 517 | info=framebuffer_alloc(sizeof(struct w100fb_par), &pdev->dev); |
518 | if (!info) { | 518 | if (!info) { |
519 | err = -ENOMEM; | 519 | err = -ENOMEM; |
520 | goto out; | 520 | goto out; |
@@ -457,6 +457,8 @@ static inline struct kiocb *aio_get_req(struct kioctx *ctx) | |||
457 | 457 | ||
458 | static inline void really_put_req(struct kioctx *ctx, struct kiocb *req) | 458 | static inline void really_put_req(struct kioctx *ctx, struct kiocb *req) |
459 | { | 459 | { |
460 | assert_spin_locked(&ctx->ctx_lock); | ||
461 | |||
460 | if (req->ki_dtor) | 462 | if (req->ki_dtor) |
461 | req->ki_dtor(req); | 463 | req->ki_dtor(req); |
462 | kmem_cache_free(kiocb_cachep, req); | 464 | kmem_cache_free(kiocb_cachep, req); |
@@ -498,6 +500,8 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req) | |||
498 | dprintk(KERN_DEBUG "aio_put(%p): f_count=%d\n", | 500 | dprintk(KERN_DEBUG "aio_put(%p): f_count=%d\n", |
499 | req, atomic_read(&req->ki_filp->f_count)); | 501 | req, atomic_read(&req->ki_filp->f_count)); |
500 | 502 | ||
503 | assert_spin_locked(&ctx->ctx_lock); | ||
504 | |||
501 | req->ki_users --; | 505 | req->ki_users --; |
502 | if (unlikely(req->ki_users < 0)) | 506 | if (unlikely(req->ki_users < 0)) |
503 | BUG(); | 507 | BUG(); |
@@ -619,14 +623,13 @@ static void unuse_mm(struct mm_struct *mm) | |||
619 | * the kiocb (to tell the caller to activate the work | 623 | * the kiocb (to tell the caller to activate the work |
620 | * queue to process it), or 0, if it found that it was | 624 | * queue to process it), or 0, if it found that it was |
621 | * already queued. | 625 | * already queued. |
622 | * | ||
623 | * Should be called with the spin lock iocb->ki_ctx->ctx_lock | ||
624 | * held | ||
625 | */ | 626 | */ |
626 | static inline int __queue_kicked_iocb(struct kiocb *iocb) | 627 | static inline int __queue_kicked_iocb(struct kiocb *iocb) |
627 | { | 628 | { |
628 | struct kioctx *ctx = iocb->ki_ctx; | 629 | struct kioctx *ctx = iocb->ki_ctx; |
629 | 630 | ||
631 | assert_spin_locked(&ctx->ctx_lock); | ||
632 | |||
630 | if (list_empty(&iocb->ki_run_list)) { | 633 | if (list_empty(&iocb->ki_run_list)) { |
631 | list_add_tail(&iocb->ki_run_list, | 634 | list_add_tail(&iocb->ki_run_list, |
632 | &ctx->run_list); | 635 | &ctx->run_list); |
@@ -771,13 +774,15 @@ out: | |||
771 | * Process all pending retries queued on the ioctx | 774 | * Process all pending retries queued on the ioctx |
772 | * run list. | 775 | * run list. |
773 | * Assumes it is operating within the aio issuer's mm | 776 | * Assumes it is operating within the aio issuer's mm |
774 | * context. Expects to be called with ctx->ctx_lock held | 777 | * context. |
775 | */ | 778 | */ |
776 | static int __aio_run_iocbs(struct kioctx *ctx) | 779 | static int __aio_run_iocbs(struct kioctx *ctx) |
777 | { | 780 | { |
778 | struct kiocb *iocb; | 781 | struct kiocb *iocb; |
779 | LIST_HEAD(run_list); | 782 | LIST_HEAD(run_list); |
780 | 783 | ||
784 | assert_spin_locked(&ctx->ctx_lock); | ||
785 | |||
781 | list_splice_init(&ctx->run_list, &run_list); | 786 | list_splice_init(&ctx->run_list, &run_list); |
782 | while (!list_empty(&run_list)) { | 787 | while (!list_empty(&run_list)) { |
783 | iocb = list_entry(run_list.next, struct kiocb, | 788 | iocb = list_entry(run_list.next, struct kiocb, |
@@ -937,28 +942,19 @@ int fastcall aio_complete(struct kiocb *iocb, long res, long res2) | |||
937 | unsigned long tail; | 942 | unsigned long tail; |
938 | int ret; | 943 | int ret; |
939 | 944 | ||
940 | /* Special case handling for sync iocbs: events go directly | 945 | /* |
941 | * into the iocb for fast handling. Note that this will not | 946 | * Special case handling for sync iocbs: |
942 | * work if we allow sync kiocbs to be cancelled. in which | 947 | * - events go directly into the iocb for fast handling |
943 | * case the usage count checks will have to move under ctx_lock | 948 | * - the sync task with the iocb in its stack holds the single iocb |
944 | * for all cases. | 949 | * ref, no other paths have a way to get another ref |
950 | * - the sync task helpfully left a reference to itself in the iocb | ||
945 | */ | 951 | */ |
946 | if (is_sync_kiocb(iocb)) { | 952 | if (is_sync_kiocb(iocb)) { |
947 | int ret; | 953 | BUG_ON(iocb->ki_users != 1); |
948 | |||
949 | iocb->ki_user_data = res; | 954 | iocb->ki_user_data = res; |
950 | if (iocb->ki_users == 1) { | 955 | iocb->ki_users = 0; |
951 | iocb->ki_users = 0; | ||
952 | ret = 1; | ||
953 | } else { | ||
954 | spin_lock_irq(&ctx->ctx_lock); | ||
955 | iocb->ki_users--; | ||
956 | ret = (0 == iocb->ki_users); | ||
957 | spin_unlock_irq(&ctx->ctx_lock); | ||
958 | } | ||
959 | /* sync iocbs put the task here for us */ | ||
960 | wake_up_process(iocb->ki_obj.tsk); | 956 | wake_up_process(iocb->ki_obj.tsk); |
961 | return ret; | 957 | return 1; |
962 | } | 958 | } |
963 | 959 | ||
964 | info = &ctx->ring_info; | 960 | info = &ctx->ring_info; |
@@ -1613,12 +1609,14 @@ asmlinkage long sys_io_submit(aio_context_t ctx_id, long nr, | |||
1613 | 1609 | ||
1614 | /* lookup_kiocb | 1610 | /* lookup_kiocb |
1615 | * Finds a given iocb for cancellation. | 1611 | * Finds a given iocb for cancellation. |
1616 | * MUST be called with ctx->ctx_lock held. | ||
1617 | */ | 1612 | */ |
1618 | static struct kiocb *lookup_kiocb(struct kioctx *ctx, struct iocb __user *iocb, | 1613 | static struct kiocb *lookup_kiocb(struct kioctx *ctx, struct iocb __user *iocb, |
1619 | u32 key) | 1614 | u32 key) |
1620 | { | 1615 | { |
1621 | struct list_head *pos; | 1616 | struct list_head *pos; |
1617 | |||
1618 | assert_spin_locked(&ctx->ctx_lock); | ||
1619 | |||
1622 | /* TODO: use a hash or array, this sucks. */ | 1620 | /* TODO: use a hash or array, this sucks. */ |
1623 | list_for_each(pos, &ctx->active_reqs) { | 1621 | list_for_each(pos, &ctx->active_reqs) { |
1624 | struct kiocb *kiocb = list_kiocb(pos); | 1622 | struct kiocb *kiocb = list_kiocb(pos); |
diff --git a/fs/ext2/super.c b/fs/ext2/super.c index e4ed4b31a433..522fa70dd8ea 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c | |||
@@ -881,7 +881,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) | |||
881 | } | 881 | } |
882 | if (EXT2_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) | 882 | if (EXT2_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) |
883 | ext2_warning(sb, __FUNCTION__, | 883 | ext2_warning(sb, __FUNCTION__, |
884 | "mounting ext3 filesystem as ext2\n"); | 884 | "mounting ext3 filesystem as ext2"); |
885 | ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY); | 885 | ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY); |
886 | percpu_counter_mod(&sbi->s_freeblocks_counter, | 886 | percpu_counter_mod(&sbi->s_freeblocks_counter, |
887 | ext2_count_free_blocks(sb)); | 887 | ext2_count_free_blocks(sb)); |
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 5d9b00e28837..8824e84f8a56 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
@@ -1384,8 +1384,10 @@ static int ext3_journalled_writepage(struct page *page, | |||
1384 | ClearPageChecked(page); | 1384 | ClearPageChecked(page); |
1385 | ret = block_prepare_write(page, 0, PAGE_CACHE_SIZE, | 1385 | ret = block_prepare_write(page, 0, PAGE_CACHE_SIZE, |
1386 | ext3_get_block); | 1386 | ext3_get_block); |
1387 | if (ret != 0) | 1387 | if (ret != 0) { |
1388 | ext3_journal_stop(handle); | ||
1388 | goto out_unlock; | 1389 | goto out_unlock; |
1390 | } | ||
1389 | ret = walk_page_buffers(handle, page_buffers(page), 0, | 1391 | ret = walk_page_buffers(handle, page_buffers(page), 0, |
1390 | PAGE_CACHE_SIZE, NULL, do_journal_get_write_access); | 1392 | PAGE_CACHE_SIZE, NULL, do_journal_get_write_access); |
1391 | 1393 | ||
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index d2fa42006d8f..9ab97cef0daa 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
@@ -195,7 +195,7 @@ static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats | |||
195 | 195 | ||
196 | static int show_map(struct seq_file *m, void *v) | 196 | static int show_map(struct seq_file *m, void *v) |
197 | { | 197 | { |
198 | return show_map_internal(m, v, 0); | 198 | return show_map_internal(m, v, NULL); |
199 | } | 199 | } |
200 | 200 | ||
201 | static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd, | 201 | static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd, |
diff --git a/include/asm-alpha/atomic.h b/include/asm-alpha/atomic.h index 20ac3d95ecd9..36505bb4e8cb 100644 --- a/include/asm-alpha/atomic.h +++ b/include/asm-alpha/atomic.h | |||
@@ -177,6 +177,18 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v) | |||
177 | return result; | 177 | return result; |
178 | } | 178 | } |
179 | 179 | ||
180 | #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) | ||
181 | |||
182 | #define atomic_add_unless(v, a, u) \ | ||
183 | ({ \ | ||
184 | int c, old; \ | ||
185 | c = atomic_read(v); \ | ||
186 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
187 | c = old; \ | ||
188 | c != (u); \ | ||
189 | }) | ||
190 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
191 | |||
180 | #define atomic_dec_return(v) atomic_sub_return(1,(v)) | 192 | #define atomic_dec_return(v) atomic_sub_return(1,(v)) |
181 | #define atomic64_dec_return(v) atomic64_sub_return(1,(v)) | 193 | #define atomic64_dec_return(v) atomic64_sub_return(1,(v)) |
182 | 194 | ||
diff --git a/include/asm-arm/arch-pxa/akita.h b/include/asm-arm/arch-pxa/akita.h index 4a1fbcfccc39..5d8cc1d9cb10 100644 --- a/include/asm-arm/arch-pxa/akita.h +++ b/include/asm-arm/arch-pxa/akita.h | |||
@@ -25,6 +25,8 @@ | |||
25 | /* Default Values */ | 25 | /* Default Values */ |
26 | #define AKITA_IOEXP_IO_OUT (AKITA_IOEXP_IR_ON | AKITA_IOEXP_AKIN_PULLUP) | 26 | #define AKITA_IOEXP_IO_OUT (AKITA_IOEXP_IR_ON | AKITA_IOEXP_AKIN_PULLUP) |
27 | 27 | ||
28 | extern struct platform_device akitaioexp_device; | ||
29 | |||
28 | void akita_set_ioexp(struct device *dev, unsigned char bitmask); | 30 | void akita_set_ioexp(struct device *dev, unsigned char bitmask); |
29 | void akita_reset_ioexp(struct device *dev, unsigned char bitmask); | 31 | void akita_reset_ioexp(struct device *dev, unsigned char bitmask); |
30 | 32 | ||
diff --git a/include/asm-arm/atomic.h b/include/asm-arm/atomic.h index 2885972b0855..75b802719723 100644 --- a/include/asm-arm/atomic.h +++ b/include/asm-arm/atomic.h | |||
@@ -80,6 +80,23 @@ static inline int atomic_sub_return(int i, atomic_t *v) | |||
80 | return result; | 80 | return result; |
81 | } | 81 | } |
82 | 82 | ||
83 | static inline int atomic_cmpxchg(atomic_t *ptr, int old, int new) | ||
84 | { | ||
85 | u32 oldval, res; | ||
86 | |||
87 | do { | ||
88 | __asm__ __volatile__("@ atomic_cmpxchg\n" | ||
89 | "ldrex %1, [%2]\n" | ||
90 | "teq %1, %3\n" | ||
91 | "strexeq %0, %4, [%2]\n" | ||
92 | : "=&r" (res), "=&r" (oldval) | ||
93 | : "r" (&ptr->counter), "Ir" (old), "r" (new) | ||
94 | : "cc"); | ||
95 | } while (res); | ||
96 | |||
97 | return oldval; | ||
98 | } | ||
99 | |||
83 | static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) | 100 | static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) |
84 | { | 101 | { |
85 | unsigned long tmp, tmp2; | 102 | unsigned long tmp, tmp2; |
@@ -131,6 +148,20 @@ static inline int atomic_sub_return(int i, atomic_t *v) | |||
131 | return val; | 148 | return val; |
132 | } | 149 | } |
133 | 150 | ||
151 | static inline int atomic_cmpxchg(atomic_t *v, int old, int new) | ||
152 | { | ||
153 | int ret; | ||
154 | unsigned long flags; | ||
155 | |||
156 | local_irq_save(flags); | ||
157 | ret = v->counter; | ||
158 | if (likely(ret == old)) | ||
159 | v->counter = new; | ||
160 | local_irq_restore(flags); | ||
161 | |||
162 | return ret; | ||
163 | } | ||
164 | |||
134 | static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) | 165 | static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) |
135 | { | 166 | { |
136 | unsigned long flags; | 167 | unsigned long flags; |
@@ -142,6 +173,17 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) | |||
142 | 173 | ||
143 | #endif /* __LINUX_ARM_ARCH__ */ | 174 | #endif /* __LINUX_ARM_ARCH__ */ |
144 | 175 | ||
176 | static inline int atomic_add_unless(atomic_t *v, int a, int u) | ||
177 | { | ||
178 | int c, old; | ||
179 | |||
180 | c = atomic_read(v); | ||
181 | while (c != u && (old = atomic_cmpxchg((v), c, c + a)) != c) | ||
182 | c = old; | ||
183 | return c != u; | ||
184 | } | ||
185 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
186 | |||
145 | #define atomic_add(i, v) (void) atomic_add_return(i, v) | 187 | #define atomic_add(i, v) (void) atomic_add_return(i, v) |
146 | #define atomic_inc(v) (void) atomic_add_return(1, v) | 188 | #define atomic_inc(v) (void) atomic_add_return(1, v) |
147 | #define atomic_sub(i, v) (void) atomic_sub_return(i, v) | 189 | #define atomic_sub(i, v) (void) atomic_sub_return(i, v) |
diff --git a/include/asm-arm26/atomic.h b/include/asm-arm26/atomic.h index 4a88235c0e76..a47cadc59686 100644 --- a/include/asm-arm26/atomic.h +++ b/include/asm-arm26/atomic.h | |||
@@ -62,6 +62,35 @@ static inline int atomic_sub_return(int i, atomic_t *v) | |||
62 | return val; | 62 | return val; |
63 | } | 63 | } |
64 | 64 | ||
65 | static inline int atomic_cmpxchg(atomic_t *v, int old, int new) | ||
66 | { | ||
67 | int ret; | ||
68 | unsigned long flags; | ||
69 | |||
70 | local_irq_save(flags); | ||
71 | ret = v->counter; | ||
72 | if (likely(ret == old)) | ||
73 | v->counter = new; | ||
74 | local_irq_restore(flags); | ||
75 | |||
76 | return ret; | ||
77 | } | ||
78 | |||
79 | static inline int atomic_add_unless(atomic_t *v, int a, int u) | ||
80 | { | ||
81 | int ret; | ||
82 | unsigned long flags; | ||
83 | |||
84 | local_irq_save(flags); | ||
85 | ret = v->counter; | ||
86 | if (ret != u) | ||
87 | v->counter += a; | ||
88 | local_irq_restore(flags); | ||
89 | |||
90 | return ret != u; | ||
91 | } | ||
92 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
93 | |||
65 | static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) | 94 | static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) |
66 | { | 95 | { |
67 | unsigned long flags; | 96 | unsigned long flags; |
diff --git a/include/asm-cris/atomic.h b/include/asm-cris/atomic.h index 8c2e78304523..683b05a57d88 100644 --- a/include/asm-cris/atomic.h +++ b/include/asm-cris/atomic.h | |||
@@ -123,6 +123,33 @@ static inline int atomic_inc_and_test(volatile atomic_t *v) | |||
123 | return retval; | 123 | return retval; |
124 | } | 124 | } |
125 | 125 | ||
126 | static inline int atomic_cmpxchg(atomic_t *v, int old, int new) | ||
127 | { | ||
128 | int ret; | ||
129 | unsigned long flags; | ||
130 | |||
131 | cris_atomic_save(v, flags); | ||
132 | ret = v->counter; | ||
133 | if (likely(ret == old)) | ||
134 | v->counter = new; | ||
135 | cris_atomic_restore(v, flags); | ||
136 | return ret; | ||
137 | } | ||
138 | |||
139 | static inline int atomic_add_unless(atomic_t *v, int a, int u) | ||
140 | { | ||
141 | int ret; | ||
142 | unsigned long flags; | ||
143 | |||
144 | cris_atomic_save(v, flags); | ||
145 | ret = v->counter; | ||
146 | if (ret != u) | ||
147 | v->counter += a; | ||
148 | cris_atomic_restore(v, flags); | ||
149 | return ret != u; | ||
150 | } | ||
151 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
152 | |||
126 | /* Atomic operations are already serializing */ | 153 | /* Atomic operations are already serializing */ |
127 | #define smp_mb__before_atomic_dec() barrier() | 154 | #define smp_mb__before_atomic_dec() barrier() |
128 | #define smp_mb__after_atomic_dec() barrier() | 155 | #define smp_mb__after_atomic_dec() barrier() |
diff --git a/include/asm-frv/atomic.h b/include/asm-frv/atomic.h index e75968463428..f6539ff569c5 100644 --- a/include/asm-frv/atomic.h +++ b/include/asm-frv/atomic.h | |||
@@ -414,4 +414,16 @@ extern uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new); | |||
414 | 414 | ||
415 | #endif | 415 | #endif |
416 | 416 | ||
417 | #define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new)) | ||
418 | |||
419 | #define atomic_add_unless(v, a, u) \ | ||
420 | ({ \ | ||
421 | int c, old; \ | ||
422 | c = atomic_read(v); \ | ||
423 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
424 | c = old; \ | ||
425 | c != (u); \ | ||
426 | }) | ||
427 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
428 | |||
417 | #endif /* _ASM_ATOMIC_H */ | 429 | #endif /* _ASM_ATOMIC_H */ |
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h index 886dbd116899..0b49f9e070f1 100644 --- a/include/asm-generic/sections.h +++ b/include/asm-generic/sections.h | |||
@@ -13,5 +13,6 @@ extern char _eextratext[] __attribute__((weak)); | |||
13 | extern char _end[]; | 13 | extern char _end[]; |
14 | extern char __per_cpu_start[], __per_cpu_end[]; | 14 | extern char __per_cpu_start[], __per_cpu_end[]; |
15 | extern char __kprobes_text_start[], __kprobes_text_end[]; | 15 | extern char __kprobes_text_start[], __kprobes_text_end[]; |
16 | extern char __initdata_begin[], __initdata_end[]; | ||
16 | 17 | ||
17 | #endif /* _ASM_GENERIC_SECTIONS_H_ */ | 18 | #endif /* _ASM_GENERIC_SECTIONS_H_ */ |
diff --git a/include/asm-h8300/atomic.h b/include/asm-h8300/atomic.h index 7230f6507995..f23d86819ea8 100644 --- a/include/asm-h8300/atomic.h +++ b/include/asm-h8300/atomic.h | |||
@@ -82,6 +82,33 @@ static __inline__ int atomic_dec_and_test(atomic_t *v) | |||
82 | return ret == 0; | 82 | return ret == 0; |
83 | } | 83 | } |
84 | 84 | ||
85 | static inline int atomic_cmpxchg(atomic_t *v, int old, int new) | ||
86 | { | ||
87 | int ret; | ||
88 | unsigned long flags; | ||
89 | |||
90 | local_irq_save(flags); | ||
91 | ret = v->counter; | ||
92 | if (likely(ret == old)) | ||
93 | v->counter = new; | ||
94 | local_irq_restore(flags); | ||
95 | return ret; | ||
96 | } | ||
97 | |||
98 | static inline int atomic_add_unless(atomic_t *v, int a, int u) | ||
99 | { | ||
100 | int ret; | ||
101 | unsigned long flags; | ||
102 | |||
103 | local_irq_save(flags); | ||
104 | ret = v->counter; | ||
105 | if (ret != u) | ||
106 | v->counter += a; | ||
107 | local_irq_restore(flags); | ||
108 | return ret != u; | ||
109 | } | ||
110 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
111 | |||
85 | static __inline__ void atomic_clear_mask(unsigned long mask, unsigned long *v) | 112 | static __inline__ void atomic_clear_mask(unsigned long mask, unsigned long *v) |
86 | { | 113 | { |
87 | __asm__ __volatile__("stc ccr,r1l\n\t" | 114 | __asm__ __volatile__("stc ccr,r1l\n\t" |
diff --git a/include/asm-i386/atomic.h b/include/asm-i386/atomic.h index 509720be772a..c68557aa04b2 100644 --- a/include/asm-i386/atomic.h +++ b/include/asm-i386/atomic.h | |||
@@ -215,6 +215,27 @@ static __inline__ int atomic_sub_return(int i, atomic_t *v) | |||
215 | return atomic_add_return(-i,v); | 215 | return atomic_add_return(-i,v); |
216 | } | 216 | } |
217 | 217 | ||
218 | #define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new)) | ||
219 | |||
220 | /** | ||
221 | * atomic_add_unless - add unless the number is a given value | ||
222 | * @v: pointer of type atomic_t | ||
223 | * @a: the amount to add to v... | ||
224 | * @u: ...unless v is equal to u. | ||
225 | * | ||
226 | * Atomically adds @a to @v, so long as it was not @u. | ||
227 | * Returns non-zero if @v was not @u, and zero otherwise. | ||
228 | */ | ||
229 | #define atomic_add_unless(v, a, u) \ | ||
230 | ({ \ | ||
231 | int c, old; \ | ||
232 | c = atomic_read(v); \ | ||
233 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
234 | c = old; \ | ||
235 | c != (u); \ | ||
236 | }) | ||
237 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
238 | |||
218 | #define atomic_inc_return(v) (atomic_add_return(1,v)) | 239 | #define atomic_inc_return(v) (atomic_add_return(1,v)) |
219 | #define atomic_dec_return(v) (atomic_sub_return(1,v)) | 240 | #define atomic_dec_return(v) (atomic_sub_return(1,v)) |
220 | 241 | ||
diff --git a/include/asm-i386/mach-default/mach_reboot.h b/include/asm-i386/mach-default/mach_reboot.h index 06ae4d81ba6a..a955e57ad016 100644 --- a/include/asm-i386/mach-default/mach_reboot.h +++ b/include/asm-i386/mach-default/mach_reboot.h | |||
@@ -19,7 +19,7 @@ static inline void kb_wait(void) | |||
19 | static inline void mach_reboot(void) | 19 | static inline void mach_reboot(void) |
20 | { | 20 | { |
21 | int i; | 21 | int i; |
22 | for (i = 0; i < 100; i++) { | 22 | for (i = 0; i < 10; i++) { |
23 | kb_wait(); | 23 | kb_wait(); |
24 | udelay(50); | 24 | udelay(50); |
25 | outb(0x60, 0x64); /* write Controller Command Byte */ | 25 | outb(0x60, 0x64); /* write Controller Command Byte */ |
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h index 8c02b0318703..5c96cf6dcb39 100644 --- a/include/asm-i386/processor.h +++ b/include/asm-i386/processor.h | |||
@@ -65,7 +65,9 @@ struct cpuinfo_x86 { | |||
65 | int f00f_bug; | 65 | int f00f_bug; |
66 | int coma_bug; | 66 | int coma_bug; |
67 | unsigned long loops_per_jiffy; | 67 | unsigned long loops_per_jiffy; |
68 | unsigned char x86_num_cores; | 68 | unsigned char x86_max_cores; /* cpuid returned max cores value */ |
69 | unsigned char booted_cores; /* number of cores as seen by OS */ | ||
70 | unsigned char apicid; | ||
69 | } __attribute__((__aligned__(SMP_CACHE_BYTES))); | 71 | } __attribute__((__aligned__(SMP_CACHE_BYTES))); |
70 | 72 | ||
71 | #define X86_VENDOR_INTEL 0 | 73 | #define X86_VENDOR_INTEL 0 |
diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h index 97d52ac49e46..772f85da1206 100644 --- a/include/asm-i386/system.h +++ b/include/asm-i386/system.h | |||
@@ -263,6 +263,10 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz | |||
263 | 263 | ||
264 | #ifdef CONFIG_X86_CMPXCHG | 264 | #ifdef CONFIG_X86_CMPXCHG |
265 | #define __HAVE_ARCH_CMPXCHG 1 | 265 | #define __HAVE_ARCH_CMPXCHG 1 |
266 | #define cmpxchg(ptr,o,n)\ | ||
267 | ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\ | ||
268 | (unsigned long)(n),sizeof(*(ptr)))) | ||
269 | #endif | ||
266 | 270 | ||
267 | static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, | 271 | static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, |
268 | unsigned long new, int size) | 272 | unsigned long new, int size) |
@@ -291,10 +295,42 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, | |||
291 | return old; | 295 | return old; |
292 | } | 296 | } |
293 | 297 | ||
294 | #define cmpxchg(ptr,o,n)\ | 298 | #ifndef CONFIG_X86_CMPXCHG |
295 | ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\ | 299 | /* |
296 | (unsigned long)(n),sizeof(*(ptr)))) | 300 | * Building a kernel capable running on 80386. It may be necessary to |
301 | * simulate the cmpxchg on the 80386 CPU. For that purpose we define | ||
302 | * a function for each of the sizes we support. | ||
303 | */ | ||
297 | 304 | ||
305 | extern unsigned long cmpxchg_386_u8(volatile void *, u8, u8); | ||
306 | extern unsigned long cmpxchg_386_u16(volatile void *, u16, u16); | ||
307 | extern unsigned long cmpxchg_386_u32(volatile void *, u32, u32); | ||
308 | |||
309 | static inline unsigned long cmpxchg_386(volatile void *ptr, unsigned long old, | ||
310 | unsigned long new, int size) | ||
311 | { | ||
312 | switch (size) { | ||
313 | case 1: | ||
314 | return cmpxchg_386_u8(ptr, old, new); | ||
315 | case 2: | ||
316 | return cmpxchg_386_u16(ptr, old, new); | ||
317 | case 4: | ||
318 | return cmpxchg_386_u32(ptr, old, new); | ||
319 | } | ||
320 | return old; | ||
321 | } | ||
322 | |||
323 | #define cmpxchg(ptr,o,n) \ | ||
324 | ({ \ | ||
325 | __typeof__(*(ptr)) __ret; \ | ||
326 | if (likely(boot_cpu_data.x86 > 3)) \ | ||
327 | __ret = __cmpxchg((ptr), (unsigned long)(o), \ | ||
328 | (unsigned long)(n), sizeof(*(ptr))); \ | ||
329 | else \ | ||
330 | __ret = cmpxchg_386((ptr), (unsigned long)(o), \ | ||
331 | (unsigned long)(n), sizeof(*(ptr))); \ | ||
332 | __ret; \ | ||
333 | }) | ||
298 | #endif | 334 | #endif |
299 | 335 | ||
300 | #ifdef CONFIG_X86_CMPXCHG64 | 336 | #ifdef CONFIG_X86_CMPXCHG64 |
diff --git a/include/asm-ia64/atomic.h b/include/asm-ia64/atomic.h index 874a6f890e75..2fbebf85c31d 100644 --- a/include/asm-ia64/atomic.h +++ b/include/asm-ia64/atomic.h | |||
@@ -88,6 +88,18 @@ ia64_atomic64_sub (__s64 i, atomic64_t *v) | |||
88 | return new; | 88 | return new; |
89 | } | 89 | } |
90 | 90 | ||
91 | #define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new)) | ||
92 | |||
93 | #define atomic_add_unless(v, a, u) \ | ||
94 | ({ \ | ||
95 | int c, old; \ | ||
96 | c = atomic_read(v); \ | ||
97 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
98 | c = old; \ | ||
99 | c != (u); \ | ||
100 | }) | ||
101 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
102 | |||
91 | #define atomic_add_return(i,v) \ | 103 | #define atomic_add_return(i,v) \ |
92 | ({ \ | 104 | ({ \ |
93 | int __ia64_aar_i = (i); \ | 105 | int __ia64_aar_i = (i); \ |
diff --git a/include/asm-m68k/atomic.h b/include/asm-m68k/atomic.h index 38f3043e7fe1..e3c962eeabf3 100644 --- a/include/asm-m68k/atomic.h +++ b/include/asm-m68k/atomic.h | |||
@@ -139,6 +139,18 @@ static inline void atomic_set_mask(unsigned long mask, unsigned long *v) | |||
139 | __asm__ __volatile__("orl %1,%0" : "+m" (*v) : "id" (mask)); | 139 | __asm__ __volatile__("orl %1,%0" : "+m" (*v) : "id" (mask)); |
140 | } | 140 | } |
141 | 141 | ||
142 | #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) | ||
143 | |||
144 | #define atomic_add_unless(v, a, u) \ | ||
145 | ({ \ | ||
146 | int c, old; \ | ||
147 | c = atomic_read(v); \ | ||
148 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
149 | c = old; \ | ||
150 | c != (u); \ | ||
151 | }) | ||
152 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
153 | |||
142 | /* Atomic operations are already serializing */ | 154 | /* Atomic operations are already serializing */ |
143 | #define smp_mb__before_atomic_dec() barrier() | 155 | #define smp_mb__before_atomic_dec() barrier() |
144 | #define smp_mb__after_atomic_dec() barrier() | 156 | #define smp_mb__after_atomic_dec() barrier() |
diff --git a/include/asm-m68k/processor.h b/include/asm-m68k/processor.h index df1575db32af..7982285e84ed 100644 --- a/include/asm-m68k/processor.h +++ b/include/asm-m68k/processor.h | |||
@@ -14,6 +14,7 @@ | |||
14 | #define current_text_addr() ({ __label__ _l; _l: &&_l;}) | 14 | #define current_text_addr() ({ __label__ _l; _l: &&_l;}) |
15 | 15 | ||
16 | #include <linux/config.h> | 16 | #include <linux/config.h> |
17 | #include <linux/thread_info.h> | ||
17 | #include <asm/segment.h> | 18 | #include <asm/segment.h> |
18 | #include <asm/fpu.h> | 19 | #include <asm/fpu.h> |
19 | #include <asm/ptrace.h> | 20 | #include <asm/ptrace.h> |
@@ -55,17 +56,6 @@ static inline void wrusp(unsigned long usp) | |||
55 | #endif | 56 | #endif |
56 | #define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr) | 57 | #define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr) |
57 | 58 | ||
58 | struct task_work { | ||
59 | unsigned char sigpending; | ||
60 | unsigned char notify_resume; /* request for notification on | ||
61 | userspace execution resumption */ | ||
62 | char need_resched; | ||
63 | unsigned char delayed_trace; /* single step a syscall */ | ||
64 | unsigned char syscall_trace; /* count of syscall interceptors */ | ||
65 | unsigned char memdie; /* task was selected to be killed */ | ||
66 | unsigned char pad[2]; | ||
67 | }; | ||
68 | |||
69 | struct thread_struct { | 59 | struct thread_struct { |
70 | unsigned long ksp; /* kernel stack pointer */ | 60 | unsigned long ksp; /* kernel stack pointer */ |
71 | unsigned long usp; /* user stack pointer */ | 61 | unsigned long usp; /* user stack pointer */ |
@@ -78,7 +68,7 @@ struct thread_struct { | |||
78 | unsigned long fp[8*3]; | 68 | unsigned long fp[8*3]; |
79 | unsigned long fpcntl[3]; /* fp control regs */ | 69 | unsigned long fpcntl[3]; /* fp control regs */ |
80 | unsigned char fpstate[FPSTATESIZE]; /* floating point state */ | 70 | unsigned char fpstate[FPSTATESIZE]; /* floating point state */ |
81 | struct task_work work; | 71 | struct thread_info info; |
82 | }; | 72 | }; |
83 | 73 | ||
84 | #define INIT_THREAD { \ | 74 | #define INIT_THREAD { \ |
diff --git a/include/asm-m68k/thread_info.h b/include/asm-m68k/thread_info.h index 2aed24f6fd2e..9532ca3c45cb 100644 --- a/include/asm-m68k/thread_info.h +++ b/include/asm-m68k/thread_info.h | |||
@@ -2,17 +2,15 @@ | |||
2 | #define _ASM_M68K_THREAD_INFO_H | 2 | #define _ASM_M68K_THREAD_INFO_H |
3 | 3 | ||
4 | #include <asm/types.h> | 4 | #include <asm/types.h> |
5 | #include <asm/processor.h> | ||
6 | #include <asm/page.h> | 5 | #include <asm/page.h> |
7 | 6 | ||
8 | struct thread_info { | 7 | struct thread_info { |
9 | struct task_struct *task; /* main task structure */ | 8 | struct task_struct *task; /* main task structure */ |
9 | unsigned long flags; | ||
10 | struct exec_domain *exec_domain; /* execution domain */ | 10 | struct exec_domain *exec_domain; /* execution domain */ |
11 | int preempt_count; /* 0 => preemptable, <0 => BUG */ | 11 | int preempt_count; /* 0 => preemptable, <0 => BUG */ |
12 | __u32 cpu; /* should always be 0 on m68k */ | 12 | __u32 cpu; /* should always be 0 on m68k */ |
13 | struct restart_block restart_block; | 13 | struct restart_block restart_block; |
14 | |||
15 | __u8 supervisor_stack[0]; | ||
16 | }; | 14 | }; |
17 | 15 | ||
18 | #define PREEMPT_ACTIVE 0x4000000 | 16 | #define PREEMPT_ACTIVE 0x4000000 |
@@ -35,84 +33,29 @@ struct thread_info { | |||
35 | #define free_thread_info(ti) free_pages((unsigned long)(ti),1) | 33 | #define free_thread_info(ti) free_pages((unsigned long)(ti),1) |
36 | #endif /* PAGE_SHIFT == 13 */ | 34 | #endif /* PAGE_SHIFT == 13 */ |
37 | 35 | ||
38 | //#define init_thread_info (init_task.thread.info) | 36 | #define init_thread_info (init_task.thread.info) |
39 | #define init_stack (init_thread_union.stack) | 37 | #define init_stack (init_thread_union.stack) |
40 | 38 | ||
41 | #define current_thread_info() (current->thread_info) | 39 | #define task_thread_info(tsk) (&(tsk)->thread.info) |
42 | 40 | #define current_thread_info() task_thread_info(current) | |
43 | 41 | ||
44 | #define __HAVE_THREAD_FUNCTIONS | 42 | #define __HAVE_THREAD_FUNCTIONS |
45 | 43 | ||
46 | #define TIF_SYSCALL_TRACE 0 /* syscall trace active */ | 44 | #define setup_thread_stack(p, org) ({ \ |
47 | #define TIF_DELAYED_TRACE 1 /* single step a syscall */ | 45 | *(struct task_struct **)(p)->thread_info = (p); \ |
48 | #define TIF_NOTIFY_RESUME 2 /* resumption notification requested */ | 46 | task_thread_info(p)->task = (p); \ |
49 | #define TIF_SIGPENDING 3 /* signal pending */ | ||
50 | #define TIF_NEED_RESCHED 4 /* rescheduling necessary */ | ||
51 | #define TIF_MEMDIE 5 | ||
52 | |||
53 | extern int thread_flag_fixme(void); | ||
54 | |||
55 | /* | ||
56 | * flag set/clear/test wrappers | ||
57 | * - pass TIF_xxxx constants to these functions | ||
58 | */ | ||
59 | |||
60 | #define __set_tsk_thread_flag(tsk, flag, val) ({ \ | ||
61 | switch (flag) { \ | ||
62 | case TIF_SIGPENDING: \ | ||
63 | tsk->thread.work.sigpending = val; \ | ||
64 | break; \ | ||
65 | case TIF_NEED_RESCHED: \ | ||
66 | tsk->thread.work.need_resched = val; \ | ||
67 | break; \ | ||
68 | case TIF_SYSCALL_TRACE: \ | ||
69 | tsk->thread.work.syscall_trace = val; \ | ||
70 | break; \ | ||
71 | case TIF_MEMDIE: \ | ||
72 | tsk->thread.work.memdie = val; \ | ||
73 | break; \ | ||
74 | default: \ | ||
75 | thread_flag_fixme(); \ | ||
76 | } \ | ||
77 | }) | 47 | }) |
78 | 48 | ||
79 | #define __get_tsk_thread_flag(tsk, flag) ({ \ | 49 | #define end_of_stack(p) ((unsigned long *)(p)->thread_info + 1) |
80 | int ___res; \ | ||
81 | switch (flag) { \ | ||
82 | case TIF_SIGPENDING: \ | ||
83 | ___res = tsk->thread.work.sigpending; \ | ||
84 | break; \ | ||
85 | case TIF_NEED_RESCHED: \ | ||
86 | ___res = tsk->thread.work.need_resched; \ | ||
87 | break; \ | ||
88 | case TIF_SYSCALL_TRACE: \ | ||
89 | ___res = tsk->thread.work.syscall_trace;\ | ||
90 | break; \ | ||
91 | case TIF_MEMDIE: \ | ||
92 | ___res = tsk->thread.work.memdie;\ | ||
93 | break; \ | ||
94 | default: \ | ||
95 | ___res = thread_flag_fixme(); \ | ||
96 | } \ | ||
97 | ___res; \ | ||
98 | }) | ||
99 | |||
100 | #define __get_set_tsk_thread_flag(tsk, flag, val) ({ \ | ||
101 | int __res = __get_tsk_thread_flag(tsk, flag); \ | ||
102 | __set_tsk_thread_flag(tsk, flag, val); \ | ||
103 | __res; \ | ||
104 | }) | ||
105 | 50 | ||
106 | #define set_tsk_thread_flag(tsk, flag) __set_tsk_thread_flag(tsk, flag, ~0) | 51 | /* entry.S relies on these definitions! |
107 | #define clear_tsk_thread_flag(tsk, flag) __set_tsk_thread_flag(tsk, flag, 0) | 52 | * bits 0-7 are tested at every exception exit |
108 | #define test_and_set_tsk_thread_flag(tsk, flag) __get_set_tsk_thread_flag(tsk, flag, ~0) | 53 | * bits 8-15 are also tested at syscall exit |
109 | #define test_tsk_thread_flag(tsk, flag) __get_tsk_thread_flag(tsk, flag) | 54 | */ |
110 | 55 | #define TIF_SIGPENDING 6 /* signal pending */ | |
111 | #define set_thread_flag(flag) set_tsk_thread_flag(current, flag) | 56 | #define TIF_NEED_RESCHED 7 /* rescheduling necessary */ |
112 | #define clear_thread_flag(flag) clear_tsk_thread_flag(current, flag) | 57 | #define TIF_DELAYED_TRACE 14 /* single step a syscall */ |
113 | #define test_thread_flag(flag) test_tsk_thread_flag(current, flag) | 58 | #define TIF_SYSCALL_TRACE 15 /* syscall trace active */ |
114 | 59 | #define TIF_MEMDIE 16 | |
115 | #define set_need_resched() set_thread_flag(TIF_NEED_RESCHED) | ||
116 | #define clear_need_resched() clear_thread_flag(TIF_NEED_RESCHED) | ||
117 | 60 | ||
118 | #endif /* _ASM_M68K_THREAD_INFO_H */ | 61 | #endif /* _ASM_M68K_THREAD_INFO_H */ |
diff --git a/include/asm-m68knommu/atomic.h b/include/asm-m68knommu/atomic.h index a83631ed8c8f..3c1cc153c415 100644 --- a/include/asm-m68knommu/atomic.h +++ b/include/asm-m68knommu/atomic.h | |||
@@ -128,6 +128,18 @@ static inline int atomic_sub_return(int i, atomic_t * v) | |||
128 | return temp; | 128 | return temp; |
129 | } | 129 | } |
130 | 130 | ||
131 | #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) | ||
132 | |||
133 | #define atomic_add_unless(v, a, u) \ | ||
134 | ({ \ | ||
135 | int c, old; \ | ||
136 | c = atomic_read(v); \ | ||
137 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
138 | c = old; \ | ||
139 | c != (u); \ | ||
140 | }) | ||
141 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
142 | |||
131 | #define atomic_dec_return(v) atomic_sub_return(1,(v)) | 143 | #define atomic_dec_return(v) atomic_sub_return(1,(v)) |
132 | #define atomic_inc_return(v) atomic_add_return(1,(v)) | 144 | #define atomic_inc_return(v) atomic_add_return(1,(v)) |
133 | 145 | ||
diff --git a/include/asm-mips/atomic.h b/include/asm-mips/atomic.h index 6202eb8a14b7..2c87b41e69ba 100644 --- a/include/asm-mips/atomic.h +++ b/include/asm-mips/atomic.h | |||
@@ -287,6 +287,27 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v) | |||
287 | return result; | 287 | return result; |
288 | } | 288 | } |
289 | 289 | ||
290 | #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) | ||
291 | |||
292 | /** | ||
293 | * atomic_add_unless - add unless the number is a given value | ||
294 | * @v: pointer of type atomic_t | ||
295 | * @a: the amount to add to v... | ||
296 | * @u: ...unless v is equal to u. | ||
297 | * | ||
298 | * Atomically adds @a to @v, so long as it was not @u. | ||
299 | * Returns non-zero if @v was not @u, and zero otherwise. | ||
300 | */ | ||
301 | #define atomic_add_unless(v, a, u) \ | ||
302 | ({ \ | ||
303 | int c, old; \ | ||
304 | c = atomic_read(v); \ | ||
305 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
306 | c = old; \ | ||
307 | c != (u); \ | ||
308 | }) | ||
309 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
310 | |||
290 | #define atomic_dec_return(v) atomic_sub_return(1,(v)) | 311 | #define atomic_dec_return(v) atomic_sub_return(1,(v)) |
291 | #define atomic_inc_return(v) atomic_add_return(1,(v)) | 312 | #define atomic_inc_return(v) atomic_add_return(1,(v)) |
292 | 313 | ||
diff --git a/include/asm-parisc/atomic.h b/include/asm-parisc/atomic.h index 048a2c7fd0c0..983e9a2b6042 100644 --- a/include/asm-parisc/atomic.h +++ b/include/asm-parisc/atomic.h | |||
@@ -164,6 +164,26 @@ static __inline__ int atomic_read(const atomic_t *v) | |||
164 | } | 164 | } |
165 | 165 | ||
166 | /* exported interface */ | 166 | /* exported interface */ |
167 | #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) | ||
168 | |||
169 | /** | ||
170 | * atomic_add_unless - add unless the number is a given value | ||
171 | * @v: pointer of type atomic_t | ||
172 | * @a: the amount to add to v... | ||
173 | * @u: ...unless v is equal to u. | ||
174 | * | ||
175 | * Atomically adds @a to @v, so long as it was not @u. | ||
176 | * Returns non-zero if @v was not @u, and zero otherwise. | ||
177 | */ | ||
178 | #define atomic_add_unless(v, a, u) \ | ||
179 | ({ \ | ||
180 | int c, old; \ | ||
181 | c = atomic_read(v); \ | ||
182 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
183 | c = old; \ | ||
184 | c != (u); \ | ||
185 | }) | ||
186 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
167 | 187 | ||
168 | #define atomic_add(i,v) ((void)(__atomic_add_return( ((int)i),(v)))) | 188 | #define atomic_add(i,v) ((void)(__atomic_add_return( ((int)i),(v)))) |
169 | #define atomic_sub(i,v) ((void)(__atomic_add_return(-((int)i),(v)))) | 189 | #define atomic_sub(i,v) ((void)(__atomic_add_return(-((int)i),(v)))) |
diff --git a/include/asm-powerpc/atomic.h b/include/asm-powerpc/atomic.h index 9c0b372a46e1..ec4b14468959 100644 --- a/include/asm-powerpc/atomic.h +++ b/include/asm-powerpc/atomic.h | |||
@@ -164,6 +164,33 @@ static __inline__ int atomic_dec_return(atomic_t *v) | |||
164 | return t; | 164 | return t; |
165 | } | 165 | } |
166 | 166 | ||
167 | #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) | ||
168 | |||
169 | /** | ||
170 | * atomic_add_unless - add unless the number is a given value | ||
171 | * @v: pointer of type atomic_t | ||
172 | * @a: the amount to add to v... | ||
173 | * @u: ...unless v is equal to u. | ||
174 | * | ||
175 | * Atomically adds @a to @v, so long as it was not @u. | ||
176 | * Returns non-zero if @v was not @u, and zero otherwise. | ||
177 | */ | ||
178 | #define atomic_add_unless(v, a, u) \ | ||
179 | ({ \ | ||
180 | int c, old; \ | ||
181 | c = atomic_read(v); \ | ||
182 | for (;;) { \ | ||
183 | if (unlikely(c == (u))) \ | ||
184 | break; \ | ||
185 | old = atomic_cmpxchg((v), c, c + (a)); \ | ||
186 | if (likely(old == c)) \ | ||
187 | break; \ | ||
188 | c = old; \ | ||
189 | } \ | ||
190 | c != (u); \ | ||
191 | }) | ||
192 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
193 | |||
167 | #define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0) | 194 | #define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0) |
168 | #define atomic_dec_and_test(v) (atomic_dec_return((v)) == 0) | 195 | #define atomic_dec_and_test(v) (atomic_dec_return((v)) == 0) |
169 | 196 | ||
diff --git a/include/asm-ppc64/btext.h b/include/asm-powerpc/btext.h index 71cce36bc630..71cce36bc630 100644 --- a/include/asm-ppc64/btext.h +++ b/include/asm-powerpc/btext.h | |||
diff --git a/include/asm-ppc64/delay.h b/include/asm-powerpc/delay.h index 05f198cf73d9..1492aa9ab716 100644 --- a/include/asm-ppc64/delay.h +++ b/include/asm-powerpc/delay.h | |||
@@ -1,5 +1,5 @@ | |||
1 | #ifndef _PPC64_DELAY_H | 1 | #ifndef _ASM_POWERPC_DELAY_H |
2 | #define _PPC64_DELAY_H | 2 | #define _ASM_POWERPC_DELAY_H |
3 | 3 | ||
4 | /* | 4 | /* |
5 | * Copyright 1996, Paul Mackerras. | 5 | * Copyright 1996, Paul Mackerras. |
@@ -15,10 +15,17 @@ | |||
15 | 15 | ||
16 | extern unsigned long tb_ticks_per_usec; | 16 | extern unsigned long tb_ticks_per_usec; |
17 | 17 | ||
18 | /* define these here to prevent circular dependencies */ | 18 | #ifdef CONFIG_PPC64 |
19 | /* define these here to prevent circular dependencies */ | ||
20 | /* these instructions control the thread priority on multi-threaded cpus */ | ||
19 | #define __HMT_low() asm volatile("or 1,1,1") | 21 | #define __HMT_low() asm volatile("or 1,1,1") |
20 | #define __HMT_medium() asm volatile("or 2,2,2") | 22 | #define __HMT_medium() asm volatile("or 2,2,2") |
21 | #define __barrier() asm volatile("":::"memory") | 23 | #else |
24 | #define __HMT_low() | ||
25 | #define __HMT_medium() | ||
26 | #endif | ||
27 | |||
28 | #define __barrier() asm volatile("" ::: "memory") | ||
22 | 29 | ||
23 | static inline unsigned long __get_tb(void) | 30 | static inline unsigned long __get_tb(void) |
24 | { | 31 | { |
@@ -32,7 +39,7 @@ static inline void __delay(unsigned long loops) | |||
32 | { | 39 | { |
33 | unsigned long start = __get_tb(); | 40 | unsigned long start = __get_tb(); |
34 | 41 | ||
35 | while((__get_tb()-start) < loops) | 42 | while((__get_tb() - start) < loops) |
36 | __HMT_low(); | 43 | __HMT_low(); |
37 | __HMT_medium(); | 44 | __HMT_medium(); |
38 | __barrier(); | 45 | __barrier(); |
@@ -45,4 +52,4 @@ static inline void udelay(unsigned long usecs) | |||
45 | __delay(loops); | 52 | __delay(loops); |
46 | } | 53 | } |
47 | 54 | ||
48 | #endif /* _PPC64_DELAY_H */ | 55 | #endif /* _ASM_POWERPC_DELAY_H */ |
diff --git a/include/asm-ppc64/eeh.h b/include/asm-powerpc/eeh.h index 89f26ab31908..89f26ab31908 100644 --- a/include/asm-ppc64/eeh.h +++ b/include/asm-powerpc/eeh.h | |||
diff --git a/include/asm-ppc64/floppy.h b/include/asm-powerpc/floppy.h index 5c497b588e54..64276a3f6153 100644 --- a/include/asm-ppc64/floppy.h +++ b/include/asm-powerpc/floppy.h | |||
@@ -7,22 +7,22 @@ | |||
7 | * | 7 | * |
8 | * Copyright (C) 1995 | 8 | * Copyright (C) 1995 |
9 | */ | 9 | */ |
10 | #ifndef __ASM_PPC64_FLOPPY_H | 10 | #ifndef __ASM_POWERPC_FLOPPY_H |
11 | #define __ASM_PPC64_FLOPPY_H | 11 | #define __ASM_POWERPC_FLOPPY_H |
12 | 12 | ||
13 | #include <linux/config.h> | 13 | #include <linux/config.h> |
14 | #include <asm/machdep.h> | 14 | #include <asm/machdep.h> |
15 | 15 | ||
16 | #define fd_inb(port) inb_p(port) | 16 | #define fd_inb(port) inb_p(port) |
17 | #define fd_outb(value,port) outb_p(value,port) | 17 | #define fd_outb(value,port) outb_p(value,port) |
18 | 18 | ||
19 | #define fd_enable_dma() enable_dma(FLOPPY_DMA) | 19 | #define fd_enable_dma() enable_dma(FLOPPY_DMA) |
20 | #define fd_disable_dma() disable_dma(FLOPPY_DMA) | 20 | #define fd_disable_dma() disable_dma(FLOPPY_DMA) |
21 | #define fd_request_dma() request_dma(FLOPPY_DMA,"floppy") | 21 | #define fd_request_dma() request_dma(FLOPPY_DMA, "floppy") |
22 | #define fd_free_dma() free_dma(FLOPPY_DMA) | 22 | #define fd_free_dma() free_dma(FLOPPY_DMA) |
23 | #define fd_clear_dma_ff() clear_dma_ff(FLOPPY_DMA) | 23 | #define fd_clear_dma_ff() clear_dma_ff(FLOPPY_DMA) |
24 | #define fd_set_dma_mode(mode) set_dma_mode(FLOPPY_DMA,mode) | 24 | #define fd_set_dma_mode(mode) set_dma_mode(FLOPPY_DMA, mode) |
25 | #define fd_set_dma_count(count) set_dma_count(FLOPPY_DMA,count) | 25 | #define fd_set_dma_count(count) set_dma_count(FLOPPY_DMA, count) |
26 | #define fd_enable_irq() enable_irq(FLOPPY_IRQ) | 26 | #define fd_enable_irq() enable_irq(FLOPPY_IRQ) |
27 | #define fd_disable_irq() disable_irq(FLOPPY_IRQ) | 27 | #define fd_disable_irq() disable_irq(FLOPPY_IRQ) |
28 | #define fd_cacheflush(addr,size) /* nothing */ | 28 | #define fd_cacheflush(addr,size) /* nothing */ |
@@ -35,10 +35,10 @@ | |||
35 | 35 | ||
36 | #include <linux/pci.h> | 36 | #include <linux/pci.h> |
37 | 37 | ||
38 | #define fd_dma_setup(addr,size,mode,io) ppc64_fd_dma_setup(addr,size,mode,io) | 38 | #define fd_dma_setup(addr,size,mode,io) powerpc_fd_dma_setup(addr,size,mode,io) |
39 | 39 | ||
40 | static __inline__ int | 40 | static __inline__ int powerpc_fd_dma_setup(char *addr, unsigned long size, |
41 | ppc64_fd_dma_setup(char *addr, unsigned long size, int mode, int io) | 41 | int mode, int io) |
42 | { | 42 | { |
43 | static unsigned long prev_size; | 43 | static unsigned long prev_size; |
44 | static dma_addr_t bus_addr = 0; | 44 | static dma_addr_t bus_addr = 0; |
@@ -55,9 +55,8 @@ ppc64_fd_dma_setup(char *addr, unsigned long size, int mode, int io) | |||
55 | bus_addr = 0; | 55 | bus_addr = 0; |
56 | } | 56 | } |
57 | 57 | ||
58 | if (!bus_addr) /* need to map it */ { | 58 | if (!bus_addr) /* need to map it */ |
59 | bus_addr = pci_map_single(NULL, addr, size, dir); | 59 | bus_addr = pci_map_single(NULL, addr, size, dir); |
60 | } | ||
61 | 60 | ||
62 | /* remember this one as prev */ | 61 | /* remember this one as prev */ |
63 | prev_addr = addr; | 62 | prev_addr = addr; |
@@ -103,4 +102,4 @@ static int FDC2 = -1; | |||
103 | 102 | ||
104 | #define EXTRA_FLOPPY_PARAMS | 103 | #define EXTRA_FLOPPY_PARAMS |
105 | 104 | ||
106 | #endif /* __ASM_PPC64_FLOPPY_H */ | 105 | #endif /* __ASM_POWERPC_FLOPPY_H */ |
diff --git a/include/asm-ppc64/hvconsole.h b/include/asm-powerpc/hvconsole.h index 6da93ce74dc0..6da93ce74dc0 100644 --- a/include/asm-ppc64/hvconsole.h +++ b/include/asm-powerpc/hvconsole.h | |||
diff --git a/include/asm-ppc64/hvcserver.h b/include/asm-powerpc/hvcserver.h index aecba9665796..aecba9665796 100644 --- a/include/asm-ppc64/hvcserver.h +++ b/include/asm-powerpc/hvcserver.h | |||
diff --git a/include/asm-powerpc/kexec.h b/include/asm-powerpc/kexec.h index 062ab9ba68eb..c72ffc709ea8 100644 --- a/include/asm-powerpc/kexec.h +++ b/include/asm-powerpc/kexec.h | |||
@@ -40,6 +40,7 @@ extern note_buf_t crash_notes[]; | |||
40 | #ifdef __powerpc64__ | 40 | #ifdef __powerpc64__ |
41 | extern void kexec_smp_wait(void); /* get and clear naca physid, wait for | 41 | extern void kexec_smp_wait(void); /* get and clear naca physid, wait for |
42 | master to copy new code to 0 */ | 42 | master to copy new code to 0 */ |
43 | extern void __init kexec_setup(void); | ||
43 | #else | 44 | #else |
44 | struct kimage; | 45 | struct kimage; |
45 | extern void machine_kexec_simple(struct kimage *image); | 46 | extern void machine_kexec_simple(struct kimage *image); |
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index 5670f0cd6143..c011abb8b600 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h | |||
@@ -93,7 +93,9 @@ struct machdep_calls { | |||
93 | 93 | ||
94 | void (*init_IRQ)(void); | 94 | void (*init_IRQ)(void); |
95 | int (*get_irq)(struct pt_regs *); | 95 | int (*get_irq)(struct pt_regs *); |
96 | void (*cpu_irq_down)(int secondary); | 96 | #ifdef CONFIG_KEXEC |
97 | void (*kexec_cpu_down)(int crash_shutdown, int secondary); | ||
98 | #endif | ||
97 | 99 | ||
98 | /* PCI stuff */ | 100 | /* PCI stuff */ |
99 | /* Called after scanning the bus, before allocating resources */ | 101 | /* Called after scanning the bus, before allocating resources */ |
diff --git a/include/asm-ppc64/nvram.h b/include/asm-powerpc/nvram.h index def47d720d3d..24bd8c2388ea 100644 --- a/include/asm-ppc64/nvram.h +++ b/include/asm-powerpc/nvram.h | |||
@@ -1,6 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * PreP compliant NVRAM access | 2 | * NVRAM definitions and access functions. |
3 | * This needs to be updated for PPC64 | ||
4 | * | 3 | * |
5 | * This program is free software; you can redistribute it and/or | 4 | * This program is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU General Public License | 5 | * modify it under the terms of the GNU General Public License |
@@ -8,8 +7,8 @@ | |||
8 | * 2 of the License, or (at your option) any later version. | 7 | * 2 of the License, or (at your option) any later version. |
9 | */ | 8 | */ |
10 | 9 | ||
11 | #ifndef _PPC64_NVRAM_H | 10 | #ifndef _ASM_POWERPC_NVRAM_H |
12 | #define _PPC64_NVRAM_H | 11 | #define _ASM_POWERPC_NVRAM_H |
13 | 12 | ||
14 | #define NVRW_CNT 0x20 | 13 | #define NVRW_CNT 0x20 |
15 | #define NVRAM_HEADER_LEN 16 /* sizeof(struct nvram_header) */ | 14 | #define NVRAM_HEADER_LEN 16 /* sizeof(struct nvram_header) */ |
@@ -69,7 +68,6 @@ extern int nvram_clear_error_log(void); | |||
69 | extern struct nvram_partition *nvram_find_partition(int sig, const char *name); | 68 | extern struct nvram_partition *nvram_find_partition(int sig, const char *name); |
70 | 69 | ||
71 | extern int pSeries_nvram_init(void); | 70 | extern int pSeries_nvram_init(void); |
72 | extern int pmac_nvram_init(void); | ||
73 | extern int mmio_nvram_init(void); | 71 | extern int mmio_nvram_init(void); |
74 | 72 | ||
75 | /* PowerMac specific nvram stuffs */ | 73 | /* PowerMac specific nvram stuffs */ |
@@ -88,7 +86,11 @@ extern u8 pmac_xpram_read(int xpaddr); | |||
88 | extern void pmac_xpram_write(int xpaddr, u8 data); | 86 | extern void pmac_xpram_write(int xpaddr, u8 data); |
89 | 87 | ||
90 | /* Synchronize NVRAM */ | 88 | /* Synchronize NVRAM */ |
91 | extern int nvram_sync(void); | 89 | extern void nvram_sync(void); |
90 | |||
91 | /* Normal access to NVRAM */ | ||
92 | extern unsigned char nvram_read_byte(int i); | ||
93 | extern void nvram_write_byte(unsigned char c, int i); | ||
92 | 94 | ||
93 | /* Some offsets in XPRAM */ | 95 | /* Some offsets in XPRAM */ |
94 | #define PMAC_XPRAM_MACHINE_LOC 0xe4 | 96 | #define PMAC_XPRAM_MACHINE_LOC 0xe4 |
@@ -112,5 +114,6 @@ struct pmac_machine_location { | |||
112 | _IOWR('p', 0x40, int) | 114 | _IOWR('p', 0x40, int) |
113 | 115 | ||
114 | #define IOC_NVRAM_GET_OFFSET _IOWR('p', 0x42, int) /* Get NVRAM partition offset */ | 116 | #define IOC_NVRAM_GET_OFFSET _IOWR('p', 0x42, int) /* Get NVRAM partition offset */ |
117 | #define IOC_NVRAM_SYNC _IO('p', 0x43) /* Sync NVRAM image */ | ||
115 | 118 | ||
116 | #endif /* _PPC64_NVRAM_H */ | 119 | #endif /* _ASM_POWERPC_NVRAM_H */ |
diff --git a/include/asm-powerpc/page.h b/include/asm-powerpc/page.h new file mode 100644 index 000000000000..18c1e5ee81a3 --- /dev/null +++ b/include/asm-powerpc/page.h | |||
@@ -0,0 +1,179 @@ | |||
1 | #ifndef _ASM_POWERPC_PAGE_H | ||
2 | #define _ASM_POWERPC_PAGE_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 2001,2005 IBM Corporation. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version | ||
10 | * 2 of the License, or (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #ifdef __KERNEL__ | ||
14 | #include <linux/config.h> | ||
15 | #include <asm/asm-compat.h> | ||
16 | |||
17 | /* | ||
18 | * On PPC32 page size is 4K. For PPC64 we support either 4K or 64K software | ||
19 | * page size. When using 64K pages however, whether we are really supporting | ||
20 | * 64K pages in HW or not is irrelevant to those definitions. | ||
21 | */ | ||
22 | #ifdef CONFIG_PPC_64K_PAGES | ||
23 | #define PAGE_SHIFT 16 | ||
24 | #else | ||
25 | #define PAGE_SHIFT 12 | ||
26 | #endif | ||
27 | |||
28 | #define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT) | ||
29 | |||
30 | /* We do define AT_SYSINFO_EHDR but don't use the gate mechanism */ | ||
31 | #define __HAVE_ARCH_GATE_AREA 1 | ||
32 | |||
33 | /* | ||
34 | * Subtle: (1 << PAGE_SHIFT) is an int, not an unsigned long. So if we | ||
35 | * assign PAGE_MASK to a larger type it gets extended the way we want | ||
36 | * (i.e. with 1s in the high bits) | ||
37 | */ | ||
38 | #define PAGE_MASK (~((1 << PAGE_SHIFT) - 1)) | ||
39 | |||
40 | #define PAGE_OFFSET ASM_CONST(CONFIG_KERNEL_START) | ||
41 | #define KERNELBASE PAGE_OFFSET | ||
42 | |||
43 | #ifdef CONFIG_DISCONTIGMEM | ||
44 | #define page_to_pfn(page) discontigmem_page_to_pfn(page) | ||
45 | #define pfn_to_page(pfn) discontigmem_pfn_to_page(pfn) | ||
46 | #define pfn_valid(pfn) discontigmem_pfn_valid(pfn) | ||
47 | #endif | ||
48 | |||
49 | #ifdef CONFIG_FLATMEM | ||
50 | #define pfn_to_page(pfn) (mem_map + (pfn)) | ||
51 | #define page_to_pfn(page) ((unsigned long)((page) - mem_map)) | ||
52 | #define pfn_valid(pfn) ((pfn) < max_mapnr) | ||
53 | #endif | ||
54 | |||
55 | #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) | ||
56 | #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) | ||
57 | #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) | ||
58 | |||
59 | #define __va(x) ((void *)((unsigned long)(x) + KERNELBASE)) | ||
60 | #define __pa(x) ((unsigned long)(x) - PAGE_OFFSET) | ||
61 | |||
62 | /* | ||
63 | * Unfortunately the PLT is in the BSS in the PPC32 ELF ABI, | ||
64 | * and needs to be executable. This means the whole heap ends | ||
65 | * up being executable. | ||
66 | */ | ||
67 | #define VM_DATA_DEFAULT_FLAGS32 (VM_READ | VM_WRITE | VM_EXEC | \ | ||
68 | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) | ||
69 | |||
70 | #define VM_DATA_DEFAULT_FLAGS64 (VM_READ | VM_WRITE | \ | ||
71 | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) | ||
72 | |||
73 | #ifdef __powerpc64__ | ||
74 | #include <asm/page_64.h> | ||
75 | #else | ||
76 | #include <asm/page_32.h> | ||
77 | #endif | ||
78 | |||
79 | /* align addr on a size boundary - adjust address up/down if needed */ | ||
80 | #define _ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1))) | ||
81 | #define _ALIGN_DOWN(addr,size) ((addr)&(~((size)-1))) | ||
82 | |||
83 | /* align addr on a size boundary - adjust address up if needed */ | ||
84 | #define _ALIGN(addr,size) _ALIGN_UP(addr,size) | ||
85 | |||
86 | /* to align the pointer to the (next) page boundary */ | ||
87 | #define PAGE_ALIGN(addr) _ALIGN(addr, PAGE_SIZE) | ||
88 | |||
89 | #ifndef __ASSEMBLY__ | ||
90 | |||
91 | #undef STRICT_MM_TYPECHECKS | ||
92 | |||
93 | #ifdef STRICT_MM_TYPECHECKS | ||
94 | /* These are used to make use of C type-checking. */ | ||
95 | |||
96 | /* PTE level */ | ||
97 | typedef struct { pte_basic_t pte; } pte_t; | ||
98 | #define pte_val(x) ((x).pte) | ||
99 | #define __pte(x) ((pte_t) { (x) }) | ||
100 | |||
101 | /* 64k pages additionally define a bigger "real PTE" type that gathers | ||
102 | * the "second half" part of the PTE for pseudo 64k pages | ||
103 | */ | ||
104 | #ifdef CONFIG_PPC_64K_PAGES | ||
105 | typedef struct { pte_t pte; unsigned long hidx; } real_pte_t; | ||
106 | #else | ||
107 | typedef struct { pte_t pte; } real_pte_t; | ||
108 | #endif | ||
109 | |||
110 | /* PMD level */ | ||
111 | typedef struct { unsigned long pmd; } pmd_t; | ||
112 | #define pmd_val(x) ((x).pmd) | ||
113 | #define __pmd(x) ((pmd_t) { (x) }) | ||
114 | |||
115 | /* PUD level exusts only on 4k pages */ | ||
116 | #ifndef CONFIG_PPC_64K_PAGES | ||
117 | typedef struct { unsigned long pud; } pud_t; | ||
118 | #define pud_val(x) ((x).pud) | ||
119 | #define __pud(x) ((pud_t) { (x) }) | ||
120 | #endif | ||
121 | |||
122 | /* PGD level */ | ||
123 | typedef struct { unsigned long pgd; } pgd_t; | ||
124 | #define pgd_val(x) ((x).pgd) | ||
125 | #define __pgd(x) ((pgd_t) { (x) }) | ||
126 | |||
127 | /* Page protection bits */ | ||
128 | typedef struct { unsigned long pgprot; } pgprot_t; | ||
129 | #define pgprot_val(x) ((x).pgprot) | ||
130 | #define __pgprot(x) ((pgprot_t) { (x) }) | ||
131 | |||
132 | #else | ||
133 | |||
134 | /* | ||
135 | * .. while these make it easier on the compiler | ||
136 | */ | ||
137 | |||
138 | typedef pte_basic_t pte_t; | ||
139 | #define pte_val(x) (x) | ||
140 | #define __pte(x) (x) | ||
141 | |||
142 | #ifdef CONFIG_PPC_64K_PAGES | ||
143 | typedef struct { pte_t pte; unsigned long hidx; } real_pte_t; | ||
144 | #else | ||
145 | typedef unsigned long real_pte_t; | ||
146 | #endif | ||
147 | |||
148 | |||
149 | typedef unsigned long pmd_t; | ||
150 | #define pmd_val(x) (x) | ||
151 | #define __pmd(x) (x) | ||
152 | |||
153 | #ifndef CONFIG_PPC_64K_PAGES | ||
154 | typedef unsigned long pud_t; | ||
155 | #define pud_val(x) (x) | ||
156 | #define __pud(x) (x) | ||
157 | #endif | ||
158 | |||
159 | typedef unsigned long pgd_t; | ||
160 | #define pgd_val(x) (x) | ||
161 | #define pgprot_val(x) (x) | ||
162 | |||
163 | typedef unsigned long pgprot_t; | ||
164 | #define __pgd(x) (x) | ||
165 | #define __pgprot(x) (x) | ||
166 | |||
167 | #endif | ||
168 | |||
169 | struct page; | ||
170 | extern void clear_user_page(void *page, unsigned long vaddr, struct page *pg); | ||
171 | extern void copy_user_page(void *to, void *from, unsigned long vaddr, | ||
172 | struct page *p); | ||
173 | extern int page_is_ram(unsigned long pfn); | ||
174 | |||
175 | #endif /* __ASSEMBLY__ */ | ||
176 | |||
177 | #endif /* __KERNEL__ */ | ||
178 | |||
179 | #endif /* _ASM_POWERPC_PAGE_H */ | ||
diff --git a/include/asm-powerpc/page_32.h b/include/asm-powerpc/page_32.h new file mode 100644 index 000000000000..7259cfd85da9 --- /dev/null +++ b/include/asm-powerpc/page_32.h | |||
@@ -0,0 +1,40 @@ | |||
1 | #ifndef _ASM_POWERPC_PAGE_32_H | ||
2 | #define _ASM_POWERPC_PAGE_32_H | ||
3 | |||
4 | #define VM_DATA_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS32 | ||
5 | |||
6 | #define PPC_MEMSTART 0 | ||
7 | |||
8 | #ifndef __ASSEMBLY__ | ||
9 | /* | ||
10 | * The basic type of a PTE - 64 bits for those CPUs with > 32 bit | ||
11 | * physical addressing. For now this just the IBM PPC440. | ||
12 | */ | ||
13 | #ifdef CONFIG_PTE_64BIT | ||
14 | typedef unsigned long long pte_basic_t; | ||
15 | #define PTE_SHIFT (PAGE_SHIFT - 3) /* 512 ptes per page */ | ||
16 | #define PTE_FMT "%16Lx" | ||
17 | #else | ||
18 | typedef unsigned long pte_basic_t; | ||
19 | #define PTE_SHIFT (PAGE_SHIFT - 2) /* 1024 ptes per page */ | ||
20 | #define PTE_FMT "%.8lx" | ||
21 | #endif | ||
22 | |||
23 | struct page; | ||
24 | extern void clear_pages(void *page, int order); | ||
25 | static inline void clear_page(void *page) { clear_pages(page, 0); } | ||
26 | extern void copy_page(void *to, void *from); | ||
27 | |||
28 | /* Pure 2^n version of get_order */ | ||
29 | extern __inline__ int get_order(unsigned long size) | ||
30 | { | ||
31 | int lz; | ||
32 | |||
33 | size = (size-1) >> PAGE_SHIFT; | ||
34 | asm ("cntlzw %0,%1" : "=r" (lz) : "r" (size)); | ||
35 | return 32 - lz; | ||
36 | } | ||
37 | |||
38 | #endif /* __ASSEMBLY__ */ | ||
39 | |||
40 | #endif /* _ASM_POWERPC_PAGE_32_H */ | ||
diff --git a/include/asm-powerpc/page_64.h b/include/asm-powerpc/page_64.h new file mode 100644 index 000000000000..c16f106b5373 --- /dev/null +++ b/include/asm-powerpc/page_64.h | |||
@@ -0,0 +1,174 @@ | |||
1 | #ifndef _ASM_POWERPC_PAGE_64_H | ||
2 | #define _ASM_POWERPC_PAGE_64_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 2001 PPC64 Team, IBM Corp | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version | ||
10 | * 2 of the License, or (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | /* | ||
14 | * We always define HW_PAGE_SHIFT to 12 as use of 64K pages remains Linux | ||
15 | * specific, every notion of page number shared with the firmware, TCEs, | ||
16 | * iommu, etc... still uses a page size of 4K. | ||
17 | */ | ||
18 | #define HW_PAGE_SHIFT 12 | ||
19 | #define HW_PAGE_SIZE (ASM_CONST(1) << HW_PAGE_SHIFT) | ||
20 | #define HW_PAGE_MASK (~(HW_PAGE_SIZE-1)) | ||
21 | |||
22 | /* | ||
23 | * PAGE_FACTOR is the number of bits factor between PAGE_SHIFT and | ||
24 | * HW_PAGE_SHIFT, that is 4K pages. | ||
25 | */ | ||
26 | #define PAGE_FACTOR (PAGE_SHIFT - HW_PAGE_SHIFT) | ||
27 | |||
28 | #define REGION_SIZE 4UL | ||
29 | #define REGION_SHIFT 60UL | ||
30 | #define REGION_MASK (((1UL<<REGION_SIZE)-1UL)<<REGION_SHIFT) | ||
31 | |||
32 | #define VMALLOCBASE ASM_CONST(0xD000000000000000) | ||
33 | #define VMALLOC_REGION_ID (VMALLOCBASE >> REGION_SHIFT) | ||
34 | #define KERNEL_REGION_ID (KERNELBASE >> REGION_SHIFT) | ||
35 | #define USER_REGION_ID (0UL) | ||
36 | #define REGION_ID(ea) (((unsigned long)(ea)) >> REGION_SHIFT) | ||
37 | |||
38 | /* Segment size */ | ||
39 | #define SID_SHIFT 28 | ||
40 | #define SID_MASK 0xfffffffffUL | ||
41 | #define ESID_MASK 0xfffffffff0000000UL | ||
42 | #define GET_ESID(x) (((x) >> SID_SHIFT) & SID_MASK) | ||
43 | |||
44 | #ifndef __ASSEMBLY__ | ||
45 | #include <asm/cache.h> | ||
46 | |||
47 | typedef unsigned long pte_basic_t; | ||
48 | |||
49 | static __inline__ void clear_page(void *addr) | ||
50 | { | ||
51 | unsigned long lines, line_size; | ||
52 | |||
53 | line_size = ppc64_caches.dline_size; | ||
54 | lines = ppc64_caches.dlines_per_page; | ||
55 | |||
56 | __asm__ __volatile__( | ||
57 | "mtctr %1 # clear_page\n\ | ||
58 | 1: dcbz 0,%0\n\ | ||
59 | add %0,%0,%3\n\ | ||
60 | bdnz+ 1b" | ||
61 | : "=r" (addr) | ||
62 | : "r" (lines), "0" (addr), "r" (line_size) | ||
63 | : "ctr", "memory"); | ||
64 | } | ||
65 | |||
66 | extern void copy_4K_page(void *to, void *from); | ||
67 | |||
68 | #ifdef CONFIG_PPC_64K_PAGES | ||
69 | static inline void copy_page(void *to, void *from) | ||
70 | { | ||
71 | unsigned int i; | ||
72 | for (i=0; i < (1 << (PAGE_SHIFT - 12)); i++) { | ||
73 | copy_4K_page(to, from); | ||
74 | to += 4096; | ||
75 | from += 4096; | ||
76 | } | ||
77 | } | ||
78 | #else /* CONFIG_PPC_64K_PAGES */ | ||
79 | static inline void copy_page(void *to, void *from) | ||
80 | { | ||
81 | copy_4K_page(to, from); | ||
82 | } | ||
83 | #endif /* CONFIG_PPC_64K_PAGES */ | ||
84 | |||
85 | /* Log 2 of page table size */ | ||
86 | extern u64 ppc64_pft_size; | ||
87 | |||
88 | /* Large pages size */ | ||
89 | extern unsigned int HPAGE_SHIFT; | ||
90 | #define HPAGE_SIZE ((1UL) << HPAGE_SHIFT) | ||
91 | #define HPAGE_MASK (~(HPAGE_SIZE - 1)) | ||
92 | #define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) | ||
93 | |||
94 | #endif /* __ASSEMBLY__ */ | ||
95 | |||
96 | #ifdef CONFIG_HUGETLB_PAGE | ||
97 | |||
98 | #define HTLB_AREA_SHIFT 40 | ||
99 | #define HTLB_AREA_SIZE (1UL << HTLB_AREA_SHIFT) | ||
100 | #define GET_HTLB_AREA(x) ((x) >> HTLB_AREA_SHIFT) | ||
101 | |||
102 | #define LOW_ESID_MASK(addr, len) (((1U << (GET_ESID(addr+len-1)+1)) \ | ||
103 | - (1U << GET_ESID(addr))) & 0xffff) | ||
104 | #define HTLB_AREA_MASK(addr, len) (((1U << (GET_HTLB_AREA(addr+len-1)+1)) \ | ||
105 | - (1U << GET_HTLB_AREA(addr))) & 0xffff) | ||
106 | |||
107 | #define ARCH_HAS_HUGEPAGE_ONLY_RANGE | ||
108 | #define ARCH_HAS_PREPARE_HUGEPAGE_RANGE | ||
109 | #define ARCH_HAS_SETCLEAR_HUGE_PTE | ||
110 | |||
111 | #define touches_hugepage_low_range(mm, addr, len) \ | ||
112 | (LOW_ESID_MASK((addr), (len)) & (mm)->context.low_htlb_areas) | ||
113 | #define touches_hugepage_high_range(mm, addr, len) \ | ||
114 | (HTLB_AREA_MASK((addr), (len)) & (mm)->context.high_htlb_areas) | ||
115 | |||
116 | #define __within_hugepage_low_range(addr, len, segmask) \ | ||
117 | ((LOW_ESID_MASK((addr), (len)) | (segmask)) == (segmask)) | ||
118 | #define within_hugepage_low_range(addr, len) \ | ||
119 | __within_hugepage_low_range((addr), (len), \ | ||
120 | current->mm->context.low_htlb_areas) | ||
121 | #define __within_hugepage_high_range(addr, len, zonemask) \ | ||
122 | ((HTLB_AREA_MASK((addr), (len)) | (zonemask)) == (zonemask)) | ||
123 | #define within_hugepage_high_range(addr, len) \ | ||
124 | __within_hugepage_high_range((addr), (len), \ | ||
125 | current->mm->context.high_htlb_areas) | ||
126 | |||
127 | #define is_hugepage_only_range(mm, addr, len) \ | ||
128 | (touches_hugepage_high_range((mm), (addr), (len)) || \ | ||
129 | touches_hugepage_low_range((mm), (addr), (len))) | ||
130 | #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA | ||
131 | |||
132 | #define in_hugepage_area(context, addr) \ | ||
133 | (cpu_has_feature(CPU_FTR_16M_PAGE) && \ | ||
134 | ( ((1 << GET_HTLB_AREA(addr)) & (context).high_htlb_areas) || \ | ||
135 | ( ((addr) < 0x100000000L) && \ | ||
136 | ((1 << GET_ESID(addr)) & (context).low_htlb_areas) ) ) ) | ||
137 | |||
138 | #else /* !CONFIG_HUGETLB_PAGE */ | ||
139 | |||
140 | #define in_hugepage_area(mm, addr) 0 | ||
141 | |||
142 | #endif /* !CONFIG_HUGETLB_PAGE */ | ||
143 | |||
144 | #ifdef MODULE | ||
145 | #define __page_aligned __attribute__((__aligned__(PAGE_SIZE))) | ||
146 | #else | ||
147 | #define __page_aligned \ | ||
148 | __attribute__((__aligned__(PAGE_SIZE), \ | ||
149 | __section__(".data.page_aligned"))) | ||
150 | #endif | ||
151 | |||
152 | #define VM_DATA_DEFAULT_FLAGS \ | ||
153 | (test_thread_flag(TIF_32BIT) ? \ | ||
154 | VM_DATA_DEFAULT_FLAGS32 : VM_DATA_DEFAULT_FLAGS64) | ||
155 | |||
156 | /* | ||
157 | * This is the default if a program doesn't have a PT_GNU_STACK | ||
158 | * program header entry. The PPC64 ELF ABI has a non executable stack | ||
159 | * stack by default, so in the absense of a PT_GNU_STACK program header | ||
160 | * we turn execute permission off. | ||
161 | */ | ||
162 | #define VM_STACK_DEFAULT_FLAGS32 (VM_READ | VM_WRITE | VM_EXEC | \ | ||
163 | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) | ||
164 | |||
165 | #define VM_STACK_DEFAULT_FLAGS64 (VM_READ | VM_WRITE | \ | ||
166 | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) | ||
167 | |||
168 | #define VM_STACK_DEFAULT_FLAGS \ | ||
169 | (test_thread_flag(TIF_32BIT) ? \ | ||
170 | VM_STACK_DEFAULT_FLAGS32 : VM_STACK_DEFAULT_FLAGS64) | ||
171 | |||
172 | #include <asm-generic/page.h> | ||
173 | |||
174 | #endif /* _ASM_POWERPC_PAGE_64_H */ | ||
diff --git a/include/asm-ppc64/serial.h b/include/asm-powerpc/serial.h index d6bcb79b7d7b..b273d630b32f 100644 --- a/include/asm-ppc64/serial.h +++ b/include/asm-powerpc/serial.h | |||
@@ -1,21 +1,16 @@ | |||
1 | /* | 1 | /* |
2 | * include/asm-ppc64/serial.h | ||
3 | */ | ||
4 | #ifndef _PPC64_SERIAL_H | ||
5 | #define _PPC64_SERIAL_H | ||
6 | |||
7 | /* | ||
8 | * This assumes you have a 1.8432 MHz clock for your UART. | ||
9 | * | ||
10 | * It'd be nice if someone built a serial card with a 24.576 MHz | ||
11 | * clock, since the 16550A is capable of handling a top speed of 1.5 | ||
12 | * megabits/second; but this requires the faster clock. | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or | 2 | * This program is free software; you can redistribute it and/or |
15 | * modify it under the terms of the GNU General Public License | 3 | * modify it under the terms of the GNU General Public License |
16 | * as published by the Free Software Foundation; either version | 4 | * as published by the Free Software Foundation; either version |
17 | * 2 of the License, or (at your option) any later version. | 5 | * 2 of the License, or (at your option) any later version. |
18 | */ | 6 | */ |
7 | #ifndef _ASM_POWERPC_SERIAL_H | ||
8 | #define _ASM_POWERPC_SERIAL_H | ||
9 | |||
10 | /* | ||
11 | * Serial ports are not listed here, because they are discovered | ||
12 | * through the device tree. | ||
13 | */ | ||
19 | 14 | ||
20 | /* Default baud base if not found in device-tree */ | 15 | /* Default baud base if not found in device-tree */ |
21 | #define BASE_BAUD ( 1843200 / 16 ) | 16 | #define BASE_BAUD ( 1843200 / 16 ) |
diff --git a/include/asm-powerpc/vdso_datapage.h b/include/asm-powerpc/vdso_datapage.h index fc323b51366b..411832d5bbdb 100644 --- a/include/asm-powerpc/vdso_datapage.h +++ b/include/asm-powerpc/vdso_datapage.h | |||
@@ -73,7 +73,7 @@ struct vdso_data { | |||
73 | /* those additional ones don't have to be located anywhere | 73 | /* those additional ones don't have to be located anywhere |
74 | * special as they were not part of the original systemcfg | 74 | * special as they were not part of the original systemcfg |
75 | */ | 75 | */ |
76 | __s64 wtom_clock_sec; /* Wall to monotonic clock */ | 76 | __s32 wtom_clock_sec; /* Wall to monotonic clock */ |
77 | __s32 wtom_clock_nsec; | 77 | __s32 wtom_clock_nsec; |
78 | __u32 syscall_map_64[SYSCALL_MAP_SIZE]; /* map of syscalls */ | 78 | __u32 syscall_map_64[SYSCALL_MAP_SIZE]; /* map of syscalls */ |
79 | __u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of syscalls */ | 79 | __u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of syscalls */ |
diff --git a/include/asm-ppc/immap_85xx.h b/include/asm-ppc/immap_85xx.h index 50fb5e47094a..9383d0c13ff8 100644 --- a/include/asm-ppc/immap_85xx.h +++ b/include/asm-ppc/immap_85xx.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85xx Internal Memory Map | 4 | * MPC85xx Internal Memory Map |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor, Inc | 8 | * Copyright 2004 Freescale Semiconductor, Inc |
9 | * | 9 | * |
diff --git a/include/asm-ppc/ipic.h b/include/asm-ppc/ipic.h index 9092b920997a..0fe396a2b666 100644 --- a/include/asm-ppc/ipic.h +++ b/include/asm-ppc/ipic.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * IPIC external definitions and structure. | 4 | * IPIC external definitions and structure. |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor, Inc | 8 | * Copyright 2005 Freescale Semiconductor, Inc |
9 | * | 9 | * |
diff --git a/include/asm-ppc/mpc83xx.h b/include/asm-ppc/mpc83xx.h index ce212201db2a..7cdf60fa69b6 100644 --- a/include/asm-ppc/mpc83xx.h +++ b/include/asm-ppc/mpc83xx.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC83xx definitions | 4 | * MPC83xx definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor, Inc | 8 | * Copyright 2005 Freescale Semiconductor, Inc |
9 | * | 9 | * |
diff --git a/include/asm-ppc/mpc85xx.h b/include/asm-ppc/mpc85xx.h index d98db980cd49..9d14baea3d71 100644 --- a/include/asm-ppc/mpc85xx.h +++ b/include/asm-ppc/mpc85xx.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * MPC85xx definitions | 4 | * MPC85xx definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2004 Freescale Semiconductor, Inc | 8 | * Copyright 2004 Freescale Semiconductor, Inc |
9 | * | 9 | * |
diff --git a/include/asm-ppc/nvram.h b/include/asm-ppc/nvram.h deleted file mode 100644 index 31ef16e3fc4f..000000000000 --- a/include/asm-ppc/nvram.h +++ /dev/null | |||
@@ -1,73 +0,0 @@ | |||
1 | /* | ||
2 | * PreP compliant NVRAM access | ||
3 | */ | ||
4 | |||
5 | #ifdef __KERNEL__ | ||
6 | #ifndef _PPC_NVRAM_H | ||
7 | #define _PPC_NVRAM_H | ||
8 | |||
9 | #define NVRAM_AS0 0x74 | ||
10 | #define NVRAM_AS1 0x75 | ||
11 | #define NVRAM_DATA 0x77 | ||
12 | |||
13 | |||
14 | /* RTC Offsets */ | ||
15 | |||
16 | #define MOTO_RTC_SECONDS 0x1FF9 | ||
17 | #define MOTO_RTC_MINUTES 0x1FFA | ||
18 | #define MOTO_RTC_HOURS 0x1FFB | ||
19 | #define MOTO_RTC_DAY_OF_WEEK 0x1FFC | ||
20 | #define MOTO_RTC_DAY_OF_MONTH 0x1FFD | ||
21 | #define MOTO_RTC_MONTH 0x1FFE | ||
22 | #define MOTO_RTC_YEAR 0x1FFF | ||
23 | #define MOTO_RTC_CONTROLA 0x1FF8 | ||
24 | #define MOTO_RTC_CONTROLB 0x1FF9 | ||
25 | |||
26 | /* PowerMac specific nvram stuffs */ | ||
27 | |||
28 | enum { | ||
29 | pmac_nvram_OF, /* Open Firmware partition */ | ||
30 | pmac_nvram_XPRAM, /* MacOS XPRAM partition */ | ||
31 | pmac_nvram_NR /* MacOS Name Registry partition */ | ||
32 | }; | ||
33 | |||
34 | /* Return partition offset in nvram */ | ||
35 | extern int pmac_get_partition(int partition); | ||
36 | |||
37 | /* Direct access to XPRAM on PowerMacs */ | ||
38 | extern u8 pmac_xpram_read(int xpaddr); | ||
39 | extern void pmac_xpram_write(int xpaddr, u8 data); | ||
40 | |||
41 | /* Synchronize NVRAM */ | ||
42 | extern void nvram_sync(void); | ||
43 | |||
44 | /* Normal access to NVRAM */ | ||
45 | extern unsigned char nvram_read_byte(int i); | ||
46 | extern void nvram_write_byte(unsigned char c, int i); | ||
47 | |||
48 | /* Some offsets in XPRAM */ | ||
49 | #define PMAC_XPRAM_MACHINE_LOC 0xe4 | ||
50 | #define PMAC_XPRAM_SOUND_VOLUME 0x08 | ||
51 | |||
52 | /* Machine location structure in PowerMac XPRAM */ | ||
53 | struct pmac_machine_location { | ||
54 | unsigned int latitude; /* 2+30 bit Fractional number */ | ||
55 | unsigned int longitude; /* 2+30 bit Fractional number */ | ||
56 | unsigned int delta; /* mix of GMT delta and DLS */ | ||
57 | }; | ||
58 | |||
59 | /* | ||
60 | * /dev/nvram ioctls | ||
61 | * | ||
62 | * Note that PMAC_NVRAM_GET_OFFSET is still supported, but is | ||
63 | * definitely obsolete. Do not use it if you can avoid it | ||
64 | */ | ||
65 | |||
66 | #define OBSOLETE_PMAC_NVRAM_GET_OFFSET \ | ||
67 | _IOWR('p', 0x40, int) | ||
68 | |||
69 | #define IOC_NVRAM_GET_OFFSET _IOWR('p', 0x42, int) /* Get NVRAM partition offset */ | ||
70 | #define IOC_NVRAM_SYNC _IO('p', 0x43) /* Sync NVRAM image */ | ||
71 | |||
72 | #endif | ||
73 | #endif /* __KERNEL__ */ | ||
diff --git a/include/asm-ppc/ppc_sys.h b/include/asm-ppc/ppc_sys.h index bba5305c29ed..83d8c77c124d 100644 --- a/include/asm-ppc/ppc_sys.h +++ b/include/asm-ppc/ppc_sys.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * PPC system definitions and library functions | 4 | * PPC system definitions and library functions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2005 Freescale Semiconductor, Inc | 8 | * Copyright 2005 Freescale Semiconductor, Inc |
9 | * | 9 | * |
diff --git a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h deleted file mode 100644 index 3efc3288f7e9..000000000000 --- a/include/asm-ppc64/page.h +++ /dev/null | |||
@@ -1,328 +0,0 @@ | |||
1 | #ifndef _PPC64_PAGE_H | ||
2 | #define _PPC64_PAGE_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 2001 PPC64 Team, IBM Corp | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version | ||
10 | * 2 of the License, or (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/config.h> | ||
14 | #include <asm/asm-compat.h> | ||
15 | |||
16 | /* | ||
17 | * We support either 4k or 64k software page size. When using 64k pages | ||
18 | * however, wether we are really supporting 64k pages in HW or not is | ||
19 | * irrelevant to those definitions. We always define HW_PAGE_SHIFT to 12 | ||
20 | * as use of 64k pages remains a linux kernel specific, every notion of | ||
21 | * page number shared with the firmware, TCEs, iommu, etc... still assumes | ||
22 | * a page size of 4096. | ||
23 | */ | ||
24 | #ifdef CONFIG_PPC_64K_PAGES | ||
25 | #define PAGE_SHIFT 16 | ||
26 | #else | ||
27 | #define PAGE_SHIFT 12 | ||
28 | #endif | ||
29 | |||
30 | #define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT) | ||
31 | #define PAGE_MASK (~(PAGE_SIZE-1)) | ||
32 | |||
33 | /* HW_PAGE_SHIFT is always 4k pages */ | ||
34 | #define HW_PAGE_SHIFT 12 | ||
35 | #define HW_PAGE_SIZE (ASM_CONST(1) << HW_PAGE_SHIFT) | ||
36 | #define HW_PAGE_MASK (~(HW_PAGE_SIZE-1)) | ||
37 | |||
38 | /* PAGE_FACTOR is the number of bits factor between PAGE_SHIFT and | ||
39 | * HW_PAGE_SHIFT, that is 4k pages | ||
40 | */ | ||
41 | #define PAGE_FACTOR (PAGE_SHIFT - HW_PAGE_SHIFT) | ||
42 | |||
43 | /* Segment size */ | ||
44 | #define SID_SHIFT 28 | ||
45 | #define SID_MASK 0xfffffffffUL | ||
46 | #define ESID_MASK 0xfffffffff0000000UL | ||
47 | #define GET_ESID(x) (((x) >> SID_SHIFT) & SID_MASK) | ||
48 | |||
49 | /* Large pages size */ | ||
50 | |||
51 | #ifndef __ASSEMBLY__ | ||
52 | extern unsigned int HPAGE_SHIFT; | ||
53 | #define HPAGE_SIZE ((1UL) << HPAGE_SHIFT) | ||
54 | #define HPAGE_MASK (~(HPAGE_SIZE - 1)) | ||
55 | #define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) | ||
56 | #endif /* __ASSEMBLY__ */ | ||
57 | |||
58 | #ifdef CONFIG_HUGETLB_PAGE | ||
59 | |||
60 | |||
61 | #define HTLB_AREA_SHIFT 40 | ||
62 | #define HTLB_AREA_SIZE (1UL << HTLB_AREA_SHIFT) | ||
63 | #define GET_HTLB_AREA(x) ((x) >> HTLB_AREA_SHIFT) | ||
64 | |||
65 | #define LOW_ESID_MASK(addr, len) (((1U << (GET_ESID(addr+len-1)+1)) \ | ||
66 | - (1U << GET_ESID(addr))) & 0xffff) | ||
67 | #define HTLB_AREA_MASK(addr, len) (((1U << (GET_HTLB_AREA(addr+len-1)+1)) \ | ||
68 | - (1U << GET_HTLB_AREA(addr))) & 0xffff) | ||
69 | |||
70 | #define ARCH_HAS_HUGEPAGE_ONLY_RANGE | ||
71 | #define ARCH_HAS_PREPARE_HUGEPAGE_RANGE | ||
72 | #define ARCH_HAS_SETCLEAR_HUGE_PTE | ||
73 | |||
74 | #define touches_hugepage_low_range(mm, addr, len) \ | ||
75 | (LOW_ESID_MASK((addr), (len)) & (mm)->context.low_htlb_areas) | ||
76 | #define touches_hugepage_high_range(mm, addr, len) \ | ||
77 | (HTLB_AREA_MASK((addr), (len)) & (mm)->context.high_htlb_areas) | ||
78 | |||
79 | #define __within_hugepage_low_range(addr, len, segmask) \ | ||
80 | ((LOW_ESID_MASK((addr), (len)) | (segmask)) == (segmask)) | ||
81 | #define within_hugepage_low_range(addr, len) \ | ||
82 | __within_hugepage_low_range((addr), (len), \ | ||
83 | current->mm->context.low_htlb_areas) | ||
84 | #define __within_hugepage_high_range(addr, len, zonemask) \ | ||
85 | ((HTLB_AREA_MASK((addr), (len)) | (zonemask)) == (zonemask)) | ||
86 | #define within_hugepage_high_range(addr, len) \ | ||
87 | __within_hugepage_high_range((addr), (len), \ | ||
88 | current->mm->context.high_htlb_areas) | ||
89 | |||
90 | #define is_hugepage_only_range(mm, addr, len) \ | ||
91 | (touches_hugepage_high_range((mm), (addr), (len)) || \ | ||
92 | touches_hugepage_low_range((mm), (addr), (len))) | ||
93 | #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA | ||
94 | |||
95 | #define in_hugepage_area(context, addr) \ | ||
96 | (cpu_has_feature(CPU_FTR_16M_PAGE) && \ | ||
97 | ( ((1 << GET_HTLB_AREA(addr)) & (context).high_htlb_areas) || \ | ||
98 | ( ((addr) < 0x100000000L) && \ | ||
99 | ((1 << GET_ESID(addr)) & (context).low_htlb_areas) ) ) ) | ||
100 | |||
101 | #else /* !CONFIG_HUGETLB_PAGE */ | ||
102 | |||
103 | #define in_hugepage_area(mm, addr) 0 | ||
104 | |||
105 | #endif /* !CONFIG_HUGETLB_PAGE */ | ||
106 | |||
107 | /* align addr on a size boundary - adjust address up/down if needed */ | ||
108 | #define _ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1))) | ||
109 | #define _ALIGN_DOWN(addr,size) ((addr)&(~((size)-1))) | ||
110 | |||
111 | /* align addr on a size boundary - adjust address up if needed */ | ||
112 | #define _ALIGN(addr,size) _ALIGN_UP(addr,size) | ||
113 | |||
114 | /* to align the pointer to the (next) page boundary */ | ||
115 | #define PAGE_ALIGN(addr) _ALIGN(addr, PAGE_SIZE) | ||
116 | |||
117 | #ifdef __KERNEL__ | ||
118 | #ifndef __ASSEMBLY__ | ||
119 | #include <asm/cache.h> | ||
120 | |||
121 | #undef STRICT_MM_TYPECHECKS | ||
122 | |||
123 | #define REGION_SIZE 4UL | ||
124 | #define REGION_SHIFT 60UL | ||
125 | #define REGION_MASK (((1UL<<REGION_SIZE)-1UL)<<REGION_SHIFT) | ||
126 | |||
127 | static __inline__ void clear_page(void *addr) | ||
128 | { | ||
129 | unsigned long lines, line_size; | ||
130 | |||
131 | line_size = ppc64_caches.dline_size; | ||
132 | lines = ppc64_caches.dlines_per_page; | ||
133 | |||
134 | __asm__ __volatile__( | ||
135 | "mtctr %1 # clear_page\n\ | ||
136 | 1: dcbz 0,%0\n\ | ||
137 | add %0,%0,%3\n\ | ||
138 | bdnz+ 1b" | ||
139 | : "=r" (addr) | ||
140 | : "r" (lines), "0" (addr), "r" (line_size) | ||
141 | : "ctr", "memory"); | ||
142 | } | ||
143 | |||
144 | extern void copy_4K_page(void *to, void *from); | ||
145 | |||
146 | #ifdef CONFIG_PPC_64K_PAGES | ||
147 | static inline void copy_page(void *to, void *from) | ||
148 | { | ||
149 | unsigned int i; | ||
150 | for (i=0; i < (1 << (PAGE_SHIFT - 12)); i++) { | ||
151 | copy_4K_page(to, from); | ||
152 | to += 4096; | ||
153 | from += 4096; | ||
154 | } | ||
155 | } | ||
156 | #else /* CONFIG_PPC_64K_PAGES */ | ||
157 | static inline void copy_page(void *to, void *from) | ||
158 | { | ||
159 | copy_4K_page(to, from); | ||
160 | } | ||
161 | #endif /* CONFIG_PPC_64K_PAGES */ | ||
162 | |||
163 | struct page; | ||
164 | extern void clear_user_page(void *page, unsigned long vaddr, struct page *pg); | ||
165 | extern void copy_user_page(void *to, void *from, unsigned long vaddr, struct page *p); | ||
166 | |||
167 | #ifdef STRICT_MM_TYPECHECKS | ||
168 | /* | ||
169 | * These are used to make use of C type-checking. | ||
170 | * Entries in the pte table are 64b, while entries in the pgd & pmd are 32b. | ||
171 | */ | ||
172 | |||
173 | /* PTE level */ | ||
174 | typedef struct { unsigned long pte; } pte_t; | ||
175 | #define pte_val(x) ((x).pte) | ||
176 | #define __pte(x) ((pte_t) { (x) }) | ||
177 | |||
178 | /* 64k pages additionally define a bigger "real PTE" type that gathers | ||
179 | * the "second half" part of the PTE for pseudo 64k pages | ||
180 | */ | ||
181 | #ifdef CONFIG_PPC_64K_PAGES | ||
182 | typedef struct { pte_t pte; unsigned long hidx; } real_pte_t; | ||
183 | #else | ||
184 | typedef struct { pte_t pte; } real_pte_t; | ||
185 | #endif | ||
186 | |||
187 | /* PMD level */ | ||
188 | typedef struct { unsigned long pmd; } pmd_t; | ||
189 | #define pmd_val(x) ((x).pmd) | ||
190 | #define __pmd(x) ((pmd_t) { (x) }) | ||
191 | |||
192 | /* PUD level exusts only on 4k pages */ | ||
193 | #ifndef CONFIG_PPC_64K_PAGES | ||
194 | typedef struct { unsigned long pud; } pud_t; | ||
195 | #define pud_val(x) ((x).pud) | ||
196 | #define __pud(x) ((pud_t) { (x) }) | ||
197 | #endif | ||
198 | |||
199 | /* PGD level */ | ||
200 | typedef struct { unsigned long pgd; } pgd_t; | ||
201 | #define pgd_val(x) ((x).pgd) | ||
202 | #define __pgd(x) ((pgd_t) { (x) }) | ||
203 | |||
204 | /* Page protection bits */ | ||
205 | typedef struct { unsigned long pgprot; } pgprot_t; | ||
206 | #define pgprot_val(x) ((x).pgprot) | ||
207 | #define __pgprot(x) ((pgprot_t) { (x) }) | ||
208 | |||
209 | #else | ||
210 | |||
211 | /* | ||
212 | * .. while these make it easier on the compiler | ||
213 | */ | ||
214 | |||
215 | typedef unsigned long pte_t; | ||
216 | #define pte_val(x) (x) | ||
217 | #define __pte(x) (x) | ||
218 | |||
219 | #ifdef CONFIG_PPC_64K_PAGES | ||
220 | typedef struct { pte_t pte; unsigned long hidx; } real_pte_t; | ||
221 | #else | ||
222 | typedef unsigned long real_pte_t; | ||
223 | #endif | ||
224 | |||
225 | |||
226 | typedef unsigned long pmd_t; | ||
227 | #define pmd_val(x) (x) | ||
228 | #define __pmd(x) (x) | ||
229 | |||
230 | #ifndef CONFIG_PPC_64K_PAGES | ||
231 | typedef unsigned long pud_t; | ||
232 | #define pud_val(x) (x) | ||
233 | #define __pud(x) (x) | ||
234 | #endif | ||
235 | |||
236 | typedef unsigned long pgd_t; | ||
237 | #define pgd_val(x) (x) | ||
238 | #define pgprot_val(x) (x) | ||
239 | |||
240 | typedef unsigned long pgprot_t; | ||
241 | #define __pgd(x) (x) | ||
242 | #define __pgprot(x) (x) | ||
243 | |||
244 | #endif | ||
245 | |||
246 | #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) | ||
247 | |||
248 | extern int page_is_ram(unsigned long pfn); | ||
249 | |||
250 | extern u64 ppc64_pft_size; /* Log 2 of page table size */ | ||
251 | |||
252 | /* We do define AT_SYSINFO_EHDR but don't use the gate mecanism */ | ||
253 | #define __HAVE_ARCH_GATE_AREA 1 | ||
254 | |||
255 | #endif /* __ASSEMBLY__ */ | ||
256 | |||
257 | #ifdef MODULE | ||
258 | #define __page_aligned __attribute__((__aligned__(PAGE_SIZE))) | ||
259 | #else | ||
260 | #define __page_aligned \ | ||
261 | __attribute__((__aligned__(PAGE_SIZE), \ | ||
262 | __section__(".data.page_aligned"))) | ||
263 | #endif | ||
264 | |||
265 | |||
266 | /* This must match the -Ttext linker address */ | ||
267 | /* Note: tophys & tovirt make assumptions about how */ | ||
268 | /* KERNELBASE is defined for performance reasons. */ | ||
269 | /* When KERNELBASE moves, those macros may have */ | ||
270 | /* to change! */ | ||
271 | #define PAGE_OFFSET ASM_CONST(0xC000000000000000) | ||
272 | #define KERNELBASE PAGE_OFFSET | ||
273 | #define VMALLOCBASE ASM_CONST(0xD000000000000000) | ||
274 | |||
275 | #define VMALLOC_REGION_ID (VMALLOCBASE >> REGION_SHIFT) | ||
276 | #define KERNEL_REGION_ID (KERNELBASE >> REGION_SHIFT) | ||
277 | #define USER_REGION_ID (0UL) | ||
278 | #define REGION_ID(ea) (((unsigned long)(ea)) >> REGION_SHIFT) | ||
279 | |||
280 | #define __va(x) ((void *)((unsigned long)(x) + KERNELBASE)) | ||
281 | |||
282 | #ifdef CONFIG_FLATMEM | ||
283 | #define pfn_to_page(pfn) (mem_map + (pfn)) | ||
284 | #define page_to_pfn(page) ((unsigned long)((page) - mem_map)) | ||
285 | #define pfn_valid(pfn) ((pfn) < max_mapnr) | ||
286 | #endif | ||
287 | |||
288 | #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) | ||
289 | #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) | ||
290 | |||
291 | #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) | ||
292 | |||
293 | /* | ||
294 | * Unfortunately the PLT is in the BSS in the PPC32 ELF ABI, | ||
295 | * and needs to be executable. This means the whole heap ends | ||
296 | * up being executable. | ||
297 | */ | ||
298 | #define VM_DATA_DEFAULT_FLAGS32 (VM_READ | VM_WRITE | VM_EXEC | \ | ||
299 | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) | ||
300 | |||
301 | #define VM_DATA_DEFAULT_FLAGS64 (VM_READ | VM_WRITE | \ | ||
302 | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) | ||
303 | |||
304 | #define VM_DATA_DEFAULT_FLAGS \ | ||
305 | (test_thread_flag(TIF_32BIT) ? \ | ||
306 | VM_DATA_DEFAULT_FLAGS32 : VM_DATA_DEFAULT_FLAGS64) | ||
307 | |||
308 | /* | ||
309 | * This is the default if a program doesn't have a PT_GNU_STACK | ||
310 | * program header entry. The PPC64 ELF ABI has a non executable stack | ||
311 | * stack by default, so in the absense of a PT_GNU_STACK program header | ||
312 | * we turn execute permission off. | ||
313 | */ | ||
314 | #define VM_STACK_DEFAULT_FLAGS32 (VM_READ | VM_WRITE | VM_EXEC | \ | ||
315 | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) | ||
316 | |||
317 | #define VM_STACK_DEFAULT_FLAGS64 (VM_READ | VM_WRITE | \ | ||
318 | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) | ||
319 | |||
320 | #define VM_STACK_DEFAULT_FLAGS \ | ||
321 | (test_thread_flag(TIF_32BIT) ? \ | ||
322 | VM_STACK_DEFAULT_FLAGS32 : VM_STACK_DEFAULT_FLAGS64) | ||
323 | |||
324 | #endif /* __KERNEL__ */ | ||
325 | |||
326 | #include <asm-generic/page.h> | ||
327 | |||
328 | #endif /* _PPC64_PAGE_H */ | ||
diff --git a/include/asm-ppc64/prom.h b/include/asm-ppc64/prom.h deleted file mode 100644 index ddfe186589fa..000000000000 --- a/include/asm-ppc64/prom.h +++ /dev/null | |||
@@ -1,220 +0,0 @@ | |||
1 | #ifndef _PPC64_PROM_H | ||
2 | #define _PPC64_PROM_H | ||
3 | |||
4 | /* | ||
5 | * Definitions for talking to the Open Firmware PROM on | ||
6 | * Power Macintosh computers. | ||
7 | * | ||
8 | * Copyright (C) 1996 Paul Mackerras. | ||
9 | * | ||
10 | * Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version | ||
15 | * 2 of the License, or (at your option) any later version. | ||
16 | */ | ||
17 | #include <linux/config.h> | ||
18 | #include <linux/proc_fs.h> | ||
19 | #include <asm/atomic.h> | ||
20 | |||
21 | #define PTRRELOC(x) ((typeof(x))((unsigned long)(x) - offset)) | ||
22 | #define PTRUNRELOC(x) ((typeof(x))((unsigned long)(x) + offset)) | ||
23 | #define RELOC(x) (*PTRRELOC(&(x))) | ||
24 | |||
25 | /* Definitions used by the flattened device tree */ | ||
26 | #define OF_DT_HEADER 0xd00dfeed /* marker */ | ||
27 | #define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */ | ||
28 | #define OF_DT_END_NODE 0x2 /* End node */ | ||
29 | #define OF_DT_PROP 0x3 /* Property: name off, size, | ||
30 | * content */ | ||
31 | #define OF_DT_NOP 0x4 /* nop */ | ||
32 | #define OF_DT_END 0x9 | ||
33 | |||
34 | #define OF_DT_VERSION 0x10 | ||
35 | |||
36 | /* | ||
37 | * This is what gets passed to the kernel by prom_init or kexec | ||
38 | * | ||
39 | * The dt struct contains the device tree structure, full pathes and | ||
40 | * property contents. The dt strings contain a separate block with just | ||
41 | * the strings for the property names, and is fully page aligned and | ||
42 | * self contained in a page, so that it can be kept around by the kernel, | ||
43 | * each property name appears only once in this page (cheap compression) | ||
44 | * | ||
45 | * the mem_rsvmap contains a map of reserved ranges of physical memory, | ||
46 | * passing it here instead of in the device-tree itself greatly simplifies | ||
47 | * the job of everybody. It's just a list of u64 pairs (base/size) that | ||
48 | * ends when size is 0 | ||
49 | */ | ||
50 | struct boot_param_header | ||
51 | { | ||
52 | u32 magic; /* magic word OF_DT_HEADER */ | ||
53 | u32 totalsize; /* total size of DT block */ | ||
54 | u32 off_dt_struct; /* offset to structure */ | ||
55 | u32 off_dt_strings; /* offset to strings */ | ||
56 | u32 off_mem_rsvmap; /* offset to memory reserve map */ | ||
57 | u32 version; /* format version */ | ||
58 | u32 last_comp_version; /* last compatible version */ | ||
59 | /* version 2 fields below */ | ||
60 | u32 boot_cpuid_phys; /* Physical CPU id we're booting on */ | ||
61 | /* version 3 fields below */ | ||
62 | u32 dt_strings_size; /* size of the DT strings block */ | ||
63 | }; | ||
64 | |||
65 | |||
66 | |||
67 | typedef u32 phandle; | ||
68 | typedef u32 ihandle; | ||
69 | |||
70 | struct address_range { | ||
71 | unsigned long space; | ||
72 | unsigned long address; | ||
73 | unsigned long size; | ||
74 | }; | ||
75 | |||
76 | struct interrupt_info { | ||
77 | int line; | ||
78 | int sense; /* +ve/-ve logic, edge or level, etc. */ | ||
79 | }; | ||
80 | |||
81 | struct pci_address { | ||
82 | u32 a_hi; | ||
83 | u32 a_mid; | ||
84 | u32 a_lo; | ||
85 | }; | ||
86 | |||
87 | struct isa_address { | ||
88 | u32 a_hi; | ||
89 | u32 a_lo; | ||
90 | }; | ||
91 | |||
92 | struct isa_range { | ||
93 | struct isa_address isa_addr; | ||
94 | struct pci_address pci_addr; | ||
95 | unsigned int size; | ||
96 | }; | ||
97 | |||
98 | struct reg_property { | ||
99 | unsigned long address; | ||
100 | unsigned long size; | ||
101 | }; | ||
102 | |||
103 | struct reg_property32 { | ||
104 | unsigned int address; | ||
105 | unsigned int size; | ||
106 | }; | ||
107 | |||
108 | struct reg_property64 { | ||
109 | unsigned long address; | ||
110 | unsigned long size; | ||
111 | }; | ||
112 | |||
113 | struct property { | ||
114 | char *name; | ||
115 | int length; | ||
116 | unsigned char *value; | ||
117 | struct property *next; | ||
118 | }; | ||
119 | |||
120 | struct device_node { | ||
121 | char *name; | ||
122 | char *type; | ||
123 | phandle node; | ||
124 | phandle linux_phandle; | ||
125 | int n_addrs; | ||
126 | struct address_range *addrs; | ||
127 | int n_intrs; | ||
128 | struct interrupt_info *intrs; | ||
129 | char *full_name; | ||
130 | |||
131 | struct property *properties; | ||
132 | struct device_node *parent; | ||
133 | struct device_node *child; | ||
134 | struct device_node *sibling; | ||
135 | struct device_node *next; /* next device of same type */ | ||
136 | struct device_node *allnext; /* next in list of all nodes */ | ||
137 | struct proc_dir_entry *pde; /* this node's proc directory */ | ||
138 | struct kref kref; | ||
139 | unsigned long _flags; | ||
140 | void *data; | ||
141 | #ifdef CONFIG_PPC_ISERIES | ||
142 | struct list_head Device_List; | ||
143 | #endif | ||
144 | }; | ||
145 | |||
146 | extern struct device_node *of_chosen; | ||
147 | |||
148 | /* flag descriptions */ | ||
149 | #define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */ | ||
150 | |||
151 | #define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags) | ||
152 | #define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags) | ||
153 | |||
154 | /* | ||
155 | * Until 32-bit ppc can add proc_dir_entries to its device_node | ||
156 | * definition, we cannot refer to pde, name_link, and addr_link | ||
157 | * in arch-independent code. | ||
158 | */ | ||
159 | #define HAVE_ARCH_DEVTREE_FIXUPS | ||
160 | |||
161 | static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_entry *de) | ||
162 | { | ||
163 | dn->pde = de; | ||
164 | } | ||
165 | |||
166 | |||
167 | /* OBSOLETE: Old stlye node lookup */ | ||
168 | extern struct device_node *find_devices(const char *name); | ||
169 | extern struct device_node *find_type_devices(const char *type); | ||
170 | extern struct device_node *find_path_device(const char *path); | ||
171 | extern struct device_node *find_compatible_devices(const char *type, | ||
172 | const char *compat); | ||
173 | extern struct device_node *find_all_nodes(void); | ||
174 | |||
175 | /* New style node lookup */ | ||
176 | extern struct device_node *of_find_node_by_name(struct device_node *from, | ||
177 | const char *name); | ||
178 | extern struct device_node *of_find_node_by_type(struct device_node *from, | ||
179 | const char *type); | ||
180 | extern struct device_node *of_find_compatible_node(struct device_node *from, | ||
181 | const char *type, const char *compat); | ||
182 | extern struct device_node *of_find_node_by_path(const char *path); | ||
183 | extern struct device_node *of_find_node_by_phandle(phandle handle); | ||
184 | extern struct device_node *of_find_all_nodes(struct device_node *prev); | ||
185 | extern struct device_node *of_get_parent(const struct device_node *node); | ||
186 | extern struct device_node *of_get_next_child(const struct device_node *node, | ||
187 | struct device_node *prev); | ||
188 | extern struct device_node *of_node_get(struct device_node *node); | ||
189 | extern void of_node_put(struct device_node *node); | ||
190 | |||
191 | /* For scanning the flat device-tree at boot time */ | ||
192 | int __init of_scan_flat_dt(int (*it)(unsigned long node, | ||
193 | const char *uname, int depth, | ||
194 | void *data), | ||
195 | void *data); | ||
196 | void* __init of_get_flat_dt_prop(unsigned long node, const char *name, | ||
197 | unsigned long *size); | ||
198 | |||
199 | /* For updating the device tree at runtime */ | ||
200 | extern void of_attach_node(struct device_node *); | ||
201 | extern void of_detach_node(const struct device_node *); | ||
202 | |||
203 | /* Other Prototypes */ | ||
204 | extern unsigned long prom_init(unsigned long, unsigned long, unsigned long, | ||
205 | unsigned long, unsigned long); | ||
206 | extern void finish_device_tree(void); | ||
207 | extern void unflatten_device_tree(void); | ||
208 | extern void early_init_devtree(void *); | ||
209 | extern int device_is_compatible(struct device_node *device, const char *); | ||
210 | extern int machine_is_compatible(const char *compat); | ||
211 | extern unsigned char *get_property(struct device_node *node, const char *name, | ||
212 | int *lenp); | ||
213 | extern void print_properties(struct device_node *node); | ||
214 | extern int prom_n_addr_cells(struct device_node* np); | ||
215 | extern int prom_n_size_cells(struct device_node* np); | ||
216 | extern int prom_n_intr_cells(struct device_node* np); | ||
217 | extern void prom_get_irq_senses(unsigned char *senses, int off, int max); | ||
218 | extern int prom_add_property(struct device_node* np, struct property* prop); | ||
219 | |||
220 | #endif /* _PPC64_PROM_H */ | ||
diff --git a/include/asm-ppc64/system.h b/include/asm-ppc64/system.h deleted file mode 100644 index bf9a6aba19c9..000000000000 --- a/include/asm-ppc64/system.h +++ /dev/null | |||
@@ -1,310 +0,0 @@ | |||
1 | #ifndef __PPC64_SYSTEM_H | ||
2 | #define __PPC64_SYSTEM_H | ||
3 | |||
4 | /* | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License | ||
7 | * as published by the Free Software Foundation; either version | ||
8 | * 2 of the License, or (at your option) any later version. | ||
9 | */ | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | #include <linux/compiler.h> | ||
13 | #include <asm/page.h> | ||
14 | #include <asm/processor.h> | ||
15 | #include <asm/hw_irq.h> | ||
16 | #include <asm/synch.h> | ||
17 | |||
18 | /* | ||
19 | * Memory barrier. | ||
20 | * The sync instruction guarantees that all memory accesses initiated | ||
21 | * by this processor have been performed (with respect to all other | ||
22 | * mechanisms that access memory). The eieio instruction is a barrier | ||
23 | * providing an ordering (separately) for (a) cacheable stores and (b) | ||
24 | * loads and stores to non-cacheable memory (e.g. I/O devices). | ||
25 | * | ||
26 | * mb() prevents loads and stores being reordered across this point. | ||
27 | * rmb() prevents loads being reordered across this point. | ||
28 | * wmb() prevents stores being reordered across this point. | ||
29 | * read_barrier_depends() prevents data-dependent loads being reordered | ||
30 | * across this point (nop on PPC). | ||
31 | * | ||
32 | * We have to use the sync instructions for mb(), since lwsync doesn't | ||
33 | * order loads with respect to previous stores. Lwsync is fine for | ||
34 | * rmb(), though. | ||
35 | * For wmb(), we use sync since wmb is used in drivers to order | ||
36 | * stores to system memory with respect to writes to the device. | ||
37 | * However, smp_wmb() can be a lighter-weight eieio barrier on | ||
38 | * SMP since it is only used to order updates to system memory. | ||
39 | */ | ||
40 | #define mb() __asm__ __volatile__ ("sync" : : : "memory") | ||
41 | #define rmb() __asm__ __volatile__ ("lwsync" : : : "memory") | ||
42 | #define wmb() __asm__ __volatile__ ("sync" : : : "memory") | ||
43 | #define read_barrier_depends() do { } while(0) | ||
44 | |||
45 | #define set_mb(var, value) do { var = value; smp_mb(); } while (0) | ||
46 | #define set_wmb(var, value) do { var = value; smp_wmb(); } while (0) | ||
47 | |||
48 | #ifdef CONFIG_SMP | ||
49 | #define smp_mb() mb() | ||
50 | #define smp_rmb() rmb() | ||
51 | #define smp_wmb() eieio() | ||
52 | #define smp_read_barrier_depends() read_barrier_depends() | ||
53 | #else | ||
54 | #define smp_mb() __asm__ __volatile__("": : :"memory") | ||
55 | #define smp_rmb() __asm__ __volatile__("": : :"memory") | ||
56 | #define smp_wmb() __asm__ __volatile__("": : :"memory") | ||
57 | #define smp_read_barrier_depends() do { } while(0) | ||
58 | #endif /* CONFIG_SMP */ | ||
59 | |||
60 | #ifdef __KERNEL__ | ||
61 | struct task_struct; | ||
62 | struct pt_regs; | ||
63 | |||
64 | #ifdef CONFIG_DEBUGGER | ||
65 | |||
66 | extern int (*__debugger)(struct pt_regs *regs); | ||
67 | extern int (*__debugger_ipi)(struct pt_regs *regs); | ||
68 | extern int (*__debugger_bpt)(struct pt_regs *regs); | ||
69 | extern int (*__debugger_sstep)(struct pt_regs *regs); | ||
70 | extern int (*__debugger_iabr_match)(struct pt_regs *regs); | ||
71 | extern int (*__debugger_dabr_match)(struct pt_regs *regs); | ||
72 | extern int (*__debugger_fault_handler)(struct pt_regs *regs); | ||
73 | |||
74 | #define DEBUGGER_BOILERPLATE(__NAME) \ | ||
75 | static inline int __NAME(struct pt_regs *regs) \ | ||
76 | { \ | ||
77 | if (unlikely(__ ## __NAME)) \ | ||
78 | return __ ## __NAME(regs); \ | ||
79 | return 0; \ | ||
80 | } | ||
81 | |||
82 | DEBUGGER_BOILERPLATE(debugger) | ||
83 | DEBUGGER_BOILERPLATE(debugger_ipi) | ||
84 | DEBUGGER_BOILERPLATE(debugger_bpt) | ||
85 | DEBUGGER_BOILERPLATE(debugger_sstep) | ||
86 | DEBUGGER_BOILERPLATE(debugger_iabr_match) | ||
87 | DEBUGGER_BOILERPLATE(debugger_dabr_match) | ||
88 | DEBUGGER_BOILERPLATE(debugger_fault_handler) | ||
89 | |||
90 | #ifdef CONFIG_XMON | ||
91 | extern void xmon_init(int enable); | ||
92 | #endif | ||
93 | |||
94 | #else | ||
95 | static inline int debugger(struct pt_regs *regs) { return 0; } | ||
96 | static inline int debugger_ipi(struct pt_regs *regs) { return 0; } | ||
97 | static inline int debugger_bpt(struct pt_regs *regs) { return 0; } | ||
98 | static inline int debugger_sstep(struct pt_regs *regs) { return 0; } | ||
99 | static inline int debugger_iabr_match(struct pt_regs *regs) { return 0; } | ||
100 | static inline int debugger_dabr_match(struct pt_regs *regs) { return 0; } | ||
101 | static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; } | ||
102 | #endif | ||
103 | |||
104 | extern int set_dabr(unsigned long dabr); | ||
105 | extern void _exception(int signr, struct pt_regs *regs, int code, | ||
106 | unsigned long addr); | ||
107 | extern int fix_alignment(struct pt_regs *regs); | ||
108 | extern void bad_page_fault(struct pt_regs *regs, unsigned long address, | ||
109 | int sig); | ||
110 | extern void show_regs(struct pt_regs * regs); | ||
111 | extern void low_hash_fault(struct pt_regs *regs, unsigned long address); | ||
112 | extern int die(const char *str, struct pt_regs *regs, long err); | ||
113 | |||
114 | extern int _get_PVR(void); | ||
115 | extern void giveup_fpu(struct task_struct *); | ||
116 | extern void disable_kernel_fp(void); | ||
117 | extern void flush_fp_to_thread(struct task_struct *); | ||
118 | extern void enable_kernel_fp(void); | ||
119 | extern void giveup_altivec(struct task_struct *); | ||
120 | extern void disable_kernel_altivec(void); | ||
121 | extern void enable_kernel_altivec(void); | ||
122 | extern int emulate_altivec(struct pt_regs *); | ||
123 | extern void cvt_fd(float *from, double *to, struct thread_struct *thread); | ||
124 | extern void cvt_df(double *from, float *to, struct thread_struct *thread); | ||
125 | |||
126 | #ifdef CONFIG_ALTIVEC | ||
127 | extern void flush_altivec_to_thread(struct task_struct *); | ||
128 | #else | ||
129 | static inline void flush_altivec_to_thread(struct task_struct *t) | ||
130 | { | ||
131 | } | ||
132 | #endif | ||
133 | |||
134 | static inline void flush_spe_to_thread(struct task_struct *t) | ||
135 | { | ||
136 | } | ||
137 | |||
138 | extern int mem_init_done; /* set on boot once kmalloc can be called */ | ||
139 | extern unsigned long memory_limit; | ||
140 | |||
141 | /* EBCDIC -> ASCII conversion for [0-9A-Z] on iSeries */ | ||
142 | extern unsigned char e2a(unsigned char); | ||
143 | |||
144 | extern struct task_struct *__switch_to(struct task_struct *, | ||
145 | struct task_struct *); | ||
146 | #define switch_to(prev, next, last) ((last) = __switch_to((prev), (next))) | ||
147 | |||
148 | struct thread_struct; | ||
149 | extern struct task_struct * _switch(struct thread_struct *prev, | ||
150 | struct thread_struct *next); | ||
151 | |||
152 | extern unsigned long klimit; | ||
153 | |||
154 | extern int powersave_nap; /* set if nap mode can be used in idle loop */ | ||
155 | |||
156 | /* | ||
157 | * Atomic exchange | ||
158 | * | ||
159 | * Changes the memory location '*ptr' to be val and returns | ||
160 | * the previous value stored there. | ||
161 | * | ||
162 | * Inline asm pulled from arch/ppc/kernel/misc.S so ppc64 | ||
163 | * is more like most of the other architectures. | ||
164 | */ | ||
165 | static __inline__ unsigned long | ||
166 | __xchg_u32(volatile unsigned int *m, unsigned long val) | ||
167 | { | ||
168 | unsigned long dummy; | ||
169 | |||
170 | __asm__ __volatile__( | ||
171 | EIEIO_ON_SMP | ||
172 | "1: lwarx %0,0,%3 # __xchg_u32\n\ | ||
173 | stwcx. %2,0,%3\n\ | ||
174 | 2: bne- 1b" | ||
175 | ISYNC_ON_SMP | ||
176 | : "=&r" (dummy), "=m" (*m) | ||
177 | : "r" (val), "r" (m) | ||
178 | : "cc", "memory"); | ||
179 | |||
180 | return (dummy); | ||
181 | } | ||
182 | |||
183 | static __inline__ unsigned long | ||
184 | __xchg_u64(volatile long *m, unsigned long val) | ||
185 | { | ||
186 | unsigned long dummy; | ||
187 | |||
188 | __asm__ __volatile__( | ||
189 | EIEIO_ON_SMP | ||
190 | "1: ldarx %0,0,%3 # __xchg_u64\n\ | ||
191 | stdcx. %2,0,%3\n\ | ||
192 | 2: bne- 1b" | ||
193 | ISYNC_ON_SMP | ||
194 | : "=&r" (dummy), "=m" (*m) | ||
195 | : "r" (val), "r" (m) | ||
196 | : "cc", "memory"); | ||
197 | |||
198 | return (dummy); | ||
199 | } | ||
200 | |||
201 | /* | ||
202 | * This function doesn't exist, so you'll get a linker error | ||
203 | * if something tries to do an invalid xchg(). | ||
204 | */ | ||
205 | extern void __xchg_called_with_bad_pointer(void); | ||
206 | |||
207 | static __inline__ unsigned long | ||
208 | __xchg(volatile void *ptr, unsigned long x, unsigned int size) | ||
209 | { | ||
210 | switch (size) { | ||
211 | case 4: | ||
212 | return __xchg_u32(ptr, x); | ||
213 | case 8: | ||
214 | return __xchg_u64(ptr, x); | ||
215 | } | ||
216 | __xchg_called_with_bad_pointer(); | ||
217 | return x; | ||
218 | } | ||
219 | |||
220 | #define xchg(ptr,x) \ | ||
221 | ({ \ | ||
222 | __typeof__(*(ptr)) _x_ = (x); \ | ||
223 | (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_, sizeof(*(ptr))); \ | ||
224 | }) | ||
225 | |||
226 | #define tas(ptr) (xchg((ptr),1)) | ||
227 | |||
228 | #define __HAVE_ARCH_CMPXCHG 1 | ||
229 | |||
230 | static __inline__ unsigned long | ||
231 | __cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new) | ||
232 | { | ||
233 | unsigned int prev; | ||
234 | |||
235 | __asm__ __volatile__ ( | ||
236 | EIEIO_ON_SMP | ||
237 | "1: lwarx %0,0,%2 # __cmpxchg_u32\n\ | ||
238 | cmpw 0,%0,%3\n\ | ||
239 | bne- 2f\n\ | ||
240 | stwcx. %4,0,%2\n\ | ||
241 | bne- 1b" | ||
242 | ISYNC_ON_SMP | ||
243 | "\n\ | ||
244 | 2:" | ||
245 | : "=&r" (prev), "=m" (*p) | ||
246 | : "r" (p), "r" (old), "r" (new), "m" (*p) | ||
247 | : "cc", "memory"); | ||
248 | |||
249 | return prev; | ||
250 | } | ||
251 | |||
252 | static __inline__ unsigned long | ||
253 | __cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new) | ||
254 | { | ||
255 | unsigned long prev; | ||
256 | |||
257 | __asm__ __volatile__ ( | ||
258 | EIEIO_ON_SMP | ||
259 | "1: ldarx %0,0,%2 # __cmpxchg_u64\n\ | ||
260 | cmpd 0,%0,%3\n\ | ||
261 | bne- 2f\n\ | ||
262 | stdcx. %4,0,%2\n\ | ||
263 | bne- 1b" | ||
264 | ISYNC_ON_SMP | ||
265 | "\n\ | ||
266 | 2:" | ||
267 | : "=&r" (prev), "=m" (*p) | ||
268 | : "r" (p), "r" (old), "r" (new), "m" (*p) | ||
269 | : "cc", "memory"); | ||
270 | |||
271 | return prev; | ||
272 | } | ||
273 | |||
274 | /* This function doesn't exist, so you'll get a linker error | ||
275 | if something tries to do an invalid cmpxchg(). */ | ||
276 | extern void __cmpxchg_called_with_bad_pointer(void); | ||
277 | |||
278 | static __inline__ unsigned long | ||
279 | __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, | ||
280 | unsigned int size) | ||
281 | { | ||
282 | switch (size) { | ||
283 | case 4: | ||
284 | return __cmpxchg_u32(ptr, old, new); | ||
285 | case 8: | ||
286 | return __cmpxchg_u64(ptr, old, new); | ||
287 | } | ||
288 | __cmpxchg_called_with_bad_pointer(); | ||
289 | return old; | ||
290 | } | ||
291 | |||
292 | #define cmpxchg(ptr,o,n)\ | ||
293 | ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\ | ||
294 | (unsigned long)(n),sizeof(*(ptr)))) | ||
295 | |||
296 | /* | ||
297 | * We handle most unaligned accesses in hardware. On the other hand | ||
298 | * unaligned DMA can be very expensive on some ppc64 IO chips (it does | ||
299 | * powers of 2 writes until it reaches sufficient alignment). | ||
300 | * | ||
301 | * Based on this we disable the IP header alignment in network drivers. | ||
302 | */ | ||
303 | #define NET_IP_ALIGN 0 | ||
304 | |||
305 | #define arch_align_stack(x) (x) | ||
306 | |||
307 | extern unsigned long reloc_offset(void); | ||
308 | |||
309 | #endif /* __KERNEL__ */ | ||
310 | #endif | ||
diff --git a/include/asm-s390/atomic.h b/include/asm-s390/atomic.h index 9d86ba6f12d0..b3bd4f679f72 100644 --- a/include/asm-s390/atomic.h +++ b/include/asm-s390/atomic.h | |||
@@ -198,6 +198,18 @@ atomic_compare_and_swap(int expected_oldval,int new_val,atomic_t *v) | |||
198 | return retval; | 198 | return retval; |
199 | } | 199 | } |
200 | 200 | ||
201 | #define atomic_cmpxchg(v, o, n) (atomic_compare_and_swap((o), (n), &((v)->counter))) | ||
202 | |||
203 | #define atomic_add_unless(v, a, u) \ | ||
204 | ({ \ | ||
205 | int c, old; \ | ||
206 | c = atomic_read(v); \ | ||
207 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
208 | c = old; \ | ||
209 | c != (u); \ | ||
210 | }) | ||
211 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
212 | |||
201 | #define smp_mb__before_atomic_dec() smp_mb() | 213 | #define smp_mb__before_atomic_dec() smp_mb() |
202 | #define smp_mb__after_atomic_dec() smp_mb() | 214 | #define smp_mb__after_atomic_dec() smp_mb() |
203 | #define smp_mb__before_atomic_inc() smp_mb() | 215 | #define smp_mb__before_atomic_inc() smp_mb() |
diff --git a/include/asm-sh/atomic.h b/include/asm-sh/atomic.h index 3c4f805da1ac..aabfd334462c 100644 --- a/include/asm-sh/atomic.h +++ b/include/asm-sh/atomic.h | |||
@@ -87,6 +87,35 @@ static __inline__ int atomic_sub_return(int i, atomic_t * v) | |||
87 | #define atomic_inc(v) atomic_add(1,(v)) | 87 | #define atomic_inc(v) atomic_add(1,(v)) |
88 | #define atomic_dec(v) atomic_sub(1,(v)) | 88 | #define atomic_dec(v) atomic_sub(1,(v)) |
89 | 89 | ||
90 | static inline int atomic_cmpxchg(atomic_t *v, int old, int new) | ||
91 | { | ||
92 | int ret; | ||
93 | unsigned long flags; | ||
94 | |||
95 | local_irq_save(flags); | ||
96 | ret = v->counter; | ||
97 | if (likely(ret == old)) | ||
98 | v->counter = new; | ||
99 | local_irq_restore(flags); | ||
100 | |||
101 | return ret; | ||
102 | } | ||
103 | |||
104 | static inline int atomic_add_unless(atomic_t *v, int a, int u) | ||
105 | { | ||
106 | int ret; | ||
107 | unsigned long flags; | ||
108 | |||
109 | local_irq_save(flags); | ||
110 | ret = v->counter; | ||
111 | if (ret != u) | ||
112 | v->counter += a; | ||
113 | local_irq_restore(flags); | ||
114 | |||
115 | return ret != u; | ||
116 | } | ||
117 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
118 | |||
90 | static __inline__ void atomic_clear_mask(unsigned int mask, atomic_t *v) | 119 | static __inline__ void atomic_clear_mask(unsigned int mask, atomic_t *v) |
91 | { | 120 | { |
92 | unsigned long flags; | 121 | unsigned long flags; |
diff --git a/include/asm-sh64/atomic.h b/include/asm-sh64/atomic.h index 8c3872d3e65f..927a2bc27b30 100644 --- a/include/asm-sh64/atomic.h +++ b/include/asm-sh64/atomic.h | |||
@@ -99,6 +99,35 @@ static __inline__ int atomic_sub_return(int i, atomic_t * v) | |||
99 | #define atomic_inc(v) atomic_add(1,(v)) | 99 | #define atomic_inc(v) atomic_add(1,(v)) |
100 | #define atomic_dec(v) atomic_sub(1,(v)) | 100 | #define atomic_dec(v) atomic_sub(1,(v)) |
101 | 101 | ||
102 | static inline int atomic_cmpxchg(atomic_t *v, int old, int new) | ||
103 | { | ||
104 | int ret; | ||
105 | unsigned long flags; | ||
106 | |||
107 | local_irq_save(flags); | ||
108 | ret = v->counter; | ||
109 | if (likely(ret == old)) | ||
110 | v->counter = new; | ||
111 | local_irq_restore(flags); | ||
112 | |||
113 | return ret; | ||
114 | } | ||
115 | |||
116 | static inline int atomic_add_unless(atomic_t *v, int a, int u) | ||
117 | { | ||
118 | int ret; | ||
119 | unsigned long flags; | ||
120 | |||
121 | local_irq_save(flags); | ||
122 | ret = v->counter; | ||
123 | if (ret != u) | ||
124 | v->counter += a; | ||
125 | local_irq_restore(flags); | ||
126 | |||
127 | return ret != u; | ||
128 | } | ||
129 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
130 | |||
102 | static __inline__ void atomic_clear_mask(unsigned int mask, atomic_t *v) | 131 | static __inline__ void atomic_clear_mask(unsigned int mask, atomic_t *v) |
103 | { | 132 | { |
104 | unsigned long flags; | 133 | unsigned long flags; |
diff --git a/include/asm-sparc/atomic.h b/include/asm-sparc/atomic.h index 37f6ab601c3d..62bec7ad271c 100644 --- a/include/asm-sparc/atomic.h +++ b/include/asm-sparc/atomic.h | |||
@@ -19,6 +19,8 @@ typedef struct { volatile int counter; } atomic_t; | |||
19 | #define ATOMIC_INIT(i) { (i) } | 19 | #define ATOMIC_INIT(i) { (i) } |
20 | 20 | ||
21 | extern int __atomic_add_return(int, atomic_t *); | 21 | extern int __atomic_add_return(int, atomic_t *); |
22 | extern int atomic_cmpxchg(atomic_t *, int, int); | ||
23 | extern int atomic_add_unless(atomic_t *, int, int); | ||
22 | extern void atomic_set(atomic_t *, int); | 24 | extern void atomic_set(atomic_t *, int); |
23 | 25 | ||
24 | #define atomic_read(v) ((v)->counter) | 26 | #define atomic_read(v) ((v)->counter) |
@@ -48,6 +50,8 @@ extern void atomic_set(atomic_t *, int); | |||
48 | #define atomic_dec_and_test(v) (atomic_dec_return(v) == 0) | 50 | #define atomic_dec_and_test(v) (atomic_dec_return(v) == 0) |
49 | #define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0) | 51 | #define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0) |
50 | 52 | ||
53 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
54 | |||
51 | /* This is the old 24-bit implementation. It's still used internally | 55 | /* This is the old 24-bit implementation. It's still used internally |
52 | * by some sparc-specific code, notably the semaphore implementation. | 56 | * by some sparc-specific code, notably the semaphore implementation. |
53 | */ | 57 | */ |
diff --git a/include/asm-sparc64/atomic.h b/include/asm-sparc64/atomic.h index e175afcf2cde..8198c3d0d007 100644 --- a/include/asm-sparc64/atomic.h +++ b/include/asm-sparc64/atomic.h | |||
@@ -70,6 +70,18 @@ extern int atomic64_sub_ret(int, atomic64_t *); | |||
70 | #define atomic_add_negative(i, v) (atomic_add_ret(i, v) < 0) | 70 | #define atomic_add_negative(i, v) (atomic_add_ret(i, v) < 0) |
71 | #define atomic64_add_negative(i, v) (atomic64_add_ret(i, v) < 0) | 71 | #define atomic64_add_negative(i, v) (atomic64_add_ret(i, v) < 0) |
72 | 72 | ||
73 | #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) | ||
74 | |||
75 | #define atomic_add_unless(v, a, u) \ | ||
76 | ({ \ | ||
77 | int c, old; \ | ||
78 | c = atomic_read(v); \ | ||
79 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
80 | c = old; \ | ||
81 | c != (u); \ | ||
82 | }) | ||
83 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
84 | |||
73 | /* Atomic operations are already serializing */ | 85 | /* Atomic operations are already serializing */ |
74 | #ifdef CONFIG_SMP | 86 | #ifdef CONFIG_SMP |
75 | #define smp_mb__before_atomic_dec() membar_storeload_loadload(); | 87 | #define smp_mb__before_atomic_dec() membar_storeload_loadload(); |
diff --git a/include/asm-v850/atomic.h b/include/asm-v850/atomic.h index 395268a8c0de..bede3172ce7f 100644 --- a/include/asm-v850/atomic.h +++ b/include/asm-v850/atomic.h | |||
@@ -90,6 +90,36 @@ static __inline__ void atomic_clear_mask (unsigned long mask, unsigned long *add | |||
90 | #define atomic_dec_and_test(v) (atomic_sub_return (1, (v)) == 0) | 90 | #define atomic_dec_and_test(v) (atomic_sub_return (1, (v)) == 0) |
91 | #define atomic_add_negative(i,v) (atomic_add_return ((i), (v)) < 0) | 91 | #define atomic_add_negative(i,v) (atomic_add_return ((i), (v)) < 0) |
92 | 92 | ||
93 | static inline int atomic_cmpxchg(atomic_t *v, int old, int new) | ||
94 | { | ||
95 | int ret; | ||
96 | unsigned long flags; | ||
97 | |||
98 | local_irq_save(flags); | ||
99 | ret = v->counter; | ||
100 | if (likely(ret == old)) | ||
101 | v->counter = new; | ||
102 | local_irq_restore(flags); | ||
103 | |||
104 | return ret; | ||
105 | } | ||
106 | |||
107 | static inline int atomic_add_unless(atomic_t *v, int a, int u) | ||
108 | { | ||
109 | int ret; | ||
110 | unsigned long flags; | ||
111 | |||
112 | local_irq_save(flags); | ||
113 | ret = v->counter; | ||
114 | if (ret != u) | ||
115 | v->counter += a; | ||
116 | local_irq_restore(flags); | ||
117 | |||
118 | return ret != u; | ||
119 | } | ||
120 | |||
121 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
122 | |||
93 | /* Atomic operations are already serializing on ARM */ | 123 | /* Atomic operations are already serializing on ARM */ |
94 | #define smp_mb__before_atomic_dec() barrier() | 124 | #define smp_mb__before_atomic_dec() barrier() |
95 | #define smp_mb__after_atomic_dec() barrier() | 125 | #define smp_mb__after_atomic_dec() barrier() |
diff --git a/include/asm-v850/hardirq.h b/include/asm-v850/hardirq.h index 5dfca8047cbe..d98488cd5af1 100644 --- a/include/asm-v850/hardirq.h +++ b/include/asm-v850/hardirq.h | |||
@@ -5,6 +5,8 @@ | |||
5 | #include <linux/threads.h> | 5 | #include <linux/threads.h> |
6 | #include <linux/cache.h> | 6 | #include <linux/cache.h> |
7 | 7 | ||
8 | #include <asm/irq.h> | ||
9 | |||
8 | typedef struct { | 10 | typedef struct { |
9 | unsigned int __softirq_pending; | 11 | unsigned int __softirq_pending; |
10 | } ____cacheline_aligned irq_cpustat_t; | 12 | } ____cacheline_aligned irq_cpustat_t; |
@@ -22,4 +24,6 @@ typedef struct { | |||
22 | # error HARDIRQ_BITS is too low! | 24 | # error HARDIRQ_BITS is too low! |
23 | #endif | 25 | #endif |
24 | 26 | ||
27 | void ack_bad_irq(unsigned int irq); | ||
28 | |||
25 | #endif /* __V850_HARDIRQ_H__ */ | 29 | #endif /* __V850_HARDIRQ_H__ */ |
diff --git a/include/asm-x86_64/apic.h b/include/asm-x86_64/apic.h index 6c5d5ca8383a..5647b7de1749 100644 --- a/include/asm-x86_64/apic.h +++ b/include/asm-x86_64/apic.h | |||
@@ -111,6 +111,8 @@ extern unsigned int nmi_watchdog; | |||
111 | 111 | ||
112 | extern int disable_timer_pin_1; | 112 | extern int disable_timer_pin_1; |
113 | 113 | ||
114 | extern void setup_threshold_lvt(unsigned long lvt_off); | ||
115 | |||
114 | #endif /* CONFIG_X86_LOCAL_APIC */ | 116 | #endif /* CONFIG_X86_LOCAL_APIC */ |
115 | 117 | ||
116 | extern unsigned boot_cpu_id; | 118 | extern unsigned boot_cpu_id; |
diff --git a/include/asm-x86_64/atomic.h b/include/asm-x86_64/atomic.h index fc4c5956e1ea..0866ef67f198 100644 --- a/include/asm-x86_64/atomic.h +++ b/include/asm-x86_64/atomic.h | |||
@@ -360,6 +360,27 @@ static __inline__ int atomic_sub_return(int i, atomic_t *v) | |||
360 | return atomic_add_return(-i,v); | 360 | return atomic_add_return(-i,v); |
361 | } | 361 | } |
362 | 362 | ||
363 | #define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new)) | ||
364 | |||
365 | /** | ||
366 | * atomic_add_unless - add unless the number is a given value | ||
367 | * @v: pointer of type atomic_t | ||
368 | * @a: the amount to add to v... | ||
369 | * @u: ...unless v is equal to u. | ||
370 | * | ||
371 | * Atomically adds @a to @v, so long as it was not @u. | ||
372 | * Returns non-zero if @v was not @u, and zero otherwise. | ||
373 | */ | ||
374 | #define atomic_add_unless(v, a, u) \ | ||
375 | ({ \ | ||
376 | int c, old; \ | ||
377 | c = atomic_read(v); \ | ||
378 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
379 | c = old; \ | ||
380 | c != (u); \ | ||
381 | }) | ||
382 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
383 | |||
363 | #define atomic_inc_return(v) (atomic_add_return(1,v)) | 384 | #define atomic_inc_return(v) (atomic_add_return(1,v)) |
364 | #define atomic_dec_return(v) (atomic_sub_return(1,v)) | 385 | #define atomic_dec_return(v) (atomic_sub_return(1,v)) |
365 | 386 | ||
diff --git a/include/asm-x86_64/cache.h b/include/asm-x86_64/cache.h index eda62bae1240..33e53424128b 100644 --- a/include/asm-x86_64/cache.h +++ b/include/asm-x86_64/cache.h | |||
@@ -9,6 +9,6 @@ | |||
9 | /* L1 cache line size */ | 9 | /* L1 cache line size */ |
10 | #define L1_CACHE_SHIFT (CONFIG_X86_L1_CACHE_SHIFT) | 10 | #define L1_CACHE_SHIFT (CONFIG_X86_L1_CACHE_SHIFT) |
11 | #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) | 11 | #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) |
12 | #define L1_CACHE_SHIFT_MAX 6 /* largest L1 which this arch supports */ | 12 | #define L1_CACHE_SHIFT_MAX 7 /* largest L1 which this arch supports */ |
13 | 13 | ||
14 | #endif | 14 | #endif |
diff --git a/include/asm-x86_64/desc.h b/include/asm-x86_64/desc.h index 68ac3c62fe3d..33764869387b 100644 --- a/include/asm-x86_64/desc.h +++ b/include/asm-x86_64/desc.h | |||
@@ -98,16 +98,19 @@ static inline void _set_gate(void *adr, unsigned type, unsigned long func, unsig | |||
98 | 98 | ||
99 | static inline void set_intr_gate(int nr, void *func) | 99 | static inline void set_intr_gate(int nr, void *func) |
100 | { | 100 | { |
101 | BUG_ON((unsigned)nr > 0xFF); | ||
101 | _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, 0); | 102 | _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, 0); |
102 | } | 103 | } |
103 | 104 | ||
104 | static inline void set_intr_gate_ist(int nr, void *func, unsigned ist) | 105 | static inline void set_intr_gate_ist(int nr, void *func, unsigned ist) |
105 | { | 106 | { |
107 | BUG_ON((unsigned)nr > 0xFF); | ||
106 | _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, ist); | 108 | _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, ist); |
107 | } | 109 | } |
108 | 110 | ||
109 | static inline void set_system_gate(int nr, void *func) | 111 | static inline void set_system_gate(int nr, void *func) |
110 | { | 112 | { |
113 | BUG_ON((unsigned)nr > 0xFF); | ||
111 | _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, 0); | 114 | _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, 0); |
112 | } | 115 | } |
113 | 116 | ||
@@ -129,9 +132,16 @@ static inline void set_tssldt_descriptor(void *ptr, unsigned long tss, unsigned | |||
129 | 132 | ||
130 | static inline void set_tss_desc(unsigned cpu, void *addr) | 133 | static inline void set_tss_desc(unsigned cpu, void *addr) |
131 | { | 134 | { |
132 | set_tssldt_descriptor(&cpu_gdt_table[cpu][GDT_ENTRY_TSS], (unsigned long)addr, | 135 | /* |
133 | DESC_TSS, | 136 | * sizeof(unsigned long) coming from an extra "long" at the end |
134 | sizeof(struct tss_struct) - 1); | 137 | * of the iobitmap. See tss_struct definition in processor.h |
138 | * | ||
139 | * -1? seg base+limit should be pointing to the address of the | ||
140 | * last valid byte | ||
141 | */ | ||
142 | set_tssldt_descriptor(&cpu_gdt_table[cpu][GDT_ENTRY_TSS], | ||
143 | (unsigned long)addr, DESC_TSS, | ||
144 | IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1); | ||
135 | } | 145 | } |
136 | 146 | ||
137 | static inline void set_ldt_desc(unsigned cpu, void *addr, int size) | 147 | static inline void set_ldt_desc(unsigned cpu, void *addr, int size) |
diff --git a/include/asm-x86_64/dma.h b/include/asm-x86_64/dma.h index 16fa3a064d0c..6f2a817b6a7c 100644 --- a/include/asm-x86_64/dma.h +++ b/include/asm-x86_64/dma.h | |||
@@ -72,8 +72,15 @@ | |||
72 | 72 | ||
73 | #define MAX_DMA_CHANNELS 8 | 73 | #define MAX_DMA_CHANNELS 8 |
74 | 74 | ||
75 | /* The maximum address that we can perform a DMA transfer to on this platform */ | 75 | |
76 | #define MAX_DMA_ADDRESS (PAGE_OFFSET+0x1000000) | 76 | /* 16MB ISA DMA zone */ |
77 | #define MAX_DMA_PFN ((16*1024*1024) >> PAGE_SHIFT) | ||
78 | |||
79 | /* 4GB broken PCI/AGP hardware bus master zone */ | ||
80 | #define MAX_DMA32_PFN ((4UL*1024*1024*1024) >> PAGE_SHIFT) | ||
81 | |||
82 | /* Compat define for old dma zone */ | ||
83 | #define MAX_DMA_ADDRESS ((unsigned long)__va(MAX_DMA_PFN << PAGE_SHIFT)) | ||
77 | 84 | ||
78 | /* 8237 DMA controllers */ | 85 | /* 8237 DMA controllers */ |
79 | #define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */ | 86 | #define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */ |
diff --git a/include/asm-x86_64/hpet.h b/include/asm-x86_64/hpet.h index a3877f570998..c20c28f5c7a0 100644 --- a/include/asm-x86_64/hpet.h +++ b/include/asm-x86_64/hpet.h | |||
@@ -14,18 +14,18 @@ | |||
14 | #define HPET_CFG 0x010 | 14 | #define HPET_CFG 0x010 |
15 | #define HPET_STATUS 0x020 | 15 | #define HPET_STATUS 0x020 |
16 | #define HPET_COUNTER 0x0f0 | 16 | #define HPET_COUNTER 0x0f0 |
17 | #define HPET_T0_CFG 0x100 | 17 | #define HPET_Tn_OFFSET 0x20 |
18 | #define HPET_T0_CMP 0x108 | 18 | #define HPET_Tn_CFG(n) (0x100 + (n) * HPET_Tn_OFFSET) |
19 | #define HPET_T0_ROUTE 0x110 | 19 | #define HPET_Tn_ROUTE(n) (0x104 + (n) * HPET_Tn_OFFSET) |
20 | #define HPET_T1_CFG 0x120 | 20 | #define HPET_Tn_CMP(n) (0x108 + (n) * HPET_Tn_OFFSET) |
21 | #define HPET_T1_CMP 0x128 | 21 | #define HPET_T0_CFG HPET_Tn_CFG(0) |
22 | #define HPET_T1_ROUTE 0x130 | 22 | #define HPET_T0_CMP HPET_Tn_CMP(0) |
23 | #define HPET_T2_CFG 0x140 | 23 | #define HPET_T1_CFG HPET_Tn_CFG(1) |
24 | #define HPET_T2_CMP 0x148 | 24 | #define HPET_T1_CMP HPET_Tn_CMP(1) |
25 | #define HPET_T2_ROUTE 0x150 | ||
26 | 25 | ||
27 | #define HPET_ID_VENDOR 0xffff0000 | 26 | #define HPET_ID_VENDOR 0xffff0000 |
28 | #define HPET_ID_LEGSUP 0x00008000 | 27 | #define HPET_ID_LEGSUP 0x00008000 |
28 | #define HPET_ID_64BIT 0x00002000 | ||
29 | #define HPET_ID_NUMBER 0x00001f00 | 29 | #define HPET_ID_NUMBER 0x00001f00 |
30 | #define HPET_ID_REV 0x000000ff | 30 | #define HPET_ID_REV 0x000000ff |
31 | #define HPET_ID_NUMBER_SHIFT 8 | 31 | #define HPET_ID_NUMBER_SHIFT 8 |
@@ -38,11 +38,18 @@ | |||
38 | #define HPET_LEGACY_8254 2 | 38 | #define HPET_LEGACY_8254 2 |
39 | #define HPET_LEGACY_RTC 8 | 39 | #define HPET_LEGACY_RTC 8 |
40 | 40 | ||
41 | #define HPET_TN_ENABLE 0x004 | 41 | #define HPET_TN_LEVEL 0x0002 |
42 | #define HPET_TN_PERIODIC 0x008 | 42 | #define HPET_TN_ENABLE 0x0004 |
43 | #define HPET_TN_PERIODIC_CAP 0x010 | 43 | #define HPET_TN_PERIODIC 0x0008 |
44 | #define HPET_TN_SETVAL 0x040 | 44 | #define HPET_TN_PERIODIC_CAP 0x0010 |
45 | #define HPET_TN_32BIT 0x100 | 45 | #define HPET_TN_64BIT_CAP 0x0020 |
46 | #define HPET_TN_SETVAL 0x0040 | ||
47 | #define HPET_TN_32BIT 0x0100 | ||
48 | #define HPET_TN_ROUTE 0x3e00 | ||
49 | #define HPET_TN_FSB 0x4000 | ||
50 | #define HPET_TN_FSB_CAP 0x8000 | ||
51 | |||
52 | #define HPET_TN_ROUTE_SHIFT 9 | ||
46 | 53 | ||
47 | extern int is_hpet_enabled(void); | 54 | extern int is_hpet_enabled(void); |
48 | extern int hpet_rtc_timer_init(void); | 55 | extern int hpet_rtc_timer_init(void); |
diff --git a/include/asm-x86_64/hw_irq.h b/include/asm-x86_64/hw_irq.h index dc97668ea0f9..c14a8c7267a6 100644 --- a/include/asm-x86_64/hw_irq.h +++ b/include/asm-x86_64/hw_irq.h | |||
@@ -55,7 +55,7 @@ struct hw_interrupt_type; | |||
55 | #define CALL_FUNCTION_VECTOR 0xfc | 55 | #define CALL_FUNCTION_VECTOR 0xfc |
56 | #define KDB_VECTOR 0xfb /* reserved for KDB */ | 56 | #define KDB_VECTOR 0xfb /* reserved for KDB */ |
57 | #define THERMAL_APIC_VECTOR 0xfa | 57 | #define THERMAL_APIC_VECTOR 0xfa |
58 | /* 0xf9 free */ | 58 | #define THRESHOLD_APIC_VECTOR 0xf9 |
59 | #define INVALIDATE_TLB_VECTOR_END 0xf8 | 59 | #define INVALIDATE_TLB_VECTOR_END 0xf8 |
60 | #define INVALIDATE_TLB_VECTOR_START 0xf0 /* f0-f8 used for TLB flush */ | 60 | #define INVALIDATE_TLB_VECTOR_START 0xf0 /* f0-f8 used for TLB flush */ |
61 | 61 | ||
diff --git a/include/asm-x86_64/ia32.h b/include/asm-x86_64/ia32.h index 6efa00fe4e7b..c7bc9c0525ba 100644 --- a/include/asm-x86_64/ia32.h +++ b/include/asm-x86_64/ia32.h | |||
@@ -165,6 +165,11 @@ struct siginfo_t; | |||
165 | int do_get_thread_area(struct thread_struct *t, struct user_desc __user *info); | 165 | int do_get_thread_area(struct thread_struct *t, struct user_desc __user *info); |
166 | int do_set_thread_area(struct thread_struct *t, struct user_desc __user *info); | 166 | int do_set_thread_area(struct thread_struct *t, struct user_desc __user *info); |
167 | int ia32_child_tls(struct task_struct *p, struct pt_regs *childregs); | 167 | int ia32_child_tls(struct task_struct *p, struct pt_regs *childregs); |
168 | |||
169 | struct linux_binprm; | ||
170 | extern int ia32_setup_arg_pages(struct linux_binprm *bprm, | ||
171 | unsigned long stack_top, int exec_stack); | ||
172 | |||
168 | #endif | 173 | #endif |
169 | 174 | ||
170 | #endif /* !CONFIG_IA32_SUPPORT */ | 175 | #endif /* !CONFIG_IA32_SUPPORT */ |
diff --git a/include/asm-x86_64/mce.h b/include/asm-x86_64/mce.h index 869249db6795..5d298b799a9f 100644 --- a/include/asm-x86_64/mce.h +++ b/include/asm-x86_64/mce.h | |||
@@ -67,6 +67,8 @@ struct mce_log { | |||
67 | /* Software defined banks */ | 67 | /* Software defined banks */ |
68 | #define MCE_EXTENDED_BANK 128 | 68 | #define MCE_EXTENDED_BANK 128 |
69 | #define MCE_THERMAL_BANK MCE_EXTENDED_BANK + 0 | 69 | #define MCE_THERMAL_BANK MCE_EXTENDED_BANK + 0 |
70 | #define MCE_THRESHOLD_BASE MCE_EXTENDED_BANK + 1 /* MCE_AMD */ | ||
71 | #define MCE_THRESHOLD_DRAM_ECC MCE_THRESHOLD_BASE + 4 | ||
70 | 72 | ||
71 | void mce_log(struct mce *m); | 73 | void mce_log(struct mce *m); |
72 | #ifdef CONFIG_X86_MCE_INTEL | 74 | #ifdef CONFIG_X86_MCE_INTEL |
@@ -77,4 +79,12 @@ static inline void mce_intel_feature_init(struct cpuinfo_x86 *c) | |||
77 | } | 79 | } |
78 | #endif | 80 | #endif |
79 | 81 | ||
82 | #ifdef CONFIG_X86_MCE_AMD | ||
83 | void mce_amd_feature_init(struct cpuinfo_x86 *c); | ||
84 | #else | ||
85 | static inline void mce_amd_feature_init(struct cpuinfo_x86 *c) | ||
86 | { | ||
87 | } | ||
88 | #endif | ||
89 | |||
80 | #endif | 90 | #endif |
diff --git a/include/asm-x86_64/mmzone.h b/include/asm-x86_64/mmzone.h index b40c661f111e..69baaa8a3ce0 100644 --- a/include/asm-x86_64/mmzone.h +++ b/include/asm-x86_64/mmzone.h | |||
@@ -17,16 +17,15 @@ | |||
17 | /* Simple perfect hash to map physical addresses to node numbers */ | 17 | /* Simple perfect hash to map physical addresses to node numbers */ |
18 | extern int memnode_shift; | 18 | extern int memnode_shift; |
19 | extern u8 memnodemap[NODEMAPSIZE]; | 19 | extern u8 memnodemap[NODEMAPSIZE]; |
20 | extern int maxnode; | ||
21 | 20 | ||
22 | extern struct pglist_data *node_data[]; | 21 | extern struct pglist_data *node_data[]; |
23 | 22 | ||
24 | static inline __attribute__((pure)) int phys_to_nid(unsigned long addr) | 23 | static inline __attribute__((pure)) int phys_to_nid(unsigned long addr) |
25 | { | 24 | { |
26 | int nid; | 25 | unsigned nid; |
27 | VIRTUAL_BUG_ON((addr >> memnode_shift) >= NODEMAPSIZE); | 26 | VIRTUAL_BUG_ON((addr >> memnode_shift) >= NODEMAPSIZE); |
28 | nid = memnodemap[addr >> memnode_shift]; | 27 | nid = memnodemap[addr >> memnode_shift]; |
29 | VIRTUAL_BUG_ON(nid > maxnode); | 28 | VIRTUAL_BUG_ON(nid >= MAX_NUMNODES || !node_data[nid]); |
30 | return nid; | 29 | return nid; |
31 | } | 30 | } |
32 | 31 | ||
@@ -41,9 +40,7 @@ static inline __attribute__((pure)) int phys_to_nid(unsigned long addr) | |||
41 | #define pfn_to_nid(pfn) phys_to_nid((unsigned long)(pfn) << PAGE_SHIFT) | 40 | #define pfn_to_nid(pfn) phys_to_nid((unsigned long)(pfn) << PAGE_SHIFT) |
42 | #define kvaddr_to_nid(kaddr) phys_to_nid(__pa(kaddr)) | 41 | #define kvaddr_to_nid(kaddr) phys_to_nid(__pa(kaddr)) |
43 | 42 | ||
44 | /* AK: this currently doesn't deal with invalid addresses. We'll see | 43 | /* Requires pfn_valid(pfn) to be true */ |
45 | if the 2.5 kernel doesn't pass them | ||
46 | (2.4 used to). */ | ||
47 | #define pfn_to_page(pfn) ({ \ | 44 | #define pfn_to_page(pfn) ({ \ |
48 | int nid = phys_to_nid(((unsigned long)(pfn)) << PAGE_SHIFT); \ | 45 | int nid = phys_to_nid(((unsigned long)(pfn)) << PAGE_SHIFT); \ |
49 | ((pfn) - node_start_pfn(nid)) + NODE_DATA(nid)->node_mem_map; \ | 46 | ((pfn) - node_start_pfn(nid)) + NODE_DATA(nid)->node_mem_map; \ |
diff --git a/include/asm-x86_64/mpspec.h b/include/asm-x86_64/mpspec.h index f267e10c023d..6f8a17d105ab 100644 --- a/include/asm-x86_64/mpspec.h +++ b/include/asm-x86_64/mpspec.h | |||
@@ -16,7 +16,7 @@ | |||
16 | /* | 16 | /* |
17 | * A maximum of 255 APICs with the current APIC ID architecture. | 17 | * A maximum of 255 APICs with the current APIC ID architecture. |
18 | */ | 18 | */ |
19 | #define MAX_APICS 128 | 19 | #define MAX_APICS 255 |
20 | 20 | ||
21 | struct intel_mp_floating | 21 | struct intel_mp_floating |
22 | { | 22 | { |
@@ -157,7 +157,8 @@ struct mpc_config_lintsrc | |||
157 | */ | 157 | */ |
158 | 158 | ||
159 | #define MAX_MP_BUSSES 256 | 159 | #define MAX_MP_BUSSES 256 |
160 | #define MAX_IRQ_SOURCES 256 | 160 | /* Each PCI slot may be a combo card with its own bus. 4 IRQ pins per slot. */ |
161 | #define MAX_IRQ_SOURCES (MAX_MP_BUSSES * 4) | ||
161 | enum mp_bustype { | 162 | enum mp_bustype { |
162 | MP_BUS_ISA = 1, | 163 | MP_BUS_ISA = 1, |
163 | MP_BUS_EISA, | 164 | MP_BUS_EISA, |
@@ -172,7 +173,7 @@ extern int smp_found_config; | |||
172 | extern void find_smp_config (void); | 173 | extern void find_smp_config (void); |
173 | extern void get_smp_config (void); | 174 | extern void get_smp_config (void); |
174 | extern int nr_ioapics; | 175 | extern int nr_ioapics; |
175 | extern int apic_version [MAX_APICS]; | 176 | extern unsigned char apic_version [MAX_APICS]; |
176 | extern int mp_irq_entries; | 177 | extern int mp_irq_entries; |
177 | extern struct mpc_config_intsrc mp_irqs [MAX_IRQ_SOURCES]; | 178 | extern struct mpc_config_intsrc mp_irqs [MAX_IRQ_SOURCES]; |
178 | extern int mpc_default_type; | 179 | extern int mpc_default_type; |
diff --git a/include/asm-x86_64/msr.h b/include/asm-x86_64/msr.h index 5a7fe3c6c3d8..24dc39651bc4 100644 --- a/include/asm-x86_64/msr.h +++ b/include/asm-x86_64/msr.h | |||
@@ -19,7 +19,7 @@ | |||
19 | : "=a" (a__), "=d" (b__) \ | 19 | : "=a" (a__), "=d" (b__) \ |
20 | : "c" (msr)); \ | 20 | : "c" (msr)); \ |
21 | val = a__ | (b__<<32); \ | 21 | val = a__ | (b__<<32); \ |
22 | } while(0); | 22 | } while(0) |
23 | 23 | ||
24 | #define wrmsr(msr,val1,val2) \ | 24 | #define wrmsr(msr,val1,val2) \ |
25 | __asm__ __volatile__("wrmsr" \ | 25 | __asm__ __volatile__("wrmsr" \ |
diff --git a/include/asm-x86_64/numa.h b/include/asm-x86_64/numa.h index bcf55c3f7f7f..d51e56fdc3da 100644 --- a/include/asm-x86_64/numa.h +++ b/include/asm-x86_64/numa.h | |||
@@ -17,6 +17,8 @@ extern void numa_add_cpu(int cpu); | |||
17 | extern void numa_init_array(void); | 17 | extern void numa_init_array(void); |
18 | extern int numa_off; | 18 | extern int numa_off; |
19 | 19 | ||
20 | extern void numa_set_node(int cpu, int node); | ||
21 | |||
20 | extern unsigned char apicid_to_node[256]; | 22 | extern unsigned char apicid_to_node[256]; |
21 | 23 | ||
22 | #define NUMA_NO_NODE 0xff | 24 | #define NUMA_NO_NODE 0xff |
diff --git a/include/asm-x86_64/page.h b/include/asm-x86_64/page.h index e5ab4d231f2c..06e489f32472 100644 --- a/include/asm-x86_64/page.h +++ b/include/asm-x86_64/page.h | |||
@@ -11,7 +11,7 @@ | |||
11 | #define PAGE_SIZE (1UL << PAGE_SHIFT) | 11 | #define PAGE_SIZE (1UL << PAGE_SHIFT) |
12 | #endif | 12 | #endif |
13 | #define PAGE_MASK (~(PAGE_SIZE-1)) | 13 | #define PAGE_MASK (~(PAGE_SIZE-1)) |
14 | #define PHYSICAL_PAGE_MASK (~(PAGE_SIZE-1) & (__PHYSICAL_MASK << PAGE_SHIFT)) | 14 | #define PHYSICAL_PAGE_MASK (~(PAGE_SIZE-1) & __PHYSICAL_MASK) |
15 | 15 | ||
16 | #define THREAD_ORDER 1 | 16 | #define THREAD_ORDER 1 |
17 | #ifdef __ASSEMBLY__ | 17 | #ifdef __ASSEMBLY__ |
diff --git a/include/asm-x86_64/pda.h b/include/asm-x86_64/pda.h index bbf89aa8a1af..8733ccfa442e 100644 --- a/include/asm-x86_64/pda.h +++ b/include/asm-x86_64/pda.h | |||
@@ -15,6 +15,7 @@ struct x8664_pda { | |||
15 | int irqcount; /* Irq nesting counter. Starts with -1 */ | 15 | int irqcount; /* Irq nesting counter. Starts with -1 */ |
16 | int cpunumber; /* Logical CPU number */ | 16 | int cpunumber; /* Logical CPU number */ |
17 | char *irqstackptr; /* top of irqstack */ | 17 | char *irqstackptr; /* top of irqstack */ |
18 | int nodenumber; /* number of current node */ | ||
18 | unsigned int __softirq_pending; | 19 | unsigned int __softirq_pending; |
19 | unsigned int __nmi_count; /* number of NMI on this CPUs */ | 20 | unsigned int __nmi_count; /* number of NMI on this CPUs */ |
20 | struct mm_struct *active_mm; | 21 | struct mm_struct *active_mm; |
diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h index 7309fffeec9a..ecf58c7c1650 100644 --- a/include/asm-x86_64/pgtable.h +++ b/include/asm-x86_64/pgtable.h | |||
@@ -16,6 +16,7 @@ extern pud_t level3_physmem_pgt[512]; | |||
16 | extern pud_t level3_ident_pgt[512]; | 16 | extern pud_t level3_ident_pgt[512]; |
17 | extern pmd_t level2_kernel_pgt[512]; | 17 | extern pmd_t level2_kernel_pgt[512]; |
18 | extern pgd_t init_level4_pgt[]; | 18 | extern pgd_t init_level4_pgt[]; |
19 | extern pgd_t boot_level4_pgt[]; | ||
19 | extern unsigned long __supported_pte_mask; | 20 | extern unsigned long __supported_pte_mask; |
20 | 21 | ||
21 | #define swapper_pg_dir init_level4_pgt | 22 | #define swapper_pg_dir init_level4_pgt |
@@ -247,7 +248,7 @@ static inline unsigned long pud_bad(pud_t pud) | |||
247 | #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) /* FIXME: is this | 248 | #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) /* FIXME: is this |
248 | right? */ | 249 | right? */ |
249 | #define pte_page(x) pfn_to_page(pte_pfn(x)) | 250 | #define pte_page(x) pfn_to_page(pte_pfn(x)) |
250 | #define pte_pfn(x) ((pte_val(x) >> PAGE_SHIFT) & __PHYSICAL_MASK) | 251 | #define pte_pfn(x) ((pte_val(x) & __PHYSICAL_MASK) >> PAGE_SHIFT) |
251 | 252 | ||
252 | static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot) | 253 | static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot) |
253 | { | 254 | { |
@@ -354,7 +355,7 @@ static inline pud_t *__pud_offset_k(pud_t *pud, unsigned long address) | |||
354 | #define pmd_clear(xp) do { set_pmd(xp, __pmd(0)); } while (0) | 355 | #define pmd_clear(xp) do { set_pmd(xp, __pmd(0)); } while (0) |
355 | #define pmd_bad(x) ((pmd_val(x) & (~PTE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE ) | 356 | #define pmd_bad(x) ((pmd_val(x) & (~PTE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE ) |
356 | #define pfn_pmd(nr,prot) (__pmd(((nr) << PAGE_SHIFT) | pgprot_val(prot))) | 357 | #define pfn_pmd(nr,prot) (__pmd(((nr) << PAGE_SHIFT) | pgprot_val(prot))) |
357 | #define pmd_pfn(x) ((pmd_val(x) >> PAGE_SHIFT) & __PHYSICAL_MASK) | 358 | #define pmd_pfn(x) ((pmd_val(x) & __PHYSICAL_MASK) >> PAGE_SHIFT) |
358 | 359 | ||
359 | #define pte_to_pgoff(pte) ((pte_val(pte) & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT) | 360 | #define pte_to_pgoff(pte) ((pte_val(pte) & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT) |
360 | #define pgoff_to_pte(off) ((pte_t) { ((off) << PAGE_SHIFT) | _PAGE_FILE }) | 361 | #define pgoff_to_pte(off) ((pte_t) { ((off) << PAGE_SHIFT) | _PAGE_FILE }) |
diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h index 03837d34fba0..4861246548f7 100644 --- a/include/asm-x86_64/processor.h +++ b/include/asm-x86_64/processor.h | |||
@@ -61,10 +61,12 @@ struct cpuinfo_x86 { | |||
61 | int x86_cache_alignment; | 61 | int x86_cache_alignment; |
62 | int x86_tlbsize; /* number of 4K pages in DTLB/ITLB combined(in pages)*/ | 62 | int x86_tlbsize; /* number of 4K pages in DTLB/ITLB combined(in pages)*/ |
63 | __u8 x86_virt_bits, x86_phys_bits; | 63 | __u8 x86_virt_bits, x86_phys_bits; |
64 | __u8 x86_num_cores; | 64 | __u8 x86_max_cores; /* cpuid returned max cores value */ |
65 | __u32 x86_power; | 65 | __u32 x86_power; |
66 | __u32 extended_cpuid_level; /* Max extended CPUID function supported */ | 66 | __u32 extended_cpuid_level; /* Max extended CPUID function supported */ |
67 | unsigned long loops_per_jiffy; | 67 | unsigned long loops_per_jiffy; |
68 | __u8 apicid; | ||
69 | __u8 booted_cores; /* number of cores as seen by OS */ | ||
68 | } ____cacheline_aligned; | 70 | } ____cacheline_aligned; |
69 | 71 | ||
70 | #define X86_VENDOR_INTEL 0 | 72 | #define X86_VENDOR_INTEL 0 |
diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h index dbb37b0adb43..34501086afef 100644 --- a/include/asm-x86_64/proto.h +++ b/include/asm-x86_64/proto.h | |||
@@ -11,6 +11,8 @@ struct pt_regs; | |||
11 | extern void start_kernel(void); | 11 | extern void start_kernel(void); |
12 | extern void pda_init(int); | 12 | extern void pda_init(int); |
13 | 13 | ||
14 | extern void zap_low_mappings(int cpu); | ||
15 | |||
14 | extern void early_idt_handler(void); | 16 | extern void early_idt_handler(void); |
15 | 17 | ||
16 | extern void mcheck_init(struct cpuinfo_x86 *c); | 18 | extern void mcheck_init(struct cpuinfo_x86 *c); |
@@ -22,6 +24,8 @@ extern void mtrr_bp_init(void); | |||
22 | #define mtrr_bp_init() do {} while (0) | 24 | #define mtrr_bp_init() do {} while (0) |
23 | #endif | 25 | #endif |
24 | extern void init_memory_mapping(unsigned long start, unsigned long end); | 26 | extern void init_memory_mapping(unsigned long start, unsigned long end); |
27 | extern void size_zones(unsigned long *z, unsigned long *h, | ||
28 | unsigned long start_pfn, unsigned long end_pfn); | ||
25 | 29 | ||
26 | extern void system_call(void); | 30 | extern void system_call(void); |
27 | extern int kernel_syscall(void); | 31 | extern int kernel_syscall(void); |
diff --git a/include/asm-x86_64/rwsem.h b/include/asm-x86_64/rwsem.h deleted file mode 100644 index 46077e9c1910..000000000000 --- a/include/asm-x86_64/rwsem.h +++ /dev/null | |||
@@ -1,283 +0,0 @@ | |||
1 | /* rwsem.h: R/W semaphores implemented using XADD/CMPXCHG for x86_64+ | ||
2 | * | ||
3 | * Written by David Howells (dhowells@redhat.com). | ||
4 | * Ported by Andi Kleen <ak@suse.de> to x86-64. | ||
5 | * | ||
6 | * Derived from asm-i386/semaphore.h and asm-i386/rwsem.h | ||
7 | * | ||
8 | * | ||
9 | * The MSW of the count is the negated number of active writers and waiting | ||
10 | * lockers, and the LSW is the total number of active locks | ||
11 | * | ||
12 | * The lock count is initialized to 0 (no active and no waiting lockers). | ||
13 | * | ||
14 | * When a writer subtracts WRITE_BIAS, it'll get 0xffff0001 for the case of an | ||
15 | * uncontended lock. This can be determined because XADD returns the old value. | ||
16 | * Readers increment by 1 and see a positive value when uncontended, negative | ||
17 | * if there are writers (and maybe) readers waiting (in which case it goes to | ||
18 | * sleep). | ||
19 | * | ||
20 | * The value of WAITING_BIAS supports up to 32766 waiting processes. This can | ||
21 | * be extended to 65534 by manually checking the whole MSW rather than relying | ||
22 | * on the S flag. | ||
23 | * | ||
24 | * The value of ACTIVE_BIAS supports up to 65535 active processes. | ||
25 | * | ||
26 | * This should be totally fair - if anything is waiting, a process that wants a | ||
27 | * lock will go to the back of the queue. When the currently active lock is | ||
28 | * released, if there's a writer at the front of the queue, then that and only | ||
29 | * that will be woken up; if there's a bunch of consecutive readers at the | ||
30 | * front, then they'll all be woken up, but no other readers will be. | ||
31 | */ | ||
32 | |||
33 | #ifndef _X8664_RWSEM_H | ||
34 | #define _X8664_RWSEM_H | ||
35 | |||
36 | #ifndef _LINUX_RWSEM_H | ||
37 | #error "please don't include asm/rwsem.h directly, use linux/rwsem.h instead" | ||
38 | #endif | ||
39 | |||
40 | #ifdef __KERNEL__ | ||
41 | |||
42 | #include <linux/list.h> | ||
43 | #include <linux/spinlock.h> | ||
44 | |||
45 | struct rwsem_waiter; | ||
46 | |||
47 | extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem); | ||
48 | extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem); | ||
49 | extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *); | ||
50 | extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem); | ||
51 | |||
52 | /* | ||
53 | * the semaphore definition | ||
54 | */ | ||
55 | struct rw_semaphore { | ||
56 | signed int count; | ||
57 | #define RWSEM_UNLOCKED_VALUE 0x00000000 | ||
58 | #define RWSEM_ACTIVE_BIAS 0x00000001 | ||
59 | #define RWSEM_ACTIVE_MASK 0x0000ffff | ||
60 | #define RWSEM_WAITING_BIAS (-0x00010000) | ||
61 | #define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS | ||
62 | #define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) | ||
63 | spinlock_t wait_lock; | ||
64 | struct list_head wait_list; | ||
65 | #if RWSEM_DEBUG | ||
66 | int debug; | ||
67 | #endif | ||
68 | }; | ||
69 | |||
70 | /* | ||
71 | * initialisation | ||
72 | */ | ||
73 | #if RWSEM_DEBUG | ||
74 | #define __RWSEM_DEBUG_INIT , 0 | ||
75 | #else | ||
76 | #define __RWSEM_DEBUG_INIT /* */ | ||
77 | #endif | ||
78 | |||
79 | #define __RWSEM_INITIALIZER(name) \ | ||
80 | { RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, LIST_HEAD_INIT((name).wait_list) \ | ||
81 | __RWSEM_DEBUG_INIT } | ||
82 | |||
83 | #define DECLARE_RWSEM(name) \ | ||
84 | struct rw_semaphore name = __RWSEM_INITIALIZER(name) | ||
85 | |||
86 | static inline void init_rwsem(struct rw_semaphore *sem) | ||
87 | { | ||
88 | sem->count = RWSEM_UNLOCKED_VALUE; | ||
89 | spin_lock_init(&sem->wait_lock); | ||
90 | INIT_LIST_HEAD(&sem->wait_list); | ||
91 | #if RWSEM_DEBUG | ||
92 | sem->debug = 0; | ||
93 | #endif | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * lock for reading | ||
98 | */ | ||
99 | static inline void __down_read(struct rw_semaphore *sem) | ||
100 | { | ||
101 | __asm__ __volatile__( | ||
102 | "# beginning down_read\n\t" | ||
103 | LOCK_PREFIX " incl (%%rdi)\n\t" /* adds 0x00000001, returns the old value */ | ||
104 | " js 2f\n\t" /* jump if we weren't granted the lock */ | ||
105 | "1:\n\t" | ||
106 | LOCK_SECTION_START("") \ | ||
107 | "2:\n\t" | ||
108 | " call rwsem_down_read_failed_thunk\n\t" | ||
109 | " jmp 1b\n" | ||
110 | LOCK_SECTION_END \ | ||
111 | "# ending down_read\n\t" | ||
112 | : "+m"(sem->count) | ||
113 | : "D"(sem) | ||
114 | : "memory", "cc"); | ||
115 | } | ||
116 | |||
117 | |||
118 | /* | ||
119 | * trylock for reading -- returns 1 if successful, 0 if contention | ||
120 | */ | ||
121 | static inline int __down_read_trylock(struct rw_semaphore *sem) | ||
122 | { | ||
123 | __s32 result, tmp; | ||
124 | __asm__ __volatile__( | ||
125 | "# beginning __down_read_trylock\n\t" | ||
126 | " movl %0,%1\n\t" | ||
127 | "1:\n\t" | ||
128 | " movl %1,%2\n\t" | ||
129 | " addl %3,%2\n\t" | ||
130 | " jle 2f\n\t" | ||
131 | LOCK_PREFIX " cmpxchgl %2,%0\n\t" | ||
132 | " jnz 1b\n\t" | ||
133 | "2:\n\t" | ||
134 | "# ending __down_read_trylock\n\t" | ||
135 | : "+m"(sem->count), "=&a"(result), "=&r"(tmp) | ||
136 | : "i"(RWSEM_ACTIVE_READ_BIAS) | ||
137 | : "memory", "cc"); | ||
138 | return result>=0 ? 1 : 0; | ||
139 | } | ||
140 | |||
141 | |||
142 | /* | ||
143 | * lock for writing | ||
144 | */ | ||
145 | static inline void __down_write(struct rw_semaphore *sem) | ||
146 | { | ||
147 | int tmp; | ||
148 | |||
149 | tmp = RWSEM_ACTIVE_WRITE_BIAS; | ||
150 | __asm__ __volatile__( | ||
151 | "# beginning down_write\n\t" | ||
152 | LOCK_PREFIX " xaddl %0,(%%rdi)\n\t" /* subtract 0x0000ffff, returns the old value */ | ||
153 | " testl %0,%0\n\t" /* was the count 0 before? */ | ||
154 | " jnz 2f\n\t" /* jump if we weren't granted the lock */ | ||
155 | "1:\n\t" | ||
156 | LOCK_SECTION_START("") | ||
157 | "2:\n\t" | ||
158 | " call rwsem_down_write_failed_thunk\n\t" | ||
159 | " jmp 1b\n" | ||
160 | LOCK_SECTION_END | ||
161 | "# ending down_write" | ||
162 | : "=&r" (tmp) | ||
163 | : "0"(tmp), "D"(sem) | ||
164 | : "memory", "cc"); | ||
165 | } | ||
166 | |||
167 | /* | ||
168 | * trylock for writing -- returns 1 if successful, 0 if contention | ||
169 | */ | ||
170 | static inline int __down_write_trylock(struct rw_semaphore *sem) | ||
171 | { | ||
172 | signed long ret = cmpxchg(&sem->count, | ||
173 | RWSEM_UNLOCKED_VALUE, | ||
174 | RWSEM_ACTIVE_WRITE_BIAS); | ||
175 | if (ret == RWSEM_UNLOCKED_VALUE) | ||
176 | return 1; | ||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | /* | ||
181 | * unlock after reading | ||
182 | */ | ||
183 | static inline void __up_read(struct rw_semaphore *sem) | ||
184 | { | ||
185 | __s32 tmp = -RWSEM_ACTIVE_READ_BIAS; | ||
186 | __asm__ __volatile__( | ||
187 | "# beginning __up_read\n\t" | ||
188 | LOCK_PREFIX " xaddl %[tmp],(%%rdi)\n\t" /* subtracts 1, returns the old value */ | ||
189 | " js 2f\n\t" /* jump if the lock is being waited upon */ | ||
190 | "1:\n\t" | ||
191 | LOCK_SECTION_START("") | ||
192 | "2:\n\t" | ||
193 | " decw %w[tmp]\n\t" /* do nothing if still outstanding active readers */ | ||
194 | " jnz 1b\n\t" | ||
195 | " call rwsem_wake_thunk\n\t" | ||
196 | " jmp 1b\n" | ||
197 | LOCK_SECTION_END | ||
198 | "# ending __up_read\n" | ||
199 | : "+m"(sem->count), [tmp] "+r" (tmp) | ||
200 | : "D"(sem) | ||
201 | : "memory", "cc"); | ||
202 | } | ||
203 | |||
204 | /* | ||
205 | * unlock after writing | ||
206 | */ | ||
207 | static inline void __up_write(struct rw_semaphore *sem) | ||
208 | { | ||
209 | unsigned tmp; | ||
210 | __asm__ __volatile__( | ||
211 | "# beginning __up_write\n\t" | ||
212 | " movl %[bias],%[tmp]\n\t" | ||
213 | LOCK_PREFIX " xaddl %[tmp],(%%rdi)\n\t" /* tries to transition 0xffff0001 -> 0x00000000 */ | ||
214 | " jnz 2f\n\t" /* jump if the lock is being waited upon */ | ||
215 | "1:\n\t" | ||
216 | LOCK_SECTION_START("") | ||
217 | "2:\n\t" | ||
218 | " decw %w[tmp]\n\t" /* did the active count reduce to 0? */ | ||
219 | " jnz 1b\n\t" /* jump back if not */ | ||
220 | " call rwsem_wake_thunk\n\t" | ||
221 | " jmp 1b\n" | ||
222 | LOCK_SECTION_END | ||
223 | "# ending __up_write\n" | ||
224 | : "+m"(sem->count), [tmp] "=r" (tmp) | ||
225 | : "D"(sem), [bias] "i"(-RWSEM_ACTIVE_WRITE_BIAS) | ||
226 | : "memory", "cc"); | ||
227 | } | ||
228 | |||
229 | /* | ||
230 | * downgrade write lock to read lock | ||
231 | */ | ||
232 | static inline void __downgrade_write(struct rw_semaphore *sem) | ||
233 | { | ||
234 | __asm__ __volatile__( | ||
235 | "# beginning __downgrade_write\n\t" | ||
236 | LOCK_PREFIX " addl %[bias],(%%rdi)\n\t" /* transitions 0xZZZZ0001 -> 0xYYYY0001 */ | ||
237 | " js 2f\n\t" /* jump if the lock is being waited upon */ | ||
238 | "1:\n\t" | ||
239 | LOCK_SECTION_START("") | ||
240 | "2:\n\t" | ||
241 | " call rwsem_downgrade_thunk\n" | ||
242 | " jmp 1b\n" | ||
243 | LOCK_SECTION_END | ||
244 | "# ending __downgrade_write\n" | ||
245 | : "=m"(sem->count) | ||
246 | : "D"(sem), [bias] "i"(-RWSEM_WAITING_BIAS), "m"(sem->count) | ||
247 | : "memory", "cc"); | ||
248 | } | ||
249 | |||
250 | /* | ||
251 | * implement atomic add functionality | ||
252 | */ | ||
253 | static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem) | ||
254 | { | ||
255 | __asm__ __volatile__( | ||
256 | LOCK_PREFIX "addl %1,%0" | ||
257 | :"=m"(sem->count) | ||
258 | :"ir"(delta), "m"(sem->count)); | ||
259 | } | ||
260 | |||
261 | /* | ||
262 | * implement exchange and add functionality | ||
263 | */ | ||
264 | static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem) | ||
265 | { | ||
266 | int tmp = delta; | ||
267 | |||
268 | __asm__ __volatile__( | ||
269 | LOCK_PREFIX "xaddl %0,(%2)" | ||
270 | : "=r"(tmp), "=m"(sem->count) | ||
271 | : "r"(sem), "m"(sem->count), "0" (tmp) | ||
272 | : "memory"); | ||
273 | |||
274 | return tmp+delta; | ||
275 | } | ||
276 | |||
277 | static inline int rwsem_is_locked(struct rw_semaphore *sem) | ||
278 | { | ||
279 | return (sem->count != 0); | ||
280 | } | ||
281 | |||
282 | #endif /* __KERNEL__ */ | ||
283 | #endif /* _X8664_RWSEM_H */ | ||
diff --git a/include/asm-x86_64/smp.h b/include/asm-x86_64/smp.h index b9fb2173ef99..d030409a8fb5 100644 --- a/include/asm-x86_64/smp.h +++ b/include/asm-x86_64/smp.h | |||
@@ -47,7 +47,6 @@ extern void lock_ipi_call_lock(void); | |||
47 | extern void unlock_ipi_call_lock(void); | 47 | extern void unlock_ipi_call_lock(void); |
48 | extern int smp_num_siblings; | 48 | extern int smp_num_siblings; |
49 | extern void smp_send_reschedule(int cpu); | 49 | extern void smp_send_reschedule(int cpu); |
50 | extern void zap_low_mappings(void); | ||
51 | void smp_stop_cpu(void); | 50 | void smp_stop_cpu(void); |
52 | extern int smp_call_function_single(int cpuid, void (*func) (void *info), | 51 | extern int smp_call_function_single(int cpuid, void (*func) (void *info), |
53 | void *info, int retry, int wait); | 52 | void *info, int retry, int wait); |
@@ -82,6 +81,8 @@ extern int safe_smp_processor_id(void); | |||
82 | extern int __cpu_disable(void); | 81 | extern int __cpu_disable(void); |
83 | extern void __cpu_die(unsigned int cpu); | 82 | extern void __cpu_die(unsigned int cpu); |
84 | extern void prefill_possible_map(void); | 83 | extern void prefill_possible_map(void); |
84 | extern unsigned num_processors; | ||
85 | extern unsigned disabled_cpus; | ||
85 | 86 | ||
86 | #endif /* !ASSEMBLY */ | 87 | #endif /* !ASSEMBLY */ |
87 | 88 | ||
diff --git a/include/asm-x86_64/spinlock.h b/include/asm-x86_64/spinlock.h index 69636831ad2f..fe484a699cc3 100644 --- a/include/asm-x86_64/spinlock.h +++ b/include/asm-x86_64/spinlock.h | |||
@@ -18,22 +18,22 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | #define __raw_spin_is_locked(x) \ | 20 | #define __raw_spin_is_locked(x) \ |
21 | (*(volatile signed char *)(&(x)->slock) <= 0) | 21 | (*(volatile signed int *)(&(x)->slock) <= 0) |
22 | 22 | ||
23 | #define __raw_spin_lock_string \ | 23 | #define __raw_spin_lock_string \ |
24 | "\n1:\t" \ | 24 | "\n1:\t" \ |
25 | "lock ; decb %0\n\t" \ | 25 | "lock ; decl %0\n\t" \ |
26 | "js 2f\n" \ | 26 | "js 2f\n" \ |
27 | LOCK_SECTION_START("") \ | 27 | LOCK_SECTION_START("") \ |
28 | "2:\t" \ | 28 | "2:\t" \ |
29 | "rep;nop\n\t" \ | 29 | "rep;nop\n\t" \ |
30 | "cmpb $0,%0\n\t" \ | 30 | "cmpl $0,%0\n\t" \ |
31 | "jle 2b\n\t" \ | 31 | "jle 2b\n\t" \ |
32 | "jmp 1b\n" \ | 32 | "jmp 1b\n" \ |
33 | LOCK_SECTION_END | 33 | LOCK_SECTION_END |
34 | 34 | ||
35 | #define __raw_spin_unlock_string \ | 35 | #define __raw_spin_unlock_string \ |
36 | "movb $1,%0" \ | 36 | "movl $1,%0" \ |
37 | :"=m" (lock->slock) : : "memory" | 37 | :"=m" (lock->slock) : : "memory" |
38 | 38 | ||
39 | static inline void __raw_spin_lock(raw_spinlock_t *lock) | 39 | static inline void __raw_spin_lock(raw_spinlock_t *lock) |
@@ -47,10 +47,10 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock) | |||
47 | 47 | ||
48 | static inline int __raw_spin_trylock(raw_spinlock_t *lock) | 48 | static inline int __raw_spin_trylock(raw_spinlock_t *lock) |
49 | { | 49 | { |
50 | char oldval; | 50 | int oldval; |
51 | 51 | ||
52 | __asm__ __volatile__( | 52 | __asm__ __volatile__( |
53 | "xchgb %b0,%1" | 53 | "xchgl %0,%1" |
54 | :"=q" (oldval), "=m" (lock->slock) | 54 | :"=q" (oldval), "=m" (lock->slock) |
55 | :"0" (0) : "memory"); | 55 | :"0" (0) : "memory"); |
56 | 56 | ||
diff --git a/include/asm-x86_64/topology.h b/include/asm-x86_64/topology.h index 1c603cd7e4d0..d39ebd5263ed 100644 --- a/include/asm-x86_64/topology.h +++ b/include/asm-x86_64/topology.h | |||
@@ -28,6 +28,8 @@ extern int __node_distance(int, int); | |||
28 | #define pcibus_to_node(bus) ((long)(bus->sysdata)) | 28 | #define pcibus_to_node(bus) ((long)(bus->sysdata)) |
29 | #define pcibus_to_cpumask(bus) node_to_cpumask(pcibus_to_node(bus)); | 29 | #define pcibus_to_cpumask(bus) node_to_cpumask(pcibus_to_node(bus)); |
30 | 30 | ||
31 | #define numa_node_id() read_pda(nodenumber) | ||
32 | |||
31 | /* sched_domains SD_NODE_INIT for x86_64 machines */ | 33 | /* sched_domains SD_NODE_INIT for x86_64 machines */ |
32 | #define SD_NODE_INIT (struct sched_domain) { \ | 34 | #define SD_NODE_INIT (struct sched_domain) { \ |
33 | .span = CPU_MASK_NONE, \ | 35 | .span = CPU_MASK_NONE, \ |
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h index 3c494b65d33a..2c42150bce0c 100644 --- a/include/asm-x86_64/unistd.h +++ b/include/asm-x86_64/unistd.h | |||
@@ -462,7 +462,7 @@ __SYSCALL(__NR_fremovexattr, sys_fremovexattr) | |||
462 | #define __NR_tkill 200 | 462 | #define __NR_tkill 200 |
463 | __SYSCALL(__NR_tkill, sys_tkill) | 463 | __SYSCALL(__NR_tkill, sys_tkill) |
464 | #define __NR_time 201 | 464 | #define __NR_time 201 |
465 | __SYSCALL(__NR_time, sys_time64) | 465 | __SYSCALL(__NR_time, sys_time) |
466 | #define __NR_futex 202 | 466 | #define __NR_futex 202 |
467 | __SYSCALL(__NR_futex, sys_futex) | 467 | __SYSCALL(__NR_futex, sys_futex) |
468 | #define __NR_sched_setaffinity 203 | 468 | #define __NR_sched_setaffinity 203 |
@@ -608,6 +608,7 @@ do { \ | |||
608 | #define __ARCH_WANT_SYS_SIGPENDING | 608 | #define __ARCH_WANT_SYS_SIGPENDING |
609 | #define __ARCH_WANT_SYS_SIGPROCMASK | 609 | #define __ARCH_WANT_SYS_SIGPROCMASK |
610 | #define __ARCH_WANT_SYS_RT_SIGACTION | 610 | #define __ARCH_WANT_SYS_RT_SIGACTION |
611 | #define __ARCH_WANT_SYS_TIME | ||
611 | #define __ARCH_WANT_COMPAT_SYS_TIME | 612 | #define __ARCH_WANT_COMPAT_SYS_TIME |
612 | #endif | 613 | #endif |
613 | 614 | ||
diff --git a/include/asm-xtensa/atomic.h b/include/asm-xtensa/atomic.h index 12b5732dc6e5..3670cc7695da 100644 --- a/include/asm-xtensa/atomic.h +++ b/include/asm-xtensa/atomic.h | |||
@@ -223,6 +223,26 @@ static inline int atomic_sub_return(int i, atomic_t * v) | |||
223 | */ | 223 | */ |
224 | #define atomic_add_negative(i,v) (atomic_add_return((i),(v)) < 0) | 224 | #define atomic_add_negative(i,v) (atomic_add_return((i),(v)) < 0) |
225 | 225 | ||
226 | #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) | ||
227 | |||
228 | /** | ||
229 | * atomic_add_unless - add unless the number is a given value | ||
230 | * @v: pointer of type atomic_t | ||
231 | * @a: the amount to add to v... | ||
232 | * @u: ...unless v is equal to u. | ||
233 | * | ||
234 | * Atomically adds @a to @v, so long as it was not @u. | ||
235 | * Returns non-zero if @v was not @u, and zero otherwise. | ||
236 | */ | ||
237 | #define atomic_add_unless(v, a, u) \ | ||
238 | ({ \ | ||
239 | int c, old; \ | ||
240 | c = atomic_read(v); \ | ||
241 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
242 | c = old; \ | ||
243 | c != (u); \ | ||
244 | }) | ||
245 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
226 | 246 | ||
227 | static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) | 247 | static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) |
228 | { | 248 | { |
diff --git a/include/linux/acct.h b/include/linux/acct.h index 93c5b3cdf951..9a66401073fc 100644 --- a/include/linux/acct.h +++ b/include/linux/acct.h | |||
@@ -16,6 +16,8 @@ | |||
16 | #define _LINUX_ACCT_H | 16 | #define _LINUX_ACCT_H |
17 | 17 | ||
18 | #include <linux/types.h> | 18 | #include <linux/types.h> |
19 | #include <linux/jiffies.h> | ||
20 | |||
19 | #include <asm/param.h> | 21 | #include <asm/param.h> |
20 | #include <asm/byteorder.h> | 22 | #include <asm/byteorder.h> |
21 | 23 | ||
diff --git a/include/linux/aio.h b/include/linux/aio.h index 403d71dcb7c8..49fd37629ee4 100644 --- a/include/linux/aio.h +++ b/include/linux/aio.h | |||
@@ -124,7 +124,7 @@ struct kiocb { | |||
124 | (x)->ki_users = 1; \ | 124 | (x)->ki_users = 1; \ |
125 | (x)->ki_key = KIOCB_SYNC_KEY; \ | 125 | (x)->ki_key = KIOCB_SYNC_KEY; \ |
126 | (x)->ki_filp = (filp); \ | 126 | (x)->ki_filp = (filp); \ |
127 | (x)->ki_ctx = &tsk->active_mm->default_kioctx; \ | 127 | (x)->ki_ctx = NULL; \ |
128 | (x)->ki_cancel = NULL; \ | 128 | (x)->ki_cancel = NULL; \ |
129 | (x)->ki_dtor = NULL; \ | 129 | (x)->ki_dtor = NULL; \ |
130 | (x)->ki_obj.tsk = tsk; \ | 130 | (x)->ki_obj.tsk = tsk; \ |
@@ -210,8 +210,15 @@ struct kioctx *lookup_ioctx(unsigned long ctx_id); | |||
210 | int FASTCALL(io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, | 210 | int FASTCALL(io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, |
211 | struct iocb *iocb)); | 211 | struct iocb *iocb)); |
212 | 212 | ||
213 | #define get_ioctx(kioctx) do { if (unlikely(atomic_read(&(kioctx)->users) <= 0)) BUG(); atomic_inc(&(kioctx)->users); } while (0) | 213 | #define get_ioctx(kioctx) do { \ |
214 | #define put_ioctx(kioctx) do { if (unlikely(atomic_dec_and_test(&(kioctx)->users))) __put_ioctx(kioctx); else if (unlikely(atomic_read(&(kioctx)->users) < 0)) BUG(); } while (0) | 214 | BUG_ON(unlikely(atomic_read(&(kioctx)->users) <= 0)); \ |
215 | atomic_inc(&(kioctx)->users); \ | ||
216 | } while (0) | ||
217 | #define put_ioctx(kioctx) do { \ | ||
218 | BUG_ON(unlikely(atomic_read(&(kioctx)->users) <= 0)); \ | ||
219 | if (unlikely(atomic_dec_and_test(&(kioctx)->users))) \ | ||
220 | __put_ioctx(kioctx); \ | ||
221 | } while (0) | ||
215 | 222 | ||
216 | #define in_aio() !is_sync_wait(current->io_wait) | 223 | #define in_aio() !is_sync_wait(current->io_wait) |
217 | /* may be used for debugging */ | 224 | /* may be used for debugging */ |
diff --git a/include/linux/bitops.h b/include/linux/bitops.h index cb3c3ef50f50..38c2fb7ebe09 100644 --- a/include/linux/bitops.h +++ b/include/linux/bitops.h | |||
@@ -84,6 +84,16 @@ static __inline__ int get_bitmask_order(unsigned int count) | |||
84 | return order; /* We could be slightly more clever with -1 here... */ | 84 | return order; /* We could be slightly more clever with -1 here... */ |
85 | } | 85 | } |
86 | 86 | ||
87 | static __inline__ int get_count_order(unsigned int count) | ||
88 | { | ||
89 | int order; | ||
90 | |||
91 | order = fls(count) - 1; | ||
92 | if (count & (count - 1)) | ||
93 | order++; | ||
94 | return order; | ||
95 | } | ||
96 | |||
87 | /* | 97 | /* |
88 | * hweightN: returns the hamming weight (i.e. the number | 98 | * hweightN: returns the hamming weight (i.e. the number |
89 | * of bits set) of a N-bit word | 99 | * of bits set) of a N-bit word |
diff --git a/include/linux/cm4000_cs.h b/include/linux/cm4000_cs.h new file mode 100644 index 000000000000..605ebe24bb2e --- /dev/null +++ b/include/linux/cm4000_cs.h | |||
@@ -0,0 +1,66 @@ | |||
1 | #ifndef _CM4000_H_ | ||
2 | #define _CM4000_H_ | ||
3 | |||
4 | #define MAX_ATR 33 | ||
5 | |||
6 | #define CM4000_MAX_DEV 4 | ||
7 | |||
8 | /* those two structures are passed via ioctl() from/to userspace. They are | ||
9 | * used by existing userspace programs, so I kepth the awkward "bIFSD" naming | ||
10 | * not to break compilation of userspace apps. -HW */ | ||
11 | |||
12 | typedef struct atreq { | ||
13 | int32_t atr_len; | ||
14 | unsigned char atr[64]; | ||
15 | int32_t power_act; | ||
16 | unsigned char bIFSD; | ||
17 | unsigned char bIFSC; | ||
18 | } atreq_t; | ||
19 | |||
20 | |||
21 | /* what is particularly stupid in the original driver is the arch-dependant | ||
22 | * member sizes. This leads to CONFIG_COMPAT breakage, since 32bit userspace | ||
23 | * will lay out the structure members differently than the 64bit kernel. | ||
24 | * | ||
25 | * I've changed "ptsreq.protocol" from "unsigned long" to "u_int32_t". | ||
26 | * On 32bit this will make no difference. With 64bit kernels, it will make | ||
27 | * 32bit apps work, too. | ||
28 | */ | ||
29 | |||
30 | typedef struct ptsreq { | ||
31 | u_int32_t protocol; /*T=0: 2^0, T=1: 2^1*/ | ||
32 | unsigned char flags; | ||
33 | unsigned char pts1; | ||
34 | unsigned char pts2; | ||
35 | unsigned char pts3; | ||
36 | } ptsreq_t; | ||
37 | |||
38 | #define CM_IOC_MAGIC 'c' | ||
39 | #define CM_IOC_MAXNR 255 | ||
40 | |||
41 | #define CM_IOCGSTATUS _IOR (CM_IOC_MAGIC, 0, unsigned char *) | ||
42 | #define CM_IOCGATR _IOWR(CM_IOC_MAGIC, 1, atreq_t *) | ||
43 | #define CM_IOCSPTS _IOW (CM_IOC_MAGIC, 2, ptsreq_t *) | ||
44 | #define CM_IOCSRDR _IO (CM_IOC_MAGIC, 3) | ||
45 | #define CM_IOCARDOFF _IO (CM_IOC_MAGIC, 4) | ||
46 | |||
47 | #define CM_IOSDBGLVL _IOW(CM_IOC_MAGIC, 250, int*) | ||
48 | |||
49 | /* card and device states */ | ||
50 | #define CM_CARD_INSERTED 0x01 | ||
51 | #define CM_CARD_POWERED 0x02 | ||
52 | #define CM_ATR_PRESENT 0x04 | ||
53 | #define CM_ATR_VALID 0x08 | ||
54 | #define CM_STATE_VALID 0x0f | ||
55 | /* extra info only from CM4000 */ | ||
56 | #define CM_NO_READER 0x10 | ||
57 | #define CM_BAD_CARD 0x20 | ||
58 | |||
59 | |||
60 | #ifdef __KERNEL__ | ||
61 | |||
62 | #define DEVICE_NAME "cmm" | ||
63 | #define MODULE_NAME "cm4000_cs" | ||
64 | |||
65 | #endif /* __KERNEL__ */ | ||
66 | #endif /* _CM4000_H_ */ | ||
diff --git a/include/linux/file.h b/include/linux/file.h index d3b1a15d5f21..418b6101b59a 100644 --- a/include/linux/file.h +++ b/include/linux/file.h | |||
@@ -33,13 +33,13 @@ struct fdtable { | |||
33 | * Open file table structure | 33 | * Open file table structure |
34 | */ | 34 | */ |
35 | struct files_struct { | 35 | struct files_struct { |
36 | atomic_t count; | 36 | atomic_t count; |
37 | spinlock_t file_lock; /* Protects all the below members. Nests inside tsk->alloc_lock */ | ||
38 | struct fdtable *fdt; | 37 | struct fdtable *fdt; |
39 | struct fdtable fdtab; | 38 | struct fdtable fdtab; |
40 | fd_set close_on_exec_init; | 39 | fd_set close_on_exec_init; |
41 | fd_set open_fds_init; | 40 | fd_set open_fds_init; |
42 | struct file * fd_array[NR_OPEN_DEFAULT]; | 41 | struct file * fd_array[NR_OPEN_DEFAULT]; |
42 | spinlock_t file_lock; /* Protects concurrent writers. Nests inside tsk->alloc_lock */ | ||
43 | }; | 43 | }; |
44 | 44 | ||
45 | #define files_fdtable(files) (rcu_dereference((files)->fdt)) | 45 | #define files_fdtable(files) (rcu_dereference((files)->fdt)) |
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h index 114d5d59f695..934aa9bda481 100644 --- a/include/linux/fsl_devices.h +++ b/include/linux/fsl_devices.h | |||
@@ -4,7 +4,7 @@ | |||
4 | * Definitions for any platform device related flags or structures for | 4 | * Definitions for any platform device related flags or structures for |
5 | * Freescale processor devices | 5 | * Freescale processor devices |
6 | * | 6 | * |
7 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) | 7 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
8 | * | 8 | * |
9 | * Copyright 2004 Freescale Semiconductor, Inc | 9 | * Copyright 2004 Freescale Semiconductor, Inc |
10 | * | 10 | * |
diff --git a/include/linux/gfp.h b/include/linux/gfp.h index c3779432a723..313dfe9b443a 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h | |||
@@ -14,6 +14,13 @@ struct vm_area_struct; | |||
14 | /* Zone modifiers in GFP_ZONEMASK (see linux/mmzone.h - low two bits) */ | 14 | /* Zone modifiers in GFP_ZONEMASK (see linux/mmzone.h - low two bits) */ |
15 | #define __GFP_DMA ((__force gfp_t)0x01u) | 15 | #define __GFP_DMA ((__force gfp_t)0x01u) |
16 | #define __GFP_HIGHMEM ((__force gfp_t)0x02u) | 16 | #define __GFP_HIGHMEM ((__force gfp_t)0x02u) |
17 | #ifdef CONFIG_DMA_IS_DMA32 | ||
18 | #define __GFP_DMA32 ((__force gfp_t)0x01) /* ZONE_DMA is ZONE_DMA32 */ | ||
19 | #elif BITS_PER_LONG < 64 | ||
20 | #define __GFP_DMA32 ((__force gfp_t)0x00) /* ZONE_NORMAL is ZONE_DMA32 */ | ||
21 | #else | ||
22 | #define __GFP_DMA32 ((__force gfp_t)0x04) /* Has own ZONE_DMA32 */ | ||
23 | #endif | ||
17 | 24 | ||
18 | /* | 25 | /* |
19 | * Action modifiers - doesn't change the zoning | 26 | * Action modifiers - doesn't change the zoning |
@@ -39,8 +46,7 @@ struct vm_area_struct; | |||
39 | #define __GFP_COMP ((__force gfp_t)0x4000u)/* Add compound page metadata */ | 46 | #define __GFP_COMP ((__force gfp_t)0x4000u)/* Add compound page metadata */ |
40 | #define __GFP_ZERO ((__force gfp_t)0x8000u)/* Return zeroed page on success */ | 47 | #define __GFP_ZERO ((__force gfp_t)0x8000u)/* Return zeroed page on success */ |
41 | #define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */ | 48 | #define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */ |
42 | #define __GFP_NORECLAIM ((__force gfp_t)0x20000u) /* No realy zone reclaim during allocation */ | 49 | #define __GFP_HARDWALL ((__force gfp_t)0x20000u) /* Enforce hardwall cpuset memory allocs */ |
43 | #define __GFP_HARDWALL ((__force gfp_t)0x40000u) /* Enforce hardwall cpuset memory allocs */ | ||
44 | 50 | ||
45 | #define __GFP_BITS_SHIFT 20 /* Room for 20 __GFP_FOO bits */ | 51 | #define __GFP_BITS_SHIFT 20 /* Room for 20 __GFP_FOO bits */ |
46 | #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1)) | 52 | #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1)) |
@@ -49,7 +55,7 @@ struct vm_area_struct; | |||
49 | #define GFP_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS| \ | 55 | #define GFP_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS| \ |
50 | __GFP_COLD|__GFP_NOWARN|__GFP_REPEAT| \ | 56 | __GFP_COLD|__GFP_NOWARN|__GFP_REPEAT| \ |
51 | __GFP_NOFAIL|__GFP_NORETRY|__GFP_NO_GROW|__GFP_COMP| \ | 57 | __GFP_NOFAIL|__GFP_NORETRY|__GFP_NO_GROW|__GFP_COMP| \ |
52 | __GFP_NOMEMALLOC|__GFP_NORECLAIM|__GFP_HARDWALL) | 58 | __GFP_NOMEMALLOC|__GFP_HARDWALL) |
53 | 59 | ||
54 | #define GFP_ATOMIC (__GFP_HIGH) | 60 | #define GFP_ATOMIC (__GFP_HIGH) |
55 | #define GFP_NOIO (__GFP_WAIT) | 61 | #define GFP_NOIO (__GFP_WAIT) |
@@ -64,6 +70,10 @@ struct vm_area_struct; | |||
64 | 70 | ||
65 | #define GFP_DMA __GFP_DMA | 71 | #define GFP_DMA __GFP_DMA |
66 | 72 | ||
73 | /* 4GB DMA on some platforms */ | ||
74 | #define GFP_DMA32 __GFP_DMA32 | ||
75 | |||
76 | |||
67 | #define gfp_zone(mask) ((__force int)((mask) & (__force gfp_t)GFP_ZONEMASK)) | 77 | #define gfp_zone(mask) ((__force int)((mask) & (__force gfp_t)GFP_ZONEMASK)) |
68 | 78 | ||
69 | /* | 79 | /* |
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h index 5912874ca83c..71d2b8a723b9 100644 --- a/include/linux/hardirq.h +++ b/include/linux/hardirq.h | |||
@@ -90,6 +90,8 @@ extern void synchronize_irq(unsigned int irq); | |||
90 | #define nmi_enter() irq_enter() | 90 | #define nmi_enter() irq_enter() |
91 | #define nmi_exit() sub_preempt_count(HARDIRQ_OFFSET) | 91 | #define nmi_exit() sub_preempt_count(HARDIRQ_OFFSET) |
92 | 92 | ||
93 | struct task_struct; | ||
94 | |||
93 | #ifndef CONFIG_VIRT_CPU_ACCOUNTING | 95 | #ifndef CONFIG_VIRT_CPU_ACCOUNTING |
94 | static inline void account_user_vtime(struct task_struct *tsk) | 96 | static inline void account_user_vtime(struct task_struct *tsk) |
95 | { | 97 | { |
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 0cea162b08c0..1056717ee501 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h | |||
@@ -102,8 +102,8 @@ static inline unsigned long hugetlb_total_pages(void) | |||
102 | #define hugetlb_fault(mm, vma, addr, write) ({ BUG(); 0; }) | 102 | #define hugetlb_fault(mm, vma, addr, write) ({ BUG(); 0; }) |
103 | 103 | ||
104 | #ifndef HPAGE_MASK | 104 | #ifndef HPAGE_MASK |
105 | #define HPAGE_MASK 0 /* Keep the compiler happy */ | 105 | #define HPAGE_MASK PAGE_MASK /* Keep the compiler happy */ |
106 | #define HPAGE_SIZE 0 | 106 | #define HPAGE_SIZE PAGE_SIZE |
107 | #endif | 107 | #endif |
108 | 108 | ||
109 | #endif /* !CONFIG_HUGETLB_PAGE */ | 109 | #endif /* !CONFIG_HUGETLB_PAGE */ |
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index 74abaecdb572..1543daaa9c5e 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h | |||
@@ -107,6 +107,7 @@ | |||
107 | #define I2C_DRIVERID_CX25840 71 /* cx2584x video encoder */ | 107 | #define I2C_DRIVERID_CX25840 71 /* cx2584x video encoder */ |
108 | #define I2C_DRIVERID_SAA7127 72 /* saa7124 video encoder */ | 108 | #define I2C_DRIVERID_SAA7127 72 /* saa7124 video encoder */ |
109 | #define I2C_DRIVERID_SAA711X 73 /* saa711x video encoders */ | 109 | #define I2C_DRIVERID_SAA711X 73 /* saa711x video encoders */ |
110 | #define I2C_DRIVERID_AKITAIOEXP 74 /* IO Expander on Sharp SL-C1000 */ | ||
110 | 111 | ||
111 | #define I2C_DRIVERID_EXP0 0xF0 /* experimental use id's */ | 112 | #define I2C_DRIVERID_EXP0 0xF0 /* experimental use id's */ |
112 | #define I2C_DRIVERID_EXP1 0xF1 | 113 | #define I2C_DRIVERID_EXP1 0xF1 |
diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 68ab5f2ab9cd..dcfd2ecccb5d 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h | |||
@@ -51,7 +51,6 @@ | |||
51 | .page_table_lock = SPIN_LOCK_UNLOCKED, \ | 51 | .page_table_lock = SPIN_LOCK_UNLOCKED, \ |
52 | .mmlist = LIST_HEAD_INIT(name.mmlist), \ | 52 | .mmlist = LIST_HEAD_INIT(name.mmlist), \ |
53 | .cpu_vm_mask = CPU_MASK_ALL, \ | 53 | .cpu_vm_mask = CPU_MASK_ALL, \ |
54 | .default_kioctx = INIT_KIOCTX(name.default_kioctx, name), \ | ||
55 | } | 54 | } |
56 | 55 | ||
57 | #define INIT_SIGNALS(sig) { \ | 56 | #define INIT_SIGNALS(sig) { \ |
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 0a90205184b0..41f150a3d2dd 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/preempt.h> | 9 | #include <linux/preempt.h> |
10 | #include <linux/cpumask.h> | 10 | #include <linux/cpumask.h> |
11 | #include <linux/hardirq.h> | 11 | #include <linux/hardirq.h> |
12 | #include <linux/sched.h> | ||
12 | #include <asm/atomic.h> | 13 | #include <asm/atomic.h> |
13 | #include <asm/ptrace.h> | 14 | #include <asm/ptrace.h> |
14 | #include <asm/system.h> | 15 | #include <asm/system.h> |
diff --git a/include/linux/mm.h b/include/linux/mm.h index 7b115feca4df..1013a42d10b1 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -206,12 +206,6 @@ struct vm_operations_struct { | |||
206 | struct mmu_gather; | 206 | struct mmu_gather; |
207 | struct inode; | 207 | struct inode; |
208 | 208 | ||
209 | #ifdef ARCH_HAS_ATOMIC_UNSIGNED | ||
210 | typedef unsigned page_flags_t; | ||
211 | #else | ||
212 | typedef unsigned long page_flags_t; | ||
213 | #endif | ||
214 | |||
215 | /* | 209 | /* |
216 | * Each physical page in the system has a struct page associated with | 210 | * Each physical page in the system has a struct page associated with |
217 | * it to keep track of whatever it is we are using the page for at the | 211 | * it to keep track of whatever it is we are using the page for at the |
@@ -219,7 +213,7 @@ typedef unsigned long page_flags_t; | |||
219 | * a page. | 213 | * a page. |
220 | */ | 214 | */ |
221 | struct page { | 215 | struct page { |
222 | page_flags_t flags; /* Atomic flags, some possibly | 216 | unsigned long flags; /* Atomic flags, some possibly |
223 | * updated asynchronously */ | 217 | * updated asynchronously */ |
224 | atomic_t _count; /* Usage count, see below. */ | 218 | atomic_t _count; /* Usage count, see below. */ |
225 | atomic_t _mapcount; /* Count of ptes mapped in mms, | 219 | atomic_t _mapcount; /* Count of ptes mapped in mms, |
@@ -435,7 +429,7 @@ static inline void put_page(struct page *page) | |||
435 | #endif | 429 | #endif |
436 | 430 | ||
437 | /* Page flags: | [SECTION] | [NODE] | ZONE | ... | FLAGS | */ | 431 | /* Page flags: | [SECTION] | [NODE] | ZONE | ... | FLAGS | */ |
438 | #define SECTIONS_PGOFF ((sizeof(page_flags_t)*8) - SECTIONS_WIDTH) | 432 | #define SECTIONS_PGOFF ((sizeof(unsigned long)*8) - SECTIONS_WIDTH) |
439 | #define NODES_PGOFF (SECTIONS_PGOFF - NODES_WIDTH) | 433 | #define NODES_PGOFF (SECTIONS_PGOFF - NODES_WIDTH) |
440 | #define ZONES_PGOFF (NODES_PGOFF - ZONES_WIDTH) | 434 | #define ZONES_PGOFF (NODES_PGOFF - ZONES_WIDTH) |
441 | 435 | ||
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index f5fa3082fd6a..2c8edad5dccf 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h | |||
@@ -71,10 +71,11 @@ struct per_cpu_pageset { | |||
71 | #endif | 71 | #endif |
72 | 72 | ||
73 | #define ZONE_DMA 0 | 73 | #define ZONE_DMA 0 |
74 | #define ZONE_NORMAL 1 | 74 | #define ZONE_DMA32 1 |
75 | #define ZONE_HIGHMEM 2 | 75 | #define ZONE_NORMAL 2 |
76 | #define ZONE_HIGHMEM 3 | ||
76 | 77 | ||
77 | #define MAX_NR_ZONES 3 /* Sync this with ZONES_SHIFT */ | 78 | #define MAX_NR_ZONES 4 /* Sync this with ZONES_SHIFT */ |
78 | #define ZONES_SHIFT 2 /* ceil(log2(MAX_NR_ZONES)) */ | 79 | #define ZONES_SHIFT 2 /* ceil(log2(MAX_NR_ZONES)) */ |
79 | 80 | ||
80 | 81 | ||
@@ -108,9 +109,10 @@ struct per_cpu_pageset { | |||
108 | 109 | ||
109 | /* | 110 | /* |
110 | * On machines where it is needed (eg PCs) we divide physical memory | 111 | * On machines where it is needed (eg PCs) we divide physical memory |
111 | * into multiple physical zones. On a PC we have 3 zones: | 112 | * into multiple physical zones. On a PC we have 4 zones: |
112 | * | 113 | * |
113 | * ZONE_DMA < 16 MB ISA DMA capable memory | 114 | * ZONE_DMA < 16 MB ISA DMA capable memory |
115 | * ZONE_DMA32 0 MB Empty | ||
114 | * ZONE_NORMAL 16-896 MB direct mapped by the kernel | 116 | * ZONE_NORMAL 16-896 MB direct mapped by the kernel |
115 | * ZONE_HIGHMEM > 896 MB only page cache and user processes | 117 | * ZONE_HIGHMEM > 896 MB only page cache and user processes |
116 | */ | 118 | */ |
@@ -329,7 +331,7 @@ void get_zone_counts(unsigned long *active, unsigned long *inactive, | |||
329 | void build_all_zonelists(void); | 331 | void build_all_zonelists(void); |
330 | void wakeup_kswapd(struct zone *zone, int order); | 332 | void wakeup_kswapd(struct zone *zone, int order); |
331 | int zone_watermark_ok(struct zone *z, int order, unsigned long mark, | 333 | int zone_watermark_ok(struct zone *z, int order, unsigned long mark, |
332 | int alloc_type, int can_try_harder, gfp_t gfp_high); | 334 | int classzone_idx, int alloc_flags); |
333 | 335 | ||
334 | #ifdef CONFIG_HAVE_MEMORY_PRESENT | 336 | #ifdef CONFIG_HAVE_MEMORY_PRESENT |
335 | void memory_present(int nid, unsigned long start, unsigned long end); | 337 | void memory_present(int nid, unsigned long start, unsigned long end); |
@@ -433,7 +435,9 @@ int lowmem_reserve_ratio_sysctl_handler(struct ctl_table *, int, struct file *, | |||
433 | 435 | ||
434 | #include <linux/topology.h> | 436 | #include <linux/topology.h> |
435 | /* Returns the number of the current Node. */ | 437 | /* Returns the number of the current Node. */ |
438 | #ifndef numa_node_id | ||
436 | #define numa_node_id() (cpu_to_node(raw_smp_processor_id())) | 439 | #define numa_node_id() (cpu_to_node(raw_smp_processor_id())) |
440 | #endif | ||
437 | 441 | ||
438 | #ifndef CONFIG_NEED_MULTIPLE_NODES | 442 | #ifndef CONFIG_NEED_MULTIPLE_NODES |
439 | 443 | ||
@@ -453,12 +457,12 @@ extern struct pglist_data contig_page_data; | |||
453 | #include <asm/sparsemem.h> | 457 | #include <asm/sparsemem.h> |
454 | #endif | 458 | #endif |
455 | 459 | ||
456 | #if BITS_PER_LONG == 32 || defined(ARCH_HAS_ATOMIC_UNSIGNED) | 460 | #if BITS_PER_LONG == 32 |
457 | /* | 461 | /* |
458 | * with 32 bit page->flags field, we reserve 8 bits for node/zone info. | 462 | * with 32 bit page->flags field, we reserve 9 bits for node/zone info. |
459 | * there are 3 zones (2 bits) and this leaves 8-2=6 bits for nodes. | 463 | * there are 4 zones (3 bits) and this leaves 9-3=6 bits for nodes. |
460 | */ | 464 | */ |
461 | #define FLAGS_RESERVED 8 | 465 | #define FLAGS_RESERVED 9 |
462 | 466 | ||
463 | #elif BITS_PER_LONG == 64 | 467 | #elif BITS_PER_LONG == 64 |
464 | /* | 468 | /* |
diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h index 72975fa8795d..934a2479f160 100644 --- a/include/linux/netfilter/nfnetlink.h +++ b/include/linux/netfilter/nfnetlink.h | |||
@@ -112,7 +112,6 @@ struct nfnl_callback | |||
112 | { | 112 | { |
113 | int (*call)(struct sock *nl, struct sk_buff *skb, | 113 | int (*call)(struct sock *nl, struct sk_buff *skb, |
114 | struct nlmsghdr *nlh, struct nfattr *cda[], int *errp); | 114 | struct nlmsghdr *nlh, struct nfattr *cda[], int *errp); |
115 | kernel_cap_t cap_required; /* capabilities required for this msg */ | ||
116 | u_int16_t attr_count; /* number of nfattr's */ | 115 | u_int16_t attr_count; /* number of nfattr's */ |
117 | }; | 116 | }; |
118 | 117 | ||
@@ -154,11 +153,14 @@ extern void nfattr_parse(struct nfattr *tb[], int maxattr, | |||
154 | 153 | ||
155 | #define nfattr_bad_size(tb, max, cta_min) \ | 154 | #define nfattr_bad_size(tb, max, cta_min) \ |
156 | ({ int __i, __res = 0; \ | 155 | ({ int __i, __res = 0; \ |
157 | for (__i=0; __i<max; __i++) \ | 156 | for (__i=0; __i<max; __i++) { \ |
157 | if (!cta_min[__i]) \ | ||
158 | continue; \ | ||
158 | if (tb[__i] && NFA_PAYLOAD(tb[__i]) < cta_min[__i]){ \ | 159 | if (tb[__i] && NFA_PAYLOAD(tb[__i]) < cta_min[__i]){ \ |
159 | __res = 1; \ | 160 | __res = 1; \ |
160 | break; \ | 161 | break; \ |
161 | } \ | 162 | } \ |
163 | } \ | ||
162 | __res; \ | 164 | __res; \ |
163 | }) | 165 | }) |
164 | 166 | ||
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index ba6c310a055f..ee700c6eb442 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h | |||
@@ -53,12 +53,12 @@ void release_pages(struct page **pages, int nr, int cold); | |||
53 | 53 | ||
54 | static inline struct page *page_cache_alloc(struct address_space *x) | 54 | static inline struct page *page_cache_alloc(struct address_space *x) |
55 | { | 55 | { |
56 | return alloc_pages(mapping_gfp_mask(x)|__GFP_NORECLAIM, 0); | 56 | return alloc_pages(mapping_gfp_mask(x), 0); |
57 | } | 57 | } |
58 | 58 | ||
59 | static inline struct page *page_cache_alloc_cold(struct address_space *x) | 59 | static inline struct page *page_cache_alloc_cold(struct address_space *x) |
60 | { | 60 | { |
61 | return alloc_pages(mapping_gfp_mask(x)|__GFP_COLD|__GFP_NORECLAIM, 0); | 61 | return alloc_pages(mapping_gfp_mask(x)|__GFP_COLD, 0); |
62 | } | 62 | } |
63 | 63 | ||
64 | typedef int filler_t(void *, struct page *); | 64 | typedef int filler_t(void *, struct page *); |
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index d00f8ba7f22b..d4c1c8fd2925 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
@@ -805,6 +805,10 @@ | |||
805 | #define PCI_DEVICE_ID_APPLE_SH_SUNGEM 0x0051 | 805 | #define PCI_DEVICE_ID_APPLE_SH_SUNGEM 0x0051 |
806 | #define PCI_DEVICE_ID_APPLE_U3L_AGP 0x0058 | 806 | #define PCI_DEVICE_ID_APPLE_U3L_AGP 0x0058 |
807 | #define PCI_DEVICE_ID_APPLE_U3H_AGP 0x0059 | 807 | #define PCI_DEVICE_ID_APPLE_U3H_AGP 0x0059 |
808 | #define PCI_DEVICE_ID_APPLE_IPID2_AGP 0x0066 | ||
809 | #define PCI_DEVICE_ID_APPLE_IPID2_ATA 0x0069 | ||
810 | #define PCI_DEVICE_ID_APPLE_IPID2_FW 0x006a | ||
811 | #define PCI_DEVICE_ID_APPLE_IPID2_GMAC 0x006b | ||
808 | #define PCI_DEVICE_ID_APPLE_TIGON3 0x1645 | 812 | #define PCI_DEVICE_ID_APPLE_TIGON3 0x1645 |
809 | 813 | ||
810 | #define PCI_VENDOR_ID_YAMAHA 0x1073 | 814 | #define PCI_VENDOR_ID_YAMAHA 0x1073 |
diff --git a/include/linux/percpu.h b/include/linux/percpu.h index 5451eb1e781d..fb8d2d24e4bb 100644 --- a/include/linux/percpu.h +++ b/include/linux/percpu.h | |||
@@ -38,7 +38,7 @@ extern void free_percpu(const void *); | |||
38 | 38 | ||
39 | #else /* CONFIG_SMP */ | 39 | #else /* CONFIG_SMP */ |
40 | 40 | ||
41 | #define per_cpu_ptr(ptr, cpu) (ptr) | 41 | #define per_cpu_ptr(ptr, cpu) ({ (void)(cpu); (ptr); }) |
42 | 42 | ||
43 | static inline void *__alloc_percpu(size_t size, size_t align) | 43 | static inline void *__alloc_percpu(size_t size, size_t align) |
44 | { | 44 | { |
diff --git a/include/linux/pm.h b/include/linux/pm.h index 1514098d156d..5be87ba3b7ac 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h | |||
@@ -94,55 +94,6 @@ struct pm_dev | |||
94 | struct list_head entry; | 94 | struct list_head entry; |
95 | }; | 95 | }; |
96 | 96 | ||
97 | #ifdef CONFIG_PM | ||
98 | |||
99 | extern int pm_active; | ||
100 | |||
101 | #define PM_IS_ACTIVE() (pm_active != 0) | ||
102 | |||
103 | /* | ||
104 | * Register a device with power management | ||
105 | */ | ||
106 | struct pm_dev __deprecated * | ||
107 | pm_register(pm_dev_t type, unsigned long id, pm_callback callback); | ||
108 | |||
109 | /* | ||
110 | * Unregister a device with power management | ||
111 | */ | ||
112 | void __deprecated pm_unregister(struct pm_dev *dev); | ||
113 | |||
114 | /* | ||
115 | * Unregister all devices with matching callback | ||
116 | */ | ||
117 | void __deprecated pm_unregister_all(pm_callback callback); | ||
118 | |||
119 | /* | ||
120 | * Send a request to all devices | ||
121 | */ | ||
122 | int __deprecated pm_send_all(pm_request_t rqst, void *data); | ||
123 | |||
124 | #else /* CONFIG_PM */ | ||
125 | |||
126 | #define PM_IS_ACTIVE() 0 | ||
127 | |||
128 | static inline struct pm_dev *pm_register(pm_dev_t type, | ||
129 | unsigned long id, | ||
130 | pm_callback callback) | ||
131 | { | ||
132 | return NULL; | ||
133 | } | ||
134 | |||
135 | static inline void pm_unregister(struct pm_dev *dev) {} | ||
136 | |||
137 | static inline void pm_unregister_all(pm_callback callback) {} | ||
138 | |||
139 | static inline int pm_send_all(pm_request_t rqst, void *data) | ||
140 | { | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | #endif /* CONFIG_PM */ | ||
145 | |||
146 | /* Functions above this comment are list-based old-style power | 97 | /* Functions above this comment are list-based old-style power |
147 | * managment. Please avoid using them. */ | 98 | * managment. Please avoid using them. */ |
148 | 99 | ||
diff --git a/include/linux/pm_legacy.h b/include/linux/pm_legacy.h new file mode 100644 index 000000000000..1252b45face1 --- /dev/null +++ b/include/linux/pm_legacy.h | |||
@@ -0,0 +1,56 @@ | |||
1 | #ifndef __LINUX_PM_LEGACY_H__ | ||
2 | #define __LINUX_PM_LEGACY_H__ | ||
3 | |||
4 | #include <linux/config.h> | ||
5 | |||
6 | #ifdef CONFIG_PM_LEGACY | ||
7 | |||
8 | extern int pm_active; | ||
9 | |||
10 | #define PM_IS_ACTIVE() (pm_active != 0) | ||
11 | |||
12 | /* | ||
13 | * Register a device with power management | ||
14 | */ | ||
15 | struct pm_dev __deprecated * | ||
16 | pm_register(pm_dev_t type, unsigned long id, pm_callback callback); | ||
17 | |||
18 | /* | ||
19 | * Unregister a device with power management | ||
20 | */ | ||
21 | void __deprecated pm_unregister(struct pm_dev *dev); | ||
22 | |||
23 | /* | ||
24 | * Unregister all devices with matching callback | ||
25 | */ | ||
26 | void __deprecated pm_unregister_all(pm_callback callback); | ||
27 | |||
28 | /* | ||
29 | * Send a request to all devices | ||
30 | */ | ||
31 | int __deprecated pm_send_all(pm_request_t rqst, void *data); | ||
32 | |||
33 | #else /* CONFIG_PM_LEGACY */ | ||
34 | |||
35 | #define PM_IS_ACTIVE() 0 | ||
36 | |||
37 | static inline struct pm_dev *pm_register(pm_dev_t type, | ||
38 | unsigned long id, | ||
39 | pm_callback callback) | ||
40 | { | ||
41 | return NULL; | ||
42 | } | ||
43 | |||
44 | static inline void pm_unregister(struct pm_dev *dev) {} | ||
45 | |||
46 | static inline void pm_unregister_all(pm_callback callback) {} | ||
47 | |||
48 | static inline int pm_send_all(pm_request_t rqst, void *data) | ||
49 | { | ||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | #endif /* CONFIG_PM_LEGACY */ | ||
54 | |||
55 | #endif /* __LINUX_PM_LEGACY_H__ */ | ||
56 | |||
diff --git a/include/linux/preempt.h b/include/linux/preempt.h index dd98c54a23b4..d9a2f5254a51 100644 --- a/include/linux/preempt.h +++ b/include/linux/preempt.h | |||
@@ -7,6 +7,7 @@ | |||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/config.h> | 9 | #include <linux/config.h> |
10 | #include <linux/thread_info.h> | ||
10 | #include <linux/linkage.h> | 11 | #include <linux/linkage.h> |
11 | 12 | ||
12 | #ifdef CONFIG_DEBUG_PREEMPT | 13 | #ifdef CONFIG_DEBUG_PREEMPT |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 2bbf968b23d9..2038bd27b041 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -357,7 +357,6 @@ struct mm_struct { | |||
357 | /* aio bits */ | 357 | /* aio bits */ |
358 | rwlock_t ioctx_list_lock; | 358 | rwlock_t ioctx_list_lock; |
359 | struct kioctx *ioctx_list; | 359 | struct kioctx *ioctx_list; |
360 | struct kioctx default_kioctx; | ||
361 | }; | 360 | }; |
362 | 361 | ||
363 | struct sighand_struct { | 362 | struct sighand_struct { |
@@ -1233,32 +1232,49 @@ static inline void task_unlock(struct task_struct *p) | |||
1233 | spin_unlock(&p->alloc_lock); | 1232 | spin_unlock(&p->alloc_lock); |
1234 | } | 1233 | } |
1235 | 1234 | ||
1235 | #ifndef __HAVE_THREAD_FUNCTIONS | ||
1236 | |||
1237 | #define task_thread_info(task) (task)->thread_info | ||
1238 | |||
1239 | static inline void setup_thread_stack(struct task_struct *p, struct task_struct *org) | ||
1240 | { | ||
1241 | *task_thread_info(p) = *task_thread_info(org); | ||
1242 | task_thread_info(p)->task = p; | ||
1243 | } | ||
1244 | |||
1245 | static inline unsigned long *end_of_stack(struct task_struct *p) | ||
1246 | { | ||
1247 | return (unsigned long *)(p->thread_info + 1); | ||
1248 | } | ||
1249 | |||
1250 | #endif | ||
1251 | |||
1236 | /* set thread flags in other task's structures | 1252 | /* set thread flags in other task's structures |
1237 | * - see asm/thread_info.h for TIF_xxxx flags available | 1253 | * - see asm/thread_info.h for TIF_xxxx flags available |
1238 | */ | 1254 | */ |
1239 | static inline void set_tsk_thread_flag(struct task_struct *tsk, int flag) | 1255 | static inline void set_tsk_thread_flag(struct task_struct *tsk, int flag) |
1240 | { | 1256 | { |
1241 | set_ti_thread_flag(tsk->thread_info,flag); | 1257 | set_ti_thread_flag(task_thread_info(tsk), flag); |
1242 | } | 1258 | } |
1243 | 1259 | ||
1244 | static inline void clear_tsk_thread_flag(struct task_struct *tsk, int flag) | 1260 | static inline void clear_tsk_thread_flag(struct task_struct *tsk, int flag) |
1245 | { | 1261 | { |
1246 | clear_ti_thread_flag(tsk->thread_info,flag); | 1262 | clear_ti_thread_flag(task_thread_info(tsk), flag); |
1247 | } | 1263 | } |
1248 | 1264 | ||
1249 | static inline int test_and_set_tsk_thread_flag(struct task_struct *tsk, int flag) | 1265 | static inline int test_and_set_tsk_thread_flag(struct task_struct *tsk, int flag) |
1250 | { | 1266 | { |
1251 | return test_and_set_ti_thread_flag(tsk->thread_info,flag); | 1267 | return test_and_set_ti_thread_flag(task_thread_info(tsk), flag); |
1252 | } | 1268 | } |
1253 | 1269 | ||
1254 | static inline int test_and_clear_tsk_thread_flag(struct task_struct *tsk, int flag) | 1270 | static inline int test_and_clear_tsk_thread_flag(struct task_struct *tsk, int flag) |
1255 | { | 1271 | { |
1256 | return test_and_clear_ti_thread_flag(tsk->thread_info,flag); | 1272 | return test_and_clear_ti_thread_flag(task_thread_info(tsk), flag); |
1257 | } | 1273 | } |
1258 | 1274 | ||
1259 | static inline int test_tsk_thread_flag(struct task_struct *tsk, int flag) | 1275 | static inline int test_tsk_thread_flag(struct task_struct *tsk, int flag) |
1260 | { | 1276 | { |
1261 | return test_ti_thread_flag(tsk->thread_info,flag); | 1277 | return test_ti_thread_flag(task_thread_info(tsk), flag); |
1262 | } | 1278 | } |
1263 | 1279 | ||
1264 | static inline void set_tsk_need_resched(struct task_struct *tsk) | 1280 | static inline void set_tsk_need_resched(struct task_struct *tsk) |
@@ -1329,12 +1345,12 @@ extern void signal_wake_up(struct task_struct *t, int resume_stopped); | |||
1329 | 1345 | ||
1330 | static inline unsigned int task_cpu(const struct task_struct *p) | 1346 | static inline unsigned int task_cpu(const struct task_struct *p) |
1331 | { | 1347 | { |
1332 | return p->thread_info->cpu; | 1348 | return task_thread_info(p)->cpu; |
1333 | } | 1349 | } |
1334 | 1350 | ||
1335 | static inline void set_task_cpu(struct task_struct *p, unsigned int cpu) | 1351 | static inline void set_task_cpu(struct task_struct *p, unsigned int cpu) |
1336 | { | 1352 | { |
1337 | p->thread_info->cpu = cpu; | 1353 | task_thread_info(p)->cpu = cpu; |
1338 | } | 1354 | } |
1339 | 1355 | ||
1340 | #else | 1356 | #else |
diff --git a/include/linux/smp_lock.h b/include/linux/smp_lock.h index b63ce7014093..fa1ff3b165fe 100644 --- a/include/linux/smp_lock.h +++ b/include/linux/smp_lock.h | |||
@@ -2,11 +2,10 @@ | |||
2 | #define __LINUX_SMPLOCK_H | 2 | #define __LINUX_SMPLOCK_H |
3 | 3 | ||
4 | #include <linux/config.h> | 4 | #include <linux/config.h> |
5 | #ifdef CONFIG_LOCK_KERNEL | ||
5 | #include <linux/sched.h> | 6 | #include <linux/sched.h> |
6 | #include <linux/spinlock.h> | 7 | #include <linux/spinlock.h> |
7 | 8 | ||
8 | #ifdef CONFIG_LOCK_KERNEL | ||
9 | |||
10 | #define kernel_locked() (current->lock_depth >= 0) | 9 | #define kernel_locked() (current->lock_depth >= 0) |
11 | 10 | ||
12 | extern int __lockfunc __reacquire_kernel_lock(void); | 11 | extern int __lockfunc __reacquire_kernel_lock(void); |
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 64f203c45378..6bc03c911a83 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h | |||
@@ -20,7 +20,6 @@ | |||
20 | 20 | ||
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/types.h> | 22 | #include <linux/types.h> |
23 | #include <linux/list.h> | ||
24 | #include <linux/compiler.h> | 23 | #include <linux/compiler.h> |
25 | 24 | ||
26 | struct file; | 25 | struct file; |
@@ -859,6 +858,7 @@ enum | |||
859 | }; | 858 | }; |
860 | 859 | ||
861 | #ifdef __KERNEL__ | 860 | #ifdef __KERNEL__ |
861 | #include <linux/list.h> | ||
862 | 862 | ||
863 | extern void sysctl_init(void); | 863 | extern void sysctl_init(void); |
864 | 864 | ||
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h index d252f45a0f9b..1c4eb41dbd89 100644 --- a/include/linux/thread_info.h +++ b/include/linux/thread_info.h | |||
@@ -27,31 +27,6 @@ extern long do_no_restart_syscall(struct restart_block *parm); | |||
27 | * - pass TIF_xxxx constants to these functions | 27 | * - pass TIF_xxxx constants to these functions |
28 | */ | 28 | */ |
29 | 29 | ||
30 | static inline void set_thread_flag(int flag) | ||
31 | { | ||
32 | set_bit(flag,¤t_thread_info()->flags); | ||
33 | } | ||
34 | |||
35 | static inline void clear_thread_flag(int flag) | ||
36 | { | ||
37 | clear_bit(flag,¤t_thread_info()->flags); | ||
38 | } | ||
39 | |||
40 | static inline int test_and_set_thread_flag(int flag) | ||
41 | { | ||
42 | return test_and_set_bit(flag,¤t_thread_info()->flags); | ||
43 | } | ||
44 | |||
45 | static inline int test_and_clear_thread_flag(int flag) | ||
46 | { | ||
47 | return test_and_clear_bit(flag,¤t_thread_info()->flags); | ||
48 | } | ||
49 | |||
50 | static inline int test_thread_flag(int flag) | ||
51 | { | ||
52 | return test_bit(flag,¤t_thread_info()->flags); | ||
53 | } | ||
54 | |||
55 | static inline void set_ti_thread_flag(struct thread_info *ti, int flag) | 30 | static inline void set_ti_thread_flag(struct thread_info *ti, int flag) |
56 | { | 31 | { |
57 | set_bit(flag,&ti->flags); | 32 | set_bit(flag,&ti->flags); |
@@ -77,15 +52,19 @@ static inline int test_ti_thread_flag(struct thread_info *ti, int flag) | |||
77 | return test_bit(flag,&ti->flags); | 52 | return test_bit(flag,&ti->flags); |
78 | } | 53 | } |
79 | 54 | ||
80 | static inline void set_need_resched(void) | 55 | #define set_thread_flag(flag) \ |
81 | { | 56 | set_ti_thread_flag(current_thread_info(), flag) |
82 | set_thread_flag(TIF_NEED_RESCHED); | 57 | #define clear_thread_flag(flag) \ |
83 | } | 58 | clear_ti_thread_flag(current_thread_info(), flag) |
84 | 59 | #define test_and_set_thread_flag(flag) \ | |
85 | static inline void clear_need_resched(void) | 60 | test_and_set_ti_thread_flag(current_thread_info(), flag) |
86 | { | 61 | #define test_and_clear_thread_flag(flag) \ |
87 | clear_thread_flag(TIF_NEED_RESCHED); | 62 | test_and_clear_ti_thread_flag(current_thread_info(), flag) |
88 | } | 63 | #define test_thread_flag(flag) \ |
64 | test_ti_thread_flag(current_thread_info(), flag) | ||
65 | |||
66 | #define set_need_resched() set_thread_flag(TIF_NEED_RESCHED) | ||
67 | #define clear_need_resched() clear_thread_flag(TIF_NEED_RESCHED) | ||
89 | 68 | ||
90 | #endif | 69 | #endif |
91 | 70 | ||
diff --git a/include/linux/time.h b/include/linux/time.h index 8e83f4e778bb..bfbe92d0767c 100644 --- a/include/linux/time.h +++ b/include/linux/time.h | |||
@@ -101,7 +101,7 @@ extern struct timespec timespec_trunc(struct timespec t, unsigned gran); | |||
101 | static inline void | 101 | static inline void |
102 | set_normalized_timespec (struct timespec *ts, time_t sec, long nsec) | 102 | set_normalized_timespec (struct timespec *ts, time_t sec, long nsec) |
103 | { | 103 | { |
104 | while (nsec > NSEC_PER_SEC) { | 104 | while (nsec >= NSEC_PER_SEC) { |
105 | nsec -= NSEC_PER_SEC; | 105 | nsec -= NSEC_PER_SEC; |
106 | ++sec; | 106 | ++sec; |
107 | } | 107 | } |
diff --git a/include/linux/usb.h b/include/linux/usb.h index 748d04385256..856d232c7562 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h | |||
@@ -819,7 +819,7 @@ typedef void (*usb_complete_t)(struct urb *, struct pt_regs *); | |||
819 | */ | 819 | */ |
820 | struct urb | 820 | struct urb |
821 | { | 821 | { |
822 | /* private, usb core and host controller only fields in the urb */ | 822 | /* private: usb core and host controller only fields in the urb */ |
823 | struct kref kref; /* reference count of the URB */ | 823 | struct kref kref; /* reference count of the URB */ |
824 | spinlock_t lock; /* lock for the URB */ | 824 | spinlock_t lock; /* lock for the URB */ |
825 | void *hcpriv; /* private data for host controller */ | 825 | void *hcpriv; /* private data for host controller */ |
@@ -827,7 +827,7 @@ struct urb | |||
827 | atomic_t use_count; /* concurrent submissions counter */ | 827 | atomic_t use_count; /* concurrent submissions counter */ |
828 | u8 reject; /* submissions will fail */ | 828 | u8 reject; /* submissions will fail */ |
829 | 829 | ||
830 | /* public, documented fields in the urb that can be used by drivers */ | 830 | /* public: documented fields in the urb that can be used by drivers */ |
831 | struct list_head urb_list; /* list head for use by the urb's | 831 | struct list_head urb_list; /* list head for use by the urb's |
832 | * current owner */ | 832 | * current owner */ |
833 | struct usb_device *dev; /* (in) pointer to associated device */ | 833 | struct usb_device *dev; /* (in) pointer to associated device */ |
@@ -1045,7 +1045,7 @@ struct usb_sg_request { | |||
1045 | size_t bytes; | 1045 | size_t bytes; |
1046 | 1046 | ||
1047 | /* | 1047 | /* |
1048 | * members below are private to usbcore, | 1048 | * members below are private: to usbcore, |
1049 | * and are not provided for driver access! | 1049 | * and are not provided for driver access! |
1050 | */ | 1050 | */ |
1051 | spinlock_t lock; | 1051 | spinlock_t lock; |
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index a114fff6568b..1cded681eb6d 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h | |||
@@ -636,6 +636,7 @@ typedef __u64 v4l2_std_id; | |||
636 | #define V4L2_STD_SECAM_K ((v4l2_std_id)0x00100000) | 636 | #define V4L2_STD_SECAM_K ((v4l2_std_id)0x00100000) |
637 | #define V4L2_STD_SECAM_K1 ((v4l2_std_id)0x00200000) | 637 | #define V4L2_STD_SECAM_K1 ((v4l2_std_id)0x00200000) |
638 | #define V4L2_STD_SECAM_L ((v4l2_std_id)0x00400000) | 638 | #define V4L2_STD_SECAM_L ((v4l2_std_id)0x00400000) |
639 | #define V4L2_STD_SECAM_LC ((v4l2_std_id)0x00800000) | ||
639 | 640 | ||
640 | /* ATSC/HDTV */ | 641 | /* ATSC/HDTV */ |
641 | #define V4L2_STD_ATSC_8_VSB ((v4l2_std_id)0x01000000) | 642 | #define V4L2_STD_ATSC_8_VSB ((v4l2_std_id)0x01000000) |
diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 0f1ba95ec8d6..ad3e9bb670c3 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h | |||
@@ -49,6 +49,7 @@ struct ir_input_state { | |||
49 | 49 | ||
50 | extern IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE]; | 50 | extern IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE]; |
51 | extern IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE]; | 51 | extern IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE]; |
52 | extern IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE]; | ||
52 | extern IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE]; | 53 | extern IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE]; |
53 | extern IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE]; | 54 | extern IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE]; |
54 | extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE]; | 55 | extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE]; |
diff --git a/include/media/ir-kbd-i2c.h b/include/media/ir-kbd-i2c.h index 00fa57eb9fde..730f21ed91db 100644 --- a/include/media/ir-kbd-i2c.h +++ b/include/media/ir-kbd-i2c.h | |||
@@ -19,4 +19,6 @@ struct IR_i2c { | |||
19 | char phys[32]; | 19 | char phys[32]; |
20 | int (*get_key)(struct IR_i2c*, u32*, u32*); | 20 | int (*get_key)(struct IR_i2c*, u32*, u32*); |
21 | }; | 21 | }; |
22 | |||
23 | int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw); | ||
22 | #endif | 24 | #endif |
diff --git a/include/media/tuner.h b/include/media/tuner.h index 9184e534b7ef..faa0f8e3091b 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h | |||
@@ -113,6 +113,7 @@ | |||
113 | #define TUNER_PHILIPS_TD1316 67 | 113 | #define TUNER_PHILIPS_TD1316 67 |
114 | 114 | ||
115 | #define TUNER_PHILIPS_TUV1236D 68 /* ATI HDTV Wonder */ | 115 | #define TUNER_PHILIPS_TUV1236D 68 /* ATI HDTV Wonder */ |
116 | #define TUNER_TNF_5335MF 69 /* Sabrent Bt848 */ | ||
116 | 117 | ||
117 | #define NOTUNER 0 | 118 | #define NOTUNER 0 |
118 | #define PAL 1 /* PAL_BG */ | 119 | #define PAL 1 /* PAL_BG */ |
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h new file mode 100644 index 000000000000..d3fd48157eb8 --- /dev/null +++ b/include/media/v4l2-common.h | |||
@@ -0,0 +1,110 @@ | |||
1 | /* | ||
2 | v4l2 common internal API header | ||
3 | |||
4 | This header contains internal shared ioctl definitions for use by the | ||
5 | internal low-level v4l2 drivers. | ||
6 | Each ioctl begins with VIDIOC_INT_ to clearly mark that it is an internal | ||
7 | define, | ||
8 | |||
9 | Copyright (C) 2005 Hans Verkuil <hverkuil@xs4all.nl> | ||
10 | |||
11 | This program is free software; you can redistribute it and/or modify | ||
12 | it under the terms of the GNU General Public License as published by | ||
13 | the Free Software Foundation; either version 2 of the License, or | ||
14 | (at your option) any later version. | ||
15 | |||
16 | This program is distributed in the hope that it will be useful, | ||
17 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | GNU General Public License for more details. | ||
20 | |||
21 | You should have received a copy of the GNU General Public License | ||
22 | along with this program; if not, write to the Free Software | ||
23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
24 | */ | ||
25 | |||
26 | #ifndef V4L2_COMMON_H_ | ||
27 | #define V4L2_COMMON_H_ | ||
28 | |||
29 | /* VIDIOC_INT_AUDIO_CLOCK_FREQ */ | ||
30 | enum v4l2_audio_clock_freq { | ||
31 | V4L2_AUDCLK_32_KHZ = 32000, | ||
32 | V4L2_AUDCLK_441_KHZ = 44100, | ||
33 | V4L2_AUDCLK_48_KHZ = 48000, | ||
34 | }; | ||
35 | |||
36 | /* VIDIOC_INT_G_REGISTER and VIDIOC_INT_S_REGISTER */ | ||
37 | struct v4l2_register { | ||
38 | u32 i2c_id; /* I2C driver ID of the I2C chip. 0 for the I2C adapter. */ | ||
39 | unsigned long reg; | ||
40 | u32 val; | ||
41 | }; | ||
42 | |||
43 | /* VIDIOC_INT_DECODE_VBI_LINE */ | ||
44 | struct v4l2_decode_vbi_line { | ||
45 | u32 is_second_field; /* Set to 0 for the first (odd) field, | ||
46 | set to 1 for the second (even) field. */ | ||
47 | u8 *p; /* Pointer to the sliced VBI data from the decoder. | ||
48 | On exit points to the start of the payload. */ | ||
49 | u32 line; /* Line number of the sliced VBI data (1-23) */ | ||
50 | u32 type; /* VBI service type (V4L2_SLICED_*). 0 if no service found */ | ||
51 | }; | ||
52 | |||
53 | /* VIDIOC_INT_G_CHIP_IDENT: identifies the actual chip installed on the board */ | ||
54 | enum v4l2_chip_ident { | ||
55 | /* general idents: reserved range 0-49 */ | ||
56 | V4L2_IDENT_UNKNOWN = 0, | ||
57 | |||
58 | /* module saa7115: reserved range 100-149 */ | ||
59 | V4L2_IDENT_SAA7114 = 104, | ||
60 | V4L2_IDENT_SAA7115 = 105, | ||
61 | |||
62 | /* module saa7127: reserved range 150-199 */ | ||
63 | V4L2_IDENT_SAA7127 = 157, | ||
64 | V4L2_IDENT_SAA7129 = 159, | ||
65 | |||
66 | /* module cx25840: reserved range 200-249 */ | ||
67 | V4L2_IDENT_CX25840 = 240, | ||
68 | V4L2_IDENT_CX25841 = 241, | ||
69 | V4L2_IDENT_CX25842 = 242, | ||
70 | V4L2_IDENT_CX25843 = 243, | ||
71 | }; | ||
72 | |||
73 | /* only implemented if CONFIG_VIDEO_ADV_DEBUG is defined */ | ||
74 | #define VIDIOC_INT_S_REGISTER _IOR ('d', 100, struct v4l2_register) | ||
75 | #define VIDIOC_INT_G_REGISTER _IOWR('d', 101, struct v4l2_register) | ||
76 | |||
77 | /* Reset the I2C chip */ | ||
78 | #define VIDIOC_INT_RESET _IO ('d', 102) | ||
79 | |||
80 | /* Set the frequency of the audio clock output. | ||
81 | Used to slave an audio processor to the video decoder, ensuring that audio | ||
82 | and video remain synchronized. */ | ||
83 | #define VIDIOC_INT_AUDIO_CLOCK_FREQ _IOR ('d', 103, enum v4l2_audio_clock_freq) | ||
84 | |||
85 | /* Video decoders that support sliced VBI need to implement this ioctl. | ||
86 | Field p of the v4l2_sliced_vbi_line struct is set to the start of the VBI | ||
87 | data that was generated by the decoder. The driver then parses the sliced | ||
88 | VBI data and sets the other fields in the struct accordingly. The pointer p | ||
89 | is updated to point to the start of the payload which can be copied | ||
90 | verbatim into the data field of the v4l2_sliced_vbi_data struct. If no | ||
91 | valid VBI data was found, then the type field is set to 0 on return. */ | ||
92 | #define VIDIOC_INT_DECODE_VBI_LINE _IOWR('d', 104, struct v4l2_decode_vbi_line) | ||
93 | |||
94 | /* Used to generate VBI signals on a video signal. v4l2_sliced_vbi_data is | ||
95 | filled with the data packets that should be output. Note that if you set | ||
96 | the line field to 0, then that VBI signal is disabled. */ | ||
97 | #define VIDIOC_INT_S_VBI_DATA _IOW ('d', 105, struct v4l2_sliced_vbi_data) | ||
98 | |||
99 | /* Used to obtain the sliced VBI packet from a readback register. Not all | ||
100 | video decoders support this. If no data is available because the readback | ||
101 | register contains invalid or erroneous data -EIO is returned. Note that | ||
102 | you must fill in the 'id' member and the 'field' member (to determine | ||
103 | whether CC data from the first or second field should be obtained). */ | ||
104 | #define VIDIOC_INT_G_VBI_DATA _IOWR('d', 106, struct v4l2_sliced_vbi_data *) | ||
105 | |||
106 | /* Returns the chip identifier or V4L2_IDENT_UNKNOWN if no identification can | ||
107 | be made. */ | ||
108 | #define VIDIOC_INT_G_CHIP_IDENT _IOR ('d', 107, enum v4l2_chip_ident *) | ||
109 | |||
110 | #endif /* V4L2_COMMON_H_ */ | ||
diff --git a/include/net/llc_pdu.h b/include/net/llc_pdu.h index c7a959428b4f..8f6306581fa7 100644 --- a/include/net/llc_pdu.h +++ b/include/net/llc_pdu.h | |||
@@ -357,7 +357,7 @@ static inline void llc_pdu_init_as_test_rsp(struct sk_buff *skb, | |||
357 | 357 | ||
358 | /* LLC Type 1 XID command/response information fields format */ | 358 | /* LLC Type 1 XID command/response information fields format */ |
359 | struct llc_xid_info { | 359 | struct llc_xid_info { |
360 | u8 fmt_id; /* always 0x18 for LLC */ | 360 | u8 fmt_id; /* always 0x81 for LLC */ |
361 | u8 type; /* different if NULL/non-NULL LSAP */ | 361 | u8 type; /* different if NULL/non-NULL LSAP */ |
362 | u8 rw; /* sender receive window */ | 362 | u8 rw; /* sender receive window */ |
363 | }; | 363 | }; |
diff --git a/include/net/tcp.h b/include/net/tcp.h index 0f9848011972..d78025f9fbea 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -552,8 +552,8 @@ extern u32 __tcp_select_window(struct sock *sk); | |||
552 | 552 | ||
553 | /* TCP timestamps are only 32-bits, this causes a slight | 553 | /* TCP timestamps are only 32-bits, this causes a slight |
554 | * complication on 64-bit systems since we store a snapshot | 554 | * complication on 64-bit systems since we store a snapshot |
555 | * of jiffies in the buffer control blocks below. We decidedly | 555 | * of jiffies in the buffer control blocks below. We decided |
556 | * only use of the low 32-bits of jiffies and hide the ugly | 556 | * to use only the low 32-bits of jiffies and hide the ugly |
557 | * casts with the following macro. | 557 | * casts with the following macro. |
558 | */ | 558 | */ |
559 | #define tcp_time_stamp ((__u32)(jiffies)) | 559 | #define tcp_time_stamp ((__u32)(jiffies)) |
diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 5a737ed9dac7..7430640f9816 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c | |||
@@ -1809,11 +1809,12 @@ int cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask) | |||
1809 | if (gfp_mask & __GFP_HARDWALL) /* If hardwall request, stop here */ | 1809 | if (gfp_mask & __GFP_HARDWALL) /* If hardwall request, stop here */ |
1810 | return 0; | 1810 | return 0; |
1811 | 1811 | ||
1812 | if (current->flags & PF_EXITING) /* Let dying task have memory */ | ||
1813 | return 1; | ||
1814 | |||
1812 | /* Not hardwall and node outside mems_allowed: scan up cpusets */ | 1815 | /* Not hardwall and node outside mems_allowed: scan up cpusets */ |
1813 | down(&callback_sem); | 1816 | down(&callback_sem); |
1814 | 1817 | ||
1815 | if (current->flags & PF_EXITING) /* Let dying task have memory */ | ||
1816 | return 1; | ||
1817 | task_lock(current); | 1818 | task_lock(current); |
1818 | cs = nearest_exclusive_ancestor(current->cpuset); | 1819 | cs = nearest_exclusive_ancestor(current->cpuset); |
1819 | task_unlock(current); | 1820 | task_unlock(current); |
diff --git a/kernel/exit.c b/kernel/exit.c index 452a1d116178..ee515683b92d 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -859,7 +859,7 @@ fastcall NORET_TYPE void do_exit(long code) | |||
859 | if (group_dead && tsk->signal->leader) | 859 | if (group_dead && tsk->signal->leader) |
860 | disassociate_ctty(1); | 860 | disassociate_ctty(1); |
861 | 861 | ||
862 | module_put(tsk->thread_info->exec_domain->module); | 862 | module_put(task_thread_info(tsk)->exec_domain->module); |
863 | if (tsk->binfmt) | 863 | if (tsk->binfmt) |
864 | module_put(tsk->binfmt->module); | 864 | module_put(tsk->binfmt->module); |
865 | 865 | ||
diff --git a/kernel/fork.c b/kernel/fork.c index 158710d22566..e0d0b77343f8 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -171,10 +171,9 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) | |||
171 | return NULL; | 171 | return NULL; |
172 | } | 172 | } |
173 | 173 | ||
174 | *ti = *orig->thread_info; | ||
175 | *tsk = *orig; | 174 | *tsk = *orig; |
176 | tsk->thread_info = ti; | 175 | tsk->thread_info = ti; |
177 | ti->task = tsk; | 176 | setup_thread_stack(tsk, orig); |
178 | 177 | ||
179 | /* One for us, one for whoever does the "release_task()" (usually parent) */ | 178 | /* One for us, one for whoever does the "release_task()" (usually parent) */ |
180 | atomic_set(&tsk->usage,2); | 179 | atomic_set(&tsk->usage,2); |
@@ -324,7 +323,6 @@ static struct mm_struct * mm_init(struct mm_struct * mm) | |||
324 | spin_lock_init(&mm->page_table_lock); | 323 | spin_lock_init(&mm->page_table_lock); |
325 | rwlock_init(&mm->ioctx_list_lock); | 324 | rwlock_init(&mm->ioctx_list_lock); |
326 | mm->ioctx_list = NULL; | 325 | mm->ioctx_list = NULL; |
327 | mm->default_kioctx = (struct kioctx)INIT_KIOCTX(mm->default_kioctx, *mm); | ||
328 | mm->free_area_cache = TASK_UNMAPPED_BASE; | 326 | mm->free_area_cache = TASK_UNMAPPED_BASE; |
329 | mm->cached_hole_size = ~0UL; | 327 | mm->cached_hole_size = ~0UL; |
330 | 328 | ||
@@ -919,7 +917,7 @@ static task_t *copy_process(unsigned long clone_flags, | |||
919 | if (nr_threads >= max_threads) | 917 | if (nr_threads >= max_threads) |
920 | goto bad_fork_cleanup_count; | 918 | goto bad_fork_cleanup_count; |
921 | 919 | ||
922 | if (!try_module_get(p->thread_info->exec_domain->module)) | 920 | if (!try_module_get(task_thread_info(p)->exec_domain->module)) |
923 | goto bad_fork_cleanup_count; | 921 | goto bad_fork_cleanup_count; |
924 | 922 | ||
925 | if (p->binfmt && !try_module_get(p->binfmt->module)) | 923 | if (p->binfmt && !try_module_get(p->binfmt->module)) |
@@ -1180,7 +1178,7 @@ bad_fork_cleanup: | |||
1180 | if (p->binfmt) | 1178 | if (p->binfmt) |
1181 | module_put(p->binfmt->module); | 1179 | module_put(p->binfmt->module); |
1182 | bad_fork_cleanup_put_domain: | 1180 | bad_fork_cleanup_put_domain: |
1183 | module_put(p->thread_info->exec_domain->module); | 1181 | module_put(task_thread_info(p)->exec_domain->module); |
1184 | bad_fork_cleanup_count: | 1182 | bad_fork_cleanup_count: |
1185 | put_group_info(p->group_info); | 1183 | put_group_info(p->group_info); |
1186 | atomic_dec(&p->user->processes); | 1184 | atomic_dec(&p->user->processes); |
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index ea55c7a1cd75..5870efb3e200 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c | |||
@@ -270,7 +270,7 @@ static void tstojiffie(struct timespec *tp, int res, u64 *jiff) | |||
270 | long sec = tp->tv_sec; | 270 | long sec = tp->tv_sec; |
271 | long nsec = tp->tv_nsec + res - 1; | 271 | long nsec = tp->tv_nsec + res - 1; |
272 | 272 | ||
273 | if (nsec > NSEC_PER_SEC) { | 273 | if (nsec >= NSEC_PER_SEC) { |
274 | sec++; | 274 | sec++; |
275 | nsec -= NSEC_PER_SEC; | 275 | nsec -= NSEC_PER_SEC; |
276 | } | 276 | } |
@@ -1209,13 +1209,9 @@ static int do_posix_clock_monotonic_get(clockid_t clock, struct timespec *tp) | |||
1209 | 1209 | ||
1210 | do_posix_clock_monotonic_gettime_parts(tp, &wall_to_mono); | 1210 | do_posix_clock_monotonic_gettime_parts(tp, &wall_to_mono); |
1211 | 1211 | ||
1212 | tp->tv_sec += wall_to_mono.tv_sec; | 1212 | set_normalized_timespec(tp, tp->tv_sec + wall_to_mono.tv_sec, |
1213 | tp->tv_nsec += wall_to_mono.tv_nsec; | 1213 | tp->tv_nsec + wall_to_mono.tv_nsec); |
1214 | 1214 | ||
1215 | if ((tp->tv_nsec - NSEC_PER_SEC) > 0) { | ||
1216 | tp->tv_nsec -= NSEC_PER_SEC; | ||
1217 | tp->tv_sec++; | ||
1218 | } | ||
1219 | return 0; | 1215 | return 0; |
1220 | } | 1216 | } |
1221 | 1217 | ||
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 46a5e5acff97..5ec248cb7f4a 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig | |||
@@ -19,6 +19,15 @@ config PM | |||
19 | will issue the hlt instruction if nothing is to be done, thereby | 19 | will issue the hlt instruction if nothing is to be done, thereby |
20 | sending the processor to sleep and saving power. | 20 | sending the processor to sleep and saving power. |
21 | 21 | ||
22 | config PM_LEGACY | ||
23 | bool "Legacy Power Management API" | ||
24 | depends on PM | ||
25 | default y | ||
26 | ---help--- | ||
27 | Support for pm_register() and friends. | ||
28 | |||
29 | If unsure, say Y. | ||
30 | |||
22 | config PM_DEBUG | 31 | config PM_DEBUG |
23 | bool "Power Management Debug Support" | 32 | bool "Power Management Debug Support" |
24 | depends on PM | 33 | depends on PM |
diff --git a/kernel/power/Makefile b/kernel/power/Makefile index c71eb4579c07..04be7d0d96a7 100644 --- a/kernel/power/Makefile +++ b/kernel/power/Makefile | |||
@@ -3,7 +3,8 @@ ifeq ($(CONFIG_PM_DEBUG),y) | |||
3 | EXTRA_CFLAGS += -DDEBUG | 3 | EXTRA_CFLAGS += -DDEBUG |
4 | endif | 4 | endif |
5 | 5 | ||
6 | obj-y := main.o process.o console.o pm.o | 6 | obj-y := main.o process.o console.o |
7 | obj-$(CONFIG_PM_LEGACY) += pm.o | ||
7 | obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o disk.o snapshot.o | 8 | obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o disk.o snapshot.o |
8 | 9 | ||
9 | obj-$(CONFIG_SUSPEND_SMP) += smp.o | 10 | obj-$(CONFIG_SUSPEND_SMP) += smp.o |
diff --git a/kernel/power/pm.c b/kernel/power/pm.c index 159149321b3c..33c508e857dd 100644 --- a/kernel/power/pm.c +++ b/kernel/power/pm.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/pm.h> | 25 | #include <linux/pm.h> |
26 | #include <linux/pm_legacy.h> | ||
26 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
27 | 28 | ||
28 | int pm_active; | 29 | int pm_active; |
diff --git a/kernel/printk.c b/kernel/printk.c index e9be027bc930..ac8a08f36207 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
@@ -491,7 +491,10 @@ __attribute__((weak)) unsigned long long printk_clock(void) | |||
491 | return sched_clock(); | 491 | return sched_clock(); |
492 | } | 492 | } |
493 | 493 | ||
494 | /* | 494 | /** |
495 | * printk - print a kernel message | ||
496 | * @fmt: format string | ||
497 | * | ||
495 | * This is printk. It can be called from any context. We want it to work. | 498 | * This is printk. It can be called from any context. We want it to work. |
496 | * | 499 | * |
497 | * We try to grab the console_sem. If we succeed, it's easy - we log the output and | 500 | * We try to grab the console_sem. If we succeed, it's easy - we log the output and |
@@ -503,6 +506,9 @@ __attribute__((weak)) unsigned long long printk_clock(void) | |||
503 | * One effect of this deferred printing is that code which calls printk() and | 506 | * One effect of this deferred printing is that code which calls printk() and |
504 | * then changes console_loglevel may break. This is because console_loglevel | 507 | * then changes console_loglevel may break. This is because console_loglevel |
505 | * is inspected when the actual printing occurs. | 508 | * is inspected when the actual printing occurs. |
509 | * | ||
510 | * See also: | ||
511 | * printf(3) | ||
506 | */ | 512 | */ |
507 | 513 | ||
508 | asmlinkage int printk(const char *fmt, ...) | 514 | asmlinkage int printk(const char *fmt, ...) |
@@ -655,6 +661,9 @@ static void call_console_drivers(unsigned long start, unsigned long end) | |||
655 | 661 | ||
656 | /** | 662 | /** |
657 | * add_preferred_console - add a device to the list of preferred consoles. | 663 | * add_preferred_console - add a device to the list of preferred consoles. |
664 | * @name: device name | ||
665 | * @idx: device index | ||
666 | * @options: options for this console | ||
658 | * | 667 | * |
659 | * The last preferred console added will be used for kernel messages | 668 | * The last preferred console added will be used for kernel messages |
660 | * and stdin/out/err for init. Normally this is used by console_setup | 669 | * and stdin/out/err for init. Normally this is used by console_setup |
@@ -764,7 +773,8 @@ void release_console_sem(void) | |||
764 | } | 773 | } |
765 | EXPORT_SYMBOL(release_console_sem); | 774 | EXPORT_SYMBOL(release_console_sem); |
766 | 775 | ||
767 | /** console_conditional_schedule - yield the CPU if required | 776 | /** |
777 | * console_conditional_schedule - yield the CPU if required | ||
768 | * | 778 | * |
769 | * If the console code is currently allowed to sleep, and | 779 | * If the console code is currently allowed to sleep, and |
770 | * if this CPU should yield the CPU to another task, do | 780 | * if this CPU should yield the CPU to another task, do |
@@ -976,6 +986,8 @@ EXPORT_SYMBOL(unregister_console); | |||
976 | 986 | ||
977 | /** | 987 | /** |
978 | * tty_write_message - write a message to a certain tty, not just the console. | 988 | * tty_write_message - write a message to a certain tty, not just the console. |
989 | * @tty: the destination tty_struct | ||
990 | * @msg: the message to write | ||
979 | * | 991 | * |
980 | * This is used for messages that need to be redirected to a specific tty. | 992 | * This is used for messages that need to be redirected to a specific tty. |
981 | * We don't put it into the syslog queue right now maybe in the future if | 993 | * We don't put it into the syslog queue right now maybe in the future if |
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index b88d4186cd7a..17ee7e5a3451 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
@@ -470,7 +470,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) | |||
470 | 470 | ||
471 | if (request == PTRACE_ATTACH) { | 471 | if (request == PTRACE_ATTACH) { |
472 | ret = ptrace_attach(child); | 472 | ret = ptrace_attach(child); |
473 | goto out; | 473 | goto out_put_task_struct; |
474 | } | 474 | } |
475 | 475 | ||
476 | ret = ptrace_check_attach(child, request == PTRACE_KILL); | 476 | ret = ptrace_check_attach(child, request == PTRACE_KILL); |
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c index 9b58f1eff3ca..eb6719c50b4e 100644 --- a/kernel/rcutorture.c +++ b/kernel/rcutorture.c | |||
@@ -195,6 +195,8 @@ rcu_torture_writer(void *arg) | |||
195 | static DEFINE_RCU_RANDOM(rand); | 195 | static DEFINE_RCU_RANDOM(rand); |
196 | 196 | ||
197 | VERBOSE_PRINTK_STRING("rcu_torture_writer task started"); | 197 | VERBOSE_PRINTK_STRING("rcu_torture_writer task started"); |
198 | set_user_nice(current, 19); | ||
199 | |||
198 | do { | 200 | do { |
199 | schedule_timeout_uninterruptible(1); | 201 | schedule_timeout_uninterruptible(1); |
200 | if (rcu_batches_completed() == oldbatch) | 202 | if (rcu_batches_completed() == oldbatch) |
@@ -238,6 +240,8 @@ rcu_torture_reader(void *arg) | |||
238 | int pipe_count; | 240 | int pipe_count; |
239 | 241 | ||
240 | VERBOSE_PRINTK_STRING("rcu_torture_reader task started"); | 242 | VERBOSE_PRINTK_STRING("rcu_torture_reader task started"); |
243 | set_user_nice(current, 19); | ||
244 | |||
241 | do { | 245 | do { |
242 | rcu_read_lock(); | 246 | rcu_read_lock(); |
243 | completed = rcu_batches_completed(); | 247 | completed = rcu_batches_completed(); |
diff --git a/kernel/sched.c b/kernel/sched.c index b6506671b2be..6f46c94cc29e 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -1437,7 +1437,7 @@ void fastcall sched_fork(task_t *p, int clone_flags) | |||
1437 | #endif | 1437 | #endif |
1438 | #ifdef CONFIG_PREEMPT | 1438 | #ifdef CONFIG_PREEMPT |
1439 | /* Want to start with kernel preemption disabled. */ | 1439 | /* Want to start with kernel preemption disabled. */ |
1440 | p->thread_info->preempt_count = 1; | 1440 | task_thread_info(p)->preempt_count = 1; |
1441 | #endif | 1441 | #endif |
1442 | /* | 1442 | /* |
1443 | * Share the timeslice between parent and child, thus the | 1443 | * Share the timeslice between parent and child, thus the |
@@ -4327,10 +4327,10 @@ static void show_task(task_t *p) | |||
4327 | #endif | 4327 | #endif |
4328 | #ifdef CONFIG_DEBUG_STACK_USAGE | 4328 | #ifdef CONFIG_DEBUG_STACK_USAGE |
4329 | { | 4329 | { |
4330 | unsigned long *n = (unsigned long *) (p->thread_info+1); | 4330 | unsigned long *n = end_of_stack(p); |
4331 | while (!*n) | 4331 | while (!*n) |
4332 | n++; | 4332 | n++; |
4333 | free = (unsigned long) n - (unsigned long)(p->thread_info+1); | 4333 | free = (unsigned long)n - (unsigned long)end_of_stack(p); |
4334 | } | 4334 | } |
4335 | #endif | 4335 | #endif |
4336 | printk("%5lu %5d %6d ", free, p->pid, p->parent->pid); | 4336 | printk("%5lu %5d %6d ", free, p->pid, p->parent->pid); |
@@ -4410,9 +4410,9 @@ void __devinit init_idle(task_t *idle, int cpu) | |||
4410 | 4410 | ||
4411 | /* Set the preempt count _outside_ the spinlocks! */ | 4411 | /* Set the preempt count _outside_ the spinlocks! */ |
4412 | #if defined(CONFIG_PREEMPT) && !defined(CONFIG_PREEMPT_BKL) | 4412 | #if defined(CONFIG_PREEMPT) && !defined(CONFIG_PREEMPT_BKL) |
4413 | idle->thread_info->preempt_count = (idle->lock_depth >= 0); | 4413 | task_thread_info(idle)->preempt_count = (idle->lock_depth >= 0); |
4414 | #else | 4414 | #else |
4415 | idle->thread_info->preempt_count = 0; | 4415 | task_thread_info(idle)->preempt_count = 0; |
4416 | #endif | 4416 | #endif |
4417 | } | 4417 | } |
4418 | 4418 | ||
diff --git a/kernel/signal.c b/kernel/signal.c index 80789a59b4db..d7611f189ef7 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -513,16 +513,7 @@ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask, | |||
513 | { | 513 | { |
514 | int sig = 0; | 514 | int sig = 0; |
515 | 515 | ||
516 | /* SIGKILL must have priority, otherwise it is quite easy | 516 | sig = next_signal(pending, mask); |
517 | * to create an unkillable process, sending sig < SIGKILL | ||
518 | * to self */ | ||
519 | if (unlikely(sigismember(&pending->signal, SIGKILL))) { | ||
520 | if (!sigismember(mask, SIGKILL)) | ||
521 | sig = SIGKILL; | ||
522 | } | ||
523 | |||
524 | if (likely(!sig)) | ||
525 | sig = next_signal(pending, mask); | ||
526 | if (sig) { | 517 | if (sig) { |
527 | if (current->notifier) { | 518 | if (current->notifier) { |
528 | if (sigismember(current->notifier_mask, sig)) { | 519 | if (sigismember(current->notifier_mask, sig)) { |
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index 84a9d18aa8da..b3d4dc858e35 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c | |||
@@ -119,13 +119,12 @@ static int stop_machine(void) | |||
119 | return ret; | 119 | return ret; |
120 | } | 120 | } |
121 | 121 | ||
122 | /* Don't schedule us away at this point, please. */ | ||
123 | local_irq_disable(); | ||
124 | |||
125 | /* Now they are all started, make them hold the CPUs, ready. */ | 122 | /* Now they are all started, make them hold the CPUs, ready. */ |
123 | preempt_disable(); | ||
126 | stopmachine_set_state(STOPMACHINE_PREPARE); | 124 | stopmachine_set_state(STOPMACHINE_PREPARE); |
127 | 125 | ||
128 | /* Make them disable irqs. */ | 126 | /* Make them disable irqs. */ |
127 | local_irq_disable(); | ||
129 | stopmachine_set_state(STOPMACHINE_DISABLE_IRQ); | 128 | stopmachine_set_state(STOPMACHINE_DISABLE_IRQ); |
130 | 129 | ||
131 | return 0; | 130 | return 0; |
@@ -135,6 +134,7 @@ static void restart_machine(void) | |||
135 | { | 134 | { |
136 | stopmachine_set_state(STOPMACHINE_EXIT); | 135 | stopmachine_set_state(STOPMACHINE_EXIT); |
137 | local_irq_enable(); | 136 | local_irq_enable(); |
137 | preempt_enable_no_resched(); | ||
138 | } | 138 | } |
139 | 139 | ||
140 | struct stop_machine_data | 140 | struct stop_machine_data |
diff --git a/mm/filemap.c b/mm/filemap.c index 5d6e4c2000dc..33a28bfde158 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -134,7 +134,7 @@ static int sync_page(void *word) | |||
134 | struct address_space *mapping; | 134 | struct address_space *mapping; |
135 | struct page *page; | 135 | struct page *page; |
136 | 136 | ||
137 | page = container_of((page_flags_t *)word, struct page, flags); | 137 | page = container_of((unsigned long *)word, struct page, flags); |
138 | 138 | ||
139 | /* | 139 | /* |
140 | * page_mapping() is being called without PG_locked held. | 140 | * page_mapping() is being called without PG_locked held. |
diff --git a/mm/memory.c b/mm/memory.c index 0f60baf6f69b..2998cfc12f5b 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -549,10 +549,10 @@ int copy_page_range(struct mm_struct *dst_mm, struct mm_struct *src_mm, | |||
549 | return 0; | 549 | return 0; |
550 | } | 550 | } |
551 | 551 | ||
552 | static void zap_pte_range(struct mmu_gather *tlb, | 552 | static unsigned long zap_pte_range(struct mmu_gather *tlb, |
553 | struct vm_area_struct *vma, pmd_t *pmd, | 553 | struct vm_area_struct *vma, pmd_t *pmd, |
554 | unsigned long addr, unsigned long end, | 554 | unsigned long addr, unsigned long end, |
555 | struct zap_details *details) | 555 | long *zap_work, struct zap_details *details) |
556 | { | 556 | { |
557 | struct mm_struct *mm = tlb->mm; | 557 | struct mm_struct *mm = tlb->mm; |
558 | pte_t *pte; | 558 | pte_t *pte; |
@@ -563,10 +563,15 @@ static void zap_pte_range(struct mmu_gather *tlb, | |||
563 | pte = pte_offset_map_lock(mm, pmd, addr, &ptl); | 563 | pte = pte_offset_map_lock(mm, pmd, addr, &ptl); |
564 | do { | 564 | do { |
565 | pte_t ptent = *pte; | 565 | pte_t ptent = *pte; |
566 | if (pte_none(ptent)) | 566 | if (pte_none(ptent)) { |
567 | (*zap_work)--; | ||
567 | continue; | 568 | continue; |
569 | } | ||
568 | if (pte_present(ptent)) { | 570 | if (pte_present(ptent)) { |
569 | struct page *page = NULL; | 571 | struct page *page = NULL; |
572 | |||
573 | (*zap_work) -= PAGE_SIZE; | ||
574 | |||
570 | if (!(vma->vm_flags & VM_RESERVED)) { | 575 | if (!(vma->vm_flags & VM_RESERVED)) { |
571 | unsigned long pfn = pte_pfn(ptent); | 576 | unsigned long pfn = pte_pfn(ptent); |
572 | if (unlikely(!pfn_valid(pfn))) | 577 | if (unlikely(!pfn_valid(pfn))) |
@@ -624,16 +629,18 @@ static void zap_pte_range(struct mmu_gather *tlb, | |||
624 | if (!pte_file(ptent)) | 629 | if (!pte_file(ptent)) |
625 | free_swap_and_cache(pte_to_swp_entry(ptent)); | 630 | free_swap_and_cache(pte_to_swp_entry(ptent)); |
626 | pte_clear_full(mm, addr, pte, tlb->fullmm); | 631 | pte_clear_full(mm, addr, pte, tlb->fullmm); |
627 | } while (pte++, addr += PAGE_SIZE, addr != end); | 632 | } while (pte++, addr += PAGE_SIZE, (addr != end && *zap_work > 0)); |
628 | 633 | ||
629 | add_mm_rss(mm, file_rss, anon_rss); | 634 | add_mm_rss(mm, file_rss, anon_rss); |
630 | pte_unmap_unlock(pte - 1, ptl); | 635 | pte_unmap_unlock(pte - 1, ptl); |
636 | |||
637 | return addr; | ||
631 | } | 638 | } |
632 | 639 | ||
633 | static inline void zap_pmd_range(struct mmu_gather *tlb, | 640 | static inline unsigned long zap_pmd_range(struct mmu_gather *tlb, |
634 | struct vm_area_struct *vma, pud_t *pud, | 641 | struct vm_area_struct *vma, pud_t *pud, |
635 | unsigned long addr, unsigned long end, | 642 | unsigned long addr, unsigned long end, |
636 | struct zap_details *details) | 643 | long *zap_work, struct zap_details *details) |
637 | { | 644 | { |
638 | pmd_t *pmd; | 645 | pmd_t *pmd; |
639 | unsigned long next; | 646 | unsigned long next; |
@@ -641,16 +648,21 @@ static inline void zap_pmd_range(struct mmu_gather *tlb, | |||
641 | pmd = pmd_offset(pud, addr); | 648 | pmd = pmd_offset(pud, addr); |
642 | do { | 649 | do { |
643 | next = pmd_addr_end(addr, end); | 650 | next = pmd_addr_end(addr, end); |
644 | if (pmd_none_or_clear_bad(pmd)) | 651 | if (pmd_none_or_clear_bad(pmd)) { |
652 | (*zap_work)--; | ||
645 | continue; | 653 | continue; |
646 | zap_pte_range(tlb, vma, pmd, addr, next, details); | 654 | } |
647 | } while (pmd++, addr = next, addr != end); | 655 | next = zap_pte_range(tlb, vma, pmd, addr, next, |
656 | zap_work, details); | ||
657 | } while (pmd++, addr = next, (addr != end && *zap_work > 0)); | ||
658 | |||
659 | return addr; | ||
648 | } | 660 | } |
649 | 661 | ||
650 | static inline void zap_pud_range(struct mmu_gather *tlb, | 662 | static inline unsigned long zap_pud_range(struct mmu_gather *tlb, |
651 | struct vm_area_struct *vma, pgd_t *pgd, | 663 | struct vm_area_struct *vma, pgd_t *pgd, |
652 | unsigned long addr, unsigned long end, | 664 | unsigned long addr, unsigned long end, |
653 | struct zap_details *details) | 665 | long *zap_work, struct zap_details *details) |
654 | { | 666 | { |
655 | pud_t *pud; | 667 | pud_t *pud; |
656 | unsigned long next; | 668 | unsigned long next; |
@@ -658,15 +670,21 @@ static inline void zap_pud_range(struct mmu_gather *tlb, | |||
658 | pud = pud_offset(pgd, addr); | 670 | pud = pud_offset(pgd, addr); |
659 | do { | 671 | do { |
660 | next = pud_addr_end(addr, end); | 672 | next = pud_addr_end(addr, end); |
661 | if (pud_none_or_clear_bad(pud)) | 673 | if (pud_none_or_clear_bad(pud)) { |
674 | (*zap_work)--; | ||
662 | continue; | 675 | continue; |
663 | zap_pmd_range(tlb, vma, pud, addr, next, details); | 676 | } |
664 | } while (pud++, addr = next, addr != end); | 677 | next = zap_pmd_range(tlb, vma, pud, addr, next, |
678 | zap_work, details); | ||
679 | } while (pud++, addr = next, (addr != end && *zap_work > 0)); | ||
680 | |||
681 | return addr; | ||
665 | } | 682 | } |
666 | 683 | ||
667 | static void unmap_page_range(struct mmu_gather *tlb, struct vm_area_struct *vma, | 684 | static unsigned long unmap_page_range(struct mmu_gather *tlb, |
685 | struct vm_area_struct *vma, | ||
668 | unsigned long addr, unsigned long end, | 686 | unsigned long addr, unsigned long end, |
669 | struct zap_details *details) | 687 | long *zap_work, struct zap_details *details) |
670 | { | 688 | { |
671 | pgd_t *pgd; | 689 | pgd_t *pgd; |
672 | unsigned long next; | 690 | unsigned long next; |
@@ -679,11 +697,16 @@ static void unmap_page_range(struct mmu_gather *tlb, struct vm_area_struct *vma, | |||
679 | pgd = pgd_offset(vma->vm_mm, addr); | 697 | pgd = pgd_offset(vma->vm_mm, addr); |
680 | do { | 698 | do { |
681 | next = pgd_addr_end(addr, end); | 699 | next = pgd_addr_end(addr, end); |
682 | if (pgd_none_or_clear_bad(pgd)) | 700 | if (pgd_none_or_clear_bad(pgd)) { |
701 | (*zap_work)--; | ||
683 | continue; | 702 | continue; |
684 | zap_pud_range(tlb, vma, pgd, addr, next, details); | 703 | } |
685 | } while (pgd++, addr = next, addr != end); | 704 | next = zap_pud_range(tlb, vma, pgd, addr, next, |
705 | zap_work, details); | ||
706 | } while (pgd++, addr = next, (addr != end && *zap_work > 0)); | ||
686 | tlb_end_vma(tlb, vma); | 707 | tlb_end_vma(tlb, vma); |
708 | |||
709 | return addr; | ||
687 | } | 710 | } |
688 | 711 | ||
689 | #ifdef CONFIG_PREEMPT | 712 | #ifdef CONFIG_PREEMPT |
@@ -724,7 +747,7 @@ unsigned long unmap_vmas(struct mmu_gather **tlbp, | |||
724 | unsigned long end_addr, unsigned long *nr_accounted, | 747 | unsigned long end_addr, unsigned long *nr_accounted, |
725 | struct zap_details *details) | 748 | struct zap_details *details) |
726 | { | 749 | { |
727 | unsigned long zap_bytes = ZAP_BLOCK_SIZE; | 750 | long zap_work = ZAP_BLOCK_SIZE; |
728 | unsigned long tlb_start = 0; /* For tlb_finish_mmu */ | 751 | unsigned long tlb_start = 0; /* For tlb_finish_mmu */ |
729 | int tlb_start_valid = 0; | 752 | int tlb_start_valid = 0; |
730 | unsigned long start = start_addr; | 753 | unsigned long start = start_addr; |
@@ -745,27 +768,25 @@ unsigned long unmap_vmas(struct mmu_gather **tlbp, | |||
745 | *nr_accounted += (end - start) >> PAGE_SHIFT; | 768 | *nr_accounted += (end - start) >> PAGE_SHIFT; |
746 | 769 | ||
747 | while (start != end) { | 770 | while (start != end) { |
748 | unsigned long block; | ||
749 | |||
750 | if (!tlb_start_valid) { | 771 | if (!tlb_start_valid) { |
751 | tlb_start = start; | 772 | tlb_start = start; |
752 | tlb_start_valid = 1; | 773 | tlb_start_valid = 1; |
753 | } | 774 | } |
754 | 775 | ||
755 | if (is_vm_hugetlb_page(vma)) { | 776 | if (unlikely(is_vm_hugetlb_page(vma))) { |
756 | block = end - start; | ||
757 | unmap_hugepage_range(vma, start, end); | 777 | unmap_hugepage_range(vma, start, end); |
758 | } else { | 778 | zap_work -= (end - start) / |
759 | block = min(zap_bytes, end - start); | 779 | (HPAGE_SIZE / PAGE_SIZE); |
760 | unmap_page_range(*tlbp, vma, start, | 780 | start = end; |
761 | start + block, details); | 781 | } else |
782 | start = unmap_page_range(*tlbp, vma, | ||
783 | start, end, &zap_work, details); | ||
784 | |||
785 | if (zap_work > 0) { | ||
786 | BUG_ON(start != end); | ||
787 | break; | ||
762 | } | 788 | } |
763 | 789 | ||
764 | start += block; | ||
765 | zap_bytes -= block; | ||
766 | if ((long)zap_bytes > 0) | ||
767 | continue; | ||
768 | |||
769 | tlb_finish_mmu(*tlbp, tlb_start, start); | 790 | tlb_finish_mmu(*tlbp, tlb_start, start); |
770 | 791 | ||
771 | if (need_resched() || | 792 | if (need_resched() || |
@@ -779,7 +800,7 @@ unsigned long unmap_vmas(struct mmu_gather **tlbp, | |||
779 | 800 | ||
780 | *tlbp = tlb_gather_mmu(vma->vm_mm, fullmm); | 801 | *tlbp = tlb_gather_mmu(vma->vm_mm, fullmm); |
781 | tlb_start_valid = 0; | 802 | tlb_start_valid = 0; |
782 | zap_bytes = ZAP_BLOCK_SIZE; | 803 | zap_work = ZAP_BLOCK_SIZE; |
783 | } | 804 | } |
784 | } | 805 | } |
785 | out: | 806 | out: |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 987225bdd661..104e69ca55e0 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -60,8 +60,11 @@ long nr_swap_pages; | |||
60 | * NORMAL allocation will leave 784M/256 of ram reserved in the ZONE_DMA | 60 | * NORMAL allocation will leave 784M/256 of ram reserved in the ZONE_DMA |
61 | * HIGHMEM allocation will leave 224M/32 of ram reserved in ZONE_NORMAL | 61 | * HIGHMEM allocation will leave 224M/32 of ram reserved in ZONE_NORMAL |
62 | * HIGHMEM allocation will (224M+784M)/256 of ram reserved in ZONE_DMA | 62 | * HIGHMEM allocation will (224M+784M)/256 of ram reserved in ZONE_DMA |
63 | * | ||
64 | * TBD: should special case ZONE_DMA32 machines here - in those we normally | ||
65 | * don't need any ZONE_NORMAL reservation | ||
63 | */ | 66 | */ |
64 | int sysctl_lowmem_reserve_ratio[MAX_NR_ZONES-1] = { 256, 32 }; | 67 | int sysctl_lowmem_reserve_ratio[MAX_NR_ZONES-1] = { 256, 256, 32 }; |
65 | 68 | ||
66 | EXPORT_SYMBOL(totalram_pages); | 69 | EXPORT_SYMBOL(totalram_pages); |
67 | 70 | ||
@@ -72,7 +75,7 @@ EXPORT_SYMBOL(totalram_pages); | |||
72 | struct zone *zone_table[1 << ZONETABLE_SHIFT] __read_mostly; | 75 | struct zone *zone_table[1 << ZONETABLE_SHIFT] __read_mostly; |
73 | EXPORT_SYMBOL(zone_table); | 76 | EXPORT_SYMBOL(zone_table); |
74 | 77 | ||
75 | static char *zone_names[MAX_NR_ZONES] = { "DMA", "Normal", "HighMem" }; | 78 | static char *zone_names[MAX_NR_ZONES] = { "DMA", "DMA32", "Normal", "HighMem" }; |
76 | int min_free_kbytes = 1024; | 79 | int min_free_kbytes = 1024; |
77 | 80 | ||
78 | unsigned long __initdata nr_kernel_pages; | 81 | unsigned long __initdata nr_kernel_pages; |
@@ -124,7 +127,7 @@ static void bad_page(const char *function, struct page *page) | |||
124 | printk(KERN_EMERG "Bad page state at %s (in process '%s', page %p)\n", | 127 | printk(KERN_EMERG "Bad page state at %s (in process '%s', page %p)\n", |
125 | function, current->comm, page); | 128 | function, current->comm, page); |
126 | printk(KERN_EMERG "flags:0x%0*lx mapping:%p mapcount:%d count:%d\n", | 129 | printk(KERN_EMERG "flags:0x%0*lx mapping:%p mapcount:%d count:%d\n", |
127 | (int)(2*sizeof(page_flags_t)), (unsigned long)page->flags, | 130 | (int)(2*sizeof(unsigned long)), (unsigned long)page->flags, |
128 | page->mapping, page_mapcount(page), page_count(page)); | 131 | page->mapping, page_mapcount(page), page_count(page)); |
129 | printk(KERN_EMERG "Backtrace:\n"); | 132 | printk(KERN_EMERG "Backtrace:\n"); |
130 | dump_stack(); | 133 | dump_stack(); |
@@ -732,9 +735,7 @@ buffered_rmqueue(struct zone *zone, int order, gfp_t gfp_flags) | |||
732 | } | 735 | } |
733 | local_irq_restore(flags); | 736 | local_irq_restore(flags); |
734 | put_cpu(); | 737 | put_cpu(); |
735 | } | 738 | } else { |
736 | |||
737 | if (page == NULL) { | ||
738 | spin_lock_irqsave(&zone->lock, flags); | 739 | spin_lock_irqsave(&zone->lock, flags); |
739 | page = __rmqueue(zone, order); | 740 | page = __rmqueue(zone, order); |
740 | spin_unlock_irqrestore(&zone->lock, flags); | 741 | spin_unlock_irqrestore(&zone->lock, flags); |
@@ -754,20 +755,25 @@ buffered_rmqueue(struct zone *zone, int order, gfp_t gfp_flags) | |||
754 | return page; | 755 | return page; |
755 | } | 756 | } |
756 | 757 | ||
758 | #define ALLOC_NO_WATERMARKS 0x01 /* don't check watermarks at all */ | ||
759 | #define ALLOC_HARDER 0x02 /* try to alloc harder */ | ||
760 | #define ALLOC_HIGH 0x04 /* __GFP_HIGH set */ | ||
761 | #define ALLOC_CPUSET 0x08 /* check for correct cpuset */ | ||
762 | |||
757 | /* | 763 | /* |
758 | * Return 1 if free pages are above 'mark'. This takes into account the order | 764 | * Return 1 if free pages are above 'mark'. This takes into account the order |
759 | * of the allocation. | 765 | * of the allocation. |
760 | */ | 766 | */ |
761 | int zone_watermark_ok(struct zone *z, int order, unsigned long mark, | 767 | int zone_watermark_ok(struct zone *z, int order, unsigned long mark, |
762 | int classzone_idx, int can_try_harder, gfp_t gfp_high) | 768 | int classzone_idx, int alloc_flags) |
763 | { | 769 | { |
764 | /* free_pages my go negative - that's OK */ | 770 | /* free_pages my go negative - that's OK */ |
765 | long min = mark, free_pages = z->free_pages - (1 << order) + 1; | 771 | long min = mark, free_pages = z->free_pages - (1 << order) + 1; |
766 | int o; | 772 | int o; |
767 | 773 | ||
768 | if (gfp_high) | 774 | if (alloc_flags & ALLOC_HIGH) |
769 | min -= min / 2; | 775 | min -= min / 2; |
770 | if (can_try_harder) | 776 | if (alloc_flags & ALLOC_HARDER) |
771 | min -= min / 4; | 777 | min -= min / 4; |
772 | 778 | ||
773 | if (free_pages <= min + z->lowmem_reserve[classzone_idx]) | 779 | if (free_pages <= min + z->lowmem_reserve[classzone_idx]) |
@@ -785,14 +791,40 @@ int zone_watermark_ok(struct zone *z, int order, unsigned long mark, | |||
785 | return 1; | 791 | return 1; |
786 | } | 792 | } |
787 | 793 | ||
788 | static inline int | 794 | /* |
789 | should_reclaim_zone(struct zone *z, gfp_t gfp_mask) | 795 | * get_page_from_freeliest goes through the zonelist trying to allocate |
796 | * a page. | ||
797 | */ | ||
798 | static struct page * | ||
799 | get_page_from_freelist(gfp_t gfp_mask, unsigned int order, | ||
800 | struct zonelist *zonelist, int alloc_flags) | ||
790 | { | 801 | { |
791 | if (!z->reclaim_pages) | 802 | struct zone **z = zonelist->zones; |
792 | return 0; | 803 | struct page *page = NULL; |
793 | if (gfp_mask & __GFP_NORECLAIM) | 804 | int classzone_idx = zone_idx(*z); |
794 | return 0; | 805 | |
795 | return 1; | 806 | /* |
807 | * Go through the zonelist once, looking for a zone with enough free. | ||
808 | * See also cpuset_zone_allowed() comment in kernel/cpuset.c. | ||
809 | */ | ||
810 | do { | ||
811 | if ((alloc_flags & ALLOC_CPUSET) && | ||
812 | !cpuset_zone_allowed(*z, gfp_mask)) | ||
813 | continue; | ||
814 | |||
815 | if (!(alloc_flags & ALLOC_NO_WATERMARKS)) { | ||
816 | if (!zone_watermark_ok(*z, order, (*z)->pages_low, | ||
817 | classzone_idx, alloc_flags)) | ||
818 | continue; | ||
819 | } | ||
820 | |||
821 | page = buffered_rmqueue(*z, order, gfp_mask); | ||
822 | if (page) { | ||
823 | zone_statistics(zonelist, *z); | ||
824 | break; | ||
825 | } | ||
826 | } while (*(++z) != NULL); | ||
827 | return page; | ||
796 | } | 828 | } |
797 | 829 | ||
798 | /* | 830 | /* |
@@ -803,105 +835,75 @@ __alloc_pages(gfp_t gfp_mask, unsigned int order, | |||
803 | struct zonelist *zonelist) | 835 | struct zonelist *zonelist) |
804 | { | 836 | { |
805 | const gfp_t wait = gfp_mask & __GFP_WAIT; | 837 | const gfp_t wait = gfp_mask & __GFP_WAIT; |
806 | struct zone **zones, *z; | 838 | struct zone **z; |
807 | struct page *page; | 839 | struct page *page; |
808 | struct reclaim_state reclaim_state; | 840 | struct reclaim_state reclaim_state; |
809 | struct task_struct *p = current; | 841 | struct task_struct *p = current; |
810 | int i; | ||
811 | int classzone_idx; | ||
812 | int do_retry; | 842 | int do_retry; |
813 | int can_try_harder; | 843 | int alloc_flags; |
814 | int did_some_progress; | 844 | int did_some_progress; |
815 | 845 | ||
816 | might_sleep_if(wait); | 846 | might_sleep_if(wait); |
817 | 847 | ||
818 | /* | 848 | z = zonelist->zones; /* the list of zones suitable for gfp_mask */ |
819 | * The caller may dip into page reserves a bit more if the caller | ||
820 | * cannot run direct reclaim, or is the caller has realtime scheduling | ||
821 | * policy | ||
822 | */ | ||
823 | can_try_harder = (unlikely(rt_task(p)) && !in_interrupt()) || !wait; | ||
824 | |||
825 | zones = zonelist->zones; /* the list of zones suitable for gfp_mask */ | ||
826 | 849 | ||
827 | if (unlikely(zones[0] == NULL)) { | 850 | if (unlikely(*z == NULL)) { |
828 | /* Should this ever happen?? */ | 851 | /* Should this ever happen?? */ |
829 | return NULL; | 852 | return NULL; |
830 | } | 853 | } |
854 | restart: | ||
855 | page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, order, | ||
856 | zonelist, ALLOC_CPUSET); | ||
857 | if (page) | ||
858 | goto got_pg; | ||
831 | 859 | ||
832 | classzone_idx = zone_idx(zones[0]); | 860 | do |
861 | wakeup_kswapd(*z, order); | ||
862 | while (*(++z)); | ||
833 | 863 | ||
834 | restart: | ||
835 | /* | 864 | /* |
836 | * Go through the zonelist once, looking for a zone with enough free. | 865 | * OK, we're below the kswapd watermark and have kicked background |
837 | * See also cpuset_zone_allowed() comment in kernel/cpuset.c. | 866 | * reclaim. Now things get more complex, so set up alloc_flags according |
867 | * to how we want to proceed. | ||
868 | * | ||
869 | * The caller may dip into page reserves a bit more if the caller | ||
870 | * cannot run direct reclaim, or if the caller has realtime scheduling | ||
871 | * policy. | ||
838 | */ | 872 | */ |
839 | for (i = 0; (z = zones[i]) != NULL; i++) { | 873 | alloc_flags = 0; |
840 | int do_reclaim = should_reclaim_zone(z, gfp_mask); | 874 | if ((unlikely(rt_task(p)) && !in_interrupt()) || !wait) |
841 | 875 | alloc_flags |= ALLOC_HARDER; | |
842 | if (!cpuset_zone_allowed(z, __GFP_HARDWALL)) | 876 | if (gfp_mask & __GFP_HIGH) |
843 | continue; | 877 | alloc_flags |= ALLOC_HIGH; |
844 | 878 | if (wait) | |
845 | /* | 879 | alloc_flags |= ALLOC_CPUSET; |
846 | * If the zone is to attempt early page reclaim then this loop | ||
847 | * will try to reclaim pages and check the watermark a second | ||
848 | * time before giving up and falling back to the next zone. | ||
849 | */ | ||
850 | zone_reclaim_retry: | ||
851 | if (!zone_watermark_ok(z, order, z->pages_low, | ||
852 | classzone_idx, 0, 0)) { | ||
853 | if (!do_reclaim) | ||
854 | continue; | ||
855 | else { | ||
856 | zone_reclaim(z, gfp_mask, order); | ||
857 | /* Only try reclaim once */ | ||
858 | do_reclaim = 0; | ||
859 | goto zone_reclaim_retry; | ||
860 | } | ||
861 | } | ||
862 | |||
863 | page = buffered_rmqueue(z, order, gfp_mask); | ||
864 | if (page) | ||
865 | goto got_pg; | ||
866 | } | ||
867 | |||
868 | for (i = 0; (z = zones[i]) != NULL; i++) | ||
869 | wakeup_kswapd(z, order); | ||
870 | 880 | ||
871 | /* | 881 | /* |
872 | * Go through the zonelist again. Let __GFP_HIGH and allocations | 882 | * Go through the zonelist again. Let __GFP_HIGH and allocations |
873 | * coming from realtime tasks to go deeper into reserves | 883 | * coming from realtime tasks go deeper into reserves. |
874 | * | 884 | * |
875 | * This is the last chance, in general, before the goto nopage. | 885 | * This is the last chance, in general, before the goto nopage. |
876 | * Ignore cpuset if GFP_ATOMIC (!wait) rather than fail alloc. | 886 | * Ignore cpuset if GFP_ATOMIC (!wait) rather than fail alloc. |
877 | * See also cpuset_zone_allowed() comment in kernel/cpuset.c. | 887 | * See also cpuset_zone_allowed() comment in kernel/cpuset.c. |
878 | */ | 888 | */ |
879 | for (i = 0; (z = zones[i]) != NULL; i++) { | 889 | page = get_page_from_freelist(gfp_mask, order, zonelist, alloc_flags); |
880 | if (!zone_watermark_ok(z, order, z->pages_min, | 890 | if (page) |
881 | classzone_idx, can_try_harder, | 891 | goto got_pg; |
882 | gfp_mask & __GFP_HIGH)) | ||
883 | continue; | ||
884 | |||
885 | if (wait && !cpuset_zone_allowed(z, gfp_mask)) | ||
886 | continue; | ||
887 | |||
888 | page = buffered_rmqueue(z, order, gfp_mask); | ||
889 | if (page) | ||
890 | goto got_pg; | ||
891 | } | ||
892 | 892 | ||
893 | /* This allocation should allow future memory freeing. */ | 893 | /* This allocation should allow future memory freeing. */ |
894 | 894 | ||
895 | if (((p->flags & PF_MEMALLOC) || unlikely(test_thread_flag(TIF_MEMDIE))) | 895 | if (((p->flags & PF_MEMALLOC) || unlikely(test_thread_flag(TIF_MEMDIE))) |
896 | && !in_interrupt()) { | 896 | && !in_interrupt()) { |
897 | if (!(gfp_mask & __GFP_NOMEMALLOC)) { | 897 | if (!(gfp_mask & __GFP_NOMEMALLOC)) { |
898 | nofail_alloc: | ||
898 | /* go through the zonelist yet again, ignoring mins */ | 899 | /* go through the zonelist yet again, ignoring mins */ |
899 | for (i = 0; (z = zones[i]) != NULL; i++) { | 900 | page = get_page_from_freelist(gfp_mask, order, |
900 | if (!cpuset_zone_allowed(z, gfp_mask)) | 901 | zonelist, ALLOC_NO_WATERMARKS|ALLOC_CPUSET); |
901 | continue; | 902 | if (page) |
902 | page = buffered_rmqueue(z, order, gfp_mask); | 903 | goto got_pg; |
903 | if (page) | 904 | if (gfp_mask & __GFP_NOFAIL) { |
904 | goto got_pg; | 905 | blk_congestion_wait(WRITE, HZ/50); |
906 | goto nofail_alloc; | ||
905 | } | 907 | } |
906 | } | 908 | } |
907 | goto nopage; | 909 | goto nopage; |
@@ -919,7 +921,7 @@ rebalance: | |||
919 | reclaim_state.reclaimed_slab = 0; | 921 | reclaim_state.reclaimed_slab = 0; |
920 | p->reclaim_state = &reclaim_state; | 922 | p->reclaim_state = &reclaim_state; |
921 | 923 | ||
922 | did_some_progress = try_to_free_pages(zones, gfp_mask); | 924 | did_some_progress = try_to_free_pages(zonelist->zones, gfp_mask); |
923 | 925 | ||
924 | p->reclaim_state = NULL; | 926 | p->reclaim_state = NULL; |
925 | p->flags &= ~PF_MEMALLOC; | 927 | p->flags &= ~PF_MEMALLOC; |
@@ -927,19 +929,10 @@ rebalance: | |||
927 | cond_resched(); | 929 | cond_resched(); |
928 | 930 | ||
929 | if (likely(did_some_progress)) { | 931 | if (likely(did_some_progress)) { |
930 | for (i = 0; (z = zones[i]) != NULL; i++) { | 932 | page = get_page_from_freelist(gfp_mask, order, |
931 | if (!zone_watermark_ok(z, order, z->pages_min, | 933 | zonelist, alloc_flags); |
932 | classzone_idx, can_try_harder, | 934 | if (page) |
933 | gfp_mask & __GFP_HIGH)) | 935 | goto got_pg; |
934 | continue; | ||
935 | |||
936 | if (!cpuset_zone_allowed(z, gfp_mask)) | ||
937 | continue; | ||
938 | |||
939 | page = buffered_rmqueue(z, order, gfp_mask); | ||
940 | if (page) | ||
941 | goto got_pg; | ||
942 | } | ||
943 | } else if ((gfp_mask & __GFP_FS) && !(gfp_mask & __GFP_NORETRY)) { | 936 | } else if ((gfp_mask & __GFP_FS) && !(gfp_mask & __GFP_NORETRY)) { |
944 | /* | 937 | /* |
945 | * Go through the zonelist yet one more time, keep | 938 | * Go through the zonelist yet one more time, keep |
@@ -947,18 +940,10 @@ rebalance: | |||
947 | * a parallel oom killing, we must fail if we're still | 940 | * a parallel oom killing, we must fail if we're still |
948 | * under heavy pressure. | 941 | * under heavy pressure. |
949 | */ | 942 | */ |
950 | for (i = 0; (z = zones[i]) != NULL; i++) { | 943 | page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, order, |
951 | if (!zone_watermark_ok(z, order, z->pages_high, | 944 | zonelist, ALLOC_CPUSET); |
952 | classzone_idx, 0, 0)) | 945 | if (page) |
953 | continue; | 946 | goto got_pg; |
954 | |||
955 | if (!cpuset_zone_allowed(z, __GFP_HARDWALL)) | ||
956 | continue; | ||
957 | |||
958 | page = buffered_rmqueue(z, order, gfp_mask); | ||
959 | if (page) | ||
960 | goto got_pg; | ||
961 | } | ||
962 | 947 | ||
963 | out_of_memory(gfp_mask, order); | 948 | out_of_memory(gfp_mask, order); |
964 | goto restart; | 949 | goto restart; |
@@ -991,9 +976,7 @@ nopage: | |||
991 | dump_stack(); | 976 | dump_stack(); |
992 | show_mem(); | 977 | show_mem(); |
993 | } | 978 | } |
994 | return NULL; | ||
995 | got_pg: | 979 | got_pg: |
996 | zone_statistics(zonelist, z); | ||
997 | return page; | 980 | return page; |
998 | } | 981 | } |
999 | 982 | ||
@@ -1441,6 +1424,10 @@ static int __init build_zonelists_node(pg_data_t *pgdat, struct zonelist *zoneli | |||
1441 | zone = pgdat->node_zones + ZONE_NORMAL; | 1424 | zone = pgdat->node_zones + ZONE_NORMAL; |
1442 | if (zone->present_pages) | 1425 | if (zone->present_pages) |
1443 | zonelist->zones[j++] = zone; | 1426 | zonelist->zones[j++] = zone; |
1427 | case ZONE_DMA32: | ||
1428 | zone = pgdat->node_zones + ZONE_DMA32; | ||
1429 | if (zone->present_pages) | ||
1430 | zonelist->zones[j++] = zone; | ||
1444 | case ZONE_DMA: | 1431 | case ZONE_DMA: |
1445 | zone = pgdat->node_zones + ZONE_DMA; | 1432 | zone = pgdat->node_zones + ZONE_DMA; |
1446 | if (zone->present_pages) | 1433 | if (zone->present_pages) |
@@ -1455,6 +1442,8 @@ static inline int highest_zone(int zone_bits) | |||
1455 | int res = ZONE_NORMAL; | 1442 | int res = ZONE_NORMAL; |
1456 | if (zone_bits & (__force int)__GFP_HIGHMEM) | 1443 | if (zone_bits & (__force int)__GFP_HIGHMEM) |
1457 | res = ZONE_HIGHMEM; | 1444 | res = ZONE_HIGHMEM; |
1445 | if (zone_bits & (__force int)__GFP_DMA32) | ||
1446 | res = ZONE_DMA32; | ||
1458 | if (zone_bits & (__force int)__GFP_DMA) | 1447 | if (zone_bits & (__force int)__GFP_DMA) |
1459 | res = ZONE_DMA; | 1448 | res = ZONE_DMA; |
1460 | return res; | 1449 | return res; |
@@ -1866,11 +1855,10 @@ static int __devinit pageset_cpuup_callback(struct notifier_block *nfb, | |||
1866 | if (process_zones(cpu)) | 1855 | if (process_zones(cpu)) |
1867 | ret = NOTIFY_BAD; | 1856 | ret = NOTIFY_BAD; |
1868 | break; | 1857 | break; |
1869 | #ifdef CONFIG_HOTPLUG_CPU | 1858 | case CPU_UP_CANCELED: |
1870 | case CPU_DEAD: | 1859 | case CPU_DEAD: |
1871 | free_zone_pagesets(cpu); | 1860 | free_zone_pagesets(cpu); |
1872 | break; | 1861 | break; |
1873 | #endif | ||
1874 | default: | 1862 | default: |
1875 | break; | 1863 | break; |
1876 | } | 1864 | } |
@@ -1975,7 +1963,7 @@ static void __init free_area_init_core(struct pglist_data *pgdat, | |||
1975 | if (zholes_size) | 1963 | if (zholes_size) |
1976 | realsize -= zholes_size[j]; | 1964 | realsize -= zholes_size[j]; |
1977 | 1965 | ||
1978 | if (j == ZONE_DMA || j == ZONE_NORMAL) | 1966 | if (j < ZONE_HIGHMEM) |
1979 | nr_kernel_pages += realsize; | 1967 | nr_kernel_pages += realsize; |
1980 | nr_all_pages += realsize; | 1968 | nr_all_pages += realsize; |
1981 | 1969 | ||
@@ -2417,13 +2405,18 @@ void setup_per_zone_pages_min(void) | |||
2417 | } | 2405 | } |
2418 | 2406 | ||
2419 | for_each_zone(zone) { | 2407 | for_each_zone(zone) { |
2408 | unsigned long tmp; | ||
2420 | spin_lock_irqsave(&zone->lru_lock, flags); | 2409 | spin_lock_irqsave(&zone->lru_lock, flags); |
2410 | tmp = (pages_min * zone->present_pages) / lowmem_pages; | ||
2421 | if (is_highmem(zone)) { | 2411 | if (is_highmem(zone)) { |
2422 | /* | 2412 | /* |
2423 | * Often, highmem doesn't need to reserve any pages. | 2413 | * __GFP_HIGH and PF_MEMALLOC allocations usually don't |
2424 | * But the pages_min/low/high values are also used for | 2414 | * need highmem pages, so cap pages_min to a small |
2425 | * batching up page reclaim activity so we need a | 2415 | * value here. |
2426 | * decent value here. | 2416 | * |
2417 | * The (pages_high-pages_low) and (pages_low-pages_min) | ||
2418 | * deltas controls asynch page reclaim, and so should | ||
2419 | * not be capped for highmem. | ||
2427 | */ | 2420 | */ |
2428 | int min_pages; | 2421 | int min_pages; |
2429 | 2422 | ||
@@ -2434,19 +2427,15 @@ void setup_per_zone_pages_min(void) | |||
2434 | min_pages = 128; | 2427 | min_pages = 128; |
2435 | zone->pages_min = min_pages; | 2428 | zone->pages_min = min_pages; |
2436 | } else { | 2429 | } else { |
2437 | /* if it's a lowmem zone, reserve a number of pages | 2430 | /* |
2431 | * If it's a lowmem zone, reserve a number of pages | ||
2438 | * proportionate to the zone's size. | 2432 | * proportionate to the zone's size. |
2439 | */ | 2433 | */ |
2440 | zone->pages_min = (pages_min * zone->present_pages) / | 2434 | zone->pages_min = tmp; |
2441 | lowmem_pages; | ||
2442 | } | 2435 | } |
2443 | 2436 | ||
2444 | /* | 2437 | zone->pages_low = zone->pages_min + tmp / 4; |
2445 | * When interpreting these watermarks, just keep in mind that: | 2438 | zone->pages_high = zone->pages_min + tmp / 2; |
2446 | * zone->pages_min == (zone->pages_min * 4) / 4; | ||
2447 | */ | ||
2448 | zone->pages_low = (zone->pages_min * 5) / 4; | ||
2449 | zone->pages_high = (zone->pages_min * 6) / 4; | ||
2450 | spin_unlock_irqrestore(&zone->lru_lock, flags); | 2439 | spin_unlock_irqrestore(&zone->lru_lock, flags); |
2451 | } | 2440 | } |
2452 | } | 2441 | } |
@@ -565,14 +565,29 @@ static void **dbg_userword(kmem_cache_t *cachep, void *objp) | |||
565 | #define BREAK_GFP_ORDER_LO 0 | 565 | #define BREAK_GFP_ORDER_LO 0 |
566 | static int slab_break_gfp_order = BREAK_GFP_ORDER_LO; | 566 | static int slab_break_gfp_order = BREAK_GFP_ORDER_LO; |
567 | 567 | ||
568 | /* Macros for storing/retrieving the cachep and or slab from the | 568 | /* Functions for storing/retrieving the cachep and or slab from the |
569 | * global 'mem_map'. These are used to find the slab an obj belongs to. | 569 | * global 'mem_map'. These are used to find the slab an obj belongs to. |
570 | * With kfree(), these are used to find the cache which an obj belongs to. | 570 | * With kfree(), these are used to find the cache which an obj belongs to. |
571 | */ | 571 | */ |
572 | #define SET_PAGE_CACHE(pg,x) ((pg)->lru.next = (struct list_head *)(x)) | 572 | static inline void page_set_cache(struct page *page, struct kmem_cache *cache) |
573 | #define GET_PAGE_CACHE(pg) ((kmem_cache_t *)(pg)->lru.next) | 573 | { |
574 | #define SET_PAGE_SLAB(pg,x) ((pg)->lru.prev = (struct list_head *)(x)) | 574 | page->lru.next = (struct list_head *)cache; |
575 | #define GET_PAGE_SLAB(pg) ((struct slab *)(pg)->lru.prev) | 575 | } |
576 | |||
577 | static inline struct kmem_cache *page_get_cache(struct page *page) | ||
578 | { | ||
579 | return (struct kmem_cache *)page->lru.next; | ||
580 | } | ||
581 | |||
582 | static inline void page_set_slab(struct page *page, struct slab *slab) | ||
583 | { | ||
584 | page->lru.prev = (struct list_head *)slab; | ||
585 | } | ||
586 | |||
587 | static inline struct slab *page_get_slab(struct page *page) | ||
588 | { | ||
589 | return (struct slab *)page->lru.prev; | ||
590 | } | ||
576 | 591 | ||
577 | /* These are the default caches for kmalloc. Custom caches can have other sizes. */ | 592 | /* These are the default caches for kmalloc. Custom caches can have other sizes. */ |
578 | struct cache_sizes malloc_sizes[] = { | 593 | struct cache_sizes malloc_sizes[] = { |
@@ -1190,11 +1205,7 @@ static void *kmem_getpages(kmem_cache_t *cachep, gfp_t flags, int nodeid) | |||
1190 | int i; | 1205 | int i; |
1191 | 1206 | ||
1192 | flags |= cachep->gfpflags; | 1207 | flags |= cachep->gfpflags; |
1193 | if (likely(nodeid == -1)) { | 1208 | page = alloc_pages_node(nodeid, flags, cachep->gfporder); |
1194 | page = alloc_pages(flags, cachep->gfporder); | ||
1195 | } else { | ||
1196 | page = alloc_pages_node(nodeid, flags, cachep->gfporder); | ||
1197 | } | ||
1198 | if (!page) | 1209 | if (!page) |
1199 | return NULL; | 1210 | return NULL; |
1200 | addr = page_address(page); | 1211 | addr = page_address(page); |
@@ -1368,7 +1379,7 @@ static void check_poison_obj(kmem_cache_t *cachep, void *objp) | |||
1368 | /* Print some data about the neighboring objects, if they | 1379 | /* Print some data about the neighboring objects, if they |
1369 | * exist: | 1380 | * exist: |
1370 | */ | 1381 | */ |
1371 | struct slab *slabp = GET_PAGE_SLAB(virt_to_page(objp)); | 1382 | struct slab *slabp = page_get_slab(virt_to_page(objp)); |
1372 | int objnr; | 1383 | int objnr; |
1373 | 1384 | ||
1374 | objnr = (objp-slabp->s_mem)/cachep->objsize; | 1385 | objnr = (objp-slabp->s_mem)/cachep->objsize; |
@@ -2138,8 +2149,8 @@ static void set_slab_attr(kmem_cache_t *cachep, struct slab *slabp, void *objp) | |||
2138 | i = 1 << cachep->gfporder; | 2149 | i = 1 << cachep->gfporder; |
2139 | page = virt_to_page(objp); | 2150 | page = virt_to_page(objp); |
2140 | do { | 2151 | do { |
2141 | SET_PAGE_CACHE(page, cachep); | 2152 | page_set_cache(page, cachep); |
2142 | SET_PAGE_SLAB(page, slabp); | 2153 | page_set_slab(page, slabp); |
2143 | page++; | 2154 | page++; |
2144 | } while (--i); | 2155 | } while (--i); |
2145 | } | 2156 | } |
@@ -2269,14 +2280,14 @@ static void *cache_free_debugcheck(kmem_cache_t *cachep, void *objp, | |||
2269 | kfree_debugcheck(objp); | 2280 | kfree_debugcheck(objp); |
2270 | page = virt_to_page(objp); | 2281 | page = virt_to_page(objp); |
2271 | 2282 | ||
2272 | if (GET_PAGE_CACHE(page) != cachep) { | 2283 | if (page_get_cache(page) != cachep) { |
2273 | printk(KERN_ERR "mismatch in kmem_cache_free: expected cache %p, got %p\n", | 2284 | printk(KERN_ERR "mismatch in kmem_cache_free: expected cache %p, got %p\n", |
2274 | GET_PAGE_CACHE(page),cachep); | 2285 | page_get_cache(page),cachep); |
2275 | printk(KERN_ERR "%p is %s.\n", cachep, cachep->name); | 2286 | printk(KERN_ERR "%p is %s.\n", cachep, cachep->name); |
2276 | printk(KERN_ERR "%p is %s.\n", GET_PAGE_CACHE(page), GET_PAGE_CACHE(page)->name); | 2287 | printk(KERN_ERR "%p is %s.\n", page_get_cache(page), page_get_cache(page)->name); |
2277 | WARN_ON(1); | 2288 | WARN_ON(1); |
2278 | } | 2289 | } |
2279 | slabp = GET_PAGE_SLAB(page); | 2290 | slabp = page_get_slab(page); |
2280 | 2291 | ||
2281 | if (cachep->flags & SLAB_RED_ZONE) { | 2292 | if (cachep->flags & SLAB_RED_ZONE) { |
2282 | if (*dbg_redzone1(cachep, objp) != RED_ACTIVE || *dbg_redzone2(cachep, objp) != RED_ACTIVE) { | 2293 | if (*dbg_redzone1(cachep, objp) != RED_ACTIVE || *dbg_redzone2(cachep, objp) != RED_ACTIVE) { |
@@ -2628,7 +2639,7 @@ static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects, int n | |||
2628 | struct slab *slabp; | 2639 | struct slab *slabp; |
2629 | unsigned int objnr; | 2640 | unsigned int objnr; |
2630 | 2641 | ||
2631 | slabp = GET_PAGE_SLAB(virt_to_page(objp)); | 2642 | slabp = page_get_slab(virt_to_page(objp)); |
2632 | l3 = cachep->nodelists[node]; | 2643 | l3 = cachep->nodelists[node]; |
2633 | list_del(&slabp->list); | 2644 | list_del(&slabp->list); |
2634 | objnr = (objp - slabp->s_mem) / cachep->objsize; | 2645 | objnr = (objp - slabp->s_mem) / cachep->objsize; |
@@ -2744,7 +2755,7 @@ static inline void __cache_free(kmem_cache_t *cachep, void *objp) | |||
2744 | #ifdef CONFIG_NUMA | 2755 | #ifdef CONFIG_NUMA |
2745 | { | 2756 | { |
2746 | struct slab *slabp; | 2757 | struct slab *slabp; |
2747 | slabp = GET_PAGE_SLAB(virt_to_page(objp)); | 2758 | slabp = page_get_slab(virt_to_page(objp)); |
2748 | if (unlikely(slabp->nodeid != numa_node_id())) { | 2759 | if (unlikely(slabp->nodeid != numa_node_id())) { |
2749 | struct array_cache *alien = NULL; | 2760 | struct array_cache *alien = NULL; |
2750 | int nodeid = slabp->nodeid; | 2761 | int nodeid = slabp->nodeid; |
@@ -2830,7 +2841,7 @@ int fastcall kmem_ptr_validate(kmem_cache_t *cachep, void *ptr) | |||
2830 | page = virt_to_page(ptr); | 2841 | page = virt_to_page(ptr); |
2831 | if (unlikely(!PageSlab(page))) | 2842 | if (unlikely(!PageSlab(page))) |
2832 | goto out; | 2843 | goto out; |
2833 | if (unlikely(GET_PAGE_CACHE(page) != cachep)) | 2844 | if (unlikely(page_get_cache(page) != cachep)) |
2834 | goto out; | 2845 | goto out; |
2835 | return 1; | 2846 | return 1; |
2836 | out: | 2847 | out: |
@@ -3026,7 +3037,7 @@ void kfree(const void *objp) | |||
3026 | return; | 3037 | return; |
3027 | local_irq_save(flags); | 3038 | local_irq_save(flags); |
3028 | kfree_debugcheck(objp); | 3039 | kfree_debugcheck(objp); |
3029 | c = GET_PAGE_CACHE(virt_to_page(objp)); | 3040 | c = page_get_cache(virt_to_page(objp)); |
3030 | __cache_free(c, (void*)objp); | 3041 | __cache_free(c, (void*)objp); |
3031 | local_irq_restore(flags); | 3042 | local_irq_restore(flags); |
3032 | } | 3043 | } |
@@ -3596,7 +3607,7 @@ unsigned int ksize(const void *objp) | |||
3596 | if (unlikely(objp == NULL)) | 3607 | if (unlikely(objp == NULL)) |
3597 | return 0; | 3608 | return 0; |
3598 | 3609 | ||
3599 | return obj_reallen(GET_PAGE_CACHE(virt_to_page(objp))); | 3610 | return obj_reallen(page_get_cache(virt_to_page(objp))); |
3600 | } | 3611 | } |
3601 | 3612 | ||
3602 | 3613 | ||
diff --git a/mm/vmscan.c b/mm/vmscan.c index 135bf8ca96ee..28130541270f 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -1074,7 +1074,7 @@ loop_again: | |||
1074 | continue; | 1074 | continue; |
1075 | 1075 | ||
1076 | if (!zone_watermark_ok(zone, order, | 1076 | if (!zone_watermark_ok(zone, order, |
1077 | zone->pages_high, 0, 0, 0)) { | 1077 | zone->pages_high, 0, 0)) { |
1078 | end_zone = i; | 1078 | end_zone = i; |
1079 | goto scan; | 1079 | goto scan; |
1080 | } | 1080 | } |
@@ -1111,7 +1111,7 @@ scan: | |||
1111 | 1111 | ||
1112 | if (nr_pages == 0) { /* Not software suspend */ | 1112 | if (nr_pages == 0) { /* Not software suspend */ |
1113 | if (!zone_watermark_ok(zone, order, | 1113 | if (!zone_watermark_ok(zone, order, |
1114 | zone->pages_high, end_zone, 0, 0)) | 1114 | zone->pages_high, end_zone, 0)) |
1115 | all_zones_ok = 0; | 1115 | all_zones_ok = 0; |
1116 | } | 1116 | } |
1117 | zone->temp_priority = priority; | 1117 | zone->temp_priority = priority; |
@@ -1259,7 +1259,7 @@ void wakeup_kswapd(struct zone *zone, int order) | |||
1259 | return; | 1259 | return; |
1260 | 1260 | ||
1261 | pgdat = zone->zone_pgdat; | 1261 | pgdat = zone->zone_pgdat; |
1262 | if (zone_watermark_ok(zone, order, zone->pages_low, 0, 0, 0)) | 1262 | if (zone_watermark_ok(zone, order, zone->pages_low, 0, 0)) |
1263 | return; | 1263 | return; |
1264 | if (pgdat->kswapd_max_order < order) | 1264 | if (pgdat->kswapd_max_order < order) |
1265 | pgdat->kswapd_max_order = order; | 1265 | pgdat->kswapd_max_order = order; |
diff --git a/net/Makefile b/net/Makefile index 4aa2f46d2a56..f5141b9d4f38 100644 --- a/net/Makefile +++ b/net/Makefile | |||
@@ -15,8 +15,8 @@ obj-$(CONFIG_NET) += $(tmp-y) | |||
15 | # LLC has to be linked before the files in net/802/ | 15 | # LLC has to be linked before the files in net/802/ |
16 | obj-$(CONFIG_LLC) += llc/ | 16 | obj-$(CONFIG_LLC) += llc/ |
17 | obj-$(CONFIG_NET) += ethernet/ 802/ sched/ netlink/ | 17 | obj-$(CONFIG_NET) += ethernet/ 802/ sched/ netlink/ |
18 | obj-$(CONFIG_INET) += ipv4/ | ||
19 | obj-$(CONFIG_NETFILTER) += netfilter/ | 18 | obj-$(CONFIG_NETFILTER) += netfilter/ |
19 | obj-$(CONFIG_INET) += ipv4/ | ||
20 | obj-$(CONFIG_XFRM) += xfrm/ | 20 | obj-$(CONFIG_XFRM) += xfrm/ |
21 | obj-$(CONFIG_UNIX) += unix/ | 21 | obj-$(CONFIG_UNIX) += unix/ |
22 | ifneq ($(CONFIG_IPV6),) | 22 | ifneq ($(CONFIG_IPV6),) |
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index d2a4fec22862..de9f4464438d 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c | |||
@@ -467,7 +467,7 @@ out: | |||
467 | } | 467 | } |
468 | #endif | 468 | #endif |
469 | 469 | ||
470 | static const int cta_min_ip[CTA_IP_MAX] = { | 470 | static const size_t cta_min_ip[CTA_IP_MAX] = { |
471 | [CTA_IP_V4_SRC-1] = sizeof(u_int32_t), | 471 | [CTA_IP_V4_SRC-1] = sizeof(u_int32_t), |
472 | [CTA_IP_V4_DST-1] = sizeof(u_int32_t), | 472 | [CTA_IP_V4_DST-1] = sizeof(u_int32_t), |
473 | }; | 473 | }; |
@@ -497,7 +497,7 @@ ctnetlink_parse_tuple_ip(struct nfattr *attr, struct ip_conntrack_tuple *tuple) | |||
497 | return 0; | 497 | return 0; |
498 | } | 498 | } |
499 | 499 | ||
500 | static const int cta_min_proto[CTA_PROTO_MAX] = { | 500 | static const size_t cta_min_proto[CTA_PROTO_MAX] = { |
501 | [CTA_PROTO_NUM-1] = sizeof(u_int16_t), | 501 | [CTA_PROTO_NUM-1] = sizeof(u_int16_t), |
502 | [CTA_PROTO_SRC_PORT-1] = sizeof(u_int16_t), | 502 | [CTA_PROTO_SRC_PORT-1] = sizeof(u_int16_t), |
503 | [CTA_PROTO_DST_PORT-1] = sizeof(u_int16_t), | 503 | [CTA_PROTO_DST_PORT-1] = sizeof(u_int16_t), |
@@ -576,7 +576,7 @@ ctnetlink_parse_tuple(struct nfattr *cda[], struct ip_conntrack_tuple *tuple, | |||
576 | } | 576 | } |
577 | 577 | ||
578 | #ifdef CONFIG_IP_NF_NAT_NEEDED | 578 | #ifdef CONFIG_IP_NF_NAT_NEEDED |
579 | static const int cta_min_protonat[CTA_PROTONAT_MAX] = { | 579 | static const size_t cta_min_protonat[CTA_PROTONAT_MAX] = { |
580 | [CTA_PROTONAT_PORT_MIN-1] = sizeof(u_int16_t), | 580 | [CTA_PROTONAT_PORT_MIN-1] = sizeof(u_int16_t), |
581 | [CTA_PROTONAT_PORT_MAX-1] = sizeof(u_int16_t), | 581 | [CTA_PROTONAT_PORT_MAX-1] = sizeof(u_int16_t), |
582 | }; | 582 | }; |
@@ -614,6 +614,11 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr, | |||
614 | return 0; | 614 | return 0; |
615 | } | 615 | } |
616 | 616 | ||
617 | static const size_t cta_min_nat[CTA_NAT_MAX] = { | ||
618 | [CTA_NAT_MINIP-1] = sizeof(u_int32_t), | ||
619 | [CTA_NAT_MAXIP-1] = sizeof(u_int32_t), | ||
620 | }; | ||
621 | |||
617 | static inline int | 622 | static inline int |
618 | ctnetlink_parse_nat(struct nfattr *cda[], | 623 | ctnetlink_parse_nat(struct nfattr *cda[], |
619 | const struct ip_conntrack *ct, struct ip_nat_range *range) | 624 | const struct ip_conntrack *ct, struct ip_nat_range *range) |
@@ -627,6 +632,9 @@ ctnetlink_parse_nat(struct nfattr *cda[], | |||
627 | 632 | ||
628 | nfattr_parse_nested(tb, CTA_NAT_MAX, cda[CTA_NAT-1]); | 633 | nfattr_parse_nested(tb, CTA_NAT_MAX, cda[CTA_NAT-1]); |
629 | 634 | ||
635 | if (nfattr_bad_size(tb, CTA_NAT_MAX, cta_min_nat)) | ||
636 | return -EINVAL; | ||
637 | |||
630 | if (tb[CTA_NAT_MINIP-1]) | 638 | if (tb[CTA_NAT_MINIP-1]) |
631 | range->min_ip = *(u_int32_t *)NFA_DATA(tb[CTA_NAT_MINIP-1]); | 639 | range->min_ip = *(u_int32_t *)NFA_DATA(tb[CTA_NAT_MINIP-1]); |
632 | 640 | ||
@@ -667,6 +675,14 @@ ctnetlink_parse_help(struct nfattr *attr, char **helper_name) | |||
667 | return 0; | 675 | return 0; |
668 | } | 676 | } |
669 | 677 | ||
678 | static const size_t cta_min[CTA_MAX] = { | ||
679 | [CTA_STATUS-1] = sizeof(u_int32_t), | ||
680 | [CTA_TIMEOUT-1] = sizeof(u_int32_t), | ||
681 | [CTA_MARK-1] = sizeof(u_int32_t), | ||
682 | [CTA_USE-1] = sizeof(u_int32_t), | ||
683 | [CTA_ID-1] = sizeof(u_int32_t) | ||
684 | }; | ||
685 | |||
670 | static int | 686 | static int |
671 | ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, | 687 | ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, |
672 | struct nlmsghdr *nlh, struct nfattr *cda[], int *errp) | 688 | struct nlmsghdr *nlh, struct nfattr *cda[], int *errp) |
@@ -678,6 +694,9 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
678 | 694 | ||
679 | DEBUGP("entered %s\n", __FUNCTION__); | 695 | DEBUGP("entered %s\n", __FUNCTION__); |
680 | 696 | ||
697 | if (nfattr_bad_size(cda, CTA_MAX, cta_min)) | ||
698 | return -EINVAL; | ||
699 | |||
681 | if (cda[CTA_TUPLE_ORIG-1]) | 700 | if (cda[CTA_TUPLE_ORIG-1]) |
682 | err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG); | 701 | err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG); |
683 | else if (cda[CTA_TUPLE_REPLY-1]) | 702 | else if (cda[CTA_TUPLE_REPLY-1]) |
@@ -760,6 +779,9 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
760 | return 0; | 779 | return 0; |
761 | } | 780 | } |
762 | 781 | ||
782 | if (nfattr_bad_size(cda, CTA_MAX, cta_min)) | ||
783 | return -EINVAL; | ||
784 | |||
763 | if (cda[CTA_TUPLE_ORIG-1]) | 785 | if (cda[CTA_TUPLE_ORIG-1]) |
764 | err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG); | 786 | err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG); |
765 | else if (cda[CTA_TUPLE_REPLY-1]) | 787 | else if (cda[CTA_TUPLE_REPLY-1]) |
@@ -1047,6 +1069,9 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
1047 | 1069 | ||
1048 | DEBUGP("entered %s\n", __FUNCTION__); | 1070 | DEBUGP("entered %s\n", __FUNCTION__); |
1049 | 1071 | ||
1072 | if (nfattr_bad_size(cda, CTA_MAX, cta_min)) | ||
1073 | return -EINVAL; | ||
1074 | |||
1050 | if (cda[CTA_TUPLE_ORIG-1]) { | 1075 | if (cda[CTA_TUPLE_ORIG-1]) { |
1051 | err = ctnetlink_parse_tuple(cda, &otuple, CTA_TUPLE_ORIG); | 1076 | err = ctnetlink_parse_tuple(cda, &otuple, CTA_TUPLE_ORIG); |
1052 | if (err < 0) | 1077 | if (err < 0) |
@@ -1252,6 +1277,11 @@ out: | |||
1252 | return skb->len; | 1277 | return skb->len; |
1253 | } | 1278 | } |
1254 | 1279 | ||
1280 | static const size_t cta_min_exp[CTA_EXPECT_MAX] = { | ||
1281 | [CTA_EXPECT_TIMEOUT-1] = sizeof(u_int32_t), | ||
1282 | [CTA_EXPECT_ID-1] = sizeof(u_int32_t) | ||
1283 | }; | ||
1284 | |||
1255 | static int | 1285 | static int |
1256 | ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, | 1286 | ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, |
1257 | struct nlmsghdr *nlh, struct nfattr *cda[], int *errp) | 1287 | struct nlmsghdr *nlh, struct nfattr *cda[], int *errp) |
@@ -1263,6 +1293,9 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, | |||
1263 | 1293 | ||
1264 | DEBUGP("entered %s\n", __FUNCTION__); | 1294 | DEBUGP("entered %s\n", __FUNCTION__); |
1265 | 1295 | ||
1296 | if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp)) | ||
1297 | return -EINVAL; | ||
1298 | |||
1266 | if (nlh->nlmsg_flags & NLM_F_DUMP) { | 1299 | if (nlh->nlmsg_flags & NLM_F_DUMP) { |
1267 | struct nfgenmsg *msg = NLMSG_DATA(nlh); | 1300 | struct nfgenmsg *msg = NLMSG_DATA(nlh); |
1268 | u32 rlen; | 1301 | u32 rlen; |
@@ -1333,6 +1366,9 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, | |||
1333 | struct ip_conntrack_helper *h; | 1366 | struct ip_conntrack_helper *h; |
1334 | int err; | 1367 | int err; |
1335 | 1368 | ||
1369 | if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp)) | ||
1370 | return -EINVAL; | ||
1371 | |||
1336 | if (cda[CTA_EXPECT_TUPLE-1]) { | 1372 | if (cda[CTA_EXPECT_TUPLE-1]) { |
1337 | /* delete a single expect by tuple */ | 1373 | /* delete a single expect by tuple */ |
1338 | err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE); | 1374 | err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE); |
@@ -1462,6 +1498,9 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, | |||
1462 | 1498 | ||
1463 | DEBUGP("entered %s\n", __FUNCTION__); | 1499 | DEBUGP("entered %s\n", __FUNCTION__); |
1464 | 1500 | ||
1501 | if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp)) | ||
1502 | return -EINVAL; | ||
1503 | |||
1465 | if (!cda[CTA_EXPECT_TUPLE-1] | 1504 | if (!cda[CTA_EXPECT_TUPLE-1] |
1466 | || !cda[CTA_EXPECT_MASK-1] | 1505 | || !cda[CTA_EXPECT_MASK-1] |
1467 | || !cda[CTA_EXPECT_MASTER-1]) | 1506 | || !cda[CTA_EXPECT_MASTER-1]) |
@@ -1504,29 +1543,22 @@ static struct notifier_block ctnl_notifier_exp = { | |||
1504 | 1543 | ||
1505 | static struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = { | 1544 | static struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = { |
1506 | [IPCTNL_MSG_CT_NEW] = { .call = ctnetlink_new_conntrack, | 1545 | [IPCTNL_MSG_CT_NEW] = { .call = ctnetlink_new_conntrack, |
1507 | .attr_count = CTA_MAX, | 1546 | .attr_count = CTA_MAX, }, |
1508 | .cap_required = CAP_NET_ADMIN }, | ||
1509 | [IPCTNL_MSG_CT_GET] = { .call = ctnetlink_get_conntrack, | 1547 | [IPCTNL_MSG_CT_GET] = { .call = ctnetlink_get_conntrack, |
1510 | .attr_count = CTA_MAX, | 1548 | .attr_count = CTA_MAX, }, |
1511 | .cap_required = CAP_NET_ADMIN }, | ||
1512 | [IPCTNL_MSG_CT_DELETE] = { .call = ctnetlink_del_conntrack, | 1549 | [IPCTNL_MSG_CT_DELETE] = { .call = ctnetlink_del_conntrack, |
1513 | .attr_count = CTA_MAX, | 1550 | .attr_count = CTA_MAX, }, |
1514 | .cap_required = CAP_NET_ADMIN }, | ||
1515 | [IPCTNL_MSG_CT_GET_CTRZERO] = { .call = ctnetlink_get_conntrack, | 1551 | [IPCTNL_MSG_CT_GET_CTRZERO] = { .call = ctnetlink_get_conntrack, |
1516 | .attr_count = CTA_MAX, | 1552 | .attr_count = CTA_MAX, }, |
1517 | .cap_required = CAP_NET_ADMIN }, | ||
1518 | }; | 1553 | }; |
1519 | 1554 | ||
1520 | static struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_EXP_MAX] = { | 1555 | static struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_EXP_MAX] = { |
1521 | [IPCTNL_MSG_EXP_GET] = { .call = ctnetlink_get_expect, | 1556 | [IPCTNL_MSG_EXP_GET] = { .call = ctnetlink_get_expect, |
1522 | .attr_count = CTA_EXPECT_MAX, | 1557 | .attr_count = CTA_EXPECT_MAX, }, |
1523 | .cap_required = CAP_NET_ADMIN }, | ||
1524 | [IPCTNL_MSG_EXP_NEW] = { .call = ctnetlink_new_expect, | 1558 | [IPCTNL_MSG_EXP_NEW] = { .call = ctnetlink_new_expect, |
1525 | .attr_count = CTA_EXPECT_MAX, | 1559 | .attr_count = CTA_EXPECT_MAX, }, |
1526 | .cap_required = CAP_NET_ADMIN }, | ||
1527 | [IPCTNL_MSG_EXP_DELETE] = { .call = ctnetlink_del_expect, | 1560 | [IPCTNL_MSG_EXP_DELETE] = { .call = ctnetlink_del_expect, |
1528 | .attr_count = CTA_EXPECT_MAX, | 1561 | .attr_count = CTA_EXPECT_MAX, }, |
1529 | .cap_required = CAP_NET_ADMIN }, | ||
1530 | }; | 1562 | }; |
1531 | 1563 | ||
1532 | static struct nfnetlink_subsystem ctnl_subsys = { | 1564 | static struct nfnetlink_subsystem ctnl_subsys = { |
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c index 5b3f5220f289..ee3b7d6c4d2e 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c | |||
@@ -357,6 +357,10 @@ nfattr_failure: | |||
357 | return -1; | 357 | return -1; |
358 | } | 358 | } |
359 | 359 | ||
360 | static const size_t cta_min_tcp[CTA_PROTOINFO_TCP_MAX] = { | ||
361 | [CTA_PROTOINFO_TCP_STATE-1] = sizeof(u_int8_t), | ||
362 | }; | ||
363 | |||
360 | static int nfattr_to_tcp(struct nfattr *cda[], struct ip_conntrack *ct) | 364 | static int nfattr_to_tcp(struct nfattr *cda[], struct ip_conntrack *ct) |
361 | { | 365 | { |
362 | struct nfattr *attr = cda[CTA_PROTOINFO_TCP-1]; | 366 | struct nfattr *attr = cda[CTA_PROTOINFO_TCP-1]; |
@@ -369,6 +373,9 @@ static int nfattr_to_tcp(struct nfattr *cda[], struct ip_conntrack *ct) | |||
369 | 373 | ||
370 | nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr); | 374 | nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr); |
371 | 375 | ||
376 | if (nfattr_bad_size(tb, CTA_PROTOINFO_TCP_MAX, cta_min_tcp)) | ||
377 | return -EINVAL; | ||
378 | |||
372 | if (!tb[CTA_PROTOINFO_TCP_STATE-1]) | 379 | if (!tb[CTA_PROTOINFO_TCP_STATE-1]) |
373 | return -EINVAL; | 380 | return -EINVAL; |
374 | 381 | ||
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 40a26b7157b4..bf2e23086bce 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -367,7 +367,7 @@ static void tcp_rcv_rtt_update(struct tcp_sock *tp, u32 sample, int win_dep) | |||
367 | * are stalled on filesystem I/O. | 367 | * are stalled on filesystem I/O. |
368 | * | 368 | * |
369 | * Also, since we are only going for a minimum in the | 369 | * Also, since we are only going for a minimum in the |
370 | * non-timestamp case, we do not smoother things out | 370 | * non-timestamp case, we do not smooth things out |
371 | * else with timestamps disabled convergence takes too | 371 | * else with timestamps disabled convergence takes too |
372 | * long. | 372 | * long. |
373 | */ | 373 | */ |
@@ -546,7 +546,7 @@ static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt) | |||
546 | * | 546 | * |
547 | * Funny. This algorithm seems to be very broken. | 547 | * Funny. This algorithm seems to be very broken. |
548 | * These formulae increase RTO, when it should be decreased, increase | 548 | * These formulae increase RTO, when it should be decreased, increase |
549 | * too slowly, when it should be increased fastly, decrease too fastly | 549 | * too slowly, when it should be increased quickly, decrease too quickly |
550 | * etc. I guess in BSD RTO takes ONE value, so that it is absolutely | 550 | * etc. I guess in BSD RTO takes ONE value, so that it is absolutely |
551 | * does not matter how to _calculate_ it. Seems, it was trap | 551 | * does not matter how to _calculate_ it. Seems, it was trap |
552 | * that VJ failed to avoid. 8) | 552 | * that VJ failed to avoid. 8) |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index ddcf7754eec2..56a09a4ac410 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -1045,9 +1045,10 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
1045 | } | 1045 | } |
1046 | #endif | 1046 | #endif |
1047 | /* Rule 8: Use longest matching prefix */ | 1047 | /* Rule 8: Use longest matching prefix */ |
1048 | if (hiscore.rule < 8) | 1048 | if (hiscore.rule < 8) { |
1049 | hiscore.matchlen = ipv6_addr_diff(&ifa_result->addr, daddr); | 1049 | hiscore.matchlen = ipv6_addr_diff(&ifa_result->addr, daddr); |
1050 | score.rule++; | 1050 | hiscore.rule++; |
1051 | } | ||
1051 | score.matchlen = ipv6_addr_diff(&ifa->addr, daddr); | 1052 | score.matchlen = ipv6_addr_diff(&ifa->addr, daddr); |
1052 | if (score.matchlen > hiscore.matchlen) { | 1053 | if (score.matchlen > hiscore.matchlen) { |
1053 | score.rule = 8; | 1054 | score.rule = 8; |
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 003fd99ff597..25757ade989f 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -287,7 +287,7 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
287 | { | 287 | { |
288 | struct ipv6_txoptions *opt; | 288 | struct ipv6_txoptions *opt; |
289 | if (optlen == 0) | 289 | if (optlen == 0) |
290 | optval = 0; | 290 | optval = NULL; |
291 | 291 | ||
292 | /* hop-by-hop / destination options are privileged option */ | 292 | /* hop-by-hop / destination options are privileged option */ |
293 | retv = -EPERM; | 293 | retv = -EPERM; |
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 971ba60bf6e9..060d61202412 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -5,10 +5,20 @@ | |||
5 | menu "IPv6: Netfilter Configuration (EXPERIMENTAL)" | 5 | menu "IPv6: Netfilter Configuration (EXPERIMENTAL)" |
6 | depends on INET && IPV6 && NETFILTER && EXPERIMENTAL | 6 | depends on INET && IPV6 && NETFILTER && EXPERIMENTAL |
7 | 7 | ||
8 | #tristate 'Connection tracking (required for masq/NAT)' CONFIG_IP6_NF_CONNTRACK | 8 | config NF_CONNTRACK_IPV6 |
9 | #if [ "$CONFIG_IP6_NF_CONNTRACK" != "n" ]; then | 9 | tristate "IPv6 support for new connection tracking (EXPERIMENTAL)" |
10 | # dep_tristate ' FTP protocol support' CONFIG_IP6_NF_FTP $CONFIG_IP6_NF_CONNTRACK | 10 | depends on EXPERIMENTAL && NF_CONNTRACK |
11 | #fi | 11 | ---help--- |
12 | Connection tracking keeps a record of what packets have passed | ||
13 | through your machine, in order to figure out how they are related | ||
14 | into connections. | ||
15 | |||
16 | This is IPv6 support on Layer 3 independent connection tracking. | ||
17 | Layer 3 independent connection tracking is experimental scheme | ||
18 | which generalize ip_conntrack to support other layer 3 protocols. | ||
19 | |||
20 | To compile it as a module, choose M here. If unsure, say N. | ||
21 | |||
12 | config IP6_NF_QUEUE | 22 | config IP6_NF_QUEUE |
13 | tristate "IP6 Userspace queueing via NETLINK (OBSOLETE)" | 23 | tristate "IP6 Userspace queueing via NETLINK (OBSOLETE)" |
14 | ---help--- | 24 | ---help--- |
@@ -114,7 +124,6 @@ config IP6_NF_MATCH_OWNER | |||
114 | 124 | ||
115 | To compile it as a module, choose M here. If unsure, say N. | 125 | To compile it as a module, choose M here. If unsure, say N. |
116 | 126 | ||
117 | # dep_tristate ' MAC address match support' CONFIG_IP6_NF_MATCH_MAC $CONFIG_IP6_NF_IPTABLES | ||
118 | config IP6_NF_MATCH_MARK | 127 | config IP6_NF_MATCH_MARK |
119 | tristate "netfilter MARK match support" | 128 | tristate "netfilter MARK match support" |
120 | depends on IP6_NF_IPTABLES | 129 | depends on IP6_NF_IPTABLES |
@@ -170,15 +179,6 @@ config IP6_NF_MATCH_PHYSDEV | |||
170 | 179 | ||
171 | To compile it as a module, choose M here. If unsure, say N. | 180 | To compile it as a module, choose M here. If unsure, say N. |
172 | 181 | ||
173 | # dep_tristate ' Multiple port match support' CONFIG_IP6_NF_MATCH_MULTIPORT $CONFIG_IP6_NF_IPTABLES | ||
174 | # dep_tristate ' TOS match support' CONFIG_IP6_NF_MATCH_TOS $CONFIG_IP6_NF_IPTABLES | ||
175 | # if [ "$CONFIG_IP6_NF_CONNTRACK" != "n" ]; then | ||
176 | # dep_tristate ' Connection state match support' CONFIG_IP6_NF_MATCH_STATE $CONFIG_IP6_NF_CONNTRACK $CONFIG_IP6_NF_IPTABLES | ||
177 | # fi | ||
178 | # if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then | ||
179 | # dep_tristate ' Unclean match support (EXPERIMENTAL)' CONFIG_IP6_NF_MATCH_UNCLEAN $CONFIG_IP6_NF_IPTABLES | ||
180 | # dep_tristate ' Owner match support (EXPERIMENTAL)' CONFIG_IP6_NF_MATCH_OWNER $CONFIG_IP6_NF_IPTABLES | ||
181 | # fi | ||
182 | # The targets | 182 | # The targets |
183 | config IP6_NF_FILTER | 183 | config IP6_NF_FILTER |
184 | tristate "Packet filtering" | 184 | tristate "Packet filtering" |
@@ -220,12 +220,6 @@ config IP6_NF_TARGET_NFQUEUE | |||
220 | 220 | ||
221 | To compile it as a module, choose M here. If unsure, say N. | 221 | To compile it as a module, choose M here. If unsure, say N. |
222 | 222 | ||
223 | # if [ "$CONFIG_IP6_NF_FILTER" != "n" ]; then | ||
224 | # dep_tristate ' REJECT target support' CONFIG_IP6_NF_TARGET_REJECT $CONFIG_IP6_NF_FILTER | ||
225 | # if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then | ||
226 | # dep_tristate ' MIRROR target support (EXPERIMENTAL)' CONFIG_IP6_NF_TARGET_MIRROR $CONFIG_IP6_NF_FILTER | ||
227 | # fi | ||
228 | # fi | ||
229 | config IP6_NF_MANGLE | 223 | config IP6_NF_MANGLE |
230 | tristate "Packet mangling" | 224 | tristate "Packet mangling" |
231 | depends on IP6_NF_IPTABLES | 225 | depends on IP6_NF_IPTABLES |
@@ -236,7 +230,6 @@ config IP6_NF_MANGLE | |||
236 | 230 | ||
237 | To compile it as a module, choose M here. If unsure, say N. | 231 | To compile it as a module, choose M here. If unsure, say N. |
238 | 232 | ||
239 | # dep_tristate ' TOS target support' CONFIG_IP6_NF_TARGET_TOS $CONFIG_IP_NF_MANGLE | ||
240 | config IP6_NF_TARGET_MARK | 233 | config IP6_NF_TARGET_MARK |
241 | tristate "MARK target support" | 234 | tristate "MARK target support" |
242 | depends on IP6_NF_MANGLE | 235 | depends on IP6_NF_MANGLE |
@@ -266,7 +259,6 @@ config IP6_NF_TARGET_HL | |||
266 | 259 | ||
267 | To compile it as a module, choose M here. If unsure, say N. | 260 | To compile it as a module, choose M here. If unsure, say N. |
268 | 261 | ||
269 | #dep_tristate ' LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES | ||
270 | config IP6_NF_RAW | 262 | config IP6_NF_RAW |
271 | tristate 'raw table support (required for TRACE)' | 263 | tristate 'raw table support (required for TRACE)' |
272 | depends on IP6_NF_IPTABLES | 264 | depends on IP6_NF_IPTABLES |
@@ -278,19 +270,5 @@ config IP6_NF_RAW | |||
278 | If you want to compile it as a module, say M here and read | 270 | If you want to compile it as a module, say M here and read |
279 | <file:Documentation/modules.txt>. If unsure, say `N'. | 271 | <file:Documentation/modules.txt>. If unsure, say `N'. |
280 | 272 | ||
281 | config NF_CONNTRACK_IPV6 | ||
282 | tristate "IPv6 support for new connection tracking (EXPERIMENTAL)" | ||
283 | depends on EXPERIMENTAL && NF_CONNTRACK | ||
284 | ---help--- | ||
285 | Connection tracking keeps a record of what packets have passed | ||
286 | through your machine, in order to figure out how they are related | ||
287 | into connections. | ||
288 | |||
289 | This is IPv6 support on Layer 3 independent connection tracking. | ||
290 | Layer 3 independent connection tracking is experimental scheme | ||
291 | which generalize ip_conntrack to support other layer 3 protocols. | ||
292 | |||
293 | To compile it as a module, choose M here. If unsure, say N. | ||
294 | |||
295 | endmenu | 273 | endmenu |
296 | 274 | ||
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index e2c90b3a8074..753a3ae8502b 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | |||
@@ -339,8 +339,8 @@ extern unsigned long nf_ct_icmpv6_timeout; | |||
339 | 339 | ||
340 | /* From nf_conntrack_frag6.c */ | 340 | /* From nf_conntrack_frag6.c */ |
341 | extern unsigned long nf_ct_frag6_timeout; | 341 | extern unsigned long nf_ct_frag6_timeout; |
342 | extern unsigned long nf_ct_frag6_low_thresh; | 342 | extern unsigned int nf_ct_frag6_low_thresh; |
343 | extern unsigned long nf_ct_frag6_high_thresh; | 343 | extern unsigned int nf_ct_frag6_high_thresh; |
344 | 344 | ||
345 | static struct ctl_table_header *nf_ct_ipv6_sysctl_header; | 345 | static struct ctl_table_header *nf_ct_ipv6_sysctl_header; |
346 | 346 | ||
@@ -367,7 +367,7 @@ static ctl_table nf_ct_sysctl_table[] = { | |||
367 | .data = &nf_ct_frag6_low_thresh, | 367 | .data = &nf_ct_frag6_low_thresh, |
368 | .maxlen = sizeof(unsigned int), | 368 | .maxlen = sizeof(unsigned int), |
369 | .mode = 0644, | 369 | .mode = 0644, |
370 | .proc_handler = &proc_dointvec_jiffies, | 370 | .proc_handler = &proc_dointvec, |
371 | }, | 371 | }, |
372 | { | 372 | { |
373 | .ctl_name = NET_NF_CONNTRACK_FRAG6_HIGH_THRESH, | 373 | .ctl_name = NET_NF_CONNTRACK_FRAG6_HIGH_THRESH, |
@@ -375,7 +375,7 @@ static ctl_table nf_ct_sysctl_table[] = { | |||
375 | .data = &nf_ct_frag6_high_thresh, | 375 | .data = &nf_ct_frag6_high_thresh, |
376 | .maxlen = sizeof(unsigned int), | 376 | .maxlen = sizeof(unsigned int), |
377 | .mode = 0644, | 377 | .mode = 0644, |
378 | .proc_handler = &proc_dointvec_jiffies, | 378 | .proc_handler = &proc_dointvec, |
379 | }, | 379 | }, |
380 | { .ctl_name = 0 } | 380 | { .ctl_name = 0 } |
381 | }; | 381 | }; |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 7640b9bb7694..c2c52af9e560 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -55,9 +55,9 @@ | |||
55 | #define NF_CT_FRAG6_LOW_THRESH 196608 /* == 192*1024 */ | 55 | #define NF_CT_FRAG6_LOW_THRESH 196608 /* == 192*1024 */ |
56 | #define NF_CT_FRAG6_TIMEOUT IPV6_FRAG_TIMEOUT | 56 | #define NF_CT_FRAG6_TIMEOUT IPV6_FRAG_TIMEOUT |
57 | 57 | ||
58 | int nf_ct_frag6_high_thresh = 256*1024; | 58 | unsigned int nf_ct_frag6_high_thresh = 256*1024; |
59 | int nf_ct_frag6_low_thresh = 192*1024; | 59 | unsigned int nf_ct_frag6_low_thresh = 192*1024; |
60 | int nf_ct_frag6_timeout = IPV6_FRAG_TIMEOUT; | 60 | unsigned long nf_ct_frag6_timeout = IPV6_FRAG_TIMEOUT; |
61 | 61 | ||
62 | struct nf_ct_frag6_skb_cb | 62 | struct nf_ct_frag6_skb_cb |
63 | { | 63 | { |
@@ -190,8 +190,10 @@ static void nf_ct_frag6_secret_rebuild(unsigned long dummy) | |||
190 | atomic_t nf_ct_frag6_mem = ATOMIC_INIT(0); | 190 | atomic_t nf_ct_frag6_mem = ATOMIC_INIT(0); |
191 | 191 | ||
192 | /* Memory Tracking Functions. */ | 192 | /* Memory Tracking Functions. */ |
193 | static inline void frag_kfree_skb(struct sk_buff *skb) | 193 | static inline void frag_kfree_skb(struct sk_buff *skb, unsigned int *work) |
194 | { | 194 | { |
195 | if (work) | ||
196 | *work -= skb->truesize; | ||
195 | atomic_sub(skb->truesize, &nf_ct_frag6_mem); | 197 | atomic_sub(skb->truesize, &nf_ct_frag6_mem); |
196 | if (NFCT_FRAG6_CB(skb)->orig) | 198 | if (NFCT_FRAG6_CB(skb)->orig) |
197 | kfree_skb(NFCT_FRAG6_CB(skb)->orig); | 199 | kfree_skb(NFCT_FRAG6_CB(skb)->orig); |
@@ -199,8 +201,11 @@ static inline void frag_kfree_skb(struct sk_buff *skb) | |||
199 | kfree_skb(skb); | 201 | kfree_skb(skb); |
200 | } | 202 | } |
201 | 203 | ||
202 | static inline void frag_free_queue(struct nf_ct_frag6_queue *fq) | 204 | static inline void frag_free_queue(struct nf_ct_frag6_queue *fq, |
205 | unsigned int *work) | ||
203 | { | 206 | { |
207 | if (work) | ||
208 | *work -= sizeof(struct nf_ct_frag6_queue); | ||
204 | atomic_sub(sizeof(struct nf_ct_frag6_queue), &nf_ct_frag6_mem); | 209 | atomic_sub(sizeof(struct nf_ct_frag6_queue), &nf_ct_frag6_mem); |
205 | kfree(fq); | 210 | kfree(fq); |
206 | } | 211 | } |
@@ -218,7 +223,8 @@ static inline struct nf_ct_frag6_queue *frag_alloc_queue(void) | |||
218 | /* Destruction primitives. */ | 223 | /* Destruction primitives. */ |
219 | 224 | ||
220 | /* Complete destruction of fq. */ | 225 | /* Complete destruction of fq. */ |
221 | static void nf_ct_frag6_destroy(struct nf_ct_frag6_queue *fq) | 226 | static void nf_ct_frag6_destroy(struct nf_ct_frag6_queue *fq, |
227 | unsigned int *work) | ||
222 | { | 228 | { |
223 | struct sk_buff *fp; | 229 | struct sk_buff *fp; |
224 | 230 | ||
@@ -230,17 +236,17 @@ static void nf_ct_frag6_destroy(struct nf_ct_frag6_queue *fq) | |||
230 | while (fp) { | 236 | while (fp) { |
231 | struct sk_buff *xp = fp->next; | 237 | struct sk_buff *xp = fp->next; |
232 | 238 | ||
233 | frag_kfree_skb(fp); | 239 | frag_kfree_skb(fp, work); |
234 | fp = xp; | 240 | fp = xp; |
235 | } | 241 | } |
236 | 242 | ||
237 | frag_free_queue(fq); | 243 | frag_free_queue(fq, work); |
238 | } | 244 | } |
239 | 245 | ||
240 | static __inline__ void fq_put(struct nf_ct_frag6_queue *fq) | 246 | static __inline__ void fq_put(struct nf_ct_frag6_queue *fq, unsigned int *work) |
241 | { | 247 | { |
242 | if (atomic_dec_and_test(&fq->refcnt)) | 248 | if (atomic_dec_and_test(&fq->refcnt)) |
243 | nf_ct_frag6_destroy(fq); | 249 | nf_ct_frag6_destroy(fq, work); |
244 | } | 250 | } |
245 | 251 | ||
246 | /* Kill fq entry. It is not destroyed immediately, | 252 | /* Kill fq entry. It is not destroyed immediately, |
@@ -262,16 +268,21 @@ static void nf_ct_frag6_evictor(void) | |||
262 | { | 268 | { |
263 | struct nf_ct_frag6_queue *fq; | 269 | struct nf_ct_frag6_queue *fq; |
264 | struct list_head *tmp; | 270 | struct list_head *tmp; |
271 | unsigned int work; | ||
265 | 272 | ||
266 | for (;;) { | 273 | work = atomic_read(&nf_ct_frag6_mem); |
267 | if (atomic_read(&nf_ct_frag6_mem) <= nf_ct_frag6_low_thresh) | 274 | if (work <= nf_ct_frag6_low_thresh) |
268 | return; | 275 | return; |
276 | |||
277 | work -= nf_ct_frag6_low_thresh; | ||
278 | while (work > 0) { | ||
269 | read_lock(&nf_ct_frag6_lock); | 279 | read_lock(&nf_ct_frag6_lock); |
270 | if (list_empty(&nf_ct_frag6_lru_list)) { | 280 | if (list_empty(&nf_ct_frag6_lru_list)) { |
271 | read_unlock(&nf_ct_frag6_lock); | 281 | read_unlock(&nf_ct_frag6_lock); |
272 | return; | 282 | return; |
273 | } | 283 | } |
274 | tmp = nf_ct_frag6_lru_list.next; | 284 | tmp = nf_ct_frag6_lru_list.next; |
285 | BUG_ON(tmp == NULL); | ||
275 | fq = list_entry(tmp, struct nf_ct_frag6_queue, lru_list); | 286 | fq = list_entry(tmp, struct nf_ct_frag6_queue, lru_list); |
276 | atomic_inc(&fq->refcnt); | 287 | atomic_inc(&fq->refcnt); |
277 | read_unlock(&nf_ct_frag6_lock); | 288 | read_unlock(&nf_ct_frag6_lock); |
@@ -281,7 +292,7 @@ static void nf_ct_frag6_evictor(void) | |||
281 | fq_kill(fq); | 292 | fq_kill(fq); |
282 | spin_unlock(&fq->lock); | 293 | spin_unlock(&fq->lock); |
283 | 294 | ||
284 | fq_put(fq); | 295 | fq_put(fq, &work); |
285 | } | 296 | } |
286 | } | 297 | } |
287 | 298 | ||
@@ -298,7 +309,7 @@ static void nf_ct_frag6_expire(unsigned long data) | |||
298 | 309 | ||
299 | out: | 310 | out: |
300 | spin_unlock(&fq->lock); | 311 | spin_unlock(&fq->lock); |
301 | fq_put(fq); | 312 | fq_put(fq, NULL); |
302 | } | 313 | } |
303 | 314 | ||
304 | /* Creation primitives. */ | 315 | /* Creation primitives. */ |
@@ -318,7 +329,7 @@ static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash, | |||
318 | atomic_inc(&fq->refcnt); | 329 | atomic_inc(&fq->refcnt); |
319 | write_unlock(&nf_ct_frag6_lock); | 330 | write_unlock(&nf_ct_frag6_lock); |
320 | fq_in->last_in |= COMPLETE; | 331 | fq_in->last_in |= COMPLETE; |
321 | fq_put(fq_in); | 332 | fq_put(fq_in, NULL); |
322 | return fq; | 333 | return fq; |
323 | } | 334 | } |
324 | } | 335 | } |
@@ -535,7 +546,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
535 | fq->fragments = next; | 546 | fq->fragments = next; |
536 | 547 | ||
537 | fq->meat -= free_it->len; | 548 | fq->meat -= free_it->len; |
538 | frag_kfree_skb(free_it); | 549 | frag_kfree_skb(free_it, NULL); |
539 | } | 550 | } |
540 | } | 551 | } |
541 | 552 | ||
@@ -811,7 +822,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb) | |||
811 | if (nf_ct_frag6_queue(fq, clone, fhdr, nhoff) < 0) { | 822 | if (nf_ct_frag6_queue(fq, clone, fhdr, nhoff) < 0) { |
812 | spin_unlock(&fq->lock); | 823 | spin_unlock(&fq->lock); |
813 | DEBUGP("Can't insert skb to queue\n"); | 824 | DEBUGP("Can't insert skb to queue\n"); |
814 | fq_put(fq); | 825 | fq_put(fq, NULL); |
815 | goto ret_orig; | 826 | goto ret_orig; |
816 | } | 827 | } |
817 | 828 | ||
@@ -822,7 +833,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb) | |||
822 | } | 833 | } |
823 | spin_unlock(&fq->lock); | 834 | spin_unlock(&fq->lock); |
824 | 835 | ||
825 | fq_put(fq); | 836 | fq_put(fq, NULL); |
826 | return ret_skb; | 837 | return ret_skb; |
827 | 838 | ||
828 | ret_orig: | 839 | ret_orig: |
@@ -881,5 +892,6 @@ int nf_ct_frag6_init(void) | |||
881 | void nf_ct_frag6_cleanup(void) | 892 | void nf_ct_frag6_cleanup(void) |
882 | { | 893 | { |
883 | del_timer(&nf_ct_frag6_secret_timer); | 894 | del_timer(&nf_ct_frag6_secret_timer); |
895 | nf_ct_frag6_low_thresh = 0; | ||
884 | nf_ct_frag6_evictor(); | 896 | nf_ct_frag6_evictor(); |
885 | } | 897 | } |
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 59d02cbbeb9e..c3f0b0783453 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c | |||
@@ -116,7 +116,9 @@ static int llc_ui_send_data(struct sock* sk, struct sk_buff *skb, int noblock) | |||
116 | struct llc_sock* llc = llc_sk(sk); | 116 | struct llc_sock* llc = llc_sk(sk); |
117 | int rc = 0; | 117 | int rc = 0; |
118 | 118 | ||
119 | if (unlikely(llc_data_accept_state(llc->state) || llc->p_flag)) { | 119 | if (unlikely(llc_data_accept_state(llc->state) || |
120 | llc->remote_busy_flag || | ||
121 | llc->p_flag)) { | ||
120 | long timeout = sock_sndtimeo(sk, noblock); | 122 | long timeout = sock_sndtimeo(sk, noblock); |
121 | 123 | ||
122 | rc = llc_ui_wait_for_busy_core(sk, timeout); | 124 | rc = llc_ui_wait_for_busy_core(sk, timeout); |
@@ -542,6 +544,7 @@ static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout) | |||
542 | if (sk_wait_event(sk, &timeout, | 544 | if (sk_wait_event(sk, &timeout, |
543 | (sk->sk_shutdown & RCV_SHUTDOWN) || | 545 | (sk->sk_shutdown & RCV_SHUTDOWN) || |
544 | (!llc_data_accept_state(llc->state) && | 546 | (!llc_data_accept_state(llc->state) && |
547 | !llc->remote_busy_flag && | ||
545 | !llc->p_flag))) | 548 | !llc->p_flag))) |
546 | break; | 549 | break; |
547 | rc = -ERESTARTSYS; | 550 | rc = -ERESTARTSYS; |
diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c index b0bcfb1f12dd..91fb6bc1b116 100644 --- a/net/llc/llc_c_ac.c +++ b/net/llc/llc_c_ac.c | |||
@@ -866,7 +866,8 @@ int llc_conn_ac_send_ack_if_needed(struct sock *sk, struct sk_buff *skb) | |||
866 | llc->ack_must_be_send = 1; | 866 | llc->ack_must_be_send = 1; |
867 | llc->ack_pf = pf_bit & 1; | 867 | llc->ack_pf = pf_bit & 1; |
868 | } | 868 | } |
869 | if (((llc->vR - llc->first_pdu_Ns + 129) % 128) >= llc->npta) { | 869 | if (((llc->vR - llc->first_pdu_Ns + 1 + LLC_2_SEQ_NBR_MODULO) |
870 | % LLC_2_SEQ_NBR_MODULO) >= llc->npta) { | ||
870 | llc_conn_ac_send_rr_rsp_f_set_ackpf(sk, skb); | 871 | llc_conn_ac_send_rr_rsp_f_set_ackpf(sk, skb); |
871 | llc->ack_must_be_send = 0; | 872 | llc->ack_must_be_send = 0; |
872 | llc->ack_pf = 0; | 873 | llc->ack_pf = 0; |
@@ -994,8 +995,8 @@ static int llc_conn_ac_inc_npta_value(struct sock *sk, struct sk_buff *skb) | |||
994 | llc->dec_step = 0; | 995 | llc->dec_step = 0; |
995 | llc->dec_cntr = llc->inc_cntr = 2; | 996 | llc->dec_cntr = llc->inc_cntr = 2; |
996 | ++llc->npta; | 997 | ++llc->npta; |
997 | if (llc->npta > 127) | 998 | if (llc->npta > ~LLC_2_SEQ_NBR_MODULO) |
998 | llc->npta = 127 ; | 999 | llc->npta = ~LLC_2_SEQ_NBR_MODULO ; |
999 | } else | 1000 | } else |
1000 | --llc->inc_cntr; | 1001 | --llc->inc_cntr; |
1001 | return 0; | 1002 | return 0; |
@@ -1065,9 +1066,10 @@ int llc_conn_ac_dec_tx_win_size(struct sock *sk, struct sk_buff *skb) | |||
1065 | struct llc_sock *llc = llc_sk(sk); | 1066 | struct llc_sock *llc = llc_sk(sk); |
1066 | u8 unacked_pdu = skb_queue_len(&llc->pdu_unack_q); | 1067 | u8 unacked_pdu = skb_queue_len(&llc->pdu_unack_q); |
1067 | 1068 | ||
1068 | llc->k -= unacked_pdu; | 1069 | if (llc->k - unacked_pdu < 1) |
1069 | if (llc->k < 2) | 1070 | llc->k = 1; |
1070 | llc->k = 2; | 1071 | else |
1072 | llc->k -= unacked_pdu; | ||
1071 | return 0; | 1073 | return 0; |
1072 | } | 1074 | } |
1073 | 1075 | ||
@@ -1084,8 +1086,8 @@ int llc_conn_ac_inc_tx_win_size(struct sock *sk, struct sk_buff *skb) | |||
1084 | struct llc_sock *llc = llc_sk(sk); | 1086 | struct llc_sock *llc = llc_sk(sk); |
1085 | 1087 | ||
1086 | llc->k += 1; | 1088 | llc->k += 1; |
1087 | if (llc->k > 128) | 1089 | if (llc->k > ~LLC_2_SEQ_NBR_MODULO) |
1088 | llc->k = 128 ; | 1090 | llc->k = ~LLC_2_SEQ_NBR_MODULO ; |
1089 | return 0; | 1091 | return 0; |
1090 | } | 1092 | } |
1091 | 1093 | ||
@@ -1309,7 +1311,7 @@ int llc_conn_ac_set_vs_nr(struct sock *sk, struct sk_buff *skb) | |||
1309 | 1311 | ||
1310 | static int llc_conn_ac_inc_vs_by_1(struct sock *sk, struct sk_buff *skb) | 1312 | static int llc_conn_ac_inc_vs_by_1(struct sock *sk, struct sk_buff *skb) |
1311 | { | 1313 | { |
1312 | llc_sk(sk)->vS = (llc_sk(sk)->vS + 1) % 128; | 1314 | llc_sk(sk)->vS = (llc_sk(sk)->vS + 1) % LLC_2_SEQ_NBR_MODULO; |
1313 | return 0; | 1315 | return 0; |
1314 | } | 1316 | } |
1315 | 1317 | ||
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 9a67c796b385..ea094b231d62 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -1395,6 +1395,13 @@ void nf_conntrack_cleanup(void) | |||
1395 | kmem_cache_destroy(nf_conntrack_expect_cachep); | 1395 | kmem_cache_destroy(nf_conntrack_expect_cachep); |
1396 | free_conntrack_hash(nf_conntrack_hash, nf_conntrack_vmalloc, | 1396 | free_conntrack_hash(nf_conntrack_hash, nf_conntrack_vmalloc, |
1397 | nf_conntrack_htable_size); | 1397 | nf_conntrack_htable_size); |
1398 | |||
1399 | /* free l3proto protocol tables */ | ||
1400 | for (i = 0; i < PF_MAX; i++) | ||
1401 | if (nf_ct_protos[i]) { | ||
1402 | kfree(nf_ct_protos[i]); | ||
1403 | nf_ct_protos[i] = NULL; | ||
1404 | } | ||
1398 | } | 1405 | } |
1399 | 1406 | ||
1400 | static struct list_head *alloc_hashtable(int size, int *vmalloced) | 1407 | static struct list_head *alloc_hashtable(int size, int *vmalloced) |
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 156680ddb042..5a6fcf349bdf 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c | |||
@@ -970,6 +970,12 @@ static int tcp_packet(struct nf_conn *conntrack, | |||
970 | conntrack->timeout.function((unsigned long) | 970 | conntrack->timeout.function((unsigned long) |
971 | conntrack); | 971 | conntrack); |
972 | return -NF_REPEAT; | 972 | return -NF_REPEAT; |
973 | } else { | ||
974 | write_unlock_bh(&tcp_lock); | ||
975 | if (LOG_INVALID(IPPROTO_TCP)) | ||
976 | nf_log_packet(pf, 0, skb, NULL, NULL, | ||
977 | NULL, "nf_ct_tcp: invalid SYN"); | ||
978 | return -NF_ACCEPT; | ||
973 | } | 979 | } |
974 | case TCP_CONNTRACK_CLOSE: | 980 | case TCP_CONNTRACK_CLOSE: |
975 | if (index == TCP_RST_SET | 981 | if (index == TCP_RST_SET |
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 45224db4fe2f..5af381f9fe3d 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c | |||
@@ -694,7 +694,7 @@ static int init_or_cleanup(int init) | |||
694 | cleanup_proc_stat: | 694 | cleanup_proc_stat: |
695 | #endif | 695 | #endif |
696 | #ifdef CONFIG_PROC_FS | 696 | #ifdef CONFIG_PROC_FS |
697 | proc_net_remove("nf_conntrack_stat"); | 697 | remove_proc_entry("nf_conntrack", proc_net_stat); |
698 | cleanup_proc_exp: | 698 | cleanup_proc_exp: |
699 | proc_net_remove("nf_conntrack_expect"); | 699 | proc_net_remove("nf_conntrack_expect"); |
700 | cleanup_proc: | 700 | cleanup_proc: |
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 83f4c53030fc..a60c59b97631 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c | |||
@@ -223,6 +223,12 @@ static inline int nfnetlink_rcv_msg(struct sk_buff *skb, | |||
223 | NFNL_SUBSYS_ID(nlh->nlmsg_type), | 223 | NFNL_SUBSYS_ID(nlh->nlmsg_type), |
224 | NFNL_MSG_TYPE(nlh->nlmsg_type)); | 224 | NFNL_MSG_TYPE(nlh->nlmsg_type)); |
225 | 225 | ||
226 | if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) { | ||
227 | DEBUGP("missing CAP_NET_ADMIN\n"); | ||
228 | *errp = -EPERM; | ||
229 | return -1; | ||
230 | } | ||
231 | |||
226 | /* Only requests are handled by kernel now. */ | 232 | /* Only requests are handled by kernel now. */ |
227 | if (!(nlh->nlmsg_flags & NLM_F_REQUEST)) { | 233 | if (!(nlh->nlmsg_flags & NLM_F_REQUEST)) { |
228 | DEBUGP("received non-request message\n"); | 234 | DEBUGP("received non-request message\n"); |
@@ -240,15 +246,12 @@ static inline int nfnetlink_rcv_msg(struct sk_buff *skb, | |||
240 | ss = nfnetlink_get_subsys(type); | 246 | ss = nfnetlink_get_subsys(type); |
241 | if (!ss) { | 247 | if (!ss) { |
242 | #ifdef CONFIG_KMOD | 248 | #ifdef CONFIG_KMOD |
243 | if (cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) { | 249 | /* don't call nfnl_shunlock, since it would reenter |
244 | /* don't call nfnl_shunlock, since it would reenter | 250 | * with further packet processing */ |
245 | * with further packet processing */ | 251 | up(&nfnl_sem); |
246 | up(&nfnl_sem); | 252 | request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type)); |
247 | request_module("nfnetlink-subsys-%d", | 253 | nfnl_shlock(); |
248 | NFNL_SUBSYS_ID(type)); | 254 | ss = nfnetlink_get_subsys(type); |
249 | nfnl_shlock(); | ||
250 | ss = nfnetlink_get_subsys(type); | ||
251 | } | ||
252 | if (!ss) | 255 | if (!ss) |
253 | #endif | 256 | #endif |
254 | goto err_inval; | 257 | goto err_inval; |
@@ -260,13 +263,6 @@ static inline int nfnetlink_rcv_msg(struct sk_buff *skb, | |||
260 | goto err_inval; | 263 | goto err_inval; |
261 | } | 264 | } |
262 | 265 | ||
263 | if (nc->cap_required && | ||
264 | !cap_raised(NETLINK_CB(skb).eff_cap, nc->cap_required)) { | ||
265 | DEBUGP("permission denied for type %d\n", type); | ||
266 | *errp = -EPERM; | ||
267 | return -1; | ||
268 | } | ||
269 | |||
270 | { | 266 | { |
271 | u_int16_t attr_count = | 267 | u_int16_t attr_count = |
272 | ss->cb[NFNL_MSG_TYPE(nlh->nlmsg_type)].attr_count; | 268 | ss->cb[NFNL_MSG_TYPE(nlh->nlmsg_type)].attr_count; |
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index d194676f3655..cba63729313d 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
@@ -862,11 +862,9 @@ out_put: | |||
862 | 862 | ||
863 | static struct nfnl_callback nfulnl_cb[NFULNL_MSG_MAX] = { | 863 | static struct nfnl_callback nfulnl_cb[NFULNL_MSG_MAX] = { |
864 | [NFULNL_MSG_PACKET] = { .call = nfulnl_recv_unsupp, | 864 | [NFULNL_MSG_PACKET] = { .call = nfulnl_recv_unsupp, |
865 | .attr_count = NFULA_MAX, | 865 | .attr_count = NFULA_MAX, }, |
866 | .cap_required = CAP_NET_ADMIN, }, | ||
867 | [NFULNL_MSG_CONFIG] = { .call = nfulnl_recv_config, | 866 | [NFULNL_MSG_CONFIG] = { .call = nfulnl_recv_config, |
868 | .attr_count = NFULA_CFG_MAX, | 867 | .attr_count = NFULA_CFG_MAX, }, |
869 | .cap_required = CAP_NET_ADMIN }, | ||
870 | }; | 868 | }; |
871 | 869 | ||
872 | static struct nfnetlink_subsystem nfulnl_subsys = { | 870 | static struct nfnetlink_subsystem nfulnl_subsys = { |
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index f065a6c94953..f28460b61e47 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c | |||
@@ -931,14 +931,11 @@ out_put: | |||
931 | 931 | ||
932 | static struct nfnl_callback nfqnl_cb[NFQNL_MSG_MAX] = { | 932 | static struct nfnl_callback nfqnl_cb[NFQNL_MSG_MAX] = { |
933 | [NFQNL_MSG_PACKET] = { .call = nfqnl_recv_unsupp, | 933 | [NFQNL_MSG_PACKET] = { .call = nfqnl_recv_unsupp, |
934 | .attr_count = NFQA_MAX, | 934 | .attr_count = NFQA_MAX, }, |
935 | .cap_required = CAP_NET_ADMIN }, | ||
936 | [NFQNL_MSG_VERDICT] = { .call = nfqnl_recv_verdict, | 935 | [NFQNL_MSG_VERDICT] = { .call = nfqnl_recv_verdict, |
937 | .attr_count = NFQA_MAX, | 936 | .attr_count = NFQA_MAX, }, |
938 | .cap_required = CAP_NET_ADMIN }, | ||
939 | [NFQNL_MSG_CONFIG] = { .call = nfqnl_recv_config, | 937 | [NFQNL_MSG_CONFIG] = { .call = nfqnl_recv_config, |
940 | .attr_count = NFQA_CFG_MAX, | 938 | .attr_count = NFQA_CFG_MAX, }, |
941 | .cap_required = CAP_NET_ADMIN }, | ||
942 | }; | 939 | }; |
943 | 940 | ||
944 | static struct nfnetlink_subsystem nfqnl_subsys = { | 941 | static struct nfnetlink_subsystem nfqnl_subsys = { |
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index e50e7cf43737..c6a51911e71e 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -1178,6 +1178,7 @@ svc_recv(struct svc_serv *serv, struct svc_rqst *rqstp, long timeout) | |||
1178 | arg->tail[0].iov_len = 0; | 1178 | arg->tail[0].iov_len = 0; |
1179 | 1179 | ||
1180 | try_to_freeze(); | 1180 | try_to_freeze(); |
1181 | cond_resched(); | ||
1181 | if (signalled()) | 1182 | if (signalled()) |
1182 | return -EINTR; | 1183 | return -EINTR; |
1183 | 1184 | ||
diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 8aaf74e64183..2f45fd2969d0 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc | |||
@@ -117,6 +117,8 @@ use strict; | |||
117 | # struct my_struct { | 117 | # struct my_struct { |
118 | # int a; | 118 | # int a; |
119 | # int b; | 119 | # int b; |
120 | # /* private: */ | ||
121 | # int c; | ||
120 | # }; | 122 | # }; |
121 | # | 123 | # |
122 | # All descriptions can be multiline, except the short function description. | 124 | # All descriptions can be multiline, except the short function description. |
@@ -1304,6 +1306,12 @@ sub dump_struct($$) { | |||
1304 | # ignore embedded structs or unions | 1306 | # ignore embedded structs or unions |
1305 | $members =~ s/{.*?}//g; | 1307 | $members =~ s/{.*?}//g; |
1306 | 1308 | ||
1309 | # ignore members marked private: | ||
1310 | $members =~ s/\/\*.*?private:.*?public:.*?\*\///gos; | ||
1311 | $members =~ s/\/\*.*?private:.*//gos; | ||
1312 | # strip comments: | ||
1313 | $members =~ s/\/\*.*?\*\///gos; | ||
1314 | |||
1307 | create_parameterlist($members, ';', $file); | 1315 | create_parameterlist($members, ';', $file); |
1308 | 1316 | ||
1309 | output_declaration($declaration_name, | 1317 | output_declaration($declaration_name, |
@@ -1329,6 +1337,7 @@ sub dump_enum($$) { | |||
1329 | my $x = shift; | 1337 | my $x = shift; |
1330 | my $file = shift; | 1338 | my $file = shift; |
1331 | 1339 | ||
1340 | $x =~ s@/\*.*?\*/@@gos; # strip comments. | ||
1332 | if ($x =~ /enum\s+(\w+)\s*{(.*)}/) { | 1341 | if ($x =~ /enum\s+(\w+)\s*{(.*)}/) { |
1333 | $declaration_name = $1; | 1342 | $declaration_name = $1; |
1334 | my $members = $2; | 1343 | my $members = $2; |
@@ -1365,6 +1374,7 @@ sub dump_typedef($$) { | |||
1365 | my $x = shift; | 1374 | my $x = shift; |
1366 | my $file = shift; | 1375 | my $file = shift; |
1367 | 1376 | ||
1377 | $x =~ s@/\*.*?\*/@@gos; # strip comments. | ||
1368 | while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) { | 1378 | while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) { |
1369 | $x =~ s/\(*.\)\s*;$/;/; | 1379 | $x =~ s/\(*.\)\s*;$/;/; |
1370 | $x =~ s/\[*.\]\s*;$/;/; | 1380 | $x =~ s/\[*.\]\s*;$/;/; |
@@ -1420,7 +1430,7 @@ sub create_parameterlist($$$) { | |||
1420 | $type = $arg; | 1430 | $type = $arg; |
1421 | $type =~ s/([^\(]+\(\*)$param/$1/; | 1431 | $type =~ s/([^\(]+\(\*)$param/$1/; |
1422 | push_parameter($param, $type, $file); | 1432 | push_parameter($param, $type, $file); |
1423 | } else { | 1433 | } elsif ($arg) { |
1424 | $arg =~ s/\s*:\s*/:/g; | 1434 | $arg =~ s/\s*:\s*/:/g; |
1425 | $arg =~ s/\s*\[/\[/g; | 1435 | $arg =~ s/\s*\[/\[/g; |
1426 | 1436 | ||
@@ -1628,7 +1638,6 @@ sub process_state3_type($$) { | |||
1628 | my $x = shift; | 1638 | my $x = shift; |
1629 | my $file = shift; | 1639 | my $file = shift; |
1630 | 1640 | ||
1631 | $x =~ s@/\*.*?\*/@@gos; # strip comments. | ||
1632 | $x =~ s@[\r\n]+@ @gos; # strip newlines/cr's. | 1641 | $x =~ s@[\r\n]+@ @gos; # strip newlines/cr's. |
1633 | $x =~ s@^\s+@@gos; # strip leading spaces | 1642 | $x =~ s@^\s+@@gos; # strip leading spaces |
1634 | $x =~ s@\s+$@@gos; # strip trailing spaces | 1643 | $x =~ s@\s+$@@gos; # strip trailing spaces |
diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c index 7c835abd99bc..3f30c57676c1 100644 --- a/sound/oss/ad1848.c +++ b/sound/oss/ad1848.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/module.h> | 47 | #include <linux/module.h> |
48 | #include <linux/stddef.h> | 48 | #include <linux/stddef.h> |
49 | #include <linux/pm.h> | 49 | #include <linux/pm.h> |
50 | #include <linux/pm_legacy.h> | ||
50 | #include <linux/isapnp.h> | 51 | #include <linux/isapnp.h> |
51 | #include <linux/pnp.h> | 52 | #include <linux/pnp.h> |
52 | #include <linux/spinlock.h> | 53 | #include <linux/spinlock.h> |
diff --git a/sound/oss/cs4281/cs4281m.c b/sound/oss/cs4281/cs4281m.c index d0d3963e1b83..adc689649fe1 100644 --- a/sound/oss/cs4281/cs4281m.c +++ b/sound/oss/cs4281/cs4281m.c | |||
@@ -298,6 +298,7 @@ struct cs4281_state { | |||
298 | struct cs4281_pipeline pl[CS4281_NUMBER_OF_PIPELINES]; | 298 | struct cs4281_pipeline pl[CS4281_NUMBER_OF_PIPELINES]; |
299 | }; | 299 | }; |
300 | 300 | ||
301 | #include <linux/pm_legacy.h> | ||
301 | #include "cs4281pm-24.c" | 302 | #include "cs4281pm-24.c" |
302 | 303 | ||
303 | #if CSDEBUG | 304 | #if CSDEBUG |
diff --git a/sound/oss/maestro.c b/sound/oss/maestro.c index 3dce504e6d6d..3abd3541cbc7 100644 --- a/sound/oss/maestro.c +++ b/sound/oss/maestro.c | |||
@@ -231,6 +231,7 @@ | |||
231 | #include <asm/uaccess.h> | 231 | #include <asm/uaccess.h> |
232 | 232 | ||
233 | #include <linux/pm.h> | 233 | #include <linux/pm.h> |
234 | #include <linux/pm_legacy.h> | ||
234 | static int maestro_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *d); | 235 | static int maestro_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *d); |
235 | 236 | ||
236 | #include "maestro.h" | 237 | #include "maestro.h" |
diff --git a/sound/oss/nm256_audio.c b/sound/oss/nm256_audio.c index 66970062eb36..0ce2c404a730 100644 --- a/sound/oss/nm256_audio.c +++ b/sound/oss/nm256_audio.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/pm.h> | 27 | #include <linux/pm.h> |
28 | #include <linux/pm_legacy.h> | ||
28 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
29 | #include <linux/spinlock.h> | 30 | #include <linux/spinlock.h> |
30 | #include "sound_config.h" | 31 | #include "sound_config.h" |
diff --git a/sound/oss/opl3sa2.c b/sound/oss/opl3sa2.c index 2efbd865109b..cd41d0e4706a 100644 --- a/sound/oss/opl3sa2.c +++ b/sound/oss/opl3sa2.c | |||
@@ -70,6 +70,7 @@ | |||
70 | #include <linux/module.h> | 70 | #include <linux/module.h> |
71 | #include <linux/delay.h> | 71 | #include <linux/delay.h> |
72 | #include <linux/pm.h> | 72 | #include <linux/pm.h> |
73 | #include <linux/pm_legacy.h> | ||
73 | #include "sound_config.h" | 74 | #include "sound_config.h" |
74 | 75 | ||
75 | #include "ad1848.h" | 76 | #include "ad1848.h" |
@@ -138,7 +139,7 @@ typedef struct { | |||
138 | struct pnp_dev* pdev; | 139 | struct pnp_dev* pdev; |
139 | int activated; /* Whether said devices have been activated */ | 140 | int activated; /* Whether said devices have been activated */ |
140 | #endif | 141 | #endif |
141 | #ifdef CONFIG_PM | 142 | #ifdef CONFIG_PM_LEGACY |
142 | unsigned int in_suspend; | 143 | unsigned int in_suspend; |
143 | struct pm_dev *pmdev; | 144 | struct pm_dev *pmdev; |
144 | #endif | 145 | #endif |
@@ -341,7 +342,7 @@ static void opl3sa2_mixer_reset(opl3sa2_state_t* devc) | |||
341 | } | 342 | } |
342 | 343 | ||
343 | /* Currently only used for power management */ | 344 | /* Currently only used for power management */ |
344 | #ifdef CONFIG_PM | 345 | #ifdef CONFIG_PM_LEGACY |
345 | static void opl3sa2_mixer_restore(opl3sa2_state_t* devc) | 346 | static void opl3sa2_mixer_restore(opl3sa2_state_t* devc) |
346 | { | 347 | { |
347 | if (devc) { | 348 | if (devc) { |
@@ -354,7 +355,7 @@ static void opl3sa2_mixer_restore(opl3sa2_state_t* devc) | |||
354 | } | 355 | } |
355 | } | 356 | } |
356 | } | 357 | } |
357 | #endif | 358 | #endif /* CONFIG_PM_LEGACY */ |
358 | 359 | ||
359 | static inline void arg_to_vol_mono(unsigned int vol, int* value) | 360 | static inline void arg_to_vol_mono(unsigned int vol, int* value) |
360 | { | 361 | { |
@@ -831,7 +832,8 @@ static struct pnp_driver opl3sa2_driver = { | |||
831 | 832 | ||
832 | /* End of component functions */ | 833 | /* End of component functions */ |
833 | 834 | ||
834 | #ifdef CONFIG_PM | 835 | #ifdef CONFIG_PM_LEGACY |
836 | |||
835 | static DEFINE_SPINLOCK(opl3sa2_lock); | 837 | static DEFINE_SPINLOCK(opl3sa2_lock); |
836 | 838 | ||
837 | /* Power Management support functions */ | 839 | /* Power Management support functions */ |
@@ -906,7 +908,7 @@ static int opl3sa2_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *dat | |||
906 | } | 908 | } |
907 | return 0; | 909 | return 0; |
908 | } | 910 | } |
909 | #endif /* CONFIG_PM */ | 911 | #endif /* CONFIG_PM_LEGACY */ |
910 | 912 | ||
911 | /* | 913 | /* |
912 | * Install OPL3-SA2 based card(s). | 914 | * Install OPL3-SA2 based card(s). |
@@ -1019,12 +1021,12 @@ static int __init init_opl3sa2(void) | |||
1019 | 1021 | ||
1020 | /* ewww =) */ | 1022 | /* ewww =) */ |
1021 | opl3sa2_state[card].card = card; | 1023 | opl3sa2_state[card].card = card; |
1022 | #ifdef CONFIG_PM | 1024 | #ifdef CONFIG_PM_LEGACY |
1023 | /* register our power management capabilities */ | 1025 | /* register our power management capabilities */ |
1024 | opl3sa2_state[card].pmdev = pm_register(PM_ISA_DEV, card, opl3sa2_pm_callback); | 1026 | opl3sa2_state[card].pmdev = pm_register(PM_ISA_DEV, card, opl3sa2_pm_callback); |
1025 | if (opl3sa2_state[card].pmdev) | 1027 | if (opl3sa2_state[card].pmdev) |
1026 | opl3sa2_state[card].pmdev->data = &opl3sa2_state[card]; | 1028 | opl3sa2_state[card].pmdev->data = &opl3sa2_state[card]; |
1027 | #endif /* CONFIG_PM */ | 1029 | #endif /* CONFIG_PM_LEGACY */ |
1028 | 1030 | ||
1029 | /* | 1031 | /* |
1030 | * Set the Yamaha 3D enhancement mode (aka Ymersion) if asked to and | 1032 | * Set the Yamaha 3D enhancement mode (aka Ymersion) if asked to and |
@@ -1081,7 +1083,7 @@ static void __exit cleanup_opl3sa2(void) | |||
1081 | int card; | 1083 | int card; |
1082 | 1084 | ||
1083 | for(card = 0; card < opl3sa2_cards_num; card++) { | 1085 | for(card = 0; card < opl3sa2_cards_num; card++) { |
1084 | #ifdef CONFIG_PM | 1086 | #ifdef CONFIG_PM_LEGACY |
1085 | if (opl3sa2_state[card].pmdev) | 1087 | if (opl3sa2_state[card].pmdev) |
1086 | pm_unregister(opl3sa2_state[card].pmdev); | 1088 | pm_unregister(opl3sa2_state[card].pmdev); |
1087 | #endif | 1089 | #endif |