aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/.gitignore1
-rw-r--r--drivers/char/Kconfig49
-rw-r--r--drivers/char/Makefile8
-rw-r--r--drivers/char/agp/agp.h2
-rw-r--r--drivers/char/agp/amd64-agp.c8
-rw-r--r--drivers/char/agp/backend.c2
-rw-r--r--drivers/char/agp/efficeon-agp.c16
-rw-r--r--drivers/char/agp/frontend.c27
-rw-r--r--drivers/char/agp/generic.c42
-rw-r--r--drivers/char/agp/intel-agp.c173
-rw-r--r--drivers/char/agp/via-agp.c4
-rw-r--r--drivers/char/amiserial.c2
-rw-r--r--drivers/char/briq_panel.c19
-rw-r--r--drivers/char/cyclades.c2
-rw-r--r--drivers/char/drm/Kconfig9
-rw-r--r--drivers/char/drm/Makefile6
-rw-r--r--drivers/char/drm/drmP.h68
-rw-r--r--drivers/char/drm/drm_auth.c64
-rw-r--r--drivers/char/drm/drm_bufs.c74
-rw-r--r--drivers/char/drm/drm_drv.c12
-rw-r--r--drivers/char/drm/drm_fops.c10
-rw-r--r--drivers/char/drm/drm_hashtab.c190
-rw-r--r--drivers/char/drm/drm_hashtab.h67
-rw-r--r--drivers/char/drm/drm_ioc32.c2
-rw-r--r--drivers/char/drm/drm_ioctl.c34
-rw-r--r--drivers/char/drm/drm_irq.c12
-rw-r--r--drivers/char/drm/drm_mm.c201
-rw-r--r--drivers/char/drm/drm_pciids.h187
-rw-r--r--drivers/char/drm/drm_proc.c2
-rw-r--r--drivers/char/drm/drm_sman.c352
-rw-r--r--drivers/char/drm/drm_sman.h176
-rw-r--r--drivers/char/drm/drm_stub.c12
-rw-r--r--drivers/char/drm/drm_vm.c45
-rw-r--r--drivers/char/drm/i810_dma.c10
-rw-r--r--drivers/char/drm/i830_dma.c4
-rw-r--r--drivers/char/drm/i915_dma.c45
-rw-r--r--drivers/char/drm/i915_drm.h6
-rw-r--r--drivers/char/drm/i915_drv.h10
-rw-r--r--drivers/char/drm/i915_irq.c16
-rw-r--r--drivers/char/drm/radeon_cp.c72
-rw-r--r--drivers/char/drm/radeon_drv.c2
-rw-r--r--drivers/char/drm/radeon_drv.h36
-rw-r--r--drivers/char/drm/radeon_state.c48
-rw-r--r--drivers/char/drm/sis_drv.c39
-rw-r--r--drivers/char/drm/sis_drv.h34
-rw-r--r--drivers/char/drm/sis_ds.c299
-rw-r--r--drivers/char/drm/sis_ds.h146
-rw-r--r--drivers/char/drm/sis_mm.c504
-rw-r--r--drivers/char/drm/via_dmablit.c68
-rw-r--r--drivers/char/drm/via_drm.h8
-rw-r--r--drivers/char/drm/via_drv.c3
-rw-r--r--drivers/char/drm/via_drv.h16
-rw-r--r--drivers/char/drm/via_ds.c273
-rw-r--r--drivers/char/drm/via_ds.h104
-rw-r--r--drivers/char/drm/via_map.c9
-rw-r--r--drivers/char/drm/via_mm.c375
-rw-r--r--drivers/char/ds1286.c15
-rw-r--r--drivers/char/epca.c2
-rw-r--r--drivers/char/esp.c2
-rw-r--r--drivers/char/generic_serial.c11
-rw-r--r--drivers/char/hpet.c4
-rw-r--r--drivers/char/hvc_console.c2
-rw-r--r--drivers/char/hvc_iseries.c7
-rw-r--r--drivers/char/hvcs.c2
-rw-r--r--drivers/char/hvsi.c2
-rw-r--r--drivers/char/hw_random/intel-rng.c186
-rw-r--r--drivers/char/ip2/ip2main.c14
-rw-r--r--drivers/char/ipmi/ipmi_devintf.c34
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c75
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c26
-rw-r--r--drivers/char/isicom.c37
-rw-r--r--drivers/char/istallion.c24
-rw-r--r--drivers/char/ite_gpio.c419
-rw-r--r--drivers/char/keyboard.c25
-rw-r--r--drivers/char/lp.c4
-rw-r--r--drivers/char/mbcs.c7
-rw-r--r--drivers/char/mem.c47
-rw-r--r--drivers/char/moxa.c82
-rw-r--r--drivers/char/mspec.c421
-rw-r--r--drivers/char/mwave/mwavedd.c4
-rw-r--r--drivers/char/mxser.c68
-rw-r--r--drivers/char/nwbutton.c5
-rw-r--r--drivers/char/pc8736x_gpio.c10
-rw-r--r--drivers/char/pcmcia/synclink_cs.c3
-rw-r--r--drivers/char/pty.c2
-rw-r--r--drivers/char/qtronixmap.c_shipped265
-rw-r--r--drivers/char/qtronixmap.map287
-rw-r--r--drivers/char/random.c8
-rw-r--r--drivers/char/raw.c50
-rw-r--r--drivers/char/rio/rio_linux.c2
-rw-r--r--drivers/char/riscom8.c24
-rw-r--r--drivers/char/rocket.c2
-rw-r--r--drivers/char/rtc.c9
-rw-r--r--drivers/char/s3c2410-rtc.c591
-rw-r--r--drivers/char/scx200_gpio.c4
-rw-r--r--drivers/char/selection.c2
-rw-r--r--drivers/char/ser_a2232.c2
-rw-r--r--drivers/char/serial167.c2
-rw-r--r--drivers/char/snsc_event.c2
-rw-r--r--drivers/char/specialix.c29
-rw-r--r--drivers/char/stallion.c2
-rw-r--r--drivers/char/sx.c2
-rw-r--r--drivers/char/synclink.c3
-rw-r--r--drivers/char/synclink_gt.c96
-rw-r--r--drivers/char/synclinkmp.c2
-rw-r--r--drivers/char/sysrq.c3
-rw-r--r--drivers/char/tipar.c6
-rw-r--r--drivers/char/tty_io.c107
-rw-r--r--drivers/char/tty_ioctl.c35
-rw-r--r--drivers/char/vc_screen.c5
-rw-r--r--drivers/char/viocons.c2
-rw-r--r--drivers/char/vme_scc.c2
-rw-r--r--drivers/char/vt.c146
-rw-r--r--drivers/char/vt_ioctl.c34
-rw-r--r--drivers/char/watchdog/Kconfig47
-rw-r--r--drivers/char/watchdog/Makefile3
-rw-r--r--drivers/char/watchdog/acquirewdt.c2
-rw-r--r--drivers/char/watchdog/advantechwdt.c2
-rw-r--r--drivers/char/watchdog/alim1535_wdt.c12
-rw-r--r--drivers/char/watchdog/alim7101_wdt.c17
-rw-r--r--drivers/char/watchdog/at91_wdt.c2
-rw-r--r--drivers/char/watchdog/booke_wdt.c2
-rw-r--r--drivers/char/watchdog/cpu5wdt.c2
-rw-r--r--drivers/char/watchdog/ep93xx_wdt.c2
-rw-r--r--drivers/char/watchdog/eurotechwdt.c2
-rw-r--r--drivers/char/watchdog/i6300esb.c2
-rw-r--r--drivers/char/watchdog/i8xx_tco.c35
-rw-r--r--drivers/char/watchdog/iTCO_wdt.c735
-rw-r--r--drivers/char/watchdog/ib700wdt.c2
-rw-r--r--drivers/char/watchdog/ibmasr.c2
-rw-r--r--drivers/char/watchdog/indydog.c2
-rw-r--r--drivers/char/watchdog/ixp2000_wdt.c2
-rw-r--r--drivers/char/watchdog/ixp4xx_wdt.c2
-rw-r--r--drivers/char/watchdog/machzwd.c5
-rw-r--r--drivers/char/watchdog/mixcomwd.c2
-rw-r--r--drivers/char/watchdog/mpc83xx_wdt.c2
-rw-r--r--drivers/char/watchdog/mpc8xx_wdt.c2
-rw-r--r--drivers/char/watchdog/mpcore_wdt.c4
-rw-r--r--drivers/char/watchdog/mv64x60_wdt.c2
-rw-r--r--drivers/char/watchdog/omap_wdt.c391
-rw-r--r--drivers/char/watchdog/omap_wdt.h64
-rw-r--r--drivers/char/watchdog/pcwd.c2
-rw-r--r--drivers/char/watchdog/pcwd_pci.c2
-rw-r--r--drivers/char/watchdog/pcwd_usb.c2
-rw-r--r--drivers/char/watchdog/pnx4008_wdt.c362
-rw-r--r--drivers/char/watchdog/s3c2410_wdt.c12
-rw-r--r--drivers/char/watchdog/sa1100_wdt.c2
-rw-r--r--drivers/char/watchdog/sbc60xxwdt.c2
-rw-r--r--drivers/char/watchdog/sbc_epx_c3.c2
-rw-r--r--drivers/char/watchdog/sc1200wdt.c2
-rw-r--r--drivers/char/watchdog/sc520_wdt.c2
-rw-r--r--drivers/char/watchdog/scx200_wdt.c2
-rw-r--r--drivers/char/watchdog/shwdt.c112
-rw-r--r--drivers/char/watchdog/softdog.c2
-rw-r--r--drivers/char/watchdog/w83627hf_wdt.c2
-rw-r--r--drivers/char/watchdog/w83877f_wdt.c2
-rw-r--r--drivers/char/watchdog/w83977f_wdt.c2
-rw-r--r--drivers/char/watchdog/wafer5823wdt.c2
-rw-r--r--drivers/char/watchdog/wdrtas.c2
-rw-r--r--drivers/char/watchdog/wdt.c2
-rw-r--r--drivers/char/watchdog/wdt285.c2
-rw-r--r--drivers/char/watchdog/wdt977.c2
-rw-r--r--drivers/char/watchdog/wdt_pci.c2
163 files changed, 5028 insertions, 4112 deletions
diff --git a/drivers/char/.gitignore b/drivers/char/.gitignore
index 73dfdcebfbba..83683a2d8e6a 100644
--- a/drivers/char/.gitignore
+++ b/drivers/char/.gitignore
@@ -1,3 +1,2 @@
1consolemap_deftbl.c 1consolemap_deftbl.c
2defkeymap.c 2defkeymap.c
3qtronixmap.c
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 52ea94b891f5..0e6f35fcc2eb 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -371,36 +371,6 @@ config AU1000_SERIAL_CONSOLE
371 If you have an Alchemy AU1000 processor (MIPS based) and you want 371 If you have an Alchemy AU1000 processor (MIPS based) and you want
372 to use a console on a serial port, say Y. Otherwise, say N. 372 to use a console on a serial port, say Y. Otherwise, say N.
373 373
374config QTRONIX_KEYBOARD
375 bool "Enable Qtronix 990P Keyboard Support"
376 depends on IT8712
377 help
378 Images of Qtronix keyboards are at
379 <http://www.qtronix.com/keyboard.html>.
380
381config IT8172_CIR
382 bool
383 depends on QTRONIX_KEYBOARD
384 default y
385
386config IT8172_SCR0
387 bool "Enable Smart Card Reader 0 Support "
388 depends on IT8712
389 help
390 Say Y here to support smart-card reader 0 (SCR0) on the Integrated
391 Technology Express, Inc. ITE8172 SBC. Vendor page at
392 <http://www.ite.com.tw/ia/brief_it8172bsp.htm>; picture of the
393 board at <http://www.mvista.com/partners/semiconductor/ite.html>.
394
395config IT8172_SCR1
396 bool "Enable Smart Card Reader 1 Support "
397 depends on IT8712
398 help
399 Say Y here to support smart-card reader 1 (SCR1) on the Integrated
400 Technology Express, Inc. ITE8172 SBC. Vendor page at
401 <http://www.ite.com.tw/ia/brief_it8172bsp.htm>; picture of the
402 board at <http://www.mvista.com/partners/semiconductor/ite.html>.
403
404config A2232 374config A2232
405 tristate "Commodore A2232 serial support (EXPERIMENTAL)" 375 tristate "Commodore A2232 serial support (EXPERIMENTAL)"
406 depends on EXPERIMENTAL && ZORRO && BROKEN_ON_SMP 376 depends on EXPERIMENTAL && ZORRO && BROKEN_ON_SMP
@@ -439,6 +409,14 @@ config SGI_MBCS
439 If you have an SGI Altix with an attached SABrick 409 If you have an SGI Altix with an attached SABrick
440 say Y or M here, otherwise say N. 410 say Y or M here, otherwise say N.
441 411
412config MSPEC
413 tristate "Memory special operations driver"
414 depends on IA64
415 help
416 If you have an ia64 and you want to enable memory special
417 operations support (formerly known as fetchop), say Y here,
418 otherwise say N.
419
442source "drivers/serial/Kconfig" 420source "drivers/serial/Kconfig"
443 421
444config UNIX98_PTYS 422config UNIX98_PTYS
@@ -739,7 +717,7 @@ config NVRAM
739 717
740config RTC 718config RTC
741 tristate "Enhanced Real Time Clock Support" 719 tristate "Enhanced Real Time Clock Support"
742 depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM 720 depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM && !SUPERH
743 ---help--- 721 ---help---
744 If you say Y here and create a character special file /dev/rtc with 722 If you say Y here and create a character special file /dev/rtc with
745 major number 10 and minor number 135 using mknod ("man mknod"), you 723 major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -823,14 +801,6 @@ config DS1302
823 will get access to the real time clock (or hardware clock) built 801 will get access to the real time clock (or hardware clock) built
824 into your computer. 802 into your computer.
825 803
826config S3C2410_RTC
827 bool "S3C2410 RTC Driver"
828 depends on ARCH_S3C2410
829 help
830 RTC (Realtime Clock) driver for the clock inbuilt into the
831 Samsung S3C2410. This can provide periodic interrupt rates
832 from 1Hz to 64Hz for user programs, and wakeup from Alarm.
833
834config COBALT_LCD 804config COBALT_LCD
835 bool "Support for Cobalt LCD" 805 bool "Support for Cobalt LCD"
836 depends on MIPS_COBALT 806 depends on MIPS_COBALT
@@ -1006,6 +976,7 @@ config GPIO_VR41XX
1006 976
1007config RAW_DRIVER 977config RAW_DRIVER
1008 tristate "RAW driver (/dev/raw/rawN) (OBSOLETE)" 978 tristate "RAW driver (/dev/raw/rawN) (OBSOLETE)"
979 depends on BLOCK
1009 help 980 help
1010 The raw driver permits block devices to be bound to /dev/raw/rawN. 981 The raw driver permits block devices to be bound to /dev/raw/rawN.
1011 Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O. 982 Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O.
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 8c6dfc621520..777cad045094 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o
47obj-$(CONFIG_HVC_DRIVER) += hvc_console.o 47obj-$(CONFIG_HVC_DRIVER) += hvc_console.o
48obj-$(CONFIG_RAW_DRIVER) += raw.o 48obj-$(CONFIG_RAW_DRIVER) += raw.o
49obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o 49obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o
50obj-$(CONFIG_MSPEC) += mspec.o
50obj-$(CONFIG_MMTIMER) += mmtimer.o 51obj-$(CONFIG_MMTIMER) += mmtimer.o
51obj-$(CONFIG_VIOCONS) += viocons.o 52obj-$(CONFIG_VIOCONS) += viocons.o
52obj-$(CONFIG_VIOTAPE) += viotape.o 53obj-$(CONFIG_VIOTAPE) += viotape.o
@@ -68,7 +69,6 @@ obj-$(CONFIG_EFI_RTC) += efirtc.o
68obj-$(CONFIG_SGI_DS1286) += ds1286.o 69obj-$(CONFIG_SGI_DS1286) += ds1286.o
69obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o 70obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o
70obj-$(CONFIG_DS1302) += ds1302.o 71obj-$(CONFIG_DS1302) += ds1302.o
71obj-$(CONFIG_S3C2410_RTC) += s3c2410-rtc.o
72ifeq ($(CONFIG_GENERIC_NVRAM),y) 72ifeq ($(CONFIG_GENERIC_NVRAM),y)
73 obj-$(CONFIG_NVRAM) += generic_nvram.o 73 obj-$(CONFIG_NVRAM) += generic_nvram.o
74else 74else
@@ -102,7 +102,7 @@ obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o
102obj-$(CONFIG_TCG_TPM) += tpm/ 102obj-$(CONFIG_TCG_TPM) += tpm/
103 103
104# Files generated that shall be removed upon make clean 104# Files generated that shall be removed upon make clean
105clean-files := consolemap_deftbl.c defkeymap.c qtronixmap.c 105clean-files := consolemap_deftbl.c defkeymap.c
106 106
107quiet_cmd_conmk = CONMK $@ 107quiet_cmd_conmk = CONMK $@
108 cmd_conmk = scripts/conmakehash $< > $@ 108 cmd_conmk = scripts/conmakehash $< > $@
@@ -112,8 +112,6 @@ $(obj)/consolemap_deftbl.c: $(src)/$(FONTMAPFILE)
112 112
113$(obj)/defkeymap.o: $(obj)/defkeymap.c 113$(obj)/defkeymap.o: $(obj)/defkeymap.c
114 114
115$(obj)/qtronixmap.o: $(obj)/qtronixmap.c
116
117# Uncomment if you're changing the keymap and have an appropriate 115# Uncomment if you're changing the keymap and have an appropriate
118# loadkeys version for the map. By default, we'll use the shipped 116# loadkeys version for the map. By default, we'll use the shipped
119# versions. 117# versions.
@@ -121,7 +119,7 @@ $(obj)/qtronixmap.o: $(obj)/qtronixmap.c
121 119
122ifdef GENERATE_KEYMAP 120ifdef GENERATE_KEYMAP
123 121
124$(obj)/defkeymap.c $(obj)/qtronixmap.c: $(obj)/%.c: $(src)/%.map 122$(obj)/defkeymap.c $(obj)/%.c: $(src)/%.map
125 loadkeys --mktable $< > $@.tmp 123 loadkeys --mktable $< > $@.tmp
126 sed -e 's/^static *//' $@.tmp > $@ 124 sed -e 's/^static *//' $@.tmp > $@
127 rm $@.tmp 125 rm $@.tmp
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index 3c623b67ea1c..8b3317fd46c9 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -117,7 +117,7 @@ struct agp_bridge_driver {
117}; 117};
118 118
119struct agp_bridge_data { 119struct agp_bridge_data {
120 struct agp_version *version; 120 const struct agp_version *version;
121 struct agp_bridge_driver *driver; 121 struct agp_bridge_driver *driver;
122 struct vm_operations_struct *vm_ops; 122 struct vm_operations_struct *vm_ops;
123 void *previous_size; 123 void *previous_size;
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 8cd52984cda5..00b17ae39736 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -409,7 +409,7 @@ static int __devinit uli_agp_init(struct pci_dev *pdev)
409 int i; 409 int i;
410 unsigned size = amd64_fetch_size(); 410 unsigned size = amd64_fetch_size();
411 printk(KERN_INFO "Setting up ULi AGP.\n"); 411 printk(KERN_INFO "Setting up ULi AGP.\n");
412 dev1 = pci_find_slot ((unsigned int)pdev->bus->number,PCI_DEVFN(0,0)); 412 dev1 = pci_get_slot (pdev->bus,PCI_DEVFN(0,0));
413 if (dev1 == NULL) { 413 if (dev1 == NULL) {
414 printk(KERN_INFO PFX "Detected a ULi chipset, " 414 printk(KERN_INFO PFX "Detected a ULi chipset, "
415 "but could not fine the secondary device.\n"); 415 "but could not fine the secondary device.\n");
@@ -442,6 +442,8 @@ static int __devinit uli_agp_init(struct pci_dev *pdev)
442 enuscr= httfea+ (size * 1024 * 1024) - 1; 442 enuscr= httfea+ (size * 1024 * 1024) - 1;
443 pci_write_config_dword(dev1, ULI_X86_64_HTT_FEA_REG, httfea); 443 pci_write_config_dword(dev1, ULI_X86_64_HTT_FEA_REG, httfea);
444 pci_write_config_dword(dev1, ULI_X86_64_ENU_SCR_REG, enuscr); 444 pci_write_config_dword(dev1, ULI_X86_64_ENU_SCR_REG, enuscr);
445
446 pci_dev_put(dev1);
445 return 0; 447 return 0;
446} 448}
447 449
@@ -466,7 +468,7 @@ static int __devinit nforce3_agp_init(struct pci_dev *pdev)
466 468
467 printk(KERN_INFO PFX "Setting up Nforce3 AGP.\n"); 469 printk(KERN_INFO PFX "Setting up Nforce3 AGP.\n");
468 470
469 dev1 = pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(11, 0)); 471 dev1 = pci_get_slot(pdev->bus, PCI_DEVFN(11, 0));
470 if (dev1 == NULL) { 472 if (dev1 == NULL) {
471 printk(KERN_INFO PFX "agpgart: Detected an NVIDIA " 473 printk(KERN_INFO PFX "agpgart: Detected an NVIDIA "
472 "nForce3 chipset, but could not find " 474 "nForce3 chipset, but could not find "
@@ -510,6 +512,8 @@ static int __devinit nforce3_agp_init(struct pci_dev *pdev)
510 pci_write_config_dword(dev1, NVIDIA_X86_64_1_APBASE2, apbase); 512 pci_write_config_dword(dev1, NVIDIA_X86_64_1_APBASE2, apbase);
511 pci_write_config_dword(dev1, NVIDIA_X86_64_1_APLIMIT2, aplimit); 513 pci_write_config_dword(dev1, NVIDIA_X86_64_1_APLIMIT2, aplimit);
512 514
515 pci_dev_put(dev1);
516
513 return 0; 517 return 0;
514} 518}
515 519
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
index 509adc403250..d59e037ddd12 100644
--- a/drivers/char/agp/backend.c
+++ b/drivers/char/agp/backend.c
@@ -44,7 +44,7 @@
44 * past 0.99 at all due to some boolean logic error. */ 44 * past 0.99 at all due to some boolean logic error. */
45#define AGPGART_VERSION_MAJOR 0 45#define AGPGART_VERSION_MAJOR 0
46#define AGPGART_VERSION_MINOR 101 46#define AGPGART_VERSION_MINOR 101
47static struct agp_version agp_current_version = 47static const struct agp_version agp_current_version =
48{ 48{
49 .major = AGPGART_VERSION_MAJOR, 49 .major = AGPGART_VERSION_MAJOR,
50 .minor = AGPGART_VERSION_MINOR, 50 .minor = AGPGART_VERSION_MINOR,
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c
index b788b0a3bbf3..30f730ff81c1 100644
--- a/drivers/char/agp/efficeon-agp.c
+++ b/drivers/char/agp/efficeon-agp.c
@@ -337,13 +337,6 @@ static struct agp_bridge_driver efficeon_driver = {
337 .agp_destroy_page = agp_generic_destroy_page, 337 .agp_destroy_page = agp_generic_destroy_page,
338}; 338};
339 339
340
341static int agp_efficeon_resume(struct pci_dev *pdev)
342{
343 printk(KERN_DEBUG PFX "agp_efficeon_resume()\n");
344 return efficeon_configure();
345}
346
347static int __devinit agp_efficeon_probe(struct pci_dev *pdev, 340static int __devinit agp_efficeon_probe(struct pci_dev *pdev,
348 const struct pci_device_id *ent) 341 const struct pci_device_id *ent)
349{ 342{
@@ -414,11 +407,18 @@ static void __devexit agp_efficeon_remove(struct pci_dev *pdev)
414 agp_put_bridge(bridge); 407 agp_put_bridge(bridge);
415} 408}
416 409
410#ifdef CONFIG_PM
417static int agp_efficeon_suspend(struct pci_dev *dev, pm_message_t state) 411static int agp_efficeon_suspend(struct pci_dev *dev, pm_message_t state)
418{ 412{
419 return 0; 413 return 0;
420} 414}
421 415
416static int agp_efficeon_resume(struct pci_dev *pdev)
417{
418 printk(KERN_DEBUG PFX "agp_efficeon_resume()\n");
419 return efficeon_configure();
420}
421#endif
422 422
423static struct pci_device_id agp_efficeon_pci_table[] = { 423static struct pci_device_id agp_efficeon_pci_table[] = {
424 { 424 {
@@ -439,8 +439,10 @@ static struct pci_driver agp_efficeon_pci_driver = {
439 .id_table = agp_efficeon_pci_table, 439 .id_table = agp_efficeon_pci_table,
440 .probe = agp_efficeon_probe, 440 .probe = agp_efficeon_probe,
441 .remove = agp_efficeon_remove, 441 .remove = agp_efficeon_remove,
442#ifdef CONFIG_PM
442 .suspend = agp_efficeon_suspend, 443 .suspend = agp_efficeon_suspend,
443 .resume = agp_efficeon_resume, 444 .resume = agp_efficeon_resume,
445#endif
444}; 446};
445 447
446static int __init agp_efficeon_init(void) 448static int __init agp_efficeon_init(void)
diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c
index d9c5a9142ad1..0f2ed2aa2d81 100644
--- a/drivers/char/agp/frontend.c
+++ b/drivers/char/agp/frontend.c
@@ -151,35 +151,12 @@ static void agp_add_seg_to_client(struct agp_client *client,
151 client->segments = seg; 151 client->segments = seg;
152} 152}
153 153
154/* Originally taken from linux/mm/mmap.c from the array
155 * protection_map.
156 * The original really should be exported to modules, or
157 * some routine which does the conversion for you
158 */
159
160static const pgprot_t my_protect_map[16] =
161{
162 __P000, __P001, __P010, __P011, __P100, __P101, __P110, __P111,
163 __S000, __S001, __S010, __S011, __S100, __S101, __S110, __S111
164};
165
166static pgprot_t agp_convert_mmap_flags(int prot) 154static pgprot_t agp_convert_mmap_flags(int prot)
167{ 155{
168#define _trans(x,bit1,bit2) \
169((bit1==bit2)?(x&bit1):(x&bit1)?bit2:0)
170
171 unsigned long prot_bits; 156 unsigned long prot_bits;
172 pgprot_t temp;
173
174 prot_bits = _trans(prot, PROT_READ, VM_READ) |
175 _trans(prot, PROT_WRITE, VM_WRITE) |
176 _trans(prot, PROT_EXEC, VM_EXEC);
177
178 prot_bits |= VM_SHARED;
179 157
180 temp = my_protect_map[prot_bits & 0x0000000f]; 158 prot_bits = calc_vm_prot_bits(prot) | VM_SHARED;
181 159 return vm_get_page_prot(prot_bits);
182 return temp;
183} 160}
184 161
185static int agp_create_segment(struct agp_client *client, struct agp_region *region) 162static int agp_create_segment(struct agp_client *client, struct agp_region *region)
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index cc5ea347a8a7..c39200161688 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -568,25 +568,37 @@ static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_
568 *bridge_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD); 568 *bridge_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD);
569 goto done; 569 goto done;
570 570
571 } else if (*requested_mode & AGPSTAT3_4X) {
572 *bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
573 *bridge_agpstat |= AGPSTAT3_4X;
574 goto done;
575
571 } else { 576 } else {
572 577
573 /* 578 /*
574 * If we didn't specify AGPx8, we can only do x4. 579 * If we didn't specify an AGP mode, we see if both
575 * If the hardware can't do x4, we're up shit creek, and never 580 * the graphics card, and the bridge can do x8, and use if so.
576 * should have got this far. 581 * If not, we fall back to x4 mode.
577 */ 582 */
578 *bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD); 583 if ((*bridge_agpstat & AGPSTAT3_8X) && (*vga_agpstat & AGPSTAT3_8X)) {
579 if ((*bridge_agpstat & AGPSTAT3_4X) && (*vga_agpstat & AGPSTAT3_4X)) 584 printk(KERN_INFO PFX "No AGP mode specified. Setting to highest mode "
580 *bridge_agpstat |= AGPSTAT3_4X; 585 "supported by bridge & card (x8).\n");
581 else { 586 *bridge_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD);
582 printk(KERN_INFO PFX "Badness. Don't know which AGP mode to set. " 587 *vga_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD);
583 "[bridge_agpstat:%x vga_agpstat:%x fell back to:- bridge_agpstat:%x vga_agpstat:%x]\n", 588 } else {
584 origbridge, origvga, *bridge_agpstat, *vga_agpstat); 589 printk(KERN_INFO PFX "Fell back to AGPx4 mode because");
585 if (!(*bridge_agpstat & AGPSTAT3_4X)) 590 if (!(*bridge_agpstat & AGPSTAT3_8X)) {
586 printk(KERN_INFO PFX "Bridge couldn't do AGP x4.\n"); 591 printk(KERN_INFO PFX "bridge couldn't do x8. bridge_agpstat:%x (orig=%x)\n",
587 if (!(*vga_agpstat & AGPSTAT3_4X)) 592 *bridge_agpstat, origbridge);
588 printk(KERN_INFO PFX "Graphic card couldn't do AGP x4.\n"); 593 *bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
589 return; 594 *bridge_agpstat |= AGPSTAT3_4X;
595 }
596 if (!(*vga_agpstat & AGPSTAT3_8X)) {
597 printk(KERN_INFO PFX "graphics card couldn't do x8. vga_agpstat:%x (orig=%x)\n",
598 *vga_agpstat, origvga);
599 *vga_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
600 *vga_agpstat |= AGPSTAT3_4X;
601 }
590 } 602 }
591 } 603 }
592 604
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 61ac3809f997..d1ede7db5a12 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -2,14 +2,6 @@
2 * Intel AGPGART routines. 2 * Intel AGPGART routines.
3 */ 3 */
4 4
5/*
6 * Intel(R) 855GM/852GM and 865G support added by David Dawes
7 * <dawes@tungstengraphics.com>.
8 *
9 * Intel(R) 915G/915GM support added by Alan Hourihane
10 * <alanh@tungstengraphics.com>.
11 */
12
13#include <linux/module.h> 5#include <linux/module.h>
14#include <linux/pci.h> 6#include <linux/pci.h>
15#include <linux/init.h> 7#include <linux/init.h>
@@ -17,6 +9,21 @@
17#include <linux/agp_backend.h> 9#include <linux/agp_backend.h>
18#include "agp.h" 10#include "agp.h"
19 11
12#define PCI_DEVICE_ID_INTEL_82946GZ_HB 0x2970
13#define PCI_DEVICE_ID_INTEL_82946GZ_IG 0x2972
14#define PCI_DEVICE_ID_INTEL_82965G_1_HB 0x2980
15#define PCI_DEVICE_ID_INTEL_82965G_1_IG 0x2982
16#define PCI_DEVICE_ID_INTEL_82965Q_HB 0x2990
17#define PCI_DEVICE_ID_INTEL_82965Q_IG 0x2992
18#define PCI_DEVICE_ID_INTEL_82965G_HB 0x29A0
19#define PCI_DEVICE_ID_INTEL_82965G_IG 0x29A2
20
21#define IS_I965 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82946GZ_HB || \
22 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_1_HB || \
23 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965Q_HB || \
24 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB)
25
26
20/* Intel 815 register */ 27/* Intel 815 register */
21#define INTEL_815_APCONT 0x51 28#define INTEL_815_APCONT 0x51
22#define INTEL_815_ATTBASE_MASK ~0x1FFFFFFF 29#define INTEL_815_ATTBASE_MASK ~0x1FFFFFFF
@@ -40,6 +47,8 @@
40#define I915_GMCH_GMS_STOLEN_48M (0x6 << 4) 47#define I915_GMCH_GMS_STOLEN_48M (0x6 << 4)
41#define I915_GMCH_GMS_STOLEN_64M (0x7 << 4) 48#define I915_GMCH_GMS_STOLEN_64M (0x7 << 4)
42 49
50/* Intel 965G registers */
51#define I965_MSAC 0x62
43 52
44/* Intel 7505 registers */ 53/* Intel 7505 registers */
45#define INTEL_I7505_APSIZE 0x74 54#define INTEL_I7505_APSIZE 0x74
@@ -354,6 +363,7 @@ static struct aper_size_info_fixed intel_i830_sizes[] =
354 /* The 64M mode still requires a 128k gatt */ 363 /* The 64M mode still requires a 128k gatt */
355 {64, 16384, 5}, 364 {64, 16384, 5},
356 {256, 65536, 6}, 365 {256, 65536, 6},
366 {512, 131072, 7},
357}; 367};
358 368
359static struct _intel_i830_private { 369static struct _intel_i830_private {
@@ -377,7 +387,11 @@ static void intel_i830_init_gtt_entries(void)
377 /* We obtain the size of the GTT, which is also stored (for some 387 /* We obtain the size of the GTT, which is also stored (for some
378 * reason) at the top of stolen memory. Then we add 4KB to that 388 * reason) at the top of stolen memory. Then we add 4KB to that
379 * for the video BIOS popup, which is also stored in there. */ 389 * for the video BIOS popup, which is also stored in there. */
380 size = agp_bridge->driver->fetch_size() + 4; 390
391 if (IS_I965)
392 size = 512 + 4;
393 else
394 size = agp_bridge->driver->fetch_size() + 4;
381 395
382 if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB || 396 if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB ||
383 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) { 397 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) {
@@ -423,7 +437,7 @@ static void intel_i830_init_gtt_entries(void)
423 if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB || 437 if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
424 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB || 438 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
425 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB || 439 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
426 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB) 440 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || IS_I965 )
427 gtt_entries = MB(48) - KB(size); 441 gtt_entries = MB(48) - KB(size);
428 else 442 else
429 gtt_entries = 0; 443 gtt_entries = 0;
@@ -433,7 +447,7 @@ static void intel_i830_init_gtt_entries(void)
433 if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB || 447 if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
434 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB || 448 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
435 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB || 449 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
436 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB) 450 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || IS_I965)
437 gtt_entries = MB(64) - KB(size); 451 gtt_entries = MB(64) - KB(size);
438 else 452 else
439 gtt_entries = 0; 453 gtt_entries = 0;
@@ -791,6 +805,77 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
791 805
792 return 0; 806 return 0;
793} 807}
808static int intel_i965_fetch_size(void)
809{
810 struct aper_size_info_fixed *values;
811 u32 offset = 0;
812 u8 temp;
813
814#define I965_512MB_ADDRESS_MASK (3<<1)
815
816 values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
817
818 pci_read_config_byte(intel_i830_private.i830_dev, I965_MSAC, &temp);
819 temp &= I965_512MB_ADDRESS_MASK;
820 switch (temp) {
821 case 0x00:
822 offset = 0; /* 128MB */
823 break;
824 case 0x06:
825 offset = 3; /* 512MB */
826 break;
827 default:
828 case 0x02:
829 offset = 2; /* 256MB */
830 break;
831 }
832
833 agp_bridge->previous_size = agp_bridge->current_size = (void *)(values + offset);
834
835 return values[offset].size;
836}
837
838/* The intel i965 automatically initializes the agp aperture during POST.
839+ * Use the memory already set aside for in the GTT.
840+ */
841static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge)
842{
843 int page_order;
844 struct aper_size_info_fixed *size;
845 int num_entries;
846 u32 temp;
847
848 size = agp_bridge->current_size;
849 page_order = size->page_order;
850 num_entries = size->num_entries;
851 agp_bridge->gatt_table_real = NULL;
852
853 pci_read_config_dword(intel_i830_private.i830_dev, I915_MMADDR, &temp);
854
855 temp &= 0xfff00000;
856 intel_i830_private.gtt = ioremap((temp + (512 * 1024)) , 512 * 1024);
857
858 if (!intel_i830_private.gtt)
859 return -ENOMEM;
860
861
862 intel_i830_private.registers = ioremap(temp,128 * 4096);
863 if (!intel_i830_private.registers)
864 return -ENOMEM;
865
866 temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000;
867 global_cache_flush(); /* FIXME: ? */
868
869 /* we have to call this as early as possible after the MMIO base address is known */
870 intel_i830_init_gtt_entries();
871
872 agp_bridge->gatt_table = NULL;
873
874 agp_bridge->gatt_bus_addr = temp;
875
876 return 0;
877}
878
794 879
795static int intel_fetch_size(void) 880static int intel_fetch_size(void)
796{ 881{
@@ -1307,7 +1392,7 @@ static struct agp_bridge_driver intel_830_driver = {
1307 .owner = THIS_MODULE, 1392 .owner = THIS_MODULE,
1308 .aperture_sizes = intel_i830_sizes, 1393 .aperture_sizes = intel_i830_sizes,
1309 .size_type = FIXED_APER_SIZE, 1394 .size_type = FIXED_APER_SIZE,
1310 .num_aperture_sizes = 3, 1395 .num_aperture_sizes = 4,
1311 .needs_scratch_page = TRUE, 1396 .needs_scratch_page = TRUE,
1312 .configure = intel_i830_configure, 1397 .configure = intel_i830_configure,
1313 .fetch_size = intel_i830_fetch_size, 1398 .fetch_size = intel_i830_fetch_size,
@@ -1469,7 +1554,7 @@ static struct agp_bridge_driver intel_915_driver = {
1469 .owner = THIS_MODULE, 1554 .owner = THIS_MODULE,
1470 .aperture_sizes = intel_i830_sizes, 1555 .aperture_sizes = intel_i830_sizes,
1471 .size_type = FIXED_APER_SIZE, 1556 .size_type = FIXED_APER_SIZE,
1472 .num_aperture_sizes = 3, 1557 .num_aperture_sizes = 4,
1473 .needs_scratch_page = TRUE, 1558 .needs_scratch_page = TRUE,
1474 .configure = intel_i915_configure, 1559 .configure = intel_i915_configure,
1475 .fetch_size = intel_i915_fetch_size, 1560 .fetch_size = intel_i915_fetch_size,
@@ -1489,6 +1574,29 @@ static struct agp_bridge_driver intel_915_driver = {
1489 .agp_destroy_page = agp_generic_destroy_page, 1574 .agp_destroy_page = agp_generic_destroy_page,
1490}; 1575};
1491 1576
1577static struct agp_bridge_driver intel_i965_driver = {
1578 .owner = THIS_MODULE,
1579 .aperture_sizes = intel_i830_sizes,
1580 .size_type = FIXED_APER_SIZE,
1581 .num_aperture_sizes = 4,
1582 .needs_scratch_page = TRUE,
1583 .configure = intel_i915_configure,
1584 .fetch_size = intel_i965_fetch_size,
1585 .cleanup = intel_i915_cleanup,
1586 .tlb_flush = intel_i810_tlbflush,
1587 .mask_memory = intel_i810_mask_memory,
1588 .masks = intel_i810_masks,
1589 .agp_enable = intel_i810_agp_enable,
1590 .cache_flush = global_cache_flush,
1591 .create_gatt_table = intel_i965_create_gatt_table,
1592 .free_gatt_table = intel_i830_free_gatt_table,
1593 .insert_memory = intel_i915_insert_entries,
1594 .remove_memory = intel_i915_remove_entries,
1595 .alloc_by_type = intel_i830_alloc_by_type,
1596 .free_by_type = intel_i810_free_by_type,
1597 .agp_alloc_page = agp_generic_alloc_page,
1598 .agp_destroy_page = agp_generic_destroy_page,
1599};
1492 1600
1493static struct agp_bridge_driver intel_7505_driver = { 1601static struct agp_bridge_driver intel_7505_driver = {
1494 .owner = THIS_MODULE, 1602 .owner = THIS_MODULE,
@@ -1684,6 +1792,35 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
1684 bridge->driver = &intel_845_driver; 1792 bridge->driver = &intel_845_driver;
1685 name = "945GM"; 1793 name = "945GM";
1686 break; 1794 break;
1795 case PCI_DEVICE_ID_INTEL_82946GZ_HB:
1796 if (find_i830(PCI_DEVICE_ID_INTEL_82946GZ_IG))
1797 bridge->driver = &intel_i965_driver;
1798 else
1799 bridge->driver = &intel_845_driver;
1800 name = "946GZ";
1801 break;
1802 case PCI_DEVICE_ID_INTEL_82965G_1_HB:
1803 if (find_i830(PCI_DEVICE_ID_INTEL_82965G_1_IG))
1804 bridge->driver = &intel_i965_driver;
1805 else
1806 bridge->driver = &intel_845_driver;
1807 name = "965G";
1808 break;
1809 case PCI_DEVICE_ID_INTEL_82965Q_HB:
1810 if (find_i830(PCI_DEVICE_ID_INTEL_82965Q_IG))
1811 bridge->driver = &intel_i965_driver;
1812 else
1813 bridge->driver = &intel_845_driver;
1814 name = "965Q";
1815 break;
1816 case PCI_DEVICE_ID_INTEL_82965G_HB:
1817 if (find_i830(PCI_DEVICE_ID_INTEL_82965G_IG))
1818 bridge->driver = &intel_i965_driver;
1819 else
1820 bridge->driver = &intel_845_driver;
1821 name = "965G";
1822 break;
1823
1687 case PCI_DEVICE_ID_INTEL_7505_0: 1824 case PCI_DEVICE_ID_INTEL_7505_0:
1688 bridge->driver = &intel_7505_driver; 1825 bridge->driver = &intel_7505_driver;
1689 name = "E7505"; 1826 name = "E7505";
@@ -1766,6 +1903,7 @@ static void __devexit agp_intel_remove(struct pci_dev *pdev)
1766 agp_put_bridge(bridge); 1903 agp_put_bridge(bridge);
1767} 1904}
1768 1905
1906#ifdef CONFIG_PM
1769static int agp_intel_resume(struct pci_dev *pdev) 1907static int agp_intel_resume(struct pci_dev *pdev)
1770{ 1908{
1771 struct agp_bridge_data *bridge = pci_get_drvdata(pdev); 1909 struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
@@ -1786,9 +1924,12 @@ static int agp_intel_resume(struct pci_dev *pdev)
1786 intel_i830_configure(); 1924 intel_i830_configure();
1787 else if (bridge->driver == &intel_810_driver) 1925 else if (bridge->driver == &intel_810_driver)
1788 intel_i810_configure(); 1926 intel_i810_configure();
1927 else if (bridge->driver == &intel_i965_driver)
1928 intel_i915_configure();
1789 1929
1790 return 0; 1930 return 0;
1791} 1931}
1932#endif
1792 1933
1793static struct pci_device_id agp_intel_pci_table[] = { 1934static struct pci_device_id agp_intel_pci_table[] = {
1794#define ID(x) \ 1935#define ID(x) \
@@ -1825,6 +1966,10 @@ static struct pci_device_id agp_intel_pci_table[] = {
1825 ID(PCI_DEVICE_ID_INTEL_82915GM_HB), 1966 ID(PCI_DEVICE_ID_INTEL_82915GM_HB),
1826 ID(PCI_DEVICE_ID_INTEL_82945G_HB), 1967 ID(PCI_DEVICE_ID_INTEL_82945G_HB),
1827 ID(PCI_DEVICE_ID_INTEL_82945GM_HB), 1968 ID(PCI_DEVICE_ID_INTEL_82945GM_HB),
1969 ID(PCI_DEVICE_ID_INTEL_82946GZ_HB),
1970 ID(PCI_DEVICE_ID_INTEL_82965G_1_HB),
1971 ID(PCI_DEVICE_ID_INTEL_82965Q_HB),
1972 ID(PCI_DEVICE_ID_INTEL_82965G_HB),
1828 { } 1973 { }
1829}; 1974};
1830 1975
@@ -1835,7 +1980,9 @@ static struct pci_driver agp_intel_pci_driver = {
1835 .id_table = agp_intel_pci_table, 1980 .id_table = agp_intel_pci_table,
1836 .probe = agp_intel_probe, 1981 .probe = agp_intel_probe,
1837 .remove = __devexit_p(agp_intel_remove), 1982 .remove = __devexit_p(agp_intel_remove),
1983#ifdef CONFIG_PM
1838 .resume = agp_intel_resume, 1984 .resume = agp_intel_resume,
1985#endif
1839}; 1986};
1840 1987
1841static int __init agp_intel_init(void) 1988static int __init agp_intel_init(void)
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
index b8ec25d17478..c149ac9ce9a7 100644
--- a/drivers/char/agp/via-agp.c
+++ b/drivers/char/agp/via-agp.c
@@ -9,7 +9,7 @@
9#include <linux/agp_backend.h> 9#include <linux/agp_backend.h>
10#include "agp.h" 10#include "agp.h"
11 11
12static struct pci_device_id agp_via_pci_table[]; 12static const struct pci_device_id agp_via_pci_table[];
13 13
14#define VIA_GARTCTRL 0x80 14#define VIA_GARTCTRL 0x80
15#define VIA_APSIZE 0x84 15#define VIA_APSIZE 0x84
@@ -485,7 +485,7 @@ static int agp_via_resume(struct pci_dev *pdev)
485#endif /* CONFIG_PM */ 485#endif /* CONFIG_PM */
486 486
487/* must be the same order as name table above */ 487/* must be the same order as name table above */
488static struct pci_device_id agp_via_pci_table[] = { 488static const struct pci_device_id agp_via_pci_table[] = {
489#define ID(x) \ 489#define ID(x) \
490 { \ 490 { \
491 .class = (PCI_CLASS_BRIDGE_HOST << 8), \ 491 .class = (PCI_CLASS_BRIDGE_HOST << 8), \
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 9d6713a93ed7..d0e92ed0a367 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -1958,7 +1958,7 @@ static void show_serial_version(void)
1958} 1958}
1959 1959
1960 1960
1961static struct tty_operations serial_ops = { 1961static const struct tty_operations serial_ops = {
1962 .open = rs_open, 1962 .open = rs_open,
1963 .close = rs_close, 1963 .close = rs_close,
1964 .write = rs_write, 1964 .write = rs_write,
diff --git a/drivers/char/briq_panel.c b/drivers/char/briq_panel.c
index a0e5eac5f33a..b8c22255f6ad 100644
--- a/drivers/char/briq_panel.c
+++ b/drivers/char/briq_panel.c
@@ -87,7 +87,7 @@ static int briq_panel_release(struct inode *ino, struct file *filep)
87 return 0; 87 return 0;
88} 88}
89 89
90static ssize_t briq_panel_read(struct file *file, char *buf, size_t count, 90static ssize_t briq_panel_read(struct file *file, char __user *buf, size_t count,
91 loff_t *ppos) 91 loff_t *ppos)
92{ 92{
93 unsigned short c; 93 unsigned short c;
@@ -135,7 +135,7 @@ static void scroll_vfd( void )
135 vfd_cursor = 20; 135 vfd_cursor = 20;
136} 136}
137 137
138static ssize_t briq_panel_write(struct file *file, const char *buf, size_t len, 138static ssize_t briq_panel_write(struct file *file, const char __user *buf, size_t len,
139 loff_t *ppos) 139 loff_t *ppos)
140{ 140{
141 size_t indx = len; 141 size_t indx = len;
@@ -150,19 +150,22 @@ static ssize_t briq_panel_write(struct file *file, const char *buf, size_t len,
150 return -EBUSY; 150 return -EBUSY;
151 151
152 for (;;) { 152 for (;;) {
153 char c;
153 if (!indx) 154 if (!indx)
154 break; 155 break;
156 if (get_user(c, buf))
157 return -EFAULT;
155 if (esc) { 158 if (esc) {
156 set_led(*buf); 159 set_led(c);
157 esc = 0; 160 esc = 0;
158 } else if (*buf == 27) { 161 } else if (c == 27) {
159 esc = 1; 162 esc = 1;
160 } else if (*buf == 12) { 163 } else if (c == 12) {
161 /* do a form feed */ 164 /* do a form feed */
162 for (i=0; i<40; i++) 165 for (i=0; i<40; i++)
163 vfd[i] = ' '; 166 vfd[i] = ' ';
164 vfd_cursor = 0; 167 vfd_cursor = 0;
165 } else if (*buf == 10) { 168 } else if (c == 10) {
166 if (vfd_cursor < 20) 169 if (vfd_cursor < 20)
167 vfd_cursor = 20; 170 vfd_cursor = 20;
168 else if (vfd_cursor < 40) 171 else if (vfd_cursor < 40)
@@ -175,7 +178,7 @@ static ssize_t briq_panel_write(struct file *file, const char *buf, size_t len,
175 /* just a character */ 178 /* just a character */
176 if (vfd_cursor > 39) 179 if (vfd_cursor > 39)
177 scroll_vfd(); 180 scroll_vfd();
178 vfd[vfd_cursor++] = *buf; 181 vfd[vfd_cursor++] = c;
179 } 182 }
180 indx--; 183 indx--;
181 buf++; 184 buf++;
@@ -202,7 +205,7 @@ static struct miscdevice briq_panel_miscdev = {
202static int __init briq_panel_init(void) 205static int __init briq_panel_init(void)
203{ 206{
204 struct device_node *root = find_path_device("/"); 207 struct device_node *root = find_path_device("/");
205 char *machine; 208 const char *machine;
206 int i; 209 int i;
207 210
208 machine = get_property(root, "model", NULL); 211 machine = get_property(root, "model", NULL);
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index c1c67281750d..f85b4eb16618 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -5205,7 +5205,7 @@ done:
5205 extra ports are ignored. 5205 extra ports are ignored.
5206 */ 5206 */
5207 5207
5208static struct tty_operations cy_ops = { 5208static const struct tty_operations cy_ops = {
5209 .open = cy_open, 5209 .open = cy_open,
5210 .close = cy_close, 5210 .close = cy_close,
5211 .write = cy_write, 5211 .write = cy_write,
diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig
index 5278c388d3e7..ef833a1c27eb 100644
--- a/drivers/char/drm/Kconfig
+++ b/drivers/char/drm/Kconfig
@@ -60,7 +60,9 @@ config DRM_I830
60 Choose this option if you have a system that has Intel 830M, 845G, 60 Choose this option if you have a system that has Intel 830M, 845G,
61 852GM, 855GM or 865G integrated graphics. If M is selected, the 61 852GM, 855GM or 865G integrated graphics. If M is selected, the
62 module will be called i830. AGP support is required for this driver 62 module will be called i830. AGP support is required for this driver
63 to work. This driver will eventually be replaced by the i915 one. 63 to work. This driver is used by the older X releases X.org 6.7 and
64 XFree86 4.3. If unsure, build this and i915 as modules and the X server
65 will load the correct one.
64 66
65config DRM_I915 67config DRM_I915
66 tristate "i915 driver" 68 tristate "i915 driver"
@@ -68,8 +70,9 @@ config DRM_I915
68 Choose this option if you have a system that has Intel 830M, 845G, 70 Choose this option if you have a system that has Intel 830M, 845G,
69 852GM, 855GM 865G or 915G integrated graphics. If M is selected, the 71 852GM, 855GM 865G or 915G integrated graphics. If M is selected, the
70 module will be called i915. AGP support is required for this driver 72 module will be called i915. AGP support is required for this driver
71 to work. This driver will eventually replace the I830 driver, when 73 to work. This driver is used by the Intel driver in X.org 6.8 and
72 later release of X start to use the new DDX and DRI. 74 XFree86 4.4 and above. If unsure, build this and i830 as modules and
75 the X server will load the correct one.
73 76
74endchoice 77endchoice
75 78
diff --git a/drivers/char/drm/Makefile b/drivers/char/drm/Makefile
index 9d180c42816c..3ad0f648c6b2 100644
--- a/drivers/char/drm/Makefile
+++ b/drivers/char/drm/Makefile
@@ -6,7 +6,7 @@ drm-objs := drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \
6 drm_drv.o drm_fops.o drm_ioctl.o drm_irq.o \ 6 drm_drv.o drm_fops.o drm_ioctl.o drm_irq.o \
7 drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \ 7 drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \
8 drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \ 8 drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \
9 drm_sysfs.o 9 drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o
10 10
11tdfx-objs := tdfx_drv.o 11tdfx-objs := tdfx_drv.o
12r128-objs := r128_drv.o r128_cce.o r128_state.o r128_irq.o 12r128-objs := r128_drv.o r128_cce.o r128_state.o r128_irq.o
@@ -16,9 +16,9 @@ i830-objs := i830_drv.o i830_dma.o i830_irq.o
16i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o 16i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o
17radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o 17radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o
18ffb-objs := ffb_drv.o ffb_context.o 18ffb-objs := ffb_drv.o ffb_context.o
19sis-objs := sis_drv.o sis_ds.o sis_mm.o 19sis-objs := sis_drv.o sis_mm.o
20savage-objs := savage_drv.o savage_bci.o savage_state.o 20savage-objs := savage_drv.o savage_bci.o savage_state.o
21via-objs := via_irq.o via_drv.o via_ds.o via_map.o via_mm.o via_dma.o via_verifier.o via_video.o via_dmablit.o 21via-objs := via_irq.o via_drv.o via_map.o via_mm.o via_dma.o via_verifier.o via_video.o via_dmablit.o
22 22
23ifeq ($(CONFIG_COMPAT),y) 23ifeq ($(CONFIG_COMPAT),y)
24drm-objs += drm_ioc32.o 24drm-objs += drm_ioc32.o
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index d2a56182bc35..7690a59ace04 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -79,6 +79,7 @@
79#define __OS_HAS_MTRR (defined(CONFIG_MTRR)) 79#define __OS_HAS_MTRR (defined(CONFIG_MTRR))
80 80
81#include "drm_os_linux.h" 81#include "drm_os_linux.h"
82#include "drm_hashtab.h"
82 83
83/***********************************************************************/ 84/***********************************************************************/
84/** \name DRM template customization defaults */ 85/** \name DRM template customization defaults */
@@ -104,7 +105,7 @@
104#define DRM_DEBUG_CODE 2 /**< Include debugging code if > 1, then 105#define DRM_DEBUG_CODE 2 /**< Include debugging code if > 1, then
105 also include looping detection. */ 106 also include looping detection. */
106 107
107#define DRM_HASH_SIZE 16 /**< Size of key hash table. Must be power of 2. */ 108#define DRM_MAGIC_HASH_ORDER 4 /**< Size of key hash table. Must be power of 2. */
108#define DRM_KERNEL_CONTEXT 0 /**< Change drm_resctx if changed */ 109#define DRM_KERNEL_CONTEXT 0 /**< Change drm_resctx if changed */
109#define DRM_RESERVED_CONTEXTS 1 /**< Change drm_resctx if changed */ 110#define DRM_RESERVED_CONTEXTS 1 /**< Change drm_resctx if changed */
110#define DRM_LOOPING_LIMIT 5000000 111#define DRM_LOOPING_LIMIT 5000000
@@ -134,19 +135,12 @@
134#define DRM_MEM_CTXBITMAP 18 135#define DRM_MEM_CTXBITMAP 18
135#define DRM_MEM_STUB 19 136#define DRM_MEM_STUB 19
136#define DRM_MEM_SGLISTS 20 137#define DRM_MEM_SGLISTS 20
137#define DRM_MEM_CTXLIST 21 138#define DRM_MEM_CTXLIST 21
139#define DRM_MEM_MM 22
140#define DRM_MEM_HASHTAB 23
138 141
139#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8) 142#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
140 143#define DRM_MAP_HASH_OFFSET 0x10000000
141/*@}*/
142
143/***********************************************************************/
144/** \name Backward compatibility section */
145/*@{*/
146
147#define DRM_RPR_ARG(vma) vma,
148
149#define VM_OFFSET(vma) ((vma)->vm_pgoff << PAGE_SHIFT)
150 144
151/*@}*/ 145/*@}*/
152 146
@@ -211,8 +205,6 @@
211/*@{*/ 205/*@{*/
212 206
213#define DRM_ARRAY_SIZE(x) ARRAY_SIZE(x) 207#define DRM_ARRAY_SIZE(x) ARRAY_SIZE(x)
214#define DRM_MIN(a,b) min(a,b)
215#define DRM_MAX(a,b) max(a,b)
216 208
217#define DRM_LEFTCOUNT(x) (((x)->rp + (x)->count - (x)->wp) % ((x)->count + 1)) 209#define DRM_LEFTCOUNT(x) (((x)->rp + (x)->count - (x)->wp) % ((x)->count + 1))
218#define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x)) 210#define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x))
@@ -286,7 +278,8 @@ typedef struct drm_devstate {
286} drm_devstate_t; 278} drm_devstate_t;
287 279
288typedef struct drm_magic_entry { 280typedef struct drm_magic_entry {
289 drm_magic_t magic; 281 drm_hash_item_t hash_item;
282 struct list_head head;
290 struct drm_file *priv; 283 struct drm_file *priv;
291 struct drm_magic_entry *next; 284 struct drm_magic_entry *next;
292} drm_magic_entry_t; 285} drm_magic_entry_t;
@@ -493,6 +486,7 @@ typedef struct drm_sigdata {
493 */ 486 */
494typedef struct drm_map_list { 487typedef struct drm_map_list {
495 struct list_head head; /**< list head */ 488 struct list_head head; /**< list head */
489 drm_hash_item_t hash;
496 drm_map_t *map; /**< mapping */ 490 drm_map_t *map; /**< mapping */
497 unsigned int user_token; 491 unsigned int user_token;
498} drm_map_list_t; 492} drm_map_list_t;
@@ -527,6 +521,22 @@ typedef struct ati_pcigart_info {
527 drm_local_map_t mapping; 521 drm_local_map_t mapping;
528} drm_ati_pcigart_info; 522} drm_ati_pcigart_info;
529 523
524/*
525 * Generic memory manager structs
526 */
527typedef struct drm_mm_node {
528 struct list_head fl_entry;
529 struct list_head ml_entry;
530 int free;
531 unsigned long start;
532 unsigned long size;
533 void *private;
534} drm_mm_node_t;
535
536typedef struct drm_mm {
537 drm_mm_node_t root_node;
538} drm_mm_t;
539
530/** 540/**
531 * DRM driver structure. This structure represent the common code for 541 * DRM driver structure. This structure represent the common code for
532 * a family of cards. There will one drm_device for each card present 542 * a family of cards. There will one drm_device for each card present
@@ -646,13 +656,15 @@ typedef struct drm_device {
646 /*@{ */ 656 /*@{ */
647 drm_file_t *file_first; /**< file list head */ 657 drm_file_t *file_first; /**< file list head */
648 drm_file_t *file_last; /**< file list tail */ 658 drm_file_t *file_last; /**< file list tail */
649 drm_magic_head_t magiclist[DRM_HASH_SIZE]; /**< magic hash table */ 659 drm_open_hash_t magiclist; /**< magic hash table */
660 struct list_head magicfree;
650 /*@} */ 661 /*@} */
651 662
652 /** \name Memory management */ 663 /** \name Memory management */
653 /*@{ */ 664 /*@{ */
654 drm_map_list_t *maplist; /**< Linked list of regions */ 665 drm_map_list_t *maplist; /**< Linked list of regions */
655 int map_count; /**< Number of mappable regions */ 666 int map_count; /**< Number of mappable regions */
667 drm_open_hash_t map_hash; /**< User token hash table for maps */
656 668
657 /** \name Context handle management */ 669 /** \name Context handle management */
658 /*@{ */ 670 /*@{ */
@@ -711,10 +723,8 @@ typedef struct drm_device {
711 drm_agp_head_t *agp; /**< AGP data */ 723 drm_agp_head_t *agp; /**< AGP data */
712 724
713 struct pci_dev *pdev; /**< PCI device structure */ 725 struct pci_dev *pdev; /**< PCI device structure */
714 int pci_domain; /**< PCI bus domain number */ 726 int pci_vendor; /**< PCI vendor id */
715 int pci_bus; /**< PCI bus number */ 727 int pci_device; /**< PCI device id */
716 int pci_slot; /**< PCI slot number */
717 int pci_func; /**< PCI function number */
718#ifdef __alpha__ 728#ifdef __alpha__
719 struct pci_controller *hose; 729 struct pci_controller *hose;
720#endif 730#endif
@@ -736,6 +746,12 @@ static __inline__ int drm_core_check_feature(struct drm_device *dev,
736 return ((dev->driver->driver_features & feature) ? 1 : 0); 746 return ((dev->driver->driver_features & feature) ? 1 : 0);
737} 747}
738 748
749#ifdef __alpha__
750#define drm_get_pci_domain(dev) dev->hose->bus->number
751#else
752#define drm_get_pci_domain(dev) 0
753#endif
754
739#if __OS_HAS_AGP 755#if __OS_HAS_AGP
740static inline int drm_core_has_AGP(struct drm_device *dev) 756static inline int drm_core_has_AGP(struct drm_device *dev)
741{ 757{
@@ -1011,6 +1027,18 @@ extern struct class_device *drm_sysfs_device_add(struct class *cs,
1011 drm_head_t *head); 1027 drm_head_t *head);
1012extern void drm_sysfs_device_remove(struct class_device *class_dev); 1028extern void drm_sysfs_device_remove(struct class_device *class_dev);
1013 1029
1030/*
1031 * Basic memory manager support (drm_mm.c)
1032 */
1033extern drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent,
1034 unsigned long size,
1035 unsigned alignment);
1036extern void drm_mm_put_block(drm_mm_t *mm, drm_mm_node_t *cur);
1037extern drm_mm_node_t *drm_mm_search_free(const drm_mm_t *mm, unsigned long size,
1038 unsigned alignment, int best_match);
1039extern int drm_mm_init(drm_mm_t *mm, unsigned long start, unsigned long size);
1040extern void drm_mm_takedown(drm_mm_t *mm);
1041
1014/* Inline replacements for DRM_IOREMAP macros */ 1042/* Inline replacements for DRM_IOREMAP macros */
1015static __inline__ void drm_core_ioremap(struct drm_map *map, 1043static __inline__ void drm_core_ioremap(struct drm_map *map,
1016 struct drm_device *dev) 1044 struct drm_device *dev)
diff --git a/drivers/char/drm/drm_auth.c b/drivers/char/drm/drm_auth.c
index 2a37586a7ee8..c7b19d35bcd6 100644
--- a/drivers/char/drm/drm_auth.c
+++ b/drivers/char/drm/drm_auth.c
@@ -36,20 +36,6 @@
36#include "drmP.h" 36#include "drmP.h"
37 37
38/** 38/**
39 * Generate a hash key from a magic.
40 *
41 * \param magic magic.
42 * \return hash key.
43 *
44 * The key is the modulus of the hash table size, #DRM_HASH_SIZE, which must be
45 * a power of 2.
46 */
47static int drm_hash_magic(drm_magic_t magic)
48{
49 return magic & (DRM_HASH_SIZE - 1);
50}
51
52/**
53 * Find the file with the given magic number. 39 * Find the file with the given magic number.
54 * 40 *
55 * \param dev DRM device. 41 * \param dev DRM device.
@@ -63,14 +49,12 @@ static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic)
63{ 49{
64 drm_file_t *retval = NULL; 50 drm_file_t *retval = NULL;
65 drm_magic_entry_t *pt; 51 drm_magic_entry_t *pt;
66 int hash = drm_hash_magic(magic); 52 drm_hash_item_t *hash;
67 53
68 mutex_lock(&dev->struct_mutex); 54 mutex_lock(&dev->struct_mutex);
69 for (pt = dev->magiclist[hash].head; pt; pt = pt->next) { 55 if (!drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
70 if (pt->magic == magic) { 56 pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item);
71 retval = pt->priv; 57 retval = pt->priv;
72 break;
73 }
74 } 58 }
75 mutex_unlock(&dev->struct_mutex); 59 mutex_unlock(&dev->struct_mutex);
76 return retval; 60 return retval;
@@ -90,28 +74,20 @@ static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic)
90static int drm_add_magic(drm_device_t * dev, drm_file_t * priv, 74static int drm_add_magic(drm_device_t * dev, drm_file_t * priv,
91 drm_magic_t magic) 75 drm_magic_t magic)
92{ 76{
93 int hash;
94 drm_magic_entry_t *entry; 77 drm_magic_entry_t *entry;
95 78
96 DRM_DEBUG("%d\n", magic); 79 DRM_DEBUG("%d\n", magic);
97 80
98 hash = drm_hash_magic(magic);
99 entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC); 81 entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC);
100 if (!entry) 82 if (!entry)
101 return -ENOMEM; 83 return -ENOMEM;
102 memset(entry, 0, sizeof(*entry)); 84 memset(entry, 0, sizeof(*entry));
103 entry->magic = magic;
104 entry->priv = priv; 85 entry->priv = priv;
105 entry->next = NULL;
106 86
87 entry->hash_item.key = (unsigned long)magic;
107 mutex_lock(&dev->struct_mutex); 88 mutex_lock(&dev->struct_mutex);
108 if (dev->magiclist[hash].tail) { 89 drm_ht_insert_item(&dev->magiclist, &entry->hash_item);
109 dev->magiclist[hash].tail->next = entry; 90 list_add_tail(&entry->head, &dev->magicfree);
110 dev->magiclist[hash].tail = entry;
111 } else {
112 dev->magiclist[hash].head = entry;
113 dev->magiclist[hash].tail = entry;
114 }
115 mutex_unlock(&dev->struct_mutex); 91 mutex_unlock(&dev->struct_mutex);
116 92
117 return 0; 93 return 0;
@@ -128,34 +104,24 @@ static int drm_add_magic(drm_device_t * dev, drm_file_t * priv,
128 */ 104 */
129static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic) 105static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic)
130{ 106{
131 drm_magic_entry_t *prev = NULL;
132 drm_magic_entry_t *pt; 107 drm_magic_entry_t *pt;
133 int hash; 108 drm_hash_item_t *hash;
134 109
135 DRM_DEBUG("%d\n", magic); 110 DRM_DEBUG("%d\n", magic);
136 hash = drm_hash_magic(magic);
137 111
138 mutex_lock(&dev->struct_mutex); 112 mutex_lock(&dev->struct_mutex);
139 for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) { 113 if (drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
140 if (pt->magic == magic) { 114 mutex_unlock(&dev->struct_mutex);
141 if (dev->magiclist[hash].head == pt) { 115 return -EINVAL;
142 dev->magiclist[hash].head = pt->next;
143 }
144 if (dev->magiclist[hash].tail == pt) {
145 dev->magiclist[hash].tail = prev;
146 }
147 if (prev) {
148 prev->next = pt->next;
149 }
150 mutex_unlock(&dev->struct_mutex);
151 return 0;
152 }
153 } 116 }
117 pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item);
118 drm_ht_remove_item(&dev->magiclist, hash);
119 list_del(&pt->head);
154 mutex_unlock(&dev->struct_mutex); 120 mutex_unlock(&dev->struct_mutex);
155 121
156 drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); 122 drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
157 123
158 return -EINVAL; 124 return 0;
159} 125}
160 126
161/** 127/**
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
index 006b06d29727..029baea33b62 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -65,43 +65,29 @@ static drm_map_list_t *drm_find_matching_map(drm_device_t *dev,
65 return NULL; 65 return NULL;
66} 66}
67 67
68/* 68static int drm_map_handle(drm_device_t *dev, drm_hash_item_t *hash,
69 * Used to allocate 32-bit handles for mappings. 69 unsigned long user_token, int hashed_handle)
70 */
71#define START_RANGE 0x10000000
72#define END_RANGE 0x40000000
73
74#ifdef _LP64
75static __inline__ unsigned int HandleID(unsigned long lhandle,
76 drm_device_t *dev)
77{ 70{
78 static unsigned int map32_handle = START_RANGE; 71 int use_hashed_handle;
79 unsigned int hash; 72#if (BITS_PER_LONG == 64)
80 73 use_hashed_handle = ((user_token & 0xFFFFFFFF00000000UL) || hashed_handle);
81 if (lhandle & 0xffffffff00000000) { 74#elif (BITS_PER_LONG == 32)
82 hash = map32_handle; 75 use_hashed_handle = hashed_handle;
83 map32_handle += PAGE_SIZE; 76#else
84 if (map32_handle > END_RANGE) 77#error Unsupported long size. Neither 64 nor 32 bits.
85 map32_handle = START_RANGE; 78#endif
86 } else
87 hash = lhandle;
88
89 while (1) {
90 drm_map_list_t *_entry;
91 list_for_each_entry(_entry, &dev->maplist->head, head) {
92 if (_entry->user_token == hash)
93 break;
94 }
95 if (&_entry->head == &dev->maplist->head)
96 return hash;
97 79
98 hash += PAGE_SIZE; 80 if (!use_hashed_handle) {
99 map32_handle += PAGE_SIZE; 81 int ret;
82 hash->key = user_token;
83 ret = drm_ht_insert_item(&dev->map_hash, hash);
84 if (ret != -EINVAL)
85 return ret;
100 } 86 }
87 return drm_ht_just_insert_please(&dev->map_hash, hash,
88 user_token, 32 - PAGE_SHIFT - 3,
89 PAGE_SHIFT, DRM_MAP_HASH_OFFSET);
101} 90}
102#else
103# define HandleID(x,dev) (unsigned int)(x)
104#endif
105 91
106/** 92/**
107 * Ioctl to specify a range of memory that is available for mapping by a non-root process. 93 * Ioctl to specify a range of memory that is available for mapping by a non-root process.
@@ -123,6 +109,8 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
123 drm_map_t *map; 109 drm_map_t *map;
124 drm_map_list_t *list; 110 drm_map_list_t *list;
125 drm_dma_handle_t *dmah; 111 drm_dma_handle_t *dmah;
112 unsigned long user_token;
113 int ret;
126 114
127 map = drm_alloc(sizeof(*map), DRM_MEM_MAPS); 115 map = drm_alloc(sizeof(*map), DRM_MEM_MAPS);
128 if (!map) 116 if (!map)
@@ -257,11 +245,20 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
257 245
258 mutex_lock(&dev->struct_mutex); 246 mutex_lock(&dev->struct_mutex);
259 list_add(&list->head, &dev->maplist->head); 247 list_add(&list->head, &dev->maplist->head);
248
260 /* Assign a 32-bit handle */ 249 /* Assign a 32-bit handle */
261 /* We do it here so that dev->struct_mutex protects the increment */ 250 /* We do it here so that dev->struct_mutex protects the increment */
262 list->user_token = HandleID(map->type == _DRM_SHM 251 user_token = (map->type == _DRM_SHM) ? (unsigned long)map->handle :
263 ? (unsigned long)map->handle 252 map->offset;
264 : map->offset, dev); 253 ret = drm_map_handle(dev, &list->hash, user_token, 0);
254 if (ret) {
255 drm_free(map, sizeof(*map), DRM_MEM_MAPS);
256 drm_free(list, sizeof(*list), DRM_MEM_MAPS);
257 mutex_unlock(&dev->struct_mutex);
258 return ret;
259 }
260
261 list->user_token = list->hash.key;
265 mutex_unlock(&dev->struct_mutex); 262 mutex_unlock(&dev->struct_mutex);
266 263
267 *maplist = list; 264 *maplist = list;
@@ -346,6 +343,7 @@ int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)
346 343
347 if (r_list->map == map) { 344 if (r_list->map == map) {
348 list_del(list); 345 list_del(list);
346 drm_ht_remove_key(&dev->map_hash, r_list->user_token);
349 drm_free(list, sizeof(*list), DRM_MEM_MAPS); 347 drm_free(list, sizeof(*list), DRM_MEM_MAPS);
350 break; 348 break;
351 } 349 }
@@ -441,8 +439,10 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
441 return -EINVAL; 439 return -EINVAL;
442 } 440 }
443 441
444 if (!map) 442 if (!map) {
443 mutex_unlock(&dev->struct_mutex);
445 return -EINVAL; 444 return -EINVAL;
445 }
446 446
447 /* Register and framebuffer maps are permanent */ 447 /* Register and framebuffer maps are permanent */
448 if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) { 448 if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) {
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index 3c0b882a8e72..b366c5b1bd16 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -118,7 +118,7 @@ static drm_ioctl_desc_t drm_ioctls[] = {
118 [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0}, 118 [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0},
119}; 119};
120 120
121#define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( drm_ioctls ) 121#define DRIVER_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
122 122
123/** 123/**
124 * Take down the DRM device. 124 * Take down the DRM device.
@@ -155,12 +155,13 @@ int drm_lastclose(drm_device_t * dev)
155 del_timer(&dev->timer); 155 del_timer(&dev->timer);
156 156
157 /* Clear pid list */ 157 /* Clear pid list */
158 for (i = 0; i < DRM_HASH_SIZE; i++) { 158 if (dev->magicfree.next) {
159 for (pt = dev->magiclist[i].head; pt; pt = next) { 159 list_for_each_entry_safe(pt, next, &dev->magicfree, head) {
160 next = pt->next; 160 list_del(&pt->head);
161 drm_ht_remove_item(&dev->magiclist, &pt->hash_item);
161 drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); 162 drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
162 } 163 }
163 dev->magiclist[i].head = dev->magiclist[i].tail = NULL; 164 drm_ht_remove(&dev->magiclist);
164 } 165 }
165 166
166 /* Clear AGP information */ 167 /* Clear AGP information */
@@ -299,6 +300,7 @@ static void drm_cleanup(drm_device_t * dev)
299 if (dev->maplist) { 300 if (dev->maplist) {
300 drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS); 301 drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
301 dev->maplist = NULL; 302 dev->maplist = NULL;
303 drm_ht_remove(&dev->map_hash);
302 } 304 }
303 305
304 drm_ctxbitmap_cleanup(dev); 306 drm_ctxbitmap_cleanup(dev);
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
index b7f7951c4587..898f47dafec0 100644
--- a/drivers/char/drm/drm_fops.c
+++ b/drivers/char/drm/drm_fops.c
@@ -53,6 +53,8 @@ static int drm_setup(drm_device_t * dev)
53 return ret; 53 return ret;
54 } 54 }
55 55
56 dev->magicfree.next = NULL;
57
56 /* prebuild the SAREA */ 58 /* prebuild the SAREA */
57 i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM, _DRM_CONTAINS_LOCK, &map); 59 i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM, _DRM_CONTAINS_LOCK, &map);
58 if (i != 0) 60 if (i != 0)
@@ -69,13 +71,11 @@ static int drm_setup(drm_device_t * dev)
69 return i; 71 return i;
70 } 72 }
71 73
72 for (i = 0; i < DRM_ARRAY_SIZE(dev->counts); i++) 74 for (i = 0; i < ARRAY_SIZE(dev->counts); i++)
73 atomic_set(&dev->counts[i], 0); 75 atomic_set(&dev->counts[i], 0);
74 76
75 for (i = 0; i < DRM_HASH_SIZE; i++) { 77 drm_ht_create(&dev->magiclist, DRM_MAGIC_HASH_ORDER);
76 dev->magiclist[i].head = NULL; 78 INIT_LIST_HEAD(&dev->magicfree);
77 dev->magiclist[i].tail = NULL;
78 }
79 79
80 dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist), DRM_MEM_CTXLIST); 80 dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist), DRM_MEM_CTXLIST);
81 if (dev->ctxlist == NULL) 81 if (dev->ctxlist == NULL)
diff --git a/drivers/char/drm/drm_hashtab.c b/drivers/char/drm/drm_hashtab.c
new file mode 100644
index 000000000000..a0b2d6802ae4
--- /dev/null
+++ b/drivers/char/drm/drm_hashtab.c
@@ -0,0 +1,190 @@
1/**************************************************************************
2 *
3 * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 *
27 **************************************************************************/
28/*
29 * Simple open hash tab implementation.
30 *
31 * Authors:
32 * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
33 */
34
35#include "drmP.h"
36#include "drm_hashtab.h"
37#include <linux/hash.h>
38
39int drm_ht_create(drm_open_hash_t *ht, unsigned int order)
40{
41 unsigned int i;
42
43 ht->size = 1 << order;
44 ht->order = order;
45 ht->fill = 0;
46 ht->table = vmalloc(ht->size*sizeof(*ht->table));
47 if (!ht->table) {
48 DRM_ERROR("Out of memory for hash table\n");
49 return -ENOMEM;
50 }
51 for (i=0; i< ht->size; ++i) {
52 INIT_HLIST_HEAD(&ht->table[i]);
53 }
54 return 0;
55}
56
57void drm_ht_verbose_list(drm_open_hash_t *ht, unsigned long key)
58{
59 drm_hash_item_t *entry;
60 struct hlist_head *h_list;
61 struct hlist_node *list;
62 unsigned int hashed_key;
63 int count = 0;
64
65 hashed_key = hash_long(key, ht->order);
66 DRM_DEBUG("Key is 0x%08lx, Hashed key is 0x%08x\n", key, hashed_key);
67 h_list = &ht->table[hashed_key];
68 hlist_for_each(list, h_list) {
69 entry = hlist_entry(list, drm_hash_item_t, head);
70 DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key);
71 }
72}
73
74static struct hlist_node *drm_ht_find_key(drm_open_hash_t *ht,
75 unsigned long key)
76{
77 drm_hash_item_t *entry;
78 struct hlist_head *h_list;
79 struct hlist_node *list;
80 unsigned int hashed_key;
81
82 hashed_key = hash_long(key, ht->order);
83 h_list = &ht->table[hashed_key];
84 hlist_for_each(list, h_list) {
85 entry = hlist_entry(list, drm_hash_item_t, head);
86 if (entry->key == key)
87 return list;
88 if (entry->key > key)
89 break;
90 }
91 return NULL;
92}
93
94
95int drm_ht_insert_item(drm_open_hash_t *ht, drm_hash_item_t *item)
96{
97 drm_hash_item_t *entry;
98 struct hlist_head *h_list;
99 struct hlist_node *list, *parent;
100 unsigned int hashed_key;
101 unsigned long key = item->key;
102
103 hashed_key = hash_long(key, ht->order);
104 h_list = &ht->table[hashed_key];
105 parent = NULL;
106 hlist_for_each(list, h_list) {
107 entry = hlist_entry(list, drm_hash_item_t, head);
108 if (entry->key == key)
109 return -EINVAL;
110 if (entry->key > key)
111 break;
112 parent = list;
113 }
114 if (parent) {
115 hlist_add_after(parent, &item->head);
116 } else {
117 hlist_add_head(&item->head, h_list);
118 }
119 return 0;
120}
121
122/*
123 * Just insert an item and return any "bits" bit key that hasn't been
124 * used before.
125 */
126int drm_ht_just_insert_please(drm_open_hash_t *ht, drm_hash_item_t *item,
127 unsigned long seed, int bits, int shift,
128 unsigned long add)
129{
130 int ret;
131 unsigned long mask = (1 << bits) - 1;
132 unsigned long first, unshifted_key;
133
134 unshifted_key = hash_long(seed, bits);
135 first = unshifted_key;
136 do {
137 item->key = (unshifted_key << shift) + add;
138 ret = drm_ht_insert_item(ht, item);
139 if (ret)
140 unshifted_key = (unshifted_key + 1) & mask;
141 } while(ret && (unshifted_key != first));
142
143 if (ret) {
144 DRM_ERROR("Available key bit space exhausted\n");
145 return -EINVAL;
146 }
147 return 0;
148}
149
150int drm_ht_find_item(drm_open_hash_t *ht, unsigned long key,
151 drm_hash_item_t **item)
152{
153 struct hlist_node *list;
154
155 list = drm_ht_find_key(ht, key);
156 if (!list)
157 return -EINVAL;
158
159 *item = hlist_entry(list, drm_hash_item_t, head);
160 return 0;
161}
162
163int drm_ht_remove_key(drm_open_hash_t *ht, unsigned long key)
164{
165 struct hlist_node *list;
166
167 list = drm_ht_find_key(ht, key);
168 if (list) {
169 hlist_del_init(list);
170 ht->fill--;
171 return 0;
172 }
173 return -EINVAL;
174}
175
176int drm_ht_remove_item(drm_open_hash_t *ht, drm_hash_item_t *item)
177{
178 hlist_del_init(&item->head);
179 ht->fill--;
180 return 0;
181}
182
183void drm_ht_remove(drm_open_hash_t *ht)
184{
185 if (ht->table) {
186 vfree(ht->table);
187 ht->table = NULL;
188 }
189}
190
diff --git a/drivers/char/drm/drm_hashtab.h b/drivers/char/drm/drm_hashtab.h
new file mode 100644
index 000000000000..40afec05bff8
--- /dev/null
+++ b/drivers/char/drm/drm_hashtab.h
@@ -0,0 +1,67 @@
1/**************************************************************************
2 *
3 * Copyright 2006 Tungsten Graphics, Inc., Bismack, ND. USA.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 *
27 **************************************************************************/
28/*
29 * Simple open hash tab implementation.
30 *
31 * Authors:
32 * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
33 */
34
35#ifndef DRM_HASHTAB_H
36#define DRM_HASHTAB_H
37
38#define drm_hash_entry(_ptr, _type, _member) container_of(_ptr, _type, _member)
39
40typedef struct drm_hash_item{
41 struct hlist_node head;
42 unsigned long key;
43} drm_hash_item_t;
44
45typedef struct drm_open_hash{
46 unsigned int size;
47 unsigned int order;
48 unsigned int fill;
49 struct hlist_head *table;
50} drm_open_hash_t;
51
52
53extern int drm_ht_create(drm_open_hash_t *ht, unsigned int order);
54extern int drm_ht_insert_item(drm_open_hash_t *ht, drm_hash_item_t *item);
55extern int drm_ht_just_insert_please(drm_open_hash_t *ht, drm_hash_item_t *item,
56 unsigned long seed, int bits, int shift,
57 unsigned long add);
58extern int drm_ht_find_item(drm_open_hash_t *ht, unsigned long key, drm_hash_item_t **item);
59
60extern void drm_ht_verbose_list(drm_open_hash_t *ht, unsigned long key);
61extern int drm_ht_remove_key(drm_open_hash_t *ht, unsigned long key);
62extern int drm_ht_remove_item(drm_open_hash_t *ht, drm_hash_item_t *item);
63extern void drm_ht_remove(drm_open_hash_t *ht);
64
65
66#endif
67
diff --git a/drivers/char/drm/drm_ioc32.c b/drivers/char/drm/drm_ioc32.c
index e9e2db18952d..d4f874520082 100644
--- a/drivers/char/drm/drm_ioc32.c
+++ b/drivers/char/drm/drm_ioc32.c
@@ -1051,7 +1051,7 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
1051 drm_ioctl_compat_t *fn; 1051 drm_ioctl_compat_t *fn;
1052 int ret; 1052 int ret;
1053 1053
1054 if (nr >= DRM_ARRAY_SIZE(drm_compat_ioctls)) 1054 if (nr >= ARRAY_SIZE(drm_compat_ioctls))
1055 return -ENOTTY; 1055 return -ENOTTY;
1056 1056
1057 fn = drm_compat_ioctls[nr]; 1057 fn = drm_compat_ioctls[nr];
diff --git a/drivers/char/drm/drm_ioctl.c b/drivers/char/drm/drm_ioctl.c
index 555f323b8a32..565895547d75 100644
--- a/drivers/char/drm/drm_ioctl.c
+++ b/drivers/char/drm/drm_ioctl.c
@@ -127,9 +127,10 @@ int drm_setunique(struct inode *inode, struct file *filp,
127 domain = bus >> 8; 127 domain = bus >> 8;
128 bus &= 0xff; 128 bus &= 0xff;
129 129
130 if ((domain != dev->pci_domain) || 130 if ((domain != drm_get_pci_domain(dev)) ||
131 (bus != dev->pci_bus) || 131 (bus != dev->pdev->bus->number) ||
132 (slot != dev->pci_slot) || (func != dev->pci_func)) 132 (slot != PCI_SLOT(dev->pdev->devfn)) ||
133 (func != PCI_FUNC(dev->pdev->devfn)))
133 return -EINVAL; 134 return -EINVAL;
134 135
135 return 0; 136 return 0;
@@ -140,15 +141,17 @@ static int drm_set_busid(drm_device_t * dev)
140 int len; 141 int len;
141 142
142 if (dev->unique != NULL) 143 if (dev->unique != NULL)
143 return EBUSY; 144 return 0;
144 145
145 dev->unique_len = 40; 146 dev->unique_len = 40;
146 dev->unique = drm_alloc(dev->unique_len + 1, DRM_MEM_DRIVER); 147 dev->unique = drm_alloc(dev->unique_len + 1, DRM_MEM_DRIVER);
147 if (dev->unique == NULL) 148 if (dev->unique == NULL)
148 return ENOMEM; 149 return -ENOMEM;
149 150
150 len = snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d", 151 len = snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d",
151 dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func); 152 drm_get_pci_domain(dev), dev->pdev->bus->number,
153 PCI_SLOT(dev->pdev->devfn),
154 PCI_FUNC(dev->pdev->devfn));
152 155
153 if (len > dev->unique_len) 156 if (len > dev->unique_len)
154 DRM_ERROR("Unique buffer overflowed\n"); 157 DRM_ERROR("Unique buffer overflowed\n");
@@ -157,7 +160,7 @@ static int drm_set_busid(drm_device_t * dev)
157 drm_alloc(strlen(dev->driver->pci_driver.name) + dev->unique_len + 160 drm_alloc(strlen(dev->driver->pci_driver.name) + dev->unique_len +
158 2, DRM_MEM_DRIVER); 161 2, DRM_MEM_DRIVER);
159 if (dev->devname == NULL) 162 if (dev->devname == NULL)
160 return ENOMEM; 163 return -ENOMEM;
161 164
162 sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, 165 sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
163 dev->unique); 166 dev->unique);
@@ -330,27 +333,32 @@ int drm_setversion(DRM_IOCTL_ARGS)
330 drm_set_version_t retv; 333 drm_set_version_t retv;
331 int if_version; 334 int if_version;
332 drm_set_version_t __user *argp = (void __user *)data; 335 drm_set_version_t __user *argp = (void __user *)data;
336 int ret;
333 337
334 DRM_COPY_FROM_USER_IOCTL(sv, argp, sizeof(sv)); 338 if (copy_from_user(&sv, argp, sizeof(sv)))
339 return -EFAULT;
335 340
336 retv.drm_di_major = DRM_IF_MAJOR; 341 retv.drm_di_major = DRM_IF_MAJOR;
337 retv.drm_di_minor = DRM_IF_MINOR; 342 retv.drm_di_minor = DRM_IF_MINOR;
338 retv.drm_dd_major = dev->driver->major; 343 retv.drm_dd_major = dev->driver->major;
339 retv.drm_dd_minor = dev->driver->minor; 344 retv.drm_dd_minor = dev->driver->minor;
340 345
341 DRM_COPY_TO_USER_IOCTL(argp, retv, sizeof(sv)); 346 if (copy_to_user(argp, &retv, sizeof(retv)))
347 return -EFAULT;
342 348
343 if (sv.drm_di_major != -1) { 349 if (sv.drm_di_major != -1) {
344 if (sv.drm_di_major != DRM_IF_MAJOR || 350 if (sv.drm_di_major != DRM_IF_MAJOR ||
345 sv.drm_di_minor < 0 || sv.drm_di_minor > DRM_IF_MINOR) 351 sv.drm_di_minor < 0 || sv.drm_di_minor > DRM_IF_MINOR)
346 return EINVAL; 352 return -EINVAL;
347 if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_di_minor); 353 if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_di_minor);
348 dev->if_version = DRM_MAX(if_version, dev->if_version); 354 dev->if_version = max(if_version, dev->if_version);
349 if (sv.drm_di_minor >= 1) { 355 if (sv.drm_di_minor >= 1) {
350 /* 356 /*
351 * Version 1.1 includes tying of DRM to specific device 357 * Version 1.1 includes tying of DRM to specific device
352 */ 358 */
353 drm_set_busid(dev); 359 ret = drm_set_busid(dev);
360 if (ret)
361 return ret;
354 } 362 }
355 } 363 }
356 364
@@ -358,7 +366,7 @@ int drm_setversion(DRM_IOCTL_ARGS)
358 if (sv.drm_dd_major != dev->driver->major || 366 if (sv.drm_dd_major != dev->driver->major ||
359 sv.drm_dd_minor < 0 367 sv.drm_dd_minor < 0
360 || sv.drm_dd_minor > dev->driver->minor) 368 || sv.drm_dd_minor > dev->driver->minor)
361 return EINVAL; 369 return -EINVAL;
362 370
363 if (dev->driver->set_version) 371 if (dev->driver->set_version)
364 dev->driver->set_version(dev, &sv); 372 dev->driver->set_version(dev, &sv);
diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c
index ebdb7182c4fd..4553a3a1e496 100644
--- a/drivers/char/drm/drm_irq.c
+++ b/drivers/char/drm/drm_irq.c
@@ -64,9 +64,9 @@ int drm_irq_by_busid(struct inode *inode, struct file *filp,
64 if (copy_from_user(&p, argp, sizeof(p))) 64 if (copy_from_user(&p, argp, sizeof(p)))
65 return -EFAULT; 65 return -EFAULT;
66 66
67 if ((p.busnum >> 8) != dev->pci_domain || 67 if ((p.busnum >> 8) != drm_get_pci_domain(dev) ||
68 (p.busnum & 0xff) != dev->pci_bus || 68 (p.busnum & 0xff) != dev->pdev->bus->number ||
69 p.devnum != dev->pci_slot || p.funcnum != dev->pci_func) 69 p.devnum != PCI_SLOT(dev->pdev->devfn) || p.funcnum != PCI_FUNC(dev->pdev->devfn))
70 return -EINVAL; 70 return -EINVAL;
71 71
72 p.irq = dev->irq; 72 p.irq = dev->irq;
@@ -255,7 +255,8 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
255 if (!dev->irq) 255 if (!dev->irq)
256 return -EINVAL; 256 return -EINVAL;
257 257
258 DRM_COPY_FROM_USER_IOCTL(vblwait, argp, sizeof(vblwait)); 258 if (copy_from_user(&vblwait, argp, sizeof(vblwait)))
259 return -EFAULT;
259 260
260 switch (vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK) { 261 switch (vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK) {
261 case _DRM_VBLANK_RELATIVE: 262 case _DRM_VBLANK_RELATIVE:
@@ -329,7 +330,8 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
329 } 330 }
330 331
331 done: 332 done:
332 DRM_COPY_TO_USER_IOCTL(argp, vblwait, sizeof(vblwait)); 333 if (copy_to_user(argp, &vblwait, sizeof(vblwait)))
334 return -EFAULT;
333 335
334 return ret; 336 return ret;
335} 337}
diff --git a/drivers/char/drm/drm_mm.c b/drivers/char/drm/drm_mm.c
new file mode 100644
index 000000000000..617526bd5b0c
--- /dev/null
+++ b/drivers/char/drm/drm_mm.c
@@ -0,0 +1,201 @@
1/**************************************************************************
2 *
3 * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 *
27 **************************************************************************/
28
29/*
30 * Generic simple memory manager implementation. Intended to be used as a base
31 * class implementation for more advanced memory managers.
32 *
33 * Note that the algorithm used is quite simple and there might be substantial
34 * performance gains if a smarter free list is implemented. Currently it is just an
35 * unordered stack of free regions. This could easily be improved if an RB-tree
36 * is used instead. At least if we expect heavy fragmentation.
37 *
38 * Aligned allocations can also see improvement.
39 *
40 * Authors:
41 * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
42 */
43
44#include "drmP.h"
45
46drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent,
47 unsigned long size, unsigned alignment)
48{
49
50 drm_mm_node_t *child;
51
52 if (alignment)
53 size += alignment - 1;
54
55 if (parent->size == size) {
56 list_del_init(&parent->fl_entry);
57 parent->free = 0;
58 return parent;
59 } else {
60 child = (drm_mm_node_t *) drm_alloc(sizeof(*child), DRM_MEM_MM);
61 if (!child)
62 return NULL;
63
64 INIT_LIST_HEAD(&child->ml_entry);
65 INIT_LIST_HEAD(&child->fl_entry);
66
67 child->free = 0;
68 child->size = size;
69 child->start = parent->start;
70
71 list_add_tail(&child->ml_entry, &parent->ml_entry);
72 parent->size -= size;
73 parent->start += size;
74 }
75 return child;
76}
77
78/*
79 * Put a block. Merge with the previous and / or next block if they are free.
80 * Otherwise add to the free stack.
81 */
82
83void drm_mm_put_block(drm_mm_t * mm, drm_mm_node_t * cur)
84{
85
86 drm_mm_node_t *list_root = &mm->root_node;
87 struct list_head *cur_head = &cur->ml_entry;
88 struct list_head *root_head = &list_root->ml_entry;
89 drm_mm_node_t *prev_node = NULL;
90 drm_mm_node_t *next_node;
91
92 int merged = 0;
93
94 if (cur_head->prev != root_head) {
95 prev_node = list_entry(cur_head->prev, drm_mm_node_t, ml_entry);
96 if (prev_node->free) {
97 prev_node->size += cur->size;
98 merged = 1;
99 }
100 }
101 if (cur_head->next != root_head) {
102 next_node = list_entry(cur_head->next, drm_mm_node_t, ml_entry);
103 if (next_node->free) {
104 if (merged) {
105 prev_node->size += next_node->size;
106 list_del(&next_node->ml_entry);
107 list_del(&next_node->fl_entry);
108 drm_free(next_node, sizeof(*next_node),
109 DRM_MEM_MM);
110 } else {
111 next_node->size += cur->size;
112 next_node->start = cur->start;
113 merged = 1;
114 }
115 }
116 }
117 if (!merged) {
118 cur->free = 1;
119 list_add(&cur->fl_entry, &list_root->fl_entry);
120 } else {
121 list_del(&cur->ml_entry);
122 drm_free(cur, sizeof(*cur), DRM_MEM_MM);
123 }
124}
125
126drm_mm_node_t *drm_mm_search_free(const drm_mm_t * mm,
127 unsigned long size,
128 unsigned alignment, int best_match)
129{
130 struct list_head *list;
131 const struct list_head *free_stack = &mm->root_node.fl_entry;
132 drm_mm_node_t *entry;
133 drm_mm_node_t *best;
134 unsigned long best_size;
135
136 best = NULL;
137 best_size = ~0UL;
138
139 if (alignment)
140 size += alignment - 1;
141
142 list_for_each(list, free_stack) {
143 entry = list_entry(list, drm_mm_node_t, fl_entry);
144 if (entry->size >= size) {
145 if (!best_match)
146 return entry;
147 if (size < best_size) {
148 best = entry;
149 best_size = entry->size;
150 }
151 }
152 }
153
154 return best;
155}
156
157int drm_mm_init(drm_mm_t * mm, unsigned long start, unsigned long size)
158{
159 drm_mm_node_t *child;
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
170 child->start = start;
171 child->size = size;
172 child->free = 1;
173
174 list_add(&child->fl_entry, &mm->root_node.fl_entry);
175 list_add(&child->ml_entry, &mm->root_node.ml_entry);
176
177 return 0;
178}
179
180EXPORT_SYMBOL(drm_mm_init);
181
182void drm_mm_takedown(drm_mm_t * mm)
183{
184 struct list_head *bnode = mm->root_node.fl_entry.next;
185 drm_mm_node_t *entry;
186
187 entry = list_entry(bnode, drm_mm_node_t, fl_entry);
188
189 if (entry->ml_entry.next != &mm->root_node.ml_entry ||
190 entry->fl_entry.next != &mm->root_node.fl_entry) {
191 DRM_ERROR("Memory manager not clean. Delaying takedown\n");
192 return;
193 }
194
195 list_del(&entry->fl_entry);
196 list_del(&entry->ml_entry);
197
198 drm_free(entry, sizeof(*entry), DRM_MEM_MM);
199}
200
201EXPORT_SYMBOL(drm_mm_takedown);
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
index b1bb3c7b568d..09398d5fbd3f 100644
--- a/drivers/char/drm/drm_pciids.h
+++ b/drivers/char/drm/drm_pciids.h
@@ -3,13 +3,13 @@
3 Please contact dri-devel@lists.sf.net to add new cards to this list 3 Please contact dri-devel@lists.sf.net to add new cards to this list
4*/ 4*/
5#define radeon_PCI_IDS \ 5#define radeon_PCI_IDS \
6 {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \ 6 {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
7 {0x1002, 0x3152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ 7 {0x1002, 0x3152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
8 {0x1002, 0x3154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ 8 {0x1002, 0x3154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
9 {0x1002, 0x3E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ 9 {0x1002, 0x3E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
10 {0x1002, 0x3E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ 10 {0x1002, 0x3E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
11 {0x1002, 0x4136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP}, \ 11 {0x1002, 0x4136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|RADEON_IS_IGP}, \
12 {0x1002, 0x4137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \ 12 {0x1002, 0x4137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP}, \
13 {0x1002, 0x4144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ 13 {0x1002, 0x4144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
14 {0x1002, 0x4145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ 14 {0x1002, 0x4145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
15 {0x1002, 0x4146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ 15 {0x1002, 0x4146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
@@ -25,35 +25,35 @@
25 {0x1002, 0x4154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ 25 {0x1002, 0x4154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
26 {0x1002, 0x4155, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ 26 {0x1002, 0x4155, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
27 {0x1002, 0x4156, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ 27 {0x1002, 0x4156, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
28 {0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \ 28 {0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP}, \
29 {0x1002, 0x4242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ 29 {0x1002, 0x4242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
30 {0x1002, 0x4243, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ 30 {0x1002, 0x4243, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
31 {0x1002, 0x4336, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ 31 {0x1002, 0x4336, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
32 {0x1002, 0x4337, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ 32 {0x1002, 0x4337, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
33 {0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ 33 {0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
34 {0x1002, 0x4966, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \ 34 {0x1002, 0x4966, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \
35 {0x1002, 0x4967, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \ 35 {0x1002, 0x4967, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \
36 {0x1002, 0x4A48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 36 {0x1002, 0x4A48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
37 {0x1002, 0x4A49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 37 {0x1002, 0x4A49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
38 {0x1002, 0x4A4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 38 {0x1002, 0x4A4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
39 {0x1002, 0x4A4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 39 {0x1002, 0x4A4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
40 {0x1002, 0x4A4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 40 {0x1002, 0x4A4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
41 {0x1002, 0x4A4D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 41 {0x1002, 0x4A4D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
42 {0x1002, 0x4A4E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ 42 {0x1002, 0x4A4E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
43 {0x1002, 0x4A4F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 43 {0x1002, 0x4A4F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
44 {0x1002, 0x4A50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 44 {0x1002, 0x4A50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
45 {0x1002, 0x4A54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 45 {0x1002, 0x4A54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
46 {0x1002, 0x4B49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 46 {0x1002, 0x4B49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
47 {0x1002, 0x4B4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 47 {0x1002, 0x4B4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
48 {0x1002, 0x4B4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 48 {0x1002, 0x4B4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
49 {0x1002, 0x4B4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 49 {0x1002, 0x4B4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
50 {0x1002, 0x4C57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \ 50 {0x1002, 0x4C57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|RADEON_IS_MOBILITY}, \
51 {0x1002, 0x4C58, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \ 51 {0x1002, 0x4C58, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|RADEON_IS_MOBILITY}, \
52 {0x1002, 0x4C59, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|CHIP_IS_MOBILITY}, \ 52 {0x1002, 0x4C59, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|RADEON_IS_MOBILITY}, \
53 {0x1002, 0x4C5A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|CHIP_IS_MOBILITY}, \ 53 {0x1002, 0x4C5A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|RADEON_IS_MOBILITY}, \
54 {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \ 54 {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \
55 {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \ 55 {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \
56 {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \ 56 {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \
57 {0x1002, 0x4E44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ 57 {0x1002, 0x4E44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
58 {0x1002, 0x4E45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ 58 {0x1002, 0x4E45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
59 {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ 59 {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
@@ -62,16 +62,16 @@
62 {0x1002, 0x4E49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ 62 {0x1002, 0x4E49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
63 {0x1002, 0x4E4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ 63 {0x1002, 0x4E4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
64 {0x1002, 0x4E4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ 64 {0x1002, 0x4E4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
65 {0x1002, 0x4E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ 65 {0x1002, 0x4E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
66 {0x1002, 0x4E51, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ 66 {0x1002, 0x4E51, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
67 {0x1002, 0x4E52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ 67 {0x1002, 0x4E52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
68 {0x1002, 0x4E53, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ 68 {0x1002, 0x4E53, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
69 {0x1002, 0x4E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ 69 {0x1002, 0x4E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
70 {0x1002, 0x4E56, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ 70 {0x1002, 0x4E56, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
71 {0x1002, 0x5144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ 71 {0x1002, 0x5144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|RADEON_SINGLE_CRTC}, \
72 {0x1002, 0x5145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ 72 {0x1002, 0x5145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|RADEON_SINGLE_CRTC}, \
73 {0x1002, 0x5146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ 73 {0x1002, 0x5146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|RADEON_SINGLE_CRTC}, \
74 {0x1002, 0x5147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ 74 {0x1002, 0x5147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|RADEON_SINGLE_CRTC}, \
75 {0x1002, 0x5148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ 75 {0x1002, 0x5148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
76 {0x1002, 0x514C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ 76 {0x1002, 0x514C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
77 {0x1002, 0x514D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ 77 {0x1002, 0x514D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
@@ -80,59 +80,59 @@
80 {0x1002, 0x5159, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ 80 {0x1002, 0x5159, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
81 {0x1002, 0x515A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ 81 {0x1002, 0x515A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
82 {0x1002, 0x515E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ 82 {0x1002, 0x515E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
83 {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \ 83 {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
84 {0x1002, 0x5462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \ 84 {0x1002, 0x5462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
85 {0x1002, 0x5464, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \ 85 {0x1002, 0x5464, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
86 {0x1002, 0x5548, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 86 {0x1002, 0x5548, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
87 {0x1002, 0x5549, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 87 {0x1002, 0x5549, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
88 {0x1002, 0x554A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 88 {0x1002, 0x554A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
89 {0x1002, 0x554B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 89 {0x1002, 0x554B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
90 {0x1002, 0x554C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 90 {0x1002, 0x554C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
91 {0x1002, 0x554D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 91 {0x1002, 0x554D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
92 {0x1002, 0x554E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 92 {0x1002, 0x554E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
93 {0x1002, 0x554F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 93 {0x1002, 0x554F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
94 {0x1002, 0x5550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 94 {0x1002, 0x5550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
95 {0x1002, 0x5551, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 95 {0x1002, 0x5551, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
96 {0x1002, 0x5552, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 96 {0x1002, 0x5552, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
97 {0x1002, 0x5554, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 97 {0x1002, 0x5554, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
98 {0x1002, 0x564A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ 98 {0x1002, 0x564A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
99 {0x1002, 0x564B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ 99 {0x1002, 0x564B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
100 {0x1002, 0x564F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ 100 {0x1002, 0x564F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
101 {0x1002, 0x5652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ 101 {0x1002, 0x5652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
102 {0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ 102 {0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
103 {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \ 103 {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP}, \
104 {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ 104 {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
105 {0x1002, 0x5960, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ 105 {0x1002, 0x5960, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
106 {0x1002, 0x5961, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ 106 {0x1002, 0x5961, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
107 {0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ 107 {0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
108 {0x1002, 0x5964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ 108 {0x1002, 0x5964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
109 {0x1002, 0x5965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ 109 {0x1002, 0x5965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
110 {0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ 110 {0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
111 {0x1002, 0x5b60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ 111 {0x1002, 0x5b60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
112 {0x1002, 0x5b62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ 112 {0x1002, 0x5b62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
113 {0x1002, 0x5b63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ 113 {0x1002, 0x5b63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
114 {0x1002, 0x5b64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ 114 {0x1002, 0x5b64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
115 {0x1002, 0x5b65, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ 115 {0x1002, 0x5b65, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
116 {0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \ 116 {0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|RADEON_IS_MOBILITY}, \
117 {0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \ 117 {0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|RADEON_IS_MOBILITY}, \
118 {0x1002, 0x5d48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ 118 {0x1002, 0x5d48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
119 {0x1002, 0x5d49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ 119 {0x1002, 0x5d49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
120 {0x1002, 0x5d4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ 120 {0x1002, 0x5d4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
121 {0x1002, 0x5d4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 121 {0x1002, 0x5d4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
122 {0x1002, 0x5d4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 122 {0x1002, 0x5d4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
123 {0x1002, 0x5d4e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 123 {0x1002, 0x5d4e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
124 {0x1002, 0x5d4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 124 {0x1002, 0x5d4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
125 {0x1002, 0x5d50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 125 {0x1002, 0x5d50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
126 {0x1002, 0x5d52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 126 {0x1002, 0x5d52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
127 {0x1002, 0x5d57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ 127 {0x1002, 0x5d57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
128 {0x1002, 0x5e48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ 128 {0x1002, 0x5e48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
129 {0x1002, 0x5e4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ 129 {0x1002, 0x5e4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
130 {0x1002, 0x5e4b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ 130 {0x1002, 0x5e4b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
131 {0x1002, 0x5e4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ 131 {0x1002, 0x5e4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
132 {0x1002, 0x5e4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ 132 {0x1002, 0x5e4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
133 {0x1002, 0x5e4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ 133 {0x1002, 0x5e4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
134 {0x1002, 0x7834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_NEW_MEMMAP}, \ 134 {0x1002, 0x7834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_NEW_MEMMAP}, \
135 {0x1002, 0x7835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ 135 {0x1002, 0x7835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
136 {0, 0, 0} 136 {0, 0, 0}
137 137
138#define r128_PCI_IDS \ 138#define r128_PCI_IDS \
@@ -209,6 +209,7 @@
209 {0x1039, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ 209 {0x1039, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
210 {0x1039, 0x5300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ 210 {0x1039, 0x5300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
211 {0x1039, 0x6300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ 211 {0x1039, 0x6300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
212 {0x1039, 0x6330, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_CHIP_315}, \
212 {0x1039, 0x7300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ 213 {0x1039, 0x7300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
213 {0, 0, 0} 214 {0, 0, 0}
214 215
@@ -227,6 +228,10 @@
227 {0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ 228 {0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
228 {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ 229 {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
229 {0x1106, 0x3108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ 230 {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, 0x3157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
233 {0x1106, 0x3344, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
234 {0x1106, 0x7204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
230 {0, 0, 0} 235 {0, 0, 0}
231 236
232#define i810_PCI_IDS \ 237#define i810_PCI_IDS \
@@ -285,5 +290,9 @@
285 {0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ 290 {0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
286 {0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ 291 {0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
287 {0x8086, 0x27a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ 292 {0x8086, 0x27a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
293 {0x8086, 0x2972, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
294 {0x8086, 0x2982, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
295 {0x8086, 0x2992, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
296 {0x8086, 0x29a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
288 {0, 0, 0} 297 {0, 0, 0}
289 298
diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c
index 362a270af0f1..62d5fe15f046 100644
--- a/drivers/char/drm/drm_proc.c
+++ b/drivers/char/drm/drm_proc.c
@@ -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 VM_OFFSET(vma)); 513 vma->vm_pgoff << PAGE_SHIFT);
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
new file mode 100644
index 000000000000..425c82336ee0
--- /dev/null
+++ b/drivers/char/drm/drm_sman.c
@@ -0,0 +1,352 @@
1/**************************************************************************
2 *
3 * Copyright 2006 Tungsten Graphics, Inc., Bismarck., ND., USA.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 * USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
24 * of the Software.
25 *
26 *
27 **************************************************************************/
28/*
29 * Simple memory manager interface that keeps track on allocate regions on a
30 * per "owner" basis. All regions associated with an "owner" can be released
31 * with a simple call. Typically if the "owner" exists. The owner is any
32 * "unsigned long" identifier. Can typically be a pointer to a file private
33 * struct or a context identifier.
34 *
35 * Authors:
36 * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
37 */
38
39#include "drm_sman.h"
40
41typedef struct drm_owner_item {
42 drm_hash_item_t owner_hash;
43 struct list_head sman_list;
44 struct list_head mem_blocks;
45} drm_owner_item_t;
46
47void drm_sman_takedown(drm_sman_t * sman)
48{
49 drm_ht_remove(&sman->user_hash_tab);
50 drm_ht_remove(&sman->owner_hash_tab);
51 if (sman->mm)
52 drm_free(sman->mm, sman->num_managers * sizeof(*sman->mm),
53 DRM_MEM_MM);
54}
55
56EXPORT_SYMBOL(drm_sman_takedown);
57
58int
59drm_sman_init(drm_sman_t * sman, unsigned int num_managers,
60 unsigned int user_order, unsigned int owner_order)
61{
62 int ret = 0;
63
64 sman->mm = (drm_sman_mm_t *) drm_calloc(num_managers, sizeof(*sman->mm),
65 DRM_MEM_MM);
66 if (!sman->mm) {
67 ret = -ENOMEM;
68 goto out;
69 }
70 sman->num_managers = num_managers;
71 INIT_LIST_HEAD(&sman->owner_items);
72 ret = drm_ht_create(&sman->owner_hash_tab, owner_order);
73 if (ret)
74 goto out1;
75 ret = drm_ht_create(&sman->user_hash_tab, user_order);
76 if (!ret)
77 goto out;
78
79 drm_ht_remove(&sman->owner_hash_tab);
80out1:
81 drm_free(sman->mm, num_managers * sizeof(*sman->mm), DRM_MEM_MM);
82out:
83 return ret;
84}
85
86EXPORT_SYMBOL(drm_sman_init);
87
88static void *drm_sman_mm_allocate(void *private, unsigned long size,
89 unsigned alignment)
90{
91 drm_mm_t *mm = (drm_mm_t *) private;
92 drm_mm_node_t *tmp;
93
94 tmp = drm_mm_search_free(mm, size, alignment, 1);
95 if (!tmp) {
96 return NULL;
97 }
98 tmp = drm_mm_get_block(tmp, size, alignment);
99 return tmp;
100}
101
102static void drm_sman_mm_free(void *private, void *ref)
103{
104 drm_mm_t *mm = (drm_mm_t *) private;
105 drm_mm_node_t *node = (drm_mm_node_t *) ref;
106
107 drm_mm_put_block(mm, node);
108}
109
110static void drm_sman_mm_destroy(void *private)
111{
112 drm_mm_t *mm = (drm_mm_t *) private;
113 drm_mm_takedown(mm);
114 drm_free(mm, sizeof(*mm), DRM_MEM_MM);
115}
116
117static unsigned long drm_sman_mm_offset(void *private, void *ref)
118{
119 drm_mm_node_t *node = (drm_mm_node_t *) ref;
120 return node->start;
121}
122
123int
124drm_sman_set_range(drm_sman_t * sman, unsigned int manager,
125 unsigned long start, unsigned long size)
126{
127 drm_sman_mm_t *sman_mm;
128 drm_mm_t *mm;
129 int ret;
130
131 BUG_ON(manager >= sman->num_managers);
132
133 sman_mm = &sman->mm[manager];
134 mm = drm_calloc(1, sizeof(*mm), DRM_MEM_MM);
135 if (!mm) {
136 return -ENOMEM;
137 }
138 sman_mm->private = mm;
139 ret = drm_mm_init(mm, start, size);
140
141 if (ret) {
142 drm_free(mm, sizeof(*mm), DRM_MEM_MM);
143 return ret;
144 }
145
146 sman_mm->allocate = drm_sman_mm_allocate;
147 sman_mm->free = drm_sman_mm_free;
148 sman_mm->destroy = drm_sman_mm_destroy;
149 sman_mm->offset = drm_sman_mm_offset;
150
151 return 0;
152}
153
154EXPORT_SYMBOL(drm_sman_set_range);
155
156int
157drm_sman_set_manager(drm_sman_t * sman, unsigned int manager,
158 drm_sman_mm_t * allocator)
159{
160 BUG_ON(manager >= sman->num_managers);
161 sman->mm[manager] = *allocator;
162
163 return 0;
164}
165
166static drm_owner_item_t *drm_sman_get_owner_item(drm_sman_t * sman,
167 unsigned long owner)
168{
169 int ret;
170 drm_hash_item_t *owner_hash_item;
171 drm_owner_item_t *owner_item;
172
173 ret = drm_ht_find_item(&sman->owner_hash_tab, owner, &owner_hash_item);
174 if (!ret) {
175 return drm_hash_entry(owner_hash_item, drm_owner_item_t,
176 owner_hash);
177 }
178
179 owner_item = drm_calloc(1, sizeof(*owner_item), DRM_MEM_MM);
180 if (!owner_item)
181 goto out;
182
183 INIT_LIST_HEAD(&owner_item->mem_blocks);
184 owner_item->owner_hash.key = owner;
185 if (drm_ht_insert_item(&sman->owner_hash_tab, &owner_item->owner_hash))
186 goto out1;
187
188 list_add_tail(&owner_item->sman_list, &sman->owner_items);
189 return owner_item;
190
191out1:
192 drm_free(owner_item, sizeof(*owner_item), DRM_MEM_MM);
193out:
194 return NULL;
195}
196
197drm_memblock_item_t *drm_sman_alloc(drm_sman_t *sman, unsigned int manager,
198 unsigned long size, unsigned alignment,
199 unsigned long owner)
200{
201 void *tmp;
202 drm_sman_mm_t *sman_mm;
203 drm_owner_item_t *owner_item;
204 drm_memblock_item_t *memblock;
205
206 BUG_ON(manager >= sman->num_managers);
207
208 sman_mm = &sman->mm[manager];
209 tmp = sman_mm->allocate(sman_mm->private, size, alignment);
210
211 if (!tmp) {
212 return NULL;
213 }
214
215 memblock = drm_calloc(1, sizeof(*memblock), DRM_MEM_MM);
216
217 if (!memblock)
218 goto out;
219
220 memblock->mm_info = tmp;
221 memblock->mm = sman_mm;
222 memblock->sman = sman;
223
224 if (drm_ht_just_insert_please
225 (&sman->user_hash_tab, &memblock->user_hash,
226 (unsigned long)memblock, 32, 0, 0))
227 goto out1;
228
229 owner_item = drm_sman_get_owner_item(sman, owner);
230 if (!owner_item)
231 goto out2;
232
233 list_add_tail(&memblock->owner_list, &owner_item->mem_blocks);
234
235 return memblock;
236
237out2:
238 drm_ht_remove_item(&sman->user_hash_tab, &memblock->user_hash);
239out1:
240 drm_free(memblock, sizeof(*memblock), DRM_MEM_MM);
241out:
242 sman_mm->free(sman_mm->private, tmp);
243
244 return NULL;
245}
246
247EXPORT_SYMBOL(drm_sman_alloc);
248
249static void drm_sman_free(drm_memblock_item_t *item)
250{
251 drm_sman_t *sman = item->sman;
252
253 list_del(&item->owner_list);
254 drm_ht_remove_item(&sman->user_hash_tab, &item->user_hash);
255 item->mm->free(item->mm->private, item->mm_info);
256 drm_free(item, sizeof(*item), DRM_MEM_MM);
257}
258
259int drm_sman_free_key(drm_sman_t *sman, unsigned int key)
260{
261 drm_hash_item_t *hash_item;
262 drm_memblock_item_t *memblock_item;
263
264 if (drm_ht_find_item(&sman->user_hash_tab, key, &hash_item))
265 return -EINVAL;
266
267 memblock_item = drm_hash_entry(hash_item, drm_memblock_item_t, user_hash);
268 drm_sman_free(memblock_item);
269 return 0;
270}
271
272EXPORT_SYMBOL(drm_sman_free_key);
273
274static void drm_sman_remove_owner(drm_sman_t *sman,
275 drm_owner_item_t *owner_item)
276{
277 list_del(&owner_item->sman_list);
278 drm_ht_remove_item(&sman->owner_hash_tab, &owner_item->owner_hash);
279 drm_free(owner_item, sizeof(*owner_item), DRM_MEM_MM);
280}
281
282int drm_sman_owner_clean(drm_sman_t *sman, unsigned long owner)
283{
284
285 drm_hash_item_t *hash_item;
286 drm_owner_item_t *owner_item;
287
288 if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) {
289 return -1;
290 }
291
292 owner_item = drm_hash_entry(hash_item, drm_owner_item_t, owner_hash);
293 if (owner_item->mem_blocks.next == &owner_item->mem_blocks) {
294 drm_sman_remove_owner(sman, owner_item);
295 return -1;
296 }
297
298 return 0;
299}
300
301EXPORT_SYMBOL(drm_sman_owner_clean);
302
303static void drm_sman_do_owner_cleanup(drm_sman_t *sman,
304 drm_owner_item_t *owner_item)
305{
306 drm_memblock_item_t *entry, *next;
307
308 list_for_each_entry_safe(entry, next, &owner_item->mem_blocks,
309 owner_list) {
310 drm_sman_free(entry);
311 }
312 drm_sman_remove_owner(sman, owner_item);
313}
314
315void drm_sman_owner_cleanup(drm_sman_t *sman, unsigned long owner)
316{
317
318 drm_hash_item_t *hash_item;
319 drm_owner_item_t *owner_item;
320
321 if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) {
322
323 return;
324 }
325
326 owner_item = drm_hash_entry(hash_item, drm_owner_item_t, owner_hash);
327 drm_sman_do_owner_cleanup(sman, owner_item);
328}
329
330EXPORT_SYMBOL(drm_sman_owner_cleanup);
331
332void drm_sman_cleanup(drm_sman_t *sman)
333{
334 drm_owner_item_t *entry, *next;
335 unsigned int i;
336 drm_sman_mm_t *sman_mm;
337
338 list_for_each_entry_safe(entry, next, &sman->owner_items, sman_list) {
339 drm_sman_do_owner_cleanup(sman, entry);
340 }
341 if (sman->mm) {
342 for (i = 0; i < sman->num_managers; ++i) {
343 sman_mm = &sman->mm[i];
344 if (sman_mm->private) {
345 sman_mm->destroy(sman_mm->private);
346 sman_mm->private = NULL;
347 }
348 }
349 }
350}
351
352EXPORT_SYMBOL(drm_sman_cleanup);
diff --git a/drivers/char/drm/drm_sman.h b/drivers/char/drm/drm_sman.h
new file mode 100644
index 000000000000..ddc732a1bf27
--- /dev/null
+++ b/drivers/char/drm/drm_sman.h
@@ -0,0 +1,176 @@
1/**************************************************************************
2 *
3 * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 *
27 **************************************************************************/
28/*
29 * Simple memory MANager interface that keeps track on allocate regions on a
30 * per "owner" basis. All regions associated with an "owner" can be released
31 * with a simple call. Typically if the "owner" exists. The owner is any
32 * "unsigned long" identifier. Can typically be a pointer to a file private
33 * struct or a context identifier.
34 *
35 * Authors:
36 * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
37 */
38
39#ifndef DRM_SMAN_H
40#define DRM_SMAN_H
41
42#include "drmP.h"
43#include "drm_hashtab.h"
44
45/*
46 * A class that is an abstration of a simple memory allocator.
47 * The sman implementation provides a default such allocator
48 * using the drm_mm.c implementation. But the user can replace it.
49 * See the SiS implementation, which may use the SiS FB kernel module
50 * for memory management.
51 */
52
53typedef struct drm_sman_mm {
54 /* private info. If allocated, needs to be destroyed by the destroy
55 function */
56 void *private;
57
58 /* Allocate a memory block with given size and alignment.
59 Return an opaque reference to the memory block */
60
61 void *(*allocate) (void *private, unsigned long size,
62 unsigned alignment);
63
64 /* Free a memory block. "ref" is the opaque reference that we got from
65 the "alloc" function */
66
67 void (*free) (void *private, void *ref);
68
69 /* Free all resources associated with this allocator */
70
71 void (*destroy) (void *private);
72
73 /* Return a memory offset from the opaque reference returned from the
74 "alloc" function */
75
76 unsigned long (*offset) (void *private, void *ref);
77} drm_sman_mm_t;
78
79typedef struct drm_memblock_item {
80 struct list_head owner_list;
81 drm_hash_item_t user_hash;
82 void *mm_info;
83 drm_sman_mm_t *mm;
84 struct drm_sman *sman;
85} drm_memblock_item_t;
86
87typedef struct drm_sman {
88 drm_sman_mm_t *mm;
89 int num_managers;
90 drm_open_hash_t owner_hash_tab;
91 drm_open_hash_t user_hash_tab;
92 struct list_head owner_items;
93} drm_sman_t;
94
95/*
96 * Take down a memory manager. This function should only be called after a
97 * successful init and after a call to drm_sman_cleanup.
98 */
99
100extern void drm_sman_takedown(drm_sman_t * sman);
101
102/*
103 * Allocate structures for a manager.
104 * num_managers are the number of memory pools to manage. (VRAM, AGP, ....)
105 * user_order is the log2 of the number of buckets in the user hash table.
106 * set this to approximately log2 of the max number of memory regions
107 * that will be allocated for _all_ pools together.
108 * owner_order is the log2 of the number of buckets in the owner hash table.
109 * set this to approximately log2 of
110 * the number of client file connections that will
111 * be using the manager.
112 *
113 */
114
115extern int drm_sman_init(drm_sman_t * sman, unsigned int num_managers,
116 unsigned int user_order, unsigned int owner_order);
117
118/*
119 * Initialize a drm_mm.c allocator. Should be called only once for each
120 * manager unless a customized allogator is used.
121 */
122
123extern int drm_sman_set_range(drm_sman_t * sman, unsigned int manager,
124 unsigned long start, unsigned long size);
125
126/*
127 * Initialize a customized allocator for one of the managers.
128 * (See the SiS module). The object pointed to by "allocator" is copied,
129 * so it can be destroyed after this call.
130 */
131
132extern int drm_sman_set_manager(drm_sman_t * sman, unsigned int mananger,
133 drm_sman_mm_t * allocator);
134
135/*
136 * Allocate a memory block. Aligment is not implemented yet.
137 */
138
139extern drm_memblock_item_t *drm_sman_alloc(drm_sman_t * sman,
140 unsigned int manager,
141 unsigned long size,
142 unsigned alignment,
143 unsigned long owner);
144/*
145 * Free a memory block identified by its user hash key.
146 */
147
148extern int drm_sman_free_key(drm_sman_t * sman, unsigned int key);
149
150/*
151 * returns 1 iff there are no stale memory blocks associated with this owner.
152 * Typically called to determine if we need to idle the hardware and call
153 * drm_sman_owner_cleanup. If there are no stale memory blocks, it removes all
154 * resources associated with owner.
155 */
156
157extern int drm_sman_owner_clean(drm_sman_t * sman, unsigned long owner);
158
159/*
160 * Frees all stale memory blocks associated with this owner. Note that this
161 * requires that the hardware is finished with all blocks, so the graphics engine
162 * should be idled before this call is made. This function also frees
163 * any resources associated with "owner" and should be called when owner
164 * is not going to be referenced anymore.
165 */
166
167extern void drm_sman_owner_cleanup(drm_sman_t * sman, unsigned long owner);
168
169/*
170 * Frees all stale memory blocks associated with the memory manager.
171 * See idling above.
172 */
173
174extern void drm_sman_cleanup(drm_sman_t * sman);
175
176#endif
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
index 9a842a36bb27..7b1d4e8659ba 100644
--- a/drivers/char/drm/drm_stub.c
+++ b/drivers/char/drm/drm_stub.c
@@ -65,22 +65,22 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
65 mutex_init(&dev->ctxlist_mutex); 65 mutex_init(&dev->ctxlist_mutex);
66 66
67 dev->pdev = pdev; 67 dev->pdev = pdev;
68 dev->pci_device = pdev->device;
69 dev->pci_vendor = pdev->vendor;
68 70
69#ifdef __alpha__ 71#ifdef __alpha__
70 dev->hose = pdev->sysdata; 72 dev->hose = pdev->sysdata;
71 dev->pci_domain = dev->hose->bus->number;
72#else
73 dev->pci_domain = 0;
74#endif 73#endif
75 dev->pci_bus = pdev->bus->number;
76 dev->pci_slot = PCI_SLOT(pdev->devfn);
77 dev->pci_func = PCI_FUNC(pdev->devfn);
78 dev->irq = pdev->irq; 74 dev->irq = pdev->irq;
79 75
80 dev->maplist = drm_calloc(1, sizeof(*dev->maplist), DRM_MEM_MAPS); 76 dev->maplist = drm_calloc(1, sizeof(*dev->maplist), DRM_MEM_MAPS);
81 if (dev->maplist == NULL) 77 if (dev->maplist == NULL)
82 return -ENOMEM; 78 return -ENOMEM;
83 INIT_LIST_HEAD(&dev->maplist->head); 79 INIT_LIST_HEAD(&dev->maplist->head);
80 if (drm_ht_create(&dev->map_hash, 12)) {
81 drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
82 return -ENOMEM;
83 }
84 84
85 /* the DRM has 6 basic counters */ 85 /* the DRM has 6 basic counters */
86 dev->counters = 6; 86 dev->counters = 6;
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c
index ffd0800ed601..b40ae438f531 100644
--- a/drivers/char/drm/drm_vm.c
+++ b/drivers/char/drm/drm_vm.c
@@ -59,7 +59,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
59 drm_device_t *dev = priv->head->dev; 59 drm_device_t *dev = priv->head->dev;
60 drm_map_t *map = NULL; 60 drm_map_t *map = NULL;
61 drm_map_list_t *r_list; 61 drm_map_list_t *r_list;
62 struct list_head *list; 62 drm_hash_item_t *hash;
63 63
64 /* 64 /*
65 * Find the right map 65 * Find the right map
@@ -70,14 +70,11 @@ 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 list_for_each(list, &dev->maplist->head) { 73 if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff << PAGE_SHIFT, &hash))
74 r_list = list_entry(list, drm_map_list_t, head); 74 goto vm_nopage_error;
75 map = r_list->map; 75
76 if (!map) 76 r_list = drm_hash_entry(hash, drm_map_list_t, hash);
77 continue; 77 map = r_list->map;
78 if (r_list->user_token == VM_OFFSET(vma))
79 break;
80 }
81 78
82 if (map && map->type == _DRM_AGP) { 79 if (map && map->type == _DRM_AGP) {
83 unsigned long offset = address - vma->vm_start; 80 unsigned long offset = address - vma->vm_start;
@@ -467,7 +464,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
467 dev = priv->head->dev; 464 dev = priv->head->dev;
468 dma = dev->dma; 465 dma = dev->dma;
469 DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", 466 DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
470 vma->vm_start, vma->vm_end, VM_OFFSET(vma)); 467 vma->vm_start, vma->vm_end, vma->vm_pgoff << PAGE_SHIFT);
471 468
472 /* Length must match exact page count */ 469 /* Length must match exact page count */
473 if (!dma || (length >> PAGE_SHIFT) != dma->page_count) { 470 if (!dma || (length >> PAGE_SHIFT) != dma->page_count) {
@@ -521,12 +518,11 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
521 drm_file_t *priv = filp->private_data; 518 drm_file_t *priv = filp->private_data;
522 drm_device_t *dev = priv->head->dev; 519 drm_device_t *dev = priv->head->dev;
523 drm_map_t *map = NULL; 520 drm_map_t *map = NULL;
524 drm_map_list_t *r_list;
525 unsigned long offset = 0; 521 unsigned long offset = 0;
526 struct list_head *list; 522 drm_hash_item_t *hash;
527 523
528 DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", 524 DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
529 vma->vm_start, vma->vm_end, VM_OFFSET(vma)); 525 vma->vm_start, vma->vm_end, vma->vm_pgoff << PAGE_SHIFT);
530 526
531 if (!priv->authenticated) 527 if (!priv->authenticated)
532 return -EACCES; 528 return -EACCES;
@@ -535,7 +531,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
535 * the AGP mapped at physical address 0 531 * the AGP mapped at physical address 0
536 * --BenH. 532 * --BenH.
537 */ 533 */
538 if (!VM_OFFSET(vma) 534 if (!(vma->vm_pgoff << PAGE_SHIFT)
539#if __OS_HAS_AGP 535#if __OS_HAS_AGP
540 && (!dev->agp 536 && (!dev->agp
541 || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE) 537 || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE)
@@ -543,23 +539,12 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
543 ) 539 )
544 return drm_mmap_dma(filp, vma); 540 return drm_mmap_dma(filp, vma);
545 541
546 /* A sequential search of a linked list is 542 if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff << PAGE_SHIFT, &hash)) {
547 fine here because: 1) there will only be 543 DRM_ERROR("Could not find map\n");
548 about 5-10 entries in the list and, 2) a 544 return -EINVAL;
549 DRI client only has to do this mapping
550 once, so it doesn't have to be optimized
551 for performance, even if the list was a
552 bit longer. */
553 list_for_each(list, &dev->maplist->head) {
554
555 r_list = list_entry(list, drm_map_list_t, head);
556 map = r_list->map;
557 if (!map)
558 continue;
559 if (r_list->user_token == VM_OFFSET(vma))
560 break;
561 } 545 }
562 546
547 map = drm_hash_entry(hash, drm_map_list_t, hash)->map;
563 if (!map || ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) 548 if (!map || ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
564 return -EPERM; 549 return -EPERM;
565 550
@@ -620,7 +605,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
620 offset = dev->driver->get_reg_ofs(dev); 605 offset = dev->driver->get_reg_ofs(dev);
621#ifdef __sparc__ 606#ifdef __sparc__
622 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); 607 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
623 if (io_remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start, 608 if (io_remap_pfn_range(vma, vma->vm_start,
624 (map->offset + offset) >> PAGE_SHIFT, 609 (map->offset + offset) >> PAGE_SHIFT,
625 vma->vm_end - vma->vm_start, 610 vma->vm_end - vma->vm_start,
626 vma->vm_page_prot)) 611 vma->vm_page_prot))
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
index c658dde3633b..fa2de70f7401 100644
--- a/drivers/char/drm/i810_dma.c
+++ b/drivers/char/drm/i810_dma.c
@@ -106,7 +106,7 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
106 unlock_kernel(); 106 unlock_kernel();
107 107
108 if (io_remap_pfn_range(vma, vma->vm_start, 108 if (io_remap_pfn_range(vma, vma->vm_start,
109 VM_OFFSET(vma) >> PAGE_SHIFT, 109 vma->vm_pgoff,
110 vma->vm_end - vma->vm_start, vma->vm_page_prot)) 110 vma->vm_end - vma->vm_start, vma->vm_page_prot))
111 return -EAGAIN; 111 return -EAGAIN;
112 return 0; 112 return 0;
@@ -141,10 +141,10 @@ static int i810_map_buffer(drm_buf_t * buf, struct file *filp)
141 MAP_SHARED, buf->bus_address); 141 MAP_SHARED, buf->bus_address);
142 dev_priv->mmap_buffer = NULL; 142 dev_priv->mmap_buffer = NULL;
143 filp->f_op = old_fops; 143 filp->f_op = old_fops;
144 if ((unsigned long)buf_priv->virtual > -1024UL) { 144 if (IS_ERR(buf_priv->virtual)) {
145 /* Real error */ 145 /* Real error */
146 DRM_ERROR("mmap error\n"); 146 DRM_ERROR("mmap error\n");
147 retcode = (signed int)buf_priv->virtual; 147 retcode = PTR_ERR(buf_priv->virtual);
148 buf_priv->virtual = NULL; 148 buf_priv->virtual = NULL;
149 } 149 }
150 up_write(&current->mm->mmap_sem); 150 up_write(&current->mm->mmap_sem);
@@ -808,7 +808,7 @@ static void i810_dma_dispatch_vertex(drm_device_t * dev,
808 ((GFX_OP_PRIMITIVE | prim | ((used / 4) - 2))); 808 ((GFX_OP_PRIMITIVE | prim | ((used / 4) - 2)));
809 809
810 if (used & 4) { 810 if (used & 4) {
811 *(u32 *) ((u32) buf_priv->kernel_virtual + used) = 0; 811 *(u32 *) ((char *) buf_priv->kernel_virtual + used) = 0;
812 used += 4; 812 used += 4;
813 } 813 }
814 814
@@ -1166,7 +1166,7 @@ static void i810_dma_dispatch_mc(drm_device_t * dev, drm_buf_t * buf, int used,
1166 1166
1167 if (buf_priv->currently_mapped == I810_BUF_MAPPED) { 1167 if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
1168 if (used & 4) { 1168 if (used & 4) {
1169 *(u32 *) ((u32) buf_priv->virtual + used) = 0; 1169 *(u32 *) ((char *) buf_priv->virtual + used) = 0;
1170 used += 4; 1170 used += 4;
1171 } 1171 }
1172 1172
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
index b0f815d8cea8..4f0e5746ab33 100644
--- a/drivers/char/drm/i830_dma.c
+++ b/drivers/char/drm/i830_dma.c
@@ -108,7 +108,7 @@ static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
108 unlock_kernel(); 108 unlock_kernel();
109 109
110 if (io_remap_pfn_range(vma, vma->vm_start, 110 if (io_remap_pfn_range(vma, vma->vm_start,
111 VM_OFFSET(vma) >> PAGE_SHIFT, 111 vma->vm_pgoff,
112 vma->vm_end - vma->vm_start, vma->vm_page_prot)) 112 vma->vm_end - vma->vm_start, vma->vm_page_prot))
113 return -EAGAIN; 113 return -EAGAIN;
114 return 0; 114 return 0;
@@ -146,7 +146,7 @@ static int i830_map_buffer(drm_buf_t * buf, struct file *filp)
146 if (IS_ERR((void *)virtual)) { /* ugh */ 146 if (IS_ERR((void *)virtual)) { /* ugh */
147 /* Real error */ 147 /* Real error */
148 DRM_ERROR("mmap error\n"); 148 DRM_ERROR("mmap error\n");
149 retcode = virtual; 149 retcode = PTR_ERR((void *)virtual);
150 buf_priv->virtual = NULL; 150 buf_priv->virtual = NULL;
151 } else { 151 } else {
152 buf_priv->virtual = (void __user *)virtual; 152 buf_priv->virtual = (void __user *)virtual;
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
index a94233bdbc0e..fb7913ff5286 100644
--- a/drivers/char/drm/i915_dma.c
+++ b/drivers/char/drm/i915_dma.c
@@ -31,6 +31,11 @@
31#include "i915_drm.h" 31#include "i915_drm.h"
32#include "i915_drv.h" 32#include "i915_drv.h"
33 33
34#define IS_I965G(dev) (dev->pci_device == 0x2972 || \
35 dev->pci_device == 0x2982 || \
36 dev->pci_device == 0x2992 || \
37 dev->pci_device == 0x29A2)
38
34/* Really want an OS-independent resettable timer. Would like to have 39/* Really want an OS-independent resettable timer. Would like to have
35 * this loop run for (eg) 3 sec, but have the timer reset every time 40 * this loop run for (eg) 3 sec, but have the timer reset every time
36 * the head pointer changes, so that EBUSY only happens if the ring 41 * the head pointer changes, so that EBUSY only happens if the ring
@@ -255,7 +260,7 @@ static int i915_dma_init(DRM_IOCTL_ARGS)
255 retcode = i915_dma_resume(dev); 260 retcode = i915_dma_resume(dev);
256 break; 261 break;
257 default: 262 default:
258 retcode = -EINVAL; 263 retcode = DRM_ERR(EINVAL);
259 break; 264 break;
260 } 265 }
261 266
@@ -347,7 +352,7 @@ static int i915_emit_cmds(drm_device_t * dev, int __user * buffer, int dwords)
347 if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8) 352 if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8)
348 return DRM_ERR(EINVAL); 353 return DRM_ERR(EINVAL);
349 354
350 BEGIN_LP_RING(((dwords+1)&~1)); 355 BEGIN_LP_RING((dwords+1)&~1);
351 356
352 for (i = 0; i < dwords;) { 357 for (i = 0; i < dwords;) {
353 int cmd, sz; 358 int cmd, sz;
@@ -386,7 +391,7 @@ static int i915_emit_box(drm_device_t * dev,
386 RING_LOCALS; 391 RING_LOCALS;
387 392
388 if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) { 393 if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) {
389 return EFAULT; 394 return DRM_ERR(EFAULT);
390 } 395 }
391 396
392 if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) { 397 if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) {
@@ -395,24 +400,40 @@ static int i915_emit_box(drm_device_t * dev,
395 return DRM_ERR(EINVAL); 400 return DRM_ERR(EINVAL);
396 } 401 }
397 402
398 BEGIN_LP_RING(6); 403 if (IS_I965G(dev)) {
399 OUT_RING(GFX_OP_DRAWRECT_INFO); 404 BEGIN_LP_RING(4);
400 OUT_RING(DR1); 405 OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
401 OUT_RING((box.x1 & 0xffff) | (box.y1 << 16)); 406 OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
402 OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16)); 407 OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
403 OUT_RING(DR4); 408 OUT_RING(DR4);
404 OUT_RING(0); 409 ADVANCE_LP_RING();
405 ADVANCE_LP_RING(); 410 } else {
411 BEGIN_LP_RING(6);
412 OUT_RING(GFX_OP_DRAWRECT_INFO);
413 OUT_RING(DR1);
414 OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
415 OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
416 OUT_RING(DR4);
417 OUT_RING(0);
418 ADVANCE_LP_RING();
419 }
406 420
407 return 0; 421 return 0;
408} 422}
409 423
424/* XXX: Emitting the counter should really be moved to part of the IRQ
425 * emit. For now, do it in both places:
426 */
427
410static void i915_emit_breadcrumb(drm_device_t *dev) 428static void i915_emit_breadcrumb(drm_device_t *dev)
411{ 429{
412 drm_i915_private_t *dev_priv = dev->dev_private; 430 drm_i915_private_t *dev_priv = dev->dev_private;
413 RING_LOCALS; 431 RING_LOCALS;
414 432
415 dev_priv->sarea_priv->last_enqueue = dev_priv->counter++; 433 dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
434
435 if (dev_priv->counter > 0x7FFFFFFFUL)
436 dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
416 437
417 BEGIN_LP_RING(4); 438 BEGIN_LP_RING(4);
418 OUT_RING(CMD_STORE_DWORD_IDX); 439 OUT_RING(CMD_STORE_DWORD_IDX);
diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h
index 5aa3e0e3bb45..6af83e613f27 100644
--- a/drivers/char/drm/i915_drm.h
+++ b/drivers/char/drm/i915_drm.h
@@ -98,6 +98,12 @@ typedef struct _drm_i915_sarea {
98 int rotated_size; 98 int rotated_size;
99 int rotated_pitch; 99 int rotated_pitch;
100 int virtualX, virtualY; 100 int virtualX, virtualY;
101
102 unsigned int front_tiled;
103 unsigned int back_tiled;
104 unsigned int depth_tiled;
105 unsigned int rotated_tiled;
106 unsigned int rotated2_tiled;
101} drm_i915_sarea_t; 107} drm_i915_sarea_t;
102 108
103/* Flags for perf_boxes 109/* Flags for perf_boxes
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
index 2d565031c002..fdc2bf192714 100644
--- a/drivers/char/drm/i915_drv.h
+++ b/drivers/char/drm/i915_drv.h
@@ -146,9 +146,9 @@ extern void i915_mem_release(drm_device_t * dev,
146#define BEGIN_LP_RING(n) do { \ 146#define BEGIN_LP_RING(n) do { \
147 if (I915_VERBOSE) \ 147 if (I915_VERBOSE) \
148 DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", \ 148 DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", \
149 n, __FUNCTION__); \ 149 (n), __FUNCTION__); \
150 if (dev_priv->ring.space < n*4) \ 150 if (dev_priv->ring.space < (n)*4) \
151 i915_wait_ring(dev, n*4, __FUNCTION__); \ 151 i915_wait_ring(dev, (n)*4, __FUNCTION__); \
152 outcount = 0; \ 152 outcount = 0; \
153 outring = dev_priv->ring.tail; \ 153 outring = dev_priv->ring.tail; \
154 ringmask = dev_priv->ring.tail_mask; \ 154 ringmask = dev_priv->ring.tail_mask; \
@@ -157,7 +157,7 @@ extern void i915_mem_release(drm_device_t * dev,
157 157
158#define OUT_RING(n) do { \ 158#define OUT_RING(n) do { \
159 if (I915_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \ 159 if (I915_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \
160 *(volatile unsigned int *)(virt + outring) = n; \ 160 *(volatile unsigned int *)(virt + outring) = (n); \
161 outcount++; \ 161 outcount++; \
162 outring += 4; \ 162 outring += 4; \
163 outring &= ringmask; \ 163 outring &= ringmask; \
@@ -254,6 +254,8 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
254#define GFX_OP_DESTBUFFER_VARS ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0) 254#define GFX_OP_DESTBUFFER_VARS ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
255#define GFX_OP_DRAWRECT_INFO ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3)) 255#define GFX_OP_DRAWRECT_INFO ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
256 256
257#define GFX_OP_DRAWRECT_INFO_I965 ((0x7900<<16)|0x2)
258
257#define MI_BATCH_BUFFER ((0x30<<23)|1) 259#define MI_BATCH_BUFFER ((0x30<<23)|1)
258#define MI_BATCH_BUFFER_START (0x31<<23) 260#define MI_BATCH_BUFFER_START (0x31<<23)
259#define MI_BATCH_BUFFER_END (0xA<<23) 261#define MI_BATCH_BUFFER_END (0xA<<23)
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
index cd96cfa430db..0d4a162aa385 100644
--- a/drivers/char/drm/i915_irq.c
+++ b/drivers/char/drm/i915_irq.c
@@ -71,21 +71,27 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
71static int i915_emit_irq(drm_device_t * dev) 71static int i915_emit_irq(drm_device_t * dev)
72{ 72{
73 drm_i915_private_t *dev_priv = dev->dev_private; 73 drm_i915_private_t *dev_priv = dev->dev_private;
74 u32 ret;
75 RING_LOCALS; 74 RING_LOCALS;
76 75
77 i915_kernel_lost_context(dev); 76 i915_kernel_lost_context(dev);
78 77
79 DRM_DEBUG("%s\n", __FUNCTION__); 78 DRM_DEBUG("%s\n", __FUNCTION__);
80 79
81 ret = dev_priv->counter; 80 dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
82 81
83 BEGIN_LP_RING(2); 82 if (dev_priv->counter > 0x7FFFFFFFUL)
83 dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
84
85 BEGIN_LP_RING(6);
86 OUT_RING(CMD_STORE_DWORD_IDX);
87 OUT_RING(20);
88 OUT_RING(dev_priv->counter);
89 OUT_RING(0);
84 OUT_RING(0); 90 OUT_RING(0);
85 OUT_RING(GFX_OP_USER_INTERRUPT); 91 OUT_RING(GFX_OP_USER_INTERRUPT);
86 ADVANCE_LP_RING(); 92 ADVANCE_LP_RING();
87 93
88 return ret; 94 return dev_priv->counter;
89} 95}
90 96
91static int i915_wait_irq(drm_device_t * dev, int irq_nr) 97static int i915_wait_irq(drm_device_t * dev, int irq_nr)
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
index 5ad43ba7b5aa..5ed965688293 100644
--- a/drivers/char/drm/radeon_cp.c
+++ b/drivers/char/drm/radeon_cp.c
@@ -864,13 +864,13 @@ static int radeon_do_pixcache_flush(drm_radeon_private_t * dev_priv)
864 864
865 dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; 865 dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
866 866
867 tmp = RADEON_READ(RADEON_RB2D_DSTCACHE_CTLSTAT); 867 tmp = RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT);
868 tmp |= RADEON_RB2D_DC_FLUSH_ALL; 868 tmp |= RADEON_RB3D_DC_FLUSH_ALL;
869 RADEON_WRITE(RADEON_RB2D_DSTCACHE_CTLSTAT, tmp); 869 RADEON_WRITE(RADEON_RB3D_DSTCACHE_CTLSTAT, tmp);
870 870
871 for (i = 0; i < dev_priv->usec_timeout; i++) { 871 for (i = 0; i < dev_priv->usec_timeout; i++) {
872 if (!(RADEON_READ(RADEON_RB2D_DSTCACHE_CTLSTAT) 872 if (!(RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT)
873 & RADEON_RB2D_DC_BUSY)) { 873 & RADEON_RB3D_DC_BUSY)) {
874 return 0; 874 return 0;
875 } 875 }
876 DRM_UDELAY(1); 876 DRM_UDELAY(1);
@@ -1130,7 +1130,7 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev,
1130 | (dev_priv->fb_location >> 16)); 1130 | (dev_priv->fb_location >> 16));
1131 1131
1132#if __OS_HAS_AGP 1132#if __OS_HAS_AGP
1133 if (dev_priv->flags & CHIP_IS_AGP) { 1133 if (dev_priv->flags & RADEON_IS_AGP) {
1134 RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base); 1134 RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base);
1135 RADEON_WRITE(RADEON_MC_AGP_LOCATION, 1135 RADEON_WRITE(RADEON_MC_AGP_LOCATION,
1136 (((dev_priv->gart_vm_start - 1 + 1136 (((dev_priv->gart_vm_start - 1 +
@@ -1158,7 +1158,7 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev,
1158 dev_priv->ring.tail = cur_read_ptr; 1158 dev_priv->ring.tail = cur_read_ptr;
1159 1159
1160#if __OS_HAS_AGP 1160#if __OS_HAS_AGP
1161 if (dev_priv->flags & CHIP_IS_AGP) { 1161 if (dev_priv->flags & RADEON_IS_AGP) {
1162 RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, 1162 RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,
1163 dev_priv->ring_rptr->offset 1163 dev_priv->ring_rptr->offset
1164 - dev->agp->base + dev_priv->gart_vm_start); 1164 - dev->agp->base + dev_priv->gart_vm_start);
@@ -1258,6 +1258,13 @@ static void radeon_test_writeback(drm_radeon_private_t * dev_priv)
1258 dev_priv->writeback_works = 0; 1258 dev_priv->writeback_works = 0;
1259 DRM_INFO("writeback forced off\n"); 1259 DRM_INFO("writeback forced off\n");
1260 } 1260 }
1261
1262 if (!dev_priv->writeback_works) {
1263 /* Disable writeback to avoid unnecessary bus master transfer */
1264 RADEON_WRITE(RADEON_CP_RB_CNTL, RADEON_READ(RADEON_CP_RB_CNTL) |
1265 RADEON_RB_NO_UPDATE);
1266 RADEON_WRITE(RADEON_SCRATCH_UMSK, 0);
1267 }
1261} 1268}
1262 1269
1263/* Enable or disable PCI-E GART on the chip */ 1270/* Enable or disable PCI-E GART on the chip */
@@ -1295,7 +1302,7 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
1295{ 1302{
1296 u32 tmp; 1303 u32 tmp;
1297 1304
1298 if (dev_priv->flags & CHIP_IS_PCIE) { 1305 if (dev_priv->flags & RADEON_IS_PCIE) {
1299 radeon_set_pciegart(dev_priv, on); 1306 radeon_set_pciegart(dev_priv, on);
1300 return; 1307 return;
1301 } 1308 }
@@ -1333,20 +1340,22 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
1333 DRM_DEBUG("\n"); 1340 DRM_DEBUG("\n");
1334 1341
1335 /* if we require new memory map but we don't have it fail */ 1342 /* if we require new memory map but we don't have it fail */
1336 if ((dev_priv->flags & CHIP_NEW_MEMMAP) && !dev_priv->new_memmap) 1343 if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) {
1337 { 1344 DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n");
1338 DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX\n");
1339 radeon_do_cleanup_cp(dev); 1345 radeon_do_cleanup_cp(dev);
1340 return DRM_ERR(EINVAL); 1346 return DRM_ERR(EINVAL);
1341 } 1347 }
1342 1348
1343 if (init->is_pci && (dev_priv->flags & CHIP_IS_AGP)) 1349 if (init->is_pci && (dev_priv->flags & RADEON_IS_AGP)) {
1344 {
1345 DRM_DEBUG("Forcing AGP card to PCI mode\n"); 1350 DRM_DEBUG("Forcing AGP card to PCI mode\n");
1346 dev_priv->flags &= ~CHIP_IS_AGP; 1351 dev_priv->flags &= ~RADEON_IS_AGP;
1352 } else if (!(dev_priv->flags & (RADEON_IS_AGP | RADEON_IS_PCI | RADEON_IS_PCIE))
1353 && !init->is_pci) {
1354 DRM_DEBUG("Restoring AGP flag\n");
1355 dev_priv->flags |= RADEON_IS_AGP;
1347 } 1356 }
1348 1357
1349 if ((!(dev_priv->flags & CHIP_IS_AGP)) && !dev->sg) { 1358 if ((!(dev_priv->flags & RADEON_IS_AGP)) && !dev->sg) {
1350 DRM_ERROR("PCI GART memory not allocated!\n"); 1359 DRM_ERROR("PCI GART memory not allocated!\n");
1351 radeon_do_cleanup_cp(dev); 1360 radeon_do_cleanup_cp(dev);
1352 return DRM_ERR(EINVAL); 1361 return DRM_ERR(EINVAL);
@@ -1489,7 +1498,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
1489 init->sarea_priv_offset); 1498 init->sarea_priv_offset);
1490 1499
1491#if __OS_HAS_AGP 1500#if __OS_HAS_AGP
1492 if (dev_priv->flags & CHIP_IS_AGP) { 1501 if (dev_priv->flags & RADEON_IS_AGP) {
1493 drm_core_ioremap(dev_priv->cp_ring, dev); 1502 drm_core_ioremap(dev_priv->cp_ring, dev);
1494 drm_core_ioremap(dev_priv->ring_rptr, dev); 1503 drm_core_ioremap(dev_priv->ring_rptr, dev);
1495 drm_core_ioremap(dev->agp_buffer_map, dev); 1504 drm_core_ioremap(dev->agp_buffer_map, dev);
@@ -1548,7 +1557,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
1548 * align it down. 1557 * align it down.
1549 */ 1558 */
1550#if __OS_HAS_AGP 1559#if __OS_HAS_AGP
1551 if (dev_priv->flags & CHIP_IS_AGP) { 1560 if (dev_priv->flags & RADEON_IS_AGP) {
1552 base = dev->agp->base; 1561 base = dev->agp->base;
1553 /* Check if valid */ 1562 /* Check if valid */
1554 if ((base + dev_priv->gart_size) > dev_priv->fb_location && 1563 if ((base + dev_priv->gart_size) > dev_priv->fb_location &&
@@ -1578,7 +1587,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
1578 } 1587 }
1579 1588
1580#if __OS_HAS_AGP 1589#if __OS_HAS_AGP
1581 if (dev_priv->flags & CHIP_IS_AGP) 1590 if (dev_priv->flags & RADEON_IS_AGP)
1582 dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset 1591 dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
1583 - dev->agp->base 1592 - dev->agp->base
1584 + dev_priv->gart_vm_start); 1593 + dev_priv->gart_vm_start);
@@ -1604,7 +1613,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
1604 dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK; 1613 dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
1605 1614
1606#if __OS_HAS_AGP 1615#if __OS_HAS_AGP
1607 if (dev_priv->flags & CHIP_IS_AGP) { 1616 if (dev_priv->flags & RADEON_IS_AGP) {
1608 /* Turn off PCI GART */ 1617 /* Turn off PCI GART */
1609 radeon_set_pcigart(dev_priv, 0); 1618 radeon_set_pcigart(dev_priv, 0);
1610 } else 1619 } else
@@ -1624,7 +1633,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
1624 dev_priv->gart_info.mapping.handle; 1633 dev_priv->gart_info.mapping.handle;
1625 1634
1626 dev_priv->gart_info.is_pcie = 1635 dev_priv->gart_info.is_pcie =
1627 !!(dev_priv->flags & CHIP_IS_PCIE); 1636 !!(dev_priv->flags & RADEON_IS_PCIE);
1628 dev_priv->gart_info.gart_table_location = 1637 dev_priv->gart_info.gart_table_location =
1629 DRM_ATI_GART_FB; 1638 DRM_ATI_GART_FB;
1630 1639
@@ -1636,7 +1645,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
1636 DRM_ATI_GART_MAIN; 1645 DRM_ATI_GART_MAIN;
1637 dev_priv->gart_info.addr = NULL; 1646 dev_priv->gart_info.addr = NULL;
1638 dev_priv->gart_info.bus_addr = 0; 1647 dev_priv->gart_info.bus_addr = 0;
1639 if (dev_priv->flags & CHIP_IS_PCIE) { 1648 if (dev_priv->flags & RADEON_IS_PCIE) {
1640 DRM_ERROR 1649 DRM_ERROR
1641 ("Cannot use PCI Express without GART in FB memory\n"); 1650 ("Cannot use PCI Express without GART in FB memory\n");
1642 radeon_do_cleanup_cp(dev); 1651 radeon_do_cleanup_cp(dev);
@@ -1678,7 +1687,7 @@ static int radeon_do_cleanup_cp(drm_device_t * dev)
1678 drm_irq_uninstall(dev); 1687 drm_irq_uninstall(dev);
1679 1688
1680#if __OS_HAS_AGP 1689#if __OS_HAS_AGP
1681 if (dev_priv->flags & CHIP_IS_AGP) { 1690 if (dev_priv->flags & RADEON_IS_AGP) {
1682 if (dev_priv->cp_ring != NULL) { 1691 if (dev_priv->cp_ring != NULL) {
1683 drm_core_ioremapfree(dev_priv->cp_ring, dev); 1692 drm_core_ioremapfree(dev_priv->cp_ring, dev);
1684 dev_priv->cp_ring = NULL; 1693 dev_priv->cp_ring = NULL;
@@ -1733,7 +1742,7 @@ static int radeon_do_resume_cp(drm_device_t * dev)
1733 DRM_DEBUG("Starting radeon_do_resume_cp()\n"); 1742 DRM_DEBUG("Starting radeon_do_resume_cp()\n");
1734 1743
1735#if __OS_HAS_AGP 1744#if __OS_HAS_AGP
1736 if (dev_priv->flags & CHIP_IS_AGP) { 1745 if (dev_priv->flags & RADEON_IS_AGP) {
1737 /* Turn off PCI GART */ 1746 /* Turn off PCI GART */
1738 radeon_set_pcigart(dev_priv, 0); 1747 radeon_set_pcigart(dev_priv, 0);
1739 } else 1748 } else
@@ -2177,13 +2186,15 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
2177 dev->dev_private = (void *)dev_priv; 2186 dev->dev_private = (void *)dev_priv;
2178 dev_priv->flags = flags; 2187 dev_priv->flags = flags;
2179 2188
2180 switch (flags & CHIP_FAMILY_MASK) { 2189 switch (flags & RADEON_FAMILY_MASK) {
2181 case CHIP_R100: 2190 case CHIP_R100:
2182 case CHIP_RV200: 2191 case CHIP_RV200:
2183 case CHIP_R200: 2192 case CHIP_R200:
2184 case CHIP_R300: 2193 case CHIP_R300:
2194 case CHIP_R350:
2185 case CHIP_R420: 2195 case CHIP_R420:
2186 dev_priv->flags |= CHIP_HAS_HIERZ; 2196 case CHIP_RV410:
2197 dev_priv->flags |= RADEON_HAS_HIERZ;
2187 break; 2198 break;
2188 default: 2199 default:
2189 /* all other chips have no hierarchical z buffer */ 2200 /* all other chips have no hierarchical z buffer */
@@ -2191,13 +2202,14 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
2191 } 2202 }
2192 2203
2193 if (drm_device_is_agp(dev)) 2204 if (drm_device_is_agp(dev))
2194 dev_priv->flags |= CHIP_IS_AGP; 2205 dev_priv->flags |= RADEON_IS_AGP;
2195 2206 else if (drm_device_is_pcie(dev))
2196 if (drm_device_is_pcie(dev)) 2207 dev_priv->flags |= RADEON_IS_PCIE;
2197 dev_priv->flags |= CHIP_IS_PCIE; 2208 else
2209 dev_priv->flags |= RADEON_IS_PCI;
2198 2210
2199 DRM_DEBUG("%s card detected\n", 2211 DRM_DEBUG("%s card detected\n",
2200 ((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : (((dev_priv->flags & CHIP_IS_PCIE) ? "PCIE" : "PCI")))); 2212 ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI"))));
2201 return ret; 2213 return ret;
2202} 2214}
2203 2215
diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
index eb985c2a31e9..2eb652ec6745 100644
--- a/drivers/char/drm/radeon_drv.c
+++ b/drivers/char/drm/radeon_drv.c
@@ -44,7 +44,7 @@ module_param_named(no_wb, radeon_no_wb, int, 0444);
44static int dri_library_name(struct drm_device *dev, char *buf) 44static int dri_library_name(struct drm_device *dev, char *buf)
45{ 45{
46 drm_radeon_private_t *dev_priv = dev->dev_private; 46 drm_radeon_private_t *dev_priv = dev->dev_private;
47 int family = dev_priv->flags & CHIP_FAMILY_MASK; 47 int family = dev_priv->flags & RADEON_FAMILY_MASK;
48 48
49 return snprintf(buf, PAGE_SIZE, "%s\n", 49 return snprintf(buf, PAGE_SIZE, "%s\n",
50 (family < CHIP_R200) ? "radeon" : 50 (family < CHIP_R200) ? "radeon" :
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index e5a256f5429c..f45cd7f147a5 100644
--- a/drivers/char/drm/radeon_drv.h
+++ b/drivers/char/drm/radeon_drv.h
@@ -133,15 +133,16 @@ enum radeon_cp_microcode_version {
133 * Chip flags 133 * Chip flags
134 */ 134 */
135enum radeon_chip_flags { 135enum radeon_chip_flags {
136 CHIP_FAMILY_MASK = 0x0000ffffUL, 136 RADEON_FAMILY_MASK = 0x0000ffffUL,
137 CHIP_FLAGS_MASK = 0xffff0000UL, 137 RADEON_FLAGS_MASK = 0xffff0000UL,
138 CHIP_IS_MOBILITY = 0x00010000UL, 138 RADEON_IS_MOBILITY = 0x00010000UL,
139 CHIP_IS_IGP = 0x00020000UL, 139 RADEON_IS_IGP = 0x00020000UL,
140 CHIP_SINGLE_CRTC = 0x00040000UL, 140 RADEON_SINGLE_CRTC = 0x00040000UL,
141 CHIP_IS_AGP = 0x00080000UL, 141 RADEON_IS_AGP = 0x00080000UL,
142 CHIP_HAS_HIERZ = 0x00100000UL, 142 RADEON_HAS_HIERZ = 0x00100000UL,
143 CHIP_IS_PCIE = 0x00200000UL, 143 RADEON_IS_PCIE = 0x00200000UL,
144 CHIP_NEW_MEMMAP = 0x00400000UL, 144 RADEON_NEW_MEMMAP = 0x00400000UL,
145 RADEON_IS_PCI = 0x00800000UL,
145}; 146};
146 147
147#define GET_RING_HEAD(dev_priv) (dev_priv->writeback_works ? \ 148#define GET_RING_HEAD(dev_priv) (dev_priv->writeback_works ? \
@@ -424,6 +425,8 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,
424#define RADEON_RB3D_COLOROFFSET 0x1c40 425#define RADEON_RB3D_COLOROFFSET 0x1c40
425#define RADEON_RB3D_COLORPITCH 0x1c48 426#define RADEON_RB3D_COLORPITCH 0x1c48
426 427
428#define RADEON_SRC_X_Y 0x1590
429
427#define RADEON_DP_GUI_MASTER_CNTL 0x146c 430#define RADEON_DP_GUI_MASTER_CNTL 0x146c
428# define RADEON_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0) 431# define RADEON_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0)
429# define RADEON_GMC_DST_PITCH_OFFSET_CNTL (1 << 1) 432# define RADEON_GMC_DST_PITCH_OFFSET_CNTL (1 << 1)
@@ -441,6 +444,7 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,
441# define RADEON_ROP3_S 0x00cc0000 444# define RADEON_ROP3_S 0x00cc0000
442# define RADEON_ROP3_P 0x00f00000 445# define RADEON_ROP3_P 0x00f00000
443#define RADEON_DP_WRITE_MASK 0x16cc 446#define RADEON_DP_WRITE_MASK 0x16cc
447#define RADEON_SRC_PITCH_OFFSET 0x1428
444#define RADEON_DST_PITCH_OFFSET 0x142c 448#define RADEON_DST_PITCH_OFFSET 0x142c
445#define RADEON_DST_PITCH_OFFSET_C 0x1c80 449#define RADEON_DST_PITCH_OFFSET_C 0x1c80
446# define RADEON_DST_TILE_LINEAR (0 << 30) 450# define RADEON_DST_TILE_LINEAR (0 << 30)
@@ -545,6 +549,11 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,
545# define RADEON_RB3D_ZC_FREE (1 << 2) 549# define RADEON_RB3D_ZC_FREE (1 << 2)
546# define RADEON_RB3D_ZC_FLUSH_ALL 0x5 550# define RADEON_RB3D_ZC_FLUSH_ALL 0x5
547# define RADEON_RB3D_ZC_BUSY (1 << 31) 551# define RADEON_RB3D_ZC_BUSY (1 << 31)
552#define RADEON_RB3D_DSTCACHE_CTLSTAT 0x325c
553# define RADEON_RB3D_DC_FLUSH (3 << 0)
554# define RADEON_RB3D_DC_FREE (3 << 2)
555# define RADEON_RB3D_DC_FLUSH_ALL 0xf
556# define RADEON_RB3D_DC_BUSY (1 << 31)
548#define RADEON_RB3D_ZSTENCILCNTL 0x1c2c 557#define RADEON_RB3D_ZSTENCILCNTL 0x1c2c
549# define RADEON_Z_TEST_MASK (7 << 4) 558# define RADEON_Z_TEST_MASK (7 << 4)
550# define RADEON_Z_TEST_ALWAYS (7 << 4) 559# define RADEON_Z_TEST_ALWAYS (7 << 4)
@@ -681,6 +690,7 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,
681#define RADEON_CP_RB_BASE 0x0700 690#define RADEON_CP_RB_BASE 0x0700
682#define RADEON_CP_RB_CNTL 0x0704 691#define RADEON_CP_RB_CNTL 0x0704
683# define RADEON_BUF_SWAP_32BIT (2 << 16) 692# define RADEON_BUF_SWAP_32BIT (2 << 16)
693# define RADEON_RB_NO_UPDATE (1 << 27)
684#define RADEON_CP_RB_RPTR_ADDR 0x070c 694#define RADEON_CP_RB_RPTR_ADDR 0x070c
685#define RADEON_CP_RB_RPTR 0x0710 695#define RADEON_CP_RB_RPTR 0x0710
686#define RADEON_CP_RB_WPTR 0x0714 696#define RADEON_CP_RB_WPTR 0x0714
@@ -986,13 +996,13 @@ do { \
986} while (0) 996} while (0)
987 997
988#define RADEON_FLUSH_CACHE() do { \ 998#define RADEON_FLUSH_CACHE() do { \
989 OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) ); \ 999 OUT_RING( CP_PACKET0( RADEON_RB3D_DSTCACHE_CTLSTAT, 0 ) ); \
990 OUT_RING( RADEON_RB2D_DC_FLUSH ); \ 1000 OUT_RING( RADEON_RB3D_DC_FLUSH ); \
991} while (0) 1001} while (0)
992 1002
993#define RADEON_PURGE_CACHE() do { \ 1003#define RADEON_PURGE_CACHE() do { \
994 OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) ); \ 1004 OUT_RING( CP_PACKET0( RADEON_RB3D_DSTCACHE_CTLSTAT, 0 ) ); \
995 OUT_RING( RADEON_RB2D_DC_FLUSH_ALL ); \ 1005 OUT_RING( RADEON_RB3D_DC_FLUSH_ALL ); \
996} while (0) 1006} while (0)
997 1007
998#define RADEON_FLUSH_ZCACHE() do { \ 1008#define RADEON_FLUSH_ZCACHE() do { \
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
index 39a7f685e3fd..feac5f005d47 100644
--- a/drivers/char/drm/radeon_state.c
+++ b/drivers/char/drm/radeon_state.c
@@ -42,7 +42,11 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
42 drm_file_t * filp_priv, 42 drm_file_t * filp_priv,
43 u32 *offset) 43 u32 *offset)
44{ 44{
45 u32 off = *offset; 45 u64 off = *offset;
46 u32 fb_start = dev_priv->fb_location;
47 u32 fb_end = fb_start + dev_priv->fb_size - 1;
48 u32 gart_start = dev_priv->gart_vm_start;
49 u32 gart_end = gart_start + dev_priv->gart_size - 1;
46 struct drm_radeon_driver_file_fields *radeon_priv; 50 struct drm_radeon_driver_file_fields *radeon_priv;
47 51
48 /* Hrm ... the story of the offset ... So this function converts 52 /* Hrm ... the story of the offset ... So this function converts
@@ -62,10 +66,8 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
62 /* First, the best case, the offset already lands in either the 66 /* First, the best case, the offset already lands in either the
63 * framebuffer or the GART mapped space 67 * framebuffer or the GART mapped space
64 */ 68 */
65 if ((off >= dev_priv->fb_location && 69 if ((off >= fb_start && off <= fb_end) ||
66 off < (dev_priv->fb_location + dev_priv->fb_size)) || 70 (off >= gart_start && off <= gart_end))
67 (off >= dev_priv->gart_vm_start &&
68 off < (dev_priv->gart_vm_start + dev_priv->gart_size)))
69 return 0; 71 return 0;
70 72
71 /* Ok, that didn't happen... now check if we have a zero based 73 /* Ok, that didn't happen... now check if we have a zero based
@@ -78,16 +80,13 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
78 } 80 }
79 81
80 /* Finally, assume we aimed at a GART offset if beyond the fb */ 82 /* Finally, assume we aimed at a GART offset if beyond the fb */
81 if (off > (dev_priv->fb_location + dev_priv->fb_size)) 83 if (off > fb_end)
82 off = off - (dev_priv->fb_location + dev_priv->fb_size) + 84 off = off - fb_end - 1 + gart_start;
83 dev_priv->gart_vm_start;
84 85
85 /* Now recheck and fail if out of bounds */ 86 /* Now recheck and fail if out of bounds */
86 if ((off >= dev_priv->fb_location && 87 if ((off >= fb_start && off <= fb_end) ||
87 off < (dev_priv->fb_location + dev_priv->fb_size)) || 88 (off >= gart_start && off <= gart_end)) {
88 (off >= dev_priv->gart_vm_start && 89 DRM_DEBUG("offset fixed up to 0x%x\n", (unsigned int)off);
89 off < (dev_priv->gart_vm_start + dev_priv->gart_size))) {
90 DRM_DEBUG("offset fixed up to 0x%x\n", off);
91 *offset = off; 90 *offset = off;
92 return 0; 91 return 0;
93 } 92 }
@@ -869,7 +868,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev,
869 */ 868 */
870 dev_priv->sarea_priv->ctx_owner = 0; 869 dev_priv->sarea_priv->ctx_owner = 0;
871 870
872 if ((dev_priv->flags & CHIP_HAS_HIERZ) 871 if ((dev_priv->flags & RADEON_HAS_HIERZ)
873 && (flags & RADEON_USE_HIERZ)) { 872 && (flags & RADEON_USE_HIERZ)) {
874 /* FIXME : reverse engineer that for Rx00 cards */ 873 /* FIXME : reverse engineer that for Rx00 cards */
875 /* FIXME : the mask supposedly contains low-res z values. So can't set 874 /* FIXME : the mask supposedly contains low-res z values. So can't set
@@ -914,7 +913,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev,
914 for (i = 0; i < nbox; i++) { 913 for (i = 0; i < nbox; i++) {
915 int tileoffset, nrtilesx, nrtilesy, j; 914 int tileoffset, nrtilesx, nrtilesy, j;
916 /* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */ 915 /* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */
917 if ((dev_priv->flags & CHIP_HAS_HIERZ) 916 if ((dev_priv->flags & RADEON_HAS_HIERZ)
918 && !(dev_priv->microcode_version == UCODE_R200)) { 917 && !(dev_priv->microcode_version == UCODE_R200)) {
919 /* FIXME : figure this out for r200 (when hierz is enabled). Or 918 /* FIXME : figure this out for r200 (when hierz is enabled). Or
920 maybe r200 actually doesn't need to put the low-res z value into 919 maybe r200 actually doesn't need to put the low-res z value into
@@ -998,7 +997,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev,
998 } 997 }
999 998
1000 /* TODO don't always clear all hi-level z tiles */ 999 /* TODO don't always clear all hi-level z tiles */
1001 if ((dev_priv->flags & CHIP_HAS_HIERZ) 1000 if ((dev_priv->flags & RADEON_HAS_HIERZ)
1002 && (dev_priv->microcode_version == UCODE_R200) 1001 && (dev_priv->microcode_version == UCODE_R200)
1003 && (flags & RADEON_USE_HIERZ)) 1002 && (flags & RADEON_USE_HIERZ))
1004 /* r100 and cards without hierarchical z-buffer have no high-level z-buffer */ 1003 /* r100 and cards without hierarchical z-buffer have no high-level z-buffer */
@@ -1270,9 +1269,9 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev)
1270 1269
1271 DRM_DEBUG("dispatch swap %d,%d-%d,%d\n", x, y, w, h); 1270 DRM_DEBUG("dispatch swap %d,%d-%d,%d\n", x, y, w, h);
1272 1271
1273 BEGIN_RING(7); 1272 BEGIN_RING(9);
1274 1273
1275 OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5)); 1274 OUT_RING(CP_PACKET0(RADEON_DP_GUI_MASTER_CNTL, 0));
1276 OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL | 1275 OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
1277 RADEON_GMC_DST_PITCH_OFFSET_CNTL | 1276 RADEON_GMC_DST_PITCH_OFFSET_CNTL |
1278 RADEON_GMC_BRUSH_NONE | 1277 RADEON_GMC_BRUSH_NONE |
@@ -1284,6 +1283,7 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev)
1284 1283
1285 /* Make this work even if front & back are flipped: 1284 /* Make this work even if front & back are flipped:
1286 */ 1285 */
1286 OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1));
1287 if (dev_priv->current_page == 0) { 1287 if (dev_priv->current_page == 0) {
1288 OUT_RING(dev_priv->back_pitch_offset); 1288 OUT_RING(dev_priv->back_pitch_offset);
1289 OUT_RING(dev_priv->front_pitch_offset); 1289 OUT_RING(dev_priv->front_pitch_offset);
@@ -1292,6 +1292,7 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev)
1292 OUT_RING(dev_priv->back_pitch_offset); 1292 OUT_RING(dev_priv->back_pitch_offset);
1293 } 1293 }
1294 1294
1295 OUT_RING(CP_PACKET0(RADEON_SRC_X_Y, 2));
1295 OUT_RING((x << 16) | y); 1296 OUT_RING((x << 16) | y);
1296 OUT_RING((x << 16) | y); 1297 OUT_RING((x << 16) | y);
1297 OUT_RING((w << 16) | h); 1298 OUT_RING((w << 16) | h);
@@ -2987,16 +2988,21 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS)
2987 case RADEON_PARAM_GART_TEX_HANDLE: 2988 case RADEON_PARAM_GART_TEX_HANDLE:
2988 value = dev_priv->gart_textures_offset; 2989 value = dev_priv->gart_textures_offset;
2989 break; 2990 break;
2990 2991 case RADEON_PARAM_SCRATCH_OFFSET:
2992 if (!dev_priv->writeback_works)
2993 return DRM_ERR(EINVAL);
2994 value = RADEON_SCRATCH_REG_OFFSET;
2995 break;
2991 case RADEON_PARAM_CARD_TYPE: 2996 case RADEON_PARAM_CARD_TYPE:
2992 if (dev_priv->flags & CHIP_IS_PCIE) 2997 if (dev_priv->flags & RADEON_IS_PCIE)
2993 value = RADEON_CARD_PCIE; 2998 value = RADEON_CARD_PCIE;
2994 else if (dev_priv->flags & CHIP_IS_AGP) 2999 else if (dev_priv->flags & RADEON_IS_AGP)
2995 value = RADEON_CARD_AGP; 3000 value = RADEON_CARD_AGP;
2996 else 3001 else
2997 value = RADEON_CARD_PCI; 3002 value = RADEON_CARD_PCI;
2998 break; 3003 break;
2999 default: 3004 default:
3005 DRM_DEBUG("Invalid parameter %d\n", param.param);
3000 return DRM_ERR(EINVAL); 3006 return DRM_ERR(EINVAL);
3001 } 3007 }
3002 3008
diff --git a/drivers/char/drm/sis_drv.c b/drivers/char/drm/sis_drv.c
index 5e9dc86f2956..3d5b3218b6ff 100644
--- a/drivers/char/drm/sis_drv.c
+++ b/drivers/char/drm/sis_drv.c
@@ -35,11 +35,44 @@ static struct pci_device_id pciidlist[] = {
35 sisdrv_PCI_IDS 35 sisdrv_PCI_IDS
36}; 36};
37 37
38static int sis_driver_load(drm_device_t *dev, unsigned long chipset)
39{
40 drm_sis_private_t *dev_priv;
41 int ret;
42
43 dev_priv = drm_calloc(1, sizeof(drm_sis_private_t), DRM_MEM_DRIVER);
44 if (dev_priv == NULL)
45 return DRM_ERR(ENOMEM);
46
47 dev->dev_private = (void *)dev_priv;
48 dev_priv->chipset = chipset;
49 ret = drm_sman_init(&dev_priv->sman, 2, 12, 8);
50 if (ret) {
51 drm_free(dev_priv, sizeof(dev_priv), DRM_MEM_DRIVER);
52 }
53
54 return ret;
55}
56
57static int sis_driver_unload(drm_device_t *dev)
58{
59 drm_sis_private_t *dev_priv = dev->dev_private;
60
61 drm_sman_takedown(&dev_priv->sman);
62 drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
63
64 return 0;
65}
66
38static struct drm_driver driver = { 67static struct drm_driver driver = {
39 .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR, 68 .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR,
40 .context_ctor = sis_init_context, 69 .load = sis_driver_load,
41 .context_dtor = sis_final_context, 70 .unload = sis_driver_unload,
42 .reclaim_buffers = drm_core_reclaim_buffers, 71 .context_dtor = NULL,
72 .dma_quiescent = sis_idle,
73 .reclaim_buffers = NULL,
74 .reclaim_buffers_locked = sis_reclaim_buffers_locked,
75 .lastclose = sis_lastclose,
43 .get_map_ofs = drm_core_get_map_ofs, 76 .get_map_ofs = drm_core_get_map_ofs,
44 .get_reg_ofs = drm_core_get_reg_ofs, 77 .get_reg_ofs = drm_core_get_reg_ofs,
45 .ioctls = sis_ioctls, 78 .ioctls = sis_ioctls,
diff --git a/drivers/char/drm/sis_drv.h b/drivers/char/drm/sis_drv.h
index e218e5269503..2b8d6f6ed7c0 100644
--- a/drivers/char/drm/sis_drv.h
+++ b/drivers/char/drm/sis_drv.h
@@ -31,23 +31,39 @@
31/* General customization: 31/* General customization:
32 */ 32 */
33 33
34#define DRIVER_AUTHOR "SIS" 34#define DRIVER_AUTHOR "SIS, Tungsten Graphics"
35#define DRIVER_NAME "sis" 35#define DRIVER_NAME "sis"
36#define DRIVER_DESC "SIS 300/630/540" 36#define DRIVER_DESC "SIS 300/630/540"
37#define DRIVER_DATE "20030826" 37#define DRIVER_DATE "20060704"
38#define DRIVER_MAJOR 1 38#define DRIVER_MAJOR 1
39#define DRIVER_MINOR 1 39#define DRIVER_MINOR 2
40#define DRIVER_PATCHLEVEL 0 40#define DRIVER_PATCHLEVEL 1
41 41
42#include "sis_ds.h" 42enum sis_family {
43 SIS_OTHER = 0,
44 SIS_CHIP_315 = 1,
45};
46
47#include "drm_sman.h"
48
49#define SIS_BASE (dev_priv->mmio)
50#define SIS_READ(reg) DRM_READ32(SIS_BASE, reg);
51#define SIS_WRITE(reg, val) DRM_WRITE32(SIS_BASE, reg, val);
43 52
44typedef struct drm_sis_private { 53typedef struct drm_sis_private {
45 memHeap_t *AGPHeap; 54 drm_local_map_t *mmio;
46 memHeap_t *FBHeap; 55 unsigned int idle_fault;
56 drm_sman_t sman;
57 unsigned int chipset;
58 int vram_initialized;
59 int agp_initialized;
60 unsigned long vram_offset;
61 unsigned long agp_offset;
47} drm_sis_private_t; 62} drm_sis_private_t;
48 63
49extern int sis_init_context(drm_device_t * dev, int context); 64extern int sis_idle(drm_device_t *dev);
50extern int sis_final_context(drm_device_t * dev, int context); 65extern void sis_reclaim_buffers_locked(drm_device_t *dev, struct file *filp);
66extern void sis_lastclose(drm_device_t *dev);
51 67
52extern drm_ioctl_desc_t sis_ioctls[]; 68extern drm_ioctl_desc_t sis_ioctls[];
53extern int sis_max_ioctl; 69extern int sis_max_ioctl;
diff --git a/drivers/char/drm/sis_ds.c b/drivers/char/drm/sis_ds.c
deleted file mode 100644
index 2e485d482943..000000000000
--- a/drivers/char/drm/sis_ds.c
+++ /dev/null
@@ -1,299 +0,0 @@
1/* sis_ds.c -- Private header for Direct Rendering Manager -*- linux-c -*-
2 * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw
3 *
4 * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
5 * All rights reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * Authors:
27 * Sung-Ching Lin <sclin@sis.com.tw>
28 *
29 */
30
31#include "drmP.h"
32#include "drm.h"
33#include "sis_ds.h"
34
35/* Set Data Structure, not check repeated value
36 * temporarily used
37 */
38
39set_t *setInit(void)
40{
41 int i;
42 set_t *set;
43
44 set = (set_t *) drm_alloc(sizeof(set_t), DRM_MEM_DRIVER);
45 if (set != NULL) {
46 for (i = 0; i < SET_SIZE; i++) {
47 set->list[i].free_next = i + 1;
48 set->list[i].alloc_next = -1;
49 }
50 set->list[SET_SIZE - 1].free_next = -1;
51 set->free = 0;
52 set->alloc = -1;
53 set->trace = -1;
54 }
55 return set;
56}
57
58int setAdd(set_t * set, ITEM_TYPE item)
59{
60 int free = set->free;
61
62 if (free != -1) {
63 set->list[free].val = item;
64 set->free = set->list[free].free_next;
65 } else {
66 return 0;
67 }
68
69 set->list[free].alloc_next = set->alloc;
70 set->alloc = free;
71 set->list[free].free_next = -1;
72
73 return 1;
74}
75
76int setDel(set_t * set, ITEM_TYPE item)
77{
78 int alloc = set->alloc;
79 int prev = -1;
80
81 while (alloc != -1) {
82 if (set->list[alloc].val == item) {
83 if (prev != -1)
84 set->list[prev].alloc_next =
85 set->list[alloc].alloc_next;
86 else
87 set->alloc = set->list[alloc].alloc_next;
88 break;
89 }
90 prev = alloc;
91 alloc = set->list[alloc].alloc_next;
92 }
93
94 if (alloc == -1)
95 return 0;
96
97 set->list[alloc].free_next = set->free;
98 set->free = alloc;
99 set->list[alloc].alloc_next = -1;
100
101 return 1;
102}
103
104/* setFirst -> setAdd -> setNext is wrong */
105
106int setFirst(set_t * set, ITEM_TYPE * item)
107{
108 if (set->alloc == -1)
109 return 0;
110
111 *item = set->list[set->alloc].val;
112 set->trace = set->list[set->alloc].alloc_next;
113
114 return 1;
115}
116
117int setNext(set_t * set, ITEM_TYPE * item)
118{
119 if (set->trace == -1)
120 return 0;
121
122 *item = set->list[set->trace].val;
123 set->trace = set->list[set->trace].alloc_next;
124
125 return 1;
126}
127
128int setDestroy(set_t * set)
129{
130 drm_free(set, sizeof(set_t), DRM_MEM_DRIVER);
131
132 return 1;
133}
134
135/*
136 * GLX Hardware Device Driver common code
137 * Copyright (C) 1999 Wittawat Yamwong
138 *
139 * Permission is hereby granted, free of charge, to any person obtaining a
140 * copy of this software and associated documentation files (the "Software"),
141 * to deal in the Software without restriction, including without limitation
142 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
143 * and/or sell copies of the Software, and to permit persons to whom the
144 * Software is furnished to do so, subject to the following conditions:
145 *
146 * The above copyright notice and this permission notice shall be included
147 * in all copies or substantial portions of the Software.
148 *
149 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
150 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
151 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
152 * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
153 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
154 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
155 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
156 *
157 */
158
159#define ISFREE(bptr) ((bptr)->free)
160
161memHeap_t *mmInit(int ofs, int size)
162{
163 PMemBlock blocks;
164
165 if (size <= 0)
166 return NULL;
167
168 blocks = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock), DRM_MEM_DRIVER);
169 if (blocks != NULL) {
170 blocks->ofs = ofs;
171 blocks->size = size;
172 blocks->free = 1;
173 return (memHeap_t *) blocks;
174 } else
175 return NULL;
176}
177
178/* Checks if a pointer 'b' is part of the heap 'heap' */
179int mmBlockInHeap(memHeap_t * heap, PMemBlock b)
180{
181 TMemBlock *p;
182
183 if (heap == NULL || b == NULL)
184 return 0;
185
186 p = heap;
187 while (p != NULL && p != b) {
188 p = p->next;
189 }
190 if (p == b)
191 return 1;
192 else
193 return 0;
194}
195
196static TMemBlock *SliceBlock(TMemBlock * p,
197 int startofs, int size,
198 int reserved, int alignment)
199{
200 TMemBlock *newblock;
201
202 /* break left */
203 if (startofs > p->ofs) {
204 newblock = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock),
205 DRM_MEM_DRIVER);
206 newblock->ofs = startofs;
207 newblock->size = p->size - (startofs - p->ofs);
208 newblock->free = 1;
209 newblock->next = p->next;
210 p->size -= newblock->size;
211 p->next = newblock;
212 p = newblock;
213 }
214
215 /* break right */
216 if (size < p->size) {
217 newblock = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock),
218 DRM_MEM_DRIVER);
219 newblock->ofs = startofs + size;
220 newblock->size = p->size - size;
221 newblock->free = 1;
222 newblock->next = p->next;
223 p->size = size;
224 p->next = newblock;
225 }
226
227 /* p = middle block */
228 p->align = alignment;
229 p->free = 0;
230 p->reserved = reserved;
231 return p;
232}
233
234PMemBlock mmAllocMem(memHeap_t * heap, int size, int align2, int startSearch)
235{
236 int mask, startofs, endofs;
237 TMemBlock *p;
238
239 if (heap == NULL || align2 < 0 || size <= 0)
240 return NULL;
241
242 mask = (1 << align2) - 1;
243 startofs = 0;
244 p = (TMemBlock *) heap;
245 while (p != NULL) {
246 if (ISFREE(p)) {
247 startofs = (p->ofs + mask) & ~mask;
248 if (startofs < startSearch) {
249 startofs = startSearch;
250 }
251 endofs = startofs + size;
252 if (endofs <= (p->ofs + p->size))
253 break;
254 }
255 p = p->next;
256 }
257 if (p == NULL)
258 return NULL;
259 p = SliceBlock(p, startofs, size, 0, mask + 1);
260 p->heap = heap;
261 return p;
262}
263
264static __inline__ int Join2Blocks(TMemBlock * p)
265{
266 if (p->free && p->next && p->next->free) {
267 TMemBlock *q = p->next;
268 p->size += q->size;
269 p->next = q->next;
270 drm_free(q, sizeof(TMemBlock), DRM_MEM_DRIVER);
271 return 1;
272 }
273 return 0;
274}
275
276int mmFreeMem(PMemBlock b)
277{
278 TMemBlock *p, *prev;
279
280 if (b == NULL)
281 return 0;
282 if (b->heap == NULL)
283 return -1;
284
285 p = b->heap;
286 prev = NULL;
287 while (p != NULL && p != b) {
288 prev = p;
289 p = p->next;
290 }
291 if (p == NULL || p->free || p->reserved)
292 return -1;
293
294 p->free = 1;
295 Join2Blocks(p);
296 if (prev)
297 Join2Blocks(prev);
298 return 0;
299}
diff --git a/drivers/char/drm/sis_ds.h b/drivers/char/drm/sis_ds.h
deleted file mode 100644
index 94f2b4728b63..000000000000
--- a/drivers/char/drm/sis_ds.h
+++ /dev/null
@@ -1,146 +0,0 @@
1/* sis_ds.h -- Private header for Direct Rendering Manager -*- linux-c -*-
2 * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw
3 */
4/*
5 * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
6 * All rights reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 *
27 * Authors:
28 * Sung-Ching Lin <sclin@sis.com.tw>
29 *
30 */
31
32#ifndef __SIS_DS_H__
33#define __SIS_DS_H__
34
35/* Set Data Structure */
36
37#define SET_SIZE 5000
38
39typedef unsigned long ITEM_TYPE;
40
41typedef struct {
42 ITEM_TYPE val;
43 int alloc_next, free_next;
44} list_item_t;
45
46typedef struct {
47 int alloc;
48 int free;
49 int trace;
50 list_item_t list[SET_SIZE];
51} set_t;
52
53set_t *setInit(void);
54int setAdd(set_t * set, ITEM_TYPE item);
55int setDel(set_t * set, ITEM_TYPE item);
56int setFirst(set_t * set, ITEM_TYPE * item);
57int setNext(set_t * set, ITEM_TYPE * item);
58int setDestroy(set_t * set);
59
60/*
61 * GLX Hardware Device Driver common code
62 * Copyright (C) 1999 Wittawat Yamwong
63 *
64 * Permission is hereby granted, free of charge, to any person obtaining a
65 * copy of this software and associated documentation files (the "Software"),
66 * to deal in the Software without restriction, including without limitation
67 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
68 * and/or sell copies of the Software, and to permit persons to whom the
69 * Software is furnished to do so, subject to the following conditions:
70 *
71 * The above copyright notice and this permission notice shall be included
72 * in all copies or substantial portions of the Software.
73 *
74 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
75 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
76 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
77 * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
78 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
79 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
80 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
81 *
82 */
83
84struct mem_block_t {
85 struct mem_block_t *next;
86 struct mem_block_t *heap;
87 int ofs, size;
88 int align;
89 unsigned int free:1;
90 unsigned int reserved:1;
91};
92typedef struct mem_block_t TMemBlock;
93typedef struct mem_block_t *PMemBlock;
94
95/* a heap is just the first block in a chain */
96typedef struct mem_block_t memHeap_t;
97
98static __inline__ int mmBlockSize(PMemBlock b)
99{
100 return b->size;
101}
102
103static __inline__ int mmOffset(PMemBlock b)
104{
105 return b->ofs;
106}
107
108static __inline__ void mmMarkReserved(PMemBlock b)
109{
110 b->reserved = 1;
111}
112
113/*
114 * input: total size in bytes
115 * return: a heap pointer if OK, NULL if error
116 */
117memHeap_t *mmInit(int ofs, int size);
118
119/*
120 * Allocate 'size' bytes with 2^align2 bytes alignment,
121 * restrict the search to free memory after 'startSearch'
122 * depth and back buffers should be in different 4mb banks
123 * to get better page hits if possible
124 * input: size = size of block
125 * align2 = 2^align2 bytes alignment
126 * startSearch = linear offset from start of heap to begin search
127 * return: pointer to the allocated block, 0 if error
128 */
129PMemBlock mmAllocMem(memHeap_t * heap, int size, int align2, int startSearch);
130
131/*
132 * Returns 1 if the block 'b' is part of the heap 'heap'
133 */
134int mmBlockInHeap(PMemBlock heap, PMemBlock b);
135
136/*
137 * Free block starts at offset
138 * input: pointer to a block
139 * return: 0 if OK, -1 if error
140 */
141int mmFreeMem(PMemBlock b);
142
143/* For debuging purpose. */
144void mmDumpMemInfo(memHeap_t * mmInit);
145
146#endif /* __SIS_DS_H__ */
diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c
index 5e9936bc307f..d26f5dbb7853 100644
--- a/drivers/char/drm/sis_mm.c
+++ b/drivers/char/drm/sis_mm.c
@@ -1,414 +1,348 @@
1/* sis_mm.c -- Private header for Direct Rendering Manager -*- linux-c -*- 1/**************************************************************************
2 * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw
3 * 2 *
4 * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan. 3 * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA.
5 * All rights reserved. 4 * All Rights Reserved.
6 * 5 *
7 * Permission is hereby granted, free of charge, to any person obtaining a 6 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"), 7 * copy of this software and associated documentation files (the
9 * to deal in the Software without restriction, including without limitation 8 * "Software"), to deal in the Software without restriction, including
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * without limitation the rights to use, copy, modify, merge, publish,
11 * and/or sell copies of the Software, and to permit persons to whom the 10 * distribute, sub license, and/or sell copies of the Software, and to
12 * Software is furnished to do so, subject to the following conditions: 11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 * 13 *
14 * The above copyright notice and this permission notice (including the next 14 * The above copyright notice and this permission notice (including the
15 * paragraph) shall be included in all copies or substantial portions of the 15 * next paragraph) shall be included in all copies or substantial portions
16 * Software. 16 * of the Software.
17 * 17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 * DEALINGS IN THE SOFTWARE. 24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 * 25 *
26 * Authors:
27 * Sung-Ching Lin <sclin@sis.com.tw>
28 * 26 *
27 **************************************************************************/
28
29/*
30 * Authors:
31 * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
29 */ 32 */
30 33
31#include "drmP.h" 34#include "drmP.h"
32#include "sis_drm.h" 35#include "sis_drm.h"
33#include "sis_drv.h" 36#include "sis_drv.h"
34#include "sis_ds.h" 37
35#if defined(__linux__) && defined(CONFIG_FB_SIS)
36#include <video/sisfb.h> 38#include <video/sisfb.h>
37#endif
38 39
39#define MAX_CONTEXT 100
40#define VIDEO_TYPE 0 40#define VIDEO_TYPE 0
41#define AGP_TYPE 1 41#define AGP_TYPE 1
42 42
43typedef struct {
44 int used;
45 int context;
46 set_t *sets[2]; /* 0 for video, 1 for AGP */
47} sis_context_t;
48 43
49static sis_context_t global_ppriv[MAX_CONTEXT]; 44#if defined(CONFIG_FB_SIS)
45/* fb management via fb device */
50 46
51static int add_alloc_set(int context, int type, unsigned int val) 47#define SIS_MM_ALIGN_SHIFT 0
52{ 48#define SIS_MM_ALIGN_MASK 0
53 int i, retval = 0;
54 49
55 for (i = 0; i < MAX_CONTEXT; i++) { 50static void *sis_sman_mm_allocate(void *private, unsigned long size,
56 if (global_ppriv[i].used && global_ppriv[i].context == context) { 51 unsigned alignment)
57 retval = setAdd(global_ppriv[i].sets[type], val);
58 break;
59 }
60 }
61 return retval;
62}
63
64static int del_alloc_set(int context, int type, unsigned int val)
65{ 52{
66 int i, retval = 0; 53 struct sis_memreq req;
67 54
68 for (i = 0; i < MAX_CONTEXT; i++) { 55 req.size = size;
69 if (global_ppriv[i].used && global_ppriv[i].context == context) { 56 sis_malloc(&req);
70 retval = setDel(global_ppriv[i].sets[type], val); 57 if (req.size == 0)
71 break; 58 return NULL;
72 } 59 else
73 } 60 return (void *)~req.offset;
74 return retval;
75} 61}
76 62
77/* fb management via fb device */ 63static void sis_sman_mm_free(void *private, void *ref)
78#if defined(__linux__) && defined(CONFIG_FB_SIS)
79
80static int sis_fb_init(DRM_IOCTL_ARGS)
81{ 64{
82 return 0; 65 sis_free(~((unsigned long)ref));
83} 66}
84 67
85static int sis_fb_alloc(DRM_IOCTL_ARGS) 68static void sis_sman_mm_destroy(void *private)
86{ 69{
87 drm_sis_mem_t fb; 70 ;
88 struct sis_memreq req;
89 drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data;
90 int retval = 0;
91
92 DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb));
93
94 req.size = fb.size;
95 sis_malloc(&req);
96 if (req.offset) {
97 /* TODO */
98 fb.offset = req.offset;
99 fb.free = req.offset;
100 if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) {
101 DRM_DEBUG("adding to allocation set fails\n");
102 sis_free(req.offset);
103 retval = DRM_ERR(EINVAL);
104 }
105 } else {
106 fb.offset = 0;
107 fb.size = 0;
108 fb.free = 0;
109 }
110
111 DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb));
112
113 DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, req.offset);
114
115 return retval;
116} 71}
117 72
118static int sis_fb_free(DRM_IOCTL_ARGS) 73static unsigned long sis_sman_mm_offset(void *private, void *ref)
119{ 74{
120 drm_sis_mem_t fb; 75 return ~((unsigned long)ref);
121 int retval = 0; 76}
122
123 DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *) data, sizeof(fb));
124
125 if (!fb.free)
126 return DRM_ERR(EINVAL);
127 77
128 if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free)) 78#else /* CONFIG_FB_SIS */
129 retval = DRM_ERR(EINVAL);
130 sis_free(fb.free);
131 79
132 DRM_DEBUG("free fb, offset = 0x%lx\n", fb.free); 80#define SIS_MM_ALIGN_SHIFT 4
81#define SIS_MM_ALIGN_MASK ( (1 << SIS_MM_ALIGN_SHIFT) - 1)
133 82
134 return retval; 83#endif /* CONFIG_FB_SIS */
135}
136 84
137#else
138
139/* Called by the X Server to initialize the FB heap. Allocations will fail
140 * unless this is called. Offset is the beginning of the heap from the
141 * framebuffer offset (MaxXFBMem in XFree86).
142 *
143 * Memory layout according to Thomas Winischofer:
144 * |------------------|DDDDDDDDDDDDDDDDDDDDDDDDDDDDD|HHHH|CCCCCCCCCCC|
145 *
146 * X driver/sisfb HW- Command-
147 * framebuffer memory DRI heap Cursor queue
148 */
149static int sis_fb_init(DRM_IOCTL_ARGS) 85static int sis_fb_init(DRM_IOCTL_ARGS)
150{ 86{
151 DRM_DEVICE; 87 DRM_DEVICE;
152 drm_sis_private_t *dev_priv = dev->dev_private; 88 drm_sis_private_t *dev_priv = dev->dev_private;
153 drm_sis_fb_t fb; 89 drm_sis_fb_t fb;
90 int ret;
154 91
155 DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_fb_t __user *) data, sizeof(fb)); 92 DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_fb_t __user *) data, sizeof(fb));
156 93
157 if (dev_priv == NULL) { 94 mutex_lock(&dev->struct_mutex);
158 dev->dev_private = drm_calloc(1, sizeof(drm_sis_private_t), 95#if defined(CONFIG_FB_SIS)
159 DRM_MEM_DRIVER); 96 {
160 dev_priv = dev->dev_private; 97 drm_sman_mm_t sman_mm;
161 if (dev_priv == NULL) 98 sman_mm.private = (void *)0xFFFFFFFF;
162 return ENOMEM; 99 sman_mm.allocate = sis_sman_mm_allocate;
100 sman_mm.free = sis_sman_mm_free;
101 sman_mm.destroy = sis_sman_mm_destroy;
102 sman_mm.offset = sis_sman_mm_offset;
103 ret =
104 drm_sman_set_manager(&dev_priv->sman, VIDEO_TYPE, &sman_mm);
163 } 105 }
106#else
107 ret = drm_sman_set_range(&dev_priv->sman, VIDEO_TYPE, 0,
108 fb.size >> SIS_MM_ALIGN_SHIFT);
109#endif
164 110
165 if (dev_priv->FBHeap != NULL) 111 if (ret) {
166 return DRM_ERR(EINVAL); 112 DRM_ERROR("VRAM memory manager initialisation error\n");
113 mutex_unlock(&dev->struct_mutex);
114 return ret;
115 }
167 116
168 dev_priv->FBHeap = mmInit(fb.offset, fb.size); 117 dev_priv->vram_initialized = 1;
118 dev_priv->vram_offset = fb.offset;
169 119
120 mutex_unlock(&dev->struct_mutex);
170 DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size); 121 DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size);
171 122
172 return 0; 123 return 0;
173} 124}
174 125
175static int sis_fb_alloc(DRM_IOCTL_ARGS) 126static int sis_drm_alloc(drm_device_t * dev, drm_file_t * priv,
127 unsigned long data, int pool)
176{ 128{
177 DRM_DEVICE;
178 drm_sis_private_t *dev_priv = dev->dev_private; 129 drm_sis_private_t *dev_priv = dev->dev_private;
179 drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data; 130 drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *) data;
180 drm_sis_mem_t fb; 131 drm_sis_mem_t mem;
181 PMemBlock block;
182 int retval = 0; 132 int retval = 0;
133 drm_memblock_item_t *item;
134
135 DRM_COPY_FROM_USER_IOCTL(mem, argp, sizeof(mem));
183 136
184 if (dev_priv == NULL || dev_priv->FBHeap == NULL) 137 mutex_lock(&dev->struct_mutex);
138
139 if (0 == ((pool == 0) ? dev_priv->vram_initialized :
140 dev_priv->agp_initialized)) {
141 DRM_ERROR
142 ("Attempt to allocate from uninitialized memory manager.\n");
185 return DRM_ERR(EINVAL); 143 return DRM_ERR(EINVAL);
144 }
186 145
187 DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb)); 146 mem.size = (mem.size + SIS_MM_ALIGN_MASK) >> SIS_MM_ALIGN_SHIFT;
188 147 item = drm_sman_alloc(&dev_priv->sman, pool, mem.size, 0,
189 block = mmAllocMem(dev_priv->FBHeap, fb.size, 0, 0); 148 (unsigned long)priv);
190 if (block) { 149
191 /* TODO */ 150 mutex_unlock(&dev->struct_mutex);
192 fb.offset = block->ofs; 151 if (item) {
193 fb.free = (unsigned long)block; 152 mem.offset = ((pool == 0) ?
194 if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) { 153 dev_priv->vram_offset : dev_priv->agp_offset) +
195 DRM_DEBUG("adding to allocation set fails\n"); 154 (item->mm->
196 mmFreeMem((PMemBlock) fb.free); 155 offset(item->mm, item->mm_info) << SIS_MM_ALIGN_SHIFT);
197 retval = DRM_ERR(EINVAL); 156 mem.free = item->user_hash.key;
198 } 157 mem.size = mem.size << SIS_MM_ALIGN_SHIFT;
199 } else { 158 } else {
200 fb.offset = 0; 159 mem.offset = 0;
201 fb.size = 0; 160 mem.size = 0;
202 fb.free = 0; 161 mem.free = 0;
162 retval = DRM_ERR(ENOMEM);
203 } 163 }
204 164
205 DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb)); 165 DRM_COPY_TO_USER_IOCTL(argp, mem, sizeof(mem));
206 166
207 DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, fb.offset); 167 DRM_DEBUG("alloc %d, size = %d, offset = %d\n", pool, mem.size,
168 mem.offset);
208 169
209 return retval; 170 return retval;
210} 171}
211 172
212static int sis_fb_free(DRM_IOCTL_ARGS) 173static int sis_drm_free(DRM_IOCTL_ARGS)
213{ 174{
214 DRM_DEVICE; 175 DRM_DEVICE;
215 drm_sis_private_t *dev_priv = dev->dev_private; 176 drm_sis_private_t *dev_priv = dev->dev_private;
216 drm_sis_mem_t fb; 177 drm_sis_mem_t mem;
178 int ret;
217 179
218 if (dev_priv == NULL || dev_priv->FBHeap == NULL) 180 DRM_COPY_FROM_USER_IOCTL(mem, (drm_sis_mem_t __user *) data,
219 return DRM_ERR(EINVAL); 181 sizeof(mem));
220 182
221 DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *) data, sizeof(fb)); 183 mutex_lock(&dev->struct_mutex);
184 ret = drm_sman_free_key(&dev_priv->sman, mem.free);
185 mutex_unlock(&dev->struct_mutex);
186 DRM_DEBUG("free = 0x%lx\n", mem.free);
222 187
223 if (!mmBlockInHeap(dev_priv->FBHeap, (PMemBlock) fb.free)) 188 return ret;
224 return DRM_ERR(EINVAL);
225
226 if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
227 return DRM_ERR(EINVAL);
228 mmFreeMem((PMemBlock) fb.free);
229
230 DRM_DEBUG("free fb, free = 0x%lx\n", fb.free);
231
232 return 0;
233} 189}
234 190
235#endif 191static int sis_fb_alloc(DRM_IOCTL_ARGS)
236 192{
237/* agp memory management */ 193 DRM_DEVICE;
194 return sis_drm_alloc(dev, priv, data, VIDEO_TYPE);
195}
238 196
239static int sis_ioctl_agp_init(DRM_IOCTL_ARGS) 197static int sis_ioctl_agp_init(DRM_IOCTL_ARGS)
240{ 198{
241 DRM_DEVICE; 199 DRM_DEVICE;
242 drm_sis_private_t *dev_priv = dev->dev_private; 200 drm_sis_private_t *dev_priv = dev->dev_private;
243 drm_sis_agp_t agp; 201 drm_sis_agp_t agp;
244 202 int ret;
245 if (dev_priv == NULL) { 203 dev_priv = dev->dev_private;
246 dev->dev_private = drm_calloc(1, sizeof(drm_sis_private_t),
247 DRM_MEM_DRIVER);
248 dev_priv = dev->dev_private;
249 if (dev_priv == NULL)
250 return ENOMEM;
251 }
252
253 if (dev_priv->AGPHeap != NULL)
254 return DRM_ERR(EINVAL);
255 204
256 DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_agp_t __user *) data, 205 DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_agp_t __user *) data,
257 sizeof(agp)); 206 sizeof(agp));
207 mutex_lock(&dev->struct_mutex);
208 ret = drm_sman_set_range(&dev_priv->sman, AGP_TYPE, 0,
209 agp.size >> SIS_MM_ALIGN_SHIFT);
210
211 if (ret) {
212 DRM_ERROR("AGP memory manager initialisation error\n");
213 mutex_unlock(&dev->struct_mutex);
214 return ret;
215 }
258 216
259 dev_priv->AGPHeap = mmInit(agp.offset, agp.size); 217 dev_priv->agp_initialized = 1;
218 dev_priv->agp_offset = agp.offset;
219 mutex_unlock(&dev->struct_mutex);
260 220
261 DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size); 221 DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size);
262
263 return 0; 222 return 0;
264} 223}
265 224
266static int sis_ioctl_agp_alloc(DRM_IOCTL_ARGS) 225static int sis_ioctl_agp_alloc(DRM_IOCTL_ARGS)
267{ 226{
268 DRM_DEVICE; 227 DRM_DEVICE;
269 drm_sis_private_t *dev_priv = dev->dev_private;
270 drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data;
271 drm_sis_mem_t agp;
272 PMemBlock block;
273 int retval = 0;
274 228
275 if (dev_priv == NULL || dev_priv->AGPHeap == NULL) 229 return sis_drm_alloc(dev, priv, data, AGP_TYPE);
276 return DRM_ERR(EINVAL); 230}
277 231
278 DRM_COPY_FROM_USER_IOCTL(agp, argp, sizeof(agp)); 232static drm_local_map_t *sis_reg_init(drm_device_t *dev)
279 233{
280 block = mmAllocMem(dev_priv->AGPHeap, agp.size, 0, 0); 234 drm_map_list_t *entry;
281 if (block) { 235 drm_local_map_t *map;
282 /* TODO */ 236
283 agp.offset = block->ofs; 237 list_for_each_entry(entry, &dev->maplist->head, head) {
284 agp.free = (unsigned long)block; 238 map = entry->map;
285 if (!add_alloc_set(agp.context, AGP_TYPE, agp.free)) { 239 if (!map)
286 DRM_DEBUG("adding to allocation set fails\n"); 240 continue;
287 mmFreeMem((PMemBlock) agp.free); 241 if (map->type == _DRM_REGISTERS) {
288 retval = -1; 242 return map;
289 } 243 }
290 } else {
291 agp.offset = 0;
292 agp.size = 0;
293 agp.free = 0;
294 } 244 }
295 245 return NULL;
296 DRM_COPY_TO_USER_IOCTL(argp, agp, sizeof(agp));
297
298 DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size, agp.offset);
299
300 return retval;
301} 246}
302 247
303static int sis_ioctl_agp_free(DRM_IOCTL_ARGS) 248int sis_idle(drm_device_t *dev)
304{ 249{
305 DRM_DEVICE;
306 drm_sis_private_t *dev_priv = dev->dev_private; 250 drm_sis_private_t *dev_priv = dev->dev_private;
307 drm_sis_mem_t agp; 251 uint32_t idle_reg;
308 252 unsigned long end;
309 if (dev_priv == NULL || dev_priv->AGPHeap == NULL) 253 int i;
310 return DRM_ERR(EINVAL);
311 254
312 DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t __user *) data, 255 if (dev_priv->idle_fault)
313 sizeof(agp)); 256 return 0;
314 257
315 if (!mmBlockInHeap(dev_priv->AGPHeap, (PMemBlock) agp.free)) 258 if (dev_priv->mmio == NULL) {
316 return DRM_ERR(EINVAL); 259 dev_priv->mmio = sis_reg_init(dev);
260 if (dev_priv->mmio == NULL) {
261 DRM_ERROR("Could not find register map.\n");
262 return 0;
263 }
264 }
265
266 /*
267 * Implement a device switch here if needed
268 */
269
270 if (dev_priv->chipset != SIS_CHIP_315)
271 return 0;
272
273 /*
274 * Timeout after 3 seconds. We cannot use DRM_WAIT_ON here
275 * because its polling frequency is too low.
276 */
277
278 end = jiffies + (DRM_HZ * 3);
279
280 for (i=0; i<4; ++i) {
281 do {
282 idle_reg = SIS_READ(0x85cc);
283 } while ( !time_after_eq(jiffies, end) &&
284 ((idle_reg & 0x80000000) != 0x80000000));
285 }
317 286
318 mmFreeMem((PMemBlock) agp.free); 287 if (time_after_eq(jiffies, end)) {
319 if (!del_alloc_set(agp.context, AGP_TYPE, agp.free)) 288 DRM_ERROR("Graphics engine idle timeout. "
320 return DRM_ERR(EINVAL); 289 "Disabling idle check\n");
290 dev_priv->idle_fault = 1;
291 }
321 292
322 DRM_DEBUG("free agp, free = 0x%lx\n", agp.free); 293 /*
294 * The caller never sees an error code. It gets trapped
295 * in libdrm.
296 */
323 297
324 return 0; 298 return 0;
325} 299}
326 300
327int sis_init_context(struct drm_device *dev, int context)
328{
329 int i;
330 301
331 for (i = 0; i < MAX_CONTEXT; i++) { 302void sis_lastclose(struct drm_device *dev)
332 if (global_ppriv[i].used && 303{
333 (global_ppriv[i].context == context)) 304 drm_sis_private_t *dev_priv = dev->dev_private;
334 break;
335 }
336 305
337 if (i >= MAX_CONTEXT) { 306 if (!dev_priv)
338 for (i = 0; i < MAX_CONTEXT; i++) { 307 return;
339 if (!global_ppriv[i].used) {
340 global_ppriv[i].context = context;
341 global_ppriv[i].used = 1;
342 global_ppriv[i].sets[0] = setInit();
343 global_ppriv[i].sets[1] = setInit();
344 DRM_DEBUG("init allocation set, socket=%d, "
345 "context = %d\n", i, context);
346 break;
347 }
348 }
349 if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) ||
350 (global_ppriv[i].sets[1] == NULL)) {
351 return 0;
352 }
353 }
354 308
355 return 1; 309 mutex_lock(&dev->struct_mutex);
310 drm_sman_cleanup(&dev_priv->sman);
311 dev_priv->vram_initialized = 0;
312 dev_priv->agp_initialized = 0;
313 dev_priv->mmio = NULL;
314 mutex_unlock(&dev->struct_mutex);
356} 315}
357 316
358int sis_final_context(struct drm_device *dev, int context) 317void sis_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
359{ 318{
360 int i; 319 drm_sis_private_t *dev_priv = dev->dev_private;
320 drm_file_t *priv = filp->private_data;
361 321
362 for (i = 0; i < MAX_CONTEXT; i++) { 322 mutex_lock(&dev->struct_mutex);
363 if (global_ppriv[i].used && 323 if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)priv)) {
364 (global_ppriv[i].context == context)) 324 mutex_unlock(&dev->struct_mutex);
365 break; 325 return;
366 } 326 }
367 327
368 if (i < MAX_CONTEXT) { 328 if (dev->driver->dma_quiescent) {
369 set_t *set; 329 dev->driver->dma_quiescent(dev);
370 ITEM_TYPE item;
371 int retval;
372
373 DRM_DEBUG("find socket %d, context = %d\n", i, context);
374
375 /* Video Memory */
376 set = global_ppriv[i].sets[0];
377 retval = setFirst(set, &item);
378 while (retval) {
379 DRM_DEBUG("free video memory 0x%lx\n", item);
380#if defined(__linux__) && defined(CONFIG_FB_SIS)
381 sis_free(item);
382#else
383 mmFreeMem((PMemBlock) item);
384#endif
385 retval = setNext(set, &item);
386 }
387 setDestroy(set);
388
389 /* AGP Memory */
390 set = global_ppriv[i].sets[1];
391 retval = setFirst(set, &item);
392 while (retval) {
393 DRM_DEBUG("free agp memory 0x%lx\n", item);
394 mmFreeMem((PMemBlock) item);
395 retval = setNext(set, &item);
396 }
397 setDestroy(set);
398
399 global_ppriv[i].used = 0;
400 } 330 }
401 331
402 return 1; 332 drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)priv);
333 mutex_unlock(&dev->struct_mutex);
334 return;
403} 335}
404 336
405drm_ioctl_desc_t sis_ioctls[] = { 337drm_ioctl_desc_t sis_ioctls[] = {
406 [DRM_IOCTL_NR(DRM_SIS_FB_ALLOC)] = {sis_fb_alloc, DRM_AUTH}, 338 [DRM_IOCTL_NR(DRM_SIS_FB_ALLOC)] = {sis_fb_alloc, DRM_AUTH},
407 [DRM_IOCTL_NR(DRM_SIS_FB_FREE)] = {sis_fb_free, DRM_AUTH}, 339 [DRM_IOCTL_NR(DRM_SIS_FB_FREE)] = {sis_drm_free, DRM_AUTH},
408 [DRM_IOCTL_NR(DRM_SIS_AGP_INIT)] = {sis_ioctl_agp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, 340 [DRM_IOCTL_NR(DRM_SIS_AGP_INIT)] =
341 {sis_ioctl_agp_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY},
409 [DRM_IOCTL_NR(DRM_SIS_AGP_ALLOC)] = {sis_ioctl_agp_alloc, DRM_AUTH}, 342 [DRM_IOCTL_NR(DRM_SIS_AGP_ALLOC)] = {sis_ioctl_agp_alloc, DRM_AUTH},
410 [DRM_IOCTL_NR(DRM_SIS_AGP_FREE)] = {sis_ioctl_agp_free, DRM_AUTH}, 343 [DRM_IOCTL_NR(DRM_SIS_AGP_FREE)] = {sis_drm_free, DRM_AUTH},
411 [DRM_IOCTL_NR(DRM_SIS_FB_INIT)] = {sis_fb_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY} 344 [DRM_IOCTL_NR(DRM_SIS_FB_INIT)] =
345 {sis_fb_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY}
412}; 346};
413 347
414int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls); 348int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls);
diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c
index 78a81a4a99c5..60c1695db300 100644
--- a/drivers/char/drm/via_dmablit.c
+++ b/drivers/char/drm/via_dmablit.c
@@ -41,9 +41,9 @@
41 41
42#include <linux/pagemap.h> 42#include <linux/pagemap.h>
43 43
44#define VIA_PGDN(x) (((unsigned long)(x)) & PAGE_MASK) 44#define VIA_PGDN(x) (((unsigned long)(x)) & PAGE_MASK)
45#define VIA_PGOFF(x) (((unsigned long)(x)) & ~PAGE_MASK) 45#define VIA_PGOFF(x) (((unsigned long)(x)) & ~PAGE_MASK)
46#define VIA_PFN(x) ((unsigned long)(x) >> PAGE_SHIFT) 46#define VIA_PFN(x) ((unsigned long)(x) >> PAGE_SHIFT)
47 47
48typedef struct _drm_via_descriptor { 48typedef struct _drm_via_descriptor {
49 uint32_t mem_addr; 49 uint32_t mem_addr;
@@ -121,19 +121,19 @@ via_map_blit_for_device(struct pci_dev *pdev,
121 121
122 while (line_len > 0) { 122 while (line_len > 0) {
123 123
124 remaining_len = min(PAGE_SIZE-VIA_PGOFF(cur_mem), line_len); 124 remaining_len = min(PAGE_SIZE-VIA_PGOFF(cur_mem), line_len);
125 line_len -= remaining_len; 125 line_len -= remaining_len;
126 126
127 if (mode == 1) { 127 if (mode == 1) {
128 desc_ptr->mem_addr = 128 desc_ptr->mem_addr =
129 dma_map_page(&pdev->dev, 129 dma_map_page(&pdev->dev,
130 vsg->pages[VIA_PFN(cur_mem) - 130 vsg->pages[VIA_PFN(cur_mem) -
131 VIA_PFN(first_addr)], 131 VIA_PFN(first_addr)],
132 VIA_PGOFF(cur_mem), remaining_len, 132 VIA_PGOFF(cur_mem), remaining_len,
133 vsg->direction); 133 vsg->direction);
134 desc_ptr->dev_addr = cur_fb; 134 desc_ptr->dev_addr = cur_fb;
135 135
136 desc_ptr->size = remaining_len; 136 desc_ptr->size = remaining_len;
137 desc_ptr->next = (uint32_t) next; 137 desc_ptr->next = (uint32_t) next;
138 next = dma_map_single(&pdev->dev, desc_ptr, sizeof(*desc_ptr), 138 next = dma_map_single(&pdev->dev, desc_ptr, sizeof(*desc_ptr),
139 DMA_TO_DEVICE); 139 DMA_TO_DEVICE);
@@ -162,7 +162,7 @@ via_map_blit_for_device(struct pci_dev *pdev,
162 162
163/* 163/*
164 * Function that frees up all resources for a blit. It is usable even if the 164 * Function that frees up all resources for a blit. It is usable even if the
165 * blit info has only be partially built as long as the status enum is consistent 165 * blit info has only been partially built as long as the status enum is consistent
166 * with the actual status of the used resources. 166 * with the actual status of the used resources.
167 */ 167 */
168 168
@@ -238,8 +238,11 @@ via_lock_all_dma_pages(drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)
238 return DRM_ERR(ENOMEM); 238 return DRM_ERR(ENOMEM);
239 memset(vsg->pages, 0, sizeof(struct page *) * vsg->num_pages); 239 memset(vsg->pages, 0, sizeof(struct page *) * vsg->num_pages);
240 down_read(&current->mm->mmap_sem); 240 down_read(&current->mm->mmap_sem);
241 ret = get_user_pages(current, current->mm, (unsigned long) xfer->mem_addr, 241 ret = get_user_pages(current, current->mm,
242 vsg->num_pages, vsg->direction, 0, vsg->pages, NULL); 242 (unsigned long)xfer->mem_addr,
243 vsg->num_pages,
244 (vsg->direction == DMA_FROM_DEVICE),
245 0, vsg->pages, NULL);
243 246
244 up_read(&current->mm->mmap_sem); 247 up_read(&current->mm->mmap_sem);
245 if (ret != vsg->num_pages) { 248 if (ret != vsg->num_pages) {
@@ -475,9 +478,15 @@ via_dmablit_timer(unsigned long data)
475 if (!timer_pending(&blitq->poll_timer)) { 478 if (!timer_pending(&blitq->poll_timer)) {
476 blitq->poll_timer.expires = jiffies+1; 479 blitq->poll_timer.expires = jiffies+1;
477 add_timer(&blitq->poll_timer); 480 add_timer(&blitq->poll_timer);
478 }
479 via_dmablit_handler(dev, engine, 0);
480 481
482 /*
483 * Rerun handler to delete timer if engines are off, and
484 * to shorten abort latency. This is a little nasty.
485 */
486
487 via_dmablit_handler(dev, engine, 0);
488
489 }
481} 490}
482 491
483 492
@@ -597,15 +606,27 @@ via_build_sg_info(drm_device_t *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *
597 * (Not a big limitation anyway.) 606 * (Not a big limitation anyway.)
598 */ 607 */
599 608
600 if (((xfer->mem_stride - xfer->line_length) >= PAGE_SIZE) || 609 if ((xfer->mem_stride - xfer->line_length) >= PAGE_SIZE) {
601 (xfer->mem_stride > 2048*4)) {
602 DRM_ERROR("Too large system memory stride. Stride: %d, " 610 DRM_ERROR("Too large system memory stride. Stride: %d, "
603 "Length: %d\n", xfer->mem_stride, xfer->line_length); 611 "Length: %d\n", xfer->mem_stride, xfer->line_length);
604 return DRM_ERR(EINVAL); 612 return DRM_ERR(EINVAL);
605 } 613 }
606 614
607 if (xfer->num_lines > 2048) { 615 if ((xfer->mem_stride == xfer->line_length) &&
608 DRM_ERROR("Too many PCI DMA bitblt lines.\n"); 616 (xfer->fb_stride == xfer->line_length)) {
617 xfer->mem_stride *= xfer->num_lines;
618 xfer->line_length = xfer->mem_stride;
619 xfer->fb_stride = xfer->mem_stride;
620 xfer->num_lines = 1;
621 }
622
623 /*
624 * Don't lock an arbitrary large number of pages, since that causes a
625 * DOS security hole.
626 */
627
628 if (xfer->num_lines > 2048 || (xfer->num_lines*xfer->mem_stride > (2048*2048*4))) {
629 DRM_ERROR("Too large PCI DMA bitblt.\n");
609 return DRM_ERR(EINVAL); 630 return DRM_ERR(EINVAL);
610 } 631 }
611 632
@@ -628,16 +649,17 @@ via_build_sg_info(drm_device_t *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *
628 649
629#ifdef VIA_BUGFREE 650#ifdef VIA_BUGFREE
630 if ((((unsigned long)xfer->mem_addr & 3) != ((unsigned long)xfer->fb_addr & 3)) || 651 if ((((unsigned long)xfer->mem_addr & 3) != ((unsigned long)xfer->fb_addr & 3)) ||
631 ((xfer->mem_stride & 3) != (xfer->fb_stride & 3))) { 652 ((xfer->num_lines > 1) && ((xfer->mem_stride & 3) != (xfer->fb_stride & 3)))) {
632 DRM_ERROR("Invalid DRM bitblt alignment.\n"); 653 DRM_ERROR("Invalid DRM bitblt alignment.\n");
633 return DRM_ERR(EINVAL); 654 return DRM_ERR(EINVAL);
634 } 655 }
635#else 656#else
636 if ((((unsigned long)xfer->mem_addr & 15) || 657 if ((((unsigned long)xfer->mem_addr & 15) ||
637 ((unsigned long)xfer->fb_addr & 3)) || (xfer->mem_stride & 15) || 658 ((unsigned long)xfer->fb_addr & 3)) ||
638 (xfer->fb_stride & 3)) { 659 ((xfer->num_lines > 1) &&
660 ((xfer->mem_stride & 15) || (xfer->fb_stride & 3)))) {
639 DRM_ERROR("Invalid DRM bitblt alignment.\n"); 661 DRM_ERROR("Invalid DRM bitblt alignment.\n");
640 return DRM_ERR(EINVAL); 662 return DRM_ERR(EINVAL);
641 } 663 }
642#endif 664#endif
643 665
@@ -715,7 +737,7 @@ via_dmablit(drm_device_t *dev, drm_via_dmablit_t *xfer)
715 drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; 737 drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
716 drm_via_sg_info_t *vsg; 738 drm_via_sg_info_t *vsg;
717 drm_via_blitq_t *blitq; 739 drm_via_blitq_t *blitq;
718 int ret; 740 int ret;
719 int engine; 741 int engine;
720 unsigned long irqsave; 742 unsigned long irqsave;
721 743
@@ -756,7 +778,7 @@ via_dmablit(drm_device_t *dev, drm_via_dmablit_t *xfer)
756 778
757/* 779/*
758 * Sync on a previously submitted blit. Note that the X server use signals extensively, and 780 * Sync on a previously submitted blit. Note that the X server use signals extensively, and
759 * that there is a very big proability that this IOCTL will be interrupted by a signal. In that 781 * that there is a very big probability that this IOCTL will be interrupted by a signal. In that
760 * case it returns with -EAGAIN for the signal to be delivered. 782 * case it returns with -EAGAIN for the signal to be delivered.
761 * The caller should then reissue the IOCTL. This is similar to what is being done for drmGetLock(). 783 * The caller should then reissue the IOCTL. This is similar to what is being done for drmGetLock().
762 */ 784 */
diff --git a/drivers/char/drm/via_drm.h b/drivers/char/drm/via_drm.h
index 47f0b5b26379..e4ee97d7156f 100644
--- a/drivers/char/drm/via_drm.h
+++ b/drivers/char/drm/via_drm.h
@@ -250,6 +250,12 @@ typedef struct drm_via_blitsync {
250 unsigned engine; 250 unsigned engine;
251} drm_via_blitsync_t; 251} drm_via_blitsync_t;
252 252
253/* - * Below,"flags" is currently unused but will be used for possible future
254 * extensions like kernel space bounce buffers for bad alignments and
255 * blit engine busy-wait polling for better latency in the absence of
256 * interrupts.
257 */
258
253typedef struct drm_via_dmablit { 259typedef struct drm_via_dmablit {
254 uint32_t num_lines; 260 uint32_t num_lines;
255 uint32_t line_length; 261 uint32_t line_length;
@@ -260,7 +266,7 @@ typedef struct drm_via_dmablit {
260 unsigned char *mem_addr; 266 unsigned char *mem_addr;
261 uint32_t mem_stride; 267 uint32_t mem_stride;
262 268
263 int bounce_buffer; 269 uint32_t flags;
264 int to_fb; 270 int to_fb;
265 271
266 drm_via_blitsync_t sync; 272 drm_via_blitsync_t sync;
diff --git a/drivers/char/drm/via_drv.c b/drivers/char/drm/via_drv.c
index b3d364d793d7..bb9dde8b1911 100644
--- a/drivers/char/drm/via_drv.c
+++ b/drivers/char/drm/via_drv.c
@@ -43,7 +43,6 @@ static struct drm_driver driver = {
43 DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL, 43 DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
44 .load = via_driver_load, 44 .load = via_driver_load,
45 .unload = via_driver_unload, 45 .unload = via_driver_unload,
46 .context_ctor = via_init_context,
47 .context_dtor = via_final_context, 46 .context_dtor = via_final_context,
48 .vblank_wait = via_driver_vblank_wait, 47 .vblank_wait = via_driver_vblank_wait,
49 .irq_preinstall = via_driver_irq_preinstall, 48 .irq_preinstall = via_driver_irq_preinstall,
@@ -53,6 +52,8 @@ static struct drm_driver driver = {
53 .dma_quiescent = via_driver_dma_quiescent, 52 .dma_quiescent = via_driver_dma_quiescent,
54 .dri_library_name = dri_library_name, 53 .dri_library_name = dri_library_name,
55 .reclaim_buffers = drm_core_reclaim_buffers, 54 .reclaim_buffers = drm_core_reclaim_buffers,
55 .reclaim_buffers_locked = via_reclaim_buffers_locked,
56 .lastclose = via_lastclose,
56 .get_map_ofs = drm_core_get_map_ofs, 57 .get_map_ofs = drm_core_get_map_ofs,
57 .get_reg_ofs = drm_core_get_reg_ofs, 58 .get_reg_ofs = drm_core_get_reg_ofs,
58 .ioctls = via_ioctls, 59 .ioctls = via_ioctls,
diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h
index 52bcc7b1ba45..d21b5b75da0f 100644
--- a/drivers/char/drm/via_drv.h
+++ b/drivers/char/drm/via_drv.h
@@ -24,15 +24,16 @@
24#ifndef _VIA_DRV_H_ 24#ifndef _VIA_DRV_H_
25#define _VIA_DRV_H_ 25#define _VIA_DRV_H_
26 26
27#include "drm_sman.h"
27#define DRIVER_AUTHOR "Various" 28#define DRIVER_AUTHOR "Various"
28 29
29#define DRIVER_NAME "via" 30#define DRIVER_NAME "via"
30#define DRIVER_DESC "VIA Unichrome / Pro" 31#define DRIVER_DESC "VIA Unichrome / Pro"
31#define DRIVER_DATE "20051116" 32#define DRIVER_DATE "20060529"
32 33
33#define DRIVER_MAJOR 2 34#define DRIVER_MAJOR 2
34#define DRIVER_MINOR 7 35#define DRIVER_MINOR 10
35#define DRIVER_PATCHLEVEL 4 36#define DRIVER_PATCHLEVEL 0
36 37
37#include "via_verifier.h" 38#include "via_verifier.h"
38 39
@@ -85,6 +86,12 @@ typedef struct drm_via_private {
85 uint32_t irq_enable_mask; 86 uint32_t irq_enable_mask;
86 uint32_t irq_pending_mask; 87 uint32_t irq_pending_mask;
87 int *irq_map; 88 int *irq_map;
89 unsigned int idle_fault;
90 drm_sman_t sman;
91 int vram_initialized;
92 int agp_initialized;
93 unsigned long vram_offset;
94 unsigned long agp_offset;
88 drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES]; 95 drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];
89} drm_via_private_t; 96} drm_via_private_t;
90 97
@@ -135,6 +142,9 @@ extern void via_init_futex(drm_via_private_t * dev_priv);
135extern void via_cleanup_futex(drm_via_private_t * dev_priv); 142extern void via_cleanup_futex(drm_via_private_t * dev_priv);
136extern void via_release_futex(drm_via_private_t * dev_priv, int context); 143extern void via_release_futex(drm_via_private_t * dev_priv, int context);
137 144
145extern void via_reclaim_buffers_locked(drm_device_t *dev, struct file *filp);
146extern void via_lastclose(drm_device_t *dev);
147
138extern void via_dmablit_handler(drm_device_t *dev, int engine, int from_irq); 148extern void via_dmablit_handler(drm_device_t *dev, int engine, int from_irq);
139extern void via_init_dmablit(drm_device_t *dev); 149extern void via_init_dmablit(drm_device_t *dev);
140 150
diff --git a/drivers/char/drm/via_ds.c b/drivers/char/drm/via_ds.c
deleted file mode 100644
index 9429736b3b96..000000000000
--- a/drivers/char/drm/via_ds.c
+++ /dev/null
@@ -1,273 +0,0 @@
1/*
2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4 * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sub license,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
20 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25#include "drmP.h"
26
27#include "via_ds.h"
28extern unsigned int VIA_DEBUG;
29
30set_t *via_setInit(void)
31{
32 int i;
33 set_t *set;
34 set = (set_t *) drm_alloc(sizeof(set_t), DRM_MEM_DRIVER);
35 for (i = 0; i < SET_SIZE; i++) {
36 set->list[i].free_next = i + 1;
37 set->list[i].alloc_next = -1;
38 }
39 set->list[SET_SIZE - 1].free_next = -1;
40 set->free = 0;
41 set->alloc = -1;
42 set->trace = -1;
43 return set;
44}
45
46int via_setAdd(set_t * set, ITEM_TYPE item)
47{
48 int free = set->free;
49 if (free != -1) {
50 set->list[free].val = item;
51 set->free = set->list[free].free_next;
52 } else {
53 return 0;
54 }
55 set->list[free].alloc_next = set->alloc;
56 set->alloc = free;
57 set->list[free].free_next = -1;
58 return 1;
59}
60
61int via_setDel(set_t * set, ITEM_TYPE item)
62{
63 int alloc = set->alloc;
64 int prev = -1;
65
66 while (alloc != -1) {
67 if (set->list[alloc].val == item) {
68 if (prev != -1)
69 set->list[prev].alloc_next =
70 set->list[alloc].alloc_next;
71 else
72 set->alloc = set->list[alloc].alloc_next;
73 break;
74 }
75 prev = alloc;
76 alloc = set->list[alloc].alloc_next;
77 }
78
79 if (alloc == -1)
80 return 0;
81
82 set->list[alloc].free_next = set->free;
83 set->free = alloc;
84 set->list[alloc].alloc_next = -1;
85
86 return 1;
87}
88
89/* setFirst -> setAdd -> setNext is wrong */
90
91int via_setFirst(set_t * set, ITEM_TYPE * item)
92{
93 if (set->alloc == -1)
94 return 0;
95
96 *item = set->list[set->alloc].val;
97 set->trace = set->list[set->alloc].alloc_next;
98
99 return 1;
100}
101
102int via_setNext(set_t * set, ITEM_TYPE * item)
103{
104 if (set->trace == -1)
105 return 0;
106
107 *item = set->list[set->trace].val;
108 set->trace = set->list[set->trace].alloc_next;
109
110 return 1;
111}
112
113int via_setDestroy(set_t * set)
114{
115 drm_free(set, sizeof(set_t), DRM_MEM_DRIVER);
116
117 return 1;
118}
119
120#define ISFREE(bptr) ((bptr)->free)
121
122#define fprintf(fmt, arg...) do{}while(0)
123
124memHeap_t *via_mmInit(int ofs, int size)
125{
126 PMemBlock blocks;
127
128 if (size <= 0)
129 return NULL;
130
131 blocks = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock), DRM_MEM_DRIVER);
132
133 if (blocks) {
134 blocks->ofs = ofs;
135 blocks->size = size;
136 blocks->free = 1;
137 return (memHeap_t *) blocks;
138 } else
139 return NULL;
140}
141
142static TMemBlock *SliceBlock(TMemBlock * p,
143 int startofs, int size,
144 int reserved, int alignment)
145{
146 TMemBlock *newblock;
147
148 /* break left */
149 if (startofs > p->ofs) {
150 newblock =
151 (TMemBlock *) drm_calloc(1, sizeof(TMemBlock),
152 DRM_MEM_DRIVER);
153 newblock->ofs = startofs;
154 newblock->size = p->size - (startofs - p->ofs);
155 newblock->free = 1;
156 newblock->next = p->next;
157 p->size -= newblock->size;
158 p->next = newblock;
159 p = newblock;
160 }
161
162 /* break right */
163 if (size < p->size) {
164 newblock =
165 (TMemBlock *) drm_calloc(1, sizeof(TMemBlock),
166 DRM_MEM_DRIVER);
167 newblock->ofs = startofs + size;
168 newblock->size = p->size - size;
169 newblock->free = 1;
170 newblock->next = p->next;
171 p->size = size;
172 p->next = newblock;
173 }
174
175 /* p = middle block */
176 p->align = alignment;
177 p->free = 0;
178 p->reserved = reserved;
179 return p;
180}
181
182PMemBlock via_mmAllocMem(memHeap_t * heap, int size, int align2,
183 int startSearch)
184{
185 int mask, startofs, endofs;
186 TMemBlock *p;
187
188 if (!heap || align2 < 0 || size <= 0)
189 return NULL;
190
191 mask = (1 << align2) - 1;
192 startofs = 0;
193 p = (TMemBlock *) heap;
194
195 while (p) {
196 if (ISFREE(p)) {
197 startofs = (p->ofs + mask) & ~mask;
198
199 if (startofs < startSearch)
200 startofs = startSearch;
201
202 endofs = startofs + size;
203
204 if (endofs <= (p->ofs + p->size))
205 break;
206 }
207
208 p = p->next;
209 }
210
211 if (!p)
212 return NULL;
213
214 p = SliceBlock(p, startofs, size, 0, mask + 1);
215 p->heap = heap;
216
217 return p;
218}
219
220static __inline__ int Join2Blocks(TMemBlock * p)
221{
222 if (p->free && p->next && p->next->free) {
223 TMemBlock *q = p->next;
224 p->size += q->size;
225 p->next = q->next;
226 drm_free(q, sizeof(TMemBlock), DRM_MEM_DRIVER);
227
228 return 1;
229 }
230
231 return 0;
232}
233
234int via_mmFreeMem(PMemBlock b)
235{
236 TMemBlock *p, *prev;
237
238 if (!b)
239 return 0;
240
241 if (!b->heap) {
242 fprintf(stderr, "no heap\n");
243
244 return -1;
245 }
246
247 p = b->heap;
248 prev = NULL;
249
250 while (p && p != b) {
251 prev = p;
252 p = p->next;
253 }
254
255 if (!p || p->free || p->reserved) {
256 if (!p)
257 fprintf(stderr, "block not found in heap\n");
258 else if (p->free)
259 fprintf(stderr, "block already free\n");
260 else
261 fprintf(stderr, "block is reserved\n");
262
263 return -1;
264 }
265
266 p->free = 1;
267 Join2Blocks(p);
268
269 if (prev)
270 Join2Blocks(prev);
271
272 return 0;
273}
diff --git a/drivers/char/drm/via_ds.h b/drivers/char/drm/via_ds.h
deleted file mode 100644
index d2bb9f37ca38..000000000000
--- a/drivers/char/drm/via_ds.h
+++ /dev/null
@@ -1,104 +0,0 @@
1/*
2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4 * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
5 * All rights reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sub license,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 */
26#ifndef _via_ds_h_
27#define _via_ds_h_
28
29#include "drmP.h"
30
31/* Set Data Structure */
32#define SET_SIZE 5000
33typedef unsigned long ITEM_TYPE;
34
35typedef struct {
36 ITEM_TYPE val;
37 int alloc_next, free_next;
38} list_item_t;
39
40typedef struct {
41 int alloc;
42 int free;
43 int trace;
44 list_item_t list[SET_SIZE];
45} set_t;
46
47set_t *via_setInit(void);
48int via_setAdd(set_t * set, ITEM_TYPE item);
49int via_setDel(set_t * set, ITEM_TYPE item);
50int via_setFirst(set_t * set, ITEM_TYPE * item);
51int via_setNext(set_t * set, ITEM_TYPE * item);
52int via_setDestroy(set_t * set);
53
54#endif
55
56#ifndef MM_INC
57#define MM_INC
58
59struct mem_block_t {
60 struct mem_block_t *next;
61 struct mem_block_t *heap;
62 int ofs, size;
63 int align;
64 unsigned int free:1;
65 unsigned int reserved:1;
66};
67typedef struct mem_block_t TMemBlock;
68typedef struct mem_block_t *PMemBlock;
69
70/* a heap is just the first block in a chain */
71typedef struct mem_block_t memHeap_t;
72
73static __inline__ int mmBlockSize(PMemBlock b)
74{
75 return b->size;
76}
77
78static __inline__ int mmOffset(PMemBlock b)
79{
80 return b->ofs;
81}
82
83static __inline__ void mmMarkReserved(PMemBlock b)
84{
85 b->reserved = 1;
86}
87
88/*
89 * input: total size in bytes
90 * return: a heap pointer if OK, NULL if error
91 */
92memHeap_t *via_mmInit(int ofs, int size);
93
94PMemBlock via_mmAllocMem(memHeap_t * heap, int size, int align2,
95 int startSearch);
96
97/*
98 * Free block starts at offset
99 * input: pointer to a block
100 * return: 0 if OK, -1 if error
101 */
102int via_mmFreeMem(PMemBlock b);
103
104#endif
diff --git a/drivers/char/drm/via_map.c b/drivers/char/drm/via_map.c
index c6a08e96285b..782011e0a58d 100644
--- a/drivers/char/drm/via_map.c
+++ b/drivers/char/drm/via_map.c
@@ -98,6 +98,7 @@ int via_map_init(DRM_IOCTL_ARGS)
98int via_driver_load(drm_device_t *dev, unsigned long chipset) 98int via_driver_load(drm_device_t *dev, unsigned long chipset)
99{ 99{
100 drm_via_private_t *dev_priv; 100 drm_via_private_t *dev_priv;
101 int ret = 0;
101 102
102 dev_priv = drm_calloc(1, sizeof(drm_via_private_t), DRM_MEM_DRIVER); 103 dev_priv = drm_calloc(1, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
103 if (dev_priv == NULL) 104 if (dev_priv == NULL)
@@ -108,13 +109,19 @@ int via_driver_load(drm_device_t *dev, unsigned long chipset)
108 if (chipset == VIA_PRO_GROUP_A) 109 if (chipset == VIA_PRO_GROUP_A)
109 dev_priv->pro_group_a = 1; 110 dev_priv->pro_group_a = 1;
110 111
111 return 0; 112 ret = drm_sman_init(&dev_priv->sman, 2, 12, 8);
113 if (ret) {
114 drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
115 }
116 return ret;
112} 117}
113 118
114int via_driver_unload(drm_device_t *dev) 119int via_driver_unload(drm_device_t *dev)
115{ 120{
116 drm_via_private_t *dev_priv = dev->dev_private; 121 drm_via_private_t *dev_priv = dev->dev_private;
117 122
123 drm_sman_takedown(&dev_priv->sman);
124
118 drm_free(dev_priv, sizeof(drm_via_private_t), DRM_MEM_DRIVER); 125 drm_free(dev_priv, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
119 126
120 return 0; 127 return 0;
diff --git a/drivers/char/drm/via_mm.c b/drivers/char/drm/via_mm.c
index 33e0cb12e4c3..2fcf0577a7aa 100644
--- a/drivers/char/drm/via_mm.c
+++ b/drivers/char/drm/via_mm.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. 2 * Copyright 2006 Tungsten Graphics Inc., Bismarck, ND., USA.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. 3 * All rights reserved.
4 * 4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a 5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"), 6 * copy of this software and associated documentation files (the "Software"),
@@ -16,347 +16,194 @@
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 * THE AUTHORS OR COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE. 22 * DEALINGS IN THE SOFTWARE.
23 */ 23 */
24/*
25 * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
26 */
27
24#include "drmP.h" 28#include "drmP.h"
25#include "via_drm.h" 29#include "via_drm.h"
26#include "via_drv.h" 30#include "via_drv.h"
27#include "via_ds.h" 31#include "drm_sman.h"
28#include "via_mm.h"
29
30#define MAX_CONTEXT 100
31
32typedef struct {
33 int used;
34 int context;
35 set_t *sets[2]; /* 0 for frame buffer, 1 for AGP , 2 for System */
36} via_context_t;
37
38static via_context_t global_ppriv[MAX_CONTEXT];
39 32
40static int via_agp_alloc(drm_via_mem_t * mem); 33#define VIA_MM_ALIGN_SHIFT 4
41static int via_agp_free(drm_via_mem_t * mem); 34#define VIA_MM_ALIGN_MASK ( (1 << VIA_MM_ALIGN_SHIFT) - 1)
42static int via_fb_alloc(drm_via_mem_t * mem);
43static int via_fb_free(drm_via_mem_t * mem);
44
45static int add_alloc_set(int context, int type, unsigned long val)
46{
47 int i, retval = 0;
48
49 for (i = 0; i < MAX_CONTEXT; i++) {
50 if (global_ppriv[i].used && global_ppriv[i].context == context) {
51 retval = via_setAdd(global_ppriv[i].sets[type], val);
52 break;
53 }
54 }
55
56 return retval;
57}
58
59static int del_alloc_set(int context, int type, unsigned long val)
60{
61 int i, retval = 0;
62
63 for (i = 0; i < MAX_CONTEXT; i++)
64 if (global_ppriv[i].used && global_ppriv[i].context == context) {
65 retval = via_setDel(global_ppriv[i].sets[type], val);
66 break;
67 }
68
69 return retval;
70}
71
72/* agp memory management */
73static memHeap_t *AgpHeap = NULL;
74 35
75int via_agp_init(DRM_IOCTL_ARGS) 36int via_agp_init(DRM_IOCTL_ARGS)
76{ 37{
38 DRM_DEVICE;
77 drm_via_agp_t agp; 39 drm_via_agp_t agp;
40 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
41 int ret;
78 42
79 DRM_COPY_FROM_USER_IOCTL(agp, (drm_via_agp_t __user *) data, 43 DRM_COPY_FROM_USER_IOCTL(agp, (drm_via_agp_t __user *) data,
80 sizeof(agp)); 44 sizeof(agp));
45 mutex_lock(&dev->struct_mutex);
46 ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_AGP, 0,
47 agp.size >> VIA_MM_ALIGN_SHIFT);
48
49 if (ret) {
50 DRM_ERROR("AGP memory manager initialisation error\n");
51 mutex_unlock(&dev->struct_mutex);
52 return ret;
53 }
81 54
82 AgpHeap = via_mmInit(agp.offset, agp.size); 55 dev_priv->agp_initialized = 1;
83 56 dev_priv->agp_offset = agp.offset;
84 DRM_DEBUG("offset = %lu, size = %lu", (unsigned long)agp.offset, 57 mutex_unlock(&dev->struct_mutex);
85 (unsigned long)agp.size);
86 58
59 DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size);
87 return 0; 60 return 0;
88} 61}
89 62
90/* fb memory management */
91static memHeap_t *FBHeap = NULL;
92
93int via_fb_init(DRM_IOCTL_ARGS) 63int via_fb_init(DRM_IOCTL_ARGS)
94{ 64{
65 DRM_DEVICE;
95 drm_via_fb_t fb; 66 drm_via_fb_t fb;
67 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
68 int ret;
96 69
97 DRM_COPY_FROM_USER_IOCTL(fb, (drm_via_fb_t __user *) data, sizeof(fb)); 70 DRM_COPY_FROM_USER_IOCTL(fb, (drm_via_fb_t __user *) data, sizeof(fb));
98 71
99 FBHeap = via_mmInit(fb.offset, fb.size); 72 mutex_lock(&dev->struct_mutex);
73 ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_VIDEO, 0,
74 fb.size >> VIA_MM_ALIGN_SHIFT);
100 75
101 DRM_DEBUG("offset = %lu, size = %lu", (unsigned long)fb.offset, 76 if (ret) {
102 (unsigned long)fb.size); 77 DRM_ERROR("VRAM memory manager initialisation error\n");
78 mutex_unlock(&dev->struct_mutex);
79 return ret;
80 }
103 81
104 return 0; 82 dev_priv->vram_initialized = 1;
105} 83 dev_priv->vram_offset = fb.offset;
106 84
107int via_init_context(struct drm_device *dev, int context) 85 mutex_unlock(&dev->struct_mutex);
108{ 86 DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size);
109 int i; 87
110 88 return 0;
111 for (i = 0; i < MAX_CONTEXT; i++)
112 if (global_ppriv[i].used &&
113 (global_ppriv[i].context == context))
114 break;
115
116 if (i >= MAX_CONTEXT) {
117 for (i = 0; i < MAX_CONTEXT; i++) {
118 if (!global_ppriv[i].used) {
119 global_ppriv[i].context = context;
120 global_ppriv[i].used = 1;
121 global_ppriv[i].sets[0] = via_setInit();
122 global_ppriv[i].sets[1] = via_setInit();
123 DRM_DEBUG("init allocation set, socket=%d,"
124 " context = %d\n", i, context);
125 break;
126 }
127 }
128
129 if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) ||
130 (global_ppriv[i].sets[1] == NULL)) {
131 return 0;
132 }
133 }
134 89
135 return 1;
136} 90}
137 91
138int via_final_context(struct drm_device *dev, int context) 92int via_final_context(struct drm_device *dev, int context)
139{ 93{
140 int i;
141 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; 94 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
142 95
143 for (i = 0; i < MAX_CONTEXT; i++)
144 if (global_ppriv[i].used &&
145 (global_ppriv[i].context == context))
146 break;
147
148 if (i < MAX_CONTEXT) {
149 set_t *set;
150 ITEM_TYPE item;
151 int retval;
152
153 DRM_DEBUG("find socket %d, context = %d\n", i, context);
154
155 /* Video Memory */
156 set = global_ppriv[i].sets[0];
157 retval = via_setFirst(set, &item);
158 while (retval) {
159 DRM_DEBUG("free video memory 0x%lx\n", item);
160 via_mmFreeMem((PMemBlock) item);
161 retval = via_setNext(set, &item);
162 }
163 via_setDestroy(set);
164
165 /* AGP Memory */
166 set = global_ppriv[i].sets[1];
167 retval = via_setFirst(set, &item);
168 while (retval) {
169 DRM_DEBUG("free agp memory 0x%lx\n", item);
170 via_mmFreeMem((PMemBlock) item);
171 retval = via_setNext(set, &item);
172 }
173 via_setDestroy(set);
174 global_ppriv[i].used = 0;
175 }
176 via_release_futex(dev_priv, context); 96 via_release_futex(dev_priv, context);
177 97
178#if defined(__linux__)
179 /* Linux specific until context tracking code gets ported to BSD */ 98 /* Linux specific until context tracking code gets ported to BSD */
180 /* Last context, perform cleanup */ 99 /* Last context, perform cleanup */
181 if (dev->ctx_count == 1 && dev->dev_private) { 100 if (dev->ctx_count == 1 && dev->dev_private) {
182 DRM_DEBUG("Last Context\n"); 101 DRM_DEBUG("Last Context\n");
183 if (dev->irq) 102 if (dev->irq)
184 drm_irq_uninstall(dev); 103 drm_irq_uninstall(dev);
185
186 via_cleanup_futex(dev_priv); 104 via_cleanup_futex(dev_priv);
187 via_do_cleanup_map(dev); 105 via_do_cleanup_map(dev);
188 } 106 }
189#endif
190
191 return 1; 107 return 1;
192} 108}
193 109
110void via_lastclose(struct drm_device *dev)
111{
112 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
113
114 if (!dev_priv)
115 return;
116
117 mutex_lock(&dev->struct_mutex);
118 drm_sman_cleanup(&dev_priv->sman);
119 dev_priv->vram_initialized = 0;
120 dev_priv->agp_initialized = 0;
121 mutex_unlock(&dev->struct_mutex);
122}
123
194int via_mem_alloc(DRM_IOCTL_ARGS) 124int via_mem_alloc(DRM_IOCTL_ARGS)
195{ 125{
126 DRM_DEVICE;
127
196 drm_via_mem_t mem; 128 drm_via_mem_t mem;
129 int retval = 0;
130 drm_memblock_item_t *item;
131 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
132 unsigned long tmpSize;
197 133
198 DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data, 134 DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data,
199 sizeof(mem)); 135 sizeof(mem));
200 136
201 switch (mem.type) { 137 if (mem.type > VIA_MEM_AGP) {
202 case VIA_MEM_VIDEO: 138 DRM_ERROR("Unknown memory type allocation\n");
203 if (via_fb_alloc(&mem) < 0) 139 return DRM_ERR(EINVAL);
204 return -EFAULT;
205 DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem,
206 sizeof(mem));
207 return 0;
208 case VIA_MEM_AGP:
209 if (via_agp_alloc(&mem) < 0)
210 return -EFAULT;
211 DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem,
212 sizeof(mem));
213 return 0;
214 } 140 }
215 141 mutex_lock(&dev->struct_mutex);
216 return -EFAULT; 142 if (0 == ((mem.type == VIA_MEM_VIDEO) ? dev_priv->vram_initialized :
217} 143 dev_priv->agp_initialized)) {
218 144 DRM_ERROR
219static int via_fb_alloc(drm_via_mem_t * mem) 145 ("Attempt to allocate from uninitialized memory manager.\n");
220{ 146 mutex_unlock(&dev->struct_mutex);
221 drm_via_mm_t fb; 147 return DRM_ERR(EINVAL);
222 PMemBlock block;
223 int retval = 0;
224
225 if (!FBHeap)
226 return -1;
227
228 fb.size = mem->size;
229 fb.context = mem->context;
230
231 block = via_mmAllocMem(FBHeap, fb.size, 5, 0);
232 if (block) {
233 fb.offset = block->ofs;
234 fb.free = (unsigned long)block;
235 if (!add_alloc_set(fb.context, VIA_MEM_VIDEO, fb.free)) {
236 DRM_DEBUG("adding to allocation set fails\n");
237 via_mmFreeMem((PMemBlock) fb.free);
238 retval = -1;
239 }
240 } else {
241 fb.offset = 0;
242 fb.size = 0;
243 fb.free = 0;
244 retval = -1;
245 } 148 }
246 149
247 mem->offset = fb.offset; 150 tmpSize = (mem.size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT;
248 mem->index = fb.free; 151 item = drm_sman_alloc(&dev_priv->sman, mem.type, tmpSize, 0,
249 152 (unsigned long)priv);
250 DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, 153 mutex_unlock(&dev->struct_mutex);
251 (int)fb.offset); 154 if (item) {
252 155 mem.offset = ((mem.type == VIA_MEM_VIDEO) ?
253 return retval; 156 dev_priv->vram_offset : dev_priv->agp_offset) +
254} 157 (item->mm->
255 158 offset(item->mm, item->mm_info) << VIA_MM_ALIGN_SHIFT);
256static int via_agp_alloc(drm_via_mem_t * mem) 159 mem.index = item->user_hash.key;
257{
258 drm_via_mm_t agp;
259 PMemBlock block;
260 int retval = 0;
261
262 if (!AgpHeap)
263 return -1;
264
265 agp.size = mem->size;
266 agp.context = mem->context;
267
268 block = via_mmAllocMem(AgpHeap, agp.size, 5, 0);
269 if (block) {
270 agp.offset = block->ofs;
271 agp.free = (unsigned long)block;
272 if (!add_alloc_set(agp.context, VIA_MEM_AGP, agp.free)) {
273 DRM_DEBUG("adding to allocation set fails\n");
274 via_mmFreeMem((PMemBlock) agp.free);
275 retval = -1;
276 }
277 } else { 160 } else {
278 agp.offset = 0; 161 mem.offset = 0;
279 agp.size = 0; 162 mem.size = 0;
280 agp.free = 0; 163 mem.index = 0;
164 DRM_DEBUG("Video memory allocation failed\n");
165 retval = DRM_ERR(ENOMEM);
281 } 166 }
167 DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem, sizeof(mem));
282 168
283 mem->offset = agp.offset;
284 mem->index = agp.free;
285
286 DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size,
287 (unsigned int)agp.offset);
288 return retval; 169 return retval;
289} 170}
290 171
291int via_mem_free(DRM_IOCTL_ARGS) 172int via_mem_free(DRM_IOCTL_ARGS)
292{ 173{
174 DRM_DEVICE;
175 drm_via_private_t *dev_priv = dev->dev_private;
293 drm_via_mem_t mem; 176 drm_via_mem_t mem;
177 int ret;
294 178
295 DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data, 179 DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data,
296 sizeof(mem)); 180 sizeof(mem));
297 181
298 switch (mem.type) { 182 mutex_lock(&dev->struct_mutex);
183 ret = drm_sman_free_key(&dev_priv->sman, mem.index);
184 mutex_unlock(&dev->struct_mutex);
185 DRM_DEBUG("free = 0x%lx\n", mem.index);
299 186
300 case VIA_MEM_VIDEO: 187 return ret;
301 if (via_fb_free(&mem) == 0)
302 return 0;
303 break;
304 case VIA_MEM_AGP:
305 if (via_agp_free(&mem) == 0)
306 return 0;
307 break;
308 }
309
310 return -EFAULT;
311} 188}
312 189
313static int via_fb_free(drm_via_mem_t * mem)
314{
315 drm_via_mm_t fb;
316 int retval = 0;
317
318 if (!FBHeap) {
319 return -1;
320 }
321
322 fb.free = mem->index;
323 fb.context = mem->context;
324
325 if (!fb.free) {
326 return -1;
327
328 }
329
330 via_mmFreeMem((PMemBlock) fb.free);
331
332 if (!del_alloc_set(fb.context, VIA_MEM_VIDEO, fb.free)) {
333 retval = -1;
334 }
335
336 DRM_DEBUG("free fb, free = %ld\n", fb.free);
337 190
338 return retval; 191void via_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
339}
340
341static int via_agp_free(drm_via_mem_t * mem)
342{ 192{
343 drm_via_mm_t agp; 193 drm_via_private_t *dev_priv = dev->dev_private;
344 194 drm_file_t *priv = filp->private_data;
345 int retval = 0;
346 195
347 agp.free = mem->index; 196 mutex_lock(&dev->struct_mutex);
348 agp.context = mem->context; 197 if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)priv)) {
349 198 mutex_unlock(&dev->struct_mutex);
350 if (!agp.free) 199 return;
351 return -1;
352
353 via_mmFreeMem((PMemBlock) agp.free);
354
355 if (!del_alloc_set(agp.context, VIA_MEM_AGP, agp.free)) {
356 retval = -1;
357 } 200 }
358 201
359 DRM_DEBUG("free agp, free = %ld\n", agp.free); 202 if (dev->driver->dma_quiescent) {
203 dev->driver->dma_quiescent(dev);
204 }
360 205
361 return retval; 206 drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)priv);
207 mutex_unlock(&dev->struct_mutex);
208 return;
362} 209}
diff --git a/drivers/char/ds1286.c b/drivers/char/ds1286.c
index 21c8229f5443..6d58b0370802 100644
--- a/drivers/char/ds1286.c
+++ b/drivers/char/ds1286.c
@@ -104,7 +104,7 @@ static int ds1286_ioctl(struct inode *inode, struct file *file,
104 switch (cmd) { 104 switch (cmd) {
105 case RTC_AIE_OFF: /* Mask alarm int. enab. bit */ 105 case RTC_AIE_OFF: /* Mask alarm int. enab. bit */
106 { 106 {
107 unsigned int flags; 107 unsigned long flags;
108 unsigned char val; 108 unsigned char val;
109 109
110 if (!capable(CAP_SYS_TIME)) 110 if (!capable(CAP_SYS_TIME))
@@ -120,7 +120,7 @@ static int ds1286_ioctl(struct inode *inode, struct file *file,
120 } 120 }
121 case RTC_AIE_ON: /* Allow alarm interrupts. */ 121 case RTC_AIE_ON: /* Allow alarm interrupts. */
122 { 122 {
123 unsigned int flags; 123 unsigned long flags;
124 unsigned char val; 124 unsigned char val;
125 125
126 if (!capable(CAP_SYS_TIME)) 126 if (!capable(CAP_SYS_TIME))
@@ -136,7 +136,7 @@ static int ds1286_ioctl(struct inode *inode, struct file *file,
136 } 136 }
137 case RTC_WIE_OFF: /* Mask watchdog int. enab. bit */ 137 case RTC_WIE_OFF: /* Mask watchdog int. enab. bit */
138 { 138 {
139 unsigned int flags; 139 unsigned long flags;
140 unsigned char val; 140 unsigned char val;
141 141
142 if (!capable(CAP_SYS_TIME)) 142 if (!capable(CAP_SYS_TIME))
@@ -152,7 +152,7 @@ static int ds1286_ioctl(struct inode *inode, struct file *file,
152 } 152 }
153 case RTC_WIE_ON: /* Allow watchdog interrupts. */ 153 case RTC_WIE_ON: /* Allow watchdog interrupts. */
154 { 154 {
155 unsigned int flags; 155 unsigned long flags;
156 unsigned char val; 156 unsigned char val;
157 157
158 if (!capable(CAP_SYS_TIME)) 158 if (!capable(CAP_SYS_TIME))
@@ -434,7 +434,7 @@ static inline unsigned char ds1286_is_updating(void)
434static void ds1286_get_time(struct rtc_time *rtc_tm) 434static void ds1286_get_time(struct rtc_time *rtc_tm)
435{ 435{
436 unsigned char save_control; 436 unsigned char save_control;
437 unsigned int flags; 437 unsigned long flags;
438 unsigned long uip_watchdog = jiffies; 438 unsigned long uip_watchdog = jiffies;
439 439
440 /* 440 /*
@@ -494,7 +494,8 @@ static int ds1286_set_time(struct rtc_time *rtc_tm)
494{ 494{
495 unsigned char mon, day, hrs, min, sec, leap_yr; 495 unsigned char mon, day, hrs, min, sec, leap_yr;
496 unsigned char save_control; 496 unsigned char save_control;
497 unsigned int yrs, flags; 497 unsigned int yrs;
498 unsigned long flags;
498 499
499 500
500 yrs = rtc_tm->tm_year + 1900; 501 yrs = rtc_tm->tm_year + 1900;
@@ -552,7 +553,7 @@ static int ds1286_set_time(struct rtc_time *rtc_tm)
552static void ds1286_get_alm_time(struct rtc_time *alm_tm) 553static void ds1286_get_alm_time(struct rtc_time *alm_tm)
553{ 554{
554 unsigned char cmd; 555 unsigned char cmd;
555 unsigned int flags; 556 unsigned long flags;
556 557
557 /* 558 /*
558 * Only the values that we read from the RTC are set. That 559 * Only the values that we read from the RTC are set. That
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index 86d290e9f307..3baa2ab8cbd4 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -1125,7 +1125,7 @@ static void __exit epca_module_exit(void)
1125 1125
1126module_exit(epca_module_exit); 1126module_exit(epca_module_exit);
1127 1127
1128static struct tty_operations pc_ops = { 1128static const struct tty_operations pc_ops = {
1129 .open = pc_open, 1129 .open = pc_open,
1130 .close = pc_close, 1130 .close = pc_close,
1131 .write = pc_write, 1131 .write = pc_write,
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index afcd83d9984b..05788c75d7fc 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -2376,7 +2376,7 @@ static inline int autoconfig(struct esp_struct * info)
2376 return (port_detected); 2376 return (port_detected);
2377} 2377}
2378 2378
2379static struct tty_operations esp_ops = { 2379static const struct tty_operations esp_ops = {
2380 .open = esp_open, 2380 .open = esp_open,
2381 .close = rs_close, 2381 .close = rs_close,
2382 .write = rs_write, 2382 .write = rs_write,
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c
index 5e59c0b42731..4711d9b3a595 100644
--- a/drivers/char/generic_serial.c
+++ b/drivers/char/generic_serial.c
@@ -746,11 +746,9 @@ void gs_set_termios (struct tty_struct * tty,
746 gs_dprintk (GS_DEBUG_TERMIOS, "termios structure (%p):\n", tiosp); 746 gs_dprintk (GS_DEBUG_TERMIOS, "termios structure (%p):\n", tiosp);
747 } 747 }
748 748
749#if 0
750 /* This is an optimization that is only allowed for dumb cards */ 749 /* This is an optimization that is only allowed for dumb cards */
751 /* Smart cards require knowledge of iflags and oflags too: that 750 /* Smart cards require knowledge of iflags and oflags too: that
752 might change hardware cooking mode.... */ 751 might change hardware cooking mode.... */
753#endif
754 if (old_termios) { 752 if (old_termios) {
755 if( (tiosp->c_iflag == old_termios->c_iflag) 753 if( (tiosp->c_iflag == old_termios->c_iflag)
756 && (tiosp->c_oflag == old_termios->c_oflag) 754 && (tiosp->c_oflag == old_termios->c_oflag)
@@ -774,14 +772,7 @@ void gs_set_termios (struct tty_struct * tty,
774 if(!memcmp(tiosp->c_cc, old_termios->c_cc, NCC)) printk("c_cc changed\n"); 772 if(!memcmp(tiosp->c_cc, old_termios->c_cc, NCC)) printk("c_cc changed\n");
775 } 773 }
776 774
777 baudrate = tiosp->c_cflag & CBAUD; 775 baudrate = tty_get_baud_rate(tty);
778 if (baudrate & CBAUDEX) {
779 baudrate &= ~CBAUDEX;
780 if ((baudrate < 1) || (baudrate > 4))
781 tiosp->c_cflag &= ~CBAUDEX;
782 else
783 baudrate += 15;
784 }
785 776
786 baudrate = gs_baudrates[baudrate]; 777 baudrate = gs_baudrates[baudrate];
787 if ((tiosp->c_cflag & CBAUD) == B38400) { 778 if ((tiosp->c_cflag & CBAUD) == B38400) {
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 8afba339f05a..58b0eb581114 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -868,8 +868,8 @@ int hpet_alloc(struct hpet_data *hdp)
868 do_div(temp, period); 868 do_div(temp, period);
869 hpetp->hp_tick_freq = temp; /* ticks per second */ 869 hpetp->hp_tick_freq = temp; /* ticks per second */
870 870
871 printk(KERN_INFO "hpet%d: at MMIO 0x%lx (virtual 0x%p), IRQ%s", 871 printk(KERN_INFO "hpet%d: at MMIO 0x%lx, IRQ%s",
872 hpetp->hp_which, hdp->hd_phys_address, hdp->hd_address, 872 hpetp->hp_which, hdp->hd_phys_address,
873 hpetp->hp_ntimer > 1 ? "s" : ""); 873 hpetp->hp_ntimer > 1 ? "s" : "");
874 for (i = 0; i < hpetp->hp_ntimer; i++) 874 for (i = 0; i < hpetp->hp_ntimer; i++)
875 printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]); 875 printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]);
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index a76d2c40dd5e..4053d1cd393f 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -696,7 +696,7 @@ int khvcd(void *unused)
696 return 0; 696 return 0;
697} 697}
698 698
699static struct tty_operations hvc_ops = { 699static const struct tty_operations hvc_ops = {
700 .open = hvc_open, 700 .open = hvc_open,
701 .close = hvc_close, 701 .close = hvc_close,
702 .write = hvc_write, 702 .write = hvc_write,
diff --git a/drivers/char/hvc_iseries.c b/drivers/char/hvc_iseries.c
index ea362011bd5b..f144a947bd17 100644
--- a/drivers/char/hvc_iseries.c
+++ b/drivers/char/hvc_iseries.c
@@ -154,9 +154,7 @@ static int put_chars(uint32_t vtermno, const char *buf, int count)
154 spin_lock_irqsave(&consolelock, flags); 154 spin_lock_irqsave(&consolelock, flags);
155 155
156 if (viochar_is_console(pi) && !viopath_isactive(pi->lp)) { 156 if (viochar_is_console(pi) && !viopath_isactive(pi->lp)) {
157 spin_lock_irqsave(&consoleloglock, flags);
158 HvCall_writeLogBuffer(buf, count); 157 HvCall_writeLogBuffer(buf, count);
159 spin_unlock_irqrestore(&consoleloglock, flags);
160 sent = count; 158 sent = count;
161 goto done; 159 goto done;
162 } 160 }
@@ -172,11 +170,8 @@ static int put_chars(uint32_t vtermno, const char *buf, int count)
172 170
173 len = (count > VIOCHAR_MAX_DATA) ? VIOCHAR_MAX_DATA : count; 171 len = (count > VIOCHAR_MAX_DATA) ? VIOCHAR_MAX_DATA : count;
174 172
175 if (viochar_is_console(pi)) { 173 if (viochar_is_console(pi))
176 spin_lock_irqsave(&consoleloglock, flags);
177 HvCall_writeLogBuffer(buf, len); 174 HvCall_writeLogBuffer(buf, len);
178 spin_unlock_irqrestore(&consoleloglock, flags);
179 }
180 175
181 init_data_event(viochar, pi->lp); 176 init_data_event(viochar, pi->lp);
182 177
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c
index 4589ff302b07..0b89bcde8c52 100644
--- a/drivers/char/hvcs.c
+++ b/drivers/char/hvcs.c
@@ -1306,7 +1306,7 @@ static int hvcs_chars_in_buffer(struct tty_struct *tty)
1306 return hvcsd->chars_in_buffer; 1306 return hvcsd->chars_in_buffer;
1307} 1307}
1308 1308
1309static struct tty_operations hvcs_ops = { 1309static const struct tty_operations hvcs_ops = {
1310 .open = hvcs_open, 1310 .open = hvcs_open,
1311 .close = hvcs_close, 1311 .close = hvcs_close,
1312 .hangup = hvcs_hangup, 1312 .hangup = hvcs_hangup,
diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c
index a89a95fb5e40..c07dc58d5c1d 100644
--- a/drivers/char/hvsi.c
+++ b/drivers/char/hvsi.c
@@ -1130,7 +1130,7 @@ static int hvsi_tiocmset(struct tty_struct *tty, struct file *file,
1130} 1130}
1131 1131
1132 1132
1133static struct tty_operations hvsi_ops = { 1133static const struct tty_operations hvsi_ops = {
1134 .open = hvsi_open, 1134 .open = hvsi_open,
1135 .close = hvsi_close, 1135 .close = hvsi_close,
1136 .write = hvsi_write, 1136 .write = hvsi_write,
diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c
index ccd7e7102234..8efbc9c0e545 100644
--- a/drivers/char/hw_random/intel-rng.c
+++ b/drivers/char/hw_random/intel-rng.c
@@ -50,6 +50,43 @@
50#define INTEL_RNG_ADDR_LEN 3 50#define INTEL_RNG_ADDR_LEN 3
51 51
52/* 52/*
53 * LPC bridge PCI config space registers
54 */
55#define FWH_DEC_EN1_REG_OLD 0xe3
56#define FWH_DEC_EN1_REG_NEW 0xd9 /* high byte of 16-bit register */
57#define FWH_F8_EN_MASK 0x80
58
59#define BIOS_CNTL_REG_OLD 0x4e
60#define BIOS_CNTL_REG_NEW 0xdc
61#define BIOS_CNTL_WRITE_ENABLE_MASK 0x01
62#define BIOS_CNTL_LOCK_ENABLE_MASK 0x02
63
64/*
65 * Magic address at which Intel Firmware Hubs get accessed
66 */
67#define INTEL_FWH_ADDR 0xffff0000
68#define INTEL_FWH_ADDR_LEN 2
69
70/*
71 * Intel Firmware Hub command codes (write to any address inside the device)
72 */
73#define INTEL_FWH_RESET_CMD 0xff /* aka READ_ARRAY */
74#define INTEL_FWH_READ_ID_CMD 0x90
75
76/*
77 * Intel Firmware Hub Read ID command result addresses
78 */
79#define INTEL_FWH_MANUFACTURER_CODE_ADDRESS 0x000000
80#define INTEL_FWH_DEVICE_CODE_ADDRESS 0x000001
81
82/*
83 * Intel Firmware Hub Read ID command result values
84 */
85#define INTEL_FWH_MANUFACTURER_CODE 0x89
86#define INTEL_FWH_DEVICE_CODE_8M 0xac
87#define INTEL_FWH_DEVICE_CODE_4M 0xad
88
89/*
53 * Data for PCI driver interface 90 * Data for PCI driver interface
54 * 91 *
55 * This data only exists for exporting the supported 92 * This data only exists for exporting the supported
@@ -58,12 +95,50 @@
58 * want to register another driver on the same PCI id. 95 * want to register another driver on the same PCI id.
59 */ 96 */
60static const struct pci_device_id pci_tbl[] = { 97static const struct pci_device_id pci_tbl[] = {
61 { 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, 98/* AA
62 { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, 99 { 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
63 { 0x8086, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, 100 { 0x8086, 0x2410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* AA */
64 { 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, 101/* AB
65 { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, 102 { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
66 { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, 103 { 0x8086, 0x2420, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* AB */
104/* ??
105 { 0x8086, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
106/* BAM, CAM, DBM, FBM, GxM
107 { 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
108 { 0x8086, 0x244c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* BAM */
109 { 0x8086, 0x248c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CAM */
110 { 0x8086, 0x24cc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* DBM */
111 { 0x8086, 0x2641, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* FBM */
112 { 0x8086, 0x27b9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* GxM */
113 { 0x8086, 0x27bd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* GxM DH */
114/* BA, CA, DB, Ex, 6300, Fx, 631x/632x, Gx
115 { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
116 { 0x8086, 0x2440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* BA */
117 { 0x8086, 0x2480, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CA */
118 { 0x8086, 0x24c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* DB */
119 { 0x8086, 0x24d0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Ex */
120 { 0x8086, 0x25a1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 6300 */
121 { 0x8086, 0x2640, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Fx */
122 { 0x8086, 0x2670, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
123 { 0x8086, 0x2671, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
124 { 0x8086, 0x2672, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
125 { 0x8086, 0x2673, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
126 { 0x8086, 0x2674, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
127 { 0x8086, 0x2675, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
128 { 0x8086, 0x2676, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
129 { 0x8086, 0x2677, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
130 { 0x8086, 0x2678, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
131 { 0x8086, 0x2679, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
132 { 0x8086, 0x267a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
133 { 0x8086, 0x267b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
134 { 0x8086, 0x267c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
135 { 0x8086, 0x267d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
136 { 0x8086, 0x267e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
137 { 0x8086, 0x267f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
138 { 0x8086, 0x27b8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Gx */
139/* E
140 { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
141 { 0x8086, 0x2450, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* E */
67 { 0, }, /* terminate list */ 142 { 0, }, /* terminate list */
68}; 143};
69MODULE_DEVICE_TABLE(pci, pci_tbl); 144MODULE_DEVICE_TABLE(pci, pci_tbl);
@@ -138,22 +213,115 @@ static struct hwrng intel_rng = {
138}; 213};
139 214
140 215
216#ifdef CONFIG_SMP
217static char __initdata waitflag;
218
219static void __init intel_init_wait(void *unused)
220{
221 while (waitflag)
222 cpu_relax();
223}
224#endif
225
141static int __init mod_init(void) 226static int __init mod_init(void)
142{ 227{
143 int err = -ENODEV; 228 int err = -ENODEV;
229 unsigned i;
230 struct pci_dev *dev = NULL;
144 void __iomem *mem; 231 void __iomem *mem;
145 u8 hw_status; 232 unsigned long flags;
233 u8 bios_cntl_off, fwh_dec_en1_off;
234 u8 bios_cntl_val = 0xff, fwh_dec_en1_val = 0xff;
235 u8 hw_status, mfc, dvc;
146 236
147 if (!pci_dev_present(pci_tbl)) 237 for (i = 0; !dev && pci_tbl[i].vendor; ++i)
238 dev = pci_get_device(pci_tbl[i].vendor, pci_tbl[i].device, NULL);
239
240 if (!dev)
148 goto out; /* Device not found. */ 241 goto out; /* Device not found. */
149 242
243 /* Check for Intel 82802 */
244 if (dev->device < 0x2640) {
245 fwh_dec_en1_off = FWH_DEC_EN1_REG_OLD;
246 bios_cntl_off = BIOS_CNTL_REG_OLD;
247 } else {
248 fwh_dec_en1_off = FWH_DEC_EN1_REG_NEW;
249 bios_cntl_off = BIOS_CNTL_REG_NEW;
250 }
251
252 pci_read_config_byte(dev, fwh_dec_en1_off, &fwh_dec_en1_val);
253 pci_read_config_byte(dev, bios_cntl_off, &bios_cntl_val);
254
255 mem = ioremap_nocache(INTEL_FWH_ADDR, INTEL_FWH_ADDR_LEN);
256 if (mem == NULL) {
257 pci_dev_put(dev);
258 err = -EBUSY;
259 goto out;
260 }
261
262 /*
263 * Since the BIOS code/data is going to disappear from its normal
264 * location with the Read ID command, all activity on the system
265 * must be stopped until the state is back to normal.
266 */
267#ifdef CONFIG_SMP
268 set_mb(waitflag, 1);
269 if (smp_call_function(intel_init_wait, NULL, 1, 0) != 0) {
270 set_mb(waitflag, 0);
271 pci_dev_put(dev);
272 printk(KERN_ERR PFX "cannot run on all processors\n");
273 err = -EAGAIN;
274 goto err_unmap;
275 }
276#endif
277 local_irq_save(flags);
278
279 if (!(fwh_dec_en1_val & FWH_F8_EN_MASK))
280 pci_write_config_byte(dev,
281 fwh_dec_en1_off,
282 fwh_dec_en1_val | FWH_F8_EN_MASK);
283 if (!(bios_cntl_val &
284 (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)))
285 pci_write_config_byte(dev,
286 bios_cntl_off,
287 bios_cntl_val | BIOS_CNTL_WRITE_ENABLE_MASK);
288
289 writeb(INTEL_FWH_RESET_CMD, mem);
290 writeb(INTEL_FWH_READ_ID_CMD, mem);
291 mfc = readb(mem + INTEL_FWH_MANUFACTURER_CODE_ADDRESS);
292 dvc = readb(mem + INTEL_FWH_DEVICE_CODE_ADDRESS);
293 writeb(INTEL_FWH_RESET_CMD, mem);
294
295 if (!(bios_cntl_val &
296 (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)))
297 pci_write_config_byte(dev, bios_cntl_off, bios_cntl_val);
298 if (!(fwh_dec_en1_val & FWH_F8_EN_MASK))
299 pci_write_config_byte(dev, fwh_dec_en1_off, fwh_dec_en1_val);
300
301 local_irq_restore(flags);
302#ifdef CONFIG_SMP
303 /* Tell other CPUs to resume. */
304 set_mb(waitflag, 0);
305#endif
306
307 iounmap(mem);
308 pci_dev_put(dev);
309
310 if (mfc != INTEL_FWH_MANUFACTURER_CODE ||
311 (dvc != INTEL_FWH_DEVICE_CODE_8M &&
312 dvc != INTEL_FWH_DEVICE_CODE_4M)) {
313 printk(KERN_ERR PFX "FWH not detected\n");
314 err = -ENODEV;
315 goto out;
316 }
317
150 err = -ENOMEM; 318 err = -ENOMEM;
151 mem = ioremap(INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN); 319 mem = ioremap(INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN);
152 if (!mem) 320 if (!mem)
153 goto out; 321 goto out;
154 intel_rng.priv = (unsigned long)mem; 322 intel_rng.priv = (unsigned long)mem;
155 323
156 /* Check for Intel 82802 */ 324 /* Check for Random Number Generator */
157 err = -ENODEV; 325 err = -ENODEV;
158 hw_status = hwstatus_get(mem); 326 hw_status = hwstatus_get(mem);
159 if ((hw_status & INTEL_RNG_PRESENT) == 0) 327 if ((hw_status & INTEL_RNG_PRESENT) == 0)
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
index 7907ae88c2f4..62ef511d143b 100644
--- a/drivers/char/ip2/ip2main.c
+++ b/drivers/char/ip2/ip2main.c
@@ -436,6 +436,7 @@ cleanup_module(void)
436#ifdef CONFIG_PCI 436#ifdef CONFIG_PCI
437 if (ip2config.type[i] == PCI && ip2config.pci_dev[i]) { 437 if (ip2config.type[i] == PCI && ip2config.pci_dev[i]) {
438 pci_disable_device(ip2config.pci_dev[i]); 438 pci_disable_device(ip2config.pci_dev[i]);
439 pci_dev_put(ip2config.pci_dev[i]);
439 ip2config.pci_dev[i] = NULL; 440 ip2config.pci_dev[i] = NULL;
440 } 441 }
441#endif 442#endif
@@ -457,7 +458,7 @@ cleanup_module(void)
457} 458}
458#endif /* MODULE */ 459#endif /* MODULE */
459 460
460static struct tty_operations ip2_ops = { 461static const struct tty_operations ip2_ops = {
461 .open = ip2_open, 462 .open = ip2_open,
462 .close = ip2_close, 463 .close = ip2_close,
463 .write = ip2_write, 464 .write = ip2_write,
@@ -505,6 +506,7 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
505 static int loaded; 506 static int loaded;
506 i2eBordStrPtr pB = NULL; 507 i2eBordStrPtr pB = NULL;
507 int rc = -1; 508 int rc = -1;
509 static struct pci_dev *pci_dev_i = NULL;
508 510
509 ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0 ); 511 ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0 );
510 512
@@ -588,8 +590,7 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
588 case PCI: 590 case PCI:
589#ifdef CONFIG_PCI 591#ifdef CONFIG_PCI
590 { 592 {
591 struct pci_dev *pci_dev_i = NULL; 593 pci_dev_i = pci_get_device(PCI_VENDOR_ID_COMPUTONE,
592 pci_dev_i = pci_find_device(PCI_VENDOR_ID_COMPUTONE,
593 PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i); 594 PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i);
594 if (pci_dev_i != NULL) { 595 if (pci_dev_i != NULL) {
595 unsigned int addr; 596 unsigned int addr;
@@ -600,7 +601,7 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
600 break; 601 break;
601 } 602 }
602 ip2config.type[i] = PCI; 603 ip2config.type[i] = PCI;
603 ip2config.pci_dev[i] = pci_dev_i; 604 ip2config.pci_dev[i] = pci_dev_get(pci_dev_i);
604 status = 605 status =
605 pci_read_config_dword(pci_dev_i, PCI_BASE_ADDRESS_1, &addr); 606 pci_read_config_dword(pci_dev_i, PCI_BASE_ADDRESS_1, &addr);
606 if ( addr & 1 ) { 607 if ( addr & 1 ) {
@@ -641,6 +642,9 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
641 break; 642 break;
642 } /* switch */ 643 } /* switch */
643 } /* for */ 644 } /* for */
645 if (pci_dev_i)
646 pci_dev_put(pci_dev_i);
647
644 for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { 648 for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
645 if ( ip2config.addr[i] ) { 649 if ( ip2config.addr[i] ) {
646 pB = kmalloc( sizeof(i2eBordStr), GFP_KERNEL); 650 pB = kmalloc( sizeof(i2eBordStr), GFP_KERNEL);
@@ -775,8 +779,6 @@ retry:
775 ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0 ); 779 ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0 );
776 goto out; 780 goto out;
777 781
778out_class:
779 class_destroy(ip2_class);
780out_chrdev: 782out_chrdev:
781 unregister_chrdev(IP2_IPL_MAJOR, "ip2"); 783 unregister_chrdev(IP2_IPL_MAJOR, "ip2");
782out: 784out:
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index 68d7c61a864e..81fcf0ce21d1 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -377,7 +377,8 @@ static int ipmi_ioctl(struct inode *inode,
377 break; 377 break;
378 } 378 }
379 379
380 rv = ipmi_register_for_cmd(priv->user, val.netfn, val.cmd); 380 rv = ipmi_register_for_cmd(priv->user, val.netfn, val.cmd,
381 IPMI_CHAN_ALL);
381 break; 382 break;
382 } 383 }
383 384
@@ -390,7 +391,36 @@ static int ipmi_ioctl(struct inode *inode,
390 break; 391 break;
391 } 392 }
392 393
393 rv = ipmi_unregister_for_cmd(priv->user, val.netfn, val.cmd); 394 rv = ipmi_unregister_for_cmd(priv->user, val.netfn, val.cmd,
395 IPMI_CHAN_ALL);
396 break;
397 }
398
399 case IPMICTL_REGISTER_FOR_CMD_CHANS:
400 {
401 struct ipmi_cmdspec_chans val;
402
403 if (copy_from_user(&val, arg, sizeof(val))) {
404 rv = -EFAULT;
405 break;
406 }
407
408 rv = ipmi_register_for_cmd(priv->user, val.netfn, val.cmd,
409 val.chans);
410 break;
411 }
412
413 case IPMICTL_UNREGISTER_FOR_CMD_CHANS:
414 {
415 struct ipmi_cmdspec_chans val;
416
417 if (copy_from_user(&val, arg, sizeof(val))) {
418 rv = -EFAULT;
419 break;
420 }
421
422 rv = ipmi_unregister_for_cmd(priv->user, val.netfn, val.cmd,
423 val.chans);
394 break; 424 break;
395 } 425 }
396 426
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 843d34c8627c..2455e8d478ac 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -96,6 +96,7 @@ struct cmd_rcvr
96 ipmi_user_t user; 96 ipmi_user_t user;
97 unsigned char netfn; 97 unsigned char netfn;
98 unsigned char cmd; 98 unsigned char cmd;
99 unsigned int chans;
99 100
100 /* 101 /*
101 * This is used to form a linked lised during mass deletion. 102 * This is used to form a linked lised during mass deletion.
@@ -953,24 +954,41 @@ int ipmi_set_gets_events(ipmi_user_t user, int val)
953 954
954static struct cmd_rcvr *find_cmd_rcvr(ipmi_smi_t intf, 955static struct cmd_rcvr *find_cmd_rcvr(ipmi_smi_t intf,
955 unsigned char netfn, 956 unsigned char netfn,
956 unsigned char cmd) 957 unsigned char cmd,
958 unsigned char chan)
957{ 959{
958 struct cmd_rcvr *rcvr; 960 struct cmd_rcvr *rcvr;
959 961
960 list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) { 962 list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) {
961 if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) 963 if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)
964 && (rcvr->chans & (1 << chan)))
962 return rcvr; 965 return rcvr;
963 } 966 }
964 return NULL; 967 return NULL;
965} 968}
966 969
970static int is_cmd_rcvr_exclusive(ipmi_smi_t intf,
971 unsigned char netfn,
972 unsigned char cmd,
973 unsigned int chans)
974{
975 struct cmd_rcvr *rcvr;
976
977 list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) {
978 if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)
979 && (rcvr->chans & chans))
980 return 0;
981 }
982 return 1;
983}
984
967int ipmi_register_for_cmd(ipmi_user_t user, 985int ipmi_register_for_cmd(ipmi_user_t user,
968 unsigned char netfn, 986 unsigned char netfn,
969 unsigned char cmd) 987 unsigned char cmd,
988 unsigned int chans)
970{ 989{
971 ipmi_smi_t intf = user->intf; 990 ipmi_smi_t intf = user->intf;
972 struct cmd_rcvr *rcvr; 991 struct cmd_rcvr *rcvr;
973 struct cmd_rcvr *entry;
974 int rv = 0; 992 int rv = 0;
975 993
976 994
@@ -979,12 +997,12 @@ int ipmi_register_for_cmd(ipmi_user_t user,
979 return -ENOMEM; 997 return -ENOMEM;
980 rcvr->cmd = cmd; 998 rcvr->cmd = cmd;
981 rcvr->netfn = netfn; 999 rcvr->netfn = netfn;
1000 rcvr->chans = chans;
982 rcvr->user = user; 1001 rcvr->user = user;
983 1002
984 mutex_lock(&intf->cmd_rcvrs_mutex); 1003 mutex_lock(&intf->cmd_rcvrs_mutex);
985 /* Make sure the command/netfn is not already registered. */ 1004 /* Make sure the command/netfn is not already registered. */
986 entry = find_cmd_rcvr(intf, netfn, cmd); 1005 if (!is_cmd_rcvr_exclusive(intf, netfn, cmd, chans)) {
987 if (entry) {
988 rv = -EBUSY; 1006 rv = -EBUSY;
989 goto out_unlock; 1007 goto out_unlock;
990 } 1008 }
@@ -1001,24 +1019,39 @@ int ipmi_register_for_cmd(ipmi_user_t user,
1001 1019
1002int ipmi_unregister_for_cmd(ipmi_user_t user, 1020int ipmi_unregister_for_cmd(ipmi_user_t user,
1003 unsigned char netfn, 1021 unsigned char netfn,
1004 unsigned char cmd) 1022 unsigned char cmd,
1023 unsigned int chans)
1005{ 1024{
1006 ipmi_smi_t intf = user->intf; 1025 ipmi_smi_t intf = user->intf;
1007 struct cmd_rcvr *rcvr; 1026 struct cmd_rcvr *rcvr;
1027 struct cmd_rcvr *rcvrs = NULL;
1028 int i, rv = -ENOENT;
1008 1029
1009 mutex_lock(&intf->cmd_rcvrs_mutex); 1030 mutex_lock(&intf->cmd_rcvrs_mutex);
1010 /* Make sure the command/netfn is not already registered. */ 1031 for (i = 0; i < IPMI_NUM_CHANNELS; i++) {
1011 rcvr = find_cmd_rcvr(intf, netfn, cmd); 1032 if (((1 << i) & chans) == 0)
1012 if ((rcvr) && (rcvr->user == user)) { 1033 continue;
1013 list_del_rcu(&rcvr->link); 1034 rcvr = find_cmd_rcvr(intf, netfn, cmd, i);
1014 mutex_unlock(&intf->cmd_rcvrs_mutex); 1035 if (rcvr == NULL)
1015 synchronize_rcu(); 1036 continue;
1037 if (rcvr->user == user) {
1038 rv = 0;
1039 rcvr->chans &= ~chans;
1040 if (rcvr->chans == 0) {
1041 list_del_rcu(&rcvr->link);
1042 rcvr->next = rcvrs;
1043 rcvrs = rcvr;
1044 }
1045 }
1046 }
1047 mutex_unlock(&intf->cmd_rcvrs_mutex);
1048 synchronize_rcu();
1049 while (rcvrs) {
1050 rcvr = rcvrs;
1051 rcvrs = rcvr->next;
1016 kfree(rcvr); 1052 kfree(rcvr);
1017 return 0;
1018 } else {
1019 mutex_unlock(&intf->cmd_rcvrs_mutex);
1020 return -ENOENT;
1021 } 1053 }
1054 return rv;
1022} 1055}
1023 1056
1024void ipmi_user_set_run_to_completion(ipmi_user_t user, int val) 1057void ipmi_user_set_run_to_completion(ipmi_user_t user, int val)
@@ -2548,6 +2581,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf,
2548 int rv = 0; 2581 int rv = 0;
2549 unsigned char netfn; 2582 unsigned char netfn;
2550 unsigned char cmd; 2583 unsigned char cmd;
2584 unsigned char chan;
2551 ipmi_user_t user = NULL; 2585 ipmi_user_t user = NULL;
2552 struct ipmi_ipmb_addr *ipmb_addr; 2586 struct ipmi_ipmb_addr *ipmb_addr;
2553 struct ipmi_recv_msg *recv_msg; 2587 struct ipmi_recv_msg *recv_msg;
@@ -2568,9 +2602,10 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf,
2568 2602
2569 netfn = msg->rsp[4] >> 2; 2603 netfn = msg->rsp[4] >> 2;
2570 cmd = msg->rsp[8]; 2604 cmd = msg->rsp[8];
2605 chan = msg->rsp[3] & 0xf;
2571 2606
2572 rcu_read_lock(); 2607 rcu_read_lock();
2573 rcvr = find_cmd_rcvr(intf, netfn, cmd); 2608 rcvr = find_cmd_rcvr(intf, netfn, cmd, chan);
2574 if (rcvr) { 2609 if (rcvr) {
2575 user = rcvr->user; 2610 user = rcvr->user;
2576 kref_get(&user->refcount); 2611 kref_get(&user->refcount);
@@ -2728,6 +2763,7 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf,
2728 int rv = 0; 2763 int rv = 0;
2729 unsigned char netfn; 2764 unsigned char netfn;
2730 unsigned char cmd; 2765 unsigned char cmd;
2766 unsigned char chan;
2731 ipmi_user_t user = NULL; 2767 ipmi_user_t user = NULL;
2732 struct ipmi_lan_addr *lan_addr; 2768 struct ipmi_lan_addr *lan_addr;
2733 struct ipmi_recv_msg *recv_msg; 2769 struct ipmi_recv_msg *recv_msg;
@@ -2748,9 +2784,10 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf,
2748 2784
2749 netfn = msg->rsp[6] >> 2; 2785 netfn = msg->rsp[6] >> 2;
2750 cmd = msg->rsp[10]; 2786 cmd = msg->rsp[10];
2787 chan = msg->rsp[3] & 0xf;
2751 2788
2752 rcu_read_lock(); 2789 rcu_read_lock();
2753 rcvr = find_cmd_rcvr(intf, netfn, cmd); 2790 rcvr = find_cmd_rcvr(intf, netfn, cmd, chan);
2754 if (rcvr) { 2791 if (rcvr) {
2755 user = rcvr->user; 2792 user = rcvr->user;
2756 kref_get(&user->refcount); 2793 kref_get(&user->refcount);
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index abca98beac14..b106c45abfc9 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -217,6 +217,11 @@ struct smi_info
217 struct list_head link; 217 struct list_head link;
218}; 218};
219 219
220#define SI_MAX_PARMS 4
221
222static int force_kipmid[SI_MAX_PARMS];
223static int num_force_kipmid;
224
220static int try_smi_init(struct smi_info *smi); 225static int try_smi_init(struct smi_info *smi);
221 226
222static ATOMIC_NOTIFIER_HEAD(xaction_notifier_list); 227static ATOMIC_NOTIFIER_HEAD(xaction_notifier_list);
@@ -908,6 +913,7 @@ static int smi_start_processing(void *send_info,
908 ipmi_smi_t intf) 913 ipmi_smi_t intf)
909{ 914{
910 struct smi_info *new_smi = send_info; 915 struct smi_info *new_smi = send_info;
916 int enable = 0;
911 917
912 new_smi->intf = intf; 918 new_smi->intf = intf;
913 919
@@ -916,7 +922,19 @@ static int smi_start_processing(void *send_info,
916 new_smi->last_timeout_jiffies = jiffies; 922 new_smi->last_timeout_jiffies = jiffies;
917 mod_timer(&new_smi->si_timer, jiffies + SI_TIMEOUT_JIFFIES); 923 mod_timer(&new_smi->si_timer, jiffies + SI_TIMEOUT_JIFFIES);
918 924
919 if (new_smi->si_type != SI_BT) { 925 /*
926 * Check if the user forcefully enabled the daemon.
927 */
928 if (new_smi->intf_num < num_force_kipmid)
929 enable = force_kipmid[new_smi->intf_num];
930 /*
931 * The BT interface is efficient enough to not need a thread,
932 * and there is no need for a thread if we have interrupts.
933 */
934 else if ((new_smi->si_type != SI_BT) && (!new_smi->irq))
935 enable = 1;
936
937 if (enable) {
920 new_smi->thread = kthread_run(ipmi_thread, new_smi, 938 new_smi->thread = kthread_run(ipmi_thread, new_smi,
921 "kipmi%d", new_smi->intf_num); 939 "kipmi%d", new_smi->intf_num);
922 if (IS_ERR(new_smi->thread)) { 940 if (IS_ERR(new_smi->thread)) {
@@ -944,7 +962,6 @@ static struct ipmi_smi_handlers handlers =
944/* There can be 4 IO ports passed in (with or without IRQs), 4 addresses, 962/* There can be 4 IO ports passed in (with or without IRQs), 4 addresses,
945 a default IO port, and 1 ACPI/SPMI address. That sets SI_MAX_DRIVERS */ 963 a default IO port, and 1 ACPI/SPMI address. That sets SI_MAX_DRIVERS */
946 964
947#define SI_MAX_PARMS 4
948static LIST_HEAD(smi_infos); 965static LIST_HEAD(smi_infos);
949static DEFINE_MUTEX(smi_infos_lock); 966static DEFINE_MUTEX(smi_infos_lock);
950static int smi_num; /* Used to sequence the SMIs */ 967static int smi_num; /* Used to sequence the SMIs */
@@ -1017,6 +1034,10 @@ MODULE_PARM_DESC(slave_addrs, "Set the default IPMB slave address for"
1017 " the controller. Normally this is 0x20, but can be" 1034 " the controller. Normally this is 0x20, but can be"
1018 " overridden by this parm. This is an array indexed" 1035 " overridden by this parm. This is an array indexed"
1019 " by interface number."); 1036 " by interface number.");
1037module_param_array(force_kipmid, int, &num_force_kipmid, 0);
1038MODULE_PARM_DESC(force_kipmid, "Force the kipmi daemon to be enabled (1) or"
1039 " disabled(0). Normally the IPMI driver auto-detects"
1040 " this, but the value may be overridden by this parm.");
1020 1041
1021 1042
1022#define IPMI_IO_ADDR_SPACE 0 1043#define IPMI_IO_ADDR_SPACE 0
@@ -1730,6 +1751,7 @@ static void __devinit dmi_find_bmc(void)
1730 int rv; 1751 int rv;
1731 1752
1732 while ((dev = dmi_find_device(DMI_DEV_TYPE_IPMI, NULL, dev))) { 1753 while ((dev = dmi_find_device(DMI_DEV_TYPE_IPMI, NULL, dev))) {
1754 memset(&data, 0, sizeof(data));
1733 rv = decode_dmi((struct dmi_header *) dev->device_data, &data); 1755 rv = decode_dmi((struct dmi_header *) dev->device_data, &data);
1734 if (!rv) 1756 if (!rv)
1735 try_init_dmi(&data); 1757 try_init_dmi(&data);
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index 913be23e0a24..ea2bbf80ad33 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -1550,7 +1550,7 @@ static void isicom_unregister_ioregion(struct pci_dev *pdev)
1550 board->base = 0; 1550 board->base = 0;
1551} 1551}
1552 1552
1553static struct tty_operations isicom_ops = { 1553static const struct tty_operations isicom_ops = {
1554 .open = isicom_open, 1554 .open = isicom_open,
1555 .close = isicom_close, 1555 .close = isicom_close,
1556 .write = isicom_write, 1556 .write = isicom_write,
@@ -1756,9 +1756,12 @@ static int __devinit load_firmware(struct pci_dev *pdev,
1756 if (retval) 1756 if (retval)
1757 goto end; 1757 goto end;
1758 1758
1759 retval = -EIO;
1760
1759 for (frame = (struct stframe *)fw->data; 1761 for (frame = (struct stframe *)fw->data;
1760 frame < (struct stframe *)(fw->data + fw->size); 1762 frame < (struct stframe *)(fw->data + fw->size);
1761 frame++) { 1763 frame = (struct stframe *)((u8 *)(frame + 1) +
1764 frame->count)) {
1762 if (WaitTillCardIsFree(base)) 1765 if (WaitTillCardIsFree(base))
1763 goto errrelfw; 1766 goto errrelfw;
1764 1767
@@ -1797,23 +1800,12 @@ static int __devinit load_firmware(struct pci_dev *pdev,
1797 } 1800 }
1798 } 1801 }
1799 1802
1800 retval = -EIO;
1801
1802 if (WaitTillCardIsFree(base))
1803 goto errrelfw;
1804
1805 outw(0xf2, base);
1806 outw(0x800, base);
1807 outw(0x0, base);
1808 outw(0x0, base);
1809 InterruptTheCard(base);
1810 outw(0x0, base + 0x4); /* for ISI4608 cards */
1811
1812/* XXX: should we test it by reading it back and comparing with original like 1803/* XXX: should we test it by reading it back and comparing with original like
1813 * in load firmware package? */ 1804 * in load firmware package? */
1814 for (frame = (struct stframe*)fw->data; 1805 for (frame = (struct stframe *)fw->data;
1815 frame < (struct stframe*)(fw->data + fw->size); 1806 frame < (struct stframe *)(fw->data + fw->size);
1816 frame++) { 1807 frame = (struct stframe *)((u8 *)(frame + 1) +
1808 frame->count)) {
1817 if (WaitTillCardIsFree(base)) 1809 if (WaitTillCardIsFree(base))
1818 goto errrelfw; 1810 goto errrelfw;
1819 1811
@@ -1863,6 +1855,17 @@ static int __devinit load_firmware(struct pci_dev *pdev,
1863 } 1855 }
1864 } 1856 }
1865 1857
1858 /* xfer ctrl */
1859 if (WaitTillCardIsFree(base))
1860 goto errrelfw;
1861
1862 outw(0xf2, base);
1863 outw(0x800, base);
1864 outw(0x0, base);
1865 outw(0x0, base);
1866 InterruptTheCard(base);
1867 outw(0x0, base + 0x4); /* for ISI4608 cards */
1868
1866 board->status |= FIRMWARE_LOADED; 1869 board->status |= FIRMWARE_LOADED;
1867 retval = 0; 1870 retval = 0;
1868 1871
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 84dfc4278139..d6e031542c6b 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -612,16 +612,6 @@ MODULE_DEVICE_TABLE(pci, istallion_pci_tbl);
612#define MINOR2BRD(min) (((min) & 0xc0) >> 6) 612#define MINOR2BRD(min) (((min) & 0xc0) >> 6)
613#define MINOR2PORT(min) ((min) & 0x3f) 613#define MINOR2PORT(min) ((min) & 0x3f)
614 614
615/*
616 * Define a baud rate table that converts termios baud rate selector
617 * into the actual baud rate value. All baud rate calculations are based
618 * on the actual baud rate required.
619 */
620static unsigned int stli_baudrates[] = {
621 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
622 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
623};
624
625/*****************************************************************************/ 615/*****************************************************************************/
626 616
627/* 617/*
@@ -2747,15 +2737,7 @@ static void stli_mkasyport(stliport_t *portp, asyport_t *pp, struct termios *tio
2747/* 2737/*
2748 * Start of by setting the baud, char size, parity and stop bit info. 2738 * Start of by setting the baud, char size, parity and stop bit info.
2749 */ 2739 */
2750 pp->baudout = tiosp->c_cflag & CBAUD; 2740 pp->baudout = tty_get_baud_rate(portp->tty);
2751 if (pp->baudout & CBAUDEX) {
2752 pp->baudout &= ~CBAUDEX;
2753 if ((pp->baudout < 1) || (pp->baudout > 4))
2754 tiosp->c_cflag &= ~CBAUDEX;
2755 else
2756 pp->baudout += 15;
2757 }
2758 pp->baudout = stli_baudrates[pp->baudout];
2759 if ((tiosp->c_cflag & CBAUD) == B38400) { 2741 if ((tiosp->c_cflag & CBAUD) == B38400) {
2760 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) 2742 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
2761 pp->baudout = 57600; 2743 pp->baudout = 57600;
@@ -3488,7 +3470,7 @@ static int stli_initecp(stlibrd_t *brdp)
3488 */ 3470 */
3489 EBRDENABLE(brdp); 3471 EBRDENABLE(brdp);
3490 sigsp = (cdkecpsig_t __iomem *) EBRDGETMEMPTR(brdp, CDK_SIGADDR); 3472 sigsp = (cdkecpsig_t __iomem *) EBRDGETMEMPTR(brdp, CDK_SIGADDR);
3491 memcpy(&sig, sigsp, sizeof(cdkecpsig_t)); 3473 memcpy_fromio(&sig, sigsp, sizeof(cdkecpsig_t));
3492 EBRDDISABLE(brdp); 3474 EBRDDISABLE(brdp);
3493 3475
3494 if (sig.magic != cpu_to_le32(ECP_MAGIC)) 3476 if (sig.magic != cpu_to_le32(ECP_MAGIC))
@@ -4654,7 +4636,7 @@ static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un
4654 return rc; 4636 return rc;
4655} 4637}
4656 4638
4657static struct tty_operations stli_ops = { 4639static const struct tty_operations stli_ops = {
4658 .open = stli_open, 4640 .open = stli_open,
4659 .close = stli_close, 4641 .close = stli_close,
4660 .write = stli_write, 4642 .write = stli_write,
diff --git a/drivers/char/ite_gpio.c b/drivers/char/ite_gpio.c
deleted file mode 100644
index cde562d70c4f..000000000000
--- a/drivers/char/ite_gpio.c
+++ /dev/null
@@ -1,419 +0,0 @@
1/*
2 * FILE NAME ite_gpio.c
3 *
4 * BRIEF MODULE DESCRIPTION
5 * API for ITE GPIO device.
6 * Driver for ITE GPIO device.
7 *
8 * Author: MontaVista Software, Inc. <source@mvista.com>
9 * Hai-Pao Fan <haipao@mvista.com>
10 *
11 * Copyright 2001 MontaVista Software Inc.
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
17 *
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
21 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * You should have received a copy of the GNU General Public License along
30 * with this program; if not, write to the Free Software Foundation, Inc.,
31 * 675 Mass Ave, Cambridge, MA 02139, USA.
32 */
33#include <linux/module.h>
34#include <linux/types.h>
35#include <linux/kernel.h>
36#include <linux/miscdevice.h>
37#include <linux/init.h>
38#include <linux/ioport.h>
39#include <asm/uaccess.h>
40#include <asm/addrspace.h>
41#include <asm/it8172/it8172_int.h>
42#include <linux/sched.h>
43#include <linux/ite_gpio.h>
44
45#define ite_gpio_base 0x14013800
46
47#define ITE_GPADR (*(volatile __u8 *)(0x14013800 + KSEG1))
48#define ITE_GPBDR (*(volatile __u8 *)(0x14013808 + KSEG1))
49#define ITE_GPCDR (*(volatile __u8 *)(0x14013810 + KSEG1))
50#define ITE_GPACR (*(volatile __u16 *)(0x14013802 + KSEG1))
51#define ITE_GPBCR (*(volatile __u16 *)(0x1401380a + KSEG1))
52#define ITE_GPCCR (*(volatile __u16 *)(0x14013812 + KSEG1))
53#define ITE_GPAICR (*(volatile __u16 *)(0x14013804 + KSEG1))
54#define ITE_GPBICR (*(volatile __u16 *)(0x1401380c + KSEG1))
55#define ITE_GPCICR (*(volatile __u16 *)(0x14013814 + KSEG1))
56#define ITE_GPAISR (*(volatile __u8 *)(0x14013806 + KSEG1))
57#define ITE_GPBISR (*(volatile __u8 *)(0x1401380e + KSEG1))
58#define ITE_GPCISR (*(volatile __u8 *)(0x14013816 + KSEG1))
59#define ITE_GCR (*(volatile __u8 *)(0x14013818 + KSEG1))
60
61#define MAX_GPIO_LINE 21
62static int ite_gpio_irq=IT8172_GPIO_IRQ;
63
64static long ite_irq_counter[MAX_GPIO_LINE];
65wait_queue_head_t ite_gpio_wait[MAX_GPIO_LINE];
66static int ite_gpio_irq_pending[MAX_GPIO_LINE];
67
68static int ite_gpio_debug=0;
69#define DEB(x) if (ite_gpio_debug>=1) x
70
71int ite_gpio_in(__u32 device, __u32 mask, volatile __u32 *data)
72{
73 DEB(printk("ite_gpio_in mask=0x%x\n",mask));
74
75 switch (device) {
76 case ITE_GPIO_PORTA:
77 ITE_GPACR = (__u16)mask; /* 0xffff */
78 *data = ITE_GPADR;
79 break;
80 case ITE_GPIO_PORTB:
81 ITE_GPBCR = (__u16)mask; /* 0xffff */
82 *data = ITE_GPBDR;
83 break;
84 case ITE_GPIO_PORTC:
85 ITE_GPCCR = (__u16)mask; /* 0x03ff */
86 *data = ITE_GPCDR;
87 break;
88 default:
89 return -EFAULT;
90 }
91
92 return 0;
93}
94
95
96int ite_gpio_out(__u32 device, __u32 mask, __u32 data)
97{
98 switch (device) {
99 case ITE_GPIO_PORTA:
100 ITE_GPACR = (__u16)mask; /* 0x5555 */
101 ITE_GPADR = (__u8)data;
102 break;
103 case ITE_GPIO_PORTB:
104 ITE_GPBCR = (__u16)mask; /* 0x5555 */
105 ITE_GPBDR = (__u8)data;
106 break;
107 case ITE_GPIO_PORTC:
108 ITE_GPCCR = (__u16)mask; /* 0x0155 */
109 ITE_GPCDR = (__u8)data;
110 break;
111 default:
112 return -EFAULT;
113 }
114
115 return 0;
116}
117
118int ite_gpio_int_ctrl(__u32 device, __u32 mask, __u32 data)
119{
120 switch (device) {
121 case ITE_GPIO_PORTA:
122 ITE_GPAICR = (ITE_GPAICR & ~mask) | (data & mask);
123 break;
124 case ITE_GPIO_PORTB:
125 ITE_GPBICR = (ITE_GPBICR & ~mask) | (data & mask);
126 break;
127 case ITE_GPIO_PORTC:
128 ITE_GPCICR = (ITE_GPCICR & ~mask) | (data & mask);
129 break;
130 default:
131 return -EFAULT;
132 }
133
134 return 0;
135}
136
137int ite_gpio_in_status(__u32 device, __u32 mask, volatile __u32 *data)
138{
139 int ret=-1;
140
141 if ((MAX_GPIO_LINE > *data) && (*data >= 0))
142 ret=ite_gpio_irq_pending[*data];
143
144 DEB(printk("ite_gpio_in_status %d ret=%d\n",*data, ret));
145
146 switch (device) {
147 case ITE_GPIO_PORTA:
148 *data = ITE_GPAISR & mask;
149 break;
150 case ITE_GPIO_PORTB:
151 *data = ITE_GPBISR & mask;
152 break;
153 case ITE_GPIO_PORTC:
154 *data = ITE_GPCISR & mask;
155 break;
156 default:
157 return -EFAULT;
158 }
159
160 return ret;
161}
162
163int ite_gpio_out_status(__u32 device, __u32 mask, __u32 data)
164{
165 switch (device) {
166 case ITE_GPIO_PORTA:
167 ITE_GPAISR = (ITE_GPAISR & ~mask) | (data & mask);
168 break;
169 case ITE_GPIO_PORTB:
170 ITE_GPBISR = (ITE_GPBISR & ~mask) | (data & mask);
171 break;
172 case ITE_GPIO_PORTC:
173 ITE_GPCISR = (ITE_GPCISR & ~mask) | (data & mask);
174 break;
175 default:
176 return -EFAULT;
177 }
178
179 return 0;
180}
181
182int ite_gpio_gen_ctrl(__u32 device, __u32 mask, __u32 data)
183{
184 ITE_GCR = (ITE_GCR & ~mask) | (data & mask);
185
186 return 0;
187}
188
189int ite_gpio_int_wait (__u32 device, __u32 mask, __u32 data)
190{
191 int i,line=0, ret=0;
192 unsigned long flags;
193
194 switch (device) {
195 case ITE_GPIO_PORTA:
196 line = data & mask;
197 break;
198 case ITE_GPIO_PORTB:
199 line = (data & mask) <<8;
200 break;
201 case ITE_GPIO_PORTC:
202 line = (data & mask) <<16;
203 break;
204 }
205 for (i=MAX_GPIO_LINE-1; i >= 0; i--) {
206 if ( (line) & (1 << i))
207 break;
208 }
209
210 DEB(printk("wait device=0x%d mask=0x%x data=0x%x index %d\n",
211 device, mask, data, i));
212
213 if (line & ~(1<<i))
214 return -EFAULT;
215
216 if (ite_gpio_irq_pending[i]==1)
217 return -EFAULT;
218
219 save_flags (flags);
220 cli();
221 ite_gpio_irq_pending[i] = 1;
222 ret = interruptible_sleep_on_timeout(&ite_gpio_wait[i], 3*HZ);
223 restore_flags (flags);
224 ite_gpio_irq_pending[i] = 0;
225
226 return ret;
227}
228
229EXPORT_SYMBOL(ite_gpio_in);
230EXPORT_SYMBOL(ite_gpio_out);
231EXPORT_SYMBOL(ite_gpio_int_ctrl);
232EXPORT_SYMBOL(ite_gpio_in_status);
233EXPORT_SYMBOL(ite_gpio_out_status);
234EXPORT_SYMBOL(ite_gpio_gen_ctrl);
235EXPORT_SYMBOL(ite_gpio_int_wait);
236
237static int ite_gpio_open(struct inode *inode, struct file *file)
238{
239 return 0;
240}
241
242
243static int ite_gpio_release(struct inode *inode, struct file *file)
244{
245 return 0;
246}
247
248
249static int ite_gpio_ioctl(struct inode *inode, struct file *file,
250 unsigned int cmd, unsigned long arg)
251{
252 static struct ite_gpio_ioctl_data ioctl_data;
253
254 if (copy_from_user(&ioctl_data, (struct ite_gpio_ioctl_data *)arg,
255 sizeof(ioctl_data)))
256 return -EFAULT;
257 if ((ioctl_data.device < ITE_GPIO_PORTA) ||
258 (ioctl_data.device > ITE_GPIO_PORTC) )
259 return -EFAULT;
260
261 switch(cmd) {
262 case ITE_GPIO_IN:
263 if (ite_gpio_in(ioctl_data.device, ioctl_data.mask,
264 &ioctl_data.data))
265 return -EFAULT;
266
267 if (copy_to_user((struct ite_gpio_ioctl_data *)arg,
268 &ioctl_data, sizeof(ioctl_data)))
269 return -EFAULT;
270 break;
271
272 case ITE_GPIO_OUT:
273 return ite_gpio_out(ioctl_data.device,
274 ioctl_data.mask, ioctl_data.data);
275 break;
276
277 case ITE_GPIO_INT_CTRL:
278 return ite_gpio_int_ctrl(ioctl_data.device,
279 ioctl_data.mask, ioctl_data.data);
280 break;
281
282 case ITE_GPIO_IN_STATUS:
283 if (ite_gpio_in_status(ioctl_data.device, ioctl_data.mask,
284 &ioctl_data.data))
285 return -EFAULT;
286 if (copy_to_user((struct ite_gpio_ioctl_data *)arg,
287 &ioctl_data, sizeof(ioctl_data)))
288 return -EFAULT;
289 break;
290
291 case ITE_GPIO_OUT_STATUS:
292 return ite_gpio_out_status(ioctl_data.device,
293 ioctl_data.mask, ioctl_data.data);
294 break;
295
296 case ITE_GPIO_GEN_CTRL:
297 return ite_gpio_gen_ctrl(ioctl_data.device,
298 ioctl_data.mask, ioctl_data.data);
299 break;
300
301 case ITE_GPIO_INT_WAIT:
302 return ite_gpio_int_wait(ioctl_data.device,
303 ioctl_data.mask, ioctl_data.data);
304 break;
305
306 default:
307 return -ENOIOCTLCMD;
308
309 }
310
311 return 0;
312}
313
314static void ite_gpio_irq_handler(int this_irq, void *dev_id,
315 struct pt_regs *regs)
316{
317 int i,line;
318
319 line = ITE_GPCISR & 0x1f;
320 for (i=4; i >=0; i--) {
321 if ( line & (1 << i)) {
322 ++ite_irq_counter[i+16];
323 ite_gpio_irq_pending[i+16] = 2;
324 wake_up_interruptible(&ite_gpio_wait[i+16]);
325
326DEB(printk("interrupt 0x%x %d\n", &ite_gpio_wait[i+16], i+16));
327
328 ITE_GPCISR = ITE_GPCISR & (1<<i);
329 return;
330 }
331 }
332 line = ITE_GPBISR;
333 for (i=7; i >= 0; i--) {
334 if ( line & (1 << i)) {
335 ++ite_irq_counter[i+8];
336 ite_gpio_irq_pending[i+8] = 2;
337 wake_up_interruptible(&ite_gpio_wait[i+8]);
338
339DEB(printk("interrupt 0x%x %d\n",ITE_GPBISR, i+8));
340
341 ITE_GPBISR = ITE_GPBISR & (1<<i);
342 return;
343 }
344 }
345 line = ITE_GPAISR;
346 for (i=7; i >= 0; i--) {
347 if ( line & (1 << i)) {
348 ++ite_irq_counter[i];
349 ite_gpio_irq_pending[i] = 2;
350 wake_up_interruptible(&ite_gpio_wait[i]);
351
352DEB(printk("interrupt 0x%x %d\n",ITE_GPAISR, i));
353
354 ITE_GPAISR = ITE_GPAISR & (1<<i);
355 return;
356 }
357 }
358}
359
360static const struct file_operations ite_gpio_fops = {
361 .owner = THIS_MODULE,
362 .ioctl = ite_gpio_ioctl,
363 .open = ite_gpio_open,
364 .release = ite_gpio_release,
365};
366
367static struct miscdevice ite_gpio_miscdev = {
368 MISC_DYNAMIC_MINOR,
369 "ite_gpio",
370 &ite_gpio_fops
371};
372
373int __init ite_gpio_init(void)
374{
375 int i;
376
377 if (misc_register(&ite_gpio_miscdev))
378 return -ENODEV;
379
380 if (!request_region(ite_gpio_base, 0x1c, "ITE GPIO"))
381 {
382 misc_deregister(&ite_gpio_miscdev);
383 return -EIO;
384 }
385
386 /* initialize registers */
387 ITE_GPACR = 0xffff;
388 ITE_GPBCR = 0xffff;
389 ITE_GPCCR = 0xffff;
390 ITE_GPAICR = 0x00ff;
391 ITE_GPBICR = 0x00ff;
392 ITE_GPCICR = 0x00ff;
393 ITE_GCR = 0;
394
395 for (i = 0; i < MAX_GPIO_LINE; i++) {
396 ite_gpio_irq_pending[i]=0;
397 init_waitqueue_head(&ite_gpio_wait[i]);
398 }
399
400 if (request_irq(ite_gpio_irq, ite_gpio_irq_handler, IRQF_SHARED, "gpio", 0) < 0) {
401 misc_deregister(&ite_gpio_miscdev);
402 release_region(ite_gpio_base, 0x1c);
403 return 0;
404 }
405
406 printk("GPIO at 0x%x (irq = %d)\n", ite_gpio_base, ite_gpio_irq);
407
408 return 0;
409}
410
411static void __exit ite_gpio_exit(void)
412{
413 misc_deregister(&ite_gpio_miscdev);
414}
415
416module_init(ite_gpio_init);
417module_exit(ite_gpio_exit);
418
419MODULE_LICENSE("GPL");
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 3e90aac37510..e2011669c7bb 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -108,7 +108,11 @@ const int NR_TYPES = ARRAY_SIZE(max_vals);
108struct kbd_struct kbd_table[MAX_NR_CONSOLES]; 108struct kbd_struct kbd_table[MAX_NR_CONSOLES];
109static struct kbd_struct *kbd = kbd_table; 109static struct kbd_struct *kbd = kbd_table;
110 110
111int spawnpid, spawnsig; 111struct vt_spawn_console vt_spawn_con = {
112 .lock = SPIN_LOCK_UNLOCKED,
113 .pid = NULL,
114 .sig = 0,
115};
112 116
113/* 117/*
114 * Variables exported for vt.c 118 * Variables exported for vt.c
@@ -578,9 +582,13 @@ static void fn_compose(struct vc_data *vc, struct pt_regs *regs)
578 582
579static void fn_spawn_con(struct vc_data *vc, struct pt_regs *regs) 583static void fn_spawn_con(struct vc_data *vc, struct pt_regs *regs)
580{ 584{
581 if (spawnpid) 585 spin_lock(&vt_spawn_con.lock);
582 if (kill_proc(spawnpid, spawnsig, 1)) 586 if (vt_spawn_con.pid)
583 spawnpid = 0; 587 if (kill_pid(vt_spawn_con.pid, vt_spawn_con.sig, 1)) {
588 put_pid(vt_spawn_con.pid);
589 vt_spawn_con.pid = NULL;
590 }
591 spin_unlock(&vt_spawn_con.lock);
584} 592}
585 593
586static void fn_SAK(struct vc_data *vc, struct pt_regs *regs) 594static void fn_SAK(struct vc_data *vc, struct pt_regs *regs)
@@ -1285,7 +1293,7 @@ static void kbd_event(struct input_handle *handle, unsigned int event_type,
1285 */ 1293 */
1286static struct input_handle *kbd_connect(struct input_handler *handler, 1294static struct input_handle *kbd_connect(struct input_handler *handler,
1287 struct input_dev *dev, 1295 struct input_dev *dev,
1288 struct input_device_id *id) 1296 const struct input_device_id *id)
1289{ 1297{
1290 struct input_handle *handle; 1298 struct input_handle *handle;
1291 int i; 1299 int i;
@@ -1334,7 +1342,7 @@ static void kbd_start(struct input_handle *handle)
1334 tasklet_enable(&keyboard_tasklet); 1342 tasklet_enable(&keyboard_tasklet);
1335} 1343}
1336 1344
1337static struct input_device_id kbd_ids[] = { 1345static const struct input_device_id kbd_ids[] = {
1338 { 1346 {
1339 .flags = INPUT_DEVICE_ID_MATCH_EVBIT, 1347 .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
1340 .evbit = { BIT(EV_KEY) }, 1348 .evbit = { BIT(EV_KEY) },
@@ -1362,6 +1370,7 @@ static struct input_handler kbd_handler = {
1362int __init kbd_init(void) 1370int __init kbd_init(void)
1363{ 1371{
1364 int i; 1372 int i;
1373 int error;
1365 1374
1366 for (i = 0; i < MAX_NR_CONSOLES; i++) { 1375 for (i = 0; i < MAX_NR_CONSOLES; i++) {
1367 kbd_table[i].ledflagstate = KBD_DEFLEDS; 1376 kbd_table[i].ledflagstate = KBD_DEFLEDS;
@@ -1373,7 +1382,9 @@ int __init kbd_init(void)
1373 kbd_table[i].kbdmode = VC_XLATE; 1382 kbd_table[i].kbdmode = VC_XLATE;
1374 } 1383 }
1375 1384
1376 input_register_handler(&kbd_handler); 1385 error = input_register_handler(&kbd_handler);
1386 if (error)
1387 return error;
1377 1388
1378 tasklet_enable(&keyboard_tasklet); 1389 tasklet_enable(&keyboard_tasklet);
1379 tasklet_schedule(&keyboard_tasklet); 1390 tasklet_schedule(&keyboard_tasklet);
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index f875fda3b089..1ecea7d448f1 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -906,7 +906,7 @@ static int __init lp_init (void)
906 lp_class = class_create(THIS_MODULE, "printer"); 906 lp_class = class_create(THIS_MODULE, "printer");
907 if (IS_ERR(lp_class)) { 907 if (IS_ERR(lp_class)) {
908 err = PTR_ERR(lp_class); 908 err = PTR_ERR(lp_class);
909 goto out_devfs; 909 goto out_reg;
910 } 910 }
911 911
912 if (parport_register_driver (&lp_driver)) { 912 if (parport_register_driver (&lp_driver)) {
@@ -927,7 +927,7 @@ static int __init lp_init (void)
927 927
928out_class: 928out_class:
929 class_destroy(lp_class); 929 class_destroy(lp_class);
930out_devfs: 930out_reg:
931 unregister_chrdev(LP_MAJOR, "lp"); 931 unregister_chrdev(LP_MAJOR, "lp");
932 return err; 932 return err;
933} 933}
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c
index 0385650f6077..636354722658 100644
--- a/drivers/char/mbcs.c
+++ b/drivers/char/mbcs.c
@@ -22,6 +22,7 @@
22#include <linux/delay.h> 22#include <linux/delay.h>
23#include <linux/device.h> 23#include <linux/device.h>
24#include <linux/mm.h> 24#include <linux/mm.h>
25#include <linux/fs.h>
25#include <linux/uio.h> 26#include <linux/uio.h>
26#include <asm/io.h> 27#include <asm/io.h>
27#include <asm/uaccess.h> 28#include <asm/uaccess.h>
@@ -447,15 +448,15 @@ loff_t mbcs_sram_llseek(struct file * filp, loff_t off, int whence)
447 loff_t newpos; 448 loff_t newpos;
448 449
449 switch (whence) { 450 switch (whence) {
450 case 0: /* SEEK_SET */ 451 case SEEK_SET:
451 newpos = off; 452 newpos = off;
452 break; 453 break;
453 454
454 case 1: /* SEEK_CUR */ 455 case SEEK_CUR:
455 newpos = filp->f_pos + off; 456 newpos = filp->f_pos + off;
456 break; 457 break;
457 458
458 case 2: /* SEEK_END */ 459 case SEEK_END:
459 newpos = MBCS_SRAM_SIZE + off; 460 newpos = MBCS_SRAM_SIZE + off;
460 break; 461 break;
461 462
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 917b20402664..6511012cbdcd 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -238,6 +238,32 @@ static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
238} 238}
239#endif 239#endif
240 240
241#ifndef CONFIG_MMU
242static unsigned long get_unmapped_area_mem(struct file *file,
243 unsigned long addr,
244 unsigned long len,
245 unsigned long pgoff,
246 unsigned long flags)
247{
248 if (!valid_mmap_phys_addr_range(pgoff, len))
249 return (unsigned long) -EINVAL;
250 return pgoff;
251}
252
253/* can't do an in-place private mapping if there's no MMU */
254static inline int private_mapping_ok(struct vm_area_struct *vma)
255{
256 return vma->vm_flags & VM_MAYSHARE;
257}
258#else
259#define get_unmapped_area_mem NULL
260
261static inline int private_mapping_ok(struct vm_area_struct *vma)
262{
263 return 1;
264}
265#endif
266
241static int mmap_mem(struct file * file, struct vm_area_struct * vma) 267static int mmap_mem(struct file * file, struct vm_area_struct * vma)
242{ 268{
243 size_t size = vma->vm_end - vma->vm_start; 269 size_t size = vma->vm_end - vma->vm_start;
@@ -245,6 +271,9 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
245 if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size)) 271 if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size))
246 return -EINVAL; 272 return -EINVAL;
247 273
274 if (!private_mapping_ok(vma))
275 return -ENOSYS;
276
248 vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff, 277 vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
249 size, 278 size,
250 vma->vm_page_prot); 279 vma->vm_page_prot);
@@ -522,7 +551,7 @@ static ssize_t write_kmem(struct file * file, const char __user * buf,
522 return virtr + wrote; 551 return virtr + wrote;
523} 552}
524 553
525#if defined(CONFIG_ISA) || !defined(__mc68000__) 554#if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__)
526static ssize_t read_port(struct file * file, char __user * buf, 555static ssize_t read_port(struct file * file, char __user * buf,
527 size_t count, loff_t *ppos) 556 size_t count, loff_t *ppos)
528{ 557{
@@ -782,6 +811,7 @@ static const struct file_operations mem_fops = {
782 .write = write_mem, 811 .write = write_mem,
783 .mmap = mmap_mem, 812 .mmap = mmap_mem,
784 .open = open_mem, 813 .open = open_mem,
814 .get_unmapped_area = get_unmapped_area_mem,
785}; 815};
786 816
787static const struct file_operations kmem_fops = { 817static const struct file_operations kmem_fops = {
@@ -790,6 +820,7 @@ static const struct file_operations kmem_fops = {
790 .write = write_kmem, 820 .write = write_kmem,
791 .mmap = mmap_kmem, 821 .mmap = mmap_kmem,
792 .open = open_kmem, 822 .open = open_kmem,
823 .get_unmapped_area = get_unmapped_area_mem,
793}; 824};
794 825
795static const struct file_operations null_fops = { 826static const struct file_operations null_fops = {
@@ -799,7 +830,7 @@ static const struct file_operations null_fops = {
799 .splice_write = splice_write_null, 830 .splice_write = splice_write_null,
800}; 831};
801 832
802#if defined(CONFIG_ISA) || !defined(__mc68000__) 833#if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__)
803static const struct file_operations port_fops = { 834static const struct file_operations port_fops = {
804 .llseek = memory_lseek, 835 .llseek = memory_lseek,
805 .read = read_port, 836 .read = read_port,
@@ -815,6 +846,10 @@ static const struct file_operations zero_fops = {
815 .mmap = mmap_zero, 846 .mmap = mmap_zero,
816}; 847};
817 848
849/*
850 * capabilities for /dev/zero
851 * - permits private mappings, "copies" are taken of the source of zeros
852 */
818static struct backing_dev_info zero_bdi = { 853static struct backing_dev_info zero_bdi = {
819 .capabilities = BDI_CAP_MAP_COPY, 854 .capabilities = BDI_CAP_MAP_COPY,
820}; 855};
@@ -862,14 +897,18 @@ static int memory_open(struct inode * inode, struct file * filp)
862 switch (iminor(inode)) { 897 switch (iminor(inode)) {
863 case 1: 898 case 1:
864 filp->f_op = &mem_fops; 899 filp->f_op = &mem_fops;
900 filp->f_mapping->backing_dev_info =
901 &directly_mappable_cdev_bdi;
865 break; 902 break;
866 case 2: 903 case 2:
867 filp->f_op = &kmem_fops; 904 filp->f_op = &kmem_fops;
905 filp->f_mapping->backing_dev_info =
906 &directly_mappable_cdev_bdi;
868 break; 907 break;
869 case 3: 908 case 3:
870 filp->f_op = &null_fops; 909 filp->f_op = &null_fops;
871 break; 910 break;
872#if defined(CONFIG_ISA) || !defined(__mc68000__) 911#if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__)
873 case 4: 912 case 4:
874 filp->f_op = &port_fops; 913 filp->f_op = &port_fops;
875 break; 914 break;
@@ -916,7 +955,7 @@ static const struct {
916 {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops}, 955 {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops},
917 {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops}, 956 {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops},
918 {3, "null", S_IRUGO | S_IWUGO, &null_fops}, 957 {3, "null", S_IRUGO | S_IWUGO, &null_fops},
919#if defined(CONFIG_ISA) || !defined(__mc68000__) 958#if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__)
920 {4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops}, 959 {4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops},
921#endif 960#endif
922 {5, "zero", S_IRUGO | S_IWUGO, &zero_fops}, 961 {5, "zero", S_IRUGO | S_IWUGO, &zero_fops},
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index a369dd6877d8..b401383808c2 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -260,7 +260,7 @@ static void MoxaPortEnable(int);
260static void MoxaPortDisable(int); 260static void MoxaPortDisable(int);
261static long MoxaPortGetMaxBaud(int); 261static long MoxaPortGetMaxBaud(int);
262static long MoxaPortSetBaud(int, long); 262static long MoxaPortSetBaud(int, long);
263static int MoxaPortSetTermio(int, struct termios *); 263static int MoxaPortSetTermio(int, struct termios *, speed_t);
264static int MoxaPortGetLineOut(int, int *, int *); 264static int MoxaPortGetLineOut(int, int *, int *);
265static void MoxaPortLineCtrl(int, int, int); 265static void MoxaPortLineCtrl(int, int, int);
266static void MoxaPortFlowCtrl(int, int, int, int, int, int); 266static void MoxaPortFlowCtrl(int, int, int, int, int, int);
@@ -281,7 +281,7 @@ static int moxa_get_serial_info(struct moxa_str *, struct serial_struct __user *
281static int moxa_set_serial_info(struct moxa_str *, struct serial_struct __user *); 281static int moxa_set_serial_info(struct moxa_str *, struct serial_struct __user *);
282static void MoxaSetFifo(int port, int enable); 282static void MoxaSetFifo(int port, int enable);
283 283
284static struct tty_operations moxa_ops = { 284static const struct tty_operations moxa_ops = {
285 .open = moxa_open, 285 .open = moxa_open,
286 .close = moxa_close, 286 .close = moxa_close,
287 .write = moxa_write, 287 .write = moxa_write,
@@ -986,7 +986,7 @@ static void set_tty_param(struct tty_struct *tty)
986 if (ts->c_iflag & IXANY) 986 if (ts->c_iflag & IXANY)
987 xany = 1; 987 xany = 1;
988 MoxaPortFlowCtrl(ch->port, rts, cts, txflow, rxflow, xany); 988 MoxaPortFlowCtrl(ch->port, rts, cts, txflow, rxflow, xany);
989 MoxaPortSetTermio(ch->port, ts); 989 MoxaPortSetTermio(ch->port, ts, tty_get_baud_rate(tty));
990} 990}
991 991
992static int block_till_ready(struct tty_struct *tty, struct file *filp, 992static int block_till_ready(struct tty_struct *tty, struct file *filp,
@@ -1900,9 +1900,10 @@ int MoxaPortsOfCard(int cardno)
1900 * 1900 *
1901 * Function 12: Configure the port. 1901 * Function 12: Configure the port.
1902 * Syntax: 1902 * Syntax:
1903 * int MoxaPortSetTermio(int port, struct termios *termio); 1903 * int MoxaPortSetTermio(int port, struct termios *termio, speed_t baud);
1904 * int port : port number (0 - 127) 1904 * int port : port number (0 - 127)
1905 * struct termios * termio : termio structure pointer 1905 * struct termios * termio : termio structure pointer
1906 * speed_t baud : baud rate
1906 * 1907 *
1907 * return: -1 : this port is invalid or termio == NULL 1908 * return: -1 : this port is invalid or termio == NULL
1908 * 0 : setting O.K. 1909 * 0 : setting O.K.
@@ -2182,11 +2183,10 @@ long MoxaPortSetBaud(int port, long baud)
2182 return (baud); 2183 return (baud);
2183} 2184}
2184 2185
2185int MoxaPortSetTermio(int port, struct termios *termio) 2186int MoxaPortSetTermio(int port, struct termios *termio, speed_t baud)
2186{ 2187{
2187 void __iomem *ofsAddr; 2188 void __iomem *ofsAddr;
2188 tcflag_t cflag; 2189 tcflag_t cflag;
2189 long baud;
2190 tcflag_t mode = 0; 2190 tcflag_t mode = 0;
2191 2191
2192 if (moxaChkPort[port] == 0 || termio == 0) 2192 if (moxaChkPort[port] == 0 || termio == 0)
@@ -2222,77 +2222,9 @@ int MoxaPortSetTermio(int port, struct termios *termio)
2222 2222
2223 moxafunc(ofsAddr, FC_SetDataMode, (ushort) mode); 2223 moxafunc(ofsAddr, FC_SetDataMode, (ushort) mode);
2224 2224
2225 cflag &= (CBAUD | CBAUDEX);
2226#ifndef B921600
2227#define B921600 (B460800+1)
2228#endif
2229 switch (cflag) {
2230 case B921600:
2231 baud = 921600L;
2232 break;
2233 case B460800:
2234 baud = 460800L;
2235 break;
2236 case B230400:
2237 baud = 230400L;
2238 break;
2239 case B115200:
2240 baud = 115200L;
2241 break;
2242 case B57600:
2243 baud = 57600L;
2244 break;
2245 case B38400:
2246 baud = 38400L;
2247 break;
2248 case B19200:
2249 baud = 19200L;
2250 break;
2251 case B9600:
2252 baud = 9600L;
2253 break;
2254 case B4800:
2255 baud = 4800L;
2256 break;
2257 case B2400:
2258 baud = 2400L;
2259 break;
2260 case B1800:
2261 baud = 1800L;
2262 break;
2263 case B1200:
2264 baud = 1200L;
2265 break;
2266 case B600:
2267 baud = 600L;
2268 break;
2269 case B300:
2270 baud = 300L;
2271 break;
2272 case B200:
2273 baud = 200L;
2274 break;
2275 case B150:
2276 baud = 150L;
2277 break;
2278 case B134:
2279 baud = 134L;
2280 break;
2281 case B110:
2282 baud = 110L;
2283 break;
2284 case B75:
2285 baud = 75L;
2286 break;
2287 case B50:
2288 baud = 50L;
2289 break;
2290 default:
2291 baud = 0;
2292 }
2293 if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) || 2225 if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
2294 (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) { 2226 (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
2295 if (baud == 921600L) 2227 if (baud >= 921600L)
2296 return (-1); 2228 return (-1);
2297 } 2229 }
2298 MoxaPortSetBaud(port, baud); 2230 MoxaPortSetBaud(port, baud);
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c
new file mode 100644
index 000000000000..5426b1e5595f
--- /dev/null
+++ b/drivers/char/mspec.c
@@ -0,0 +1,421 @@
1/*
2 * Copyright (C) 2001-2006 Silicon Graphics, Inc. All rights
3 * reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License
7 * as published by the Free Software Foundation.
8 */
9
10/*
11 * SN Platform Special Memory (mspec) Support
12 *
13 * This driver exports the SN special memory (mspec) facility to user
14 * processes.
15 * There are three types of memory made available thru this driver:
16 * fetchops, uncached and cached.
17 *
18 * Fetchops are atomic memory operations that are implemented in the
19 * memory controller on SGI SN hardware.
20 *
21 * Uncached are used for memory write combining feature of the ia64
22 * cpu.
23 *
24 * Cached are used for areas of memory that are used as cached addresses
25 * on our partition and used as uncached addresses from other partitions.
26 * Due to a design constraint of the SN2 Shub, you can not have processors
27 * on the same FSB perform both a cached and uncached reference to the
28 * same cache line. These special memory cached regions prevent the
29 * kernel from ever dropping in a TLB entry and therefore prevent the
30 * processor from ever speculating a cache line from this page.
31 */
32
33#include <linux/config.h>
34#include <linux/types.h>
35#include <linux/kernel.h>
36#include <linux/module.h>
37#include <linux/init.h>
38#include <linux/errno.h>
39#include <linux/miscdevice.h>
40#include <linux/spinlock.h>
41#include <linux/mm.h>
42#include <linux/vmalloc.h>
43#include <linux/string.h>
44#include <linux/slab.h>
45#include <linux/numa.h>
46#include <asm/page.h>
47#include <asm/system.h>
48#include <asm/pgtable.h>
49#include <asm/atomic.h>
50#include <asm/tlbflush.h>
51#include <asm/uncached.h>
52#include <asm/sn/addrs.h>
53#include <asm/sn/arch.h>
54#include <asm/sn/mspec.h>
55#include <asm/sn/sn_cpuid.h>
56#include <asm/sn/io.h>
57#include <asm/sn/bte.h>
58#include <asm/sn/shubio.h>
59
60
61#define FETCHOP_ID "SGI Fetchop,"
62#define CACHED_ID "Cached,"
63#define UNCACHED_ID "Uncached"
64#define REVISION "4.0"
65#define MSPEC_BASENAME "mspec"
66
67/*
68 * Page types allocated by the device.
69 */
70enum {
71 MSPEC_FETCHOP = 1,
72 MSPEC_CACHED,
73 MSPEC_UNCACHED
74};
75
76static int is_sn2;
77
78/*
79 * One of these structures is allocated when an mspec region is mmaped. The
80 * structure is pointed to by the vma->vm_private_data field in the vma struct.
81 * This structure is used to record the addresses of the mspec pages.
82 */
83struct vma_data {
84 atomic_t refcnt; /* Number of vmas sharing the data. */
85 spinlock_t lock; /* Serialize access to the vma. */
86 int count; /* Number of pages allocated. */
87 int type; /* Type of pages allocated. */
88 unsigned long maddr[0]; /* Array of MSPEC addresses. */
89};
90
91/* used on shub2 to clear FOP cache in the HUB */
92static unsigned long scratch_page[MAX_NUMNODES];
93#define SH2_AMO_CACHE_ENTRIES 4
94
95static inline int
96mspec_zero_block(unsigned long addr, int len)
97{
98 int status;
99
100 if (is_sn2) {
101 if (is_shub2()) {
102 int nid;
103 void *p;
104 int i;
105
106 nid = nasid_to_cnodeid(get_node_number(__pa(addr)));
107 p = (void *)TO_AMO(scratch_page[nid]);
108
109 for (i=0; i < SH2_AMO_CACHE_ENTRIES; i++) {
110 FETCHOP_LOAD_OP(p, FETCHOP_LOAD);
111 p += FETCHOP_VAR_SIZE;
112 }
113 }
114
115 status = bte_copy(0, addr & ~__IA64_UNCACHED_OFFSET, len,
116 BTE_WACQUIRE | BTE_ZERO_FILL, NULL);
117 } else {
118 memset((char *) addr, 0, len);
119 status = 0;
120 }
121 return status;
122}
123
124/*
125 * mspec_open
126 *
127 * Called when a device mapping is created by a means other than mmap
128 * (via fork, etc.). Increments the reference count on the underlying
129 * mspec data so it is not freed prematurely.
130 */
131static void
132mspec_open(struct vm_area_struct *vma)
133{
134 struct vma_data *vdata;
135
136 vdata = vma->vm_private_data;
137 atomic_inc(&vdata->refcnt);
138}
139
140/*
141 * mspec_close
142 *
143 * Called when unmapping a device mapping. Frees all mspec pages
144 * belonging to the vma.
145 */
146static void
147mspec_close(struct vm_area_struct *vma)
148{
149 struct vma_data *vdata;
150 int i, pages, result, vdata_size;
151
152 vdata = vma->vm_private_data;
153 if (!atomic_dec_and_test(&vdata->refcnt))
154 return;
155
156 pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
157 vdata_size = sizeof(struct vma_data) + pages * sizeof(long);
158 for (i = 0; i < pages; i++) {
159 if (vdata->maddr[i] == 0)
160 continue;
161 /*
162 * Clear the page before sticking it back
163 * into the pool.
164 */
165 result = mspec_zero_block(vdata->maddr[i], PAGE_SIZE);
166 if (!result)
167 uncached_free_page(vdata->maddr[i]);
168 else
169 printk(KERN_WARNING "mspec_close(): "
170 "failed to zero page %i\n",
171 result);
172 }
173
174 if (vdata_size <= PAGE_SIZE)
175 kfree(vdata);
176 else
177 vfree(vdata);
178}
179
180
181/*
182 * mspec_nopfn
183 *
184 * Creates a mspec page and maps it to user space.
185 */
186static unsigned long
187mspec_nopfn(struct vm_area_struct *vma, unsigned long address)
188{
189 unsigned long paddr, maddr;
190 unsigned long pfn;
191 int index;
192 struct vma_data *vdata = vma->vm_private_data;
193
194 index = (address - vma->vm_start) >> PAGE_SHIFT;
195 maddr = (volatile unsigned long) vdata->maddr[index];
196 if (maddr == 0) {
197 maddr = uncached_alloc_page(numa_node_id());
198 if (maddr == 0)
199 return NOPFN_OOM;
200
201 spin_lock(&vdata->lock);
202 if (vdata->maddr[index] == 0) {
203 vdata->count++;
204 vdata->maddr[index] = maddr;
205 } else {
206 uncached_free_page(maddr);
207 maddr = vdata->maddr[index];
208 }
209 spin_unlock(&vdata->lock);
210 }
211
212 if (vdata->type == MSPEC_FETCHOP)
213 paddr = TO_AMO(maddr);
214 else
215 paddr = __pa(TO_CAC(maddr));
216
217 pfn = paddr >> PAGE_SHIFT;
218
219 return pfn;
220}
221
222static struct vm_operations_struct mspec_vm_ops = {
223 .open = mspec_open,
224 .close = mspec_close,
225 .nopfn = mspec_nopfn
226};
227
228/*
229 * mspec_mmap
230 *
231 * Called when mmaping the device. Initializes the vma with a fault handler
232 * and private data structure necessary to allocate, track, and free the
233 * underlying pages.
234 */
235static int
236mspec_mmap(struct file *file, struct vm_area_struct *vma, int type)
237{
238 struct vma_data *vdata;
239 int pages, vdata_size;
240
241 if (vma->vm_pgoff != 0)
242 return -EINVAL;
243
244 if ((vma->vm_flags & VM_SHARED) == 0)
245 return -EINVAL;
246
247 if ((vma->vm_flags & VM_WRITE) == 0)
248 return -EPERM;
249
250 pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
251 vdata_size = sizeof(struct vma_data) + pages * sizeof(long);
252 if (vdata_size <= PAGE_SIZE)
253 vdata = kmalloc(vdata_size, GFP_KERNEL);
254 else
255 vdata = vmalloc(vdata_size);
256 if (!vdata)
257 return -ENOMEM;
258 memset(vdata, 0, vdata_size);
259
260 vdata->type = type;
261 spin_lock_init(&vdata->lock);
262 vdata->refcnt = ATOMIC_INIT(1);
263 vma->vm_private_data = vdata;
264
265 vma->vm_flags |= (VM_IO | VM_LOCKED | VM_RESERVED | VM_PFNMAP);
266 if (vdata->type == MSPEC_FETCHOP || vdata->type == MSPEC_UNCACHED)
267 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
268 vma->vm_ops = &mspec_vm_ops;
269
270 return 0;
271}
272
273static int
274fetchop_mmap(struct file *file, struct vm_area_struct *vma)
275{
276 return mspec_mmap(file, vma, MSPEC_FETCHOP);
277}
278
279static int
280cached_mmap(struct file *file, struct vm_area_struct *vma)
281{
282 return mspec_mmap(file, vma, MSPEC_CACHED);
283}
284
285static int
286uncached_mmap(struct file *file, struct vm_area_struct *vma)
287{
288 return mspec_mmap(file, vma, MSPEC_UNCACHED);
289}
290
291static struct file_operations fetchop_fops = {
292 .owner = THIS_MODULE,
293 .mmap = fetchop_mmap
294};
295
296static struct miscdevice fetchop_miscdev = {
297 .minor = MISC_DYNAMIC_MINOR,
298 .name = "sgi_fetchop",
299 .fops = &fetchop_fops
300};
301
302static struct file_operations cached_fops = {
303 .owner = THIS_MODULE,
304 .mmap = cached_mmap
305};
306
307static struct miscdevice cached_miscdev = {
308 .minor = MISC_DYNAMIC_MINOR,
309 .name = "mspec_cached",
310 .fops = &cached_fops
311};
312
313static struct file_operations uncached_fops = {
314 .owner = THIS_MODULE,
315 .mmap = uncached_mmap
316};
317
318static struct miscdevice uncached_miscdev = {
319 .minor = MISC_DYNAMIC_MINOR,
320 .name = "mspec_uncached",
321 .fops = &uncached_fops
322};
323
324/*
325 * mspec_init
326 *
327 * Called at boot time to initialize the mspec facility.
328 */
329static int __init
330mspec_init(void)
331{
332 int ret;
333 int nid;
334
335 /*
336 * The fetchop device only works on SN2 hardware, uncached and cached
337 * memory drivers should both be valid on all ia64 hardware
338 */
339 if (ia64_platform_is("sn2")) {
340 is_sn2 = 1;
341 if (is_shub2()) {
342 ret = -ENOMEM;
343 for_each_online_node(nid) {
344 int actual_nid;
345 int nasid;
346 unsigned long phys;
347
348 scratch_page[nid] = uncached_alloc_page(nid);
349 if (scratch_page[nid] == 0)
350 goto free_scratch_pages;
351 phys = __pa(scratch_page[nid]);
352 nasid = get_node_number(phys);
353 actual_nid = nasid_to_cnodeid(nasid);
354 if (actual_nid != nid)
355 goto free_scratch_pages;
356 }
357 }
358
359 ret = misc_register(&fetchop_miscdev);
360 if (ret) {
361 printk(KERN_ERR
362 "%s: failed to register device %i\n",
363 FETCHOP_ID, ret);
364 goto free_scratch_pages;
365 }
366 }
367 ret = misc_register(&cached_miscdev);
368 if (ret) {
369 printk(KERN_ERR "%s: failed to register device %i\n",
370 CACHED_ID, ret);
371 if (is_sn2)
372 misc_deregister(&fetchop_miscdev);
373 goto free_scratch_pages;
374 }
375 ret = misc_register(&uncached_miscdev);
376 if (ret) {
377 printk(KERN_ERR "%s: failed to register device %i\n",
378 UNCACHED_ID, ret);
379 misc_deregister(&cached_miscdev);
380 if (is_sn2)
381 misc_deregister(&fetchop_miscdev);
382 goto free_scratch_pages;
383 }
384
385 printk(KERN_INFO "%s %s initialized devices: %s %s %s\n",
386 MSPEC_BASENAME, REVISION, is_sn2 ? FETCHOP_ID : "",
387 CACHED_ID, UNCACHED_ID);
388
389 return 0;
390
391 free_scratch_pages:
392 for_each_node(nid) {
393 if (scratch_page[nid] != 0)
394 uncached_free_page(scratch_page[nid]);
395 }
396 return ret;
397}
398
399static void __exit
400mspec_exit(void)
401{
402 int nid;
403
404 misc_deregister(&uncached_miscdev);
405 misc_deregister(&cached_miscdev);
406 if (is_sn2) {
407 misc_deregister(&fetchop_miscdev);
408
409 for_each_node(nid) {
410 if (scratch_page[nid] != 0)
411 uncached_free_page(scratch_page[nid]);
412 }
413 }
414}
415
416module_init(mspec_init);
417module_exit(mspec_exit);
418
419MODULE_AUTHOR("Silicon Graphics, Inc. <linux-altix@sgi.com>");
420MODULE_DESCRIPTION("Driver for SGI SN special memory operations");
421MODULE_LICENSE("GPL");
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c
index 39a2e661ff55..8d14823b0514 100644
--- a/drivers/char/mwave/mwavedd.c
+++ b/drivers/char/mwave/mwavedd.c
@@ -297,7 +297,7 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
297 " ipcnum %x, usIntCount %x\n", 297 " ipcnum %x, usIntCount %x\n",
298 ipcnum, 298 ipcnum,
299 pDrvData->IPCs[ipcnum].usIntCount); 299 pDrvData->IPCs[ipcnum].usIntCount);
300 if (ipcnum > ARRAY_SIZE(pDrvData->IPCs)) { 300 if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) {
301 PRINTK_ERROR(KERN_ERR_MWAVE 301 PRINTK_ERROR(KERN_ERR_MWAVE
302 "mwavedd::mwave_ioctl:" 302 "mwavedd::mwave_ioctl:"
303 " IOCTL_MW_GET_IPC: Error:" 303 " IOCTL_MW_GET_IPC: Error:"
@@ -355,7 +355,7 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
355 "mwavedd::mwave_ioctl IOCTL_MW_UNREGISTER_IPC" 355 "mwavedd::mwave_ioctl IOCTL_MW_UNREGISTER_IPC"
356 " ipcnum %x\n", 356 " ipcnum %x\n",
357 ipcnum); 357 ipcnum);
358 if (ipcnum > ARRAY_SIZE(pDrvData->IPCs)) { 358 if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) {
359 PRINTK_ERROR(KERN_ERR_MWAVE 359 PRINTK_ERROR(KERN_ERR_MWAVE
360 "mwavedd::mwave_ioctl:" 360 "mwavedd::mwave_ioctl:"
361 " IOCTL_MW_UNREGISTER_IPC:" 361 " IOCTL_MW_UNREGISTER_IPC:"
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 556abd3e0d07..8253fca8efd5 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -453,7 +453,7 @@ static int CheckIsMoxaMust(int io)
453 453
454/* above is modified by Victor Yu. 08-15-2002 */ 454/* above is modified by Victor Yu. 08-15-2002 */
455 455
456static struct tty_operations mxser_ops = { 456static const struct tty_operations mxser_ops = {
457 .open = mxser_open, 457 .open = mxser_open,
458 .close = mxser_close, 458 .close = mxser_close,
459 .write = mxser_write, 459 .write = mxser_write,
@@ -2554,71 +2554,7 @@ static int mxser_change_speed(struct mxser_struct *info, struct termios *old_ter
2554#define B921600 (B460800 +1) 2554#define B921600 (B460800 +1)
2555#endif 2555#endif
2556 if (mxser_set_baud_method[info->port] == 0) { 2556 if (mxser_set_baud_method[info->port] == 0) {
2557 switch (cflag & (CBAUD | CBAUDEX)) { 2557 baud = tty_get_baud_rate(info->tty);
2558 case B921600:
2559 baud = 921600;
2560 break;
2561 case B460800:
2562 baud = 460800;
2563 break;
2564 case B230400:
2565 baud = 230400;
2566 break;
2567 case B115200:
2568 baud = 115200;
2569 break;
2570 case B57600:
2571 baud = 57600;
2572 break;
2573 case B38400:
2574 baud = 38400;
2575 break;
2576 case B19200:
2577 baud = 19200;
2578 break;
2579 case B9600:
2580 baud = 9600;
2581 break;
2582 case B4800:
2583 baud = 4800;
2584 break;
2585 case B2400:
2586 baud = 2400;
2587 break;
2588 case B1800:
2589 baud = 1800;
2590 break;
2591 case B1200:
2592 baud = 1200;
2593 break;
2594 case B600:
2595 baud = 600;
2596 break;
2597 case B300:
2598 baud = 300;
2599 break;
2600 case B200:
2601 baud = 200;
2602 break;
2603 case B150:
2604 baud = 150;
2605 break;
2606 case B134:
2607 baud = 134;
2608 break;
2609 case B110:
2610 baud = 110;
2611 break;
2612 case B75:
2613 baud = 75;
2614 break;
2615 case B50:
2616 baud = 50;
2617 break;
2618 default:
2619 baud = 0;
2620 break;
2621 }
2622 mxser_set_baud(info, baud); 2558 mxser_set_baud(info, baud);
2623 } 2559 }
2624 2560
diff --git a/drivers/char/nwbutton.c b/drivers/char/nwbutton.c
index 7c57ebfa8640..ea1aa7764f8e 100644
--- a/drivers/char/nwbutton.c
+++ b/drivers/char/nwbutton.c
@@ -127,9 +127,8 @@ static void button_consume_callbacks (int bpcount)
127static void button_sequence_finished (unsigned long parameters) 127static void button_sequence_finished (unsigned long parameters)
128{ 128{
129#ifdef CONFIG_NWBUTTON_REBOOT /* Reboot using button is enabled */ 129#ifdef CONFIG_NWBUTTON_REBOOT /* Reboot using button is enabled */
130 if (button_press_count == reboot_count) { 130 if (button_press_count == reboot_count)
131 kill_proc (1, SIGINT, 1); /* Ask init to reboot us */ 131 kill_cad_pid(SIGINT, 1); /* Ask init to reboot us */
132 }
133#endif /* CONFIG_NWBUTTON_REBOOT */ 132#endif /* CONFIG_NWBUTTON_REBOOT */
134 button_consume_callbacks (button_press_count); 133 button_consume_callbacks (button_press_count);
135 bcount = sprintf (button_output_buffer, "%d\n", button_press_count); 134 bcount = sprintf (button_output_buffer, "%d\n", button_press_count);
diff --git a/drivers/char/pc8736x_gpio.c b/drivers/char/pc8736x_gpio.c
index 84e5a68635f1..ecfaf180e5bd 100644
--- a/drivers/char/pc8736x_gpio.c
+++ b/drivers/char/pc8736x_gpio.c
@@ -188,16 +188,6 @@ static void pc8736x_gpio_set(unsigned minor, int val)
188 pc8736x_gpio_shadow[port] = val; 188 pc8736x_gpio_shadow[port] = val;
189} 189}
190 190
191static void pc8736x_gpio_set_high(unsigned index)
192{
193 pc8736x_gpio_set(index, 1);
194}
195
196static void pc8736x_gpio_set_low(unsigned index)
197{
198 pc8736x_gpio_set(index, 0);
199}
200
201static int pc8736x_gpio_current(unsigned minor) 191static int pc8736x_gpio_current(unsigned minor)
202{ 192{
203 int port, bit; 193 int port, bit;
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 00f574cbb0d4..d1ecb2c6de98 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -57,7 +57,6 @@
57#include <linux/netdevice.h> 57#include <linux/netdevice.h>
58#include <linux/vmalloc.h> 58#include <linux/vmalloc.h>
59#include <linux/init.h> 59#include <linux/init.h>
60#include <asm/serial.h>
61#include <linux/delay.h> 60#include <linux/delay.h>
62#include <linux/ioctl.h> 61#include <linux/ioctl.h>
63 62
@@ -3010,7 +3009,7 @@ static struct pcmcia_driver mgslpc_driver = {
3010 .resume = mgslpc_resume, 3009 .resume = mgslpc_resume,
3011}; 3010};
3012 3011
3013static struct tty_operations mgslpc_ops = { 3012static const struct tty_operations mgslpc_ops = {
3014 .open = mgslpc_open, 3013 .open = mgslpc_open,
3015 .close = mgslpc_close, 3014 .close = mgslpc_close,
3016 .write = mgslpc_write, 3015 .write = mgslpc_write,
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index 34dd4c38110e..80d3eedd7f96 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -224,7 +224,7 @@ static void pty_set_termios(struct tty_struct *tty, struct termios *old_termios)
224 tty->termios->c_cflag |= (CS8 | CREAD); 224 tty->termios->c_cflag |= (CS8 | CREAD);
225} 225}
226 226
227static struct tty_operations pty_ops = { 227static const struct tty_operations pty_ops = {
228 .open = pty_open, 228 .open = pty_open,
229 .close = pty_close, 229 .close = pty_close,
230 .write = pty_write, 230 .write = pty_write,
diff --git a/drivers/char/qtronixmap.c_shipped b/drivers/char/qtronixmap.c_shipped
deleted file mode 100644
index 1e2b92b7d57a..000000000000
--- a/drivers/char/qtronixmap.c_shipped
+++ /dev/null
@@ -1,265 +0,0 @@
1
2/* Do not edit this file! It was automatically generated by */
3/* loadkeys --mktable defkeymap.map > defkeymap.c */
4
5#include <linux/types.h>
6#include <linux/keyboard.h>
7#include <linux/kd.h>
8
9u_short plain_map[NR_KEYS] = {
10 0xf200, 0xf060, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036,
11 0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf200, 0xf07f,
12 0xf009, 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75,
13 0xfb69, 0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf05c, 0xf207, 0xfb61,
14 0xfb73, 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c,
15 0xf03b, 0xf027, 0xf060, 0xf201, 0xf700, 0xf200, 0xfb7a, 0xfb78,
16 0xfb63, 0xfb76, 0xfb62, 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf02f,
17 0xf200, 0xf700, 0xf702, 0xf200, 0xf703, 0xf020, 0xf703, 0xf200,
18 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
19 0xf200, 0xf200, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf601,
20 0xf200, 0xf200, 0xf200, 0xf603, 0xf600, 0xf118, 0xf119, 0xf200,
21 0xf200, 0xf602, 0xf208, 0xf02d, 0xf02b, 0xf30c, 0xf02e, 0xf30d,
22 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
23 0xf200, 0xf200, 0xf200, 0xf117, 0xf600, 0xf200, 0xf01b, 0xf200,
24 0xf100, 0xf101, 0xf102, 0xf103, 0xf104, 0xf105, 0xf106, 0xf107,
25 0xf108, 0xf109, 0xf200, 0xf200, 0xf200, 0xf200, 0xf11d, 0xf200,
26};
27
28u_short shift_map[NR_KEYS] = {
29 0xf200, 0xf07e, 0xf021, 0xf040, 0xf023, 0xf024, 0xf025, 0xf05e,
30 0xf026, 0xf02a, 0xf028, 0xf029, 0xf05f, 0xf02b, 0xf200, 0xf07f,
31 0xf009, 0xfb51, 0xfb57, 0xfb45, 0xfb52, 0xfb54, 0xfb59, 0xfb55,
32 0xfb49, 0xfb4f, 0xfb50, 0xf07b, 0xf07d, 0xf07c, 0xf207, 0xfb41,
33 0xfb53, 0xfb44, 0xfb46, 0xfb47, 0xfb48, 0xfb4a, 0xfb4b, 0xfb4c,
34 0xf03a, 0xf022, 0xf07e, 0xf201, 0xf700, 0xf200, 0xfb5a, 0xfb58,
35 0xfb43, 0xfb56, 0xfb42, 0xfb4e, 0xfb4d, 0xf03c, 0xf03e, 0xf03f,
36 0xf200, 0xf700, 0xf702, 0xf200, 0xf703, 0xf020, 0xf703, 0xf200,
37 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
38 0xf200, 0xf200, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf601,
39 0xf200, 0xf200, 0xf200, 0xf603, 0xf600, 0xf20b, 0xf20a, 0xf200,
40 0xf200, 0xf602, 0xf213, 0xf02d, 0xf02b, 0xf30c, 0xf02e, 0xf30d,
41 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
42 0xf200, 0xf200, 0xf200, 0xf117, 0xf600, 0xf200, 0xf01b, 0xf200,
43 0xf10a, 0xf10b, 0xf10c, 0xf10d, 0xf10e, 0xf10f, 0xf110, 0xf111,
44 0xf112, 0xf113, 0xf200, 0xf200, 0xf200, 0xf200, 0xf11d, 0xf200,
45};
46
47u_short altgr_map[NR_KEYS] = {
48 0xf200, 0xf200, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200,
49 0xf07b, 0xf05b, 0xf05d, 0xf07d, 0xf05c, 0xf200, 0xf200, 0xf200,
50 0xf200, 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75,
51 0xfb69, 0xfb6f, 0xfb70, 0xf200, 0xf200, 0xf200, 0xf207, 0xfb61,
52 0xfb73, 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c,
53 0xf200, 0xf200, 0xf200, 0xf201, 0xf700, 0xf200, 0xfb7a, 0xfb78,
54 0xfb63, 0xfb76, 0xfb62, 0xfb6e, 0xfb6d, 0xf200, 0xf200, 0xf200,
55 0xf200, 0xf700, 0xf702, 0xf200, 0xf703, 0xf200, 0xf703, 0xf200,
56 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
57 0xf200, 0xf200, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf601,
58 0xf200, 0xf200, 0xf200, 0xf603, 0xf600, 0xf118, 0xf119, 0xf200,
59 0xf200, 0xf602, 0xf208, 0xf02d, 0xf02b, 0xf30c, 0xf02e, 0xf30d,
60 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
61 0xf200, 0xf200, 0xf200, 0xf117, 0xf600, 0xf200, 0xf200, 0xf200,
62 0xf50c, 0xf50d, 0xf50e, 0xf50f, 0xf510, 0xf511, 0xf512, 0xf513,
63 0xf514, 0xf515, 0xf200, 0xf200, 0xf200, 0xf200, 0xf11d, 0xf200,
64};
65
66u_short ctrl_map[NR_KEYS] = {
67 0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e,
68 0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, 0xf008,
69 0xf200, 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015,
70 0xf009, 0xf00f, 0xf010, 0xf01b, 0xf01d, 0xf01c, 0xf207, 0xf001,
71 0xf013, 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c,
72 0xf007, 0xf000, 0xf200, 0xf201, 0xf700, 0xf200, 0xf01a, 0xf018,
73 0xf003, 0xf016, 0xf002, 0xf00e, 0xf20e, 0xf07f, 0xf200, 0xf200,
74 0xf200, 0xf700, 0xf702, 0xf200, 0xf703, 0xf000, 0xf703, 0xf200,
75 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
76 0xf200, 0xf200, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf601,
77 0xf200, 0xf200, 0xf200, 0xf603, 0xf600, 0xf118, 0xf119, 0xf200,
78 0xf200, 0xf602, 0xf208, 0xf02d, 0xf02b, 0xf30c, 0xf02e, 0xf30d,
79 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
80 0xf200, 0xf200, 0xf200, 0xf117, 0xf600, 0xf200, 0xf200, 0xf200,
81 0xf100, 0xf101, 0xf102, 0xf103, 0xf104, 0xf105, 0xf106, 0xf107,
82 0xf108, 0xf109, 0xf200, 0xf200, 0xf200, 0xf200, 0xf11d, 0xf200,
83};
84
85u_short shift_ctrl_map[NR_KEYS] = {
86 0xf200, 0xf200, 0xf200, 0xf000, 0xf200, 0xf200, 0xf200, 0xf200,
87 0xf200, 0xf200, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, 0xf200,
88 0xf200, 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015,
89 0xf009, 0xf00f, 0xf010, 0xf200, 0xf200, 0xf200, 0xf207, 0xf001,
90 0xf013, 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c,
91 0xf200, 0xf200, 0xf200, 0xf201, 0xf700, 0xf200, 0xf01a, 0xf018,
92 0xf003, 0xf016, 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf200,
93 0xf200, 0xf700, 0xf702, 0xf200, 0xf703, 0xf200, 0xf703, 0xf200,
94 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
95 0xf200, 0xf200, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf601,
96 0xf200, 0xf200, 0xf200, 0xf603, 0xf600, 0xf118, 0xf119, 0xf200,
97 0xf200, 0xf602, 0xf208, 0xf02d, 0xf02b, 0xf30c, 0xf02e, 0xf30d,
98 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
99 0xf200, 0xf200, 0xf200, 0xf117, 0xf600, 0xf200, 0xf200, 0xf200,
100 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
101 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf11d, 0xf200,
102};
103
104u_short alt_map[NR_KEYS] = {
105 0xf200, 0xf81b, 0xf831, 0xf832, 0xf833, 0xf834, 0xf835, 0xf836,
106 0xf837, 0xf838, 0xf839, 0xf830, 0xf82d, 0xf83d, 0xf200, 0xf87f,
107 0xf809, 0xf871, 0xf877, 0xf865, 0xf872, 0xf874, 0xf879, 0xf875,
108 0xf869, 0xf86f, 0xf870, 0xf85b, 0xf85d, 0xf85c, 0xf207, 0xf861,
109 0xf873, 0xf864, 0xf866, 0xf867, 0xf868, 0xf86a, 0xf86b, 0xf83b,
110 0xf827, 0xf860, 0xf200, 0xf80d, 0xf700, 0xf200, 0xf87a, 0xf878,
111 0xf863, 0xf876, 0xf862, 0xf82c, 0xf82e, 0xf82f, 0xf200, 0xf200,
112 0xf200, 0xf700, 0xf702, 0xf200, 0xf703, 0xf820, 0xf703, 0xf200,
113 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
114 0xf200, 0xf200, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf210,
115 0xf200, 0xf200, 0xf200, 0xf603, 0xf600, 0xf118, 0xf119, 0xf200,
116 0xf200, 0xf211, 0xf208, 0xf02d, 0xf02b, 0xf30c, 0xf02e, 0xf30d,
117 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
118 0xf200, 0xf200, 0xf200, 0xf117, 0xf600, 0xf200, 0xf200, 0xf200,
119 0xf500, 0xf501, 0xf502, 0xf503, 0xf504, 0xf505, 0xf506, 0xf507,
120 0xf508, 0xf509, 0xf200, 0xf200, 0xf200, 0xf200, 0xf11d, 0xf200,
121};
122
123u_short ctrl_alt_map[NR_KEYS] = {
124 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
125 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
126 0xf200, 0xf811, 0xf817, 0xf805, 0xf812, 0xf814, 0xf819, 0xf815,
127 0xf809, 0xf80f, 0xf810, 0xf200, 0xf200, 0xf200, 0xf207, 0xf801,
128 0xf813, 0xf804, 0xf806, 0xf807, 0xf808, 0xf80a, 0xf80b, 0xf80c,
129 0xf200, 0xf200, 0xf200, 0xf201, 0xf700, 0xf200, 0xf81a, 0xf818,
130 0xf803, 0xf816, 0xf802, 0xf80e, 0xf80d, 0xf200, 0xf200, 0xf200,
131 0xf200, 0xf700, 0xf702, 0xf200, 0xf703, 0xf200, 0xf703, 0xf200,
132 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
133 0xf200, 0xf200, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf601,
134 0xf200, 0xf200, 0xf200, 0xf603, 0xf600, 0xf118, 0xf119, 0xf200,
135 0xf200, 0xf602, 0xf208, 0xf02d, 0xf02b, 0xf30c, 0xf02e, 0xf30d,
136 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
137 0xf200, 0xf200, 0xf200, 0xf117, 0xf600, 0xf200, 0xf200, 0xf200,
138 0xf500, 0xf501, 0xf502, 0xf503, 0xf504, 0xf505, 0xf506, 0xf507,
139 0xf508, 0xf509, 0xf200, 0xf200, 0xf200, 0xf200, 0xf11d, 0xf200,
140};
141
142ushort *key_maps[MAX_NR_KEYMAPS] = {
143 plain_map, shift_map, altgr_map, 0,
144 ctrl_map, shift_ctrl_map, 0, 0,
145 alt_map, 0, 0, 0,
146 ctrl_alt_map, 0
147};
148
149unsigned int keymap_count = 7;
150
151
152/*
153 * Philosophy: most people do not define more strings, but they who do
154 * often want quite a lot of string space. So, we statically allocate
155 * the default and allocate dynamically in chunks of 512 bytes.
156 */
157
158char func_buf[] = {
159 '\033', '[', '[', 'A', 0,
160 '\033', '[', '[', 'B', 0,
161 '\033', '[', '[', 'C', 0,
162 '\033', '[', '[', 'D', 0,
163 '\033', '[', '[', 'E', 0,
164 '\033', '[', '1', '7', '~', 0,
165 '\033', '[', '1', '8', '~', 0,
166 '\033', '[', '1', '9', '~', 0,
167 '\033', '[', '2', '0', '~', 0,
168 '\033', '[', '2', '1', '~', 0,
169 '\033', '[', '2', '3', '~', 0,
170 '\033', '[', '2', '4', '~', 0,
171 '\033', '[', '2', '5', '~', 0,
172 '\033', '[', '2', '6', '~', 0,
173 '\033', '[', '2', '8', '~', 0,
174 '\033', '[', '2', '9', '~', 0,
175 '\033', '[', '3', '1', '~', 0,
176 '\033', '[', '3', '2', '~', 0,
177 '\033', '[', '3', '3', '~', 0,
178 '\033', '[', '3', '4', '~', 0,
179 '\033', '[', '1', '~', 0,
180 '\033', '[', '2', '~', 0,
181 '\033', '[', '3', '~', 0,
182 '\033', '[', '4', '~', 0,
183 '\033', '[', '5', '~', 0,
184 '\033', '[', '6', '~', 0,
185 '\033', '[', 'M', 0,
186 '\033', '[', 'P', 0,
187};
188
189
190char *funcbufptr = func_buf;
191int funcbufsize = sizeof(func_buf);
192int funcbufleft = 0; /* space left */
193
194char *func_table[MAX_NR_FUNC] = {
195 func_buf + 0,
196 func_buf + 5,
197 func_buf + 10,
198 func_buf + 15,
199 func_buf + 20,
200 func_buf + 25,
201 func_buf + 31,
202 func_buf + 37,
203 func_buf + 43,
204 func_buf + 49,
205 func_buf + 55,
206 func_buf + 61,
207 func_buf + 67,
208 func_buf + 73,
209 func_buf + 79,
210 func_buf + 85,
211 func_buf + 91,
212 func_buf + 97,
213 func_buf + 103,
214 func_buf + 109,
215 func_buf + 115,
216 func_buf + 120,
217 func_buf + 125,
218 func_buf + 130,
219 func_buf + 135,
220 func_buf + 140,
221 func_buf + 145,
222 0,
223 0,
224 func_buf + 149,
225 0,
226};
227
228struct kbdiacr accent_table[MAX_DIACR] = {
229 {'`', 'A', 'À'}, {'`', 'a', 'à'},
230 {'\'', 'A', 'Á'}, {'\'', 'a', 'á'},
231 {'^', 'A', 'Â'}, {'^', 'a', 'â'},
232 {'~', 'A', 'Ã'}, {'~', 'a', 'ã'},
233 {'"', 'A', 'Ä'}, {'"', 'a', 'ä'},
234 {'O', 'A', 'Å'}, {'o', 'a', 'å'},
235 {'0', 'A', 'Å'}, {'0', 'a', 'å'},
236 {'A', 'A', 'Å'}, {'a', 'a', 'å'},
237 {'A', 'E', 'Æ'}, {'a', 'e', 'æ'},
238 {',', 'C', 'Ç'}, {',', 'c', 'ç'},
239 {'`', 'E', 'È'}, {'`', 'e', 'è'},
240 {'\'', 'E', 'É'}, {'\'', 'e', 'é'},
241 {'^', 'E', 'Ê'}, {'^', 'e', 'ê'},
242 {'"', 'E', 'Ë'}, {'"', 'e', 'ë'},
243 {'`', 'I', 'Ì'}, {'`', 'i', 'ì'},
244 {'\'', 'I', 'Í'}, {'\'', 'i', 'í'},
245 {'^', 'I', 'Î'}, {'^', 'i', 'î'},
246 {'"', 'I', 'Ï'}, {'"', 'i', 'ï'},
247 {'-', 'D', 'Ð'}, {'-', 'd', 'ð'},
248 {'~', 'N', 'Ñ'}, {'~', 'n', 'ñ'},
249 {'`', 'O', 'Ò'}, {'`', 'o', 'ò'},
250 {'\'', 'O', 'Ó'}, {'\'', 'o', 'ó'},
251 {'^', 'O', 'Ô'}, {'^', 'o', 'ô'},
252 {'~', 'O', 'Õ'}, {'~', 'o', 'õ'},
253 {'"', 'O', 'Ö'}, {'"', 'o', 'ö'},
254 {'/', 'O', 'Ø'}, {'/', 'o', 'ø'},
255 {'`', 'U', 'Ù'}, {'`', 'u', 'ù'},
256 {'\'', 'U', 'Ú'}, {'\'', 'u', 'ú'},
257 {'^', 'U', 'Û'}, {'^', 'u', 'û'},
258 {'"', 'U', 'Ü'}, {'"', 'u', 'ü'},
259 {'\'', 'Y', 'Ý'}, {'\'', 'y', 'ý'},
260 {'T', 'H', 'Þ'}, {'t', 'h', 'þ'},
261 {'s', 's', 'ß'}, {'"', 'y', 'ÿ'},
262 {'s', 'z', 'ß'}, {'i', 'j', 'ÿ'},
263};
264
265unsigned int accent_table_size = 68;
diff --git a/drivers/char/qtronixmap.map b/drivers/char/qtronixmap.map
deleted file mode 100644
index 8d1ff5c1e281..000000000000
--- a/drivers/char/qtronixmap.map
+++ /dev/null
@@ -1,287 +0,0 @@
1# Default kernel keymap. This uses 7 modifier combinations.
2keymaps 0-2,4-5,8,12
3# Change the above line into
4# keymaps 0-2,4-6,8,12
5# in case you want the entries
6# altgr control keycode 83 = Boot
7# altgr control keycode 111 = Boot
8# below.
9#
10# In fact AltGr is used very little, and one more keymap can
11# be saved by mapping AltGr to Alt (and adapting a few entries):
12# keycode 100 = Alt
13#
14keycode 1 = grave asciitilde
15 alt keycode 1 = Meta_Escape
16keycode 2 = one exclam
17 alt keycode 2 = Meta_one
18keycode 3 = two at at
19 control keycode 3 = nul
20 shift control keycode 3 = nul
21 alt keycode 3 = Meta_two
22keycode 4 = three numbersign
23 control keycode 4 = Escape
24 alt keycode 4 = Meta_three
25keycode 5 = four dollar dollar
26 control keycode 5 = Control_backslash
27 alt keycode 5 = Meta_four
28keycode 6 = five percent
29 control keycode 6 = Control_bracketright
30 alt keycode 6 = Meta_five
31keycode 7 = six asciicircum
32 control keycode 7 = Control_asciicircum
33 alt keycode 7 = Meta_six
34keycode 8 = seven ampersand braceleft
35 control keycode 8 = Control_underscore
36 alt keycode 8 = Meta_seven
37keycode 9 = eight asterisk bracketleft
38 control keycode 9 = Delete
39 alt keycode 9 = Meta_eight
40keycode 10 = nine parenleft bracketright
41 alt keycode 10 = Meta_nine
42keycode 11 = zero parenright braceright
43 alt keycode 11 = Meta_zero
44keycode 12 = minus underscore backslash
45 control keycode 12 = Control_underscore
46 shift control keycode 12 = Control_underscore
47 alt keycode 12 = Meta_minus
48keycode 13 = equal plus
49 alt keycode 13 = Meta_equal
50keycode 15 = Delete Delete
51 control keycode 15 = BackSpace
52 alt keycode 15 = Meta_Delete
53keycode 16 = Tab Tab
54 alt keycode 16 = Meta_Tab
55keycode 17 = q
56keycode 18 = w
57keycode 19 = e
58keycode 20 = r
59keycode 21 = t
60keycode 22 = y
61keycode 23 = u
62keycode 24 = i
63keycode 25 = o
64keycode 26 = p
65keycode 27 = bracketleft braceleft
66 control keycode 27 = Escape
67 alt keycode 27 = Meta_bracketleft
68keycode 28 = bracketright braceright
69 control keycode 28 = Control_bracketright
70 alt keycode 28 = Meta_bracketright
71keycode 29 = backslash bar
72 control keycode 29 = Control_backslash
73 alt keycode 29 = Meta_backslash
74keycode 30 = Caps_Lock
75keycode 31 = a
76keycode 32 = s
77keycode 33 = d
78keycode 34 = f
79keycode 35 = g
80keycode 36 = h
81keycode 37 = j
82keycode 38 = k
83keycode 39 = l
84keycode 40 = semicolon colon
85 alt keycode 39 = Meta_semicolon
86keycode 41 = apostrophe quotedbl
87 control keycode 40 = Control_g
88 alt keycode 40 = Meta_apostrophe
89keycode 42 = grave asciitilde
90 control keycode 41 = nul
91 alt keycode 41 = Meta_grave
92keycode 43 = Return
93 alt keycode 43 = Meta_Control_m
94keycode 44 = Shift
95keycode 46 = z
96keycode 47 = x
97keycode 48 = c
98keycode 49 = v
99keycode 50 = b
100keycode 51 = n
101keycode 52 = m
102keycode 53 = comma less
103 alt keycode 51 = Meta_comma
104keycode 54 = period greater
105 control keycode 52 = Compose
106 alt keycode 52 = Meta_period
107keycode 55 = slash question
108 control keycode 53 = Delete
109 alt keycode 53 = Meta_slash
110keycode 57 = Shift
111keycode 58 = Control
112keycode 60 = Alt
113keycode 61 = space space
114 control keycode 61 = nul
115 alt keycode 61 = Meta_space
116keycode 62 = Alt
117
118keycode 75 = Insert
119keycode 76 = Delete
120
121keycode 83 = Up
122keycode 84 = Down
123
124keycode 85 = Prior
125 shift keycode 85 = Scroll_Backward
126keycode 86 = Next
127 shift keycode 86 = Scroll_Forward
128keycode 89 = Right
129 alt keycode 89 = Incr_Console
130keycode 79 = Left
131 alt keycode 79 = Decr_Console
132
133keycode 90 = Num_Lock
134 shift keycode 90 = Bare_Num_Lock
135
136keycode 91 = minus
137keycode 92 = plus
138keycode 93 = KP_Multiply
139keycode 94 = period
140keycode 95 = KP_Divide
141
142keycode 107 = Select
143keycode 108 = Down
144
145keycode 110 = Escape Escape
146 alt keycode 1 = Meta_Escape
147
148keycode 112 = F1 F11 Console_13
149 control keycode 112 = F1
150 alt keycode 112 = Console_1
151 control alt keycode 112 = Console_1
152keycode 113 = F2 F12 Console_14
153 control keycode 113 = F2
154 alt keycode 113 = Console_2
155 control alt keycode 113 = Console_2
156keycode 114 = F3 F13 Console_15
157 control keycode 114 = F3
158 alt keycode 114 = Console_3
159 control alt keycode 114 = Console_3
160keycode 115 = F4 F14 Console_16
161 control keycode 115 = F4
162 alt keycode 115 = Console_4
163 control alt keycode 115 = Console_4
164keycode 116 = F5 F15 Console_17
165 control keycode 116 = F5
166 alt keycode 116 = Console_5
167 control alt keycode 116 = Console_5
168keycode 117 = F6 F16 Console_18
169 control keycode 117 = F6
170 alt keycode 117 = Console_6
171 control alt keycode 117 = Console_6
172keycode 118 = F7 F17 Console_19
173 control keycode 118 = F7
174 alt keycode 118 = Console_7
175 control alt keycode 118 = Console_7
176keycode 119 = F8 F18 Console_20
177 control keycode 119 = F8
178 alt keycode 119 = Console_8
179 control alt keycode 119 = Console_8
180keycode 120 = F9 F19 Console_21
181 control keycode 120 = F9
182 alt keycode 120 = Console_9
183 control alt keycode 120 = Console_9
184keycode 121 = F10 F20 Console_22
185 control keycode 121 = F10
186 alt keycode 121 = Console_10
187 control alt keycode 121 = Console_10
188
189keycode 126 = Pause
190
191
192string F1 = "\033[[A"
193string F2 = "\033[[B"
194string F3 = "\033[[C"
195string F4 = "\033[[D"
196string F5 = "\033[[E"
197string F6 = "\033[17~"
198string F7 = "\033[18~"
199string F8 = "\033[19~"
200string F9 = "\033[20~"
201string F10 = "\033[21~"
202string F11 = "\033[23~"
203string F12 = "\033[24~"
204string F13 = "\033[25~"
205string F14 = "\033[26~"
206string F15 = "\033[28~"
207string F16 = "\033[29~"
208string F17 = "\033[31~"
209string F18 = "\033[32~"
210string F19 = "\033[33~"
211string F20 = "\033[34~"
212string Find = "\033[1~"
213string Insert = "\033[2~"
214string Remove = "\033[3~"
215string Select = "\033[4~"
216string Prior = "\033[5~"
217string Next = "\033[6~"
218string Macro = "\033[M"
219string Pause = "\033[P"
220compose '`' 'A' to 'À'
221compose '`' 'a' to 'à'
222compose '\'' 'A' to 'Á'
223compose '\'' 'a' to 'á'
224compose '^' 'A' to 'Â'
225compose '^' 'a' to 'â'
226compose '~' 'A' to 'Ã'
227compose '~' 'a' to 'ã'
228compose '"' 'A' to 'Ä'
229compose '"' 'a' to 'ä'
230compose 'O' 'A' to 'Å'
231compose 'o' 'a' to 'å'
232compose '0' 'A' to 'Å'
233compose '0' 'a' to 'å'
234compose 'A' 'A' to 'Å'
235compose 'a' 'a' to 'å'
236compose 'A' 'E' to 'Æ'
237compose 'a' 'e' to 'æ'
238compose ',' 'C' to 'Ç'
239compose ',' 'c' to 'ç'
240compose '`' 'E' to 'È'
241compose '`' 'e' to 'è'
242compose '\'' 'E' to 'É'
243compose '\'' 'e' to 'é'
244compose '^' 'E' to 'Ê'
245compose '^' 'e' to 'ê'
246compose '"' 'E' to 'Ë'
247compose '"' 'e' to 'ë'
248compose '`' 'I' to 'Ì'
249compose '`' 'i' to 'ì'
250compose '\'' 'I' to 'Í'
251compose '\'' 'i' to 'í'
252compose '^' 'I' to 'Î'
253compose '^' 'i' to 'î'
254compose '"' 'I' to 'Ï'
255compose '"' 'i' to 'ï'
256compose '-' 'D' to 'Ð'
257compose '-' 'd' to 'ð'
258compose '~' 'N' to 'Ñ'
259compose '~' 'n' to 'ñ'
260compose '`' 'O' to 'Ò'
261compose '`' 'o' to 'ò'
262compose '\'' 'O' to 'Ó'
263compose '\'' 'o' to 'ó'
264compose '^' 'O' to 'Ô'
265compose '^' 'o' to 'ô'
266compose '~' 'O' to 'Õ'
267compose '~' 'o' to 'õ'
268compose '"' 'O' to 'Ö'
269compose '"' 'o' to 'ö'
270compose '/' 'O' to 'Ø'
271compose '/' 'o' to 'ø'
272compose '`' 'U' to 'Ù'
273compose '`' 'u' to 'ù'
274compose '\'' 'U' to 'Ú'
275compose '\'' 'u' to 'ú'
276compose '^' 'U' to 'Û'
277compose '^' 'u' to 'û'
278compose '"' 'U' to 'Ü'
279compose '"' 'u' to 'ü'
280compose '\'' 'Y' to 'Ý'
281compose '\'' 'y' to 'ý'
282compose 'T' 'H' to 'Þ'
283compose 't' 'h' to 'þ'
284compose 's' 's' to 'ß'
285compose '"' 'y' to 'ÿ'
286compose 's' 'z' to 'ß'
287compose 'i' 'j' to 'ÿ'
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 4c3a5ca9d8f7..07f47a0208a7 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -655,6 +655,7 @@ void add_interrupt_randomness(int irq)
655 add_timer_randomness(irq_timer_state[irq], 0x100 + irq); 655 add_timer_randomness(irq_timer_state[irq], 0x100 + irq);
656} 656}
657 657
658#ifdef CONFIG_BLOCK
658void add_disk_randomness(struct gendisk *disk) 659void add_disk_randomness(struct gendisk *disk)
659{ 660{
660 if (!disk || !disk->random) 661 if (!disk || !disk->random)
@@ -667,6 +668,7 @@ void add_disk_randomness(struct gendisk *disk)
667} 668}
668 669
669EXPORT_SYMBOL(add_disk_randomness); 670EXPORT_SYMBOL(add_disk_randomness);
671#endif
670 672
671#define EXTRACT_SIZE 10 673#define EXTRACT_SIZE 10
672 674
@@ -887,8 +889,8 @@ static void init_std_data(struct entropy_store *r)
887 889
888 do_gettimeofday(&tv); 890 do_gettimeofday(&tv);
889 add_entropy_words(r, (__u32 *)&tv, sizeof(tv)/4); 891 add_entropy_words(r, (__u32 *)&tv, sizeof(tv)/4);
890 add_entropy_words(r, (__u32 *)&system_utsname, 892 add_entropy_words(r, (__u32 *)utsname(),
891 sizeof(system_utsname)/4); 893 sizeof(*(utsname()))/4);
892} 894}
893 895
894static int __init rand_initialize(void) 896static int __init rand_initialize(void)
@@ -918,6 +920,7 @@ void rand_initialize_irq(int irq)
918 } 920 }
919} 921}
920 922
923#ifdef CONFIG_BLOCK
921void rand_initialize_disk(struct gendisk *disk) 924void rand_initialize_disk(struct gendisk *disk)
922{ 925{
923 struct timer_rand_state *state; 926 struct timer_rand_state *state;
@@ -932,6 +935,7 @@ void rand_initialize_disk(struct gendisk *disk)
932 disk->random = state; 935 disk->random = state;
933 } 936 }
934} 937}
938#endif
935 939
936static ssize_t 940static ssize_t
937random_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos) 941random_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos)
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index 579868af4a54..89b718e326e5 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -238,39 +238,14 @@ out:
238 return err; 238 return err;
239} 239}
240 240
241static ssize_t raw_file_write(struct file *file, const char __user *buf,
242 size_t count, loff_t *ppos)
243{
244 struct iovec local_iov = {
245 .iov_base = (char __user *)buf,
246 .iov_len = count
247 };
248
249 return generic_file_write_nolock(file, &local_iov, 1, ppos);
250}
251
252static ssize_t raw_file_aio_write(struct kiocb *iocb, const char __user *buf,
253 size_t count, loff_t pos)
254{
255 struct iovec local_iov = {
256 .iov_base = (char __user *)buf,
257 .iov_len = count
258 };
259
260 return generic_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos);
261}
262
263
264static const struct file_operations raw_fops = { 241static const struct file_operations raw_fops = {
265 .read = generic_file_read, 242 .read = do_sync_read,
266 .aio_read = generic_file_aio_read, 243 .aio_read = generic_file_aio_read,
267 .write = raw_file_write, 244 .write = do_sync_write,
268 .aio_write = raw_file_aio_write, 245 .aio_write = generic_file_aio_write_nolock,
269 .open = raw_open, 246 .open = raw_open,
270 .release= raw_release, 247 .release= raw_release,
271 .ioctl = raw_ioctl, 248 .ioctl = raw_ioctl,
272 .readv = generic_file_readv,
273 .writev = generic_file_writev,
274 .owner = THIS_MODULE, 249 .owner = THIS_MODULE,
275}; 250};
276 251
@@ -288,31 +263,34 @@ static struct cdev raw_cdev = {
288static int __init raw_init(void) 263static int __init raw_init(void)
289{ 264{
290 dev_t dev = MKDEV(RAW_MAJOR, 0); 265 dev_t dev = MKDEV(RAW_MAJOR, 0);
266 int ret;
291 267
292 if (register_chrdev_region(dev, MAX_RAW_MINORS, "raw")) 268 ret = register_chrdev_region(dev, MAX_RAW_MINORS, "raw");
269 if (ret)
293 goto error; 270 goto error;
294 271
295 cdev_init(&raw_cdev, &raw_fops); 272 cdev_init(&raw_cdev, &raw_fops);
296 if (cdev_add(&raw_cdev, dev, MAX_RAW_MINORS)) { 273 ret = cdev_add(&raw_cdev, dev, MAX_RAW_MINORS);
274 if (ret) {
297 kobject_put(&raw_cdev.kobj); 275 kobject_put(&raw_cdev.kobj);
298 unregister_chrdev_region(dev, MAX_RAW_MINORS); 276 goto error_region;
299 goto error;
300 } 277 }
301 278
302 raw_class = class_create(THIS_MODULE, "raw"); 279 raw_class = class_create(THIS_MODULE, "raw");
303 if (IS_ERR(raw_class)) { 280 if (IS_ERR(raw_class)) {
304 printk(KERN_ERR "Error creating raw class.\n"); 281 printk(KERN_ERR "Error creating raw class.\n");
305 cdev_del(&raw_cdev); 282 cdev_del(&raw_cdev);
306 unregister_chrdev_region(dev, MAX_RAW_MINORS); 283 ret = PTR_ERR(raw_class);
307 goto error; 284 goto error_region;
308 } 285 }
309 class_device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL, "rawctl"); 286 class_device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
310 287
311 return 0; 288 return 0;
312 289
290error_region:
291 unregister_chrdev_region(dev, MAX_RAW_MINORS);
313error: 292error:
314 printk(KERN_ERR "error register raw device\n"); 293 return ret;
315 return 1;
316} 294}
317 295
318static void __exit raw_exit(void) 296static void __exit raw_exit(void)
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
index 3fa80aaf4527..202a3b0945b7 100644
--- a/drivers/char/rio/rio_linux.c
+++ b/drivers/char/rio/rio_linux.c
@@ -727,7 +727,7 @@ static struct vpd_prom *get_VPD_PROM(struct Host *hp)
727 return &vpdp; 727 return &vpdp;
728} 728}
729 729
730static struct tty_operations rio_ops = { 730static const struct tty_operations rio_ops = {
731 .open = riotopen, 731 .open = riotopen,
732 .close = gs_close, 732 .close = gs_close,
733 .write = gs_write, 733 .write = gs_write,
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index f1c94f771af5..214d850112fd 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -675,26 +675,12 @@ static void rc_change_speed(struct riscom_board *bp, struct riscom_port *port)
675 port->COR2 = 0; 675 port->COR2 = 0;
676 port->MSVR = MSVR_RTS; 676 port->MSVR = MSVR_RTS;
677 677
678 baud = C_BAUD(tty); 678 baud = tty_get_baud_rate(tty);
679
680 if (baud & CBAUDEX) {
681 baud &= ~CBAUDEX;
682 if (baud < 1 || baud > 2)
683 port->tty->termios->c_cflag &= ~CBAUDEX;
684 else
685 baud += 15;
686 }
687 if (baud == 15) {
688 if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
689 baud ++;
690 if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
691 baud += 2;
692 }
693 679
694 /* Select port on the board */ 680 /* Select port on the board */
695 rc_out(bp, CD180_CAR, port_No(port)); 681 rc_out(bp, CD180_CAR, port_No(port));
696 682
697 if (!baud_table[baud]) { 683 if (!baud) {
698 /* Drop DTR & exit */ 684 /* Drop DTR & exit */
699 bp->DTR |= (1u << port_No(port)); 685 bp->DTR |= (1u << port_No(port));
700 rc_out(bp, RC_DTR, bp->DTR); 686 rc_out(bp, RC_DTR, bp->DTR);
@@ -710,7 +696,7 @@ static void rc_change_speed(struct riscom_board *bp, struct riscom_port *port)
710 */ 696 */
711 697
712 /* Set baud rate for port */ 698 /* Set baud rate for port */
713 tmp = (((RC_OSCFREQ + baud_table[baud]/2) / baud_table[baud] + 699 tmp = (((RC_OSCFREQ + baud/2) / baud +
714 CD180_TPC/2) / CD180_TPC); 700 CD180_TPC/2) / CD180_TPC);
715 701
716 rc_out(bp, CD180_RBPRH, (tmp >> 8) & 0xff); 702 rc_out(bp, CD180_RBPRH, (tmp >> 8) & 0xff);
@@ -718,7 +704,7 @@ static void rc_change_speed(struct riscom_board *bp, struct riscom_port *port)
718 rc_out(bp, CD180_RBPRL, tmp & 0xff); 704 rc_out(bp, CD180_RBPRL, tmp & 0xff);
719 rc_out(bp, CD180_TBPRL, tmp & 0xff); 705 rc_out(bp, CD180_TBPRL, tmp & 0xff);
720 706
721 baud = (baud_table[baud] + 5) / 10; /* Estimated CPS */ 707 baud = (baud + 5) / 10; /* Estimated CPS */
722 708
723 /* Two timer ticks seems enough to wakeup something like SLIP driver */ 709 /* Two timer ticks seems enough to wakeup something like SLIP driver */
724 tmp = ((baud + HZ/2) / HZ) * 2 - CD180_NFIFO; 710 tmp = ((baud + HZ/2) / HZ) * 2 - CD180_NFIFO;
@@ -1597,7 +1583,7 @@ static void do_softint(void *private_)
1597 } 1583 }
1598} 1584}
1599 1585
1600static struct tty_operations riscom_ops = { 1586static const struct tty_operations riscom_ops = {
1601 .open = rc_open, 1587 .open = rc_open,
1602 .close = rc_close, 1588 .close = rc_close,
1603 .write = rc_write, 1589 .write = rc_write,
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index 0ac131881322..bac80056f7e0 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -2334,7 +2334,7 @@ static int __init init_ISA(int i)
2334 return (1); 2334 return (1);
2335} 2335}
2336 2336
2337static struct tty_operations rocket_ops = { 2337static const struct tty_operations rocket_ops = {
2338 .open = rp_open, 2338 .open = rp_open,
2339 .close = rp_close, 2339 .close = rp_close,
2340 .write = rp_write, 2340 .write = rp_write,
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index 6e6a7c7a7eff..656f8c0ca52e 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -209,11 +209,12 @@ static const unsigned char days_in_mo[] =
209 */ 209 */
210static inline unsigned char rtc_is_updating(void) 210static inline unsigned char rtc_is_updating(void)
211{ 211{
212 unsigned long flags;
212 unsigned char uip; 213 unsigned char uip;
213 214
214 spin_lock_irq(&rtc_lock); 215 spin_lock_irqsave(&rtc_lock, flags);
215 uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); 216 uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
216 spin_unlock_irq(&rtc_lock); 217 spin_unlock_irqrestore(&rtc_lock, flags);
217 return uip; 218 return uip;
218} 219}
219 220
@@ -1261,10 +1262,8 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
1261 * Once the read clears, read the RTC time (again via ioctl). Easy. 1262 * Once the read clears, read the RTC time (again via ioctl). Easy.
1262 */ 1263 */
1263 1264
1264 while (rtc_is_updating() != 0 && jiffies - uip_watchdog < 2*HZ/100) { 1265 while (rtc_is_updating() != 0 && jiffies - uip_watchdog < 2*HZ/100)
1265 barrier();
1266 cpu_relax(); 1266 cpu_relax();
1267 }
1268 1267
1269 /* 1268 /*
1270 * Only the values that we read from the RTC are set. We leave 1269 * Only the values that we read from the RTC are set. We leave
diff --git a/drivers/char/s3c2410-rtc.c b/drivers/char/s3c2410-rtc.c
deleted file mode 100644
index 5458ef1634e5..000000000000
--- a/drivers/char/s3c2410-rtc.c
+++ /dev/null
@@ -1,591 +0,0 @@
1/* drivers/char/s3c2410_rtc.c
2 *
3 * Copyright (c) 2004 Simtec Electronics <linux@simtec.co.uk>
4 * http://www.simtec.co.uk/products/SWLINUX/
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * S3C2410 Internal RTC Driver
11 *
12 * Changelog:
13 * 08-Nov-2004 BJD Initial creation
14 * 12-Nov-2004 BJD Added periodic IRQ and PM code
15 * 22-Nov-2004 BJD Sign-test on alarm code to check for <0
16 * 10-Mar-2005 LCVR Changed S3C2410_VA_RTC to S3C24XX_VA_RTC
17*/
18
19#include <linux/module.h>
20#include <linux/fs.h>
21#include <linux/string.h>
22#include <linux/init.h>
23#include <linux/platform_device.h>
24#include <linux/interrupt.h>
25#include <linux/rtc.h>
26#include <linux/bcd.h>
27#include <linux/clk.h>
28
29#include <asm/hardware.h>
30#include <asm/uaccess.h>
31#include <asm/io.h>
32#include <asm/irq.h>
33#include <asm/rtc.h>
34
35#include <asm/mach/time.h>
36
37#include <asm/arch/regs-rtc.h>
38
39/* need this for the RTC_AF definitions */
40#include <linux/mc146818rtc.h>
41
42#undef S3C24XX_VA_RTC
43#define S3C24XX_VA_RTC s3c2410_rtc_base
44
45static struct resource *s3c2410_rtc_mem;
46
47static void __iomem *s3c2410_rtc_base;
48static int s3c2410_rtc_alarmno = NO_IRQ;
49static int s3c2410_rtc_tickno = NO_IRQ;
50static int s3c2410_rtc_freq = 1;
51
52static DEFINE_SPINLOCK(s3c2410_rtc_pie_lock);
53
54/* IRQ Handlers */
55
56static irqreturn_t s3c2410_rtc_alarmirq(int irq, void *id, struct pt_regs *r)
57{
58 rtc_update(1, RTC_AF | RTC_IRQF);
59 return IRQ_HANDLED;
60}
61
62static irqreturn_t s3c2410_rtc_tickirq(int irq, void *id, struct pt_regs *r)
63{
64 rtc_update(1, RTC_PF | RTC_IRQF);
65 return IRQ_HANDLED;
66}
67
68/* Update control registers */
69static void s3c2410_rtc_setaie(int to)
70{
71 unsigned int tmp;
72
73 pr_debug("%s: aie=%d\n", __FUNCTION__, to);
74
75 tmp = readb(S3C2410_RTCALM);
76
77 if (to)
78 tmp |= S3C2410_RTCALM_ALMEN;
79 else
80 tmp &= ~S3C2410_RTCALM_ALMEN;
81
82
83 writeb(tmp, S3C2410_RTCALM);
84}
85
86static void s3c2410_rtc_setpie(int to)
87{
88 unsigned int tmp;
89
90 pr_debug("%s: pie=%d\n", __FUNCTION__, to);
91
92 spin_lock_irq(&s3c2410_rtc_pie_lock);
93 tmp = readb(S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE;
94
95 if (to)
96 tmp |= S3C2410_TICNT_ENABLE;
97
98 writeb(tmp, S3C2410_TICNT);
99 spin_unlock_irq(&s3c2410_rtc_pie_lock);
100}
101
102static void s3c2410_rtc_setfreq(int freq)
103{
104 unsigned int tmp;
105
106 spin_lock_irq(&s3c2410_rtc_pie_lock);
107 tmp = readb(S3C2410_TICNT) & S3C2410_TICNT_ENABLE;
108
109 s3c2410_rtc_freq = freq;
110
111 tmp |= (128 / freq)-1;
112
113 writeb(tmp, S3C2410_TICNT);
114 spin_unlock_irq(&s3c2410_rtc_pie_lock);
115}
116
117/* Time read/write */
118
119static int s3c2410_rtc_gettime(struct rtc_time *rtc_tm)
120{
121 unsigned int have_retried = 0;
122
123 retry_get_time:
124 rtc_tm->tm_min = readb(S3C2410_RTCMIN);
125 rtc_tm->tm_hour = readb(S3C2410_RTCHOUR);
126 rtc_tm->tm_mday = readb(S3C2410_RTCDATE);
127 rtc_tm->tm_mon = readb(S3C2410_RTCMON);
128 rtc_tm->tm_year = readb(S3C2410_RTCYEAR);
129 rtc_tm->tm_sec = readb(S3C2410_RTCSEC);
130
131 /* the only way to work out wether the system was mid-update
132 * when we read it is to check the second counter, and if it
133 * is zero, then we re-try the entire read
134 */
135
136 if (rtc_tm->tm_sec == 0 && !have_retried) {
137 have_retried = 1;
138 goto retry_get_time;
139 }
140
141 pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n",
142 rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
143 rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
144
145 BCD_TO_BIN(rtc_tm->tm_sec);
146 BCD_TO_BIN(rtc_tm->tm_min);
147 BCD_TO_BIN(rtc_tm->tm_hour);
148 BCD_TO_BIN(rtc_tm->tm_mday);
149 BCD_TO_BIN(rtc_tm->tm_mon);
150 BCD_TO_BIN(rtc_tm->tm_year);
151
152 rtc_tm->tm_year += 100;
153 rtc_tm->tm_mon -= 1;
154
155 return 0;
156}
157
158
159static int s3c2410_rtc_settime(struct rtc_time *tm)
160{
161 /* the rtc gets round the y2k problem by just not supporting it */
162
163 if (tm->tm_year < 100)
164 return -EINVAL;
165
166 writeb(BIN2BCD(tm->tm_sec), S3C2410_RTCSEC);
167 writeb(BIN2BCD(tm->tm_min), S3C2410_RTCMIN);
168 writeb(BIN2BCD(tm->tm_hour), S3C2410_RTCHOUR);
169 writeb(BIN2BCD(tm->tm_mday), S3C2410_RTCDATE);
170 writeb(BIN2BCD(tm->tm_mon + 1), S3C2410_RTCMON);
171 writeb(BIN2BCD(tm->tm_year - 100), S3C2410_RTCYEAR);
172
173 return 0;
174}
175
176static int s3c2410_rtc_getalarm(struct rtc_wkalrm *alrm)
177{
178 struct rtc_time *alm_tm = &alrm->time;
179 unsigned int alm_en;
180
181 alm_tm->tm_sec = readb(S3C2410_ALMSEC);
182 alm_tm->tm_min = readb(S3C2410_ALMMIN);
183 alm_tm->tm_hour = readb(S3C2410_ALMHOUR);
184 alm_tm->tm_mon = readb(S3C2410_ALMMON);
185 alm_tm->tm_mday = readb(S3C2410_ALMDATE);
186 alm_tm->tm_year = readb(S3C2410_ALMYEAR);
187
188 alm_en = readb(S3C2410_RTCALM);
189
190 pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n",
191 alm_en,
192 alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday,
193 alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec);
194
195
196 /* decode the alarm enable field */
197
198 if (alm_en & S3C2410_RTCALM_SECEN) {
199 BCD_TO_BIN(alm_tm->tm_sec);
200 } else {
201 alm_tm->tm_sec = 0xff;
202 }
203
204 if (alm_en & S3C2410_RTCALM_MINEN) {
205 BCD_TO_BIN(alm_tm->tm_min);
206 } else {
207 alm_tm->tm_min = 0xff;
208 }
209
210 if (alm_en & S3C2410_RTCALM_HOUREN) {
211 BCD_TO_BIN(alm_tm->tm_hour);
212 } else {
213 alm_tm->tm_hour = 0xff;
214 }
215
216 if (alm_en & S3C2410_RTCALM_DAYEN) {
217 BCD_TO_BIN(alm_tm->tm_mday);
218 } else {
219 alm_tm->tm_mday = 0xff;
220 }
221
222 if (alm_en & S3C2410_RTCALM_MONEN) {
223 BCD_TO_BIN(alm_tm->tm_mon);
224 alm_tm->tm_mon -= 1;
225 } else {
226 alm_tm->tm_mon = 0xff;
227 }
228
229 if (alm_en & S3C2410_RTCALM_YEAREN) {
230 BCD_TO_BIN(alm_tm->tm_year);
231 } else {
232 alm_tm->tm_year = 0xffff;
233 }
234
235 /* todo - set alrm->enabled ? */
236
237 return 0;
238}
239
240static int s3c2410_rtc_setalarm(struct rtc_wkalrm *alrm)
241{
242 struct rtc_time *tm = &alrm->time;
243 unsigned int alrm_en;
244
245 pr_debug("s3c2410_rtc_setalarm: %d, %02x/%02x/%02x %02x.%02x.%02x\n",
246 alrm->enabled,
247 tm->tm_mday & 0xff, tm->tm_mon & 0xff, tm->tm_year & 0xff,
248 tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec);
249
250 if (alrm->enabled || 1) {
251 alrm_en = readb(S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN;
252 writeb(0x00, S3C2410_RTCALM);
253
254 if (tm->tm_sec < 60 && tm->tm_sec >= 0) {
255 alrm_en |= S3C2410_RTCALM_SECEN;
256 writeb(BIN2BCD(tm->tm_sec), S3C2410_ALMSEC);
257 }
258
259 if (tm->tm_min < 60 && tm->tm_min >= 0) {
260 alrm_en |= S3C2410_RTCALM_MINEN;
261 writeb(BIN2BCD(tm->tm_min), S3C2410_ALMMIN);
262 }
263
264 if (tm->tm_hour < 24 && tm->tm_hour >= 0) {
265 alrm_en |= S3C2410_RTCALM_HOUREN;
266 writeb(BIN2BCD(tm->tm_hour), S3C2410_ALMHOUR);
267 }
268
269 pr_debug("setting S3C2410_RTCALM to %08x\n", alrm_en);
270
271 writeb(alrm_en, S3C2410_RTCALM);
272 enable_irq_wake(s3c2410_rtc_alarmno);
273 } else {
274 alrm_en = readb(S3C2410_RTCALM);
275 alrm_en &= ~S3C2410_RTCALM_ALMEN;
276 writeb(alrm_en, S3C2410_RTCALM);
277 disable_irq_wake(s3c2410_rtc_alarmno);
278 }
279
280 return 0;
281}
282
283static int s3c2410_rtc_ioctl(unsigned int cmd, unsigned long arg)
284{
285 switch (cmd) {
286 case RTC_AIE_OFF:
287 case RTC_AIE_ON:
288 s3c2410_rtc_setaie((cmd == RTC_AIE_ON) ? 1 : 0);
289 return 0;
290
291 case RTC_PIE_OFF:
292 case RTC_PIE_ON:
293 s3c2410_rtc_setpie((cmd == RTC_PIE_ON) ? 1 : 0);
294 return 0;
295
296 case RTC_IRQP_READ:
297 return put_user(s3c2410_rtc_freq, (unsigned long __user *)arg);
298
299 case RTC_IRQP_SET:
300 if (arg < 1 || arg > 64)
301 return -EINVAL;
302
303 if (!capable(CAP_SYS_RESOURCE))
304 return -EACCES;
305
306 /* check for power of 2 */
307
308 if ((arg & (arg-1)) != 0)
309 return -EINVAL;
310
311 pr_debug("s3c2410_rtc: setting frequency %ld\n", arg);
312
313 s3c2410_rtc_setfreq(arg);
314 return 0;
315
316 case RTC_UIE_ON:
317 case RTC_UIE_OFF:
318 return -EINVAL;
319 }
320
321 return -EINVAL;
322}
323
324static int s3c2410_rtc_proc(char *buf)
325{
326 unsigned int rtcalm = readb(S3C2410_RTCALM);
327 unsigned int ticnt = readb (S3C2410_TICNT);
328 char *p = buf;
329
330 p += sprintf(p, "alarm_IRQ\t: %s\n",
331 (rtcalm & S3C2410_RTCALM_ALMEN) ? "yes" : "no" );
332 p += sprintf(p, "periodic_IRQ\t: %s\n",
333 (ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" );
334 p += sprintf(p, "periodic_freq\t: %d\n", s3c2410_rtc_freq);
335
336 return p - buf;
337}
338
339static int s3c2410_rtc_open(void)
340{
341 int ret;
342
343 ret = request_irq(s3c2410_rtc_alarmno, s3c2410_rtc_alarmirq,
344 IRQF_DISABLED, "s3c2410-rtc alarm", NULL);
345
346 if (ret)
347 printk(KERN_ERR "IRQ%d already in use\n", s3c2410_rtc_alarmno);
348
349 ret = request_irq(s3c2410_rtc_tickno, s3c2410_rtc_tickirq,
350 IRQF_DISABLED, "s3c2410-rtc tick", NULL);
351
352 if (ret) {
353 printk(KERN_ERR "IRQ%d already in use\n", s3c2410_rtc_tickno);
354 goto tick_err;
355 }
356
357 return ret;
358
359 tick_err:
360 free_irq(s3c2410_rtc_alarmno, NULL);
361 return ret;
362}
363
364static void s3c2410_rtc_release(void)
365{
366 /* do not clear AIE here, it may be needed for wake */
367
368 s3c2410_rtc_setpie(0);
369 free_irq(s3c2410_rtc_alarmno, NULL);
370 free_irq(s3c2410_rtc_tickno, NULL);
371}
372
373static struct rtc_ops s3c2410_rtcops = {
374 .owner = THIS_MODULE,
375 .open = s3c2410_rtc_open,
376 .release = s3c2410_rtc_release,
377 .ioctl = s3c2410_rtc_ioctl,
378 .read_time = s3c2410_rtc_gettime,
379 .set_time = s3c2410_rtc_settime,
380 .read_alarm = s3c2410_rtc_getalarm,
381 .set_alarm = s3c2410_rtc_setalarm,
382 .proc = s3c2410_rtc_proc,
383};
384
385static void s3c2410_rtc_enable(struct platform_device *pdev, int en)
386{
387 unsigned int tmp;
388
389 if (s3c2410_rtc_base == NULL)
390 return;
391
392 if (!en) {
393 tmp = readb(S3C2410_RTCCON);
394 writeb(tmp & ~S3C2410_RTCCON_RTCEN, S3C2410_RTCCON);
395
396 tmp = readb(S3C2410_TICNT);
397 writeb(tmp & ~S3C2410_TICNT_ENABLE, S3C2410_TICNT);
398 } else {
399 /* re-enable the device, and check it is ok */
400
401 if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0){
402 dev_info(&pdev->dev, "rtc disabled, re-enabling\n");
403
404 tmp = readb(S3C2410_RTCCON);
405 writeb(tmp | S3C2410_RTCCON_RTCEN , S3C2410_RTCCON);
406 }
407
408 if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)){
409 dev_info(&pdev->dev, "removing S3C2410_RTCCON_CNTSEL\n");
410
411 tmp = readb(S3C2410_RTCCON);
412 writeb(tmp& ~S3C2410_RTCCON_CNTSEL , S3C2410_RTCCON);
413 }
414
415 if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)){
416 dev_info(&pdev->dev, "removing S3C2410_RTCCON_CLKRST\n");
417
418 tmp = readb(S3C2410_RTCCON);
419 writeb(tmp & ~S3C2410_RTCCON_CLKRST, S3C2410_RTCCON);
420 }
421 }
422}
423
424static int s3c2410_rtc_remove(struct platform_device *dev)
425{
426 unregister_rtc(&s3c2410_rtcops);
427
428 s3c2410_rtc_setpie(0);
429 s3c2410_rtc_setaie(0);
430
431 if (s3c2410_rtc_mem != NULL) {
432 pr_debug("s3c2410_rtc: releasing s3c2410_rtc_mem\n");
433 iounmap(s3c2410_rtc_base);
434 release_resource(s3c2410_rtc_mem);
435 kfree(s3c2410_rtc_mem);
436 }
437
438 return 0;
439}
440
441static int s3c2410_rtc_probe(struct platform_device *pdev)
442{
443 struct resource *res;
444 int ret;
445
446 pr_debug("%s: probe=%p\n", __FUNCTION__, pdev);
447
448 /* find the IRQs */
449
450 s3c2410_rtc_tickno = platform_get_irq(pdev, 1);
451 if (s3c2410_rtc_tickno < 0) {
452 dev_err(&pdev->dev, "no irq for rtc tick\n");
453 return -ENOENT;
454 }
455
456 s3c2410_rtc_alarmno = platform_get_irq(pdev, 0);
457 if (s3c2410_rtc_alarmno < 0) {
458 dev_err(&pdev->dev, "no irq for alarm\n");
459 return -ENOENT;
460 }
461
462 pr_debug("s3c2410_rtc: tick irq %d, alarm irq %d\n",
463 s3c2410_rtc_tickno, s3c2410_rtc_alarmno);
464
465 /* get the memory region */
466
467 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
468 if (res == NULL) {
469 dev_err(&pdev->dev, "failed to get memory region resource\n");
470 return -ENOENT;
471 }
472
473 s3c2410_rtc_mem = request_mem_region(res->start, res->end-res->start+1,
474 pdev->name);
475
476 if (s3c2410_rtc_mem == NULL) {
477 dev_err(&pdev->dev, "failed to reserve memory region\n");
478 ret = -ENOENT;
479 goto exit_err;
480 }
481
482 s3c2410_rtc_base = ioremap(res->start, res->end - res->start + 1);
483 if (s3c2410_rtc_base == NULL) {
484 dev_err(&pdev->dev, "failed ioremap()\n");
485 ret = -EINVAL;
486 goto exit_err;
487 }
488
489 s3c2410_rtc_mem = res;
490 pr_debug("s3c2410_rtc_base=%p\n", s3c2410_rtc_base);
491
492 pr_debug("s3c2410_rtc: RTCCON=%02x\n", readb(S3C2410_RTCCON));
493
494 /* check to see if everything is setup correctly */
495
496 s3c2410_rtc_enable(pdev, 1);
497
498 pr_debug("s3c2410_rtc: RTCCON=%02x\n", readb(S3C2410_RTCCON));
499
500 s3c2410_rtc_setfreq(s3c2410_rtc_freq);
501
502 /* register RTC and exit */
503
504 register_rtc(&s3c2410_rtcops);
505 return 0;
506
507 exit_err:
508 dev_err(&pdev->dev, "error %d during initialisation\n", ret);
509
510 return ret;
511}
512
513#ifdef CONFIG_PM
514
515/* S3C2410 RTC Power management control */
516
517static struct timespec s3c2410_rtc_delta;
518
519static int ticnt_save;
520
521static int s3c2410_rtc_suspend(struct platform_device *pdev, pm_message_t state)
522{
523 struct rtc_time tm;
524 struct timespec time;
525
526 time.tv_nsec = 0;
527
528 /* save TICNT for anyone using periodic interrupts */
529
530 ticnt_save = readb(S3C2410_TICNT);
531
532 /* calculate time delta for suspend */
533
534 s3c2410_rtc_gettime(&tm);
535 rtc_tm_to_time(&tm, &time.tv_sec);
536 save_time_delta(&s3c2410_rtc_delta, &time);
537 s3c2410_rtc_enable(pdev, 0);
538
539 return 0;
540}
541
542static int s3c2410_rtc_resume(struct platform_device *pdev)
543{
544 struct rtc_time tm;
545 struct timespec time;
546
547 time.tv_nsec = 0;
548
549 s3c2410_rtc_enable(pdev, 1);
550 s3c2410_rtc_gettime(&tm);
551 rtc_tm_to_time(&tm, &time.tv_sec);
552 restore_time_delta(&s3c2410_rtc_delta, &time);
553
554 writeb(ticnt_save, S3C2410_TICNT);
555 return 0;
556}
557#else
558#define s3c2410_rtc_suspend NULL
559#define s3c2410_rtc_resume NULL
560#endif
561
562static struct platform_driver s3c2410_rtcdrv = {
563 .probe = s3c2410_rtc_probe,
564 .remove = s3c2410_rtc_remove,
565 .suspend = s3c2410_rtc_suspend,
566 .resume = s3c2410_rtc_resume,
567 .driver = {
568 .name = "s3c2410-rtc",
569 .owner = THIS_MODULE,
570 },
571};
572
573static char __initdata banner[] = "S3C2410 RTC, (c) 2004 Simtec Electronics\n";
574
575static int __init s3c2410_rtc_init(void)
576{
577 printk(banner);
578 return platform_driver_register(&s3c2410_rtcdrv);
579}
580
581static void __exit s3c2410_rtc_exit(void)
582{
583 platform_driver_unregister(&s3c2410_rtcdrv);
584}
585
586module_init(s3c2410_rtc_init);
587module_exit(s3c2410_rtc_exit);
588
589MODULE_DESCRIPTION("S3C24XX RTC Driver");
590MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
591MODULE_LICENSE("GPL");
diff --git a/drivers/char/scx200_gpio.c b/drivers/char/scx200_gpio.c
index b956c7babd18..99e5272e3c53 100644
--- a/drivers/char/scx200_gpio.c
+++ b/drivers/char/scx200_gpio.c
@@ -44,7 +44,7 @@ struct nsc_gpio_ops scx200_gpio_ops = {
44 .gpio_change = scx200_gpio_change, 44 .gpio_change = scx200_gpio_change,
45 .gpio_current = scx200_gpio_current 45 .gpio_current = scx200_gpio_current
46}; 46};
47EXPORT_SYMBOL(scx200_gpio_ops); 47EXPORT_SYMBOL_GPL(scx200_gpio_ops);
48 48
49static int scx200_gpio_open(struct inode *inode, struct file *file) 49static int scx200_gpio_open(struct inode *inode, struct file *file)
50{ 50{
@@ -69,7 +69,7 @@ static const struct file_operations scx200_gpio_fileops = {
69 .release = scx200_gpio_release, 69 .release = scx200_gpio_release,
70}; 70};
71 71
72struct cdev scx200_gpio_cdev; /* use 1 cdev for all pins */ 72static struct cdev scx200_gpio_cdev; /* use 1 cdev for all pins */
73 73
74static int __init scx200_gpio_init(void) 74static int __init scx200_gpio_init(void)
75{ 75{
diff --git a/drivers/char/selection.c b/drivers/char/selection.c
index 71093a9fc462..74cff839c857 100644
--- a/drivers/char/selection.c
+++ b/drivers/char/selection.c
@@ -33,7 +33,7 @@ extern void poke_blanked_console(void);
33 33
34/* Variables for selection control. */ 34/* Variables for selection control. */
35/* Use a dynamic buffer, instead of static (Dec 1994) */ 35/* Use a dynamic buffer, instead of static (Dec 1994) */
36struct vc_data *sel_cons; /* must not be disallocated */ 36struct vc_data *sel_cons; /* must not be deallocated */
37static volatile int sel_start = -1; /* cleared by clear_selection */ 37static volatile int sel_start = -1; /* cleared by clear_selection */
38static int sel_end; 38static int sel_end;
39static int sel_buffer_lth; 39static int sel_buffer_lth;
diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c
index 510bd3e0e88b..65c751d0d643 100644
--- a/drivers/char/ser_a2232.c
+++ b/drivers/char/ser_a2232.c
@@ -661,7 +661,7 @@ static void a2232_init_portstructs(void)
661 } 661 }
662} 662}
663 663
664static struct tty_operations a2232_ops = { 664static const struct tty_operations a2232_ops = {
665 .open = a2232_open, 665 .open = a2232_open,
666 .close = gs_close, 666 .close = gs_close,
667 .write = gs_write, 667 .write = gs_write,
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c
index 21a710cb4bba..b4ea1266b663 100644
--- a/drivers/char/serial167.c
+++ b/drivers/char/serial167.c
@@ -2158,7 +2158,7 @@ mvme167_serial_console_setup(int cflag)
2158 rcor >> 5, rbpr); 2158 rcor >> 5, rbpr);
2159} /* serial_console_init */ 2159} /* serial_console_init */
2160 2160
2161static struct tty_operations cy_ops = { 2161static const struct tty_operations cy_ops = {
2162 .open = cy_open, 2162 .open = cy_open,
2163 .close = cy_close, 2163 .close = cy_close,
2164 .write = cy_write, 2164 .write = cy_write,
diff --git a/drivers/char/snsc_event.c b/drivers/char/snsc_event.c
index d12d4f629cec..864854c58866 100644
--- a/drivers/char/snsc_event.c
+++ b/drivers/char/snsc_event.c
@@ -220,7 +220,7 @@ scdrv_dispatch_event(char *event, int len)
220 " Sending SIGPWR to init...\n"); 220 " Sending SIGPWR to init...\n");
221 221
222 /* give a SIGPWR signal to init proc */ 222 /* give a SIGPWR signal to init proc */
223 kill_proc(1, SIGPWR, 0); 223 kill_cad_pid(SIGPWR, 0);
224 } else { 224 } else {
225 /* print to system log */ 225 /* print to system log */
226 printk("%s|$(0x%x)%s\n", severity, esp_code, desc); 226 printk("%s|$(0x%x)%s\n", severity, esp_code, desc);
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index a1d303f9a33d..902c48dca3bc 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -182,7 +182,6 @@ static int sx_poll = HZ;
182#define RS_EVENT_WRITE_WAKEUP 0 182#define RS_EVENT_WRITE_WAKEUP 0
183 183
184static struct tty_driver *specialix_driver; 184static struct tty_driver *specialix_driver;
185static unsigned char * tmp_buf;
186 185
187static unsigned long baud_table[] = { 186static unsigned long baud_table[] = {
188 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 187 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
@@ -1087,24 +1086,16 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
1087 port->MSVR = (sx_in(bp, CD186x_MSVR) & MSVR_RTS); 1086 port->MSVR = (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
1088 spin_unlock_irqrestore(&bp->lock, flags); 1087 spin_unlock_irqrestore(&bp->lock, flags);
1089 dprintk (SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR); 1088 dprintk (SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR);
1090 baud = C_BAUD(tty); 1089 baud = tty_get_baud_rate(tty);
1091 1090
1092 if (baud & CBAUDEX) { 1091 if (baud == 38400) {
1093 baud &= ~CBAUDEX;
1094 if (baud < 1 || baud > 2)
1095 port->tty->termios->c_cflag &= ~CBAUDEX;
1096 else
1097 baud += 15;
1098 }
1099 if (baud == 15) {
1100 if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) 1092 if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
1101 baud ++; 1093 baud ++;
1102 if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) 1094 if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
1103 baud += 2; 1095 baud += 2;
1104 } 1096 }
1105 1097
1106 1098 if (!baud) {
1107 if (!baud_table[baud]) {
1108 /* Drop DTR & exit */ 1099 /* Drop DTR & exit */
1109 dprintk (SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n"); 1100 dprintk (SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n");
1110 if (!SX_CRTSCTS (tty)) { 1101 if (!SX_CRTSCTS (tty)) {
@@ -1134,7 +1125,7 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
1134 "This is an untested option, please be carefull.\n", 1125 "This is an untested option, please be carefull.\n",
1135 port_No (port), tmp); 1126 port_No (port), tmp);
1136 else 1127 else
1137 tmp = (((SX_OSCFREQ + baud_table[baud]/2) / baud_table[baud] + 1128 tmp = (((SX_OSCFREQ + baud/2) / baud +
1138 CD186x_TPC/2) / CD186x_TPC); 1129 CD186x_TPC/2) / CD186x_TPC);
1139 1130
1140 if ((tmp < 0x10) && time_before(again, jiffies)) { 1131 if ((tmp < 0x10) && time_before(again, jiffies)) {
@@ -1682,7 +1673,7 @@ static int sx_write(struct tty_struct * tty,
1682 1673
1683 bp = port_Board(port); 1674 bp = port_Board(port);
1684 1675
1685 if (!port->xmit_buf || !tmp_buf) { 1676 if (!port->xmit_buf) {
1686 func_exit(); 1677 func_exit();
1687 return 0; 1678 return 0;
1688 } 1679 }
@@ -2372,7 +2363,7 @@ static void do_softint(void *private_)
2372 func_exit(); 2363 func_exit();
2373} 2364}
2374 2365
2375static struct tty_operations sx_ops = { 2366static const struct tty_operations sx_ops = {
2376 .open = sx_open, 2367 .open = sx_open,
2377 .close = sx_close, 2368 .close = sx_close,
2378 .write = sx_write, 2369 .write = sx_write,
@@ -2406,12 +2397,6 @@ static int sx_init_drivers(void)
2406 return 1; 2397 return 1;
2407 } 2398 }
2408 2399
2409 if (!(tmp_buf = (unsigned char *) get_zeroed_page(GFP_KERNEL))) {
2410 printk(KERN_ERR "sx: Couldn't get free page.\n");
2411 put_tty_driver(specialix_driver);
2412 func_exit();
2413 return 1;
2414 }
2415 specialix_driver->owner = THIS_MODULE; 2400 specialix_driver->owner = THIS_MODULE;
2416 specialix_driver->name = "ttyW"; 2401 specialix_driver->name = "ttyW";
2417 specialix_driver->major = SPECIALIX_NORMAL_MAJOR; 2402 specialix_driver->major = SPECIALIX_NORMAL_MAJOR;
@@ -2425,7 +2410,6 @@ static int sx_init_drivers(void)
2425 2410
2426 if ((error = tty_register_driver(specialix_driver))) { 2411 if ((error = tty_register_driver(specialix_driver))) {
2427 put_tty_driver(specialix_driver); 2412 put_tty_driver(specialix_driver);
2428 free_page((unsigned long)tmp_buf);
2429 printk(KERN_ERR "sx: Couldn't register specialix IO8+ driver, error = %d\n", 2413 printk(KERN_ERR "sx: Couldn't register specialix IO8+ driver, error = %d\n",
2430 error); 2414 error);
2431 func_exit(); 2415 func_exit();
@@ -2451,7 +2435,6 @@ static void sx_release_drivers(void)
2451{ 2435{
2452 func_enter(); 2436 func_enter();
2453 2437
2454 free_page((unsigned long)tmp_buf);
2455 tty_unregister_driver(specialix_driver); 2438 tty_unregister_driver(specialix_driver);
2456 put_tty_driver(specialix_driver); 2439 put_tty_driver(specialix_driver);
2457 func_exit(); 2440 func_exit();
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 3beb2203d24b..bd711537ec4e 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -2993,7 +2993,7 @@ static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, uns
2993 return(rc); 2993 return(rc);
2994} 2994}
2995 2995
2996static struct tty_operations stl_ops = { 2996static const struct tty_operations stl_ops = {
2997 .open = stl_open, 2997 .open = stl_open,
2998 .close = stl_close, 2998 .close = stl_close,
2999 .write = stl_write, 2999 .write = stl_write,
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index e1cd2bc4b1e4..57e31e5eaedb 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -2226,7 +2226,7 @@ static int probe_si (struct sx_board *board)
2226 return 1; 2226 return 1;
2227} 2227}
2228 2228
2229static struct tty_operations sx_ops = { 2229static const struct tty_operations sx_ops = {
2230 .break_ctl = sx_break, 2230 .break_ctl = sx_break,
2231 .open = sx_open, 2231 .open = sx_open,
2232 .close = gs_close, 2232 .close = gs_close,
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index 78b1b1a2732b..38d94987de83 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -87,7 +87,6 @@
87 87
88#include <linux/vmalloc.h> 88#include <linux/vmalloc.h>
89#include <linux/init.h> 89#include <linux/init.h>
90#include <asm/serial.h>
91 90
92#include <linux/delay.h> 91#include <linux/delay.h>
93#include <linux/ioctl.h> 92#include <linux/ioctl.h>
@@ -4360,7 +4359,7 @@ static struct mgsl_struct* mgsl_allocate_device(void)
4360 4359
4361} /* end of mgsl_allocate_device()*/ 4360} /* end of mgsl_allocate_device()*/
4362 4361
4363static struct tty_operations mgsl_ops = { 4362static const struct tty_operations mgsl_ops = {
4364 .open = mgsl_open, 4363 .open = mgsl_open,
4365 .close = mgsl_close, 4364 .close = mgsl_close,
4366 .write = mgsl_write, 4365 .write = mgsl_write,
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 2f07b085536b..bdc7cb248b8f 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: synclink_gt.c,v 4.25 2006/02/06 21:20:33 paulkf Exp $ 2 * $Id: synclink_gt.c,v 4.36 2006/08/28 20:47:14 paulkf Exp $
3 * 3 *
4 * Device driver for Microgate SyncLink GT serial adapters. 4 * Device driver for Microgate SyncLink GT serial adapters.
5 * 5 *
@@ -91,12 +91,12 @@
91 * module identification 91 * module identification
92 */ 92 */
93static char *driver_name = "SyncLink GT"; 93static char *driver_name = "SyncLink GT";
94static char *driver_version = "$Revision: 4.25 $"; 94static char *driver_version = "$Revision: 4.36 $";
95static char *tty_driver_name = "synclink_gt"; 95static char *tty_driver_name = "synclink_gt";
96static char *tty_dev_prefix = "ttySLG"; 96static char *tty_dev_prefix = "ttySLG";
97MODULE_LICENSE("GPL"); 97MODULE_LICENSE("GPL");
98#define MGSL_MAGIC 0x5401 98#define MGSL_MAGIC 0x5401
99#define MAX_DEVICES 12 99#define MAX_DEVICES 32
100 100
101static struct pci_device_id pci_table[] = { 101static struct pci_device_id pci_table[] = {
102 {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, 102 {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
@@ -461,7 +461,7 @@ static int adapter_test(struct slgt_info *info);
461static void reset_adapter(struct slgt_info *info); 461static void reset_adapter(struct slgt_info *info);
462static void reset_port(struct slgt_info *info); 462static void reset_port(struct slgt_info *info);
463static void async_mode(struct slgt_info *info); 463static void async_mode(struct slgt_info *info);
464static void hdlc_mode(struct slgt_info *info); 464static void sync_mode(struct slgt_info *info);
465 465
466static void rx_stop(struct slgt_info *info); 466static void rx_stop(struct slgt_info *info);
467static void rx_start(struct slgt_info *info); 467static void rx_start(struct slgt_info *info);
@@ -881,7 +881,9 @@ static int write(struct tty_struct *tty,
881 if (!count) 881 if (!count)
882 goto cleanup; 882 goto cleanup;
883 883
884 if (info->params.mode == MGSL_MODE_RAW) { 884 if (info->params.mode == MGSL_MODE_RAW ||
885 info->params.mode == MGSL_MODE_MONOSYNC ||
886 info->params.mode == MGSL_MODE_BISYNC) {
885 unsigned int bufs_needed = (count/DMABUFSIZE); 887 unsigned int bufs_needed = (count/DMABUFSIZE);
886 unsigned int bufs_free = free_tbuf_count(info); 888 unsigned int bufs_free = free_tbuf_count(info);
887 if (count % DMABUFSIZE) 889 if (count % DMABUFSIZE)
@@ -1897,6 +1899,8 @@ static void bh_handler(void* context)
1897 while(rx_get_frame(info)); 1899 while(rx_get_frame(info));
1898 break; 1900 break;
1899 case MGSL_MODE_RAW: 1901 case MGSL_MODE_RAW:
1902 case MGSL_MODE_MONOSYNC:
1903 case MGSL_MODE_BISYNC:
1900 while(rx_get_buf(info)); 1904 while(rx_get_buf(info));
1901 break; 1905 break;
1902 } 1906 }
@@ -2362,10 +2366,9 @@ static void program_hw(struct slgt_info *info)
2362 rx_stop(info); 2366 rx_stop(info);
2363 tx_stop(info); 2367 tx_stop(info);
2364 2368
2365 if (info->params.mode == MGSL_MODE_HDLC || 2369 if (info->params.mode != MGSL_MODE_ASYNC ||
2366 info->params.mode == MGSL_MODE_RAW ||
2367 info->netcount) 2370 info->netcount)
2368 hdlc_mode(info); 2371 sync_mode(info);
2369 else 2372 else
2370 async_mode(info); 2373 async_mode(info);
2371 2374
@@ -2564,6 +2567,10 @@ static int rx_enable(struct slgt_info *info, int enable)
2564 if (enable) { 2567 if (enable) {
2565 if (!info->rx_enabled) 2568 if (!info->rx_enabled)
2566 rx_start(info); 2569 rx_start(info);
2570 else if (enable == 2) {
2571 /* force hunt mode (write 1 to RCR[3]) */
2572 wr_reg16(info, RCR, rd_reg16(info, RCR) | BIT3);
2573 }
2567 } else { 2574 } else {
2568 if (info->rx_enabled) 2575 if (info->rx_enabled)
2569 rx_stop(info); 2576 rx_stop(info);
@@ -3434,7 +3441,7 @@ static void __devexit remove_one(struct pci_dev *dev)
3434{ 3441{
3435} 3442}
3436 3443
3437static struct tty_operations ops = { 3444static const struct tty_operations ops = {
3438 .open = open, 3445 .open = open,
3439 .close = close, 3446 .close = close,
3440 .write = write, 3447 .write = write,
@@ -3748,7 +3755,7 @@ static void tx_start(struct slgt_info *info)
3748{ 3755{
3749 if (!info->tx_enabled) { 3756 if (!info->tx_enabled) {
3750 wr_reg16(info, TCR, 3757 wr_reg16(info, TCR,
3751 (unsigned short)(rd_reg16(info, TCR) | BIT1)); 3758 (unsigned short)((rd_reg16(info, TCR) | BIT1) & ~BIT2));
3752 info->tx_enabled = TRUE; 3759 info->tx_enabled = TRUE;
3753 } 3760 }
3754 3761
@@ -3775,13 +3782,18 @@ static void tx_start(struct slgt_info *info)
3775 tdma_reset(info); 3782 tdma_reset(info);
3776 /* set 1st descriptor address */ 3783 /* set 1st descriptor address */
3777 wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc); 3784 wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc);
3778 if (info->params.mode == MGSL_MODE_RAW) 3785 switch(info->params.mode) {
3786 case MGSL_MODE_RAW:
3787 case MGSL_MODE_MONOSYNC:
3788 case MGSL_MODE_BISYNC:
3779 wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */ 3789 wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */
3780 else 3790 break;
3791 default:
3781 wr_reg32(info, TDCSR, BIT0); /* DMA enable */ 3792 wr_reg32(info, TDCSR, BIT0); /* DMA enable */
3793 }
3782 } 3794 }
3783 3795
3784 if (info->params.mode != MGSL_MODE_RAW) { 3796 if (info->params.mode == MGSL_MODE_HDLC) {
3785 info->tx_timer.expires = jiffies + msecs_to_jiffies(5000); 3797 info->tx_timer.expires = jiffies + msecs_to_jiffies(5000);
3786 add_timer(&info->tx_timer); 3798 add_timer(&info->tx_timer);
3787 } 3799 }
@@ -3814,7 +3826,6 @@ static void tx_stop(struct slgt_info *info)
3814 /* reset and disable transmitter */ 3826 /* reset and disable transmitter */
3815 val = rd_reg16(info, TCR) & ~BIT1; /* clear enable bit */ 3827 val = rd_reg16(info, TCR) & ~BIT1; /* clear enable bit */
3816 wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */ 3828 wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */
3817 wr_reg16(info, TCR, val); /* clear reset */
3818 3829
3819 slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER); 3830 slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER);
3820 3831
@@ -3982,7 +3993,7 @@ static void async_mode(struct slgt_info *info)
3982 enable_loopback(info); 3993 enable_loopback(info);
3983} 3994}
3984 3995
3985static void hdlc_mode(struct slgt_info *info) 3996static void sync_mode(struct slgt_info *info)
3986{ 3997{
3987 unsigned short val; 3998 unsigned short val;
3988 3999
@@ -3992,7 +4003,7 @@ static void hdlc_mode(struct slgt_info *info)
3992 4003
3993 /* TCR (tx control) 4004 /* TCR (tx control)
3994 * 4005 *
3995 * 15..13 mode, 000=HDLC 001=raw sync 4006 * 15..13 mode, 000=HDLC 001=raw 010=async 011=monosync 100=bisync
3996 * 12..10 encoding 4007 * 12..10 encoding
3997 * 09 CRC enable 4008 * 09 CRC enable
3998 * 08 CRC32 4009 * 08 CRC32
@@ -4006,8 +4017,11 @@ static void hdlc_mode(struct slgt_info *info)
4006 */ 4017 */
4007 val = 0; 4018 val = 0;
4008 4019
4009 if (info->params.mode == MGSL_MODE_RAW) 4020 switch(info->params.mode) {
4010 val |= BIT13; 4021 case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break;
4022 case MGSL_MODE_BISYNC: val |= BIT15; break;
4023 case MGSL_MODE_RAW: val |= BIT13; break;
4024 }
4011 if (info->if_mode & MGSL_INTERFACE_RTS_EN) 4025 if (info->if_mode & MGSL_INTERFACE_RTS_EN)
4012 val |= BIT7; 4026 val |= BIT7;
4013 4027
@@ -4058,7 +4072,7 @@ static void hdlc_mode(struct slgt_info *info)
4058 4072
4059 /* RCR (rx control) 4073 /* RCR (rx control)
4060 * 4074 *
4061 * 15..13 mode, 000=HDLC 001=raw sync 4075 * 15..13 mode, 000=HDLC 001=raw 010=async 011=monosync 100=bisync
4062 * 12..10 encoding 4076 * 12..10 encoding
4063 * 09 CRC enable 4077 * 09 CRC enable
4064 * 08 CRC32 4078 * 08 CRC32
@@ -4069,8 +4083,11 @@ static void hdlc_mode(struct slgt_info *info)
4069 */ 4083 */
4070 val = 0; 4084 val = 0;
4071 4085
4072 if (info->params.mode == MGSL_MODE_RAW) 4086 switch(info->params.mode) {
4073 val |= BIT13; 4087 case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break;
4088 case MGSL_MODE_BISYNC: val |= BIT15; break;
4089 case MGSL_MODE_RAW: val |= BIT13; break;
4090 }
4074 4091
4075 switch(info->params.encoding) 4092 switch(info->params.encoding)
4076 { 4093 {
@@ -4309,10 +4326,15 @@ static void free_rbufs(struct slgt_info *info, unsigned int i, unsigned int last
4309 while(!done) { 4326 while(!done) {
4310 /* reset current buffer for reuse */ 4327 /* reset current buffer for reuse */
4311 info->rbufs[i].status = 0; 4328 info->rbufs[i].status = 0;
4312 if (info->params.mode == MGSL_MODE_RAW) 4329 switch(info->params.mode) {
4330 case MGSL_MODE_RAW:
4331 case MGSL_MODE_MONOSYNC:
4332 case MGSL_MODE_BISYNC:
4313 set_desc_count(info->rbufs[i], info->raw_rx_size); 4333 set_desc_count(info->rbufs[i], info->raw_rx_size);
4314 else 4334 break;
4335 default:
4315 set_desc_count(info->rbufs[i], DMABUFSIZE); 4336 set_desc_count(info->rbufs[i], DMABUFSIZE);
4337 }
4316 4338
4317 if (i == last) 4339 if (i == last)
4318 done = 1; 4340 done = 1;
@@ -4477,13 +4499,24 @@ cleanup:
4477static int rx_get_buf(struct slgt_info *info) 4499static int rx_get_buf(struct slgt_info *info)
4478{ 4500{
4479 unsigned int i = info->rbuf_current; 4501 unsigned int i = info->rbuf_current;
4502 unsigned int count;
4480 4503
4481 if (!desc_complete(info->rbufs[i])) 4504 if (!desc_complete(info->rbufs[i]))
4482 return 0; 4505 return 0;
4483 DBGDATA(info, info->rbufs[i].buf, desc_count(info->rbufs[i]), "rx"); 4506 count = desc_count(info->rbufs[i]);
4484 DBGINFO(("rx_get_buf size=%d\n", desc_count(info->rbufs[i]))); 4507 switch(info->params.mode) {
4485 ldisc_receive_buf(info->tty, info->rbufs[i].buf, 4508 case MGSL_MODE_MONOSYNC:
4486 info->flag_buf, desc_count(info->rbufs[i])); 4509 case MGSL_MODE_BISYNC:
4510 /* ignore residue in byte synchronous modes */
4511 if (desc_residue(info->rbufs[i]))
4512 count--;
4513 break;
4514 }
4515 DBGDATA(info, info->rbufs[i].buf, count, "rx");
4516 DBGINFO(("rx_get_buf size=%d\n", count));
4517 if (count)
4518 ldisc_receive_buf(info->tty, info->rbufs[i].buf,
4519 info->flag_buf, count);
4487 free_rbufs(info, i, i); 4520 free_rbufs(info, i, i);
4488 return 1; 4521 return 1;
4489} 4522}
@@ -4549,8 +4582,13 @@ static void tx_load(struct slgt_info *info, const char *buf, unsigned int size)
4549 size -= count; 4582 size -= count;
4550 buf += count; 4583 buf += count;
4551 4584
4552 if (!size && info->params.mode != MGSL_MODE_RAW) 4585 /*
4553 set_desc_eof(*d, 1); /* HDLC: set EOF of last desc */ 4586 * set EOF bit for last buffer of HDLC frame or
4587 * for every buffer in raw mode
4588 */
4589 if ((!size && info->params.mode == MGSL_MODE_HDLC) ||
4590 info->params.mode == MGSL_MODE_RAW)
4591 set_desc_eof(*d, 1);
4554 else 4592 else
4555 set_desc_eof(*d, 0); 4593 set_desc_eof(*d, 0);
4556 4594
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index 66f3754fbbdf..6eb75dcd7961 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -3929,7 +3929,7 @@ void device_init(int adapter_num, struct pci_dev *pdev)
3929 } 3929 }
3930} 3930}
3931 3931
3932static struct tty_operations ops = { 3932static const struct tty_operations ops = {
3933 .open = open, 3933 .open = open,
3934 .close = close, 3934 .close = close,
3935 .write = write, 3935 .write = write,
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index ee3ca8f1768e..6b4d4d1e343d 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -113,6 +113,7 @@ static struct sysrq_key_op sysrq_crashdump_op = {
113static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs, 113static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs,
114 struct tty_struct *tty) 114 struct tty_struct *tty)
115{ 115{
116 lockdep_off();
116 local_irq_enable(); 117 local_irq_enable();
117 emergency_restart(); 118 emergency_restart();
118} 119}
@@ -208,7 +209,7 @@ static void send_sig_all(int sig)
208 struct task_struct *p; 209 struct task_struct *p;
209 210
210 for_each_process(p) { 211 for_each_process(p) {
211 if (p->mm && p->pid != 1) 212 if (p->mm && !is_init(p))
212 /* Not swapper, init nor kernel thread */ 213 /* Not swapper, init nor kernel thread */
213 force_sig(sig, p); 214 force_sig(sig, p);
214 } 215 }
diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c
index d30dc09dbbc9..9df0ca1be0e3 100644
--- a/drivers/char/tipar.c
+++ b/drivers/char/tipar.c
@@ -224,14 +224,16 @@ probe_ti_parallel(int minor)
224{ 224{
225 int i; 225 int i;
226 int seq[] = { 0x00, 0x20, 0x10, 0x30 }; 226 int seq[] = { 0x00, 0x20, 0x10, 0x30 };
227 int data;
227 228
228 for (i = 3; i >= 0; i--) { 229 for (i = 3; i >= 0; i--) {
229 outbyte(3, minor); 230 outbyte(3, minor);
230 outbyte(i, minor); 231 outbyte(i, minor);
231 udelay(delay); 232 udelay(delay);
233 data = inbyte(minor) & 0x30;
232 pr_debug("tipar: Probing -> %i: 0x%02x 0x%02x\n", i, 234 pr_debug("tipar: Probing -> %i: 0x%02x 0x%02x\n", i,
233 data & 0x30, seq[i]); 235 data, seq[i]);
234 if ((inbyte(minor) & 0x30) != seq[i]) { 236 if (data != seq[i]) {
235 outbyte(3, minor); 237 outbyte(3, minor);
236 return -1; 238 return -1;
237 } 239 }
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index bb0d9199e994..e90ea39c7c4b 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -129,6 +129,7 @@ LIST_HEAD(tty_drivers); /* linked list of tty drivers */
129/* Semaphore to protect creating and releasing a tty. This is shared with 129/* Semaphore to protect creating and releasing a tty. This is shared with
130 vt.c for deeply disgusting hack reasons */ 130 vt.c for deeply disgusting hack reasons */
131DEFINE_MUTEX(tty_mutex); 131DEFINE_MUTEX(tty_mutex);
132EXPORT_SYMBOL(tty_mutex);
132 133
133#ifdef CONFIG_UNIX98_PTYS 134#ifdef CONFIG_UNIX98_PTYS
134extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */ 135extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */
@@ -160,17 +161,11 @@ static void release_mem(struct tty_struct *tty, int idx);
160 * been initialized in any way but has been zeroed 161 * been initialized in any way but has been zeroed
161 * 162 *
162 * Locking: none 163 * Locking: none
163 * FIXME: use kzalloc
164 */ 164 */
165 165
166static struct tty_struct *alloc_tty_struct(void) 166static struct tty_struct *alloc_tty_struct(void)
167{ 167{
168 struct tty_struct *tty; 168 return kzalloc(sizeof(struct tty_struct), GFP_KERNEL);
169
170 tty = kmalloc(sizeof(struct tty_struct), GFP_KERNEL);
171 if (tty)
172 memset(tty, 0, sizeof(struct tty_struct));
173 return tty;
174} 169}
175 170
176static void tty_buffer_free_all(struct tty_struct *); 171static void tty_buffer_free_all(struct tty_struct *);
@@ -483,10 +478,9 @@ int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars,
483 tb->used += space; 478 tb->used += space;
484 copied += space; 479 copied += space;
485 chars += space; 480 chars += space;
486 } 481 /* There is a small chance that we need to split the data over
487 /* There is a small chance that we need to split the data over 482 several buffers. If this is the case we must loop */
488 several buffers. If this is the case we must loop */ 483 } while (unlikely(size > copied));
489 while (unlikely(size > copied));
490 return copied; 484 return copied;
491} 485}
492EXPORT_SYMBOL(tty_insert_flip_string); 486EXPORT_SYMBOL(tty_insert_flip_string);
@@ -521,10 +515,9 @@ int tty_insert_flip_string_flags(struct tty_struct *tty,
521 copied += space; 515 copied += space;
522 chars += space; 516 chars += space;
523 flags += space; 517 flags += space;
524 } 518 /* There is a small chance that we need to split the data over
525 /* There is a small chance that we need to split the data over 519 several buffers. If this is the case we must loop */
526 several buffers. If this is the case we must loop */ 520 } while (unlikely(size > copied));
527 while (unlikely(size > copied));
528 return copied; 521 return copied;
529} 522}
530EXPORT_SYMBOL(tty_insert_flip_string_flags); 523EXPORT_SYMBOL(tty_insert_flip_string_flags);
@@ -626,9 +619,9 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
626 619
627static void tty_set_termios_ldisc(struct tty_struct *tty, int num) 620static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
628{ 621{
629 down(&tty->termios_sem); 622 mutex_lock(&tty->termios_mutex);
630 tty->termios->c_line = num; 623 tty->termios->c_line = num;
631 up(&tty->termios_sem); 624 mutex_unlock(&tty->termios_mutex);
632} 625}
633 626
634/* 627/*
@@ -1346,9 +1339,9 @@ static void do_tty_hangup(void *data)
1346 */ 1339 */
1347 if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) 1340 if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS)
1348 { 1341 {
1349 down(&tty->termios_sem); 1342 mutex_lock(&tty->termios_mutex);
1350 *tty->termios = tty->driver->init_termios; 1343 *tty->termios = tty->driver->init_termios;
1351 up(&tty->termios_sem); 1344 mutex_unlock(&tty->termios_mutex);
1352 } 1345 }
1353 1346
1354 /* Defer ldisc switch */ 1347 /* Defer ldisc switch */
@@ -2072,8 +2065,9 @@ fail_no_mem:
2072 2065
2073 /* call the tty release_mem routine to clean out this slot */ 2066 /* call the tty release_mem routine to clean out this slot */
2074release_mem_out: 2067release_mem_out:
2075 printk(KERN_INFO "init_dev: ldisc open failed, " 2068 if (printk_ratelimit())
2076 "clearing slot %d\n", idx); 2069 printk(KERN_INFO "init_dev: ldisc open failed, "
2070 "clearing slot %d\n", idx);
2077 release_mem(tty, idx); 2071 release_mem(tty, idx);
2078 goto end_init; 2072 goto end_init;
2079} 2073}
@@ -2726,6 +2720,8 @@ static int tty_fasync(int fd, struct file * filp, int on)
2726 * Locking: 2720 * Locking:
2727 * Called functions take tty_ldisc_lock 2721 * Called functions take tty_ldisc_lock
2728 * current->signal->tty check is safe without locks 2722 * current->signal->tty check is safe without locks
2723 *
2724 * FIXME: may race normal receive processing
2729 */ 2725 */
2730 2726
2731static int tiocsti(struct tty_struct *tty, char __user *p) 2727static int tiocsti(struct tty_struct *tty, char __user *p)
@@ -2748,18 +2744,21 @@ static int tiocsti(struct tty_struct *tty, char __user *p)
2748 * @tty; tty 2744 * @tty; tty
2749 * @arg: user buffer for result 2745 * @arg: user buffer for result
2750 * 2746 *
2751 * Copies the kernel idea of the window size into the user buffer. No 2747 * Copies the kernel idea of the window size into the user buffer.
2752 * locking is done.
2753 * 2748 *
2754 * FIXME: Returning random values racing a window size set is wrong 2749 * Locking: tty->termios_sem is taken to ensure the winsize data
2755 * should lock here against that 2750 * is consistent.
2756 */ 2751 */
2757 2752
2758static int tiocgwinsz(struct tty_struct *tty, struct winsize __user * arg) 2753static int tiocgwinsz(struct tty_struct *tty, struct winsize __user * arg)
2759{ 2754{
2760 if (copy_to_user(arg, &tty->winsize, sizeof(*arg))) 2755 int err;
2761 return -EFAULT; 2756
2762 return 0; 2757 mutex_lock(&tty->termios_mutex);
2758 err = copy_to_user(arg, &tty->winsize, sizeof(*arg));
2759 mutex_unlock(&tty->termios_mutex);
2760
2761 return err ? -EFAULT: 0;
2763} 2762}
2764 2763
2765/** 2764/**
@@ -2772,12 +2771,11 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user * arg)
2772 * actually has driver level meaning and triggers a VC resize. 2771 * actually has driver level meaning and triggers a VC resize.
2773 * 2772 *
2774 * Locking: 2773 * Locking:
2775 * The console_sem is used to ensure we do not try and resize 2774 * Called function use the console_sem is used to ensure we do
2776 * the console twice at once. 2775 * not try and resize the console twice at once.
2777 * FIXME: Two racing size sets may leave the console and kernel 2776 * The tty->termios_sem is used to ensure we don't double
2778 * parameters disagreeing. Is this exploitable ? 2777 * resize and get confused. Lock order - tty->termios.sem before
2779 * FIXME: Random values racing a window size get is wrong 2778 * console sem
2780 * should lock here against that
2781 */ 2779 */
2782 2780
2783static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, 2781static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
@@ -2787,17 +2785,18 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
2787 2785
2788 if (copy_from_user(&tmp_ws, arg, sizeof(*arg))) 2786 if (copy_from_user(&tmp_ws, arg, sizeof(*arg)))
2789 return -EFAULT; 2787 return -EFAULT;
2788
2789 mutex_lock(&tty->termios_mutex);
2790 if (!memcmp(&tmp_ws, &tty->winsize, sizeof(*arg))) 2790 if (!memcmp(&tmp_ws, &tty->winsize, sizeof(*arg)))
2791 return 0; 2791 goto done;
2792
2792#ifdef CONFIG_VT 2793#ifdef CONFIG_VT
2793 if (tty->driver->type == TTY_DRIVER_TYPE_CONSOLE) { 2794 if (tty->driver->type == TTY_DRIVER_TYPE_CONSOLE) {
2794 int rc; 2795 if (vc_lock_resize(tty->driver_data, tmp_ws.ws_col,
2795 2796 tmp_ws.ws_row)) {
2796 acquire_console_sem(); 2797 mutex_unlock(&tty->termios_mutex);
2797 rc = vc_resize(tty->driver_data, tmp_ws.ws_col, tmp_ws.ws_row); 2798 return -ENXIO;
2798 release_console_sem(); 2799 }
2799 if (rc)
2800 return -ENXIO;
2801 } 2800 }
2802#endif 2801#endif
2803 if (tty->pgrp > 0) 2802 if (tty->pgrp > 0)
@@ -2806,6 +2805,8 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
2806 kill_pg(real_tty->pgrp, SIGWINCH, 1); 2805 kill_pg(real_tty->pgrp, SIGWINCH, 1);
2807 tty->winsize = tmp_ws; 2806 tty->winsize = tmp_ws;
2808 real_tty->winsize = tmp_ws; 2807 real_tty->winsize = tmp_ws;
2808done:
2809 mutex_unlock(&tty->termios_mutex);
2809 return 0; 2810 return 0;
2810} 2811}
2811 2812
@@ -2880,9 +2881,7 @@ static int fionbio(struct file *file, int __user *p)
2880 * Locking: 2881 * Locking:
2881 * Takes tasklist lock internally to walk sessions 2882 * Takes tasklist lock internally to walk sessions
2882 * Takes task_lock() when updating signal->tty 2883 * Takes task_lock() when updating signal->tty
2883 * 2884 * Takes tty_mutex() to protect tty instance
2884 * FIXME: tty_mutex is needed to protect signal->tty references.
2885 * FIXME: why task_lock on the signal->tty reference ??
2886 * 2885 *
2887 */ 2886 */
2888 2887
@@ -2917,9 +2916,11 @@ static int tiocsctty(struct tty_struct *tty, int arg)
2917 } else 2916 } else
2918 return -EPERM; 2917 return -EPERM;
2919 } 2918 }
2919 mutex_lock(&tty_mutex);
2920 task_lock(current); 2920 task_lock(current);
2921 current->signal->tty = tty; 2921 current->signal->tty = tty;
2922 task_unlock(current); 2922 task_unlock(current);
2923 mutex_unlock(&tty_mutex);
2923 current->signal->tty_old_pgrp = 0; 2924 current->signal->tty_old_pgrp = 0;
2924 tty->session = current->signal->session; 2925 tty->session = current->signal->session;
2925 tty->pgrp = process_group(current); 2926 tty->pgrp = process_group(current);
@@ -2959,8 +2960,6 @@ static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
2959 * permitted where the tty session is our session. 2960 * permitted where the tty session is our session.
2960 * 2961 *
2961 * Locking: None 2962 * Locking: None
2962 *
2963 * FIXME: current->signal->tty referencing is unsafe.
2964 */ 2963 */
2965 2964
2966static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p) 2965static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
@@ -3039,19 +3038,20 @@ static int tiocsetd(struct tty_struct *tty, int __user *p)
3039 * timed break functionality. 3038 * timed break functionality.
3040 * 3039 *
3041 * Locking: 3040 * Locking:
3042 * None 3041 * atomic_write_lock serializes
3043 * 3042 *
3044 * FIXME:
3045 * What if two overlap
3046 */ 3043 */
3047 3044
3048static int send_break(struct tty_struct *tty, unsigned int duration) 3045static int send_break(struct tty_struct *tty, unsigned int duration)
3049{ 3046{
3047 if (mutex_lock_interruptible(&tty->atomic_write_lock))
3048 return -EINTR;
3050 tty->driver->break_ctl(tty, -1); 3049 tty->driver->break_ctl(tty, -1);
3051 if (!signal_pending(current)) { 3050 if (!signal_pending(current)) {
3052 msleep_interruptible(duration); 3051 msleep_interruptible(duration);
3053 } 3052 }
3054 tty->driver->break_ctl(tty, 0); 3053 tty->driver->break_ctl(tty, 0);
3054 mutex_unlock(&tty->atomic_write_lock);
3055 if (signal_pending(current)) 3055 if (signal_pending(current))
3056 return -EINTR; 3056 return -EINTR;
3057 return 0; 3057 return 0;
@@ -3144,6 +3144,8 @@ int tty_ioctl(struct inode * inode, struct file * file,
3144 if (tty_paranoia_check(tty, inode, "tty_ioctl")) 3144 if (tty_paranoia_check(tty, inode, "tty_ioctl"))
3145 return -EINVAL; 3145 return -EINVAL;
3146 3146
3147 /* CHECKME: is this safe as one end closes ? */
3148
3147 real_tty = tty; 3149 real_tty = tty;
3148 if (tty->driver->type == TTY_DRIVER_TYPE_PTY && 3150 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
3149 tty->driver->subtype == PTY_TYPE_MASTER) 3151 tty->driver->subtype == PTY_TYPE_MASTER)
@@ -3580,7 +3582,7 @@ static void initialize_tty_struct(struct tty_struct *tty)
3580 tty_buffer_init(tty); 3582 tty_buffer_init(tty);
3581 INIT_WORK(&tty->buf.work, flush_to_ldisc, tty); 3583 INIT_WORK(&tty->buf.work, flush_to_ldisc, tty);
3582 init_MUTEX(&tty->buf.pty_sem); 3584 init_MUTEX(&tty->buf.pty_sem);
3583 init_MUTEX(&tty->termios_sem); 3585 mutex_init(&tty->termios_mutex);
3584 init_waitqueue_head(&tty->write_wait); 3586 init_waitqueue_head(&tty->write_wait);
3585 init_waitqueue_head(&tty->read_wait); 3587 init_waitqueue_head(&tty->read_wait);
3586 INIT_WORK(&tty->hangup_work, do_tty_hangup, tty); 3588 INIT_WORK(&tty->hangup_work, do_tty_hangup, tty);
@@ -3678,7 +3680,8 @@ void put_tty_driver(struct tty_driver *driver)
3678 kfree(driver); 3680 kfree(driver);
3679} 3681}
3680 3682
3681void tty_set_operations(struct tty_driver *driver, struct tty_operations *op) 3683void tty_set_operations(struct tty_driver *driver,
3684 const struct tty_operations *op)
3682{ 3685{
3683 driver->open = op->open; 3686 driver->open = op->open;
3684 driver->close = op->close; 3687 driver->close = op->close;
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index 4ad47d321bd4..3b6fa7b0be8b 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -20,6 +20,7 @@
20#include <linux/mm.h> 20#include <linux/mm.h>
21#include <linux/module.h> 21#include <linux/module.h>
22#include <linux/bitops.h> 22#include <linux/bitops.h>
23#include <linux/mutex.h>
23 24
24#include <asm/io.h> 25#include <asm/io.h>
25#include <asm/uaccess.h> 26#include <asm/uaccess.h>
@@ -131,7 +132,7 @@ static void change_termios(struct tty_struct * tty, struct termios * new_termios
131 132
132 /* FIXME: we need to decide on some locking/ordering semantics 133 /* FIXME: we need to decide on some locking/ordering semantics
133 for the set_termios notification eventually */ 134 for the set_termios notification eventually */
134 down(&tty->termios_sem); 135 mutex_lock(&tty->termios_mutex);
135 136
136 *tty->termios = *new_termios; 137 *tty->termios = *new_termios;
137 unset_locked_termios(tty->termios, &old_termios, tty->termios_locked); 138 unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
@@ -176,7 +177,7 @@ static void change_termios(struct tty_struct * tty, struct termios * new_termios
176 (ld->set_termios)(tty, &old_termios); 177 (ld->set_termios)(tty, &old_termios);
177 tty_ldisc_deref(ld); 178 tty_ldisc_deref(ld);
178 } 179 }
179 up(&tty->termios_sem); 180 mutex_unlock(&tty->termios_mutex);
180} 181}
181 182
182/** 183/**
@@ -284,13 +285,13 @@ static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
284{ 285{
285 struct sgttyb tmp; 286 struct sgttyb tmp;
286 287
287 down(&tty->termios_sem); 288 mutex_lock(&tty->termios_mutex);
288 tmp.sg_ispeed = 0; 289 tmp.sg_ispeed = 0;
289 tmp.sg_ospeed = 0; 290 tmp.sg_ospeed = 0;
290 tmp.sg_erase = tty->termios->c_cc[VERASE]; 291 tmp.sg_erase = tty->termios->c_cc[VERASE];
291 tmp.sg_kill = tty->termios->c_cc[VKILL]; 292 tmp.sg_kill = tty->termios->c_cc[VKILL];
292 tmp.sg_flags = get_sgflags(tty); 293 tmp.sg_flags = get_sgflags(tty);
293 up(&tty->termios_sem); 294 mutex_unlock(&tty->termios_mutex);
294 295
295 return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0; 296 return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
296} 297}
@@ -345,12 +346,12 @@ static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
345 if (copy_from_user(&tmp, sgttyb, sizeof(tmp))) 346 if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
346 return -EFAULT; 347 return -EFAULT;
347 348
348 down(&tty->termios_sem); 349 mutex_lock(&tty->termios_mutex);
349 termios = *tty->termios; 350 termios = *tty->termios;
350 termios.c_cc[VERASE] = tmp.sg_erase; 351 termios.c_cc[VERASE] = tmp.sg_erase;
351 termios.c_cc[VKILL] = tmp.sg_kill; 352 termios.c_cc[VKILL] = tmp.sg_kill;
352 set_sgflags(&termios, tmp.sg_flags); 353 set_sgflags(&termios, tmp.sg_flags);
353 up(&tty->termios_sem); 354 mutex_unlock(&tty->termios_mutex);
354 change_termios(tty, &termios); 355 change_termios(tty, &termios);
355 return 0; 356 return 0;
356} 357}
@@ -422,24 +423,28 @@ static int set_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
422 * 423 *
423 * Send a high priority character to the tty even if stopped 424 * Send a high priority character to the tty even if stopped
424 * 425 *
425 * Locking: none 426 * Locking: none for xchar method, write ordering for write method.
426 *
427 * FIXME: overlapping calls with start/stop tty lose state of tty
428 */ 427 */
429 428
430static void send_prio_char(struct tty_struct *tty, char ch) 429static int send_prio_char(struct tty_struct *tty, char ch)
431{ 430{
432 int was_stopped = tty->stopped; 431 int was_stopped = tty->stopped;
433 432
434 if (tty->driver->send_xchar) { 433 if (tty->driver->send_xchar) {
435 tty->driver->send_xchar(tty, ch); 434 tty->driver->send_xchar(tty, ch);
436 return; 435 return 0;
437 } 436 }
437
438 if (mutex_lock_interruptible(&tty->atomic_write_lock))
439 return -ERESTARTSYS;
440
438 if (was_stopped) 441 if (was_stopped)
439 start_tty(tty); 442 start_tty(tty);
440 tty->driver->write(tty, &ch, 1); 443 tty->driver->write(tty, &ch, 1);
441 if (was_stopped) 444 if (was_stopped)
442 stop_tty(tty); 445 stop_tty(tty);
446 mutex_unlock(&tty->atomic_write_lock);
447 return 0;
443} 448}
444 449
445int n_tty_ioctl(struct tty_struct * tty, struct file * file, 450int n_tty_ioctl(struct tty_struct * tty, struct file * file,
@@ -513,11 +518,11 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
513 break; 518 break;
514 case TCIOFF: 519 case TCIOFF:
515 if (STOP_CHAR(tty) != __DISABLED_CHAR) 520 if (STOP_CHAR(tty) != __DISABLED_CHAR)
516 send_prio_char(tty, STOP_CHAR(tty)); 521 return send_prio_char(tty, STOP_CHAR(tty));
517 break; 522 break;
518 case TCION: 523 case TCION:
519 if (START_CHAR(tty) != __DISABLED_CHAR) 524 if (START_CHAR(tty) != __DISABLED_CHAR)
520 send_prio_char(tty, START_CHAR(tty)); 525 return send_prio_char(tty, START_CHAR(tty));
521 break; 526 break;
522 default: 527 default:
523 return -EINVAL; 528 return -EINVAL;
@@ -592,11 +597,11 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
592 case TIOCSSOFTCAR: 597 case TIOCSSOFTCAR:
593 if (get_user(arg, (unsigned int __user *) arg)) 598 if (get_user(arg, (unsigned int __user *) arg))
594 return -EFAULT; 599 return -EFAULT;
595 down(&tty->termios_sem); 600 mutex_lock(&tty->termios_mutex);
596 tty->termios->c_cflag = 601 tty->termios->c_cflag =
597 ((tty->termios->c_cflag & ~CLOCAL) | 602 ((tty->termios->c_cflag & ~CLOCAL) |
598 (arg ? CLOCAL : 0)); 603 (arg ? CLOCAL : 0));
599 up(&tty->termios_sem); 604 mutex_unlock(&tty->termios_mutex);
600 return 0; 605 return 0;
601 default: 606 default:
602 return -ENOIOCTLCMD; 607 return -ENOIOCTLCMD;
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index a9247b5213d5..bd7a98c6ea7a 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -474,14 +474,15 @@ static const struct file_operations vcs_fops = {
474 474
475static struct class *vc_class; 475static struct class *vc_class;
476 476
477void vcs_make_devfs(struct tty_struct *tty) 477void vcs_make_sysfs(struct tty_struct *tty)
478{ 478{
479 class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1), 479 class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1),
480 NULL, "vcs%u", tty->index + 1); 480 NULL, "vcs%u", tty->index + 1);
481 class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129), 481 class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129),
482 NULL, "vcsa%u", tty->index + 1); 482 NULL, "vcsa%u", tty->index + 1);
483} 483}
484void vcs_remove_devfs(struct tty_struct *tty) 484
485void vcs_remove_sysfs(struct tty_struct *tty)
485{ 486{
486 class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 1)); 487 class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 1));
487 class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 129)); 488 class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 129));
diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c
index f3efeaf2826e..a362ee9c92dd 100644
--- a/drivers/char/viocons.c
+++ b/drivers/char/viocons.c
@@ -1047,7 +1047,7 @@ static int send_open(HvLpIndex remoteLp, void *sem)
1047 0, 0, 0, 0); 1047 0, 0, 0, 0);
1048} 1048}
1049 1049
1050static struct tty_operations serial_ops = { 1050static const struct tty_operations serial_ops = {
1051 .open = viotty_open, 1051 .open = viotty_open,
1052 .close = viotty_close, 1052 .close = viotty_close,
1053 .write = viotty_write, 1053 .write = viotty_write,
diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c
index bfe5ea948f6a..c2ca31eb850b 100644
--- a/drivers/char/vme_scc.c
+++ b/drivers/char/vme_scc.c
@@ -113,7 +113,7 @@ static struct real_driver scc_real_driver = {
113}; 113};
114 114
115 115
116static struct tty_operations scc_ops = { 116static const struct tty_operations scc_ops = {
117 .open = scc_open, 117 .open = scc_open,
118 .close = gs_close, 118 .close = gs_close,
119 .write = gs_write, 119 .write = gs_write,
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index da7e66a2a38b..8e4413f6fbaf 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -63,6 +63,13 @@
63 * 63 *
64 * Removed console_lock, enabled interrupts across all console operations 64 * Removed console_lock, enabled interrupts across all console operations
65 * 13 March 2001, Andrew Morton 65 * 13 March 2001, Andrew Morton
66 *
67 * Fixed UTF-8 mode so alternate charset modes always work according
68 * to control sequences interpreted in do_con_trol function
69 * preserving backward VT100 semigraphics compatibility,
70 * malformed UTF sequences represented as sequences of replacement glyphs,
71 * original codes or '?' as a last resort if replacement glyph is undefined
72 * by Adam Tla/lka <atlka@pg.gda.pl>, Aug 2006
66 */ 73 */
67 74
68#include <linux/module.h> 75#include <linux/module.h>
@@ -99,7 +106,8 @@
99#define MAX_NR_CON_DRIVER 16 106#define MAX_NR_CON_DRIVER 16
100 107
101#define CON_DRIVER_FLAG_MODULE 1 108#define CON_DRIVER_FLAG_MODULE 1
102#define CON_DRIVER_FLAG_INIT 2 109#define CON_DRIVER_FLAG_INIT 2
110#define CON_DRIVER_FLAG_ATTR 4
103 111
104struct con_driver { 112struct con_driver {
105 const struct consw *con; 113 const struct consw *con;
@@ -128,16 +136,8 @@ const struct consw *conswitchp;
128#define DEFAULT_BELL_PITCH 750 136#define DEFAULT_BELL_PITCH 750
129#define DEFAULT_BELL_DURATION (HZ/8) 137#define DEFAULT_BELL_DURATION (HZ/8)
130 138
131extern void vcs_make_devfs(struct tty_struct *tty); 139extern void vcs_make_sysfs(struct tty_struct *tty);
132extern void vcs_remove_devfs(struct tty_struct *tty); 140extern void vcs_remove_sysfs(struct tty_struct *tty);
133
134extern void console_map_init(void);
135#ifdef CONFIG_PROM_CONSOLE
136extern void prom_con_init(void);
137#endif
138#ifdef CONFIG_MDA_CONSOLE
139extern int mda_console_init(void);
140#endif
141 141
142struct vc vc_cons [MAX_NR_CONSOLES]; 142struct vc vc_cons [MAX_NR_CONSOLES];
143 143
@@ -730,7 +730,8 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
730 visual_init(vc, currcons, 1); 730 visual_init(vc, currcons, 1);
731 if (!*vc->vc_uni_pagedir_loc) 731 if (!*vc->vc_uni_pagedir_loc)
732 con_set_default_unimap(vc); 732 con_set_default_unimap(vc);
733 vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL); 733 if (!vc->vc_kmalloced)
734 vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
734 if (!vc->vc_screenbuf) { 735 if (!vc->vc_screenbuf) {
735 kfree(vc); 736 kfree(vc);
736 vc_cons[currcons].d = NULL; 737 vc_cons[currcons].d = NULL;
@@ -878,14 +879,24 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
878 return err; 879 return err;
879} 880}
880 881
882int vc_lock_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
883{
884 int rc;
885
886 acquire_console_sem();
887 rc = vc_resize(vc, cols, lines);
888 release_console_sem();
889 return rc;
890}
881 891
882void vc_disallocate(unsigned int currcons) 892void vc_deallocate(unsigned int currcons)
883{ 893{
884 WARN_CONSOLE_UNLOCKED(); 894 WARN_CONSOLE_UNLOCKED();
885 895
886 if (vc_cons_allocated(currcons)) { 896 if (vc_cons_allocated(currcons)) {
887 struct vc_data *vc = vc_cons[currcons].d; 897 struct vc_data *vc = vc_cons[currcons].d;
888 vc->vc_sw->con_deinit(vc); 898 vc->vc_sw->con_deinit(vc);
899 put_pid(vc->vt_pid);
889 module_put(vc->vc_sw->owner); 900 module_put(vc->vc_sw->owner);
890 if (vc->vc_kmalloced) 901 if (vc->vc_kmalloced)
891 kfree(vc->vc_screenbuf); 902 kfree(vc->vc_screenbuf);
@@ -2005,17 +2016,23 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
2005 /* Do no translation at all in control states */ 2016 /* Do no translation at all in control states */
2006 if (vc->vc_state != ESnormal) { 2017 if (vc->vc_state != ESnormal) {
2007 tc = c; 2018 tc = c;
2008 } else if (vc->vc_utf) { 2019 } else if (vc->vc_utf && !vc->vc_disp_ctrl) {
2009 /* Combine UTF-8 into Unicode */ 2020 /* Combine UTF-8 into Unicode */
2010 /* Incomplete characters silently ignored */ 2021 /* Malformed sequences as sequences of replacement glyphs */
2022rescan_last_byte:
2011 if(c > 0x7f) { 2023 if(c > 0x7f) {
2012 if (vc->vc_utf_count > 0 && (c & 0xc0) == 0x80) { 2024 if (vc->vc_utf_count) {
2013 vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f); 2025 if ((c & 0xc0) == 0x80) {
2014 vc->vc_utf_count--; 2026 vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f);
2015 if (vc->vc_utf_count == 0) 2027 if (--vc->vc_utf_count) {
2016 tc = c = vc->vc_utf_char; 2028 vc->vc_npar++;
2017 else continue; 2029 continue;
2030 }
2031 tc = c = vc->vc_utf_char;
2032 } else
2033 goto replacement_glyph;
2018 } else { 2034 } else {
2035 vc->vc_npar = 0;
2019 if ((c & 0xe0) == 0xc0) { 2036 if ((c & 0xe0) == 0xc0) {
2020 vc->vc_utf_count = 1; 2037 vc->vc_utf_count = 1;
2021 vc->vc_utf_char = (c & 0x1f); 2038 vc->vc_utf_char = (c & 0x1f);
@@ -2032,14 +2049,15 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
2032 vc->vc_utf_count = 5; 2049 vc->vc_utf_count = 5;
2033 vc->vc_utf_char = (c & 0x01); 2050 vc->vc_utf_char = (c & 0x01);
2034 } else 2051 } else
2035 vc->vc_utf_count = 0; 2052 goto replacement_glyph;
2036 continue; 2053 continue;
2037 } 2054 }
2038 } else { 2055 } else {
2056 if (vc->vc_utf_count)
2057 goto replacement_glyph;
2039 tc = c; 2058 tc = c;
2040 vc->vc_utf_count = 0;
2041 } 2059 }
2042 } else { /* no utf */ 2060 } else { /* no utf or alternate charset mode */
2043 tc = vc->vc_translate[vc->vc_toggle_meta ? (c | 0x80) : c]; 2061 tc = vc->vc_translate[vc->vc_toggle_meta ? (c | 0x80) : c];
2044 } 2062 }
2045 2063
@@ -2054,31 +2072,33 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
2054 * direct-to-font zone in UTF-8 mode. 2072 * direct-to-font zone in UTF-8 mode.
2055 */ 2073 */
2056 ok = tc && (c >= 32 || 2074 ok = tc && (c >= 32 ||
2057 (!vc->vc_utf && !(((vc->vc_disp_ctrl ? CTRL_ALWAYS 2075 !(vc->vc_disp_ctrl ? (CTRL_ALWAYS >> c) & 1 :
2058 : CTRL_ACTION) >> c) & 1))) 2076 vc->vc_utf || ((CTRL_ACTION >> c) & 1)))
2059 && (c != 127 || vc->vc_disp_ctrl) 2077 && (c != 127 || vc->vc_disp_ctrl)
2060 && (c != 128+27); 2078 && (c != 128+27);
2061 2079
2062 if (vc->vc_state == ESnormal && ok) { 2080 if (vc->vc_state == ESnormal && ok) {
2063 /* Now try to find out how to display it */ 2081 /* Now try to find out how to display it */
2064 tc = conv_uni_to_pc(vc, tc); 2082 tc = conv_uni_to_pc(vc, tc);
2065 if ( tc == -4 ) { 2083 if (tc & ~charmask) {
2084 if ( tc == -4 ) {
2066 /* If we got -4 (not found) then see if we have 2085 /* If we got -4 (not found) then see if we have
2067 defined a replacement character (U+FFFD) */ 2086 defined a replacement character (U+FFFD) */
2068 tc = conv_uni_to_pc(vc, 0xfffd); 2087replacement_glyph:
2069 2088 tc = conv_uni_to_pc(vc, 0xfffd);
2070 /* One reason for the -4 can be that we just 2089 if (!(tc & ~charmask))
2071 did a clear_unimap(); 2090 goto display_glyph;
2072 try at least to show something. */ 2091 } else if ( tc != -3 )
2073 if (tc == -4) 2092 continue; /* nothing to display */
2074 tc = c; 2093 /* no hash table or no replacement --
2075 } else if ( tc == -3 ) { 2094 * hope for the best */
2076 /* Bad hash table -- hope for the best */ 2095 if ( c & ~charmask )
2077 tc = c; 2096 tc = '?';
2078 } 2097 else
2079 if (tc & ~charmask) 2098 tc = c;
2080 continue; /* Conversion failed */ 2099 }
2081 2100
2101display_glyph:
2082 if (vc->vc_need_wrap || vc->vc_decim) 2102 if (vc->vc_need_wrap || vc->vc_decim)
2083 FLUSH 2103 FLUSH
2084 if (vc->vc_need_wrap) { 2104 if (vc->vc_need_wrap) {
@@ -2102,6 +2122,15 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
2102 vc->vc_x++; 2122 vc->vc_x++;
2103 draw_to = (vc->vc_pos += 2); 2123 draw_to = (vc->vc_pos += 2);
2104 } 2124 }
2125 if (vc->vc_utf_count) {
2126 if (vc->vc_npar) {
2127 vc->vc_npar--;
2128 goto display_glyph;
2129 }
2130 vc->vc_utf_count = 0;
2131 c = orig;
2132 goto rescan_last_byte;
2133 }
2105 continue; 2134 continue;
2106 } 2135 }
2107 FLUSH 2136 FLUSH
@@ -2498,7 +2527,7 @@ static int con_open(struct tty_struct *tty, struct file *filp)
2498 tty->winsize.ws_col = vc_cons[currcons].d->vc_cols; 2527 tty->winsize.ws_col = vc_cons[currcons].d->vc_cols;
2499 } 2528 }
2500 release_console_sem(); 2529 release_console_sem();
2501 vcs_make_devfs(tty); 2530 vcs_make_sysfs(tty);
2502 return ret; 2531 return ret;
2503 } 2532 }
2504 } 2533 }
@@ -2511,7 +2540,7 @@ static int con_open(struct tty_struct *tty, struct file *filp)
2511 * and taking a ref against the tty while we're in the process of forgetting 2540 * and taking a ref against the tty while we're in the process of forgetting
2512 * about it and cleaning things up. 2541 * about it and cleaning things up.
2513 * 2542 *
2514 * This is because vcs_remove_devfs() can sleep and will drop the BKL. 2543 * This is because vcs_remove_sysfs() can sleep and will drop the BKL.
2515 */ 2544 */
2516static void con_close(struct tty_struct *tty, struct file *filp) 2545static void con_close(struct tty_struct *tty, struct file *filp)
2517{ 2546{
@@ -2524,7 +2553,7 @@ static void con_close(struct tty_struct *tty, struct file *filp)
2524 vc->vc_tty = NULL; 2553 vc->vc_tty = NULL;
2525 tty->driver_data = NULL; 2554 tty->driver_data = NULL;
2526 release_console_sem(); 2555 release_console_sem();
2527 vcs_remove_devfs(tty); 2556 vcs_remove_sysfs(tty);
2528 mutex_unlock(&tty_mutex); 2557 mutex_unlock(&tty_mutex);
2529 /* 2558 /*
2530 * tty_mutex is released, but we still hold BKL, so there is 2559 * tty_mutex is released, but we still hold BKL, so there is
@@ -2639,7 +2668,7 @@ static int __init con_init(void)
2639} 2668}
2640console_initcall(con_init); 2669console_initcall(con_init);
2641 2670
2642static struct tty_operations con_ops = { 2671static const struct tty_operations con_ops = {
2643 .open = con_open, 2672 .open = con_open,
2644 .close = con_close, 2673 .close = con_close,
2645 .write = con_write, 2674 .write = con_write,
@@ -3034,22 +3063,37 @@ static struct class_device_attribute class_device_attrs[] = {
3034static int vtconsole_init_class_device(struct con_driver *con) 3063static int vtconsole_init_class_device(struct con_driver *con)
3035{ 3064{
3036 int i; 3065 int i;
3066 int error = 0;
3037 3067
3068 con->flag |= CON_DRIVER_FLAG_ATTR;
3038 class_set_devdata(con->class_dev, con); 3069 class_set_devdata(con->class_dev, con);
3039 for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) 3070 for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) {
3040 class_device_create_file(con->class_dev, 3071 error = class_device_create_file(con->class_dev,
3041 &class_device_attrs[i]); 3072 &class_device_attrs[i]);
3073 if (error)
3074 break;
3075 }
3042 3076
3043 return 0; 3077 if (error) {
3078 while (--i >= 0)
3079 class_device_remove_file(con->class_dev,
3080 &class_device_attrs[i]);
3081 con->flag &= ~CON_DRIVER_FLAG_ATTR;
3082 }
3083
3084 return error;
3044} 3085}
3045 3086
3046static void vtconsole_deinit_class_device(struct con_driver *con) 3087static void vtconsole_deinit_class_device(struct con_driver *con)
3047{ 3088{
3048 int i; 3089 int i;
3049 3090
3050 for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) 3091 if (con->flag & CON_DRIVER_FLAG_ATTR) {
3051 class_device_remove_file(con->class_dev, 3092 for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
3052 &class_device_attrs[i]); 3093 class_device_remove_file(con->class_dev,
3094 &class_device_attrs[i]);
3095 con->flag &= ~CON_DRIVER_FLAG_ATTR;
3096 }
3053} 3097}
3054 3098
3055/** 3099/**
@@ -3148,6 +3192,7 @@ int register_con_driver(const struct consw *csw, int first, int last)
3148 } else { 3192 } else {
3149 vtconsole_init_class_device(con_driver); 3193 vtconsole_init_class_device(con_driver);
3150 } 3194 }
3195
3151err: 3196err:
3152 release_console_sem(); 3197 release_console_sem();
3153 module_put(owner); 3198 module_put(owner);
@@ -3765,6 +3810,7 @@ EXPORT_SYMBOL(default_blu);
3765EXPORT_SYMBOL(update_region); 3810EXPORT_SYMBOL(update_region);
3766EXPORT_SYMBOL(redraw_screen); 3811EXPORT_SYMBOL(redraw_screen);
3767EXPORT_SYMBOL(vc_resize); 3812EXPORT_SYMBOL(vc_resize);
3813EXPORT_SYMBOL(vc_lock_resize);
3768EXPORT_SYMBOL(fg_console); 3814EXPORT_SYMBOL(fg_console);
3769EXPORT_SYMBOL(console_blank_hook); 3815EXPORT_SYMBOL(console_blank_hook);
3770EXPORT_SYMBOL(console_blanked); 3816EXPORT_SYMBOL(console_blanked);
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index a5628a8b6620..ac5d60edbafa 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -96,7 +96,7 @@ do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm, struct kbd_str
96 if (!perm) 96 if (!perm)
97 return -EPERM; 97 return -EPERM;
98 if (!i && v == K_NOSUCHMAP) { 98 if (!i && v == K_NOSUCHMAP) {
99 /* disallocate map */ 99 /* deallocate map */
100 key_map = key_maps[s]; 100 key_map = key_maps[s];
101 if (s && key_map) { 101 if (s && key_map) {
102 key_maps[s] = NULL; 102 key_maps[s] = NULL;
@@ -645,13 +645,16 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
645 */ 645 */
646 case KDSIGACCEPT: 646 case KDSIGACCEPT:
647 { 647 {
648 extern int spawnpid, spawnsig;
649 if (!perm || !capable(CAP_KILL)) 648 if (!perm || !capable(CAP_KILL))
650 return -EPERM; 649 return -EPERM;
651 if (!valid_signal(arg) || arg < 1 || arg == SIGKILL) 650 if (!valid_signal(arg) || arg < 1 || arg == SIGKILL)
652 return -EINVAL; 651 return -EINVAL;
653 spawnpid = current->pid; 652
654 spawnsig = arg; 653 spin_lock_irq(&vt_spawn_con.lock);
654 put_pid(vt_spawn_con.pid);
655 vt_spawn_con.pid = get_pid(task_pid(current));
656 vt_spawn_con.sig = arg;
657 spin_unlock_irq(&vt_spawn_con.lock);
655 return 0; 658 return 0;
656 } 659 }
657 660
@@ -669,7 +672,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
669 vc->vt_mode = tmp; 672 vc->vt_mode = tmp;
670 /* the frsig is ignored, so we set it to 0 */ 673 /* the frsig is ignored, so we set it to 0 */
671 vc->vt_mode.frsig = 0; 674 vc->vt_mode.frsig = 0;
672 vc->vt_pid = current->pid; 675 put_pid(xchg(&vc->vt_pid, get_pid(task_pid(current))));
673 /* no switch is required -- saw@shade.msu.ru */ 676 /* no switch is required -- saw@shade.msu.ru */
674 vc->vt_newvt = -1; 677 vc->vt_newvt = -1;
675 release_console_sem(); 678 release_console_sem();
@@ -819,20 +822,20 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
819 if (arg > MAX_NR_CONSOLES) 822 if (arg > MAX_NR_CONSOLES)
820 return -ENXIO; 823 return -ENXIO;
821 if (arg == 0) { 824 if (arg == 0) {
822 /* disallocate all unused consoles, but leave 0 */ 825 /* deallocate all unused consoles, but leave 0 */
823 acquire_console_sem(); 826 acquire_console_sem();
824 for (i=1; i<MAX_NR_CONSOLES; i++) 827 for (i=1; i<MAX_NR_CONSOLES; i++)
825 if (! VT_BUSY(i)) 828 if (! VT_BUSY(i))
826 vc_disallocate(i); 829 vc_deallocate(i);
827 release_console_sem(); 830 release_console_sem();
828 } else { 831 } else {
829 /* disallocate a single console, if possible */ 832 /* deallocate a single console, if possible */
830 arg--; 833 arg--;
831 if (VT_BUSY(arg)) 834 if (VT_BUSY(arg))
832 return -EBUSY; 835 return -EBUSY;
833 if (arg) { /* leave 0 */ 836 if (arg) { /* leave 0 */
834 acquire_console_sem(); 837 acquire_console_sem();
835 vc_disallocate(arg); 838 vc_deallocate(arg);
836 release_console_sem(); 839 release_console_sem();
837 } 840 }
838 } 841 }
@@ -847,11 +850,8 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
847 if (get_user(ll, &vtsizes->v_rows) || 850 if (get_user(ll, &vtsizes->v_rows) ||
848 get_user(cc, &vtsizes->v_cols)) 851 get_user(cc, &vtsizes->v_cols))
849 return -EFAULT; 852 return -EFAULT;
850 for (i = 0; i < MAX_NR_CONSOLES; i++) { 853 for (i = 0; i < MAX_NR_CONSOLES; i++)
851 acquire_console_sem(); 854 vc_lock_resize(vc_cons[i].d, cc, ll);
852 vc_resize(vc_cons[i].d, cc, ll);
853 release_console_sem();
854 }
855 return 0; 855 return 0;
856 } 856 }
857 857
@@ -1063,7 +1063,7 @@ void reset_vc(struct vc_data *vc)
1063 vc->vt_mode.relsig = 0; 1063 vc->vt_mode.relsig = 0;
1064 vc->vt_mode.acqsig = 0; 1064 vc->vt_mode.acqsig = 0;
1065 vc->vt_mode.frsig = 0; 1065 vc->vt_mode.frsig = 0;
1066 vc->vt_pid = -1; 1066 put_pid(xchg(&vc->vt_pid, NULL));
1067 vc->vt_newvt = -1; 1067 vc->vt_newvt = -1;
1068 if (!in_interrupt()) /* Via keyboard.c:SAK() - akpm */ 1068 if (!in_interrupt()) /* Via keyboard.c:SAK() - akpm */
1069 reset_palette(vc); 1069 reset_palette(vc);
@@ -1114,7 +1114,7 @@ static void complete_change_console(struct vc_data *vc)
1114 * tell us if the process has gone or something else 1114 * tell us if the process has gone or something else
1115 * is awry 1115 * is awry
1116 */ 1116 */
1117 if (kill_proc(vc->vt_pid, vc->vt_mode.acqsig, 1) != 0) { 1117 if (kill_pid(vc->vt_pid, vc->vt_mode.acqsig, 1) != 0) {
1118 /* 1118 /*
1119 * The controlling process has died, so we revert back to 1119 * The controlling process has died, so we revert back to
1120 * normal operation. In this case, we'll also change back 1120 * normal operation. In this case, we'll also change back
@@ -1174,7 +1174,7 @@ void change_console(struct vc_data *new_vc)
1174 * tell us if the process has gone or something else 1174 * tell us if the process has gone or something else
1175 * is awry 1175 * is awry
1176 */ 1176 */
1177 if (kill_proc(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) { 1177 if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) {
1178 /* 1178 /*
1179 * It worked. Mark the vt to switch to and 1179 * It worked. Mark the vt to switch to and
1180 * return. The process needs to send us a 1180 * return. The process needs to send us a
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index fff89c2d88fd..89e46d6dfc4e 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -165,6 +165,24 @@ config EP93XX_WATCHDOG
165 To compile this driver as a module, choose M here: the 165 To compile this driver as a module, choose M here: the
166 module will be called ep93xx_wdt. 166 module will be called ep93xx_wdt.
167 167
168config OMAP_WATCHDOG
169 tristate "OMAP Watchdog"
170 depends on WATCHDOG && (ARCH_OMAP16XX || ARCH_OMAP24XX)
171 help
172 Support for TI OMAP1610/OMAP1710/OMAP2420 watchdog. Say 'Y' here to
173 enable the OMAP1610/OMAP1710 watchdog timer.
174
175config PNX4008_WATCHDOG
176 tristate "PNX4008 Watchdog"
177 depends on WATCHDOG && ARCH_PNX4008
178 help
179 Say Y here if to include support for the watchdog timer
180 in the PNX4008 processor.
181 This driver can be built as a module by choosing M. The module
182 will be called pnx4008_wdt.
183
184 Say N if you are unsure.
185
168# X86 (i386 + ia64 + x86_64) Architecture 186# X86 (i386 + ia64 + x86_64) Architecture
169 187
170config ACQUIRE_WDT 188config ACQUIRE_WDT
@@ -298,6 +316,27 @@ config I8XX_TCO
298 To compile this driver as a module, choose M here: the 316 To compile this driver as a module, choose M here: the
299 module will be called i8xx_tco. 317 module will be called i8xx_tco.
300 318
319config ITCO_WDT
320 tristate "Intel TCO Timer/Watchdog (EXPERIMENTAL)"
321 depends on WATCHDOG && (X86 || IA64) && PCI && EXPERIMENTAL
322 ---help---
323 Hardware driver for the intel TCO timer based watchdog devices.
324 These drivers are included in the Intel 82801 I/O Controller
325 Hub family 'from ICH0 up to ICH7) and in the Intel 6300ESB
326 controller hub.
327
328 The TCO (Total Cost of Ownership) timer is a watchdog timer
329 that will reboot the machine after its second expiration. The
330 expiration time can be configured with the "heartbeat" parameter.
331
332 On some motherboards the driver may fail to reset the chipset's
333 NO_REBOOT flag which prevents the watchdog from rebooting the
334 machine. If this is the case you will get a kernel message like
335 "failed to reset NO_REBOOT flag, reboot disabled by hardware".
336
337 To compile this driver as a module, choose M here: the
338 module will be called iTCO_wdt.
339
301config SC1200_WDT 340config SC1200_WDT
302 tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog" 341 tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog"
303 depends on WATCHDOG && X86 342 depends on WATCHDOG && X86
@@ -510,6 +549,14 @@ config SH_WDT
510 To compile this driver as a module, choose M here: the 549 To compile this driver as a module, choose M here: the
511 module will be called shwdt. 550 module will be called shwdt.
512 551
552config SH_WDT_MMAP
553 bool "Allow mmap of SH WDT"
554 default n
555 depends on SH_WDT
556 help
557 If you say Y here, user applications will be able to mmap the
558 WDT/CPG registers.
559#
513# SPARC64 Architecture 560# SPARC64 Architecture
514 561
515config WATCHDOG_CP1XXX 562config WATCHDOG_CP1XXX
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index 6ab77b61a643..7f70abad465a 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
24 24
25# ARM Architecture 25# ARM Architecture
26obj-$(CONFIG_AT91_WATCHDOG) += at91_wdt.o 26obj-$(CONFIG_AT91_WATCHDOG) += at91_wdt.o
27obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
27obj-$(CONFIG_21285_WATCHDOG) += wdt285.o 28obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
28obj-$(CONFIG_977_WATCHDOG) += wdt977.o 29obj-$(CONFIG_977_WATCHDOG) += wdt977.o
29obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o 30obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
@@ -32,6 +33,7 @@ obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o
32obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o 33obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
33obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o 34obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o
34obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o 35obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o
36obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o
35 37
36# X86 (i386 + ia64 + x86_64) Architecture 38# X86 (i386 + ia64 + x86_64) Architecture
37obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o 39obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
@@ -45,6 +47,7 @@ obj-$(CONFIG_IBMASR) += ibmasr.o
45obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o 47obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o
46obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o 48obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o
47obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o 49obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o
50obj-$(CONFIG_ITCO_WDT) += iTCO_wdt.o
48obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o 51obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
49obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o 52obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
50obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o 53obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o
diff --git a/drivers/char/watchdog/acquirewdt.c b/drivers/char/watchdog/acquirewdt.c
index c77fe3cf2852..154d67e591e5 100644
--- a/drivers/char/watchdog/acquirewdt.c
+++ b/drivers/char/watchdog/acquirewdt.c
@@ -183,7 +183,7 @@ static int acq_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
183 } 183 }
184 184
185 default: 185 default:
186 return -ENOIOCTLCMD; 186 return -ENOTTY;
187 } 187 }
188} 188}
189 189
diff --git a/drivers/char/watchdog/advantechwdt.c b/drivers/char/watchdog/advantechwdt.c
index 8069be445edc..9d732769ba01 100644
--- a/drivers/char/watchdog/advantechwdt.c
+++ b/drivers/char/watchdog/advantechwdt.c
@@ -176,7 +176,7 @@ advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
176 } 176 }
177 177
178 default: 178 default:
179 return -ENOIOCTLCMD; 179 return -ENOTTY;
180 } 180 }
181 return 0; 181 return 0;
182} 182}
diff --git a/drivers/char/watchdog/alim1535_wdt.c b/drivers/char/watchdog/alim1535_wdt.c
index c5c94e4c9495..01b0d132ee41 100644
--- a/drivers/char/watchdog/alim1535_wdt.c
+++ b/drivers/char/watchdog/alim1535_wdt.c
@@ -236,7 +236,7 @@ static int ali_ioctl(struct inode *inode, struct file *file,
236 return put_user(timeout, p); 236 return put_user(timeout, p);
237 237
238 default: 238 default:
239 return -ENOIOCTLCMD; 239 return -ENOTTY;
240 } 240 }
241} 241}
242 242
@@ -330,17 +330,20 @@ static int __init ali_find_watchdog(void)
330 u32 wdog; 330 u32 wdog;
331 331
332 /* Check for a 1535 series bridge */ 332 /* Check for a 1535 series bridge */
333 pdev = pci_find_device(PCI_VENDOR_ID_AL, 0x1535, NULL); 333 pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x1535, NULL);
334 if(pdev == NULL) 334 if(pdev == NULL)
335 return -ENODEV; 335 return -ENODEV;
336 pci_dev_put(pdev);
336 337
337 /* Check for the a 7101 PMU */ 338 /* Check for the a 7101 PMU */
338 pdev = pci_find_device(PCI_VENDOR_ID_AL, 0x7101, NULL); 339 pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x7101, NULL);
339 if(pdev == NULL) 340 if(pdev == NULL)
340 return -ENODEV; 341 return -ENODEV;
341 342
342 if(pci_enable_device(pdev)) 343 if(pci_enable_device(pdev)) {
344 pci_dev_put(pdev);
343 return -EIO; 345 return -EIO;
346 }
344 347
345 ali_pci = pdev; 348 ali_pci = pdev;
346 349
@@ -447,6 +450,7 @@ static void __exit watchdog_exit(void)
447 /* Deregister */ 450 /* Deregister */
448 unregister_reboot_notifier(&ali_notifier); 451 unregister_reboot_notifier(&ali_notifier);
449 misc_deregister(&ali_miscdev); 452 misc_deregister(&ali_miscdev);
453 pci_dev_put(ali_pci);
450} 454}
451 455
452module_init(watchdog_init); 456module_init(watchdog_init);
diff --git a/drivers/char/watchdog/alim7101_wdt.c b/drivers/char/watchdog/alim7101_wdt.c
index ffd7684f999b..5948863b592b 100644
--- a/drivers/char/watchdog/alim7101_wdt.c
+++ b/drivers/char/watchdog/alim7101_wdt.c
@@ -277,7 +277,7 @@ static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u
277 case WDIOC_GETTIMEOUT: 277 case WDIOC_GETTIMEOUT:
278 return put_user(timeout, p); 278 return put_user(timeout, p);
279 default: 279 default:
280 return -ENOIOCTLCMD; 280 return -ENOTTY;
281 } 281 }
282} 282}
283 283
@@ -333,6 +333,7 @@ static void __exit alim7101_wdt_unload(void)
333 /* Deregister */ 333 /* Deregister */
334 misc_deregister(&wdt_miscdev); 334 misc_deregister(&wdt_miscdev);
335 unregister_reboot_notifier(&wdt_notifier); 335 unregister_reboot_notifier(&wdt_notifier);
336 pci_dev_put(alim7101_pmu);
336} 337}
337 338
338static int __init alim7101_wdt_init(void) 339static int __init alim7101_wdt_init(void)
@@ -342,7 +343,8 @@ static int __init alim7101_wdt_init(void)
342 char tmp; 343 char tmp;
343 344
344 printk(KERN_INFO PFX "Steve Hill <steve@navaho.co.uk>.\n"); 345 printk(KERN_INFO PFX "Steve Hill <steve@navaho.co.uk>.\n");
345 alim7101_pmu = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,NULL); 346 alim7101_pmu = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,
347 NULL);
346 if (!alim7101_pmu) { 348 if (!alim7101_pmu) {
347 printk(KERN_INFO PFX "ALi M7101 PMU not present - WDT not set\n"); 349 printk(KERN_INFO PFX "ALi M7101 PMU not present - WDT not set\n");
348 return -EBUSY; 350 return -EBUSY;
@@ -351,21 +353,23 @@ static int __init alim7101_wdt_init(void)
351 /* Set the WDT in the PMU to 1 second */ 353 /* Set the WDT in the PMU to 1 second */
352 pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, 0x02); 354 pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, 0x02);
353 355
354 ali1543_south = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); 356 ali1543_south = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
357 NULL);
355 if (!ali1543_south) { 358 if (!ali1543_south) {
356 printk(KERN_INFO PFX "ALi 1543 South-Bridge not present - WDT not set\n"); 359 printk(KERN_INFO PFX "ALi 1543 South-Bridge not present - WDT not set\n");
357 return -EBUSY; 360 goto err_out;
358 } 361 }
359 pci_read_config_byte(ali1543_south, 0x5e, &tmp); 362 pci_read_config_byte(ali1543_south, 0x5e, &tmp);
363 pci_dev_put(ali1543_south);
360 if ((tmp & 0x1e) == 0x00) { 364 if ((tmp & 0x1e) == 0x00) {
361 if (!use_gpio) { 365 if (!use_gpio) {
362 printk(KERN_INFO PFX "Detected old alim7101 revision 'a1d'. If this is a cobalt board, set the 'use_gpio' module parameter.\n"); 366 printk(KERN_INFO PFX "Detected old alim7101 revision 'a1d'. If this is a cobalt board, set the 'use_gpio' module parameter.\n");
363 return -EBUSY; 367 goto err_out;
364 } 368 }
365 nowayout = 1; 369 nowayout = 1;
366 } else if ((tmp & 0x1e) != 0x12 && (tmp & 0x1e) != 0x00) { 370 } else if ((tmp & 0x1e) != 0x12 && (tmp & 0x1e) != 0x00) {
367 printk(KERN_INFO PFX "ALi 1543 South-Bridge does not have the correct revision number (???1001?) - WDT not set\n"); 371 printk(KERN_INFO PFX "ALi 1543 South-Bridge does not have the correct revision number (???1001?) - WDT not set\n");
368 return -EBUSY; 372 goto err_out;
369 } 373 }
370 374
371 if(timeout < 1 || timeout > 3600) /* arbitrary upper limit */ 375 if(timeout < 1 || timeout > 3600) /* arbitrary upper limit */
@@ -404,6 +408,7 @@ static int __init alim7101_wdt_init(void)
404err_out_miscdev: 408err_out_miscdev:
405 misc_deregister(&wdt_miscdev); 409 misc_deregister(&wdt_miscdev);
406err_out: 410err_out:
411 pci_dev_put(alim7101_pmu);
407 return rc; 412 return rc;
408} 413}
409 414
diff --git a/drivers/char/watchdog/at91_wdt.c b/drivers/char/watchdog/at91_wdt.c
index cc266715ea32..4e7a1145e78f 100644
--- a/drivers/char/watchdog/at91_wdt.c
+++ b/drivers/char/watchdog/at91_wdt.c
@@ -168,7 +168,7 @@ static int at91_wdt_ioctl(struct inode *inode, struct file *file,
168 return 0; 168 return 0;
169 169
170 default: 170 default:
171 return -ENOIOCTLCMD; 171 return -ENOTTY;
172 } 172 }
173} 173}
174 174
diff --git a/drivers/char/watchdog/booke_wdt.c b/drivers/char/watchdog/booke_wdt.c
index e3cefc538b40..488902231cc2 100644
--- a/drivers/char/watchdog/booke_wdt.c
+++ b/drivers/char/watchdog/booke_wdt.c
@@ -125,7 +125,7 @@ static int booke_wdt_ioctl (struct inode *inode, struct file *file,
125 return -EINVAL; 125 return -EINVAL;
126 return 0; 126 return 0;
127 default: 127 default:
128 return -ENOIOCTLCMD; 128 return -ENOTTY;
129 } 129 }
130 130
131 return 0; 131 return 0;
diff --git a/drivers/char/watchdog/cpu5wdt.c b/drivers/char/watchdog/cpu5wdt.c
index 04c7e49918db..00bdabb90f27 100644
--- a/drivers/char/watchdog/cpu5wdt.c
+++ b/drivers/char/watchdog/cpu5wdt.c
@@ -183,7 +183,7 @@ static int cpu5wdt_ioctl(struct inode *inode, struct file *file, unsigned int cm
183 } 183 }
184 break; 184 break;
185 default: 185 default:
186 return -ENOIOCTLCMD; 186 return -ENOTTY;
187 } 187 }
188 return 0; 188 return 0;
189} 189}
diff --git a/drivers/char/watchdog/ep93xx_wdt.c b/drivers/char/watchdog/ep93xx_wdt.c
index 77c8a955ae9e..01cf123b1616 100644
--- a/drivers/char/watchdog/ep93xx_wdt.c
+++ b/drivers/char/watchdog/ep93xx_wdt.c
@@ -144,7 +144,7 @@ static int
144ep93xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 144ep93xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
145 unsigned long arg) 145 unsigned long arg)
146{ 146{
147 int ret = -ENOIOCTLCMD; 147 int ret = -ENOTTY;
148 148
149 switch (cmd) { 149 switch (cmd) {
150 case WDIOC_GETSUPPORT: 150 case WDIOC_GETSUPPORT:
diff --git a/drivers/char/watchdog/eurotechwdt.c b/drivers/char/watchdog/eurotechwdt.c
index 62dbccb2f6df..4f4269754c46 100644
--- a/drivers/char/watchdog/eurotechwdt.c
+++ b/drivers/char/watchdog/eurotechwdt.c
@@ -240,7 +240,7 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file,
240 240
241 switch(cmd) { 241 switch(cmd) {
242 default: 242 default:
243 return -ENOIOCTLCMD; 243 return -ENOTTY;
244 244
245 case WDIOC_GETSUPPORT: 245 case WDIOC_GETSUPPORT:
246 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; 246 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
diff --git a/drivers/char/watchdog/i6300esb.c b/drivers/char/watchdog/i6300esb.c
index 870539eabbf3..fb64df4d7c87 100644
--- a/drivers/char/watchdog/i6300esb.c
+++ b/drivers/char/watchdog/i6300esb.c
@@ -315,7 +315,7 @@ static int esb_ioctl (struct inode *inode, struct file *file,
315 return put_user(heartbeat, p); 315 return put_user(heartbeat, p);
316 316
317 default: 317 default:
318 return -ENOIOCTLCMD; 318 return -ENOTTY;
319 } 319 }
320} 320}
321 321
diff --git a/drivers/char/watchdog/i8xx_tco.c b/drivers/char/watchdog/i8xx_tco.c
index 8385dd36eefe..e0627d79707b 100644
--- a/drivers/char/watchdog/i8xx_tco.c
+++ b/drivers/char/watchdog/i8xx_tco.c
@@ -356,7 +356,7 @@ static int i8xx_tco_ioctl (struct inode *inode, struct file *file,
356 } 356 }
357 357
358 default: 358 default:
359 return -ENOIOCTLCMD; 359 return -ENOTTY;
360 } 360 }
361} 361}
362 362
@@ -406,18 +406,18 @@ static struct notifier_block i8xx_tco_notifier = {
406 * want to register another driver on the same PCI id. 406 * want to register another driver on the same PCI id.
407 */ 407 */
408static struct pci_device_id i8xx_tco_pci_tbl[] = { 408static struct pci_device_id i8xx_tco_pci_tbl[] = {
409 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, PCI_ANY_ID, PCI_ANY_ID, }, 409 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0) },
410 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, PCI_ANY_ID, PCI_ANY_ID, }, 410 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0) },
411 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, PCI_ANY_ID, PCI_ANY_ID, }, 411 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0) },
412 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, PCI_ANY_ID, PCI_ANY_ID, }, 412 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10) },
413 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, PCI_ANY_ID, PCI_ANY_ID, }, 413 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0) },
414 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, PCI_ANY_ID, PCI_ANY_ID, }, 414 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12) },
415 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, PCI_ANY_ID, PCI_ANY_ID, }, 415 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0) },
416 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, PCI_ANY_ID, PCI_ANY_ID, }, 416 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12) },
417 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0, PCI_ANY_ID, PCI_ANY_ID, }, 417 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0) },
418 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, PCI_ANY_ID, PCI_ANY_ID, }, 418 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0) },
419 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, PCI_ANY_ID, PCI_ANY_ID, }, 419 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1) },
420 { 0, }, /* End of list */ 420 { }, /* End of list */
421}; 421};
422MODULE_DEVICE_TABLE (pci, i8xx_tco_pci_tbl); 422MODULE_DEVICE_TABLE (pci, i8xx_tco_pci_tbl);
423 423
@@ -434,12 +434,11 @@ static unsigned char __init i8xx_tco_getdevice (void)
434 * Find the PCI device 434 * Find the PCI device
435 */ 435 */
436 436
437 while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { 437 for_each_pci_dev(dev)
438 if (pci_match_id(i8xx_tco_pci_tbl, dev)) { 438 if (pci_match_id(i8xx_tco_pci_tbl, dev)) {
439 i8xx_tco_pci = dev; 439 i8xx_tco_pci = dev;
440 break; 440 break;
441 } 441 }
442 }
443 442
444 if (i8xx_tco_pci) { 443 if (i8xx_tco_pci) {
445 /* 444 /*
@@ -454,6 +453,7 @@ static unsigned char __init i8xx_tco_getdevice (void)
454 /* Something's wrong here, ACPIBASE has to be set */ 453 /* Something's wrong here, ACPIBASE has to be set */
455 if (badr == 0x0001 || badr == 0x0000) { 454 if (badr == 0x0001 || badr == 0x0000) {
456 printk (KERN_ERR PFX "failed to get TCOBASE address\n"); 455 printk (KERN_ERR PFX "failed to get TCOBASE address\n");
456 pci_dev_put(i8xx_tco_pci);
457 return 0; 457 return 0;
458 } 458 }
459 459
@@ -465,6 +465,7 @@ static unsigned char __init i8xx_tco_getdevice (void)
465 pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1); 465 pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1);
466 if (val1 & 0x02) { 466 if (val1 & 0x02) {
467 printk (KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n"); 467 printk (KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n");
468 pci_dev_put(i8xx_tco_pci);
468 return 0; /* Cannot reset NO_REBOOT bit */ 469 return 0; /* Cannot reset NO_REBOOT bit */
469 } 470 }
470 } 471 }
@@ -476,6 +477,7 @@ static unsigned char __init i8xx_tco_getdevice (void)
476 if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) { 477 if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) {
477 printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", 478 printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
478 SMI_EN + 1); 479 SMI_EN + 1);
480 pci_dev_put(i8xx_tco_pci);
479 return 0; 481 return 0;
480 } 482 }
481 val1 = inb (SMI_EN + 1); 483 val1 = inb (SMI_EN + 1);
@@ -542,6 +544,7 @@ unreg_notifier:
542unreg_region: 544unreg_region:
543 release_region (TCOBASE, 0x10); 545 release_region (TCOBASE, 0x10);
544out: 546out:
547 pci_dev_put(i8xx_tco_pci);
545 return ret; 548 return ret;
546} 549}
547 550
@@ -555,6 +558,8 @@ static void __exit watchdog_cleanup (void)
555 misc_deregister (&i8xx_tco_miscdev); 558 misc_deregister (&i8xx_tco_miscdev);
556 unregister_reboot_notifier(&i8xx_tco_notifier); 559 unregister_reboot_notifier(&i8xx_tco_notifier);
557 release_region (TCOBASE, 0x10); 560 release_region (TCOBASE, 0x10);
561
562 pci_dev_put(i8xx_tco_pci);
558} 563}
559 564
560module_init(watchdog_init); 565module_init(watchdog_init);
diff --git a/drivers/char/watchdog/iTCO_wdt.c b/drivers/char/watchdog/iTCO_wdt.c
new file mode 100644
index 000000000000..8f89948832fc
--- /dev/null
+++ b/drivers/char/watchdog/iTCO_wdt.c
@@ -0,0 +1,735 @@
1/*
2 * intel TCO Watchdog Driver (Used in i82801 and i6300ESB chipsets)
3 *
4 * (c) Copyright 2006 Wim Van Sebroeck <wim@iguana.be>.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 * Neither Wim Van Sebroeck nor Iguana vzw. admit liability nor
12 * provide warranty for any of this software. This material is
13 * provided "AS-IS" and at no charge.
14 *
15 * The TCO watchdog is implemented in the following I/O controller hubs:
16 * (See the intel documentation on http://developer.intel.com.)
17 * 82801AA (ICH) : document number 290655-003, 290677-014,
18 * 82801AB (ICHO) : document number 290655-003, 290677-014,
19 * 82801BA (ICH2) : document number 290687-002, 298242-027,
20 * 82801BAM (ICH2-M) : document number 290687-002, 298242-027,
21 * 82801CA (ICH3-S) : document number 290733-003, 290739-013,
22 * 82801CAM (ICH3-M) : document number 290716-001, 290718-007,
23 * 82801DB (ICH4) : document number 290744-001, 290745-020,
24 * 82801DBM (ICH4-M) : document number 252337-001, 252663-005,
25 * 82801E (C-ICH) : document number 273599-001, 273645-002,
26 * 82801EB (ICH5) : document number 252516-001, 252517-003,
27 * 82801ER (ICH5R) : document number 252516-001, 252517-003,
28 * 82801FB (ICH6) : document number 301473-002, 301474-007,
29 * 82801FR (ICH6R) : document number 301473-002, 301474-007,
30 * 82801FBM (ICH6-M) : document number 301473-002, 301474-007,
31 * 82801FW (ICH6W) : document number 301473-001, 301474-007,
32 * 82801FRW (ICH6RW) : document number 301473-001, 301474-007,
33 * 82801GB (ICH7) : document number 307013-002, 307014-009,
34 * 82801GR (ICH7R) : document number 307013-002, 307014-009,
35 * 82801GDH (ICH7DH) : document number 307013-002, 307014-009,
36 * 82801GBM (ICH7-M) : document number 307013-002, 307014-009,
37 * 82801GHM (ICH7-M DH) : document number 307013-002, 307014-009,
38 * 6300ESB (6300ESB) : document number 300641-003
39 */
40
41/*
42 * Includes, defines, variables, module parameters, ...
43 */
44
45/* Module and version information */
46#define DRV_NAME "iTCO_wdt"
47#define DRV_VERSION "1.00"
48#define DRV_RELDATE "30-Jul-2006"
49#define PFX DRV_NAME ": "
50
51/* Includes */
52#include <linux/config.h> /* For CONFIG_WATCHDOG_NOWAYOUT/... */
53#include <linux/module.h> /* For module specific items */
54#include <linux/moduleparam.h> /* For new moduleparam's */
55#include <linux/types.h> /* For standard types (like size_t) */
56#include <linux/errno.h> /* For the -ENODEV/... values */
57#include <linux/kernel.h> /* For printk/panic/... */
58#include <linux/miscdevice.h> /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
59#include <linux/watchdog.h> /* For the watchdog specific items */
60#include <linux/init.h> /* For __init/__exit/... */
61#include <linux/fs.h> /* For file operations */
62#include <linux/platform_device.h> /* For platform_driver framework */
63#include <linux/pci.h> /* For pci functions */
64#include <linux/ioport.h> /* For io-port access */
65#include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */
66
67#include <asm/uaccess.h> /* For copy_to_user/put_user/... */
68#include <asm/io.h> /* For inb/outb/... */
69
70/* TCO related info */
71enum iTCO_chipsets {
72 TCO_ICH = 0, /* ICH */
73 TCO_ICH0, /* ICH0 */
74 TCO_ICH2, /* ICH2 */
75 TCO_ICH2M, /* ICH2-M */
76 TCO_ICH3, /* ICH3-S */
77 TCO_ICH3M, /* ICH3-M */
78 TCO_ICH4, /* ICH4 */
79 TCO_ICH4M, /* ICH4-M */
80 TCO_CICH, /* C-ICH */
81 TCO_ICH5, /* ICH5 & ICH5R */
82 TCO_6300ESB, /* 6300ESB */
83 TCO_ICH6, /* ICH6 & ICH6R */
84 TCO_ICH6M, /* ICH6-M */
85 TCO_ICH6W, /* ICH6W & ICH6RW */
86 TCO_ICH7, /* ICH7 & ICH7R */
87 TCO_ICH7M, /* ICH7-M */
88 TCO_ICH7MDH, /* ICH7-M DH */
89};
90
91static struct {
92 char *name;
93 unsigned int iTCO_version;
94} iTCO_chipset_info[] __devinitdata = {
95 {"ICH", 1},
96 {"ICH0", 1},
97 {"ICH2", 1},
98 {"ICH2-M", 1},
99 {"ICH3-S", 1},
100 {"ICH3-M", 1},
101 {"ICH4", 1},
102 {"ICH4-M", 1},
103 {"C-ICH", 1},
104 {"ICH5 or ICH5R", 1},
105 {"6300ESB", 1},
106 {"ICH6 or ICH6R", 2},
107 {"ICH6-M", 2},
108 {"ICH6W or ICH6RW", 2},
109 {"ICH7 or ICH7R", 2},
110 {"ICH7-M", 2},
111 {"ICH7-M DH", 2},
112 {NULL,0}
113};
114
115/*
116 * This data only exists for exporting the supported PCI ids
117 * via MODULE_DEVICE_TABLE. We do not actually register a
118 * pci_driver, because the I/O Controller Hub has also other
119 * functions that probably will be registered by other drivers.
120 */
121static struct pci_device_id iTCO_wdt_pci_tbl[] = {
122 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH },
123 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH0 },
124 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH2 },
125 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH2M },
126 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH3 },
127 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH3M },
128 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH4 },
129 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH4M },
130 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_CICH },
131 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH5 },
132 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_6300ESB },
133 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH6 },
134 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH6M },
135 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH6W },
136 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7 },
137 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7M },
138 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7MDH },
139 { 0, }, /* End of list */
140};
141MODULE_DEVICE_TABLE (pci, iTCO_wdt_pci_tbl);
142
143/* Address definitions for the TCO */
144#define TCOBASE iTCO_wdt_private.ACPIBASE + 0x60 /* TCO base address */
145#define SMI_EN iTCO_wdt_private.ACPIBASE + 0x30 /* SMI Control and Enable Register */
146
147#define TCO_RLD TCOBASE + 0x00 /* TCO Timer Reload and Current Value */
148#define TCOv1_TMR TCOBASE + 0x01 /* TCOv1 Timer Initial Value */
149#define TCO_DAT_IN TCOBASE + 0x02 /* TCO Data In Register */
150#define TCO_DAT_OUT TCOBASE + 0x03 /* TCO Data Out Register */
151#define TCO1_STS TCOBASE + 0x04 /* TCO1 Status Register */
152#define TCO2_STS TCOBASE + 0x06 /* TCO2 Status Register */
153#define TCO1_CNT TCOBASE + 0x08 /* TCO1 Control Register */
154#define TCO2_CNT TCOBASE + 0x0a /* TCO2 Control Register */
155#define TCOv2_TMR TCOBASE + 0x12 /* TCOv2 Timer Initial Value */
156
157/* internal variables */
158static unsigned long is_active;
159static char expect_release;
160static struct { /* this is private data for the iTCO_wdt device */
161 unsigned int iTCO_version; /* TCO version/generation */
162 unsigned long ACPIBASE; /* The cards ACPIBASE address (TCOBASE = ACPIBASE+0x60) */
163 unsigned long __iomem *gcs; /* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2) */
164 spinlock_t io_lock; /* the lock for io operations */
165 struct pci_dev *pdev; /* the PCI-device */
166} iTCO_wdt_private;
167
168static struct platform_device *iTCO_wdt_platform_device; /* the watchdog platform device */
169
170/* module parameters */
171#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */
172static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */
173module_param(heartbeat, int, 0);
174MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<heartbeat<39 (TCO v1) or 613 (TCO v2), default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
175
176static int nowayout = WATCHDOG_NOWAYOUT;
177module_param(nowayout, int, 0);
178MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
179
180/*
181 * Some TCO specific functions
182 */
183
184static inline unsigned int seconds_to_ticks(int seconds)
185{
186 /* the internal timer is stored as ticks which decrement
187 * every 0.6 seconds */
188 return (seconds * 10) / 6;
189}
190
191static void iTCO_wdt_set_NO_REBOOT_bit(void)
192{
193 u32 val32;
194
195 /* Set the NO_REBOOT bit: this disables reboots */
196 if (iTCO_wdt_private.iTCO_version == 2) {
197 val32 = readl(iTCO_wdt_private.gcs);
198 val32 |= 0x00000020;
199 writel(val32, iTCO_wdt_private.gcs);
200 } else if (iTCO_wdt_private.iTCO_version == 1) {
201 pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
202 val32 |= 0x00000002;
203 pci_write_config_dword(iTCO_wdt_private.pdev, 0xd4, val32);
204 }
205}
206
207static int iTCO_wdt_unset_NO_REBOOT_bit(void)
208{
209 int ret = 0;
210 u32 val32;
211
212 /* Unset the NO_REBOOT bit: this enables reboots */
213 if (iTCO_wdt_private.iTCO_version == 2) {
214 val32 = readl(iTCO_wdt_private.gcs);
215 val32 &= 0xffffffdf;
216 writel(val32, iTCO_wdt_private.gcs);
217
218 val32 = readl(iTCO_wdt_private.gcs);
219 if (val32 & 0x00000020)
220 ret = -EIO;
221 } else if (iTCO_wdt_private.iTCO_version == 1) {
222 pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
223 val32 &= 0xfffffffd;
224 pci_write_config_dword(iTCO_wdt_private.pdev, 0xd4, val32);
225
226 pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
227 if (val32 & 0x00000002)
228 ret = -EIO;
229 }
230
231 return ret; /* returns: 0 = OK, -EIO = Error */
232}
233
234static int iTCO_wdt_start(void)
235{
236 unsigned int val;
237
238 spin_lock(&iTCO_wdt_private.io_lock);
239
240 /* disable chipset's NO_REBOOT bit */
241 if (iTCO_wdt_unset_NO_REBOOT_bit()) {
242 printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n");
243 return -EIO;
244 }
245
246 /* Bit 11: TCO Timer Halt -> 0 = The TCO timer is enabled to count */
247 val = inw(TCO1_CNT);
248 val &= 0xf7ff;
249 outw(val, TCO1_CNT);
250 val = inw(TCO1_CNT);
251 spin_unlock(&iTCO_wdt_private.io_lock);
252
253 if (val & 0x0800)
254 return -1;
255 return 0;
256}
257
258static int iTCO_wdt_stop(void)
259{
260 unsigned int val;
261
262 spin_lock(&iTCO_wdt_private.io_lock);
263
264 /* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */
265 val = inw(TCO1_CNT);
266 val |= 0x0800;
267 outw(val, TCO1_CNT);
268 val = inw(TCO1_CNT);
269
270 /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
271 iTCO_wdt_set_NO_REBOOT_bit();
272
273 spin_unlock(&iTCO_wdt_private.io_lock);
274
275 if ((val & 0x0800) == 0)
276 return -1;
277 return 0;
278}
279
280static int iTCO_wdt_keepalive(void)
281{
282 spin_lock(&iTCO_wdt_private.io_lock);
283
284 /* Reload the timer by writing to the TCO Timer Counter register */
285 if (iTCO_wdt_private.iTCO_version == 2) {
286 outw(0x01, TCO_RLD);
287 } else if (iTCO_wdt_private.iTCO_version == 1) {
288 outb(0x01, TCO_RLD);
289 }
290
291 spin_unlock(&iTCO_wdt_private.io_lock);
292 return 0;
293}
294
295static int iTCO_wdt_set_heartbeat(int t)
296{
297 unsigned int val16;
298 unsigned char val8;
299 unsigned int tmrval;
300
301 tmrval = seconds_to_ticks(t);
302 /* from the specs: */
303 /* "Values of 0h-3h are ignored and should not be attempted" */
304 if (tmrval < 0x04)
305 return -EINVAL;
306 if (((iTCO_wdt_private.iTCO_version == 2) && (tmrval > 0x3ff)) ||
307 ((iTCO_wdt_private.iTCO_version == 1) && (tmrval > 0x03f)))
308 return -EINVAL;
309
310 /* Write new heartbeat to watchdog */
311 if (iTCO_wdt_private.iTCO_version == 2) {
312 spin_lock(&iTCO_wdt_private.io_lock);
313 val16 = inw(TCOv2_TMR);
314 val16 &= 0xfc00;
315 val16 |= tmrval;
316 outw(val16, TCOv2_TMR);
317 val16 = inw(TCOv2_TMR);
318 spin_unlock(&iTCO_wdt_private.io_lock);
319
320 if ((val16 & 0x3ff) != tmrval)
321 return -EINVAL;
322 } else if (iTCO_wdt_private.iTCO_version == 1) {
323 spin_lock(&iTCO_wdt_private.io_lock);
324 val8 = inb(TCOv1_TMR);
325 val8 &= 0xc0;
326 val8 |= (tmrval & 0xff);
327 outb(val8, TCOv1_TMR);
328 val8 = inb(TCOv1_TMR);
329 spin_unlock(&iTCO_wdt_private.io_lock);
330
331 if ((val8 & 0x3f) != tmrval)
332 return -EINVAL;
333 }
334
335 heartbeat = t;
336 return 0;
337}
338
339static int iTCO_wdt_get_timeleft (int *time_left)
340{
341 unsigned int val16;
342 unsigned char val8;
343
344 /* read the TCO Timer */
345 if (iTCO_wdt_private.iTCO_version == 2) {
346 spin_lock(&iTCO_wdt_private.io_lock);
347 val16 = inw(TCO_RLD);
348 val16 &= 0x3ff;
349 spin_unlock(&iTCO_wdt_private.io_lock);
350
351 *time_left = (val16 * 6) / 10;
352 } else if (iTCO_wdt_private.iTCO_version == 1) {
353 spin_lock(&iTCO_wdt_private.io_lock);
354 val8 = inb(TCO_RLD);
355 val8 &= 0x3f;
356 spin_unlock(&iTCO_wdt_private.io_lock);
357
358 *time_left = (val8 * 6) / 10;
359 }
360 return 0;
361}
362
363/*
364 * /dev/watchdog handling
365 */
366
367static int iTCO_wdt_open (struct inode *inode, struct file *file)
368{
369 /* /dev/watchdog can only be opened once */
370 if (test_and_set_bit(0, &is_active))
371 return -EBUSY;
372
373 /*
374 * Reload and activate timer
375 */
376 iTCO_wdt_keepalive();
377 iTCO_wdt_start();
378 return nonseekable_open(inode, file);
379}
380
381static int iTCO_wdt_release (struct inode *inode, struct file *file)
382{
383 /*
384 * Shut off the timer.
385 */
386 if (expect_release == 42) {
387 iTCO_wdt_stop();
388 } else {
389 printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
390 iTCO_wdt_keepalive();
391 }
392 clear_bit(0, &is_active);
393 expect_release = 0;
394 return 0;
395}
396
397static ssize_t iTCO_wdt_write (struct file *file, const char __user *data,
398 size_t len, loff_t * ppos)
399{
400 /* See if we got the magic character 'V' and reload the timer */
401 if (len) {
402 if (!nowayout) {
403 size_t i;
404
405 /* note: just in case someone wrote the magic character
406 * five months ago... */
407 expect_release = 0;
408
409 /* scan to see whether or not we got the magic character */
410 for (i = 0; i != len; i++) {
411 char c;
412 if (get_user(c, data+i))
413 return -EFAULT;
414 if (c == 'V')
415 expect_release = 42;
416 }
417 }
418
419 /* someone wrote to us, we should reload the timer */
420 iTCO_wdt_keepalive();
421 }
422 return len;
423}
424
425static int iTCO_wdt_ioctl (struct inode *inode, struct file *file,
426 unsigned int cmd, unsigned long arg)
427{
428 int new_options, retval = -EINVAL;
429 int new_heartbeat;
430 int time_left;
431 void __user *argp = (void __user *)arg;
432 int __user *p = argp;
433 static struct watchdog_info ident = {
434 .options = WDIOF_SETTIMEOUT |
435 WDIOF_KEEPALIVEPING |
436 WDIOF_MAGICCLOSE,
437 .firmware_version = 0,
438 .identity = DRV_NAME,
439 };
440
441 switch (cmd) {
442 case WDIOC_GETSUPPORT:
443 return copy_to_user(argp, &ident,
444 sizeof (ident)) ? -EFAULT : 0;
445
446 case WDIOC_GETSTATUS:
447 case WDIOC_GETBOOTSTATUS:
448 return put_user(0, p);
449
450 case WDIOC_KEEPALIVE:
451 iTCO_wdt_keepalive();
452 return 0;
453
454 case WDIOC_SETOPTIONS:
455 {
456 if (get_user(new_options, p))
457 return -EFAULT;
458
459 if (new_options & WDIOS_DISABLECARD) {
460 iTCO_wdt_stop();
461 retval = 0;
462 }
463
464 if (new_options & WDIOS_ENABLECARD) {
465 iTCO_wdt_keepalive();
466 iTCO_wdt_start();
467 retval = 0;
468 }
469
470 return retval;
471 }
472
473 case WDIOC_SETTIMEOUT:
474 {
475 if (get_user(new_heartbeat, p))
476 return -EFAULT;
477
478 if (iTCO_wdt_set_heartbeat(new_heartbeat))
479 return -EINVAL;
480
481 iTCO_wdt_keepalive();
482 /* Fall */
483 }
484
485 case WDIOC_GETTIMEOUT:
486 return put_user(heartbeat, p);
487
488 case WDIOC_GETTIMELEFT:
489 {
490 if (iTCO_wdt_get_timeleft(&time_left))
491 return -EINVAL;
492
493 return put_user(time_left, p);
494 }
495
496 default:
497 return -ENOTTY;
498 }
499}
500
501/*
502 * Kernel Interfaces
503 */
504
505static struct file_operations iTCO_wdt_fops = {
506 .owner = THIS_MODULE,
507 .llseek = no_llseek,
508 .write = iTCO_wdt_write,
509 .ioctl = iTCO_wdt_ioctl,
510 .open = iTCO_wdt_open,
511 .release = iTCO_wdt_release,
512};
513
514static struct miscdevice iTCO_wdt_miscdev = {
515 .minor = WATCHDOG_MINOR,
516 .name = "watchdog",
517 .fops = &iTCO_wdt_fops,
518};
519
520/*
521 * Init & exit routines
522 */
523
524static int iTCO_wdt_init(struct pci_dev *pdev, const struct pci_device_id *ent, struct platform_device *dev)
525{
526 int ret;
527 u32 base_address;
528 unsigned long RCBA;
529 unsigned long val32;
530
531 /*
532 * Find the ACPI/PM base I/O address which is the base
533 * for the TCO registers (TCOBASE=ACPIBASE + 0x60)
534 * ACPIBASE is bits [15:7] from 0x40-0x43
535 */
536 pci_read_config_dword(pdev, 0x40, &base_address);
537 base_address &= 0x00007f80;
538 if (base_address == 0x00000000) {
539 /* Something's wrong here, ACPIBASE has to be set */
540 printk(KERN_ERR PFX "failed to get TCOBASE address\n");
541 pci_dev_put(pdev);
542 return -ENODEV;
543 }
544 iTCO_wdt_private.iTCO_version = iTCO_chipset_info[ent->driver_data].iTCO_version;
545 iTCO_wdt_private.ACPIBASE = base_address;
546 iTCO_wdt_private.pdev = pdev;
547
548 /* Get the Memory-Mapped GCS register, we need it for the NO_REBOOT flag (TCO v2) */
549 /* To get access to it you have to read RCBA from PCI Config space 0xf0
550 and use it as base. GCS = RCBA + ICH6_GCS(0x3410). */
551 if (iTCO_wdt_private.iTCO_version == 2) {
552 pci_read_config_dword(pdev, 0xf0, &base_address);
553 RCBA = base_address & 0xffffc000;
554 iTCO_wdt_private.gcs = ioremap((RCBA + 0x3410),4);
555 }
556
557 /* Check chipset's NO_REBOOT bit */
558 if (iTCO_wdt_unset_NO_REBOOT_bit()) {
559 printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n");
560 ret = -ENODEV; /* Cannot reset NO_REBOOT bit */
561 goto out;
562 }
563
564 /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
565 iTCO_wdt_set_NO_REBOOT_bit();
566
567 /* Set the TCO_EN bit in SMI_EN register */
568 if (!request_region(SMI_EN, 4, "iTCO_wdt")) {
569 printk(KERN_ERR PFX "I/O address 0x%04lx already in use\n",
570 SMI_EN );
571 ret = -EIO;
572 goto out;
573 }
574 val32 = inl(SMI_EN);
575 val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */
576 outl(val32, SMI_EN);
577 release_region(SMI_EN, 4);
578
579 /* The TCO I/O registers reside in a 32-byte range pointed to by the TCOBASE value */
580 if (!request_region (TCOBASE, 0x20, "iTCO_wdt")) {
581 printk (KERN_ERR PFX "I/O address 0x%04lx already in use\n",
582 TCOBASE);
583 ret = -EIO;
584 goto out;
585 }
586
587 printk(KERN_INFO PFX "Found a %s TCO device (Version=%d, TCOBASE=0x%04lx)\n",
588 iTCO_chipset_info[ent->driver_data].name,
589 iTCO_chipset_info[ent->driver_data].iTCO_version,
590 TCOBASE);
591
592 /* Clear out the (probably old) status */
593 outb(0, TCO1_STS);
594 outb(3, TCO2_STS);
595
596 /* Make sure the watchdog is not running */
597 iTCO_wdt_stop();
598
599 /* Check that the heartbeat value is within it's range ; if not reset to the default */
600 if (iTCO_wdt_set_heartbeat(heartbeat)) {
601 iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT);
602 printk(KERN_INFO PFX "heartbeat value must be 2<heartbeat<39 (TCO v1) or 613 (TCO v2), using %d\n",
603 heartbeat);
604 }
605
606 ret = misc_register(&iTCO_wdt_miscdev);
607 if (ret != 0) {
608 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
609 WATCHDOG_MINOR, ret);
610 goto unreg_region;
611 }
612
613 printk (KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
614 heartbeat, nowayout);
615
616 return 0;
617
618unreg_region:
619 release_region (TCOBASE, 0x20);
620out:
621 if (iTCO_wdt_private.iTCO_version == 2)
622 iounmap(iTCO_wdt_private.gcs);
623 pci_dev_put(iTCO_wdt_private.pdev);
624 iTCO_wdt_private.ACPIBASE = 0;
625 return ret;
626}
627
628static void iTCO_wdt_cleanup(void)
629{
630 /* Stop the timer before we leave */
631 if (!nowayout)
632 iTCO_wdt_stop();
633
634 /* Deregister */
635 misc_deregister(&iTCO_wdt_miscdev);
636 release_region(TCOBASE, 0x20);
637 if (iTCO_wdt_private.iTCO_version == 2)
638 iounmap(iTCO_wdt_private.gcs);
639 pci_dev_put(iTCO_wdt_private.pdev);
640 iTCO_wdt_private.ACPIBASE = 0;
641}
642
643static int iTCO_wdt_probe(struct platform_device *dev)
644{
645 int found = 0;
646 struct pci_dev *pdev = NULL;
647 const struct pci_device_id *ent;
648
649 spin_lock_init(&iTCO_wdt_private.io_lock);
650
651 for_each_pci_dev(pdev) {
652 ent = pci_match_id(iTCO_wdt_pci_tbl, pdev);
653 if (ent) {
654 if (!(iTCO_wdt_init(pdev, ent, dev))) {
655 found++;
656 break;
657 }
658 }
659 }
660
661 if (!found) {
662 printk(KERN_INFO PFX "No card detected\n");
663 return -ENODEV;
664 }
665
666 return 0;
667}
668
669static int iTCO_wdt_remove(struct platform_device *dev)
670{
671 if (iTCO_wdt_private.ACPIBASE)
672 iTCO_wdt_cleanup();
673
674 return 0;
675}
676
677static void iTCO_wdt_shutdown(struct platform_device *dev)
678{
679 iTCO_wdt_stop();
680}
681
682#define iTCO_wdt_suspend NULL
683#define iTCO_wdt_resume NULL
684
685static struct platform_driver iTCO_wdt_driver = {
686 .probe = iTCO_wdt_probe,
687 .remove = iTCO_wdt_remove,
688 .shutdown = iTCO_wdt_shutdown,
689 .suspend = iTCO_wdt_suspend,
690 .resume = iTCO_wdt_resume,
691 .driver = {
692 .owner = THIS_MODULE,
693 .name = DRV_NAME,
694 },
695};
696
697static int __init iTCO_wdt_init_module(void)
698{
699 int err;
700
701 printk(KERN_INFO PFX "Intel TCO WatchDog Timer Driver v%s (%s)\n",
702 DRV_VERSION, DRV_RELDATE);
703
704 err = platform_driver_register(&iTCO_wdt_driver);
705 if (err)
706 return err;
707
708 iTCO_wdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0);
709 if (IS_ERR(iTCO_wdt_platform_device)) {
710 err = PTR_ERR(iTCO_wdt_platform_device);
711 goto unreg_platform_driver;
712 }
713
714 return 0;
715
716unreg_platform_driver:
717 platform_driver_unregister(&iTCO_wdt_driver);
718 return err;
719}
720
721static void __exit iTCO_wdt_cleanup_module(void)
722{
723 platform_device_unregister(iTCO_wdt_platform_device);
724 platform_driver_unregister(&iTCO_wdt_driver);
725 printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
726}
727
728module_init(iTCO_wdt_init_module);
729module_exit(iTCO_wdt_cleanup_module);
730
731MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>");
732MODULE_DESCRIPTION("Intel TCO WatchDog Timer Driver");
733MODULE_VERSION(DRV_VERSION);
734MODULE_LICENSE("GPL");
735MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/ib700wdt.c b/drivers/char/watchdog/ib700wdt.c
index fd95f7327798..c1ed209a138c 100644
--- a/drivers/char/watchdog/ib700wdt.c
+++ b/drivers/char/watchdog/ib700wdt.c
@@ -199,7 +199,7 @@ ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
199 break; 199 break;
200 200
201 default: 201 default:
202 return -ENOIOCTLCMD; 202 return -ENOTTY;
203 } 203 }
204 return 0; 204 return 0;
205} 205}
diff --git a/drivers/char/watchdog/ibmasr.c b/drivers/char/watchdog/ibmasr.c
index 26ceee7a4df0..dd6760f1a23b 100644
--- a/drivers/char/watchdog/ibmasr.c
+++ b/drivers/char/watchdog/ibmasr.c
@@ -295,7 +295,7 @@ static int asr_ioctl(struct inode *inode, struct file *file,
295 } 295 }
296 } 296 }
297 297
298 return -ENOIOCTLCMD; 298 return -ENOTTY;
299} 299}
300 300
301static int asr_open(struct inode *inode, struct file *file) 301static int asr_open(struct inode *inode, struct file *file)
diff --git a/drivers/char/watchdog/indydog.c b/drivers/char/watchdog/indydog.c
index dacc1c20a310..0bc239308989 100644
--- a/drivers/char/watchdog/indydog.c
+++ b/drivers/char/watchdog/indydog.c
@@ -112,7 +112,7 @@ static int indydog_ioctl(struct inode *inode, struct file *file,
112 112
113 switch (cmd) { 113 switch (cmd) {
114 default: 114 default:
115 return -ENOIOCTLCMD; 115 return -ENOTTY;
116 case WDIOC_GETSUPPORT: 116 case WDIOC_GETSUPPORT:
117 if (copy_to_user((struct watchdog_info *)arg, 117 if (copy_to_user((struct watchdog_info *)arg,
118 &ident, sizeof(ident))) 118 &ident, sizeof(ident)))
diff --git a/drivers/char/watchdog/ixp2000_wdt.c b/drivers/char/watchdog/ixp2000_wdt.c
index 692908819e26..c91d9a660ec0 100644
--- a/drivers/char/watchdog/ixp2000_wdt.c
+++ b/drivers/char/watchdog/ixp2000_wdt.c
@@ -107,7 +107,7 @@ static int
107ixp2000_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 107ixp2000_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
108 unsigned long arg) 108 unsigned long arg)
109{ 109{
110 int ret = -ENOIOCTLCMD; 110 int ret = -ENOTTY;
111 int time; 111 int time;
112 112
113 switch (cmd) { 113 switch (cmd) {
diff --git a/drivers/char/watchdog/ixp4xx_wdt.c b/drivers/char/watchdog/ixp4xx_wdt.c
index 9db5cf2c38c3..db477f712388 100644
--- a/drivers/char/watchdog/ixp4xx_wdt.c
+++ b/drivers/char/watchdog/ixp4xx_wdt.c
@@ -102,7 +102,7 @@ static int
102ixp4xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 102ixp4xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
103 unsigned long arg) 103 unsigned long arg)
104{ 104{
105 int ret = -ENOIOCTLCMD; 105 int ret = -ENOTTY;
106 int time; 106 int time;
107 107
108 switch (cmd) { 108 switch (cmd) {
diff --git a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c
index 23734e07fb22..276577d08fba 100644
--- a/drivers/char/watchdog/machzwd.c
+++ b/drivers/char/watchdog/machzwd.c
@@ -329,7 +329,7 @@ static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
329 break; 329 break;
330 330
331 default: 331 default:
332 return -ENOIOCTLCMD; 332 return -ENOTTY;
333 } 333 }
334 334
335 return 0; 335 return 0;
@@ -426,8 +426,7 @@ static int __init zf_init(void)
426 printk(KERN_INFO PFX ": MachZ ZF-Logic Watchdog driver initializing.\n"); 426 printk(KERN_INFO PFX ": MachZ ZF-Logic Watchdog driver initializing.\n");
427 427
428 ret = zf_get_ZFL_version(); 428 ret = zf_get_ZFL_version();
429 printk("%#x\n", ret); 429 if ((!ret) || (ret == 0xffff)) {
430 if((!ret) || (ret != 0xffff)){
431 printk(KERN_WARNING PFX ": no ZF-Logic found\n"); 430 printk(KERN_WARNING PFX ": no ZF-Logic found\n");
432 return -ENODEV; 431 return -ENODEV;
433 } 432 }
diff --git a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c
index ae943324d251..c2dac0aa1d62 100644
--- a/drivers/char/watchdog/mixcomwd.c
+++ b/drivers/char/watchdog/mixcomwd.c
@@ -185,7 +185,7 @@ static int mixcomwd_ioctl(struct inode *inode, struct file *file,
185 mixcomwd_ping(); 185 mixcomwd_ping();
186 break; 186 break;
187 default: 187 default:
188 return -ENOIOCTLCMD; 188 return -ENOTTY;
189 } 189 }
190 return 0; 190 return 0;
191} 191}
diff --git a/drivers/char/watchdog/mpc83xx_wdt.c b/drivers/char/watchdog/mpc83xx_wdt.c
index a480903ee1a5..18ca752e2f90 100644
--- a/drivers/char/watchdog/mpc83xx_wdt.c
+++ b/drivers/char/watchdog/mpc83xx_wdt.c
@@ -125,7 +125,7 @@ static int mpc83xx_wdt_ioctl(struct inode *inode, struct file *file,
125 case WDIOC_GETTIMEOUT: 125 case WDIOC_GETTIMEOUT:
126 return put_user(timeout_sec, p); 126 return put_user(timeout_sec, p);
127 default: 127 default:
128 return -ENOIOCTLCMD; 128 return -ENOTTY;
129 } 129 }
130} 130}
131 131
diff --git a/drivers/char/watchdog/mpc8xx_wdt.c b/drivers/char/watchdog/mpc8xx_wdt.c
index 35dd9e6e1140..8aaed10dd499 100644
--- a/drivers/char/watchdog/mpc8xx_wdt.c
+++ b/drivers/char/watchdog/mpc8xx_wdt.c
@@ -126,7 +126,7 @@ static int mpc8xx_wdt_ioctl(struct inode *inode, struct file *file,
126 break; 126 break;
127 127
128 default: 128 default:
129 return -ENOIOCTLCMD; 129 return -ENOTTY;
130 } 130 }
131 131
132 return 0; 132 return 0;
diff --git a/drivers/char/watchdog/mpcore_wdt.c b/drivers/char/watchdog/mpcore_wdt.c
index 54b3c56ead0d..02d336ace504 100644
--- a/drivers/char/watchdog/mpcore_wdt.c
+++ b/drivers/char/watchdog/mpcore_wdt.c
@@ -221,7 +221,7 @@ static int mpcore_wdt_ioctl(struct inode *inode, struct file *file,
221 } uarg; 221 } uarg;
222 222
223 if (_IOC_DIR(cmd) && _IOC_SIZE(cmd) > sizeof(uarg)) 223 if (_IOC_DIR(cmd) && _IOC_SIZE(cmd) > sizeof(uarg))
224 return -ENOIOCTLCMD; 224 return -ENOTTY;
225 225
226 if (_IOC_DIR(cmd) & _IOC_WRITE) { 226 if (_IOC_DIR(cmd) & _IOC_WRITE) {
227 ret = copy_from_user(&uarg, (void __user *)arg, _IOC_SIZE(cmd)); 227 ret = copy_from_user(&uarg, (void __user *)arg, _IOC_SIZE(cmd));
@@ -271,7 +271,7 @@ static int mpcore_wdt_ioctl(struct inode *inode, struct file *file,
271 break; 271 break;
272 272
273 default: 273 default:
274 return -ENOIOCTLCMD; 274 return -ENOTTY;
275 } 275 }
276 276
277 if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) { 277 if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
diff --git a/drivers/char/watchdog/mv64x60_wdt.c b/drivers/char/watchdog/mv64x60_wdt.c
index 5c8fab345b40..b887cdb01334 100644
--- a/drivers/char/watchdog/mv64x60_wdt.c
+++ b/drivers/char/watchdog/mv64x60_wdt.c
@@ -160,7 +160,7 @@ static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file,
160 break; 160 break;
161 161
162 default: 162 default:
163 return -ENOIOCTLCMD; 163 return -ENOTTY;
164 } 164 }
165 165
166 return 0; 166 return 0;
diff --git a/drivers/char/watchdog/omap_wdt.c b/drivers/char/watchdog/omap_wdt.c
new file mode 100644
index 000000000000..8f90b90a5021
--- /dev/null
+++ b/drivers/char/watchdog/omap_wdt.c
@@ -0,0 +1,391 @@
1/*
2 * linux/drivers/char/watchdog/omap_wdt.c
3 *
4 * Watchdog driver for the TI OMAP 16xx & 24xx 32KHz (non-secure) watchdog
5 *
6 * Author: MontaVista Software, Inc.
7 * <gdavis@mvista.com> or <source@mvista.com>
8 *
9 * 2003 (c) MontaVista Software, Inc. This file is licensed under the
10 * terms of the GNU General Public License version 2. This program is
11 * licensed "as is" without any warranty of any kind, whether express
12 * or implied.
13 *
14 * History:
15 *
16 * 20030527: George G. Davis <gdavis@mvista.com>
17 * Initially based on linux-2.4.19-rmk7-pxa1/drivers/char/sa1100_wdt.c
18 * (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
19 * Based on SoftDog driver by Alan Cox <alan@redhat.com>
20 *
21 * Copyright (c) 2004 Texas Instruments.
22 * 1. Modified to support OMAP1610 32-KHz watchdog timer
23 * 2. Ported to 2.6 kernel
24 *
25 * Copyright (c) 2005 David Brownell
26 * Use the driver model and standard identifiers; handle bigger timeouts.
27 */
28
29#include <linux/module.h>
30#include <linux/config.h>
31#include <linux/types.h>
32#include <linux/kernel.h>
33#include <linux/fs.h>
34#include <linux/mm.h>
35#include <linux/miscdevice.h>
36#include <linux/watchdog.h>
37#include <linux/reboot.h>
38#include <linux/smp_lock.h>
39#include <linux/init.h>
40#include <linux/err.h>
41#include <linux/platform_device.h>
42#include <linux/moduleparam.h>
43#include <linux/clk.h>
44
45#include <asm/io.h>
46#include <asm/uaccess.h>
47#include <asm/hardware.h>
48#include <asm/bitops.h>
49
50#include <asm/arch/prcm.h>
51
52#include "omap_wdt.h"
53
54static unsigned timer_margin;
55module_param(timer_margin, uint, 0);
56MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)");
57
58static int omap_wdt_users;
59static struct clk *armwdt_ck = NULL;
60static struct clk *mpu_wdt_ick = NULL;
61static struct clk *mpu_wdt_fck = NULL;
62
63static unsigned int wdt_trgr_pattern = 0x1234;
64
65static void omap_wdt_ping(void)
66{
67 /* wait for posted write to complete */
68 while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x08)
69 cpu_relax();
70 wdt_trgr_pattern = ~wdt_trgr_pattern;
71 omap_writel(wdt_trgr_pattern, (OMAP_WATCHDOG_TGR));
72 /* wait for posted write to complete */
73 while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x08)
74 cpu_relax();
75 /* reloaded WCRR from WLDR */
76}
77
78static void omap_wdt_enable(void)
79{
80 /* Sequence to enable the watchdog */
81 omap_writel(0xBBBB, OMAP_WATCHDOG_SPR);
82 while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x10)
83 cpu_relax();
84 omap_writel(0x4444, OMAP_WATCHDOG_SPR);
85 while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x10)
86 cpu_relax();
87}
88
89static void omap_wdt_disable(void)
90{
91 /* sequence required to disable watchdog */
92 omap_writel(0xAAAA, OMAP_WATCHDOG_SPR); /* TIMER_MODE */
93 while (omap_readl(OMAP_WATCHDOG_WPS) & 0x10)
94 cpu_relax();
95 omap_writel(0x5555, OMAP_WATCHDOG_SPR); /* TIMER_MODE */
96 while (omap_readl(OMAP_WATCHDOG_WPS) & 0x10)
97 cpu_relax();
98}
99
100static void omap_wdt_adjust_timeout(unsigned new_timeout)
101{
102 if (new_timeout < TIMER_MARGIN_MIN)
103 new_timeout = TIMER_MARGIN_DEFAULT;
104 if (new_timeout > TIMER_MARGIN_MAX)
105 new_timeout = TIMER_MARGIN_MAX;
106 timer_margin = new_timeout;
107}
108
109static void omap_wdt_set_timeout(void)
110{
111 u32 pre_margin = GET_WLDR_VAL(timer_margin);
112
113 /* just count up at 32 KHz */
114 while (omap_readl(OMAP_WATCHDOG_WPS) & 0x04)
115 cpu_relax();
116 omap_writel(pre_margin, OMAP_WATCHDOG_LDR);
117 while (omap_readl(OMAP_WATCHDOG_WPS) & 0x04)
118 cpu_relax();
119}
120
121/*
122 * Allow only one task to hold it open
123 */
124
125static int omap_wdt_open(struct inode *inode, struct file *file)
126{
127 if (test_and_set_bit(1, (unsigned long *)&omap_wdt_users))
128 return -EBUSY;
129
130 if (cpu_is_omap16xx())
131 clk_enable(armwdt_ck); /* Enable the clock */
132
133 if (cpu_is_omap24xx()) {
134 clk_enable(mpu_wdt_ick); /* Enable the interface clock */
135 clk_enable(mpu_wdt_fck); /* Enable the functional clock */
136 }
137
138 /* initialize prescaler */
139 while (omap_readl(OMAP_WATCHDOG_WPS) & 0x01)
140 cpu_relax();
141 omap_writel((1 << 5) | (PTV << 2), OMAP_WATCHDOG_CNTRL);
142 while (omap_readl(OMAP_WATCHDOG_WPS) & 0x01)
143 cpu_relax();
144
145 omap_wdt_set_timeout();
146 omap_wdt_enable();
147 return 0;
148}
149
150static int omap_wdt_release(struct inode *inode, struct file *file)
151{
152 /*
153 * Shut off the timer unless NOWAYOUT is defined.
154 */
155#ifndef CONFIG_WATCHDOG_NOWAYOUT
156 omap_wdt_disable();
157
158 if (cpu_is_omap16xx()) {
159 clk_disable(armwdt_ck); /* Disable the clock */
160 clk_put(armwdt_ck);
161 armwdt_ck = NULL;
162 }
163
164 if (cpu_is_omap24xx()) {
165 clk_disable(mpu_wdt_ick); /* Disable the clock */
166 clk_disable(mpu_wdt_fck); /* Disable the clock */
167 clk_put(mpu_wdt_ick);
168 clk_put(mpu_wdt_fck);
169 mpu_wdt_ick = NULL;
170 mpu_wdt_fck = NULL;
171 }
172#else
173 printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n");
174#endif
175 omap_wdt_users = 0;
176 return 0;
177}
178
179static ssize_t
180omap_wdt_write(struct file *file, const char __user *data,
181 size_t len, loff_t *ppos)
182{
183 /* Refresh LOAD_TIME. */
184 if (len)
185 omap_wdt_ping();
186 return len;
187}
188
189static int
190omap_wdt_ioctl(struct inode *inode, struct file *file,
191 unsigned int cmd, unsigned long arg)
192{
193 int new_margin;
194 static struct watchdog_info ident = {
195 .identity = "OMAP Watchdog",
196 .options = WDIOF_SETTIMEOUT,
197 .firmware_version = 0,
198 };
199
200 switch (cmd) {
201 default:
202 return -ENOIOCTLCMD;
203 case WDIOC_GETSUPPORT:
204 return copy_to_user((struct watchdog_info __user *)arg, &ident,
205 sizeof(ident));
206 case WDIOC_GETSTATUS:
207 return put_user(0, (int __user *)arg);
208 case WDIOC_GETBOOTSTATUS:
209 if (cpu_is_omap16xx())
210 return put_user(omap_readw(ARM_SYSST),
211 (int __user *)arg);
212 if (cpu_is_omap24xx())
213 return put_user(omap_prcm_get_reset_sources(),
214 (int __user *)arg);
215 case WDIOC_KEEPALIVE:
216 omap_wdt_ping();
217 return 0;
218 case WDIOC_SETTIMEOUT:
219 if (get_user(new_margin, (int __user *)arg))
220 return -EFAULT;
221 omap_wdt_adjust_timeout(new_margin);
222
223 omap_wdt_disable();
224 omap_wdt_set_timeout();
225 omap_wdt_enable();
226
227 omap_wdt_ping();
228 /* Fall */
229 case WDIOC_GETTIMEOUT:
230 return put_user(timer_margin, (int __user *)arg);
231 }
232}
233
234static struct file_operations omap_wdt_fops = {
235 .owner = THIS_MODULE,
236 .write = omap_wdt_write,
237 .ioctl = omap_wdt_ioctl,
238 .open = omap_wdt_open,
239 .release = omap_wdt_release,
240};
241
242static struct miscdevice omap_wdt_miscdev = {
243 .minor = WATCHDOG_MINOR,
244 .name = "watchdog",
245 .fops = &omap_wdt_fops
246};
247
248static int __init omap_wdt_probe(struct platform_device *pdev)
249{
250 struct resource *res, *mem;
251 int ret;
252
253 /* reserve static register mappings */
254 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
255 if (!res)
256 return -ENOENT;
257
258 mem = request_mem_region(res->start, res->end - res->start + 1,
259 pdev->name);
260 if (mem == NULL)
261 return -EBUSY;
262
263 platform_set_drvdata(pdev, mem);
264
265 omap_wdt_users = 0;
266
267 if (cpu_is_omap16xx()) {
268 armwdt_ck = clk_get(&pdev->dev, "armwdt_ck");
269 if (IS_ERR(armwdt_ck)) {
270 ret = PTR_ERR(armwdt_ck);
271 armwdt_ck = NULL;
272 goto fail;
273 }
274 }
275
276 if (cpu_is_omap24xx()) {
277 mpu_wdt_ick = clk_get(&pdev->dev, "mpu_wdt_ick");
278 if (IS_ERR(mpu_wdt_ick)) {
279 ret = PTR_ERR(mpu_wdt_ick);
280 mpu_wdt_ick = NULL;
281 goto fail;
282 }
283 mpu_wdt_fck = clk_get(&pdev->dev, "mpu_wdt_fck");
284 if (IS_ERR(mpu_wdt_fck)) {
285 ret = PTR_ERR(mpu_wdt_fck);
286 mpu_wdt_fck = NULL;
287 goto fail;
288 }
289 }
290
291 omap_wdt_disable();
292 omap_wdt_adjust_timeout(timer_margin);
293
294 omap_wdt_miscdev.dev = &pdev->dev;
295 ret = misc_register(&omap_wdt_miscdev);
296 if (ret)
297 goto fail;
298
299 pr_info("OMAP Watchdog Timer: initial timeout %d sec\n", timer_margin);
300
301 /* autogate OCP interface clock */
302 omap_writel(0x01, OMAP_WATCHDOG_SYS_CONFIG);
303 return 0;
304
305fail:
306 if (armwdt_ck)
307 clk_put(armwdt_ck);
308 if (mpu_wdt_ick)
309 clk_put(mpu_wdt_ick);
310 if (mpu_wdt_fck)
311 clk_put(mpu_wdt_fck);
312 release_resource(mem);
313 return ret;
314}
315
316static void omap_wdt_shutdown(struct platform_device *pdev)
317{
318 omap_wdt_disable();
319}
320
321static int omap_wdt_remove(struct platform_device *pdev)
322{
323 struct resource *mem = platform_get_drvdata(pdev);
324 misc_deregister(&omap_wdt_miscdev);
325 release_resource(mem);
326 if (armwdt_ck)
327 clk_put(armwdt_ck);
328 if (mpu_wdt_ick)
329 clk_put(mpu_wdt_ick);
330 if (mpu_wdt_fck)
331 clk_put(mpu_wdt_fck);
332 return 0;
333}
334
335#ifdef CONFIG_PM
336
337/* REVISIT ... not clear this is the best way to handle system suspend; and
338 * it's very inappropriate for selective device suspend (e.g. suspending this
339 * through sysfs rather than by stopping the watchdog daemon). Also, this
340 * may not play well enough with NOWAYOUT...
341 */
342
343static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state)
344{
345 if (omap_wdt_users)
346 omap_wdt_disable();
347 return 0;
348}
349
350static int omap_wdt_resume(struct platform_device *pdev)
351{
352 if (omap_wdt_users) {
353 omap_wdt_enable();
354 omap_wdt_ping();
355 }
356 return 0;
357}
358
359#else
360#define omap_wdt_suspend NULL
361#define omap_wdt_resume NULL
362#endif
363
364static struct platform_driver omap_wdt_driver = {
365 .probe = omap_wdt_probe,
366 .remove = omap_wdt_remove,
367 .shutdown = omap_wdt_shutdown,
368 .suspend = omap_wdt_suspend,
369 .resume = omap_wdt_resume,
370 .driver = {
371 .owner = THIS_MODULE,
372 .name = "omap_wdt",
373 },
374};
375
376static int __init omap_wdt_init(void)
377{
378 return platform_driver_register(&omap_wdt_driver);
379}
380
381static void __exit omap_wdt_exit(void)
382{
383 platform_driver_unregister(&omap_wdt_driver);
384}
385
386module_init(omap_wdt_init);
387module_exit(omap_wdt_exit);
388
389MODULE_AUTHOR("George G. Davis");
390MODULE_LICENSE("GPL");
391MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/omap_wdt.h b/drivers/char/watchdog/omap_wdt.h
new file mode 100644
index 000000000000..52a532a5114a
--- /dev/null
+++ b/drivers/char/watchdog/omap_wdt.h
@@ -0,0 +1,64 @@
1/*
2 * linux/drivers/char/watchdog/omap_wdt.h
3 *
4 * BRIEF MODULE DESCRIPTION
5 * OMAP Watchdog timer register definitions
6 *
7 * Copyright (C) 2004 Texas Instruments.
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
17 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
20 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 * You should have received a copy of the GNU General Public License along
26 * with this program; if not, write to the Free Software Foundation, Inc.,
27 * 675 Mass Ave, Cambridge, MA 02139, USA.
28 */
29
30#ifndef _OMAP_WATCHDOG_H
31#define _OMAP_WATCHDOG_H
32
33#define OMAP1610_WATCHDOG_BASE 0xfffeb000
34#define OMAP2420_WATCHDOG_BASE 0x48022000 /*WDT Timer 2 */
35
36#ifdef CONFIG_ARCH_OMAP24XX
37#define OMAP_WATCHDOG_BASE OMAP2420_WATCHDOG_BASE
38#else
39#define OMAP_WATCHDOG_BASE OMAP1610_WATCHDOG_BASE
40#define RM_RSTST_WKUP 0
41#endif
42
43#define OMAP_WATCHDOG_REV (OMAP_WATCHDOG_BASE + 0x00)
44#define OMAP_WATCHDOG_SYS_CONFIG (OMAP_WATCHDOG_BASE + 0x10)
45#define OMAP_WATCHDOG_STATUS (OMAP_WATCHDOG_BASE + 0x14)
46#define OMAP_WATCHDOG_CNTRL (OMAP_WATCHDOG_BASE + 0x24)
47#define OMAP_WATCHDOG_CRR (OMAP_WATCHDOG_BASE + 0x28)
48#define OMAP_WATCHDOG_LDR (OMAP_WATCHDOG_BASE + 0x2c)
49#define OMAP_WATCHDOG_TGR (OMAP_WATCHDOG_BASE + 0x30)
50#define OMAP_WATCHDOG_WPS (OMAP_WATCHDOG_BASE + 0x34)
51#define OMAP_WATCHDOG_SPR (OMAP_WATCHDOG_BASE + 0x48)
52
53/* Using the prescaler, the OMAP watchdog could go for many
54 * months before firing. These limits work without scaling,
55 * with the 60 second default assumed by most tools and docs.
56 */
57#define TIMER_MARGIN_MAX (24 * 60 * 60) /* 1 day */
58#define TIMER_MARGIN_DEFAULT 60 /* 60 secs */
59#define TIMER_MARGIN_MIN 1
60
61#define PTV 0 /* prescale */
62#define GET_WLDR_VAL(secs) (0xffffffff - ((secs) * (32768/(1<<PTV))) + 1)
63
64#endif /* _OMAP_WATCHDOG_H */
diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c
index cd7d1b6a5d9f..6f8515db5b07 100644
--- a/drivers/char/watchdog/pcwd.c
+++ b/drivers/char/watchdog/pcwd.c
@@ -572,7 +572,7 @@ static int pcwd_ioctl(struct inode *inode, struct file *file,
572 572
573 switch(cmd) { 573 switch(cmd) {
574 default: 574 default:
575 return -ENOIOCTLCMD; 575 return -ENOTTY;
576 576
577 case WDIOC_GETSUPPORT: 577 case WDIOC_GETSUPPORT:
578 if(copy_to_user(argp, &ident, sizeof(ident))) 578 if(copy_to_user(argp, &ident, sizeof(ident)))
diff --git a/drivers/char/watchdog/pcwd_pci.c b/drivers/char/watchdog/pcwd_pci.c
index c7cfd6dbfe1b..2de6e497c140 100644
--- a/drivers/char/watchdog/pcwd_pci.c
+++ b/drivers/char/watchdog/pcwd_pci.c
@@ -541,7 +541,7 @@ static int pcipcwd_ioctl(struct inode *inode, struct file *file,
541 } 541 }
542 542
543 default: 543 default:
544 return -ENOIOCTLCMD; 544 return -ENOTTY;
545 } 545 }
546} 546}
547 547
diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c
index b7ae73dcdd08..77662cb0ac46 100644
--- a/drivers/char/watchdog/pcwd_usb.c
+++ b/drivers/char/watchdog/pcwd_usb.c
@@ -445,7 +445,7 @@ static int usb_pcwd_ioctl(struct inode *inode, struct file *file,
445 } 445 }
446 446
447 default: 447 default:
448 return -ENOIOCTLCMD; 448 return -ENOTTY;
449 } 449 }
450} 450}
451 451
diff --git a/drivers/char/watchdog/pnx4008_wdt.c b/drivers/char/watchdog/pnx4008_wdt.c
new file mode 100644
index 000000000000..db2731ba88e3
--- /dev/null
+++ b/drivers/char/watchdog/pnx4008_wdt.c
@@ -0,0 +1,362 @@
1/*
2 * drivers/char/watchdog/pnx4008_wdt.c
3 *
4 * Watchdog driver for PNX4008 board
5 *
6 * Authors: Dmitry Chigirev <source@mvista.com>,
7 * Vitaly Wool <vitalywool@gmail.com>
8 * Based on sa1100 driver,
9 * Copyright (C) 2000 Oleg Drokin <green@crimea.edu>
10 *
11 * 2005-2006 (c) MontaVista Software, Inc. This file is licensed under
12 * the terms of the GNU General Public License version 2. This program
13 * is licensed "as is" without any warranty of any kind, whether express
14 * or implied.
15 */
16
17#include <linux/config.h>
18#include <linux/module.h>
19#include <linux/moduleparam.h>
20#include <linux/types.h>
21#include <linux/kernel.h>
22#include <linux/fs.h>
23#include <linux/miscdevice.h>
24#include <linux/watchdog.h>
25#include <linux/init.h>
26#include <linux/bitops.h>
27#include <linux/ioport.h>
28#include <linux/device.h>
29#include <linux/platform_device.h>
30#include <linux/clk.h>
31#include <linux/spinlock.h>
32
33#include <asm/hardware.h>
34#include <asm/uaccess.h>
35#include <asm/io.h>
36
37#define MODULE_NAME "PNX4008-WDT: "
38
39/* WatchDog Timer - Chapter 23 Page 207 */
40
41#define DEFAULT_HEARTBEAT 19
42#define MAX_HEARTBEAT 60
43
44/* Watchdog timer register set definition */
45#define WDTIM_INT(p) ((p) + 0x0)
46#define WDTIM_CTRL(p) ((p) + 0x4)
47#define WDTIM_COUNTER(p) ((p) + 0x8)
48#define WDTIM_MCTRL(p) ((p) + 0xC)
49#define WDTIM_MATCH0(p) ((p) + 0x10)
50#define WDTIM_EMR(p) ((p) + 0x14)
51#define WDTIM_PULSE(p) ((p) + 0x18)
52#define WDTIM_RES(p) ((p) + 0x1C)
53
54/* WDTIM_INT bit definitions */
55#define MATCH_INT 1
56
57/* WDTIM_CTRL bit definitions */
58#define COUNT_ENAB 1
59#define RESET_COUNT (1<<1)
60#define DEBUG_EN (1<<2)
61
62/* WDTIM_MCTRL bit definitions */
63#define MR0_INT 1
64#undef RESET_COUNT0
65#define RESET_COUNT0 (1<<2)
66#define STOP_COUNT0 (1<<2)
67#define M_RES1 (1<<3)
68#define M_RES2 (1<<4)
69#define RESFRC1 (1<<5)
70#define RESFRC2 (1<<6)
71
72/* WDTIM_EMR bit definitions */
73#define EXT_MATCH0 1
74#define MATCH_OUTPUT_HIGH (2<<4) /*a MATCH_CTRL setting */
75
76/* WDTIM_RES bit definitions */
77#define WDOG_RESET 1 /* read only */
78
79#define WDOG_COUNTER_RATE 13000000 /*the counter clock is 13 MHz fixed */
80
81static int nowayout = WATCHDOG_NOWAYOUT;
82static int heartbeat = DEFAULT_HEARTBEAT;
83
84static spinlock_t io_lock;
85static unsigned long wdt_status;
86#define WDT_IN_USE 0
87#define WDT_OK_TO_CLOSE 1
88#define WDT_REGION_INITED 2
89#define WDT_DEVICE_INITED 3
90
91static unsigned long boot_status;
92
93static struct resource *wdt_mem;
94static void __iomem *wdt_base;
95struct clk *wdt_clk;
96
97static void wdt_enable(void)
98{
99 spin_lock(&io_lock);
100
101 if (wdt_clk)
102 clk_set_rate(wdt_clk, 1);
103
104 /* stop counter, initiate counter reset */
105 __raw_writel(RESET_COUNT, WDTIM_CTRL(wdt_base));
106 /*wait for reset to complete. 100% guarantee event */
107 while (__raw_readl(WDTIM_COUNTER(wdt_base)))
108 cpu_relax();
109 /* internal and external reset, stop after that */
110 __raw_writel(M_RES2 | STOP_COUNT0 | RESET_COUNT0,
111 WDTIM_MCTRL(wdt_base));
112 /* configure match output */
113 __raw_writel(MATCH_OUTPUT_HIGH, WDTIM_EMR(wdt_base));
114 /* clear interrupt, just in case */
115 __raw_writel(MATCH_INT, WDTIM_INT(wdt_base));
116 /* the longest pulse period 65541/(13*10^6) seconds ~ 5 ms. */
117 __raw_writel(0xFFFF, WDTIM_PULSE(wdt_base));
118 __raw_writel(heartbeat * WDOG_COUNTER_RATE, WDTIM_MATCH0(wdt_base));
119 /*enable counter, stop when debugger active */
120 __raw_writel(COUNT_ENAB | DEBUG_EN, WDTIM_CTRL(wdt_base));
121
122 spin_unlock(&io_lock);
123}
124
125static void wdt_disable(void)
126{
127 spin_lock(&io_lock);
128
129 __raw_writel(0, WDTIM_CTRL(wdt_base)); /*stop counter */
130 if (wdt_clk)
131 clk_set_rate(wdt_clk, 0);
132
133 spin_unlock(&io_lock);
134}
135
136static int pnx4008_wdt_open(struct inode *inode, struct file *file)
137{
138 if (test_and_set_bit(WDT_IN_USE, &wdt_status))
139 return -EBUSY;
140
141 clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
142
143 wdt_enable();
144
145 return nonseekable_open(inode, file);
146}
147
148static ssize_t
149pnx4008_wdt_write(struct file *file, const char *data, size_t len,
150 loff_t * ppos)
151{
152 /* Can't seek (pwrite) on this device */
153 if (ppos != &file->f_pos)
154 return -ESPIPE;
155
156 if (len) {
157 if (!nowayout) {
158 size_t i;
159
160 clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
161
162 for (i = 0; i != len; i++) {
163 char c;
164
165 if (get_user(c, data + i))
166 return -EFAULT;
167 if (c == 'V')
168 set_bit(WDT_OK_TO_CLOSE, &wdt_status);
169 }
170 }
171 wdt_enable();
172 }
173
174 return len;
175}
176
177static struct watchdog_info ident = {
178 .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE |
179 WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
180 .identity = "PNX4008 Watchdog",
181};
182
183static int
184pnx4008_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
185 unsigned long arg)
186{
187 int ret = -ENOTTY;
188 int time;
189
190 switch (cmd) {
191 case WDIOC_GETSUPPORT:
192 ret = copy_to_user((struct watchdog_info *)arg, &ident,
193 sizeof(ident)) ? -EFAULT : 0;
194 break;
195
196 case WDIOC_GETSTATUS:
197 ret = put_user(0, (int *)arg);
198 break;
199
200 case WDIOC_GETBOOTSTATUS:
201 ret = put_user(boot_status, (int *)arg);
202 break;
203
204 case WDIOC_SETTIMEOUT:
205 ret = get_user(time, (int *)arg);
206 if (ret)
207 break;
208
209 if (time <= 0 || time > MAX_HEARTBEAT) {
210 ret = -EINVAL;
211 break;
212 }
213
214 heartbeat = time;
215 wdt_enable();
216 /* Fall through */
217
218 case WDIOC_GETTIMEOUT:
219 ret = put_user(heartbeat, (int *)arg);
220 break;
221
222 case WDIOC_KEEPALIVE:
223 wdt_enable();
224 ret = 0;
225 break;
226 }
227 return ret;
228}
229
230static int pnx4008_wdt_release(struct inode *inode, struct file *file)
231{
232 if (!test_bit(WDT_OK_TO_CLOSE, &wdt_status))
233 printk(KERN_WARNING "WATCHDOG: Device closed unexpectdly\n");
234
235 wdt_disable();
236 clear_bit(WDT_IN_USE, &wdt_status);
237 clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
238
239 return 0;
240}
241
242static struct file_operations pnx4008_wdt_fops = {
243 .owner = THIS_MODULE,
244 .llseek = no_llseek,
245 .write = pnx4008_wdt_write,
246 .ioctl = pnx4008_wdt_ioctl,
247 .open = pnx4008_wdt_open,
248 .release = pnx4008_wdt_release,
249};
250
251static struct miscdevice pnx4008_wdt_miscdev = {
252 .minor = WATCHDOG_MINOR,
253 .name = "watchdog",
254 .fops = &pnx4008_wdt_fops,
255};
256
257static int pnx4008_wdt_probe(struct platform_device *pdev)
258{
259 int ret = 0, size;
260 struct resource *res;
261
262 spin_lock_init(&io_lock);
263
264 if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
265 heartbeat = DEFAULT_HEARTBEAT;
266
267 printk(KERN_INFO MODULE_NAME
268 "PNX4008 Watchdog Timer: heartbeat %d sec\n", heartbeat);
269
270 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
271 if (res == NULL) {
272 printk(KERN_INFO MODULE_NAME
273 "failed to get memory region resouce\n");
274 return -ENOENT;
275 }
276
277 size = res->end - res->start + 1;
278 wdt_mem = request_mem_region(res->start, size, pdev->name);
279
280 if (wdt_mem == NULL) {
281 printk(KERN_INFO MODULE_NAME "failed to get memory region\n");
282 return -ENOENT;
283 }
284 wdt_base = (void __iomem *)IO_ADDRESS(res->start);
285
286 wdt_clk = clk_get(&pdev->dev, "wdt_ck");
287 if (!wdt_clk) {
288 release_resource(wdt_mem);
289 kfree(wdt_mem);
290 goto out;
291 } else
292 clk_set_rate(wdt_clk, 1);
293
294 ret = misc_register(&pnx4008_wdt_miscdev);
295 if (ret < 0) {
296 printk(KERN_ERR MODULE_NAME "cannot register misc device\n");
297 release_resource(wdt_mem);
298 kfree(wdt_mem);
299 clk_set_rate(wdt_clk, 0);
300 } else {
301 boot_status = (__raw_readl(WDTIM_RES(wdt_base)) & WDOG_RESET) ?
302 WDIOF_CARDRESET : 0;
303 wdt_disable(); /*disable for now */
304 set_bit(WDT_DEVICE_INITED, &wdt_status);
305 }
306
307out:
308 return ret;
309}
310
311static int pnx4008_wdt_remove(struct platform_device *pdev)
312{
313 misc_deregister(&pnx4008_wdt_miscdev);
314 if (wdt_clk) {
315 clk_set_rate(wdt_clk, 0);
316 clk_put(wdt_clk);
317 wdt_clk = NULL;
318 }
319 if (wdt_mem) {
320 release_resource(wdt_mem);
321 kfree(wdt_mem);
322 wdt_mem = NULL;
323 }
324 return 0;
325}
326
327static struct platform_driver platform_wdt_driver = {
328 .driver = {
329 .name = "watchdog",
330 },
331 .probe = pnx4008_wdt_probe,
332 .remove = pnx4008_wdt_remove,
333};
334
335static int __init pnx4008_wdt_init(void)
336{
337 return platform_driver_register(&platform_wdt_driver);
338}
339
340static void __exit pnx4008_wdt_exit(void)
341{
342 return platform_driver_unregister(&platform_wdt_driver);
343}
344
345module_init(pnx4008_wdt_init);
346module_exit(pnx4008_wdt_exit);
347
348MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
349MODULE_DESCRIPTION("PNX4008 Watchdog Driver");
350
351module_param(heartbeat, int, 0);
352MODULE_PARM_DESC(heartbeat,
353 "Watchdog heartbeat period in seconds from 1 to "
354 __MODULE_STRING(MAX_HEARTBEAT) ", default "
355 __MODULE_STRING(DEFAULT_HEARTBEAT));
356
357module_param(nowayout, int, 0);
358MODULE_PARM_DESC(nowayout,
359 "Set to 1 to keep watchdog running after device release");
360
361MODULE_LICENSE("GPL");
362MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c
index be978e8ed754..b36a04ae9ab8 100644
--- a/drivers/char/watchdog/s3c2410_wdt.c
+++ b/drivers/char/watchdog/s3c2410_wdt.c
@@ -62,7 +62,7 @@
62#define CONFIG_S3C2410_WATCHDOG_ATBOOT (0) 62#define CONFIG_S3C2410_WATCHDOG_ATBOOT (0)
63#define CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME (15) 63#define CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME (15)
64 64
65static int nowayout = WATCHDOG_NOWAYOUT; 65static int nowayout = WATCHDOG_NOWAYOUT;
66static int tmr_margin = CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME; 66static int tmr_margin = CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME;
67static int tmr_atboot = CONFIG_S3C2410_WATCHDOG_ATBOOT; 67static int tmr_atboot = CONFIG_S3C2410_WATCHDOG_ATBOOT;
68static int soft_noboot = 0; 68static int soft_noboot = 0;
@@ -213,11 +213,10 @@ static int s3c2410wdt_open(struct inode *inode, struct file *file)
213 if(down_trylock(&open_lock)) 213 if(down_trylock(&open_lock))
214 return -EBUSY; 214 return -EBUSY;
215 215
216 if (nowayout) { 216 if (nowayout)
217 __module_get(THIS_MODULE); 217 __module_get(THIS_MODULE);
218 } else { 218
219 allow_close = CLOSE_STATE_ALLOW; 219 allow_close = CLOSE_STATE_NOT;
220 }
221 220
222 /* start the timer */ 221 /* start the timer */
223 s3c2410wdt_start(); 222 s3c2410wdt_start();
@@ -230,6 +229,7 @@ static int s3c2410wdt_release(struct inode *inode, struct file *file)
230 * Shut off the timer. 229 * Shut off the timer.
231 * Lock it in if it's a module and we set nowayout 230 * Lock it in if it's a module and we set nowayout
232 */ 231 */
232
233 if (allow_close == CLOSE_STATE_ALLOW) { 233 if (allow_close == CLOSE_STATE_ALLOW) {
234 s3c2410wdt_stop(); 234 s3c2410wdt_stop();
235 } else { 235 } else {
@@ -288,7 +288,7 @@ static int s3c2410wdt_ioctl(struct inode *inode, struct file *file,
288 288
289 switch (cmd) { 289 switch (cmd) {
290 default: 290 default:
291 return -ENOIOCTLCMD; 291 return -ENOTTY;
292 292
293 case WDIOC_GETSUPPORT: 293 case WDIOC_GETSUPPORT:
294 return copy_to_user(argp, &s3c2410_wdt_ident, 294 return copy_to_user(argp, &s3c2410_wdt_ident,
diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c
index 1fc16d995788..33c1137f17d6 100644
--- a/drivers/char/watchdog/sa1100_wdt.c
+++ b/drivers/char/watchdog/sa1100_wdt.c
@@ -90,7 +90,7 @@ static struct watchdog_info ident = {
90static int sa1100dog_ioctl(struct inode *inode, struct file *file, 90static int sa1100dog_ioctl(struct inode *inode, struct file *file,
91 unsigned int cmd, unsigned long arg) 91 unsigned int cmd, unsigned long arg)
92{ 92{
93 int ret = -ENOIOCTLCMD; 93 int ret = -ENOTTY;
94 int time; 94 int time;
95 void __user *argp = (void __user *)arg; 95 void __user *argp = (void __user *)arg;
96 int __user *p = argp; 96 int __user *p = argp;
diff --git a/drivers/char/watchdog/sbc60xxwdt.c b/drivers/char/watchdog/sbc60xxwdt.c
index 4663c2fd53cd..c7b2045bc76b 100644
--- a/drivers/char/watchdog/sbc60xxwdt.c
+++ b/drivers/char/watchdog/sbc60xxwdt.c
@@ -235,7 +235,7 @@ static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
235 switch(cmd) 235 switch(cmd)
236 { 236 {
237 default: 237 default:
238 return -ENOIOCTLCMD; 238 return -ENOTTY;
239 case WDIOC_GETSUPPORT: 239 case WDIOC_GETSUPPORT:
240 return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0; 240 return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0;
241 case WDIOC_GETSTATUS: 241 case WDIOC_GETSTATUS:
diff --git a/drivers/char/watchdog/sbc_epx_c3.c b/drivers/char/watchdog/sbc_epx_c3.c
index bfc475dabe6d..8882b427d24f 100644
--- a/drivers/char/watchdog/sbc_epx_c3.c
+++ b/drivers/char/watchdog/sbc_epx_c3.c
@@ -141,7 +141,7 @@ static int epx_c3_ioctl(struct inode *inode, struct file *file,
141 141
142 return retval; 142 return retval;
143 default: 143 default:
144 return -ENOIOCTLCMD; 144 return -ENOTTY;
145 } 145 }
146} 146}
147 147
diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c
index 7c3cf293a5af..d8d0f28e0acf 100644
--- a/drivers/char/watchdog/sc1200wdt.c
+++ b/drivers/char/watchdog/sc1200wdt.c
@@ -180,7 +180,7 @@ static int sc1200wdt_ioctl(struct inode *inode, struct file *file, unsigned int
180 180
181 switch (cmd) { 181 switch (cmd) {
182 default: 182 default:
183 return -ENOIOCTLCMD; /* Keep Pavel Machek amused ;) */ 183 return -ENOTTY;
184 184
185 case WDIOC_GETSUPPORT: 185 case WDIOC_GETSUPPORT:
186 if (copy_to_user(argp, &ident, sizeof ident)) 186 if (copy_to_user(argp, &ident, sizeof ident))
diff --git a/drivers/char/watchdog/sc520_wdt.c b/drivers/char/watchdog/sc520_wdt.c
index 2c7c9db71be8..caec37ba750a 100644
--- a/drivers/char/watchdog/sc520_wdt.c
+++ b/drivers/char/watchdog/sc520_wdt.c
@@ -290,7 +290,7 @@ static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
290 switch(cmd) 290 switch(cmd)
291 { 291 {
292 default: 292 default:
293 return -ENOIOCTLCMD; 293 return -ENOTTY;
294 case WDIOC_GETSUPPORT: 294 case WDIOC_GETSUPPORT:
295 return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0; 295 return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0;
296 case WDIOC_GETSTATUS: 296 case WDIOC_GETSTATUS:
diff --git a/drivers/char/watchdog/scx200_wdt.c b/drivers/char/watchdog/scx200_wdt.c
index c561299a5537..fc0e0347f9d2 100644
--- a/drivers/char/watchdog/scx200_wdt.c
+++ b/drivers/char/watchdog/scx200_wdt.c
@@ -166,7 +166,7 @@ static int scx200_wdt_ioctl(struct inode *inode, struct file *file,
166 166
167 switch (cmd) { 167 switch (cmd) {
168 default: 168 default:
169 return -ENOIOCTLCMD; 169 return -ENOTTY;
170 case WDIOC_GETSUPPORT: 170 case WDIOC_GETSUPPORT:
171 if(copy_to_user(argp, &ident, sizeof(ident))) 171 if(copy_to_user(argp, &ident, sizeof(ident)))
172 return -EFAULT; 172 return -EFAULT;
diff --git a/drivers/char/watchdog/shwdt.c b/drivers/char/watchdog/shwdt.c
index 1355038f1044..dc403629aeb3 100644
--- a/drivers/char/watchdog/shwdt.c
+++ b/drivers/char/watchdog/shwdt.c
@@ -27,7 +27,7 @@
27#include <linux/notifier.h> 27#include <linux/notifier.h>
28#include <linux/ioport.h> 28#include <linux/ioport.h>
29#include <linux/fs.h> 29#include <linux/fs.h>
30 30#include <linux/mm.h>
31#include <asm/io.h> 31#include <asm/io.h>
32#include <asm/uaccess.h> 32#include <asm/uaccess.h>
33#include <asm/watchdog.h> 33#include <asm/watchdog.h>
@@ -125,7 +125,6 @@ static void sh_wdt_start(void)
125 125
126/** 126/**
127 * sh_wdt_stop - Stop the Watchdog 127 * sh_wdt_stop - Stop the Watchdog
128 *
129 * Stops the watchdog. 128 * Stops the watchdog.
130 */ 129 */
131static void sh_wdt_stop(void) 130static void sh_wdt_stop(void)
@@ -141,22 +140,20 @@ static void sh_wdt_stop(void)
141 140
142/** 141/**
143 * sh_wdt_keepalive - Keep the Userspace Watchdog Alive 142 * sh_wdt_keepalive - Keep the Userspace Watchdog Alive
144 *
145 * The Userspace watchdog got a KeepAlive: schedule the next heartbeat. 143 * The Userspace watchdog got a KeepAlive: schedule the next heartbeat.
146 */ 144 */
147static void sh_wdt_keepalive(void) 145static inline void sh_wdt_keepalive(void)
148{ 146{
149 next_heartbeat = jiffies + (heartbeat * HZ); 147 next_heartbeat = jiffies + (heartbeat * HZ);
150} 148}
151 149
152/** 150/**
153 * sh_wdt_set_heartbeat - Set the Userspace Watchdog heartbeat 151 * sh_wdt_set_heartbeat - Set the Userspace Watchdog heartbeat
154 *
155 * Set the Userspace Watchdog heartbeat 152 * Set the Userspace Watchdog heartbeat
156 */ 153 */
157static int sh_wdt_set_heartbeat(int t) 154static int sh_wdt_set_heartbeat(int t)
158{ 155{
159 if ((t < 1) || (t > 3600)) /* arbitrary upper limit */ 156 if (unlikely((t < 1) || (t > 3600))) /* arbitrary upper limit */
160 return -EINVAL; 157 return -EINVAL;
161 158
162 heartbeat = t; 159 heartbeat = t;
@@ -165,7 +162,6 @@ static int sh_wdt_set_heartbeat(int t)
165 162
166/** 163/**
167 * sh_wdt_ping - Ping the Watchdog 164 * sh_wdt_ping - Ping the Watchdog
168 *
169 * @data: Unused 165 * @data: Unused
170 * 166 *
171 * Clears overflow bit, resets timer counter. 167 * Clears overflow bit, resets timer counter.
@@ -182,14 +178,13 @@ static void sh_wdt_ping(unsigned long data)
182 sh_wdt_write_cnt(0); 178 sh_wdt_write_cnt(0);
183 179
184 mod_timer(&timer, next_ping_period(clock_division_ratio)); 180 mod_timer(&timer, next_ping_period(clock_division_ratio));
185 } else { 181 } else
186 printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n"); 182 printk(KERN_WARNING PFX "Heartbeat lost! Will not ping "
187 } 183 "the watchdog\n");
188} 184}
189 185
190/** 186/**
191 * sh_wdt_open - Open the Device 187 * sh_wdt_open - Open the Device
192 *
193 * @inode: inode of device 188 * @inode: inode of device
194 * @file: file handle of device 189 * @file: file handle of device
195 * 190 *
@@ -209,7 +204,6 @@ static int sh_wdt_open(struct inode *inode, struct file *file)
209 204
210/** 205/**
211 * sh_wdt_close - Close the Device 206 * sh_wdt_close - Close the Device
212 *
213 * @inode: inode of device 207 * @inode: inode of device
214 * @file: file handle of device 208 * @file: file handle of device
215 * 209 *
@@ -220,7 +214,8 @@ static int sh_wdt_close(struct inode *inode, struct file *file)
220 if (shwdt_expect_close == 42) { 214 if (shwdt_expect_close == 42) {
221 sh_wdt_stop(); 215 sh_wdt_stop();
222 } else { 216 } else {
223 printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); 217 printk(KERN_CRIT PFX "Unexpected close, not "
218 "stopping watchdog!\n");
224 sh_wdt_keepalive(); 219 sh_wdt_keepalive();
225 } 220 }
226 221
@@ -232,7 +227,6 @@ static int sh_wdt_close(struct inode *inode, struct file *file)
232 227
233/** 228/**
234 * sh_wdt_write - Write to Device 229 * sh_wdt_write - Write to Device
235 *
236 * @file: file handle of device 230 * @file: file handle of device
237 * @buf: buffer to write 231 * @buf: buffer to write
238 * @count: length of buffer 232 * @count: length of buffer
@@ -264,8 +258,56 @@ static ssize_t sh_wdt_write(struct file *file, const char *buf,
264} 258}
265 259
266/** 260/**
267 * sh_wdt_ioctl - Query Device 261 * sh_wdt_mmap - map WDT/CPG registers into userspace
262 * @file: file structure for the device
263 * @vma: VMA to map the registers into
264 *
265 * A simple mmap() implementation for the corner cases where the counter
266 * needs to be mapped in userspace directly. Due to the relatively small
267 * size of the area, neighbouring registers not necessarily tied to the
268 * CPG will also be accessible through the register page, so this remains
269 * configurable for users that really know what they're doing.
268 * 270 *
271 * Additionaly, the register page maps in the CPG register base relative
272 * to the nearest page-aligned boundary, which requires that userspace do
273 * the appropriate CPU subtype math for calculating the page offset for
274 * the counter value.
275 */
276static int sh_wdt_mmap(struct file *file, struct vm_area_struct *vma)
277{
278 int ret = -ENOSYS;
279
280#ifdef CONFIG_SH_WDT_MMAP
281 unsigned long addr;
282
283 /* Only support the simple cases where we map in a register page. */
284 if (((vma->vm_end - vma->vm_start) != PAGE_SIZE) || vma->vm_pgoff)
285 return -EINVAL;
286
287 /*
288 * Pick WTCNT as the start, it's usually the first register after the
289 * FRQCR, and neither one are generally page-aligned out of the box.
290 */
291 addr = WTCNT & ~(PAGE_SIZE - 1);
292
293 vma->vm_flags |= VM_IO;
294 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
295
296 if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
297 PAGE_SIZE, vma->vm_page_prot)) {
298 printk(KERN_ERR PFX "%s: io_remap_pfn_range failed\n",
299 __FUNCTION__);
300 return -EAGAIN;
301 }
302
303 ret = 0;
304#endif
305
306 return ret;
307}
308
309/**
310 * sh_wdt_ioctl - Query Device
269 * @inode: inode of device 311 * @inode: inode of device
270 * @file: file handle of device 312 * @file: file handle of device
271 * @cmd: watchdog command 313 * @cmd: watchdog command
@@ -318,7 +360,7 @@ static int sh_wdt_ioctl(struct inode *inode, struct file *file,
318 360
319 return retval; 361 return retval;
320 default: 362 default:
321 return -ENOIOCTLCMD; 363 return -ENOTTY;
322 } 364 }
323 365
324 return 0; 366 return 0;
@@ -326,7 +368,6 @@ static int sh_wdt_ioctl(struct inode *inode, struct file *file,
326 368
327/** 369/**
328 * sh_wdt_notify_sys - Notifier Handler 370 * sh_wdt_notify_sys - Notifier Handler
329 *
330 * @this: notifier block 371 * @this: notifier block
331 * @code: notifier event 372 * @code: notifier event
332 * @unused: unused 373 * @unused: unused
@@ -337,9 +378,8 @@ static int sh_wdt_ioctl(struct inode *inode, struct file *file,
337static int sh_wdt_notify_sys(struct notifier_block *this, 378static int sh_wdt_notify_sys(struct notifier_block *this,
338 unsigned long code, void *unused) 379 unsigned long code, void *unused)
339{ 380{
340 if (code == SYS_DOWN || code == SYS_HALT) { 381 if (code == SYS_DOWN || code == SYS_HALT)
341 sh_wdt_stop(); 382 sh_wdt_stop();
342 }
343 383
344 return NOTIFY_DONE; 384 return NOTIFY_DONE;
345} 385}
@@ -351,10 +391,12 @@ static const struct file_operations sh_wdt_fops = {
351 .ioctl = sh_wdt_ioctl, 391 .ioctl = sh_wdt_ioctl,
352 .open = sh_wdt_open, 392 .open = sh_wdt_open,
353 .release = sh_wdt_close, 393 .release = sh_wdt_close,
394 .mmap = sh_wdt_mmap,
354}; 395};
355 396
356static struct watchdog_info sh_wdt_info = { 397static struct watchdog_info sh_wdt_info = {
357 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, 398 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
399 WDIOF_MAGICCLOSE,
358 .firmware_version = 1, 400 .firmware_version = 1,
359 .identity = "SH WDT", 401 .identity = "SH WDT",
360}; 402};
@@ -371,7 +413,6 @@ static struct miscdevice sh_wdt_miscdev = {
371 413
372/** 414/**
373 * sh_wdt_init - Initialize module 415 * sh_wdt_init - Initialize module
374 *
375 * Registers the device and notifier handler. Actual device 416 * Registers the device and notifier handler. Actual device
376 * initialization is handled by sh_wdt_open(). 417 * initialization is handled by sh_wdt_open().
377 */ 418 */
@@ -381,15 +422,15 @@ static int __init sh_wdt_init(void)
381 422
382 if ((clock_division_ratio < 0x5) || (clock_division_ratio > 0x7)) { 423 if ((clock_division_ratio < 0x5) || (clock_division_ratio > 0x7)) {
383 clock_division_ratio = WTCSR_CKS_4096; 424 clock_division_ratio = WTCSR_CKS_4096;
384 printk(KERN_INFO PFX "clock_division_ratio value must be 0x5<=x<=0x7, using %d\n", 425 printk(KERN_INFO PFX "clock_division_ratio value must "
385 clock_division_ratio); 426 "be 0x5<=x<=0x7, using %d\n", clock_division_ratio);
386 } 427 }
387 428
388 if (sh_wdt_set_heartbeat(heartbeat)) 429 rc = sh_wdt_set_heartbeat(heartbeat);
389 { 430 if (unlikely(rc)) {
390 heartbeat = WATCHDOG_HEARTBEAT; 431 heartbeat = WATCHDOG_HEARTBEAT;
391 printk(KERN_INFO PFX "heartbeat value must be 1<=x<=3600, using %d\n", 432 printk(KERN_INFO PFX "heartbeat value must "
392 heartbeat); 433 "be 1<=x<=3600, using %d\n", heartbeat);
393 } 434 }
394 435
395 init_timer(&timer); 436 init_timer(&timer);
@@ -397,15 +438,16 @@ static int __init sh_wdt_init(void)
397 timer.data = 0; 438 timer.data = 0;
398 439
399 rc = register_reboot_notifier(&sh_wdt_notifier); 440 rc = register_reboot_notifier(&sh_wdt_notifier);
400 if (rc) { 441 if (unlikely(rc)) {
401 printk(KERN_ERR PFX "Can't register reboot notifier (err=%d)\n", rc); 442 printk(KERN_ERR PFX "Can't register reboot notifier (err=%d)\n",
443 rc);
402 return rc; 444 return rc;
403 } 445 }
404 446
405 rc = misc_register(&sh_wdt_miscdev); 447 rc = misc_register(&sh_wdt_miscdev);
406 if (rc) { 448 if (unlikely(rc)) {
407 printk(KERN_ERR PFX "Can't register miscdev on minor=%d (err=%d)\n", 449 printk(KERN_ERR PFX "Can't register miscdev on "
408 sh_wdt_miscdev.minor, rc); 450 "minor=%d (err=%d)\n", sh_wdt_miscdev.minor, rc);
409 unregister_reboot_notifier(&sh_wdt_notifier); 451 unregister_reboot_notifier(&sh_wdt_notifier);
410 return rc; 452 return rc;
411 } 453 }
@@ -418,7 +460,6 @@ static int __init sh_wdt_init(void)
418 460
419/** 461/**
420 * sh_wdt_exit - Deinitialize module 462 * sh_wdt_exit - Deinitialize module
421 *
422 * Unregisters the device and notifier handler. Actual device 463 * Unregisters the device and notifier handler. Actual device
423 * deinitialization is handled by sh_wdt_close(). 464 * deinitialization is handled by sh_wdt_close().
424 */ 465 */
@@ -434,14 +475,13 @@ MODULE_LICENSE("GPL");
434MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 475MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
435 476
436module_param(clock_division_ratio, int, 0); 477module_param(clock_division_ratio, int, 0);
437MODULE_PARM_DESC(clock_division_ratio, "Clock division ratio. Valid ranges are from 0x5 (1.31ms) to 0x7 (5.25ms). Defaults to 0x7."); 478MODULE_PARM_DESC(clock_division_ratio, "Clock division ratio. Valid ranges are from 0x5 (1.31ms) to 0x7 (5.25ms). (default=" __MODULE_STRING(clock_division_ratio) ")");
438 479
439module_param(heartbeat, int, 0); 480module_param(heartbeat, int, 0);
440MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (1<=heartbeat<=3600, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); 481MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (1<=heartbeat<=3600, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
441 482
442module_param(nowayout, int, 0); 483module_param(nowayout, int, 0);
443MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 484MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
444 485
445module_init(sh_wdt_init); 486module_init(sh_wdt_init);
446module_exit(sh_wdt_exit); 487module_exit(sh_wdt_exit);
447
diff --git a/drivers/char/watchdog/softdog.c b/drivers/char/watchdog/softdog.c
index ef8da517545a..4067e1f8a368 100644
--- a/drivers/char/watchdog/softdog.c
+++ b/drivers/char/watchdog/softdog.c
@@ -203,7 +203,7 @@ static int softdog_ioctl(struct inode *inode, struct file *file,
203 }; 203 };
204 switch (cmd) { 204 switch (cmd) {
205 default: 205 default:
206 return -ENOIOCTLCMD; 206 return -ENOTTY;
207 case WDIOC_GETSUPPORT: 207 case WDIOC_GETSUPPORT:
208 return copy_to_user(argp, &ident, 208 return copy_to_user(argp, &ident,
209 sizeof(ident)) ? -EFAULT : 0; 209 sizeof(ident)) ? -EFAULT : 0;
diff --git a/drivers/char/watchdog/w83627hf_wdt.c b/drivers/char/watchdog/w83627hf_wdt.c
index 13f16d41c2fd..b4adc527e687 100644
--- a/drivers/char/watchdog/w83627hf_wdt.c
+++ b/drivers/char/watchdog/w83627hf_wdt.c
@@ -223,7 +223,7 @@ wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
223 } 223 }
224 224
225 default: 225 default:
226 return -ENOIOCTLCMD; 226 return -ENOTTY;
227 } 227 }
228 return 0; 228 return 0;
229} 229}
diff --git a/drivers/char/watchdog/w83877f_wdt.c b/drivers/char/watchdog/w83877f_wdt.c
index ccf6c0915945..b0e5f84d6baf 100644
--- a/drivers/char/watchdog/w83877f_wdt.c
+++ b/drivers/char/watchdog/w83877f_wdt.c
@@ -252,7 +252,7 @@ static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
252 switch(cmd) 252 switch(cmd)
253 { 253 {
254 default: 254 default:
255 return -ENOIOCTLCMD; 255 return -ENOTTY;
256 case WDIOC_GETSUPPORT: 256 case WDIOC_GETSUPPORT:
257 return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0; 257 return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0;
258 case WDIOC_GETSTATUS: 258 case WDIOC_GETSTATUS:
diff --git a/drivers/char/watchdog/w83977f_wdt.c b/drivers/char/watchdog/w83977f_wdt.c
index 98f4e17db70a..2c8d5d8bd4e8 100644
--- a/drivers/char/watchdog/w83977f_wdt.c
+++ b/drivers/char/watchdog/w83977f_wdt.c
@@ -393,7 +393,7 @@ static int wdt_ioctl(struct inode *inode, struct file *file,
393 switch(cmd) 393 switch(cmd)
394 { 394 {
395 default: 395 default:
396 return -ENOIOCTLCMD; 396 return -ENOTTY;
397 397
398 case WDIOC_GETSUPPORT: 398 case WDIOC_GETSUPPORT:
399 return copy_to_user(uarg.ident, &ident, sizeof(ident)) ? -EFAULT : 0; 399 return copy_to_user(uarg.ident, &ident, sizeof(ident)) ? -EFAULT : 0;
diff --git a/drivers/char/watchdog/wafer5823wdt.c b/drivers/char/watchdog/wafer5823wdt.c
index 2bb6a9d6ad28..163e028ef9ed 100644
--- a/drivers/char/watchdog/wafer5823wdt.c
+++ b/drivers/char/watchdog/wafer5823wdt.c
@@ -174,7 +174,7 @@ static int wafwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd
174 } 174 }
175 175
176 default: 176 default:
177 return -ENOIOCTLCMD; 177 return -ENOTTY;
178 } 178 }
179 return 0; 179 return 0;
180} 180}
diff --git a/drivers/char/watchdog/wdrtas.c b/drivers/char/watchdog/wdrtas.c
index 5c38cdf41731..1d64e277567d 100644
--- a/drivers/char/watchdog/wdrtas.c
+++ b/drivers/char/watchdog/wdrtas.c
@@ -385,7 +385,7 @@ wdrtas_ioctl(struct inode *inode, struct file *file,
385 return put_user(wdrtas_interval, argp); 385 return put_user(wdrtas_interval, argp);
386 386
387 default: 387 default:
388 return -ENOIOCTLCMD; 388 return -ENOTTY;
389 } 389 }
390} 390}
391 391
diff --git a/drivers/char/watchdog/wdt.c b/drivers/char/watchdog/wdt.c
index 70be81e39a61..13f23f4a2233 100644
--- a/drivers/char/watchdog/wdt.c
+++ b/drivers/char/watchdog/wdt.c
@@ -341,7 +341,7 @@ static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
341 switch(cmd) 341 switch(cmd)
342 { 342 {
343 default: 343 default:
344 return -ENOIOCTLCMD; 344 return -ENOTTY;
345 case WDIOC_GETSUPPORT: 345 case WDIOC_GETSUPPORT:
346 return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0; 346 return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0;
347 347
diff --git a/drivers/char/watchdog/wdt285.c b/drivers/char/watchdog/wdt285.c
index 6555fb844f23..89a249e23fde 100644
--- a/drivers/char/watchdog/wdt285.c
+++ b/drivers/char/watchdog/wdt285.c
@@ -137,7 +137,7 @@ watchdog_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
137 unsigned long arg) 137 unsigned long arg)
138{ 138{
139 unsigned int new_margin; 139 unsigned int new_margin;
140 int ret = -ENOIOCTLCMD; 140 int ret = -ENOTTY;
141 141
142 switch(cmd) { 142 switch(cmd) {
143 case WDIOC_GETSUPPORT: 143 case WDIOC_GETSUPPORT:
diff --git a/drivers/char/watchdog/wdt977.c b/drivers/char/watchdog/wdt977.c
index a0935bc775f8..6253041b235b 100644
--- a/drivers/char/watchdog/wdt977.c
+++ b/drivers/char/watchdog/wdt977.c
@@ -361,7 +361,7 @@ static int wdt977_ioctl(struct inode *inode, struct file *file,
361 switch(cmd) 361 switch(cmd)
362 { 362 {
363 default: 363 default:
364 return -ENOIOCTLCMD; 364 return -ENOTTY;
365 365
366 case WDIOC_GETSUPPORT: 366 case WDIOC_GETSUPPORT:
367 return copy_to_user(uarg.ident, &ident, 367 return copy_to_user(uarg.ident, &ident,
diff --git a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c
index 5918ca2c9c35..74d8cf836e13 100644
--- a/drivers/char/watchdog/wdt_pci.c
+++ b/drivers/char/watchdog/wdt_pci.c
@@ -386,7 +386,7 @@ static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd
386 switch(cmd) 386 switch(cmd)
387 { 387 {
388 default: 388 default:
389 return -ENOIOCTLCMD; 389 return -ENOTTY;
390 case WDIOC_GETSUPPORT: 390 case WDIOC_GETSUPPORT:
391 return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0; 391 return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0;
392 392