diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2007-10-12 21:27:47 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2007-10-12 21:27:47 -0400 |
commit | b981d8b3f5e008ff10d993be633ad00564fc22cd (patch) | |
tree | e292dc07b22308912cf6a58354a608b9e5e8e1fd /drivers/char | |
parent | b11d2127c4893a7315d1e16273bc8560049fa3ca (diff) | |
parent | 2b9e0aae1d50e880c58d46788e5e3ebd89d75d62 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts:
drivers/macintosh/adbhid.c
Diffstat (limited to 'drivers/char')
104 files changed, 2997 insertions, 711 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index d8d7125529c4..b391776e5bf3 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -130,6 +130,7 @@ config ROCKETPORT | |||
130 | config CYCLADES | 130 | config CYCLADES |
131 | tristate "Cyclades async mux support" | 131 | tristate "Cyclades async mux support" |
132 | depends on SERIAL_NONSTANDARD && (PCI || ISA) | 132 | depends on SERIAL_NONSTANDARD && (PCI || ISA) |
133 | select FW_LOADER | ||
133 | ---help--- | 134 | ---help--- |
134 | This driver supports Cyclades Z and Y multiserial boards. | 135 | This driver supports Cyclades Z and Y multiserial boards. |
135 | You would need something like this to connect more than two modems to | 136 | You would need something like this to connect more than two modems to |
@@ -185,7 +186,7 @@ config ESPSERIAL | |||
185 | 186 | ||
186 | config MOXA_INTELLIO | 187 | config MOXA_INTELLIO |
187 | tristate "Moxa Intellio support" | 188 | tristate "Moxa Intellio support" |
188 | depends on SERIAL_NONSTANDARD | 189 | depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI) |
189 | help | 190 | help |
190 | Say Y here if you have a Moxa Intellio multiport serial card. | 191 | Say Y here if you have a Moxa Intellio multiport serial card. |
191 | 192 | ||
@@ -241,7 +242,7 @@ config SYNCLINK | |||
241 | 242 | ||
242 | config SYNCLINKMP | 243 | config SYNCLINKMP |
243 | tristate "SyncLink Multiport support" | 244 | tristate "SyncLink Multiport support" |
244 | depends on SERIAL_NONSTANDARD | 245 | depends on SERIAL_NONSTANDARD && PCI |
245 | help | 246 | help |
246 | Enable support for the SyncLink Multiport (2 or 4 ports) | 247 | Enable support for the SyncLink Multiport (2 or 4 ports) |
247 | serial adapter, running asynchronous and HDLC communications up | 248 | serial adapter, running asynchronous and HDLC communications up |
@@ -372,39 +373,6 @@ config ISTALLION | |||
372 | To compile this driver as a module, choose M here: the | 373 | To compile this driver as a module, choose M here: the |
373 | module will be called istallion. | 374 | module will be called istallion. |
374 | 375 | ||
375 | config SERIAL_DEC | ||
376 | bool "DECstation serial support" | ||
377 | depends on MACH_DECSTATION | ||
378 | default y | ||
379 | help | ||
380 | This selects whether you want to be asked about drivers for | ||
381 | DECstation serial ports. | ||
382 | |||
383 | Note that the answer to this question won't directly affect the | ||
384 | kernel: saying N will just cause the configurator to skip all | ||
385 | the questions about DECstation serial ports. | ||
386 | |||
387 | config SERIAL_DEC_CONSOLE | ||
388 | bool "Support for console on a DECstation serial port" | ||
389 | depends on SERIAL_DEC | ||
390 | default y | ||
391 | help | ||
392 | If you say Y here, it will be possible to use a serial port as the | ||
393 | system console (the system console is the device which receives all | ||
394 | kernel messages and warnings and which allows logins in single user | ||
395 | mode). Note that the firmware uses ttyS0 as the serial console on | ||
396 | the Maxine and ttyS2 on the others. | ||
397 | |||
398 | If unsure, say Y. | ||
399 | |||
400 | config ZS | ||
401 | bool "Z85C30 Serial Support" | ||
402 | depends on SERIAL_DEC | ||
403 | default y | ||
404 | help | ||
405 | Documentation on the Zilog 85C350 serial communications controller | ||
406 | is downloadable at <http://www.zilog.com/pdfs/serial/z85c30.pdf> | ||
407 | |||
408 | config A2232 | 376 | config A2232 |
409 | tristate "Commodore A2232 serial support (EXPERIMENTAL)" | 377 | tristate "Commodore A2232 serial support (EXPERIMENTAL)" |
410 | depends on EXPERIMENTAL && ZORRO && BROKEN_ON_SMP | 378 | depends on EXPERIMENTAL && ZORRO && BROKEN_ON_SMP |
@@ -637,6 +605,14 @@ config HVC_BEAT | |||
637 | help | 605 | help |
638 | Toshiba's Cell Reference Set Beat Console device driver | 606 | Toshiba's Cell Reference Set Beat Console device driver |
639 | 607 | ||
608 | config HVC_XEN | ||
609 | bool "Xen Hypervisor Console support" | ||
610 | depends on XEN | ||
611 | select HVC_DRIVER | ||
612 | default y | ||
613 | help | ||
614 | Xen virtual console device driver | ||
615 | |||
640 | config HVCS | 616 | config HVCS |
641 | tristate "IBM Hypervisor Virtual Console Server support" | 617 | tristate "IBM Hypervisor Virtual Console Server support" |
642 | depends on PPC_PSERIES | 618 | depends on PPC_PSERIES |
@@ -751,7 +727,7 @@ config NVRAM | |||
751 | 727 | ||
752 | config RTC | 728 | config RTC |
753 | tristate "Enhanced Real Time Clock Support" | 729 | tristate "Enhanced Real Time Clock Support" |
754 | depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM && !SUPERH && !S390 | 730 | depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC && !FRV && !ARM && !SUPERH && !S390 |
755 | ---help--- | 731 | ---help--- |
756 | If you say Y here and create a character special file /dev/rtc with | 732 | If you say Y here and create a character special file /dev/rtc with |
757 | major number 10 and minor number 135 using mknod ("man mknod"), you | 733 | major number 10 and minor number 135 using mknod ("man mknod"), you |
@@ -775,6 +751,28 @@ config RTC | |||
775 | To compile this driver as a module, choose M here: the | 751 | To compile this driver as a module, choose M here: the |
776 | module will be called rtc. | 752 | module will be called rtc. |
777 | 753 | ||
754 | config JS_RTC | ||
755 | tristate "Enhanced Real Time Clock Support" | ||
756 | depends on SPARC32 && PCI | ||
757 | ---help--- | ||
758 | If you say Y here and create a character special file /dev/rtc with | ||
759 | major number 10 and minor number 135 using mknod ("man mknod"), you | ||
760 | will get access to the real time clock (or hardware clock) built | ||
761 | into your computer. | ||
762 | |||
763 | Every PC has such a clock built in. It can be used to generate | ||
764 | signals from as low as 1Hz up to 8192Hz, and can also be used | ||
765 | as a 24 hour alarm. It reports status information via the file | ||
766 | /proc/driver/rtc and its behaviour is set by various ioctls on | ||
767 | /dev/rtc. | ||
768 | |||
769 | If you think you have a use for such a device (such as periodic data | ||
770 | sampling), then say Y here, and read <file:Documentation/rtc.txt> | ||
771 | for details. | ||
772 | |||
773 | To compile this driver as a module, choose M here: the | ||
774 | module will be called js-rtc. | ||
775 | |||
778 | config SGI_DS1286 | 776 | config SGI_DS1286 |
779 | tristate "SGI DS1286 RTC support" | 777 | tristate "SGI DS1286 RTC support" |
780 | depends on SGI_IP22 | 778 | depends on SGI_IP22 |
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index f2996a95eb07..c78ff26647ee 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -42,12 +42,14 @@ obj-$(CONFIG_SYNCLINK_GT) += synclink_gt.o | |||
42 | obj-$(CONFIG_N_HDLC) += n_hdlc.o | 42 | obj-$(CONFIG_N_HDLC) += n_hdlc.o |
43 | obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o | 43 | obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o |
44 | obj-$(CONFIG_SX) += sx.o generic_serial.o | 44 | obj-$(CONFIG_SX) += sx.o generic_serial.o |
45 | obj-$(CONFIG_LGUEST_GUEST) += hvc_lguest.o | ||
45 | obj-$(CONFIG_RIO) += rio/ generic_serial.o | 46 | obj-$(CONFIG_RIO) += rio/ generic_serial.o |
46 | obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o | 47 | obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o |
47 | obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o | 48 | obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o |
48 | obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o | 49 | obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o |
49 | obj-$(CONFIG_HVC_BEAT) += hvc_beat.o | 50 | obj-$(CONFIG_HVC_BEAT) += hvc_beat.o |
50 | obj-$(CONFIG_HVC_DRIVER) += hvc_console.o | 51 | obj-$(CONFIG_HVC_DRIVER) += hvc_console.o |
52 | obj-$(CONFIG_HVC_XEN) += hvc_xen.o | ||
51 | obj-$(CONFIG_RAW_DRIVER) += raw.o | 53 | obj-$(CONFIG_RAW_DRIVER) += raw.o |
52 | obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o | 54 | obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o |
53 | obj-$(CONFIG_MSPEC) += mspec.o | 55 | obj-$(CONFIG_MSPEC) += mspec.o |
@@ -95,7 +97,6 @@ obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o | |||
95 | obj-$(CONFIG_GPIO_TB0219) += tb0219.o | 97 | obj-$(CONFIG_GPIO_TB0219) += tb0219.o |
96 | obj-$(CONFIG_TELCLOCK) += tlclk.o | 98 | obj-$(CONFIG_TELCLOCK) += tlclk.o |
97 | 99 | ||
98 | obj-$(CONFIG_WATCHDOG) += watchdog/ | ||
99 | obj-$(CONFIG_MWAVE) += mwave/ | 100 | obj-$(CONFIG_MWAVE) += mwave/ |
100 | obj-$(CONFIG_AGP) += agp/ | 101 | obj-$(CONFIG_AGP) += agp/ |
101 | obj-$(CONFIG_DRM) += drm/ | 102 | obj-$(CONFIG_DRM) += drm/ |
@@ -105,6 +106,11 @@ obj-$(CONFIG_IPMI_HANDLER) += ipmi/ | |||
105 | obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o | 106 | obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o |
106 | obj-$(CONFIG_TCG_TPM) += tpm/ | 107 | obj-$(CONFIG_TCG_TPM) += tpm/ |
107 | 108 | ||
109 | obj-$(CONFIG_PS3_FLASH) += ps3flash.o | ||
110 | |||
111 | obj-$(CONFIG_JS_RTC) += js-rtc.o | ||
112 | js-rtc-y = rtc.o | ||
113 | |||
108 | # Files generated that shall be removed upon make clean | 114 | # Files generated that shall be removed upon make clean |
109 | clean-files := consolemap_deftbl.c defkeymap.c | 115 | clean-files := consolemap_deftbl.c defkeymap.c |
110 | 116 | ||
@@ -123,7 +129,7 @@ $(obj)/defkeymap.o: $(obj)/defkeymap.c | |||
123 | 129 | ||
124 | ifdef GENERATE_KEYMAP | 130 | ifdef GENERATE_KEYMAP |
125 | 131 | ||
126 | $(obj)/defkeymap.c $(obj)/%.c: $(src)/%.map | 132 | $(obj)/defkeymap.c: $(obj)/%.c: $(src)/%.map |
127 | loadkeys --mktable $< > $@.tmp | 133 | loadkeys --mktable $< > $@.tmp |
128 | sed -e 's/^static *//' $@.tmp > $@ | 134 | sed -e 's/^static *//' $@.tmp > $@ |
129 | rm $@.tmp | 135 | rm $@.tmp |
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index a9f9c48c2424..713533d8a86e 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig | |||
@@ -50,7 +50,7 @@ config AGP_ATI | |||
50 | 50 | ||
51 | config AGP_AMD | 51 | config AGP_AMD |
52 | tristate "AMD Irongate, 761, and 762 chipset support" | 52 | tristate "AMD Irongate, 761, and 762 chipset support" |
53 | depends on AGP && X86_32 | 53 | depends on AGP && (X86_32 || ALPHA) |
54 | help | 54 | help |
55 | This option gives you AGP support for the GLX component of | 55 | This option gives you AGP support for the GLX component of |
56 | X on AMD Irongate, 761, and 762 chipsets. | 56 | X on AMD Irongate, 761, and 762 chipsets. |
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h index 35ab1a9f8e8b..8955e7ff759a 100644 --- a/drivers/char/agp/agp.h +++ b/drivers/char/agp/agp.h | |||
@@ -176,7 +176,7 @@ struct agp_bridge_data { | |||
176 | #define I830_GMCH_MEM_MASK 0x1 | 176 | #define I830_GMCH_MEM_MASK 0x1 |
177 | #define I830_GMCH_MEM_64M 0x1 | 177 | #define I830_GMCH_MEM_64M 0x1 |
178 | #define I830_GMCH_MEM_128M 0 | 178 | #define I830_GMCH_MEM_128M 0 |
179 | #define I830_GMCH_GMS_MASK 0xF0 | 179 | #define I830_GMCH_GMS_MASK 0x70 |
180 | #define I830_GMCH_GMS_DISABLED 0x00 | 180 | #define I830_GMCH_GMS_DISABLED 0x00 |
181 | #define I830_GMCH_GMS_LOCAL 0x10 | 181 | #define I830_GMCH_GMS_LOCAL 0x10 |
182 | #define I830_GMCH_GMS_STOLEN_512 0x20 | 182 | #define I830_GMCH_GMS_STOLEN_512 0x20 |
@@ -190,6 +190,7 @@ struct agp_bridge_data { | |||
190 | #define INTEL_I830_ERRSTS 0x92 | 190 | #define INTEL_I830_ERRSTS 0x92 |
191 | 191 | ||
192 | /* Intel 855GM/852GM registers */ | 192 | /* Intel 855GM/852GM registers */ |
193 | #define I855_GMCH_GMS_MASK 0xF0 | ||
193 | #define I855_GMCH_GMS_STOLEN_0M 0x0 | 194 | #define I855_GMCH_GMS_STOLEN_0M 0x0 |
194 | #define I855_GMCH_GMS_STOLEN_1M (0x1 << 4) | 195 | #define I855_GMCH_GMS_STOLEN_1M (0x1 << 4) |
195 | #define I855_GMCH_GMS_STOLEN_4M (0x2 << 4) | 196 | #define I855_GMCH_GMS_STOLEN_4M (0x2 << 4) |
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c index df0ddf14b85c..f60bca70d1fb 100644 --- a/drivers/char/agp/amd-k7-agp.c +++ b/drivers/char/agp/amd-k7-agp.c | |||
@@ -223,6 +223,8 @@ static int amd_irongate_configure(void) | |||
223 | pci_read_config_dword(agp_bridge->dev, AMD_MMBASE, &temp); | 223 | pci_read_config_dword(agp_bridge->dev, AMD_MMBASE, &temp); |
224 | temp = (temp & PCI_BASE_ADDRESS_MEM_MASK); | 224 | temp = (temp & PCI_BASE_ADDRESS_MEM_MASK); |
225 | amd_irongate_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096); | 225 | amd_irongate_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096); |
226 | if (!amd_irongate_private.registers) | ||
227 | return -ENOMEM; | ||
226 | 228 | ||
227 | /* Write out the address of the gatt table */ | 229 | /* Write out the address of the gatt table */ |
228 | writel(agp_bridge->gatt_bus_addr, amd_irongate_private.registers+AMD_ATTBASE); | 230 | writel(agp_bridge->gatt_bus_addr, amd_irongate_private.registers+AMD_ATTBASE); |
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index 780e59e588ad..2d46b713c8f2 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c | |||
@@ -123,21 +123,16 @@ static int ati_create_gatt_pages(int nr_tables) | |||
123 | 123 | ||
124 | for (i = 0; i < nr_tables; i++) { | 124 | for (i = 0; i < nr_tables; i++) { |
125 | entry = kzalloc(sizeof(struct ati_page_map), GFP_KERNEL); | 125 | entry = kzalloc(sizeof(struct ati_page_map), GFP_KERNEL); |
126 | tables[i] = entry; | ||
126 | if (entry == NULL) { | 127 | if (entry == NULL) { |
127 | while (i > 0) { | ||
128 | kfree(tables[i-1]); | ||
129 | i--; | ||
130 | } | ||
131 | kfree(tables); | ||
132 | retval = -ENOMEM; | 128 | retval = -ENOMEM; |
133 | break; | 129 | break; |
134 | } | 130 | } |
135 | tables[i] = entry; | ||
136 | retval = ati_create_page_map(entry); | 131 | retval = ati_create_page_map(entry); |
137 | if (retval != 0) | 132 | if (retval != 0) |
138 | break; | 133 | break; |
139 | } | 134 | } |
140 | ati_generic_private.num_tables = nr_tables; | 135 | ati_generic_private.num_tables = i; |
141 | ati_generic_private.gatt_pages = tables; | 136 | ati_generic_private.gatt_pages = tables; |
142 | 137 | ||
143 | if (retval != 0) | 138 | if (retval != 0) |
@@ -218,6 +213,9 @@ static int ati_configure(void) | |||
218 | temp = (temp & 0xfffff000); | 213 | temp = (temp & 0xfffff000); |
219 | ati_generic_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096); | 214 | ati_generic_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096); |
220 | 215 | ||
216 | if (!ati_generic_private.registers) | ||
217 | return -ENOMEM; | ||
218 | |||
221 | if (is_r200()) | 219 | if (is_r200()) |
222 | pci_write_config_dword(agp_bridge->dev, ATI_RS100_IG_AGPMODE, 0x20000); | 220 | pci_write_config_dword(agp_bridge->dev, ATI_RS100_IG_AGPMODE, 0x20000); |
223 | else | 221 | else |
diff --git a/drivers/char/agp/compat_ioctl.c b/drivers/char/agp/compat_ioctl.c index fcb4b1bf0d4e..ecd4248861b9 100644 --- a/drivers/char/agp/compat_ioctl.c +++ b/drivers/char/agp/compat_ioctl.c | |||
@@ -28,6 +28,7 @@ | |||
28 | 28 | ||
29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
30 | #include <linux/pci.h> | 30 | #include <linux/pci.h> |
31 | #include <linux/fs.h> | ||
31 | #include <linux/agpgart.h> | 32 | #include <linux/agpgart.h> |
32 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
33 | #include "agp.h" | 34 | #include "agp.h" |
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c index df8da7262853..d78cd09186aa 100644 --- a/drivers/char/agp/efficeon-agp.c +++ b/drivers/char/agp/efficeon-agp.c | |||
@@ -375,6 +375,7 @@ static int __devinit agp_efficeon_probe(struct pci_dev *pdev, | |||
375 | if (!r->start && r->end) { | 375 | if (!r->start && r->end) { |
376 | if (pci_assign_resource(pdev, 0)) { | 376 | if (pci_assign_resource(pdev, 0)) { |
377 | printk(KERN_ERR PFX "could not assign resource 0\n"); | 377 | printk(KERN_ERR PFX "could not assign resource 0\n"); |
378 | agp_put_bridge(bridge); | ||
378 | return -ENODEV; | 379 | return -ENODEV; |
379 | } | 380 | } |
380 | } | 381 | } |
@@ -386,6 +387,7 @@ static int __devinit agp_efficeon_probe(struct pci_dev *pdev, | |||
386 | */ | 387 | */ |
387 | if (pci_enable_device(pdev)) { | 388 | if (pci_enable_device(pdev)) { |
388 | printk(KERN_ERR PFX "Unable to Enable PCI device\n"); | 389 | printk(KERN_ERR PFX "Unable to Enable PCI device\n"); |
390 | agp_put_bridge(bridge); | ||
389 | return -ENODEV; | 391 | return -ENODEV; |
390 | } | 392 | } |
391 | 393 | ||
diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c index c7ed617aa7ff..7791e98de51c 100644 --- a/drivers/char/agp/frontend.c +++ b/drivers/char/agp/frontend.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/agpgart.h> | 37 | #include <linux/agpgart.h> |
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/mm.h> | 39 | #include <linux/mm.h> |
40 | #include <linux/fs.h> | ||
40 | #include <linux/sched.h> | 41 | #include <linux/sched.h> |
41 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
42 | #include <asm/pgtable.h> | 43 | #include <asm/pgtable.h> |
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index d535c406b319..3db4f4076ed4 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c | |||
@@ -1170,7 +1170,6 @@ void *agp_generic_alloc_page(struct agp_bridge_data *bridge) | |||
1170 | map_page_into_agp(page); | 1170 | map_page_into_agp(page); |
1171 | 1171 | ||
1172 | get_page(page); | 1172 | get_page(page); |
1173 | SetPageLocked(page); | ||
1174 | atomic_inc(&agp_bridge->current_memory_agp); | 1173 | atomic_inc(&agp_bridge->current_memory_agp); |
1175 | return page_address(page); | 1174 | return page_address(page); |
1176 | } | 1175 | } |
@@ -1187,7 +1186,6 @@ void agp_generic_destroy_page(void *addr) | |||
1187 | page = virt_to_page(addr); | 1186 | page = virt_to_page(addr); |
1188 | unmap_page_from_agp(page); | 1187 | unmap_page_from_agp(page); |
1189 | put_page(page); | 1188 | put_page(page); |
1190 | unlock_page(page); | ||
1191 | free_page((unsigned long)addr); | 1189 | free_page((unsigned long)addr); |
1192 | atomic_dec(&agp_bridge->current_memory_agp); | 1190 | atomic_dec(&agp_bridge->current_memory_agp); |
1193 | } | 1191 | } |
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c index bcdb149c8179..313a133a1172 100644 --- a/drivers/char/agp/hp-agp.c +++ b/drivers/char/agp/hp-agp.c | |||
@@ -221,6 +221,7 @@ hp_zx1_lba_init (u64 hpa) | |||
221 | if (cap != PCI_CAP_ID_AGP) { | 221 | if (cap != PCI_CAP_ID_AGP) { |
222 | printk(KERN_ERR PFX "Invalid capability ID 0x%02x at 0x%x\n", | 222 | printk(KERN_ERR PFX "Invalid capability ID 0x%02x at 0x%x\n", |
223 | cap, hp->lba_cap_offset); | 223 | cap, hp->lba_cap_offset); |
224 | iounmap(hp->lba_regs); | ||
224 | return -ENODEV; | 225 | return -ENODEV; |
225 | } | 226 | } |
226 | 227 | ||
diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c index 53354bf83af7..75d2aca6353d 100644 --- a/drivers/char/agp/i460-agp.c +++ b/drivers/char/agp/i460-agp.c | |||
@@ -249,6 +249,10 @@ static int i460_create_gatt_table (struct agp_bridge_data *bridge) | |||
249 | num_entries = A_SIZE_8(temp)->num_entries; | 249 | num_entries = A_SIZE_8(temp)->num_entries; |
250 | 250 | ||
251 | i460.gatt = ioremap(INTEL_I460_ATTBASE, PAGE_SIZE << page_order); | 251 | i460.gatt = ioremap(INTEL_I460_ATTBASE, PAGE_SIZE << page_order); |
252 | if (!i460.gatt) { | ||
253 | printk(KERN_ERR PFX "ioremap failed\n"); | ||
254 | return -ENOMEM; | ||
255 | } | ||
252 | 256 | ||
253 | /* These are no good, the should be removed from the agp_bridge strucure... */ | 257 | /* These are no good, the should be removed from the agp_bridge strucure... */ |
254 | agp_bridge->gatt_table_real = NULL; | 258 | agp_bridge->gatt_table_real = NULL; |
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index a1240603912c..141ca176c397 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c | |||
@@ -20,7 +20,9 @@ | |||
20 | #define PCI_DEVICE_ID_INTEL_82965G_IG 0x29A2 | 20 | #define PCI_DEVICE_ID_INTEL_82965G_IG 0x29A2 |
21 | #define PCI_DEVICE_ID_INTEL_82965GM_HB 0x2A00 | 21 | #define PCI_DEVICE_ID_INTEL_82965GM_HB 0x2A00 |
22 | #define PCI_DEVICE_ID_INTEL_82965GM_IG 0x2A02 | 22 | #define PCI_DEVICE_ID_INTEL_82965GM_IG 0x2A02 |
23 | #define PCI_DEVICE_ID_INTEL_82965GME_HB 0x2A10 | ||
23 | #define PCI_DEVICE_ID_INTEL_82965GME_IG 0x2A12 | 24 | #define PCI_DEVICE_ID_INTEL_82965GME_IG 0x2A12 |
25 | #define PCI_DEVICE_ID_INTEL_82945GME_HB 0x27AC | ||
24 | #define PCI_DEVICE_ID_INTEL_82945GME_IG 0x27AE | 26 | #define PCI_DEVICE_ID_INTEL_82945GME_IG 0x27AE |
25 | #define PCI_DEVICE_ID_INTEL_G33_HB 0x29C0 | 27 | #define PCI_DEVICE_ID_INTEL_G33_HB 0x29C0 |
26 | #define PCI_DEVICE_ID_INTEL_G33_IG 0x29C2 | 28 | #define PCI_DEVICE_ID_INTEL_G33_IG 0x29C2 |
@@ -33,7 +35,8 @@ | |||
33 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_1_HB || \ | 35 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_1_HB || \ |
34 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965Q_HB || \ | 36 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965Q_HB || \ |
35 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \ | 37 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \ |
36 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB) | 38 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB || \ |
39 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GME_HB) | ||
37 | 40 | ||
38 | #define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \ | 41 | #define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \ |
39 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \ | 42 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \ |
@@ -213,7 +216,6 @@ static void *i8xx_alloc_pages(void) | |||
213 | } | 216 | } |
214 | global_flush_tlb(); | 217 | global_flush_tlb(); |
215 | get_page(page); | 218 | get_page(page); |
216 | SetPageLocked(page); | ||
217 | atomic_inc(&agp_bridge->current_memory_agp); | 219 | atomic_inc(&agp_bridge->current_memory_agp); |
218 | return page_address(page); | 220 | return page_address(page); |
219 | } | 221 | } |
@@ -229,7 +231,6 @@ static void i8xx_destroy_pages(void *addr) | |||
229 | change_page_attr(page, 4, PAGE_KERNEL); | 231 | change_page_attr(page, 4, PAGE_KERNEL); |
230 | global_flush_tlb(); | 232 | global_flush_tlb(); |
231 | put_page(page); | 233 | put_page(page); |
232 | unlock_page(page); | ||
233 | __free_pages(page, 2); | 234 | __free_pages(page, 2); |
234 | atomic_dec(&agp_bridge->current_memory_agp); | 235 | atomic_dec(&agp_bridge->current_memory_agp); |
235 | } | 236 | } |
@@ -505,7 +506,7 @@ static void intel_i830_init_gtt_entries(void) | |||
505 | break; | 506 | break; |
506 | } | 507 | } |
507 | } else { | 508 | } else { |
508 | switch (gmch_ctrl & I830_GMCH_GMS_MASK) { | 509 | switch (gmch_ctrl & I855_GMCH_GMS_MASK) { |
509 | case I855_GMCH_GMS_STOLEN_1M: | 510 | case I855_GMCH_GMS_STOLEN_1M: |
510 | gtt_entries = MB(1) - KB(size); | 511 | gtt_entries = MB(1) - KB(size); |
511 | break; | 512 | break; |
@@ -527,6 +528,7 @@ static void intel_i830_init_gtt_entries(void) | |||
527 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB || | 528 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB || |
528 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB || | 529 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB || |
529 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || | 530 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || |
531 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GME_HB || | ||
530 | IS_I965 || IS_G33) | 532 | IS_I965 || IS_G33) |
531 | gtt_entries = MB(48) - KB(size); | 533 | gtt_entries = MB(48) - KB(size); |
532 | else | 534 | else |
@@ -538,6 +540,7 @@ static void intel_i830_init_gtt_entries(void) | |||
538 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB || | 540 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB || |
539 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB || | 541 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB || |
540 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || | 542 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || |
543 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GME_HB || | ||
541 | IS_I965 || IS_G33) | 544 | IS_I965 || IS_G33) |
542 | gtt_entries = MB(64) - KB(size); | 545 | gtt_entries = MB(64) - KB(size); |
543 | else | 546 | else |
@@ -911,6 +914,7 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge) | |||
911 | struct aper_size_info_fixed *size; | 914 | struct aper_size_info_fixed *size; |
912 | int num_entries; | 915 | int num_entries; |
913 | u32 temp, temp2; | 916 | u32 temp, temp2; |
917 | int gtt_map_size = 256 * 1024; | ||
914 | 918 | ||
915 | size = agp_bridge->current_size; | 919 | size = agp_bridge->current_size; |
916 | page_order = size->page_order; | 920 | page_order = size->page_order; |
@@ -920,15 +924,19 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge) | |||
920 | pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp); | 924 | pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp); |
921 | pci_read_config_dword(intel_private.pcidev, I915_PTEADDR,&temp2); | 925 | pci_read_config_dword(intel_private.pcidev, I915_PTEADDR,&temp2); |
922 | 926 | ||
923 | intel_private.gtt = ioremap(temp2, 256 * 1024); | 927 | if (IS_G33) |
928 | gtt_map_size = 1024 * 1024; /* 1M on G33 */ | ||
929 | intel_private.gtt = ioremap(temp2, gtt_map_size); | ||
924 | if (!intel_private.gtt) | 930 | if (!intel_private.gtt) |
925 | return -ENOMEM; | 931 | return -ENOMEM; |
926 | 932 | ||
927 | temp &= 0xfff80000; | 933 | temp &= 0xfff80000; |
928 | 934 | ||
929 | intel_private.registers = ioremap(temp,128 * 4096); | 935 | intel_private.registers = ioremap(temp,128 * 4096); |
930 | if (!intel_private.registers) | 936 | if (!intel_private.registers) { |
937 | iounmap(intel_private.gtt); | ||
931 | return -ENOMEM; | 938 | return -ENOMEM; |
939 | } | ||
932 | 940 | ||
933 | temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; | 941 | temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; |
934 | global_cache_flush(); /* FIXME: ? */ | 942 | global_cache_flush(); /* FIXME: ? */ |
@@ -982,13 +990,15 @@ static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge) | |||
982 | temp &= 0xfff00000; | 990 | temp &= 0xfff00000; |
983 | intel_private.gtt = ioremap((temp + (512 * 1024)) , 512 * 1024); | 991 | intel_private.gtt = ioremap((temp + (512 * 1024)) , 512 * 1024); |
984 | 992 | ||
985 | if (!intel_private.gtt) | 993 | if (!intel_private.gtt) |
986 | return -ENOMEM; | 994 | return -ENOMEM; |
987 | 995 | ||
988 | 996 | ||
989 | intel_private.registers = ioremap(temp,128 * 4096); | 997 | intel_private.registers = ioremap(temp,128 * 4096); |
990 | if (!intel_private.registers) | 998 | if (!intel_private.registers) { |
991 | return -ENOMEM; | 999 | iounmap(intel_private.gtt); |
1000 | return -ENOMEM; | ||
1001 | } | ||
992 | 1002 | ||
993 | temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; | 1003 | temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; |
994 | global_cache_flush(); /* FIXME: ? */ | 1004 | global_cache_flush(); /* FIXME: ? */ |
@@ -1848,9 +1858,9 @@ static const struct intel_driver_description { | |||
1848 | NULL, &intel_915_driver }, | 1858 | NULL, &intel_915_driver }, |
1849 | { PCI_DEVICE_ID_INTEL_82945G_HB, PCI_DEVICE_ID_INTEL_82945G_IG, 0, "945G", | 1859 | { PCI_DEVICE_ID_INTEL_82945G_HB, PCI_DEVICE_ID_INTEL_82945G_IG, 0, "945G", |
1850 | NULL, &intel_915_driver }, | 1860 | NULL, &intel_915_driver }, |
1851 | { PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GM_IG, 1, "945GM", | 1861 | { PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GM_IG, 0, "945GM", |
1852 | NULL, &intel_915_driver }, | 1862 | NULL, &intel_915_driver }, |
1853 | { PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GME_IG, 0, "945GME", | 1863 | { PCI_DEVICE_ID_INTEL_82945GME_HB, PCI_DEVICE_ID_INTEL_82945GME_IG, 0, "945GME", |
1854 | NULL, &intel_915_driver }, | 1864 | NULL, &intel_915_driver }, |
1855 | { PCI_DEVICE_ID_INTEL_82946GZ_HB, PCI_DEVICE_ID_INTEL_82946GZ_IG, 0, "946GZ", | 1865 | { PCI_DEVICE_ID_INTEL_82946GZ_HB, PCI_DEVICE_ID_INTEL_82946GZ_IG, 0, "946GZ", |
1856 | NULL, &intel_i965_driver }, | 1866 | NULL, &intel_i965_driver }, |
@@ -1860,9 +1870,9 @@ static const struct intel_driver_description { | |||
1860 | NULL, &intel_i965_driver }, | 1870 | NULL, &intel_i965_driver }, |
1861 | { PCI_DEVICE_ID_INTEL_82965G_HB, PCI_DEVICE_ID_INTEL_82965G_IG, 0, "965G", | 1871 | { PCI_DEVICE_ID_INTEL_82965G_HB, PCI_DEVICE_ID_INTEL_82965G_IG, 0, "965G", |
1862 | NULL, &intel_i965_driver }, | 1872 | NULL, &intel_i965_driver }, |
1863 | { PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GM_IG, 1, "965GM", | 1873 | { PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GM_IG, 0, "965GM", |
1864 | NULL, &intel_i965_driver }, | 1874 | NULL, &intel_i965_driver }, |
1865 | { PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GME_IG, 0, "965GME/GLE", | 1875 | { PCI_DEVICE_ID_INTEL_82965GME_HB, PCI_DEVICE_ID_INTEL_82965GME_IG, 0, "965GME/GLE", |
1866 | NULL, &intel_i965_driver }, | 1876 | NULL, &intel_i965_driver }, |
1867 | { PCI_DEVICE_ID_INTEL_7505_0, 0, 0, "E7505", &intel_7505_driver, NULL }, | 1877 | { PCI_DEVICE_ID_INTEL_7505_0, 0, 0, "E7505", &intel_7505_driver, NULL }, |
1868 | { PCI_DEVICE_ID_INTEL_7205_0, 0, 0, "E7205", &intel_7505_driver, NULL }, | 1878 | { PCI_DEVICE_ID_INTEL_7205_0, 0, 0, "E7205", &intel_7505_driver, NULL }, |
@@ -2051,11 +2061,13 @@ static struct pci_device_id agp_intel_pci_table[] = { | |||
2051 | ID(PCI_DEVICE_ID_INTEL_82915GM_HB), | 2061 | ID(PCI_DEVICE_ID_INTEL_82915GM_HB), |
2052 | ID(PCI_DEVICE_ID_INTEL_82945G_HB), | 2062 | ID(PCI_DEVICE_ID_INTEL_82945G_HB), |
2053 | ID(PCI_DEVICE_ID_INTEL_82945GM_HB), | 2063 | ID(PCI_DEVICE_ID_INTEL_82945GM_HB), |
2064 | ID(PCI_DEVICE_ID_INTEL_82945GME_HB), | ||
2054 | ID(PCI_DEVICE_ID_INTEL_82946GZ_HB), | 2065 | ID(PCI_DEVICE_ID_INTEL_82946GZ_HB), |
2055 | ID(PCI_DEVICE_ID_INTEL_82965G_1_HB), | 2066 | ID(PCI_DEVICE_ID_INTEL_82965G_1_HB), |
2056 | ID(PCI_DEVICE_ID_INTEL_82965Q_HB), | 2067 | ID(PCI_DEVICE_ID_INTEL_82965Q_HB), |
2057 | ID(PCI_DEVICE_ID_INTEL_82965G_HB), | 2068 | ID(PCI_DEVICE_ID_INTEL_82965G_HB), |
2058 | ID(PCI_DEVICE_ID_INTEL_82965GM_HB), | 2069 | ID(PCI_DEVICE_ID_INTEL_82965GM_HB), |
2070 | ID(PCI_DEVICE_ID_INTEL_82965GME_HB), | ||
2059 | ID(PCI_DEVICE_ID_INTEL_G33_HB), | 2071 | ID(PCI_DEVICE_ID_INTEL_G33_HB), |
2060 | ID(PCI_DEVICE_ID_INTEL_Q35_HB), | 2072 | ID(PCI_DEVICE_ID_INTEL_Q35_HB), |
2061 | ID(PCI_DEVICE_ID_INTEL_Q33_HB), | 2073 | ID(PCI_DEVICE_ID_INTEL_Q33_HB), |
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c index 6cd7373dcdf4..225ed2a53d45 100644 --- a/drivers/char/agp/nvidia-agp.c +++ b/drivers/char/agp/nvidia-agp.c | |||
@@ -157,6 +157,9 @@ static int nvidia_configure(void) | |||
157 | nvidia_private.aperture = | 157 | nvidia_private.aperture = |
158 | (volatile u32 __iomem *) ioremap(apbase, 33 * PAGE_SIZE); | 158 | (volatile u32 __iomem *) ioremap(apbase, 33 * PAGE_SIZE); |
159 | 159 | ||
160 | if (!nvidia_private.aperture) | ||
161 | return -ENOMEM; | ||
162 | |||
160 | return 0; | 163 | return 0; |
161 | } | 164 | } |
162 | 165 | ||
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c index cda608c42bea..98cf8abb3e57 100644 --- a/drivers/char/agp/sgi-agp.c +++ b/drivers/char/agp/sgi-agp.c | |||
@@ -51,7 +51,6 @@ static void *sgi_tioca_alloc_page(struct agp_bridge_data *bridge) | |||
51 | return NULL; | 51 | return NULL; |
52 | 52 | ||
53 | get_page(page); | 53 | get_page(page); |
54 | SetPageLocked(page); | ||
55 | atomic_inc(&agp_bridge->current_memory_agp); | 54 | atomic_inc(&agp_bridge->current_memory_agp); |
56 | return page_address(page); | 55 | return page_address(page); |
57 | } | 56 | } |
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c index 9aaf401a8975..0ecc54d327bc 100644 --- a/drivers/char/agp/via-agp.c +++ b/drivers/char/agp/via-agp.c | |||
@@ -399,6 +399,11 @@ static struct agp_device_ids via_agp_device_ids[] __devinitdata = | |||
399 | .device_id = PCI_DEVICE_ID_VIA_P4M890, | 399 | .device_id = PCI_DEVICE_ID_VIA_P4M890, |
400 | .chipset_name = "P4M890", | 400 | .chipset_name = "P4M890", |
401 | }, | 401 | }, |
402 | /* P4M900 */ | ||
403 | { | ||
404 | .device_id = PCI_DEVICE_ID_VIA_VT3364, | ||
405 | .chipset_name = "P4M900", | ||
406 | }, | ||
402 | { }, /* dummy final entry, always present */ | 407 | { }, /* dummy final entry, always present */ |
403 | }; | 408 | }; |
404 | 409 | ||
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 7b02bf1289a2..3d468f502d2d 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c | |||
@@ -1721,12 +1721,11 @@ static int get_async_struct(int line, struct async_struct **ret_info) | |||
1721 | *ret_info = sstate->info; | 1721 | *ret_info = sstate->info; |
1722 | return 0; | 1722 | return 0; |
1723 | } | 1723 | } |
1724 | info = kmalloc(sizeof(struct async_struct), GFP_KERNEL); | 1724 | info = kzalloc(sizeof(struct async_struct), GFP_KERNEL); |
1725 | if (!info) { | 1725 | if (!info) { |
1726 | sstate->count--; | 1726 | sstate->count--; |
1727 | return -ENOMEM; | 1727 | return -ENOMEM; |
1728 | } | 1728 | } |
1729 | memset(info, 0, sizeof(struct async_struct)); | ||
1730 | #ifdef DECLARE_WAITQUEUE | 1729 | #ifdef DECLARE_WAITQUEUE |
1731 | init_waitqueue_head(&info->open_wait); | 1730 | init_waitqueue_head(&info->open_wait); |
1732 | init_waitqueue_head(&info->close_wait); | 1731 | init_waitqueue_head(&info->close_wait); |
diff --git a/drivers/char/decserial.c b/drivers/char/decserial.c deleted file mode 100644 index 8ea2bea2b183..000000000000 --- a/drivers/char/decserial.c +++ /dev/null | |||
@@ -1,67 +0,0 @@ | |||
1 | /* | ||
2 | * sercons.c | ||
3 | * choose the right serial device at boot time | ||
4 | * | ||
5 | * triemer 6-SEP-1998 | ||
6 | * sercons.c is designed to allow the three different kinds | ||
7 | * of serial devices under the decstation world to co-exist | ||
8 | * in the same kernel. The idea here is to abstract | ||
9 | * the pieces of the drivers that are common to this file | ||
10 | * so that they do not clash at compile time and runtime. | ||
11 | * | ||
12 | * HK 16-SEP-1998 v0.002 | ||
13 | * removed the PROM console as this is not a real serial | ||
14 | * device. Added support for PROM console in drivers/char/tty_io.c | ||
15 | * instead. Although it may work to enable more than one | ||
16 | * console device I strongly recommend to use only one. | ||
17 | */ | ||
18 | |||
19 | #include <linux/init.h> | ||
20 | #include <asm/dec/machtype.h> | ||
21 | |||
22 | #ifdef CONFIG_ZS | ||
23 | extern int zs_init(void); | ||
24 | #endif | ||
25 | |||
26 | #ifdef CONFIG_SERIAL_CONSOLE | ||
27 | |||
28 | #ifdef CONFIG_ZS | ||
29 | extern void zs_serial_console_init(void); | ||
30 | #endif | ||
31 | |||
32 | #endif | ||
33 | |||
34 | /* rs_init - starts up the serial interface - | ||
35 | handle normal case of starting up the serial interface */ | ||
36 | |||
37 | #ifdef CONFIG_SERIAL | ||
38 | |||
39 | int __init rs_init(void) | ||
40 | { | ||
41 | #ifdef CONFIG_ZS | ||
42 | if (IOASIC) | ||
43 | return zs_init(); | ||
44 | #endif | ||
45 | return -ENXIO; | ||
46 | } | ||
47 | |||
48 | __initcall(rs_init); | ||
49 | |||
50 | #endif | ||
51 | |||
52 | #ifdef CONFIG_SERIAL_CONSOLE | ||
53 | |||
54 | /* serial_console_init handles the special case of starting | ||
55 | * up the console on the serial port | ||
56 | */ | ||
57 | static int __init decserial_console_init(void) | ||
58 | { | ||
59 | #ifdef CONFIG_ZS | ||
60 | if (IOASIC) | ||
61 | zs_serial_console_init(); | ||
62 | #endif | ||
63 | return 0; | ||
64 | } | ||
65 | console_initcall(decserial_console_init); | ||
66 | |||
67 | #endif | ||
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index 923174c54a1c..c115b39b8517 100644 --- a/drivers/char/drm/drm_bufs.c +++ b/drivers/char/drm/drm_bufs.c | |||
@@ -177,8 +177,14 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset, | |||
177 | MTRR_TYPE_WRCOMB, 1); | 177 | MTRR_TYPE_WRCOMB, 1); |
178 | } | 178 | } |
179 | } | 179 | } |
180 | if (map->type == _DRM_REGISTERS) | 180 | if (map->type == _DRM_REGISTERS) { |
181 | map->handle = ioremap(map->offset, map->size); | 181 | map->handle = ioremap(map->offset, map->size); |
182 | if (!map->handle) { | ||
183 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | ||
184 | return -ENOMEM; | ||
185 | } | ||
186 | } | ||
187 | |||
182 | break; | 188 | break; |
183 | case _DRM_SHM: | 189 | case _DRM_SHM: |
184 | list = drm_find_matching_map(dev, map); | 190 | list = drm_find_matching_map(dev, map); |
@@ -479,11 +485,6 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp, | |||
479 | return -EINVAL; | 485 | return -EINVAL; |
480 | } | 486 | } |
481 | 487 | ||
482 | if (!map) { | ||
483 | mutex_unlock(&dev->struct_mutex); | ||
484 | return -EINVAL; | ||
485 | } | ||
486 | |||
487 | /* Register and framebuffer maps are permanent */ | 488 | /* Register and framebuffer maps are permanent */ |
488 | if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) { | 489 | if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) { |
489 | mutex_unlock(&dev->struct_mutex); | 490 | mutex_unlock(&dev->struct_mutex); |
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c index 3359cc2b9736..8e7d713a5a15 100644 --- a/drivers/char/drm/i915_dma.c +++ b/drivers/char/drm/i915_dma.c | |||
@@ -184,6 +184,8 @@ static int i915_initialize(struct drm_device * dev, | |||
184 | * private backbuffer/depthbuffer usage. | 184 | * private backbuffer/depthbuffer usage. |
185 | */ | 185 | */ |
186 | dev_priv->use_mi_batchbuffer_start = 0; | 186 | dev_priv->use_mi_batchbuffer_start = 0; |
187 | if (IS_I965G(dev)) /* 965 doesn't support older method */ | ||
188 | dev_priv->use_mi_batchbuffer_start = 1; | ||
187 | 189 | ||
188 | /* Allow hardware batchbuffers unless told otherwise. | 190 | /* Allow hardware batchbuffers unless told otherwise. |
189 | */ | 191 | */ |
@@ -517,8 +519,13 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev, | |||
517 | 519 | ||
518 | if (dev_priv->use_mi_batchbuffer_start) { | 520 | if (dev_priv->use_mi_batchbuffer_start) { |
519 | BEGIN_LP_RING(2); | 521 | BEGIN_LP_RING(2); |
520 | OUT_RING(MI_BATCH_BUFFER_START | (2 << 6)); | 522 | if (IS_I965G(dev)) { |
521 | OUT_RING(batch->start | MI_BATCH_NON_SECURE); | 523 | OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965); |
524 | OUT_RING(batch->start); | ||
525 | } else { | ||
526 | OUT_RING(MI_BATCH_BUFFER_START | (2 << 6)); | ||
527 | OUT_RING(batch->start | MI_BATCH_NON_SECURE); | ||
528 | } | ||
522 | ADVANCE_LP_RING(); | 529 | ADVANCE_LP_RING(); |
523 | } else { | 530 | } else { |
524 | BEGIN_LP_RING(4); | 531 | BEGIN_LP_RING(4); |
@@ -735,7 +742,8 @@ static int i915_setparam(DRM_IOCTL_ARGS) | |||
735 | 742 | ||
736 | switch (param.param) { | 743 | switch (param.param) { |
737 | case I915_SETPARAM_USE_MI_BATCHBUFFER_START: | 744 | case I915_SETPARAM_USE_MI_BATCHBUFFER_START: |
738 | dev_priv->use_mi_batchbuffer_start = param.value; | 745 | if (!IS_I965G(dev)) |
746 | dev_priv->use_mi_batchbuffer_start = param.value; | ||
739 | break; | 747 | break; |
740 | case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY: | 748 | case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY: |
741 | dev_priv->tex_lru_log_granularity = param.value; | 749 | dev_priv->tex_lru_log_granularity = param.value; |
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h index fd918565f4e5..28b98733beb8 100644 --- a/drivers/char/drm/i915_drv.h +++ b/drivers/char/drm/i915_drv.h | |||
@@ -210,6 +210,12 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); | |||
210 | #define I915REG_INT_MASK_R 0x020a8 | 210 | #define I915REG_INT_MASK_R 0x020a8 |
211 | #define I915REG_INT_ENABLE_R 0x020a0 | 211 | #define I915REG_INT_ENABLE_R 0x020a0 |
212 | 212 | ||
213 | #define I915REG_PIPEASTAT 0x70024 | ||
214 | #define I915REG_PIPEBSTAT 0x71024 | ||
215 | |||
216 | #define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17) | ||
217 | #define I915_VBLANK_CLEAR (1UL<<1) | ||
218 | |||
213 | #define SRX_INDEX 0x3c4 | 219 | #define SRX_INDEX 0x3c4 |
214 | #define SRX_DATA 0x3c5 | 220 | #define SRX_DATA 0x3c5 |
215 | #define SR01 1 | 221 | #define SR01 1 |
@@ -282,6 +288,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); | |||
282 | #define MI_BATCH_BUFFER_START (0x31<<23) | 288 | #define MI_BATCH_BUFFER_START (0x31<<23) |
283 | #define MI_BATCH_BUFFER_END (0xA<<23) | 289 | #define MI_BATCH_BUFFER_END (0xA<<23) |
284 | #define MI_BATCH_NON_SECURE (1) | 290 | #define MI_BATCH_NON_SECURE (1) |
291 | #define MI_BATCH_NON_SECURE_I965 (1<<8) | ||
285 | 292 | ||
286 | #define MI_WAIT_FOR_EVENT ((0x3<<23)) | 293 | #define MI_WAIT_FOR_EVENT ((0x3<<23)) |
287 | #define MI_WAIT_FOR_PLANE_A_FLIP (1<<2) | 294 | #define MI_WAIT_FOR_PLANE_A_FLIP (1<<2) |
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c index 4b4b2ce89863..bb8e9e9c8201 100644 --- a/drivers/char/drm/i915_irq.c +++ b/drivers/char/drm/i915_irq.c | |||
@@ -214,6 +214,10 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
214 | struct drm_device *dev = (struct drm_device *) arg; | 214 | struct drm_device *dev = (struct drm_device *) arg; |
215 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 215 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
216 | u16 temp; | 216 | u16 temp; |
217 | u32 pipea_stats, pipeb_stats; | ||
218 | |||
219 | pipea_stats = I915_READ(I915REG_PIPEASTAT); | ||
220 | pipeb_stats = I915_READ(I915REG_PIPEBSTAT); | ||
217 | 221 | ||
218 | temp = I915_READ16(I915REG_INT_IDENTITY_R); | 222 | temp = I915_READ16(I915REG_INT_IDENTITY_R); |
219 | 223 | ||
@@ -225,6 +229,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
225 | return IRQ_NONE; | 229 | return IRQ_NONE; |
226 | 230 | ||
227 | I915_WRITE16(I915REG_INT_IDENTITY_R, temp); | 231 | I915_WRITE16(I915REG_INT_IDENTITY_R, temp); |
232 | (void) I915_READ16(I915REG_INT_IDENTITY_R); | ||
233 | DRM_READMEMORYBARRIER(); | ||
228 | 234 | ||
229 | dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); | 235 | dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); |
230 | 236 | ||
@@ -252,6 +258,12 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
252 | 258 | ||
253 | if (dev_priv->swaps_pending > 0) | 259 | if (dev_priv->swaps_pending > 0) |
254 | drm_locked_tasklet(dev, i915_vblank_tasklet); | 260 | drm_locked_tasklet(dev, i915_vblank_tasklet); |
261 | I915_WRITE(I915REG_PIPEASTAT, | ||
262 | pipea_stats|I915_VBLANK_INTERRUPT_ENABLE| | ||
263 | I915_VBLANK_CLEAR); | ||
264 | I915_WRITE(I915REG_PIPEBSTAT, | ||
265 | pipeb_stats|I915_VBLANK_INTERRUPT_ENABLE| | ||
266 | I915_VBLANK_CLEAR); | ||
255 | } | 267 | } |
256 | 268 | ||
257 | return IRQ_HANDLED; | 269 | return IRQ_HANDLED; |
diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c index fdb8609dd76f..3dd1ed3d1bf5 100644 --- a/drivers/char/drm/via_dmablit.c +++ b/drivers/char/drm/via_dmablit.c | |||
@@ -273,10 +273,9 @@ via_alloc_desc_pages(drm_via_sg_info_t *vsg) | |||
273 | vsg->num_desc_pages = (vsg->num_desc + vsg->descriptors_per_page - 1) / | 273 | vsg->num_desc_pages = (vsg->num_desc + vsg->descriptors_per_page - 1) / |
274 | vsg->descriptors_per_page; | 274 | vsg->descriptors_per_page; |
275 | 275 | ||
276 | if (NULL == (vsg->desc_pages = kmalloc(sizeof(void *) * vsg->num_desc_pages, GFP_KERNEL))) | 276 | if (NULL == (vsg->desc_pages = kcalloc(vsg->num_desc_pages, sizeof(void *), GFP_KERNEL))) |
277 | return DRM_ERR(ENOMEM); | 277 | return DRM_ERR(ENOMEM); |
278 | 278 | ||
279 | memset(vsg->desc_pages, 0, sizeof(void *) * vsg->num_desc_pages); | ||
280 | vsg->state = dr_via_desc_pages_alloc; | 279 | vsg->state = dr_via_desc_pages_alloc; |
281 | for (i=0; i<vsg->num_desc_pages; ++i) { | 280 | for (i=0; i<vsg->num_desc_pages; ++i) { |
282 | if (NULL == (vsg->desc_pages[i] = | 281 | if (NULL == (vsg->desc_pages[i] = |
@@ -561,7 +560,7 @@ via_init_dmablit(struct drm_device *dev) | |||
561 | blitq->head = 0; | 560 | blitq->head = 0; |
562 | blitq->cur = 0; | 561 | blitq->cur = 0; |
563 | blitq->serviced = 0; | 562 | blitq->serviced = 0; |
564 | blitq->num_free = VIA_NUM_BLIT_SLOTS; | 563 | blitq->num_free = VIA_NUM_BLIT_SLOTS - 1; |
565 | blitq->num_outstanding = 0; | 564 | blitq->num_outstanding = 0; |
566 | blitq->is_active = 0; | 565 | blitq->is_active = 0; |
567 | blitq->aborting = 0; | 566 | blitq->aborting = 0; |
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c index 9b8278e1f4f8..acbfe1c49b4d 100644 --- a/drivers/char/dsp56k.c +++ b/drivers/char/dsp56k.c | |||
@@ -513,7 +513,7 @@ static int __init dsp56k_init_driver(void) | |||
513 | err = PTR_ERR(dsp56k_class); | 513 | err = PTR_ERR(dsp56k_class); |
514 | goto out_chrdev; | 514 | goto out_chrdev; |
515 | } | 515 | } |
516 | class_device_create(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), NULL, "dsp56k"); | 516 | device_create(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), "dsp56k"); |
517 | 517 | ||
518 | printk(banner); | 518 | printk(banner); |
519 | goto out; | 519 | goto out; |
@@ -527,7 +527,7 @@ module_init(dsp56k_init_driver); | |||
527 | 527 | ||
528 | static void __exit dsp56k_cleanup_driver(void) | 528 | static void __exit dsp56k_cleanup_driver(void) |
529 | { | 529 | { |
530 | class_device_destroy(dsp56k_class, MKDEV(DSP56K_MAJOR, 0)); | 530 | device_destroy(dsp56k_class, MKDEV(DSP56K_MAJOR, 0)); |
531 | class_destroy(dsp56k_class); | 531 | class_destroy(dsp56k_class); |
532 | unregister_chrdev(DSP56K_MAJOR, "dsp56k"); | 532 | unregister_chrdev(DSP56K_MAJOR, "dsp56k"); |
533 | } | 533 | } |
diff --git a/drivers/char/esp.c b/drivers/char/esp.c index 74cd5118af57..2e7ae42a5503 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c | |||
@@ -2459,7 +2459,7 @@ static int __init espserial_init(void) | |||
2459 | return 1; | 2459 | return 1; |
2460 | } | 2460 | } |
2461 | 2461 | ||
2462 | info = kmalloc(sizeof(struct esp_struct), GFP_KERNEL); | 2462 | info = kzalloc(sizeof(struct esp_struct), GFP_KERNEL); |
2463 | 2463 | ||
2464 | if (!info) | 2464 | if (!info) |
2465 | { | 2465 | { |
@@ -2469,7 +2469,6 @@ static int __init espserial_init(void) | |||
2469 | return 1; | 2469 | return 1; |
2470 | } | 2470 | } |
2471 | 2471 | ||
2472 | memset((void *)info, 0, sizeof(struct esp_struct)); | ||
2473 | spin_lock_init(&info->lock); | 2472 | spin_lock_init(&info->lock); |
2474 | /* rx_trigger, tx_trigger are needed by autoconfig */ | 2473 | /* rx_trigger, tx_trigger are needed by autoconfig */ |
2475 | info->config.rx_trigger = rx_trigger; | 2474 | info->config.rx_trigger = rx_trigger; |
@@ -2527,7 +2526,7 @@ static int __init espserial_init(void) | |||
2527 | if (!dma) | 2526 | if (!dma) |
2528 | info->stat_flags |= ESP_STAT_NEVER_DMA; | 2527 | info->stat_flags |= ESP_STAT_NEVER_DMA; |
2529 | 2528 | ||
2530 | info = kmalloc(sizeof(struct esp_struct), GFP_KERNEL); | 2529 | info = kzalloc(sizeof(struct esp_struct), GFP_KERNEL); |
2531 | if (!info) | 2530 | if (!info) |
2532 | { | 2531 | { |
2533 | printk(KERN_ERR "Couldn't allocate memory for esp serial device information\n"); | 2532 | printk(KERN_ERR "Couldn't allocate memory for esp serial device information\n"); |
@@ -2536,7 +2535,6 @@ static int __init espserial_init(void) | |||
2536 | return 0; | 2535 | return 0; |
2537 | } | 2536 | } |
2538 | 2537 | ||
2539 | memset((void *)info, 0, sizeof(struct esp_struct)); | ||
2540 | /* rx_trigger, tx_trigger are needed by autoconfig */ | 2538 | /* rx_trigger, tx_trigger are needed by autoconfig */ |
2541 | info->config.rx_trigger = rx_trigger; | 2539 | info->config.rx_trigger = rx_trigger; |
2542 | info->config.tx_trigger = tx_trigger; | 2540 | info->config.tx_trigger = tx_trigger; |
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 0be700f4e8fd..4c16778e3f84 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/bcd.h> | 29 | #include <linux/bcd.h> |
30 | #include <linux/seq_file.h> | 30 | #include <linux/seq_file.h> |
31 | #include <linux/bitops.h> | 31 | #include <linux/bitops.h> |
32 | #include <linux/clocksource.h> | ||
32 | 33 | ||
33 | #include <asm/current.h> | 34 | #include <asm/current.h> |
34 | #include <asm/uaccess.h> | 35 | #include <asm/uaccess.h> |
@@ -51,8 +52,37 @@ | |||
51 | 52 | ||
52 | #define HPET_RANGE_SIZE 1024 /* from HPET spec */ | 53 | #define HPET_RANGE_SIZE 1024 /* from HPET spec */ |
53 | 54 | ||
55 | #if BITS_PER_LONG == 64 | ||
56 | #define write_counter(V, MC) writeq(V, MC) | ||
57 | #define read_counter(MC) readq(MC) | ||
58 | #else | ||
59 | #define write_counter(V, MC) writel(V, MC) | ||
60 | #define read_counter(MC) readl(MC) | ||
61 | #endif | ||
62 | |||
54 | static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ; | 63 | static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ; |
55 | 64 | ||
65 | /* This clocksource driver currently only works on ia64 */ | ||
66 | #ifdef CONFIG_IA64 | ||
67 | static void __iomem *hpet_mctr; | ||
68 | |||
69 | static cycle_t read_hpet(void) | ||
70 | { | ||
71 | return (cycle_t)read_counter((void __iomem *)hpet_mctr); | ||
72 | } | ||
73 | |||
74 | static struct clocksource clocksource_hpet = { | ||
75 | .name = "hpet", | ||
76 | .rating = 250, | ||
77 | .read = read_hpet, | ||
78 | .mask = CLOCKSOURCE_MASK(64), | ||
79 | .mult = 0, /*to be caluclated*/ | ||
80 | .shift = 10, | ||
81 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
82 | }; | ||
83 | static struct clocksource *hpet_clocksource; | ||
84 | #endif | ||
85 | |||
56 | /* A lock for concurrent access by app and isr hpet activity. */ | 86 | /* A lock for concurrent access by app and isr hpet activity. */ |
57 | static DEFINE_SPINLOCK(hpet_lock); | 87 | static DEFINE_SPINLOCK(hpet_lock); |
58 | /* A lock for concurrent intermodule access to hpet and isr hpet activity. */ | 88 | /* A lock for concurrent intermodule access to hpet and isr hpet activity. */ |
@@ -79,7 +109,7 @@ struct hpets { | |||
79 | struct hpets *hp_next; | 109 | struct hpets *hp_next; |
80 | struct hpet __iomem *hp_hpet; | 110 | struct hpet __iomem *hp_hpet; |
81 | unsigned long hp_hpet_phys; | 111 | unsigned long hp_hpet_phys; |
82 | struct time_interpolator *hp_interpolator; | 112 | struct clocksource *hp_clocksource; |
83 | unsigned long long hp_tick_freq; | 113 | unsigned long long hp_tick_freq; |
84 | unsigned long hp_delta; | 114 | unsigned long hp_delta; |
85 | unsigned int hp_ntimer; | 115 | unsigned int hp_ntimer; |
@@ -94,13 +124,6 @@ static struct hpets *hpets; | |||
94 | #define HPET_PERIODIC 0x0004 | 124 | #define HPET_PERIODIC 0x0004 |
95 | #define HPET_SHARED_IRQ 0x0008 | 125 | #define HPET_SHARED_IRQ 0x0008 |
96 | 126 | ||
97 | #if BITS_PER_LONG == 64 | ||
98 | #define write_counter(V, MC) writeq(V, MC) | ||
99 | #define read_counter(MC) readq(MC) | ||
100 | #else | ||
101 | #define write_counter(V, MC) writel(V, MC) | ||
102 | #define read_counter(MC) readl(MC) | ||
103 | #endif | ||
104 | 127 | ||
105 | #ifndef readq | 128 | #ifndef readq |
106 | static inline unsigned long long readq(void __iomem *addr) | 129 | static inline unsigned long long readq(void __iomem *addr) |
@@ -737,27 +760,6 @@ static ctl_table dev_root[] = { | |||
737 | 760 | ||
738 | static struct ctl_table_header *sysctl_header; | 761 | static struct ctl_table_header *sysctl_header; |
739 | 762 | ||
740 | static void hpet_register_interpolator(struct hpets *hpetp) | ||
741 | { | ||
742 | #ifdef CONFIG_TIME_INTERPOLATION | ||
743 | struct time_interpolator *ti; | ||
744 | |||
745 | ti = kzalloc(sizeof(*ti), GFP_KERNEL); | ||
746 | if (!ti) | ||
747 | return; | ||
748 | |||
749 | ti->source = TIME_SOURCE_MMIO64; | ||
750 | ti->shift = 10; | ||
751 | ti->addr = &hpetp->hp_hpet->hpet_mc; | ||
752 | ti->frequency = hpetp->hp_tick_freq; | ||
753 | ti->drift = HPET_DRIFT; | ||
754 | ti->mask = -1; | ||
755 | |||
756 | hpetp->hp_interpolator = ti; | ||
757 | register_time_interpolator(ti); | ||
758 | #endif | ||
759 | } | ||
760 | |||
761 | /* | 763 | /* |
762 | * Adjustment for when arming the timer with | 764 | * Adjustment for when arming the timer with |
763 | * initial conditions. That is, main counter | 765 | * initial conditions. That is, main counter |
@@ -909,7 +911,19 @@ int hpet_alloc(struct hpet_data *hdp) | |||
909 | } | 911 | } |
910 | 912 | ||
911 | hpetp->hp_delta = hpet_calibrate(hpetp); | 913 | hpetp->hp_delta = hpet_calibrate(hpetp); |
912 | hpet_register_interpolator(hpetp); | 914 | |
915 | /* This clocksource driver currently only works on ia64 */ | ||
916 | #ifdef CONFIG_IA64 | ||
917 | if (!hpet_clocksource) { | ||
918 | hpet_mctr = (void __iomem *)&hpetp->hp_hpet->hpet_mc; | ||
919 | CLKSRC_FSYS_MMIO_SET(clocksource_hpet.fsys_mmio, hpet_mctr); | ||
920 | clocksource_hpet.mult = clocksource_hz2mult(hpetp->hp_tick_freq, | ||
921 | clocksource_hpet.shift); | ||
922 | clocksource_register(&clocksource_hpet); | ||
923 | hpetp->hp_clocksource = &clocksource_hpet; | ||
924 | hpet_clocksource = &clocksource_hpet; | ||
925 | } | ||
926 | #endif | ||
913 | 927 | ||
914 | return 0; | 928 | return 0; |
915 | } | 929 | } |
@@ -932,14 +946,14 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data) | |||
932 | printk(KERN_DEBUG "%s: 0x%lx is busy\n", | 946 | printk(KERN_DEBUG "%s: 0x%lx is busy\n", |
933 | __FUNCTION__, hdp->hd_phys_address); | 947 | __FUNCTION__, hdp->hd_phys_address); |
934 | iounmap(hdp->hd_address); | 948 | iounmap(hdp->hd_address); |
935 | return -EBUSY; | 949 | return AE_ALREADY_EXISTS; |
936 | } | 950 | } |
937 | } else if (res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) { | 951 | } else if (res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) { |
938 | struct acpi_resource_fixed_memory32 *fixmem32; | 952 | struct acpi_resource_fixed_memory32 *fixmem32; |
939 | 953 | ||
940 | fixmem32 = &res->data.fixed_memory32; | 954 | fixmem32 = &res->data.fixed_memory32; |
941 | if (!fixmem32) | 955 | if (!fixmem32) |
942 | return -EINVAL; | 956 | return AE_NO_MEMORY; |
943 | 957 | ||
944 | hdp->hd_phys_address = fixmem32->address; | 958 | hdp->hd_phys_address = fixmem32->address; |
945 | hdp->hd_address = ioremap(fixmem32->address, | 959 | hdp->hd_address = ioremap(fixmem32->address, |
@@ -949,7 +963,7 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data) | |||
949 | printk(KERN_DEBUG "%s: 0x%lx is busy\n", | 963 | printk(KERN_DEBUG "%s: 0x%lx is busy\n", |
950 | __FUNCTION__, hdp->hd_phys_address); | 964 | __FUNCTION__, hdp->hd_phys_address); |
951 | iounmap(hdp->hd_address); | 965 | iounmap(hdp->hd_address); |
952 | return -EBUSY; | 966 | return AE_ALREADY_EXISTS; |
953 | } | 967 | } |
954 | } else if (res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) { | 968 | } else if (res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) { |
955 | struct acpi_resource_extended_irq *irqp; | 969 | struct acpi_resource_extended_irq *irqp; |
@@ -995,13 +1009,19 @@ static int hpet_acpi_add(struct acpi_device *device) | |||
995 | 1009 | ||
996 | static int hpet_acpi_remove(struct acpi_device *device, int type) | 1010 | static int hpet_acpi_remove(struct acpi_device *device, int type) |
997 | { | 1011 | { |
998 | /* XXX need to unregister interpolator, dealloc mem, etc */ | 1012 | /* XXX need to unregister clocksource, dealloc mem, etc */ |
999 | return -EINVAL; | 1013 | return -EINVAL; |
1000 | } | 1014 | } |
1001 | 1015 | ||
1016 | static const struct acpi_device_id hpet_device_ids[] = { | ||
1017 | {"PNP0103", 0}, | ||
1018 | {"", 0}, | ||
1019 | }; | ||
1020 | MODULE_DEVICE_TABLE(acpi, hpet_device_ids); | ||
1021 | |||
1002 | static struct acpi_driver hpet_acpi_driver = { | 1022 | static struct acpi_driver hpet_acpi_driver = { |
1003 | .name = "hpet", | 1023 | .name = "hpet", |
1004 | .ids = "PNP0103", | 1024 | .ids = hpet_device_ids, |
1005 | .ops = { | 1025 | .ops = { |
1006 | .add = hpet_acpi_add, | 1026 | .add = hpet_acpi_add, |
1007 | .remove = hpet_acpi_remove, | 1027 | .remove = hpet_acpi_remove, |
diff --git a/drivers/char/hvc_beat.c b/drivers/char/hvc_beat.c index 6f019f19be71..e74bb949c289 100644 --- a/drivers/char/hvc_beat.c +++ b/drivers/char/hvc_beat.c | |||
@@ -97,7 +97,7 @@ static int hvc_beat_config(char *p) | |||
97 | return 0; | 97 | return 0; |
98 | } | 98 | } |
99 | 99 | ||
100 | static int hvc_beat_console_init(void) | 100 | static int __init hvc_beat_console_init(void) |
101 | { | 101 | { |
102 | if (hvc_beat_useit && machine_is_compatible("Beat")) { | 102 | if (hvc_beat_useit && machine_is_compatible("Beat")) { |
103 | hvc_instantiate(0, 0, &hvc_beat_get_put_ops); | 103 | hvc_instantiate(0, 0, &hvc_beat_get_put_ops); |
@@ -106,7 +106,7 @@ static int hvc_beat_console_init(void) | |||
106 | } | 106 | } |
107 | 107 | ||
108 | /* temp */ | 108 | /* temp */ |
109 | static int hvc_beat_init(void) | 109 | static int __init hvc_beat_init(void) |
110 | { | 110 | { |
111 | struct hvc_struct *hp; | 111 | struct hvc_struct *hp; |
112 | 112 | ||
diff --git a/drivers/char/hvc_iseries.c b/drivers/char/hvc_iseries.c index b37f1d5a5be6..a08f8f981c11 100644 --- a/drivers/char/hvc_iseries.c +++ b/drivers/char/hvc_iseries.c | |||
@@ -472,7 +472,7 @@ static void hvc_handle_event(struct HvLpEvent *event) | |||
472 | } | 472 | } |
473 | } | 473 | } |
474 | 474 | ||
475 | static int send_open(HvLpIndex remoteLp, void *sem) | 475 | static int __init send_open(HvLpIndex remoteLp, void *sem) |
476 | { | 476 | { |
477 | return HvCallEvent_signalLpEventFast(remoteLp, | 477 | return HvCallEvent_signalLpEventFast(remoteLp, |
478 | HvLpEvent_Type_VirtualIo, | 478 | HvLpEvent_Type_VirtualIo, |
@@ -484,7 +484,7 @@ static int send_open(HvLpIndex remoteLp, void *sem) | |||
484 | 0, 0, 0, 0); | 484 | 0, 0, 0, 0); |
485 | } | 485 | } |
486 | 486 | ||
487 | static int hvc_vio_init(void) | 487 | static int __init hvc_vio_init(void) |
488 | { | 488 | { |
489 | atomic_t wait_flag; | 489 | atomic_t wait_flag; |
490 | int rc; | 490 | int rc; |
@@ -552,14 +552,14 @@ static int hvc_vio_init(void) | |||
552 | } | 552 | } |
553 | module_init(hvc_vio_init); /* after drivers/char/hvc_console.c */ | 553 | module_init(hvc_vio_init); /* after drivers/char/hvc_console.c */ |
554 | 554 | ||
555 | static void hvc_vio_exit(void) | 555 | static void __exit hvc_vio_exit(void) |
556 | { | 556 | { |
557 | vio_unregister_driver(&hvc_vio_driver); | 557 | vio_unregister_driver(&hvc_vio_driver); |
558 | } | 558 | } |
559 | module_exit(hvc_vio_exit); | 559 | module_exit(hvc_vio_exit); |
560 | 560 | ||
561 | /* the device tree order defines our numbering */ | 561 | /* the device tree order defines our numbering */ |
562 | static int hvc_find_vtys(void) | 562 | static int __init hvc_find_vtys(void) |
563 | { | 563 | { |
564 | struct device_node *vty; | 564 | struct device_node *vty; |
565 | int num_found = 0; | 565 | int num_found = 0; |
diff --git a/drivers/char/hvc_lguest.c b/drivers/char/hvc_lguest.c new file mode 100644 index 000000000000..3d6bd0baa56d --- /dev/null +++ b/drivers/char/hvc_lguest.c | |||
@@ -0,0 +1,177 @@ | |||
1 | /*D:300 | ||
2 | * The Guest console driver | ||
3 | * | ||
4 | * This is a trivial console driver: we use lguest's DMA mechanism to send | ||
5 | * bytes out, and register a DMA buffer to receive bytes in. It is assumed to | ||
6 | * be present and available from the very beginning of boot. | ||
7 | * | ||
8 | * Writing console drivers is one of the few remaining Dark Arts in Linux. | ||
9 | * Fortunately for us, the path of virtual consoles has been well-trodden by | ||
10 | * the PowerPC folks, who wrote "hvc_console.c" to generically support any | ||
11 | * virtual console. We use that infrastructure which only requires us to write | ||
12 | * the basic put_chars and get_chars functions and call the right register | ||
13 | * functions. | ||
14 | :*/ | ||
15 | |||
16 | /*M:002 The console can be flooded: while the Guest is processing input the | ||
17 | * Host can send more. Buffering in the Host could alleviate this, but it is a | ||
18 | * difficult problem in general. :*/ | ||
19 | /* Copyright (C) 2006 Rusty Russell, IBM Corporation | ||
20 | * | ||
21 | * This program is free software; you can redistribute it and/or modify | ||
22 | * it under the terms of the GNU General Public License as published by | ||
23 | * the Free Software Foundation; either version 2 of the License, or | ||
24 | * (at your option) any later version. | ||
25 | * | ||
26 | * This program is distributed in the hope that it will be useful, | ||
27 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
28 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
29 | * GNU General Public License for more details. | ||
30 | * | ||
31 | * You should have received a copy of the GNU General Public License | ||
32 | * along with this program; if not, write to the Free Software | ||
33 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
34 | */ | ||
35 | #include <linux/err.h> | ||
36 | #include <linux/init.h> | ||
37 | #include <linux/lguest_bus.h> | ||
38 | #include <asm/paravirt.h> | ||
39 | #include "hvc_console.h" | ||
40 | |||
41 | /*D:340 This is our single console input buffer, with associated "struct | ||
42 | * lguest_dma" referring to it. Note the 0-terminated length array, and the | ||
43 | * use of physical address for the buffer itself. */ | ||
44 | static char inbuf[256]; | ||
45 | static struct lguest_dma cons_input = { .used_len = 0, | ||
46 | .addr[0] = __pa(inbuf), | ||
47 | .len[0] = sizeof(inbuf), | ||
48 | .len[1] = 0 }; | ||
49 | |||
50 | /*D:310 The put_chars() callback is pretty straightforward. | ||
51 | * | ||
52 | * First we put the pointer and length in a "struct lguest_dma": we only have | ||
53 | * one pointer, so we set the second length to 0. Then we use SEND_DMA to send | ||
54 | * the data to (Host) buffers attached to the console key. Usually a device's | ||
55 | * key is a physical address within the device's memory, but because the | ||
56 | * console device doesn't have any associated physical memory, we use the | ||
57 | * LGUEST_CONSOLE_DMA_KEY constant (aka 0). */ | ||
58 | static int put_chars(u32 vtermno, const char *buf, int count) | ||
59 | { | ||
60 | struct lguest_dma dma; | ||
61 | |||
62 | /* FIXME: DMA buffers in a "struct lguest_dma" are not allowed | ||
63 | * to go over page boundaries. This never seems to happen, | ||
64 | * but if it did we'd need to fix this code. */ | ||
65 | dma.len[0] = count; | ||
66 | dma.len[1] = 0; | ||
67 | dma.addr[0] = __pa(buf); | ||
68 | |||
69 | lguest_send_dma(LGUEST_CONSOLE_DMA_KEY, &dma); | ||
70 | /* We're expected to return the amount of data we wrote: all of it. */ | ||
71 | return count; | ||
72 | } | ||
73 | |||
74 | /*D:350 get_chars() is the callback from the hvc_console infrastructure when | ||
75 | * an interrupt is received. | ||
76 | * | ||
77 | * Firstly we see if our buffer has been filled: if not, we return. The rest | ||
78 | * of the code deals with the fact that the hvc_console() infrastructure only | ||
79 | * asks us for 16 bytes at a time. We keep a "cons_offset" variable for | ||
80 | * partially-read buffers. */ | ||
81 | static int get_chars(u32 vtermno, char *buf, int count) | ||
82 | { | ||
83 | static int cons_offset; | ||
84 | |||
85 | /* Nothing left to see here... */ | ||
86 | if (!cons_input.used_len) | ||
87 | return 0; | ||
88 | |||
89 | /* You want more than we have to give? Well, try wanting less! */ | ||
90 | if (cons_input.used_len - cons_offset < count) | ||
91 | count = cons_input.used_len - cons_offset; | ||
92 | |||
93 | /* Copy across to their buffer and increment offset. */ | ||
94 | memcpy(buf, inbuf + cons_offset, count); | ||
95 | cons_offset += count; | ||
96 | |||
97 | /* Finished? Zero offset, and reset cons_input so Host will use it | ||
98 | * again. */ | ||
99 | if (cons_offset == cons_input.used_len) { | ||
100 | cons_offset = 0; | ||
101 | cons_input.used_len = 0; | ||
102 | } | ||
103 | return count; | ||
104 | } | ||
105 | /*:*/ | ||
106 | |||
107 | static struct hv_ops lguest_cons = { | ||
108 | .get_chars = get_chars, | ||
109 | .put_chars = put_chars, | ||
110 | }; | ||
111 | |||
112 | /*D:320 Console drivers are initialized very early so boot messages can go | ||
113 | * out. At this stage, the console is output-only. Our driver checks we're a | ||
114 | * Guest, and if so hands hvc_instantiate() the console number (0), priority | ||
115 | * (0), and the struct hv_ops containing the put_chars() function. */ | ||
116 | static int __init cons_init(void) | ||
117 | { | ||
118 | if (strcmp(paravirt_ops.name, "lguest") != 0) | ||
119 | return 0; | ||
120 | |||
121 | return hvc_instantiate(0, 0, &lguest_cons); | ||
122 | } | ||
123 | console_initcall(cons_init); | ||
124 | |||
125 | /*D:370 To set up and manage our virtual console, we call hvc_alloc() and | ||
126 | * stash the result in the private pointer of the "struct lguest_device". | ||
127 | * Since we never remove the console device we never need this pointer again, | ||
128 | * but using ->private is considered good form, and you never know who's going | ||
129 | * to copy your driver. | ||
130 | * | ||
131 | * Once the console is set up, we bind our input buffer ready for input. */ | ||
132 | static int lguestcons_probe(struct lguest_device *lgdev) | ||
133 | { | ||
134 | int err; | ||
135 | |||
136 | /* The first argument of hvc_alloc() is the virtual console number, so | ||
137 | * we use zero. The second argument is the interrupt number. | ||
138 | * | ||
139 | * The third argument is a "struct hv_ops" containing the put_chars() | ||
140 | * and get_chars() pointers. The final argument is the output buffer | ||
141 | * size: we use 256 and expect the Host to have room for us to send | ||
142 | * that much. */ | ||
143 | lgdev->private = hvc_alloc(0, lgdev_irq(lgdev), &lguest_cons, 256); | ||
144 | if (IS_ERR(lgdev->private)) | ||
145 | return PTR_ERR(lgdev->private); | ||
146 | |||
147 | /* We bind a single DMA buffer at key LGUEST_CONSOLE_DMA_KEY. | ||
148 | * "cons_input" is that statically-initialized global DMA buffer we saw | ||
149 | * above, and we also give the interrupt we want. */ | ||
150 | err = lguest_bind_dma(LGUEST_CONSOLE_DMA_KEY, &cons_input, 1, | ||
151 | lgdev_irq(lgdev)); | ||
152 | if (err) | ||
153 | printk("lguest console: failed to bind buffer.\n"); | ||
154 | return err; | ||
155 | } | ||
156 | /* Note the use of lgdev_irq() for the interrupt number. We tell hvc_alloc() | ||
157 | * to expect input when this interrupt is triggered, and then tell | ||
158 | * lguest_bind_dma() that is the interrupt to send us when input comes in. */ | ||
159 | |||
160 | /*D:360 From now on the console driver follows standard Guest driver form: | ||
161 | * register_lguest_driver() registers the device type and probe function, and | ||
162 | * the probe function sets up the device. | ||
163 | * | ||
164 | * The standard "struct lguest_driver": */ | ||
165 | static struct lguest_driver lguestcons_drv = { | ||
166 | .name = "lguestcons", | ||
167 | .owner = THIS_MODULE, | ||
168 | .device_type = LGUEST_DEVICE_T_CONSOLE, | ||
169 | .probe = lguestcons_probe, | ||
170 | }; | ||
171 | |||
172 | /* The standard init function */ | ||
173 | static int __init hvc_lguest_init(void) | ||
174 | { | ||
175 | return register_lguest_driver(&lguestcons_drv); | ||
176 | } | ||
177 | module_init(hvc_lguest_init); | ||
diff --git a/drivers/char/hvc_rtas.c b/drivers/char/hvc_rtas.c index 4b97eaf18602..bb09413d5a21 100644 --- a/drivers/char/hvc_rtas.c +++ b/drivers/char/hvc_rtas.c | |||
@@ -115,7 +115,7 @@ static void __exit hvc_rtas_exit(void) | |||
115 | module_exit(hvc_rtas_exit); | 115 | module_exit(hvc_rtas_exit); |
116 | 116 | ||
117 | /* This will happen prior to module init. There is no tty at this time? */ | 117 | /* This will happen prior to module init. There is no tty at this time? */ |
118 | static int hvc_rtas_console_init(void) | 118 | static int __init hvc_rtas_console_init(void) |
119 | { | 119 | { |
120 | rtascons_put_char_token = rtas_token("put-term-char"); | 120 | rtascons_put_char_token = rtas_token("put-term-char"); |
121 | if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE) | 121 | if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE) |
diff --git a/drivers/char/hvc_xen.c b/drivers/char/hvc_xen.c new file mode 100644 index 000000000000..dd68f8541c2d --- /dev/null +++ b/drivers/char/hvc_xen.c | |||
@@ -0,0 +1,159 @@ | |||
1 | /* | ||
2 | * xen console driver interface to hvc_console.c | ||
3 | * | ||
4 | * (c) 2007 Gerd Hoffmann <kraxel@suse.de> | ||
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 as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/console.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/err.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/types.h> | ||
26 | |||
27 | #include <asm/xen/hypervisor.h> | ||
28 | #include <xen/page.h> | ||
29 | #include <xen/events.h> | ||
30 | #include <xen/interface/io/console.h> | ||
31 | #include <xen/hvc-console.h> | ||
32 | |||
33 | #include "hvc_console.h" | ||
34 | |||
35 | #define HVC_COOKIE 0x58656e /* "Xen" in hex */ | ||
36 | |||
37 | static struct hvc_struct *hvc; | ||
38 | static int xencons_irq; | ||
39 | |||
40 | /* ------------------------------------------------------------------ */ | ||
41 | |||
42 | static inline struct xencons_interface *xencons_interface(void) | ||
43 | { | ||
44 | return mfn_to_virt(xen_start_info->console.domU.mfn); | ||
45 | } | ||
46 | |||
47 | static inline void notify_daemon(void) | ||
48 | { | ||
49 | /* Use evtchn: this is called early, before irq is set up. */ | ||
50 | notify_remote_via_evtchn(xen_start_info->console.domU.evtchn); | ||
51 | } | ||
52 | |||
53 | static int write_console(uint32_t vtermno, const char *data, int len) | ||
54 | { | ||
55 | struct xencons_interface *intf = xencons_interface(); | ||
56 | XENCONS_RING_IDX cons, prod; | ||
57 | int sent = 0; | ||
58 | |||
59 | cons = intf->out_cons; | ||
60 | prod = intf->out_prod; | ||
61 | mb(); /* update queue values before going on */ | ||
62 | BUG_ON((prod - cons) > sizeof(intf->out)); | ||
63 | |||
64 | while ((sent < len) && ((prod - cons) < sizeof(intf->out))) | ||
65 | intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++]; | ||
66 | |||
67 | wmb(); /* write ring before updating pointer */ | ||
68 | intf->out_prod = prod; | ||
69 | |||
70 | notify_daemon(); | ||
71 | return sent; | ||
72 | } | ||
73 | |||
74 | static int read_console(uint32_t vtermno, char *buf, int len) | ||
75 | { | ||
76 | struct xencons_interface *intf = xencons_interface(); | ||
77 | XENCONS_RING_IDX cons, prod; | ||
78 | int recv = 0; | ||
79 | |||
80 | cons = intf->in_cons; | ||
81 | prod = intf->in_prod; | ||
82 | mb(); /* get pointers before reading ring */ | ||
83 | BUG_ON((prod - cons) > sizeof(intf->in)); | ||
84 | |||
85 | while (cons != prod && recv < len) | ||
86 | buf[recv++] = intf->in[MASK_XENCONS_IDX(cons++, intf->in)]; | ||
87 | |||
88 | mb(); /* read ring before consuming */ | ||
89 | intf->in_cons = cons; | ||
90 | |||
91 | notify_daemon(); | ||
92 | return recv; | ||
93 | } | ||
94 | |||
95 | static struct hv_ops hvc_ops = { | ||
96 | .get_chars = read_console, | ||
97 | .put_chars = write_console, | ||
98 | }; | ||
99 | |||
100 | static int __init xen_init(void) | ||
101 | { | ||
102 | struct hvc_struct *hp; | ||
103 | |||
104 | if (!is_running_on_xen()) | ||
105 | return 0; | ||
106 | |||
107 | xencons_irq = bind_evtchn_to_irq(xen_start_info->console.domU.evtchn); | ||
108 | if (xencons_irq < 0) | ||
109 | xencons_irq = 0 /* NO_IRQ */; | ||
110 | hp = hvc_alloc(HVC_COOKIE, xencons_irq, &hvc_ops, 256); | ||
111 | if (IS_ERR(hp)) | ||
112 | return PTR_ERR(hp); | ||
113 | |||
114 | hvc = hp; | ||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static void __exit xen_fini(void) | ||
119 | { | ||
120 | if (hvc) | ||
121 | hvc_remove(hvc); | ||
122 | } | ||
123 | |||
124 | static int xen_cons_init(void) | ||
125 | { | ||
126 | if (!is_running_on_xen()) | ||
127 | return 0; | ||
128 | |||
129 | hvc_instantiate(HVC_COOKIE, 0, &hvc_ops); | ||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | module_init(xen_init); | ||
134 | module_exit(xen_fini); | ||
135 | console_initcall(xen_cons_init); | ||
136 | |||
137 | static void xenboot_write_console(struct console *console, const char *string, | ||
138 | unsigned len) | ||
139 | { | ||
140 | unsigned int linelen, off = 0; | ||
141 | const char *pos; | ||
142 | |||
143 | while (off < len && NULL != (pos = strchr(string+off, '\n'))) { | ||
144 | linelen = pos-string+off; | ||
145 | if (off + linelen > len) | ||
146 | break; | ||
147 | write_console(0, string+off, linelen); | ||
148 | write_console(0, "\r\n", 2); | ||
149 | off += linelen + 1; | ||
150 | } | ||
151 | if (off < len) | ||
152 | write_console(0, string+off, len-off); | ||
153 | } | ||
154 | |||
155 | struct console xenboot_console = { | ||
156 | .name = "xenboot", | ||
157 | .write = xenboot_write_console, | ||
158 | .flags = CON_PRINTBUFFER | CON_BOOT, | ||
159 | }; | ||
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c index 207f7343ba60..69d8866de783 100644 --- a/drivers/char/hvcs.c +++ b/drivers/char/hvcs.c | |||
@@ -210,9 +210,9 @@ static struct ktermios hvcs_tty_termios = { | |||
210 | static int hvcs_parm_num_devs = -1; | 210 | static int hvcs_parm_num_devs = -1; |
211 | module_param(hvcs_parm_num_devs, int, 0); | 211 | module_param(hvcs_parm_num_devs, int, 0); |
212 | 212 | ||
213 | char hvcs_driver_name[] = "hvcs"; | 213 | static const char hvcs_driver_name[] = "hvcs"; |
214 | char hvcs_device_node[] = "hvcs"; | 214 | static const char hvcs_device_node[] = "hvcs"; |
215 | char hvcs_driver_string[] | 215 | static const char hvcs_driver_string[] |
216 | = "IBM hvcs (Hypervisor Virtual Console Server) Driver"; | 216 | = "IBM hvcs (Hypervisor Virtual Console Server) Driver"; |
217 | 217 | ||
218 | /* Status of partner info rescan triggered via sysfs. */ | 218 | /* Status of partner info rescan triggered via sysfs. */ |
@@ -784,12 +784,10 @@ static int __devinit hvcs_probe( | |||
784 | return -EFAULT; | 784 | return -EFAULT; |
785 | } | 785 | } |
786 | 786 | ||
787 | hvcsd = kmalloc(sizeof(*hvcsd), GFP_KERNEL); | 787 | hvcsd = kzalloc(sizeof(*hvcsd), GFP_KERNEL); |
788 | if (!hvcsd) | 788 | if (!hvcsd) |
789 | return -ENODEV; | 789 | return -ENODEV; |
790 | 790 | ||
791 | /* hvcsd->tty is zeroed out with the memset */ | ||
792 | memset(hvcsd, 0x00, sizeof(*hvcsd)); | ||
793 | 791 | ||
794 | spin_lock_init(&hvcsd->lock); | 792 | spin_lock_init(&hvcsd->lock); |
795 | /* Automatically incs the refcount the first time */ | 793 | /* Automatically incs the refcount the first time */ |
@@ -1094,7 +1092,7 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address, | |||
1094 | * NOTICE: Do NOT hold either the hvcs_struct.lock or hvcs_structs_lock when | 1092 | * NOTICE: Do NOT hold either the hvcs_struct.lock or hvcs_structs_lock when |
1095 | * calling this function or you will get deadlock. | 1093 | * calling this function or you will get deadlock. |
1096 | */ | 1094 | */ |
1097 | struct hvcs_struct *hvcs_get_by_index(int index) | 1095 | static struct hvcs_struct *hvcs_get_by_index(int index) |
1098 | { | 1096 | { |
1099 | struct hvcs_struct *hvcsd = NULL; | 1097 | struct hvcs_struct *hvcsd = NULL; |
1100 | unsigned long flags; | 1098 | unsigned long flags; |
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 7cda04b33534..2d7cd486e025 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig | |||
@@ -41,7 +41,7 @@ config HW_RANDOM_AMD | |||
41 | 41 | ||
42 | config HW_RANDOM_GEODE | 42 | config HW_RANDOM_GEODE |
43 | tristate "AMD Geode HW Random Number Generator support" | 43 | tristate "AMD Geode HW Random Number Generator support" |
44 | depends on HW_RANDOM && X86 && PCI | 44 | depends on HW_RANDOM && X86_32 && PCI |
45 | default HW_RANDOM | 45 | default HW_RANDOM |
46 | ---help--- | 46 | ---help--- |
47 | This driver provides kernel-side support for the Random Number | 47 | This driver provides kernel-side support for the Random Number |
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c index 0289705967de..cd406416effd 100644 --- a/drivers/char/i8k.c +++ b/drivers/char/i8k.c | |||
@@ -98,9 +98,9 @@ struct smm_regs { | |||
98 | unsigned int edi __attribute__ ((packed)); | 98 | unsigned int edi __attribute__ ((packed)); |
99 | }; | 99 | }; |
100 | 100 | ||
101 | static inline char *i8k_get_dmi_data(int field) | 101 | static inline const char *i8k_get_dmi_data(int field) |
102 | { | 102 | { |
103 | char *dmi_data = dmi_get_system_info(field); | 103 | const char *dmi_data = dmi_get_system_info(field); |
104 | 104 | ||
105 | return dmi_data && *dmi_data ? dmi_data : "?"; | 105 | return dmi_data && *dmi_data ? dmi_data : "?"; |
106 | } | 106 | } |
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 83c7258d3580..bd94d5f9e62b 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c | |||
@@ -411,8 +411,8 @@ cleanup_module(void) | |||
411 | iiResetDelay( i2BoardPtrTable[i] ); | 411 | iiResetDelay( i2BoardPtrTable[i] ); |
412 | /* free io addresses and Tibet */ | 412 | /* free io addresses and Tibet */ |
413 | release_region( ip2config.addr[i], 8 ); | 413 | release_region( ip2config.addr[i], 8 ); |
414 | class_device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i)); | 414 | device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i)); |
415 | class_device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i + 1)); | 415 | device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i + 1)); |
416 | } | 416 | } |
417 | /* Disable and remove interrupt handler. */ | 417 | /* Disable and remove interrupt handler. */ |
418 | if ( (ip2config.irq[i] > 0) && have_requested_irq(ip2config.irq[i]) ) { | 418 | if ( (ip2config.irq[i] > 0) && have_requested_irq(ip2config.irq[i]) ) { |
@@ -425,9 +425,7 @@ cleanup_module(void) | |||
425 | printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", err); | 425 | printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", err); |
426 | } | 426 | } |
427 | put_tty_driver(ip2_tty_driver); | 427 | put_tty_driver(ip2_tty_driver); |
428 | if ( ( err = unregister_chrdev ( IP2_IPL_MAJOR, pcIpl ) ) ) { | 428 | unregister_chrdev(IP2_IPL_MAJOR, pcIpl); |
429 | printk(KERN_ERR "IP2: failed to unregister IPL driver (%d)\n", err); | ||
430 | } | ||
431 | remove_proc_entry("ip2mem", &proc_root); | 429 | remove_proc_entry("ip2mem", &proc_root); |
432 | 430 | ||
433 | // free memory | 431 | // free memory |
@@ -502,7 +500,6 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize) | |||
502 | { | 500 | { |
503 | int i, j, box; | 501 | int i, j, box; |
504 | int err = 0; | 502 | int err = 0; |
505 | int status = 0; | ||
506 | static int loaded; | 503 | static int loaded; |
507 | i2eBordStrPtr pB = NULL; | 504 | i2eBordStrPtr pB = NULL; |
508 | int rc = -1; | 505 | int rc = -1; |
@@ -590,6 +587,8 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize) | |||
590 | case PCI: | 587 | case PCI: |
591 | #ifdef CONFIG_PCI | 588 | #ifdef CONFIG_PCI |
592 | { | 589 | { |
590 | int status; | ||
591 | |||
593 | pci_dev_i = pci_get_device(PCI_VENDOR_ID_COMPUTONE, | 592 | pci_dev_i = pci_get_device(PCI_VENDOR_ID_COMPUTONE, |
594 | PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i); | 593 | PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i); |
595 | if (pci_dev_i != NULL) { | 594 | if (pci_dev_i != NULL) { |
@@ -719,12 +718,12 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize) | |||
719 | } | 718 | } |
720 | 719 | ||
721 | if ( NULL != ( pB = i2BoardPtrTable[i] ) ) { | 720 | if ( NULL != ( pB = i2BoardPtrTable[i] ) ) { |
722 | class_device_create(ip2_class, NULL, | 721 | device_create(ip2_class, NULL, |
723 | MKDEV(IP2_IPL_MAJOR, 4 * i), | 722 | MKDEV(IP2_IPL_MAJOR, 4 * i), |
724 | NULL, "ipl%d", i); | 723 | "ipl%d", i); |
725 | class_device_create(ip2_class, NULL, | 724 | device_create(ip2_class, NULL, |
726 | MKDEV(IP2_IPL_MAJOR, 4 * i + 1), | 725 | MKDEV(IP2_IPL_MAJOR, 4 * i + 1), |
727 | NULL, "stat%d", i); | 726 | "stat%d", i); |
728 | 727 | ||
729 | for ( box = 0; box < ABS_MAX_BOXES; ++box ) | 728 | for ( box = 0; box < ABS_MAX_BOXES; ++box ) |
730 | { | 729 | { |
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index c2aa44ee6eb6..0246a2b8ce48 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c | |||
@@ -865,7 +865,7 @@ static void ipmi_new_smi(int if_num, struct device *device) | |||
865 | entry->dev = dev; | 865 | entry->dev = dev; |
866 | 866 | ||
867 | mutex_lock(®_list_mutex); | 867 | mutex_lock(®_list_mutex); |
868 | class_device_create(ipmi_class, NULL, dev, device, "ipmi%d", if_num); | 868 | device_create(ipmi_class, device, dev, "ipmi%d", if_num); |
869 | list_add(&entry->link, ®_list); | 869 | list_add(&entry->link, ®_list); |
870 | mutex_unlock(®_list_mutex); | 870 | mutex_unlock(®_list_mutex); |
871 | } | 871 | } |
@@ -883,7 +883,7 @@ static void ipmi_smi_gone(int if_num) | |||
883 | break; | 883 | break; |
884 | } | 884 | } |
885 | } | 885 | } |
886 | class_device_destroy(ipmi_class, dev); | 886 | device_destroy(ipmi_class, dev); |
887 | mutex_unlock(®_list_mutex); | 887 | mutex_unlock(®_list_mutex); |
888 | } | 888 | } |
889 | 889 | ||
@@ -938,7 +938,7 @@ static __exit void cleanup_ipmi(void) | |||
938 | mutex_lock(®_list_mutex); | 938 | mutex_lock(®_list_mutex); |
939 | list_for_each_entry_safe(entry, entry2, ®_list, link) { | 939 | list_for_each_entry_safe(entry, entry2, ®_list, link) { |
940 | list_del(&entry->link); | 940 | list_del(&entry->link); |
941 | class_device_destroy(ipmi_class, entry->dev); | 941 | device_destroy(ipmi_class, entry->dev); |
942 | kfree(entry); | 942 | kfree(entry); |
943 | } | 943 | } |
944 | mutex_unlock(®_list_mutex); | 944 | mutex_unlock(®_list_mutex); |
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index b5df7e61aeb2..6a01dd9e43f8 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -2639,10 +2639,9 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
2639 | return -ENODEV; | 2639 | return -ENODEV; |
2640 | } | 2640 | } |
2641 | 2641 | ||
2642 | intf = kmalloc(sizeof(*intf), GFP_KERNEL); | 2642 | intf = kzalloc(sizeof(*intf), GFP_KERNEL); |
2643 | if (!intf) | 2643 | if (!intf) |
2644 | return -ENOMEM; | 2644 | return -ENOMEM; |
2645 | memset(intf, 0, sizeof(*intf)); | ||
2646 | 2645 | ||
2647 | intf->ipmi_version_major = ipmi_version_major(device_id); | 2646 | intf->ipmi_version_major = ipmi_version_major(device_id); |
2648 | intf->ipmi_version_minor = ipmi_version_minor(device_id); | 2647 | intf->ipmi_version_minor = ipmi_version_minor(device_id); |
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 4edfdda0cf99..a2894d425153 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -1965,10 +1965,10 @@ struct dmi_ipmi_data | |||
1965 | u8 slave_addr; | 1965 | u8 slave_addr; |
1966 | }; | 1966 | }; |
1967 | 1967 | ||
1968 | static int __devinit decode_dmi(struct dmi_header *dm, | 1968 | static int __devinit decode_dmi(const struct dmi_header *dm, |
1969 | struct dmi_ipmi_data *dmi) | 1969 | struct dmi_ipmi_data *dmi) |
1970 | { | 1970 | { |
1971 | u8 *data = (u8 *)dm; | 1971 | const u8 *data = (const u8 *)dm; |
1972 | unsigned long base_addr; | 1972 | unsigned long base_addr; |
1973 | u8 reg_spacing; | 1973 | u8 reg_spacing; |
1974 | u8 len = dm->length; | 1974 | u8 len = dm->length; |
@@ -2050,6 +2050,7 @@ static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data) | |||
2050 | info->si_type = SI_BT; | 2050 | info->si_type = SI_BT; |
2051 | break; | 2051 | break; |
2052 | default: | 2052 | default: |
2053 | kfree(info); | ||
2053 | return; | 2054 | return; |
2054 | } | 2055 | } |
2055 | 2056 | ||
@@ -2090,13 +2091,14 @@ static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data) | |||
2090 | 2091 | ||
2091 | static void __devinit dmi_find_bmc(void) | 2092 | static void __devinit dmi_find_bmc(void) |
2092 | { | 2093 | { |
2093 | struct dmi_device *dev = NULL; | 2094 | const struct dmi_device *dev = NULL; |
2094 | struct dmi_ipmi_data data; | 2095 | struct dmi_ipmi_data data; |
2095 | int rv; | 2096 | int rv; |
2096 | 2097 | ||
2097 | while ((dev = dmi_find_device(DMI_DEV_TYPE_IPMI, NULL, dev))) { | 2098 | while ((dev = dmi_find_device(DMI_DEV_TYPE_IPMI, NULL, dev))) { |
2098 | memset(&data, 0, sizeof(data)); | 2099 | memset(&data, 0, sizeof(data)); |
2099 | rv = decode_dmi((struct dmi_header *) dev->device_data, &data); | 2100 | rv = decode_dmi((const struct dmi_header *) dev->device_data, |
2101 | &data); | ||
2100 | if (!rv) | 2102 | if (!rv) |
2101 | try_init_dmi(&data); | 2103 | try_init_dmi(&data); |
2102 | } | 2104 | } |
@@ -2214,7 +2216,8 @@ static int ipmi_pci_resume(struct pci_dev *pdev) | |||
2214 | 2216 | ||
2215 | static struct pci_device_id ipmi_pci_devices[] = { | 2217 | static struct pci_device_id ipmi_pci_devices[] = { |
2216 | { PCI_DEVICE(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID) }, | 2218 | { PCI_DEVICE(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID) }, |
2217 | { PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE_MASK) } | 2219 | { PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE_MASK) }, |
2220 | { 0, } | ||
2218 | }; | 2221 | }; |
2219 | MODULE_DEVICE_TABLE(pci, ipmi_pci_devices); | 2222 | MODULE_DEVICE_TABLE(pci, ipmi_pci_devices); |
2220 | 2223 | ||
@@ -2250,19 +2253,19 @@ static int __devinit ipmi_of_probe(struct of_device *dev, | |||
2250 | return ret; | 2253 | return ret; |
2251 | } | 2254 | } |
2252 | 2255 | ||
2253 | regsize = get_property(np, "reg-size", &proplen); | 2256 | regsize = of_get_property(np, "reg-size", &proplen); |
2254 | if (regsize && proplen != 4) { | 2257 | if (regsize && proplen != 4) { |
2255 | dev_warn(&dev->dev, PFX "invalid regsize from OF\n"); | 2258 | dev_warn(&dev->dev, PFX "invalid regsize from OF\n"); |
2256 | return -EINVAL; | 2259 | return -EINVAL; |
2257 | } | 2260 | } |
2258 | 2261 | ||
2259 | regspacing = get_property(np, "reg-spacing", &proplen); | 2262 | regspacing = of_get_property(np, "reg-spacing", &proplen); |
2260 | if (regspacing && proplen != 4) { | 2263 | if (regspacing && proplen != 4) { |
2261 | dev_warn(&dev->dev, PFX "invalid regspacing from OF\n"); | 2264 | dev_warn(&dev->dev, PFX "invalid regspacing from OF\n"); |
2262 | return -EINVAL; | 2265 | return -EINVAL; |
2263 | } | 2266 | } |
2264 | 2267 | ||
2265 | regshift = get_property(np, "reg-shift", &proplen); | 2268 | regshift = of_get_property(np, "reg-shift", &proplen); |
2266 | if (regshift && proplen != 4) { | 2269 | if (regshift && proplen != 4) { |
2267 | dev_warn(&dev->dev, PFX "invalid regshift from OF\n"); | 2270 | dev_warn(&dev->dev, PFX "invalid regshift from OF\n"); |
2268 | return -EINVAL; | 2271 | return -EINVAL; |
@@ -2291,7 +2294,7 @@ static int __devinit ipmi_of_probe(struct of_device *dev, | |||
2291 | info->irq = irq_of_parse_and_map(dev->node, 0); | 2294 | info->irq = irq_of_parse_and_map(dev->node, 0); |
2292 | info->dev = &dev->dev; | 2295 | info->dev = &dev->dev; |
2293 | 2296 | ||
2294 | dev_dbg(&dev->dev, "addr 0x%lx regsize %ld spacing %ld irq %x\n", | 2297 | dev_dbg(&dev->dev, "addr 0x%lx regsize %d spacing %d irq %x\n", |
2295 | info->io.addr_data, info->io.regsize, info->io.regspacing, | 2298 | info->io.addr_data, info->io.regsize, info->io.regspacing, |
2296 | info->irq); | 2299 | info->irq); |
2297 | 2300 | ||
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 3c66f402f9d7..1f27be1ec3d4 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c | |||
@@ -4624,9 +4624,8 @@ static int __init istallion_module_init(void) | |||
4624 | 4624 | ||
4625 | istallion_class = class_create(THIS_MODULE, "staliomem"); | 4625 | istallion_class = class_create(THIS_MODULE, "staliomem"); |
4626 | for (i = 0; i < 4; i++) | 4626 | for (i = 0; i < 4; i++) |
4627 | class_device_create(istallion_class, NULL, | 4627 | device_create(istallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i), |
4628 | MKDEV(STL_SIOMEMMAJOR, i), | 4628 | "staliomem%d", i); |
4629 | NULL, "staliomem%d", i); | ||
4630 | 4629 | ||
4631 | return 0; | 4630 | return 0; |
4632 | err_deinit: | 4631 | err_deinit: |
@@ -4659,8 +4658,7 @@ static void __exit istallion_module_exit(void) | |||
4659 | unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"); | 4658 | unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"); |
4660 | 4659 | ||
4661 | for (j = 0; j < 4; j++) | 4660 | for (j = 0; j < 4; j++) |
4662 | class_device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, | 4661 | device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, j)); |
4663 | j)); | ||
4664 | class_destroy(istallion_class); | 4662 | class_destroy(istallion_class); |
4665 | 4663 | ||
4666 | pci_unregister_driver(&stli_pcidriver); | 4664 | pci_unregister_driver(&stli_pcidriver); |
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 2ce0af1bd588..d95f316afb5a 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c | |||
@@ -1022,10 +1022,6 @@ static const unsigned short x86_keycodes[256] = | |||
1022 | 308,310,313,314,315,317,318,319,320,357,322,323,324,325,276,330, | 1022 | 308,310,313,314,315,317,318,319,320,357,322,323,324,325,276,330, |
1023 | 332,340,365,342,343,344,345,346,356,270,341,368,369,370,371,372 }; | 1023 | 332,340,365,342,343,344,345,346,356,270,341,368,369,370,371,372 }; |
1024 | 1024 | ||
1025 | #ifdef CONFIG_MAC_EMUMOUSEBTN | ||
1026 | extern int mac_hid_mouse_emulate_buttons(int, int, int); | ||
1027 | #endif /* CONFIG_MAC_EMUMOUSEBTN */ | ||
1028 | |||
1029 | #ifdef CONFIG_SPARC | 1025 | #ifdef CONFIG_SPARC |
1030 | static int sparc_l1_a_state = 0; | 1026 | static int sparc_l1_a_state = 0; |
1031 | extern void sun_do_break(void); | 1027 | extern void sun_do_break(void); |
diff --git a/drivers/char/lcd.c b/drivers/char/lcd.c index 1f0962616ee5..4fe9206f84de 100644 --- a/drivers/char/lcd.c +++ b/drivers/char/lcd.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <asm/io.h> | 25 | #include <asm/io.h> |
26 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
27 | #include <asm/system.h> | 27 | #include <asm/system.h> |
28 | #include <linux/delay.h> | ||
29 | 28 | ||
30 | #include "lcd.h" | 29 | #include "lcd.h" |
31 | 30 | ||
diff --git a/drivers/char/lp.c b/drivers/char/lp.c index 62051f8b0910..c59e2a0996cc 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c | |||
@@ -799,8 +799,7 @@ static int lp_register(int nr, struct parport *port) | |||
799 | if (reset) | 799 | if (reset) |
800 | lp_reset(nr); | 800 | lp_reset(nr); |
801 | 801 | ||
802 | class_device_create(lp_class, NULL, MKDEV(LP_MAJOR, nr), port->dev, | 802 | device_create(lp_class, port->dev, MKDEV(LP_MAJOR, nr), "lp%d", nr); |
803 | "lp%d", nr); | ||
804 | 803 | ||
805 | printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name, | 804 | printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name, |
806 | (port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven"); | 805 | (port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven"); |
@@ -971,7 +970,7 @@ static void lp_cleanup_module (void) | |||
971 | if (lp_table[offset].dev == NULL) | 970 | if (lp_table[offset].dev == NULL) |
972 | continue; | 971 | continue; |
973 | parport_unregister_device(lp_table[offset].dev); | 972 | parport_unregister_device(lp_table[offset].dev); |
974 | class_device_destroy(lp_class, MKDEV(LP_MAJOR, offset)); | 973 | device_destroy(lp_class, MKDEV(LP_MAJOR, offset)); |
975 | } | 974 | } |
976 | class_destroy(lp_class); | 975 | class_destroy(lp_class); |
977 | } | 976 | } |
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c index 57f9115a456c..7ee5d9444926 100644 --- a/drivers/char/mbcs.c +++ b/drivers/char/mbcs.c | |||
@@ -39,14 +39,14 @@ | |||
39 | #else | 39 | #else |
40 | #define DBG(fmt...) | 40 | #define DBG(fmt...) |
41 | #endif | 41 | #endif |
42 | int mbcs_major; | 42 | static int mbcs_major; |
43 | 43 | ||
44 | LIST_HEAD(soft_list); | 44 | static LIST_HEAD(soft_list); |
45 | 45 | ||
46 | /* | 46 | /* |
47 | * file operations | 47 | * file operations |
48 | */ | 48 | */ |
49 | const struct file_operations mbcs_ops = { | 49 | static const struct file_operations mbcs_ops = { |
50 | .open = mbcs_open, | 50 | .open = mbcs_open, |
51 | .llseek = mbcs_sram_llseek, | 51 | .llseek = mbcs_sram_llseek, |
52 | .read = mbcs_sram_read, | 52 | .read = mbcs_sram_read, |
@@ -377,7 +377,7 @@ dmaread_exit: | |||
377 | return rv; | 377 | return rv; |
378 | } | 378 | } |
379 | 379 | ||
380 | int mbcs_open(struct inode *ip, struct file *fp) | 380 | static int mbcs_open(struct inode *ip, struct file *fp) |
381 | { | 381 | { |
382 | struct mbcs_soft *soft; | 382 | struct mbcs_soft *soft; |
383 | int minor; | 383 | int minor; |
@@ -394,7 +394,7 @@ int mbcs_open(struct inode *ip, struct file *fp) | |||
394 | return -ENODEV; | 394 | return -ENODEV; |
395 | } | 395 | } |
396 | 396 | ||
397 | ssize_t mbcs_sram_read(struct file * fp, char __user *buf, size_t len, loff_t * off) | 397 | static ssize_t mbcs_sram_read(struct file * fp, char __user *buf, size_t len, loff_t * off) |
398 | { | 398 | { |
399 | struct cx_dev *cx_dev = fp->private_data; | 399 | struct cx_dev *cx_dev = fp->private_data; |
400 | struct mbcs_soft *soft = cx_dev->soft; | 400 | struct mbcs_soft *soft = cx_dev->soft; |
@@ -418,7 +418,7 @@ ssize_t mbcs_sram_read(struct file * fp, char __user *buf, size_t len, loff_t * | |||
418 | return rv; | 418 | return rv; |
419 | } | 419 | } |
420 | 420 | ||
421 | ssize_t | 421 | static ssize_t |
422 | mbcs_sram_write(struct file * fp, const char __user *buf, size_t len, loff_t * off) | 422 | mbcs_sram_write(struct file * fp, const char __user *buf, size_t len, loff_t * off) |
423 | { | 423 | { |
424 | struct cx_dev *cx_dev = fp->private_data; | 424 | struct cx_dev *cx_dev = fp->private_data; |
@@ -443,7 +443,7 @@ mbcs_sram_write(struct file * fp, const char __user *buf, size_t len, loff_t * o | |||
443 | return rv; | 443 | return rv; |
444 | } | 444 | } |
445 | 445 | ||
446 | loff_t mbcs_sram_llseek(struct file * filp, loff_t off, int whence) | 446 | static loff_t mbcs_sram_llseek(struct file * filp, loff_t off, int whence) |
447 | { | 447 | { |
448 | loff_t newpos; | 448 | loff_t newpos; |
449 | 449 | ||
@@ -491,7 +491,7 @@ static void mbcs_gscr_pioaddr_set(struct mbcs_soft *soft) | |||
491 | soft->gscr_addr = mbcs_pioaddr(soft, MBCS_GSCR_START); | 491 | soft->gscr_addr = mbcs_pioaddr(soft, MBCS_GSCR_START); |
492 | } | 492 | } |
493 | 493 | ||
494 | int mbcs_gscr_mmap(struct file *fp, struct vm_area_struct *vma) | 494 | static int mbcs_gscr_mmap(struct file *fp, struct vm_area_struct *vma) |
495 | { | 495 | { |
496 | struct cx_dev *cx_dev = fp->private_data; | 496 | struct cx_dev *cx_dev = fp->private_data; |
497 | struct mbcs_soft *soft = cx_dev->soft; | 497 | struct mbcs_soft *soft = cx_dev->soft; |
@@ -793,7 +793,7 @@ static int mbcs_remove(struct cx_dev *dev) | |||
793 | return 0; | 793 | return 0; |
794 | } | 794 | } |
795 | 795 | ||
796 | const struct cx_device_id __devinitdata mbcs_id_table[] = { | 796 | static const struct cx_device_id __devinitdata mbcs_id_table[] = { |
797 | { | 797 | { |
798 | .part_num = MBCS_PART_NUM, | 798 | .part_num = MBCS_PART_NUM, |
799 | .mfg_num = MBCS_MFG_NUM, | 799 | .mfg_num = MBCS_MFG_NUM, |
@@ -807,7 +807,7 @@ const struct cx_device_id __devinitdata mbcs_id_table[] = { | |||
807 | 807 | ||
808 | MODULE_DEVICE_TABLE(cx, mbcs_id_table); | 808 | MODULE_DEVICE_TABLE(cx, mbcs_id_table); |
809 | 809 | ||
810 | struct cx_drv mbcs_driver = { | 810 | static struct cx_drv mbcs_driver = { |
811 | .name = DEVICE_NAME, | 811 | .name = DEVICE_NAME, |
812 | .id_table = mbcs_id_table, | 812 | .id_table = mbcs_id_table, |
813 | .probe = mbcs_probe, | 813 | .probe = mbcs_probe, |
@@ -816,12 +816,7 @@ struct cx_drv mbcs_driver = { | |||
816 | 816 | ||
817 | static void __exit mbcs_exit(void) | 817 | static void __exit mbcs_exit(void) |
818 | { | 818 | { |
819 | int rv; | 819 | unregister_chrdev(mbcs_major, DEVICE_NAME); |
820 | |||
821 | rv = unregister_chrdev(mbcs_major, DEVICE_NAME); | ||
822 | if (rv < 0) | ||
823 | DBG(KERN_ALERT "Error in unregister_chrdev: %d\n", rv); | ||
824 | |||
825 | cx_driver_unregister(&mbcs_driver); | 820 | cx_driver_unregister(&mbcs_driver); |
826 | } | 821 | } |
827 | 822 | ||
diff --git a/drivers/char/mbcs.h b/drivers/char/mbcs.h index e7fd47e43257..c9905a3c3353 100644 --- a/drivers/char/mbcs.h +++ b/drivers/char/mbcs.h | |||
@@ -542,12 +542,12 @@ struct mbcs_soft { | |||
542 | struct semaphore algolock; | 542 | struct semaphore algolock; |
543 | }; | 543 | }; |
544 | 544 | ||
545 | extern int mbcs_open(struct inode *ip, struct file *fp); | 545 | static int mbcs_open(struct inode *ip, struct file *fp); |
546 | extern ssize_t mbcs_sram_read(struct file *fp, char __user *buf, size_t len, | 546 | static ssize_t mbcs_sram_read(struct file *fp, char __user *buf, size_t len, |
547 | loff_t * off); | 547 | loff_t * off); |
548 | extern ssize_t mbcs_sram_write(struct file *fp, const char __user *buf, size_t len, | 548 | static ssize_t mbcs_sram_write(struct file *fp, const char __user *buf, size_t len, |
549 | loff_t * off); | 549 | loff_t * off); |
550 | extern loff_t mbcs_sram_llseek(struct file *filp, loff_t off, int whence); | 550 | static loff_t mbcs_sram_llseek(struct file *filp, loff_t off, int whence); |
551 | extern int mbcs_gscr_mmap(struct file *fp, struct vm_area_struct *vma); | 551 | static int mbcs_gscr_mmap(struct file *fp, struct vm_area_struct *vma); |
552 | 552 | ||
553 | #endif // __MBCS_H__ | 553 | #endif // __MBCS_H__ |
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c index 6e55cfb9c65a..e60a74c66e3d 100644 --- a/drivers/char/mmtimer.c +++ b/drivers/char/mmtimer.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/errno.h> | 26 | #include <linux/errno.h> |
27 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
28 | #include <linux/fs.h> | ||
28 | #include <linux/mmtimer.h> | 29 | #include <linux/mmtimer.h> |
29 | #include <linux/miscdevice.h> | 30 | #include <linux/miscdevice.h> |
30 | #include <linux/posix-timers.h> | 31 | #include <linux/posix-timers.h> |
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c index c716ef0dd370..04ac155d3a07 100644 --- a/drivers/char/mspec.c +++ b/drivers/char/mspec.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/miscdevice.h> | 38 | #include <linux/miscdevice.h> |
39 | #include <linux/spinlock.h> | 39 | #include <linux/spinlock.h> |
40 | #include <linux/mm.h> | 40 | #include <linux/mm.h> |
41 | #include <linux/fs.h> | ||
41 | #include <linux/vmalloc.h> | 42 | #include <linux/vmalloc.h> |
42 | #include <linux/string.h> | 43 | #include <linux/string.h> |
43 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
@@ -66,7 +67,7 @@ | |||
66 | /* | 67 | /* |
67 | * Page types allocated by the device. | 68 | * Page types allocated by the device. |
68 | */ | 69 | */ |
69 | enum { | 70 | enum mspec_page_type { |
70 | MSPEC_FETCHOP = 1, | 71 | MSPEC_FETCHOP = 1, |
71 | MSPEC_CACHED, | 72 | MSPEC_CACHED, |
72 | MSPEC_UNCACHED | 73 | MSPEC_UNCACHED |
@@ -82,15 +83,25 @@ static int is_sn2; | |||
82 | * One of these structures is allocated when an mspec region is mmaped. The | 83 | * One of these structures is allocated when an mspec region is mmaped. The |
83 | * structure is pointed to by the vma->vm_private_data field in the vma struct. | 84 | * structure is pointed to by the vma->vm_private_data field in the vma struct. |
84 | * This structure is used to record the addresses of the mspec pages. | 85 | * This structure is used to record the addresses of the mspec pages. |
86 | * This structure is shared by all vma's that are split off from the | ||
87 | * original vma when split_vma()'s are done. | ||
88 | * | ||
89 | * The refcnt is incremented atomically because mm->mmap_sem does not | ||
90 | * protect in fork case where multiple tasks share the vma_data. | ||
85 | */ | 91 | */ |
86 | struct vma_data { | 92 | struct vma_data { |
87 | atomic_t refcnt; /* Number of vmas sharing the data. */ | 93 | atomic_t refcnt; /* Number of vmas sharing the data. */ |
88 | spinlock_t lock; /* Serialize access to the vma. */ | 94 | spinlock_t lock; /* Serialize access to this structure. */ |
89 | int count; /* Number of pages allocated. */ | 95 | int count; /* Number of pages allocated. */ |
90 | int type; /* Type of pages allocated. */ | 96 | enum mspec_page_type type; /* Type of pages allocated. */ |
97 | int flags; /* See VMD_xxx below. */ | ||
98 | unsigned long vm_start; /* Original (unsplit) base. */ | ||
99 | unsigned long vm_end; /* Original (unsplit) end. */ | ||
91 | unsigned long maddr[0]; /* Array of MSPEC addresses. */ | 100 | unsigned long maddr[0]; /* Array of MSPEC addresses. */ |
92 | }; | 101 | }; |
93 | 102 | ||
103 | #define VMD_VMALLOCED 0x1 /* vmalloc'd rather than kmalloc'd */ | ||
104 | |||
94 | /* used on shub2 to clear FOP cache in the HUB */ | 105 | /* used on shub2 to clear FOP cache in the HUB */ |
95 | static unsigned long scratch_page[MAX_NUMNODES]; | 106 | static unsigned long scratch_page[MAX_NUMNODES]; |
96 | #define SH2_AMO_CACHE_ENTRIES 4 | 107 | #define SH2_AMO_CACHE_ENTRIES 4 |
@@ -128,8 +139,8 @@ mspec_zero_block(unsigned long addr, int len) | |||
128 | * mspec_open | 139 | * mspec_open |
129 | * | 140 | * |
130 | * Called when a device mapping is created by a means other than mmap | 141 | * Called when a device mapping is created by a means other than mmap |
131 | * (via fork, etc.). Increments the reference count on the underlying | 142 | * (via fork, munmap, etc.). Increments the reference count on the |
132 | * mspec data so it is not freed prematurely. | 143 | * underlying mspec data so it is not freed prematurely. |
133 | */ | 144 | */ |
134 | static void | 145 | static void |
135 | mspec_open(struct vm_area_struct *vma) | 146 | mspec_open(struct vm_area_struct *vma) |
@@ -144,43 +155,43 @@ mspec_open(struct vm_area_struct *vma) | |||
144 | * mspec_close | 155 | * mspec_close |
145 | * | 156 | * |
146 | * Called when unmapping a device mapping. Frees all mspec pages | 157 | * Called when unmapping a device mapping. Frees all mspec pages |
147 | * belonging to the vma. | 158 | * belonging to all the vma's sharing this vma_data structure. |
148 | */ | 159 | */ |
149 | static void | 160 | static void |
150 | mspec_close(struct vm_area_struct *vma) | 161 | mspec_close(struct vm_area_struct *vma) |
151 | { | 162 | { |
152 | struct vma_data *vdata; | 163 | struct vma_data *vdata; |
153 | int i, pages, result, vdata_size; | 164 | int index, last_index; |
165 | unsigned long my_page; | ||
154 | 166 | ||
155 | vdata = vma->vm_private_data; | 167 | vdata = vma->vm_private_data; |
168 | |||
156 | if (!atomic_dec_and_test(&vdata->refcnt)) | 169 | if (!atomic_dec_and_test(&vdata->refcnt)) |
157 | return; | 170 | return; |
158 | 171 | ||
159 | pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; | 172 | last_index = (vdata->vm_end - vdata->vm_start) >> PAGE_SHIFT; |
160 | vdata_size = sizeof(struct vma_data) + pages * sizeof(long); | 173 | for (index = 0; index < last_index; index++) { |
161 | for (i = 0; i < pages; i++) { | 174 | if (vdata->maddr[index] == 0) |
162 | if (vdata->maddr[i] == 0) | ||
163 | continue; | 175 | continue; |
164 | /* | 176 | /* |
165 | * Clear the page before sticking it back | 177 | * Clear the page before sticking it back |
166 | * into the pool. | 178 | * into the pool. |
167 | */ | 179 | */ |
168 | result = mspec_zero_block(vdata->maddr[i], PAGE_SIZE); | 180 | my_page = vdata->maddr[index]; |
169 | if (!result) | 181 | vdata->maddr[index] = 0; |
170 | uncached_free_page(vdata->maddr[i]); | 182 | if (!mspec_zero_block(my_page, PAGE_SIZE)) |
183 | uncached_free_page(my_page); | ||
171 | else | 184 | else |
172 | printk(KERN_WARNING "mspec_close(): " | 185 | printk(KERN_WARNING "mspec_close(): " |
173 | "failed to zero page %i\n", | 186 | "failed to zero page %ld\n", my_page); |
174 | result); | ||
175 | } | 187 | } |
176 | 188 | ||
177 | if (vdata_size <= PAGE_SIZE) | 189 | if (vdata->flags & VMD_VMALLOCED) |
178 | kfree(vdata); | ||
179 | else | ||
180 | vfree(vdata); | 190 | vfree(vdata); |
191 | else | ||
192 | kfree(vdata); | ||
181 | } | 193 | } |
182 | 194 | ||
183 | |||
184 | /* | 195 | /* |
185 | * mspec_nopfn | 196 | * mspec_nopfn |
186 | * | 197 | * |
@@ -194,7 +205,8 @@ mspec_nopfn(struct vm_area_struct *vma, unsigned long address) | |||
194 | int index; | 205 | int index; |
195 | struct vma_data *vdata = vma->vm_private_data; | 206 | struct vma_data *vdata = vma->vm_private_data; |
196 | 207 | ||
197 | index = (address - vma->vm_start) >> PAGE_SHIFT; | 208 | BUG_ON(address < vdata->vm_start || address >= vdata->vm_end); |
209 | index = (address - vdata->vm_start) >> PAGE_SHIFT; | ||
198 | maddr = (volatile unsigned long) vdata->maddr[index]; | 210 | maddr = (volatile unsigned long) vdata->maddr[index]; |
199 | if (maddr == 0) { | 211 | if (maddr == 0) { |
200 | maddr = uncached_alloc_page(numa_node_id()); | 212 | maddr = uncached_alloc_page(numa_node_id()); |
@@ -236,10 +248,11 @@ static struct vm_operations_struct mspec_vm_ops = { | |||
236 | * underlying pages. | 248 | * underlying pages. |
237 | */ | 249 | */ |
238 | static int | 250 | static int |
239 | mspec_mmap(struct file *file, struct vm_area_struct *vma, int type) | 251 | mspec_mmap(struct file *file, struct vm_area_struct *vma, |
252 | enum mspec_page_type type) | ||
240 | { | 253 | { |
241 | struct vma_data *vdata; | 254 | struct vma_data *vdata; |
242 | int pages, vdata_size; | 255 | int pages, vdata_size, flags = 0; |
243 | 256 | ||
244 | if (vma->vm_pgoff != 0) | 257 | if (vma->vm_pgoff != 0) |
245 | return -EINVAL; | 258 | return -EINVAL; |
@@ -254,12 +267,17 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma, int type) | |||
254 | vdata_size = sizeof(struct vma_data) + pages * sizeof(long); | 267 | vdata_size = sizeof(struct vma_data) + pages * sizeof(long); |
255 | if (vdata_size <= PAGE_SIZE) | 268 | if (vdata_size <= PAGE_SIZE) |
256 | vdata = kmalloc(vdata_size, GFP_KERNEL); | 269 | vdata = kmalloc(vdata_size, GFP_KERNEL); |
257 | else | 270 | else { |
258 | vdata = vmalloc(vdata_size); | 271 | vdata = vmalloc(vdata_size); |
272 | flags = VMD_VMALLOCED; | ||
273 | } | ||
259 | if (!vdata) | 274 | if (!vdata) |
260 | return -ENOMEM; | 275 | return -ENOMEM; |
261 | memset(vdata, 0, vdata_size); | 276 | memset(vdata, 0, vdata_size); |
262 | 277 | ||
278 | vdata->vm_start = vma->vm_start; | ||
279 | vdata->vm_end = vma->vm_end; | ||
280 | vdata->flags = flags; | ||
263 | vdata->type = type; | 281 | vdata->type = type; |
264 | spin_lock_init(&vdata->lock); | 282 | spin_lock_init(&vdata->lock); |
265 | vdata->refcnt = ATOMIC_INIT(1); | 283 | vdata->refcnt = ATOMIC_INIT(1); |
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index fee58e03dbe2..cc5d77797def 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c | |||
@@ -1629,7 +1629,7 @@ static int cmm_open(struct inode *inode, struct file *filp) | |||
1629 | { | 1629 | { |
1630 | struct cm4000_dev *dev; | 1630 | struct cm4000_dev *dev; |
1631 | struct pcmcia_device *link; | 1631 | struct pcmcia_device *link; |
1632 | int rc, minor = iminor(inode); | 1632 | int minor = iminor(inode); |
1633 | 1633 | ||
1634 | if (minor >= CM4000_MAX_DEV) | 1634 | if (minor >= CM4000_MAX_DEV) |
1635 | return -ENODEV; | 1635 | return -ENODEV; |
@@ -1668,7 +1668,6 @@ static int cmm_open(struct inode *inode, struct file *filp) | |||
1668 | start_monitor(dev); | 1668 | start_monitor(dev); |
1669 | 1669 | ||
1670 | link->open = 1; /* only one open per device */ | 1670 | link->open = 1; /* only one open per device */ |
1671 | rc = 0; | ||
1672 | 1671 | ||
1673 | DEBUGP(2, dev, "<- cmm_open\n"); | 1672 | DEBUGP(2, dev, "<- cmm_open\n"); |
1674 | return nonseekable_open(inode, filp); | 1673 | return nonseekable_open(inode, filp); |
@@ -1824,7 +1823,7 @@ static int cm4000_resume(struct pcmcia_device *link) | |||
1824 | 1823 | ||
1825 | static void cm4000_release(struct pcmcia_device *link) | 1824 | static void cm4000_release(struct pcmcia_device *link) |
1826 | { | 1825 | { |
1827 | cmm_cm4000_release(link->priv); /* delay release until device closed */ | 1826 | cmm_cm4000_release(link); /* delay release until device closed */ |
1828 | pcmcia_disable_device(link); | 1827 | pcmcia_disable_device(link); |
1829 | } | 1828 | } |
1830 | 1829 | ||
@@ -1864,8 +1863,7 @@ static int cm4000_probe(struct pcmcia_device *link) | |||
1864 | return ret; | 1863 | return ret; |
1865 | } | 1864 | } |
1866 | 1865 | ||
1867 | class_device_create(cmm_class, NULL, MKDEV(major, i), NULL, | 1866 | device_create(cmm_class, NULL, MKDEV(major, i), "cmm%d", i); |
1868 | "cmm%d", i); | ||
1869 | 1867 | ||
1870 | return 0; | 1868 | return 0; |
1871 | } | 1869 | } |
@@ -1889,7 +1887,7 @@ static void cm4000_detach(struct pcmcia_device *link) | |||
1889 | dev_table[devno] = NULL; | 1887 | dev_table[devno] = NULL; |
1890 | kfree(dev); | 1888 | kfree(dev); |
1891 | 1889 | ||
1892 | class_device_destroy(cmm_class, MKDEV(major, devno)); | 1890 | device_destroy(cmm_class, MKDEV(major, devno)); |
1893 | 1891 | ||
1894 | return; | 1892 | return; |
1895 | } | 1893 | } |
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index af88181a17f4..a0b9c8728d56 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c | |||
@@ -599,7 +599,7 @@ cs_release: | |||
599 | 599 | ||
600 | static void reader_release(struct pcmcia_device *link) | 600 | static void reader_release(struct pcmcia_device *link) |
601 | { | 601 | { |
602 | cm4040_reader_release(link->priv); | 602 | cm4040_reader_release(link); |
603 | pcmcia_disable_device(link); | 603 | pcmcia_disable_device(link); |
604 | } | 604 | } |
605 | 605 | ||
@@ -642,8 +642,7 @@ static int reader_probe(struct pcmcia_device *link) | |||
642 | return ret; | 642 | return ret; |
643 | } | 643 | } |
644 | 644 | ||
645 | class_device_create(cmx_class, NULL, MKDEV(major, i), NULL, | 645 | device_create(cmx_class, NULL, MKDEV(major, i), "cmx%d", i); |
646 | "cmx%d", i); | ||
647 | 646 | ||
648 | return 0; | 647 | return 0; |
649 | } | 648 | } |
@@ -666,7 +665,7 @@ static void reader_detach(struct pcmcia_device *link) | |||
666 | dev_table[devno] = NULL; | 665 | dev_table[devno] = NULL; |
667 | kfree(dev); | 666 | kfree(dev); |
668 | 667 | ||
669 | class_device_destroy(cmx_class, MKDEV(major, devno)); | 668 | device_destroy(cmx_class, MKDEV(major, devno)); |
670 | 669 | ||
671 | return; | 670 | return; |
672 | } | 671 | } |
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 13808f6083a0..2b889317461e 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
@@ -540,13 +540,12 @@ static int mgslpc_probe(struct pcmcia_device *link) | |||
540 | if (debug_level >= DEBUG_LEVEL_INFO) | 540 | if (debug_level >= DEBUG_LEVEL_INFO) |
541 | printk("mgslpc_attach\n"); | 541 | printk("mgslpc_attach\n"); |
542 | 542 | ||
543 | info = kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL); | 543 | info = kzalloc(sizeof(MGSLPC_INFO), GFP_KERNEL); |
544 | if (!info) { | 544 | if (!info) { |
545 | printk("Error can't allocate device instance data\n"); | 545 | printk("Error can't allocate device instance data\n"); |
546 | return -ENOMEM; | 546 | return -ENOMEM; |
547 | } | 547 | } |
548 | 548 | ||
549 | memset(info, 0, sizeof(MGSLPC_INFO)); | ||
550 | info->magic = MGSLPC_MAGIC; | 549 | info->magic = MGSLPC_MAGIC; |
551 | INIT_WORK(&info->task, bh_handler); | 550 | INIT_WORK(&info->task, bh_handler); |
552 | info->max_frame_size = 4096; | 551 | info->max_frame_size = 4096; |
diff --git a/drivers/char/ps3flash.c b/drivers/char/ps3flash.c new file mode 100644 index 000000000000..79b6f461be75 --- /dev/null +++ b/drivers/char/ps3flash.c | |||
@@ -0,0 +1,440 @@ | |||
1 | /* | ||
2 | * PS3 FLASH ROM Storage Driver | ||
3 | * | ||
4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. | ||
5 | * Copyright 2007 Sony Corp. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published | ||
9 | * by the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/fs.h> | ||
22 | #include <linux/miscdevice.h> | ||
23 | #include <linux/uaccess.h> | ||
24 | |||
25 | #include <asm/lv1call.h> | ||
26 | #include <asm/ps3stor.h> | ||
27 | |||
28 | |||
29 | #define DEVICE_NAME "ps3flash" | ||
30 | |||
31 | #define FLASH_BLOCK_SIZE (256*1024) | ||
32 | |||
33 | |||
34 | struct ps3flash_private { | ||
35 | struct mutex mutex; /* Bounce buffer mutex */ | ||
36 | }; | ||
37 | |||
38 | static struct ps3_storage_device *ps3flash_dev; | ||
39 | |||
40 | static ssize_t ps3flash_read_write_sectors(struct ps3_storage_device *dev, | ||
41 | u64 lpar, u64 start_sector, | ||
42 | u64 sectors, int write) | ||
43 | { | ||
44 | u64 res = ps3stor_read_write_sectors(dev, lpar, start_sector, sectors, | ||
45 | write); | ||
46 | if (res) { | ||
47 | dev_err(&dev->sbd.core, "%s:%u: %s failed 0x%lx\n", __func__, | ||
48 | __LINE__, write ? "write" : "read", res); | ||
49 | return -EIO; | ||
50 | } | ||
51 | return sectors; | ||
52 | } | ||
53 | |||
54 | static ssize_t ps3flash_read_sectors(struct ps3_storage_device *dev, | ||
55 | u64 start_sector, u64 sectors, | ||
56 | unsigned int sector_offset) | ||
57 | { | ||
58 | u64 max_sectors, lpar; | ||
59 | |||
60 | max_sectors = dev->bounce_size / dev->blk_size; | ||
61 | if (sectors > max_sectors) { | ||
62 | dev_dbg(&dev->sbd.core, "%s:%u Limiting sectors to %lu\n", | ||
63 | __func__, __LINE__, max_sectors); | ||
64 | sectors = max_sectors; | ||
65 | } | ||
66 | |||
67 | lpar = dev->bounce_lpar + sector_offset * dev->blk_size; | ||
68 | return ps3flash_read_write_sectors(dev, lpar, start_sector, sectors, | ||
69 | 0); | ||
70 | } | ||
71 | |||
72 | static ssize_t ps3flash_write_chunk(struct ps3_storage_device *dev, | ||
73 | u64 start_sector) | ||
74 | { | ||
75 | u64 sectors = dev->bounce_size / dev->blk_size; | ||
76 | return ps3flash_read_write_sectors(dev, dev->bounce_lpar, start_sector, | ||
77 | sectors, 1); | ||
78 | } | ||
79 | |||
80 | static loff_t ps3flash_llseek(struct file *file, loff_t offset, int origin) | ||
81 | { | ||
82 | struct ps3_storage_device *dev = ps3flash_dev; | ||
83 | loff_t res; | ||
84 | |||
85 | mutex_lock(&file->f_mapping->host->i_mutex); | ||
86 | switch (origin) { | ||
87 | case 1: | ||
88 | offset += file->f_pos; | ||
89 | break; | ||
90 | case 2: | ||
91 | offset += dev->regions[dev->region_idx].size*dev->blk_size; | ||
92 | break; | ||
93 | } | ||
94 | if (offset < 0) { | ||
95 | res = -EINVAL; | ||
96 | goto out; | ||
97 | } | ||
98 | |||
99 | file->f_pos = offset; | ||
100 | res = file->f_pos; | ||
101 | |||
102 | out: | ||
103 | mutex_unlock(&file->f_mapping->host->i_mutex); | ||
104 | return res; | ||
105 | } | ||
106 | |||
107 | static ssize_t ps3flash_read(struct file *file, char __user *buf, size_t count, | ||
108 | loff_t *pos) | ||
109 | { | ||
110 | struct ps3_storage_device *dev = ps3flash_dev; | ||
111 | struct ps3flash_private *priv = dev->sbd.core.driver_data; | ||
112 | u64 size, start_sector, end_sector, offset; | ||
113 | ssize_t sectors_read; | ||
114 | size_t remaining, n; | ||
115 | |||
116 | dev_dbg(&dev->sbd.core, | ||
117 | "%s:%u: Reading %zu bytes at position %lld to user 0x%p\n", | ||
118 | __func__, __LINE__, count, *pos, buf); | ||
119 | |||
120 | size = dev->regions[dev->region_idx].size*dev->blk_size; | ||
121 | if (*pos >= size || !count) | ||
122 | return 0; | ||
123 | |||
124 | if (*pos + count > size) { | ||
125 | dev_dbg(&dev->sbd.core, | ||
126 | "%s:%u Truncating count from %zu to %llu\n", __func__, | ||
127 | __LINE__, count, size - *pos); | ||
128 | count = size - *pos; | ||
129 | } | ||
130 | |||
131 | start_sector = *pos / dev->blk_size; | ||
132 | offset = *pos % dev->blk_size; | ||
133 | end_sector = DIV_ROUND_UP(*pos + count, dev->blk_size); | ||
134 | |||
135 | remaining = count; | ||
136 | do { | ||
137 | mutex_lock(&priv->mutex); | ||
138 | |||
139 | sectors_read = ps3flash_read_sectors(dev, start_sector, | ||
140 | end_sector-start_sector, | ||
141 | 0); | ||
142 | if (sectors_read < 0) { | ||
143 | mutex_unlock(&priv->mutex); | ||
144 | goto fail; | ||
145 | } | ||
146 | |||
147 | n = min(remaining, sectors_read*dev->blk_size-offset); | ||
148 | dev_dbg(&dev->sbd.core, | ||
149 | "%s:%u: copy %lu bytes from 0x%p to user 0x%p\n", | ||
150 | __func__, __LINE__, n, dev->bounce_buf+offset, buf); | ||
151 | if (copy_to_user(buf, dev->bounce_buf+offset, n)) { | ||
152 | mutex_unlock(&priv->mutex); | ||
153 | sectors_read = -EFAULT; | ||
154 | goto fail; | ||
155 | } | ||
156 | |||
157 | mutex_unlock(&priv->mutex); | ||
158 | |||
159 | *pos += n; | ||
160 | buf += n; | ||
161 | remaining -= n; | ||
162 | start_sector += sectors_read; | ||
163 | offset = 0; | ||
164 | } while (remaining > 0); | ||
165 | |||
166 | return count; | ||
167 | |||
168 | fail: | ||
169 | return sectors_read; | ||
170 | } | ||
171 | |||
172 | static ssize_t ps3flash_write(struct file *file, const char __user *buf, | ||
173 | size_t count, loff_t *pos) | ||
174 | { | ||
175 | struct ps3_storage_device *dev = ps3flash_dev; | ||
176 | struct ps3flash_private *priv = dev->sbd.core.driver_data; | ||
177 | u64 size, chunk_sectors, start_write_sector, end_write_sector, | ||
178 | end_read_sector, start_read_sector, head, tail, offset; | ||
179 | ssize_t res; | ||
180 | size_t remaining, n; | ||
181 | unsigned int sec_off; | ||
182 | |||
183 | dev_dbg(&dev->sbd.core, | ||
184 | "%s:%u: Writing %zu bytes at position %lld from user 0x%p\n", | ||
185 | __func__, __LINE__, count, *pos, buf); | ||
186 | |||
187 | size = dev->regions[dev->region_idx].size*dev->blk_size; | ||
188 | if (*pos >= size || !count) | ||
189 | return 0; | ||
190 | |||
191 | if (*pos + count > size) { | ||
192 | dev_dbg(&dev->sbd.core, | ||
193 | "%s:%u Truncating count from %zu to %llu\n", __func__, | ||
194 | __LINE__, count, size - *pos); | ||
195 | count = size - *pos; | ||
196 | } | ||
197 | |||
198 | chunk_sectors = dev->bounce_size / dev->blk_size; | ||
199 | |||
200 | start_write_sector = *pos / dev->bounce_size * chunk_sectors; | ||
201 | offset = *pos % dev->bounce_size; | ||
202 | end_write_sector = DIV_ROUND_UP(*pos + count, dev->bounce_size) * | ||
203 | chunk_sectors; | ||
204 | |||
205 | end_read_sector = DIV_ROUND_UP(*pos, dev->blk_size); | ||
206 | start_read_sector = (*pos + count) / dev->blk_size; | ||
207 | |||
208 | /* | ||
209 | * As we have to write in 256 KiB chunks, while we can read in blk_size | ||
210 | * (usually 512 bytes) chunks, we perform the following steps: | ||
211 | * 1. Read from start_write_sector to end_read_sector ("head") | ||
212 | * 2. Read from start_read_sector to end_write_sector ("tail") | ||
213 | * 3. Copy data to buffer | ||
214 | * 4. Write from start_write_sector to end_write_sector | ||
215 | * All of this is complicated by using only one 256 KiB bounce buffer. | ||
216 | */ | ||
217 | |||
218 | head = end_read_sector - start_write_sector; | ||
219 | tail = end_write_sector - start_read_sector; | ||
220 | |||
221 | remaining = count; | ||
222 | do { | ||
223 | mutex_lock(&priv->mutex); | ||
224 | |||
225 | if (end_read_sector >= start_read_sector) { | ||
226 | /* Merge head and tail */ | ||
227 | dev_dbg(&dev->sbd.core, | ||
228 | "Merged head and tail: %lu sectors at %lu\n", | ||
229 | chunk_sectors, start_write_sector); | ||
230 | res = ps3flash_read_sectors(dev, start_write_sector, | ||
231 | chunk_sectors, 0); | ||
232 | if (res < 0) | ||
233 | goto fail; | ||
234 | } else { | ||
235 | if (head) { | ||
236 | /* Read head */ | ||
237 | dev_dbg(&dev->sbd.core, | ||
238 | "head: %lu sectors at %lu\n", head, | ||
239 | start_write_sector); | ||
240 | res = ps3flash_read_sectors(dev, | ||
241 | start_write_sector, | ||
242 | head, 0); | ||
243 | if (res < 0) | ||
244 | goto fail; | ||
245 | } | ||
246 | if (start_read_sector < | ||
247 | start_write_sector+chunk_sectors) { | ||
248 | /* Read tail */ | ||
249 | dev_dbg(&dev->sbd.core, | ||
250 | "tail: %lu sectors at %lu\n", tail, | ||
251 | start_read_sector); | ||
252 | sec_off = start_read_sector-start_write_sector; | ||
253 | res = ps3flash_read_sectors(dev, | ||
254 | start_read_sector, | ||
255 | tail, sec_off); | ||
256 | if (res < 0) | ||
257 | goto fail; | ||
258 | } | ||
259 | } | ||
260 | |||
261 | n = min(remaining, dev->bounce_size-offset); | ||
262 | dev_dbg(&dev->sbd.core, | ||
263 | "%s:%u: copy %lu bytes from user 0x%p to 0x%p\n", | ||
264 | __func__, __LINE__, n, buf, dev->bounce_buf+offset); | ||
265 | if (copy_from_user(dev->bounce_buf+offset, buf, n)) { | ||
266 | res = -EFAULT; | ||
267 | goto fail; | ||
268 | } | ||
269 | |||
270 | res = ps3flash_write_chunk(dev, start_write_sector); | ||
271 | if (res < 0) | ||
272 | goto fail; | ||
273 | |||
274 | mutex_unlock(&priv->mutex); | ||
275 | |||
276 | *pos += n; | ||
277 | buf += n; | ||
278 | remaining -= n; | ||
279 | start_write_sector += chunk_sectors; | ||
280 | head = 0; | ||
281 | offset = 0; | ||
282 | } while (remaining > 0); | ||
283 | |||
284 | return count; | ||
285 | |||
286 | fail: | ||
287 | mutex_unlock(&priv->mutex); | ||
288 | return res; | ||
289 | } | ||
290 | |||
291 | |||
292 | static irqreturn_t ps3flash_interrupt(int irq, void *data) | ||
293 | { | ||
294 | struct ps3_storage_device *dev = data; | ||
295 | int res; | ||
296 | u64 tag, status; | ||
297 | |||
298 | res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status); | ||
299 | |||
300 | if (tag != dev->tag) | ||
301 | dev_err(&dev->sbd.core, | ||
302 | "%s:%u: tag mismatch, got %lx, expected %lx\n", | ||
303 | __func__, __LINE__, tag, dev->tag); | ||
304 | |||
305 | if (res) { | ||
306 | dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%lx\n", | ||
307 | __func__, __LINE__, res, status); | ||
308 | } else { | ||
309 | dev->lv1_status = status; | ||
310 | complete(&dev->done); | ||
311 | } | ||
312 | return IRQ_HANDLED; | ||
313 | } | ||
314 | |||
315 | |||
316 | static const struct file_operations ps3flash_fops = { | ||
317 | .owner = THIS_MODULE, | ||
318 | .llseek = ps3flash_llseek, | ||
319 | .read = ps3flash_read, | ||
320 | .write = ps3flash_write, | ||
321 | }; | ||
322 | |||
323 | static struct miscdevice ps3flash_misc = { | ||
324 | .minor = MISC_DYNAMIC_MINOR, | ||
325 | .name = DEVICE_NAME, | ||
326 | .fops = &ps3flash_fops, | ||
327 | }; | ||
328 | |||
329 | static int __devinit ps3flash_probe(struct ps3_system_bus_device *_dev) | ||
330 | { | ||
331 | struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core); | ||
332 | struct ps3flash_private *priv; | ||
333 | int error; | ||
334 | unsigned long tmp; | ||
335 | |||
336 | tmp = dev->regions[dev->region_idx].start*dev->blk_size; | ||
337 | if (tmp % FLASH_BLOCK_SIZE) { | ||
338 | dev_err(&dev->sbd.core, | ||
339 | "%s:%u region start %lu is not aligned\n", __func__, | ||
340 | __LINE__, tmp); | ||
341 | return -EINVAL; | ||
342 | } | ||
343 | tmp = dev->regions[dev->region_idx].size*dev->blk_size; | ||
344 | if (tmp % FLASH_BLOCK_SIZE) { | ||
345 | dev_err(&dev->sbd.core, | ||
346 | "%s:%u region size %lu is not aligned\n", __func__, | ||
347 | __LINE__, tmp); | ||
348 | return -EINVAL; | ||
349 | } | ||
350 | |||
351 | /* use static buffer, kmalloc cannot allocate 256 KiB */ | ||
352 | if (!ps3flash_bounce_buffer.address) | ||
353 | return -ENODEV; | ||
354 | |||
355 | if (ps3flash_dev) { | ||
356 | dev_err(&dev->sbd.core, | ||
357 | "Only one FLASH device is supported\n"); | ||
358 | return -EBUSY; | ||
359 | } | ||
360 | |||
361 | ps3flash_dev = dev; | ||
362 | |||
363 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
364 | if (!priv) { | ||
365 | error = -ENOMEM; | ||
366 | goto fail; | ||
367 | } | ||
368 | |||
369 | dev->sbd.core.driver_data = priv; | ||
370 | mutex_init(&priv->mutex); | ||
371 | |||
372 | dev->bounce_size = ps3flash_bounce_buffer.size; | ||
373 | dev->bounce_buf = ps3flash_bounce_buffer.address; | ||
374 | |||
375 | error = ps3stor_setup(dev, ps3flash_interrupt); | ||
376 | if (error) | ||
377 | goto fail_free_priv; | ||
378 | |||
379 | ps3flash_misc.parent = &dev->sbd.core; | ||
380 | error = misc_register(&ps3flash_misc); | ||
381 | if (error) { | ||
382 | dev_err(&dev->sbd.core, "%s:%u: misc_register failed %d\n", | ||
383 | __func__, __LINE__, error); | ||
384 | goto fail_teardown; | ||
385 | } | ||
386 | |||
387 | dev_info(&dev->sbd.core, "%s:%u: registered misc device %d\n", | ||
388 | __func__, __LINE__, ps3flash_misc.minor); | ||
389 | return 0; | ||
390 | |||
391 | fail_teardown: | ||
392 | ps3stor_teardown(dev); | ||
393 | fail_free_priv: | ||
394 | kfree(priv); | ||
395 | dev->sbd.core.driver_data = NULL; | ||
396 | fail: | ||
397 | ps3flash_dev = NULL; | ||
398 | return error; | ||
399 | } | ||
400 | |||
401 | static int ps3flash_remove(struct ps3_system_bus_device *_dev) | ||
402 | { | ||
403 | struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core); | ||
404 | |||
405 | misc_deregister(&ps3flash_misc); | ||
406 | ps3stor_teardown(dev); | ||
407 | kfree(dev->sbd.core.driver_data); | ||
408 | dev->sbd.core.driver_data = NULL; | ||
409 | ps3flash_dev = NULL; | ||
410 | return 0; | ||
411 | } | ||
412 | |||
413 | |||
414 | static struct ps3_system_bus_driver ps3flash = { | ||
415 | .match_id = PS3_MATCH_ID_STOR_FLASH, | ||
416 | .core.name = DEVICE_NAME, | ||
417 | .core.owner = THIS_MODULE, | ||
418 | .probe = ps3flash_probe, | ||
419 | .remove = ps3flash_remove, | ||
420 | .shutdown = ps3flash_remove, | ||
421 | }; | ||
422 | |||
423 | |||
424 | static int __init ps3flash_init(void) | ||
425 | { | ||
426 | return ps3_system_bus_driver_register(&ps3flash); | ||
427 | } | ||
428 | |||
429 | static void __exit ps3flash_exit(void) | ||
430 | { | ||
431 | ps3_system_bus_driver_unregister(&ps3flash); | ||
432 | } | ||
433 | |||
434 | module_init(ps3flash_init); | ||
435 | module_exit(ps3flash_exit); | ||
436 | |||
437 | MODULE_LICENSE("GPL"); | ||
438 | MODULE_DESCRIPTION("PS3 FLASH ROM Storage Driver"); | ||
439 | MODULE_AUTHOR("Sony Corporation"); | ||
440 | MODULE_ALIAS(PS3_MODULE_ALIAS_STOR_FLASH); | ||
diff --git a/drivers/char/pty.c b/drivers/char/pty.c index de14aea34e11..73de77105fea 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c | |||
@@ -248,14 +248,19 @@ static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file, | |||
248 | return -ENOIOCTLCMD; | 248 | return -ENOIOCTLCMD; |
249 | } | 249 | } |
250 | 250 | ||
251 | static int legacy_count = CONFIG_LEGACY_PTY_COUNT; | ||
252 | module_param(legacy_count, int, 0); | ||
253 | |||
251 | static void __init legacy_pty_init(void) | 254 | static void __init legacy_pty_init(void) |
252 | { | 255 | { |
256 | if (legacy_count <= 0) | ||
257 | return; | ||
253 | 258 | ||
254 | pty_driver = alloc_tty_driver(NR_PTYS); | 259 | pty_driver = alloc_tty_driver(legacy_count); |
255 | if (!pty_driver) | 260 | if (!pty_driver) |
256 | panic("Couldn't allocate pty driver"); | 261 | panic("Couldn't allocate pty driver"); |
257 | 262 | ||
258 | pty_slave_driver = alloc_tty_driver(NR_PTYS); | 263 | pty_slave_driver = alloc_tty_driver(legacy_count); |
259 | if (!pty_slave_driver) | 264 | if (!pty_slave_driver) |
260 | panic("Couldn't allocate pty slave driver"); | 265 | panic("Couldn't allocate pty slave driver"); |
261 | 266 | ||
diff --git a/drivers/char/random.c b/drivers/char/random.c index 7f5271272f91..af274e5a25ee 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -693,9 +693,14 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes) | |||
693 | 693 | ||
694 | if (r->pull && r->entropy_count < nbytes * 8 && | 694 | if (r->pull && r->entropy_count < nbytes * 8 && |
695 | r->entropy_count < r->poolinfo->POOLBITS) { | 695 | r->entropy_count < r->poolinfo->POOLBITS) { |
696 | int bytes = max_t(int, random_read_wakeup_thresh / 8, | 696 | /* If we're limited, always leave two wakeup worth's BITS */ |
697 | min_t(int, nbytes, sizeof(tmp))); | ||
698 | int rsvd = r->limit ? 0 : random_read_wakeup_thresh/4; | 697 | int rsvd = r->limit ? 0 : random_read_wakeup_thresh/4; |
698 | int bytes = nbytes; | ||
699 | |||
700 | /* pull at least as many as BYTES as wakeup BITS */ | ||
701 | bytes = max_t(int, bytes, random_read_wakeup_thresh / 8); | ||
702 | /* but never more than the buffer size */ | ||
703 | bytes = min_t(int, bytes, sizeof(tmp)); | ||
699 | 704 | ||
700 | DEBUG_ENT("going to reseed %s with %d bits " | 705 | DEBUG_ENT("going to reseed %s with %d bits " |
701 | "(%d of %d requested)\n", | 706 | "(%d of %d requested)\n", |
@@ -1545,11 +1550,13 @@ __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr, | |||
1545 | * As close as possible to RFC 793, which | 1550 | * As close as possible to RFC 793, which |
1546 | * suggests using a 250 kHz clock. | 1551 | * suggests using a 250 kHz clock. |
1547 | * Further reading shows this assumes 2 Mb/s networks. | 1552 | * Further reading shows this assumes 2 Mb/s networks. |
1548 | * For 10 Gb/s Ethernet, a 1 GHz clock is appropriate. | 1553 | * For 10 Mb/s Ethernet, a 1 MHz clock is appropriate. |
1549 | * That's funny, Linux has one built in! Use it! | 1554 | * For 10 Gb/s Ethernet, a 1 GHz clock should be ok, but |
1550 | * (Networks are faster now - should this be increased?) | 1555 | * we also need to limit the resolution so that the u32 seq |
1556 | * overlaps less than one time per MSL (2 minutes). | ||
1557 | * Choosing a clock of 64 ns period is OK. (period of 274 s) | ||
1551 | */ | 1558 | */ |
1552 | seq += ktime_get_real().tv64; | 1559 | seq += ktime_get_real().tv64 >> 6; |
1553 | #if 0 | 1560 | #if 0 |
1554 | printk("init_seq(%lx, %lx, %d, %d) = %d\n", | 1561 | printk("init_seq(%lx, %lx, %d, %d) = %d\n", |
1555 | saddr, daddr, sport, dport, seq); | 1562 | saddr, daddr, sport, dport, seq); |
diff --git a/drivers/char/raw.c b/drivers/char/raw.c index 1f0d7c60c944..bbfa0e241cba 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c | |||
@@ -255,10 +255,7 @@ static const struct file_operations raw_ctl_fops = { | |||
255 | .owner = THIS_MODULE, | 255 | .owner = THIS_MODULE, |
256 | }; | 256 | }; |
257 | 257 | ||
258 | static struct cdev raw_cdev = { | 258 | static struct cdev raw_cdev; |
259 | .kobj = {.name = "raw", }, | ||
260 | .owner = THIS_MODULE, | ||
261 | }; | ||
262 | 259 | ||
263 | static int __init raw_init(void) | 260 | static int __init raw_init(void) |
264 | { | 261 | { |
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c index 294e9cb0c449..0ce96670f979 100644 --- a/drivers/char/rio/rio_linux.c +++ b/drivers/char/rio/rio_linux.c | |||
@@ -803,9 +803,7 @@ static void *ckmalloc(int size) | |||
803 | { | 803 | { |
804 | void *p; | 804 | void *p; |
805 | 805 | ||
806 | p = kmalloc(size, GFP_KERNEL); | 806 | p = kzalloc(size, GFP_KERNEL); |
807 | if (p) | ||
808 | memset(p, 0, size); | ||
809 | return p; | 807 | return p; |
810 | } | 808 | } |
811 | 809 | ||
diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c index 8cc60b693460..7321d002c34f 100644 --- a/drivers/char/rio/riocmd.c +++ b/drivers/char/rio/riocmd.c | |||
@@ -556,9 +556,7 @@ struct CmdBlk *RIOGetCmdBlk(void) | |||
556 | { | 556 | { |
557 | struct CmdBlk *CmdBlkP; | 557 | struct CmdBlk *CmdBlkP; |
558 | 558 | ||
559 | CmdBlkP = kmalloc(sizeof(struct CmdBlk), GFP_ATOMIC); | 559 | CmdBlkP = kzalloc(sizeof(struct CmdBlk), GFP_ATOMIC); |
560 | if (CmdBlkP) | ||
561 | memset(CmdBlkP, 0, sizeof(struct CmdBlk)); | ||
562 | return CmdBlkP; | 560 | return CmdBlkP; |
563 | } | 561 | } |
564 | 562 | ||
diff --git a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c index 7e988357326e..991119c9f473 100644 --- a/drivers/char/rio/riotable.c +++ b/drivers/char/rio/riotable.c | |||
@@ -863,8 +863,7 @@ int RIOReMapPorts(struct rio_info *p, struct Host *HostP, struct Map *HostMapP) | |||
863 | if (PortP->TxRingBuffer) | 863 | if (PortP->TxRingBuffer) |
864 | memset(PortP->TxRingBuffer, 0, p->RIOBufferSize); | 864 | memset(PortP->TxRingBuffer, 0, p->RIOBufferSize); |
865 | else if (p->RIOBufferSize) { | 865 | else if (p->RIOBufferSize) { |
866 | PortP->TxRingBuffer = kmalloc(p->RIOBufferSize, GFP_KERNEL); | 866 | PortP->TxRingBuffer = kzalloc(p->RIOBufferSize, GFP_KERNEL); |
867 | memset(PortP->TxRingBuffer, 0, p->RIOBufferSize); | ||
868 | } | 867 | } |
869 | PortP->TxBufferOut = 0; | 868 | PortP->TxBufferOut = 0; |
870 | PortP->TxBufferIn = 0; | 869 | PortP->TxBufferIn = 0; |
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 0270080ff0c0..56cbba7b6ec0 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c | |||
@@ -635,12 +635,11 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev) | |||
635 | ctlp = sCtlNumToCtlPtr(board); | 635 | ctlp = sCtlNumToCtlPtr(board); |
636 | 636 | ||
637 | /* Get a r_port struct for the port, fill it in and save it globally, indexed by line number */ | 637 | /* Get a r_port struct for the port, fill it in and save it globally, indexed by line number */ |
638 | info = kmalloc(sizeof (struct r_port), GFP_KERNEL); | 638 | info = kzalloc(sizeof (struct r_port), GFP_KERNEL); |
639 | if (!info) { | 639 | if (!info) { |
640 | printk(KERN_INFO "Couldn't allocate info struct for line #%d\n", line); | 640 | printk(KERN_INFO "Couldn't allocate info struct for line #%d\n", line); |
641 | return; | 641 | return; |
642 | } | 642 | } |
643 | memset(info, 0, sizeof (struct r_port)); | ||
644 | 643 | ||
645 | info->magic = RPORT_MAGIC; | 644 | info->magic = RPORT_MAGIC; |
646 | info->line = line; | 645 | info->line = line; |
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 22cf7aa56cc4..ec6b65ec69ea 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c | |||
@@ -82,16 +82,13 @@ | |||
82 | #include <asm/uaccess.h> | 82 | #include <asm/uaccess.h> |
83 | #include <asm/system.h> | 83 | #include <asm/system.h> |
84 | 84 | ||
85 | #if defined(__i386__) | 85 | #ifdef CONFIG_X86 |
86 | #include <asm/hpet.h> | 86 | #include <asm/hpet.h> |
87 | #endif | 87 | #endif |
88 | 88 | ||
89 | #ifdef __sparc__ | 89 | #ifdef CONFIG_SPARC32 |
90 | #include <linux/pci.h> | 90 | #include <linux/pci.h> |
91 | #include <asm/ebus.h> | 91 | #include <asm/ebus.h> |
92 | #ifdef __sparc_v9__ | ||
93 | #include <asm/isa.h> | ||
94 | #endif | ||
95 | 92 | ||
96 | static unsigned long rtc_port; | 93 | static unsigned long rtc_port; |
97 | static int rtc_irq = PCI_IRQ_NONE; | 94 | static int rtc_irq = PCI_IRQ_NONE; |
@@ -930,13 +927,9 @@ static int __init rtc_init(void) | |||
930 | unsigned int year, ctrl; | 927 | unsigned int year, ctrl; |
931 | char *guess = NULL; | 928 | char *guess = NULL; |
932 | #endif | 929 | #endif |
933 | #ifdef __sparc__ | 930 | #ifdef CONFIG_SPARC32 |
934 | struct linux_ebus *ebus; | 931 | struct linux_ebus *ebus; |
935 | struct linux_ebus_device *edev; | 932 | struct linux_ebus_device *edev; |
936 | #ifdef __sparc_v9__ | ||
937 | struct sparc_isa_bridge *isa_br; | ||
938 | struct sparc_isa_device *isa_dev; | ||
939 | #endif | ||
940 | #else | 933 | #else |
941 | void *r; | 934 | void *r; |
942 | #ifdef RTC_IRQ | 935 | #ifdef RTC_IRQ |
@@ -944,7 +937,7 @@ static int __init rtc_init(void) | |||
944 | #endif | 937 | #endif |
945 | #endif | 938 | #endif |
946 | 939 | ||
947 | #ifdef __sparc__ | 940 | #ifdef CONFIG_SPARC32 |
948 | for_each_ebus(ebus) { | 941 | for_each_ebus(ebus) { |
949 | for_each_ebusdev(edev, ebus) { | 942 | for_each_ebusdev(edev, ebus) { |
950 | if(strcmp(edev->prom_node->name, "rtc") == 0) { | 943 | if(strcmp(edev->prom_node->name, "rtc") == 0) { |
@@ -954,17 +947,6 @@ static int __init rtc_init(void) | |||
954 | } | 947 | } |
955 | } | 948 | } |
956 | } | 949 | } |
957 | #ifdef __sparc_v9__ | ||
958 | for_each_isa(isa_br) { | ||
959 | for_each_isadev(isa_dev, isa_br) { | ||
960 | if (strcmp(isa_dev->prom_node->name, "rtc") == 0) { | ||
961 | rtc_port = isa_dev->resource.start; | ||
962 | rtc_irq = isa_dev->irq; | ||
963 | goto found; | ||
964 | } | ||
965 | } | ||
966 | } | ||
967 | #endif | ||
968 | rtc_has_irq = 0; | 950 | rtc_has_irq = 0; |
969 | printk(KERN_ERR "rtc_init: no PC rtc found\n"); | 951 | printk(KERN_ERR "rtc_init: no PC rtc found\n"); |
970 | return -EIO; | 952 | return -EIO; |
@@ -1020,7 +1002,7 @@ no_irq: | |||
1020 | 1002 | ||
1021 | #endif | 1003 | #endif |
1022 | 1004 | ||
1023 | #endif /* __sparc__ vs. others */ | 1005 | #endif /* CONFIG_SPARC32 vs. others */ |
1024 | 1006 | ||
1025 | if (misc_register(&rtc_dev)) { | 1007 | if (misc_register(&rtc_dev)) { |
1026 | #ifdef RTC_IRQ | 1008 | #ifdef RTC_IRQ |
@@ -1105,7 +1087,7 @@ static void __exit rtc_exit (void) | |||
1105 | remove_proc_entry ("driver/rtc", NULL); | 1087 | remove_proc_entry ("driver/rtc", NULL); |
1106 | misc_deregister(&rtc_dev); | 1088 | misc_deregister(&rtc_dev); |
1107 | 1089 | ||
1108 | #ifdef __sparc__ | 1090 | #ifdef CONFIG_SPARC32 |
1109 | if (rtc_has_irq) | 1091 | if (rtc_has_irq) |
1110 | free_irq (rtc_irq, &rtc_port); | 1092 | free_irq (rtc_irq, &rtc_port); |
1111 | #else | 1093 | #else |
@@ -1117,7 +1099,7 @@ static void __exit rtc_exit (void) | |||
1117 | if (rtc_has_irq) | 1099 | if (rtc_has_irq) |
1118 | free_irq (RTC_IRQ, NULL); | 1100 | free_irq (RTC_IRQ, NULL); |
1119 | #endif | 1101 | #endif |
1120 | #endif /* __sparc__ */ | 1102 | #endif /* CONFIG_SPARC32 */ |
1121 | } | 1103 | } |
1122 | 1104 | ||
1123 | module_init(rtc_init); | 1105 | module_init(rtc_init); |
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index c585b4738f86..f1497cecffd8 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c | |||
@@ -2573,16 +2573,10 @@ static struct tty_driver *serial167_console_device(struct console *c, | |||
2573 | return cy_serial_driver; | 2573 | return cy_serial_driver; |
2574 | } | 2574 | } |
2575 | 2575 | ||
2576 | static int __init serial167_console_setup(struct console *co, char *options) | ||
2577 | { | ||
2578 | return 0; | ||
2579 | } | ||
2580 | |||
2581 | static struct console sercons = { | 2576 | static struct console sercons = { |
2582 | .name = "ttyS", | 2577 | .name = "ttyS", |
2583 | .write = serial167_console_write, | 2578 | .write = serial167_console_write, |
2584 | .device = serial167_console_device, | 2579 | .device = serial167_console_device, |
2585 | .setup = serial167_console_setup, | ||
2586 | .flags = CON_PRINTBUFFER, | 2580 | .flags = CON_PRINTBUFFER, |
2587 | .index = -1, | 2581 | .index = -1, |
2588 | }; | 2582 | }; |
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c index 52753e723eaa..b9c1dba6bd01 100644 --- a/drivers/char/snsc.c +++ b/drivers/char/snsc.c | |||
@@ -441,8 +441,7 @@ scdrv_init(void) | |||
441 | continue; | 441 | continue; |
442 | } | 442 | } |
443 | 443 | ||
444 | class_device_create(snsc_class, NULL, dev, NULL, | 444 | device_create(snsc_class, NULL, dev, "%s", devname); |
445 | "%s", devname); | ||
446 | 445 | ||
447 | ia64_sn_irtr_intr_enable(scd->scd_nasid, | 446 | ia64_sn_irtr_intr_enable(scd->scd_nasid, |
448 | 0 /*ignored */ , | 447 | 0 /*ignored */ , |
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 73037a4d3c50..859858561ab6 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c | |||
@@ -875,7 +875,7 @@ found: | |||
875 | 875 | ||
876 | #ifdef CONFIG_ACPI | 876 | #ifdef CONFIG_ACPI |
877 | if (sonypi_acpi_device) | 877 | if (sonypi_acpi_device) |
878 | acpi_bus_generate_event(sonypi_acpi_device, 1, event); | 878 | acpi_bus_generate_proc_event(sonypi_acpi_device, 1, event); |
879 | #endif | 879 | #endif |
880 | 880 | ||
881 | kfifo_put(sonypi_device.fifo, (unsigned char *)&event, sizeof(event)); | 881 | kfifo_put(sonypi_device.fifo, (unsigned char *)&event, sizeof(event)); |
@@ -1147,10 +1147,15 @@ static int sonypi_acpi_remove(struct acpi_device *device, int type) | |||
1147 | return 0; | 1147 | return 0; |
1148 | } | 1148 | } |
1149 | 1149 | ||
1150 | const static struct acpi_device_id sonypi_device_ids[] = { | ||
1151 | {"SNY6001", 0}, | ||
1152 | {"", 0}, | ||
1153 | }; | ||
1154 | |||
1150 | static struct acpi_driver sonypi_acpi_driver = { | 1155 | static struct acpi_driver sonypi_acpi_driver = { |
1151 | .name = "sonypi", | 1156 | .name = "sonypi", |
1152 | .class = "hkey", | 1157 | .class = "hkey", |
1153 | .ids = "SNY6001", | 1158 | .ids = sonypi_device_ids, |
1154 | .ops = { | 1159 | .ops = { |
1155 | .add = sonypi_acpi_add, | 1160 | .add = sonypi_acpi_add, |
1156 | .remove = sonypi_acpi_remove, | 1161 | .remove = sonypi_acpi_remove, |
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 93d0bb8b4c0f..45758d5b56ef 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c | |||
@@ -4778,9 +4778,8 @@ static int __init stallion_module_init(void) | |||
4778 | if (IS_ERR(stallion_class)) | 4778 | if (IS_ERR(stallion_class)) |
4779 | printk("STALLION: failed to create class\n"); | 4779 | printk("STALLION: failed to create class\n"); |
4780 | for (i = 0; i < 4; i++) | 4780 | for (i = 0; i < 4; i++) |
4781 | class_device_create(stallion_class, NULL, | 4781 | device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i), |
4782 | MKDEV(STL_SIOMEMMAJOR, i), NULL, | 4782 | "staliomem%d", i); |
4783 | "staliomem%d", i); | ||
4784 | 4783 | ||
4785 | return 0; | 4784 | return 0; |
4786 | err_unrtty: | 4785 | err_unrtty: |
@@ -4795,7 +4794,6 @@ static void __exit stallion_module_exit(void) | |||
4795 | { | 4794 | { |
4796 | struct stlbrd *brdp; | 4795 | struct stlbrd *brdp; |
4797 | unsigned int i, j; | 4796 | unsigned int i, j; |
4798 | int retval; | ||
4799 | 4797 | ||
4800 | pr_debug("cleanup_module()\n"); | 4798 | pr_debug("cleanup_module()\n"); |
4801 | 4799 | ||
@@ -4817,10 +4815,8 @@ static void __exit stallion_module_exit(void) | |||
4817 | } | 4815 | } |
4818 | 4816 | ||
4819 | for (i = 0; i < 4; i++) | 4817 | for (i = 0; i < 4; i++) |
4820 | class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i)); | 4818 | device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i)); |
4821 | if ((retval = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"))) | 4819 | unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"); |
4822 | printk("STALLION: failed to un-register serial memory device, " | ||
4823 | "errno=%d\n", -retval); | ||
4824 | class_destroy(stallion_class); | 4820 | class_destroy(stallion_class); |
4825 | 4821 | ||
4826 | pci_unregister_driver(&stl_pcidriver); | 4822 | pci_unregister_driver(&stl_pcidriver); |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index f53e51ddb9d7..fdc256b380b8 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
@@ -4324,13 +4324,12 @@ static struct mgsl_struct* mgsl_allocate_device(void) | |||
4324 | { | 4324 | { |
4325 | struct mgsl_struct *info; | 4325 | struct mgsl_struct *info; |
4326 | 4326 | ||
4327 | info = kmalloc(sizeof(struct mgsl_struct), | 4327 | info = kzalloc(sizeof(struct mgsl_struct), |
4328 | GFP_KERNEL); | 4328 | GFP_KERNEL); |
4329 | 4329 | ||
4330 | if (!info) { | 4330 | if (!info) { |
4331 | printk("Error can't allocate device instance data\n"); | 4331 | printk("Error can't allocate device instance data\n"); |
4332 | } else { | 4332 | } else { |
4333 | memset(info, 0, sizeof(struct mgsl_struct)); | ||
4334 | info->magic = MGSL_MAGIC; | 4333 | info->magic = MGSL_MAGIC; |
4335 | INIT_WORK(&info->task, mgsl_bh_handler); | 4334 | INIT_WORK(&info->task, mgsl_bh_handler); |
4336 | info->max_frame_size = 4096; | 4335 | info->max_frame_size = 4096; |
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 428b514201f4..2f97d2f8f916 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.36 2006/08/28 20:47:14 paulkf Exp $ | 2 | * $Id: synclink_gt.c,v 4.50 2007/07/25 19:29:25 paulkf Exp $ |
3 | * | 3 | * |
4 | * Device driver for Microgate SyncLink GT serial adapters. | 4 | * Device driver for Microgate SyncLink GT serial adapters. |
5 | * | 5 | * |
@@ -93,7 +93,7 @@ | |||
93 | * module identification | 93 | * module identification |
94 | */ | 94 | */ |
95 | static char *driver_name = "SyncLink GT"; | 95 | static char *driver_name = "SyncLink GT"; |
96 | static char *driver_version = "$Revision: 4.36 $"; | 96 | static char *driver_version = "$Revision: 4.50 $"; |
97 | static char *tty_driver_name = "synclink_gt"; | 97 | static char *tty_driver_name = "synclink_gt"; |
98 | static char *tty_dev_prefix = "ttySLG"; | 98 | static char *tty_dev_prefix = "ttySLG"; |
99 | MODULE_LICENSE("GPL"); | 99 | MODULE_LICENSE("GPL"); |
@@ -477,6 +477,7 @@ static void tx_set_idle(struct slgt_info *info); | |||
477 | static unsigned int free_tbuf_count(struct slgt_info *info); | 477 | static unsigned int free_tbuf_count(struct slgt_info *info); |
478 | static void reset_tbufs(struct slgt_info *info); | 478 | static void reset_tbufs(struct slgt_info *info); |
479 | static void tdma_reset(struct slgt_info *info); | 479 | static void tdma_reset(struct slgt_info *info); |
480 | static void tdma_start(struct slgt_info *info); | ||
480 | static void tx_load(struct slgt_info *info, const char *buf, unsigned int count); | 481 | static void tx_load(struct slgt_info *info, const char *buf, unsigned int count); |
481 | 482 | ||
482 | static void get_signals(struct slgt_info *info); | 483 | static void get_signals(struct slgt_info *info); |
@@ -904,6 +905,8 @@ start: | |||
904 | spin_lock_irqsave(&info->lock,flags); | 905 | spin_lock_irqsave(&info->lock,flags); |
905 | if (!info->tx_active) | 906 | if (!info->tx_active) |
906 | tx_start(info); | 907 | tx_start(info); |
908 | else | ||
909 | tdma_start(info); | ||
907 | spin_unlock_irqrestore(&info->lock,flags); | 910 | spin_unlock_irqrestore(&info->lock,flags); |
908 | } | 911 | } |
909 | 912 | ||
@@ -1562,6 +1565,9 @@ static int hdlcdev_open(struct net_device *dev) | |||
1562 | int rc; | 1565 | int rc; |
1563 | unsigned long flags; | 1566 | unsigned long flags; |
1564 | 1567 | ||
1568 | if (!try_module_get(THIS_MODULE)) | ||
1569 | return -EBUSY; | ||
1570 | |||
1565 | DBGINFO(("%s hdlcdev_open\n", dev->name)); | 1571 | DBGINFO(("%s hdlcdev_open\n", dev->name)); |
1566 | 1572 | ||
1567 | /* generic HDLC layer open processing */ | 1573 | /* generic HDLC layer open processing */ |
@@ -1631,6 +1637,7 @@ static int hdlcdev_close(struct net_device *dev) | |||
1631 | info->netcount=0; | 1637 | info->netcount=0; |
1632 | spin_unlock_irqrestore(&info->netlock, flags); | 1638 | spin_unlock_irqrestore(&info->netlock, flags); |
1633 | 1639 | ||
1640 | module_put(THIS_MODULE); | ||
1634 | return 0; | 1641 | return 0; |
1635 | } | 1642 | } |
1636 | 1643 | ||
@@ -3414,13 +3421,12 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev | |||
3414 | { | 3421 | { |
3415 | struct slgt_info *info; | 3422 | struct slgt_info *info; |
3416 | 3423 | ||
3417 | info = kmalloc(sizeof(struct slgt_info), GFP_KERNEL); | 3424 | info = kzalloc(sizeof(struct slgt_info), GFP_KERNEL); |
3418 | 3425 | ||
3419 | if (!info) { | 3426 | if (!info) { |
3420 | DBGERR(("%s device alloc failed adapter=%d port=%d\n", | 3427 | DBGERR(("%s device alloc failed adapter=%d port=%d\n", |
3421 | driver_name, adapter_num, port_num)); | 3428 | driver_name, adapter_num, port_num)); |
3422 | } else { | 3429 | } else { |
3423 | memset(info, 0, sizeof(struct slgt_info)); | ||
3424 | info->magic = MGSL_MAGIC; | 3430 | info->magic = MGSL_MAGIC; |
3425 | INIT_WORK(&info->task, bh_handler); | 3431 | INIT_WORK(&info->task, bh_handler); |
3426 | info->max_frame_size = 4096; | 3432 | info->max_frame_size = 4096; |
@@ -3872,44 +3878,58 @@ static void tx_start(struct slgt_info *info) | |||
3872 | slgt_irq_on(info, IRQ_TXUNDER + IRQ_TXIDLE); | 3878 | slgt_irq_on(info, IRQ_TXUNDER + IRQ_TXIDLE); |
3873 | /* clear tx idle and underrun status bits */ | 3879 | /* clear tx idle and underrun status bits */ |
3874 | wr_reg16(info, SSR, (unsigned short)(IRQ_TXIDLE + IRQ_TXUNDER)); | 3880 | wr_reg16(info, SSR, (unsigned short)(IRQ_TXIDLE + IRQ_TXUNDER)); |
3875 | |||
3876 | if (!(rd_reg32(info, TDCSR) & BIT0)) { | ||
3877 | /* tx DMA stopped, restart tx DMA */ | ||
3878 | tdma_reset(info); | ||
3879 | /* set 1st descriptor address */ | ||
3880 | wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc); | ||
3881 | switch(info->params.mode) { | ||
3882 | case MGSL_MODE_RAW: | ||
3883 | case MGSL_MODE_MONOSYNC: | ||
3884 | case MGSL_MODE_BISYNC: | ||
3885 | wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */ | ||
3886 | break; | ||
3887 | default: | ||
3888 | wr_reg32(info, TDCSR, BIT0); /* DMA enable */ | ||
3889 | } | ||
3890 | } | ||
3891 | |||
3892 | if (info->params.mode == MGSL_MODE_HDLC) | 3881 | if (info->params.mode == MGSL_MODE_HDLC) |
3893 | mod_timer(&info->tx_timer, jiffies + | 3882 | mod_timer(&info->tx_timer, jiffies + |
3894 | msecs_to_jiffies(5000)); | 3883 | msecs_to_jiffies(5000)); |
3895 | } else { | 3884 | } else { |
3896 | tdma_reset(info); | ||
3897 | /* set 1st descriptor address */ | ||
3898 | wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc); | ||
3899 | |||
3900 | slgt_irq_off(info, IRQ_TXDATA); | 3885 | slgt_irq_off(info, IRQ_TXDATA); |
3901 | slgt_irq_on(info, IRQ_TXIDLE); | 3886 | slgt_irq_on(info, IRQ_TXIDLE); |
3902 | /* clear tx idle status bit */ | 3887 | /* clear tx idle status bit */ |
3903 | wr_reg16(info, SSR, IRQ_TXIDLE); | 3888 | wr_reg16(info, SSR, IRQ_TXIDLE); |
3904 | |||
3905 | /* enable tx DMA */ | ||
3906 | wr_reg32(info, TDCSR, BIT0); | ||
3907 | } | 3889 | } |
3908 | 3890 | tdma_start(info); | |
3909 | info->tx_active = 1; | 3891 | info->tx_active = 1; |
3910 | } | 3892 | } |
3911 | } | 3893 | } |
3912 | 3894 | ||
3895 | /* | ||
3896 | * start transmit DMA if inactive and there are unsent buffers | ||
3897 | */ | ||
3898 | static void tdma_start(struct slgt_info *info) | ||
3899 | { | ||
3900 | unsigned int i; | ||
3901 | |||
3902 | if (rd_reg32(info, TDCSR) & BIT0) | ||
3903 | return; | ||
3904 | |||
3905 | /* transmit DMA inactive, check for unsent buffers */ | ||
3906 | i = info->tbuf_start; | ||
3907 | while (!desc_count(info->tbufs[i])) { | ||
3908 | if (++i == info->tbuf_count) | ||
3909 | i = 0; | ||
3910 | if (i == info->tbuf_current) | ||
3911 | return; | ||
3912 | } | ||
3913 | info->tbuf_start = i; | ||
3914 | |||
3915 | /* there are unsent buffers, start transmit DMA */ | ||
3916 | |||
3917 | /* reset needed if previous error condition */ | ||
3918 | tdma_reset(info); | ||
3919 | |||
3920 | /* set 1st descriptor address */ | ||
3921 | wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc); | ||
3922 | switch(info->params.mode) { | ||
3923 | case MGSL_MODE_RAW: | ||
3924 | case MGSL_MODE_MONOSYNC: | ||
3925 | case MGSL_MODE_BISYNC: | ||
3926 | wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */ | ||
3927 | break; | ||
3928 | default: | ||
3929 | wr_reg32(info, TDCSR, BIT0); /* DMA enable */ | ||
3930 | } | ||
3931 | } | ||
3932 | |||
3913 | static void tx_stop(struct slgt_info *info) | 3933 | static void tx_stop(struct slgt_info *info) |
3914 | { | 3934 | { |
3915 | unsigned short val; | 3935 | unsigned short val; |
@@ -4643,8 +4663,8 @@ static unsigned int free_tbuf_count(struct slgt_info *info) | |||
4643 | i=0; | 4663 | i=0; |
4644 | } while (i != info->tbuf_current); | 4664 | } while (i != info->tbuf_current); |
4645 | 4665 | ||
4646 | /* last buffer with zero count may be in use, assume it is */ | 4666 | /* if tx DMA active, last zero count buffer is in use */ |
4647 | if (count) | 4667 | if (count && (rd_reg32(info, TDCSR) & BIT0)) |
4648 | --count; | 4668 | --count; |
4649 | 4669 | ||
4650 | return count; | 4670 | return count; |
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index a65407b32079..c63013b2fc36 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c | |||
@@ -3786,14 +3786,13 @@ static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev) | |||
3786 | { | 3786 | { |
3787 | SLMP_INFO *info; | 3787 | SLMP_INFO *info; |
3788 | 3788 | ||
3789 | info = kmalloc(sizeof(SLMP_INFO), | 3789 | info = kzalloc(sizeof(SLMP_INFO), |
3790 | GFP_KERNEL); | 3790 | GFP_KERNEL); |
3791 | 3791 | ||
3792 | if (!info) { | 3792 | if (!info) { |
3793 | printk("%s(%d) Error can't allocate device instance data for adapter %d, port %d\n", | 3793 | printk("%s(%d) Error can't allocate device instance data for adapter %d, port %d\n", |
3794 | __FILE__,__LINE__, adapter_num, port_num); | 3794 | __FILE__,__LINE__, adapter_num, port_num); |
3795 | } else { | 3795 | } else { |
3796 | memset(info, 0, sizeof(SLMP_INFO)); | ||
3797 | info->magic = MGSL_MAGIC; | 3796 | info->magic = MGSL_MAGIC; |
3798 | INIT_WORK(&info->task, bh_handler); | 3797 | INIT_WORK(&info->task, bh_handler); |
3799 | info->max_frame_size = 4096; | 3798 | info->max_frame_size = 4096; |
diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c index 35b40b996534..cef55c40654f 100644 --- a/drivers/char/tipar.c +++ b/drivers/char/tipar.c | |||
@@ -441,8 +441,8 @@ tipar_register(int nr, struct parport *port) | |||
441 | goto out; | 441 | goto out; |
442 | } | 442 | } |
443 | 443 | ||
444 | class_device_create(tipar_class, NULL, MKDEV(TIPAR_MAJOR, | 444 | device_create(tipar_class, port->dev, MKDEV(TIPAR_MAJOR, |
445 | TIPAR_MINOR + nr), port->dev, "par%d", nr); | 445 | TIPAR_MINOR + nr), "par%d", nr); |
446 | 446 | ||
447 | /* Display informations */ | 447 | /* Display informations */ |
448 | pr_info("tipar%d: using %s (%s)\n", nr, port->name, (port->irq == | 448 | pr_info("tipar%d: using %s (%s)\n", nr, port->name, (port->irq == |
@@ -534,7 +534,7 @@ tipar_cleanup_module(void) | |||
534 | if (table[i].dev == NULL) | 534 | if (table[i].dev == NULL) |
535 | continue; | 535 | continue; |
536 | parport_unregister_device(table[i].dev); | 536 | parport_unregister_device(table[i].dev); |
537 | class_device_destroy(tipar_class, MKDEV(TIPAR_MAJOR, i)); | 537 | device_destroy(tipar_class, MKDEV(TIPAR_MAJOR, i)); |
538 | } | 538 | } |
539 | class_destroy(tipar_class); | 539 | class_destroy(tipar_class); |
540 | 540 | ||
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 9bb542913b86..39564b76d4a3 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * Reiner Sailer <sailer@watson.ibm.com> | 7 | * Reiner Sailer <sailer@watson.ibm.com> |
8 | * Kylene Hall <kjhall@us.ibm.com> | 8 | * Kylene Hall <kjhall@us.ibm.com> |
9 | * | 9 | * |
10 | * Maintained by: <tpmdd_devel@lists.sourceforge.net> | 10 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> |
11 | * | 11 | * |
12 | * Device driver for TCG/TCPA TPM (trusted platform module). | 12 | * Device driver for TCG/TCPA TPM (trusted platform module). |
13 | * Specifications at www.trustedcomputinggroup.org | 13 | * Specifications at www.trustedcomputinggroup.org |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index b2e2b002a1bb..d15ccddc92eb 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -7,7 +7,7 @@ | |||
7 | * Reiner Sailer <sailer@watson.ibm.com> | 7 | * Reiner Sailer <sailer@watson.ibm.com> |
8 | * Kylene Hall <kjhall@us.ibm.com> | 8 | * Kylene Hall <kjhall@us.ibm.com> |
9 | * | 9 | * |
10 | * Maintained by: <tpmdd_devel@lists.sourceforge.net> | 10 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> |
11 | * | 11 | * |
12 | * Device driver for TCG/TCPA TPM (trusted platform module). | 12 | * Device driver for TCG/TCPA TPM (trusted platform module). |
13 | * Specifications at www.trustedcomputinggroup.org | 13 | * Specifications at www.trustedcomputinggroup.org |
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c index 1ab0896070be..d0e7926eb486 100644 --- a/drivers/char/tpm/tpm_atmel.c +++ b/drivers/char/tpm/tpm_atmel.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * Reiner Sailer <sailer@watson.ibm.com> | 7 | * Reiner Sailer <sailer@watson.ibm.com> |
8 | * Kylene Hall <kjhall@us.ibm.com> | 8 | * Kylene Hall <kjhall@us.ibm.com> |
9 | * | 9 | * |
10 | * Maintained by: <tpmdd_devel@lists.sourceforge.net> | 10 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> |
11 | * | 11 | * |
12 | * Device driver for TCG/TCPA TPM (trusted platform module). | 12 | * Device driver for TCG/TCPA TPM (trusted platform module). |
13 | * Specifications at www.trustedcomputinggroup.org | 13 | * Specifications at www.trustedcomputinggroup.org |
diff --git a/drivers/char/tpm/tpm_atmel.h b/drivers/char/tpm/tpm_atmel.h index 9363bcf0a402..6c831f9466b7 100644 --- a/drivers/char/tpm/tpm_atmel.h +++ b/drivers/char/tpm/tpm_atmel.h | |||
@@ -4,7 +4,7 @@ | |||
4 | * Authors: | 4 | * Authors: |
5 | * Kylene Hall <kjhall@us.ibm.com> | 5 | * Kylene Hall <kjhall@us.ibm.com> |
6 | * | 6 | * |
7 | * Maintained by: <tpmdd_devel@lists.sourceforge.net> | 7 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> |
8 | * | 8 | * |
9 | * Device driver for TCG/TCPA TPM (trusted platform module). | 9 | * Device driver for TCG/TCPA TPM (trusted platform module). |
10 | * Specifications at www.trustedcomputinggroup.org | 10 | * Specifications at www.trustedcomputinggroup.org |
diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c index 4eba32b23b29..60a2d2630e36 100644 --- a/drivers/char/tpm/tpm_bios.c +++ b/drivers/char/tpm/tpm_bios.c | |||
@@ -7,6 +7,8 @@ | |||
7 | * Reiner Sailer <sailer@watson.ibm.com> | 7 | * Reiner Sailer <sailer@watson.ibm.com> |
8 | * Kylene Hall <kjhall@us.ibm.com> | 8 | * Kylene Hall <kjhall@us.ibm.com> |
9 | * | 9 | * |
10 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> | ||
11 | * | ||
10 | * Access to the eventlog extended by the TCG BIOS of PC platform | 12 | * Access to the eventlog extended by the TCG BIOS of PC platform |
11 | * | 13 | * |
12 | * This program is free software; you can redistribute it and/or | 14 | * This program is free software; you can redistribute it and/or |
@@ -427,7 +429,7 @@ static int tpm_ascii_bios_measurements_open(struct inode *inode, | |||
427 | return -ENOMEM; | 429 | return -ENOMEM; |
428 | 430 | ||
429 | if ((err = read_log(log))) | 431 | if ((err = read_log(log))) |
430 | return err; | 432 | goto out_free; |
431 | 433 | ||
432 | /* now register seq file */ | 434 | /* now register seq file */ |
433 | err = seq_open(file, &tpm_ascii_b_measurments_seqops); | 435 | err = seq_open(file, &tpm_ascii_b_measurments_seqops); |
@@ -435,10 +437,15 @@ static int tpm_ascii_bios_measurements_open(struct inode *inode, | |||
435 | seq = file->private_data; | 437 | seq = file->private_data; |
436 | seq->private = log; | 438 | seq->private = log; |
437 | } else { | 439 | } else { |
438 | kfree(log->bios_event_log); | 440 | goto out_free; |
439 | kfree(log); | ||
440 | } | 441 | } |
442 | |||
443 | out: | ||
441 | return err; | 444 | return err; |
445 | out_free: | ||
446 | kfree(log->bios_event_log); | ||
447 | kfree(log); | ||
448 | goto out; | ||
442 | } | 449 | } |
443 | 450 | ||
444 | const struct file_operations tpm_ascii_bios_measurements_ops = { | 451 | const struct file_operations tpm_ascii_bios_measurements_ops = { |
@@ -460,7 +467,7 @@ static int tpm_binary_bios_measurements_open(struct inode *inode, | |||
460 | return -ENOMEM; | 467 | return -ENOMEM; |
461 | 468 | ||
462 | if ((err = read_log(log))) | 469 | if ((err = read_log(log))) |
463 | return err; | 470 | goto out_free; |
464 | 471 | ||
465 | /* now register seq file */ | 472 | /* now register seq file */ |
466 | err = seq_open(file, &tpm_binary_b_measurments_seqops); | 473 | err = seq_open(file, &tpm_binary_b_measurments_seqops); |
@@ -468,10 +475,15 @@ static int tpm_binary_bios_measurements_open(struct inode *inode, | |||
468 | seq = file->private_data; | 475 | seq = file->private_data; |
469 | seq->private = log; | 476 | seq->private = log; |
470 | } else { | 477 | } else { |
471 | kfree(log->bios_event_log); | 478 | goto out_free; |
472 | kfree(log); | ||
473 | } | 479 | } |
480 | |||
481 | out: | ||
474 | return err; | 482 | return err; |
483 | out_free: | ||
484 | kfree(log->bios_event_log); | ||
485 | kfree(log); | ||
486 | goto out; | ||
475 | } | 487 | } |
476 | 488 | ||
477 | const struct file_operations tpm_binary_bios_measurements_ops = { | 489 | const struct file_operations tpm_binary_bios_measurements_ops = { |
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c index 608f73071bef..6313326bc41f 100644 --- a/drivers/char/tpm/tpm_nsc.c +++ b/drivers/char/tpm/tpm_nsc.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * Reiner Sailer <sailer@watson.ibm.com> | 7 | * Reiner Sailer <sailer@watson.ibm.com> |
8 | * Kylene Hall <kjhall@us.ibm.com> | 8 | * Kylene Hall <kjhall@us.ibm.com> |
9 | * | 9 | * |
10 | * Maintained by: <tpmdd_devel@lists.sourceforge.net> | 10 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> |
11 | * | 11 | * |
12 | * Device driver for TCG/TCPA TPM (trusted platform module). | 12 | * Device driver for TCG/TCPA TPM (trusted platform module). |
13 | * Specifications at www.trustedcomputinggroup.org | 13 | * Specifications at www.trustedcomputinggroup.org |
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 483f3f60013c..23fa18a6654c 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c | |||
@@ -5,6 +5,8 @@ | |||
5 | * Leendert van Doorn <leendert@watson.ibm.com> | 5 | * Leendert van Doorn <leendert@watson.ibm.com> |
6 | * Kylene Hall <kjhall@us.ibm.com> | 6 | * Kylene Hall <kjhall@us.ibm.com> |
7 | * | 7 | * |
8 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> | ||
9 | * | ||
8 | * Device driver for TCG/TCPA TPM (trusted platform module). | 10 | * Device driver for TCG/TCPA TPM (trusted platform module). |
9 | * Specifications at www.trustedcomputinggroup.org | 11 | * Specifications at www.trustedcomputinggroup.org |
10 | * | 12 | * |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index de37ebc3a4cf..9c867cf6de64 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -369,25 +369,54 @@ static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b) | |||
369 | } | 369 | } |
370 | 370 | ||
371 | /** | 371 | /** |
372 | * tty_buffer_flush - flush full tty buffers | 372 | * __tty_buffer_flush - flush full tty buffers |
373 | * @tty: tty to flush | 373 | * @tty: tty to flush |
374 | * | 374 | * |
375 | * flush all the buffers containing receive data | 375 | * flush all the buffers containing receive data. Caller must |
376 | * hold the buffer lock and must have ensured no parallel flush to | ||
377 | * ldisc is running. | ||
376 | * | 378 | * |
377 | * Locking: none | 379 | * Locking: Caller must hold tty->buf.lock |
378 | */ | 380 | */ |
379 | 381 | ||
380 | static void tty_buffer_flush(struct tty_struct *tty) | 382 | static void __tty_buffer_flush(struct tty_struct *tty) |
381 | { | 383 | { |
382 | struct tty_buffer *thead; | 384 | struct tty_buffer *thead; |
383 | unsigned long flags; | ||
384 | 385 | ||
385 | spin_lock_irqsave(&tty->buf.lock, flags); | ||
386 | while((thead = tty->buf.head) != NULL) { | 386 | while((thead = tty->buf.head) != NULL) { |
387 | tty->buf.head = thead->next; | 387 | tty->buf.head = thead->next; |
388 | tty_buffer_free(tty, thead); | 388 | tty_buffer_free(tty, thead); |
389 | } | 389 | } |
390 | tty->buf.tail = NULL; | 390 | tty->buf.tail = NULL; |
391 | } | ||
392 | |||
393 | /** | ||
394 | * tty_buffer_flush - flush full tty buffers | ||
395 | * @tty: tty to flush | ||
396 | * | ||
397 | * flush all the buffers containing receive data. If the buffer is | ||
398 | * being processed by flush_to_ldisc then we defer the processing | ||
399 | * to that function | ||
400 | * | ||
401 | * Locking: none | ||
402 | */ | ||
403 | |||
404 | static void tty_buffer_flush(struct tty_struct *tty) | ||
405 | { | ||
406 | unsigned long flags; | ||
407 | spin_lock_irqsave(&tty->buf.lock, flags); | ||
408 | |||
409 | /* If the data is being pushed to the tty layer then we can't | ||
410 | process it here. Instead set a flag and the flush_to_ldisc | ||
411 | path will process the flush request before it exits */ | ||
412 | if (test_bit(TTY_FLUSHING, &tty->flags)) { | ||
413 | set_bit(TTY_FLUSHPENDING, &tty->flags); | ||
414 | spin_unlock_irqrestore(&tty->buf.lock, flags); | ||
415 | wait_event(tty->read_wait, | ||
416 | test_bit(TTY_FLUSHPENDING, &tty->flags) == 0); | ||
417 | return; | ||
418 | } else | ||
419 | __tty_buffer_flush(tty); | ||
391 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 420 | spin_unlock_irqrestore(&tty->buf.lock, flags); |
392 | } | 421 | } |
393 | 422 | ||
@@ -2034,8 +2063,7 @@ static int init_dev(struct tty_driver *driver, int idx, | |||
2034 | } | 2063 | } |
2035 | 2064 | ||
2036 | if (!*tp_loc) { | 2065 | if (!*tp_loc) { |
2037 | tp = (struct ktermios *) kmalloc(sizeof(struct ktermios), | 2066 | tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL); |
2038 | GFP_KERNEL); | ||
2039 | if (!tp) | 2067 | if (!tp) |
2040 | goto free_mem_out; | 2068 | goto free_mem_out; |
2041 | *tp = driver->init_termios; | 2069 | *tp = driver->init_termios; |
@@ -2065,8 +2093,7 @@ static int init_dev(struct tty_driver *driver, int idx, | |||
2065 | } | 2093 | } |
2066 | 2094 | ||
2067 | if (!*o_tp_loc) { | 2095 | if (!*o_tp_loc) { |
2068 | o_tp = (struct ktermios *) | 2096 | o_tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL); |
2069 | kmalloc(sizeof(struct ktermios), GFP_KERNEL); | ||
2070 | if (!o_tp) | 2097 | if (!o_tp) |
2071 | goto free_mem_out; | 2098 | goto free_mem_out; |
2072 | *o_tp = driver->other->init_termios; | 2099 | *o_tp = driver->other->init_termios; |
@@ -3594,6 +3621,7 @@ static void flush_to_ldisc(struct work_struct *work) | |||
3594 | return; | 3621 | return; |
3595 | 3622 | ||
3596 | spin_lock_irqsave(&tty->buf.lock, flags); | 3623 | spin_lock_irqsave(&tty->buf.lock, flags); |
3624 | set_bit(TTY_FLUSHING, &tty->flags); /* So we know a flush is running */ | ||
3597 | head = tty->buf.head; | 3625 | head = tty->buf.head; |
3598 | if (head != NULL) { | 3626 | if (head != NULL) { |
3599 | tty->buf.head = NULL; | 3627 | tty->buf.head = NULL; |
@@ -3607,6 +3635,11 @@ static void flush_to_ldisc(struct work_struct *work) | |||
3607 | tty_buffer_free(tty, tbuf); | 3635 | tty_buffer_free(tty, tbuf); |
3608 | continue; | 3636 | continue; |
3609 | } | 3637 | } |
3638 | /* Ldisc or user is trying to flush the buffers | ||
3639 | we are feeding to the ldisc, stop feeding the | ||
3640 | line discipline as we want to empty the queue */ | ||
3641 | if (test_bit(TTY_FLUSHPENDING, &tty->flags)) | ||
3642 | break; | ||
3610 | if (!tty->receive_room) { | 3643 | if (!tty->receive_room) { |
3611 | schedule_delayed_work(&tty->buf.work, 1); | 3644 | schedule_delayed_work(&tty->buf.work, 1); |
3612 | break; | 3645 | break; |
@@ -3620,8 +3653,17 @@ static void flush_to_ldisc(struct work_struct *work) | |||
3620 | disc->receive_buf(tty, char_buf, flag_buf, count); | 3653 | disc->receive_buf(tty, char_buf, flag_buf, count); |
3621 | spin_lock_irqsave(&tty->buf.lock, flags); | 3654 | spin_lock_irqsave(&tty->buf.lock, flags); |
3622 | } | 3655 | } |
3656 | /* Restore the queue head */ | ||
3623 | tty->buf.head = head; | 3657 | tty->buf.head = head; |
3624 | } | 3658 | } |
3659 | /* We may have a deferred request to flush the input buffer, | ||
3660 | if so pull the chain under the lock and empty the queue */ | ||
3661 | if (test_bit(TTY_FLUSHPENDING, &tty->flags)) { | ||
3662 | __tty_buffer_flush(tty); | ||
3663 | clear_bit(TTY_FLUSHPENDING, &tty->flags); | ||
3664 | wake_up(&tty->read_wait); | ||
3665 | } | ||
3666 | clear_bit(TTY_FLUSHING, &tty->flags); | ||
3625 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 3667 | spin_unlock_irqrestore(&tty->buf.lock, flags); |
3626 | 3668 | ||
3627 | tty_ldisc_deref(disc); | 3669 | tty_ldisc_deref(disc); |
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index 3423e9ee6481..3ee73cf64bd2 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c | |||
@@ -795,6 +795,7 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file, | |||
795 | if (L_ICANON(tty)) | 795 | if (L_ICANON(tty)) |
796 | retval = inq_canon(tty); | 796 | retval = inq_canon(tty); |
797 | return put_user(retval, (unsigned int __user *) arg); | 797 | return put_user(retval, (unsigned int __user *) arg); |
798 | #ifndef TCGETS2 | ||
798 | case TIOCGLCKTRMIOS: | 799 | case TIOCGLCKTRMIOS: |
799 | if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked)) | 800 | if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked)) |
800 | return -EFAULT; | 801 | return -EFAULT; |
@@ -806,6 +807,19 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file, | |||
806 | if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg)) | 807 | if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg)) |
807 | return -EFAULT; | 808 | return -EFAULT; |
808 | return 0; | 809 | return 0; |
810 | #else | ||
811 | case TIOCGLCKTRMIOS: | ||
812 | if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked)) | ||
813 | return -EFAULT; | ||
814 | return 0; | ||
815 | |||
816 | case TIOCSLCKTRMIOS: | ||
817 | if (!capable(CAP_SYS_ADMIN)) | ||
818 | return -EPERM; | ||
819 | if (user_termios_to_kernel_termios_1(real_tty->termios_locked, (struct termios __user *) arg)) | ||
820 | return -EFAULT; | ||
821 | return 0; | ||
822 | #endif | ||
809 | 823 | ||
810 | case TIOCPKT: | 824 | case TIOCPKT: |
811 | { | 825 | { |
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index db57277117bb..db7a731e2362 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c | |||
@@ -92,47 +92,6 @@ struct viot_devinfo_struct { | |||
92 | #define VIOTAPOP_SETPART 14 | 92 | #define VIOTAPOP_SETPART 14 |
93 | #define VIOTAPOP_UNLOAD 15 | 93 | #define VIOTAPOP_UNLOAD 15 |
94 | 94 | ||
95 | struct viotapelpevent { | ||
96 | struct HvLpEvent event; | ||
97 | u32 reserved; | ||
98 | u16 version; | ||
99 | u16 sub_type_result; | ||
100 | u16 tape; | ||
101 | u16 flags; | ||
102 | u32 token; | ||
103 | u64 len; | ||
104 | union { | ||
105 | struct { | ||
106 | u32 tape_op; | ||
107 | u32 count; | ||
108 | } op; | ||
109 | struct { | ||
110 | u32 type; | ||
111 | u32 resid; | ||
112 | u32 dsreg; | ||
113 | u32 gstat; | ||
114 | u32 erreg; | ||
115 | u32 file_no; | ||
116 | u32 block_no; | ||
117 | } get_status; | ||
118 | struct { | ||
119 | u32 block_no; | ||
120 | } get_pos; | ||
121 | } u; | ||
122 | }; | ||
123 | |||
124 | enum viotapesubtype { | ||
125 | viotapeopen = 0x0001, | ||
126 | viotapeclose = 0x0002, | ||
127 | viotaperead = 0x0003, | ||
128 | viotapewrite = 0x0004, | ||
129 | viotapegetinfo = 0x0005, | ||
130 | viotapeop = 0x0006, | ||
131 | viotapegetpos = 0x0007, | ||
132 | viotapesetpos = 0x0008, | ||
133 | viotapegetstatus = 0x0009 | ||
134 | }; | ||
135 | |||
136 | enum viotaperc { | 95 | enum viotaperc { |
137 | viotape_InvalidRange = 0x0601, | 96 | viotape_InvalidRange = 0x0601, |
138 | viotape_InvalidToken = 0x0602, | 97 | viotape_InvalidToken = 0x0602, |
@@ -223,14 +182,11 @@ static const struct vio_error_entry viotape_err_table[] = { | |||
223 | #define VIOT_WRITING 2 | 182 | #define VIOT_WRITING 2 |
224 | 183 | ||
225 | /* Our info on the tapes */ | 184 | /* Our info on the tapes */ |
226 | struct tape_descr { | 185 | static struct { |
227 | char rsrcname[10]; | 186 | const char *rsrcname; |
228 | char type[4]; | 187 | const char *type; |
229 | char model[3]; | 188 | const char *model; |
230 | }; | 189 | } viotape_unitinfo[VIOTAPE_MAX_TAPE]; |
231 | |||
232 | static struct tape_descr *viotape_unitinfo; | ||
233 | static dma_addr_t viotape_unitinfo_token; | ||
234 | 190 | ||
235 | static struct mtget viomtget[VIOTAPE_MAX_TAPE]; | 191 | static struct mtget viomtget[VIOTAPE_MAX_TAPE]; |
236 | 192 | ||
@@ -381,53 +337,6 @@ int tape_rc_to_errno(int tape_rc, char *operation, int tapeno) | |||
381 | return -err->errno; | 337 | return -err->errno; |
382 | } | 338 | } |
383 | 339 | ||
384 | /* Get info on all tapes from OS/400 */ | ||
385 | static int get_viotape_info(void) | ||
386 | { | ||
387 | HvLpEvent_Rc hvrc; | ||
388 | int i; | ||
389 | size_t len = sizeof(*viotape_unitinfo) * VIOTAPE_MAX_TAPE; | ||
390 | struct op_struct *op = get_op_struct(); | ||
391 | |||
392 | if (op == NULL) | ||
393 | return -ENOMEM; | ||
394 | |||
395 | viotape_unitinfo = dma_alloc_coherent(iSeries_vio_dev, len, | ||
396 | &viotape_unitinfo_token, GFP_ATOMIC); | ||
397 | if (viotape_unitinfo == NULL) { | ||
398 | free_op_struct(op); | ||
399 | return -ENOMEM; | ||
400 | } | ||
401 | |||
402 | memset(viotape_unitinfo, 0, len); | ||
403 | |||
404 | hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, | ||
405 | HvLpEvent_Type_VirtualIo, | ||
406 | viomajorsubtype_tape | viotapegetinfo, | ||
407 | HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, | ||
408 | viopath_sourceinst(viopath_hostLp), | ||
409 | viopath_targetinst(viopath_hostLp), | ||
410 | (u64) (unsigned long) op, VIOVERSION << 16, | ||
411 | viotape_unitinfo_token, len, 0, 0); | ||
412 | if (hvrc != HvLpEvent_Rc_Good) { | ||
413 | printk(VIOTAPE_KERN_WARN "hv error on op %d\n", | ||
414 | (int)hvrc); | ||
415 | free_op_struct(op); | ||
416 | return -EIO; | ||
417 | } | ||
418 | |||
419 | wait_for_completion(&op->com); | ||
420 | |||
421 | free_op_struct(op); | ||
422 | |||
423 | for (i = 0; | ||
424 | ((i < VIOTAPE_MAX_TAPE) && (viotape_unitinfo[i].rsrcname[0])); | ||
425 | i++) | ||
426 | viotape_numdev++; | ||
427 | return 0; | ||
428 | } | ||
429 | |||
430 | |||
431 | /* Write */ | 340 | /* Write */ |
432 | static ssize_t viotap_write(struct file *file, const char *buf, | 341 | static ssize_t viotap_write(struct file *file, const char *buf, |
433 | size_t count, loff_t * ppos) | 342 | size_t count, loff_t * ppos) |
@@ -899,7 +808,6 @@ static void vioHandleTapeEvent(struct HvLpEvent *event) | |||
899 | tapeminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK; | 808 | tapeminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK; |
900 | op = (struct op_struct *)event->xCorrelationToken; | 809 | op = (struct op_struct *)event->xCorrelationToken; |
901 | switch (tapeminor) { | 810 | switch (tapeminor) { |
902 | case viotapegetinfo: | ||
903 | case viotapeopen: | 811 | case viotapeopen: |
904 | case viotapeclose: | 812 | case viotapeclose: |
905 | op->rc = tevent->sub_type_result; | 813 | op->rc = tevent->sub_type_result; |
@@ -942,19 +850,31 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
942 | { | 850 | { |
943 | int i = vdev->unit_address; | 851 | int i = vdev->unit_address; |
944 | int j; | 852 | int j; |
853 | struct device_node *node = vdev->dev.archdata.of_node; | ||
945 | 854 | ||
946 | if (i >= viotape_numdev) | 855 | if (i > VIOTAPE_MAX_TAPE) |
947 | return -ENODEV; | 856 | return -ENODEV; |
857 | if (!node) | ||
858 | return -ENODEV; | ||
859 | |||
860 | if (i >= viotape_numdev) | ||
861 | viotape_numdev = i + 1; | ||
948 | 862 | ||
949 | tape_device[i] = &vdev->dev; | 863 | tape_device[i] = &vdev->dev; |
864 | viotape_unitinfo[i].rsrcname = of_get_property(node, | ||
865 | "linux,vio_rsrcname", NULL); | ||
866 | viotape_unitinfo[i].type = of_get_property(node, "linux,vio_type", | ||
867 | NULL); | ||
868 | viotape_unitinfo[i].model = of_get_property(node, "linux,vio_model", | ||
869 | NULL); | ||
950 | 870 | ||
951 | state[i].cur_part = 0; | 871 | state[i].cur_part = 0; |
952 | for (j = 0; j < MAX_PARTITIONS; ++j) | 872 | for (j = 0; j < MAX_PARTITIONS; ++j) |
953 | state[i].part_stat_rwi[j] = VIOT_IDLE; | 873 | state[i].part_stat_rwi[j] = VIOT_IDLE; |
954 | class_device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i), NULL, | 874 | device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i), |
955 | "iseries!vt%d", i); | 875 | "iseries!vt%d", i); |
956 | class_device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80), | 876 | device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80), |
957 | NULL, "iseries!nvt%d", i); | 877 | "iseries!nvt%d", i); |
958 | printk(VIOTAPE_KERN_INFO "tape iseries/vt%d is iSeries " | 878 | printk(VIOTAPE_KERN_INFO "tape iseries/vt%d is iSeries " |
959 | "resource %10.10s type %4.4s, model %3.3s\n", | 879 | "resource %10.10s type %4.4s, model %3.3s\n", |
960 | i, viotape_unitinfo[i].rsrcname, | 880 | i, viotape_unitinfo[i].rsrcname, |
@@ -966,8 +886,8 @@ static int viotape_remove(struct vio_dev *vdev) | |||
966 | { | 886 | { |
967 | int i = vdev->unit_address; | 887 | int i = vdev->unit_address; |
968 | 888 | ||
969 | class_device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80)); | 889 | device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80)); |
970 | class_device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i)); | 890 | device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i)); |
971 | return 0; | 891 | return 0; |
972 | } | 892 | } |
973 | 893 | ||
@@ -1044,11 +964,6 @@ int __init viotap_init(void) | |||
1044 | goto unreg_chrdev; | 964 | goto unreg_chrdev; |
1045 | } | 965 | } |
1046 | 966 | ||
1047 | if ((ret = get_viotape_info()) < 0) { | ||
1048 | printk(VIOTAPE_KERN_WARN "Unable to obtain virtual device information"); | ||
1049 | goto unreg_class; | ||
1050 | } | ||
1051 | |||
1052 | ret = vio_register_driver(&viotape_driver); | 967 | ret = vio_register_driver(&viotape_driver); |
1053 | if (ret) | 968 | if (ret) |
1054 | goto unreg_class; | 969 | goto unreg_class; |
@@ -1098,19 +1013,10 @@ static int chg_state(int index, unsigned char new_state, struct file *file) | |||
1098 | /* Cleanup */ | 1013 | /* Cleanup */ |
1099 | static void __exit viotap_exit(void) | 1014 | static void __exit viotap_exit(void) |
1100 | { | 1015 | { |
1101 | int ret; | ||
1102 | |||
1103 | remove_proc_entry("iSeries/viotape", NULL); | 1016 | remove_proc_entry("iSeries/viotape", NULL); |
1104 | vio_unregister_driver(&viotape_driver); | 1017 | vio_unregister_driver(&viotape_driver); |
1105 | class_destroy(tape_class); | 1018 | class_destroy(tape_class); |
1106 | ret = unregister_chrdev(VIOTAPE_MAJOR, "viotape"); | 1019 | unregister_chrdev(VIOTAPE_MAJOR, "viotape"); |
1107 | if (ret < 0) | ||
1108 | printk(VIOTAPE_KERN_WARN "Error unregistering device: %d\n", | ||
1109 | ret); | ||
1110 | if (viotape_unitinfo) | ||
1111 | dma_free_coherent(iSeries_vio_dev, | ||
1112 | sizeof(viotape_unitinfo[0]) * VIOTAPE_MAX_TAPE, | ||
1113 | viotape_unitinfo, viotape_unitinfo_token); | ||
1114 | viopath_close(viopath_hostLp, viomajorsubtype_tape, VIOTAPE_MAXREQ + 2); | 1020 | viopath_close(viopath_hostLp, viomajorsubtype_tape, VIOTAPE_MAXREQ + 2); |
1115 | vio_clearHandler(viomajorsubtype_tape); | 1021 | vio_clearHandler(viomajorsubtype_tape); |
1116 | clear_op_struct_pool(); | 1022 | clear_op_struct_pool(); |
diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c index bef6d886d4fb..e122a0e87bb0 100644 --- a/drivers/char/vme_scc.c +++ b/drivers/char/vme_scc.c | |||
@@ -1013,18 +1013,10 @@ static struct tty_driver *scc_console_device(struct console *c, int *index) | |||
1013 | return scc_driver; | 1013 | return scc_driver; |
1014 | } | 1014 | } |
1015 | 1015 | ||
1016 | |||
1017 | static int __init scc_console_setup(struct console *co, char *options) | ||
1018 | { | ||
1019 | return 0; | ||
1020 | } | ||
1021 | |||
1022 | |||
1023 | static struct console sercons = { | 1016 | static struct console sercons = { |
1024 | .name = "ttyS", | 1017 | .name = "ttyS", |
1025 | .write = scc_console_write, | 1018 | .write = scc_console_write, |
1026 | .device = scc_console_device, | 1019 | .device = scc_console_device, |
1027 | .setup = scc_console_setup, | ||
1028 | .flags = CON_PRINTBUFFER, | 1020 | .flags = CON_PRINTBUFFER, |
1029 | .index = -1, | 1021 | .index = -1, |
1030 | }; | 1022 | }; |
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index c6f6f4209739..7a61a2a9aafe 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c | |||
@@ -770,6 +770,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
770 | /* | 770 | /* |
771 | * Switching-from response | 771 | * Switching-from response |
772 | */ | 772 | */ |
773 | acquire_console_sem(); | ||
773 | if (vc->vt_newvt >= 0) { | 774 | if (vc->vt_newvt >= 0) { |
774 | if (arg == 0) | 775 | if (arg == 0) |
775 | /* | 776 | /* |
@@ -784,7 +785,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
784 | * complete the switch. | 785 | * complete the switch. |
785 | */ | 786 | */ |
786 | int newvt; | 787 | int newvt; |
787 | acquire_console_sem(); | ||
788 | newvt = vc->vt_newvt; | 788 | newvt = vc->vt_newvt; |
789 | vc->vt_newvt = -1; | 789 | vc->vt_newvt = -1; |
790 | i = vc_allocate(newvt); | 790 | i = vc_allocate(newvt); |
@@ -798,7 +798,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
798 | * other console switches.. | 798 | * other console switches.. |
799 | */ | 799 | */ |
800 | complete_change_console(vc_cons[newvt].d); | 800 | complete_change_console(vc_cons[newvt].d); |
801 | release_console_sem(); | ||
802 | } | 801 | } |
803 | } | 802 | } |
804 | 803 | ||
@@ -810,9 +809,12 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
810 | /* | 809 | /* |
811 | * If it's just an ACK, ignore it | 810 | * If it's just an ACK, ignore it |
812 | */ | 811 | */ |
813 | if (arg != VT_ACKACQ) | 812 | if (arg != VT_ACKACQ) { |
813 | release_console_sem(); | ||
814 | return -EINVAL; | 814 | return -EINVAL; |
815 | } | ||
815 | } | 816 | } |
817 | release_console_sem(); | ||
816 | 818 | ||
817 | return 0; | 819 | return 0; |
818 | 820 | ||
@@ -1030,7 +1032,7 @@ static DECLARE_WAIT_QUEUE_HEAD(vt_activate_queue); | |||
1030 | 1032 | ||
1031 | /* | 1033 | /* |
1032 | * Sleeps until a vt is activated, or the task is interrupted. Returns | 1034 | * Sleeps until a vt is activated, or the task is interrupted. Returns |
1033 | * 0 if activation, -EINTR if interrupted. | 1035 | * 0 if activation, -EINTR if interrupted by a signal handler. |
1034 | */ | 1036 | */ |
1035 | int vt_waitactive(int vt) | 1037 | int vt_waitactive(int vt) |
1036 | { | 1038 | { |
@@ -1055,7 +1057,7 @@ int vt_waitactive(int vt) | |||
1055 | break; | 1057 | break; |
1056 | } | 1058 | } |
1057 | release_console_sem(); | 1059 | release_console_sem(); |
1058 | retval = -EINTR; | 1060 | retval = -ERESTARTNOHAND; |
1059 | if (signal_pending(current)) | 1061 | if (signal_pending(current)) |
1060 | break; | 1062 | break; |
1061 | schedule(); | 1063 | schedule(); |
@@ -1208,15 +1210,18 @@ void change_console(struct vc_data *new_vc) | |||
1208 | /* | 1210 | /* |
1209 | * Send the signal as privileged - kill_pid() will | 1211 | * Send the signal as privileged - kill_pid() will |
1210 | * tell us if the process has gone or something else | 1212 | * tell us if the process has gone or something else |
1211 | * is awry | 1213 | * is awry. |
1214 | * | ||
1215 | * We need to set vt_newvt *before* sending the signal or we | ||
1216 | * have a race. | ||
1212 | */ | 1217 | */ |
1218 | vc->vt_newvt = new_vc->vc_num; | ||
1213 | if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) { | 1219 | if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) { |
1214 | /* | 1220 | /* |
1215 | * It worked. Mark the vt to switch to and | 1221 | * It worked. Mark the vt to switch to and |
1216 | * return. The process needs to send us a | 1222 | * return. The process needs to send us a |
1217 | * VT_RELDISP ioctl to complete the switch. | 1223 | * VT_RELDISP ioctl to complete the switch. |
1218 | */ | 1224 | */ |
1219 | vc->vt_newvt = new_vc->vc_num; | ||
1220 | return; | 1225 | return; |
1221 | } | 1226 | } |
1222 | 1227 | ||
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index 2f48ba329961..37bddc1802de 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig | |||
@@ -55,6 +55,8 @@ config SOFT_WATCHDOG | |||
55 | To compile this driver as a module, choose M here: the | 55 | To compile this driver as a module, choose M here: the |
56 | module will be called softdog. | 56 | module will be called softdog. |
57 | 57 | ||
58 | # ALPHA Architecture | ||
59 | |||
58 | # ARM Architecture | 60 | # ARM Architecture |
59 | 61 | ||
60 | config AT91RM9200_WATCHDOG | 62 | config AT91RM9200_WATCHDOG |
@@ -187,15 +189,64 @@ config PNX4008_WATCHDOG | |||
187 | 189 | ||
188 | Say N if you are unsure. | 190 | Say N if you are unsure. |
189 | 191 | ||
192 | config IOP_WATCHDOG | ||
193 | tristate "IOP Watchdog" | ||
194 | depends on PLAT_IOP | ||
195 | select WATCHDOG_NOWAYOUT if (ARCH_IOP32X || ARCH_IOP33X) | ||
196 | help | ||
197 | Say Y here if to include support for the watchdog timer | ||
198 | in the Intel IOP3XX & IOP13XX I/O Processors. This driver can | ||
199 | be built as a module by choosing M. The module will | ||
200 | be called iop_wdt. | ||
201 | |||
202 | Note: The IOP13XX watchdog does an Internal Bus Reset which will | ||
203 | affect both cores and the peripherals of the IOP. The ATU-X | ||
204 | and/or ATUe configuration registers will remain intact, but if | ||
205 | operating as an Root Complex and/or Central Resource, the PCI-X | ||
206 | and/or PCIe busses will also be reset. THIS IS A VERY BIG HAMMER. | ||
207 | |||
208 | config DAVINCI_WATCHDOG | ||
209 | tristate "DaVinci watchdog" | ||
210 | depends on ARCH_DAVINCI | ||
211 | help | ||
212 | Say Y here if to include support for the watchdog timer | ||
213 | in the DaVinci DM644x/DM646x processors. | ||
214 | To compile this driver as a module, choose M here: the | ||
215 | module will be called davinci_wdt. | ||
216 | |||
217 | NOTE: once enabled, this timer cannot be disabled. | ||
218 | Say N if you are unsure. | ||
219 | |||
220 | # ARM26 Architecture | ||
221 | |||
190 | # AVR32 Architecture | 222 | # AVR32 Architecture |
191 | 223 | ||
192 | config AT32AP700X_WDT | 224 | config AT32AP700X_WDT |
193 | tristate "AT32AP700x watchdog" | 225 | tristate "AT32AP700x watchdog" |
194 | depends on WATCHDOG && CPU_AT32AP7000 | 226 | depends on CPU_AT32AP7000 |
195 | help | 227 | help |
196 | Watchdog timer embedded into AT32AP700x devices. This will reboot | 228 | Watchdog timer embedded into AT32AP700x devices. This will reboot |
197 | your system when the timeout is reached. | 229 | your system when the timeout is reached. |
198 | 230 | ||
231 | # BLACKFIN Architecture | ||
232 | |||
233 | config BFIN_WDT | ||
234 | tristate "Blackfin On-Chip Watchdog Timer" | ||
235 | depends on BLACKFIN | ||
236 | ---help--- | ||
237 | If you say yes here you will get support for the Blackfin On-Chip | ||
238 | Watchdog Timer. If you have one of these processors and wish to | ||
239 | have watchdog support enabled, say Y, otherwise say N. | ||
240 | |||
241 | To compile this driver as a module, choose M here: the | ||
242 | module will be called bfin_wdt. | ||
243 | |||
244 | # CRIS Architecture | ||
245 | |||
246 | # FRV Architecture | ||
247 | |||
248 | # H8300 Architecture | ||
249 | |||
199 | # X86 (i386 + ia64 + x86_64) Architecture | 250 | # X86 (i386 + ia64 + x86_64) Architecture |
200 | 251 | ||
201 | config ACQUIRE_WDT | 252 | config ACQUIRE_WDT |
@@ -524,37 +575,11 @@ config SBC_EPX_C3_WATCHDOG | |||
524 | To compile this driver as a module, choose M here: the | 575 | To compile this driver as a module, choose M here: the |
525 | module will be called sbc_epx_c3. | 576 | module will be called sbc_epx_c3. |
526 | 577 | ||
527 | # PowerPC Architecture | 578 | # M32R Architecture |
528 | |||
529 | config 8xx_WDT | ||
530 | tristate "MPC8xx Watchdog Timer" | ||
531 | depends on 8xx | ||
532 | |||
533 | config 83xx_WDT | ||
534 | tristate "MPC83xx Watchdog Timer" | ||
535 | depends on PPC_83xx | ||
536 | |||
537 | config MV64X60_WDT | ||
538 | tristate "MV64X60 (Marvell Discovery) Watchdog Timer" | ||
539 | depends on MV64X60 | ||
540 | |||
541 | config BOOKE_WDT | ||
542 | bool "PowerPC Book-E Watchdog Timer" | ||
543 | depends on BOOKE || 4xx | ||
544 | ---help--- | ||
545 | Please see Documentation/watchdog/watchdog-api.txt for | ||
546 | more information. | ||
547 | |||
548 | # PPC64 Architecture | ||
549 | 579 | ||
550 | config WATCHDOG_RTAS | 580 | # M68K Architecture |
551 | tristate "RTAS watchdog" | ||
552 | depends on PPC_RTAS | ||
553 | help | ||
554 | This driver adds watchdog support for the RTAS watchdog. | ||
555 | 581 | ||
556 | To compile this driver as a module, choose M here. The module | 582 | # M68KNOMMU Architecture |
557 | will be called wdrtas. | ||
558 | 583 | ||
559 | # MIPS Architecture | 584 | # MIPS Architecture |
560 | 585 | ||
@@ -584,6 +609,44 @@ config WDT_RM9K_GPI | |||
584 | To compile this driver as a module, choose M here: the | 609 | To compile this driver as a module, choose M here: the |
585 | module will be called rm9k_wdt. | 610 | module will be called rm9k_wdt. |
586 | 611 | ||
612 | # PARISC Architecture | ||
613 | |||
614 | # POWERPC Architecture | ||
615 | |||
616 | config MPC5200_WDT | ||
617 | tristate "MPC5200 Watchdog Timer" | ||
618 | depends on PPC_MPC52xx | ||
619 | |||
620 | config 8xx_WDT | ||
621 | tristate "MPC8xx Watchdog Timer" | ||
622 | depends on 8xx | ||
623 | |||
624 | config 83xx_WDT | ||
625 | tristate "MPC83xx Watchdog Timer" | ||
626 | depends on PPC_83xx | ||
627 | |||
628 | config MV64X60_WDT | ||
629 | tristate "MV64X60 (Marvell Discovery) Watchdog Timer" | ||
630 | depends on MV64X60 | ||
631 | |||
632 | config BOOKE_WDT | ||
633 | bool "PowerPC Book-E Watchdog Timer" | ||
634 | depends on BOOKE || 4xx | ||
635 | ---help--- | ||
636 | Please see Documentation/watchdog/watchdog-api.txt for | ||
637 | more information. | ||
638 | |||
639 | # PPC64 Architecture | ||
640 | |||
641 | config WATCHDOG_RTAS | ||
642 | tristate "RTAS watchdog" | ||
643 | depends on PPC_RTAS | ||
644 | help | ||
645 | This driver adds watchdog support for the RTAS watchdog. | ||
646 | |||
647 | To compile this driver as a module, choose M here. The module | ||
648 | will be called wdrtas. | ||
649 | |||
587 | # S390 Architecture | 650 | # S390 Architecture |
588 | 651 | ||
589 | config ZVM_WATCHDOG | 652 | config ZVM_WATCHDOG |
@@ -598,11 +661,11 @@ config ZVM_WATCHDOG | |||
598 | To compile this driver as a module, choose M here. The module | 661 | To compile this driver as a module, choose M here. The module |
599 | will be called vmwatchdog. | 662 | will be called vmwatchdog. |
600 | 663 | ||
601 | # SUPERH Architecture | 664 | # SUPERH (sh + sh64) Architecture |
602 | 665 | ||
603 | config SH_WDT | 666 | config SH_WDT |
604 | tristate "SuperH Watchdog" | 667 | tristate "SuperH Watchdog" |
605 | depends on SUPERH | 668 | depends on SUPERH && (CPU_SH3 || CPU_SH4) |
606 | help | 669 | help |
607 | This driver adds watchdog support for the integrated watchdog in the | 670 | This driver adds watchdog support for the integrated watchdog in the |
608 | SuperH processors. If you have one of these processors and wish | 671 | SuperH processors. If you have one of these processors and wish |
@@ -625,6 +688,8 @@ config SH_WDT_MMAP | |||
625 | If you say Y here, user applications will be able to mmap the | 688 | If you say Y here, user applications will be able to mmap the |
626 | WDT/CPG registers. | 689 | WDT/CPG registers. |
627 | 690 | ||
691 | # SPARC Architecture | ||
692 | |||
628 | # SPARC64 Architecture | 693 | # SPARC64 Architecture |
629 | 694 | ||
630 | config WATCHDOG_CP1XXX | 695 | config WATCHDOG_CP1XXX |
@@ -649,6 +714,10 @@ config WATCHDOG_RIO | |||
649 | machines. The watchdog timeout period is normally one minute but | 714 | machines. The watchdog timeout period is normally one minute but |
650 | can be changed with a boot-time parameter. | 715 | can be changed with a boot-time parameter. |
651 | 716 | ||
717 | # V850 Architecture | ||
718 | |||
719 | # XTENSA Architecture | ||
720 | |||
652 | # | 721 | # |
653 | # ISA-based Watchdog Cards | 722 | # ISA-based Watchdog Cards |
654 | # | 723 | # |
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index 3907ec04a4e5..389f8b14ccc4 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile | |||
@@ -22,6 +22,8 @@ obj-$(CONFIG_WDTPCI) += wdt_pci.o | |||
22 | # USB-based Watchdog Cards | 22 | # USB-based Watchdog Cards |
23 | obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o | 23 | obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o |
24 | 24 | ||
25 | # ALPHA Architecture | ||
26 | |||
25 | # ARM Architecture | 27 | # ARM Architecture |
26 | obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o | 28 | obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o |
27 | obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o | 29 | obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o |
@@ -35,10 +37,23 @@ obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o | |||
35 | obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o | 37 | obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o |
36 | obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o | 38 | obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o |
37 | obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o | 39 | obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o |
40 | obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o | ||
41 | obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o | ||
42 | |||
43 | # ARM26 Architecture | ||
38 | 44 | ||
39 | # AVR32 Architecture | 45 | # AVR32 Architecture |
40 | obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o | 46 | obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o |
41 | 47 | ||
48 | # BLACKFIN Architecture | ||
49 | obj-$(CONFIG_BFIN_WDT) += bfin_wdt.o | ||
50 | |||
51 | # CRIS Architecture | ||
52 | |||
53 | # FRV Architecture | ||
54 | |||
55 | # H8300 Architecture | ||
56 | |||
42 | # X86 (i386 + ia64 + x86_64) Architecture | 57 | # X86 (i386 + ia64 + x86_64) Architecture |
43 | obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o | 58 | obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o |
44 | obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o | 59 | obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o |
@@ -65,8 +80,22 @@ obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o | |||
65 | obj-$(CONFIG_MACHZ_WDT) += machzwd.o | 80 | obj-$(CONFIG_MACHZ_WDT) += machzwd.o |
66 | obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o | 81 | obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o |
67 | 82 | ||
68 | # PowerPC Architecture | 83 | # M32R Architecture |
84 | |||
85 | # M68K Architecture | ||
86 | |||
87 | # M68KNOMMU Architecture | ||
88 | |||
89 | # MIPS Architecture | ||
90 | obj-$(CONFIG_INDYDOG) += indydog.o | ||
91 | obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o | ||
92 | obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o | ||
93 | |||
94 | # PARISC Architecture | ||
95 | |||
96 | # POWERPC Architecture | ||
69 | obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o | 97 | obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o |
98 | obj-$(CONFIG_MPC5200_WDT) += mpc5200_wdt.o | ||
70 | obj-$(CONFIG_83xx_WDT) += mpc83xx_wdt.o | 99 | obj-$(CONFIG_83xx_WDT) += mpc83xx_wdt.o |
71 | obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o | 100 | obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o |
72 | obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o | 101 | obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o |
@@ -74,17 +103,18 @@ obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o | |||
74 | # PPC64 Architecture | 103 | # PPC64 Architecture |
75 | obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o | 104 | obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o |
76 | 105 | ||
77 | # MIPS Architecture | ||
78 | obj-$(CONFIG_INDYDOG) += indydog.o | ||
79 | obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o | ||
80 | obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o | ||
81 | |||
82 | # S390 Architecture | 106 | # S390 Architecture |
83 | 107 | ||
84 | # SUPERH Architecture | 108 | # SUPERH (sh + sh64) Architecture |
85 | obj-$(CONFIG_SH_WDT) += shwdt.o | 109 | obj-$(CONFIG_SH_WDT) += shwdt.o |
86 | 110 | ||
111 | # SPARC Architecture | ||
112 | |||
87 | # SPARC64 Architecture | 113 | # SPARC64 Architecture |
88 | 114 | ||
115 | # V850 Architecture | ||
116 | |||
117 | # XTENSA Architecture | ||
118 | |||
89 | # Architecture Independant | 119 | # Architecture Independant |
90 | obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o | 120 | obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o |
diff --git a/drivers/char/watchdog/alim1535_wdt.c b/drivers/char/watchdog/alim1535_wdt.c index e3f6a7d0c83d..c404fc69e7e6 100644 --- a/drivers/char/watchdog/alim1535_wdt.c +++ b/drivers/char/watchdog/alim1535_wdt.c | |||
@@ -312,6 +312,7 @@ static int ali_notify_sys(struct notifier_block *this, unsigned long code, void | |||
312 | */ | 312 | */ |
313 | 313 | ||
314 | static struct pci_device_id ali_pci_tbl[] = { | 314 | static struct pci_device_id ali_pci_tbl[] = { |
315 | { PCI_VENDOR_ID_AL, 0x1533, PCI_ANY_ID, PCI_ANY_ID,}, | ||
315 | { PCI_VENDOR_ID_AL, 0x1535, PCI_ANY_ID, PCI_ANY_ID,}, | 316 | { PCI_VENDOR_ID_AL, 0x1535, PCI_ANY_ID, PCI_ANY_ID,}, |
316 | { 0, }, | 317 | { 0, }, |
317 | }; | 318 | }; |
@@ -329,9 +330,11 @@ static int __init ali_find_watchdog(void) | |||
329 | struct pci_dev *pdev; | 330 | struct pci_dev *pdev; |
330 | u32 wdog; | 331 | u32 wdog; |
331 | 332 | ||
332 | /* Check for a 1535 series bridge */ | 333 | /* Check for a 1533/1535 series bridge */ |
333 | pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x1535, NULL); | 334 | pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x1535, NULL); |
334 | if(pdev == NULL) | 335 | if (pdev == NULL) |
336 | pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x1533, NULL); | ||
337 | if (pdev == NULL) | ||
335 | return -ENODEV; | 338 | return -ENODEV; |
336 | pci_dev_put(pdev); | 339 | pci_dev_put(pdev); |
337 | 340 | ||
diff --git a/drivers/char/watchdog/bfin_wdt.c b/drivers/char/watchdog/bfin_wdt.c new file mode 100644 index 000000000000..309d27913fc1 --- /dev/null +++ b/drivers/char/watchdog/bfin_wdt.c | |||
@@ -0,0 +1,490 @@ | |||
1 | /* | ||
2 | * Blackfin On-Chip Watchdog Driver | ||
3 | * Supports BF53[123]/BF53[467]/BF54[2489]/BF561 | ||
4 | * | ||
5 | * Originally based on softdog.c | ||
6 | * Copyright 2006-2007 Analog Devices Inc. | ||
7 | * Copyright 2006-2007 Michele d'Amico | ||
8 | * Copyright 1996 Alan Cox <alan@redhat.com> | ||
9 | * | ||
10 | * Enter bugs at http://blackfin.uclinux.org/ | ||
11 | * | ||
12 | * Licensed under the GPL-2 or later. | ||
13 | */ | ||
14 | |||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/moduleparam.h> | ||
18 | #include <linux/types.h> | ||
19 | #include <linux/timer.h> | ||
20 | #include <linux/miscdevice.h> | ||
21 | #include <linux/watchdog.h> | ||
22 | #include <linux/fs.h> | ||
23 | #include <linux/notifier.h> | ||
24 | #include <linux/reboot.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <asm/blackfin.h> | ||
28 | #include <asm/uaccess.h> | ||
29 | |||
30 | #define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args) | ||
31 | #define stampit() stamp("here i am") | ||
32 | |||
33 | #define WATCHDOG_NAME "bfin-wdt" | ||
34 | #define PFX WATCHDOG_NAME ": " | ||
35 | |||
36 | /* The BF561 has two watchdogs (one per core), but since Linux | ||
37 | * only runs on core A, we'll just work with that one. | ||
38 | */ | ||
39 | #ifdef BF561_FAMILY | ||
40 | # define bfin_read_WDOG_CTL() bfin_read_WDOGA_CTL() | ||
41 | # define bfin_read_WDOG_CNT() bfin_read_WDOGA_CNT() | ||
42 | # define bfin_read_WDOG_STAT() bfin_read_WDOGA_STAT() | ||
43 | # define bfin_write_WDOG_CTL(x) bfin_write_WDOGA_CTL(x) | ||
44 | # define bfin_write_WDOG_CNT(x) bfin_write_WDOGA_CNT(x) | ||
45 | # define bfin_write_WDOG_STAT(x) bfin_write_WDOGA_STAT(x) | ||
46 | #endif | ||
47 | |||
48 | /* Bit in SWRST that indicates boot caused by watchdog */ | ||
49 | #define SWRST_RESET_WDOG 0x4000 | ||
50 | |||
51 | /* Bit in WDOG_CTL that indicates watchdog has expired (WDR0) */ | ||
52 | #define WDOG_EXPIRED 0x8000 | ||
53 | |||
54 | /* Masks for WDEV field in WDOG_CTL register */ | ||
55 | #define ICTL_RESET 0x0 | ||
56 | #define ICTL_NMI 0x2 | ||
57 | #define ICTL_GPI 0x4 | ||
58 | #define ICTL_NONE 0x6 | ||
59 | #define ICTL_MASK 0x6 | ||
60 | |||
61 | /* Masks for WDEN field in WDOG_CTL register */ | ||
62 | #define WDEN_MASK 0x0FF0 | ||
63 | #define WDEN_ENABLE 0x0000 | ||
64 | #define WDEN_DISABLE 0x0AD0 | ||
65 | |||
66 | /* some defaults */ | ||
67 | #define WATCHDOG_TIMEOUT 20 | ||
68 | |||
69 | static unsigned int timeout = WATCHDOG_TIMEOUT; | ||
70 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
71 | static struct watchdog_info bfin_wdt_info; | ||
72 | static unsigned long open_check; | ||
73 | static char expect_close; | ||
74 | static spinlock_t bfin_wdt_spinlock = SPIN_LOCK_UNLOCKED; | ||
75 | |||
76 | /** | ||
77 | * bfin_wdt_keepalive - Keep the Userspace Watchdog Alive | ||
78 | * | ||
79 | * The Userspace watchdog got a KeepAlive: schedule the next timeout. | ||
80 | */ | ||
81 | static int bfin_wdt_keepalive(void) | ||
82 | { | ||
83 | stampit(); | ||
84 | bfin_write_WDOG_STAT(0); | ||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | /** | ||
89 | * bfin_wdt_stop - Stop the Watchdog | ||
90 | * | ||
91 | * Stops the on-chip watchdog. | ||
92 | */ | ||
93 | static int bfin_wdt_stop(void) | ||
94 | { | ||
95 | stampit(); | ||
96 | bfin_write_WDOG_CTL(WDEN_DISABLE); | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | /** | ||
101 | * bfin_wdt_start - Start the Watchdog | ||
102 | * | ||
103 | * Starts the on-chip watchdog. Automatically loads WDOG_CNT | ||
104 | * into WDOG_STAT for us. | ||
105 | */ | ||
106 | static int bfin_wdt_start(void) | ||
107 | { | ||
108 | stampit(); | ||
109 | bfin_write_WDOG_CTL(WDEN_ENABLE | ICTL_RESET); | ||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * bfin_wdt_running - Check Watchdog status | ||
115 | * | ||
116 | * See if the watchdog is running. | ||
117 | */ | ||
118 | static int bfin_wdt_running(void) | ||
119 | { | ||
120 | stampit(); | ||
121 | return ((bfin_read_WDOG_CTL() & WDEN_MASK) != WDEN_DISABLE); | ||
122 | } | ||
123 | |||
124 | /** | ||
125 | * bfin_wdt_set_timeout - Set the Userspace Watchdog timeout | ||
126 | * @t: new timeout value (in seconds) | ||
127 | * | ||
128 | * Translate the specified timeout in seconds into System Clock | ||
129 | * terms which is what the on-chip Watchdog requires. | ||
130 | */ | ||
131 | static int bfin_wdt_set_timeout(unsigned long t) | ||
132 | { | ||
133 | u32 cnt; | ||
134 | unsigned long flags; | ||
135 | |||
136 | stampit(); | ||
137 | |||
138 | cnt = t * get_sclk(); | ||
139 | if (cnt < get_sclk()) { | ||
140 | printk(KERN_WARNING PFX "timeout value is too large\n"); | ||
141 | return -EINVAL; | ||
142 | } | ||
143 | |||
144 | spin_lock_irqsave(&bfin_wdt_spinlock, flags); | ||
145 | { | ||
146 | int run = bfin_wdt_running(); | ||
147 | bfin_wdt_stop(); | ||
148 | bfin_write_WDOG_CNT(cnt); | ||
149 | if (run) bfin_wdt_start(); | ||
150 | } | ||
151 | spin_unlock_irqrestore(&bfin_wdt_spinlock, flags); | ||
152 | |||
153 | timeout = t; | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | /** | ||
159 | * bfin_wdt_open - Open the Device | ||
160 | * @inode: inode of device | ||
161 | * @file: file handle of device | ||
162 | * | ||
163 | * Watchdog device is opened and started. | ||
164 | */ | ||
165 | static int bfin_wdt_open(struct inode *inode, struct file *file) | ||
166 | { | ||
167 | stampit(); | ||
168 | |||
169 | if (test_and_set_bit(0, &open_check)) | ||
170 | return -EBUSY; | ||
171 | |||
172 | if (nowayout) | ||
173 | __module_get(THIS_MODULE); | ||
174 | |||
175 | bfin_wdt_keepalive(); | ||
176 | bfin_wdt_start(); | ||
177 | |||
178 | return nonseekable_open(inode, file); | ||
179 | } | ||
180 | |||
181 | /** | ||
182 | * bfin_wdt_close - Close the Device | ||
183 | * @inode: inode of device | ||
184 | * @file: file handle of device | ||
185 | * | ||
186 | * Watchdog device is closed and stopped. | ||
187 | */ | ||
188 | static int bfin_wdt_release(struct inode *inode, struct file *file) | ||
189 | { | ||
190 | stampit(); | ||
191 | |||
192 | if (expect_close == 42) { | ||
193 | bfin_wdt_stop(); | ||
194 | } else { | ||
195 | printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); | ||
196 | bfin_wdt_keepalive(); | ||
197 | } | ||
198 | |||
199 | expect_close = 0; | ||
200 | clear_bit(0, &open_check); | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | /** | ||
206 | * bfin_wdt_write - Write to Device | ||
207 | * @file: file handle of device | ||
208 | * @buf: buffer to write | ||
209 | * @count: length of buffer | ||
210 | * @ppos: offset | ||
211 | * | ||
212 | * Pings the watchdog on write. | ||
213 | */ | ||
214 | static ssize_t bfin_wdt_write(struct file *file, const char __user *data, | ||
215 | size_t len, loff_t *ppos) | ||
216 | { | ||
217 | stampit(); | ||
218 | |||
219 | if (len) { | ||
220 | if (!nowayout) { | ||
221 | size_t i; | ||
222 | |||
223 | /* In case it was set long ago */ | ||
224 | expect_close = 0; | ||
225 | |||
226 | for (i = 0; i != len; i++) { | ||
227 | char c; | ||
228 | if (get_user(c, data + i)) | ||
229 | return -EFAULT; | ||
230 | if (c == 'V') | ||
231 | expect_close = 42; | ||
232 | } | ||
233 | } | ||
234 | bfin_wdt_keepalive(); | ||
235 | } | ||
236 | |||
237 | return len; | ||
238 | } | ||
239 | |||
240 | /** | ||
241 | * bfin_wdt_ioctl - Query Device | ||
242 | * @inode: inode of device | ||
243 | * @file: file handle of device | ||
244 | * @cmd: watchdog command | ||
245 | * @arg: argument | ||
246 | * | ||
247 | * Query basic information from the device or ping it, as outlined by the | ||
248 | * watchdog API. | ||
249 | */ | ||
250 | static int bfin_wdt_ioctl(struct inode *inode, struct file *file, | ||
251 | unsigned int cmd, unsigned long arg) | ||
252 | { | ||
253 | void __user *argp = (void __user *)arg; | ||
254 | int __user *p = argp; | ||
255 | |||
256 | stampit(); | ||
257 | |||
258 | switch (cmd) { | ||
259 | default: | ||
260 | return -ENOTTY; | ||
261 | |||
262 | case WDIOC_GETSUPPORT: | ||
263 | if (copy_to_user(argp, &bfin_wdt_info, sizeof(bfin_wdt_info))) | ||
264 | return -EFAULT; | ||
265 | else | ||
266 | return 0; | ||
267 | |||
268 | case WDIOC_GETSTATUS: | ||
269 | case WDIOC_GETBOOTSTATUS: | ||
270 | return put_user(!!(_bfin_swrst & SWRST_RESET_WDOG), p); | ||
271 | |||
272 | case WDIOC_KEEPALIVE: | ||
273 | bfin_wdt_keepalive(); | ||
274 | return 0; | ||
275 | |||
276 | case WDIOC_SETTIMEOUT: { | ||
277 | int new_timeout; | ||
278 | |||
279 | if (get_user(new_timeout, p)) | ||
280 | return -EFAULT; | ||
281 | |||
282 | if (bfin_wdt_set_timeout(new_timeout)) | ||
283 | return -EINVAL; | ||
284 | } | ||
285 | /* Fall */ | ||
286 | case WDIOC_GETTIMEOUT: | ||
287 | return put_user(timeout, p); | ||
288 | |||
289 | case WDIOC_SETOPTIONS: { | ||
290 | unsigned long flags; | ||
291 | int options, ret = -EINVAL; | ||
292 | |||
293 | if (get_user(options, p)) | ||
294 | return -EFAULT; | ||
295 | |||
296 | spin_lock_irqsave(&bfin_wdt_spinlock, flags); | ||
297 | |||
298 | if (options & WDIOS_DISABLECARD) { | ||
299 | bfin_wdt_stop(); | ||
300 | ret = 0; | ||
301 | } | ||
302 | |||
303 | if (options & WDIOS_ENABLECARD) { | ||
304 | bfin_wdt_start(); | ||
305 | ret = 0; | ||
306 | } | ||
307 | |||
308 | spin_unlock_irqrestore(&bfin_wdt_spinlock, flags); | ||
309 | |||
310 | return ret; | ||
311 | } | ||
312 | } | ||
313 | } | ||
314 | |||
315 | /** | ||
316 | * bfin_wdt_notify_sys - Notifier Handler | ||
317 | * @this: notifier block | ||
318 | * @code: notifier event | ||
319 | * @unused: unused | ||
320 | * | ||
321 | * Handles specific events, such as turning off the watchdog during a | ||
322 | * shutdown event. | ||
323 | */ | ||
324 | static int bfin_wdt_notify_sys(struct notifier_block *this, unsigned long code, | ||
325 | void *unused) | ||
326 | { | ||
327 | stampit(); | ||
328 | |||
329 | if (code == SYS_DOWN || code == SYS_HALT) | ||
330 | bfin_wdt_stop(); | ||
331 | |||
332 | return NOTIFY_DONE; | ||
333 | } | ||
334 | |||
335 | #ifdef CONFIG_PM | ||
336 | static int state_before_suspend; | ||
337 | |||
338 | /** | ||
339 | * bfin_wdt_suspend - suspend the watchdog | ||
340 | * @pdev: device being suspended | ||
341 | * @state: requested suspend state | ||
342 | * | ||
343 | * Remember if the watchdog was running and stop it. | ||
344 | * TODO: is this even right? Doesn't seem to be any | ||
345 | * standard in the watchdog world ... | ||
346 | */ | ||
347 | static int bfin_wdt_suspend(struct platform_device *pdev, pm_message_t state) | ||
348 | { | ||
349 | stampit(); | ||
350 | |||
351 | state_before_suspend = bfin_wdt_running(); | ||
352 | bfin_wdt_stop(); | ||
353 | |||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | /** | ||
358 | * bfin_wdt_resume - resume the watchdog | ||
359 | * @pdev: device being resumed | ||
360 | * | ||
361 | * If the watchdog was running, turn it back on. | ||
362 | */ | ||
363 | static int bfin_wdt_resume(struct platform_device *pdev) | ||
364 | { | ||
365 | stampit(); | ||
366 | |||
367 | if (state_before_suspend) { | ||
368 | bfin_wdt_set_timeout(timeout); | ||
369 | bfin_wdt_start(); | ||
370 | } | ||
371 | |||
372 | return 0; | ||
373 | } | ||
374 | #else | ||
375 | # define bfin_wdt_suspend NULL | ||
376 | # define bfin_wdt_resume NULL | ||
377 | #endif | ||
378 | |||
379 | static struct platform_device bfin_wdt_device = { | ||
380 | .name = WATCHDOG_NAME, | ||
381 | .id = -1, | ||
382 | }; | ||
383 | |||
384 | static struct platform_driver bfin_wdt_driver = { | ||
385 | .driver = { | ||
386 | .name = WATCHDOG_NAME, | ||
387 | .owner = THIS_MODULE, | ||
388 | }, | ||
389 | .suspend = bfin_wdt_suspend, | ||
390 | .resume = bfin_wdt_resume, | ||
391 | }; | ||
392 | |||
393 | static struct file_operations bfin_wdt_fops = { | ||
394 | .owner = THIS_MODULE, | ||
395 | .llseek = no_llseek, | ||
396 | .write = bfin_wdt_write, | ||
397 | .ioctl = bfin_wdt_ioctl, | ||
398 | .open = bfin_wdt_open, | ||
399 | .release = bfin_wdt_release, | ||
400 | }; | ||
401 | |||
402 | static struct miscdevice bfin_wdt_miscdev = { | ||
403 | .minor = WATCHDOG_MINOR, | ||
404 | .name = "watchdog", | ||
405 | .fops = &bfin_wdt_fops, | ||
406 | }; | ||
407 | |||
408 | static struct watchdog_info bfin_wdt_info = { | ||
409 | .identity = "Blackfin Watchdog", | ||
410 | .options = WDIOF_SETTIMEOUT | | ||
411 | WDIOF_KEEPALIVEPING | | ||
412 | WDIOF_MAGICCLOSE, | ||
413 | }; | ||
414 | |||
415 | static struct notifier_block bfin_wdt_notifier = { | ||
416 | .notifier_call = bfin_wdt_notify_sys, | ||
417 | }; | ||
418 | |||
419 | /** | ||
420 | * bfin_wdt_init - Initialize module | ||
421 | * | ||
422 | * Registers the device and notifier handler. Actual device | ||
423 | * initialization is handled by bfin_wdt_open(). | ||
424 | */ | ||
425 | static int __init bfin_wdt_init(void) | ||
426 | { | ||
427 | int ret; | ||
428 | |||
429 | stampit(); | ||
430 | |||
431 | /* Check that the timeout value is within range */ | ||
432 | if (bfin_wdt_set_timeout(timeout)) | ||
433 | return -EINVAL; | ||
434 | |||
435 | /* Since this is an on-chip device and needs no board-specific | ||
436 | * resources, we'll handle all the platform device stuff here. | ||
437 | */ | ||
438 | ret = platform_device_register(&bfin_wdt_device); | ||
439 | if (ret) | ||
440 | return ret; | ||
441 | |||
442 | ret = platform_driver_probe(&bfin_wdt_driver, NULL); | ||
443 | if (ret) | ||
444 | return ret; | ||
445 | |||
446 | ret = register_reboot_notifier(&bfin_wdt_notifier); | ||
447 | if (ret) { | ||
448 | printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret); | ||
449 | return ret; | ||
450 | } | ||
451 | |||
452 | ret = misc_register(&bfin_wdt_miscdev); | ||
453 | if (ret) { | ||
454 | printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | ||
455 | WATCHDOG_MINOR, ret); | ||
456 | unregister_reboot_notifier(&bfin_wdt_notifier); | ||
457 | return ret; | ||
458 | } | ||
459 | |||
460 | printk(KERN_INFO PFX "initialized: timeout=%d sec (nowayout=%d)\n", | ||
461 | timeout, nowayout); | ||
462 | |||
463 | return 0; | ||
464 | } | ||
465 | |||
466 | /** | ||
467 | * bfin_wdt_exit - Deinitialize module | ||
468 | * | ||
469 | * Unregisters the device and notifier handler. Actual device | ||
470 | * deinitialization is handled by bfin_wdt_close(). | ||
471 | */ | ||
472 | static void __exit bfin_wdt_exit(void) | ||
473 | { | ||
474 | misc_deregister(&bfin_wdt_miscdev); | ||
475 | unregister_reboot_notifier(&bfin_wdt_notifier); | ||
476 | } | ||
477 | |||
478 | module_init(bfin_wdt_init); | ||
479 | module_exit(bfin_wdt_exit); | ||
480 | |||
481 | MODULE_AUTHOR("Michele d'Amico, Mike Frysinger <vapier@gentoo.org>"); | ||
482 | MODULE_DESCRIPTION("Blackfin Watchdog Device Driver"); | ||
483 | MODULE_LICENSE("GPL"); | ||
484 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
485 | |||
486 | module_param(timeout, uint, 0); | ||
487 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=((2^32)/SCLK), default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | ||
488 | |||
489 | module_param(nowayout, int, 0); | ||
490 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
diff --git a/drivers/char/watchdog/booke_wdt.c b/drivers/char/watchdog/booke_wdt.c index 0f5c77ddd39d..d362f5bf658a 100644 --- a/drivers/char/watchdog/booke_wdt.c +++ b/drivers/char/watchdog/booke_wdt.c | |||
@@ -144,7 +144,7 @@ static int booke_wdt_open (struct inode *inode, struct file *file) | |||
144 | booke_wdt_period); | 144 | booke_wdt_period); |
145 | } | 145 | } |
146 | 146 | ||
147 | return 0; | 147 | return nonseekable_open(inode, file); |
148 | } | 148 | } |
149 | 149 | ||
150 | static const struct file_operations booke_wdt_fops = { | 150 | static const struct file_operations booke_wdt_fops = { |
diff --git a/drivers/char/watchdog/cpu5wdt.c b/drivers/char/watchdog/cpu5wdt.c index d0d45a8b09f0..5941ca601a3a 100644 --- a/drivers/char/watchdog/cpu5wdt.c +++ b/drivers/char/watchdog/cpu5wdt.c | |||
@@ -162,6 +162,10 @@ static int cpu5wdt_ioctl(struct inode *inode, struct file *file, unsigned int cm | |||
162 | if ( copy_to_user(argp, &value, sizeof(int)) ) | 162 | if ( copy_to_user(argp, &value, sizeof(int)) ) |
163 | return -EFAULT; | 163 | return -EFAULT; |
164 | break; | 164 | break; |
165 | case WDIOC_GETBOOTSTATUS: | ||
166 | if ( copy_to_user(argp, &value, sizeof(int)) ) | ||
167 | return -EFAULT; | ||
168 | break; | ||
165 | case WDIOC_GETSUPPORT: | 169 | case WDIOC_GETSUPPORT: |
166 | if ( copy_to_user(argp, &ident, sizeof(ident)) ) | 170 | if ( copy_to_user(argp, &ident, sizeof(ident)) ) |
167 | return -EFAULT; | 171 | return -EFAULT; |
diff --git a/drivers/char/watchdog/davinci_wdt.c b/drivers/char/watchdog/davinci_wdt.c new file mode 100644 index 000000000000..19db5302ba6e --- /dev/null +++ b/drivers/char/watchdog/davinci_wdt.c | |||
@@ -0,0 +1,281 @@ | |||
1 | /* | ||
2 | * drivers/char/watchdog/davinci_wdt.c | ||
3 | * | ||
4 | * Watchdog driver for DaVinci DM644x/DM646x processors | ||
5 | * | ||
6 | * Copyright (C) 2006 Texas Instruments. | ||
7 | * | ||
8 | * 2007 (c) MontaVista Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This program | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/moduleparam.h> | ||
16 | #include <linux/types.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/fs.h> | ||
19 | #include <linux/miscdevice.h> | ||
20 | #include <linux/watchdog.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/bitops.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | |||
26 | #include <asm/hardware.h> | ||
27 | #include <asm/uaccess.h> | ||
28 | #include <asm/io.h> | ||
29 | |||
30 | #define MODULE_NAME "DAVINCI-WDT: " | ||
31 | |||
32 | #define DEFAULT_HEARTBEAT 60 | ||
33 | #define MAX_HEARTBEAT 600 /* really the max margin is 264/27MHz*/ | ||
34 | |||
35 | /* Timer register set definition */ | ||
36 | #define PID12 (0x0) | ||
37 | #define EMUMGT (0x4) | ||
38 | #define TIM12 (0x10) | ||
39 | #define TIM34 (0x14) | ||
40 | #define PRD12 (0x18) | ||
41 | #define PRD34 (0x1C) | ||
42 | #define TCR (0x20) | ||
43 | #define TGCR (0x24) | ||
44 | #define WDTCR (0x28) | ||
45 | |||
46 | /* TCR bit definitions */ | ||
47 | #define ENAMODE12_DISABLED (0 << 6) | ||
48 | #define ENAMODE12_ONESHOT (1 << 6) | ||
49 | #define ENAMODE12_PERIODIC (2 << 6) | ||
50 | |||
51 | /* TGCR bit definitions */ | ||
52 | #define TIM12RS_UNRESET (1 << 0) | ||
53 | #define TIM34RS_UNRESET (1 << 1) | ||
54 | #define TIMMODE_64BIT_WDOG (2 << 2) | ||
55 | |||
56 | /* WDTCR bit definitions */ | ||
57 | #define WDEN (1 << 14) | ||
58 | #define WDFLAG (1 << 15) | ||
59 | #define WDKEY_SEQ0 (0xa5c6 << 16) | ||
60 | #define WDKEY_SEQ1 (0xda7e << 16) | ||
61 | |||
62 | static int heartbeat = DEFAULT_HEARTBEAT; | ||
63 | |||
64 | static spinlock_t io_lock; | ||
65 | static unsigned long wdt_status; | ||
66 | #define WDT_IN_USE 0 | ||
67 | #define WDT_OK_TO_CLOSE 1 | ||
68 | #define WDT_REGION_INITED 2 | ||
69 | #define WDT_DEVICE_INITED 3 | ||
70 | |||
71 | static struct resource *wdt_mem; | ||
72 | static void __iomem *wdt_base; | ||
73 | |||
74 | static void wdt_service(void) | ||
75 | { | ||
76 | spin_lock(&io_lock); | ||
77 | |||
78 | /* put watchdog in service state */ | ||
79 | davinci_writel(WDKEY_SEQ0, wdt_base + WDTCR); | ||
80 | /* put watchdog in active state */ | ||
81 | davinci_writel(WDKEY_SEQ1, wdt_base + WDTCR); | ||
82 | |||
83 | spin_unlock(&io_lock); | ||
84 | } | ||
85 | |||
86 | static void wdt_enable(void) | ||
87 | { | ||
88 | u32 tgcr; | ||
89 | u32 timer_margin; | ||
90 | |||
91 | spin_lock(&io_lock); | ||
92 | |||
93 | /* disable, internal clock source */ | ||
94 | davinci_writel(0, wdt_base + TCR); | ||
95 | /* reset timer, set mode to 64-bit watchdog, and unreset */ | ||
96 | davinci_writel(0, wdt_base + TGCR); | ||
97 | tgcr = TIMMODE_64BIT_WDOG | TIM12RS_UNRESET | TIM34RS_UNRESET; | ||
98 | davinci_writel(tgcr, wdt_base + TGCR); | ||
99 | /* clear counter regs */ | ||
100 | davinci_writel(0, wdt_base + TIM12); | ||
101 | davinci_writel(0, wdt_base + TIM34); | ||
102 | /* set timeout period */ | ||
103 | timer_margin = (((u64)heartbeat * CLOCK_TICK_RATE) & 0xffffffff); | ||
104 | davinci_writel(timer_margin, wdt_base + PRD12); | ||
105 | timer_margin = (((u64)heartbeat * CLOCK_TICK_RATE) >> 32); | ||
106 | davinci_writel(timer_margin, wdt_base + PRD34); | ||
107 | /* enable run continuously */ | ||
108 | davinci_writel(ENAMODE12_PERIODIC, wdt_base + TCR); | ||
109 | /* Once the WDT is in pre-active state write to | ||
110 | * TIM12, TIM34, PRD12, PRD34, TCR, TGCR, WDTCR are | ||
111 | * write protected (except for the WDKEY field) | ||
112 | */ | ||
113 | /* put watchdog in pre-active state */ | ||
114 | davinci_writel(WDKEY_SEQ0 | WDEN, wdt_base + WDTCR); | ||
115 | /* put watchdog in active state */ | ||
116 | davinci_writel(WDKEY_SEQ1 | WDEN, wdt_base + WDTCR); | ||
117 | |||
118 | spin_unlock(&io_lock); | ||
119 | } | ||
120 | |||
121 | static int davinci_wdt_open(struct inode *inode, struct file *file) | ||
122 | { | ||
123 | if (test_and_set_bit(WDT_IN_USE, &wdt_status)) | ||
124 | return -EBUSY; | ||
125 | |||
126 | wdt_enable(); | ||
127 | |||
128 | return nonseekable_open(inode, file); | ||
129 | } | ||
130 | |||
131 | static ssize_t | ||
132 | davinci_wdt_write(struct file *file, const char *data, size_t len, | ||
133 | loff_t *ppos) | ||
134 | { | ||
135 | if (len) | ||
136 | wdt_service(); | ||
137 | |||
138 | return len; | ||
139 | } | ||
140 | |||
141 | static struct watchdog_info ident = { | ||
142 | .options = WDIOF_KEEPALIVEPING, | ||
143 | .identity = "DaVinci Watchdog", | ||
144 | }; | ||
145 | |||
146 | static int | ||
147 | davinci_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | ||
148 | unsigned long arg) | ||
149 | { | ||
150 | int ret = -ENOTTY; | ||
151 | |||
152 | switch (cmd) { | ||
153 | case WDIOC_GETSUPPORT: | ||
154 | ret = copy_to_user((struct watchdog_info *)arg, &ident, | ||
155 | sizeof(ident)) ? -EFAULT : 0; | ||
156 | break; | ||
157 | |||
158 | case WDIOC_GETSTATUS: | ||
159 | case WDIOC_GETBOOTSTATUS: | ||
160 | ret = put_user(0, (int *)arg); | ||
161 | break; | ||
162 | |||
163 | case WDIOC_GETTIMEOUT: | ||
164 | ret = put_user(heartbeat, (int *)arg); | ||
165 | break; | ||
166 | |||
167 | case WDIOC_KEEPALIVE: | ||
168 | wdt_service(); | ||
169 | ret = 0; | ||
170 | break; | ||
171 | } | ||
172 | return ret; | ||
173 | } | ||
174 | |||
175 | static int davinci_wdt_release(struct inode *inode, struct file *file) | ||
176 | { | ||
177 | wdt_service(); | ||
178 | clear_bit(WDT_IN_USE, &wdt_status); | ||
179 | |||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | static const struct file_operations davinci_wdt_fops = { | ||
184 | .owner = THIS_MODULE, | ||
185 | .llseek = no_llseek, | ||
186 | .write = davinci_wdt_write, | ||
187 | .ioctl = davinci_wdt_ioctl, | ||
188 | .open = davinci_wdt_open, | ||
189 | .release = davinci_wdt_release, | ||
190 | }; | ||
191 | |||
192 | static struct miscdevice davinci_wdt_miscdev = { | ||
193 | .minor = WATCHDOG_MINOR, | ||
194 | .name = "watchdog", | ||
195 | .fops = &davinci_wdt_fops, | ||
196 | }; | ||
197 | |||
198 | static int davinci_wdt_probe(struct platform_device *pdev) | ||
199 | { | ||
200 | int ret = 0, size; | ||
201 | struct resource *res; | ||
202 | |||
203 | spin_lock_init(&io_lock); | ||
204 | |||
205 | if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT) | ||
206 | heartbeat = DEFAULT_HEARTBEAT; | ||
207 | |||
208 | printk(KERN_INFO MODULE_NAME | ||
209 | "DaVinci Watchdog Timer: heartbeat %d sec\n", heartbeat); | ||
210 | |||
211 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
212 | if (res == NULL) { | ||
213 | printk(KERN_INFO MODULE_NAME | ||
214 | "failed to get memory region resource\n"); | ||
215 | return -ENOENT; | ||
216 | } | ||
217 | |||
218 | size = res->end - res->start + 1; | ||
219 | wdt_mem = request_mem_region(res->start, size, pdev->name); | ||
220 | |||
221 | if (wdt_mem == NULL) { | ||
222 | printk(KERN_INFO MODULE_NAME "failed to get memory region\n"); | ||
223 | return -ENOENT; | ||
224 | } | ||
225 | wdt_base = (void __iomem *)(res->start); | ||
226 | |||
227 | ret = misc_register(&davinci_wdt_miscdev); | ||
228 | if (ret < 0) { | ||
229 | printk(KERN_ERR MODULE_NAME "cannot register misc device\n"); | ||
230 | release_resource(wdt_mem); | ||
231 | kfree(wdt_mem); | ||
232 | } else { | ||
233 | set_bit(WDT_DEVICE_INITED, &wdt_status); | ||
234 | } | ||
235 | |||
236 | return ret; | ||
237 | } | ||
238 | |||
239 | static int davinci_wdt_remove(struct platform_device *pdev) | ||
240 | { | ||
241 | misc_deregister(&davinci_wdt_miscdev); | ||
242 | if (wdt_mem) { | ||
243 | release_resource(wdt_mem); | ||
244 | kfree(wdt_mem); | ||
245 | wdt_mem = NULL; | ||
246 | } | ||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | static struct platform_driver platform_wdt_driver = { | ||
251 | .driver = { | ||
252 | .name = "watchdog", | ||
253 | }, | ||
254 | .probe = davinci_wdt_probe, | ||
255 | .remove = davinci_wdt_remove, | ||
256 | }; | ||
257 | |||
258 | static int __init davinci_wdt_init(void) | ||
259 | { | ||
260 | return platform_driver_register(&platform_wdt_driver); | ||
261 | } | ||
262 | |||
263 | static void __exit davinci_wdt_exit(void) | ||
264 | { | ||
265 | return platform_driver_unregister(&platform_wdt_driver); | ||
266 | } | ||
267 | |||
268 | module_init(davinci_wdt_init); | ||
269 | module_exit(davinci_wdt_exit); | ||
270 | |||
271 | MODULE_AUTHOR("Texas Instruments"); | ||
272 | MODULE_DESCRIPTION("DaVinci Watchdog Driver"); | ||
273 | |||
274 | module_param(heartbeat, int, 0); | ||
275 | MODULE_PARM_DESC(heartbeat, | ||
276 | "Watchdog heartbeat period in seconds from 1 to " | ||
277 | __MODULE_STRING(MAX_HEARTBEAT) ", default " | ||
278 | __MODULE_STRING(DEFAULT_HEARTBEAT)); | ||
279 | |||
280 | MODULE_LICENSE("GPL"); | ||
281 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
diff --git a/drivers/char/watchdog/eurotechwdt.c b/drivers/char/watchdog/eurotechwdt.c index b070324e27a6..b14e9d1f164d 100644 --- a/drivers/char/watchdog/eurotechwdt.c +++ b/drivers/char/watchdog/eurotechwdt.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Eurotech CPU-1220/1410 on board WDT driver | 2 | * Eurotech CPU-1220/1410/1420 on board WDT driver |
3 | * | 3 | * |
4 | * (c) Copyright 2001 Ascensit <support@ascensit.com> | 4 | * (c) Copyright 2001 Ascensit <support@ascensit.com> |
5 | * (c) Copyright 2001 Rodolfo Giometti <giometti@ascensit.com> | 5 | * (c) Copyright 2001 Rodolfo Giometti <giometti@ascensit.com> |
@@ -25,6 +25,9 @@ | |||
25 | 25 | ||
26 | /* Changelog: | 26 | /* Changelog: |
27 | * | 27 | * |
28 | * 2001 - Rodolfo Giometti | ||
29 | * Initial release | ||
30 | * | ||
28 | * 2002/04/25 - Rob Radez | 31 | * 2002/04/25 - Rob Radez |
29 | * clean up #includes | 32 | * clean up #includes |
30 | * clean up locking | 33 | * clean up locking |
@@ -33,13 +36,15 @@ | |||
33 | * add WDIOC_GETSTATUS and WDIOC_SETOPTIONS ioctls | 36 | * add WDIOC_GETSTATUS and WDIOC_SETOPTIONS ioctls |
34 | * add expect_close support | 37 | * add expect_close support |
35 | * | 38 | * |
36 | * 2001 - Rodolfo Giometti | ||
37 | * Initial release | ||
38 | * | ||
39 | * 2002.05.30 - Joel Becker <joel.becker@oracle.com> | 39 | * 2002.05.30 - Joel Becker <joel.becker@oracle.com> |
40 | * Added Matt Domsch's nowayout module option. | 40 | * Added Matt Domsch's nowayout module option. |
41 | */ | 41 | */ |
42 | 42 | ||
43 | /* | ||
44 | * The eurotech CPU-1220/1410/1420's watchdog is a part | ||
45 | * of the on-board SUPER I/O device SMSC FDC 37B782. | ||
46 | */ | ||
47 | |||
43 | #include <linux/interrupt.h> | 48 | #include <linux/interrupt.h> |
44 | #include <linux/module.h> | 49 | #include <linux/module.h> |
45 | #include <linux/moduleparam.h> | 50 | #include <linux/moduleparam.h> |
diff --git a/drivers/char/watchdog/iTCO_wdt.c b/drivers/char/watchdog/iTCO_wdt.c index eac4f9b9f007..cd5a565bc3a0 100644 --- a/drivers/char/watchdog/iTCO_wdt.c +++ b/drivers/char/watchdog/iTCO_wdt.c | |||
@@ -39,7 +39,12 @@ | |||
39 | * 82801HR (ICH8R) : document number 313056-002, 313057-004, | 39 | * 82801HR (ICH8R) : document number 313056-002, 313057-004, |
40 | * 82801HH (ICH8DH) : document number 313056-002, 313057-004, | 40 | * 82801HH (ICH8DH) : document number 313056-002, 313057-004, |
41 | * 82801HO (ICH8DO) : document number 313056-002, 313057-004, | 41 | * 82801HO (ICH8DO) : document number 313056-002, 313057-004, |
42 | * 6300ESB (6300ESB) : document number 300641-003 | 42 | * 82801IB (ICH9) : document number 316972-001, 316973-001, |
43 | * 82801IR (ICH9R) : document number 316972-001, 316973-001, | ||
44 | * 82801IH (ICH9DH) : document number 316972-001, 316973-001, | ||
45 | * 6300ESB (6300ESB) : document number 300641-003, 300884-010, | ||
46 | * 631xESB (631xESB) : document number 313082-001, 313075-005, | ||
47 | * 632xESB (632xESB) : document number 313082-001, 313075-005 | ||
43 | */ | 48 | */ |
44 | 49 | ||
45 | /* | 50 | /* |
@@ -48,8 +53,8 @@ | |||
48 | 53 | ||
49 | /* Module and version information */ | 54 | /* Module and version information */ |
50 | #define DRV_NAME "iTCO_wdt" | 55 | #define DRV_NAME "iTCO_wdt" |
51 | #define DRV_VERSION "1.01" | 56 | #define DRV_VERSION "1.02" |
52 | #define DRV_RELDATE "21-Jan-2007" | 57 | #define DRV_RELDATE "26-Jul-2007" |
53 | #define PFX DRV_NAME ": " | 58 | #define PFX DRV_NAME ": " |
54 | 59 | ||
55 | /* Includes */ | 60 | /* Includes */ |
@@ -92,6 +97,10 @@ enum iTCO_chipsets { | |||
92 | TCO_ICH8, /* ICH8 & ICH8R */ | 97 | TCO_ICH8, /* ICH8 & ICH8R */ |
93 | TCO_ICH8DH, /* ICH8DH */ | 98 | TCO_ICH8DH, /* ICH8DH */ |
94 | TCO_ICH8DO, /* ICH8DO */ | 99 | TCO_ICH8DO, /* ICH8DO */ |
100 | TCO_ICH9, /* ICH9 */ | ||
101 | TCO_ICH9R, /* ICH9R */ | ||
102 | TCO_ICH9DH, /* ICH9DH */ | ||
103 | TCO_631XESB, /* 631xESB/632xESB */ | ||
95 | }; | 104 | }; |
96 | 105 | ||
97 | static struct { | 106 | static struct { |
@@ -118,6 +127,10 @@ static struct { | |||
118 | {"ICH8 or ICH8R", 2}, | 127 | {"ICH8 or ICH8R", 2}, |
119 | {"ICH8DH", 2}, | 128 | {"ICH8DH", 2}, |
120 | {"ICH8DO", 2}, | 129 | {"ICH8DO", 2}, |
130 | {"ICH9", 2}, | ||
131 | {"ICH9R", 2}, | ||
132 | {"ICH9DH", 2}, | ||
133 | {"631xESB/632xESB", 2}, | ||
121 | {NULL,0} | 134 | {NULL,0} |
122 | }; | 135 | }; |
123 | 136 | ||
@@ -148,6 +161,25 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = { | |||
148 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8 }, | 161 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8 }, |
149 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DH }, | 162 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DH }, |
150 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DO }, | 163 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DO }, |
164 | { PCI_VENDOR_ID_INTEL, 0x2918, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9 }, | ||
165 | { PCI_VENDOR_ID_INTEL, 0x2916, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9R }, | ||
166 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9DH }, | ||
167 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, | ||
168 | { PCI_VENDOR_ID_INTEL, 0x2671, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, | ||
169 | { PCI_VENDOR_ID_INTEL, 0x2672, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, | ||
170 | { PCI_VENDOR_ID_INTEL, 0x2673, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, | ||
171 | { PCI_VENDOR_ID_INTEL, 0x2674, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, | ||
172 | { PCI_VENDOR_ID_INTEL, 0x2675, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, | ||
173 | { PCI_VENDOR_ID_INTEL, 0x2676, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, | ||
174 | { PCI_VENDOR_ID_INTEL, 0x2677, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, | ||
175 | { PCI_VENDOR_ID_INTEL, 0x2678, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, | ||
176 | { PCI_VENDOR_ID_INTEL, 0x2679, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, | ||
177 | { PCI_VENDOR_ID_INTEL, 0x267a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, | ||
178 | { PCI_VENDOR_ID_INTEL, 0x267b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, | ||
179 | { PCI_VENDOR_ID_INTEL, 0x267c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, | ||
180 | { PCI_VENDOR_ID_INTEL, 0x267d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, | ||
181 | { PCI_VENDOR_ID_INTEL, 0x267e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, | ||
182 | { PCI_VENDOR_ID_INTEL, 0x267f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, | ||
151 | { 0, }, /* End of list */ | 183 | { 0, }, /* End of list */ |
152 | }; | 184 | }; |
153 | MODULE_DEVICE_TABLE (pci, iTCO_wdt_pci_tbl); | 185 | MODULE_DEVICE_TABLE (pci, iTCO_wdt_pci_tbl); |
diff --git a/drivers/char/watchdog/iop_wdt.c b/drivers/char/watchdog/iop_wdt.c new file mode 100644 index 000000000000..bbbd91af754d --- /dev/null +++ b/drivers/char/watchdog/iop_wdt.c | |||
@@ -0,0 +1,262 @@ | |||
1 | /* | ||
2 | * drivers/char/watchdog/iop_wdt.c | ||
3 | * | ||
4 | * WDT driver for Intel I/O Processors | ||
5 | * Copyright (C) 2005, Intel Corporation. | ||
6 | * | ||
7 | * Based on ixp4xx driver, Copyright 2004 (c) MontaVista, Software, Inc. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms and conditions of the GNU General Public License, | ||
11 | * version 2, as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along with | ||
19 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple | ||
20 | * Place - Suite 330, Boston, MA 02111-1307 USA. | ||
21 | * | ||
22 | * Curt E Bruns <curt.e.bruns@intel.com> | ||
23 | * Peter Milne <peter.milne@d-tacq.com> | ||
24 | * Dan Williams <dan.j.williams@intel.com> | ||
25 | */ | ||
26 | |||
27 | #include <linux/module.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/fs.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/device.h> | ||
32 | #include <linux/miscdevice.h> | ||
33 | #include <linux/watchdog.h> | ||
34 | #include <linux/uaccess.h> | ||
35 | #include <asm/hardware.h> | ||
36 | |||
37 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
38 | static unsigned long wdt_status; | ||
39 | static unsigned long boot_status; | ||
40 | |||
41 | #define WDT_IN_USE 0 | ||
42 | #define WDT_OK_TO_CLOSE 1 | ||
43 | #define WDT_ENABLED 2 | ||
44 | |||
45 | static unsigned long iop_watchdog_timeout(void) | ||
46 | { | ||
47 | return (0xffffffffUL / get_iop_tick_rate()); | ||
48 | } | ||
49 | |||
50 | /** | ||
51 | * wdt_supports_disable - determine if we are accessing a iop13xx watchdog | ||
52 | * or iop3xx by whether it has a disable command | ||
53 | */ | ||
54 | static int wdt_supports_disable(void) | ||
55 | { | ||
56 | int can_disable; | ||
57 | |||
58 | if (IOP_WDTCR_EN_ARM != IOP_WDTCR_DIS_ARM) | ||
59 | can_disable = 1; | ||
60 | else | ||
61 | can_disable = 0; | ||
62 | |||
63 | return can_disable; | ||
64 | } | ||
65 | |||
66 | static void wdt_enable(void) | ||
67 | { | ||
68 | /* Arm and enable the Timer to starting counting down from 0xFFFF.FFFF | ||
69 | * Takes approx. 10.7s to timeout | ||
70 | */ | ||
71 | write_wdtcr(IOP_WDTCR_EN_ARM); | ||
72 | write_wdtcr(IOP_WDTCR_EN); | ||
73 | } | ||
74 | |||
75 | /* returns 0 if the timer was successfully disabled */ | ||
76 | static int wdt_disable(void) | ||
77 | { | ||
78 | /* Stop Counting */ | ||
79 | if (wdt_supports_disable()) { | ||
80 | write_wdtcr(IOP_WDTCR_DIS_ARM); | ||
81 | write_wdtcr(IOP_WDTCR_DIS); | ||
82 | clear_bit(WDT_ENABLED, &wdt_status); | ||
83 | printk(KERN_INFO "WATCHDOG: Disabled\n"); | ||
84 | return 0; | ||
85 | } else | ||
86 | return 1; | ||
87 | } | ||
88 | |||
89 | static int iop_wdt_open(struct inode *inode, struct file *file) | ||
90 | { | ||
91 | if (test_and_set_bit(WDT_IN_USE, &wdt_status)) | ||
92 | return -EBUSY; | ||
93 | |||
94 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
95 | |||
96 | wdt_enable(); | ||
97 | |||
98 | set_bit(WDT_ENABLED, &wdt_status); | ||
99 | |||
100 | return nonseekable_open(inode, file); | ||
101 | } | ||
102 | |||
103 | static ssize_t | ||
104 | iop_wdt_write(struct file *file, const char *data, size_t len, | ||
105 | loff_t *ppos) | ||
106 | { | ||
107 | if (len) { | ||
108 | if (!nowayout) { | ||
109 | size_t i; | ||
110 | |||
111 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
112 | |||
113 | for (i = 0; i != len; i++) { | ||
114 | char c; | ||
115 | |||
116 | if (get_user(c, data + i)) | ||
117 | return -EFAULT; | ||
118 | if (c == 'V') | ||
119 | set_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
120 | } | ||
121 | } | ||
122 | wdt_enable(); | ||
123 | } | ||
124 | |||
125 | return len; | ||
126 | } | ||
127 | |||
128 | static struct watchdog_info ident = { | ||
129 | .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, | ||
130 | .identity = "iop watchdog", | ||
131 | }; | ||
132 | |||
133 | static int | ||
134 | iop_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | ||
135 | unsigned long arg) | ||
136 | { | ||
137 | int options; | ||
138 | int ret = -ENOTTY; | ||
139 | |||
140 | switch (cmd) { | ||
141 | case WDIOC_GETSUPPORT: | ||
142 | if (copy_to_user | ||
143 | ((struct watchdog_info *)arg, &ident, sizeof ident)) | ||
144 | ret = -EFAULT; | ||
145 | else | ||
146 | ret = 0; | ||
147 | break; | ||
148 | |||
149 | case WDIOC_GETSTATUS: | ||
150 | ret = put_user(0, (int *)arg); | ||
151 | break; | ||
152 | |||
153 | case WDIOC_GETBOOTSTATUS: | ||
154 | ret = put_user(boot_status, (int *)arg); | ||
155 | break; | ||
156 | |||
157 | case WDIOC_GETTIMEOUT: | ||
158 | ret = put_user(iop_watchdog_timeout(), (int *)arg); | ||
159 | break; | ||
160 | |||
161 | case WDIOC_KEEPALIVE: | ||
162 | wdt_enable(); | ||
163 | ret = 0; | ||
164 | break; | ||
165 | |||
166 | case WDIOC_SETOPTIONS: | ||
167 | if (get_user(options, (int *)arg)) | ||
168 | return -EFAULT; | ||
169 | |||
170 | if (options & WDIOS_DISABLECARD) { | ||
171 | if (!nowayout) { | ||
172 | if (wdt_disable() == 0) { | ||
173 | set_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
174 | ret = 0; | ||
175 | } else | ||
176 | ret = -ENXIO; | ||
177 | } else | ||
178 | ret = 0; | ||
179 | } | ||
180 | |||
181 | if (options & WDIOS_ENABLECARD) { | ||
182 | wdt_enable(); | ||
183 | ret = 0; | ||
184 | } | ||
185 | break; | ||
186 | } | ||
187 | |||
188 | return ret; | ||
189 | } | ||
190 | |||
191 | static int iop_wdt_release(struct inode *inode, struct file *file) | ||
192 | { | ||
193 | int state = 1; | ||
194 | if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) | ||
195 | if (test_bit(WDT_ENABLED, &wdt_status)) | ||
196 | state = wdt_disable(); | ||
197 | |||
198 | /* if the timer is not disbaled reload and notify that we are still | ||
199 | * going down | ||
200 | */ | ||
201 | if (state != 0) { | ||
202 | wdt_enable(); | ||
203 | printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - " | ||
204 | "reset in %lu seconds\n", iop_watchdog_timeout()); | ||
205 | } | ||
206 | |||
207 | clear_bit(WDT_IN_USE, &wdt_status); | ||
208 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
209 | |||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | static const struct file_operations iop_wdt_fops = { | ||
214 | .owner = THIS_MODULE, | ||
215 | .llseek = no_llseek, | ||
216 | .write = iop_wdt_write, | ||
217 | .ioctl = iop_wdt_ioctl, | ||
218 | .open = iop_wdt_open, | ||
219 | .release = iop_wdt_release, | ||
220 | }; | ||
221 | |||
222 | static struct miscdevice iop_wdt_miscdev = { | ||
223 | .minor = WATCHDOG_MINOR, | ||
224 | .name = "watchdog", | ||
225 | .fops = &iop_wdt_fops, | ||
226 | }; | ||
227 | |||
228 | static int __init iop_wdt_init(void) | ||
229 | { | ||
230 | int ret; | ||
231 | |||
232 | ret = misc_register(&iop_wdt_miscdev); | ||
233 | if (ret == 0) | ||
234 | printk("iop watchdog timer: timeout %lu sec\n", | ||
235 | iop_watchdog_timeout()); | ||
236 | |||
237 | /* check if the reset was caused by the watchdog timer */ | ||
238 | boot_status = (read_rcsr() & IOP_RCSR_WDT) ? WDIOF_CARDRESET : 0; | ||
239 | |||
240 | /* Configure Watchdog Timeout to cause an Internal Bus (IB) Reset | ||
241 | * NOTE: An IB Reset will Reset both cores in the IOP342 | ||
242 | */ | ||
243 | write_wdtsr(IOP13XX_WDTCR_IB_RESET); | ||
244 | |||
245 | return ret; | ||
246 | } | ||
247 | |||
248 | static void __exit iop_wdt_exit(void) | ||
249 | { | ||
250 | misc_deregister(&iop_wdt_miscdev); | ||
251 | } | ||
252 | |||
253 | module_init(iop_wdt_init); | ||
254 | module_exit(iop_wdt_exit); | ||
255 | |||
256 | module_param(nowayout, int, 0); | ||
257 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); | ||
258 | |||
259 | MODULE_AUTHOR("Curt E Bruns <curt.e.bruns@intel.com>"); | ||
260 | MODULE_DESCRIPTION("iop watchdog timer driver"); | ||
261 | MODULE_LICENSE("GPL"); | ||
262 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
diff --git a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c index a0d27160c80e..6d35bb112a5f 100644 --- a/drivers/char/watchdog/machzwd.c +++ b/drivers/char/watchdog/machzwd.c | |||
@@ -321,6 +321,7 @@ static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
321 | break; | 321 | break; |
322 | 322 | ||
323 | case WDIOC_GETSTATUS: | 323 | case WDIOC_GETSTATUS: |
324 | case WDIOC_GETBOOTSTATUS: | ||
324 | return put_user(0, p); | 325 | return put_user(0, p); |
325 | 326 | ||
326 | case WDIOC_KEEPALIVE: | 327 | case WDIOC_KEEPALIVE: |
diff --git a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c index db2ccb864412..1adf1d56027d 100644 --- a/drivers/char/watchdog/mixcomwd.c +++ b/drivers/char/watchdog/mixcomwd.c | |||
@@ -215,6 +215,11 @@ static int mixcomwd_ioctl(struct inode *inode, struct file *file, | |||
215 | return -EFAULT; | 215 | return -EFAULT; |
216 | } | 216 | } |
217 | break; | 217 | break; |
218 | case WDIOC_GETBOOTSTATUS: | ||
219 | if (copy_to_user(p, &status, sizeof(int))) { | ||
220 | return -EFAULT; | ||
221 | } | ||
222 | break; | ||
218 | case WDIOC_GETSUPPORT: | 223 | case WDIOC_GETSUPPORT: |
219 | if (copy_to_user(argp, &ident, sizeof(ident))) { | 224 | if (copy_to_user(argp, &ident, sizeof(ident))) { |
220 | return -EFAULT; | 225 | return -EFAULT; |
diff --git a/drivers/char/watchdog/mpc5200_wdt.c b/drivers/char/watchdog/mpc5200_wdt.c new file mode 100644 index 000000000000..564143d40610 --- /dev/null +++ b/drivers/char/watchdog/mpc5200_wdt.c | |||
@@ -0,0 +1,286 @@ | |||
1 | #include <linux/init.h> | ||
2 | #include <linux/module.h> | ||
3 | #include <linux/miscdevice.h> | ||
4 | #include <linux/watchdog.h> | ||
5 | #include <linux/io.h> | ||
6 | #include <linux/spinlock.h> | ||
7 | #include <asm/of_platform.h> | ||
8 | #include <asm/uaccess.h> | ||
9 | #include <asm/mpc52xx.h> | ||
10 | |||
11 | |||
12 | #define GPT_MODE_WDT (1<<15) | ||
13 | #define GPT_MODE_CE (1<<12) | ||
14 | #define GPT_MODE_MS_TIMER (0x4) | ||
15 | |||
16 | |||
17 | struct mpc5200_wdt { | ||
18 | unsigned count; /* timer ticks before watchdog kicks in */ | ||
19 | long ipb_freq; | ||
20 | struct miscdevice miscdev; | ||
21 | struct resource mem; | ||
22 | struct mpc52xx_gpt __iomem *regs; | ||
23 | spinlock_t io_lock; | ||
24 | }; | ||
25 | |||
26 | /* is_active stores wether or not the /dev/watchdog device is opened */ | ||
27 | static unsigned long is_active; | ||
28 | |||
29 | /* misc devices don't provide a way, to get back to 'dev' or 'miscdev' from | ||
30 | * file operations, which sucks. But there can be max 1 watchdog anyway, so... | ||
31 | */ | ||
32 | static struct mpc5200_wdt *wdt_global; | ||
33 | |||
34 | |||
35 | /* helper to calculate timeout in timer counts */ | ||
36 | static void mpc5200_wdt_set_timeout(struct mpc5200_wdt *wdt, int timeout) | ||
37 | { | ||
38 | /* use biggest prescaler of 64k */ | ||
39 | wdt->count = (wdt->ipb_freq + 0xffff) / 0x10000 * timeout; | ||
40 | |||
41 | if (wdt->count > 0xffff) | ||
42 | wdt->count = 0xffff; | ||
43 | } | ||
44 | /* return timeout in seconds (calculated from timer count) */ | ||
45 | static int mpc5200_wdt_get_timeout(struct mpc5200_wdt *wdt) | ||
46 | { | ||
47 | return wdt->count * 0x10000 / wdt->ipb_freq; | ||
48 | } | ||
49 | |||
50 | |||
51 | /* watchdog operations */ | ||
52 | static int mpc5200_wdt_start(struct mpc5200_wdt *wdt) | ||
53 | { | ||
54 | spin_lock(&wdt->io_lock); | ||
55 | /* disable */ | ||
56 | out_be32(&wdt->regs->mode, 0); | ||
57 | /* set timeout, with maximum prescaler */ | ||
58 | out_be32(&wdt->regs->count, 0x0 | wdt->count); | ||
59 | /* enable watchdog */ | ||
60 | out_be32(&wdt->regs->mode, GPT_MODE_CE | GPT_MODE_WDT | GPT_MODE_MS_TIMER); | ||
61 | spin_unlock(&wdt->io_lock); | ||
62 | |||
63 | return 0; | ||
64 | } | ||
65 | static int mpc5200_wdt_ping(struct mpc5200_wdt *wdt) | ||
66 | { | ||
67 | spin_lock(&wdt->io_lock); | ||
68 | /* writing A5 to OCPW resets the watchdog */ | ||
69 | out_be32(&wdt->regs->mode, 0xA5000000 | (0xffffff & in_be32(&wdt->regs->mode))); | ||
70 | spin_unlock(&wdt->io_lock); | ||
71 | return 0; | ||
72 | } | ||
73 | static int mpc5200_wdt_stop(struct mpc5200_wdt *wdt) | ||
74 | { | ||
75 | spin_lock(&wdt->io_lock); | ||
76 | /* disable */ | ||
77 | out_be32(&wdt->regs->mode, 0); | ||
78 | spin_unlock(&wdt->io_lock); | ||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | |||
83 | /* file operations */ | ||
84 | static ssize_t mpc5200_wdt_write(struct file *file, const char *data, | ||
85 | size_t len, loff_t *ppos) | ||
86 | { | ||
87 | struct mpc5200_wdt *wdt = file->private_data; | ||
88 | mpc5200_wdt_ping(wdt); | ||
89 | return 0; | ||
90 | } | ||
91 | static struct watchdog_info mpc5200_wdt_info = { | ||
92 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, | ||
93 | .identity = "mpc5200 watchdog on GPT0", | ||
94 | }; | ||
95 | static int mpc5200_wdt_ioctl(struct inode *inode, struct file *file, | ||
96 | unsigned int cmd, unsigned long arg) | ||
97 | { | ||
98 | struct mpc5200_wdt *wdt = file->private_data; | ||
99 | int __user *data = (int __user *)arg; | ||
100 | int timeout; | ||
101 | int ret = 0; | ||
102 | |||
103 | switch (cmd) { | ||
104 | case WDIOC_GETSUPPORT: | ||
105 | ret = copy_to_user(data, &mpc5200_wdt_info, | ||
106 | sizeof(mpc5200_wdt_info)); | ||
107 | if (ret) | ||
108 | ret = -EFAULT; | ||
109 | break; | ||
110 | |||
111 | case WDIOC_GETSTATUS: | ||
112 | case WDIOC_GETBOOTSTATUS: | ||
113 | ret = put_user(0, data); | ||
114 | break; | ||
115 | |||
116 | case WDIOC_KEEPALIVE: | ||
117 | mpc5200_wdt_ping(wdt); | ||
118 | break; | ||
119 | |||
120 | case WDIOC_SETTIMEOUT: | ||
121 | ret = get_user(timeout, data); | ||
122 | if (ret) | ||
123 | break; | ||
124 | mpc5200_wdt_set_timeout(wdt, timeout); | ||
125 | mpc5200_wdt_start(wdt); | ||
126 | /* fall through and return the timeout */ | ||
127 | |||
128 | case WDIOC_GETTIMEOUT: | ||
129 | timeout = mpc5200_wdt_get_timeout(wdt); | ||
130 | ret = put_user(timeout, data); | ||
131 | break; | ||
132 | |||
133 | default: | ||
134 | ret = -ENOTTY; | ||
135 | } | ||
136 | return ret; | ||
137 | } | ||
138 | static int mpc5200_wdt_open(struct inode *inode, struct file *file) | ||
139 | { | ||
140 | /* /dev/watchdog can only be opened once */ | ||
141 | if (test_and_set_bit(0, &is_active)) | ||
142 | return -EBUSY; | ||
143 | |||
144 | /* Set and activate the watchdog */ | ||
145 | mpc5200_wdt_set_timeout(wdt_global, 30); | ||
146 | mpc5200_wdt_start(wdt_global); | ||
147 | file->private_data = wdt_global; | ||
148 | return nonseekable_open(inode, file); | ||
149 | } | ||
150 | static int mpc5200_wdt_release(struct inode *inode, struct file *file) | ||
151 | { | ||
152 | #if WATCHDOG_NOWAYOUT == 0 | ||
153 | struct mpc5200_wdt *wdt = file->private_data; | ||
154 | mpc5200_wdt_stop(wdt); | ||
155 | wdt->count = 0; /* == disabled */ | ||
156 | #endif | ||
157 | clear_bit(0, &is_active); | ||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static struct file_operations mpc5200_wdt_fops = { | ||
162 | .owner = THIS_MODULE, | ||
163 | .write = mpc5200_wdt_write, | ||
164 | .ioctl = mpc5200_wdt_ioctl, | ||
165 | .open = mpc5200_wdt_open, | ||
166 | .release = mpc5200_wdt_release, | ||
167 | }; | ||
168 | |||
169 | /* module operations */ | ||
170 | static int mpc5200_wdt_probe(struct of_device *op, const struct of_device_id *match) | ||
171 | { | ||
172 | struct mpc5200_wdt *wdt; | ||
173 | int err; | ||
174 | const void *has_wdt; | ||
175 | int size; | ||
176 | |||
177 | has_wdt = of_get_property(op->node, "has-wdt", NULL); | ||
178 | if (!has_wdt) | ||
179 | return -ENODEV; | ||
180 | |||
181 | wdt = kzalloc(sizeof(*wdt), GFP_KERNEL); | ||
182 | if (!wdt) | ||
183 | return -ENOMEM; | ||
184 | |||
185 | wdt->ipb_freq = mpc52xx_find_ipb_freq(op->node); | ||
186 | |||
187 | err = of_address_to_resource(op->node, 0, &wdt->mem); | ||
188 | if (err) | ||
189 | goto out_free; | ||
190 | size = wdt->mem.end - wdt->mem.start + 1; | ||
191 | if (!request_mem_region(wdt->mem.start, size, "mpc5200_wdt")) { | ||
192 | err = -ENODEV; | ||
193 | goto out_free; | ||
194 | } | ||
195 | wdt->regs = ioremap(wdt->mem.start, size); | ||
196 | if (!wdt->regs) { | ||
197 | err = -ENODEV; | ||
198 | goto out_release; | ||
199 | } | ||
200 | |||
201 | dev_set_drvdata(&op->dev, wdt); | ||
202 | spin_lock_init(&wdt->io_lock); | ||
203 | |||
204 | wdt->miscdev = (struct miscdevice) { | ||
205 | .minor = WATCHDOG_MINOR, | ||
206 | .name = "watchdog", | ||
207 | .fops = &mpc5200_wdt_fops, | ||
208 | .parent = &op->dev, | ||
209 | }; | ||
210 | wdt_global = wdt; | ||
211 | err = misc_register(&wdt->miscdev); | ||
212 | if (!err) | ||
213 | return 0; | ||
214 | |||
215 | iounmap(wdt->regs); | ||
216 | out_release: | ||
217 | release_mem_region(wdt->mem.start, size); | ||
218 | out_free: | ||
219 | kfree(wdt); | ||
220 | return err; | ||
221 | } | ||
222 | |||
223 | static int mpc5200_wdt_remove(struct of_device *op) | ||
224 | { | ||
225 | struct mpc5200_wdt *wdt = dev_get_drvdata(&op->dev); | ||
226 | |||
227 | mpc5200_wdt_stop(wdt); | ||
228 | misc_deregister(&wdt->miscdev); | ||
229 | iounmap(wdt->regs); | ||
230 | release_mem_region(wdt->mem.start, wdt->mem.end - wdt->mem.start + 1); | ||
231 | kfree(wdt); | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | static int mpc5200_wdt_suspend(struct of_device *op, pm_message_t state) | ||
236 | { | ||
237 | struct mpc5200_wdt *wdt = dev_get_drvdata(&op->dev); | ||
238 | mpc5200_wdt_stop(wdt); | ||
239 | return 0; | ||
240 | } | ||
241 | static int mpc5200_wdt_resume(struct of_device *op) | ||
242 | { | ||
243 | struct mpc5200_wdt *wdt = dev_get_drvdata(&op->dev); | ||
244 | if (wdt->count) | ||
245 | mpc5200_wdt_start(wdt); | ||
246 | return 0; | ||
247 | } | ||
248 | static int mpc5200_wdt_shutdown(struct of_device *op) | ||
249 | { | ||
250 | struct mpc5200_wdt *wdt = dev_get_drvdata(&op->dev); | ||
251 | mpc5200_wdt_stop(wdt); | ||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | static struct of_device_id mpc5200_wdt_match[] = { | ||
256 | { .compatible = "mpc5200-gpt", }, | ||
257 | {}, | ||
258 | }; | ||
259 | static struct of_platform_driver mpc5200_wdt_driver = { | ||
260 | .owner = THIS_MODULE, | ||
261 | .name = "mpc5200-gpt-wdt", | ||
262 | .match_table = mpc5200_wdt_match, | ||
263 | .probe = mpc5200_wdt_probe, | ||
264 | .remove = mpc5200_wdt_remove, | ||
265 | .suspend = mpc5200_wdt_suspend, | ||
266 | .resume = mpc5200_wdt_resume, | ||
267 | .shutdown = mpc5200_wdt_shutdown, | ||
268 | }; | ||
269 | |||
270 | |||
271 | static int __init mpc5200_wdt_init(void) | ||
272 | { | ||
273 | return of_register_platform_driver(&mpc5200_wdt_driver); | ||
274 | } | ||
275 | |||
276 | static void __exit mpc5200_wdt_exit(void) | ||
277 | { | ||
278 | of_unregister_platform_driver(&mpc5200_wdt_driver); | ||
279 | } | ||
280 | |||
281 | module_init(mpc5200_wdt_init); | ||
282 | module_exit(mpc5200_wdt_exit); | ||
283 | |||
284 | MODULE_AUTHOR("Domen Puncer <domen.puncer@telargo.com>"); | ||
285 | MODULE_LICENSE("Dual BSD/GPL"); | ||
286 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
diff --git a/drivers/char/watchdog/mpc83xx_wdt.c b/drivers/char/watchdog/mpc83xx_wdt.c index 18ca752e2f90..a0bf95fb9763 100644 --- a/drivers/char/watchdog/mpc83xx_wdt.c +++ b/drivers/char/watchdog/mpc83xx_wdt.c | |||
@@ -119,6 +119,9 @@ static int mpc83xx_wdt_ioctl(struct inode *inode, struct file *file, | |||
119 | switch (cmd) { | 119 | switch (cmd) { |
120 | case WDIOC_GETSUPPORT: | 120 | case WDIOC_GETSUPPORT: |
121 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; | 121 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; |
122 | case WDIOC_GETSTATUS: | ||
123 | case WDIOC_GETBOOTSTATUS: | ||
124 | return put_user(0, p); | ||
122 | case WDIOC_KEEPALIVE: | 125 | case WDIOC_KEEPALIVE: |
123 | mpc83xx_wdt_keepalive(); | 126 | mpc83xx_wdt_keepalive(); |
124 | return 0; | 127 | return 0; |
diff --git a/drivers/char/watchdog/mpc8xx_wdt.c b/drivers/char/watchdog/mpc8xx_wdt.c index 8aaed10dd499..85b5734403a5 100644 --- a/drivers/char/watchdog/mpc8xx_wdt.c +++ b/drivers/char/watchdog/mpc8xx_wdt.c | |||
@@ -57,7 +57,7 @@ static int mpc8xx_wdt_open(struct inode *inode, struct file *file) | |||
57 | m8xx_wdt_reset(); | 57 | m8xx_wdt_reset(); |
58 | mpc8xx_wdt_handler_disable(); | 58 | mpc8xx_wdt_handler_disable(); |
59 | 59 | ||
60 | return 0; | 60 | return nonseekable_open(inode, file); |
61 | } | 61 | } |
62 | 62 | ||
63 | static int mpc8xx_wdt_release(struct inode *inode, struct file *file) | 63 | static int mpc8xx_wdt_release(struct inode *inode, struct file *file) |
diff --git a/drivers/char/watchdog/mpcore_wdt.c b/drivers/char/watchdog/mpcore_wdt.c index e88947f8fe53..0d2b27735419 100644 --- a/drivers/char/watchdog/mpcore_wdt.c +++ b/drivers/char/watchdog/mpcore_wdt.c | |||
@@ -328,12 +328,11 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev) | |||
328 | goto err_out; | 328 | goto err_out; |
329 | } | 329 | } |
330 | 330 | ||
331 | wdt = kmalloc(sizeof(struct mpcore_wdt), GFP_KERNEL); | 331 | wdt = kzalloc(sizeof(struct mpcore_wdt), GFP_KERNEL); |
332 | if (!wdt) { | 332 | if (!wdt) { |
333 | ret = -ENOMEM; | 333 | ret = -ENOMEM; |
334 | goto err_out; | 334 | goto err_out; |
335 | } | 335 | } |
336 | memset(wdt, 0, sizeof(struct mpcore_wdt)); | ||
337 | 336 | ||
338 | wdt->dev = &dev->dev; | 337 | wdt->dev = &dev->dev; |
339 | wdt->irq = platform_get_irq(dev, 0); | 338 | wdt->irq = platform_get_irq(dev, 0); |
diff --git a/drivers/char/watchdog/mtx-1_wdt.c b/drivers/char/watchdog/mtx-1_wdt.c index 419ab445c944..dcfd401a7ad7 100644 --- a/drivers/char/watchdog/mtx-1_wdt.c +++ b/drivers/char/watchdog/mtx-1_wdt.c | |||
@@ -143,6 +143,7 @@ static int mtx1_wdt_ioctl(struct inode *inode, struct file *file, unsigned int c | |||
143 | mtx1_wdt_reset(); | 143 | mtx1_wdt_reset(); |
144 | break; | 144 | break; |
145 | case WDIOC_GETSTATUS: | 145 | case WDIOC_GETSTATUS: |
146 | case WDIOC_GETBOOTSTATUS: | ||
146 | if ( copy_to_user(argp, &value, sizeof(int)) ) | 147 | if ( copy_to_user(argp, &value, sizeof(int)) ) |
147 | return -EFAULT; | 148 | return -EFAULT; |
148 | break; | 149 | break; |
diff --git a/drivers/char/watchdog/mv64x60_wdt.c b/drivers/char/watchdog/mv64x60_wdt.c index b887cdb01334..0365c317f7e1 100644 --- a/drivers/char/watchdog/mv64x60_wdt.c +++ b/drivers/char/watchdog/mv64x60_wdt.c | |||
@@ -23,61 +23,101 @@ | |||
23 | #include <linux/watchdog.h> | 23 | #include <linux/watchdog.h> |
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | 25 | ||
26 | #include <asm/mv64x60.h> | 26 | #include <linux/mv643xx.h> |
27 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
28 | #include <asm/io.h> | 28 | #include <asm/io.h> |
29 | 29 | ||
30 | /* MV64x60 WDC (config) register access definitions */ | 30 | #define MV64x60_WDT_WDC_OFFSET 0 |
31 | #define MV64x60_WDC_CTL1_MASK (3 << 24) | 31 | |
32 | #define MV64x60_WDC_CTL1(val) ((val & 3) << 24) | 32 | /* |
33 | #define MV64x60_WDC_CTL2_MASK (3 << 26) | 33 | * The watchdog configuration register contains a pair of 2-bit fields, |
34 | #define MV64x60_WDC_CTL2(val) ((val & 3) << 26) | 34 | * 1. a reload field, bits 27-26, which triggers a reload of |
35 | * the countdown register, and | ||
36 | * 2. an enable field, bits 25-24, which toggles between | ||
37 | * enabling and disabling the watchdog timer. | ||
38 | * Bit 31 is a read-only field which indicates whether the | ||
39 | * watchdog timer is currently enabled. | ||
40 | * | ||
41 | * The low 24 bits contain the timer reload value. | ||
42 | */ | ||
43 | #define MV64x60_WDC_ENABLE_SHIFT 24 | ||
44 | #define MV64x60_WDC_SERVICE_SHIFT 26 | ||
45 | #define MV64x60_WDC_ENABLED_SHIFT 31 | ||
46 | |||
47 | #define MV64x60_WDC_ENABLED_TRUE 1 | ||
48 | #define MV64x60_WDC_ENABLED_FALSE 0 | ||
35 | 49 | ||
36 | /* Flags bits */ | 50 | /* Flags bits */ |
37 | #define MV64x60_WDOG_FLAG_OPENED 0 | 51 | #define MV64x60_WDOG_FLAG_OPENED 0 |
38 | #define MV64x60_WDOG_FLAG_ENABLED 1 | ||
39 | 52 | ||
40 | static unsigned long wdt_flags; | 53 | static unsigned long wdt_flags; |
41 | static int wdt_status; | 54 | static int wdt_status; |
42 | static void __iomem *mv64x60_regs; | 55 | static void __iomem *mv64x60_wdt_regs; |
43 | static int mv64x60_wdt_timeout; | 56 | static int mv64x60_wdt_timeout; |
57 | static int mv64x60_wdt_count; | ||
58 | static unsigned int bus_clk; | ||
59 | static char expect_close; | ||
60 | static DEFINE_SPINLOCK(mv64x60_wdt_spinlock); | ||
61 | |||
62 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
63 | module_param(nowayout, int, 0); | ||
64 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
44 | 65 | ||
45 | static void mv64x60_wdt_reg_write(u32 val) | 66 | static int mv64x60_wdt_toggle_wdc(int enabled_predicate, int field_shift) |
46 | { | 67 | { |
47 | /* Allow write only to CTL1 / CTL2 fields, retaining values in | 68 | u32 data; |
48 | * other fields. | 69 | u32 enabled; |
49 | */ | 70 | int ret = 0; |
50 | u32 data = readl(mv64x60_regs + MV64x60_WDT_WDC); | 71 | |
51 | data &= ~(MV64x60_WDC_CTL1_MASK | MV64x60_WDC_CTL2_MASK); | 72 | spin_lock(&mv64x60_wdt_spinlock); |
52 | data |= val; | 73 | data = readl(mv64x60_wdt_regs + MV64x60_WDT_WDC_OFFSET); |
53 | writel(data, mv64x60_regs + MV64x60_WDT_WDC); | 74 | enabled = (data >> MV64x60_WDC_ENABLED_SHIFT) & 1; |
75 | |||
76 | /* only toggle the requested field if enabled state matches predicate */ | ||
77 | if ((enabled ^ enabled_predicate) == 0) { | ||
78 | /* We write a 1, then a 2 -- to the appropriate field */ | ||
79 | data = (1 << field_shift) | mv64x60_wdt_count; | ||
80 | writel(data, mv64x60_wdt_regs + MV64x60_WDT_WDC_OFFSET); | ||
81 | |||
82 | data = (2 << field_shift) | mv64x60_wdt_count; | ||
83 | writel(data, mv64x60_wdt_regs + MV64x60_WDT_WDC_OFFSET); | ||
84 | ret = 1; | ||
85 | } | ||
86 | spin_unlock(&mv64x60_wdt_spinlock); | ||
87 | |||
88 | return ret; | ||
54 | } | 89 | } |
55 | 90 | ||
56 | static void mv64x60_wdt_service(void) | 91 | static void mv64x60_wdt_service(void) |
57 | { | 92 | { |
58 | /* Write 01 followed by 10 to CTL2 */ | 93 | mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_TRUE, |
59 | mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x01)); | 94 | MV64x60_WDC_SERVICE_SHIFT); |
60 | mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x02)); | 95 | } |
96 | |||
97 | static void mv64x60_wdt_handler_enable(void) | ||
98 | { | ||
99 | if (mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_FALSE, | ||
100 | MV64x60_WDC_ENABLE_SHIFT)) { | ||
101 | mv64x60_wdt_service(); | ||
102 | printk(KERN_NOTICE "mv64x60_wdt: watchdog activated\n"); | ||
103 | } | ||
61 | } | 104 | } |
62 | 105 | ||
63 | static void mv64x60_wdt_handler_disable(void) | 106 | static void mv64x60_wdt_handler_disable(void) |
64 | { | 107 | { |
65 | if (test_and_clear_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) { | 108 | if (mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_TRUE, |
66 | /* Write 01 followed by 10 to CTL1 */ | 109 | MV64x60_WDC_ENABLE_SHIFT)) |
67 | mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01)); | ||
68 | mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02)); | ||
69 | printk(KERN_NOTICE "mv64x60_wdt: watchdog deactivated\n"); | 110 | printk(KERN_NOTICE "mv64x60_wdt: watchdog deactivated\n"); |
70 | } | ||
71 | } | 111 | } |
72 | 112 | ||
73 | static void mv64x60_wdt_handler_enable(void) | 113 | static void mv64x60_wdt_set_timeout(unsigned int timeout) |
74 | { | 114 | { |
75 | if (!test_and_set_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) { | 115 | /* maximum bus cycle count is 0xFFFFFFFF */ |
76 | /* Write 01 followed by 10 to CTL1 */ | 116 | if (timeout > 0xFFFFFFFF / bus_clk) |
77 | mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01)); | 117 | timeout = 0xFFFFFFFF / bus_clk; |
78 | mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02)); | 118 | |
79 | printk(KERN_NOTICE "mv64x60_wdt: watchdog activated\n"); | 119 | mv64x60_wdt_count = timeout * bus_clk >> 8; |
80 | } | 120 | mv64x60_wdt_timeout = timeout; |
81 | } | 121 | } |
82 | 122 | ||
83 | static int mv64x60_wdt_open(struct inode *inode, struct file *file) | 123 | static int mv64x60_wdt_open(struct inode *inode, struct file *file) |
@@ -85,21 +125,24 @@ static int mv64x60_wdt_open(struct inode *inode, struct file *file) | |||
85 | if (test_and_set_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags)) | 125 | if (test_and_set_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags)) |
86 | return -EBUSY; | 126 | return -EBUSY; |
87 | 127 | ||
88 | mv64x60_wdt_service(); | 128 | if (nowayout) |
89 | mv64x60_wdt_handler_enable(); | 129 | __module_get(THIS_MODULE); |
90 | 130 | ||
91 | nonseekable_open(inode, file); | 131 | mv64x60_wdt_handler_enable(); |
92 | 132 | ||
93 | return 0; | 133 | return nonseekable_open(inode, file); |
94 | } | 134 | } |
95 | 135 | ||
96 | static int mv64x60_wdt_release(struct inode *inode, struct file *file) | 136 | static int mv64x60_wdt_release(struct inode *inode, struct file *file) |
97 | { | 137 | { |
98 | mv64x60_wdt_service(); | 138 | if (expect_close == 42) |
99 | 139 | mv64x60_wdt_handler_disable(); | |
100 | #if !defined(CONFIG_WATCHDOG_NOWAYOUT) | 140 | else { |
101 | mv64x60_wdt_handler_disable(); | 141 | printk(KERN_CRIT |
102 | #endif | 142 | "mv64x60_wdt: unexpected close, not stopping timer!\n"); |
143 | mv64x60_wdt_service(); | ||
144 | } | ||
145 | expect_close = 0; | ||
103 | 146 | ||
104 | clear_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags); | 147 | clear_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags); |
105 | 148 | ||
@@ -109,8 +152,22 @@ static int mv64x60_wdt_release(struct inode *inode, struct file *file) | |||
109 | static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data, | 152 | static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data, |
110 | size_t len, loff_t * ppos) | 153 | size_t len, loff_t * ppos) |
111 | { | 154 | { |
112 | if (len) | 155 | if (len) { |
156 | if (!nowayout) { | ||
157 | size_t i; | ||
158 | |||
159 | expect_close = 0; | ||
160 | |||
161 | for (i = 0; i != len; i++) { | ||
162 | char c; | ||
163 | if(get_user(c, data + i)) | ||
164 | return -EFAULT; | ||
165 | if (c == 'V') | ||
166 | expect_close = 42; | ||
167 | } | ||
168 | } | ||
113 | mv64x60_wdt_service(); | 169 | mv64x60_wdt_service(); |
170 | } | ||
114 | 171 | ||
115 | return len; | 172 | return len; |
116 | } | 173 | } |
@@ -119,9 +176,12 @@ static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file, | |||
119 | unsigned int cmd, unsigned long arg) | 176 | unsigned int cmd, unsigned long arg) |
120 | { | 177 | { |
121 | int timeout; | 178 | int timeout; |
179 | int options; | ||
122 | void __user *argp = (void __user *)arg; | 180 | void __user *argp = (void __user *)arg; |
123 | static struct watchdog_info info = { | 181 | static struct watchdog_info info = { |
124 | .options = WDIOF_KEEPALIVEPING, | 182 | .options = WDIOF_SETTIMEOUT | |
183 | WDIOF_MAGICCLOSE | | ||
184 | WDIOF_KEEPALIVEPING, | ||
125 | .firmware_version = 0, | 185 | .firmware_version = 0, |
126 | .identity = "MV64x60 watchdog", | 186 | .identity = "MV64x60 watchdog", |
127 | }; | 187 | }; |
@@ -143,7 +203,15 @@ static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file, | |||
143 | return -EOPNOTSUPP; | 203 | return -EOPNOTSUPP; |
144 | 204 | ||
145 | case WDIOC_SETOPTIONS: | 205 | case WDIOC_SETOPTIONS: |
146 | return -EOPNOTSUPP; | 206 | if (get_user(options, (int __user *)argp)) |
207 | return -EFAULT; | ||
208 | |||
209 | if (options & WDIOS_DISABLECARD) | ||
210 | mv64x60_wdt_handler_disable(); | ||
211 | |||
212 | if (options & WDIOS_ENABLECARD) | ||
213 | mv64x60_wdt_handler_enable(); | ||
214 | break; | ||
147 | 215 | ||
148 | case WDIOC_KEEPALIVE: | 216 | case WDIOC_KEEPALIVE: |
149 | mv64x60_wdt_service(); | 217 | mv64x60_wdt_service(); |
@@ -151,11 +219,13 @@ static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file, | |||
151 | break; | 219 | break; |
152 | 220 | ||
153 | case WDIOC_SETTIMEOUT: | 221 | case WDIOC_SETTIMEOUT: |
154 | return -EOPNOTSUPP; | 222 | if (get_user(timeout, (int __user *)argp)) |
223 | return -EFAULT; | ||
224 | mv64x60_wdt_set_timeout(timeout); | ||
225 | /* Fall through */ | ||
155 | 226 | ||
156 | case WDIOC_GETTIMEOUT: | 227 | case WDIOC_GETTIMEOUT: |
157 | timeout = mv64x60_wdt_timeout * HZ; | 228 | if (put_user(mv64x60_wdt_timeout, (int __user *)argp)) |
158 | if (put_user(timeout, (int __user *)argp)) | ||
159 | return -EFAULT; | 229 | return -EFAULT; |
160 | break; | 230 | break; |
161 | 231 | ||
@@ -184,18 +254,33 @@ static struct miscdevice mv64x60_wdt_miscdev = { | |||
184 | static int __devinit mv64x60_wdt_probe(struct platform_device *dev) | 254 | static int __devinit mv64x60_wdt_probe(struct platform_device *dev) |
185 | { | 255 | { |
186 | struct mv64x60_wdt_pdata *pdata = dev->dev.platform_data; | 256 | struct mv64x60_wdt_pdata *pdata = dev->dev.platform_data; |
187 | int bus_clk = 133; | 257 | struct resource *r; |
258 | int timeout = 10; | ||
188 | 259 | ||
189 | mv64x60_wdt_timeout = 10; | 260 | bus_clk = 133; /* in MHz */ |
190 | if (pdata) { | 261 | if (pdata) { |
191 | mv64x60_wdt_timeout = pdata->timeout; | 262 | timeout = pdata->timeout; |
192 | bus_clk = pdata->bus_clk; | 263 | bus_clk = pdata->bus_clk; |
193 | } | 264 | } |
194 | 265 | ||
195 | mv64x60_regs = mv64x60_get_bridge_vbase(); | 266 | /* Since bus_clk is truncated MHz, actual frequency could be |
267 | * up to 1MHz higher. Round up, since it's better to time out | ||
268 | * too late than too soon. | ||
269 | */ | ||
270 | bus_clk++; | ||
271 | bus_clk *= 1000000; /* convert to Hz */ | ||
272 | |||
273 | r = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
274 | if (!r) | ||
275 | return -ENODEV; | ||
196 | 276 | ||
197 | writel((mv64x60_wdt_timeout * (bus_clk * 1000000)) >> 8, | 277 | mv64x60_wdt_regs = ioremap(r->start, r->end - r->start + 1); |
198 | mv64x60_regs + MV64x60_WDT_WDC); | 278 | if (mv64x60_wdt_regs == NULL) |
279 | return -ENOMEM; | ||
280 | |||
281 | mv64x60_wdt_set_timeout(timeout); | ||
282 | |||
283 | mv64x60_wdt_handler_disable(); /* in case timer was already running */ | ||
199 | 284 | ||
200 | return misc_register(&mv64x60_wdt_miscdev); | 285 | return misc_register(&mv64x60_wdt_miscdev); |
201 | } | 286 | } |
@@ -204,9 +289,10 @@ static int __devexit mv64x60_wdt_remove(struct platform_device *dev) | |||
204 | { | 289 | { |
205 | misc_deregister(&mv64x60_wdt_miscdev); | 290 | misc_deregister(&mv64x60_wdt_miscdev); |
206 | 291 | ||
207 | mv64x60_wdt_service(); | ||
208 | mv64x60_wdt_handler_disable(); | 292 | mv64x60_wdt_handler_disable(); |
209 | 293 | ||
294 | iounmap(mv64x60_wdt_regs); | ||
295 | |||
210 | return 0; | 296 | return 0; |
211 | } | 297 | } |
212 | 298 | ||
@@ -219,40 +305,16 @@ static struct platform_driver mv64x60_wdt_driver = { | |||
219 | }, | 305 | }, |
220 | }; | 306 | }; |
221 | 307 | ||
222 | static struct platform_device *mv64x60_wdt_dev; | ||
223 | |||
224 | static int __init mv64x60_wdt_init(void) | 308 | static int __init mv64x60_wdt_init(void) |
225 | { | 309 | { |
226 | int ret; | ||
227 | |||
228 | printk(KERN_INFO "MV64x60 watchdog driver\n"); | 310 | printk(KERN_INFO "MV64x60 watchdog driver\n"); |
229 | 311 | ||
230 | mv64x60_wdt_dev = platform_device_alloc(MV64x60_WDT_NAME, -1); | 312 | return platform_driver_register(&mv64x60_wdt_driver); |
231 | if (!mv64x60_wdt_dev) { | ||
232 | ret = -ENOMEM; | ||
233 | goto out; | ||
234 | } | ||
235 | |||
236 | ret = platform_device_add(mv64x60_wdt_dev); | ||
237 | if (ret) { | ||
238 | platform_device_put(mv64x60_wdt_dev); | ||
239 | goto out; | ||
240 | } | ||
241 | |||
242 | ret = platform_driver_register(&mv64x60_wdt_driver); | ||
243 | if (ret) { | ||
244 | platform_device_unregister(mv64x60_wdt_dev); | ||
245 | goto out; | ||
246 | } | ||
247 | |||
248 | out: | ||
249 | return ret; | ||
250 | } | 313 | } |
251 | 314 | ||
252 | static void __exit mv64x60_wdt_exit(void) | 315 | static void __exit mv64x60_wdt_exit(void) |
253 | { | 316 | { |
254 | platform_driver_unregister(&mv64x60_wdt_driver); | 317 | platform_driver_unregister(&mv64x60_wdt_driver); |
255 | platform_device_unregister(mv64x60_wdt_dev); | ||
256 | } | 318 | } |
257 | 319 | ||
258 | module_init(mv64x60_wdt_init); | 320 | module_init(mv64x60_wdt_init); |
diff --git a/drivers/char/watchdog/omap_wdt.c b/drivers/char/watchdog/omap_wdt.c index b36fa8de2131..719b066f73c4 100644 --- a/drivers/char/watchdog/omap_wdt.c +++ b/drivers/char/watchdog/omap_wdt.c | |||
@@ -142,7 +142,7 @@ static int omap_wdt_open(struct inode *inode, struct file *file) | |||
142 | 142 | ||
143 | omap_wdt_set_timeout(); | 143 | omap_wdt_set_timeout(); |
144 | omap_wdt_enable(); | 144 | omap_wdt_enable(); |
145 | return 0; | 145 | return nonseekable_open(inode, file); |
146 | } | 146 | } |
147 | 147 | ||
148 | static int omap_wdt_release(struct inode *inode, struct file *file) | 148 | static int omap_wdt_release(struct inode *inode, struct file *file) |
@@ -197,7 +197,7 @@ omap_wdt_ioctl(struct inode *inode, struct file *file, | |||
197 | 197 | ||
198 | switch (cmd) { | 198 | switch (cmd) { |
199 | default: | 199 | default: |
200 | return -ENOIOCTLCMD; | 200 | return -ENOTTY; |
201 | case WDIOC_GETSUPPORT: | 201 | case WDIOC_GETSUPPORT: |
202 | return copy_to_user((struct watchdog_info __user *)arg, &ident, | 202 | return copy_to_user((struct watchdog_info __user *)arg, &ident, |
203 | sizeof(ident)); | 203 | sizeof(ident)); |
diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c index 1e7a6719d5ba..0f3fd6c9c354 100644 --- a/drivers/char/watchdog/pcwd_usb.c +++ b/drivers/char/watchdog/pcwd_usb.c | |||
@@ -626,12 +626,11 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi | |||
626 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); | 626 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); |
627 | 627 | ||
628 | /* allocate memory for our device and initialize it */ | 628 | /* allocate memory for our device and initialize it */ |
629 | usb_pcwd = kmalloc (sizeof(struct usb_pcwd_private), GFP_KERNEL); | 629 | usb_pcwd = kzalloc (sizeof(struct usb_pcwd_private), GFP_KERNEL); |
630 | if (usb_pcwd == NULL) { | 630 | if (usb_pcwd == NULL) { |
631 | printk(KERN_ERR PFX "Out of memory\n"); | 631 | printk(KERN_ERR PFX "Out of memory\n"); |
632 | goto error; | 632 | goto error; |
633 | } | 633 | } |
634 | memset (usb_pcwd, 0x00, sizeof (*usb_pcwd)); | ||
635 | 634 | ||
636 | usb_pcwd_device = usb_pcwd; | 635 | usb_pcwd_device = usb_pcwd; |
637 | 636 | ||
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c index 50430bced2f2..5d1c15f83d23 100644 --- a/drivers/char/watchdog/s3c2410_wdt.c +++ b/drivers/char/watchdog/s3c2410_wdt.c | |||
@@ -52,10 +52,10 @@ | |||
52 | 52 | ||
53 | #include <asm/arch/map.h> | 53 | #include <asm/arch/map.h> |
54 | 54 | ||
55 | #undef S3C24XX_VA_WATCHDOG | 55 | #undef S3C_VA_WATCHDOG |
56 | #define S3C24XX_VA_WATCHDOG (0) | 56 | #define S3C_VA_WATCHDOG (0) |
57 | 57 | ||
58 | #include <asm/arch/regs-watchdog.h> | 58 | #include <asm/plat-s3c/regs-watchdog.h> |
59 | 59 | ||
60 | #define PFX "s3c2410-wdt: " | 60 | #define PFX "s3c2410-wdt: " |
61 | 61 | ||
diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c index 33c1137f17d6..3475f47aaa45 100644 --- a/drivers/char/watchdog/sa1100_wdt.c +++ b/drivers/char/watchdog/sa1100_wdt.c | |||
@@ -45,7 +45,6 @@ static int boot_status; | |||
45 | */ | 45 | */ |
46 | static int sa1100dog_open(struct inode *inode, struct file *file) | 46 | static int sa1100dog_open(struct inode *inode, struct file *file) |
47 | { | 47 | { |
48 | nonseekable_open(inode, file); | ||
49 | if (test_and_set_bit(1,&sa1100wdt_users)) | 48 | if (test_and_set_bit(1,&sa1100wdt_users)) |
50 | return -EBUSY; | 49 | return -EBUSY; |
51 | 50 | ||
@@ -54,7 +53,7 @@ static int sa1100dog_open(struct inode *inode, struct file *file) | |||
54 | OSSR = OSSR_M3; | 53 | OSSR = OSSR_M3; |
55 | OWER = OWER_WME; | 54 | OWER = OWER_WME; |
56 | OIER |= OIER_E3; | 55 | OIER |= OIER_E3; |
57 | return 0; | 56 | return nonseekable_open(inode, file); |
58 | } | 57 | } |
59 | 58 | ||
60 | /* | 59 | /* |
diff --git a/drivers/char/watchdog/sbc60xxwdt.c b/drivers/char/watchdog/sbc60xxwdt.c index b6282039198c..e4f3cb6090bc 100644 --- a/drivers/char/watchdog/sbc60xxwdt.c +++ b/drivers/char/watchdog/sbc60xxwdt.c | |||
@@ -191,8 +191,6 @@ static ssize_t fop_write(struct file * file, const char __user * buf, size_t cou | |||
191 | 191 | ||
192 | static int fop_open(struct inode * inode, struct file * file) | 192 | static int fop_open(struct inode * inode, struct file * file) |
193 | { | 193 | { |
194 | nonseekable_open(inode, file); | ||
195 | |||
196 | /* Just in case we're already talking to someone... */ | 194 | /* Just in case we're already talking to someone... */ |
197 | if(test_and_set_bit(0, &wdt_is_open)) | 195 | if(test_and_set_bit(0, &wdt_is_open)) |
198 | return -EBUSY; | 196 | return -EBUSY; |
@@ -202,7 +200,7 @@ static int fop_open(struct inode * inode, struct file * file) | |||
202 | 200 | ||
203 | /* Good, fire up the show */ | 201 | /* Good, fire up the show */ |
204 | wdt_startup(); | 202 | wdt_startup(); |
205 | return 0; | 203 | return nonseekable_open(inode, file); |
206 | } | 204 | } |
207 | 205 | ||
208 | static int fop_close(struct inode * inode, struct file * file) | 206 | static int fop_close(struct inode * inode, struct file * file) |
diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c index 2f7ba7a514fe..9670d47190d0 100644 --- a/drivers/char/watchdog/sc1200wdt.c +++ b/drivers/char/watchdog/sc1200wdt.c | |||
@@ -150,8 +150,6 @@ static inline int sc1200wdt_status(void) | |||
150 | 150 | ||
151 | static int sc1200wdt_open(struct inode *inode, struct file *file) | 151 | static int sc1200wdt_open(struct inode *inode, struct file *file) |
152 | { | 152 | { |
153 | nonseekable_open(inode, file); | ||
154 | |||
155 | /* allow one at a time */ | 153 | /* allow one at a time */ |
156 | if (down_trylock(&open_sem)) | 154 | if (down_trylock(&open_sem)) |
157 | return -EBUSY; | 155 | return -EBUSY; |
@@ -162,7 +160,7 @@ static int sc1200wdt_open(struct inode *inode, struct file *file) | |||
162 | sc1200wdt_start(); | 160 | sc1200wdt_start(); |
163 | printk(KERN_INFO PFX "Watchdog enabled, timeout = %d min(s)", timeout); | 161 | printk(KERN_INFO PFX "Watchdog enabled, timeout = %d min(s)", timeout); |
164 | 162 | ||
165 | return 0; | 163 | return nonseekable_open(inode, file); |
166 | } | 164 | } |
167 | 165 | ||
168 | 166 | ||
diff --git a/drivers/char/watchdog/sc520_wdt.c b/drivers/char/watchdog/sc520_wdt.c index 2676a43895a7..e8594c64d1e6 100644 --- a/drivers/char/watchdog/sc520_wdt.c +++ b/drivers/char/watchdog/sc520_wdt.c | |||
@@ -248,8 +248,6 @@ static ssize_t fop_write(struct file * file, const char __user * buf, size_t cou | |||
248 | 248 | ||
249 | static int fop_open(struct inode * inode, struct file * file) | 249 | static int fop_open(struct inode * inode, struct file * file) |
250 | { | 250 | { |
251 | nonseekable_open(inode, file); | ||
252 | |||
253 | /* Just in case we're already talking to someone... */ | 251 | /* Just in case we're already talking to someone... */ |
254 | if(test_and_set_bit(0, &wdt_is_open)) | 252 | if(test_and_set_bit(0, &wdt_is_open)) |
255 | return -EBUSY; | 253 | return -EBUSY; |
@@ -258,7 +256,7 @@ static int fop_open(struct inode * inode, struct file * file) | |||
258 | 256 | ||
259 | /* Good, fire up the show */ | 257 | /* Good, fire up the show */ |
260 | wdt_startup(); | 258 | wdt_startup(); |
261 | return 0; | 259 | return nonseekable_open(inode, file); |
262 | } | 260 | } |
263 | 261 | ||
264 | static int fop_close(struct inode * inode, struct file * file) | 262 | static int fop_close(struct inode * inode, struct file * file) |
diff --git a/drivers/char/watchdog/w83627hf_wdt.c b/drivers/char/watchdog/w83627hf_wdt.c index b46e7f47d705..df33b3b5a53c 100644 --- a/drivers/char/watchdog/w83627hf_wdt.c +++ b/drivers/char/watchdog/w83627hf_wdt.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * (c) Copyright 2007 Vlad Drukker <vlad@storewiz.com> | 4 | * (c) Copyright 2007 Vlad Drukker <vlad@storewiz.com> |
5 | * added support for W83627THF. | 5 | * added support for W83627THF. |
6 | * | 6 | * |
7 | * (c) Copyright 2003 Pádraig Brady <P@draigBrady.com> | 7 | * (c) Copyright 2003,2007 Pádraig Brady <P@draigBrady.com> |
8 | * | 8 | * |
9 | * Based on advantechwdt.c which is based on wdt.c. | 9 | * Based on advantechwdt.c which is based on wdt.c. |
10 | * Original copyright messages: | 10 | * Original copyright messages: |
@@ -42,7 +42,7 @@ | |||
42 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
43 | #include <asm/system.h> | 43 | #include <asm/system.h> |
44 | 44 | ||
45 | #define WATCHDOG_NAME "w83627hf/thf WDT" | 45 | #define WATCHDOG_NAME "w83627hf/thf/hg WDT" |
46 | #define PFX WATCHDOG_NAME ": " | 46 | #define PFX WATCHDOG_NAME ": " |
47 | #define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ | 47 | #define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ |
48 | 48 | ||
@@ -57,7 +57,7 @@ MODULE_PARM_DESC(wdt_io, "w83627hf/thf WDT io port (default 0x2E)"); | |||
57 | 57 | ||
58 | static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ | 58 | static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ |
59 | module_param(timeout, int, 0); | 59 | module_param(timeout, int, 0); |
60 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=63, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) "."); | 60 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=255, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) "."); |
61 | 61 | ||
62 | static int nowayout = WATCHDOG_NOWAYOUT; | 62 | static int nowayout = WATCHDOG_NOWAYOUT; |
63 | module_param(nowayout, int, 0); | 63 | module_param(nowayout, int, 0); |
@@ -78,9 +78,9 @@ w83627hf_select_wd_register(void) | |||
78 | outb_p(0x87, WDT_EFER); /* Enter extended function mode */ | 78 | outb_p(0x87, WDT_EFER); /* Enter extended function mode */ |
79 | outb_p(0x87, WDT_EFER); /* Again according to manual */ | 79 | outb_p(0x87, WDT_EFER); /* Again according to manual */ |
80 | 80 | ||
81 | outb(0x20, WDT_EFER); /* check chip version */ | 81 | outb(0x20, WDT_EFER); /* check chip version */ |
82 | c = inb(WDT_EFDR); | 82 | c = inb(WDT_EFDR); |
83 | if (c == 0x82) { /* W83627THF */ | 83 | if (c == 0x82) { /* W83627THF */ |
84 | outb_p(0x2b, WDT_EFER); /* select GPIO3 */ | 84 | outb_p(0x2b, WDT_EFER); /* select GPIO3 */ |
85 | c = ((inb_p(WDT_EFDR) & 0xf7) | 0x04); /* select WDT0 */ | 85 | c = ((inb_p(WDT_EFDR) & 0xf7) | 0x04); /* select WDT0 */ |
86 | outb_p(0x2b, WDT_EFER); | 86 | outb_p(0x2b, WDT_EFER); |
@@ -114,11 +114,17 @@ w83627hf_init(void) | |||
114 | printk (KERN_INFO PFX "Watchdog already running. Resetting timeout to %d sec\n", timeout); | 114 | printk (KERN_INFO PFX "Watchdog already running. Resetting timeout to %d sec\n", timeout); |
115 | outb_p(timeout, WDT_EFDR); /* Write back to CRF6 */ | 115 | outb_p(timeout, WDT_EFDR); /* Write back to CRF6 */ |
116 | } | 116 | } |
117 | |||
117 | outb_p(0xF5, WDT_EFER); /* Select CRF5 */ | 118 | outb_p(0xF5, WDT_EFER); /* Select CRF5 */ |
118 | t=inb_p(WDT_EFDR); /* read CRF5 */ | 119 | t=inb_p(WDT_EFDR); /* read CRF5 */ |
119 | t&=~0x0C; /* set second mode & disable keyboard turning off watchdog */ | 120 | t&=~0x0C; /* set second mode & disable keyboard turning off watchdog */ |
120 | outb_p(t, WDT_EFDR); /* Write back to CRF5 */ | 121 | outb_p(t, WDT_EFDR); /* Write back to CRF5 */ |
121 | 122 | ||
123 | outb_p(0xF7, WDT_EFER); /* Select CRF7 */ | ||
124 | t=inb_p(WDT_EFDR); /* read CRF7 */ | ||
125 | t&=~0xC0; /* disable keyboard & mouse turning off watchdog */ | ||
126 | outb_p(t, WDT_EFDR); /* Write back to CRF7 */ | ||
127 | |||
122 | w83627hf_unselect_wd_register(); | 128 | w83627hf_unselect_wd_register(); |
123 | } | 129 | } |
124 | 130 | ||
@@ -126,7 +132,7 @@ static void | |||
126 | wdt_ctrl(int timeout) | 132 | wdt_ctrl(int timeout) |
127 | { | 133 | { |
128 | spin_lock(&io_lock); | 134 | spin_lock(&io_lock); |
129 | 135 | ||
130 | w83627hf_select_wd_register(); | 136 | w83627hf_select_wd_register(); |
131 | 137 | ||
132 | outb_p(0xF6, WDT_EFER); /* Select CRF6 */ | 138 | outb_p(0xF6, WDT_EFER); /* Select CRF6 */ |
@@ -154,7 +160,7 @@ wdt_disable(void) | |||
154 | static int | 160 | static int |
155 | wdt_set_heartbeat(int t) | 161 | wdt_set_heartbeat(int t) |
156 | { | 162 | { |
157 | if ((t < 1) || (t > 63)) | 163 | if ((t < 1) || (t > 255)) |
158 | return -EINVAL; | 164 | return -EINVAL; |
159 | 165 | ||
160 | timeout = t; | 166 | timeout = t; |
@@ -324,11 +330,11 @@ wdt_init(void) | |||
324 | 330 | ||
325 | spin_lock_init(&io_lock); | 331 | spin_lock_init(&io_lock); |
326 | 332 | ||
327 | printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF/THF Super I/O chip initialising.\n"); | 333 | printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF/THF/HG Super I/O chip initialising.\n"); |
328 | 334 | ||
329 | if (wdt_set_heartbeat(timeout)) { | 335 | if (wdt_set_heartbeat(timeout)) { |
330 | wdt_set_heartbeat(WATCHDOG_TIMEOUT); | 336 | wdt_set_heartbeat(WATCHDOG_TIMEOUT); |
331 | printk (KERN_INFO PFX "timeout value must be 1<=timeout<=63, using %d\n", | 337 | printk (KERN_INFO PFX "timeout value must be 1<=timeout<=255, using %d\n", |
332 | WATCHDOG_TIMEOUT); | 338 | WATCHDOG_TIMEOUT); |
333 | } | 339 | } |
334 | 340 | ||