diff options
author | Paul Mundt <lethal@linux-sh.org> | 2009-07-06 22:55:05 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2009-07-06 22:55:05 -0400 |
commit | 2b5c0c72ea404d6b554a8284031dd78748314b9e (patch) | |
tree | 468b7f3d8db0abe6a09ee221dce1de5de2bb8d12 /drivers | |
parent | 2dbc8a23cc2e677422f6dea991aca4e3d31ab65f (diff) | |
parent | dc53fffc105f68cb08ca872acd51550e89aa2e67 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 into sh/for-2.6.31
Diffstat (limited to 'drivers')
82 files changed, 2292 insertions, 1296 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index c7a527c08a09..65a0655e7fc8 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -226,8 +226,18 @@ static inline void addQ(struct hlist_head *list, CommandList_struct *c) | |||
226 | 226 | ||
227 | static inline void removeQ(CommandList_struct *c) | 227 | static inline void removeQ(CommandList_struct *c) |
228 | { | 228 | { |
229 | if (WARN_ON(hlist_unhashed(&c->list))) | 229 | /* |
230 | * After kexec/dump some commands might still | ||
231 | * be in flight, which the firmware will try | ||
232 | * to complete. Resetting the firmware doesn't work | ||
233 | * with old fw revisions, so we have to mark | ||
234 | * them off as 'stale' to prevent the driver from | ||
235 | * falling over. | ||
236 | */ | ||
237 | if (WARN_ON(hlist_unhashed(&c->list))) { | ||
238 | c->cmd_type = CMD_MSG_STALE; | ||
230 | return; | 239 | return; |
240 | } | ||
231 | 241 | ||
232 | hlist_del_init(&c->list); | 242 | hlist_del_init(&c->list); |
233 | } | 243 | } |
@@ -4246,7 +4256,8 @@ static void fail_all_cmds(unsigned long ctlr) | |||
4246 | while (!hlist_empty(&h->cmpQ)) { | 4256 | while (!hlist_empty(&h->cmpQ)) { |
4247 | c = hlist_entry(h->cmpQ.first, CommandList_struct, list); | 4257 | c = hlist_entry(h->cmpQ.first, CommandList_struct, list); |
4248 | removeQ(c); | 4258 | removeQ(c); |
4249 | c->err_info->CommandStatus = CMD_HARDWARE_ERR; | 4259 | if (c->cmd_type != CMD_MSG_STALE) |
4260 | c->err_info->CommandStatus = CMD_HARDWARE_ERR; | ||
4250 | if (c->cmd_type == CMD_RWREQ) { | 4261 | if (c->cmd_type == CMD_RWREQ) { |
4251 | complete_command(h, c, 0); | 4262 | complete_command(h, c, 0); |
4252 | } else if (c->cmd_type == CMD_IOCTL_PEND) | 4263 | } else if (c->cmd_type == CMD_IOCTL_PEND) |
diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h index cd665b00c7c5..dbaed1ea0da3 100644 --- a/drivers/block/cciss_cmd.h +++ b/drivers/block/cciss_cmd.h | |||
@@ -274,6 +274,7 @@ typedef struct _ErrorInfo_struct { | |||
274 | #define CMD_SCSI 0x03 | 274 | #define CMD_SCSI 0x03 |
275 | #define CMD_MSG_DONE 0x04 | 275 | #define CMD_MSG_DONE 0x04 |
276 | #define CMD_MSG_TIMEOUT 0x05 | 276 | #define CMD_MSG_TIMEOUT 0x05 |
277 | #define CMD_MSG_STALE 0xff | ||
277 | 278 | ||
278 | /* This structure needs to be divisible by 8 for new | 279 | /* This structure needs to be divisible by 8 for new |
279 | * indexing method. | 280 | * indexing method. |
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 0bd01f49cfd8..6a06913b01d3 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -1029,10 +1029,6 @@ config CS5535_GPIO | |||
1029 | 1029 | ||
1030 | If compiled as a module, it will be called cs5535_gpio. | 1030 | If compiled as a module, it will be called cs5535_gpio. |
1031 | 1031 | ||
1032 | config GPIO_VR41XX | ||
1033 | tristate "NEC VR4100 series General-purpose I/O Unit support" | ||
1034 | depends on CPU_VR41XX | ||
1035 | |||
1036 | config RAW_DRIVER | 1032 | config RAW_DRIVER |
1037 | tristate "RAW driver (/dev/raw/rawN)" | 1033 | tristate "RAW driver (/dev/raw/rawN)" |
1038 | depends on BLOCK | 1034 | depends on BLOCK |
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 189efcff08ce..66f779ad4f4c 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -95,7 +95,6 @@ obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o | |||
95 | obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o | 95 | obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o |
96 | obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o | 96 | obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o |
97 | obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o | 97 | obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o |
98 | obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o | ||
99 | obj-$(CONFIG_GPIO_TB0219) += tb0219.o | 98 | obj-$(CONFIG_GPIO_TB0219) += tb0219.o |
100 | obj-$(CONFIG_TELCLOCK) += tlclk.o | 99 | obj-$(CONFIG_TELCLOCK) += tlclk.o |
101 | 100 | ||
diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c index 6062b62800fd..b3ec9b10e292 100644 --- a/drivers/char/tb0219.c +++ b/drivers/char/tb0219.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for TANBAC TB0219 base board. | 2 | * Driver for TANBAC TB0219 base board. |
3 | * | 3 | * |
4 | * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2005 Yoichi Yuasa <yuasa@linux-mips.org> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
@@ -28,7 +28,7 @@ | |||
28 | #include <asm/vr41xx/giu.h> | 28 | #include <asm/vr41xx/giu.h> |
29 | #include <asm/vr41xx/tb0219.h> | 29 | #include <asm/vr41xx/tb0219.h> |
30 | 30 | ||
31 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); | 31 | MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); |
32 | MODULE_DESCRIPTION("TANBAC TB0219 base board driver"); | 32 | MODULE_DESCRIPTION("TANBAC TB0219 base board driver"); |
33 | MODULE_LICENSE("GPL"); | 33 | MODULE_LICENSE("GPL"); |
34 | 34 | ||
diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c index 54c837288d19..e69de29bb2d1 100644 --- a/drivers/char/vr41xx_giu.c +++ b/drivers/char/vr41xx_giu.c | |||
@@ -1,680 +0,0 @@ | |||
1 | /* | ||
2 | * Driver for NEC VR4100 series General-purpose I/O Unit. | ||
3 | * | ||
4 | * Copyright (C) 2002 MontaVista Software Inc. | ||
5 | * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> | ||
6 | * Copyright (C) 2003-2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | #include <linux/errno.h> | ||
23 | #include <linux/fs.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/irq.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/platform_device.h> | ||
30 | #include <linux/smp_lock.h> | ||
31 | #include <linux/spinlock.h> | ||
32 | #include <linux/types.h> | ||
33 | |||
34 | #include <asm/io.h> | ||
35 | #include <asm/vr41xx/giu.h> | ||
36 | #include <asm/vr41xx/irq.h> | ||
37 | #include <asm/vr41xx/vr41xx.h> | ||
38 | |||
39 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); | ||
40 | MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver"); | ||
41 | MODULE_LICENSE("GPL"); | ||
42 | |||
43 | static int major; /* default is dynamic major device number */ | ||
44 | module_param(major, int, 0); | ||
45 | MODULE_PARM_DESC(major, "Major device number"); | ||
46 | |||
47 | #define GIUIOSELL 0x00 | ||
48 | #define GIUIOSELH 0x02 | ||
49 | #define GIUPIODL 0x04 | ||
50 | #define GIUPIODH 0x06 | ||
51 | #define GIUINTSTATL 0x08 | ||
52 | #define GIUINTSTATH 0x0a | ||
53 | #define GIUINTENL 0x0c | ||
54 | #define GIUINTENH 0x0e | ||
55 | #define GIUINTTYPL 0x10 | ||
56 | #define GIUINTTYPH 0x12 | ||
57 | #define GIUINTALSELL 0x14 | ||
58 | #define GIUINTALSELH 0x16 | ||
59 | #define GIUINTHTSELL 0x18 | ||
60 | #define GIUINTHTSELH 0x1a | ||
61 | #define GIUPODATL 0x1c | ||
62 | #define GIUPODATEN 0x1c | ||
63 | #define GIUPODATH 0x1e | ||
64 | #define PIOEN0 0x0100 | ||
65 | #define PIOEN1 0x0200 | ||
66 | #define GIUPODAT 0x1e | ||
67 | #define GIUFEDGEINHL 0x20 | ||
68 | #define GIUFEDGEINHH 0x22 | ||
69 | #define GIUREDGEINHL 0x24 | ||
70 | #define GIUREDGEINHH 0x26 | ||
71 | |||
72 | #define GIUUSEUPDN 0x1e0 | ||
73 | #define GIUTERMUPDN 0x1e2 | ||
74 | |||
75 | #define GPIO_HAS_PULLUPDOWN_IO 0x0001 | ||
76 | #define GPIO_HAS_OUTPUT_ENABLE 0x0002 | ||
77 | #define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100 | ||
78 | |||
79 | static spinlock_t giu_lock; | ||
80 | static unsigned long giu_flags; | ||
81 | static unsigned int giu_nr_pins; | ||
82 | |||
83 | static void __iomem *giu_base; | ||
84 | |||
85 | #define giu_read(offset) readw(giu_base + (offset)) | ||
86 | #define giu_write(offset, value) writew((value), giu_base + (offset)) | ||
87 | |||
88 | #define GPIO_PIN_OF_IRQ(irq) ((irq) - GIU_IRQ_BASE) | ||
89 | #define GIUINT_HIGH_OFFSET 16 | ||
90 | #define GIUINT_HIGH_MAX 32 | ||
91 | |||
92 | static inline uint16_t giu_set(uint16_t offset, uint16_t set) | ||
93 | { | ||
94 | uint16_t data; | ||
95 | |||
96 | data = giu_read(offset); | ||
97 | data |= set; | ||
98 | giu_write(offset, data); | ||
99 | |||
100 | return data; | ||
101 | } | ||
102 | |||
103 | static inline uint16_t giu_clear(uint16_t offset, uint16_t clear) | ||
104 | { | ||
105 | uint16_t data; | ||
106 | |||
107 | data = giu_read(offset); | ||
108 | data &= ~clear; | ||
109 | giu_write(offset, data); | ||
110 | |||
111 | return data; | ||
112 | } | ||
113 | |||
114 | static void ack_giuint_low(unsigned int irq) | ||
115 | { | ||
116 | giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq)); | ||
117 | } | ||
118 | |||
119 | static void mask_giuint_low(unsigned int irq) | ||
120 | { | ||
121 | giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); | ||
122 | } | ||
123 | |||
124 | static void mask_ack_giuint_low(unsigned int irq) | ||
125 | { | ||
126 | unsigned int pin; | ||
127 | |||
128 | pin = GPIO_PIN_OF_IRQ(irq); | ||
129 | giu_clear(GIUINTENL, 1 << pin); | ||
130 | giu_write(GIUINTSTATL, 1 << pin); | ||
131 | } | ||
132 | |||
133 | static void unmask_giuint_low(unsigned int irq) | ||
134 | { | ||
135 | giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); | ||
136 | } | ||
137 | |||
138 | static struct irq_chip giuint_low_irq_chip = { | ||
139 | .name = "GIUINTL", | ||
140 | .ack = ack_giuint_low, | ||
141 | .mask = mask_giuint_low, | ||
142 | .mask_ack = mask_ack_giuint_low, | ||
143 | .unmask = unmask_giuint_low, | ||
144 | }; | ||
145 | |||
146 | static void ack_giuint_high(unsigned int irq) | ||
147 | { | ||
148 | giu_write(GIUINTSTATH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | ||
149 | } | ||
150 | |||
151 | static void mask_giuint_high(unsigned int irq) | ||
152 | { | ||
153 | giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | ||
154 | } | ||
155 | |||
156 | static void mask_ack_giuint_high(unsigned int irq) | ||
157 | { | ||
158 | unsigned int pin; | ||
159 | |||
160 | pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET; | ||
161 | giu_clear(GIUINTENH, 1 << pin); | ||
162 | giu_write(GIUINTSTATH, 1 << pin); | ||
163 | } | ||
164 | |||
165 | static void unmask_giuint_high(unsigned int irq) | ||
166 | { | ||
167 | giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | ||
168 | } | ||
169 | |||
170 | static struct irq_chip giuint_high_irq_chip = { | ||
171 | .name = "GIUINTH", | ||
172 | .ack = ack_giuint_high, | ||
173 | .mask = mask_giuint_high, | ||
174 | .mask_ack = mask_ack_giuint_high, | ||
175 | .unmask = unmask_giuint_high, | ||
176 | }; | ||
177 | |||
178 | static int giu_get_irq(unsigned int irq) | ||
179 | { | ||
180 | uint16_t pendl, pendh, maskl, maskh; | ||
181 | int i; | ||
182 | |||
183 | pendl = giu_read(GIUINTSTATL); | ||
184 | pendh = giu_read(GIUINTSTATH); | ||
185 | maskl = giu_read(GIUINTENL); | ||
186 | maskh = giu_read(GIUINTENH); | ||
187 | |||
188 | maskl &= pendl; | ||
189 | maskh &= pendh; | ||
190 | |||
191 | if (maskl) { | ||
192 | for (i = 0; i < 16; i++) { | ||
193 | if (maskl & (1 << i)) | ||
194 | return GIU_IRQ(i); | ||
195 | } | ||
196 | } else if (maskh) { | ||
197 | for (i = 0; i < 16; i++) { | ||
198 | if (maskh & (1 << i)) | ||
199 | return GIU_IRQ(i + GIUINT_HIGH_OFFSET); | ||
200 | } | ||
201 | } | ||
202 | |||
203 | printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n", | ||
204 | maskl, pendl, maskh, pendh); | ||
205 | |||
206 | atomic_inc(&irq_err_count); | ||
207 | |||
208 | return -EINVAL; | ||
209 | } | ||
210 | |||
211 | void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal) | ||
212 | { | ||
213 | uint16_t mask; | ||
214 | |||
215 | if (pin < GIUINT_HIGH_OFFSET) { | ||
216 | mask = 1 << pin; | ||
217 | if (trigger != IRQ_TRIGGER_LEVEL) { | ||
218 | giu_set(GIUINTTYPL, mask); | ||
219 | if (signal == IRQ_SIGNAL_HOLD) | ||
220 | giu_set(GIUINTHTSELL, mask); | ||
221 | else | ||
222 | giu_clear(GIUINTHTSELL, mask); | ||
223 | if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { | ||
224 | switch (trigger) { | ||
225 | case IRQ_TRIGGER_EDGE_FALLING: | ||
226 | giu_set(GIUFEDGEINHL, mask); | ||
227 | giu_clear(GIUREDGEINHL, mask); | ||
228 | break; | ||
229 | case IRQ_TRIGGER_EDGE_RISING: | ||
230 | giu_clear(GIUFEDGEINHL, mask); | ||
231 | giu_set(GIUREDGEINHL, mask); | ||
232 | break; | ||
233 | default: | ||
234 | giu_set(GIUFEDGEINHL, mask); | ||
235 | giu_set(GIUREDGEINHL, mask); | ||
236 | break; | ||
237 | } | ||
238 | } | ||
239 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
240 | &giuint_low_irq_chip, | ||
241 | handle_edge_irq); | ||
242 | } else { | ||
243 | giu_clear(GIUINTTYPL, mask); | ||
244 | giu_clear(GIUINTHTSELL, mask); | ||
245 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
246 | &giuint_low_irq_chip, | ||
247 | handle_level_irq); | ||
248 | } | ||
249 | giu_write(GIUINTSTATL, mask); | ||
250 | } else if (pin < GIUINT_HIGH_MAX) { | ||
251 | mask = 1 << (pin - GIUINT_HIGH_OFFSET); | ||
252 | if (trigger != IRQ_TRIGGER_LEVEL) { | ||
253 | giu_set(GIUINTTYPH, mask); | ||
254 | if (signal == IRQ_SIGNAL_HOLD) | ||
255 | giu_set(GIUINTHTSELH, mask); | ||
256 | else | ||
257 | giu_clear(GIUINTHTSELH, mask); | ||
258 | if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { | ||
259 | switch (trigger) { | ||
260 | case IRQ_TRIGGER_EDGE_FALLING: | ||
261 | giu_set(GIUFEDGEINHH, mask); | ||
262 | giu_clear(GIUREDGEINHH, mask); | ||
263 | break; | ||
264 | case IRQ_TRIGGER_EDGE_RISING: | ||
265 | giu_clear(GIUFEDGEINHH, mask); | ||
266 | giu_set(GIUREDGEINHH, mask); | ||
267 | break; | ||
268 | default: | ||
269 | giu_set(GIUFEDGEINHH, mask); | ||
270 | giu_set(GIUREDGEINHH, mask); | ||
271 | break; | ||
272 | } | ||
273 | } | ||
274 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
275 | &giuint_high_irq_chip, | ||
276 | handle_edge_irq); | ||
277 | } else { | ||
278 | giu_clear(GIUINTTYPH, mask); | ||
279 | giu_clear(GIUINTHTSELH, mask); | ||
280 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
281 | &giuint_high_irq_chip, | ||
282 | handle_level_irq); | ||
283 | } | ||
284 | giu_write(GIUINTSTATH, mask); | ||
285 | } | ||
286 | } | ||
287 | EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger); | ||
288 | |||
289 | void vr41xx_set_irq_level(unsigned int pin, irq_level_t level) | ||
290 | { | ||
291 | uint16_t mask; | ||
292 | |||
293 | if (pin < GIUINT_HIGH_OFFSET) { | ||
294 | mask = 1 << pin; | ||
295 | if (level == IRQ_LEVEL_HIGH) | ||
296 | giu_set(GIUINTALSELL, mask); | ||
297 | else | ||
298 | giu_clear(GIUINTALSELL, mask); | ||
299 | giu_write(GIUINTSTATL, mask); | ||
300 | } else if (pin < GIUINT_HIGH_MAX) { | ||
301 | mask = 1 << (pin - GIUINT_HIGH_OFFSET); | ||
302 | if (level == IRQ_LEVEL_HIGH) | ||
303 | giu_set(GIUINTALSELH, mask); | ||
304 | else | ||
305 | giu_clear(GIUINTALSELH, mask); | ||
306 | giu_write(GIUINTSTATH, mask); | ||
307 | } | ||
308 | } | ||
309 | EXPORT_SYMBOL_GPL(vr41xx_set_irq_level); | ||
310 | |||
311 | gpio_data_t vr41xx_gpio_get_pin(unsigned int pin) | ||
312 | { | ||
313 | uint16_t reg, mask; | ||
314 | |||
315 | if (pin >= giu_nr_pins) | ||
316 | return GPIO_DATA_INVAL; | ||
317 | |||
318 | if (pin < 16) { | ||
319 | reg = giu_read(GIUPIODL); | ||
320 | mask = (uint16_t)1 << pin; | ||
321 | } else if (pin < 32) { | ||
322 | reg = giu_read(GIUPIODH); | ||
323 | mask = (uint16_t)1 << (pin - 16); | ||
324 | } else if (pin < 48) { | ||
325 | reg = giu_read(GIUPODATL); | ||
326 | mask = (uint16_t)1 << (pin - 32); | ||
327 | } else { | ||
328 | reg = giu_read(GIUPODATH); | ||
329 | mask = (uint16_t)1 << (pin - 48); | ||
330 | } | ||
331 | |||
332 | if (reg & mask) | ||
333 | return GPIO_DATA_HIGH; | ||
334 | |||
335 | return GPIO_DATA_LOW; | ||
336 | } | ||
337 | EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin); | ||
338 | |||
339 | int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data) | ||
340 | { | ||
341 | uint16_t offset, mask, reg; | ||
342 | unsigned long flags; | ||
343 | |||
344 | if (pin >= giu_nr_pins) | ||
345 | return -EINVAL; | ||
346 | |||
347 | if (pin < 16) { | ||
348 | offset = GIUPIODL; | ||
349 | mask = (uint16_t)1 << pin; | ||
350 | } else if (pin < 32) { | ||
351 | offset = GIUPIODH; | ||
352 | mask = (uint16_t)1 << (pin - 16); | ||
353 | } else if (pin < 48) { | ||
354 | offset = GIUPODATL; | ||
355 | mask = (uint16_t)1 << (pin - 32); | ||
356 | } else { | ||
357 | offset = GIUPODATH; | ||
358 | mask = (uint16_t)1 << (pin - 48); | ||
359 | } | ||
360 | |||
361 | spin_lock_irqsave(&giu_lock, flags); | ||
362 | |||
363 | reg = giu_read(offset); | ||
364 | if (data == GPIO_DATA_HIGH) | ||
365 | reg |= mask; | ||
366 | else | ||
367 | reg &= ~mask; | ||
368 | giu_write(offset, reg); | ||
369 | |||
370 | spin_unlock_irqrestore(&giu_lock, flags); | ||
371 | |||
372 | return 0; | ||
373 | } | ||
374 | EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin); | ||
375 | |||
376 | int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir) | ||
377 | { | ||
378 | uint16_t offset, mask, reg; | ||
379 | unsigned long flags; | ||
380 | |||
381 | if (pin >= giu_nr_pins) | ||
382 | return -EINVAL; | ||
383 | |||
384 | if (pin < 16) { | ||
385 | offset = GIUIOSELL; | ||
386 | mask = (uint16_t)1 << pin; | ||
387 | } else if (pin < 32) { | ||
388 | offset = GIUIOSELH; | ||
389 | mask = (uint16_t)1 << (pin - 16); | ||
390 | } else { | ||
391 | if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) { | ||
392 | offset = GIUPODATEN; | ||
393 | mask = (uint16_t)1 << (pin - 32); | ||
394 | } else { | ||
395 | switch (pin) { | ||
396 | case 48: | ||
397 | offset = GIUPODATH; | ||
398 | mask = PIOEN0; | ||
399 | break; | ||
400 | case 49: | ||
401 | offset = GIUPODATH; | ||
402 | mask = PIOEN1; | ||
403 | break; | ||
404 | default: | ||
405 | return -EINVAL; | ||
406 | } | ||
407 | } | ||
408 | } | ||
409 | |||
410 | spin_lock_irqsave(&giu_lock, flags); | ||
411 | |||
412 | reg = giu_read(offset); | ||
413 | if (dir == GPIO_OUTPUT) | ||
414 | reg |= mask; | ||
415 | else | ||
416 | reg &= ~mask; | ||
417 | giu_write(offset, reg); | ||
418 | |||
419 | spin_unlock_irqrestore(&giu_lock, flags); | ||
420 | |||
421 | return 0; | ||
422 | } | ||
423 | EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction); | ||
424 | |||
425 | int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull) | ||
426 | { | ||
427 | uint16_t reg, mask; | ||
428 | unsigned long flags; | ||
429 | |||
430 | if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO) | ||
431 | return -EPERM; | ||
432 | |||
433 | if (pin >= 15) | ||
434 | return -EINVAL; | ||
435 | |||
436 | mask = (uint16_t)1 << pin; | ||
437 | |||
438 | spin_lock_irqsave(&giu_lock, flags); | ||
439 | |||
440 | if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) { | ||
441 | reg = giu_read(GIUTERMUPDN); | ||
442 | if (pull == GPIO_PULL_UP) | ||
443 | reg |= mask; | ||
444 | else | ||
445 | reg &= ~mask; | ||
446 | giu_write(GIUTERMUPDN, reg); | ||
447 | |||
448 | reg = giu_read(GIUUSEUPDN); | ||
449 | reg |= mask; | ||
450 | giu_write(GIUUSEUPDN, reg); | ||
451 | } else { | ||
452 | reg = giu_read(GIUUSEUPDN); | ||
453 | reg &= ~mask; | ||
454 | giu_write(GIUUSEUPDN, reg); | ||
455 | } | ||
456 | |||
457 | spin_unlock_irqrestore(&giu_lock, flags); | ||
458 | |||
459 | return 0; | ||
460 | } | ||
461 | EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown); | ||
462 | |||
463 | static ssize_t gpio_read(struct file *file, char __user *buf, size_t len, | ||
464 | loff_t *ppos) | ||
465 | { | ||
466 | unsigned int pin; | ||
467 | char value = '0'; | ||
468 | |||
469 | pin = iminor(file->f_path.dentry->d_inode); | ||
470 | if (pin >= giu_nr_pins) | ||
471 | return -EBADF; | ||
472 | |||
473 | if (vr41xx_gpio_get_pin(pin) == GPIO_DATA_HIGH) | ||
474 | value = '1'; | ||
475 | |||
476 | if (len <= 0) | ||
477 | return -EFAULT; | ||
478 | |||
479 | if (put_user(value, buf)) | ||
480 | return -EFAULT; | ||
481 | |||
482 | return 1; | ||
483 | } | ||
484 | |||
485 | static ssize_t gpio_write(struct file *file, const char __user *data, | ||
486 | size_t len, loff_t *ppos) | ||
487 | { | ||
488 | unsigned int pin; | ||
489 | size_t i; | ||
490 | char c; | ||
491 | int retval = 0; | ||
492 | |||
493 | pin = iminor(file->f_path.dentry->d_inode); | ||
494 | if (pin >= giu_nr_pins) | ||
495 | return -EBADF; | ||
496 | |||
497 | for (i = 0; i < len; i++) { | ||
498 | if (get_user(c, data + i)) | ||
499 | return -EFAULT; | ||
500 | |||
501 | switch (c) { | ||
502 | case '0': | ||
503 | retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_LOW); | ||
504 | break; | ||
505 | case '1': | ||
506 | retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_HIGH); | ||
507 | break; | ||
508 | case 'D': | ||
509 | printk(KERN_INFO "GPIO%d: pull down\n", pin); | ||
510 | retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DOWN); | ||
511 | break; | ||
512 | case 'd': | ||
513 | printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin); | ||
514 | retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE); | ||
515 | break; | ||
516 | case 'I': | ||
517 | printk(KERN_INFO "GPIO%d: input\n", pin); | ||
518 | retval = vr41xx_gpio_set_direction(pin, GPIO_INPUT); | ||
519 | break; | ||
520 | case 'O': | ||
521 | printk(KERN_INFO "GPIO%d: output\n", pin); | ||
522 | retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT); | ||
523 | break; | ||
524 | case 'o': | ||
525 | printk(KERN_INFO "GPIO%d: output disable\n", pin); | ||
526 | retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT_DISABLE); | ||
527 | break; | ||
528 | case 'P': | ||
529 | printk(KERN_INFO "GPIO%d: pull up\n", pin); | ||
530 | retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_UP); | ||
531 | break; | ||
532 | case 'p': | ||
533 | printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin); | ||
534 | retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE); | ||
535 | break; | ||
536 | default: | ||
537 | break; | ||
538 | } | ||
539 | |||
540 | if (retval < 0) | ||
541 | break; | ||
542 | } | ||
543 | |||
544 | return i; | ||
545 | } | ||
546 | |||
547 | static int gpio_open(struct inode *inode, struct file *file) | ||
548 | { | ||
549 | unsigned int pin; | ||
550 | |||
551 | cycle_kernel_lock(); | ||
552 | pin = iminor(inode); | ||
553 | if (pin >= giu_nr_pins) | ||
554 | return -EBADF; | ||
555 | |||
556 | return nonseekable_open(inode, file); | ||
557 | } | ||
558 | |||
559 | static int gpio_release(struct inode *inode, struct file *file) | ||
560 | { | ||
561 | unsigned int pin; | ||
562 | |||
563 | pin = iminor(inode); | ||
564 | if (pin >= giu_nr_pins) | ||
565 | return -EBADF; | ||
566 | |||
567 | return 0; | ||
568 | } | ||
569 | |||
570 | static const struct file_operations gpio_fops = { | ||
571 | .owner = THIS_MODULE, | ||
572 | .read = gpio_read, | ||
573 | .write = gpio_write, | ||
574 | .open = gpio_open, | ||
575 | .release = gpio_release, | ||
576 | }; | ||
577 | |||
578 | static int __devinit giu_probe(struct platform_device *dev) | ||
579 | { | ||
580 | struct resource *res; | ||
581 | unsigned int trigger, i, pin; | ||
582 | struct irq_chip *chip; | ||
583 | int irq, retval; | ||
584 | |||
585 | switch (dev->id) { | ||
586 | case GPIO_50PINS_PULLUPDOWN: | ||
587 | giu_flags = GPIO_HAS_PULLUPDOWN_IO; | ||
588 | giu_nr_pins = 50; | ||
589 | break; | ||
590 | case GPIO_36PINS: | ||
591 | giu_nr_pins = 36; | ||
592 | break; | ||
593 | case GPIO_48PINS_EDGE_SELECT: | ||
594 | giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT; | ||
595 | giu_nr_pins = 48; | ||
596 | break; | ||
597 | default: | ||
598 | printk(KERN_ERR "GIU: unknown ID %d\n", dev->id); | ||
599 | return -ENODEV; | ||
600 | } | ||
601 | |||
602 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
603 | if (!res) | ||
604 | return -EBUSY; | ||
605 | |||
606 | giu_base = ioremap(res->start, res->end - res->start + 1); | ||
607 | if (!giu_base) | ||
608 | return -ENOMEM; | ||
609 | |||
610 | retval = register_chrdev(major, "GIU", &gpio_fops); | ||
611 | if (retval < 0) { | ||
612 | iounmap(giu_base); | ||
613 | giu_base = NULL; | ||
614 | return retval; | ||
615 | } | ||
616 | |||
617 | if (major == 0) { | ||
618 | major = retval; | ||
619 | printk(KERN_INFO "GIU: major number %d\n", major); | ||
620 | } | ||
621 | |||
622 | spin_lock_init(&giu_lock); | ||
623 | |||
624 | giu_write(GIUINTENL, 0); | ||
625 | giu_write(GIUINTENH, 0); | ||
626 | |||
627 | trigger = giu_read(GIUINTTYPH) << 16; | ||
628 | trigger |= giu_read(GIUINTTYPL); | ||
629 | for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) { | ||
630 | pin = GPIO_PIN_OF_IRQ(i); | ||
631 | if (pin < GIUINT_HIGH_OFFSET) | ||
632 | chip = &giuint_low_irq_chip; | ||
633 | else | ||
634 | chip = &giuint_high_irq_chip; | ||
635 | |||
636 | if (trigger & (1 << pin)) | ||
637 | set_irq_chip_and_handler(i, chip, handle_edge_irq); | ||
638 | else | ||
639 | set_irq_chip_and_handler(i, chip, handle_level_irq); | ||
640 | |||
641 | } | ||
642 | |||
643 | irq = platform_get_irq(dev, 0); | ||
644 | if (irq < 0 || irq >= nr_irqs) | ||
645 | return -EBUSY; | ||
646 | |||
647 | return cascade_irq(irq, giu_get_irq); | ||
648 | } | ||
649 | |||
650 | static int __devexit giu_remove(struct platform_device *dev) | ||
651 | { | ||
652 | if (giu_base) { | ||
653 | iounmap(giu_base); | ||
654 | giu_base = NULL; | ||
655 | } | ||
656 | |||
657 | return 0; | ||
658 | } | ||
659 | |||
660 | static struct platform_driver giu_device_driver = { | ||
661 | .probe = giu_probe, | ||
662 | .remove = __devexit_p(giu_remove), | ||
663 | .driver = { | ||
664 | .name = "GIU", | ||
665 | .owner = THIS_MODULE, | ||
666 | }, | ||
667 | }; | ||
668 | |||
669 | static int __init vr41xx_giu_init(void) | ||
670 | { | ||
671 | return platform_driver_register(&giu_device_driver); | ||
672 | } | ||
673 | |||
674 | static void __exit vr41xx_giu_exit(void) | ||
675 | { | ||
676 | platform_driver_unregister(&giu_device_driver); | ||
677 | } | ||
678 | |||
679 | module_init(vr41xx_giu_init); | ||
680 | module_exit(vr41xx_giu_exit); | ||
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 543fccac81bb..f74edae5cb4c 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c | |||
@@ -196,8 +196,8 @@ static void allocate_broadcast_channel(struct fw_card *card, int generation) | |||
196 | { | 196 | { |
197 | int channel, bandwidth = 0; | 197 | int channel, bandwidth = 0; |
198 | 198 | ||
199 | fw_iso_resource_manage(card, generation, 1ULL << 31, | 199 | fw_iso_resource_manage(card, generation, 1ULL << 31, &channel, |
200 | &channel, &bandwidth, true); | 200 | &bandwidth, true, card->bm_transaction_data); |
201 | if (channel == 31) { | 201 | if (channel == 31) { |
202 | card->broadcast_channel_allocated = true; | 202 | card->broadcast_channel_allocated = true; |
203 | device_for_each_child(card->device, (void *)(long)generation, | 203 | device_for_each_child(card->device, (void *)(long)generation, |
@@ -230,7 +230,6 @@ static void fw_card_bm_work(struct work_struct *work) | |||
230 | bool do_reset = false; | 230 | bool do_reset = false; |
231 | bool root_device_is_running; | 231 | bool root_device_is_running; |
232 | bool root_device_is_cmc; | 232 | bool root_device_is_cmc; |
233 | __be32 lock_data[2]; | ||
234 | 233 | ||
235 | spin_lock_irqsave(&card->lock, flags); | 234 | spin_lock_irqsave(&card->lock, flags); |
236 | 235 | ||
@@ -273,22 +272,23 @@ static void fw_card_bm_work(struct work_struct *work) | |||
273 | goto pick_me; | 272 | goto pick_me; |
274 | } | 273 | } |
275 | 274 | ||
276 | lock_data[0] = cpu_to_be32(0x3f); | 275 | card->bm_transaction_data[0] = cpu_to_be32(0x3f); |
277 | lock_data[1] = cpu_to_be32(local_id); | 276 | card->bm_transaction_data[1] = cpu_to_be32(local_id); |
278 | 277 | ||
279 | spin_unlock_irqrestore(&card->lock, flags); | 278 | spin_unlock_irqrestore(&card->lock, flags); |
280 | 279 | ||
281 | rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, | 280 | rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, |
282 | irm_id, generation, SCODE_100, | 281 | irm_id, generation, SCODE_100, |
283 | CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID, | 282 | CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID, |
284 | lock_data, sizeof(lock_data)); | 283 | card->bm_transaction_data, |
284 | sizeof(card->bm_transaction_data)); | ||
285 | 285 | ||
286 | if (rcode == RCODE_GENERATION) | 286 | if (rcode == RCODE_GENERATION) |
287 | /* Another bus reset, BM work has been rescheduled. */ | 287 | /* Another bus reset, BM work has been rescheduled. */ |
288 | goto out; | 288 | goto out; |
289 | 289 | ||
290 | if (rcode == RCODE_COMPLETE && | 290 | if (rcode == RCODE_COMPLETE && |
291 | lock_data[0] != cpu_to_be32(0x3f)) { | 291 | card->bm_transaction_data[0] != cpu_to_be32(0x3f)) { |
292 | 292 | ||
293 | /* Somebody else is BM. Only act as IRM. */ | 293 | /* Somebody else is BM. Only act as IRM. */ |
294 | if (local_id == irm_id) | 294 | if (local_id == irm_id) |
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index d1d30c615b0f..ced186d7e9a9 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c | |||
@@ -125,6 +125,7 @@ struct iso_resource { | |||
125 | int generation; | 125 | int generation; |
126 | u64 channels; | 126 | u64 channels; |
127 | s32 bandwidth; | 127 | s32 bandwidth; |
128 | __be32 transaction_data[2]; | ||
128 | struct iso_resource_event *e_alloc, *e_dealloc; | 129 | struct iso_resource_event *e_alloc, *e_dealloc; |
129 | }; | 130 | }; |
130 | 131 | ||
@@ -1049,7 +1050,8 @@ static void iso_resource_work(struct work_struct *work) | |||
1049 | r->channels, &channel, &bandwidth, | 1050 | r->channels, &channel, &bandwidth, |
1050 | todo == ISO_RES_ALLOC || | 1051 | todo == ISO_RES_ALLOC || |
1051 | todo == ISO_RES_REALLOC || | 1052 | todo == ISO_RES_REALLOC || |
1052 | todo == ISO_RES_ALLOC_ONCE); | 1053 | todo == ISO_RES_ALLOC_ONCE, |
1054 | r->transaction_data); | ||
1053 | /* | 1055 | /* |
1054 | * Is this generation outdated already? As long as this resource sticks | 1056 | * Is this generation outdated already? As long as this resource sticks |
1055 | * in the idr, it will be scheduled again for a newer generation or at | 1057 | * in the idr, it will be scheduled again for a newer generation or at |
diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c index 166f19c6d38d..110e731f5574 100644 --- a/drivers/firewire/core-iso.c +++ b/drivers/firewire/core-iso.c | |||
@@ -177,9 +177,8 @@ EXPORT_SYMBOL(fw_iso_context_stop); | |||
177 | */ | 177 | */ |
178 | 178 | ||
179 | static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, | 179 | static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, |
180 | int bandwidth, bool allocate) | 180 | int bandwidth, bool allocate, __be32 data[2]) |
181 | { | 181 | { |
182 | __be32 data[2]; | ||
183 | int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0; | 182 | int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0; |
184 | 183 | ||
185 | /* | 184 | /* |
@@ -215,9 +214,9 @@ static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, | |||
215 | } | 214 | } |
216 | 215 | ||
217 | static int manage_channel(struct fw_card *card, int irm_id, int generation, | 216 | static int manage_channel(struct fw_card *card, int irm_id, int generation, |
218 | u32 channels_mask, u64 offset, bool allocate) | 217 | u32 channels_mask, u64 offset, bool allocate, __be32 data[2]) |
219 | { | 218 | { |
220 | __be32 data[2], c, all, old; | 219 | __be32 c, all, old; |
221 | int i, retry = 5; | 220 | int i, retry = 5; |
222 | 221 | ||
223 | old = all = allocate ? cpu_to_be32(~0) : 0; | 222 | old = all = allocate ? cpu_to_be32(~0) : 0; |
@@ -260,7 +259,7 @@ static int manage_channel(struct fw_card *card, int irm_id, int generation, | |||
260 | } | 259 | } |
261 | 260 | ||
262 | static void deallocate_channel(struct fw_card *card, int irm_id, | 261 | static void deallocate_channel(struct fw_card *card, int irm_id, |
263 | int generation, int channel) | 262 | int generation, int channel, __be32 buffer[2]) |
264 | { | 263 | { |
265 | u32 mask; | 264 | u32 mask; |
266 | u64 offset; | 265 | u64 offset; |
@@ -269,7 +268,7 @@ static void deallocate_channel(struct fw_card *card, int irm_id, | |||
269 | offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI : | 268 | offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI : |
270 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO; | 269 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO; |
271 | 270 | ||
272 | manage_channel(card, irm_id, generation, mask, offset, false); | 271 | manage_channel(card, irm_id, generation, mask, offset, false, buffer); |
273 | } | 272 | } |
274 | 273 | ||
275 | /** | 274 | /** |
@@ -298,7 +297,7 @@ static void deallocate_channel(struct fw_card *card, int irm_id, | |||
298 | */ | 297 | */ |
299 | void fw_iso_resource_manage(struct fw_card *card, int generation, | 298 | void fw_iso_resource_manage(struct fw_card *card, int generation, |
300 | u64 channels_mask, int *channel, int *bandwidth, | 299 | u64 channels_mask, int *channel, int *bandwidth, |
301 | bool allocate) | 300 | bool allocate, __be32 buffer[2]) |
302 | { | 301 | { |
303 | u32 channels_hi = channels_mask; /* channels 31...0 */ | 302 | u32 channels_hi = channels_mask; /* channels 31...0 */ |
304 | u32 channels_lo = channels_mask >> 32; /* channels 63...32 */ | 303 | u32 channels_lo = channels_mask >> 32; /* channels 63...32 */ |
@@ -310,10 +309,12 @@ void fw_iso_resource_manage(struct fw_card *card, int generation, | |||
310 | 309 | ||
311 | if (channels_hi) | 310 | if (channels_hi) |
312 | c = manage_channel(card, irm_id, generation, channels_hi, | 311 | c = manage_channel(card, irm_id, generation, channels_hi, |
313 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, allocate); | 312 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, |
313 | allocate, buffer); | ||
314 | if (channels_lo && c < 0) { | 314 | if (channels_lo && c < 0) { |
315 | c = manage_channel(card, irm_id, generation, channels_lo, | 315 | c = manage_channel(card, irm_id, generation, channels_lo, |
316 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, allocate); | 316 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, |
317 | allocate, buffer); | ||
317 | if (c >= 0) | 318 | if (c >= 0) |
318 | c += 32; | 319 | c += 32; |
319 | } | 320 | } |
@@ -325,12 +326,13 @@ void fw_iso_resource_manage(struct fw_card *card, int generation, | |||
325 | if (*bandwidth == 0) | 326 | if (*bandwidth == 0) |
326 | return; | 327 | return; |
327 | 328 | ||
328 | ret = manage_bandwidth(card, irm_id, generation, *bandwidth, allocate); | 329 | ret = manage_bandwidth(card, irm_id, generation, *bandwidth, |
330 | allocate, buffer); | ||
329 | if (ret < 0) | 331 | if (ret < 0) |
330 | *bandwidth = 0; | 332 | *bandwidth = 0; |
331 | 333 | ||
332 | if (allocate && ret < 0 && c >= 0) { | 334 | if (allocate && ret < 0 && c >= 0) { |
333 | deallocate_channel(card, irm_id, generation, c); | 335 | deallocate_channel(card, irm_id, generation, c, buffer); |
334 | *channel = ret; | 336 | *channel = ret; |
335 | } | 337 | } |
336 | } | 338 | } |
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index c3cfc647e5e3..6052816be353 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h | |||
@@ -120,7 +120,8 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event); | |||
120 | 120 | ||
121 | int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma); | 121 | int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma); |
122 | void fw_iso_resource_manage(struct fw_card *card, int generation, | 122 | void fw_iso_resource_manage(struct fw_card *card, int generation, |
123 | u64 channels_mask, int *channel, int *bandwidth, bool allocate); | 123 | u64 channels_mask, int *channel, int *bandwidth, |
124 | bool allocate, __be32 buffer[2]); | ||
124 | 125 | ||
125 | 126 | ||
126 | /* -topology */ | 127 | /* -topology */ |
diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index 24c45635376a..8d51568ee143 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c | |||
@@ -201,6 +201,12 @@ static struct fw_device *target_device(struct sbp2_target *tgt) | |||
201 | #define SBP2_CYCLE_LIMIT (0xc8 << 12) /* 200 125us cycles */ | 201 | #define SBP2_CYCLE_LIMIT (0xc8 << 12) /* 200 125us cycles */ |
202 | 202 | ||
203 | /* | 203 | /* |
204 | * There is no transport protocol limit to the CDB length, but we implement | ||
205 | * a fixed length only. 16 bytes is enough for disks larger than 2 TB. | ||
206 | */ | ||
207 | #define SBP2_MAX_CDB_SIZE 16 | ||
208 | |||
209 | /* | ||
204 | * The default maximum s/g segment size of a FireWire controller is | 210 | * The default maximum s/g segment size of a FireWire controller is |
205 | * usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to | 211 | * usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to |
206 | * be quadlet-aligned, we set the length limit to 0xffff & ~3. | 212 | * be quadlet-aligned, we set the length limit to 0xffff & ~3. |
@@ -312,7 +318,7 @@ struct sbp2_command_orb { | |||
312 | struct sbp2_pointer next; | 318 | struct sbp2_pointer next; |
313 | struct sbp2_pointer data_descriptor; | 319 | struct sbp2_pointer data_descriptor; |
314 | __be32 misc; | 320 | __be32 misc; |
315 | u8 command_block[12]; | 321 | u8 command_block[SBP2_MAX_CDB_SIZE]; |
316 | } request; | 322 | } request; |
317 | struct scsi_cmnd *cmd; | 323 | struct scsi_cmnd *cmd; |
318 | scsi_done_fn_t done; | 324 | scsi_done_fn_t done; |
@@ -1146,6 +1152,8 @@ static int sbp2_probe(struct device *dev) | |||
1146 | if (fw_device_enable_phys_dma(device) < 0) | 1152 | if (fw_device_enable_phys_dma(device) < 0) |
1147 | goto fail_shost_put; | 1153 | goto fail_shost_put; |
1148 | 1154 | ||
1155 | shost->max_cmd_len = SBP2_MAX_CDB_SIZE; | ||
1156 | |||
1149 | if (scsi_add_host(shost, &unit->device) < 0) | 1157 | if (scsi_add_host(shost, &unit->device) < 0) |
1150 | goto fail_shost_put; | 1158 | goto fail_shost_put; |
1151 | 1159 | ||
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 3582c39f9725..96dda81c9228 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -79,6 +79,12 @@ config GPIO_XILINX | |||
79 | help | 79 | help |
80 | Say yes here to support the Xilinx FPGA GPIO device | 80 | Say yes here to support the Xilinx FPGA GPIO device |
81 | 81 | ||
82 | config GPIO_VR41XX | ||
83 | tristate "NEC VR4100 series General-purpose I/O Uint support" | ||
84 | depends on CPU_VR41XX | ||
85 | help | ||
86 | Say yes here to support the NEC VR4100 series General-purpose I/O Uint | ||
87 | |||
82 | comment "I2C GPIO expanders:" | 88 | comment "I2C GPIO expanders:" |
83 | 89 | ||
84 | config GPIO_MAX732X | 90 | config GPIO_MAX732X |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index ef90203e8f3c..9244c6fcd8be 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -13,3 +13,4 @@ obj-$(CONFIG_GPIO_PL061) += pl061.o | |||
13 | obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o | 13 | obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o |
14 | obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o | 14 | obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o |
15 | obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o | 15 | obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o |
16 | obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o | ||
diff --git a/drivers/gpio/vr41xx_giu.c b/drivers/gpio/vr41xx_giu.c new file mode 100644 index 000000000000..b70e06133e78 --- /dev/null +++ b/drivers/gpio/vr41xx_giu.c | |||
@@ -0,0 +1,586 @@ | |||
1 | /* | ||
2 | * Driver for NEC VR4100 series General-purpose I/O Unit. | ||
3 | * | ||
4 | * Copyright (C) 2002 MontaVista Software Inc. | ||
5 | * Author: Yoichi Yuasa <source@mvista.com> | ||
6 | * Copyright (C) 2003-2009 Yoichi Yuasa <yuasa@linux-mips.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | #include <linux/errno.h> | ||
23 | #include <linux/fs.h> | ||
24 | #include <linux/gpio.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/io.h> | ||
28 | #include <linux/irq.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/platform_device.h> | ||
32 | #include <linux/smp_lock.h> | ||
33 | #include <linux/spinlock.h> | ||
34 | #include <linux/types.h> | ||
35 | |||
36 | #include <asm/vr41xx/giu.h> | ||
37 | #include <asm/vr41xx/irq.h> | ||
38 | #include <asm/vr41xx/vr41xx.h> | ||
39 | |||
40 | MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); | ||
41 | MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver"); | ||
42 | MODULE_LICENSE("GPL"); | ||
43 | |||
44 | #define GIUIOSELL 0x00 | ||
45 | #define GIUIOSELH 0x02 | ||
46 | #define GIUPIODL 0x04 | ||
47 | #define GIUPIODH 0x06 | ||
48 | #define GIUINTSTATL 0x08 | ||
49 | #define GIUINTSTATH 0x0a | ||
50 | #define GIUINTENL 0x0c | ||
51 | #define GIUINTENH 0x0e | ||
52 | #define GIUINTTYPL 0x10 | ||
53 | #define GIUINTTYPH 0x12 | ||
54 | #define GIUINTALSELL 0x14 | ||
55 | #define GIUINTALSELH 0x16 | ||
56 | #define GIUINTHTSELL 0x18 | ||
57 | #define GIUINTHTSELH 0x1a | ||
58 | #define GIUPODATL 0x1c | ||
59 | #define GIUPODATEN 0x1c | ||
60 | #define GIUPODATH 0x1e | ||
61 | #define PIOEN0 0x0100 | ||
62 | #define PIOEN1 0x0200 | ||
63 | #define GIUPODAT 0x1e | ||
64 | #define GIUFEDGEINHL 0x20 | ||
65 | #define GIUFEDGEINHH 0x22 | ||
66 | #define GIUREDGEINHL 0x24 | ||
67 | #define GIUREDGEINHH 0x26 | ||
68 | |||
69 | #define GIUUSEUPDN 0x1e0 | ||
70 | #define GIUTERMUPDN 0x1e2 | ||
71 | |||
72 | #define GPIO_HAS_PULLUPDOWN_IO 0x0001 | ||
73 | #define GPIO_HAS_OUTPUT_ENABLE 0x0002 | ||
74 | #define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100 | ||
75 | |||
76 | enum { | ||
77 | GPIO_INPUT, | ||
78 | GPIO_OUTPUT, | ||
79 | }; | ||
80 | |||
81 | static DEFINE_SPINLOCK(giu_lock); | ||
82 | static unsigned long giu_flags; | ||
83 | |||
84 | static void __iomem *giu_base; | ||
85 | |||
86 | #define giu_read(offset) readw(giu_base + (offset)) | ||
87 | #define giu_write(offset, value) writew((value), giu_base + (offset)) | ||
88 | |||
89 | #define GPIO_PIN_OF_IRQ(irq) ((irq) - GIU_IRQ_BASE) | ||
90 | #define GIUINT_HIGH_OFFSET 16 | ||
91 | #define GIUINT_HIGH_MAX 32 | ||
92 | |||
93 | static inline u16 giu_set(u16 offset, u16 set) | ||
94 | { | ||
95 | u16 data; | ||
96 | |||
97 | data = giu_read(offset); | ||
98 | data |= set; | ||
99 | giu_write(offset, data); | ||
100 | |||
101 | return data; | ||
102 | } | ||
103 | |||
104 | static inline u16 giu_clear(u16 offset, u16 clear) | ||
105 | { | ||
106 | u16 data; | ||
107 | |||
108 | data = giu_read(offset); | ||
109 | data &= ~clear; | ||
110 | giu_write(offset, data); | ||
111 | |||
112 | return data; | ||
113 | } | ||
114 | |||
115 | static void ack_giuint_low(unsigned int irq) | ||
116 | { | ||
117 | giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq)); | ||
118 | } | ||
119 | |||
120 | static void mask_giuint_low(unsigned int irq) | ||
121 | { | ||
122 | giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); | ||
123 | } | ||
124 | |||
125 | static void mask_ack_giuint_low(unsigned int irq) | ||
126 | { | ||
127 | unsigned int pin; | ||
128 | |||
129 | pin = GPIO_PIN_OF_IRQ(irq); | ||
130 | giu_clear(GIUINTENL, 1 << pin); | ||
131 | giu_write(GIUINTSTATL, 1 << pin); | ||
132 | } | ||
133 | |||
134 | static void unmask_giuint_low(unsigned int irq) | ||
135 | { | ||
136 | giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); | ||
137 | } | ||
138 | |||
139 | static struct irq_chip giuint_low_irq_chip = { | ||
140 | .name = "GIUINTL", | ||
141 | .ack = ack_giuint_low, | ||
142 | .mask = mask_giuint_low, | ||
143 | .mask_ack = mask_ack_giuint_low, | ||
144 | .unmask = unmask_giuint_low, | ||
145 | }; | ||
146 | |||
147 | static void ack_giuint_high(unsigned int irq) | ||
148 | { | ||
149 | giu_write(GIUINTSTATH, | ||
150 | 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | ||
151 | } | ||
152 | |||
153 | static void mask_giuint_high(unsigned int irq) | ||
154 | { | ||
155 | giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | ||
156 | } | ||
157 | |||
158 | static void mask_ack_giuint_high(unsigned int irq) | ||
159 | { | ||
160 | unsigned int pin; | ||
161 | |||
162 | pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET; | ||
163 | giu_clear(GIUINTENH, 1 << pin); | ||
164 | giu_write(GIUINTSTATH, 1 << pin); | ||
165 | } | ||
166 | |||
167 | static void unmask_giuint_high(unsigned int irq) | ||
168 | { | ||
169 | giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | ||
170 | } | ||
171 | |||
172 | static struct irq_chip giuint_high_irq_chip = { | ||
173 | .name = "GIUINTH", | ||
174 | .ack = ack_giuint_high, | ||
175 | .mask = mask_giuint_high, | ||
176 | .mask_ack = mask_ack_giuint_high, | ||
177 | .unmask = unmask_giuint_high, | ||
178 | }; | ||
179 | |||
180 | static int giu_get_irq(unsigned int irq) | ||
181 | { | ||
182 | u16 pendl, pendh, maskl, maskh; | ||
183 | int i; | ||
184 | |||
185 | pendl = giu_read(GIUINTSTATL); | ||
186 | pendh = giu_read(GIUINTSTATH); | ||
187 | maskl = giu_read(GIUINTENL); | ||
188 | maskh = giu_read(GIUINTENH); | ||
189 | |||
190 | maskl &= pendl; | ||
191 | maskh &= pendh; | ||
192 | |||
193 | if (maskl) { | ||
194 | for (i = 0; i < 16; i++) { | ||
195 | if (maskl & (1 << i)) | ||
196 | return GIU_IRQ(i); | ||
197 | } | ||
198 | } else if (maskh) { | ||
199 | for (i = 0; i < 16; i++) { | ||
200 | if (maskh & (1 << i)) | ||
201 | return GIU_IRQ(i + GIUINT_HIGH_OFFSET); | ||
202 | } | ||
203 | } | ||
204 | |||
205 | printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n", | ||
206 | maskl, pendl, maskh, pendh); | ||
207 | |||
208 | atomic_inc(&irq_err_count); | ||
209 | |||
210 | return -EINVAL; | ||
211 | } | ||
212 | |||
213 | void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, | ||
214 | irq_signal_t signal) | ||
215 | { | ||
216 | u16 mask; | ||
217 | |||
218 | if (pin < GIUINT_HIGH_OFFSET) { | ||
219 | mask = 1 << pin; | ||
220 | if (trigger != IRQ_TRIGGER_LEVEL) { | ||
221 | giu_set(GIUINTTYPL, mask); | ||
222 | if (signal == IRQ_SIGNAL_HOLD) | ||
223 | giu_set(GIUINTHTSELL, mask); | ||
224 | else | ||
225 | giu_clear(GIUINTHTSELL, mask); | ||
226 | if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { | ||
227 | switch (trigger) { | ||
228 | case IRQ_TRIGGER_EDGE_FALLING: | ||
229 | giu_set(GIUFEDGEINHL, mask); | ||
230 | giu_clear(GIUREDGEINHL, mask); | ||
231 | break; | ||
232 | case IRQ_TRIGGER_EDGE_RISING: | ||
233 | giu_clear(GIUFEDGEINHL, mask); | ||
234 | giu_set(GIUREDGEINHL, mask); | ||
235 | break; | ||
236 | default: | ||
237 | giu_set(GIUFEDGEINHL, mask); | ||
238 | giu_set(GIUREDGEINHL, mask); | ||
239 | break; | ||
240 | } | ||
241 | } | ||
242 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
243 | &giuint_low_irq_chip, | ||
244 | handle_edge_irq); | ||
245 | } else { | ||
246 | giu_clear(GIUINTTYPL, mask); | ||
247 | giu_clear(GIUINTHTSELL, mask); | ||
248 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
249 | &giuint_low_irq_chip, | ||
250 | handle_level_irq); | ||
251 | } | ||
252 | giu_write(GIUINTSTATL, mask); | ||
253 | } else if (pin < GIUINT_HIGH_MAX) { | ||
254 | mask = 1 << (pin - GIUINT_HIGH_OFFSET); | ||
255 | if (trigger != IRQ_TRIGGER_LEVEL) { | ||
256 | giu_set(GIUINTTYPH, mask); | ||
257 | if (signal == IRQ_SIGNAL_HOLD) | ||
258 | giu_set(GIUINTHTSELH, mask); | ||
259 | else | ||
260 | giu_clear(GIUINTHTSELH, mask); | ||
261 | if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { | ||
262 | switch (trigger) { | ||
263 | case IRQ_TRIGGER_EDGE_FALLING: | ||
264 | giu_set(GIUFEDGEINHH, mask); | ||
265 | giu_clear(GIUREDGEINHH, mask); | ||
266 | break; | ||
267 | case IRQ_TRIGGER_EDGE_RISING: | ||
268 | giu_clear(GIUFEDGEINHH, mask); | ||
269 | giu_set(GIUREDGEINHH, mask); | ||
270 | break; | ||
271 | default: | ||
272 | giu_set(GIUFEDGEINHH, mask); | ||
273 | giu_set(GIUREDGEINHH, mask); | ||
274 | break; | ||
275 | } | ||
276 | } | ||
277 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
278 | &giuint_high_irq_chip, | ||
279 | handle_edge_irq); | ||
280 | } else { | ||
281 | giu_clear(GIUINTTYPH, mask); | ||
282 | giu_clear(GIUINTHTSELH, mask); | ||
283 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
284 | &giuint_high_irq_chip, | ||
285 | handle_level_irq); | ||
286 | } | ||
287 | giu_write(GIUINTSTATH, mask); | ||
288 | } | ||
289 | } | ||
290 | EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger); | ||
291 | |||
292 | void vr41xx_set_irq_level(unsigned int pin, irq_level_t level) | ||
293 | { | ||
294 | u16 mask; | ||
295 | |||
296 | if (pin < GIUINT_HIGH_OFFSET) { | ||
297 | mask = 1 << pin; | ||
298 | if (level == IRQ_LEVEL_HIGH) | ||
299 | giu_set(GIUINTALSELL, mask); | ||
300 | else | ||
301 | giu_clear(GIUINTALSELL, mask); | ||
302 | giu_write(GIUINTSTATL, mask); | ||
303 | } else if (pin < GIUINT_HIGH_MAX) { | ||
304 | mask = 1 << (pin - GIUINT_HIGH_OFFSET); | ||
305 | if (level == IRQ_LEVEL_HIGH) | ||
306 | giu_set(GIUINTALSELH, mask); | ||
307 | else | ||
308 | giu_clear(GIUINTALSELH, mask); | ||
309 | giu_write(GIUINTSTATH, mask); | ||
310 | } | ||
311 | } | ||
312 | EXPORT_SYMBOL_GPL(vr41xx_set_irq_level); | ||
313 | |||
314 | static int giu_set_direction(struct gpio_chip *chip, unsigned pin, int dir) | ||
315 | { | ||
316 | u16 offset, mask, reg; | ||
317 | unsigned long flags; | ||
318 | |||
319 | if (pin >= chip->ngpio) | ||
320 | return -EINVAL; | ||
321 | |||
322 | if (pin < 16) { | ||
323 | offset = GIUIOSELL; | ||
324 | mask = 1 << pin; | ||
325 | } else if (pin < 32) { | ||
326 | offset = GIUIOSELH; | ||
327 | mask = 1 << (pin - 16); | ||
328 | } else { | ||
329 | if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) { | ||
330 | offset = GIUPODATEN; | ||
331 | mask = 1 << (pin - 32); | ||
332 | } else { | ||
333 | switch (pin) { | ||
334 | case 48: | ||
335 | offset = GIUPODATH; | ||
336 | mask = PIOEN0; | ||
337 | break; | ||
338 | case 49: | ||
339 | offset = GIUPODATH; | ||
340 | mask = PIOEN1; | ||
341 | break; | ||
342 | default: | ||
343 | return -EINVAL; | ||
344 | } | ||
345 | } | ||
346 | } | ||
347 | |||
348 | spin_lock_irqsave(&giu_lock, flags); | ||
349 | |||
350 | reg = giu_read(offset); | ||
351 | if (dir == GPIO_OUTPUT) | ||
352 | reg |= mask; | ||
353 | else | ||
354 | reg &= ~mask; | ||
355 | giu_write(offset, reg); | ||
356 | |||
357 | spin_unlock_irqrestore(&giu_lock, flags); | ||
358 | |||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull) | ||
363 | { | ||
364 | u16 reg, mask; | ||
365 | unsigned long flags; | ||
366 | |||
367 | if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO) | ||
368 | return -EPERM; | ||
369 | |||
370 | if (pin >= 15) | ||
371 | return -EINVAL; | ||
372 | |||
373 | mask = 1 << pin; | ||
374 | |||
375 | spin_lock_irqsave(&giu_lock, flags); | ||
376 | |||
377 | if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) { | ||
378 | reg = giu_read(GIUTERMUPDN); | ||
379 | if (pull == GPIO_PULL_UP) | ||
380 | reg |= mask; | ||
381 | else | ||
382 | reg &= ~mask; | ||
383 | giu_write(GIUTERMUPDN, reg); | ||
384 | |||
385 | reg = giu_read(GIUUSEUPDN); | ||
386 | reg |= mask; | ||
387 | giu_write(GIUUSEUPDN, reg); | ||
388 | } else { | ||
389 | reg = giu_read(GIUUSEUPDN); | ||
390 | reg &= ~mask; | ||
391 | giu_write(GIUUSEUPDN, reg); | ||
392 | } | ||
393 | |||
394 | spin_unlock_irqrestore(&giu_lock, flags); | ||
395 | |||
396 | return 0; | ||
397 | } | ||
398 | EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown); | ||
399 | |||
400 | static int vr41xx_gpio_get(struct gpio_chip *chip, unsigned pin) | ||
401 | { | ||
402 | u16 reg, mask; | ||
403 | |||
404 | if (pin >= chip->ngpio) | ||
405 | return -EINVAL; | ||
406 | |||
407 | if (pin < 16) { | ||
408 | reg = giu_read(GIUPIODL); | ||
409 | mask = 1 << pin; | ||
410 | } else if (pin < 32) { | ||
411 | reg = giu_read(GIUPIODH); | ||
412 | mask = 1 << (pin - 16); | ||
413 | } else if (pin < 48) { | ||
414 | reg = giu_read(GIUPODATL); | ||
415 | mask = 1 << (pin - 32); | ||
416 | } else { | ||
417 | reg = giu_read(GIUPODATH); | ||
418 | mask = 1 << (pin - 48); | ||
419 | } | ||
420 | |||
421 | if (reg & mask) | ||
422 | return 1; | ||
423 | |||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | static void vr41xx_gpio_set(struct gpio_chip *chip, unsigned pin, | ||
428 | int value) | ||
429 | { | ||
430 | u16 offset, mask, reg; | ||
431 | unsigned long flags; | ||
432 | |||
433 | if (pin >= chip->ngpio) | ||
434 | return; | ||
435 | |||
436 | if (pin < 16) { | ||
437 | offset = GIUPIODL; | ||
438 | mask = 1 << pin; | ||
439 | } else if (pin < 32) { | ||
440 | offset = GIUPIODH; | ||
441 | mask = 1 << (pin - 16); | ||
442 | } else if (pin < 48) { | ||
443 | offset = GIUPODATL; | ||
444 | mask = 1 << (pin - 32); | ||
445 | } else { | ||
446 | offset = GIUPODATH; | ||
447 | mask = 1 << (pin - 48); | ||
448 | } | ||
449 | |||
450 | spin_lock_irqsave(&giu_lock, flags); | ||
451 | |||
452 | reg = giu_read(offset); | ||
453 | if (value) | ||
454 | reg |= mask; | ||
455 | else | ||
456 | reg &= ~mask; | ||
457 | giu_write(offset, reg); | ||
458 | |||
459 | spin_unlock_irqrestore(&giu_lock, flags); | ||
460 | } | ||
461 | |||
462 | |||
463 | static int vr41xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | ||
464 | { | ||
465 | return giu_set_direction(chip, offset, GPIO_INPUT); | ||
466 | } | ||
467 | |||
468 | static int vr41xx_gpio_direction_output(struct gpio_chip *chip, unsigned offset, | ||
469 | int value) | ||
470 | { | ||
471 | vr41xx_gpio_set(chip, offset, value); | ||
472 | |||
473 | return giu_set_direction(chip, offset, GPIO_OUTPUT); | ||
474 | } | ||
475 | |||
476 | static int vr41xx_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | ||
477 | { | ||
478 | if (offset >= chip->ngpio) | ||
479 | return -EINVAL; | ||
480 | |||
481 | return GIU_IRQ_BASE + offset; | ||
482 | } | ||
483 | |||
484 | static struct gpio_chip vr41xx_gpio_chip = { | ||
485 | .label = "vr41xx", | ||
486 | .owner = THIS_MODULE, | ||
487 | .direction_input = vr41xx_gpio_direction_input, | ||
488 | .get = vr41xx_gpio_get, | ||
489 | .direction_output = vr41xx_gpio_direction_output, | ||
490 | .set = vr41xx_gpio_set, | ||
491 | .to_irq = vr41xx_gpio_to_irq, | ||
492 | }; | ||
493 | |||
494 | static int __devinit giu_probe(struct platform_device *pdev) | ||
495 | { | ||
496 | struct resource *res; | ||
497 | unsigned int trigger, i, pin; | ||
498 | struct irq_chip *chip; | ||
499 | int irq, retval; | ||
500 | |||
501 | switch (pdev->id) { | ||
502 | case GPIO_50PINS_PULLUPDOWN: | ||
503 | giu_flags = GPIO_HAS_PULLUPDOWN_IO; | ||
504 | vr41xx_gpio_chip.ngpio = 50; | ||
505 | break; | ||
506 | case GPIO_36PINS: | ||
507 | vr41xx_gpio_chip.ngpio = 36; | ||
508 | break; | ||
509 | case GPIO_48PINS_EDGE_SELECT: | ||
510 | giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT; | ||
511 | vr41xx_gpio_chip.ngpio = 48; | ||
512 | break; | ||
513 | default: | ||
514 | dev_err(&pdev->dev, "GIU: unknown ID %d\n", pdev->id); | ||
515 | return -ENODEV; | ||
516 | } | ||
517 | |||
518 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
519 | if (!res) | ||
520 | return -EBUSY; | ||
521 | |||
522 | giu_base = ioremap(res->start, res->end - res->start + 1); | ||
523 | if (!giu_base) | ||
524 | return -ENOMEM; | ||
525 | |||
526 | vr41xx_gpio_chip.dev = &pdev->dev; | ||
527 | |||
528 | retval = gpiochip_add(&vr41xx_gpio_chip); | ||
529 | |||
530 | giu_write(GIUINTENL, 0); | ||
531 | giu_write(GIUINTENH, 0); | ||
532 | |||
533 | trigger = giu_read(GIUINTTYPH) << 16; | ||
534 | trigger |= giu_read(GIUINTTYPL); | ||
535 | for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) { | ||
536 | pin = GPIO_PIN_OF_IRQ(i); | ||
537 | if (pin < GIUINT_HIGH_OFFSET) | ||
538 | chip = &giuint_low_irq_chip; | ||
539 | else | ||
540 | chip = &giuint_high_irq_chip; | ||
541 | |||
542 | if (trigger & (1 << pin)) | ||
543 | set_irq_chip_and_handler(i, chip, handle_edge_irq); | ||
544 | else | ||
545 | set_irq_chip_and_handler(i, chip, handle_level_irq); | ||
546 | |||
547 | } | ||
548 | |||
549 | irq = platform_get_irq(pdev, 0); | ||
550 | if (irq < 0 || irq >= nr_irqs) | ||
551 | return -EBUSY; | ||
552 | |||
553 | return cascade_irq(irq, giu_get_irq); | ||
554 | } | ||
555 | |||
556 | static int __devexit giu_remove(struct platform_device *pdev) | ||
557 | { | ||
558 | if (giu_base) { | ||
559 | iounmap(giu_base); | ||
560 | giu_base = NULL; | ||
561 | } | ||
562 | |||
563 | return 0; | ||
564 | } | ||
565 | |||
566 | static struct platform_driver giu_device_driver = { | ||
567 | .probe = giu_probe, | ||
568 | .remove = __devexit_p(giu_remove), | ||
569 | .driver = { | ||
570 | .name = "GIU", | ||
571 | .owner = THIS_MODULE, | ||
572 | }, | ||
573 | }; | ||
574 | |||
575 | static int __init vr41xx_giu_init(void) | ||
576 | { | ||
577 | return platform_driver_register(&giu_device_driver); | ||
578 | } | ||
579 | |||
580 | static void __exit vr41xx_giu_exit(void) | ||
581 | { | ||
582 | platform_driver_unregister(&giu_device_driver); | ||
583 | } | ||
584 | |||
585 | module_init(vr41xx_giu_init); | ||
586 | module_exit(vr41xx_giu_exit); | ||
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 83b734aec923..52b25f8b111d 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c | |||
@@ -880,6 +880,7 @@ static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud) | |||
880 | } | 880 | } |
881 | 881 | ||
882 | shost->hostdata[0] = (unsigned long)lu; | 882 | shost->hostdata[0] = (unsigned long)lu; |
883 | shost->max_cmd_len = SBP2_MAX_CDB_SIZE; | ||
883 | 884 | ||
884 | if (!scsi_add_host(shost, &ud->device)) { | 885 | if (!scsi_add_host(shost, &ud->device)) { |
885 | lu->shost = shost; | 886 | lu->shost = shost; |
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index c5036f1cc5b0..64a3a66a8a39 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h | |||
@@ -25,6 +25,12 @@ | |||
25 | #define SBP2_DEVICE_NAME "sbp2" | 25 | #define SBP2_DEVICE_NAME "sbp2" |
26 | 26 | ||
27 | /* | 27 | /* |
28 | * There is no transport protocol limit to the CDB length, but we implement | ||
29 | * a fixed length only. 16 bytes is enough for disks larger than 2 TB. | ||
30 | */ | ||
31 | #define SBP2_MAX_CDB_SIZE 16 | ||
32 | |||
33 | /* | ||
28 | * SBP-2 specific definitions | 34 | * SBP-2 specific definitions |
29 | */ | 35 | */ |
30 | 36 | ||
@@ -51,7 +57,7 @@ struct sbp2_command_orb { | |||
51 | u32 data_descriptor_hi; | 57 | u32 data_descriptor_hi; |
52 | u32 data_descriptor_lo; | 58 | u32 data_descriptor_lo; |
53 | u32 misc; | 59 | u32 misc; |
54 | u8 cdb[12]; | 60 | u8 cdb[SBP2_MAX_CDB_SIZE]; |
55 | } __attribute__((packed)); | 61 | } __attribute__((packed)); |
56 | 62 | ||
57 | #define SBP2_LOGIN_REQUEST 0x0 | 63 | #define SBP2_LOGIN_REQUEST 0x0 |
diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c index 2adf9cb265da..d114d3a9e1e9 100644 --- a/drivers/input/misc/cobalt_btns.c +++ b/drivers/input/misc/cobalt_btns.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Cobalt button interface driver. | 2 | * Cobalt button interface driver. |
3 | * | 3 | * |
4 | * Copyright (C) 2007-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2007-2008 Yoichi Yuasa <yuasa@linux-mips.org> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
@@ -148,7 +148,7 @@ static int __devexit cobalt_buttons_remove(struct platform_device *pdev) | |||
148 | return 0; | 148 | return 0; |
149 | } | 149 | } |
150 | 150 | ||
151 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); | 151 | MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); |
152 | MODULE_DESCRIPTION("Cobalt button interface driver"); | 152 | MODULE_DESCRIPTION("Cobalt button interface driver"); |
153 | MODULE_LICENSE("GPL"); | 153 | MODULE_LICENSE("GPL"); |
154 | /* work with hotplug and coldplug */ | 154 | /* work with hotplug and coldplug */ |
diff --git a/drivers/leds/leds-cobalt-raq.c b/drivers/leds/leds-cobalt-raq.c index ff0e8c3fbf9b..5f1ce810815f 100644 --- a/drivers/leds/leds-cobalt-raq.c +++ b/drivers/leds/leds-cobalt-raq.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * LEDs driver for the Cobalt Raq series. | 2 | * LEDs driver for the Cobalt Raq series. |
3 | * | 3 | * |
4 | * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2007 Yoichi Yuasa <yuasa@linux-mips.org> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c index b6da9c3873fe..aa20ce8cc668 100644 --- a/drivers/media/common/tuners/tuner-xc2028.c +++ b/drivers/media/common/tuners/tuner-xc2028.c | |||
@@ -1096,8 +1096,19 @@ static int xc2028_set_params(struct dvb_frontend *fe, | |||
1096 | } | 1096 | } |
1097 | 1097 | ||
1098 | /* All S-code tables need a 200kHz shift */ | 1098 | /* All S-code tables need a 200kHz shift */ |
1099 | if (priv->ctrl.demod) | 1099 | if (priv->ctrl.demod) { |
1100 | demod = priv->ctrl.demod + 200; | 1100 | demod = priv->ctrl.demod + 200; |
1101 | /* | ||
1102 | * The DTV7 S-code table needs a 700 kHz shift. | ||
1103 | * Thanks to Terry Wu <terrywu2009@gmail.com> for reporting this | ||
1104 | * | ||
1105 | * DTV7 is only used in Australia. Germany or Italy may also | ||
1106 | * use this firmware after initialization, but a tune to a UHF | ||
1107 | * channel should then cause DTV78 to be used. | ||
1108 | */ | ||
1109 | if (type & DTV7) | ||
1110 | demod += 500; | ||
1111 | } | ||
1101 | 1112 | ||
1102 | return generic_set_freq(fe, p->frequency, | 1113 | return generic_set_freq(fe, p->frequency, |
1103 | T_DIGITAL_TV, type, 0, demod); | 1114 | T_DIGITAL_TV, type, 0, demod); |
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index 68eb4493f991..d8d4214fd65f 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig | |||
@@ -1,5 +1,6 @@ | |||
1 | config TTPCI_EEPROM | 1 | config TTPCI_EEPROM |
2 | tristate | 2 | tristate |
3 | depends on I2C | ||
3 | default n | 4 | default n |
4 | 5 | ||
5 | config DVB_AV7110 | 6 | config DVB_AV7110 |
diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c index 640421ceb24a..46d216329611 100644 --- a/drivers/media/radio/radio-si470x.c +++ b/drivers/media/radio/radio-si470x.c | |||
@@ -1200,7 +1200,7 @@ static int si470x_fops_release(struct file *file) | |||
1200 | video_unregister_device(radio->videodev); | 1200 | video_unregister_device(radio->videodev); |
1201 | kfree(radio->buffer); | 1201 | kfree(radio->buffer); |
1202 | kfree(radio); | 1202 | kfree(radio); |
1203 | goto done; | 1203 | goto unlock; |
1204 | } | 1204 | } |
1205 | 1205 | ||
1206 | /* stop rds reception */ | 1206 | /* stop rds reception */ |
@@ -1213,9 +1213,8 @@ static int si470x_fops_release(struct file *file) | |||
1213 | retval = si470x_stop(radio); | 1213 | retval = si470x_stop(radio); |
1214 | usb_autopm_put_interface(radio->intf); | 1214 | usb_autopm_put_interface(radio->intf); |
1215 | } | 1215 | } |
1216 | 1216 | unlock: | |
1217 | mutex_unlock(&radio->disconnect_lock); | 1217 | mutex_unlock(&radio->disconnect_lock); |
1218 | |||
1219 | done: | 1218 | done: |
1220 | return retval; | 1219 | return retval; |
1221 | } | 1220 | } |
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 061e147f6f26..84b6fc15519d 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -312,6 +312,14 @@ config VIDEO_OV7670 | |||
312 | OV7670 VGA camera. It currently only works with the M88ALP01 | 312 | OV7670 VGA camera. It currently only works with the M88ALP01 |
313 | controller. | 313 | controller. |
314 | 314 | ||
315 | config VIDEO_MT9V011 | ||
316 | tristate "Micron mt9v011 sensor support" | ||
317 | depends on I2C && VIDEO_V4L2 | ||
318 | ---help--- | ||
319 | This is a Video4Linux2 sensor-level driver for the Micron | ||
320 | mt0v011 1.3 Mpixel camera. It currently only works with the | ||
321 | em28xx driver. | ||
322 | |||
315 | config VIDEO_TCM825X | 323 | config VIDEO_TCM825X |
316 | tristate "TCM825x camera sensor support" | 324 | tristate "TCM825x camera sensor support" |
317 | depends on I2C && VIDEO_V4L2 | 325 | depends on I2C && VIDEO_V4L2 |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 7fb3add1b387..9f2e3214a482 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
@@ -69,6 +69,7 @@ obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o | |||
69 | obj-$(CONFIG_VIDEO_OV7670) += ov7670.o | 69 | obj-$(CONFIG_VIDEO_OV7670) += ov7670.o |
70 | obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o | 70 | obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o |
71 | obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o | 71 | obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o |
72 | obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o | ||
72 | 73 | ||
73 | obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o | 74 | obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o |
74 | obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o | 75 | obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o |
diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index c92a25036f0e..36f2d76006fd 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c | |||
@@ -198,11 +198,14 @@ static const struct cx18_card_pci_info cx18_pci_mpc718[] = { | |||
198 | 198 | ||
199 | static const struct cx18_card cx18_card_mpc718 = { | 199 | static const struct cx18_card cx18_card_mpc718 = { |
200 | .type = CX18_CARD_YUAN_MPC718, | 200 | .type = CX18_CARD_YUAN_MPC718, |
201 | .name = "Yuan MPC718", | 201 | .name = "Yuan MPC718 MiniPCI DVB-T/Analog", |
202 | .comment = "Analog video capture works; some audio line in may not.\n", | 202 | .comment = "Experimenters needed for device to work well.\n" |
203 | "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n", | ||
203 | .v4l2_capabilities = CX18_CAP_ENCODER, | 204 | .v4l2_capabilities = CX18_CAP_ENCODER, |
204 | .hw_audio_ctrl = CX18_HW_418_AV, | 205 | .hw_audio_ctrl = CX18_HW_418_AV, |
205 | .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_RESET_CTRL, | 206 | .hw_muxer = CX18_HW_GPIO_MUX, |
207 | .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | | ||
208 | CX18_HW_GPIO_MUX | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL, | ||
206 | .video_inputs = { | 209 | .video_inputs = { |
207 | { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, | 210 | { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, |
208 | { CX18_CARD_INPUT_SVIDEO1, 1, | 211 | { CX18_CARD_INPUT_SVIDEO1, 1, |
@@ -211,27 +214,34 @@ static const struct cx18_card cx18_card_mpc718 = { | |||
211 | { CX18_CARD_INPUT_SVIDEO2, 2, | 214 | { CX18_CARD_INPUT_SVIDEO2, 2, |
212 | CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 }, | 215 | CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 }, |
213 | { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 }, | 216 | { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 }, |
214 | { CX18_CARD_INPUT_COMPOSITE3, 2, CX18_AV_COMPOSITE3 }, | ||
215 | }, | 217 | }, |
216 | .audio_inputs = { | 218 | .audio_inputs = { |
217 | { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 }, | 219 | { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 }, |
218 | { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 0 }, | 220 | { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 1 }, |
219 | { CX18_CARD_INPUT_LINE_IN2, CX18_AV_AUDIO_SERIAL1, 0 }, | 221 | { CX18_CARD_INPUT_LINE_IN2, CX18_AV_AUDIO_SERIAL2, 1 }, |
220 | }, | 222 | }, |
221 | .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO_SERIAL1, 0 }, | ||
222 | .tuners = { | 223 | .tuners = { |
223 | /* XC3028 tuner */ | 224 | /* XC3028 tuner */ |
224 | { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, | 225 | { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, |
225 | }, | 226 | }, |
227 | /* FIXME - the FM radio is just a guess and driver doesn't use SIF */ | ||
228 | .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 }, | ||
226 | .ddr = { | 229 | .ddr = { |
227 | /* Probably Samsung K4D263238G-VC33 memory */ | 230 | /* Hynix HY5DU283222B DDR RAM */ |
228 | .chip_config = 0x003, | 231 | .chip_config = 0x303, |
229 | .refresh = 0x30c, | 232 | .refresh = 0x3bd, |
230 | .timing1 = 0x23230b73, | 233 | .timing1 = 0x36320966, |
231 | .timing2 = 0x08, | 234 | .timing2 = 0x1f, |
232 | .tune_lane = 0, | 235 | .tune_lane = 0, |
233 | .initial_emrs = 2, | 236 | .initial_emrs = 2, |
234 | }, | 237 | }, |
238 | .gpio_init.initial_value = 0x1, | ||
239 | .gpio_init.direction = 0x3, | ||
240 | /* FIXME - these GPIO's are just guesses */ | ||
241 | .gpio_audio_input = { .mask = 0x3, | ||
242 | .tuner = 0x1, | ||
243 | .linein = 0x3, | ||
244 | .radio = 0x1 }, | ||
235 | .xceive_pin = 0, | 245 | .xceive_pin = 0, |
236 | .pci_list = cx18_pci_mpc718, | 246 | .pci_list = cx18_pci_mpc718, |
237 | .i2c = &cx18_i2c_std, | 247 | .i2c = &cx18_i2c_std, |
diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index 6ea3fe623ef4..51a0c33b25b7 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c | |||
@@ -30,6 +30,10 @@ | |||
30 | #include "s5h1409.h" | 30 | #include "s5h1409.h" |
31 | #include "mxl5005s.h" | 31 | #include "mxl5005s.h" |
32 | #include "zl10353.h" | 32 | #include "zl10353.h" |
33 | |||
34 | #include <linux/firmware.h> | ||
35 | #include "mt352.h" | ||
36 | #include "mt352_priv.h" | ||
33 | #include "tuner-xc2028.h" | 37 | #include "tuner-xc2028.h" |
34 | 38 | ||
35 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 39 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
@@ -38,6 +42,11 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | |||
38 | #define CX18_CLOCK_ENABLE2 0xc71024 | 42 | #define CX18_CLOCK_ENABLE2 0xc71024 |
39 | #define CX18_DMUX_CLK_MASK 0x0080 | 43 | #define CX18_DMUX_CLK_MASK 0x0080 |
40 | 44 | ||
45 | /* | ||
46 | * CX18_CARD_HVR_1600_ESMT | ||
47 | * CX18_CARD_HVR_1600_SAMSUNG | ||
48 | */ | ||
49 | |||
41 | static struct mxl5005s_config hauppauge_hvr1600_tuner = { | 50 | static struct mxl5005s_config hauppauge_hvr1600_tuner = { |
42 | .i2c_address = 0xC6 >> 1, | 51 | .i2c_address = 0xC6 >> 1, |
43 | .if_freq = IF_FREQ_5380000HZ, | 52 | .if_freq = IF_FREQ_5380000HZ, |
@@ -65,6 +74,9 @@ static struct s5h1409_config hauppauge_hvr1600_config = { | |||
65 | .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK | 74 | .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK |
66 | }; | 75 | }; |
67 | 76 | ||
77 | /* | ||
78 | * CX18_CARD_LEADTEK_DVR3100H | ||
79 | */ | ||
68 | /* Information/confirmation of proper config values provided by Terry Wu */ | 80 | /* Information/confirmation of proper config values provided by Terry Wu */ |
69 | static struct zl10353_config leadtek_dvr3100h_demod = { | 81 | static struct zl10353_config leadtek_dvr3100h_demod = { |
70 | .demod_address = 0x1e >> 1, /* Datasheet suggested straps */ | 82 | .demod_address = 0x1e >> 1, /* Datasheet suggested straps */ |
@@ -74,6 +86,121 @@ static struct zl10353_config leadtek_dvr3100h_demod = { | |||
74 | .disable_i2c_gate_ctrl = 1, /* Disable the I2C gate */ | 86 | .disable_i2c_gate_ctrl = 1, /* Disable the I2C gate */ |
75 | }; | 87 | }; |
76 | 88 | ||
89 | /* | ||
90 | * CX18_CARD_YUAN_MPC718 | ||
91 | */ | ||
92 | /* | ||
93 | * Due to | ||
94 | * | ||
95 | * 1. an absence of information on how to prgram the MT352 | ||
96 | * 2. the Linux mt352 module pushing MT352 initialzation off onto us here | ||
97 | * | ||
98 | * We have to use an init sequence that *you* must extract from the Windows | ||
99 | * driver (yuanrap.sys) and which we load as a firmware. | ||
100 | * | ||
101 | * If someone can provide me with a Zarlink MT352 (Intel CE6352?) Design Manual | ||
102 | * with chip programming details, then I can remove this annoyance. | ||
103 | */ | ||
104 | static int yuan_mpc718_mt352_reqfw(struct cx18_stream *stream, | ||
105 | const struct firmware **fw) | ||
106 | { | ||
107 | struct cx18 *cx = stream->cx; | ||
108 | const char *fn = "dvb-cx18-mpc718-mt352.fw"; | ||
109 | int ret; | ||
110 | |||
111 | ret = request_firmware(fw, fn, &cx->pci_dev->dev); | ||
112 | if (ret) | ||
113 | CX18_ERR("Unable to open firmware file %s\n", fn); | ||
114 | else { | ||
115 | size_t sz = (*fw)->size; | ||
116 | if (sz < 2 || sz > 64 || (sz % 2) != 0) { | ||
117 | CX18_ERR("Firmware %s has a bad size: %lu bytes\n", | ||
118 | fn, (unsigned long) sz); | ||
119 | ret = -EILSEQ; | ||
120 | release_firmware(*fw); | ||
121 | *fw = NULL; | ||
122 | } | ||
123 | } | ||
124 | |||
125 | if (ret) { | ||
126 | CX18_ERR("The MPC718 board variant with the MT352 DVB-T" | ||
127 | "demodualtor will not work without it\n"); | ||
128 | CX18_ERR("Run 'linux/Documentation/dvb/get_dvb_firmware " | ||
129 | "mpc718' if you need the firmware\n"); | ||
130 | } | ||
131 | return ret; | ||
132 | } | ||
133 | |||
134 | static int yuan_mpc718_mt352_init(struct dvb_frontend *fe) | ||
135 | { | ||
136 | struct cx18_dvb *dvb = container_of(fe->dvb, | ||
137 | struct cx18_dvb, dvb_adapter); | ||
138 | struct cx18_stream *stream = container_of(dvb, struct cx18_stream, dvb); | ||
139 | const struct firmware *fw = NULL; | ||
140 | int ret; | ||
141 | int i; | ||
142 | u8 buf[3]; | ||
143 | |||
144 | ret = yuan_mpc718_mt352_reqfw(stream, &fw); | ||
145 | if (ret) | ||
146 | return ret; | ||
147 | |||
148 | /* Loop through all the register-value pairs in the firmware file */ | ||
149 | for (i = 0; i < fw->size; i += 2) { | ||
150 | buf[0] = fw->data[i]; | ||
151 | /* Intercept a few registers we want to set ourselves */ | ||
152 | switch (buf[0]) { | ||
153 | case TRL_NOMINAL_RATE_0: | ||
154 | /* Set our custom OFDM bandwidth in the case below */ | ||
155 | break; | ||
156 | case TRL_NOMINAL_RATE_1: | ||
157 | /* 6 MHz: 64/7 * 6/8 / 20.48 * 2^16 = 0x55b6.db6 */ | ||
158 | /* 7 MHz: 64/7 * 7/8 / 20.48 * 2^16 = 0x6400 */ | ||
159 | /* 8 MHz: 64/7 * 8/8 / 20.48 * 2^16 = 0x7249.249 */ | ||
160 | buf[1] = 0x72; | ||
161 | buf[2] = 0x49; | ||
162 | mt352_write(fe, buf, 3); | ||
163 | break; | ||
164 | case INPUT_FREQ_0: | ||
165 | /* Set our custom IF in the case below */ | ||
166 | break; | ||
167 | case INPUT_FREQ_1: | ||
168 | /* 4.56 MHz IF: (20.48 - 4.56)/20.48 * 2^14 = 0x31c0 */ | ||
169 | buf[1] = 0x31; | ||
170 | buf[2] = 0xc0; | ||
171 | mt352_write(fe, buf, 3); | ||
172 | break; | ||
173 | default: | ||
174 | /* Pass through the register-value pair from the fw */ | ||
175 | buf[1] = fw->data[i+1]; | ||
176 | mt352_write(fe, buf, 2); | ||
177 | break; | ||
178 | } | ||
179 | } | ||
180 | |||
181 | buf[0] = (u8) TUNER_GO; | ||
182 | buf[1] = 0x01; /* Go */ | ||
183 | mt352_write(fe, buf, 2); | ||
184 | release_firmware(fw); | ||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | static struct mt352_config yuan_mpc718_mt352_demod = { | ||
189 | .demod_address = 0x1e >> 1, | ||
190 | .adc_clock = 20480, /* 20.480 MHz */ | ||
191 | .if2 = 4560, /* 4.560 MHz */ | ||
192 | .no_tuner = 1, /* XC3028 is not behind the gate */ | ||
193 | .demod_init = yuan_mpc718_mt352_init, | ||
194 | }; | ||
195 | |||
196 | static struct zl10353_config yuan_mpc718_zl10353_demod = { | ||
197 | .demod_address = 0x1e >> 1, /* Datasheet suggested straps */ | ||
198 | .if2 = 45600, /* 4.560 MHz IF from the XC3028 */ | ||
199 | .parallel_ts = 1, /* Not a serial TS */ | ||
200 | .no_tuner = 1, /* XC3028 is not behind the gate */ | ||
201 | .disable_i2c_gate_ctrl = 1, /* Disable the I2C gate */ | ||
202 | }; | ||
203 | |||
77 | static int dvb_register(struct cx18_stream *stream); | 204 | static int dvb_register(struct cx18_stream *stream); |
78 | 205 | ||
79 | /* Kernel DVB framework calls this when the feed needs to start. | 206 | /* Kernel DVB framework calls this when the feed needs to start. |
@@ -113,6 +240,7 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) | |||
113 | break; | 240 | break; |
114 | 241 | ||
115 | case CX18_CARD_LEADTEK_DVR3100H: | 242 | case CX18_CARD_LEADTEK_DVR3100H: |
243 | case CX18_CARD_YUAN_MPC718: | ||
116 | default: | 244 | default: |
117 | /* Assumption - Parallel transport - Signalling | 245 | /* Assumption - Parallel transport - Signalling |
118 | * undefined or default. | 246 | * undefined or default. |
@@ -326,6 +454,38 @@ static int dvb_register(struct cx18_stream *stream) | |||
326 | fe->ops.tuner_ops.set_config(fe, &ctrl); | 454 | fe->ops.tuner_ops.set_config(fe, &ctrl); |
327 | } | 455 | } |
328 | break; | 456 | break; |
457 | case CX18_CARD_YUAN_MPC718: | ||
458 | /* | ||
459 | * TODO | ||
460 | * Apparently, these cards also could instead have a | ||
461 | * DiBcom demod supported by one of the db7000 drivers | ||
462 | */ | ||
463 | dvb->fe = dvb_attach(mt352_attach, | ||
464 | &yuan_mpc718_mt352_demod, | ||
465 | &cx->i2c_adap[1]); | ||
466 | if (dvb->fe == NULL) | ||
467 | dvb->fe = dvb_attach(zl10353_attach, | ||
468 | &yuan_mpc718_zl10353_demod, | ||
469 | &cx->i2c_adap[1]); | ||
470 | if (dvb->fe != NULL) { | ||
471 | struct dvb_frontend *fe; | ||
472 | struct xc2028_config cfg = { | ||
473 | .i2c_adap = &cx->i2c_adap[1], | ||
474 | .i2c_addr = 0xc2 >> 1, | ||
475 | .ctrl = NULL, | ||
476 | }; | ||
477 | static struct xc2028_ctrl ctrl = { | ||
478 | .fname = XC2028_DEFAULT_FIRMWARE, | ||
479 | .max_len = 64, | ||
480 | .demod = XC3028_FE_ZARLINK456, | ||
481 | .type = XC2028_AUTO, | ||
482 | }; | ||
483 | |||
484 | fe = dvb_attach(xc2028_attach, dvb->fe, &cfg); | ||
485 | if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) | ||
486 | fe->ops.tuner_ops.set_config(fe, &ctrl); | ||
487 | } | ||
488 | break; | ||
329 | default: | 489 | default: |
330 | /* No Digital Tv Support */ | 490 | /* No Digital Tv Support */ |
331 | break; | 491 | break; |
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 48a975134ac5..86ac529e62be 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c | |||
@@ -463,6 +463,30 @@ static struct xc5000_config mygica_x8506_xc5000_config = { | |||
463 | .if_khz = 5380, | 463 | .if_khz = 5380, |
464 | }; | 464 | }; |
465 | 465 | ||
466 | static int cx23885_dvb_set_frontend(struct dvb_frontend *fe, | ||
467 | struct dvb_frontend_parameters *param) | ||
468 | { | ||
469 | struct cx23885_tsport *port = fe->dvb->priv; | ||
470 | struct cx23885_dev *dev = port->dev; | ||
471 | |||
472 | switch (dev->board) { | ||
473 | case CX23885_BOARD_HAUPPAUGE_HVR1275: | ||
474 | switch (param->u.vsb.modulation) { | ||
475 | case VSB_8: | ||
476 | cx23885_gpio_clear(dev, GPIO_5); | ||
477 | break; | ||
478 | case QAM_64: | ||
479 | case QAM_256: | ||
480 | default: | ||
481 | cx23885_gpio_set(dev, GPIO_5); | ||
482 | break; | ||
483 | } | ||
484 | break; | ||
485 | } | ||
486 | return (port->set_frontend_save) ? | ||
487 | port->set_frontend_save(fe, param) : -ENODEV; | ||
488 | } | ||
489 | |||
466 | static int dvb_register(struct cx23885_tsport *port) | 490 | static int dvb_register(struct cx23885_tsport *port) |
467 | { | 491 | { |
468 | struct cx23885_dev *dev = port->dev; | 492 | struct cx23885_dev *dev = port->dev; |
@@ -502,6 +526,12 @@ static int dvb_register(struct cx23885_tsport *port) | |||
502 | 0x60, &dev->i2c_bus[1].i2c_adap, | 526 | 0x60, &dev->i2c_bus[1].i2c_adap, |
503 | &hauppauge_hvr127x_config); | 527 | &hauppauge_hvr127x_config); |
504 | } | 528 | } |
529 | |||
530 | /* FIXME: temporary hack */ | ||
531 | /* define bridge override to set_frontend */ | ||
532 | port->set_frontend_save = fe0->dvb.frontend->ops.set_frontend; | ||
533 | fe0->dvb.frontend->ops.set_frontend = cx23885_dvb_set_frontend; | ||
534 | |||
505 | break; | 535 | break; |
506 | case CX23885_BOARD_HAUPPAUGE_HVR1255: | 536 | case CX23885_BOARD_HAUPPAUGE_HVR1255: |
507 | i2c_bus = &dev->i2c_bus[0]; | 537 | i2c_bus = &dev->i2c_bus[0]; |
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 1a2ac518a3f1..214a55e943b7 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h | |||
@@ -288,6 +288,10 @@ struct cx23885_tsport { | |||
288 | /* Allow a single tsport to have multiple frontends */ | 288 | /* Allow a single tsport to have multiple frontends */ |
289 | u32 num_frontends; | 289 | u32 num_frontends; |
290 | void *port_priv; | 290 | void *port_priv; |
291 | |||
292 | /* FIXME: temporary hack */ | ||
293 | int (*set_frontend_save) (struct dvb_frontend *, | ||
294 | struct dvb_frontend_parameters *); | ||
291 | }; | 295 | }; |
292 | 296 | ||
293 | struct cx23885_dev { | 297 | struct cx23885_dev { |
diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig index 16a5af30e9d1..6524b493e033 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/video/em28xx/Kconfig | |||
@@ -8,6 +8,8 @@ config VIDEO_EM28XX | |||
8 | select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO | 8 | select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO |
9 | select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO | 9 | select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO |
10 | select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO | 10 | select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO |
11 | select VIDEO_MT9V011 if VIDEO_HELPER_CHIPS_AUTO | ||
12 | |||
11 | ---help--- | 13 | ---help--- |
12 | This is a video4linux driver for Empia 28xx based TV cards. | 14 | This is a video4linux driver for Empia 28xx based TV cards. |
13 | 15 | ||
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index c43fdb9bc888..ebd24a25fb85 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
@@ -58,6 +58,8 @@ static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; | |||
58 | module_param_array(card, int, NULL, 0444); | 58 | module_param_array(card, int, NULL, 0444); |
59 | MODULE_PARM_DESC(card, "card type"); | 59 | MODULE_PARM_DESC(card, "card type"); |
60 | 60 | ||
61 | #define MT9V011_VERSION 0x8243 | ||
62 | |||
61 | /* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */ | 63 | /* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */ |
62 | static unsigned long em28xx_devused; | 64 | static unsigned long em28xx_devused; |
63 | 65 | ||
@@ -191,6 +193,13 @@ static struct em28xx_reg_seq terratec_av350_unmute_gpio[] = { | |||
191 | {EM28XX_R08_GPIO, 0xff, 0xff, 10}, | 193 | {EM28XX_R08_GPIO, 0xff, 0xff, 10}, |
192 | { -1, -1, -1, -1}, | 194 | { -1, -1, -1, -1}, |
193 | }; | 195 | }; |
196 | |||
197 | static struct em28xx_reg_seq silvercrest_reg_seq[] = { | ||
198 | {EM28XX_R08_GPIO, 0xff, 0xff, 10}, | ||
199 | {EM28XX_R08_GPIO, 0x01, 0xf7, 10}, | ||
200 | { -1, -1, -1, -1}, | ||
201 | }; | ||
202 | |||
194 | /* | 203 | /* |
195 | * Board definitions | 204 | * Board definitions |
196 | */ | 205 | */ |
@@ -438,6 +447,18 @@ struct em28xx_board em28xx_boards[] = { | |||
438 | .amux = EM28XX_AMUX_VIDEO, | 447 | .amux = EM28XX_AMUX_VIDEO, |
439 | } }, | 448 | } }, |
440 | }, | 449 | }, |
450 | [EM2820_BOARD_SILVERCREST_WEBCAM] = { | ||
451 | .name = "Silvercrest Webcam 1.3mpix", | ||
452 | .tuner_type = TUNER_ABSENT, | ||
453 | .is_27xx = 1, | ||
454 | .decoder = EM28XX_MT9V011, | ||
455 | .input = { { | ||
456 | .type = EM28XX_VMUX_COMPOSITE1, | ||
457 | .vmux = 0, | ||
458 | .amux = EM28XX_AMUX_VIDEO, | ||
459 | .gpio = silvercrest_reg_seq, | ||
460 | } }, | ||
461 | }, | ||
441 | [EM2821_BOARD_SUPERCOMP_USB_2] = { | 462 | [EM2821_BOARD_SUPERCOMP_USB_2] = { |
442 | .name = "Supercomp USB 2.0 TV", | 463 | .name = "Supercomp USB 2.0 TV", |
443 | .valid = EM28XX_BOARD_NOT_VALIDATED, | 464 | .valid = EM28XX_BOARD_NOT_VALIDATED, |
@@ -826,7 +847,7 @@ struct em28xx_board em28xx_boards[] = { | |||
826 | .tuner_gpio = default_tuner_gpio, | 847 | .tuner_gpio = default_tuner_gpio, |
827 | .decoder = EM28XX_TVP5150, | 848 | .decoder = EM28XX_TVP5150, |
828 | .has_dvb = 1, | 849 | .has_dvb = 1, |
829 | .dvb_gpio = default_analog, | 850 | .dvb_gpio = default_digital, |
830 | .input = { { | 851 | .input = { { |
831 | .type = EM28XX_VMUX_TELEVISION, | 852 | .type = EM28XX_VMUX_TELEVISION, |
832 | .vmux = TVP5150_COMPOSITE0, | 853 | .vmux = TVP5150_COMPOSITE0, |
@@ -1639,6 +1660,11 @@ static unsigned short tvp5150_addrs[] = { | |||
1639 | I2C_CLIENT_END | 1660 | I2C_CLIENT_END |
1640 | }; | 1661 | }; |
1641 | 1662 | ||
1663 | static unsigned short mt9v011_addrs[] = { | ||
1664 | 0xba >> 1, | ||
1665 | I2C_CLIENT_END | ||
1666 | }; | ||
1667 | |||
1642 | static unsigned short msp3400_addrs[] = { | 1668 | static unsigned short msp3400_addrs[] = { |
1643 | 0x80 >> 1, | 1669 | 0x80 >> 1, |
1644 | 0x88 >> 1, | 1670 | 0x88 >> 1, |
@@ -1678,6 +1704,46 @@ static inline void em28xx_set_model(struct em28xx *dev) | |||
1678 | EM28XX_I2C_FREQ_100_KHZ; | 1704 | EM28XX_I2C_FREQ_100_KHZ; |
1679 | } | 1705 | } |
1680 | 1706 | ||
1707 | /* HINT method: webcam I2C chips | ||
1708 | * | ||
1709 | * This method work for webcams with Micron sensors | ||
1710 | */ | ||
1711 | static int em28xx_hint_sensor(struct em28xx *dev) | ||
1712 | { | ||
1713 | int rc; | ||
1714 | char *sensor_name; | ||
1715 | unsigned char cmd; | ||
1716 | __be16 version_be; | ||
1717 | u16 version; | ||
1718 | |||
1719 | if (dev->model != EM2820_BOARD_UNKNOWN) | ||
1720 | return 0; | ||
1721 | |||
1722 | dev->i2c_client.addr = 0xba >> 1; | ||
1723 | cmd = 0; | ||
1724 | i2c_master_send(&dev->i2c_client, &cmd, 1); | ||
1725 | rc = i2c_master_recv(&dev->i2c_client, (char *)&version_be, 2); | ||
1726 | if (rc != 2) | ||
1727 | return -EINVAL; | ||
1728 | |||
1729 | version = be16_to_cpu(version_be); | ||
1730 | |||
1731 | switch (version) { | ||
1732 | case MT9V011_VERSION: | ||
1733 | dev->model = EM2820_BOARD_SILVERCREST_WEBCAM; | ||
1734 | sensor_name = "mt9v011"; | ||
1735 | break; | ||
1736 | default: | ||
1737 | printk("Unknown Sensor 0x%04x\n", be16_to_cpu(version)); | ||
1738 | return -EINVAL; | ||
1739 | } | ||
1740 | |||
1741 | em28xx_errdev("Sensor is %s, assuming that webcam is %s\n", | ||
1742 | sensor_name, em28xx_boards[dev->model].name); | ||
1743 | |||
1744 | return 0; | ||
1745 | } | ||
1746 | |||
1681 | /* Since em28xx_pre_card_setup() requires a proper dev->model, | 1747 | /* Since em28xx_pre_card_setup() requires a proper dev->model, |
1682 | * this won't work for boards with generic PCI IDs | 1748 | * this won't work for boards with generic PCI IDs |
1683 | */ | 1749 | */ |
@@ -1706,7 +1772,10 @@ void em28xx_pre_card_setup(struct em28xx *dev) | |||
1706 | em28xx_info("chip ID is em2750\n"); | 1772 | em28xx_info("chip ID is em2750\n"); |
1707 | break; | 1773 | break; |
1708 | case CHIP_ID_EM2820: | 1774 | case CHIP_ID_EM2820: |
1709 | em28xx_info("chip ID is em2820\n"); | 1775 | if (dev->board.is_27xx) |
1776 | em28xx_info("chip is em2710\n"); | ||
1777 | else | ||
1778 | em28xx_info("chip ID is em2820\n"); | ||
1710 | break; | 1779 | break; |
1711 | case CHIP_ID_EM2840: | 1780 | case CHIP_ID_EM2840: |
1712 | em28xx_info("chip ID is em2840\n"); | 1781 | em28xx_info("chip ID is em2840\n"); |
@@ -2158,6 +2227,10 @@ void em28xx_card_setup(struct em28xx *dev) | |||
2158 | before probing the i2c bus. */ | 2227 | before probing the i2c bus. */ |
2159 | em28xx_set_mode(dev, EM28XX_ANALOG_MODE); | 2228 | em28xx_set_mode(dev, EM28XX_ANALOG_MODE); |
2160 | break; | 2229 | break; |
2230 | case EM2820_BOARD_SILVERCREST_WEBCAM: | ||
2231 | /* FIXME: need to document the registers bellow */ | ||
2232 | em28xx_write_reg(dev, 0x0d, 0x42); | ||
2233 | em28xx_write_reg(dev, 0x13, 0x08); | ||
2161 | } | 2234 | } |
2162 | 2235 | ||
2163 | if (dev->board.has_snapshot_button) | 2236 | if (dev->board.has_snapshot_button) |
@@ -2189,6 +2262,10 @@ void em28xx_card_setup(struct em28xx *dev) | |||
2189 | v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, | 2262 | v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, |
2190 | "tvp5150", "tvp5150", tvp5150_addrs); | 2263 | "tvp5150", "tvp5150", tvp5150_addrs); |
2191 | 2264 | ||
2265 | if (dev->board.decoder == EM28XX_MT9V011) | ||
2266 | v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, | ||
2267 | "mt9v011", "mt9v011", mt9v011_addrs); | ||
2268 | |||
2192 | if (dev->board.adecoder == EM28XX_TVAUDIO) | 2269 | if (dev->board.adecoder == EM28XX_TVAUDIO) |
2193 | v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, | 2270 | v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, |
2194 | "tvaudio", "tvaudio", dev->board.tvaudio_addr); | 2271 | "tvaudio", "tvaudio", dev->board.tvaudio_addr); |
@@ -2333,6 +2410,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
2333 | return errCode; | 2410 | return errCode; |
2334 | } | 2411 | } |
2335 | 2412 | ||
2413 | em28xx_hint_sensor(dev); | ||
2414 | |||
2336 | /* Do board specific init and eeprom reading */ | 2415 | /* Do board specific init and eeprom reading */ |
2337 | em28xx_card_setup(dev); | 2416 | em28xx_card_setup(dev); |
2338 | 2417 | ||
@@ -2573,6 +2652,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
2573 | retval = em28xx_init_dev(&dev, udev, interface, nr); | 2652 | retval = em28xx_init_dev(&dev, udev, interface, nr); |
2574 | if (retval) { | 2653 | if (retval) { |
2575 | em28xx_devused &= ~(1<<dev->devno); | 2654 | em28xx_devused &= ~(1<<dev->devno); |
2655 | mutex_unlock(&dev->lock); | ||
2576 | kfree(dev); | 2656 | kfree(dev); |
2577 | goto err; | 2657 | goto err; |
2578 | } | 2658 | } |
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index c8d7ce8fbd36..079ab4d563a6 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c | |||
@@ -648,17 +648,28 @@ int em28xx_capture_start(struct em28xx *dev, int start) | |||
648 | int em28xx_set_outfmt(struct em28xx *dev) | 648 | int em28xx_set_outfmt(struct em28xx *dev) |
649 | { | 649 | { |
650 | int ret; | 650 | int ret; |
651 | int vinmode, vinctl, outfmt; | ||
652 | |||
653 | outfmt = dev->format->reg; | ||
654 | |||
655 | if (dev->board.is_27xx) { | ||
656 | vinmode = 0x0d; | ||
657 | vinctl = 0x00; | ||
658 | } else { | ||
659 | vinmode = 0x10; | ||
660 | vinctl = 0x11; | ||
661 | } | ||
651 | 662 | ||
652 | ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT, | 663 | ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT, |
653 | dev->format->reg | 0x20, 0x3f); | 664 | outfmt | 0x20, 0xff); |
654 | if (ret < 0) | 665 | if (ret < 0) |
655 | return ret; | 666 | return ret; |
656 | 667 | ||
657 | ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, 0x10); | 668 | ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, vinmode); |
658 | if (ret < 0) | 669 | if (ret < 0) |
659 | return ret; | 670 | return ret; |
660 | 671 | ||
661 | return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x11); | 672 | return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctl); |
662 | } | 673 | } |
663 | 674 | ||
664 | static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, | 675 | static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, |
@@ -695,13 +706,19 @@ static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v) | |||
695 | { | 706 | { |
696 | u8 mode; | 707 | u8 mode; |
697 | /* the em2800 scaler only supports scaling down to 50% */ | 708 | /* the em2800 scaler only supports scaling down to 50% */ |
698 | if (dev->board.is_em2800) | 709 | |
710 | if (dev->board.is_27xx) { | ||
711 | /* FIXME: Don't use the scaler yet */ | ||
712 | mode = 0; | ||
713 | } else if (dev->board.is_em2800) { | ||
699 | mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00); | 714 | mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00); |
700 | else { | 715 | } else { |
701 | u8 buf[2]; | 716 | u8 buf[2]; |
717 | |||
702 | buf[0] = h; | 718 | buf[0] = h; |
703 | buf[1] = h >> 8; | 719 | buf[1] = h >> 8; |
704 | em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2); | 720 | em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2); |
721 | |||
705 | buf[0] = v; | 722 | buf[0] = v; |
706 | buf[1] = v >> 8; | 723 | buf[1] = v >> 8; |
707 | em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2); | 724 | em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2); |
@@ -720,8 +737,11 @@ int em28xx_resolution_set(struct em28xx *dev) | |||
720 | height = norm_maxh(dev) >> 1; | 737 | height = norm_maxh(dev) >> 1; |
721 | 738 | ||
722 | em28xx_set_outfmt(dev); | 739 | em28xx_set_outfmt(dev); |
740 | |||
741 | |||
723 | em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2); | 742 | em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2); |
724 | em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2); | 743 | em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2); |
744 | |||
725 | return em28xx_scaler_set(dev, dev->hscale, dev->vscale); | 745 | return em28xx_scaler_set(dev, dev->hscale, dev->vscale); |
726 | } | 746 | } |
727 | 747 | ||
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index e7b47c8da8f3..3da97c32b8fa 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c | |||
@@ -243,6 +243,14 @@ static struct s5h1409_config em28xx_s5h1409_with_xc3028 = { | |||
243 | .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK | 243 | .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK |
244 | }; | 244 | }; |
245 | 245 | ||
246 | static struct zl10353_config em28xx_terratec_xs_zl10353_xc3028 = { | ||
247 | .demod_address = (0x1e >> 1), | ||
248 | .no_tuner = 1, | ||
249 | .disable_i2c_gate_ctrl = 1, | ||
250 | .parallel_ts = 1, | ||
251 | .if2 = 45600, | ||
252 | }; | ||
253 | |||
246 | #ifdef EM28XX_DRX397XD_SUPPORT | 254 | #ifdef EM28XX_DRX397XD_SUPPORT |
247 | /* [TODO] djh - not sure yet what the device config needs to contain */ | 255 | /* [TODO] djh - not sure yet what the device config needs to contain */ |
248 | static struct drx397xD_config em28xx_drx397xD_with_xc3028 = { | 256 | static struct drx397xD_config em28xx_drx397xD_with_xc3028 = { |
@@ -433,7 +441,6 @@ static int dvb_init(struct em28xx *dev) | |||
433 | } | 441 | } |
434 | break; | 442 | break; |
435 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: | 443 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: |
436 | case EM2880_BOARD_TERRATEC_HYBRID_XS: | ||
437 | case EM2880_BOARD_KWORLD_DVB_310U: | 444 | case EM2880_BOARD_KWORLD_DVB_310U: |
438 | case EM2880_BOARD_EMPIRE_DUAL_TV: | 445 | case EM2880_BOARD_EMPIRE_DUAL_TV: |
439 | dvb->frontend = dvb_attach(zl10353_attach, | 446 | dvb->frontend = dvb_attach(zl10353_attach, |
@@ -444,6 +451,25 @@ static int dvb_init(struct em28xx *dev) | |||
444 | goto out_free; | 451 | goto out_free; |
445 | } | 452 | } |
446 | break; | 453 | break; |
454 | case EM2880_BOARD_TERRATEC_HYBRID_XS: | ||
455 | dvb->frontend = dvb_attach(zl10353_attach, | ||
456 | &em28xx_terratec_xs_zl10353_xc3028, | ||
457 | &dev->i2c_adap); | ||
458 | if (dvb->frontend == NULL) { | ||
459 | /* This board could have either a zl10353 or a mt352. | ||
460 | If the chip id isn't for zl10353, try mt352 */ | ||
461 | |||
462 | /* FIXME: make support for mt352 work */ | ||
463 | printk(KERN_ERR "version of this board with mt352 not " | ||
464 | "currently supported\n"); | ||
465 | result = -EINVAL; | ||
466 | goto out_free; | ||
467 | } | ||
468 | if (attach_xc3028(0x61, dev) < 0) { | ||
469 | result = -EINVAL; | ||
470 | goto out_free; | ||
471 | } | ||
472 | break; | ||
447 | case EM2883_BOARD_KWORLD_HYBRID_330U: | 473 | case EM2883_BOARD_KWORLD_HYBRID_330U: |
448 | case EM2882_BOARD_EVGA_INDTUBE: | 474 | case EM2882_BOARD_EVGA_INDTUBE: |
449 | dvb->frontend = dvb_attach(s5h1409_attach, | 475 | dvb->frontend = dvb_attach(s5h1409_attach, |
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 2c86fcf089f5..27e33a287dfc 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c | |||
@@ -483,7 +483,7 @@ static char *i2c_devs[128] = { | |||
483 | [0xa0 >> 1] = "eeprom", | 483 | [0xa0 >> 1] = "eeprom", |
484 | [0xb0 >> 1] = "tda9874", | 484 | [0xb0 >> 1] = "tda9874", |
485 | [0xb8 >> 1] = "tvp5150a", | 485 | [0xb8 >> 1] = "tvp5150a", |
486 | [0xba >> 1] = "tvp5150a", | 486 | [0xba >> 1] = "webcam sensor or tvp5150a", |
487 | [0xc0 >> 1] = "tuner (analog)", | 487 | [0xc0 >> 1] = "tuner (analog)", |
488 | [0xc2 >> 1] = "tuner (analog)", | 488 | [0xc2 >> 1] = "tuner (analog)", |
489 | [0xc4 >> 1] = "tuner (analog)", | 489 | [0xc4 >> 1] = "tuner (analog)", |
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 8fe1beecfffa..14316c912179 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -90,10 +90,35 @@ MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); | |||
90 | /* supported video standards */ | 90 | /* supported video standards */ |
91 | static struct em28xx_fmt format[] = { | 91 | static struct em28xx_fmt format[] = { |
92 | { | 92 | { |
93 | .name = "16bpp YUY2, 4:2:2, packed", | 93 | .name = "16 bpp YUY2, 4:2:2, packed", |
94 | .fourcc = V4L2_PIX_FMT_YUYV, | 94 | .fourcc = V4L2_PIX_FMT_YUYV, |
95 | .depth = 16, | 95 | .depth = 16, |
96 | .reg = EM28XX_OUTFMT_YUV422_Y0UY1V, | 96 | .reg = EM28XX_OUTFMT_YUV422_Y0UY1V, |
97 | }, { | ||
98 | .name = "16 bpp RGB 565, LE", | ||
99 | .fourcc = V4L2_PIX_FMT_RGB565, | ||
100 | .depth = 16, | ||
101 | .reg = EM28XX_OUTFMT_RGB_16_656, | ||
102 | }, { | ||
103 | .name = "8 bpp Bayer BGBG..GRGR", | ||
104 | .fourcc = V4L2_PIX_FMT_SBGGR8, | ||
105 | .depth = 8, | ||
106 | .reg = EM28XX_OUTFMT_RGB_8_BGBG, | ||
107 | }, { | ||
108 | .name = "8 bpp Bayer GRGR..BGBG", | ||
109 | .fourcc = V4L2_PIX_FMT_SGRBG8, | ||
110 | .depth = 8, | ||
111 | .reg = EM28XX_OUTFMT_RGB_8_GRGR, | ||
112 | }, { | ||
113 | .name = "8 bpp Bayer GBGB..RGRG", | ||
114 | .fourcc = V4L2_PIX_FMT_SGBRG8, | ||
115 | .depth = 8, | ||
116 | .reg = EM28XX_OUTFMT_RGB_8_GBGB, | ||
117 | }, { | ||
118 | .name = "12 bpp YUV411", | ||
119 | .fourcc = V4L2_PIX_FMT_YUV411P, | ||
120 | .depth = 12, | ||
121 | .reg = EM28XX_OUTFMT_YUV411, | ||
97 | }, | 122 | }, |
98 | }; | 123 | }; |
99 | 124 | ||
@@ -701,7 +726,11 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
701 | return -EINVAL; | 726 | return -EINVAL; |
702 | } | 727 | } |
703 | 728 | ||
704 | if (dev->board.is_em2800) { | 729 | if (dev->board.is_27xx) { |
730 | /* FIXME: This is the only supported fmt */ | ||
731 | width = 640; | ||
732 | height = 480; | ||
733 | } else if (dev->board.is_em2800) { | ||
705 | /* the em2800 can only scale down to 50% */ | 734 | /* the em2800 can only scale down to 50% */ |
706 | height = height > (3 * maxh / 4) ? maxh : maxh / 2; | 735 | height = height > (3 * maxh / 4) ? maxh : maxh / 2; |
707 | width = width > (3 * maxw / 4) ? maxw : maxw / 2; | 736 | width = width > (3 * maxw / 4) ? maxw : maxw / 2; |
@@ -733,13 +762,40 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
733 | return 0; | 762 | return 0; |
734 | } | 763 | } |
735 | 764 | ||
765 | static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc, | ||
766 | unsigned width, unsigned height) | ||
767 | { | ||
768 | struct em28xx_fmt *fmt; | ||
769 | |||
770 | /* FIXME: This is the only supported fmt */ | ||
771 | if (dev->board.is_27xx) { | ||
772 | width = 640; | ||
773 | height = 480; | ||
774 | } | ||
775 | |||
776 | fmt = format_by_fourcc(fourcc); | ||
777 | if (!fmt) | ||
778 | return -EINVAL; | ||
779 | |||
780 | dev->format = fmt; | ||
781 | dev->width = width; | ||
782 | dev->height = height; | ||
783 | |||
784 | /* set new image size */ | ||
785 | get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); | ||
786 | |||
787 | em28xx_set_alternate(dev); | ||
788 | em28xx_resolution_set(dev); | ||
789 | |||
790 | return 0; | ||
791 | } | ||
792 | |||
736 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | 793 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, |
737 | struct v4l2_format *f) | 794 | struct v4l2_format *f) |
738 | { | 795 | { |
739 | struct em28xx_fh *fh = priv; | 796 | struct em28xx_fh *fh = priv; |
740 | struct em28xx *dev = fh->dev; | 797 | struct em28xx *dev = fh->dev; |
741 | int rc; | 798 | int rc; |
742 | struct em28xx_fmt *fmt; | ||
743 | 799 | ||
744 | rc = check_dev(dev); | 800 | rc = check_dev(dev); |
745 | if (rc < 0) | 801 | if (rc < 0) |
@@ -749,12 +805,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
749 | 805 | ||
750 | vidioc_try_fmt_vid_cap(file, priv, f); | 806 | vidioc_try_fmt_vid_cap(file, priv, f); |
751 | 807 | ||
752 | fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
753 | if (!fmt) { | ||
754 | rc = -EINVAL; | ||
755 | goto out; | ||
756 | } | ||
757 | |||
758 | if (videobuf_queue_is_busy(&fh->vb_vidq)) { | 808 | if (videobuf_queue_is_busy(&fh->vb_vidq)) { |
759 | em28xx_errdev("%s queue busy\n", __func__); | 809 | em28xx_errdev("%s queue busy\n", __func__); |
760 | rc = -EBUSY; | 810 | rc = -EBUSY; |
@@ -767,16 +817,8 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
767 | goto out; | 817 | goto out; |
768 | } | 818 | } |
769 | 819 | ||
770 | /* set new image size */ | 820 | rc = em28xx_set_video_format(dev, f->fmt.pix.pixelformat, |
771 | dev->width = f->fmt.pix.width; | 821 | f->fmt.pix.width, f->fmt.pix.height); |
772 | dev->height = f->fmt.pix.height; | ||
773 | dev->format = fmt; | ||
774 | get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); | ||
775 | |||
776 | em28xx_set_alternate(dev); | ||
777 | em28xx_resolution_set(dev); | ||
778 | |||
779 | rc = 0; | ||
780 | 822 | ||
781 | out: | 823 | out: |
782 | mutex_unlock(&dev->lock); | 824 | mutex_unlock(&dev->lock); |
@@ -1616,11 +1658,6 @@ static int em28xx_v4l2_open(struct file *filp) | |||
1616 | filp->private_data = fh; | 1658 | filp->private_data = fh; |
1617 | 1659 | ||
1618 | if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { | 1660 | if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { |
1619 | dev->width = norm_maxw(dev); | ||
1620 | dev->height = norm_maxh(dev); | ||
1621 | dev->hscale = 0; | ||
1622 | dev->vscale = 0; | ||
1623 | |||
1624 | em28xx_set_mode(dev, EM28XX_ANALOG_MODE); | 1661 | em28xx_set_mode(dev, EM28XX_ANALOG_MODE); |
1625 | em28xx_set_alternate(dev); | 1662 | em28xx_set_alternate(dev); |
1626 | em28xx_resolution_set(dev); | 1663 | em28xx_resolution_set(dev); |
@@ -1962,15 +1999,14 @@ int em28xx_register_analog_devices(struct em28xx *dev) | |||
1962 | 1999 | ||
1963 | /* set default norm */ | 2000 | /* set default norm */ |
1964 | dev->norm = em28xx_video_template.current_norm; | 2001 | dev->norm = em28xx_video_template.current_norm; |
1965 | dev->width = norm_maxw(dev); | ||
1966 | dev->height = norm_maxh(dev); | ||
1967 | dev->interlaced = EM28XX_INTERLACED_DEFAULT; | 2002 | dev->interlaced = EM28XX_INTERLACED_DEFAULT; |
1968 | dev->hscale = 0; | ||
1969 | dev->vscale = 0; | ||
1970 | dev->ctl_input = 0; | 2003 | dev->ctl_input = 0; |
1971 | 2004 | ||
1972 | /* Analog specific initialization */ | 2005 | /* Analog specific initialization */ |
1973 | dev->format = &format[0]; | 2006 | dev->format = &format[0]; |
2007 | em28xx_set_video_format(dev, format[0].fourcc, | ||
2008 | norm_maxw(dev), norm_maxh(dev)); | ||
2009 | |||
1974 | video_mux(dev, dev->ctl_input); | 2010 | video_mux(dev, dev->ctl_input); |
1975 | 2011 | ||
1976 | /* Audio defaults */ | 2012 | /* Audio defaults */ |
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 813ce45c2f99..d90fef463764 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
@@ -107,6 +107,7 @@ | |||
107 | #define EM2860_BOARD_TERRATEC_AV350 68 | 107 | #define EM2860_BOARD_TERRATEC_AV350 68 |
108 | #define EM2882_BOARD_KWORLD_ATSC_315U 69 | 108 | #define EM2882_BOARD_KWORLD_ATSC_315U 69 |
109 | #define EM2882_BOARD_EVGA_INDTUBE 70 | 109 | #define EM2882_BOARD_EVGA_INDTUBE 70 |
110 | #define EM2820_BOARD_SILVERCREST_WEBCAM 71 | ||
110 | 111 | ||
111 | /* Limits minimum and default number of buffers */ | 112 | /* Limits minimum and default number of buffers */ |
112 | #define EM28XX_MIN_BUF 4 | 113 | #define EM28XX_MIN_BUF 4 |
@@ -360,6 +361,7 @@ enum em28xx_decoder { | |||
360 | EM28XX_NODECODER, | 361 | EM28XX_NODECODER, |
361 | EM28XX_TVP5150, | 362 | EM28XX_TVP5150, |
362 | EM28XX_SAA711X, | 363 | EM28XX_SAA711X, |
364 | EM28XX_MT9V011, | ||
363 | }; | 365 | }; |
364 | 366 | ||
365 | enum em28xx_adecoder { | 367 | enum em28xx_adecoder { |
@@ -388,6 +390,7 @@ struct em28xx_board { | |||
388 | unsigned int max_range_640_480:1; | 390 | unsigned int max_range_640_480:1; |
389 | unsigned int has_dvb:1; | 391 | unsigned int has_dvb:1; |
390 | unsigned int has_snapshot_button:1; | 392 | unsigned int has_snapshot_button:1; |
393 | unsigned int is_27xx:1; | ||
391 | unsigned int valid:1; | 394 | unsigned int valid:1; |
392 | 395 | ||
393 | unsigned char xclk, i2c_speed; | 396 | unsigned char xclk, i2c_speed; |
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.h b/drivers/media/video/gspca/stv06xx/stv06xx.h index 9df7137fe67e..992ce530f138 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx.h | |||
@@ -36,10 +36,6 @@ | |||
36 | 36 | ||
37 | #define STV_ISOC_ENDPOINT_ADDR 0x81 | 37 | #define STV_ISOC_ENDPOINT_ADDR 0x81 |
38 | 38 | ||
39 | #ifndef V4L2_PIX_FMT_SGRBG8 | ||
40 | #define V4L2_PIX_FMT_SGRBG8 v4l2_fourcc('G', 'R', 'B', 'G') | ||
41 | #endif | ||
42 | |||
43 | #define STV_REG23 0x0423 | 39 | #define STV_REG23 0x0423 |
44 | 40 | ||
45 | /* Control registers of the STV0600 ASIC */ | 41 | /* Control registers of the STV0600 ASIC */ |
diff --git a/drivers/media/video/mt9v011.c b/drivers/media/video/mt9v011.c new file mode 100644 index 000000000000..1fe8fc9183a7 --- /dev/null +++ b/drivers/media/video/mt9v011.c | |||
@@ -0,0 +1,431 @@ | |||
1 | /* | ||
2 | * mt9v011 -Micron 1/4-Inch VGA Digital Image Sensor | ||
3 | * | ||
4 | * Copyright (c) 2009 Mauro Carvalho Chehab (mchehab@redhat.com) | ||
5 | * This code is placed under the terms of the GNU General Public License v2 | ||
6 | */ | ||
7 | |||
8 | #include <linux/i2c.h> | ||
9 | #include <linux/videodev2.h> | ||
10 | #include <linux/delay.h> | ||
11 | #include <media/v4l2-device.h> | ||
12 | #include "mt9v011.h" | ||
13 | #include <media/v4l2-i2c-drv.h> | ||
14 | #include <media/v4l2-chip-ident.h> | ||
15 | |||
16 | MODULE_DESCRIPTION("Micron mt9v011 sensor driver"); | ||
17 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
18 | MODULE_LICENSE("GPL"); | ||
19 | |||
20 | |||
21 | static int debug; | ||
22 | module_param(debug, int, 0); | ||
23 | MODULE_PARM_DESC(debug, "Debug level (0-2)"); | ||
24 | |||
25 | /* supported controls */ | ||
26 | static struct v4l2_queryctrl mt9v011_qctrl[] = { | ||
27 | { | ||
28 | .id = V4L2_CID_GAIN, | ||
29 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
30 | .name = "Gain", | ||
31 | .minimum = 0, | ||
32 | .maximum = (1 << 10) - 1, | ||
33 | .step = 1, | ||
34 | .default_value = 0x0020, | ||
35 | .flags = 0, | ||
36 | }, { | ||
37 | .id = V4L2_CID_RED_BALANCE, | ||
38 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
39 | .name = "Red Balance", | ||
40 | .minimum = -1 << 9, | ||
41 | .maximum = (1 << 9) - 1, | ||
42 | .step = 1, | ||
43 | .default_value = 0, | ||
44 | .flags = 0, | ||
45 | }, { | ||
46 | .id = V4L2_CID_BLUE_BALANCE, | ||
47 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
48 | .name = "Blue Balance", | ||
49 | .minimum = -1 << 9, | ||
50 | .maximum = (1 << 9) - 1, | ||
51 | .step = 1, | ||
52 | .default_value = 0, | ||
53 | .flags = 0, | ||
54 | }, | ||
55 | }; | ||
56 | |||
57 | struct mt9v011 { | ||
58 | struct v4l2_subdev sd; | ||
59 | unsigned width, height; | ||
60 | |||
61 | u16 global_gain, red_bal, blue_bal; | ||
62 | }; | ||
63 | |||
64 | static inline struct mt9v011 *to_mt9v011(struct v4l2_subdev *sd) | ||
65 | { | ||
66 | return container_of(sd, struct mt9v011, sd); | ||
67 | } | ||
68 | |||
69 | static int mt9v011_read(struct v4l2_subdev *sd, unsigned char addr) | ||
70 | { | ||
71 | struct i2c_client *c = v4l2_get_subdevdata(sd); | ||
72 | __be16 buffer; | ||
73 | int rc, val; | ||
74 | |||
75 | rc = i2c_master_send(c, &addr, 1); | ||
76 | if (rc != 1) | ||
77 | v4l2_dbg(0, debug, sd, | ||
78 | "i2c i/o error: rc == %d (should be 1)\n", rc); | ||
79 | |||
80 | msleep(10); | ||
81 | |||
82 | rc = i2c_master_recv(c, (char *)&buffer, 2); | ||
83 | if (rc != 2) | ||
84 | v4l2_dbg(0, debug, sd, | ||
85 | "i2c i/o error: rc == %d (should be 2)\n", rc); | ||
86 | |||
87 | val = be16_to_cpu(buffer); | ||
88 | |||
89 | v4l2_dbg(2, debug, sd, "mt9v011: read 0x%02x = 0x%04x\n", addr, val); | ||
90 | |||
91 | return val; | ||
92 | } | ||
93 | |||
94 | static void mt9v011_write(struct v4l2_subdev *sd, unsigned char addr, | ||
95 | u16 value) | ||
96 | { | ||
97 | struct i2c_client *c = v4l2_get_subdevdata(sd); | ||
98 | unsigned char buffer[3]; | ||
99 | int rc; | ||
100 | |||
101 | buffer[0] = addr; | ||
102 | buffer[1] = value >> 8; | ||
103 | buffer[2] = value & 0xff; | ||
104 | |||
105 | v4l2_dbg(2, debug, sd, | ||
106 | "mt9v011: writing 0x%02x 0x%04x\n", buffer[0], value); | ||
107 | rc = i2c_master_send(c, buffer, 3); | ||
108 | if (rc != 3) | ||
109 | v4l2_dbg(0, debug, sd, | ||
110 | "i2c i/o error: rc == %d (should be 3)\n", rc); | ||
111 | } | ||
112 | |||
113 | |||
114 | struct i2c_reg_value { | ||
115 | unsigned char reg; | ||
116 | u16 value; | ||
117 | }; | ||
118 | |||
119 | /* | ||
120 | * Values used at the original driver | ||
121 | * Some values are marked as Reserved at the datasheet | ||
122 | */ | ||
123 | static const struct i2c_reg_value mt9v011_init_default[] = { | ||
124 | { R0D_MT9V011_RESET, 0x0001 }, | ||
125 | { R0D_MT9V011_RESET, 0x0000 }, | ||
126 | |||
127 | { R0C_MT9V011_SHUTTER_DELAY, 0x0000 }, | ||
128 | { R09_MT9V011_SHUTTER_WIDTH, 0x1fc }, | ||
129 | |||
130 | { R0A_MT9V011_CLK_SPEED, 0x0000 }, | ||
131 | { R1E_MT9V011_DIGITAL_ZOOM, 0x0000 }, | ||
132 | { R20_MT9V011_READ_MODE, 0x1000 }, | ||
133 | |||
134 | { R07_MT9V011_OUT_CTRL, 0x000a }, /* chip enable */ | ||
135 | }; | ||
136 | |||
137 | static void set_balance(struct v4l2_subdev *sd) | ||
138 | { | ||
139 | struct mt9v011 *core = to_mt9v011(sd); | ||
140 | u16 green1_gain, green2_gain, blue_gain, red_gain; | ||
141 | |||
142 | green1_gain = core->global_gain; | ||
143 | green2_gain = core->global_gain; | ||
144 | |||
145 | blue_gain = core->global_gain + | ||
146 | core->global_gain * core->blue_bal / (1 << 9); | ||
147 | |||
148 | red_gain = core->global_gain + | ||
149 | core->global_gain * core->blue_bal / (1 << 9); | ||
150 | |||
151 | mt9v011_write(sd, R2B_MT9V011_GREEN_1_GAIN, green1_gain); | ||
152 | mt9v011_write(sd, R2E_MT9V011_GREEN_2_GAIN, green1_gain); | ||
153 | mt9v011_write(sd, R2C_MT9V011_BLUE_GAIN, blue_gain); | ||
154 | mt9v011_write(sd, R2D_MT9V011_RED_GAIN, red_gain); | ||
155 | } | ||
156 | |||
157 | static void set_res(struct v4l2_subdev *sd) | ||
158 | { | ||
159 | struct mt9v011 *core = to_mt9v011(sd); | ||
160 | unsigned vstart, hstart; | ||
161 | |||
162 | /* | ||
163 | * The mt9v011 doesn't have scaling. So, in order to select the desired | ||
164 | * resolution, we're cropping at the middle of the sensor. | ||
165 | * hblank and vblank should be adjusted, in order to warrant that | ||
166 | * we'll preserve the line timings for 30 fps, no matter what resolution | ||
167 | * is selected. | ||
168 | * NOTE: datasheet says that width (and height) should be filled with | ||
169 | * width-1. However, this doesn't work, since one pixel per line will | ||
170 | * be missing. | ||
171 | */ | ||
172 | |||
173 | hstart = 14 + (640 - core->width) / 2; | ||
174 | mt9v011_write(sd, R02_MT9V011_COLSTART, hstart); | ||
175 | mt9v011_write(sd, R04_MT9V011_WIDTH, core->width); | ||
176 | mt9v011_write(sd, R05_MT9V011_HBLANK, 771 - core->width); | ||
177 | |||
178 | vstart = 8 + (640 - core->height) / 2; | ||
179 | mt9v011_write(sd, R01_MT9V011_ROWSTART, vstart); | ||
180 | mt9v011_write(sd, R03_MT9V011_HEIGHT, core->height); | ||
181 | mt9v011_write(sd, R06_MT9V011_VBLANK, 508 - core->height); | ||
182 | }; | ||
183 | |||
184 | static int mt9v011_reset(struct v4l2_subdev *sd, u32 val) | ||
185 | { | ||
186 | int i; | ||
187 | |||
188 | for (i = 0; i < ARRAY_SIZE(mt9v011_init_default); i++) | ||
189 | mt9v011_write(sd, mt9v011_init_default[i].reg, | ||
190 | mt9v011_init_default[i].value); | ||
191 | |||
192 | set_balance(sd); | ||
193 | set_res(sd); | ||
194 | |||
195 | return 0; | ||
196 | }; | ||
197 | |||
198 | static int mt9v011_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
199 | { | ||
200 | struct mt9v011 *core = to_mt9v011(sd); | ||
201 | |||
202 | v4l2_dbg(1, debug, sd, "g_ctrl called\n"); | ||
203 | |||
204 | switch (ctrl->id) { | ||
205 | case V4L2_CID_GAIN: | ||
206 | ctrl->value = core->global_gain; | ||
207 | return 0; | ||
208 | case V4L2_CID_RED_BALANCE: | ||
209 | ctrl->value = core->red_bal; | ||
210 | return 0; | ||
211 | case V4L2_CID_BLUE_BALANCE: | ||
212 | ctrl->value = core->blue_bal; | ||
213 | return 0; | ||
214 | } | ||
215 | return -EINVAL; | ||
216 | } | ||
217 | |||
218 | static int mt9v011_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
219 | { | ||
220 | struct mt9v011 *core = to_mt9v011(sd); | ||
221 | u8 i, n; | ||
222 | n = ARRAY_SIZE(mt9v011_qctrl); | ||
223 | |||
224 | for (i = 0; i < n; i++) { | ||
225 | if (ctrl->id != mt9v011_qctrl[i].id) | ||
226 | continue; | ||
227 | if (ctrl->value < mt9v011_qctrl[i].minimum || | ||
228 | ctrl->value > mt9v011_qctrl[i].maximum) | ||
229 | return -ERANGE; | ||
230 | v4l2_dbg(1, debug, sd, "s_ctrl: id=%d, value=%d\n", | ||
231 | ctrl->id, ctrl->value); | ||
232 | break; | ||
233 | } | ||
234 | |||
235 | switch (ctrl->id) { | ||
236 | case V4L2_CID_GAIN: | ||
237 | core->global_gain = ctrl->value; | ||
238 | break; | ||
239 | case V4L2_CID_RED_BALANCE: | ||
240 | core->red_bal = ctrl->value; | ||
241 | break; | ||
242 | case V4L2_CID_BLUE_BALANCE: | ||
243 | core->blue_bal = ctrl->value; | ||
244 | break; | ||
245 | default: | ||
246 | return -EINVAL; | ||
247 | } | ||
248 | |||
249 | set_balance(sd); | ||
250 | |||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | static int mt9v011_enum_fmt(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt) | ||
255 | { | ||
256 | if (fmt->index > 0) | ||
257 | return -EINVAL; | ||
258 | |||
259 | fmt->flags = 0; | ||
260 | strcpy(fmt->description, "8 bpp Bayer GRGR..BGBG"); | ||
261 | fmt->pixelformat = V4L2_PIX_FMT_SGRBG8; | ||
262 | |||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | static int mt9v011_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | ||
267 | { | ||
268 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | ||
269 | |||
270 | if (pix->pixelformat != V4L2_PIX_FMT_SGRBG8) | ||
271 | return -EINVAL; | ||
272 | |||
273 | v4l_bound_align_image(&pix->width, 48, 639, 1, | ||
274 | &pix->height, 32, 480, 1, 0); | ||
275 | |||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | static int mt9v011_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | ||
280 | { | ||
281 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | ||
282 | struct mt9v011 *core = to_mt9v011(sd); | ||
283 | int rc; | ||
284 | |||
285 | rc = mt9v011_try_fmt(sd, fmt); | ||
286 | if (rc < 0) | ||
287 | return -EINVAL; | ||
288 | |||
289 | core->width = pix->width; | ||
290 | core->height = pix->height; | ||
291 | |||
292 | set_res(sd); | ||
293 | |||
294 | return 0; | ||
295 | } | ||
296 | |||
297 | |||
298 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
299 | static int mt9v011_g_register(struct v4l2_subdev *sd, | ||
300 | struct v4l2_dbg_register *reg) | ||
301 | { | ||
302 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
303 | |||
304 | if (!v4l2_chip_match_i2c_client(client, ®->match)) | ||
305 | return -EINVAL; | ||
306 | if (!capable(CAP_SYS_ADMIN)) | ||
307 | return -EPERM; | ||
308 | |||
309 | reg->val = mt9v011_read(sd, reg->reg & 0xff); | ||
310 | reg->size = 2; | ||
311 | |||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | static int mt9v011_s_register(struct v4l2_subdev *sd, | ||
316 | struct v4l2_dbg_register *reg) | ||
317 | { | ||
318 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
319 | |||
320 | if (!v4l2_chip_match_i2c_client(client, ®->match)) | ||
321 | return -EINVAL; | ||
322 | if (!capable(CAP_SYS_ADMIN)) | ||
323 | return -EPERM; | ||
324 | |||
325 | mt9v011_write(sd, reg->reg & 0xff, reg->val & 0xffff); | ||
326 | |||
327 | return 0; | ||
328 | } | ||
329 | #endif | ||
330 | |||
331 | static int mt9v011_g_chip_ident(struct v4l2_subdev *sd, | ||
332 | struct v4l2_dbg_chip_ident *chip) | ||
333 | { | ||
334 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
335 | |||
336 | return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_MT9V011, | ||
337 | MT9V011_VERSION); | ||
338 | } | ||
339 | |||
340 | static const struct v4l2_subdev_core_ops mt9v011_core_ops = { | ||
341 | .g_ctrl = mt9v011_g_ctrl, | ||
342 | .s_ctrl = mt9v011_s_ctrl, | ||
343 | .reset = mt9v011_reset, | ||
344 | .g_chip_ident = mt9v011_g_chip_ident, | ||
345 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
346 | .g_register = mt9v011_g_register, | ||
347 | .s_register = mt9v011_s_register, | ||
348 | #endif | ||
349 | }; | ||
350 | |||
351 | static const struct v4l2_subdev_video_ops mt9v011_video_ops = { | ||
352 | .enum_fmt = mt9v011_enum_fmt, | ||
353 | .try_fmt = mt9v011_try_fmt, | ||
354 | .s_fmt = mt9v011_s_fmt, | ||
355 | }; | ||
356 | |||
357 | static const struct v4l2_subdev_ops mt9v011_ops = { | ||
358 | .core = &mt9v011_core_ops, | ||
359 | .video = &mt9v011_video_ops, | ||
360 | }; | ||
361 | |||
362 | |||
363 | /**************************************************************************** | ||
364 | I2C Client & Driver | ||
365 | ****************************************************************************/ | ||
366 | |||
367 | static int mt9v011_probe(struct i2c_client *c, | ||
368 | const struct i2c_device_id *id) | ||
369 | { | ||
370 | u16 version; | ||
371 | struct mt9v011 *core; | ||
372 | struct v4l2_subdev *sd; | ||
373 | |||
374 | /* Check if the adapter supports the needed features */ | ||
375 | if (!i2c_check_functionality(c->adapter, | ||
376 | I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) | ||
377 | return -EIO; | ||
378 | |||
379 | core = kzalloc(sizeof(struct mt9v011), GFP_KERNEL); | ||
380 | if (!core) | ||
381 | return -ENOMEM; | ||
382 | |||
383 | sd = &core->sd; | ||
384 | v4l2_i2c_subdev_init(sd, c, &mt9v011_ops); | ||
385 | |||
386 | /* Check if the sensor is really a MT9V011 */ | ||
387 | version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION); | ||
388 | if (version != MT9V011_VERSION) { | ||
389 | v4l2_info(sd, "*** unknown micron chip detected (0x%04x.\n", | ||
390 | version); | ||
391 | kfree(core); | ||
392 | return -EINVAL; | ||
393 | } | ||
394 | |||
395 | core->global_gain = 0x0024; | ||
396 | core->width = 640; | ||
397 | core->height = 480; | ||
398 | |||
399 | v4l_info(c, "chip found @ 0x%02x (%s)\n", | ||
400 | c->addr << 1, c->adapter->name); | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | static int mt9v011_remove(struct i2c_client *c) | ||
406 | { | ||
407 | struct v4l2_subdev *sd = i2c_get_clientdata(c); | ||
408 | |||
409 | v4l2_dbg(1, debug, sd, | ||
410 | "mt9v011.c: removing mt9v011 adapter on address 0x%x\n", | ||
411 | c->addr << 1); | ||
412 | |||
413 | v4l2_device_unregister_subdev(sd); | ||
414 | kfree(to_mt9v011(sd)); | ||
415 | return 0; | ||
416 | } | ||
417 | |||
418 | /* ----------------------------------------------------------------------- */ | ||
419 | |||
420 | static const struct i2c_device_id mt9v011_id[] = { | ||
421 | { "mt9v011", 0 }, | ||
422 | { } | ||
423 | }; | ||
424 | MODULE_DEVICE_TABLE(i2c, mt9v011_id); | ||
425 | |||
426 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | ||
427 | .name = "mt9v011", | ||
428 | .probe = mt9v011_probe, | ||
429 | .remove = mt9v011_remove, | ||
430 | .id_table = mt9v011_id, | ||
431 | }; | ||
diff --git a/drivers/media/video/mt9v011.h b/drivers/media/video/mt9v011.h new file mode 100644 index 000000000000..9e443ee30558 --- /dev/null +++ b/drivers/media/video/mt9v011.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | * mt9v011 -Micron 1/4-Inch VGA Digital Image Sensor | ||
3 | * | ||
4 | * Copyright (c) 2009 Mauro Carvalho Chehab (mchehab@redhat.com) | ||
5 | * This code is placed under the terms of the GNU General Public License v2 | ||
6 | */ | ||
7 | |||
8 | #ifndef MT9V011_H_ | ||
9 | #define MT9V011_H_ | ||
10 | |||
11 | #define R00_MT9V011_CHIP_VERSION 0x00 | ||
12 | #define R01_MT9V011_ROWSTART 0x01 | ||
13 | #define R02_MT9V011_COLSTART 0x02 | ||
14 | #define R03_MT9V011_HEIGHT 0x03 | ||
15 | #define R04_MT9V011_WIDTH 0x04 | ||
16 | #define R05_MT9V011_HBLANK 0x05 | ||
17 | #define R06_MT9V011_VBLANK 0x06 | ||
18 | #define R07_MT9V011_OUT_CTRL 0x07 | ||
19 | #define R09_MT9V011_SHUTTER_WIDTH 0x09 | ||
20 | #define R0A_MT9V011_CLK_SPEED 0x0a | ||
21 | #define R0B_MT9V011_RESTART 0x0b | ||
22 | #define R0C_MT9V011_SHUTTER_DELAY 0x0c | ||
23 | #define R0D_MT9V011_RESET 0x0d | ||
24 | #define R1E_MT9V011_DIGITAL_ZOOM 0x1e | ||
25 | #define R20_MT9V011_READ_MODE 0x20 | ||
26 | #define R2B_MT9V011_GREEN_1_GAIN 0x2b | ||
27 | #define R2C_MT9V011_BLUE_GAIN 0x2c | ||
28 | #define R2D_MT9V011_RED_GAIN 0x2d | ||
29 | #define R2E_MT9V011_GREEN_2_GAIN 0x2e | ||
30 | #define R35_MT9V011_GLOBAL_GAIN 0x35 | ||
31 | #define RF1_MT9V011_CHIP_ENABLE 0xf1 | ||
32 | |||
33 | #define MT9V011_VERSION 0x8243 | ||
34 | |||
35 | #endif | ||
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 16f595d4337a..9f5ae8167855 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c | |||
@@ -237,11 +237,11 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd) | |||
237 | return -ENOMEM; | 237 | return -ENOMEM; |
238 | 238 | ||
239 | icd->num_user_formats = fmts; | 239 | icd->num_user_formats = fmts; |
240 | fmts = 0; | ||
241 | 240 | ||
242 | dev_dbg(&icd->dev, "Found %d supported formats.\n", fmts); | 241 | dev_dbg(&icd->dev, "Found %d supported formats.\n", fmts); |
243 | 242 | ||
244 | /* Second pass - actually fill data formats */ | 243 | /* Second pass - actually fill data formats */ |
244 | fmts = 0; | ||
245 | for (i = 0; i < icd->num_formats; i++) | 245 | for (i = 0; i < icd->num_formats; i++) |
246 | if (!ici->ops->get_formats) { | 246 | if (!ici->ops->get_formats) { |
247 | icd->user_formats[i].host_fmt = icd->formats + i; | 247 | icd->user_formats[i].host_fmt = icd->formats + i; |
@@ -877,8 +877,11 @@ static int soc_camera_probe(struct device *dev) | |||
877 | (unsigned short)~0; | 877 | (unsigned short)~0; |
878 | 878 | ||
879 | ret = soc_camera_init_user_formats(icd); | 879 | ret = soc_camera_init_user_formats(icd); |
880 | if (ret < 0) | 880 | if (ret < 0) { |
881 | if (icd->ops->remove) | ||
882 | icd->ops->remove(icd); | ||
881 | goto eiufmt; | 883 | goto eiufmt; |
884 | } | ||
882 | 885 | ||
883 | icd->height = DEFAULT_HEIGHT; | 886 | icd->height = DEFAULT_HEIGHT; |
884 | icd->width = DEFAULT_WIDTH; | 887 | icd->width = DEFAULT_WIDTH; |
@@ -902,8 +905,10 @@ static int soc_camera_remove(struct device *dev) | |||
902 | { | 905 | { |
903 | struct soc_camera_device *icd = to_soc_camera_dev(dev); | 906 | struct soc_camera_device *icd = to_soc_camera_dev(dev); |
904 | 907 | ||
908 | mutex_lock(&icd->video_lock); | ||
905 | if (icd->ops->remove) | 909 | if (icd->ops->remove) |
906 | icd->ops->remove(icd); | 910 | icd->ops->remove(icd); |
911 | mutex_unlock(&icd->video_lock); | ||
907 | 912 | ||
908 | soc_camera_free_user_formats(icd); | 913 | soc_camera_free_user_formats(icd); |
909 | 914 | ||
@@ -1145,6 +1150,7 @@ evidallocd: | |||
1145 | } | 1150 | } |
1146 | EXPORT_SYMBOL(soc_camera_video_start); | 1151 | EXPORT_SYMBOL(soc_camera_video_start); |
1147 | 1152 | ||
1153 | /* Called from client .remove() methods with .video_lock held */ | ||
1148 | void soc_camera_video_stop(struct soc_camera_device *icd) | 1154 | void soc_camera_video_stop(struct soc_camera_device *icd) |
1149 | { | 1155 | { |
1150 | struct video_device *vdev = icd->vdev; | 1156 | struct video_device *vdev = icd->vdev; |
@@ -1154,10 +1160,8 @@ void soc_camera_video_stop(struct soc_camera_device *icd) | |||
1154 | if (!icd->dev.parent || !vdev) | 1160 | if (!icd->dev.parent || !vdev) |
1155 | return; | 1161 | return; |
1156 | 1162 | ||
1157 | mutex_lock(&icd->video_lock); | ||
1158 | video_unregister_device(vdev); | 1163 | video_unregister_device(vdev); |
1159 | icd->vdev = NULL; | 1164 | icd->vdev = NULL; |
1160 | mutex_unlock(&icd->video_lock); | ||
1161 | } | 1165 | } |
1162 | EXPORT_SYMBOL(soc_camera_video_stop); | 1166 | EXPORT_SYMBOL(soc_camera_video_stop); |
1163 | 1167 | ||
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index cd7266858462..7705fc6baf00 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c | |||
@@ -343,6 +343,53 @@ static struct bar_std bars[] = { | |||
343 | #define TO_U(r, g, b) \ | 343 | #define TO_U(r, g, b) \ |
344 | (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128) | 344 | (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128) |
345 | 345 | ||
346 | /* precalculate color bar values to speed up rendering */ | ||
347 | static void precalculate_bars(struct vivi_fh *fh) | ||
348 | { | ||
349 | struct vivi_dev *dev = fh->dev; | ||
350 | unsigned char r, g, b; | ||
351 | int k, is_yuv; | ||
352 | |||
353 | fh->input = dev->input; | ||
354 | |||
355 | for (k = 0; k < 8; k++) { | ||
356 | r = bars[fh->input].bar[k][0]; | ||
357 | g = bars[fh->input].bar[k][1]; | ||
358 | b = bars[fh->input].bar[k][2]; | ||
359 | is_yuv = 0; | ||
360 | |||
361 | switch (fh->fmt->fourcc) { | ||
362 | case V4L2_PIX_FMT_YUYV: | ||
363 | case V4L2_PIX_FMT_UYVY: | ||
364 | is_yuv = 1; | ||
365 | break; | ||
366 | case V4L2_PIX_FMT_RGB565: | ||
367 | case V4L2_PIX_FMT_RGB565X: | ||
368 | r >>= 3; | ||
369 | g >>= 2; | ||
370 | b >>= 3; | ||
371 | break; | ||
372 | case V4L2_PIX_FMT_RGB555: | ||
373 | case V4L2_PIX_FMT_RGB555X: | ||
374 | r >>= 3; | ||
375 | g >>= 3; | ||
376 | b >>= 3; | ||
377 | break; | ||
378 | } | ||
379 | |||
380 | if (is_yuv) { | ||
381 | fh->bars[k][0] = TO_Y(r, g, b); /* Luma */ | ||
382 | fh->bars[k][1] = TO_U(r, g, b); /* Cb */ | ||
383 | fh->bars[k][2] = TO_V(r, g, b); /* Cr */ | ||
384 | } else { | ||
385 | fh->bars[k][0] = r; | ||
386 | fh->bars[k][1] = g; | ||
387 | fh->bars[k][2] = b; | ||
388 | } | ||
389 | } | ||
390 | |||
391 | } | ||
392 | |||
346 | #define TSTAMP_MIN_Y 24 | 393 | #define TSTAMP_MIN_Y 24 |
347 | #define TSTAMP_MAX_Y (TSTAMP_MIN_Y + 15) | 394 | #define TSTAMP_MAX_Y (TSTAMP_MIN_Y + 15) |
348 | #define TSTAMP_INPUT_X 10 | 395 | #define TSTAMP_INPUT_X 10 |
@@ -755,6 +802,8 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, | |||
755 | buf->vb.height = fh->height; | 802 | buf->vb.height = fh->height; |
756 | buf->vb.field = field; | 803 | buf->vb.field = field; |
757 | 804 | ||
805 | precalculate_bars(fh); | ||
806 | |||
758 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { | 807 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { |
759 | rc = videobuf_iolock(vq, &buf->vb, NULL); | 808 | rc = videobuf_iolock(vq, &buf->vb, NULL); |
760 | if (rc < 0) | 809 | if (rc < 0) |
@@ -893,53 +942,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
893 | return 0; | 942 | return 0; |
894 | } | 943 | } |
895 | 944 | ||
896 | /* precalculate color bar values to speed up rendering */ | ||
897 | static void precalculate_bars(struct vivi_fh *fh) | ||
898 | { | ||
899 | struct vivi_dev *dev = fh->dev; | ||
900 | unsigned char r, g, b; | ||
901 | int k, is_yuv; | ||
902 | |||
903 | fh->input = dev->input; | ||
904 | |||
905 | for (k = 0; k < 8; k++) { | ||
906 | r = bars[fh->input].bar[k][0]; | ||
907 | g = bars[fh->input].bar[k][1]; | ||
908 | b = bars[fh->input].bar[k][2]; | ||
909 | is_yuv = 0; | ||
910 | |||
911 | switch (fh->fmt->fourcc) { | ||
912 | case V4L2_PIX_FMT_YUYV: | ||
913 | case V4L2_PIX_FMT_UYVY: | ||
914 | is_yuv = 1; | ||
915 | break; | ||
916 | case V4L2_PIX_FMT_RGB565: | ||
917 | case V4L2_PIX_FMT_RGB565X: | ||
918 | r >>= 3; | ||
919 | g >>= 2; | ||
920 | b >>= 3; | ||
921 | break; | ||
922 | case V4L2_PIX_FMT_RGB555: | ||
923 | case V4L2_PIX_FMT_RGB555X: | ||
924 | r >>= 3; | ||
925 | g >>= 3; | ||
926 | b >>= 3; | ||
927 | break; | ||
928 | } | ||
929 | |||
930 | if (is_yuv) { | ||
931 | fh->bars[k][0] = TO_Y(r, g, b); /* Luma */ | ||
932 | fh->bars[k][1] = TO_U(r, g, b); /* Cb */ | ||
933 | fh->bars[k][2] = TO_V(r, g, b); /* Cr */ | ||
934 | } else { | ||
935 | fh->bars[k][0] = r; | ||
936 | fh->bars[k][1] = g; | ||
937 | fh->bars[k][2] = b; | ||
938 | } | ||
939 | } | ||
940 | |||
941 | } | ||
942 | |||
943 | /*FIXME: This seems to be generic enough to be at videodev2 */ | 945 | /*FIXME: This seems to be generic enough to be at videodev2 */ |
944 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | 946 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, |
945 | struct v4l2_format *f) | 947 | struct v4l2_format *f) |
@@ -965,8 +967,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
965 | fh->vb_vidq.field = f->fmt.pix.field; | 967 | fh->vb_vidq.field = f->fmt.pix.field; |
966 | fh->type = f->type; | 968 | fh->type = f->type; |
967 | 969 | ||
968 | precalculate_bars(fh); | ||
969 | |||
970 | ret = 0; | 970 | ret = 0; |
971 | out: | 971 | out: |
972 | mutex_unlock(&q->vb_lock); | 972 | mutex_unlock(&q->vb_lock); |
@@ -1357,6 +1357,7 @@ static int __init vivi_create_instance(int inst) | |||
1357 | goto unreg_dev; | 1357 | goto unreg_dev; |
1358 | 1358 | ||
1359 | *vfd = vivi_template; | 1359 | *vfd = vivi_template; |
1360 | vfd->debug = debug; | ||
1360 | 1361 | ||
1361 | ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr); | 1362 | ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr); |
1362 | if (ret < 0) | 1363 | if (ret < 0) |
diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c index 671a7efe86a8..c1de4afa89a6 100644 --- a/drivers/mfd/ezx-pcap.c +++ b/drivers/mfd/ezx-pcap.c | |||
@@ -238,8 +238,10 @@ static irqreturn_t pcap_adc_irq(int irq, void *_pcap) | |||
238 | mutex_lock(&pcap->adc_mutex); | 238 | mutex_lock(&pcap->adc_mutex); |
239 | req = pcap->adc_queue[pcap->adc_head]; | 239 | req = pcap->adc_queue[pcap->adc_head]; |
240 | 240 | ||
241 | if (WARN(!req, KERN_WARNING "adc irq without pending request\n")) | 241 | if (WARN(!req, KERN_WARNING "adc irq without pending request\n")) { |
242 | mutex_unlock(&pcap->adc_mutex); | ||
242 | return IRQ_HANDLED; | 243 | return IRQ_HANDLED; |
244 | } | ||
243 | 245 | ||
244 | /* read requested channels results */ | 246 | /* read requested channels results */ |
245 | ezx_pcap_read(pcap, PCAP_REG_ADC, &tmp); | 247 | ezx_pcap_read(pcap, PCAP_REG_ADC, &tmp); |
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index 4c7b7962f6b8..0cc5eeff5ee8 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c | |||
@@ -367,7 +367,8 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to) | |||
367 | break; | 367 | break; |
368 | 368 | ||
369 | default: | 369 | default: |
370 | return -1; | 370 | gate = -1; |
371 | goto already; | ||
371 | } | 372 | } |
372 | 373 | ||
373 | writel(mode, sm->regs + SM501_POWER_MODE_CONTROL); | 374 | writel(mode, sm->regs + SM501_POWER_MODE_CONTROL); |
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index 5d610cbcfe80..0f0e0b919ef4 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c | |||
@@ -1134,7 +1134,7 @@ static const struct file_operations ccio_proc_bitmap_fops = { | |||
1134 | .llseek = seq_lseek, | 1134 | .llseek = seq_lseek, |
1135 | .release = single_release, | 1135 | .release = single_release, |
1136 | }; | 1136 | }; |
1137 | #endif | 1137 | #endif /* CONFIG_PROC_FS */ |
1138 | 1138 | ||
1139 | /** | 1139 | /** |
1140 | * ccio_find_ioc - Find the ioc in the ioc_list | 1140 | * ccio_find_ioc - Find the ioc in the ioc_list |
@@ -1568,14 +1568,15 @@ static int __init ccio_probe(struct parisc_device *dev) | |||
1568 | /* if this fails, no I/O cards will work, so may as well bug */ | 1568 | /* if this fails, no I/O cards will work, so may as well bug */ |
1569 | BUG_ON(dev->dev.platform_data == NULL); | 1569 | BUG_ON(dev->dev.platform_data == NULL); |
1570 | HBA_DATA(dev->dev.platform_data)->iommu = ioc; | 1570 | HBA_DATA(dev->dev.platform_data)->iommu = ioc; |
1571 | 1571 | ||
1572 | #ifdef CONFIG_PROC_FS | ||
1572 | if (ioc_count == 0) { | 1573 | if (ioc_count == 0) { |
1573 | proc_create(MODULE_NAME, 0, proc_runway_root, | 1574 | proc_create(MODULE_NAME, 0, proc_runway_root, |
1574 | &ccio_proc_info_fops); | 1575 | &ccio_proc_info_fops); |
1575 | proc_create(MODULE_NAME"-bitmap", 0, proc_runway_root, | 1576 | proc_create(MODULE_NAME"-bitmap", 0, proc_runway_root, |
1576 | &ccio_proc_bitmap_fops); | 1577 | &ccio_proc_bitmap_fops); |
1577 | } | 1578 | } |
1578 | 1579 | #endif | |
1579 | ioc_count++; | 1580 | ioc_count++; |
1580 | 1581 | ||
1581 | parisc_has_iommu(); | 1582 | parisc_has_iommu(); |
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index 52ae0b1d470c..c590974e9815 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c | |||
@@ -353,7 +353,7 @@ static unsigned int dino_startup_irq(unsigned int irq) | |||
353 | return 0; | 353 | return 0; |
354 | } | 354 | } |
355 | 355 | ||
356 | static struct hw_interrupt_type dino_interrupt_type = { | 356 | static struct irq_chip dino_interrupt_type = { |
357 | .typename = "GSC-PCI", | 357 | .typename = "GSC-PCI", |
358 | .startup = dino_startup_irq, | 358 | .startup = dino_startup_irq, |
359 | .shutdown = dino_disable_irq, | 359 | .shutdown = dino_disable_irq, |
@@ -1019,22 +1019,22 @@ static int __init dino_probe(struct parisc_device *dev) | |||
1019 | ** It's not used to avoid chicken/egg problems | 1019 | ** It's not used to avoid chicken/egg problems |
1020 | ** with configuration accessor functions. | 1020 | ** with configuration accessor functions. |
1021 | */ | 1021 | */ |
1022 | bus = pci_scan_bus_parented(&dev->dev, dino_current_bus, | 1022 | dino_dev->hba.hba_bus = bus = pci_scan_bus_parented(&dev->dev, |
1023 | &dino_cfg_ops, NULL); | 1023 | dino_current_bus, &dino_cfg_ops, NULL); |
1024 | |||
1024 | if(bus) { | 1025 | if(bus) { |
1025 | pci_bus_add_devices(bus); | ||
1026 | /* This code *depends* on scanning being single threaded | 1026 | /* This code *depends* on scanning being single threaded |
1027 | * if it isn't, this global bus number count will fail | 1027 | * if it isn't, this global bus number count will fail |
1028 | */ | 1028 | */ |
1029 | dino_current_bus = bus->subordinate + 1; | 1029 | dino_current_bus = bus->subordinate + 1; |
1030 | pci_bus_assign_resources(bus); | 1030 | pci_bus_assign_resources(bus); |
1031 | pci_bus_add_devices(bus); | ||
1031 | } else { | 1032 | } else { |
1032 | printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (probably duplicate bus number %d)\n", | 1033 | printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (duplicate bus number %d?)\n", |
1033 | dev_name(&dev->dev), dino_current_bus); | 1034 | dev_name(&dev->dev), dino_current_bus); |
1034 | /* increment the bus number in case of duplicates */ | 1035 | /* increment the bus number in case of duplicates */ |
1035 | dino_current_bus++; | 1036 | dino_current_bus++; |
1036 | } | 1037 | } |
1037 | dino_dev->hba.hba_bus = bus; | ||
1038 | return 0; | 1038 | return 0; |
1039 | } | 1039 | } |
1040 | 1040 | ||
diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c index 5b89f404e668..51220749cb65 100644 --- a/drivers/parisc/eisa.c +++ b/drivers/parisc/eisa.c | |||
@@ -188,7 +188,7 @@ static unsigned int eisa_startup_irq(unsigned int irq) | |||
188 | return 0; | 188 | return 0; |
189 | } | 189 | } |
190 | 190 | ||
191 | static struct hw_interrupt_type eisa_interrupt_type = { | 191 | static struct irq_chip eisa_interrupt_type = { |
192 | .typename = "EISA", | 192 | .typename = "EISA", |
193 | .startup = eisa_startup_irq, | 193 | .startup = eisa_startup_irq, |
194 | .shutdown = eisa_disable_irq, | 194 | .shutdown = eisa_disable_irq, |
diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c index d33632917696..647adc9f85ad 100644 --- a/drivers/parisc/gsc.c +++ b/drivers/parisc/gsc.c | |||
@@ -148,7 +148,7 @@ static unsigned int gsc_asic_startup_irq(unsigned int irq) | |||
148 | return 0; | 148 | return 0; |
149 | } | 149 | } |
150 | 150 | ||
151 | static struct hw_interrupt_type gsc_asic_interrupt_type = { | 151 | static struct irq_chip gsc_asic_interrupt_type = { |
152 | .typename = "GSC-ASIC", | 152 | .typename = "GSC-ASIC", |
153 | .startup = gsc_asic_startup_irq, | 153 | .startup = gsc_asic_startup_irq, |
154 | .shutdown = gsc_asic_disable_irq, | 154 | .shutdown = gsc_asic_disable_irq, |
@@ -158,7 +158,7 @@ static struct hw_interrupt_type gsc_asic_interrupt_type = { | |||
158 | .end = no_end_irq, | 158 | .end = no_end_irq, |
159 | }; | 159 | }; |
160 | 160 | ||
161 | int gsc_assign_irq(struct hw_interrupt_type *type, void *data) | 161 | int gsc_assign_irq(struct irq_chip *type, void *data) |
162 | { | 162 | { |
163 | static int irq = GSC_IRQ_BASE; | 163 | static int irq = GSC_IRQ_BASE; |
164 | struct irq_desc *desc; | 164 | struct irq_desc *desc; |
diff --git a/drivers/parisc/gsc.h b/drivers/parisc/gsc.h index 762a1babad60..b9d7bfb68e24 100644 --- a/drivers/parisc/gsc.h +++ b/drivers/parisc/gsc.h | |||
@@ -38,7 +38,7 @@ struct gsc_asic { | |||
38 | int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic); | 38 | int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic); |
39 | int gsc_alloc_irq(struct gsc_irq *dev); /* dev needs an irq */ | 39 | int gsc_alloc_irq(struct gsc_irq *dev); /* dev needs an irq */ |
40 | int gsc_claim_irq(struct gsc_irq *dev, int irq); /* dev needs this irq */ | 40 | int gsc_claim_irq(struct gsc_irq *dev, int irq); /* dev needs this irq */ |
41 | int gsc_assign_irq(struct hw_interrupt_type *type, void *data); | 41 | int gsc_assign_irq(struct irq_chip *type, void *data); |
42 | int gsc_find_local_irq(unsigned int irq, int *global_irq, int limit); | 42 | int gsc_find_local_irq(unsigned int irq, int *global_irq, int limit); |
43 | void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl, | 43 | void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl, |
44 | void (*choose)(struct parisc_device *child, void *ctrl)); | 44 | void (*choose)(struct parisc_device *child, void *ctrl)); |
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 4a9cc92d4d18..88e333553212 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c | |||
@@ -729,7 +729,7 @@ static int iosapic_set_affinity_irq(unsigned int irq, | |||
729 | } | 729 | } |
730 | #endif | 730 | #endif |
731 | 731 | ||
732 | static struct hw_interrupt_type iosapic_interrupt_type = { | 732 | static struct irq_chip iosapic_interrupt_type = { |
733 | .typename = "IO-SAPIC-level", | 733 | .typename = "IO-SAPIC-level", |
734 | .startup = iosapic_startup_irq, | 734 | .startup = iosapic_startup_irq, |
735 | .shutdown = iosapic_disable_irq, | 735 | .shutdown = iosapic_disable_irq, |
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index 59fbbf128365..ede614616f8e 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c | |||
@@ -980,28 +980,38 @@ static void | |||
980 | lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) | 980 | lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) |
981 | { | 981 | { |
982 | unsigned long bytecnt; | 982 | unsigned long bytecnt; |
983 | pdc_pat_cell_mod_maddr_block_t pa_pdc_cell; /* PA_VIEW */ | ||
984 | pdc_pat_cell_mod_maddr_block_t io_pdc_cell; /* IO_VIEW */ | ||
985 | long io_count; | 983 | long io_count; |
986 | long status; /* PDC return status */ | 984 | long status; /* PDC return status */ |
987 | long pa_count; | 985 | long pa_count; |
986 | pdc_pat_cell_mod_maddr_block_t *pa_pdc_cell; /* PA_VIEW */ | ||
987 | pdc_pat_cell_mod_maddr_block_t *io_pdc_cell; /* IO_VIEW */ | ||
988 | int i; | 988 | int i; |
989 | 989 | ||
990 | pa_pdc_cell = kzalloc(sizeof(pdc_pat_cell_mod_maddr_block_t), GFP_KERNEL); | ||
991 | if (!pa_pdc_cell) | ||
992 | return; | ||
993 | |||
994 | io_pdc_cell = kzalloc(sizeof(pdc_pat_cell_mod_maddr_block_t), GFP_KERNEL); | ||
995 | if (!pa_pdc_cell) { | ||
996 | kfree(pa_pdc_cell); | ||
997 | return; | ||
998 | } | ||
999 | |||
990 | /* return cell module (IO view) */ | 1000 | /* return cell module (IO view) */ |
991 | status = pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc, pa_dev->mod_index, | 1001 | status = pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc, pa_dev->mod_index, |
992 | PA_VIEW, & pa_pdc_cell); | 1002 | PA_VIEW, pa_pdc_cell); |
993 | pa_count = pa_pdc_cell.mod[1]; | 1003 | pa_count = pa_pdc_cell->mod[1]; |
994 | 1004 | ||
995 | status |= pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc, pa_dev->mod_index, | 1005 | status |= pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc, pa_dev->mod_index, |
996 | IO_VIEW, &io_pdc_cell); | 1006 | IO_VIEW, io_pdc_cell); |
997 | io_count = io_pdc_cell.mod[1]; | 1007 | io_count = io_pdc_cell->mod[1]; |
998 | 1008 | ||
999 | /* We've already done this once for device discovery...*/ | 1009 | /* We've already done this once for device discovery...*/ |
1000 | if (status != PDC_OK) { | 1010 | if (status != PDC_OK) { |
1001 | panic("pdc_pat_cell_module() call failed for LBA!\n"); | 1011 | panic("pdc_pat_cell_module() call failed for LBA!\n"); |
1002 | } | 1012 | } |
1003 | 1013 | ||
1004 | if (PAT_GET_ENTITY(pa_pdc_cell.mod_info) != PAT_ENTITY_LBA) { | 1014 | if (PAT_GET_ENTITY(pa_pdc_cell->mod_info) != PAT_ENTITY_LBA) { |
1005 | panic("pdc_pat_cell_module() entity returned != PAT_ENTITY_LBA!\n"); | 1015 | panic("pdc_pat_cell_module() entity returned != PAT_ENTITY_LBA!\n"); |
1006 | } | 1016 | } |
1007 | 1017 | ||
@@ -1016,8 +1026,8 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) | |||
1016 | } *p, *io; | 1026 | } *p, *io; |
1017 | struct resource *r; | 1027 | struct resource *r; |
1018 | 1028 | ||
1019 | p = (void *) &(pa_pdc_cell.mod[2+i*3]); | 1029 | p = (void *) &(pa_pdc_cell->mod[2+i*3]); |
1020 | io = (void *) &(io_pdc_cell.mod[2+i*3]); | 1030 | io = (void *) &(io_pdc_cell->mod[2+i*3]); |
1021 | 1031 | ||
1022 | /* Convert the PAT range data to PCI "struct resource" */ | 1032 | /* Convert the PAT range data to PCI "struct resource" */ |
1023 | switch(p->type & 0xff) { | 1033 | switch(p->type & 0xff) { |
@@ -1096,6 +1106,9 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) | |||
1096 | break; | 1106 | break; |
1097 | } | 1107 | } |
1098 | } | 1108 | } |
1109 | |||
1110 | kfree(pa_pdc_cell); | ||
1111 | kfree(io_pdc_cell); | ||
1099 | } | 1112 | } |
1100 | #else | 1113 | #else |
1101 | /* keep compiler from complaining about missing declarations */ | 1114 | /* keep compiler from complaining about missing declarations */ |
@@ -1509,10 +1522,6 @@ lba_driver_probe(struct parisc_device *dev) | |||
1509 | lba_bus = lba_dev->hba.hba_bus = | 1522 | lba_bus = lba_dev->hba.hba_bus = |
1510 | pci_scan_bus_parented(&dev->dev, lba_dev->hba.bus_num.start, | 1523 | pci_scan_bus_parented(&dev->dev, lba_dev->hba.bus_num.start, |
1511 | cfg_ops, NULL); | 1524 | cfg_ops, NULL); |
1512 | if (lba_bus) { | ||
1513 | lba_next_bus = lba_bus->subordinate + 1; | ||
1514 | pci_bus_add_devices(lba_bus); | ||
1515 | } | ||
1516 | 1525 | ||
1517 | /* This is in lieu of calling pci_assign_unassigned_resources() */ | 1526 | /* This is in lieu of calling pci_assign_unassigned_resources() */ |
1518 | if (is_pdc_pat()) { | 1527 | if (is_pdc_pat()) { |
@@ -1533,7 +1542,6 @@ lba_driver_probe(struct parisc_device *dev) | |||
1533 | } | 1542 | } |
1534 | pci_enable_bridges(lba_bus); | 1543 | pci_enable_bridges(lba_bus); |
1535 | 1544 | ||
1536 | |||
1537 | /* | 1545 | /* |
1538 | ** Once PCI register ops has walked the bus, access to config | 1546 | ** Once PCI register ops has walked the bus, access to config |
1539 | ** space is restricted. Avoids master aborts on config cycles. | 1547 | ** space is restricted. Avoids master aborts on config cycles. |
@@ -1543,6 +1551,11 @@ lba_driver_probe(struct parisc_device *dev) | |||
1543 | lba_dev->flags |= LBA_FLAG_SKIP_PROBE; | 1551 | lba_dev->flags |= LBA_FLAG_SKIP_PROBE; |
1544 | } | 1552 | } |
1545 | 1553 | ||
1554 | if (lba_bus) { | ||
1555 | lba_next_bus = lba_bus->subordinate + 1; | ||
1556 | pci_bus_add_devices(lba_bus); | ||
1557 | } | ||
1558 | |||
1546 | /* Whew! Finally done! Tell services we got this one covered. */ | 1559 | /* Whew! Finally done! Tell services we got this one covered. */ |
1547 | return 0; | 1560 | return 0; |
1548 | } | 1561 | } |
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index d46dd57450ac..123d8fe3427d 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c | |||
@@ -2057,6 +2057,7 @@ void sba_directed_lmmio(struct parisc_device *pci_hba, struct resource *r) | |||
2057 | r->start = (base & ~1UL) | PCI_F_EXTEND; | 2057 | r->start = (base & ~1UL) | PCI_F_EXTEND; |
2058 | size = ~ READ_REG32(reg + LMMIO_DIRECT0_MASK); | 2058 | size = ~ READ_REG32(reg + LMMIO_DIRECT0_MASK); |
2059 | r->end = r->start + size; | 2059 | r->end = r->start + size; |
2060 | r->flags = IORESOURCE_MEM; | ||
2060 | } | 2061 | } |
2061 | } | 2062 | } |
2062 | 2063 | ||
@@ -2093,4 +2094,5 @@ void sba_distributed_lmmio(struct parisc_device *pci_hba, struct resource *r ) | |||
2093 | size = (~READ_REG32(sba->sba_hpa + LMMIO_DIST_MASK)) / ROPES_PER_IOC; | 2094 | size = (~READ_REG32(sba->sba_hpa + LMMIO_DIST_MASK)) / ROPES_PER_IOC; |
2094 | r->start += rope * (size + 1); /* adjust base for this rope */ | 2095 | r->start += rope * (size + 1); /* adjust base for this rope */ |
2095 | r->end = r->start + size; | 2096 | r->end = r->start + size; |
2097 | r->flags = IORESOURCE_MEM; | ||
2096 | } | 2098 | } |
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c index 33e5ade774ca..675f04e6597a 100644 --- a/drivers/parisc/superio.c +++ b/drivers/parisc/superio.c | |||
@@ -325,7 +325,7 @@ static unsigned int superio_startup_irq(unsigned int irq) | |||
325 | return 0; | 325 | return 0; |
326 | } | 326 | } |
327 | 327 | ||
328 | static struct hw_interrupt_type superio_interrupt_type = { | 328 | static struct irq_chip superio_interrupt_type = { |
329 | .typename = SUPERIO, | 329 | .typename = SUPERIO, |
330 | .startup = superio_startup_irq, | 330 | .startup = superio_startup_irq, |
331 | .shutdown = superio_disable_irq, | 331 | .shutdown = superio_disable_irq, |
@@ -434,8 +434,8 @@ static void __init superio_parport_init(void) | |||
434 | 0 /*base_hi*/, | 434 | 0 /*base_hi*/, |
435 | PAR_IRQ, | 435 | PAR_IRQ, |
436 | PARPORT_DMA_NONE /* dma */, | 436 | PARPORT_DMA_NONE /* dma */, |
437 | NULL /*struct pci_dev* */), | 437 | NULL /*struct pci_dev* */, |
438 | 0 /* shared irq flags */ ) | 438 | 0 /* shared irq flags */)) |
439 | 439 | ||
440 | printk(KERN_WARNING PFX "Probing parallel port failed.\n"); | 440 | printk(KERN_WARNING PFX "Probing parallel port failed.\n"); |
441 | #endif /* CONFIG_PARPORT_PC */ | 441 | #endif /* CONFIG_PARPORT_PC */ |
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index 844580489d4d..5c5043f239cf 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c | |||
@@ -555,6 +555,8 @@ static struct hotplug_slot *get_slot_from_name (const char *name) | |||
555 | * @slot: pointer to the &struct hotplug_slot to register | 555 | * @slot: pointer to the &struct hotplug_slot to register |
556 | * @devnr: device number | 556 | * @devnr: device number |
557 | * @name: name registered with kobject core | 557 | * @name: name registered with kobject core |
558 | * @owner: caller module owner | ||
559 | * @mod_name: caller module name | ||
558 | * | 560 | * |
559 | * Registers a hotplug slot with the pci hotplug subsystem, which will allow | 561 | * Registers a hotplug slot with the pci hotplug subsystem, which will allow |
560 | * userspace interaction to the slot. | 562 | * userspace interaction to the slot. |
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 420afa887283..360fb67a30d7 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
@@ -56,14 +56,32 @@ | |||
56 | #define MAX_AGAW_WIDTH 64 | 56 | #define MAX_AGAW_WIDTH 64 |
57 | 57 | ||
58 | #define DOMAIN_MAX_ADDR(gaw) ((((u64)1) << gaw) - 1) | 58 | #define DOMAIN_MAX_ADDR(gaw) ((((u64)1) << gaw) - 1) |
59 | #define DOMAIN_MAX_PFN(gaw) ((((u64)1) << (gaw-VTD_PAGE_SHIFT)) - 1) | ||
59 | 60 | ||
60 | #define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT) | 61 | #define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT) |
61 | #define DMA_32BIT_PFN IOVA_PFN(DMA_BIT_MASK(32)) | 62 | #define DMA_32BIT_PFN IOVA_PFN(DMA_BIT_MASK(32)) |
62 | #define DMA_64BIT_PFN IOVA_PFN(DMA_BIT_MASK(64)) | 63 | #define DMA_64BIT_PFN IOVA_PFN(DMA_BIT_MASK(64)) |
63 | 64 | ||
64 | #ifndef PHYSICAL_PAGE_MASK | 65 | |
65 | #define PHYSICAL_PAGE_MASK PAGE_MASK | 66 | /* VT-d pages must always be _smaller_ than MM pages. Otherwise things |
66 | #endif | 67 | are never going to work. */ |
68 | static inline unsigned long dma_to_mm_pfn(unsigned long dma_pfn) | ||
69 | { | ||
70 | return dma_pfn >> (PAGE_SHIFT - VTD_PAGE_SHIFT); | ||
71 | } | ||
72 | |||
73 | static inline unsigned long mm_to_dma_pfn(unsigned long mm_pfn) | ||
74 | { | ||
75 | return mm_pfn << (PAGE_SHIFT - VTD_PAGE_SHIFT); | ||
76 | } | ||
77 | static inline unsigned long page_to_dma_pfn(struct page *pg) | ||
78 | { | ||
79 | return mm_to_dma_pfn(page_to_pfn(pg)); | ||
80 | } | ||
81 | static inline unsigned long virt_to_dma_pfn(void *p) | ||
82 | { | ||
83 | return page_to_dma_pfn(virt_to_page(p)); | ||
84 | } | ||
67 | 85 | ||
68 | /* global iommu list, set NULL for ignored DMAR units */ | 86 | /* global iommu list, set NULL for ignored DMAR units */ |
69 | static struct intel_iommu **g_iommus; | 87 | static struct intel_iommu **g_iommus; |
@@ -204,12 +222,17 @@ static inline void dma_set_pte_prot(struct dma_pte *pte, unsigned long prot) | |||
204 | 222 | ||
205 | static inline u64 dma_pte_addr(struct dma_pte *pte) | 223 | static inline u64 dma_pte_addr(struct dma_pte *pte) |
206 | { | 224 | { |
207 | return (pte->val & VTD_PAGE_MASK); | 225 | #ifdef CONFIG_64BIT |
226 | return pte->val & VTD_PAGE_MASK; | ||
227 | #else | ||
228 | /* Must have a full atomic 64-bit read */ | ||
229 | return __cmpxchg64(pte, 0ULL, 0ULL) & VTD_PAGE_MASK; | ||
230 | #endif | ||
208 | } | 231 | } |
209 | 232 | ||
210 | static inline void dma_set_pte_addr(struct dma_pte *pte, u64 addr) | 233 | static inline void dma_set_pte_pfn(struct dma_pte *pte, unsigned long pfn) |
211 | { | 234 | { |
212 | pte->val |= (addr & VTD_PAGE_MASK); | 235 | pte->val |= (uint64_t)pfn << VTD_PAGE_SHIFT; |
213 | } | 236 | } |
214 | 237 | ||
215 | static inline bool dma_pte_present(struct dma_pte *pte) | 238 | static inline bool dma_pte_present(struct dma_pte *pte) |
@@ -217,6 +240,11 @@ static inline bool dma_pte_present(struct dma_pte *pte) | |||
217 | return (pte->val & 3) != 0; | 240 | return (pte->val & 3) != 0; |
218 | } | 241 | } |
219 | 242 | ||
243 | static inline int first_pte_in_page(struct dma_pte *pte) | ||
244 | { | ||
245 | return !((unsigned long)pte & ~VTD_PAGE_MASK); | ||
246 | } | ||
247 | |||
220 | /* | 248 | /* |
221 | * This domain is a statically identity mapping domain. | 249 | * This domain is a statically identity mapping domain. |
222 | * 1. This domain creats a static 1:1 mapping to all usable memory. | 250 | * 1. This domain creats a static 1:1 mapping to all usable memory. |
@@ -244,7 +272,6 @@ struct dmar_domain { | |||
244 | struct iova_domain iovad; /* iova's that belong to this domain */ | 272 | struct iova_domain iovad; /* iova's that belong to this domain */ |
245 | 273 | ||
246 | struct dma_pte *pgd; /* virtual address */ | 274 | struct dma_pte *pgd; /* virtual address */ |
247 | spinlock_t mapping_lock; /* page table lock */ | ||
248 | int gaw; /* max guest address width */ | 275 | int gaw; /* max guest address width */ |
249 | 276 | ||
250 | /* adjusted guest address width, 0 is level 2 30-bit */ | 277 | /* adjusted guest address width, 0 is level 2 30-bit */ |
@@ -648,80 +675,78 @@ static inline int width_to_agaw(int width) | |||
648 | 675 | ||
649 | static inline unsigned int level_to_offset_bits(int level) | 676 | static inline unsigned int level_to_offset_bits(int level) |
650 | { | 677 | { |
651 | return (12 + (level - 1) * LEVEL_STRIDE); | 678 | return (level - 1) * LEVEL_STRIDE; |
652 | } | 679 | } |
653 | 680 | ||
654 | static inline int address_level_offset(u64 addr, int level) | 681 | static inline int pfn_level_offset(unsigned long pfn, int level) |
655 | { | 682 | { |
656 | return ((addr >> level_to_offset_bits(level)) & LEVEL_MASK); | 683 | return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK; |
657 | } | 684 | } |
658 | 685 | ||
659 | static inline u64 level_mask(int level) | 686 | static inline unsigned long level_mask(int level) |
660 | { | 687 | { |
661 | return ((u64)-1 << level_to_offset_bits(level)); | 688 | return -1UL << level_to_offset_bits(level); |
662 | } | 689 | } |
663 | 690 | ||
664 | static inline u64 level_size(int level) | 691 | static inline unsigned long level_size(int level) |
665 | { | 692 | { |
666 | return ((u64)1 << level_to_offset_bits(level)); | 693 | return 1UL << level_to_offset_bits(level); |
667 | } | 694 | } |
668 | 695 | ||
669 | static inline u64 align_to_level(u64 addr, int level) | 696 | static inline unsigned long align_to_level(unsigned long pfn, int level) |
670 | { | 697 | { |
671 | return ((addr + level_size(level) - 1) & level_mask(level)); | 698 | return (pfn + level_size(level) - 1) & level_mask(level); |
672 | } | 699 | } |
673 | 700 | ||
674 | static struct dma_pte * addr_to_dma_pte(struct dmar_domain *domain, u64 addr) | 701 | static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, |
702 | unsigned long pfn) | ||
675 | { | 703 | { |
676 | int addr_width = agaw_to_width(domain->agaw); | 704 | int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; |
677 | struct dma_pte *parent, *pte = NULL; | 705 | struct dma_pte *parent, *pte = NULL; |
678 | int level = agaw_to_level(domain->agaw); | 706 | int level = agaw_to_level(domain->agaw); |
679 | int offset; | 707 | int offset; |
680 | unsigned long flags; | ||
681 | 708 | ||
682 | BUG_ON(!domain->pgd); | 709 | BUG_ON(!domain->pgd); |
683 | 710 | BUG_ON(addr_width < BITS_PER_LONG && pfn >> addr_width); | |
684 | addr &= (((u64)1) << addr_width) - 1; | ||
685 | parent = domain->pgd; | 711 | parent = domain->pgd; |
686 | 712 | ||
687 | spin_lock_irqsave(&domain->mapping_lock, flags); | ||
688 | while (level > 0) { | 713 | while (level > 0) { |
689 | void *tmp_page; | 714 | void *tmp_page; |
690 | 715 | ||
691 | offset = address_level_offset(addr, level); | 716 | offset = pfn_level_offset(pfn, level); |
692 | pte = &parent[offset]; | 717 | pte = &parent[offset]; |
693 | if (level == 1) | 718 | if (level == 1) |
694 | break; | 719 | break; |
695 | 720 | ||
696 | if (!dma_pte_present(pte)) { | 721 | if (!dma_pte_present(pte)) { |
722 | uint64_t pteval; | ||
723 | |||
697 | tmp_page = alloc_pgtable_page(); | 724 | tmp_page = alloc_pgtable_page(); |
698 | 725 | ||
699 | if (!tmp_page) { | 726 | if (!tmp_page) |
700 | spin_unlock_irqrestore(&domain->mapping_lock, | ||
701 | flags); | ||
702 | return NULL; | 727 | return NULL; |
728 | |||
729 | domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE); | ||
730 | pteval = (virt_to_dma_pfn(tmp_page) << VTD_PAGE_SHIFT) | DMA_PTE_READ | DMA_PTE_WRITE; | ||
731 | if (cmpxchg64(&pte->val, 0ULL, pteval)) { | ||
732 | /* Someone else set it while we were thinking; use theirs. */ | ||
733 | free_pgtable_page(tmp_page); | ||
734 | } else { | ||
735 | dma_pte_addr(pte); | ||
736 | domain_flush_cache(domain, pte, sizeof(*pte)); | ||
703 | } | 737 | } |
704 | domain_flush_cache(domain, tmp_page, PAGE_SIZE); | ||
705 | dma_set_pte_addr(pte, virt_to_phys(tmp_page)); | ||
706 | /* | ||
707 | * high level table always sets r/w, last level page | ||
708 | * table control read/write | ||
709 | */ | ||
710 | dma_set_pte_readable(pte); | ||
711 | dma_set_pte_writable(pte); | ||
712 | domain_flush_cache(domain, pte, sizeof(*pte)); | ||
713 | } | 738 | } |
714 | parent = phys_to_virt(dma_pte_addr(pte)); | 739 | parent = phys_to_virt(dma_pte_addr(pte)); |
715 | level--; | 740 | level--; |
716 | } | 741 | } |
717 | 742 | ||
718 | spin_unlock_irqrestore(&domain->mapping_lock, flags); | ||
719 | return pte; | 743 | return pte; |
720 | } | 744 | } |
721 | 745 | ||
722 | /* return address's pte at specific level */ | 746 | /* return address's pte at specific level */ |
723 | static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr, | 747 | static struct dma_pte *dma_pfn_level_pte(struct dmar_domain *domain, |
724 | int level) | 748 | unsigned long pfn, |
749 | int level) | ||
725 | { | 750 | { |
726 | struct dma_pte *parent, *pte = NULL; | 751 | struct dma_pte *parent, *pte = NULL; |
727 | int total = agaw_to_level(domain->agaw); | 752 | int total = agaw_to_level(domain->agaw); |
@@ -729,7 +754,7 @@ static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr, | |||
729 | 754 | ||
730 | parent = domain->pgd; | 755 | parent = domain->pgd; |
731 | while (level <= total) { | 756 | while (level <= total) { |
732 | offset = address_level_offset(addr, total); | 757 | offset = pfn_level_offset(pfn, total); |
733 | pte = &parent[offset]; | 758 | pte = &parent[offset]; |
734 | if (level == total) | 759 | if (level == total) |
735 | return pte; | 760 | return pte; |
@@ -742,74 +767,82 @@ static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr, | |||
742 | return NULL; | 767 | return NULL; |
743 | } | 768 | } |
744 | 769 | ||
745 | /* clear one page's page table */ | ||
746 | static void dma_pte_clear_one(struct dmar_domain *domain, u64 addr) | ||
747 | { | ||
748 | struct dma_pte *pte = NULL; | ||
749 | |||
750 | /* get last level pte */ | ||
751 | pte = dma_addr_level_pte(domain, addr, 1); | ||
752 | |||
753 | if (pte) { | ||
754 | dma_clear_pte(pte); | ||
755 | domain_flush_cache(domain, pte, sizeof(*pte)); | ||
756 | } | ||
757 | } | ||
758 | |||
759 | /* clear last level pte, a tlb flush should be followed */ | 770 | /* clear last level pte, a tlb flush should be followed */ |
760 | static void dma_pte_clear_range(struct dmar_domain *domain, u64 start, u64 end) | 771 | static void dma_pte_clear_range(struct dmar_domain *domain, |
772 | unsigned long start_pfn, | ||
773 | unsigned long last_pfn) | ||
761 | { | 774 | { |
762 | int addr_width = agaw_to_width(domain->agaw); | 775 | int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; |
763 | int npages; | 776 | struct dma_pte *first_pte, *pte; |
764 | 777 | ||
765 | start &= (((u64)1) << addr_width) - 1; | 778 | BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width); |
766 | end &= (((u64)1) << addr_width) - 1; | 779 | BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width); |
767 | /* in case it's partial page */ | ||
768 | start &= PAGE_MASK; | ||
769 | end = PAGE_ALIGN(end); | ||
770 | npages = (end - start) / VTD_PAGE_SIZE; | ||
771 | 780 | ||
772 | /* we don't need lock here, nobody else touches the iova range */ | 781 | /* we don't need lock here; nobody else touches the iova range */ |
773 | while (npages--) { | 782 | while (start_pfn <= last_pfn) { |
774 | dma_pte_clear_one(domain, start); | 783 | first_pte = pte = dma_pfn_level_pte(domain, start_pfn, 1); |
775 | start += VTD_PAGE_SIZE; | 784 | if (!pte) { |
785 | start_pfn = align_to_level(start_pfn + 1, 2); | ||
786 | continue; | ||
787 | } | ||
788 | do { | ||
789 | dma_clear_pte(pte); | ||
790 | start_pfn++; | ||
791 | pte++; | ||
792 | } while (start_pfn <= last_pfn && !first_pte_in_page(pte)); | ||
793 | |||
794 | domain_flush_cache(domain, first_pte, | ||
795 | (void *)pte - (void *)first_pte); | ||
776 | } | 796 | } |
777 | } | 797 | } |
778 | 798 | ||
779 | /* free page table pages. last level pte should already be cleared */ | 799 | /* free page table pages. last level pte should already be cleared */ |
780 | static void dma_pte_free_pagetable(struct dmar_domain *domain, | 800 | static void dma_pte_free_pagetable(struct dmar_domain *domain, |
781 | u64 start, u64 end) | 801 | unsigned long start_pfn, |
802 | unsigned long last_pfn) | ||
782 | { | 803 | { |
783 | int addr_width = agaw_to_width(domain->agaw); | 804 | int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; |
784 | struct dma_pte *pte; | 805 | struct dma_pte *first_pte, *pte; |
785 | int total = agaw_to_level(domain->agaw); | 806 | int total = agaw_to_level(domain->agaw); |
786 | int level; | 807 | int level; |
787 | u64 tmp; | 808 | unsigned long tmp; |
788 | 809 | ||
789 | start &= (((u64)1) << addr_width) - 1; | 810 | BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width); |
790 | end &= (((u64)1) << addr_width) - 1; | 811 | BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width); |
791 | 812 | ||
792 | /* we don't need lock here, nobody else touches the iova range */ | 813 | /* We don't need lock here; nobody else touches the iova range */ |
793 | level = 2; | 814 | level = 2; |
794 | while (level <= total) { | 815 | while (level <= total) { |
795 | tmp = align_to_level(start, level); | 816 | tmp = align_to_level(start_pfn, level); |
796 | if (tmp >= end || (tmp + level_size(level) > end)) | 817 | |
818 | /* If we can't even clear one PTE at this level, we're done */ | ||
819 | if (tmp + level_size(level) - 1 > last_pfn) | ||
797 | return; | 820 | return; |
798 | 821 | ||
799 | while (tmp < end) { | 822 | while (tmp + level_size(level) - 1 <= last_pfn) { |
800 | pte = dma_addr_level_pte(domain, tmp, level); | 823 | first_pte = pte = dma_pfn_level_pte(domain, tmp, level); |
801 | if (pte) { | 824 | if (!pte) { |
802 | free_pgtable_page( | 825 | tmp = align_to_level(tmp + 1, level + 1); |
803 | phys_to_virt(dma_pte_addr(pte))); | 826 | continue; |
804 | dma_clear_pte(pte); | ||
805 | domain_flush_cache(domain, pte, sizeof(*pte)); | ||
806 | } | 827 | } |
807 | tmp += level_size(level); | 828 | do { |
829 | if (dma_pte_present(pte)) { | ||
830 | free_pgtable_page(phys_to_virt(dma_pte_addr(pte))); | ||
831 | dma_clear_pte(pte); | ||
832 | } | ||
833 | pte++; | ||
834 | tmp += level_size(level); | ||
835 | } while (!first_pte_in_page(pte) && | ||
836 | tmp + level_size(level) - 1 <= last_pfn); | ||
837 | |||
838 | domain_flush_cache(domain, first_pte, | ||
839 | (void *)pte - (void *)first_pte); | ||
840 | |||
808 | } | 841 | } |
809 | level++; | 842 | level++; |
810 | } | 843 | } |
811 | /* free pgd */ | 844 | /* free pgd */ |
812 | if (start == 0 && end >= ((((u64)1) << addr_width) - 1)) { | 845 | if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) { |
813 | free_pgtable_page(domain->pgd); | 846 | free_pgtable_page(domain->pgd); |
814 | domain->pgd = NULL; | 847 | domain->pgd = NULL; |
815 | } | 848 | } |
@@ -1035,11 +1068,11 @@ static void iommu_flush_dev_iotlb(struct dmar_domain *domain, | |||
1035 | } | 1068 | } |
1036 | 1069 | ||
1037 | static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did, | 1070 | static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did, |
1038 | u64 addr, unsigned int pages) | 1071 | unsigned long pfn, unsigned int pages) |
1039 | { | 1072 | { |
1040 | unsigned int mask = ilog2(__roundup_pow_of_two(pages)); | 1073 | unsigned int mask = ilog2(__roundup_pow_of_two(pages)); |
1074 | uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT; | ||
1041 | 1075 | ||
1042 | BUG_ON(addr & (~VTD_PAGE_MASK)); | ||
1043 | BUG_ON(pages == 0); | 1076 | BUG_ON(pages == 0); |
1044 | 1077 | ||
1045 | /* | 1078 | /* |
@@ -1054,7 +1087,12 @@ static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did, | |||
1054 | else | 1087 | else |
1055 | iommu->flush.flush_iotlb(iommu, did, addr, mask, | 1088 | iommu->flush.flush_iotlb(iommu, did, addr, mask, |
1056 | DMA_TLB_PSI_FLUSH); | 1089 | DMA_TLB_PSI_FLUSH); |
1057 | if (did) | 1090 | |
1091 | /* | ||
1092 | * In caching mode, domain ID 0 is reserved for non-present to present | ||
1093 | * mapping flush. Device IOTLB doesn't need to be flushed in this case. | ||
1094 | */ | ||
1095 | if (!cap_caching_mode(iommu->cap) || did) | ||
1058 | iommu_flush_dev_iotlb(iommu->domains[did], addr, mask); | 1096 | iommu_flush_dev_iotlb(iommu->domains[did], addr, mask); |
1059 | } | 1097 | } |
1060 | 1098 | ||
@@ -1279,7 +1317,6 @@ static void dmar_init_reserved_ranges(void) | |||
1279 | struct pci_dev *pdev = NULL; | 1317 | struct pci_dev *pdev = NULL; |
1280 | struct iova *iova; | 1318 | struct iova *iova; |
1281 | int i; | 1319 | int i; |
1282 | u64 addr, size; | ||
1283 | 1320 | ||
1284 | init_iova_domain(&reserved_iova_list, DMA_32BIT_PFN); | 1321 | init_iova_domain(&reserved_iova_list, DMA_32BIT_PFN); |
1285 | 1322 | ||
@@ -1302,12 +1339,9 @@ static void dmar_init_reserved_ranges(void) | |||
1302 | r = &pdev->resource[i]; | 1339 | r = &pdev->resource[i]; |
1303 | if (!r->flags || !(r->flags & IORESOURCE_MEM)) | 1340 | if (!r->flags || !(r->flags & IORESOURCE_MEM)) |
1304 | continue; | 1341 | continue; |
1305 | addr = r->start; | 1342 | iova = reserve_iova(&reserved_iova_list, |
1306 | addr &= PHYSICAL_PAGE_MASK; | 1343 | IOVA_PFN(r->start), |
1307 | size = r->end - addr; | 1344 | IOVA_PFN(r->end)); |
1308 | size = PAGE_ALIGN(size); | ||
1309 | iova = reserve_iova(&reserved_iova_list, IOVA_PFN(addr), | ||
1310 | IOVA_PFN(size + addr) - 1); | ||
1311 | if (!iova) | 1345 | if (!iova) |
1312 | printk(KERN_ERR "Reserve iova failed\n"); | 1346 | printk(KERN_ERR "Reserve iova failed\n"); |
1313 | } | 1347 | } |
@@ -1341,7 +1375,6 @@ static int domain_init(struct dmar_domain *domain, int guest_width) | |||
1341 | unsigned long sagaw; | 1375 | unsigned long sagaw; |
1342 | 1376 | ||
1343 | init_iova_domain(&domain->iovad, DMA_32BIT_PFN); | 1377 | init_iova_domain(&domain->iovad, DMA_32BIT_PFN); |
1344 | spin_lock_init(&domain->mapping_lock); | ||
1345 | spin_lock_init(&domain->iommu_lock); | 1378 | spin_lock_init(&domain->iommu_lock); |
1346 | 1379 | ||
1347 | domain_reserve_special_ranges(domain); | 1380 | domain_reserve_special_ranges(domain); |
@@ -1388,7 +1421,6 @@ static void domain_exit(struct dmar_domain *domain) | |||
1388 | { | 1421 | { |
1389 | struct dmar_drhd_unit *drhd; | 1422 | struct dmar_drhd_unit *drhd; |
1390 | struct intel_iommu *iommu; | 1423 | struct intel_iommu *iommu; |
1391 | u64 end; | ||
1392 | 1424 | ||
1393 | /* Domain 0 is reserved, so dont process it */ | 1425 | /* Domain 0 is reserved, so dont process it */ |
1394 | if (!domain) | 1426 | if (!domain) |
@@ -1397,14 +1429,12 @@ static void domain_exit(struct dmar_domain *domain) | |||
1397 | domain_remove_dev_info(domain); | 1429 | domain_remove_dev_info(domain); |
1398 | /* destroy iovas */ | 1430 | /* destroy iovas */ |
1399 | put_iova_domain(&domain->iovad); | 1431 | put_iova_domain(&domain->iovad); |
1400 | end = DOMAIN_MAX_ADDR(domain->gaw); | ||
1401 | end = end & (~PAGE_MASK); | ||
1402 | 1432 | ||
1403 | /* clear ptes */ | 1433 | /* clear ptes */ |
1404 | dma_pte_clear_range(domain, 0, end); | 1434 | dma_pte_clear_range(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); |
1405 | 1435 | ||
1406 | /* free page tables */ | 1436 | /* free page tables */ |
1407 | dma_pte_free_pagetable(domain, 0, end); | 1437 | dma_pte_free_pagetable(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); |
1408 | 1438 | ||
1409 | for_each_active_iommu(iommu, drhd) | 1439 | for_each_active_iommu(iommu, drhd) |
1410 | if (test_bit(iommu->seq_id, &domain->iommu_bmp)) | 1440 | if (test_bit(iommu->seq_id, &domain->iommu_bmp)) |
@@ -1618,42 +1648,86 @@ static int domain_context_mapped(struct pci_dev *pdev) | |||
1618 | tmp->devfn); | 1648 | tmp->devfn); |
1619 | } | 1649 | } |
1620 | 1650 | ||
1621 | static int | 1651 | static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn, |
1622 | domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova, | 1652 | struct scatterlist *sg, unsigned long phys_pfn, |
1623 | u64 hpa, size_t size, int prot) | 1653 | unsigned long nr_pages, int prot) |
1624 | { | 1654 | { |
1625 | u64 start_pfn, end_pfn; | 1655 | struct dma_pte *first_pte = NULL, *pte = NULL; |
1626 | struct dma_pte *pte; | 1656 | phys_addr_t uninitialized_var(pteval); |
1627 | int index; | 1657 | int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; |
1628 | int addr_width = agaw_to_width(domain->agaw); | 1658 | unsigned long sg_res; |
1629 | 1659 | ||
1630 | hpa &= (((u64)1) << addr_width) - 1; | 1660 | BUG_ON(addr_width < BITS_PER_LONG && (iov_pfn + nr_pages - 1) >> addr_width); |
1631 | 1661 | ||
1632 | if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0) | 1662 | if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0) |
1633 | return -EINVAL; | 1663 | return -EINVAL; |
1634 | iova &= PAGE_MASK; | 1664 | |
1635 | start_pfn = ((u64)hpa) >> VTD_PAGE_SHIFT; | 1665 | prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP; |
1636 | end_pfn = (VTD_PAGE_ALIGN(((u64)hpa) + size)) >> VTD_PAGE_SHIFT; | 1666 | |
1637 | index = 0; | 1667 | if (sg) |
1638 | while (start_pfn < end_pfn) { | 1668 | sg_res = 0; |
1639 | pte = addr_to_dma_pte(domain, iova + VTD_PAGE_SIZE * index); | 1669 | else { |
1640 | if (!pte) | 1670 | sg_res = nr_pages + 1; |
1641 | return -ENOMEM; | 1671 | pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | prot; |
1672 | } | ||
1673 | |||
1674 | while (nr_pages--) { | ||
1675 | uint64_t tmp; | ||
1676 | |||
1677 | if (!sg_res) { | ||
1678 | sg_res = (sg->offset + sg->length + VTD_PAGE_SIZE - 1) >> VTD_PAGE_SHIFT; | ||
1679 | sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + sg->offset; | ||
1680 | sg->dma_length = sg->length; | ||
1681 | pteval = page_to_phys(sg_page(sg)) | prot; | ||
1682 | } | ||
1683 | if (!pte) { | ||
1684 | first_pte = pte = pfn_to_dma_pte(domain, iov_pfn); | ||
1685 | if (!pte) | ||
1686 | return -ENOMEM; | ||
1687 | } | ||
1642 | /* We don't need lock here, nobody else | 1688 | /* We don't need lock here, nobody else |
1643 | * touches the iova range | 1689 | * touches the iova range |
1644 | */ | 1690 | */ |
1645 | BUG_ON(dma_pte_addr(pte)); | 1691 | tmp = cmpxchg64_local(&pte->val, 0ULL, pteval); |
1646 | dma_set_pte_addr(pte, start_pfn << VTD_PAGE_SHIFT); | 1692 | if (tmp) { |
1647 | dma_set_pte_prot(pte, prot); | 1693 | static int dumps = 5; |
1648 | if (prot & DMA_PTE_SNP) | 1694 | printk(KERN_CRIT "ERROR: DMA PTE for vPFN 0x%lx already set (to %llx not %llx)\n", |
1649 | dma_set_pte_snp(pte); | 1695 | iov_pfn, tmp, (unsigned long long)pteval); |
1650 | domain_flush_cache(domain, pte, sizeof(*pte)); | 1696 | if (dumps) { |
1651 | start_pfn++; | 1697 | dumps--; |
1652 | index++; | 1698 | debug_dma_dump_mappings(NULL); |
1699 | } | ||
1700 | WARN_ON(1); | ||
1701 | } | ||
1702 | pte++; | ||
1703 | if (!nr_pages || first_pte_in_page(pte)) { | ||
1704 | domain_flush_cache(domain, first_pte, | ||
1705 | (void *)pte - (void *)first_pte); | ||
1706 | pte = NULL; | ||
1707 | } | ||
1708 | iov_pfn++; | ||
1709 | pteval += VTD_PAGE_SIZE; | ||
1710 | sg_res--; | ||
1711 | if (!sg_res) | ||
1712 | sg = sg_next(sg); | ||
1653 | } | 1713 | } |
1654 | return 0; | 1714 | return 0; |
1655 | } | 1715 | } |
1656 | 1716 | ||
1717 | static inline int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn, | ||
1718 | struct scatterlist *sg, unsigned long nr_pages, | ||
1719 | int prot) | ||
1720 | { | ||
1721 | return __domain_mapping(domain, iov_pfn, sg, 0, nr_pages, prot); | ||
1722 | } | ||
1723 | |||
1724 | static inline int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn, | ||
1725 | unsigned long phys_pfn, unsigned long nr_pages, | ||
1726 | int prot) | ||
1727 | { | ||
1728 | return __domain_mapping(domain, iov_pfn, NULL, phys_pfn, nr_pages, prot); | ||
1729 | } | ||
1730 | |||
1657 | static void iommu_detach_dev(struct intel_iommu *iommu, u8 bus, u8 devfn) | 1731 | static void iommu_detach_dev(struct intel_iommu *iommu, u8 bus, u8 devfn) |
1658 | { | 1732 | { |
1659 | if (!iommu) | 1733 | if (!iommu) |
@@ -1844,58 +1918,61 @@ error: | |||
1844 | 1918 | ||
1845 | static int iommu_identity_mapping; | 1919 | static int iommu_identity_mapping; |
1846 | 1920 | ||
1921 | static int iommu_domain_identity_map(struct dmar_domain *domain, | ||
1922 | unsigned long long start, | ||
1923 | unsigned long long end) | ||
1924 | { | ||
1925 | unsigned long first_vpfn = start >> VTD_PAGE_SHIFT; | ||
1926 | unsigned long last_vpfn = end >> VTD_PAGE_SHIFT; | ||
1927 | |||
1928 | if (!reserve_iova(&domain->iovad, dma_to_mm_pfn(first_vpfn), | ||
1929 | dma_to_mm_pfn(last_vpfn))) { | ||
1930 | printk(KERN_ERR "IOMMU: reserve iova failed\n"); | ||
1931 | return -ENOMEM; | ||
1932 | } | ||
1933 | |||
1934 | pr_debug("Mapping reserved region %llx-%llx for domain %d\n", | ||
1935 | start, end, domain->id); | ||
1936 | /* | ||
1937 | * RMRR range might have overlap with physical memory range, | ||
1938 | * clear it first | ||
1939 | */ | ||
1940 | dma_pte_clear_range(domain, first_vpfn, last_vpfn); | ||
1941 | |||
1942 | return domain_pfn_mapping(domain, first_vpfn, first_vpfn, | ||
1943 | last_vpfn - first_vpfn + 1, | ||
1944 | DMA_PTE_READ|DMA_PTE_WRITE); | ||
1945 | } | ||
1946 | |||
1847 | static int iommu_prepare_identity_map(struct pci_dev *pdev, | 1947 | static int iommu_prepare_identity_map(struct pci_dev *pdev, |
1848 | unsigned long long start, | 1948 | unsigned long long start, |
1849 | unsigned long long end) | 1949 | unsigned long long end) |
1850 | { | 1950 | { |
1851 | struct dmar_domain *domain; | 1951 | struct dmar_domain *domain; |
1852 | unsigned long size; | ||
1853 | unsigned long long base; | ||
1854 | int ret; | 1952 | int ret; |
1855 | 1953 | ||
1856 | printk(KERN_INFO | 1954 | printk(KERN_INFO |
1857 | "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n", | 1955 | "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n", |
1858 | pci_name(pdev), start, end); | 1956 | pci_name(pdev), start, end); |
1859 | if (iommu_identity_mapping) | 1957 | |
1860 | domain = si_domain; | 1958 | domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH); |
1861 | else | ||
1862 | /* page table init */ | ||
1863 | domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH); | ||
1864 | if (!domain) | 1959 | if (!domain) |
1865 | return -ENOMEM; | 1960 | return -ENOMEM; |
1866 | 1961 | ||
1867 | /* The address might not be aligned */ | 1962 | ret = iommu_domain_identity_map(domain, start, end); |
1868 | base = start & PAGE_MASK; | ||
1869 | size = end - base; | ||
1870 | size = PAGE_ALIGN(size); | ||
1871 | if (!reserve_iova(&domain->iovad, IOVA_PFN(base), | ||
1872 | IOVA_PFN(base + size) - 1)) { | ||
1873 | printk(KERN_ERR "IOMMU: reserve iova failed\n"); | ||
1874 | ret = -ENOMEM; | ||
1875 | goto error; | ||
1876 | } | ||
1877 | |||
1878 | pr_debug("Mapping reserved region %lx@%llx for %s\n", | ||
1879 | size, base, pci_name(pdev)); | ||
1880 | /* | ||
1881 | * RMRR range might have overlap with physical memory range, | ||
1882 | * clear it first | ||
1883 | */ | ||
1884 | dma_pte_clear_range(domain, base, base + size); | ||
1885 | |||
1886 | ret = domain_page_mapping(domain, base, base, size, | ||
1887 | DMA_PTE_READ|DMA_PTE_WRITE); | ||
1888 | if (ret) | 1963 | if (ret) |
1889 | goto error; | 1964 | goto error; |
1890 | 1965 | ||
1891 | /* context entry init */ | 1966 | /* context entry init */ |
1892 | ret = domain_context_mapping(domain, pdev, CONTEXT_TT_MULTI_LEVEL); | 1967 | ret = domain_context_mapping(domain, pdev, CONTEXT_TT_MULTI_LEVEL); |
1893 | if (!ret) | 1968 | if (ret) |
1894 | return 0; | 1969 | goto error; |
1895 | error: | 1970 | |
1971 | return 0; | ||
1972 | |||
1973 | error: | ||
1896 | domain_exit(domain); | 1974 | domain_exit(domain); |
1897 | return ret; | 1975 | return ret; |
1898 | |||
1899 | } | 1976 | } |
1900 | 1977 | ||
1901 | static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr, | 1978 | static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr, |
@@ -1907,64 +1984,6 @@ static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr, | |||
1907 | rmrr->end_address + 1); | 1984 | rmrr->end_address + 1); |
1908 | } | 1985 | } |
1909 | 1986 | ||
1910 | struct iommu_prepare_data { | ||
1911 | struct pci_dev *pdev; | ||
1912 | int ret; | ||
1913 | }; | ||
1914 | |||
1915 | static int __init iommu_prepare_work_fn(unsigned long start_pfn, | ||
1916 | unsigned long end_pfn, void *datax) | ||
1917 | { | ||
1918 | struct iommu_prepare_data *data; | ||
1919 | |||
1920 | data = (struct iommu_prepare_data *)datax; | ||
1921 | |||
1922 | data->ret = iommu_prepare_identity_map(data->pdev, | ||
1923 | start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT); | ||
1924 | return data->ret; | ||
1925 | |||
1926 | } | ||
1927 | |||
1928 | static int __init iommu_prepare_with_active_regions(struct pci_dev *pdev) | ||
1929 | { | ||
1930 | int nid; | ||
1931 | struct iommu_prepare_data data; | ||
1932 | |||
1933 | data.pdev = pdev; | ||
1934 | data.ret = 0; | ||
1935 | |||
1936 | for_each_online_node(nid) { | ||
1937 | work_with_active_regions(nid, iommu_prepare_work_fn, &data); | ||
1938 | if (data.ret) | ||
1939 | return data.ret; | ||
1940 | } | ||
1941 | return data.ret; | ||
1942 | } | ||
1943 | |||
1944 | #ifdef CONFIG_DMAR_GFX_WA | ||
1945 | static void __init iommu_prepare_gfx_mapping(void) | ||
1946 | { | ||
1947 | struct pci_dev *pdev = NULL; | ||
1948 | int ret; | ||
1949 | |||
1950 | for_each_pci_dev(pdev) { | ||
1951 | if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO || | ||
1952 | !IS_GFX_DEVICE(pdev)) | ||
1953 | continue; | ||
1954 | printk(KERN_INFO "IOMMU: gfx device %s 1-1 mapping\n", | ||
1955 | pci_name(pdev)); | ||
1956 | ret = iommu_prepare_with_active_regions(pdev); | ||
1957 | if (ret) | ||
1958 | printk(KERN_ERR "IOMMU: mapping reserved region failed\n"); | ||
1959 | } | ||
1960 | } | ||
1961 | #else /* !CONFIG_DMAR_GFX_WA */ | ||
1962 | static inline void iommu_prepare_gfx_mapping(void) | ||
1963 | { | ||
1964 | return; | ||
1965 | } | ||
1966 | #endif | ||
1967 | |||
1968 | #ifdef CONFIG_DMAR_FLOPPY_WA | 1987 | #ifdef CONFIG_DMAR_FLOPPY_WA |
1969 | static inline void iommu_prepare_isa(void) | 1988 | static inline void iommu_prepare_isa(void) |
1970 | { | 1989 | { |
@@ -1975,12 +1994,12 @@ static inline void iommu_prepare_isa(void) | |||
1975 | if (!pdev) | 1994 | if (!pdev) |
1976 | return; | 1995 | return; |
1977 | 1996 | ||
1978 | printk(KERN_INFO "IOMMU: Prepare 0-16M unity mapping for LPC\n"); | 1997 | printk(KERN_INFO "IOMMU: Prepare 0-16MiB unity mapping for LPC\n"); |
1979 | ret = iommu_prepare_identity_map(pdev, 0, 16*1024*1024); | 1998 | ret = iommu_prepare_identity_map(pdev, 0, 16*1024*1024); |
1980 | 1999 | ||
1981 | if (ret) | 2000 | if (ret) |
1982 | printk(KERN_ERR "IOMMU: Failed to create 0-64M identity map, " | 2001 | printk(KERN_ERR "IOMMU: Failed to create 0-16MiB identity map; " |
1983 | "floppy might not work\n"); | 2002 | "floppy might not work\n"); |
1984 | 2003 | ||
1985 | } | 2004 | } |
1986 | #else | 2005 | #else |
@@ -2008,16 +2027,30 @@ static int __init init_context_pass_through(void) | |||
2008 | } | 2027 | } |
2009 | 2028 | ||
2010 | static int md_domain_init(struct dmar_domain *domain, int guest_width); | 2029 | static int md_domain_init(struct dmar_domain *domain, int guest_width); |
2030 | |||
2031 | static int __init si_domain_work_fn(unsigned long start_pfn, | ||
2032 | unsigned long end_pfn, void *datax) | ||
2033 | { | ||
2034 | int *ret = datax; | ||
2035 | |||
2036 | *ret = iommu_domain_identity_map(si_domain, | ||
2037 | (uint64_t)start_pfn << PAGE_SHIFT, | ||
2038 | (uint64_t)end_pfn << PAGE_SHIFT); | ||
2039 | return *ret; | ||
2040 | |||
2041 | } | ||
2042 | |||
2011 | static int si_domain_init(void) | 2043 | static int si_domain_init(void) |
2012 | { | 2044 | { |
2013 | struct dmar_drhd_unit *drhd; | 2045 | struct dmar_drhd_unit *drhd; |
2014 | struct intel_iommu *iommu; | 2046 | struct intel_iommu *iommu; |
2015 | int ret = 0; | 2047 | int nid, ret = 0; |
2016 | 2048 | ||
2017 | si_domain = alloc_domain(); | 2049 | si_domain = alloc_domain(); |
2018 | if (!si_domain) | 2050 | if (!si_domain) |
2019 | return -EFAULT; | 2051 | return -EFAULT; |
2020 | 2052 | ||
2053 | pr_debug("Identity mapping domain is domain %d\n", si_domain->id); | ||
2021 | 2054 | ||
2022 | for_each_active_iommu(iommu, drhd) { | 2055 | for_each_active_iommu(iommu, drhd) { |
2023 | ret = iommu_attach_domain(si_domain, iommu); | 2056 | ret = iommu_attach_domain(si_domain, iommu); |
@@ -2034,6 +2067,12 @@ static int si_domain_init(void) | |||
2034 | 2067 | ||
2035 | si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY; | 2068 | si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY; |
2036 | 2069 | ||
2070 | for_each_online_node(nid) { | ||
2071 | work_with_active_regions(nid, si_domain_work_fn, &ret); | ||
2072 | if (ret) | ||
2073 | return ret; | ||
2074 | } | ||
2075 | |||
2037 | return 0; | 2076 | return 0; |
2038 | } | 2077 | } |
2039 | 2078 | ||
@@ -2078,6 +2117,47 @@ static int domain_add_dev_info(struct dmar_domain *domain, | |||
2078 | return 0; | 2117 | return 0; |
2079 | } | 2118 | } |
2080 | 2119 | ||
2120 | static int iommu_should_identity_map(struct pci_dev *pdev, int startup) | ||
2121 | { | ||
2122 | if (iommu_identity_mapping == 2) | ||
2123 | return IS_GFX_DEVICE(pdev); | ||
2124 | |||
2125 | /* | ||
2126 | * We want to start off with all devices in the 1:1 domain, and | ||
2127 | * take them out later if we find they can't access all of memory. | ||
2128 | * | ||
2129 | * However, we can't do this for PCI devices behind bridges, | ||
2130 | * because all PCI devices behind the same bridge will end up | ||
2131 | * with the same source-id on their transactions. | ||
2132 | * | ||
2133 | * Practically speaking, we can't change things around for these | ||
2134 | * devices at run-time, because we can't be sure there'll be no | ||
2135 | * DMA transactions in flight for any of their siblings. | ||
2136 | * | ||
2137 | * So PCI devices (unless they're on the root bus) as well as | ||
2138 | * their parent PCI-PCI or PCIe-PCI bridges must be left _out_ of | ||
2139 | * the 1:1 domain, just in _case_ one of their siblings turns out | ||
2140 | * not to be able to map all of memory. | ||
2141 | */ | ||
2142 | if (!pdev->is_pcie) { | ||
2143 | if (!pci_is_root_bus(pdev->bus)) | ||
2144 | return 0; | ||
2145 | if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI) | ||
2146 | return 0; | ||
2147 | } else if (pdev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) | ||
2148 | return 0; | ||
2149 | |||
2150 | /* | ||
2151 | * At boot time, we don't yet know if devices will be 64-bit capable. | ||
2152 | * Assume that they will -- if they turn out not to be, then we can | ||
2153 | * take them out of the 1:1 domain later. | ||
2154 | */ | ||
2155 | if (!startup) | ||
2156 | return pdev->dma_mask > DMA_BIT_MASK(32); | ||
2157 | |||
2158 | return 1; | ||
2159 | } | ||
2160 | |||
2081 | static int iommu_prepare_static_identity_mapping(void) | 2161 | static int iommu_prepare_static_identity_mapping(void) |
2082 | { | 2162 | { |
2083 | struct pci_dev *pdev = NULL; | 2163 | struct pci_dev *pdev = NULL; |
@@ -2087,16 +2167,19 @@ static int iommu_prepare_static_identity_mapping(void) | |||
2087 | if (ret) | 2167 | if (ret) |
2088 | return -EFAULT; | 2168 | return -EFAULT; |
2089 | 2169 | ||
2090 | printk(KERN_INFO "IOMMU: Setting identity map:\n"); | ||
2091 | for_each_pci_dev(pdev) { | 2170 | for_each_pci_dev(pdev) { |
2092 | ret = iommu_prepare_with_active_regions(pdev); | 2171 | if (iommu_should_identity_map(pdev, 1)) { |
2093 | if (ret) { | 2172 | printk(KERN_INFO "IOMMU: identity mapping for device %s\n", |
2094 | printk(KERN_INFO "1:1 mapping to one domain failed.\n"); | 2173 | pci_name(pdev)); |
2095 | return -EFAULT; | 2174 | |
2175 | ret = domain_context_mapping(si_domain, pdev, | ||
2176 | CONTEXT_TT_MULTI_LEVEL); | ||
2177 | if (ret) | ||
2178 | return ret; | ||
2179 | ret = domain_add_dev_info(si_domain, pdev); | ||
2180 | if (ret) | ||
2181 | return ret; | ||
2096 | } | 2182 | } |
2097 | ret = domain_add_dev_info(si_domain, pdev); | ||
2098 | if (ret) | ||
2099 | return ret; | ||
2100 | } | 2183 | } |
2101 | 2184 | ||
2102 | return 0; | 2185 | return 0; |
@@ -2251,6 +2334,10 @@ int __init init_dmars(void) | |||
2251 | * identity mapping if iommu_identity_mapping is set. | 2334 | * identity mapping if iommu_identity_mapping is set. |
2252 | */ | 2335 | */ |
2253 | if (!iommu_pass_through) { | 2336 | if (!iommu_pass_through) { |
2337 | #ifdef CONFIG_DMAR_BROKEN_GFX_WA | ||
2338 | if (!iommu_identity_mapping) | ||
2339 | iommu_identity_mapping = 2; | ||
2340 | #endif | ||
2254 | if (iommu_identity_mapping) | 2341 | if (iommu_identity_mapping) |
2255 | iommu_prepare_static_identity_mapping(); | 2342 | iommu_prepare_static_identity_mapping(); |
2256 | /* | 2343 | /* |
@@ -2284,8 +2371,6 @@ int __init init_dmars(void) | |||
2284 | } | 2371 | } |
2285 | } | 2372 | } |
2286 | 2373 | ||
2287 | iommu_prepare_gfx_mapping(); | ||
2288 | |||
2289 | iommu_prepare_isa(); | 2374 | iommu_prepare_isa(); |
2290 | } | 2375 | } |
2291 | 2376 | ||
@@ -2330,50 +2415,40 @@ error: | |||
2330 | return ret; | 2415 | return ret; |
2331 | } | 2416 | } |
2332 | 2417 | ||
2333 | static inline u64 aligned_size(u64 host_addr, size_t size) | 2418 | /* Returns a number of VTD pages, but aligned to MM page size */ |
2334 | { | 2419 | static inline unsigned long aligned_nrpages(unsigned long host_addr, |
2335 | u64 addr; | 2420 | size_t size) |
2336 | addr = (host_addr & (~PAGE_MASK)) + size; | ||
2337 | return PAGE_ALIGN(addr); | ||
2338 | } | ||
2339 | |||
2340 | struct iova * | ||
2341 | iommu_alloc_iova(struct dmar_domain *domain, size_t size, u64 end) | ||
2342 | { | 2421 | { |
2343 | struct iova *piova; | 2422 | host_addr &= ~PAGE_MASK; |
2344 | 2423 | return PAGE_ALIGN(host_addr + size) >> VTD_PAGE_SHIFT; | |
2345 | /* Make sure it's in range */ | ||
2346 | end = min_t(u64, DOMAIN_MAX_ADDR(domain->gaw), end); | ||
2347 | if (!size || (IOVA_START_ADDR + size > end)) | ||
2348 | return NULL; | ||
2349 | |||
2350 | piova = alloc_iova(&domain->iovad, | ||
2351 | size >> PAGE_SHIFT, IOVA_PFN(end), 1); | ||
2352 | return piova; | ||
2353 | } | 2424 | } |
2354 | 2425 | ||
2355 | static struct iova * | 2426 | /* This takes a number of _MM_ pages, not VTD pages */ |
2356 | __intel_alloc_iova(struct device *dev, struct dmar_domain *domain, | 2427 | static struct iova *intel_alloc_iova(struct device *dev, |
2357 | size_t size, u64 dma_mask) | 2428 | struct dmar_domain *domain, |
2429 | unsigned long nrpages, uint64_t dma_mask) | ||
2358 | { | 2430 | { |
2359 | struct pci_dev *pdev = to_pci_dev(dev); | 2431 | struct pci_dev *pdev = to_pci_dev(dev); |
2360 | struct iova *iova = NULL; | 2432 | struct iova *iova = NULL; |
2361 | 2433 | ||
2362 | if (dma_mask <= DMA_BIT_MASK(32) || dmar_forcedac) | 2434 | /* Restrict dma_mask to the width that the iommu can handle */ |
2363 | iova = iommu_alloc_iova(domain, size, dma_mask); | 2435 | dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw), dma_mask); |
2364 | else { | 2436 | |
2437 | if (!dmar_forcedac && dma_mask > DMA_BIT_MASK(32)) { | ||
2365 | /* | 2438 | /* |
2366 | * First try to allocate an io virtual address in | 2439 | * First try to allocate an io virtual address in |
2367 | * DMA_BIT_MASK(32) and if that fails then try allocating | 2440 | * DMA_BIT_MASK(32) and if that fails then try allocating |
2368 | * from higher range | 2441 | * from higher range |
2369 | */ | 2442 | */ |
2370 | iova = iommu_alloc_iova(domain, size, DMA_BIT_MASK(32)); | 2443 | iova = alloc_iova(&domain->iovad, nrpages, |
2371 | if (!iova) | 2444 | IOVA_PFN(DMA_BIT_MASK(32)), 1); |
2372 | iova = iommu_alloc_iova(domain, size, dma_mask); | 2445 | if (iova) |
2373 | } | 2446 | return iova; |
2374 | 2447 | } | |
2375 | if (!iova) { | 2448 | iova = alloc_iova(&domain->iovad, nrpages, IOVA_PFN(dma_mask), 1); |
2376 | printk(KERN_ERR"Allocating iova for %s failed", pci_name(pdev)); | 2449 | if (unlikely(!iova)) { |
2450 | printk(KERN_ERR "Allocating %ld-page iova for %s failed", | ||
2451 | nrpages, pci_name(pdev)); | ||
2377 | return NULL; | 2452 | return NULL; |
2378 | } | 2453 | } |
2379 | 2454 | ||
@@ -2415,16 +2490,24 @@ static int iommu_dummy(struct pci_dev *pdev) | |||
2415 | } | 2490 | } |
2416 | 2491 | ||
2417 | /* Check if the pdev needs to go through non-identity map and unmap process.*/ | 2492 | /* Check if the pdev needs to go through non-identity map and unmap process.*/ |
2418 | static int iommu_no_mapping(struct pci_dev *pdev) | 2493 | static int iommu_no_mapping(struct device *dev) |
2419 | { | 2494 | { |
2495 | struct pci_dev *pdev; | ||
2420 | int found; | 2496 | int found; |
2421 | 2497 | ||
2498 | if (unlikely(dev->bus != &pci_bus_type)) | ||
2499 | return 1; | ||
2500 | |||
2501 | pdev = to_pci_dev(dev); | ||
2502 | if (iommu_dummy(pdev)) | ||
2503 | return 1; | ||
2504 | |||
2422 | if (!iommu_identity_mapping) | 2505 | if (!iommu_identity_mapping) |
2423 | return iommu_dummy(pdev); | 2506 | return 0; |
2424 | 2507 | ||
2425 | found = identity_mapping(pdev); | 2508 | found = identity_mapping(pdev); |
2426 | if (found) { | 2509 | if (found) { |
2427 | if (pdev->dma_mask > DMA_BIT_MASK(32)) | 2510 | if (iommu_should_identity_map(pdev, 0)) |
2428 | return 1; | 2511 | return 1; |
2429 | else { | 2512 | else { |
2430 | /* | 2513 | /* |
@@ -2441,9 +2524,12 @@ static int iommu_no_mapping(struct pci_dev *pdev) | |||
2441 | * In case of a detached 64 bit DMA device from vm, the device | 2524 | * In case of a detached 64 bit DMA device from vm, the device |
2442 | * is put into si_domain for identity mapping. | 2525 | * is put into si_domain for identity mapping. |
2443 | */ | 2526 | */ |
2444 | if (pdev->dma_mask > DMA_BIT_MASK(32)) { | 2527 | if (iommu_should_identity_map(pdev, 0)) { |
2445 | int ret; | 2528 | int ret; |
2446 | ret = domain_add_dev_info(si_domain, pdev); | 2529 | ret = domain_add_dev_info(si_domain, pdev); |
2530 | if (ret) | ||
2531 | return 0; | ||
2532 | ret = domain_context_mapping(si_domain, pdev, CONTEXT_TT_MULTI_LEVEL); | ||
2447 | if (!ret) { | 2533 | if (!ret) { |
2448 | printk(KERN_INFO "64bit %s uses identity mapping\n", | 2534 | printk(KERN_INFO "64bit %s uses identity mapping\n", |
2449 | pci_name(pdev)); | 2535 | pci_name(pdev)); |
@@ -2452,7 +2538,7 @@ static int iommu_no_mapping(struct pci_dev *pdev) | |||
2452 | } | 2538 | } |
2453 | } | 2539 | } |
2454 | 2540 | ||
2455 | return iommu_dummy(pdev); | 2541 | return 0; |
2456 | } | 2542 | } |
2457 | 2543 | ||
2458 | static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, | 2544 | static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, |
@@ -2468,7 +2554,7 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, | |||
2468 | 2554 | ||
2469 | BUG_ON(dir == DMA_NONE); | 2555 | BUG_ON(dir == DMA_NONE); |
2470 | 2556 | ||
2471 | if (iommu_no_mapping(pdev)) | 2557 | if (iommu_no_mapping(hwdev)) |
2472 | return paddr; | 2558 | return paddr; |
2473 | 2559 | ||
2474 | domain = get_valid_domain_for_dev(pdev); | 2560 | domain = get_valid_domain_for_dev(pdev); |
@@ -2476,14 +2562,13 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, | |||
2476 | return 0; | 2562 | return 0; |
2477 | 2563 | ||
2478 | iommu = domain_get_iommu(domain); | 2564 | iommu = domain_get_iommu(domain); |
2479 | size = aligned_size((u64)paddr, size); | 2565 | size = aligned_nrpages(paddr, size); |
2480 | 2566 | ||
2481 | iova = __intel_alloc_iova(hwdev, domain, size, pdev->dma_mask); | 2567 | iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size), |
2568 | pdev->dma_mask); | ||
2482 | if (!iova) | 2569 | if (!iova) |
2483 | goto error; | 2570 | goto error; |
2484 | 2571 | ||
2485 | start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT; | ||
2486 | |||
2487 | /* | 2572 | /* |
2488 | * Check if DMAR supports zero-length reads on write only | 2573 | * Check if DMAR supports zero-length reads on write only |
2489 | * mappings.. | 2574 | * mappings.. |
@@ -2499,20 +2584,20 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, | |||
2499 | * might have two guest_addr mapping to the same host paddr, but this | 2584 | * might have two guest_addr mapping to the same host paddr, but this |
2500 | * is not a big problem | 2585 | * is not a big problem |
2501 | */ | 2586 | */ |
2502 | ret = domain_page_mapping(domain, start_paddr, | 2587 | ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova->pfn_lo), |
2503 | ((u64)paddr) & PHYSICAL_PAGE_MASK, | 2588 | paddr >> VTD_PAGE_SHIFT, size, prot); |
2504 | size, prot); | ||
2505 | if (ret) | 2589 | if (ret) |
2506 | goto error; | 2590 | goto error; |
2507 | 2591 | ||
2508 | /* it's a non-present to present mapping. Only flush if caching mode */ | 2592 | /* it's a non-present to present mapping. Only flush if caching mode */ |
2509 | if (cap_caching_mode(iommu->cap)) | 2593 | if (cap_caching_mode(iommu->cap)) |
2510 | iommu_flush_iotlb_psi(iommu, 0, start_paddr, | 2594 | iommu_flush_iotlb_psi(iommu, 0, mm_to_dma_pfn(iova->pfn_lo), size); |
2511 | size >> VTD_PAGE_SHIFT); | ||
2512 | else | 2595 | else |
2513 | iommu_flush_write_buffer(iommu); | 2596 | iommu_flush_write_buffer(iommu); |
2514 | 2597 | ||
2515 | return start_paddr + ((u64)paddr & (~PAGE_MASK)); | 2598 | start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT; |
2599 | start_paddr += paddr & ~PAGE_MASK; | ||
2600 | return start_paddr; | ||
2516 | 2601 | ||
2517 | error: | 2602 | error: |
2518 | if (iova) | 2603 | if (iova) |
@@ -2605,11 +2690,11 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr, | |||
2605 | { | 2690 | { |
2606 | struct pci_dev *pdev = to_pci_dev(dev); | 2691 | struct pci_dev *pdev = to_pci_dev(dev); |
2607 | struct dmar_domain *domain; | 2692 | struct dmar_domain *domain; |
2608 | unsigned long start_addr; | 2693 | unsigned long start_pfn, last_pfn; |
2609 | struct iova *iova; | 2694 | struct iova *iova; |
2610 | struct intel_iommu *iommu; | 2695 | struct intel_iommu *iommu; |
2611 | 2696 | ||
2612 | if (iommu_no_mapping(pdev)) | 2697 | if (iommu_no_mapping(dev)) |
2613 | return; | 2698 | return; |
2614 | 2699 | ||
2615 | domain = find_domain(pdev); | 2700 | domain = find_domain(pdev); |
@@ -2618,22 +2703,25 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr, | |||
2618 | iommu = domain_get_iommu(domain); | 2703 | iommu = domain_get_iommu(domain); |
2619 | 2704 | ||
2620 | iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr)); | 2705 | iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr)); |
2621 | if (!iova) | 2706 | if (WARN_ONCE(!iova, "Driver unmaps unmatched page at PFN %llx\n", |
2707 | (unsigned long long)dev_addr)) | ||
2622 | return; | 2708 | return; |
2623 | 2709 | ||
2624 | start_addr = iova->pfn_lo << PAGE_SHIFT; | 2710 | start_pfn = mm_to_dma_pfn(iova->pfn_lo); |
2625 | size = aligned_size((u64)dev_addr, size); | 2711 | last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1; |
2626 | 2712 | ||
2627 | pr_debug("Device %s unmapping: %zx@%llx\n", | 2713 | pr_debug("Device %s unmapping: pfn %lx-%lx\n", |
2628 | pci_name(pdev), size, (unsigned long long)start_addr); | 2714 | pci_name(pdev), start_pfn, last_pfn); |
2629 | 2715 | ||
2630 | /* clear the whole page */ | 2716 | /* clear the whole page */ |
2631 | dma_pte_clear_range(domain, start_addr, start_addr + size); | 2717 | dma_pte_clear_range(domain, start_pfn, last_pfn); |
2718 | |||
2632 | /* free page tables */ | 2719 | /* free page tables */ |
2633 | dma_pte_free_pagetable(domain, start_addr, start_addr + size); | 2720 | dma_pte_free_pagetable(domain, start_pfn, last_pfn); |
2721 | |||
2634 | if (intel_iommu_strict) { | 2722 | if (intel_iommu_strict) { |
2635 | iommu_flush_iotlb_psi(iommu, domain->id, start_addr, | 2723 | iommu_flush_iotlb_psi(iommu, domain->id, start_pfn, |
2636 | size >> VTD_PAGE_SHIFT); | 2724 | last_pfn - start_pfn + 1); |
2637 | /* free iova */ | 2725 | /* free iova */ |
2638 | __free_iova(&domain->iovad, iova); | 2726 | __free_iova(&domain->iovad, iova); |
2639 | } else { | 2727 | } else { |
@@ -2691,17 +2779,13 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist, | |||
2691 | int nelems, enum dma_data_direction dir, | 2779 | int nelems, enum dma_data_direction dir, |
2692 | struct dma_attrs *attrs) | 2780 | struct dma_attrs *attrs) |
2693 | { | 2781 | { |
2694 | int i; | ||
2695 | struct pci_dev *pdev = to_pci_dev(hwdev); | 2782 | struct pci_dev *pdev = to_pci_dev(hwdev); |
2696 | struct dmar_domain *domain; | 2783 | struct dmar_domain *domain; |
2697 | unsigned long start_addr; | 2784 | unsigned long start_pfn, last_pfn; |
2698 | struct iova *iova; | 2785 | struct iova *iova; |
2699 | size_t size = 0; | ||
2700 | phys_addr_t addr; | ||
2701 | struct scatterlist *sg; | ||
2702 | struct intel_iommu *iommu; | 2786 | struct intel_iommu *iommu; |
2703 | 2787 | ||
2704 | if (iommu_no_mapping(pdev)) | 2788 | if (iommu_no_mapping(hwdev)) |
2705 | return; | 2789 | return; |
2706 | 2790 | ||
2707 | domain = find_domain(pdev); | 2791 | domain = find_domain(pdev); |
@@ -2710,22 +2794,21 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist, | |||
2710 | iommu = domain_get_iommu(domain); | 2794 | iommu = domain_get_iommu(domain); |
2711 | 2795 | ||
2712 | iova = find_iova(&domain->iovad, IOVA_PFN(sglist[0].dma_address)); | 2796 | iova = find_iova(&domain->iovad, IOVA_PFN(sglist[0].dma_address)); |
2713 | if (!iova) | 2797 | if (WARN_ONCE(!iova, "Driver unmaps unmatched sglist at PFN %llx\n", |
2798 | (unsigned long long)sglist[0].dma_address)) | ||
2714 | return; | 2799 | return; |
2715 | for_each_sg(sglist, sg, nelems, i) { | ||
2716 | addr = page_to_phys(sg_page(sg)) + sg->offset; | ||
2717 | size += aligned_size((u64)addr, sg->length); | ||
2718 | } | ||
2719 | 2800 | ||
2720 | start_addr = iova->pfn_lo << PAGE_SHIFT; | 2801 | start_pfn = mm_to_dma_pfn(iova->pfn_lo); |
2802 | last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1; | ||
2721 | 2803 | ||
2722 | /* clear the whole page */ | 2804 | /* clear the whole page */ |
2723 | dma_pte_clear_range(domain, start_addr, start_addr + size); | 2805 | dma_pte_clear_range(domain, start_pfn, last_pfn); |
2806 | |||
2724 | /* free page tables */ | 2807 | /* free page tables */ |
2725 | dma_pte_free_pagetable(domain, start_addr, start_addr + size); | 2808 | dma_pte_free_pagetable(domain, start_pfn, last_pfn); |
2726 | 2809 | ||
2727 | iommu_flush_iotlb_psi(iommu, domain->id, start_addr, | 2810 | iommu_flush_iotlb_psi(iommu, domain->id, start_pfn, |
2728 | size >> VTD_PAGE_SHIFT); | 2811 | (last_pfn - start_pfn + 1)); |
2729 | 2812 | ||
2730 | /* free iova */ | 2813 | /* free iova */ |
2731 | __free_iova(&domain->iovad, iova); | 2814 | __free_iova(&domain->iovad, iova); |
@@ -2748,21 +2831,20 @@ static int intel_nontranslate_map_sg(struct device *hddev, | |||
2748 | static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems, | 2831 | static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems, |
2749 | enum dma_data_direction dir, struct dma_attrs *attrs) | 2832 | enum dma_data_direction dir, struct dma_attrs *attrs) |
2750 | { | 2833 | { |
2751 | phys_addr_t addr; | ||
2752 | int i; | 2834 | int i; |
2753 | struct pci_dev *pdev = to_pci_dev(hwdev); | 2835 | struct pci_dev *pdev = to_pci_dev(hwdev); |
2754 | struct dmar_domain *domain; | 2836 | struct dmar_domain *domain; |
2755 | size_t size = 0; | 2837 | size_t size = 0; |
2756 | int prot = 0; | 2838 | int prot = 0; |
2757 | size_t offset = 0; | 2839 | size_t offset_pfn = 0; |
2758 | struct iova *iova = NULL; | 2840 | struct iova *iova = NULL; |
2759 | int ret; | 2841 | int ret; |
2760 | struct scatterlist *sg; | 2842 | struct scatterlist *sg; |
2761 | unsigned long start_addr; | 2843 | unsigned long start_vpfn; |
2762 | struct intel_iommu *iommu; | 2844 | struct intel_iommu *iommu; |
2763 | 2845 | ||
2764 | BUG_ON(dir == DMA_NONE); | 2846 | BUG_ON(dir == DMA_NONE); |
2765 | if (iommu_no_mapping(pdev)) | 2847 | if (iommu_no_mapping(hwdev)) |
2766 | return intel_nontranslate_map_sg(hwdev, sglist, nelems, dir); | 2848 | return intel_nontranslate_map_sg(hwdev, sglist, nelems, dir); |
2767 | 2849 | ||
2768 | domain = get_valid_domain_for_dev(pdev); | 2850 | domain = get_valid_domain_for_dev(pdev); |
@@ -2771,12 +2853,11 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne | |||
2771 | 2853 | ||
2772 | iommu = domain_get_iommu(domain); | 2854 | iommu = domain_get_iommu(domain); |
2773 | 2855 | ||
2774 | for_each_sg(sglist, sg, nelems, i) { | 2856 | for_each_sg(sglist, sg, nelems, i) |
2775 | addr = page_to_phys(sg_page(sg)) + sg->offset; | 2857 | size += aligned_nrpages(sg->offset, sg->length); |
2776 | size += aligned_size((u64)addr, sg->length); | ||
2777 | } | ||
2778 | 2858 | ||
2779 | iova = __intel_alloc_iova(hwdev, domain, size, pdev->dma_mask); | 2859 | iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size), |
2860 | pdev->dma_mask); | ||
2780 | if (!iova) { | 2861 | if (!iova) { |
2781 | sglist->dma_length = 0; | 2862 | sglist->dma_length = 0; |
2782 | return 0; | 2863 | return 0; |
@@ -2792,35 +2873,24 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne | |||
2792 | if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) | 2873 | if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) |
2793 | prot |= DMA_PTE_WRITE; | 2874 | prot |= DMA_PTE_WRITE; |
2794 | 2875 | ||
2795 | start_addr = iova->pfn_lo << PAGE_SHIFT; | 2876 | start_vpfn = mm_to_dma_pfn(iova->pfn_lo); |
2796 | offset = 0; | 2877 | |
2797 | for_each_sg(sglist, sg, nelems, i) { | 2878 | ret = domain_sg_mapping(domain, start_vpfn, sglist, mm_to_dma_pfn(size), prot); |
2798 | addr = page_to_phys(sg_page(sg)) + sg->offset; | 2879 | if (unlikely(ret)) { |
2799 | size = aligned_size((u64)addr, sg->length); | 2880 | /* clear the page */ |
2800 | ret = domain_page_mapping(domain, start_addr + offset, | 2881 | dma_pte_clear_range(domain, start_vpfn, |
2801 | ((u64)addr) & PHYSICAL_PAGE_MASK, | 2882 | start_vpfn + size - 1); |
2802 | size, prot); | 2883 | /* free page tables */ |
2803 | if (ret) { | 2884 | dma_pte_free_pagetable(domain, start_vpfn, |
2804 | /* clear the page */ | 2885 | start_vpfn + size - 1); |
2805 | dma_pte_clear_range(domain, start_addr, | 2886 | /* free iova */ |
2806 | start_addr + offset); | 2887 | __free_iova(&domain->iovad, iova); |
2807 | /* free page tables */ | 2888 | return 0; |
2808 | dma_pte_free_pagetable(domain, start_addr, | ||
2809 | start_addr + offset); | ||
2810 | /* free iova */ | ||
2811 | __free_iova(&domain->iovad, iova); | ||
2812 | return 0; | ||
2813 | } | ||
2814 | sg->dma_address = start_addr + offset + | ||
2815 | ((u64)addr & (~PAGE_MASK)); | ||
2816 | sg->dma_length = sg->length; | ||
2817 | offset += size; | ||
2818 | } | 2889 | } |
2819 | 2890 | ||
2820 | /* it's a non-present to present mapping. Only flush if caching mode */ | 2891 | /* it's a non-present to present mapping. Only flush if caching mode */ |
2821 | if (cap_caching_mode(iommu->cap)) | 2892 | if (cap_caching_mode(iommu->cap)) |
2822 | iommu_flush_iotlb_psi(iommu, 0, start_addr, | 2893 | iommu_flush_iotlb_psi(iommu, 0, start_vpfn, offset_pfn); |
2823 | offset >> VTD_PAGE_SHIFT); | ||
2824 | else | 2894 | else |
2825 | iommu_flush_write_buffer(iommu); | 2895 | iommu_flush_write_buffer(iommu); |
2826 | 2896 | ||
@@ -3325,7 +3395,6 @@ static int md_domain_init(struct dmar_domain *domain, int guest_width) | |||
3325 | int adjust_width; | 3395 | int adjust_width; |
3326 | 3396 | ||
3327 | init_iova_domain(&domain->iovad, DMA_32BIT_PFN); | 3397 | init_iova_domain(&domain->iovad, DMA_32BIT_PFN); |
3328 | spin_lock_init(&domain->mapping_lock); | ||
3329 | spin_lock_init(&domain->iommu_lock); | 3398 | spin_lock_init(&domain->iommu_lock); |
3330 | 3399 | ||
3331 | domain_reserve_special_ranges(domain); | 3400 | domain_reserve_special_ranges(domain); |
@@ -3379,8 +3448,6 @@ static void iommu_free_vm_domain(struct dmar_domain *domain) | |||
3379 | 3448 | ||
3380 | static void vm_domain_exit(struct dmar_domain *domain) | 3449 | static void vm_domain_exit(struct dmar_domain *domain) |
3381 | { | 3450 | { |
3382 | u64 end; | ||
3383 | |||
3384 | /* Domain 0 is reserved, so dont process it */ | 3451 | /* Domain 0 is reserved, so dont process it */ |
3385 | if (!domain) | 3452 | if (!domain) |
3386 | return; | 3453 | return; |
@@ -3388,14 +3455,12 @@ static void vm_domain_exit(struct dmar_domain *domain) | |||
3388 | vm_domain_remove_all_dev_info(domain); | 3455 | vm_domain_remove_all_dev_info(domain); |
3389 | /* destroy iovas */ | 3456 | /* destroy iovas */ |
3390 | put_iova_domain(&domain->iovad); | 3457 | put_iova_domain(&domain->iovad); |
3391 | end = DOMAIN_MAX_ADDR(domain->gaw); | ||
3392 | end = end & (~VTD_PAGE_MASK); | ||
3393 | 3458 | ||
3394 | /* clear ptes */ | 3459 | /* clear ptes */ |
3395 | dma_pte_clear_range(domain, 0, end); | 3460 | dma_pte_clear_range(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); |
3396 | 3461 | ||
3397 | /* free page tables */ | 3462 | /* free page tables */ |
3398 | dma_pte_free_pagetable(domain, 0, end); | 3463 | dma_pte_free_pagetable(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); |
3399 | 3464 | ||
3400 | iommu_free_vm_domain(domain); | 3465 | iommu_free_vm_domain(domain); |
3401 | free_domain_mem(domain); | 3466 | free_domain_mem(domain); |
@@ -3504,7 +3569,7 @@ static int intel_iommu_map_range(struct iommu_domain *domain, | |||
3504 | if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping) | 3569 | if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping) |
3505 | prot |= DMA_PTE_SNP; | 3570 | prot |= DMA_PTE_SNP; |
3506 | 3571 | ||
3507 | max_addr = (iova & VTD_PAGE_MASK) + VTD_PAGE_ALIGN(size); | 3572 | max_addr = iova + size; |
3508 | if (dmar_domain->max_addr < max_addr) { | 3573 | if (dmar_domain->max_addr < max_addr) { |
3509 | int min_agaw; | 3574 | int min_agaw; |
3510 | u64 end; | 3575 | u64 end; |
@@ -3522,8 +3587,11 @@ static int intel_iommu_map_range(struct iommu_domain *domain, | |||
3522 | } | 3587 | } |
3523 | dmar_domain->max_addr = max_addr; | 3588 | dmar_domain->max_addr = max_addr; |
3524 | } | 3589 | } |
3525 | 3590 | /* Round up size to next multiple of PAGE_SIZE, if it and | |
3526 | ret = domain_page_mapping(dmar_domain, iova, hpa, size, prot); | 3591 | the low bits of hpa would take us onto the next page */ |
3592 | size = aligned_nrpages(hpa, size); | ||
3593 | ret = domain_pfn_mapping(dmar_domain, iova >> VTD_PAGE_SHIFT, | ||
3594 | hpa >> VTD_PAGE_SHIFT, size, prot); | ||
3527 | return ret; | 3595 | return ret; |
3528 | } | 3596 | } |
3529 | 3597 | ||
@@ -3531,15 +3599,12 @@ static void intel_iommu_unmap_range(struct iommu_domain *domain, | |||
3531 | unsigned long iova, size_t size) | 3599 | unsigned long iova, size_t size) |
3532 | { | 3600 | { |
3533 | struct dmar_domain *dmar_domain = domain->priv; | 3601 | struct dmar_domain *dmar_domain = domain->priv; |
3534 | dma_addr_t base; | ||
3535 | 3602 | ||
3536 | /* The address might not be aligned */ | 3603 | dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT, |
3537 | base = iova & VTD_PAGE_MASK; | 3604 | (iova + size - 1) >> VTD_PAGE_SHIFT); |
3538 | size = VTD_PAGE_ALIGN(size); | ||
3539 | dma_pte_clear_range(dmar_domain, base, base + size); | ||
3540 | 3605 | ||
3541 | if (dmar_domain->max_addr == base + size) | 3606 | if (dmar_domain->max_addr == iova + size) |
3542 | dmar_domain->max_addr = base; | 3607 | dmar_domain->max_addr = iova; |
3543 | } | 3608 | } |
3544 | 3609 | ||
3545 | static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, | 3610 | static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, |
@@ -3549,7 +3614,7 @@ static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, | |||
3549 | struct dma_pte *pte; | 3614 | struct dma_pte *pte; |
3550 | u64 phys = 0; | 3615 | u64 phys = 0; |
3551 | 3616 | ||
3552 | pte = addr_to_dma_pte(dmar_domain, iova); | 3617 | pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT); |
3553 | if (pte) | 3618 | if (pte) |
3554 | phys = dma_pte_addr(pte); | 3619 | phys = dma_pte_addr(pte); |
3555 | 3620 | ||
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index d9f06fbfa0bf..d986afb7032b 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -127,17 +127,23 @@ static inline __attribute_const__ u32 msi_enabled_mask(u16 control) | |||
127 | * reliably as devices without an INTx disable bit will then generate a | 127 | * reliably as devices without an INTx disable bit will then generate a |
128 | * level IRQ which will never be cleared. | 128 | * level IRQ which will never be cleared. |
129 | */ | 129 | */ |
130 | static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) | 130 | static u32 __msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) |
131 | { | 131 | { |
132 | u32 mask_bits = desc->masked; | 132 | u32 mask_bits = desc->masked; |
133 | 133 | ||
134 | if (!desc->msi_attrib.maskbit) | 134 | if (!desc->msi_attrib.maskbit) |
135 | return; | 135 | return 0; |
136 | 136 | ||
137 | mask_bits &= ~mask; | 137 | mask_bits &= ~mask; |
138 | mask_bits |= flag; | 138 | mask_bits |= flag; |
139 | pci_write_config_dword(desc->dev, desc->mask_pos, mask_bits); | 139 | pci_write_config_dword(desc->dev, desc->mask_pos, mask_bits); |
140 | desc->masked = mask_bits; | 140 | |
141 | return mask_bits; | ||
142 | } | ||
143 | |||
144 | static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) | ||
145 | { | ||
146 | desc->masked = __msi_mask_irq(desc, mask, flag); | ||
141 | } | 147 | } |
142 | 148 | ||
143 | /* | 149 | /* |
@@ -147,15 +153,21 @@ static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) | |||
147 | * file. This saves a few milliseconds when initialising devices with lots | 153 | * file. This saves a few milliseconds when initialising devices with lots |
148 | * of MSI-X interrupts. | 154 | * of MSI-X interrupts. |
149 | */ | 155 | */ |
150 | static void msix_mask_irq(struct msi_desc *desc, u32 flag) | 156 | static u32 __msix_mask_irq(struct msi_desc *desc, u32 flag) |
151 | { | 157 | { |
152 | u32 mask_bits = desc->masked; | 158 | u32 mask_bits = desc->masked; |
153 | unsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + | 159 | unsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + |
154 | PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET; | 160 | PCI_MSIX_ENTRY_VECTOR_CTRL; |
155 | mask_bits &= ~1; | 161 | mask_bits &= ~1; |
156 | mask_bits |= flag; | 162 | mask_bits |= flag; |
157 | writel(mask_bits, desc->mask_base + offset); | 163 | writel(mask_bits, desc->mask_base + offset); |
158 | desc->masked = mask_bits; | 164 | |
165 | return mask_bits; | ||
166 | } | ||
167 | |||
168 | static void msix_mask_irq(struct msi_desc *desc, u32 flag) | ||
169 | { | ||
170 | desc->masked = __msix_mask_irq(desc, flag); | ||
159 | } | 171 | } |
160 | 172 | ||
161 | static void msi_set_mask_bit(unsigned irq, u32 flag) | 173 | static void msi_set_mask_bit(unsigned irq, u32 flag) |
@@ -188,9 +200,9 @@ void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) | |||
188 | void __iomem *base = entry->mask_base + | 200 | void __iomem *base = entry->mask_base + |
189 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; | 201 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; |
190 | 202 | ||
191 | msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); | 203 | msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR); |
192 | msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); | 204 | msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR); |
193 | msg->data = readl(base + PCI_MSIX_ENTRY_DATA_OFFSET); | 205 | msg->data = readl(base + PCI_MSIX_ENTRY_DATA); |
194 | } else { | 206 | } else { |
195 | struct pci_dev *dev = entry->dev; | 207 | struct pci_dev *dev = entry->dev; |
196 | int pos = entry->msi_attrib.pos; | 208 | int pos = entry->msi_attrib.pos; |
@@ -225,11 +237,9 @@ void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) | |||
225 | base = entry->mask_base + | 237 | base = entry->mask_base + |
226 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; | 238 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; |
227 | 239 | ||
228 | writel(msg->address_lo, | 240 | writel(msg->address_lo, base + PCI_MSIX_ENTRY_LOWER_ADDR); |
229 | base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); | 241 | writel(msg->address_hi, base + PCI_MSIX_ENTRY_UPPER_ADDR); |
230 | writel(msg->address_hi, | 242 | writel(msg->data, base + PCI_MSIX_ENTRY_DATA); |
231 | base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); | ||
232 | writel(msg->data, base + PCI_MSIX_ENTRY_DATA_OFFSET); | ||
233 | } else { | 243 | } else { |
234 | struct pci_dev *dev = entry->dev; | 244 | struct pci_dev *dev = entry->dev; |
235 | int pos = entry->msi_attrib.pos; | 245 | int pos = entry->msi_attrib.pos; |
@@ -385,6 +395,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec) | |||
385 | /* Configure MSI capability structure */ | 395 | /* Configure MSI capability structure */ |
386 | ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSI); | 396 | ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSI); |
387 | if (ret) { | 397 | if (ret) { |
398 | msi_mask_irq(entry, mask, ~mask); | ||
388 | msi_free_irqs(dev); | 399 | msi_free_irqs(dev); |
389 | return ret; | 400 | return ret; |
390 | } | 401 | } |
@@ -439,8 +450,14 @@ static int msix_capability_init(struct pci_dev *dev, | |||
439 | 450 | ||
440 | for (i = 0; i < nvec; i++) { | 451 | for (i = 0; i < nvec; i++) { |
441 | entry = alloc_msi_entry(dev); | 452 | entry = alloc_msi_entry(dev); |
442 | if (!entry) | 453 | if (!entry) { |
443 | break; | 454 | if (!i) |
455 | iounmap(base); | ||
456 | else | ||
457 | msi_free_irqs(dev); | ||
458 | /* No enough memory. Don't try again */ | ||
459 | return -ENOMEM; | ||
460 | } | ||
444 | 461 | ||
445 | j = entries[i].entry; | 462 | j = entries[i].entry; |
446 | entry->msi_attrib.is_msix = 1; | 463 | entry->msi_attrib.is_msix = 1; |
@@ -487,7 +504,7 @@ static int msix_capability_init(struct pci_dev *dev, | |||
487 | set_irq_msi(entry->irq, entry); | 504 | set_irq_msi(entry->irq, entry); |
488 | j = entries[i].entry; | 505 | j = entries[i].entry; |
489 | entry->masked = readl(base + j * PCI_MSIX_ENTRY_SIZE + | 506 | entry->masked = readl(base + j * PCI_MSIX_ENTRY_SIZE + |
490 | PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET); | 507 | PCI_MSIX_ENTRY_VECTOR_CTRL); |
491 | msix_mask_irq(entry, 1); | 508 | msix_mask_irq(entry, 1); |
492 | i++; | 509 | i++; |
493 | } | 510 | } |
@@ -611,9 +628,11 @@ void pci_msi_shutdown(struct pci_dev *dev) | |||
611 | pci_intx_for_msi(dev, 1); | 628 | pci_intx_for_msi(dev, 1); |
612 | dev->msi_enabled = 0; | 629 | dev->msi_enabled = 0; |
613 | 630 | ||
631 | /* Return the device with MSI unmasked as initial states */ | ||
614 | pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &ctrl); | 632 | pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &ctrl); |
615 | mask = msi_capable_mask(ctrl); | 633 | mask = msi_capable_mask(ctrl); |
616 | msi_mask_irq(desc, mask, ~mask); | 634 | /* Keep cached state to be restored */ |
635 | __msi_mask_irq(desc, mask, ~mask); | ||
617 | 636 | ||
618 | /* Restore dev->irq to its default pin-assertion irq */ | 637 | /* Restore dev->irq to its default pin-assertion irq */ |
619 | dev->irq = desc->msi_attrib.default_irq; | 638 | dev->irq = desc->msi_attrib.default_irq; |
@@ -653,7 +672,6 @@ static int msi_free_irqs(struct pci_dev* dev) | |||
653 | 672 | ||
654 | list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) { | 673 | list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) { |
655 | if (entry->msi_attrib.is_msix) { | 674 | if (entry->msi_attrib.is_msix) { |
656 | msix_mask_irq(entry, 1); | ||
657 | if (list_is_last(&entry->list, &dev->msi_list)) | 675 | if (list_is_last(&entry->list, &dev->msi_list)) |
658 | iounmap(entry->mask_base); | 676 | iounmap(entry->mask_base); |
659 | } | 677 | } |
@@ -741,9 +759,17 @@ static void msix_free_all_irqs(struct pci_dev *dev) | |||
741 | 759 | ||
742 | void pci_msix_shutdown(struct pci_dev* dev) | 760 | void pci_msix_shutdown(struct pci_dev* dev) |
743 | { | 761 | { |
762 | struct msi_desc *entry; | ||
763 | |||
744 | if (!pci_msi_enable || !dev || !dev->msix_enabled) | 764 | if (!pci_msi_enable || !dev || !dev->msix_enabled) |
745 | return; | 765 | return; |
746 | 766 | ||
767 | /* Return the device with MSI-X masked as initial states */ | ||
768 | list_for_each_entry(entry, &dev->msi_list, list) { | ||
769 | /* Keep cached states to be restored */ | ||
770 | __msix_mask_irq(entry, 1); | ||
771 | } | ||
772 | |||
747 | msix_set_enable(dev, 0); | 773 | msix_set_enable(dev, 0); |
748 | pci_intx_for_msi(dev, 1); | 774 | pci_intx_for_msi(dev, 1); |
749 | dev->msix_enabled = 0; | 775 | dev->msix_enabled = 0; |
diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h index a0662842550b..de27c1cb5a2b 100644 --- a/drivers/pci/msi.h +++ b/drivers/pci/msi.h | |||
@@ -6,11 +6,11 @@ | |||
6 | #ifndef MSI_H | 6 | #ifndef MSI_H |
7 | #define MSI_H | 7 | #define MSI_H |
8 | 8 | ||
9 | #define PCI_MSIX_ENTRY_SIZE 16 | 9 | #define PCI_MSIX_ENTRY_SIZE 16 |
10 | #define PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET 0 | 10 | #define PCI_MSIX_ENTRY_LOWER_ADDR 0 |
11 | #define PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET 4 | 11 | #define PCI_MSIX_ENTRY_UPPER_ADDR 4 |
12 | #define PCI_MSIX_ENTRY_DATA_OFFSET 8 | 12 | #define PCI_MSIX_ENTRY_DATA 8 |
13 | #define PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET 12 | 13 | #define PCI_MSIX_ENTRY_VECTOR_CTRL 12 |
14 | 14 | ||
15 | #define msi_control_reg(base) (base + PCI_MSI_FLAGS) | 15 | #define msi_control_reg(base) (base + PCI_MSI_FLAGS) |
16 | #define msi_lower_address_reg(base) (base + PCI_MSI_ADDRESS_LO) | 16 | #define msi_lower_address_reg(base) (base + PCI_MSI_ADDRESS_LO) |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 6c93af5ced18..dbd0f947f497 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -1517,11 +1517,20 @@ void pci_enable_ari(struct pci_dev *dev) | |||
1517 | * | 1517 | * |
1518 | * Perform INTx swizzling for a device behind one level of bridge. This is | 1518 | * Perform INTx swizzling for a device behind one level of bridge. This is |
1519 | * required by section 9.1 of the PCI-to-PCI bridge specification for devices | 1519 | * required by section 9.1 of the PCI-to-PCI bridge specification for devices |
1520 | * behind bridges on add-in cards. | 1520 | * behind bridges on add-in cards. For devices with ARI enabled, the slot |
1521 | * number is always 0 (see the Implementation Note in section 2.2.8.1 of | ||
1522 | * the PCI Express Base Specification, Revision 2.1) | ||
1521 | */ | 1523 | */ |
1522 | u8 pci_swizzle_interrupt_pin(struct pci_dev *dev, u8 pin) | 1524 | u8 pci_swizzle_interrupt_pin(struct pci_dev *dev, u8 pin) |
1523 | { | 1525 | { |
1524 | return (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1; | 1526 | int slot; |
1527 | |||
1528 | if (pci_ari_enabled(dev->bus)) | ||
1529 | slot = 0; | ||
1530 | else | ||
1531 | slot = PCI_SLOT(dev->devfn); | ||
1532 | |||
1533 | return (((pin - 1) + slot) % 4) + 1; | ||
1525 | } | 1534 | } |
1526 | 1535 | ||
1527 | int | 1536 | int |
@@ -2171,7 +2180,7 @@ static int pci_parent_bus_reset(struct pci_dev *dev, int probe) | |||
2171 | u16 ctrl; | 2180 | u16 ctrl; |
2172 | struct pci_dev *pdev; | 2181 | struct pci_dev *pdev; |
2173 | 2182 | ||
2174 | if (dev->subordinate) | 2183 | if (pci_is_root_bus(dev->bus) || dev->subordinate || !dev->bus->self) |
2175 | return -ENOTTY; | 2184 | return -ENOTTY; |
2176 | 2185 | ||
2177 | list_for_each_entry(pdev, &dev->bus->devices, bus_list) | 2186 | list_for_each_entry(pdev, &dev->bus->devices, bus_list) |
diff --git a/drivers/pci/pcie/aer/ecrc.c b/drivers/pci/pcie/aer/ecrc.c index ece97df4df6d..a928d8ab6bda 100644 --- a/drivers/pci/pcie/aer/ecrc.c +++ b/drivers/pci/pcie/aer/ecrc.c | |||
@@ -106,7 +106,7 @@ void pcie_set_ecrc_checking(struct pci_dev *dev) | |||
106 | disable_ecrc_checking(dev); | 106 | disable_ecrc_checking(dev); |
107 | break; | 107 | break; |
108 | case ECRC_POLICY_ON: | 108 | case ECRC_POLICY_ON: |
109 | enable_ecrc_checking(dev);; | 109 | enable_ecrc_checking(dev); |
110 | break; | 110 | break; |
111 | default: | 111 | default: |
112 | return; | 112 | return; |
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 56552d74abea..06b965623962 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -1058,6 +1058,11 @@ static void __devinit quirk_no_ata_d3(struct pci_dev *pdev) | |||
1058 | } | 1058 | } |
1059 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_ANY_ID, quirk_no_ata_d3); | 1059 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_ANY_ID, quirk_no_ata_d3); |
1060 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, PCI_ANY_ID, quirk_no_ata_d3); | 1060 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, PCI_ANY_ID, quirk_no_ata_d3); |
1061 | /* ALi loses some register settings that we cannot then restore */ | ||
1062 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AL, PCI_ANY_ID, quirk_no_ata_d3); | ||
1063 | /* VIA comes back fine but we need to keep it alive or ACPI GTM failures | ||
1064 | occur when mode detecting */ | ||
1065 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_no_ata_d3); | ||
1061 | 1066 | ||
1062 | /* This was originally an Alpha specific thing, but it really fits here. | 1067 | /* This was originally an Alpha specific thing, but it really fits here. |
1063 | * The i82375 PCI/EISA bridge appears as non-classified. Fix that. | 1068 | * The i82375 PCI/EISA bridge appears as non-classified. Fix that. |
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c index eddb0748b0ea..8c02b6c53bdb 100644 --- a/drivers/pci/slot.c +++ b/drivers/pci/slot.c | |||
@@ -311,7 +311,7 @@ EXPORT_SYMBOL_GPL(pci_destroy_slot); | |||
311 | #include <linux/pci_hotplug.h> | 311 | #include <linux/pci_hotplug.h> |
312 | /** | 312 | /** |
313 | * pci_hp_create_link - create symbolic link to the hotplug driver module. | 313 | * pci_hp_create_link - create symbolic link to the hotplug driver module. |
314 | * @slot: struct pci_slot | 314 | * @pci_slot: struct pci_slot |
315 | * | 315 | * |
316 | * Helper function for pci_hotplug_core.c to create symbolic link to | 316 | * Helper function for pci_hotplug_core.c to create symbolic link to |
317 | * the hotplug driver module. | 317 | * the hotplug driver module. |
@@ -334,7 +334,7 @@ EXPORT_SYMBOL_GPL(pci_hp_create_module_link); | |||
334 | 334 | ||
335 | /** | 335 | /** |
336 | * pci_hp_remove_link - remove symbolic link to the hotplug driver module. | 336 | * pci_hp_remove_link - remove symbolic link to the hotplug driver module. |
337 | * @slot: struct pci_slot | 337 | * @pci_slot: struct pci_slot |
338 | * | 338 | * |
339 | * Helper function for pci_hotplug_core.c to remove symbolic link to | 339 | * Helper function for pci_hotplug_core.c to remove symbolic link to |
340 | * the hotplug driver module. | 340 | * the hotplug driver module. |
diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c index 659421d0ca46..d4ad50d737b0 100644 --- a/drivers/pcmcia/vrc4171_card.c +++ b/drivers/pcmcia/vrc4171_card.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * vrc4171_card.c, NEC VRC4171 Card Controller driver for Socket Services. | 2 | * vrc4171_card.c, NEC VRC4171 Card Controller driver for Socket Services. |
3 | * | 3 | * |
4 | * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@linux-mips.org> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
@@ -32,7 +32,7 @@ | |||
32 | #include "i82365.h" | 32 | #include "i82365.h" |
33 | 33 | ||
34 | MODULE_DESCRIPTION("NEC VRC4171 Card Controllers driver for Socket Services"); | 34 | MODULE_DESCRIPTION("NEC VRC4171 Card Controllers driver for Socket Services"); |
35 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); | 35 | MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); |
36 | MODULE_LICENSE("GPL"); | 36 | MODULE_LICENSE("GPL"); |
37 | 37 | ||
38 | #define CARD_MAX_SLOTS 2 | 38 | #define CARD_MAX_SLOTS 2 |
diff --git a/drivers/pcmcia/vrc4173_cardu.c b/drivers/pcmcia/vrc4173_cardu.c index 812f038e9bda..9b3c15827e5c 100644 --- a/drivers/pcmcia/vrc4173_cardu.c +++ b/drivers/pcmcia/vrc4173_cardu.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * NEC VRC4173 CARDU driver for Socket Services | 6 | * NEC VRC4173 CARDU driver for Socket Services |
7 | * (This device doesn't support CardBus. it is supporting only 16bit PC Card.) | 7 | * (This device doesn't support CardBus. it is supporting only 16bit PC Card.) |
8 | * | 8 | * |
9 | * Copyright 2002,2003 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 9 | * Copyright 2002,2003 Yoichi Yuasa <yuasa@linux-mips.org> |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify it | 11 | * This program is free software; you can redistribute it and/or modify it |
12 | * under the terms of the GNU General Public License as published by the | 12 | * under the terms of the GNU General Public License as published by the |
@@ -41,7 +41,7 @@ | |||
41 | #include "vrc4173_cardu.h" | 41 | #include "vrc4173_cardu.h" |
42 | 42 | ||
43 | MODULE_DESCRIPTION("NEC VRC4173 CARDU driver for Socket Services"); | 43 | MODULE_DESCRIPTION("NEC VRC4173 CARDU driver for Socket Services"); |
44 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); | 44 | MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); |
45 | MODULE_LICENSE("GPL"); | 45 | MODULE_LICENSE("GPL"); |
46 | 46 | ||
47 | static int vrc4173_cardu_slots; | 47 | static int vrc4173_cardu_slots; |
diff --git a/drivers/pcmcia/vrc4173_cardu.h b/drivers/pcmcia/vrc4173_cardu.h index 7d77c74120c1..a7d96018ed8d 100644 --- a/drivers/pcmcia/vrc4173_cardu.h +++ b/drivers/pcmcia/vrc4173_cardu.h | |||
@@ -5,7 +5,7 @@ | |||
5 | * BRIEF MODULE DESCRIPTION | 5 | * BRIEF MODULE DESCRIPTION |
6 | * Include file for NEC VRC4173 CARDU. | 6 | * Include file for NEC VRC4173 CARDU. |
7 | * | 7 | * |
8 | * Copyright 2002 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 8 | * Copyright 2002 Yoichi Yuasa <yuasa@linux-mips.org> |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify it | 10 | * This program is free software; you can redistribute it and/or modify it |
11 | * under the terms of the GNU General Public License as published by the | 11 | * under the terms of the GNU General Public License as published by the |
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 32b27739ec2a..713f7bf5afb3 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c | |||
@@ -283,7 +283,7 @@ static void ds1374_work(struct work_struct *work) | |||
283 | 283 | ||
284 | stat = i2c_smbus_read_byte_data(client, DS1374_REG_SR); | 284 | stat = i2c_smbus_read_byte_data(client, DS1374_REG_SR); |
285 | if (stat < 0) | 285 | if (stat < 0) |
286 | return; | 286 | goto unlock; |
287 | 287 | ||
288 | if (stat & DS1374_REG_SR_AF) { | 288 | if (stat & DS1374_REG_SR_AF) { |
289 | stat &= ~DS1374_REG_SR_AF; | 289 | stat &= ~DS1374_REG_SR_AF; |
@@ -302,7 +302,7 @@ static void ds1374_work(struct work_struct *work) | |||
302 | out: | 302 | out: |
303 | if (!ds1374->exiting) | 303 | if (!ds1374->exiting) |
304 | enable_irq(client->irq); | 304 | enable_irq(client->irq); |
305 | 305 | unlock: | |
306 | mutex_unlock(&ds1374->mutex); | 306 | mutex_unlock(&ds1374->mutex); |
307 | } | 307 | } |
308 | 308 | ||
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index f11297aff854..2c839d0d21bd 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for NEC VR4100 series Real Time Clock unit. | 2 | * Driver for NEC VR4100 series Real Time Clock unit. |
3 | * | 3 | * |
4 | * Copyright (C) 2003-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2003-2008 Yoichi Yuasa <yuasa@linux-mips.org> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
@@ -33,7 +33,7 @@ | |||
33 | #include <asm/io.h> | 33 | #include <asm/io.h> |
34 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
35 | 35 | ||
36 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); | 36 | MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); |
37 | MODULE_DESCRIPTION("NEC VR4100 series RTC driver"); | 37 | MODULE_DESCRIPTION("NEC VR4100 series RTC driver"); |
38 | MODULE_LICENSE("GPL v2"); | 38 | MODULE_LICENSE("GPL v2"); |
39 | 39 | ||
diff --git a/drivers/scsi/cxgb3i/Kbuild b/drivers/scsi/cxgb3i/Kbuild index 25a2032bfa26..70d060b7ff4f 100644 --- a/drivers/scsi/cxgb3i/Kbuild +++ b/drivers/scsi/cxgb3i/Kbuild | |||
@@ -1,4 +1,4 @@ | |||
1 | EXTRA_CFLAGS += -I$(TOPDIR)/drivers/net/cxgb3 | 1 | EXTRA_CFLAGS += -I$(srctree)/drivers/net/cxgb3 |
2 | 2 | ||
3 | cxgb3i-y := cxgb3i_init.o cxgb3i_iscsi.o cxgb3i_pdu.o cxgb3i_offload.o cxgb3i_ddp.o | 3 | cxgb3i-y := cxgb3i_init.o cxgb3i_iscsi.o cxgb3i_pdu.o cxgb3i_offload.o cxgb3i_ddp.o |
4 | obj-$(CONFIG_SCSI_CXGB3_ISCSI) += cxgb3i.o | 4 | obj-$(CONFIG_SCSI_CXGB3_ISCSI) += cxgb3i.o |
diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c index 74369a3f963b..c399f485aa7d 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c +++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c | |||
@@ -13,6 +13,7 @@ | |||
13 | 13 | ||
14 | #include <linux/inet.h> | 14 | #include <linux/inet.h> |
15 | #include <linux/crypto.h> | 15 | #include <linux/crypto.h> |
16 | #include <linux/if_vlan.h> | ||
16 | #include <net/dst.h> | 17 | #include <net/dst.h> |
17 | #include <net/tcp.h> | 18 | #include <net/tcp.h> |
18 | #include <scsi/scsi_cmnd.h> | 19 | #include <scsi/scsi_cmnd.h> |
@@ -184,6 +185,9 @@ static struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *ndev) | |||
184 | struct cxgb3i_adapter *snic; | 185 | struct cxgb3i_adapter *snic; |
185 | int i; | 186 | int i; |
186 | 187 | ||
188 | if (ndev->priv_flags & IFF_802_1Q_VLAN) | ||
189 | ndev = vlan_dev_real_dev(ndev); | ||
190 | |||
187 | read_lock(&cxgb3i_snic_rwlock); | 191 | read_lock(&cxgb3i_snic_rwlock); |
188 | list_for_each_entry(snic, &cxgb3i_snic_list, list_head) { | 192 | list_for_each_entry(snic, &cxgb3i_snic_list, list_head) { |
189 | for (i = 0; i < snic->hba_cnt; i++) { | 193 | for (i = 0; i < snic->hba_cnt; i++) { |
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c index a84072865fc2..2c266c01dc5a 100644 --- a/drivers/scsi/fnic/fnic_main.c +++ b/drivers/scsi/fnic/fnic_main.c | |||
@@ -473,16 +473,16 @@ static int __devinit fnic_probe(struct pci_dev *pdev, | |||
473 | * limitation for the device. Try 40-bit first, and | 473 | * limitation for the device. Try 40-bit first, and |
474 | * fail to 32-bit. | 474 | * fail to 32-bit. |
475 | */ | 475 | */ |
476 | err = pci_set_dma_mask(pdev, DMA_40BIT_MASK); | 476 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(40)); |
477 | if (err) { | 477 | if (err) { |
478 | err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); | 478 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); |
479 | if (err) { | 479 | if (err) { |
480 | shost_printk(KERN_ERR, fnic->lport->host, | 480 | shost_printk(KERN_ERR, fnic->lport->host, |
481 | "No usable DMA configuration " | 481 | "No usable DMA configuration " |
482 | "aborting\n"); | 482 | "aborting\n"); |
483 | goto err_out_release_regions; | 483 | goto err_out_release_regions; |
484 | } | 484 | } |
485 | err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); | 485 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); |
486 | if (err) { | 486 | if (err) { |
487 | shost_printk(KERN_ERR, fnic->lport->host, | 487 | shost_printk(KERN_ERR, fnic->lport->host, |
488 | "Unable to obtain 32-bit DMA " | 488 | "Unable to obtain 32-bit DMA " |
@@ -490,7 +490,7 @@ static int __devinit fnic_probe(struct pci_dev *pdev, | |||
490 | goto err_out_release_regions; | 490 | goto err_out_release_regions; |
491 | } | 491 | } |
492 | } else { | 492 | } else { |
493 | err = pci_set_consistent_dma_mask(pdev, DMA_40BIT_MASK); | 493 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(40)); |
494 | if (err) { | 494 | if (err) { |
495 | shost_printk(KERN_ERR, fnic->lport->host, | 495 | shost_printk(KERN_ERR, fnic->lport->host, |
496 | "Unable to obtain 40-bit DMA " | 496 | "Unable to obtain 40-bit DMA " |
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index eabf36502856..bfc996971b81 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c | |||
@@ -245,7 +245,7 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic, | |||
245 | struct vnic_wq_copy *wq, | 245 | struct vnic_wq_copy *wq, |
246 | struct fnic_io_req *io_req, | 246 | struct fnic_io_req *io_req, |
247 | struct scsi_cmnd *sc, | 247 | struct scsi_cmnd *sc, |
248 | u32 sg_count) | 248 | int sg_count) |
249 | { | 249 | { |
250 | struct scatterlist *sg; | 250 | struct scatterlist *sg; |
251 | struct fc_rport *rport = starget_to_rport(scsi_target(sc->device)); | 251 | struct fc_rport *rport = starget_to_rport(scsi_target(sc->device)); |
@@ -260,9 +260,6 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic, | |||
260 | char msg[2]; | 260 | char msg[2]; |
261 | 261 | ||
262 | if (sg_count) { | 262 | if (sg_count) { |
263 | BUG_ON(sg_count < 0); | ||
264 | BUG_ON(sg_count > FNIC_MAX_SG_DESC_CNT); | ||
265 | |||
266 | /* For each SGE, create a device desc entry */ | 263 | /* For each SGE, create a device desc entry */ |
267 | desc = io_req->sgl_list; | 264 | desc = io_req->sgl_list; |
268 | for_each_sg(scsi_sglist(sc), sg, sg_count, i) { | 265 | for_each_sg(scsi_sglist(sc), sg, sg_count, i) { |
@@ -344,7 +341,7 @@ int fnic_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
344 | struct fnic *fnic; | 341 | struct fnic *fnic; |
345 | struct vnic_wq_copy *wq; | 342 | struct vnic_wq_copy *wq; |
346 | int ret; | 343 | int ret; |
347 | u32 sg_count; | 344 | int sg_count; |
348 | unsigned long flags; | 345 | unsigned long flags; |
349 | unsigned long ptr; | 346 | unsigned long ptr; |
350 | 347 | ||
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 869a11bdccbd..9928704e235f 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c | |||
@@ -1095,9 +1095,14 @@ static void adapter_info_rsp(struct srp_event_struct *evt_struct) | |||
1095 | MAX_INDIRECT_BUFS); | 1095 | MAX_INDIRECT_BUFS); |
1096 | hostdata->host->sg_tablesize = MAX_INDIRECT_BUFS; | 1096 | hostdata->host->sg_tablesize = MAX_INDIRECT_BUFS; |
1097 | } | 1097 | } |
1098 | |||
1099 | if (hostdata->madapter_info.os_type == 3) { | ||
1100 | enable_fast_fail(hostdata); | ||
1101 | return; | ||
1102 | } | ||
1098 | } | 1103 | } |
1099 | 1104 | ||
1100 | enable_fast_fail(hostdata); | 1105 | send_srp_login(hostdata); |
1101 | } | 1106 | } |
1102 | 1107 | ||
1103 | /** | 1108 | /** |
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 2eee9e6e4fe8..292c02f810d0 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c | |||
@@ -3670,13 +3670,14 @@ static void | |||
3670 | fc_bsg_goose_queue(struct fc_rport *rport) | 3670 | fc_bsg_goose_queue(struct fc_rport *rport) |
3671 | { | 3671 | { |
3672 | int flagset; | 3672 | int flagset; |
3673 | unsigned long flags; | ||
3673 | 3674 | ||
3674 | if (!rport->rqst_q) | 3675 | if (!rport->rqst_q) |
3675 | return; | 3676 | return; |
3676 | 3677 | ||
3677 | get_device(&rport->dev); | 3678 | get_device(&rport->dev); |
3678 | 3679 | ||
3679 | spin_lock(rport->rqst_q->queue_lock); | 3680 | spin_lock_irqsave(rport->rqst_q->queue_lock, flags); |
3680 | flagset = test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags) && | 3681 | flagset = test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags) && |
3681 | !test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags); | 3682 | !test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags); |
3682 | if (flagset) | 3683 | if (flagset) |
@@ -3684,7 +3685,7 @@ fc_bsg_goose_queue(struct fc_rport *rport) | |||
3684 | __blk_run_queue(rport->rqst_q); | 3685 | __blk_run_queue(rport->rqst_q); |
3685 | if (flagset) | 3686 | if (flagset) |
3686 | queue_flag_clear(QUEUE_FLAG_REENTER, rport->rqst_q); | 3687 | queue_flag_clear(QUEUE_FLAG_REENTER, rport->rqst_q); |
3687 | spin_unlock(rport->rqst_q->queue_lock); | 3688 | spin_unlock_irqrestore(rport->rqst_q->queue_lock, flags); |
3688 | 3689 | ||
3689 | put_device(&rport->dev); | 3690 | put_device(&rport->dev); |
3690 | } | 3691 | } |
diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c index 97f3158fa7b5..27e84e4b1fa9 100644 --- a/drivers/scsi/zalon.c +++ b/drivers/scsi/zalon.c | |||
@@ -134,7 +134,7 @@ zalon_probe(struct parisc_device *dev) | |||
134 | 134 | ||
135 | host = ncr_attach(&zalon7xx_template, unit, &device); | 135 | host = ncr_attach(&zalon7xx_template, unit, &device); |
136 | if (!host) | 136 | if (!host) |
137 | goto fail; | 137 | return -ENODEV; |
138 | 138 | ||
139 | if (request_irq(dev->irq, ncr53c8xx_intr, IRQF_SHARED, "zalon", host)) { | 139 | if (request_irq(dev->irq, ncr53c8xx_intr, IRQF_SHARED, "zalon", host)) { |
140 | dev_printk(KERN_ERR, &dev->dev, "irq problem with %d, detaching\n ", | 140 | dev_printk(KERN_ERR, &dev->dev, "irq problem with %d, detaching\n ", |
diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c index 0573f3b5175e..dac550e57c29 100644 --- a/drivers/serial/vr41xx_siu.c +++ b/drivers/serial/vr41xx_siu.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for NEC VR4100 series Serial Interface Unit. | 2 | * Driver for NEC VR4100 series Serial Interface Unit. |
3 | * | 3 | * |
4 | * Copyright (C) 2004-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2004-2008 Yoichi Yuasa <yuasa@linux-mips.org> |
5 | * | 5 | * |
6 | * Based on drivers/serial/8250.c, by Russell King. | 6 | * Based on drivers/serial/8250.c, by Russell King. |
7 | * | 7 | * |
diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c index 3fd3e3b412b6..3c6feed46f6e 100644 --- a/drivers/ssb/driver_mipscore.c +++ b/drivers/ssb/driver_mipscore.c | |||
@@ -49,29 +49,54 @@ static const u32 ipsflag_irq_shift[] = { | |||
49 | 49 | ||
50 | static inline u32 ssb_irqflag(struct ssb_device *dev) | 50 | static inline u32 ssb_irqflag(struct ssb_device *dev) |
51 | { | 51 | { |
52 | return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG; | 52 | u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG); |
53 | if (tpsflag) | ||
54 | return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG; | ||
55 | else | ||
56 | /* not irq supported */ | ||
57 | return 0x3f; | ||
58 | } | ||
59 | |||
60 | static struct ssb_device *find_device(struct ssb_device *rdev, int irqflag) | ||
61 | { | ||
62 | struct ssb_bus *bus = rdev->bus; | ||
63 | int i; | ||
64 | for (i = 0; i < bus->nr_devices; i++) { | ||
65 | struct ssb_device *dev; | ||
66 | dev = &(bus->devices[i]); | ||
67 | if (ssb_irqflag(dev) == irqflag) | ||
68 | return dev; | ||
69 | } | ||
70 | return NULL; | ||
53 | } | 71 | } |
54 | 72 | ||
55 | /* Get the MIPS IRQ assignment for a specified device. | 73 | /* Get the MIPS IRQ assignment for a specified device. |
56 | * If unassigned, 0 is returned. | 74 | * If unassigned, 0 is returned. |
75 | * If disabled, 5 is returned. | ||
76 | * If not supported, 6 is returned. | ||
57 | */ | 77 | */ |
58 | unsigned int ssb_mips_irq(struct ssb_device *dev) | 78 | unsigned int ssb_mips_irq(struct ssb_device *dev) |
59 | { | 79 | { |
60 | struct ssb_bus *bus = dev->bus; | 80 | struct ssb_bus *bus = dev->bus; |
81 | struct ssb_device *mdev = bus->mipscore.dev; | ||
61 | u32 irqflag; | 82 | u32 irqflag; |
62 | u32 ipsflag; | 83 | u32 ipsflag; |
63 | u32 tmp; | 84 | u32 tmp; |
64 | unsigned int irq; | 85 | unsigned int irq; |
65 | 86 | ||
66 | irqflag = ssb_irqflag(dev); | 87 | irqflag = ssb_irqflag(dev); |
88 | if (irqflag == 0x3f) | ||
89 | return 6; | ||
67 | ipsflag = ssb_read32(bus->mipscore.dev, SSB_IPSFLAG); | 90 | ipsflag = ssb_read32(bus->mipscore.dev, SSB_IPSFLAG); |
68 | for (irq = 1; irq <= 4; irq++) { | 91 | for (irq = 1; irq <= 4; irq++) { |
69 | tmp = ((ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]); | 92 | tmp = ((ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]); |
70 | if (tmp == irqflag) | 93 | if (tmp == irqflag) |
71 | break; | 94 | break; |
72 | } | 95 | } |
73 | if (irq == 5) | 96 | if (irq == 5) { |
74 | irq = 0; | 97 | if ((1 << irqflag) & ssb_read32(mdev, SSB_INTVEC)) |
98 | irq = 0; | ||
99 | } | ||
75 | 100 | ||
76 | return irq; | 101 | return irq; |
77 | } | 102 | } |
@@ -97,25 +122,56 @@ static void set_irq(struct ssb_device *dev, unsigned int irq) | |||
97 | struct ssb_device *mdev = bus->mipscore.dev; | 122 | struct ssb_device *mdev = bus->mipscore.dev; |
98 | u32 irqflag = ssb_irqflag(dev); | 123 | u32 irqflag = ssb_irqflag(dev); |
99 | 124 | ||
125 | BUG_ON(oldirq == 6); | ||
126 | |||
100 | dev->irq = irq + 2; | 127 | dev->irq = irq + 2; |
101 | 128 | ||
102 | ssb_dprintk(KERN_INFO PFX | ||
103 | "set_irq: core 0x%04x, irq %d => %d\n", | ||
104 | dev->id.coreid, oldirq, irq); | ||
105 | /* clear the old irq */ | 129 | /* clear the old irq */ |
106 | if (oldirq == 0) | 130 | if (oldirq == 0) |
107 | ssb_write32(mdev, SSB_INTVEC, (~(1 << irqflag) & ssb_read32(mdev, SSB_INTVEC))); | 131 | ssb_write32(mdev, SSB_INTVEC, (~(1 << irqflag) & ssb_read32(mdev, SSB_INTVEC))); |
108 | else | 132 | else if (oldirq != 5) |
109 | clear_irq(bus, oldirq); | 133 | clear_irq(bus, oldirq); |
110 | 134 | ||
111 | /* assign the new one */ | 135 | /* assign the new one */ |
112 | if (irq == 0) { | 136 | if (irq == 0) { |
113 | ssb_write32(mdev, SSB_INTVEC, ((1 << irqflag) | ssb_read32(mdev, SSB_INTVEC))); | 137 | ssb_write32(mdev, SSB_INTVEC, ((1 << irqflag) | ssb_read32(mdev, SSB_INTVEC))); |
114 | } else { | 138 | } else { |
139 | u32 ipsflag = ssb_read32(mdev, SSB_IPSFLAG); | ||
140 | if ((ipsflag & ipsflag_irq_mask[irq]) != ipsflag_irq_mask[irq]) { | ||
141 | u32 oldipsflag = (ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]; | ||
142 | struct ssb_device *olddev = find_device(dev, oldipsflag); | ||
143 | if (olddev) | ||
144 | set_irq(olddev, 0); | ||
145 | } | ||
115 | irqflag <<= ipsflag_irq_shift[irq]; | 146 | irqflag <<= ipsflag_irq_shift[irq]; |
116 | irqflag |= (ssb_read32(mdev, SSB_IPSFLAG) & ~ipsflag_irq_mask[irq]); | 147 | irqflag |= (ipsflag & ~ipsflag_irq_mask[irq]); |
117 | ssb_write32(mdev, SSB_IPSFLAG, irqflag); | 148 | ssb_write32(mdev, SSB_IPSFLAG, irqflag); |
118 | } | 149 | } |
150 | ssb_dprintk(KERN_INFO PFX | ||
151 | "set_irq: core 0x%04x, irq %d => %d\n", | ||
152 | dev->id.coreid, oldirq+2, irq+2); | ||
153 | } | ||
154 | |||
155 | static void print_irq(struct ssb_device *dev, unsigned int irq) | ||
156 | { | ||
157 | int i; | ||
158 | static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"}; | ||
159 | ssb_dprintk(KERN_INFO PFX | ||
160 | "core 0x%04x, irq :", dev->id.coreid); | ||
161 | for (i = 0; i <= 6; i++) { | ||
162 | ssb_dprintk(" %s%s", irq_name[i], i==irq?"*":" "); | ||
163 | } | ||
164 | ssb_dprintk("\n"); | ||
165 | } | ||
166 | |||
167 | static void dump_irq(struct ssb_bus *bus) | ||
168 | { | ||
169 | int i; | ||
170 | for (i = 0; i < bus->nr_devices; i++) { | ||
171 | struct ssb_device *dev; | ||
172 | dev = &(bus->devices[i]); | ||
173 | print_irq(dev, ssb_mips_irq(dev)); | ||
174 | } | ||
119 | } | 175 | } |
120 | 176 | ||
121 | static void ssb_mips_serial_init(struct ssb_mipscore *mcore) | 177 | static void ssb_mips_serial_init(struct ssb_mipscore *mcore) |
@@ -197,16 +253,23 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore) | |||
197 | 253 | ||
198 | /* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */ | 254 | /* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */ |
199 | for (irq = 2, i = 0; i < bus->nr_devices; i++) { | 255 | for (irq = 2, i = 0; i < bus->nr_devices; i++) { |
256 | int mips_irq; | ||
200 | dev = &(bus->devices[i]); | 257 | dev = &(bus->devices[i]); |
201 | dev->irq = ssb_mips_irq(dev) + 2; | 258 | mips_irq = ssb_mips_irq(dev); |
259 | if (mips_irq > 4) | ||
260 | dev->irq = 0; | ||
261 | else | ||
262 | dev->irq = mips_irq + 2; | ||
263 | if (dev->irq > 5) | ||
264 | continue; | ||
202 | switch (dev->id.coreid) { | 265 | switch (dev->id.coreid) { |
203 | case SSB_DEV_USB11_HOST: | 266 | case SSB_DEV_USB11_HOST: |
204 | /* shouldn't need a separate irq line for non-4710, most of them have a proper | 267 | /* shouldn't need a separate irq line for non-4710, most of them have a proper |
205 | * external usb controller on the pci */ | 268 | * external usb controller on the pci */ |
206 | if ((bus->chip_id == 0x4710) && (irq <= 4)) { | 269 | if ((bus->chip_id == 0x4710) && (irq <= 4)) { |
207 | set_irq(dev, irq++); | 270 | set_irq(dev, irq++); |
208 | break; | ||
209 | } | 271 | } |
272 | break; | ||
210 | /* fallthrough */ | 273 | /* fallthrough */ |
211 | case SSB_DEV_PCI: | 274 | case SSB_DEV_PCI: |
212 | case SSB_DEV_ETHERNET: | 275 | case SSB_DEV_ETHERNET: |
@@ -220,6 +283,8 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore) | |||
220 | } | 283 | } |
221 | } | 284 | } |
222 | } | 285 | } |
286 | ssb_dprintk(KERN_INFO PFX "after irq reconfiguration\n"); | ||
287 | dump_irq(bus); | ||
223 | 288 | ||
224 | ssb_mips_serial_init(mcore); | 289 | ssb_mips_serial_init(mcore); |
225 | ssb_mips_flash_detect(mcore); | 290 | ssb_mips_flash_detect(mcore); |
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index f8d9045d668a..0f7a30b7d2d1 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c | |||
@@ -1261,7 +1261,7 @@ static int mon_alloc_buff(struct mon_pgmap *map, int npages) | |||
1261 | return -ENOMEM; | 1261 | return -ENOMEM; |
1262 | } | 1262 | } |
1263 | map[n].ptr = (unsigned char *) vaddr; | 1263 | map[n].ptr = (unsigned char *) vaddr; |
1264 | map[n].pg = virt_to_page(vaddr); | 1264 | map[n].pg = virt_to_page((void *) vaddr); |
1265 | } | 1265 | } |
1266 | return 0; | 1266 | return 0; |
1267 | } | 1267 | } |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index d6d65ef85f54..8afcf08eba98 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -616,6 +616,8 @@ config FB_STI | |||
616 | select FB_CFB_FILLRECT | 616 | select FB_CFB_FILLRECT |
617 | select FB_CFB_COPYAREA | 617 | select FB_CFB_COPYAREA |
618 | select FB_CFB_IMAGEBLIT | 618 | select FB_CFB_IMAGEBLIT |
619 | select STI_CONSOLE | ||
620 | select VT | ||
619 | default y | 621 | default y |
620 | ---help--- | 622 | ---help--- |
621 | STI refers to the HP "Standard Text Interface" which is a set of | 623 | STI refers to the HP "Standard Text Interface" which is a set of |
diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c index 7bad24ed04ef..108b89e09a80 100644 --- a/drivers/video/cobalt_lcdfb.c +++ b/drivers/video/cobalt_lcdfb.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Cobalt server LCD frame buffer driver. | 2 | * Cobalt server LCD frame buffer driver. |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2008 Yoichi Yuasa <yuasa@linux-mips.org> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 53ea05645ff8..53eb39652791 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
@@ -1513,8 +1513,6 @@ register_framebuffer(struct fb_info *fb_info) | |||
1513 | if (!registered_fb[i]) | 1513 | if (!registered_fb[i]) |
1514 | break; | 1514 | break; |
1515 | fb_info->node = i; | 1515 | fb_info->node = i; |
1516 | mutex_init(&fb_info->lock); | ||
1517 | mutex_init(&fb_info->mm_lock); | ||
1518 | 1516 | ||
1519 | fb_info->dev = device_create(fb_class, fb_info->device, | 1517 | fb_info->dev = device_create(fb_class, fb_info->device, |
1520 | MKDEV(FB_MAJOR, i), NULL, "fb%d", i); | 1518 | MKDEV(FB_MAJOR, i), NULL, "fb%d", i); |
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index d4a2c11d9809..afc04df39a03 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c | |||
@@ -62,6 +62,9 @@ struct fb_info *framebuffer_alloc(size_t size, struct device *dev) | |||
62 | mutex_init(&info->bl_curve_mutex); | 62 | mutex_init(&info->bl_curve_mutex); |
63 | #endif | 63 | #endif |
64 | 64 | ||
65 | mutex_init(&info->lock); | ||
66 | mutex_init(&info->mm_lock); | ||
67 | |||
65 | return info; | 68 | return info; |
66 | #undef PADDING | 69 | #undef PADDING |
67 | #undef BYTES_PER_LONG | 70 | #undef BYTES_PER_LONG |
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 59c3a2e14913..76bc51b616d1 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c | |||
@@ -2083,6 +2083,7 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm | |||
2083 | spin_lock_init(&ACCESS_FBINFO(lock.accel)); | 2083 | spin_lock_init(&ACCESS_FBINFO(lock.accel)); |
2084 | init_rwsem(&ACCESS_FBINFO(crtc2.lock)); | 2084 | init_rwsem(&ACCESS_FBINFO(crtc2.lock)); |
2085 | init_rwsem(&ACCESS_FBINFO(altout.lock)); | 2085 | init_rwsem(&ACCESS_FBINFO(altout.lock)); |
2086 | mutex_init(&ACCESS_FBINFO(fbcon).lock); | ||
2086 | mutex_init(&ACCESS_FBINFO(fbcon).mm_lock); | 2087 | mutex_init(&ACCESS_FBINFO(fbcon).mm_lock); |
2087 | ACCESS_FBINFO(irq_flags) = 0; | 2088 | ACCESS_FBINFO(irq_flags) = 0; |
2088 | init_waitqueue_head(&ACCESS_FBINFO(crtc1.vsync.wait)); | 2089 | init_waitqueue_head(&ACCESS_FBINFO(crtc1.vsync.wait)); |
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 43680e545427..bb63c07e13de 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c | |||
@@ -211,23 +211,21 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var, | |||
211 | 211 | ||
212 | /** | 212 | /** |
213 | * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock. | 213 | * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock. |
214 | * @id: window id. | ||
214 | * @sfb: The hardware state. | 215 | * @sfb: The hardware state. |
215 | * @pixclock: The pixel clock wanted, in picoseconds. | 216 | * @pixclock: The pixel clock wanted, in picoseconds. |
216 | * | 217 | * |
217 | * Given the specified pixel clock, work out the necessary divider to get | 218 | * Given the specified pixel clock, work out the necessary divider to get |
218 | * close to the output frequency. | 219 | * close to the output frequency. |
219 | */ | 220 | */ |
220 | static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk) | 221 | static int s3c_fb_calc_pixclk(unsigned char id, struct s3c_fb *sfb, unsigned int pixclk) |
221 | { | 222 | { |
223 | struct s3c_fb_pd_win *win = sfb->pdata->win[id]; | ||
222 | unsigned long clk = clk_get_rate(sfb->bus_clk); | 224 | unsigned long clk = clk_get_rate(sfb->bus_clk); |
223 | unsigned long long tmp; | ||
224 | unsigned int result; | 225 | unsigned int result; |
225 | 226 | ||
226 | tmp = (unsigned long long)clk; | 227 | pixclk *= win->win_mode.refresh; |
227 | tmp *= pixclk; | 228 | result = clk / pixclk; |
228 | |||
229 | do_div(tmp, 1000000000UL); | ||
230 | result = (unsigned int)tmp / 1000; | ||
231 | 229 | ||
232 | dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n", | 230 | dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n", |
233 | pixclk, clk, result, clk / result); | 231 | pixclk, clk, result, clk / result); |
@@ -267,6 +265,7 @@ static int s3c_fb_set_par(struct fb_info *info) | |||
267 | struct s3c_fb *sfb = win->parent; | 265 | struct s3c_fb *sfb = win->parent; |
268 | void __iomem *regs = sfb->regs; | 266 | void __iomem *regs = sfb->regs; |
269 | int win_no = win->index; | 267 | int win_no = win->index; |
268 | u32 osdc_data = 0; | ||
270 | u32 data; | 269 | u32 data; |
271 | u32 pagewidth; | 270 | u32 pagewidth; |
272 | int clkdiv; | 271 | int clkdiv; |
@@ -302,7 +301,7 @@ static int s3c_fb_set_par(struct fb_info *info) | |||
302 | /* use window 0 as the basis for the lcd output timings */ | 301 | /* use window 0 as the basis for the lcd output timings */ |
303 | 302 | ||
304 | if (win_no == 0) { | 303 | if (win_no == 0) { |
305 | clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock); | 304 | clkdiv = s3c_fb_calc_pixclk(win_no, sfb, var->pixclock); |
306 | 305 | ||
307 | data = sfb->pdata->vidcon0; | 306 | data = sfb->pdata->vidcon0; |
308 | data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR); | 307 | data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR); |
@@ -359,8 +358,6 @@ static int s3c_fb_set_par(struct fb_info *info) | |||
359 | 358 | ||
360 | data = var->xres * var->yres; | 359 | data = var->xres * var->yres; |
361 | 360 | ||
362 | u32 osdc_data = 0; | ||
363 | |||
364 | osdc_data = VIDISD14C_ALPHA1_R(0xf) | | 361 | osdc_data = VIDISD14C_ALPHA1_R(0xf) | |
365 | VIDISD14C_ALPHA1_G(0xf) | | 362 | VIDISD14C_ALPHA1_G(0xf) | |
366 | VIDISD14C_ALPHA1_B(0xf); | 363 | VIDISD14C_ALPHA1_B(0xf); |
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index fd33455389b8..4a067f0d0ceb 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c | |||
@@ -6367,7 +6367,6 @@ error_3: vfree(ivideo->bios_abase); | |||
6367 | sis_fb_info->fix = ivideo->sisfb_fix; | 6367 | sis_fb_info->fix = ivideo->sisfb_fix; |
6368 | sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset; | 6368 | sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset; |
6369 | sis_fb_info->fbops = &sisfb_ops; | 6369 | sis_fb_info->fbops = &sisfb_ops; |
6370 | sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info); | ||
6371 | sis_fb_info->pseudo_palette = ivideo->pseudo_palette; | 6370 | sis_fb_info->pseudo_palette = ivideo->pseudo_palette; |
6372 | 6371 | ||
6373 | fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0); | 6372 | fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0); |
diff --git a/drivers/vlynq/Kconfig b/drivers/vlynq/Kconfig index f6542211db48..a9efb1625321 100644 --- a/drivers/vlynq/Kconfig +++ b/drivers/vlynq/Kconfig | |||
@@ -13,7 +13,7 @@ config VLYNQ | |||
13 | 13 | ||
14 | config VLYNQ_DEBUG | 14 | config VLYNQ_DEBUG |
15 | bool "VLYNQ bus debug" | 15 | bool "VLYNQ bus debug" |
16 | depends on VLYNQ && KERNEL_DEBUG | 16 | depends on VLYNQ && DEBUG_KERNEL |
17 | help | 17 | help |
18 | Turn on VLYNQ bus debugging. | 18 | Turn on VLYNQ bus debugging. |
19 | 19 | ||
diff --git a/drivers/vlynq/vlynq.c b/drivers/vlynq/vlynq.c index 7335433b067b..f05d2a368367 100644 --- a/drivers/vlynq/vlynq.c +++ b/drivers/vlynq/vlynq.c | |||
@@ -76,7 +76,7 @@ struct vlynq_regs { | |||
76 | u32 int_device[8]; | 76 | u32 int_device[8]; |
77 | }; | 77 | }; |
78 | 78 | ||
79 | #ifdef VLYNQ_DEBUG | 79 | #ifdef CONFIG_VLYNQ_DEBUG |
80 | static void vlynq_dump_regs(struct vlynq_device *dev) | 80 | static void vlynq_dump_regs(struct vlynq_device *dev) |
81 | { | 81 | { |
82 | int i; | 82 | int i; |