diff options
Diffstat (limited to 'drivers/char')
30 files changed, 1154 insertions, 341 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 9e43e39dc35c..d08bb4ee1307 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -610,6 +610,13 @@ config HVC_RTAS | |||
610 | help | 610 | help |
611 | IBM Console device driver which makes use of RTAS | 611 | IBM Console device driver which makes use of RTAS |
612 | 612 | ||
613 | config HVC_BEAT | ||
614 | bool "Toshiba's Beat Hypervisor Console support" | ||
615 | depends on PPC_CELLEB | ||
616 | select HVC_DRIVER | ||
617 | help | ||
618 | Toshiba's Cell Reference Set Beat Console device driver | ||
619 | |||
613 | config HVCS | 620 | config HVCS |
614 | tristate "IBM Hypervisor Virtual Console Server support" | 621 | tristate "IBM Hypervisor Virtual Console Server support" |
615 | depends on PPC_PSERIES | 622 | depends on PPC_PSERIES |
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index fc110637ced6..ae8567cc529c 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -45,6 +45,7 @@ obj-$(CONFIG_RIO) += rio/ generic_serial.o | |||
45 | obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o | 45 | obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o |
46 | obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o | 46 | obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o |
47 | obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o | 47 | obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o |
48 | obj-$(CONFIG_HVC_BEAT) += hvc_beat.o | ||
48 | obj-$(CONFIG_HVC_DRIVER) += hvc_console.o | 49 | obj-$(CONFIG_HVC_DRIVER) += hvc_console.o |
49 | obj-$(CONFIG_RAW_DRIVER) += raw.o | 50 | obj-$(CONFIG_RAW_DRIVER) += raw.o |
50 | obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o | 51 | obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o |
@@ -59,6 +60,8 @@ obj-$(CONFIG_BRIQ_PANEL) += briq_panel.o | |||
59 | obj-$(CONFIG_PRINTER) += lp.o | 60 | obj-$(CONFIG_PRINTER) += lp.o |
60 | obj-$(CONFIG_TIPAR) += tipar.o | 61 | obj-$(CONFIG_TIPAR) += tipar.o |
61 | 62 | ||
63 | obj-$(CONFIG_APM_EMULATION) += apm-emulation.o | ||
64 | |||
62 | obj-$(CONFIG_DTLK) += dtlk.o | 65 | obj-$(CONFIG_DTLK) += dtlk.o |
63 | obj-$(CONFIG_R3964) += n_r3964.o | 66 | obj-$(CONFIG_R3964) += n_r3964.o |
64 | obj-$(CONFIG_APPLICOM) += applicom.o | 67 | obj-$(CONFIG_APPLICOM) += applicom.o |
diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c new file mode 100644 index 000000000000..179c7a3b6e75 --- /dev/null +++ b/drivers/char/apm-emulation.c | |||
@@ -0,0 +1,672 @@ | |||
1 | /* | ||
2 | * bios-less APM driver for ARM Linux | ||
3 | * Jamey Hicks <jamey@crl.dec.com> | ||
4 | * adapted from the APM BIOS driver for Linux by Stephen Rothwell (sfr@linuxcare.com) | ||
5 | * | ||
6 | * APM 1.2 Reference: | ||
7 | * Intel Corporation, Microsoft Corporation. Advanced Power Management | ||
8 | * (APM) BIOS Interface Specification, Revision 1.2, February 1996. | ||
9 | * | ||
10 | * [This document is available from Microsoft at: | ||
11 | * http://www.microsoft.com/hwdev/busbios/amp_12.htm] | ||
12 | */ | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/poll.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/proc_fs.h> | ||
17 | #include <linux/miscdevice.h> | ||
18 | #include <linux/apm_bios.h> | ||
19 | #include <linux/capability.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/pm.h> | ||
22 | #include <linux/apm-emulation.h> | ||
23 | #include <linux/device.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/list.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/completion.h> | ||
28 | #include <linux/kthread.h> | ||
29 | #include <linux/delay.h> | ||
30 | |||
31 | #include <asm/system.h> | ||
32 | |||
33 | /* | ||
34 | * The apm_bios device is one of the misc char devices. | ||
35 | * This is its minor number. | ||
36 | */ | ||
37 | #define APM_MINOR_DEV 134 | ||
38 | |||
39 | /* | ||
40 | * See Documentation/Config.help for the configuration options. | ||
41 | * | ||
42 | * Various options can be changed at boot time as follows: | ||
43 | * (We allow underscores for compatibility with the modules code) | ||
44 | * apm=on/off enable/disable APM | ||
45 | */ | ||
46 | |||
47 | /* | ||
48 | * Maximum number of events stored | ||
49 | */ | ||
50 | #define APM_MAX_EVENTS 16 | ||
51 | |||
52 | struct apm_queue { | ||
53 | unsigned int event_head; | ||
54 | unsigned int event_tail; | ||
55 | apm_event_t events[APM_MAX_EVENTS]; | ||
56 | }; | ||
57 | |||
58 | /* | ||
59 | * The per-file APM data | ||
60 | */ | ||
61 | struct apm_user { | ||
62 | struct list_head list; | ||
63 | |||
64 | unsigned int suser: 1; | ||
65 | unsigned int writer: 1; | ||
66 | unsigned int reader: 1; | ||
67 | |||
68 | int suspend_result; | ||
69 | unsigned int suspend_state; | ||
70 | #define SUSPEND_NONE 0 /* no suspend pending */ | ||
71 | #define SUSPEND_PENDING 1 /* suspend pending read */ | ||
72 | #define SUSPEND_READ 2 /* suspend read, pending ack */ | ||
73 | #define SUSPEND_ACKED 3 /* suspend acked */ | ||
74 | #define SUSPEND_WAIT 4 /* waiting for suspend */ | ||
75 | #define SUSPEND_DONE 5 /* suspend completed */ | ||
76 | |||
77 | struct apm_queue queue; | ||
78 | }; | ||
79 | |||
80 | /* | ||
81 | * Local variables | ||
82 | */ | ||
83 | static int suspends_pending; | ||
84 | static int apm_disabled; | ||
85 | static struct task_struct *kapmd_tsk; | ||
86 | |||
87 | static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue); | ||
88 | static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue); | ||
89 | |||
90 | /* | ||
91 | * This is a list of everyone who has opened /dev/apm_bios | ||
92 | */ | ||
93 | static DECLARE_RWSEM(user_list_lock); | ||
94 | static LIST_HEAD(apm_user_list); | ||
95 | |||
96 | /* | ||
97 | * kapmd info. kapmd provides us a process context to handle | ||
98 | * "APM" events within - specifically necessary if we're going | ||
99 | * to be suspending the system. | ||
100 | */ | ||
101 | static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait); | ||
102 | static DEFINE_SPINLOCK(kapmd_queue_lock); | ||
103 | static struct apm_queue kapmd_queue; | ||
104 | |||
105 | static DEFINE_MUTEX(state_lock); | ||
106 | |||
107 | static const char driver_version[] = "1.13"; /* no spaces */ | ||
108 | |||
109 | |||
110 | |||
111 | /* | ||
112 | * Compatibility cruft until the IPAQ people move over to the new | ||
113 | * interface. | ||
114 | */ | ||
115 | static void __apm_get_power_status(struct apm_power_info *info) | ||
116 | { | ||
117 | } | ||
118 | |||
119 | /* | ||
120 | * This allows machines to provide their own "apm get power status" function. | ||
121 | */ | ||
122 | void (*apm_get_power_status)(struct apm_power_info *) = __apm_get_power_status; | ||
123 | EXPORT_SYMBOL(apm_get_power_status); | ||
124 | |||
125 | |||
126 | /* | ||
127 | * APM event queue management. | ||
128 | */ | ||
129 | static inline int queue_empty(struct apm_queue *q) | ||
130 | { | ||
131 | return q->event_head == q->event_tail; | ||
132 | } | ||
133 | |||
134 | static inline apm_event_t queue_get_event(struct apm_queue *q) | ||
135 | { | ||
136 | q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS; | ||
137 | return q->events[q->event_tail]; | ||
138 | } | ||
139 | |||
140 | static void queue_add_event(struct apm_queue *q, apm_event_t event) | ||
141 | { | ||
142 | q->event_head = (q->event_head + 1) % APM_MAX_EVENTS; | ||
143 | if (q->event_head == q->event_tail) { | ||
144 | static int notified; | ||
145 | |||
146 | if (notified++ == 0) | ||
147 | printk(KERN_ERR "apm: an event queue overflowed\n"); | ||
148 | q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS; | ||
149 | } | ||
150 | q->events[q->event_head] = event; | ||
151 | } | ||
152 | |||
153 | static void queue_event(apm_event_t event) | ||
154 | { | ||
155 | struct apm_user *as; | ||
156 | |||
157 | down_read(&user_list_lock); | ||
158 | list_for_each_entry(as, &apm_user_list, list) { | ||
159 | if (as->reader) | ||
160 | queue_add_event(&as->queue, event); | ||
161 | } | ||
162 | up_read(&user_list_lock); | ||
163 | wake_up_interruptible(&apm_waitqueue); | ||
164 | } | ||
165 | |||
166 | /* | ||
167 | * queue_suspend_event - queue an APM suspend event. | ||
168 | * | ||
169 | * Check that we're in a state where we can suspend. If not, | ||
170 | * return -EBUSY. Otherwise, queue an event to all "writer" | ||
171 | * users. If there are no "writer" users, return '1' to | ||
172 | * indicate that we can immediately suspend. | ||
173 | */ | ||
174 | static int queue_suspend_event(apm_event_t event, struct apm_user *sender) | ||
175 | { | ||
176 | struct apm_user *as; | ||
177 | int ret = 1; | ||
178 | |||
179 | mutex_lock(&state_lock); | ||
180 | down_read(&user_list_lock); | ||
181 | |||
182 | /* | ||
183 | * If a thread is still processing, we can't suspend, so reject | ||
184 | * the request. | ||
185 | */ | ||
186 | list_for_each_entry(as, &apm_user_list, list) { | ||
187 | if (as != sender && as->reader && as->writer && as->suser && | ||
188 | as->suspend_state != SUSPEND_NONE) { | ||
189 | ret = -EBUSY; | ||
190 | goto out; | ||
191 | } | ||
192 | } | ||
193 | |||
194 | list_for_each_entry(as, &apm_user_list, list) { | ||
195 | if (as != sender && as->reader && as->writer && as->suser) { | ||
196 | as->suspend_state = SUSPEND_PENDING; | ||
197 | suspends_pending++; | ||
198 | queue_add_event(&as->queue, event); | ||
199 | ret = 0; | ||
200 | } | ||
201 | } | ||
202 | out: | ||
203 | up_read(&user_list_lock); | ||
204 | mutex_unlock(&state_lock); | ||
205 | wake_up_interruptible(&apm_waitqueue); | ||
206 | return ret; | ||
207 | } | ||
208 | |||
209 | static void apm_suspend(void) | ||
210 | { | ||
211 | struct apm_user *as; | ||
212 | int err = pm_suspend(PM_SUSPEND_MEM); | ||
213 | |||
214 | /* | ||
215 | * Anyone on the APM queues will think we're still suspended. | ||
216 | * Send a message so everyone knows we're now awake again. | ||
217 | */ | ||
218 | queue_event(APM_NORMAL_RESUME); | ||
219 | |||
220 | /* | ||
221 | * Finally, wake up anyone who is sleeping on the suspend. | ||
222 | */ | ||
223 | mutex_lock(&state_lock); | ||
224 | down_read(&user_list_lock); | ||
225 | list_for_each_entry(as, &apm_user_list, list) { | ||
226 | if (as->suspend_state == SUSPEND_WAIT || | ||
227 | as->suspend_state == SUSPEND_ACKED) { | ||
228 | as->suspend_result = err; | ||
229 | as->suspend_state = SUSPEND_DONE; | ||
230 | } | ||
231 | } | ||
232 | up_read(&user_list_lock); | ||
233 | mutex_unlock(&state_lock); | ||
234 | |||
235 | wake_up(&apm_suspend_waitqueue); | ||
236 | } | ||
237 | |||
238 | static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos) | ||
239 | { | ||
240 | struct apm_user *as = fp->private_data; | ||
241 | apm_event_t event; | ||
242 | int i = count, ret = 0; | ||
243 | |||
244 | if (count < sizeof(apm_event_t)) | ||
245 | return -EINVAL; | ||
246 | |||
247 | if (queue_empty(&as->queue) && fp->f_flags & O_NONBLOCK) | ||
248 | return -EAGAIN; | ||
249 | |||
250 | wait_event_interruptible(apm_waitqueue, !queue_empty(&as->queue)); | ||
251 | |||
252 | while ((i >= sizeof(event)) && !queue_empty(&as->queue)) { | ||
253 | event = queue_get_event(&as->queue); | ||
254 | |||
255 | ret = -EFAULT; | ||
256 | if (copy_to_user(buf, &event, sizeof(event))) | ||
257 | break; | ||
258 | |||
259 | mutex_lock(&state_lock); | ||
260 | if (as->suspend_state == SUSPEND_PENDING && | ||
261 | (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND)) | ||
262 | as->suspend_state = SUSPEND_READ; | ||
263 | mutex_unlock(&state_lock); | ||
264 | |||
265 | buf += sizeof(event); | ||
266 | i -= sizeof(event); | ||
267 | } | ||
268 | |||
269 | if (i < count) | ||
270 | ret = count - i; | ||
271 | |||
272 | return ret; | ||
273 | } | ||
274 | |||
275 | static unsigned int apm_poll(struct file *fp, poll_table * wait) | ||
276 | { | ||
277 | struct apm_user *as = fp->private_data; | ||
278 | |||
279 | poll_wait(fp, &apm_waitqueue, wait); | ||
280 | return queue_empty(&as->queue) ? 0 : POLLIN | POLLRDNORM; | ||
281 | } | ||
282 | |||
283 | /* | ||
284 | * apm_ioctl - handle APM ioctl | ||
285 | * | ||
286 | * APM_IOC_SUSPEND | ||
287 | * This IOCTL is overloaded, and performs two functions. It is used to: | ||
288 | * - initiate a suspend | ||
289 | * - acknowledge a suspend read from /dev/apm_bios. | ||
290 | * Only when everyone who has opened /dev/apm_bios with write permission | ||
291 | * has acknowledge does the actual suspend happen. | ||
292 | */ | ||
293 | static int | ||
294 | apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) | ||
295 | { | ||
296 | struct apm_user *as = filp->private_data; | ||
297 | unsigned long flags; | ||
298 | int err = -EINVAL; | ||
299 | |||
300 | if (!as->suser || !as->writer) | ||
301 | return -EPERM; | ||
302 | |||
303 | switch (cmd) { | ||
304 | case APM_IOC_SUSPEND: | ||
305 | mutex_lock(&state_lock); | ||
306 | |||
307 | as->suspend_result = -EINTR; | ||
308 | |||
309 | if (as->suspend_state == SUSPEND_READ) { | ||
310 | int pending; | ||
311 | |||
312 | /* | ||
313 | * If we read a suspend command from /dev/apm_bios, | ||
314 | * then the corresponding APM_IOC_SUSPEND ioctl is | ||
315 | * interpreted as an acknowledge. | ||
316 | */ | ||
317 | as->suspend_state = SUSPEND_ACKED; | ||
318 | suspends_pending--; | ||
319 | pending = suspends_pending == 0; | ||
320 | mutex_unlock(&state_lock); | ||
321 | |||
322 | /* | ||
323 | * If there are no further acknowledges required, | ||
324 | * suspend the system. | ||
325 | */ | ||
326 | if (pending) | ||
327 | apm_suspend(); | ||
328 | |||
329 | /* | ||
330 | * Wait for the suspend/resume to complete. If there | ||
331 | * are pending acknowledges, we wait here for them. | ||
332 | * | ||
333 | * Note: we need to ensure that the PM subsystem does | ||
334 | * not kick us out of the wait when it suspends the | ||
335 | * threads. | ||
336 | */ | ||
337 | flags = current->flags; | ||
338 | current->flags |= PF_NOFREEZE; | ||
339 | |||
340 | wait_event(apm_suspend_waitqueue, | ||
341 | as->suspend_state == SUSPEND_DONE); | ||
342 | } else { | ||
343 | as->suspend_state = SUSPEND_WAIT; | ||
344 | mutex_unlock(&state_lock); | ||
345 | |||
346 | /* | ||
347 | * Otherwise it is a request to suspend the system. | ||
348 | * Queue an event for all readers, and expect an | ||
349 | * acknowledge from all writers who haven't already | ||
350 | * acknowledged. | ||
351 | */ | ||
352 | err = queue_suspend_event(APM_USER_SUSPEND, as); | ||
353 | if (err < 0) { | ||
354 | /* | ||
355 | * Avoid taking the lock here - this | ||
356 | * should be fine. | ||
357 | */ | ||
358 | as->suspend_state = SUSPEND_NONE; | ||
359 | break; | ||
360 | } | ||
361 | |||
362 | if (err > 0) | ||
363 | apm_suspend(); | ||
364 | |||
365 | /* | ||
366 | * Wait for the suspend/resume to complete. If there | ||
367 | * are pending acknowledges, we wait here for them. | ||
368 | * | ||
369 | * Note: we need to ensure that the PM subsystem does | ||
370 | * not kick us out of the wait when it suspends the | ||
371 | * threads. | ||
372 | */ | ||
373 | flags = current->flags; | ||
374 | current->flags |= PF_NOFREEZE; | ||
375 | |||
376 | wait_event_interruptible(apm_suspend_waitqueue, | ||
377 | as->suspend_state == SUSPEND_DONE); | ||
378 | } | ||
379 | |||
380 | current->flags = flags; | ||
381 | |||
382 | mutex_lock(&state_lock); | ||
383 | err = as->suspend_result; | ||
384 | as->suspend_state = SUSPEND_NONE; | ||
385 | mutex_unlock(&state_lock); | ||
386 | break; | ||
387 | } | ||
388 | |||
389 | return err; | ||
390 | } | ||
391 | |||
392 | static int apm_release(struct inode * inode, struct file * filp) | ||
393 | { | ||
394 | struct apm_user *as = filp->private_data; | ||
395 | int pending = 0; | ||
396 | |||
397 | filp->private_data = NULL; | ||
398 | |||
399 | down_write(&user_list_lock); | ||
400 | list_del(&as->list); | ||
401 | up_write(&user_list_lock); | ||
402 | |||
403 | /* | ||
404 | * We are now unhooked from the chain. As far as new | ||
405 | * events are concerned, we no longer exist. However, we | ||
406 | * need to balance suspends_pending, which means the | ||
407 | * possibility of sleeping. | ||
408 | */ | ||
409 | mutex_lock(&state_lock); | ||
410 | if (as->suspend_state != SUSPEND_NONE) { | ||
411 | suspends_pending -= 1; | ||
412 | pending = suspends_pending == 0; | ||
413 | } | ||
414 | mutex_unlock(&state_lock); | ||
415 | if (pending) | ||
416 | apm_suspend(); | ||
417 | |||
418 | kfree(as); | ||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | static int apm_open(struct inode * inode, struct file * filp) | ||
423 | { | ||
424 | struct apm_user *as; | ||
425 | |||
426 | as = kzalloc(sizeof(*as), GFP_KERNEL); | ||
427 | if (as) { | ||
428 | /* | ||
429 | * XXX - this is a tiny bit broken, when we consider BSD | ||
430 | * process accounting. If the device is opened by root, we | ||
431 | * instantly flag that we used superuser privs. Who knows, | ||
432 | * we might close the device immediately without doing a | ||
433 | * privileged operation -- cevans | ||
434 | */ | ||
435 | as->suser = capable(CAP_SYS_ADMIN); | ||
436 | as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE; | ||
437 | as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ; | ||
438 | |||
439 | down_write(&user_list_lock); | ||
440 | list_add(&as->list, &apm_user_list); | ||
441 | up_write(&user_list_lock); | ||
442 | |||
443 | filp->private_data = as; | ||
444 | } | ||
445 | |||
446 | return as ? 0 : -ENOMEM; | ||
447 | } | ||
448 | |||
449 | static struct file_operations apm_bios_fops = { | ||
450 | .owner = THIS_MODULE, | ||
451 | .read = apm_read, | ||
452 | .poll = apm_poll, | ||
453 | .ioctl = apm_ioctl, | ||
454 | .open = apm_open, | ||
455 | .release = apm_release, | ||
456 | }; | ||
457 | |||
458 | static struct miscdevice apm_device = { | ||
459 | .minor = APM_MINOR_DEV, | ||
460 | .name = "apm_bios", | ||
461 | .fops = &apm_bios_fops | ||
462 | }; | ||
463 | |||
464 | |||
465 | #ifdef CONFIG_PROC_FS | ||
466 | /* | ||
467 | * Arguments, with symbols from linux/apm_bios.h. | ||
468 | * | ||
469 | * 0) Linux driver version (this will change if format changes) | ||
470 | * 1) APM BIOS Version. Usually 1.0, 1.1 or 1.2. | ||
471 | * 2) APM flags from APM Installation Check (0x00): | ||
472 | * bit 0: APM_16_BIT_SUPPORT | ||
473 | * bit 1: APM_32_BIT_SUPPORT | ||
474 | * bit 2: APM_IDLE_SLOWS_CLOCK | ||
475 | * bit 3: APM_BIOS_DISABLED | ||
476 | * bit 4: APM_BIOS_DISENGAGED | ||
477 | * 3) AC line status | ||
478 | * 0x00: Off-line | ||
479 | * 0x01: On-line | ||
480 | * 0x02: On backup power (BIOS >= 1.1 only) | ||
481 | * 0xff: Unknown | ||
482 | * 4) Battery status | ||
483 | * 0x00: High | ||
484 | * 0x01: Low | ||
485 | * 0x02: Critical | ||
486 | * 0x03: Charging | ||
487 | * 0x04: Selected battery not present (BIOS >= 1.2 only) | ||
488 | * 0xff: Unknown | ||
489 | * 5) Battery flag | ||
490 | * bit 0: High | ||
491 | * bit 1: Low | ||
492 | * bit 2: Critical | ||
493 | * bit 3: Charging | ||
494 | * bit 7: No system battery | ||
495 | * 0xff: Unknown | ||
496 | * 6) Remaining battery life (percentage of charge): | ||
497 | * 0-100: valid | ||
498 | * -1: Unknown | ||
499 | * 7) Remaining battery life (time units): | ||
500 | * Number of remaining minutes or seconds | ||
501 | * -1: Unknown | ||
502 | * 8) min = minutes; sec = seconds | ||
503 | */ | ||
504 | static int apm_get_info(char *buf, char **start, off_t fpos, int length) | ||
505 | { | ||
506 | struct apm_power_info info; | ||
507 | char *units; | ||
508 | int ret; | ||
509 | |||
510 | info.ac_line_status = 0xff; | ||
511 | info.battery_status = 0xff; | ||
512 | info.battery_flag = 0xff; | ||
513 | info.battery_life = -1; | ||
514 | info.time = -1; | ||
515 | info.units = -1; | ||
516 | |||
517 | if (apm_get_power_status) | ||
518 | apm_get_power_status(&info); | ||
519 | |||
520 | switch (info.units) { | ||
521 | default: units = "?"; break; | ||
522 | case 0: units = "min"; break; | ||
523 | case 1: units = "sec"; break; | ||
524 | } | ||
525 | |||
526 | ret = sprintf(buf, "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n", | ||
527 | driver_version, APM_32_BIT_SUPPORT, | ||
528 | info.ac_line_status, info.battery_status, | ||
529 | info.battery_flag, info.battery_life, | ||
530 | info.time, units); | ||
531 | |||
532 | return ret; | ||
533 | } | ||
534 | #endif | ||
535 | |||
536 | static int kapmd(void *arg) | ||
537 | { | ||
538 | do { | ||
539 | apm_event_t event; | ||
540 | int ret; | ||
541 | |||
542 | wait_event_interruptible(kapmd_wait, | ||
543 | !queue_empty(&kapmd_queue) || kthread_should_stop()); | ||
544 | |||
545 | if (kthread_should_stop()) | ||
546 | break; | ||
547 | |||
548 | spin_lock_irq(&kapmd_queue_lock); | ||
549 | event = 0; | ||
550 | if (!queue_empty(&kapmd_queue)) | ||
551 | event = queue_get_event(&kapmd_queue); | ||
552 | spin_unlock_irq(&kapmd_queue_lock); | ||
553 | |||
554 | switch (event) { | ||
555 | case 0: | ||
556 | break; | ||
557 | |||
558 | case APM_LOW_BATTERY: | ||
559 | case APM_POWER_STATUS_CHANGE: | ||
560 | queue_event(event); | ||
561 | break; | ||
562 | |||
563 | case APM_USER_SUSPEND: | ||
564 | case APM_SYS_SUSPEND: | ||
565 | ret = queue_suspend_event(event, NULL); | ||
566 | if (ret < 0) { | ||
567 | /* | ||
568 | * We were busy. Try again in 50ms. | ||
569 | */ | ||
570 | queue_add_event(&kapmd_queue, event); | ||
571 | msleep(50); | ||
572 | } | ||
573 | if (ret > 0) | ||
574 | apm_suspend(); | ||
575 | break; | ||
576 | |||
577 | case APM_CRITICAL_SUSPEND: | ||
578 | apm_suspend(); | ||
579 | break; | ||
580 | } | ||
581 | } while (1); | ||
582 | |||
583 | return 0; | ||
584 | } | ||
585 | |||
586 | static int __init apm_init(void) | ||
587 | { | ||
588 | int ret; | ||
589 | |||
590 | if (apm_disabled) { | ||
591 | printk(KERN_NOTICE "apm: disabled on user request.\n"); | ||
592 | return -ENODEV; | ||
593 | } | ||
594 | |||
595 | kapmd_tsk = kthread_create(kapmd, NULL, "kapmd"); | ||
596 | if (IS_ERR(kapmd_tsk)) { | ||
597 | ret = PTR_ERR(kapmd_tsk); | ||
598 | kapmd_tsk = NULL; | ||
599 | return ret; | ||
600 | } | ||
601 | kapmd_tsk->flags |= PF_NOFREEZE; | ||
602 | wake_up_process(kapmd_tsk); | ||
603 | |||
604 | #ifdef CONFIG_PROC_FS | ||
605 | create_proc_info_entry("apm", 0, NULL, apm_get_info); | ||
606 | #endif | ||
607 | |||
608 | ret = misc_register(&apm_device); | ||
609 | if (ret != 0) { | ||
610 | remove_proc_entry("apm", NULL); | ||
611 | kthread_stop(kapmd_tsk); | ||
612 | } | ||
613 | |||
614 | return ret; | ||
615 | } | ||
616 | |||
617 | static void __exit apm_exit(void) | ||
618 | { | ||
619 | misc_deregister(&apm_device); | ||
620 | remove_proc_entry("apm", NULL); | ||
621 | |||
622 | kthread_stop(kapmd_tsk); | ||
623 | } | ||
624 | |||
625 | module_init(apm_init); | ||
626 | module_exit(apm_exit); | ||
627 | |||
628 | MODULE_AUTHOR("Stephen Rothwell"); | ||
629 | MODULE_DESCRIPTION("Advanced Power Management"); | ||
630 | MODULE_LICENSE("GPL"); | ||
631 | |||
632 | #ifndef MODULE | ||
633 | static int __init apm_setup(char *str) | ||
634 | { | ||
635 | while ((str != NULL) && (*str != '\0')) { | ||
636 | if (strncmp(str, "off", 3) == 0) | ||
637 | apm_disabled = 1; | ||
638 | if (strncmp(str, "on", 2) == 0) | ||
639 | apm_disabled = 0; | ||
640 | str = strchr(str, ','); | ||
641 | if (str != NULL) | ||
642 | str += strspn(str, ", \t"); | ||
643 | } | ||
644 | return 1; | ||
645 | } | ||
646 | |||
647 | __setup("apm=", apm_setup); | ||
648 | #endif | ||
649 | |||
650 | /** | ||
651 | * apm_queue_event - queue an APM event for kapmd | ||
652 | * @event: APM event | ||
653 | * | ||
654 | * Queue an APM event for kapmd to process and ultimately take the | ||
655 | * appropriate action. Only a subset of events are handled: | ||
656 | * %APM_LOW_BATTERY | ||
657 | * %APM_POWER_STATUS_CHANGE | ||
658 | * %APM_USER_SUSPEND | ||
659 | * %APM_SYS_SUSPEND | ||
660 | * %APM_CRITICAL_SUSPEND | ||
661 | */ | ||
662 | void apm_queue_event(apm_event_t event) | ||
663 | { | ||
664 | unsigned long flags; | ||
665 | |||
666 | spin_lock_irqsave(&kapmd_queue_lock, flags); | ||
667 | queue_add_event(&kapmd_queue, event); | ||
668 | spin_unlock_irqrestore(&kapmd_queue_lock, flags); | ||
669 | |||
670 | wake_up_interruptible(&kapmd_wait); | ||
671 | } | ||
672 | EXPORT_SYMBOL(apm_queue_event); | ||
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 6dcdceb81203..85d99e21e188 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h | |||
@@ -532,11 +532,13 @@ typedef struct drm_mm_node { | |||
532 | int free; | 532 | int free; |
533 | unsigned long start; | 533 | unsigned long start; |
534 | unsigned long size; | 534 | unsigned long size; |
535 | struct drm_mm *mm; | ||
535 | void *private; | 536 | void *private; |
536 | } drm_mm_node_t; | 537 | } drm_mm_node_t; |
537 | 538 | ||
538 | typedef struct drm_mm { | 539 | typedef struct drm_mm { |
539 | drm_mm_node_t root_node; | 540 | struct list_head fl_entry; |
541 | struct list_head ml_entry; | ||
540 | } drm_mm_t; | 542 | } drm_mm_t; |
541 | 543 | ||
542 | /** | 544 | /** |
@@ -843,9 +845,6 @@ extern void drm_mem_init(void); | |||
843 | extern int drm_mem_info(char *buf, char **start, off_t offset, | 845 | extern int drm_mem_info(char *buf, char **start, off_t offset, |
844 | int request, int *eof, void *data); | 846 | int request, int *eof, void *data); |
845 | extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area); | 847 | extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area); |
846 | extern void *drm_ioremap(unsigned long offset, unsigned long size, | ||
847 | drm_device_t * dev); | ||
848 | extern void drm_ioremapfree(void *pt, unsigned long size, drm_device_t * dev); | ||
849 | 848 | ||
850 | extern DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type); | 849 | extern DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type); |
851 | extern int drm_free_agp(DRM_AGP_MEM * handle, int pages); | 850 | extern int drm_free_agp(DRM_AGP_MEM * handle, int pages); |
@@ -1053,33 +1052,18 @@ extern void drm_sysfs_device_remove(struct class_device *class_dev); | |||
1053 | extern drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent, | 1052 | extern drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent, |
1054 | unsigned long size, | 1053 | unsigned long size, |
1055 | unsigned alignment); | 1054 | unsigned alignment); |
1056 | extern void drm_mm_put_block(drm_mm_t *mm, drm_mm_node_t *cur); | 1055 | void drm_mm_put_block(drm_mm_node_t * cur); |
1057 | extern drm_mm_node_t *drm_mm_search_free(const drm_mm_t *mm, unsigned long size, | 1056 | extern drm_mm_node_t *drm_mm_search_free(const drm_mm_t *mm, unsigned long size, |
1058 | unsigned alignment, int best_match); | 1057 | unsigned alignment, int best_match); |
1059 | extern int drm_mm_init(drm_mm_t *mm, unsigned long start, unsigned long size); | 1058 | extern int drm_mm_init(drm_mm_t *mm, unsigned long start, unsigned long size); |
1060 | extern void drm_mm_takedown(drm_mm_t *mm); | 1059 | extern void drm_mm_takedown(drm_mm_t *mm); |
1060 | extern int drm_mm_clean(drm_mm_t *mm); | ||
1061 | extern unsigned long drm_mm_tail_space(drm_mm_t *mm); | ||
1062 | extern int drm_mm_remove_space_from_tail(drm_mm_t *mm, unsigned long size); | ||
1063 | extern int drm_mm_add_space_to_tail(drm_mm_t *mm, unsigned long size); | ||
1061 | 1064 | ||
1062 | /* Inline replacements for DRM_IOREMAP macros */ | 1065 | extern void drm_core_ioremap(struct drm_map *map, struct drm_device *dev); |
1063 | static __inline__ void drm_core_ioremap(struct drm_map *map, | 1066 | extern void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev); |
1064 | struct drm_device *dev) | ||
1065 | { | ||
1066 | map->handle = drm_ioremap(map->offset, map->size, dev); | ||
1067 | } | ||
1068 | |||
1069 | #if 0 | ||
1070 | static __inline__ void drm_core_ioremap_nocache(struct drm_map *map, | ||
1071 | struct drm_device *dev) | ||
1072 | { | ||
1073 | map->handle = drm_ioremap_nocache(map->offset, map->size, dev); | ||
1074 | } | ||
1075 | #endif /* 0 */ | ||
1076 | |||
1077 | static __inline__ void drm_core_ioremapfree(struct drm_map *map, | ||
1078 | struct drm_device *dev) | ||
1079 | { | ||
1080 | if (map->handle && map->size) | ||
1081 | drm_ioremapfree(map->handle, map->size, dev); | ||
1082 | } | ||
1083 | 1067 | ||
1084 | static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, | 1068 | static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, |
1085 | unsigned int token) | 1069 | unsigned int token) |
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index 9f65f5697ba8..a6828cc14e58 100644 --- a/drivers/char/drm/drm_bufs.c +++ b/drivers/char/drm/drm_bufs.c | |||
@@ -79,14 +79,14 @@ static int drm_map_handle(drm_device_t *dev, drm_hash_item_t *hash, | |||
79 | 79 | ||
80 | if (!use_hashed_handle) { | 80 | if (!use_hashed_handle) { |
81 | int ret; | 81 | int ret; |
82 | hash->key = user_token; | 82 | hash->key = user_token >> PAGE_SHIFT; |
83 | ret = drm_ht_insert_item(&dev->map_hash, hash); | 83 | ret = drm_ht_insert_item(&dev->map_hash, hash); |
84 | if (ret != -EINVAL) | 84 | if (ret != -EINVAL) |
85 | return ret; | 85 | return ret; |
86 | } | 86 | } |
87 | return drm_ht_just_insert_please(&dev->map_hash, hash, | 87 | return drm_ht_just_insert_please(&dev->map_hash, hash, |
88 | user_token, 32 - PAGE_SHIFT - 3, | 88 | user_token, 32 - PAGE_SHIFT - 3, |
89 | PAGE_SHIFT, DRM_MAP_HASH_OFFSET); | 89 | 0, DRM_MAP_HASH_OFFSET >> PAGE_SHIFT); |
90 | } | 90 | } |
91 | 91 | ||
92 | /** | 92 | /** |
@@ -178,11 +178,11 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, | |||
178 | } | 178 | } |
179 | } | 179 | } |
180 | if (map->type == _DRM_REGISTERS) | 180 | if (map->type == _DRM_REGISTERS) |
181 | map->handle = drm_ioremap(map->offset, map->size, dev); | 181 | map->handle = ioremap(map->offset, map->size); |
182 | break; | 182 | break; |
183 | 183 | ||
184 | case _DRM_SHM: | 184 | case _DRM_SHM: |
185 | map->handle = vmalloc_32(map->size); | 185 | map->handle = vmalloc_user(map->size); |
186 | DRM_DEBUG("%lu %d %p\n", | 186 | DRM_DEBUG("%lu %d %p\n", |
187 | map->size, drm_order(map->size), map->handle); | 187 | map->size, drm_order(map->size), map->handle); |
188 | if (!map->handle) { | 188 | if (!map->handle) { |
@@ -238,7 +238,7 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, | |||
238 | list = drm_alloc(sizeof(*list), DRM_MEM_MAPS); | 238 | list = drm_alloc(sizeof(*list), DRM_MEM_MAPS); |
239 | if (!list) { | 239 | if (!list) { |
240 | if (map->type == _DRM_REGISTERS) | 240 | if (map->type == _DRM_REGISTERS) |
241 | drm_ioremapfree(map->handle, map->size, dev); | 241 | iounmap(map->handle); |
242 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | 242 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); |
243 | return -EINVAL; | 243 | return -EINVAL; |
244 | } | 244 | } |
@@ -255,14 +255,14 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, | |||
255 | ret = drm_map_handle(dev, &list->hash, user_token, 0); | 255 | ret = drm_map_handle(dev, &list->hash, user_token, 0); |
256 | if (ret) { | 256 | if (ret) { |
257 | if (map->type == _DRM_REGISTERS) | 257 | if (map->type == _DRM_REGISTERS) |
258 | drm_ioremapfree(map->handle, map->size, dev); | 258 | iounmap(map->handle); |
259 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | 259 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); |
260 | drm_free(list, sizeof(*list), DRM_MEM_MAPS); | 260 | drm_free(list, sizeof(*list), DRM_MEM_MAPS); |
261 | mutex_unlock(&dev->struct_mutex); | 261 | mutex_unlock(&dev->struct_mutex); |
262 | return ret; | 262 | return ret; |
263 | } | 263 | } |
264 | 264 | ||
265 | list->user_token = list->hash.key; | 265 | list->user_token = list->hash.key << PAGE_SHIFT; |
266 | mutex_unlock(&dev->struct_mutex); | 266 | mutex_unlock(&dev->struct_mutex); |
267 | 267 | ||
268 | *maplist = list; | 268 | *maplist = list; |
@@ -347,7 +347,8 @@ int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map) | |||
347 | 347 | ||
348 | if (r_list->map == map) { | 348 | if (r_list->map == map) { |
349 | list_del(list); | 349 | list_del(list); |
350 | drm_ht_remove_key(&dev->map_hash, r_list->user_token); | 350 | drm_ht_remove_key(&dev->map_hash, |
351 | r_list->user_token >> PAGE_SHIFT); | ||
351 | drm_free(list, sizeof(*list), DRM_MEM_MAPS); | 352 | drm_free(list, sizeof(*list), DRM_MEM_MAPS); |
352 | break; | 353 | break; |
353 | } | 354 | } |
@@ -362,7 +363,7 @@ int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map) | |||
362 | 363 | ||
363 | switch (map->type) { | 364 | switch (map->type) { |
364 | case _DRM_REGISTERS: | 365 | case _DRM_REGISTERS: |
365 | drm_ioremapfree(map->handle, map->size, dev); | 366 | iounmap(map->handle); |
366 | /* FALLTHROUGH */ | 367 | /* FALLTHROUGH */ |
367 | case _DRM_FRAME_BUFFER: | 368 | case _DRM_FRAME_BUFFER: |
368 | if (drm_core_has_MTRR(dev) && map->mtrr >= 0) { | 369 | if (drm_core_has_MTRR(dev) && map->mtrr >= 0) { |
diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c index 5681cae1d404..92a867082376 100644 --- a/drivers/char/drm/drm_memory.c +++ b/drivers/char/drm/drm_memory.c | |||
@@ -79,28 +79,6 @@ void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area) | |||
79 | } | 79 | } |
80 | 80 | ||
81 | #if __OS_HAS_AGP | 81 | #if __OS_HAS_AGP |
82 | /* | ||
83 | * Find the drm_map that covers the range [offset, offset+size). | ||
84 | */ | ||
85 | static drm_map_t *drm_lookup_map(unsigned long offset, | ||
86 | unsigned long size, drm_device_t * dev) | ||
87 | { | ||
88 | struct list_head *list; | ||
89 | drm_map_list_t *r_list; | ||
90 | drm_map_t *map; | ||
91 | |||
92 | list_for_each(list, &dev->maplist->head) { | ||
93 | r_list = (drm_map_list_t *) list; | ||
94 | map = r_list->map; | ||
95 | if (!map) | ||
96 | continue; | ||
97 | if (map->offset <= offset | ||
98 | && (offset + size) <= (map->offset + map->size)) | ||
99 | return map; | ||
100 | } | ||
101 | return NULL; | ||
102 | } | ||
103 | |||
104 | static void *agp_remap(unsigned long offset, unsigned long size, | 82 | static void *agp_remap(unsigned long offset, unsigned long size, |
105 | drm_device_t * dev) | 83 | drm_device_t * dev) |
106 | { | 84 | { |
@@ -169,13 +147,6 @@ int drm_unbind_agp(DRM_AGP_MEM * handle) | |||
169 | } | 147 | } |
170 | 148 | ||
171 | #else /* __OS_HAS_AGP */ | 149 | #else /* __OS_HAS_AGP */ |
172 | |||
173 | static inline drm_map_t *drm_lookup_map(unsigned long offset, | ||
174 | unsigned long size, drm_device_t * dev) | ||
175 | { | ||
176 | return NULL; | ||
177 | } | ||
178 | |||
179 | static inline void *agp_remap(unsigned long offset, unsigned long size, | 150 | static inline void *agp_remap(unsigned long offset, unsigned long size, |
180 | drm_device_t * dev) | 151 | drm_device_t * dev) |
181 | { | 152 | { |
@@ -184,57 +155,28 @@ static inline void *agp_remap(unsigned long offset, unsigned long size, | |||
184 | 155 | ||
185 | #endif /* agp */ | 156 | #endif /* agp */ |
186 | 157 | ||
187 | void *drm_ioremap(unsigned long offset, unsigned long size, | 158 | #endif /* debug_memory */ |
188 | drm_device_t * dev) | ||
189 | { | ||
190 | if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) { | ||
191 | drm_map_t *map = drm_lookup_map(offset, size, dev); | ||
192 | |||
193 | if (map && map->type == _DRM_AGP) | ||
194 | return agp_remap(offset, size, dev); | ||
195 | } | ||
196 | return ioremap(offset, size); | ||
197 | } | ||
198 | EXPORT_SYMBOL(drm_ioremap); | ||
199 | 159 | ||
200 | #if 0 | 160 | void drm_core_ioremap(struct drm_map *map, struct drm_device *dev) |
201 | void *drm_ioremap_nocache(unsigned long offset, | ||
202 | unsigned long size, drm_device_t * dev) | ||
203 | { | 161 | { |
204 | if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) { | 162 | if (drm_core_has_AGP(dev) && |
205 | drm_map_t *map = drm_lookup_map(offset, size, dev); | 163 | dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP) |
206 | 164 | map->handle = agp_remap(map->offset, map->size, dev); | |
207 | if (map && map->type == _DRM_AGP) | 165 | else |
208 | return agp_remap(offset, size, dev); | 166 | map->handle = ioremap(map->offset, map->size); |
209 | } | ||
210 | return ioremap_nocache(offset, size); | ||
211 | } | 167 | } |
212 | #endif /* 0 */ | 168 | EXPORT_SYMBOL(drm_core_ioremap); |
213 | 169 | ||
214 | void drm_ioremapfree(void *pt, unsigned long size, | 170 | void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev) |
215 | drm_device_t * dev) | ||
216 | { | 171 | { |
217 | /* | 172 | if (!map->handle || !map->size) |
218 | * This is a bit ugly. It would be much cleaner if the DRM API would use separate | 173 | return; |
219 | * routines for handling mappings in the AGP space. Hopefully this can be done in | 174 | |
220 | * a future revision of the interface... | 175 | if (drm_core_has_AGP(dev) && |
221 | */ | 176 | dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP) |
222 | if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture | 177 | vunmap(map->handle); |
223 | && ((unsigned long)pt >= VMALLOC_START | 178 | else |
224 | && (unsigned long)pt < VMALLOC_END)) { | 179 | iounmap(map->handle); |
225 | unsigned long offset; | ||
226 | drm_map_t *map; | ||
227 | |||
228 | offset = drm_follow_page(pt) | ((unsigned long)pt & ~PAGE_MASK); | ||
229 | map = drm_lookup_map(offset, size, dev); | ||
230 | if (map && map->type == _DRM_AGP) { | ||
231 | vunmap(pt); | ||
232 | return; | ||
233 | } | ||
234 | } | ||
235 | |||
236 | iounmap(pt); | ||
237 | } | 180 | } |
238 | EXPORT_SYMBOL(drm_ioremapfree); | 181 | EXPORT_SYMBOL(drm_core_ioremapfree); |
239 | 182 | ||
240 | #endif /* debug_memory */ | ||
diff --git a/drivers/char/drm/drm_memory.h b/drivers/char/drm/drm_memory.h index f1b97aff10cf..63e425b5ea82 100644 --- a/drivers/char/drm/drm_memory.h +++ b/drivers/char/drm/drm_memory.h | |||
@@ -56,26 +56,6 @@ | |||
56 | # endif | 56 | # endif |
57 | #endif | 57 | #endif |
58 | 58 | ||
59 | static inline unsigned long drm_follow_page(void *vaddr) | ||
60 | { | ||
61 | pgd_t *pgd = pgd_offset_k((unsigned long)vaddr); | ||
62 | pud_t *pud = pud_offset(pgd, (unsigned long)vaddr); | ||
63 | pmd_t *pmd = pmd_offset(pud, (unsigned long)vaddr); | ||
64 | pte_t *ptep = pte_offset_kernel(pmd, (unsigned long)vaddr); | ||
65 | return pte_pfn(*ptep) << PAGE_SHIFT; | ||
66 | } | ||
67 | |||
68 | #else /* __OS_HAS_AGP */ | 59 | #else /* __OS_HAS_AGP */ |
69 | 60 | ||
70 | static inline unsigned long drm_follow_page(void *vaddr) | ||
71 | { | ||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | #endif | 61 | #endif |
76 | |||
77 | void *drm_ioremap(unsigned long offset, unsigned long size, | ||
78 | drm_device_t * dev); | ||
79 | |||
80 | void drm_ioremapfree(void *pt, unsigned long size, | ||
81 | drm_device_t * dev); | ||
diff --git a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h index 74581af806e1..6463271deea8 100644 --- a/drivers/char/drm/drm_memory_debug.h +++ b/drivers/char/drm/drm_memory_debug.h | |||
@@ -205,76 +205,6 @@ void drm_free (void *pt, size_t size, int area) { | |||
205 | } | 205 | } |
206 | } | 206 | } |
207 | 207 | ||
208 | void *drm_ioremap (unsigned long offset, unsigned long size, | ||
209 | drm_device_t * dev) { | ||
210 | void *pt; | ||
211 | |||
212 | if (!size) { | ||
213 | DRM_MEM_ERROR(DRM_MEM_MAPPINGS, | ||
214 | "Mapping 0 bytes at 0x%08lx\n", offset); | ||
215 | return NULL; | ||
216 | } | ||
217 | |||
218 | if (!(pt = drm_ioremap(offset, size, dev))) { | ||
219 | spin_lock(&drm_mem_lock); | ||
220 | ++drm_mem_stats[DRM_MEM_MAPPINGS].fail_count; | ||
221 | spin_unlock(&drm_mem_lock); | ||
222 | return NULL; | ||
223 | } | ||
224 | spin_lock(&drm_mem_lock); | ||
225 | ++drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count; | ||
226 | drm_mem_stats[DRM_MEM_MAPPINGS].bytes_allocated += size; | ||
227 | spin_unlock(&drm_mem_lock); | ||
228 | return pt; | ||
229 | } | ||
230 | |||
231 | #if 0 | ||
232 | void *drm_ioremap_nocache (unsigned long offset, unsigned long size, | ||
233 | drm_device_t * dev) { | ||
234 | void *pt; | ||
235 | |||
236 | if (!size) { | ||
237 | DRM_MEM_ERROR(DRM_MEM_MAPPINGS, | ||
238 | "Mapping 0 bytes at 0x%08lx\n", offset); | ||
239 | return NULL; | ||
240 | } | ||
241 | |||
242 | if (!(pt = drm_ioremap_nocache(offset, size, dev))) { | ||
243 | spin_lock(&drm_mem_lock); | ||
244 | ++drm_mem_stats[DRM_MEM_MAPPINGS].fail_count; | ||
245 | spin_unlock(&drm_mem_lock); | ||
246 | return NULL; | ||
247 | } | ||
248 | spin_lock(&drm_mem_lock); | ||
249 | ++drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count; | ||
250 | drm_mem_stats[DRM_MEM_MAPPINGS].bytes_allocated += size; | ||
251 | spin_unlock(&drm_mem_lock); | ||
252 | return pt; | ||
253 | } | ||
254 | #endif /* 0 */ | ||
255 | |||
256 | void drm_ioremapfree (void *pt, unsigned long size, drm_device_t * dev) { | ||
257 | int alloc_count; | ||
258 | int free_count; | ||
259 | |||
260 | if (!pt) | ||
261 | DRM_MEM_ERROR(DRM_MEM_MAPPINGS, | ||
262 | "Attempt to free NULL pointer\n"); | ||
263 | else | ||
264 | drm_ioremapfree(pt, size, dev); | ||
265 | |||
266 | spin_lock(&drm_mem_lock); | ||
267 | drm_mem_stats[DRM_MEM_MAPPINGS].bytes_freed += size; | ||
268 | free_count = ++drm_mem_stats[DRM_MEM_MAPPINGS].free_count; | ||
269 | alloc_count = drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count; | ||
270 | spin_unlock(&drm_mem_lock); | ||
271 | if (free_count > alloc_count) { | ||
272 | DRM_MEM_ERROR(DRM_MEM_MAPPINGS, | ||
273 | "Excess frees: %d frees, %d allocs\n", | ||
274 | free_count, alloc_count); | ||
275 | } | ||
276 | } | ||
277 | |||
278 | #if __OS_HAS_AGP | 208 | #if __OS_HAS_AGP |
279 | 209 | ||
280 | DRM_AGP_MEM *drm_alloc_agp (drm_device_t *dev, int pages, u32 type) { | 210 | DRM_AGP_MEM *drm_alloc_agp (drm_device_t *dev, int pages, u32 type) { |
diff --git a/drivers/char/drm/drm_mm.c b/drivers/char/drm/drm_mm.c index 617526bd5b0c..9b46b85027d0 100644 --- a/drivers/char/drm/drm_mm.c +++ b/drivers/char/drm/drm_mm.c | |||
@@ -42,36 +42,131 @@ | |||
42 | */ | 42 | */ |
43 | 43 | ||
44 | #include "drmP.h" | 44 | #include "drmP.h" |
45 | #include <linux/slab.h> | ||
46 | |||
47 | unsigned long drm_mm_tail_space(drm_mm_t *mm) | ||
48 | { | ||
49 | struct list_head *tail_node; | ||
50 | drm_mm_node_t *entry; | ||
51 | |||
52 | tail_node = mm->ml_entry.prev; | ||
53 | entry = list_entry(tail_node, drm_mm_node_t, ml_entry); | ||
54 | if (!entry->free) | ||
55 | return 0; | ||
56 | |||
57 | return entry->size; | ||
58 | } | ||
59 | |||
60 | int drm_mm_remove_space_from_tail(drm_mm_t *mm, unsigned long size) | ||
61 | { | ||
62 | struct list_head *tail_node; | ||
63 | drm_mm_node_t *entry; | ||
64 | |||
65 | tail_node = mm->ml_entry.prev; | ||
66 | entry = list_entry(tail_node, drm_mm_node_t, ml_entry); | ||
67 | if (!entry->free) | ||
68 | return -ENOMEM; | ||
69 | |||
70 | if (entry->size <= size) | ||
71 | return -ENOMEM; | ||
72 | |||
73 | entry->size -= size; | ||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | |||
78 | static int drm_mm_create_tail_node(drm_mm_t *mm, | ||
79 | unsigned long start, | ||
80 | unsigned long size) | ||
81 | { | ||
82 | drm_mm_node_t *child; | ||
83 | |||
84 | child = (drm_mm_node_t *) | ||
85 | drm_alloc(sizeof(*child), DRM_MEM_MM); | ||
86 | if (!child) | ||
87 | return -ENOMEM; | ||
88 | |||
89 | child->free = 1; | ||
90 | child->size = size; | ||
91 | child->start = start; | ||
92 | child->mm = mm; | ||
93 | |||
94 | list_add_tail(&child->ml_entry, &mm->ml_entry); | ||
95 | list_add_tail(&child->fl_entry, &mm->fl_entry); | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | |||
101 | int drm_mm_add_space_to_tail(drm_mm_t *mm, unsigned long size) | ||
102 | { | ||
103 | struct list_head *tail_node; | ||
104 | drm_mm_node_t *entry; | ||
105 | |||
106 | tail_node = mm->ml_entry.prev; | ||
107 | entry = list_entry(tail_node, drm_mm_node_t, ml_entry); | ||
108 | if (!entry->free) { | ||
109 | return drm_mm_create_tail_node(mm, entry->start + entry->size, size); | ||
110 | } | ||
111 | entry->size += size; | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static drm_mm_node_t *drm_mm_split_at_start(drm_mm_node_t *parent, | ||
116 | unsigned long size) | ||
117 | { | ||
118 | drm_mm_node_t *child; | ||
119 | |||
120 | child = (drm_mm_node_t *) | ||
121 | drm_alloc(sizeof(*child), DRM_MEM_MM); | ||
122 | if (!child) | ||
123 | return NULL; | ||
124 | |||
125 | INIT_LIST_HEAD(&child->fl_entry); | ||
126 | |||
127 | child->free = 0; | ||
128 | child->size = size; | ||
129 | child->start = parent->start; | ||
130 | child->mm = parent->mm; | ||
131 | |||
132 | list_add_tail(&child->ml_entry, &parent->ml_entry); | ||
133 | INIT_LIST_HEAD(&child->fl_entry); | ||
134 | |||
135 | parent->size -= size; | ||
136 | parent->start += size; | ||
137 | return child; | ||
138 | } | ||
139 | |||
140 | |||
45 | 141 | ||
46 | drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent, | 142 | drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent, |
47 | unsigned long size, unsigned alignment) | 143 | unsigned long size, unsigned alignment) |
48 | { | 144 | { |
49 | 145 | ||
146 | drm_mm_node_t *align_splitoff = NULL; | ||
50 | drm_mm_node_t *child; | 147 | drm_mm_node_t *child; |
148 | unsigned tmp = 0; | ||
51 | 149 | ||
52 | if (alignment) | 150 | if (alignment) |
53 | size += alignment - 1; | 151 | tmp = parent->start % alignment; |
152 | |||
153 | if (tmp) { | ||
154 | align_splitoff = drm_mm_split_at_start(parent, alignment - tmp); | ||
155 | if (!align_splitoff) | ||
156 | return NULL; | ||
157 | } | ||
54 | 158 | ||
55 | if (parent->size == size) { | 159 | if (parent->size == size) { |
56 | list_del_init(&parent->fl_entry); | 160 | list_del_init(&parent->fl_entry); |
57 | parent->free = 0; | 161 | parent->free = 0; |
58 | return parent; | 162 | return parent; |
59 | } else { | 163 | } else { |
60 | child = (drm_mm_node_t *) drm_alloc(sizeof(*child), DRM_MEM_MM); | 164 | child = drm_mm_split_at_start(parent, size); |
61 | if (!child) | 165 | } |
62 | return NULL; | ||
63 | |||
64 | INIT_LIST_HEAD(&child->ml_entry); | ||
65 | INIT_LIST_HEAD(&child->fl_entry); | ||
66 | 166 | ||
67 | child->free = 0; | 167 | if (align_splitoff) |
68 | child->size = size; | 168 | drm_mm_put_block(align_splitoff); |
69 | child->start = parent->start; | ||
70 | 169 | ||
71 | list_add_tail(&child->ml_entry, &parent->ml_entry); | ||
72 | parent->size -= size; | ||
73 | parent->start += size; | ||
74 | } | ||
75 | return child; | 170 | return child; |
76 | } | 171 | } |
77 | 172 | ||
@@ -80,12 +175,12 @@ drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent, | |||
80 | * Otherwise add to the free stack. | 175 | * Otherwise add to the free stack. |
81 | */ | 176 | */ |
82 | 177 | ||
83 | void drm_mm_put_block(drm_mm_t * mm, drm_mm_node_t * cur) | 178 | void drm_mm_put_block(drm_mm_node_t * cur) |
84 | { | 179 | { |
85 | 180 | ||
86 | drm_mm_node_t *list_root = &mm->root_node; | 181 | drm_mm_t *mm = cur->mm; |
87 | struct list_head *cur_head = &cur->ml_entry; | 182 | struct list_head *cur_head = &cur->ml_entry; |
88 | struct list_head *root_head = &list_root->ml_entry; | 183 | struct list_head *root_head = &mm->ml_entry; |
89 | drm_mm_node_t *prev_node = NULL; | 184 | drm_mm_node_t *prev_node = NULL; |
90 | drm_mm_node_t *next_node; | 185 | drm_mm_node_t *next_node; |
91 | 186 | ||
@@ -116,7 +211,7 @@ void drm_mm_put_block(drm_mm_t * mm, drm_mm_node_t * cur) | |||
116 | } | 211 | } |
117 | if (!merged) { | 212 | if (!merged) { |
118 | cur->free = 1; | 213 | cur->free = 1; |
119 | list_add(&cur->fl_entry, &list_root->fl_entry); | 214 | list_add(&cur->fl_entry, &mm->fl_entry); |
120 | } else { | 215 | } else { |
121 | list_del(&cur->ml_entry); | 216 | list_del(&cur->ml_entry); |
122 | drm_free(cur, sizeof(*cur), DRM_MEM_MM); | 217 | drm_free(cur, sizeof(*cur), DRM_MEM_MM); |
@@ -128,20 +223,30 @@ drm_mm_node_t *drm_mm_search_free(const drm_mm_t * mm, | |||
128 | unsigned alignment, int best_match) | 223 | unsigned alignment, int best_match) |
129 | { | 224 | { |
130 | struct list_head *list; | 225 | struct list_head *list; |
131 | const struct list_head *free_stack = &mm->root_node.fl_entry; | 226 | const struct list_head *free_stack = &mm->fl_entry; |
132 | drm_mm_node_t *entry; | 227 | drm_mm_node_t *entry; |
133 | drm_mm_node_t *best; | 228 | drm_mm_node_t *best; |
134 | unsigned long best_size; | 229 | unsigned long best_size; |
230 | unsigned wasted; | ||
135 | 231 | ||
136 | best = NULL; | 232 | best = NULL; |
137 | best_size = ~0UL; | 233 | best_size = ~0UL; |
138 | 234 | ||
139 | if (alignment) | ||
140 | size += alignment - 1; | ||
141 | |||
142 | list_for_each(list, free_stack) { | 235 | list_for_each(list, free_stack) { |
143 | entry = list_entry(list, drm_mm_node_t, fl_entry); | 236 | entry = list_entry(list, drm_mm_node_t, fl_entry); |
144 | if (entry->size >= size) { | 237 | wasted = 0; |
238 | |||
239 | if (entry->size < size) | ||
240 | continue; | ||
241 | |||
242 | if (alignment) { | ||
243 | register unsigned tmp = entry->start % alignment; | ||
244 | if (tmp) | ||
245 | wasted += alignment - tmp; | ||
246 | } | ||
247 | |||
248 | |||
249 | if (entry->size >= size + wasted) { | ||
145 | if (!best_match) | 250 | if (!best_match) |
146 | return entry; | 251 | return entry; |
147 | if (size < best_size) { | 252 | if (size < best_size) { |
@@ -154,40 +259,32 @@ drm_mm_node_t *drm_mm_search_free(const drm_mm_t * mm, | |||
154 | return best; | 259 | return best; |
155 | } | 260 | } |
156 | 261 | ||
157 | int drm_mm_init(drm_mm_t * mm, unsigned long start, unsigned long size) | 262 | int drm_mm_clean(drm_mm_t * mm) |
158 | { | 263 | { |
159 | drm_mm_node_t *child; | 264 | struct list_head *head = &mm->ml_entry; |
160 | |||
161 | INIT_LIST_HEAD(&mm->root_node.ml_entry); | ||
162 | INIT_LIST_HEAD(&mm->root_node.fl_entry); | ||
163 | child = (drm_mm_node_t *) drm_alloc(sizeof(*child), DRM_MEM_MM); | ||
164 | if (!child) | ||
165 | return -ENOMEM; | ||
166 | |||
167 | INIT_LIST_HEAD(&child->ml_entry); | ||
168 | INIT_LIST_HEAD(&child->fl_entry); | ||
169 | 265 | ||
170 | child->start = start; | 266 | return (head->next->next == head); |
171 | child->size = size; | 267 | } |
172 | child->free = 1; | ||
173 | 268 | ||
174 | list_add(&child->fl_entry, &mm->root_node.fl_entry); | 269 | int drm_mm_init(drm_mm_t * mm, unsigned long start, unsigned long size) |
175 | list_add(&child->ml_entry, &mm->root_node.ml_entry); | 270 | { |
271 | INIT_LIST_HEAD(&mm->ml_entry); | ||
272 | INIT_LIST_HEAD(&mm->fl_entry); | ||
176 | 273 | ||
177 | return 0; | 274 | return drm_mm_create_tail_node(mm, start, size); |
178 | } | 275 | } |
179 | 276 | ||
180 | EXPORT_SYMBOL(drm_mm_init); | 277 | EXPORT_SYMBOL(drm_mm_init); |
181 | 278 | ||
182 | void drm_mm_takedown(drm_mm_t * mm) | 279 | void drm_mm_takedown(drm_mm_t * mm) |
183 | { | 280 | { |
184 | struct list_head *bnode = mm->root_node.fl_entry.next; | 281 | struct list_head *bnode = mm->fl_entry.next; |
185 | drm_mm_node_t *entry; | 282 | drm_mm_node_t *entry; |
186 | 283 | ||
187 | entry = list_entry(bnode, drm_mm_node_t, fl_entry); | 284 | entry = list_entry(bnode, drm_mm_node_t, fl_entry); |
188 | 285 | ||
189 | if (entry->ml_entry.next != &mm->root_node.ml_entry || | 286 | if (entry->ml_entry.next != &mm->ml_entry || |
190 | entry->fl_entry.next != &mm->root_node.fl_entry) { | 287 | entry->fl_entry.next != &mm->fl_entry) { |
191 | DRM_ERROR("Memory manager not clean. Delaying takedown\n"); | 288 | DRM_ERROR("Memory manager not clean. Delaying takedown\n"); |
192 | return; | 289 | return; |
193 | } | 290 | } |
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h index 09398d5fbd3f..ad54b845978b 100644 --- a/drivers/char/drm/drm_pciids.h +++ b/drivers/char/drm/drm_pciids.h | |||
@@ -226,12 +226,14 @@ | |||
226 | {0x1106, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 226 | {0x1106, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
227 | {0x1106, 0x3118, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_PRO_GROUP_A}, \ | 227 | {0x1106, 0x3118, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_PRO_GROUP_A}, \ |
228 | {0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 228 | {0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
229 | {0x1106, 0x7204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
229 | {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 230 | {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
230 | {0x1106, 0x3108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 231 | {0x1106, 0x3108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
231 | {0x1106, 0x3304, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 232 | {0x1106, 0x3304, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
232 | {0x1106, 0x3157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 233 | {0x1106, 0x3157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
233 | {0x1106, 0x3344, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 234 | {0x1106, 0x3344, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
234 | {0x1106, 0x7204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 235 | {0x1106, 0x3343, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
236 | {0x1106, 0x3230, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_DX9_0}, \ | ||
235 | {0, 0, 0} | 237 | {0, 0, 0} |
236 | 238 | ||
237 | #define i810_PCI_IDS \ | 239 | #define i810_PCI_IDS \ |
diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c index 62d5fe15f046..7fd0da712142 100644 --- a/drivers/char/drm/drm_proc.c +++ b/drivers/char/drm/drm_proc.c | |||
@@ -500,7 +500,7 @@ static int drm__vma_info(char *buf, char **start, off_t offset, int request, | |||
500 | for (pt = dev->vmalist; pt; pt = pt->next) { | 500 | for (pt = dev->vmalist; pt; pt = pt->next) { |
501 | if (!(vma = pt->vma)) | 501 | if (!(vma = pt->vma)) |
502 | continue; | 502 | continue; |
503 | DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx", | 503 | DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx000", |
504 | pt->pid, | 504 | pt->pid, |
505 | vma->vm_start, | 505 | vma->vm_start, |
506 | vma->vm_end, | 506 | vma->vm_end, |
@@ -510,7 +510,7 @@ static int drm__vma_info(char *buf, char **start, off_t offset, int request, | |||
510 | vma->vm_flags & VM_MAYSHARE ? 's' : 'p', | 510 | vma->vm_flags & VM_MAYSHARE ? 's' : 'p', |
511 | vma->vm_flags & VM_LOCKED ? 'l' : '-', | 511 | vma->vm_flags & VM_LOCKED ? 'l' : '-', |
512 | vma->vm_flags & VM_IO ? 'i' : '-', | 512 | vma->vm_flags & VM_IO ? 'i' : '-', |
513 | vma->vm_pgoff << PAGE_SHIFT); | 513 | vma->vm_pgoff); |
514 | 514 | ||
515 | #if defined(__i386__) | 515 | #if defined(__i386__) |
516 | pgprot = pgprot_val(vma->vm_page_prot); | 516 | pgprot = pgprot_val(vma->vm_page_prot); |
diff --git a/drivers/char/drm/drm_sman.c b/drivers/char/drm/drm_sman.c index 19c81d2e13d0..e15db6d6bea9 100644 --- a/drivers/char/drm/drm_sman.c +++ b/drivers/char/drm/drm_sman.c | |||
@@ -101,10 +101,9 @@ static void *drm_sman_mm_allocate(void *private, unsigned long size, | |||
101 | 101 | ||
102 | static void drm_sman_mm_free(void *private, void *ref) | 102 | static void drm_sman_mm_free(void *private, void *ref) |
103 | { | 103 | { |
104 | drm_mm_t *mm = (drm_mm_t *) private; | ||
105 | drm_mm_node_t *node = (drm_mm_node_t *) ref; | 104 | drm_mm_node_t *node = (drm_mm_node_t *) ref; |
106 | 105 | ||
107 | drm_mm_put_block(mm, node); | 106 | drm_mm_put_block(node); |
108 | } | 107 | } |
109 | 108 | ||
110 | static void drm_sman_mm_destroy(void *private) | 109 | static void drm_sman_mm_destroy(void *private) |
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c index b9cfc077f6bc..54a632848955 100644 --- a/drivers/char/drm/drm_vm.c +++ b/drivers/char/drm/drm_vm.c | |||
@@ -70,7 +70,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, | |||
70 | if (!dev->agp || !dev->agp->cant_use_aperture) | 70 | if (!dev->agp || !dev->agp->cant_use_aperture) |
71 | goto vm_nopage_error; | 71 | goto vm_nopage_error; |
72 | 72 | ||
73 | if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff << PAGE_SHIFT, &hash)) | 73 | if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash)) |
74 | goto vm_nopage_error; | 74 | goto vm_nopage_error; |
75 | 75 | ||
76 | r_list = drm_hash_entry(hash, drm_map_list_t, hash); | 76 | r_list = drm_hash_entry(hash, drm_map_list_t, hash); |
@@ -227,7 +227,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma) | |||
227 | map->size); | 227 | map->size); |
228 | DRM_DEBUG("mtrr_del = %d\n", retcode); | 228 | DRM_DEBUG("mtrr_del = %d\n", retcode); |
229 | } | 229 | } |
230 | drm_ioremapfree(map->handle, map->size, dev); | 230 | iounmap(map->handle); |
231 | break; | 231 | break; |
232 | case _DRM_SHM: | 232 | case _DRM_SHM: |
233 | vfree(map->handle); | 233 | vfree(map->handle); |
@@ -463,8 +463,8 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) | |||
463 | lock_kernel(); | 463 | lock_kernel(); |
464 | dev = priv->head->dev; | 464 | dev = priv->head->dev; |
465 | dma = dev->dma; | 465 | dma = dev->dma; |
466 | DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", | 466 | DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n", |
467 | vma->vm_start, vma->vm_end, vma->vm_pgoff << PAGE_SHIFT); | 467 | vma->vm_start, vma->vm_end, vma->vm_pgoff); |
468 | 468 | ||
469 | /* Length must match exact page count */ | 469 | /* Length must match exact page count */ |
470 | if (!dma || (length >> PAGE_SHIFT) != dma->page_count) { | 470 | if (!dma || (length >> PAGE_SHIFT) != dma->page_count) { |
@@ -537,8 +537,8 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
537 | unsigned long offset = 0; | 537 | unsigned long offset = 0; |
538 | drm_hash_item_t *hash; | 538 | drm_hash_item_t *hash; |
539 | 539 | ||
540 | DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", | 540 | DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n", |
541 | vma->vm_start, vma->vm_end, vma->vm_pgoff << PAGE_SHIFT); | 541 | vma->vm_start, vma->vm_end, vma->vm_pgoff); |
542 | 542 | ||
543 | if (!priv->authenticated) | 543 | if (!priv->authenticated) |
544 | return -EACCES; | 544 | return -EACCES; |
@@ -547,7 +547,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
547 | * the AGP mapped at physical address 0 | 547 | * the AGP mapped at physical address 0 |
548 | * --BenH. | 548 | * --BenH. |
549 | */ | 549 | */ |
550 | if (!(vma->vm_pgoff << PAGE_SHIFT) | 550 | if (!vma->vm_pgoff |
551 | #if __OS_HAS_AGP | 551 | #if __OS_HAS_AGP |
552 | && (!dev->agp | 552 | && (!dev->agp |
553 | || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE) | 553 | || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE) |
@@ -555,7 +555,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
555 | ) | 555 | ) |
556 | return drm_mmap_dma(filp, vma); | 556 | return drm_mmap_dma(filp, vma); |
557 | 557 | ||
558 | if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff << PAGE_SHIFT, &hash)) { | 558 | if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash)) { |
559 | DRM_ERROR("Could not find map\n"); | 559 | DRM_ERROR("Could not find map\n"); |
560 | return -EINVAL; | 560 | return -EINVAL; |
561 | } | 561 | } |
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c index fa2de70f7401..60cb4e45a75e 100644 --- a/drivers/char/drm/i810_dma.c +++ b/drivers/char/drm/i810_dma.c | |||
@@ -219,8 +219,7 @@ static int i810_dma_cleanup(drm_device_t * dev) | |||
219 | (drm_i810_private_t *) dev->dev_private; | 219 | (drm_i810_private_t *) dev->dev_private; |
220 | 220 | ||
221 | if (dev_priv->ring.virtual_start) { | 221 | if (dev_priv->ring.virtual_start) { |
222 | drm_ioremapfree((void *)dev_priv->ring.virtual_start, | 222 | drm_core_ioremapfree(&dev_priv->ring.map, dev); |
223 | dev_priv->ring.Size, dev); | ||
224 | } | 223 | } |
225 | if (dev_priv->hw_status_page) { | 224 | if (dev_priv->hw_status_page) { |
226 | pci_free_consistent(dev->pdev, PAGE_SIZE, | 225 | pci_free_consistent(dev->pdev, PAGE_SIZE, |
@@ -236,9 +235,9 @@ static int i810_dma_cleanup(drm_device_t * dev) | |||
236 | for (i = 0; i < dma->buf_count; i++) { | 235 | for (i = 0; i < dma->buf_count; i++) { |
237 | drm_buf_t *buf = dma->buflist[i]; | 236 | drm_buf_t *buf = dma->buflist[i]; |
238 | drm_i810_buf_priv_t *buf_priv = buf->dev_private; | 237 | drm_i810_buf_priv_t *buf_priv = buf->dev_private; |
238 | |||
239 | if (buf_priv->kernel_virtual && buf->total) | 239 | if (buf_priv->kernel_virtual && buf->total) |
240 | drm_ioremapfree(buf_priv->kernel_virtual, | 240 | drm_core_ioremapfree(&buf_priv->map, dev); |
241 | buf->total, dev); | ||
242 | } | 241 | } |
243 | } | 242 | } |
244 | return 0; | 243 | return 0; |
@@ -311,8 +310,15 @@ static int i810_freelist_init(drm_device_t * dev, drm_i810_private_t * dev_priv) | |||
311 | 310 | ||
312 | *buf_priv->in_use = I810_BUF_FREE; | 311 | *buf_priv->in_use = I810_BUF_FREE; |
313 | 312 | ||
314 | buf_priv->kernel_virtual = drm_ioremap(buf->bus_address, | 313 | buf_priv->map.offset = buf->bus_address; |
315 | buf->total, dev); | 314 | buf_priv->map.size = buf->total; |
315 | buf_priv->map.type = _DRM_AGP; | ||
316 | buf_priv->map.flags = 0; | ||
317 | buf_priv->map.mtrr = 0; | ||
318 | |||
319 | drm_core_ioremap(&buf_priv->map, dev); | ||
320 | buf_priv->kernel_virtual = buf_priv->map.handle; | ||
321 | |||
316 | } | 322 | } |
317 | return 0; | 323 | return 0; |
318 | } | 324 | } |
@@ -363,18 +369,24 @@ static int i810_dma_initialize(drm_device_t * dev, | |||
363 | dev_priv->ring.End = init->ring_end; | 369 | dev_priv->ring.End = init->ring_end; |
364 | dev_priv->ring.Size = init->ring_size; | 370 | dev_priv->ring.Size = init->ring_size; |
365 | 371 | ||
366 | dev_priv->ring.virtual_start = drm_ioremap(dev->agp->base + | 372 | dev_priv->ring.map.offset = dev->agp->base + init->ring_start; |
367 | init->ring_start, | 373 | dev_priv->ring.map.size = init->ring_size; |
368 | init->ring_size, dev); | 374 | dev_priv->ring.map.type = _DRM_AGP; |
375 | dev_priv->ring.map.flags = 0; | ||
376 | dev_priv->ring.map.mtrr = 0; | ||
369 | 377 | ||
370 | if (dev_priv->ring.virtual_start == NULL) { | 378 | drm_core_ioremap(&dev_priv->ring.map, dev); |
379 | |||
380 | if (dev_priv->ring.map.handle == NULL) { | ||
371 | dev->dev_private = (void *)dev_priv; | 381 | dev->dev_private = (void *)dev_priv; |
372 | i810_dma_cleanup(dev); | 382 | i810_dma_cleanup(dev); |
373 | DRM_ERROR("can not ioremap virtual address for" | 383 | DRM_ERROR("can not ioremap virtual address for" |
374 | " ring buffer\n"); | 384 | " ring buffer\n"); |
375 | return -ENOMEM; | 385 | return DRM_ERR(ENOMEM); |
376 | } | 386 | } |
377 | 387 | ||
388 | dev_priv->ring.virtual_start = dev_priv->ring.map.handle; | ||
389 | |||
378 | dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; | 390 | dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; |
379 | 391 | ||
380 | dev_priv->w = init->w; | 392 | dev_priv->w = init->w; |
diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h index e8cf3ff606f0..e6df49f4928a 100644 --- a/drivers/char/drm/i810_drv.h +++ b/drivers/char/drm/i810_drv.h | |||
@@ -61,6 +61,7 @@ typedef struct drm_i810_buf_priv { | |||
61 | int currently_mapped; | 61 | int currently_mapped; |
62 | void *virtual; | 62 | void *virtual; |
63 | void *kernel_virtual; | 63 | void *kernel_virtual; |
64 | drm_local_map_t map; | ||
64 | } drm_i810_buf_priv_t; | 65 | } drm_i810_buf_priv_t; |
65 | 66 | ||
66 | typedef struct _drm_i810_ring_buffer { | 67 | typedef struct _drm_i810_ring_buffer { |
@@ -72,6 +73,7 @@ typedef struct _drm_i810_ring_buffer { | |||
72 | int head; | 73 | int head; |
73 | int tail; | 74 | int tail; |
74 | int space; | 75 | int space; |
76 | drm_local_map_t map; | ||
75 | } drm_i810_ring_buffer_t; | 77 | } drm_i810_ring_buffer_t; |
76 | 78 | ||
77 | typedef struct drm_i810_private { | 79 | typedef struct drm_i810_private { |
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c index 4f0e5746ab33..95224455ec0c 100644 --- a/drivers/char/drm/i830_dma.c +++ b/drivers/char/drm/i830_dma.c | |||
@@ -223,8 +223,7 @@ static int i830_dma_cleanup(drm_device_t * dev) | |||
223 | (drm_i830_private_t *) dev->dev_private; | 223 | (drm_i830_private_t *) dev->dev_private; |
224 | 224 | ||
225 | if (dev_priv->ring.virtual_start) { | 225 | if (dev_priv->ring.virtual_start) { |
226 | drm_ioremapfree((void *)dev_priv->ring.virtual_start, | 226 | drm_core_ioremapfree(&dev_priv->ring.map, dev); |
227 | dev_priv->ring.Size, dev); | ||
228 | } | 227 | } |
229 | if (dev_priv->hw_status_page) { | 228 | if (dev_priv->hw_status_page) { |
230 | pci_free_consistent(dev->pdev, PAGE_SIZE, | 229 | pci_free_consistent(dev->pdev, PAGE_SIZE, |
@@ -242,8 +241,7 @@ static int i830_dma_cleanup(drm_device_t * dev) | |||
242 | drm_buf_t *buf = dma->buflist[i]; | 241 | drm_buf_t *buf = dma->buflist[i]; |
243 | drm_i830_buf_priv_t *buf_priv = buf->dev_private; | 242 | drm_i830_buf_priv_t *buf_priv = buf->dev_private; |
244 | if (buf_priv->kernel_virtual && buf->total) | 243 | if (buf_priv->kernel_virtual && buf->total) |
245 | drm_ioremapfree(buf_priv->kernel_virtual, | 244 | drm_core_ioremapfree(&buf_priv->map, dev); |
246 | buf->total, dev); | ||
247 | } | 245 | } |
248 | } | 246 | } |
249 | return 0; | 247 | return 0; |
@@ -320,8 +318,14 @@ static int i830_freelist_init(drm_device_t * dev, drm_i830_private_t * dev_priv) | |||
320 | 318 | ||
321 | *buf_priv->in_use = I830_BUF_FREE; | 319 | *buf_priv->in_use = I830_BUF_FREE; |
322 | 320 | ||
323 | buf_priv->kernel_virtual = drm_ioremap(buf->bus_address, | 321 | buf_priv->map.offset = buf->bus_address; |
324 | buf->total, dev); | 322 | buf_priv->map.size = buf->total; |
323 | buf_priv->map.type = _DRM_AGP; | ||
324 | buf_priv->map.flags = 0; | ||
325 | buf_priv->map.mtrr = 0; | ||
326 | |||
327 | drm_core_ioremap(&buf_priv->map, dev); | ||
328 | buf_priv->kernel_virtual = buf_priv->map.handle; | ||
325 | } | 329 | } |
326 | return 0; | 330 | return 0; |
327 | } | 331 | } |
@@ -373,18 +377,24 @@ static int i830_dma_initialize(drm_device_t * dev, | |||
373 | dev_priv->ring.End = init->ring_end; | 377 | dev_priv->ring.End = init->ring_end; |
374 | dev_priv->ring.Size = init->ring_size; | 378 | dev_priv->ring.Size = init->ring_size; |
375 | 379 | ||
376 | dev_priv->ring.virtual_start = drm_ioremap(dev->agp->base + | 380 | dev_priv->ring.map.offset = dev->agp->base + init->ring_start; |
377 | init->ring_start, | 381 | dev_priv->ring.map.size = init->ring_size; |
378 | init->ring_size, dev); | 382 | dev_priv->ring.map.type = _DRM_AGP; |
383 | dev_priv->ring.map.flags = 0; | ||
384 | dev_priv->ring.map.mtrr = 0; | ||
385 | |||
386 | drm_core_ioremap(&dev_priv->ring.map, dev); | ||
379 | 387 | ||
380 | if (dev_priv->ring.virtual_start == NULL) { | 388 | if (dev_priv->ring.map.handle == NULL) { |
381 | dev->dev_private = (void *)dev_priv; | 389 | dev->dev_private = (void *)dev_priv; |
382 | i830_dma_cleanup(dev); | 390 | i830_dma_cleanup(dev); |
383 | DRM_ERROR("can not ioremap virtual address for" | 391 | DRM_ERROR("can not ioremap virtual address for" |
384 | " ring buffer\n"); | 392 | " ring buffer\n"); |
385 | return -ENOMEM; | 393 | return DRM_ERR(ENOMEM); |
386 | } | 394 | } |
387 | 395 | ||
396 | dev_priv->ring.virtual_start = dev_priv->ring.map.handle; | ||
397 | |||
388 | dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; | 398 | dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; |
389 | 399 | ||
390 | dev_priv->w = init->w; | 400 | dev_priv->w = init->w; |
diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h index 85bc5be6f916..e91f94afb4bb 100644 --- a/drivers/char/drm/i830_drv.h +++ b/drivers/char/drm/i830_drv.h | |||
@@ -68,6 +68,7 @@ typedef struct drm_i830_buf_priv { | |||
68 | int currently_mapped; | 68 | int currently_mapped; |
69 | void __user *virtual; | 69 | void __user *virtual; |
70 | void *kernel_virtual; | 70 | void *kernel_virtual; |
71 | drm_local_map_t map; | ||
71 | } drm_i830_buf_priv_t; | 72 | } drm_i830_buf_priv_t; |
72 | 73 | ||
73 | typedef struct _drm_i830_ring_buffer { | 74 | typedef struct _drm_i830_ring_buffer { |
@@ -79,6 +80,7 @@ typedef struct _drm_i830_ring_buffer { | |||
79 | int head; | 80 | int head; |
80 | int tail; | 81 | int tail; |
81 | int space; | 82 | int space; |
83 | drm_local_map_t map; | ||
82 | } drm_i830_ring_buffer_t; | 84 | } drm_i830_ring_buffer_t; |
83 | 85 | ||
84 | typedef struct drm_i830_private { | 86 | typedef struct drm_i830_private { |
diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c index a691ae74129d..c0539c6299cf 100644 --- a/drivers/char/drm/via_dma.c +++ b/drivers/char/drm/via_dma.c | |||
@@ -190,6 +190,11 @@ static int via_initialize(drm_device_t * dev, | |||
190 | return DRM_ERR(EFAULT); | 190 | return DRM_ERR(EFAULT); |
191 | } | 191 | } |
192 | 192 | ||
193 | if (dev_priv->chipset == VIA_DX9_0) { | ||
194 | DRM_ERROR("AGP DMA is not supported on this chip\n"); | ||
195 | return DRM_ERR(EINVAL); | ||
196 | } | ||
197 | |||
193 | dev_priv->ring.map.offset = dev->agp->base + init->offset; | 198 | dev_priv->ring.map.offset = dev->agp->base + init->offset; |
194 | dev_priv->ring.map.size = init->size; | 199 | dev_priv->ring.map.size = init->size; |
195 | dev_priv->ring.map.type = 0; | 200 | dev_priv->ring.map.type = 0; |
@@ -480,6 +485,7 @@ static int via_hook_segment(drm_via_private_t * dev_priv, | |||
480 | VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); | 485 | VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); |
481 | VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); | 486 | VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); |
482 | VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); | 487 | VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); |
488 | VIA_READ(VIA_REG_TRANSPACE); | ||
483 | } | 489 | } |
484 | } | 490 | } |
485 | return paused; | 491 | return paused; |
@@ -557,8 +563,9 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv) | |||
557 | 563 | ||
558 | VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); | 564 | VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); |
559 | VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); | 565 | VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); |
560 | 566 | DRM_WRITEMEMORYBARRIER(); | |
561 | VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK); | 567 | VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK); |
568 | VIA_READ(VIA_REG_TRANSPACE); | ||
562 | } | 569 | } |
563 | 570 | ||
564 | static void via_pad_cache(drm_via_private_t * dev_priv, int qwords) | 571 | static void via_pad_cache(drm_via_private_t * dev_priv, int qwords) |
diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c index 806f9ce5f47b..2054d5773717 100644 --- a/drivers/char/drm/via_dmablit.c +++ b/drivers/char/drm/via_dmablit.c | |||
@@ -218,7 +218,9 @@ via_fire_dmablit(drm_device_t *dev, drm_via_sg_info_t *vsg, int engine) | |||
218 | VIA_WRITE(VIA_PCI_DMA_MR0 + engine*0x04, VIA_DMA_MR_CM | VIA_DMA_MR_TDIE); | 218 | VIA_WRITE(VIA_PCI_DMA_MR0 + engine*0x04, VIA_DMA_MR_CM | VIA_DMA_MR_TDIE); |
219 | VIA_WRITE(VIA_PCI_DMA_BCR0 + engine*0x10, 0); | 219 | VIA_WRITE(VIA_PCI_DMA_BCR0 + engine*0x10, 0); |
220 | VIA_WRITE(VIA_PCI_DMA_DPR0 + engine*0x10, vsg->chain_start); | 220 | VIA_WRITE(VIA_PCI_DMA_DPR0 + engine*0x10, vsg->chain_start); |
221 | DRM_WRITEMEMORYBARRIER(); | ||
221 | VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DE | VIA_DMA_CSR_TS); | 222 | VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DE | VIA_DMA_CSR_TS); |
223 | VIA_READ(VIA_PCI_DMA_CSR0 + engine*0x04); | ||
222 | } | 224 | } |
223 | 225 | ||
224 | /* | 226 | /* |
diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h index d21b5b75da0f..8b8778d4a423 100644 --- a/drivers/char/drm/via_drv.h +++ b/drivers/char/drm/via_drv.h | |||
@@ -29,10 +29,10 @@ | |||
29 | 29 | ||
30 | #define DRIVER_NAME "via" | 30 | #define DRIVER_NAME "via" |
31 | #define DRIVER_DESC "VIA Unichrome / Pro" | 31 | #define DRIVER_DESC "VIA Unichrome / Pro" |
32 | #define DRIVER_DATE "20060529" | 32 | #define DRIVER_DATE "20061227" |
33 | 33 | ||
34 | #define DRIVER_MAJOR 2 | 34 | #define DRIVER_MAJOR 2 |
35 | #define DRIVER_MINOR 10 | 35 | #define DRIVER_MINOR 11 |
36 | #define DRIVER_PATCHLEVEL 0 | 36 | #define DRIVER_PATCHLEVEL 0 |
37 | 37 | ||
38 | #include "via_verifier.h" | 38 | #include "via_verifier.h" |
@@ -79,7 +79,7 @@ typedef struct drm_via_private { | |||
79 | char pci_buf[VIA_PCI_BUF_SIZE]; | 79 | char pci_buf[VIA_PCI_BUF_SIZE]; |
80 | const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE]; | 80 | const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE]; |
81 | uint32_t num_fire_offsets; | 81 | uint32_t num_fire_offsets; |
82 | int pro_group_a; | 82 | int chipset; |
83 | drm_via_irq_t via_irqs[VIA_NUM_IRQS]; | 83 | drm_via_irq_t via_irqs[VIA_NUM_IRQS]; |
84 | unsigned num_irqs; | 84 | unsigned num_irqs; |
85 | maskarray_t *irq_masks; | 85 | maskarray_t *irq_masks; |
@@ -96,8 +96,9 @@ typedef struct drm_via_private { | |||
96 | } drm_via_private_t; | 96 | } drm_via_private_t; |
97 | 97 | ||
98 | enum via_family { | 98 | enum via_family { |
99 | VIA_OTHER = 0, | 99 | VIA_OTHER = 0, /* Baseline */ |
100 | VIA_PRO_GROUP_A, | 100 | VIA_PRO_GROUP_A, /* Another video engine and DMA commands */ |
101 | VIA_DX9_0 /* Same video as pro_group_a, but 3D is unsupported */ | ||
101 | }; | 102 | }; |
102 | 103 | ||
103 | /* VIA MMIO register access */ | 104 | /* VIA MMIO register access */ |
diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c index c33d068cde19..1ac5941ad237 100644 --- a/drivers/char/drm/via_irq.c +++ b/drivers/char/drm/via_irq.c | |||
@@ -258,12 +258,16 @@ void via_driver_irq_preinstall(drm_device_t * dev) | |||
258 | dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE; | 258 | dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE; |
259 | dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING; | 259 | dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING; |
260 | 260 | ||
261 | dev_priv->irq_masks = (dev_priv->pro_group_a) ? | 261 | if (dev_priv->chipset == VIA_PRO_GROUP_A || |
262 | via_pro_group_a_irqs : via_unichrome_irqs; | 262 | dev_priv->chipset == VIA_DX9_0) { |
263 | dev_priv->num_irqs = (dev_priv->pro_group_a) ? | 263 | dev_priv->irq_masks = via_pro_group_a_irqs; |
264 | via_num_pro_group_a : via_num_unichrome; | 264 | dev_priv->num_irqs = via_num_pro_group_a; |
265 | dev_priv->irq_map = (dev_priv->pro_group_a) ? | 265 | dev_priv->irq_map = via_irqmap_pro_group_a; |
266 | via_irqmap_pro_group_a : via_irqmap_unichrome; | 266 | } else { |
267 | dev_priv->irq_masks = via_unichrome_irqs; | ||
268 | dev_priv->num_irqs = via_num_unichrome; | ||
269 | dev_priv->irq_map = via_irqmap_unichrome; | ||
270 | } | ||
267 | 271 | ||
268 | for (i = 0; i < dev_priv->num_irqs; ++i) { | 272 | for (i = 0; i < dev_priv->num_irqs; ++i) { |
269 | atomic_set(&cur_irq->irq_received, 0); | 273 | atomic_set(&cur_irq->irq_received, 0); |
diff --git a/drivers/char/drm/via_map.c b/drivers/char/drm/via_map.c index 782011e0a58d..4e3fc072aa3b 100644 --- a/drivers/char/drm/via_map.c +++ b/drivers/char/drm/via_map.c | |||
@@ -106,8 +106,7 @@ int via_driver_load(drm_device_t *dev, unsigned long chipset) | |||
106 | 106 | ||
107 | dev->dev_private = (void *)dev_priv; | 107 | dev->dev_private = (void *)dev_priv; |
108 | 108 | ||
109 | if (chipset == VIA_PRO_GROUP_A) | 109 | dev_priv->chipset = chipset; |
110 | dev_priv->pro_group_a = 1; | ||
111 | 110 | ||
112 | ret = drm_sman_init(&dev_priv->sman, 2, 12, 8); | 111 | ret = drm_sman_init(&dev_priv->sman, 2, 12, 8); |
113 | if (ret) { | 112 | if (ret) { |
diff --git a/drivers/char/drm/via_verifier.c b/drivers/char/drm/via_verifier.c index 70c897c88766..2e7e08078287 100644 --- a/drivers/char/drm/via_verifier.c +++ b/drivers/char/drm/via_verifier.c | |||
@@ -306,6 +306,7 @@ static __inline__ int finish_current_sequence(drm_via_state_t * cur_seq) | |||
306 | unsigned long lo = ~0, hi = 0, tmp; | 306 | unsigned long lo = ~0, hi = 0, tmp; |
307 | uint32_t *addr, *pitch, *height, tex; | 307 | uint32_t *addr, *pitch, *height, tex; |
308 | unsigned i; | 308 | unsigned i; |
309 | int npot; | ||
309 | 310 | ||
310 | if (end > 9) | 311 | if (end > 9) |
311 | end = 9; | 312 | end = 9; |
@@ -316,12 +317,15 @@ static __inline__ int finish_current_sequence(drm_via_state_t * cur_seq) | |||
316 | &(cur_seq->t_addr[tex = cur_seq->texture][start]); | 317 | &(cur_seq->t_addr[tex = cur_seq->texture][start]); |
317 | pitch = &(cur_seq->pitch[tex][start]); | 318 | pitch = &(cur_seq->pitch[tex][start]); |
318 | height = &(cur_seq->height[tex][start]); | 319 | height = &(cur_seq->height[tex][start]); |
319 | 320 | npot = cur_seq->tex_npot[tex]; | |
320 | for (i = start; i <= end; ++i) { | 321 | for (i = start; i <= end; ++i) { |
321 | tmp = *addr++; | 322 | tmp = *addr++; |
322 | if (tmp < lo) | 323 | if (tmp < lo) |
323 | lo = tmp; | 324 | lo = tmp; |
324 | tmp += (*height++ << *pitch++); | 325 | if (i == 0 && npot) |
326 | tmp += (*height++ * *pitch++); | ||
327 | else | ||
328 | tmp += (*height++ << *pitch++); | ||
325 | if (tmp > hi) | 329 | if (tmp > hi) |
326 | hi = tmp; | 330 | hi = tmp; |
327 | } | 331 | } |
@@ -443,13 +447,21 @@ investigate_hazard(uint32_t cmd, hazard_t hz, drm_via_state_t * cur_seq) | |||
443 | return 0; | 447 | return 0; |
444 | case check_texture_addr3: | 448 | case check_texture_addr3: |
445 | cur_seq->unfinished = tex_address; | 449 | cur_seq->unfinished = tex_address; |
446 | tmp = ((cmd >> 24) - 0x2B); | 450 | tmp = ((cmd >> 24) - HC_SubA_HTXnL0Pit); |
447 | cur_seq->pitch[cur_seq->texture][tmp] = | 451 | if (tmp == 0 && |
448 | (cmd & 0x00F00000) >> 20; | 452 | (cmd & HC_HTXnEnPit_MASK)) { |
449 | if (!tmp && (cmd & 0x000FFFFF)) { | 453 | cur_seq->pitch[cur_seq->texture][tmp] = |
450 | DRM_ERROR | 454 | (cmd & HC_HTXnLnPit_MASK); |
451 | ("Unimplemented texture level 0 pitch mode.\n"); | 455 | cur_seq->tex_npot[cur_seq->texture] = 1; |
452 | return 2; | 456 | } else { |
457 | cur_seq->pitch[cur_seq->texture][tmp] = | ||
458 | (cmd & HC_HTXnLnPitE_MASK) >> HC_HTXnLnPitE_SHIFT; | ||
459 | cur_seq->tex_npot[cur_seq->texture] = 0; | ||
460 | if (cmd & 0x000FFFFF) { | ||
461 | DRM_ERROR | ||
462 | ("Unimplemented texture level 0 pitch mode.\n"); | ||
463 | return 2; | ||
464 | } | ||
453 | } | 465 | } |
454 | return 0; | 466 | return 0; |
455 | case check_texture_addr4: | 467 | case check_texture_addr4: |
@@ -961,7 +973,13 @@ via_verify_command_stream(const uint32_t * buf, unsigned int size, | |||
961 | uint32_t cmd; | 973 | uint32_t cmd; |
962 | const uint32_t *buf_end = buf + (size >> 2); | 974 | const uint32_t *buf_end = buf + (size >> 2); |
963 | verifier_state_t state = state_command; | 975 | verifier_state_t state = state_command; |
964 | int pro_group_a = dev_priv->pro_group_a; | 976 | int cme_video; |
977 | int supported_3d; | ||
978 | |||
979 | cme_video = (dev_priv->chipset == VIA_PRO_GROUP_A || | ||
980 | dev_priv->chipset == VIA_DX9_0); | ||
981 | |||
982 | supported_3d = dev_priv->chipset != VIA_DX9_0; | ||
965 | 983 | ||
966 | hc_state->dev = dev; | 984 | hc_state->dev = dev; |
967 | hc_state->unfinished = no_sequence; | 985 | hc_state->unfinished = no_sequence; |
@@ -986,17 +1004,21 @@ via_verify_command_stream(const uint32_t * buf, unsigned int size, | |||
986 | state = via_check_vheader6(&buf, buf_end); | 1004 | state = via_check_vheader6(&buf, buf_end); |
987 | break; | 1005 | break; |
988 | case state_command: | 1006 | case state_command: |
989 | if (HALCYON_HEADER2 == (cmd = *buf)) | 1007 | if ((HALCYON_HEADER2 == (cmd = *buf)) && |
1008 | supported_3d) | ||
990 | state = state_header2; | 1009 | state = state_header2; |
991 | else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1) | 1010 | else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1) |
992 | state = state_header1; | 1011 | state = state_header1; |
993 | else if (pro_group_a | 1012 | else if (cme_video |
994 | && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5) | 1013 | && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5) |
995 | state = state_vheader5; | 1014 | state = state_vheader5; |
996 | else if (pro_group_a | 1015 | else if (cme_video |
997 | && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6) | 1016 | && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6) |
998 | state = state_vheader6; | 1017 | state = state_vheader6; |
999 | else { | 1018 | else if ((cmd == HALCYON_HEADER2) && !supported_3d) { |
1019 | DRM_ERROR("Accelerated 3D is not supported on this chipset yet.\n"); | ||
1020 | state = state_error; | ||
1021 | } else { | ||
1000 | DRM_ERROR | 1022 | DRM_ERROR |
1001 | ("Invalid / Unimplemented DMA HEADER command. 0x%x\n", | 1023 | ("Invalid / Unimplemented DMA HEADER command. 0x%x\n", |
1002 | cmd); | 1024 | cmd); |
diff --git a/drivers/char/drm/via_verifier.h b/drivers/char/drm/via_verifier.h index 256590fcc22a..b77f59df0278 100644 --- a/drivers/char/drm/via_verifier.h +++ b/drivers/char/drm/via_verifier.h | |||
@@ -43,6 +43,7 @@ typedef struct { | |||
43 | uint32_t tex_level_lo[2]; | 43 | uint32_t tex_level_lo[2]; |
44 | uint32_t tex_level_hi[2]; | 44 | uint32_t tex_level_hi[2]; |
45 | uint32_t tex_palette_size[2]; | 45 | uint32_t tex_palette_size[2]; |
46 | uint32_t tex_npot[2]; | ||
46 | drm_via_sequence_t unfinished; | 47 | drm_via_sequence_t unfinished; |
47 | int agp_texture; | 48 | int agp_texture; |
48 | int multitex; | 49 | int multitex; |
diff --git a/drivers/char/hvc_beat.c b/drivers/char/hvc_beat.c new file mode 100644 index 000000000000..6f019f19be71 --- /dev/null +++ b/drivers/char/hvc_beat.c | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * Beat hypervisor console driver | ||
3 | * | ||
4 | * (C) Copyright 2006 TOSHIBA CORPORATION | ||
5 | * | ||
6 | * This code is based on drivers/char/hvc_rtas.c: | ||
7 | * (C) Copyright IBM Corporation 2001-2005 | ||
8 | * (C) Copyright Red Hat, Inc. 2005 | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
23 | */ | ||
24 | |||
25 | #include <linux/module.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/err.h> | ||
28 | #include <linux/string.h> | ||
29 | #include <linux/console.h> | ||
30 | #include <asm/prom.h> | ||
31 | #include <asm/hvconsole.h> | ||
32 | #include <asm/firmware.h> | ||
33 | |||
34 | #include "hvc_console.h" | ||
35 | |||
36 | extern int64_t beat_get_term_char(uint64_t, uint64_t *, uint64_t *, uint64_t *); | ||
37 | extern int64_t beat_put_term_char(uint64_t, uint64_t, uint64_t, uint64_t); | ||
38 | |||
39 | struct hvc_struct *hvc_beat_dev = NULL; | ||
40 | |||
41 | /* bug: only one queue is available regardless of vtermno */ | ||
42 | static int hvc_beat_get_chars(uint32_t vtermno, char *buf, int cnt) | ||
43 | { | ||
44 | static unsigned char q[sizeof(unsigned long) * 2] | ||
45 | __attribute__((aligned(sizeof(unsigned long)))); | ||
46 | static int qlen = 0; | ||
47 | unsigned long got; | ||
48 | |||
49 | again: | ||
50 | if (qlen) { | ||
51 | if (qlen > cnt) { | ||
52 | memcpy(buf, q, cnt); | ||
53 | qlen -= cnt; | ||
54 | memmove(q + cnt, q, qlen); | ||
55 | return cnt; | ||
56 | } else { /* qlen <= cnt */ | ||
57 | int r; | ||
58 | |||
59 | memcpy(buf, q, qlen); | ||
60 | r = qlen; | ||
61 | qlen = 0; | ||
62 | return r; | ||
63 | } | ||
64 | } | ||
65 | if (beat_get_term_char(vtermno, &got, | ||
66 | ((unsigned long *)q), ((unsigned long *)q) + 1) == 0) { | ||
67 | qlen = got; | ||
68 | goto again; | ||
69 | } | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static int hvc_beat_put_chars(uint32_t vtermno, const char *buf, int cnt) | ||
74 | { | ||
75 | unsigned long kb[2]; | ||
76 | int rest, nlen; | ||
77 | |||
78 | for (rest = cnt; rest > 0; rest -= nlen) { | ||
79 | nlen = (rest > 16) ? 16 : rest; | ||
80 | memcpy(kb, buf, nlen); | ||
81 | beat_put_term_char(vtermno, rest, kb[0], kb[1]); | ||
82 | rest -= nlen; | ||
83 | } | ||
84 | return cnt; | ||
85 | } | ||
86 | |||
87 | static struct hv_ops hvc_beat_get_put_ops = { | ||
88 | .get_chars = hvc_beat_get_chars, | ||
89 | .put_chars = hvc_beat_put_chars, | ||
90 | }; | ||
91 | |||
92 | static int hvc_beat_useit = 1; | ||
93 | |||
94 | static int hvc_beat_config(char *p) | ||
95 | { | ||
96 | hvc_beat_useit = simple_strtoul(p, NULL, 0); | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static int hvc_beat_console_init(void) | ||
101 | { | ||
102 | if (hvc_beat_useit && machine_is_compatible("Beat")) { | ||
103 | hvc_instantiate(0, 0, &hvc_beat_get_put_ops); | ||
104 | } | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | /* temp */ | ||
109 | static int hvc_beat_init(void) | ||
110 | { | ||
111 | struct hvc_struct *hp; | ||
112 | |||
113 | if (!firmware_has_feature(FW_FEATURE_BEAT)) | ||
114 | return -ENODEV; | ||
115 | |||
116 | hp = hvc_alloc(0, NO_IRQ, &hvc_beat_get_put_ops, 16); | ||
117 | if (IS_ERR(hp)) | ||
118 | return PTR_ERR(hp); | ||
119 | hvc_beat_dev = hp; | ||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static void __exit hvc_beat_exit(void) | ||
124 | { | ||
125 | if (hvc_beat_dev) | ||
126 | hvc_remove(hvc_beat_dev); | ||
127 | } | ||
128 | |||
129 | module_init(hvc_beat_init); | ||
130 | module_exit(hvc_beat_exit); | ||
131 | |||
132 | __setup("hvc_beat=", hvc_beat_config); | ||
133 | |||
134 | console_initcall(hvc_beat_console_init); | ||
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index f1afd26a509f..a7b33d2f5991 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -1802,7 +1802,7 @@ static __devinit int try_init_acpi(struct SPMITable *spmi) | |||
1802 | return -ENODEV; | 1802 | return -ENODEV; |
1803 | } | 1803 | } |
1804 | 1804 | ||
1805 | if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) | 1805 | if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) |
1806 | addr_space = IPMI_MEM_ADDR_SPACE; | 1806 | addr_space = IPMI_MEM_ADDR_SPACE; |
1807 | else | 1807 | else |
1808 | addr_space = IPMI_IO_ADDR_SPACE; | 1808 | addr_space = IPMI_IO_ADDR_SPACE; |
@@ -1848,19 +1848,19 @@ static __devinit int try_init_acpi(struct SPMITable *spmi) | |||
1848 | info->irq_setup = NULL; | 1848 | info->irq_setup = NULL; |
1849 | } | 1849 | } |
1850 | 1850 | ||
1851 | if (spmi->addr.register_bit_width) { | 1851 | if (spmi->addr.bit_width) { |
1852 | /* A (hopefully) properly formed register bit width. */ | 1852 | /* A (hopefully) properly formed register bit width. */ |
1853 | info->io.regspacing = spmi->addr.register_bit_width / 8; | 1853 | info->io.regspacing = spmi->addr.bit_width / 8; |
1854 | } else { | 1854 | } else { |
1855 | info->io.regspacing = DEFAULT_REGSPACING; | 1855 | info->io.regspacing = DEFAULT_REGSPACING; |
1856 | } | 1856 | } |
1857 | info->io.regsize = info->io.regspacing; | 1857 | info->io.regsize = info->io.regspacing; |
1858 | info->io.regshift = spmi->addr.register_bit_offset; | 1858 | info->io.regshift = spmi->addr.bit_offset; |
1859 | 1859 | ||
1860 | if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { | 1860 | if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { |
1861 | info->io_setup = mem_setup; | 1861 | info->io_setup = mem_setup; |
1862 | info->io.addr_type = IPMI_IO_ADDR_SPACE; | 1862 | info->io.addr_type = IPMI_IO_ADDR_SPACE; |
1863 | } else if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) { | 1863 | } else if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_IO) { |
1864 | info->io_setup = port_setup; | 1864 | info->io_setup = port_setup; |
1865 | info->io.addr_type = IPMI_MEM_ADDR_SPACE; | 1865 | info->io.addr_type = IPMI_MEM_ADDR_SPACE; |
1866 | } else { | 1866 | } else { |
@@ -1888,10 +1888,8 @@ static __devinit void acpi_find_bmc(void) | |||
1888 | return; | 1888 | return; |
1889 | 1889 | ||
1890 | for (i = 0; ; i++) { | 1890 | for (i = 0; ; i++) { |
1891 | status = acpi_get_firmware_table("SPMI", i+1, | 1891 | status = acpi_get_table(ACPI_SIG_SPMI, i+1, |
1892 | ACPI_LOGICAL_ADDRESSING, | 1892 | (struct acpi_table_header **)&spmi); |
1893 | (struct acpi_table_header **) | ||
1894 | &spmi); | ||
1895 | if (status != AE_OK) | 1893 | if (status != AE_OK) |
1896 | return; | 1894 | return; |
1897 | 1895 | ||
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 13935235e066..7fd3cd5ddf21 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c | |||
@@ -215,7 +215,7 @@ static void sysrq_handle_showstate_blocked(int key, struct tty_struct *tty) | |||
215 | } | 215 | } |
216 | static struct sysrq_key_op sysrq_showstate_blocked_op = { | 216 | static struct sysrq_key_op sysrq_showstate_blocked_op = { |
217 | .handler = sysrq_handle_showstate_blocked, | 217 | .handler = sysrq_handle_showstate_blocked, |
218 | .help_msg = "showBlockedTasks", | 218 | .help_msg = "shoW-blocked-tasks", |
219 | .action_msg = "Show Blocked State", | 219 | .action_msg = "Show Blocked State", |
220 | .enable_mask = SYSRQ_ENABLE_DUMP, | 220 | .enable_mask = SYSRQ_ENABLE_DUMP, |
221 | }; | 221 | }; |
@@ -315,15 +315,16 @@ static struct sysrq_key_op *sysrq_key_table[36] = { | |||
315 | &sysrq_loglevel_op, /* 9 */ | 315 | &sysrq_loglevel_op, /* 9 */ |
316 | 316 | ||
317 | /* | 317 | /* |
318 | * Don't use for system provided sysrqs, it is handled specially on | 318 | * a: Don't use for system provided sysrqs, it is handled specially on |
319 | * sparc and will never arrive | 319 | * sparc and will never arrive. |
320 | */ | 320 | */ |
321 | NULL, /* a */ | 321 | NULL, /* a */ |
322 | &sysrq_reboot_op, /* b */ | 322 | &sysrq_reboot_op, /* b */ |
323 | &sysrq_crashdump_op, /* c */ | 323 | &sysrq_crashdump_op, /* c & ibm_emac driver debug */ |
324 | &sysrq_showlocks_op, /* d */ | 324 | &sysrq_showlocks_op, /* d */ |
325 | &sysrq_term_op, /* e */ | 325 | &sysrq_term_op, /* e */ |
326 | &sysrq_moom_op, /* f */ | 326 | &sysrq_moom_op, /* f */ |
327 | /* g: May be registered by ppc for kgdb */ | ||
327 | NULL, /* g */ | 328 | NULL, /* g */ |
328 | NULL, /* h */ | 329 | NULL, /* h */ |
329 | &sysrq_kill_op, /* i */ | 330 | &sysrq_kill_op, /* i */ |
@@ -332,18 +333,19 @@ static struct sysrq_key_op *sysrq_key_table[36] = { | |||
332 | NULL, /* l */ | 333 | NULL, /* l */ |
333 | &sysrq_showmem_op, /* m */ | 334 | &sysrq_showmem_op, /* m */ |
334 | &sysrq_unrt_op, /* n */ | 335 | &sysrq_unrt_op, /* n */ |
335 | /* This will often be registered as 'Off' at init time */ | 336 | /* o: This will often be registered as 'Off' at init time */ |
336 | NULL, /* o */ | 337 | NULL, /* o */ |
337 | &sysrq_showregs_op, /* p */ | 338 | &sysrq_showregs_op, /* p */ |
338 | NULL, /* q */ | 339 | NULL, /* q */ |
339 | &sysrq_unraw_op, /* r */ | 340 | &sysrq_unraw_op, /* r */ |
340 | &sysrq_sync_op, /* s */ | 341 | &sysrq_sync_op, /* s */ |
341 | &sysrq_showstate_op, /* t */ | 342 | &sysrq_showstate_op, /* t */ |
342 | &sysrq_mountro_op, /* u */ | 343 | &sysrq_mountro_op, /* u */ |
343 | /* May be assigned at init time by SMP VOYAGER */ | 344 | /* v: May be registered at init time by SMP VOYAGER */ |
344 | NULL, /* v */ | 345 | NULL, /* v */ |
345 | NULL, /* w */ | 346 | &sysrq_showstate_blocked_op, /* w */ |
346 | &sysrq_showstate_blocked_op, /* x */ | 347 | /* x: May be registered on ppc/powerpc for xmon */ |
348 | NULL, /* x */ | ||
347 | NULL, /* y */ | 349 | NULL, /* y */ |
348 | NULL /* z */ | 350 | NULL /* z */ |
349 | }; | 351 | }; |
diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c index a611972024e6..7fca5f470beb 100644 --- a/drivers/char/tpm/tpm_bios.c +++ b/drivers/char/tpm/tpm_bios.c | |||
@@ -372,10 +372,8 @@ static int read_log(struct tpm_bios_log *log) | |||
372 | } | 372 | } |
373 | 373 | ||
374 | /* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */ | 374 | /* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */ |
375 | status = acpi_get_firmware_table(ACPI_TCPA_SIG, 1, | 375 | status = acpi_get_table(ACPI_SIG_TCPA, 1, |
376 | ACPI_LOGICAL_ADDRESSING, | 376 | (struct acpi_table_header **)&buff); |
377 | (struct acpi_table_header **) | ||
378 | &buff); | ||
379 | 377 | ||
380 | if (ACPI_FAILURE(status)) { | 378 | if (ACPI_FAILURE(status)) { |
381 | printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n", | 379 | printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n", |
@@ -409,7 +407,7 @@ static int read_log(struct tpm_bios_log *log) | |||
409 | 407 | ||
410 | log->bios_event_log_end = log->bios_event_log + len; | 408 | log->bios_event_log_end = log->bios_event_log + len; |
411 | 409 | ||
412 | acpi_os_map_memory(start, len, (void *) &virt); | 410 | virt = acpi_os_map_memory(start, len); |
413 | 411 | ||
414 | memcpy(log->bios_event_log, virt, len); | 412 | memcpy(log->bios_event_log, virt, len); |
415 | 413 | ||
diff --git a/drivers/char/watchdog/booke_wdt.c b/drivers/char/watchdog/booke_wdt.c index 488902231cc2..0e23f29f71ab 100644 --- a/drivers/char/watchdog/booke_wdt.c +++ b/drivers/char/watchdog/booke_wdt.c | |||
@@ -35,7 +35,7 @@ | |||
35 | #ifdef CONFIG_FSL_BOOKE | 35 | #ifdef CONFIG_FSL_BOOKE |
36 | #define WDT_PERIOD_DEFAULT 63 /* Ex. wdt_period=28 bus=333Mhz , reset=~40sec */ | 36 | #define WDT_PERIOD_DEFAULT 63 /* Ex. wdt_period=28 bus=333Mhz , reset=~40sec */ |
37 | #else | 37 | #else |
38 | #define WDT_PERIOD_DEFAULT 4 /* Refer to the PPC40x and PPC4xx manuals */ | 38 | #define WDT_PERIOD_DEFAULT 3 /* Refer to the PPC40x and PPC4xx manuals */ |
39 | #endif /* for timing information */ | 39 | #endif /* for timing information */ |
40 | 40 | ||
41 | u32 booke_wdt_enabled = 0; | 41 | u32 booke_wdt_enabled = 0; |
@@ -48,12 +48,22 @@ u32 booke_wdt_period = WDT_PERIOD_DEFAULT; | |||
48 | #endif | 48 | #endif |
49 | 49 | ||
50 | /* | 50 | /* |
51 | * booke_wdt_ping: | ||
52 | */ | ||
53 | static __inline__ void booke_wdt_ping(void) | ||
54 | { | ||
55 | mtspr(SPRN_TSR, TSR_ENW|TSR_WIS); | ||
56 | } | ||
57 | |||
58 | /* | ||
51 | * booke_wdt_enable: | 59 | * booke_wdt_enable: |
52 | */ | 60 | */ |
53 | static __inline__ void booke_wdt_enable(void) | 61 | static __inline__ void booke_wdt_enable(void) |
54 | { | 62 | { |
55 | u32 val; | 63 | u32 val; |
56 | 64 | ||
65 | /* clear status before enabling watchdog */ | ||
66 | booke_wdt_ping(); | ||
57 | val = mfspr(SPRN_TCR); | 67 | val = mfspr(SPRN_TCR); |
58 | val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(booke_wdt_period)); | 68 | val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(booke_wdt_period)); |
59 | 69 | ||
@@ -61,14 +71,6 @@ static __inline__ void booke_wdt_enable(void) | |||
61 | } | 71 | } |
62 | 72 | ||
63 | /* | 73 | /* |
64 | * booke_wdt_ping: | ||
65 | */ | ||
66 | static __inline__ void booke_wdt_ping(void) | ||
67 | { | ||
68 | mtspr(SPRN_TSR, TSR_ENW|TSR_WIS); | ||
69 | } | ||
70 | |||
71 | /* | ||
72 | * booke_wdt_write: | 74 | * booke_wdt_write: |
73 | */ | 75 | */ |
74 | static ssize_t booke_wdt_write (struct file *file, const char __user *buf, | 76 | static ssize_t booke_wdt_write (struct file *file, const char __user *buf, |
diff --git a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c index 276577d08fba..4d730fdbd528 100644 --- a/drivers/char/watchdog/machzwd.c +++ b/drivers/char/watchdog/machzwd.c | |||
@@ -325,7 +325,7 @@ static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
325 | return put_user(0, p); | 325 | return put_user(0, p); |
326 | 326 | ||
327 | case WDIOC_KEEPALIVE: | 327 | case WDIOC_KEEPALIVE: |
328 | zf_ping(0); | 328 | zf_ping(NULL); |
329 | break; | 329 | break; |
330 | 330 | ||
331 | default: | 331 | default: |