diff options
author | Wim Van Sebroeck <wim@iguana.be> | 2007-05-11 15:03:13 -0400 |
---|---|---|
committer | Wim Van Sebroeck <wim@iguana.be> | 2007-05-11 15:03:13 -0400 |
commit | 5c34202b8bf942da411b6599668a76b07449bbfd (patch) | |
tree | 5719c361321eaddc8e4f1b0c8a7994f0e9a6fdd3 /drivers/char | |
parent | 0d4804b31f91cfbcff6d62af0bc09a893a1c8ae0 (diff) | |
parent | 1f8a6b658a943b4f04a1fc7b3a420360202c86cd (diff) |
Merge /pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'drivers/char')
109 files changed, 3298 insertions, 2681 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index d0c978fbc204..abcafac64738 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -6,6 +6,7 @@ menu "Character devices" | |||
6 | 6 | ||
7 | config VT | 7 | config VT |
8 | bool "Virtual terminal" if EMBEDDED | 8 | bool "Virtual terminal" if EMBEDDED |
9 | depends on !S390 | ||
9 | select INPUT | 10 | select INPUT |
10 | default y if !VIOCONS | 11 | default y if !VIOCONS |
11 | ---help--- | 12 | ---help--- |
@@ -81,6 +82,7 @@ config VT_HW_CONSOLE_BINDING | |||
81 | 82 | ||
82 | config SERIAL_NONSTANDARD | 83 | config SERIAL_NONSTANDARD |
83 | bool "Non-standard serial port support" | 84 | bool "Non-standard serial port support" |
85 | depends on HAS_IOMEM | ||
84 | ---help--- | 86 | ---help--- |
85 | Say Y here if you have any non-standard serial boards -- boards | 87 | Say Y here if you have any non-standard serial boards -- boards |
86 | which aren't supported using the standard "dumb" serial driver. | 88 | which aren't supported using the standard "dumb" serial driver. |
@@ -127,7 +129,7 @@ config ROCKETPORT | |||
127 | 129 | ||
128 | config CYCLADES | 130 | config CYCLADES |
129 | tristate "Cyclades async mux support" | 131 | tristate "Cyclades async mux support" |
130 | depends on SERIAL_NONSTANDARD | 132 | depends on SERIAL_NONSTANDARD && (PCI || ISA) |
131 | ---help--- | 133 | ---help--- |
132 | This driver supports Cyclades Z and Y multiserial boards. | 134 | This driver supports Cyclades Z and Y multiserial boards. |
133 | You would need something like this to connect more than two modems to | 135 | You would need something like this to connect more than two modems to |
@@ -631,7 +633,8 @@ config HVC_CONSOLE | |||
631 | 633 | ||
632 | config HVC_ISERIES | 634 | config HVC_ISERIES |
633 | bool "iSeries Hypervisor Virtual Console support" | 635 | bool "iSeries Hypervisor Virtual Console support" |
634 | depends on PPC_ISERIES && !VIOCONS | 636 | depends on PPC_ISERIES |
637 | default y | ||
635 | select HVC_DRIVER | 638 | select HVC_DRIVER |
636 | help | 639 | help |
637 | iSeries machines support a hypervisor virtual console. | 640 | iSeries machines support a hypervisor virtual console. |
@@ -764,7 +767,7 @@ config NVRAM | |||
764 | 767 | ||
765 | config RTC | 768 | config RTC |
766 | tristate "Enhanced Real Time Clock Support" | 769 | tristate "Enhanced Real Time Clock Support" |
767 | depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM && !SUPERH | 770 | depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM && !SUPERH && !S390 |
768 | ---help--- | 771 | ---help--- |
769 | If you say Y here and create a character special file /dev/rtc with | 772 | If you say Y here and create a character special file /dev/rtc with |
770 | major number 10 and minor number 135 using mknod ("man mknod"), you | 773 | major number 10 and minor number 135 using mknod ("man mknod"), you |
@@ -812,7 +815,7 @@ config SGI_IP27_RTC | |||
812 | 815 | ||
813 | config GEN_RTC | 816 | config GEN_RTC |
814 | tristate "Generic /dev/rtc emulation" | 817 | tristate "Generic /dev/rtc emulation" |
815 | depends on RTC!=y && !IA64 && !ARM && !M32R && !SPARC && !FRV | 818 | depends on RTC!=y && !IA64 && !ARM && !M32R && !SPARC && !FRV && !S390 |
816 | ---help--- | 819 | ---help--- |
817 | If you say Y here and create a character special file /dev/rtc with | 820 | If you say Y here and create a character special file /dev/rtc with |
818 | major number 10 and minor number 135 using mknod ("man mknod"), you | 821 | major number 10 and minor number 135 using mknod ("man mknod"), you |
@@ -857,6 +860,7 @@ config COBALT_LCD | |||
857 | 860 | ||
858 | config DTLK | 861 | config DTLK |
859 | tristate "Double Talk PC internal speech card support" | 862 | tristate "Double Talk PC internal speech card support" |
863 | depends on ISA | ||
860 | help | 864 | help |
861 | This driver is for the DoubleTalk PC, a speech synthesizer | 865 | This driver is for the DoubleTalk PC, a speech synthesizer |
862 | manufactured by RC Systems (<http://www.rcsys.com/>). It is also | 866 | manufactured by RC Systems (<http://www.rcsys.com/>). It is also |
@@ -905,8 +909,8 @@ config SONYPI | |||
905 | To compile this driver as a module, choose M here: the | 909 | To compile this driver as a module, choose M here: the |
906 | module will be called sonypi. | 910 | module will be called sonypi. |
907 | 911 | ||
908 | config TANBAC_TB0219 | 912 | config GPIO_TB0219 |
909 | tristate "TANBAC TB0219 base board support" | 913 | tristate "TANBAC TB0219 GPIO support" |
910 | depends on TANBAC_TB022X | 914 | depends on TANBAC_TB022X |
911 | select GPIO_VR41XX | 915 | select GPIO_VR41XX |
912 | 916 | ||
@@ -1042,7 +1046,7 @@ config HPET_MMAP | |||
1042 | 1046 | ||
1043 | config HANGCHECK_TIMER | 1047 | config HANGCHECK_TIMER |
1044 | tristate "Hangcheck timer" | 1048 | tristate "Hangcheck timer" |
1045 | depends on X86 || IA64 || PPC64 | 1049 | depends on X86 || IA64 || PPC64 || S390 |
1046 | help | 1050 | help |
1047 | The hangcheck-timer module detects when the system has gone | 1051 | The hangcheck-timer module detects when the system has gone |
1048 | out to lunch past a certain margin. It can reboot the system | 1052 | out to lunch past a certain margin. It can reboot the system |
@@ -1071,5 +1075,13 @@ config TELCLOCK | |||
1071 | /sys/devices/platform/telco_clock, with a number of files for | 1075 | /sys/devices/platform/telco_clock, with a number of files for |
1072 | controlling the behavior of this hardware. | 1076 | controlling the behavior of this hardware. |
1073 | 1077 | ||
1078 | config DEVPORT | ||
1079 | bool | ||
1080 | depends on !M68K | ||
1081 | depends on ISA || PCI | ||
1082 | default y | ||
1083 | |||
1084 | source "drivers/s390/char/Kconfig" | ||
1085 | |||
1074 | endmenu | 1086 | endmenu |
1075 | 1087 | ||
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index ae8567cc529c..2f56ecc035aa 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -91,7 +91,7 @@ obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o | |||
91 | obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o | 91 | obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o |
92 | obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o | 92 | obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o |
93 | obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o | 93 | obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o |
94 | obj-$(CONFIG_TANBAC_TB0219) += tb0219.o | 94 | obj-$(CONFIG_GPIO_TB0219) += tb0219.o |
95 | obj-$(CONFIG_TELCLOCK) += tlclk.o | 95 | obj-$(CONFIG_TELCLOCK) += tlclk.o |
96 | 96 | ||
97 | obj-$(CONFIG_WATCHDOG) += watchdog/ | 97 | obj-$(CONFIG_WATCHDOG) += watchdog/ |
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c index 5b684fddcc03..4941ddb78939 100644 --- a/drivers/char/agp/ali-agp.c +++ b/drivers/char/agp/ali-agp.c | |||
@@ -145,6 +145,7 @@ static void *m1541_alloc_page(struct agp_bridge_data *bridge) | |||
145 | void *addr = agp_generic_alloc_page(agp_bridge); | 145 | void *addr = agp_generic_alloc_page(agp_bridge); |
146 | u32 temp; | 146 | u32 temp; |
147 | 147 | ||
148 | global_flush_tlb(); | ||
148 | if (!addr) | 149 | if (!addr) |
149 | return NULL; | 150 | return NULL; |
150 | 151 | ||
@@ -160,6 +161,7 @@ static void ali_destroy_page(void * addr) | |||
160 | if (addr) { | 161 | if (addr) { |
161 | global_cache_flush(); /* is this really needed? --hch */ | 162 | global_cache_flush(); /* is this really needed? --hch */ |
162 | agp_generic_destroy_page(addr); | 163 | agp_generic_destroy_page(addr); |
164 | global_flush_tlb(); | ||
163 | } | 165 | } |
164 | } | 166 | } |
165 | 167 | ||
diff --git a/drivers/char/agp/alpha-agp.c b/drivers/char/agp/alpha-agp.c index b0acf41c0db9..aa8f3a39a704 100644 --- a/drivers/char/agp/alpha-agp.c +++ b/drivers/char/agp/alpha-agp.c | |||
@@ -173,7 +173,7 @@ alpha_core_agp_setup(void) | |||
173 | /* | 173 | /* |
174 | * Build a fake pci_dev struct | 174 | * Build a fake pci_dev struct |
175 | */ | 175 | */ |
176 | pdev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); | 176 | pdev = alloc_pci_dev(); |
177 | if (!pdev) | 177 | if (!pdev) |
178 | return -ENOMEM; | 178 | return -ENOMEM; |
179 | pdev->vendor = 0xffff; | 179 | pdev->vendor = 0xffff; |
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 485720486d60..c9f0f250d78f 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/agp_backend.h> | 14 | #include <linux/agp_backend.h> |
15 | #include <linux/mmzone.h> | 15 | #include <linux/mmzone.h> |
16 | #include <asm/page.h> /* PAGE_SIZE */ | 16 | #include <asm/page.h> /* PAGE_SIZE */ |
17 | #include <asm/e820.h> | ||
17 | #include <asm/k8.h> | 18 | #include <asm/k8.h> |
18 | #include "agp.h" | 19 | #include "agp.h" |
19 | 20 | ||
@@ -259,7 +260,6 @@ static const struct agp_bridge_driver amd_8151_driver = { | |||
259 | /* Some basic sanity checks for the aperture. */ | 260 | /* Some basic sanity checks for the aperture. */ |
260 | static int __devinit aperture_valid(u64 aper, u32 size) | 261 | static int __devinit aperture_valid(u64 aper, u32 size) |
261 | { | 262 | { |
262 | u32 pfn, c; | ||
263 | if (aper == 0) { | 263 | if (aper == 0) { |
264 | printk(KERN_ERR PFX "No aperture\n"); | 264 | printk(KERN_ERR PFX "No aperture\n"); |
265 | return 0; | 265 | return 0; |
@@ -272,14 +272,9 @@ static int __devinit aperture_valid(u64 aper, u32 size) | |||
272 | printk(KERN_ERR PFX "Aperture out of bounds\n"); | 272 | printk(KERN_ERR PFX "Aperture out of bounds\n"); |
273 | return 0; | 273 | return 0; |
274 | } | 274 | } |
275 | pfn = aper >> PAGE_SHIFT; | 275 | if (e820_any_mapped(aper, aper + size, E820_RAM)) { |
276 | for (c = 0; c < size/PAGE_SIZE; c++) { | 276 | printk(KERN_ERR PFX "Aperture pointing to RAM\n"); |
277 | if (!pfn_valid(pfn + c)) | 277 | return 0; |
278 | break; | ||
279 | if (!PageReserved(pfn_to_page(pfn + c))) { | ||
280 | printk(KERN_ERR PFX "Aperture pointing to RAM\n"); | ||
281 | return 0; | ||
282 | } | ||
283 | } | 278 | } |
284 | 279 | ||
285 | /* Request the Aperture. This catches cases when someone else | 280 | /* Request the Aperture. This catches cases when someone else |
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index f902d71947ba..45aeb917ec63 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c | |||
@@ -51,28 +51,6 @@ int agp_memory_reserved; | |||
51 | */ | 51 | */ |
52 | EXPORT_SYMBOL_GPL(agp_memory_reserved); | 52 | EXPORT_SYMBOL_GPL(agp_memory_reserved); |
53 | 53 | ||
54 | #if defined(CONFIG_X86) | ||
55 | int map_page_into_agp(struct page *page) | ||
56 | { | ||
57 | int i; | ||
58 | i = change_page_attr(page, 1, PAGE_KERNEL_NOCACHE); | ||
59 | /* Caller's responsibility to call global_flush_tlb() for | ||
60 | * performance reasons */ | ||
61 | return i; | ||
62 | } | ||
63 | EXPORT_SYMBOL_GPL(map_page_into_agp); | ||
64 | |||
65 | int unmap_page_from_agp(struct page *page) | ||
66 | { | ||
67 | int i; | ||
68 | i = change_page_attr(page, 1, PAGE_KERNEL); | ||
69 | /* Caller's responsibility to call global_flush_tlb() for | ||
70 | * performance reasons */ | ||
71 | return i; | ||
72 | } | ||
73 | EXPORT_SYMBOL_GPL(unmap_page_from_agp); | ||
74 | #endif | ||
75 | |||
76 | /* | 54 | /* |
77 | * Generic routines for handling agp_memory structures - | 55 | * Generic routines for handling agp_memory structures - |
78 | * They use the basic page allocation routines to do the brunt of the work. | 56 | * They use the basic page allocation routines to do the brunt of the work. |
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 55392a45a14b..9c69f2e761f5 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c | |||
@@ -186,8 +186,9 @@ static void *i8xx_alloc_pages(void) | |||
186 | return NULL; | 186 | return NULL; |
187 | 187 | ||
188 | if (change_page_attr(page, 4, PAGE_KERNEL_NOCACHE) < 0) { | 188 | if (change_page_attr(page, 4, PAGE_KERNEL_NOCACHE) < 0) { |
189 | change_page_attr(page, 4, PAGE_KERNEL); | ||
189 | global_flush_tlb(); | 190 | global_flush_tlb(); |
190 | __free_page(page); | 191 | __free_pages(page, 2); |
191 | return NULL; | 192 | return NULL; |
192 | } | 193 | } |
193 | global_flush_tlb(); | 194 | global_flush_tlb(); |
@@ -209,7 +210,7 @@ static void i8xx_destroy_pages(void *addr) | |||
209 | global_flush_tlb(); | 210 | global_flush_tlb(); |
210 | put_page(page); | 211 | put_page(page); |
211 | unlock_page(page); | 212 | unlock_page(page); |
212 | free_pages((unsigned long)addr, 2); | 213 | __free_pages(page, 2); |
213 | atomic_dec(&agp_bridge->current_memory_agp); | 214 | atomic_dec(&agp_bridge->current_memory_agp); |
214 | } | 215 | } |
215 | 216 | ||
@@ -315,9 +316,6 @@ static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type) | |||
315 | struct agp_memory *new; | 316 | struct agp_memory *new; |
316 | void *addr; | 317 | void *addr; |
317 | 318 | ||
318 | if (pg_count != 1 && pg_count != 4) | ||
319 | return NULL; | ||
320 | |||
321 | switch (pg_count) { | 319 | switch (pg_count) { |
322 | case 1: addr = agp_bridge->driver->agp_alloc_page(agp_bridge); | 320 | case 1: addr = agp_bridge->driver->agp_alloc_page(agp_bridge); |
323 | global_flush_tlb(); | 321 | global_flush_tlb(); |
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c index 0c9dab557c94..6cd7373dcdf4 100644 --- a/drivers/char/agp/nvidia-agp.c +++ b/drivers/char/agp/nvidia-agp.c | |||
@@ -320,11 +320,11 @@ static int __devinit agp_nvidia_probe(struct pci_dev *pdev, | |||
320 | u8 cap_ptr; | 320 | u8 cap_ptr; |
321 | 321 | ||
322 | nvidia_private.dev_1 = | 322 | nvidia_private.dev_1 = |
323 | pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 1)); | 323 | pci_get_bus_and_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 1)); |
324 | nvidia_private.dev_2 = | 324 | nvidia_private.dev_2 = |
325 | pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 2)); | 325 | pci_get_bus_and_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 2)); |
326 | nvidia_private.dev_3 = | 326 | nvidia_private.dev_3 = |
327 | pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(30, 0)); | 327 | pci_get_bus_and_slot((unsigned int)pdev->bus->number, PCI_DEVFN(30, 0)); |
328 | 328 | ||
329 | if (!nvidia_private.dev_1 || !nvidia_private.dev_2 || !nvidia_private.dev_3) { | 329 | if (!nvidia_private.dev_1 || !nvidia_private.dev_2 || !nvidia_private.dev_3) { |
330 | printk(KERN_INFO PFX "Detected an NVIDIA nForce/nForce2 " | 330 | printk(KERN_INFO PFX "Detected an NVIDIA nForce/nForce2 " |
@@ -443,6 +443,9 @@ static int __init agp_nvidia_init(void) | |||
443 | static void __exit agp_nvidia_cleanup(void) | 443 | static void __exit agp_nvidia_cleanup(void) |
444 | { | 444 | { |
445 | pci_unregister_driver(&agp_nvidia_pci_driver); | 445 | pci_unregister_driver(&agp_nvidia_pci_driver); |
446 | pci_dev_put(nvidia_private.dev_1); | ||
447 | pci_dev_put(nvidia_private.dev_2); | ||
448 | pci_dev_put(nvidia_private.dev_3); | ||
446 | } | 449 | } |
447 | 450 | ||
448 | module_init(agp_nvidia_init); | 451 | module_init(agp_nvidia_init); |
diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c index 3d83b461ccad..f4562cc22343 100644 --- a/drivers/char/agp/parisc-agp.c +++ b/drivers/char/agp/parisc-agp.c | |||
@@ -329,7 +329,7 @@ parisc_agp_setup(void __iomem *ioc_hpa, void __iomem *lba_hpa) | |||
329 | struct agp_bridge_data *bridge; | 329 | struct agp_bridge_data *bridge; |
330 | int error = 0; | 330 | int error = 0; |
331 | 331 | ||
332 | fake_bridge_dev = kmalloc(sizeof (struct pci_dev), GFP_KERNEL); | 332 | fake_bridge_dev = alloc_pci_dev(); |
333 | if (!fake_bridge_dev) { | 333 | if (!fake_bridge_dev) { |
334 | error = -ENOMEM; | 334 | error = -ENOMEM; |
335 | goto fail; | 335 | goto fail; |
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c index ee8f50edde1b..cda608c42bea 100644 --- a/drivers/char/agp/sgi-agp.c +++ b/drivers/char/agp/sgi-agp.c | |||
@@ -47,9 +47,8 @@ static void *sgi_tioca_alloc_page(struct agp_bridge_data *bridge) | |||
47 | 47 | ||
48 | nid = info->ca_closest_node; | 48 | nid = info->ca_closest_node; |
49 | page = alloc_pages_node(nid, GFP_KERNEL, 0); | 49 | page = alloc_pages_node(nid, GFP_KERNEL, 0); |
50 | if (page == NULL) { | 50 | if (!page) |
51 | return 0; | 51 | return NULL; |
52 | } | ||
53 | 52 | ||
54 | get_page(page); | 53 | get_page(page); |
55 | SetPageLocked(page); | 54 | SetPageLocked(page); |
diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c index 125f4282d955..eb1a1c738190 100644 --- a/drivers/char/agp/sis-agp.c +++ b/drivers/char/agp/sis-agp.c | |||
@@ -143,96 +143,6 @@ static struct agp_bridge_driver sis_driver = { | |||
143 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, | 143 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
144 | }; | 144 | }; |
145 | 145 | ||
146 | static struct agp_device_ids sis_agp_device_ids[] __devinitdata = | ||
147 | { | ||
148 | { | ||
149 | .device_id = PCI_DEVICE_ID_SI_5591_AGP, | ||
150 | .chipset_name = "5591", | ||
151 | }, | ||
152 | { | ||
153 | .device_id = PCI_DEVICE_ID_SI_530, | ||
154 | .chipset_name = "530", | ||
155 | }, | ||
156 | { | ||
157 | .device_id = PCI_DEVICE_ID_SI_540, | ||
158 | .chipset_name = "540", | ||
159 | }, | ||
160 | { | ||
161 | .device_id = PCI_DEVICE_ID_SI_550, | ||
162 | .chipset_name = "550", | ||
163 | }, | ||
164 | { | ||
165 | .device_id = PCI_DEVICE_ID_SI_620, | ||
166 | .chipset_name = "620", | ||
167 | }, | ||
168 | { | ||
169 | .device_id = PCI_DEVICE_ID_SI_630, | ||
170 | .chipset_name = "630", | ||
171 | }, | ||
172 | { | ||
173 | .device_id = PCI_DEVICE_ID_SI_635, | ||
174 | .chipset_name = "635", | ||
175 | }, | ||
176 | { | ||
177 | .device_id = PCI_DEVICE_ID_SI_645, | ||
178 | .chipset_name = "645", | ||
179 | }, | ||
180 | { | ||
181 | .device_id = PCI_DEVICE_ID_SI_646, | ||
182 | .chipset_name = "646", | ||
183 | }, | ||
184 | { | ||
185 | .device_id = PCI_DEVICE_ID_SI_648, | ||
186 | .chipset_name = "648", | ||
187 | }, | ||
188 | { | ||
189 | .device_id = PCI_DEVICE_ID_SI_650, | ||
190 | .chipset_name = "650", | ||
191 | }, | ||
192 | { | ||
193 | .device_id = PCI_DEVICE_ID_SI_651, | ||
194 | .chipset_name = "651", | ||
195 | }, | ||
196 | { | ||
197 | .device_id = PCI_DEVICE_ID_SI_655, | ||
198 | .chipset_name = "655", | ||
199 | }, | ||
200 | { | ||
201 | .device_id = PCI_DEVICE_ID_SI_661, | ||
202 | .chipset_name = "661", | ||
203 | }, | ||
204 | { | ||
205 | .device_id = PCI_DEVICE_ID_SI_730, | ||
206 | .chipset_name = "730", | ||
207 | }, | ||
208 | { | ||
209 | .device_id = PCI_DEVICE_ID_SI_735, | ||
210 | .chipset_name = "735", | ||
211 | }, | ||
212 | { | ||
213 | .device_id = PCI_DEVICE_ID_SI_740, | ||
214 | .chipset_name = "740", | ||
215 | }, | ||
216 | { | ||
217 | .device_id = PCI_DEVICE_ID_SI_741, | ||
218 | .chipset_name = "741", | ||
219 | }, | ||
220 | { | ||
221 | .device_id = PCI_DEVICE_ID_SI_745, | ||
222 | .chipset_name = "745", | ||
223 | }, | ||
224 | { | ||
225 | .device_id = PCI_DEVICE_ID_SI_746, | ||
226 | .chipset_name = "746", | ||
227 | }, | ||
228 | { | ||
229 | .device_id = PCI_DEVICE_ID_SI_760, | ||
230 | .chipset_name = "760", | ||
231 | }, | ||
232 | { }, /* dummy final entry, always present */ | ||
233 | }; | ||
234 | |||
235 | |||
236 | // chipsets that require the 'delay hack' | 146 | // chipsets that require the 'delay hack' |
237 | static int sis_broken_chipsets[] __devinitdata = { | 147 | static int sis_broken_chipsets[] __devinitdata = { |
238 | PCI_DEVICE_ID_SI_648, | 148 | PCI_DEVICE_ID_SI_648, |
@@ -269,29 +179,15 @@ static void __devinit sis_get_driver(struct agp_bridge_data *bridge) | |||
269 | static int __devinit agp_sis_probe(struct pci_dev *pdev, | 179 | static int __devinit agp_sis_probe(struct pci_dev *pdev, |
270 | const struct pci_device_id *ent) | 180 | const struct pci_device_id *ent) |
271 | { | 181 | { |
272 | struct agp_device_ids *devs = sis_agp_device_ids; | ||
273 | struct agp_bridge_data *bridge; | 182 | struct agp_bridge_data *bridge; |
274 | u8 cap_ptr; | 183 | u8 cap_ptr; |
275 | int j; | ||
276 | 184 | ||
277 | cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); | 185 | cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); |
278 | if (!cap_ptr) | 186 | if (!cap_ptr) |
279 | return -ENODEV; | 187 | return -ENODEV; |
280 | 188 | ||
281 | /* probe for known chipsets */ | ||
282 | for (j = 0; devs[j].chipset_name; j++) { | ||
283 | if (pdev->device == devs[j].device_id) { | ||
284 | printk(KERN_INFO PFX "Detected SiS %s chipset\n", | ||
285 | devs[j].chipset_name); | ||
286 | goto found; | ||
287 | } | ||
288 | } | ||
289 | |||
290 | printk(KERN_ERR PFX "Unsupported SiS chipset (device id: %04x)\n", | ||
291 | pdev->device); | ||
292 | return -ENODEV; | ||
293 | 189 | ||
294 | found: | 190 | printk(KERN_INFO PFX "Detected SiS chipset - id:%i\n", pdev->device); |
295 | bridge = agp_alloc_bridge(); | 191 | bridge = agp_alloc_bridge(); |
296 | if (!bridge) | 192 | if (!bridge) |
297 | return -ENOMEM; | 193 | return -ENOMEM; |
@@ -320,12 +216,172 @@ static void __devexit agp_sis_remove(struct pci_dev *pdev) | |||
320 | 216 | ||
321 | static struct pci_device_id agp_sis_pci_table[] = { | 217 | static struct pci_device_id agp_sis_pci_table[] = { |
322 | { | 218 | { |
323 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | 219 | .class = (PCI_CLASS_BRIDGE_HOST << 8), |
324 | .class_mask = ~0, | 220 | .class_mask = ~0, |
325 | .vendor = PCI_VENDOR_ID_SI, | 221 | .vendor = PCI_VENDOR_ID_SI, |
326 | .device = PCI_ANY_ID, | 222 | .device = PCI_DEVICE_ID_SI_5591_AGP, |
327 | .subvendor = PCI_ANY_ID, | 223 | .subvendor = PCI_ANY_ID, |
328 | .subdevice = PCI_ANY_ID, | 224 | .subdevice = PCI_ANY_ID, |
225 | }, | ||
226 | { | ||
227 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
228 | .class_mask = ~0, | ||
229 | .vendor = PCI_VENDOR_ID_SI, | ||
230 | .device = PCI_DEVICE_ID_SI_530, | ||
231 | .subvendor = PCI_ANY_ID, | ||
232 | .subdevice = PCI_ANY_ID, | ||
233 | }, | ||
234 | { | ||
235 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
236 | .class_mask = ~0, | ||
237 | .vendor = PCI_VENDOR_ID_SI, | ||
238 | .device = PCI_DEVICE_ID_SI_540, | ||
239 | .subvendor = PCI_ANY_ID, | ||
240 | .subdevice = PCI_ANY_ID, | ||
241 | }, | ||
242 | { | ||
243 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
244 | .class_mask = ~0, | ||
245 | .vendor = PCI_VENDOR_ID_SI, | ||
246 | .device = PCI_DEVICE_ID_SI_550, | ||
247 | .subvendor = PCI_ANY_ID, | ||
248 | .subdevice = PCI_ANY_ID, | ||
249 | }, | ||
250 | { | ||
251 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
252 | .class_mask = ~0, | ||
253 | .vendor = PCI_VENDOR_ID_SI, | ||
254 | .device = PCI_DEVICE_ID_SI_620, | ||
255 | .subvendor = PCI_ANY_ID, | ||
256 | .subdevice = PCI_ANY_ID, | ||
257 | }, | ||
258 | { | ||
259 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
260 | .class_mask = ~0, | ||
261 | .vendor = PCI_VENDOR_ID_SI, | ||
262 | .device = PCI_DEVICE_ID_SI_630, | ||
263 | .subvendor = PCI_ANY_ID, | ||
264 | .subdevice = PCI_ANY_ID, | ||
265 | }, | ||
266 | { | ||
267 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
268 | .class_mask = ~0, | ||
269 | .vendor = PCI_VENDOR_ID_SI, | ||
270 | .device = PCI_DEVICE_ID_SI_635, | ||
271 | .subvendor = PCI_ANY_ID, | ||
272 | .subdevice = PCI_ANY_ID, | ||
273 | }, | ||
274 | { | ||
275 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
276 | .class_mask = ~0, | ||
277 | .vendor = PCI_VENDOR_ID_SI, | ||
278 | .device = PCI_DEVICE_ID_SI_645, | ||
279 | .subvendor = PCI_ANY_ID, | ||
280 | .subdevice = PCI_ANY_ID, | ||
281 | }, | ||
282 | { | ||
283 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
284 | .class_mask = ~0, | ||
285 | .vendor = PCI_VENDOR_ID_SI, | ||
286 | .device = PCI_DEVICE_ID_SI_646, | ||
287 | .subvendor = PCI_ANY_ID, | ||
288 | .subdevice = PCI_ANY_ID, | ||
289 | }, | ||
290 | { | ||
291 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
292 | .class_mask = ~0, | ||
293 | .vendor = PCI_VENDOR_ID_SI, | ||
294 | .device = PCI_DEVICE_ID_SI_648, | ||
295 | .subvendor = PCI_ANY_ID, | ||
296 | .subdevice = PCI_ANY_ID, | ||
297 | }, | ||
298 | { | ||
299 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
300 | .class_mask = ~0, | ||
301 | .vendor = PCI_VENDOR_ID_SI, | ||
302 | .device = PCI_DEVICE_ID_SI_650, | ||
303 | .subvendor = PCI_ANY_ID, | ||
304 | .subdevice = PCI_ANY_ID, | ||
305 | }, | ||
306 | { | ||
307 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
308 | .class_mask = ~0, | ||
309 | .vendor = PCI_VENDOR_ID_SI, | ||
310 | .device = PCI_DEVICE_ID_SI_651, | ||
311 | .subvendor = PCI_ANY_ID, | ||
312 | .subdevice = PCI_ANY_ID, | ||
313 | }, | ||
314 | { | ||
315 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
316 | .class_mask = ~0, | ||
317 | .vendor = PCI_VENDOR_ID_SI, | ||
318 | .device = PCI_DEVICE_ID_SI_655, | ||
319 | .subvendor = PCI_ANY_ID, | ||
320 | .subdevice = PCI_ANY_ID, | ||
321 | }, | ||
322 | { | ||
323 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
324 | .class_mask = ~0, | ||
325 | .vendor = PCI_VENDOR_ID_SI, | ||
326 | .device = PCI_DEVICE_ID_SI_661, | ||
327 | .subvendor = PCI_ANY_ID, | ||
328 | .subdevice = PCI_ANY_ID, | ||
329 | }, | ||
330 | { | ||
331 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
332 | .class_mask = ~0, | ||
333 | .vendor = PCI_VENDOR_ID_SI, | ||
334 | .device = PCI_DEVICE_ID_SI_730, | ||
335 | .subvendor = PCI_ANY_ID, | ||
336 | .subdevice = PCI_ANY_ID, | ||
337 | }, | ||
338 | { | ||
339 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
340 | .class_mask = ~0, | ||
341 | .vendor = PCI_VENDOR_ID_SI, | ||
342 | .device = PCI_DEVICE_ID_SI_735, | ||
343 | .subvendor = PCI_ANY_ID, | ||
344 | .subdevice = PCI_ANY_ID, | ||
345 | }, | ||
346 | { | ||
347 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
348 | .class_mask = ~0, | ||
349 | .vendor = PCI_VENDOR_ID_SI, | ||
350 | .device = PCI_DEVICE_ID_SI_740, | ||
351 | .subvendor = PCI_ANY_ID, | ||
352 | .subdevice = PCI_ANY_ID, | ||
353 | }, | ||
354 | { | ||
355 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
356 | .class_mask = ~0, | ||
357 | .vendor = PCI_VENDOR_ID_SI, | ||
358 | .device = PCI_DEVICE_ID_SI_741, | ||
359 | .subvendor = PCI_ANY_ID, | ||
360 | .subdevice = PCI_ANY_ID, | ||
361 | }, | ||
362 | { | ||
363 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
364 | .class_mask = ~0, | ||
365 | .vendor = PCI_VENDOR_ID_SI, | ||
366 | .device = PCI_DEVICE_ID_SI_745, | ||
367 | .subvendor = PCI_ANY_ID, | ||
368 | .subdevice = PCI_ANY_ID, | ||
369 | }, | ||
370 | { | ||
371 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
372 | .class_mask = ~0, | ||
373 | .vendor = PCI_VENDOR_ID_SI, | ||
374 | .device = PCI_DEVICE_ID_SI_746, | ||
375 | .subvendor = PCI_ANY_ID, | ||
376 | .subdevice = PCI_ANY_ID, | ||
377 | }, | ||
378 | { | ||
379 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
380 | .class_mask = ~0, | ||
381 | .vendor = PCI_VENDOR_ID_SI, | ||
382 | .device = PCI_DEVICE_ID_SI_760, | ||
383 | .subvendor = PCI_ANY_ID, | ||
384 | .subdevice = PCI_ANY_ID, | ||
329 | }, | 385 | }, |
330 | { } | 386 | { } |
331 | }; | 387 | }; |
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c index 55212a3811fd..551ef25063ef 100644 --- a/drivers/char/agp/sworks-agp.c +++ b/drivers/char/agp/sworks-agp.c | |||
@@ -455,15 +455,6 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev, | |||
455 | u32 temp, temp2; | 455 | u32 temp, temp2; |
456 | u8 cap_ptr = 0; | 456 | u8 cap_ptr = 0; |
457 | 457 | ||
458 | /* Everything is on func 1 here so we are hardcoding function one */ | ||
459 | bridge_dev = pci_find_slot((unsigned int)pdev->bus->number, | ||
460 | PCI_DEVFN(0, 1)); | ||
461 | if (!bridge_dev) { | ||
462 | printk(KERN_INFO PFX "Detected a Serverworks chipset " | ||
463 | "but could not find the secondary device.\n"); | ||
464 | return -ENODEV; | ||
465 | } | ||
466 | |||
467 | cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); | 458 | cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); |
468 | 459 | ||
469 | switch (pdev->device) { | 460 | switch (pdev->device) { |
@@ -483,6 +474,15 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev, | |||
483 | return -ENODEV; | 474 | return -ENODEV; |
484 | } | 475 | } |
485 | 476 | ||
477 | /* Everything is on func 1 here so we are hardcoding function one */ | ||
478 | bridge_dev = pci_get_bus_and_slot((unsigned int)pdev->bus->number, | ||
479 | PCI_DEVFN(0, 1)); | ||
480 | if (!bridge_dev) { | ||
481 | printk(KERN_INFO PFX "Detected a Serverworks chipset " | ||
482 | "but could not find the secondary device.\n"); | ||
483 | return -ENODEV; | ||
484 | } | ||
485 | |||
486 | serverworks_private.svrwrks_dev = bridge_dev; | 486 | serverworks_private.svrwrks_dev = bridge_dev; |
487 | serverworks_private.gart_addr_ofs = 0x10; | 487 | serverworks_private.gart_addr_ofs = 0x10; |
488 | 488 | ||
@@ -515,7 +515,7 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev, | |||
515 | 515 | ||
516 | bridge->driver = &sworks_driver; | 516 | bridge->driver = &sworks_driver; |
517 | bridge->dev_private_data = &serverworks_private, | 517 | bridge->dev_private_data = &serverworks_private, |
518 | bridge->dev = pdev; | 518 | bridge->dev = pci_dev_get(pdev); |
519 | 519 | ||
520 | pci_set_drvdata(pdev, bridge); | 520 | pci_set_drvdata(pdev, bridge); |
521 | return agp_add_bridge(bridge); | 521 | return agp_add_bridge(bridge); |
@@ -525,8 +525,11 @@ static void __devexit agp_serverworks_remove(struct pci_dev *pdev) | |||
525 | { | 525 | { |
526 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); | 526 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); |
527 | 527 | ||
528 | pci_dev_put(bridge->dev); | ||
528 | agp_remove_bridge(bridge); | 529 | agp_remove_bridge(bridge); |
529 | agp_put_bridge(bridge); | 530 | agp_put_bridge(bridge); |
531 | pci_dev_put(serverworks_private.svrwrks_dev); | ||
532 | serverworks_private.svrwrks_dev = NULL; | ||
530 | } | 533 | } |
531 | 534 | ||
532 | static struct pci_device_id agp_serverworks_pci_table[] = { | 535 | static struct pci_device_id agp_serverworks_pci_table[] = { |
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index 91b062126a68..42c0a600b1ac 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c | |||
@@ -613,7 +613,7 @@ static int __devinit agp_uninorth_probe(struct pci_dev *pdev, | |||
613 | uninorth_node = of_find_node_by_name(NULL, "u3"); | 613 | uninorth_node = of_find_node_by_name(NULL, "u3"); |
614 | } | 614 | } |
615 | if (uninorth_node) { | 615 | if (uninorth_node) { |
616 | const int *revprop = get_property(uninorth_node, | 616 | const int *revprop = of_get_property(uninorth_node, |
617 | "device-rev", NULL); | 617 | "device-rev", NULL); |
618 | if (revprop != NULL) | 618 | if (revprop != NULL) |
619 | uninorth_rev = *revprop & 0x3f; | 619 | uninorth_rev = *revprop & 0x3f; |
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 0e2b72f2b887..4eaceabd8cea 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c | |||
@@ -1574,7 +1574,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1574 | if (timeout && time_after(jiffies, orig_jiffies + timeout)) | 1574 | if (timeout && time_after(jiffies, orig_jiffies + timeout)) |
1575 | break; | 1575 | break; |
1576 | } | 1576 | } |
1577 | current->state = TASK_RUNNING; | 1577 | __set_current_state(TASK_RUNNING); |
1578 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | 1578 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT |
1579 | printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); | 1579 | printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); |
1580 | #endif | 1580 | #endif |
@@ -1700,7 +1700,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
1700 | #endif | 1700 | #endif |
1701 | schedule(); | 1701 | schedule(); |
1702 | } | 1702 | } |
1703 | current->state = TASK_RUNNING; | 1703 | __set_current_state(TASK_RUNNING); |
1704 | remove_wait_queue(&info->open_wait, &wait); | 1704 | remove_wait_queue(&info->open_wait, &wait); |
1705 | if (extra_count) | 1705 | if (extra_count) |
1706 | state->count++; | 1706 | state->count++; |
diff --git a/drivers/char/briq_panel.c b/drivers/char/briq_panel.c index c70d52ace8b2..ed53f541d9e8 100644 --- a/drivers/char/briq_panel.c +++ b/drivers/char/briq_panel.c | |||
@@ -206,7 +206,7 @@ static int __init briq_panel_init(void) | |||
206 | const char *machine; | 206 | const char *machine; |
207 | int i; | 207 | int i; |
208 | 208 | ||
209 | machine = get_property(root, "model", NULL); | 209 | machine = of_get_property(root, "model", NULL); |
210 | if (!machine || strncmp(machine, "TotalImpact,BRIQ-1", 18) != 0) { | 210 | if (!machine || strncmp(machine, "TotalImpact,BRIQ-1", 18) != 0) { |
211 | of_node_put(root); | 211 | of_node_put(root); |
212 | return -ENODEV; | 212 | return -ENODEV; |
diff --git a/drivers/char/consolemap.c b/drivers/char/consolemap.c index b99b7561260d..fd40b959afdd 100644 --- a/drivers/char/consolemap.c +++ b/drivers/char/consolemap.c | |||
@@ -626,10 +626,10 @@ conv_uni_to_pc(struct vc_data *conp, long ucs) | |||
626 | 626 | ||
627 | /* Only 16-bit codes supported at this time */ | 627 | /* Only 16-bit codes supported at this time */ |
628 | if (ucs > 0xffff) | 628 | if (ucs > 0xffff) |
629 | ucs = 0xfffd; /* U+FFFD: REPLACEMENT CHARACTER */ | 629 | return -4; /* Not found */ |
630 | else if (ucs < 0x20 || ucs >= 0xfffe) | 630 | else if (ucs < 0x20) |
631 | return -1; /* Not a printable character */ | 631 | return -1; /* Not a printable character */ |
632 | else if (ucs == 0xfeff || (ucs >= 0x200a && ucs <= 0x200f)) | 632 | else if (ucs == 0xfeff || (ucs >= 0x200b && ucs <= 0x200f)) |
633 | return -2; /* Zero-width space */ | 633 | return -2; /* Zero-width space */ |
634 | /* | 634 | /* |
635 | * UNI_DIRECT_BASE indicates the start of the region in the User Zone | 635 | * UNI_DIRECT_BASE indicates the start of the region in the User Zone |
diff --git a/drivers/char/cs5535_gpio.c b/drivers/char/cs5535_gpio.c index c02d9e99e050..fe6d2407baed 100644 --- a/drivers/char/cs5535_gpio.c +++ b/drivers/char/cs5535_gpio.c | |||
@@ -44,6 +44,7 @@ static struct pci_device_id divil_pci[] = { | |||
44 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) }, | 44 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) }, |
45 | { } /* NULL entry */ | 45 | { } /* NULL entry */ |
46 | }; | 46 | }; |
47 | MODULE_DEVICE_TABLE(pci, divil_pci); | ||
47 | 48 | ||
48 | static struct cdev cs5535_gpio_cdev; | 49 | static struct cdev cs5535_gpio_cdev; |
49 | 50 | ||
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 16dc5d1d3cb4..c72ee97d3892 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c | |||
@@ -10,15 +10,14 @@ | |||
10 | * | 10 | * |
11 | * Initially written by Randolph Bentson <bentson@grieg.seaslug.org>. | 11 | * Initially written by Randolph Bentson <bentson@grieg.seaslug.org>. |
12 | * Modified and maintained by Marcio Saito <marcio@cyclades.com>. | 12 | * Modified and maintained by Marcio Saito <marcio@cyclades.com>. |
13 | * Currently maintained by Cyclades team <async@cyclades.com>. | ||
14 | * | 13 | * |
15 | * For Technical support and installation problems, please send e-mail | 14 | * Copyright (C) 2007 Jiri Slaby <jirislaby@gmail.com> |
16 | * to support@cyclades.com. | ||
17 | * | 15 | * |
18 | * Much of the design and some of the code came from serial.c | 16 | * Much of the design and some of the code came from serial.c |
19 | * which was copyright (C) 1991, 1992 Linus Torvalds. It was | 17 | * which was copyright (C) 1991, 1992 Linus Torvalds. It was |
20 | * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92, | 18 | * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92, |
21 | * and then fixed as suggested by Michael K. Johnson 12/12/92. | 19 | * and then fixed as suggested by Michael K. Johnson 12/12/92. |
20 | * Converted to pci probing and cleaned up by Jiri Slaby. | ||
22 | * | 21 | * |
23 | * This version supports shared IRQ's (only for PCI boards). | 22 | * This version supports shared IRQ's (only for PCI boards). |
24 | * | 23 | * |
@@ -591,7 +590,7 @@ | |||
591 | * | 590 | * |
592 | */ | 591 | */ |
593 | 592 | ||
594 | #define CY_VERSION "2.4" | 593 | #define CY_VERSION "2.5" |
595 | 594 | ||
596 | /* If you need to install more boards than NR_CARDS, change the constant | 595 | /* If you need to install more boards than NR_CARDS, change the constant |
597 | in the definition below. No other change is necessary to support up to | 596 | in the definition below. No other change is necessary to support up to |
@@ -624,12 +623,6 @@ | |||
624 | #undef CY_ENABLE_MONITORING | 623 | #undef CY_ENABLE_MONITORING |
625 | #undef CY_PCI_DEBUG | 624 | #undef CY_PCI_DEBUG |
626 | 625 | ||
627 | #if 0 | ||
628 | #define PAUSE __asm__("nop") | ||
629 | #else | ||
630 | #define PAUSE do {} while (0) | ||
631 | #endif | ||
632 | |||
633 | /* | 626 | /* |
634 | * Include section | 627 | * Include section |
635 | */ | 628 | */ |
@@ -659,17 +652,6 @@ | |||
659 | #include <asm/irq.h> | 652 | #include <asm/irq.h> |
660 | #include <asm/uaccess.h> | 653 | #include <asm/uaccess.h> |
661 | 654 | ||
662 | #define CY_LOCK(info,flags) \ | ||
663 | do { \ | ||
664 | spin_lock_irqsave(&cy_card[info->card].card_lock, flags); \ | ||
665 | } while (0) | ||
666 | |||
667 | #define CY_UNLOCK(info,flags) \ | ||
668 | do { \ | ||
669 | spin_unlock_irqrestore(&cy_card[info->card].card_lock, flags); \ | ||
670 | } while (0) | ||
671 | |||
672 | #include <linux/types.h> | ||
673 | #include <linux/kernel.h> | 655 | #include <linux/kernel.h> |
674 | #include <linux/pci.h> | 656 | #include <linux/pci.h> |
675 | 657 | ||
@@ -682,13 +664,13 @@ static void cy_send_xchar(struct tty_struct *tty, char ch); | |||
682 | #define IS_CYC_Z(card) ((card).num_chips == -1) | 664 | #define IS_CYC_Z(card) ((card).num_chips == -1) |
683 | 665 | ||
684 | #define Z_FPGA_CHECK(card) \ | 666 | #define Z_FPGA_CHECK(card) \ |
685 | ((cy_readl(&((struct RUNTIME_9060 __iomem *) \ | 667 | ((readl(&((struct RUNTIME_9060 __iomem *) \ |
686 | ((card).ctl_addr))->init_ctrl) & (1<<17)) != 0) | 668 | ((card).ctl_addr))->init_ctrl) & (1<<17)) != 0) |
687 | 669 | ||
688 | #define ISZLOADED(card) (((ZO_V1==cy_readl(&((struct RUNTIME_9060 __iomem *) \ | 670 | #define ISZLOADED(card) (((ZO_V1==readl(&((struct RUNTIME_9060 __iomem *) \ |
689 | ((card).ctl_addr))->mail_box_0)) || \ | 671 | ((card).ctl_addr))->mail_box_0)) || \ |
690 | Z_FPGA_CHECK(card)) && \ | 672 | Z_FPGA_CHECK(card)) && \ |
691 | (ZFIRM_ID==cy_readl(&((struct FIRM_ID __iomem *) \ | 673 | (ZFIRM_ID==readl(&((struct FIRM_ID __iomem *) \ |
692 | ((card).base_addr+ID_ADDRESS))->signature))) | 674 | ((card).base_addr+ID_ADDRESS))->signature))) |
693 | 675 | ||
694 | #ifndef SERIAL_XMIT_SIZE | 676 | #ifndef SERIAL_XMIT_SIZE |
@@ -725,8 +707,8 @@ static unsigned int cy_isa_addresses[] = { | |||
725 | #define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses) | 707 | #define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses) |
726 | 708 | ||
727 | #ifdef MODULE | 709 | #ifdef MODULE |
728 | static long maddr[NR_CARDS] = { 0, }; | 710 | static long maddr[NR_CARDS]; |
729 | static int irq[NR_CARDS] = { 0, }; | 711 | static int irq[NR_CARDS]; |
730 | 712 | ||
731 | module_param_array(maddr, long, NULL, 0); | 713 | module_param_array(maddr, long, NULL, 0); |
732 | module_param_array(irq, int, NULL, 0); | 714 | module_param_array(irq, int, NULL, 0); |
@@ -739,11 +721,6 @@ module_param_array(irq, int, NULL, 0); | |||
739 | */ | 721 | */ |
740 | static struct cyclades_card cy_card[NR_CARDS]; | 722 | static struct cyclades_card cy_card[NR_CARDS]; |
741 | 723 | ||
742 | /* This is the per-channel data structure containing pointers, flags | ||
743 | and variables for the port. This driver supports a maximum of NR_PORTS. | ||
744 | */ | ||
745 | static struct cyclades_port cy_port[NR_PORTS]; | ||
746 | |||
747 | static int cy_next_channel; /* next minor available */ | 724 | static int cy_next_channel; /* next minor available */ |
748 | 725 | ||
749 | /* | 726 | /* |
@@ -825,9 +802,6 @@ static int cy_chip_offset[] = { 0x0000, | |||
825 | 802 | ||
826 | /* PCI related definitions */ | 803 | /* PCI related definitions */ |
827 | 804 | ||
828 | static unsigned short cy_pci_nboard; | ||
829 | static unsigned short cy_isa_nboard; | ||
830 | static unsigned short cy_nboard; | ||
831 | #ifdef CONFIG_PCI | 805 | #ifdef CONFIG_PCI |
832 | static struct pci_device_id cy_pci_dev_id[] __devinitdata = { | 806 | static struct pci_device_id cy_pci_dev_id[] __devinitdata = { |
833 | { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Lo) }, /* PCI < 1Mb */ | 807 | { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Lo) }, /* PCI < 1Mb */ |
@@ -845,7 +819,7 @@ MODULE_DEVICE_TABLE(pci, cy_pci_dev_id); | |||
845 | 819 | ||
846 | static void cy_start(struct tty_struct *); | 820 | static void cy_start(struct tty_struct *); |
847 | static void set_line_char(struct cyclades_port *); | 821 | static void set_line_char(struct cyclades_port *); |
848 | static int cyz_issue_cmd(struct cyclades_card *, uclong, ucchar, uclong); | 822 | static int cyz_issue_cmd(struct cyclades_card *, __u32, __u8, __u32); |
849 | #ifdef CONFIG_ISA | 823 | #ifdef CONFIG_ISA |
850 | static unsigned detect_isa_irq(void __iomem *); | 824 | static unsigned detect_isa_irq(void __iomem *); |
851 | #endif /* CONFIG_ISA */ | 825 | #endif /* CONFIG_ISA */ |
@@ -858,7 +832,6 @@ static void cyz_poll(unsigned long); | |||
858 | /* The Cyclades-Z polling cycle is defined by this variable */ | 832 | /* The Cyclades-Z polling cycle is defined by this variable */ |
859 | static long cyz_polling_cycle = CZ_DEF_POLL; | 833 | static long cyz_polling_cycle = CZ_DEF_POLL; |
860 | 834 | ||
861 | static int cyz_timeron = 0; | ||
862 | static DEFINE_TIMER(cyz_timerlist, cyz_poll, 0, 0); | 835 | static DEFINE_TIMER(cyz_timerlist, cyz_poll, 0, 0); |
863 | 836 | ||
864 | #else /* CONFIG_CYZ_INTR */ | 837 | #else /* CONFIG_CYZ_INTR */ |
@@ -871,21 +844,14 @@ static inline int serial_paranoia_check(struct cyclades_port *info, | |||
871 | { | 844 | { |
872 | #ifdef SERIAL_PARANOIA_CHECK | 845 | #ifdef SERIAL_PARANOIA_CHECK |
873 | if (!info) { | 846 | if (!info) { |
874 | printk("cyc Warning: null cyclades_port for (%s) in %s\n", | 847 | printk(KERN_WARNING "cyc Warning: null cyclades_port for (%s) " |
875 | name, routine); | 848 | "in %s\n", name, routine); |
876 | return 1; | ||
877 | } | ||
878 | |||
879 | if ((long)info < (long)(&cy_port[0]) || | ||
880 | (long)(&cy_port[NR_PORTS]) < (long)info) { | ||
881 | printk("cyc Warning: cyclades_port out of range for (%s) in " | ||
882 | "%s\n", name, routine); | ||
883 | return 1; | 849 | return 1; |
884 | } | 850 | } |
885 | 851 | ||
886 | if (info->magic != CYCLADES_MAGIC) { | 852 | if (info->magic != CYCLADES_MAGIC) { |
887 | printk("cyc Warning: bad magic number for serial struct (%s) " | 853 | printk(KERN_WARNING "cyc Warning: bad magic number for serial " |
888 | "in %s\n", name, routine); | 854 | "struct (%s) in %s\n", name, routine); |
889 | return 1; | 855 | return 1; |
890 | } | 856 | } |
891 | #endif | 857 | #endif |
@@ -943,22 +909,16 @@ do_softint(struct work_struct *work) | |||
943 | if (test_and_clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event)) | 909 | if (test_and_clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event)) |
944 | wake_up_interruptible(&info->open_wait); | 910 | wake_up_interruptible(&info->open_wait); |
945 | #ifdef CONFIG_CYZ_INTR | 911 | #ifdef CONFIG_CYZ_INTR |
946 | if (test_and_clear_bit(Cy_EVENT_Z_RX_FULL, &info->event)) { | 912 | if (test_and_clear_bit(Cy_EVENT_Z_RX_FULL, &info->event) && |
947 | if (cyz_rx_full_timer[info->line].function == NULL) { | 913 | !timer_pending(&cyz_rx_full_timer[info->line])) |
948 | cyz_rx_full_timer[info->line].expires = jiffies + 1; | 914 | mod_timer(&cyz_rx_full_timer[info->line], jiffies + 1); |
949 | cyz_rx_full_timer[info->line].function = cyz_rx_restart; | ||
950 | cyz_rx_full_timer[info->line].data = | ||
951 | (unsigned long)info; | ||
952 | add_timer(&cyz_rx_full_timer[info->line]); | ||
953 | } | ||
954 | } | ||
955 | #endif | 915 | #endif |
956 | if (test_and_clear_bit(Cy_EVENT_DELTA_WAKEUP, &info->event)) | 916 | if (test_and_clear_bit(Cy_EVENT_DELTA_WAKEUP, &info->event)) |
957 | wake_up_interruptible(&info->delta_msr_wait); | 917 | wake_up_interruptible(&info->delta_msr_wait); |
958 | tty_wakeup(tty); | 918 | tty_wakeup(tty); |
959 | #ifdef Z_WAKE | 919 | #ifdef Z_WAKE |
960 | if (test_and_clear_bit(Cy_EVENT_SHUTDOWN_WAKEUP, &info->event)) | 920 | if (test_and_clear_bit(Cy_EVENT_SHUTDOWN_WAKEUP, &info->event)) |
961 | wake_up_interruptible(&info->shutdown_wait); | 921 | complete(&info->shutdown_wait); |
962 | #endif | 922 | #endif |
963 | } /* do_softint */ | 923 | } /* do_softint */ |
964 | 924 | ||
@@ -975,11 +935,11 @@ do_softint(struct work_struct *work) | |||
975 | */ | 935 | */ |
976 | static int cyy_issue_cmd(void __iomem * base_addr, u_char cmd, int index) | 936 | static int cyy_issue_cmd(void __iomem * base_addr, u_char cmd, int index) |
977 | { | 937 | { |
978 | volatile int i; | 938 | unsigned int i; |
979 | 939 | ||
980 | /* Check to see that the previous command has completed */ | 940 | /* Check to see that the previous command has completed */ |
981 | for (i = 0; i < 100; i++) { | 941 | for (i = 0; i < 100; i++) { |
982 | if (cy_readb(base_addr + (CyCCR << index)) == 0) { | 942 | if (readb(base_addr + (CyCCR << index)) == 0) { |
983 | break; | 943 | break; |
984 | } | 944 | } |
985 | udelay(10L); | 945 | udelay(10L); |
@@ -1022,7 +982,7 @@ static unsigned detect_isa_irq(void __iomem * address) | |||
1022 | 982 | ||
1023 | cy_writeb(address + (CyCAR << index), 0); | 983 | cy_writeb(address + (CyCAR << index), 0); |
1024 | cy_writeb(address + (CySRER << index), | 984 | cy_writeb(address + (CySRER << index), |
1025 | cy_readb(address + (CySRER << index)) | CyTxRdy); | 985 | readb(address + (CySRER << index)) | CyTxRdy); |
1026 | local_irq_restore(flags); | 986 | local_irq_restore(flags); |
1027 | 987 | ||
1028 | /* Wait ... */ | 988 | /* Wait ... */ |
@@ -1032,11 +992,11 @@ static unsigned detect_isa_irq(void __iomem * address) | |||
1032 | irq = probe_irq_off(irqs); | 992 | irq = probe_irq_off(irqs); |
1033 | 993 | ||
1034 | /* Clean up */ | 994 | /* Clean up */ |
1035 | save_xir = (u_char) cy_readb(address + (CyTIR << index)); | 995 | save_xir = (u_char) readb(address + (CyTIR << index)); |
1036 | save_car = cy_readb(address + (CyCAR << index)); | 996 | save_car = readb(address + (CyCAR << index)); |
1037 | cy_writeb(address + (CyCAR << index), (save_xir & 0x3)); | 997 | cy_writeb(address + (CyCAR << index), (save_xir & 0x3)); |
1038 | cy_writeb(address + (CySRER << index), | 998 | cy_writeb(address + (CySRER << index), |
1039 | cy_readb(address + (CySRER << index)) & ~CyTxRdy); | 999 | readb(address + (CySRER << index)) & ~CyTxRdy); |
1040 | cy_writeb(address + (CyTIR << index), (save_xir & 0x3f)); | 1000 | cy_writeb(address + (CyTIR << index), (save_xir & 0x3f)); |
1041 | cy_writeb(address + (CyCAR << index), (save_car)); | 1001 | cy_writeb(address + (CyCAR << index), (save_car)); |
1042 | cy_writeb(address + (Cy_ClrIntr << index), 0); | 1002 | cy_writeb(address + (Cy_ClrIntr << index), 0); |
@@ -1051,45 +1011,43 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, | |||
1051 | { | 1011 | { |
1052 | struct cyclades_port *info; | 1012 | struct cyclades_port *info; |
1053 | struct tty_struct *tty; | 1013 | struct tty_struct *tty; |
1054 | volatile int char_count; | 1014 | int char_count; |
1055 | int i, j, len, mdm_change, mdm_status, outch; | 1015 | int j, len, mdm_change, mdm_status, outch; |
1056 | int save_xir, channel, save_car; | 1016 | int save_xir, channel, save_car; |
1057 | char data; | 1017 | char data; |
1058 | 1018 | ||
1059 | if (status & CySRReceive) { /* reception interrupt */ | 1019 | if (status & CySRReceive) { /* reception interrupt */ |
1060 | #ifdef CY_DEBUG_INTERRUPTS | 1020 | #ifdef CY_DEBUG_INTERRUPTS |
1061 | printk("cyy_interrupt: rcvd intr, chip %d\n\r", chip); | 1021 | printk(KERN_DEBUG "cyy_interrupt: rcvd intr, chip %d\n", chip); |
1062 | #endif | 1022 | #endif |
1063 | /* determine the channel & change to that context */ | 1023 | /* determine the channel & change to that context */ |
1064 | spin_lock(&cinfo->card_lock); | 1024 | spin_lock(&cinfo->card_lock); |
1065 | save_xir = (u_char) cy_readb(base_addr + (CyRIR << index)); | 1025 | save_xir = (u_char) readb(base_addr + (CyRIR << index)); |
1066 | channel = (u_short) (save_xir & CyIRChannel); | 1026 | channel = (u_short) (save_xir & CyIRChannel); |
1067 | i = channel + chip * 4 + cinfo->first_line; | 1027 | info = &cinfo->ports[channel + chip * 4]; |
1068 | info = &cy_port[i]; | 1028 | save_car = readb(base_addr + (CyCAR << index)); |
1069 | info->last_active = jiffies; | ||
1070 | save_car = cy_readb(base_addr + (CyCAR << index)); | ||
1071 | cy_writeb(base_addr + (CyCAR << index), save_xir); | 1029 | cy_writeb(base_addr + (CyCAR << index), save_xir); |
1072 | 1030 | ||
1073 | /* if there is nowhere to put the data, discard it */ | 1031 | /* if there is nowhere to put the data, discard it */ |
1074 | if (info->tty == 0) { | 1032 | if (info->tty == NULL) { |
1075 | j = (cy_readb(base_addr + (CyRIVR << index)) & | 1033 | j = (readb(base_addr + (CyRIVR << index)) & |
1076 | CyIVRMask); | 1034 | CyIVRMask); |
1077 | if (j == CyIVRRxEx) { /* exception */ | 1035 | if (j == CyIVRRxEx) { /* exception */ |
1078 | data = cy_readb(base_addr + (CyRDSR << index)); | 1036 | data = readb(base_addr + (CyRDSR << index)); |
1079 | } else { /* normal character reception */ | 1037 | } else { /* normal character reception */ |
1080 | char_count = cy_readb(base_addr + | 1038 | char_count = readb(base_addr + |
1081 | (CyRDCR << index)); | 1039 | (CyRDCR << index)); |
1082 | while (char_count--) { | 1040 | while (char_count--) { |
1083 | data = cy_readb(base_addr + | 1041 | data = readb(base_addr + |
1084 | (CyRDSR << index)); | 1042 | (CyRDSR << index)); |
1085 | } | 1043 | } |
1086 | } | 1044 | } |
1087 | } else { /* there is an open port for this data */ | 1045 | } else { /* there is an open port for this data */ |
1088 | tty = info->tty; | 1046 | tty = info->tty; |
1089 | j = (cy_readb(base_addr + (CyRIVR << index)) & | 1047 | j = (readb(base_addr + (CyRIVR << index)) & |
1090 | CyIVRMask); | 1048 | CyIVRMask); |
1091 | if (j == CyIVRRxEx) { /* exception */ | 1049 | if (j == CyIVRRxEx) { /* exception */ |
1092 | data = cy_readb(base_addr + (CyRDSR << index)); | 1050 | data = readb(base_addr + (CyRDSR << index)); |
1093 | 1051 | ||
1094 | /* For statistics only */ | 1052 | /* For statistics only */ |
1095 | if (data & CyBREAK) | 1053 | if (data & CyBREAK) |
@@ -1110,7 +1068,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, | |||
1110 | if (data & CyBREAK) { | 1068 | if (data & CyBREAK) { |
1111 | tty_insert_flip_char( | 1069 | tty_insert_flip_char( |
1112 | tty, | 1070 | tty, |
1113 | cy_readb( | 1071 | readb( |
1114 | base_addr + | 1072 | base_addr + |
1115 | (CyRDSR << | 1073 | (CyRDSR << |
1116 | index)), | 1074 | index)), |
@@ -1123,7 +1081,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, | |||
1123 | } else if (data & CyFRAME) { | 1081 | } else if (data & CyFRAME) { |
1124 | tty_insert_flip_char( | 1082 | tty_insert_flip_char( |
1125 | tty, | 1083 | tty, |
1126 | cy_readb( | 1084 | readb( |
1127 | base_addr + | 1085 | base_addr + |
1128 | (CyRDSR << | 1086 | (CyRDSR << |
1129 | index)), | 1087 | index)), |
@@ -1135,7 +1093,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, | |||
1135 | /* Pieces of seven... */ | 1093 | /* Pieces of seven... */ |
1136 | tty_insert_flip_char( | 1094 | tty_insert_flip_char( |
1137 | tty, | 1095 | tty, |
1138 | cy_readb( | 1096 | readb( |
1139 | base_addr + | 1097 | base_addr + |
1140 | (CyRDSR << | 1098 | (CyRDSR << |
1141 | index)), | 1099 | index)), |
@@ -1154,7 +1112,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, | |||
1154 | */ | 1112 | */ |
1155 | tty_insert_flip_char( | 1113 | tty_insert_flip_char( |
1156 | tty, | 1114 | tty, |
1157 | cy_readb( | 1115 | readb( |
1158 | base_addr + | 1116 | base_addr + |
1159 | (CyRDSR << | 1117 | (CyRDSR << |
1160 | index)), | 1118 | index)), |
@@ -1186,7 +1144,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, | |||
1186 | } | 1144 | } |
1187 | } else { /* normal character reception */ | 1145 | } else { /* normal character reception */ |
1188 | /* load # chars available from the chip */ | 1146 | /* load # chars available from the chip */ |
1189 | char_count = cy_readb(base_addr + | 1147 | char_count = readb(base_addr + |
1190 | (CyRDCR << index)); | 1148 | (CyRDCR << index)); |
1191 | 1149 | ||
1192 | #ifdef CY_ENABLE_MONITORING | 1150 | #ifdef CY_ENABLE_MONITORING |
@@ -1198,7 +1156,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, | |||
1198 | #endif | 1156 | #endif |
1199 | len = tty_buffer_request_room(tty, char_count); | 1157 | len = tty_buffer_request_room(tty, char_count); |
1200 | while (len--) { | 1158 | while (len--) { |
1201 | data = cy_readb(base_addr + | 1159 | data = readb(base_addr + |
1202 | (CyRDSR << index)); | 1160 | (CyRDSR << index)); |
1203 | tty_insert_flip_char(tty, data, | 1161 | tty_insert_flip_char(tty, data, |
1204 | TTY_NORMAL); | 1162 | TTY_NORMAL); |
@@ -1223,29 +1181,27 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, | |||
1223 | is empty, we know we can always stuff a dozen | 1181 | is empty, we know we can always stuff a dozen |
1224 | characters. */ | 1182 | characters. */ |
1225 | #ifdef CY_DEBUG_INTERRUPTS | 1183 | #ifdef CY_DEBUG_INTERRUPTS |
1226 | printk("cyy_interrupt: xmit intr, chip %d\n\r", chip); | 1184 | printk(KERN_DEBUG "cyy_interrupt: xmit intr, chip %d\n", chip); |
1227 | #endif | 1185 | #endif |
1228 | 1186 | ||
1229 | /* determine the channel & change to that context */ | 1187 | /* determine the channel & change to that context */ |
1230 | spin_lock(&cinfo->card_lock); | 1188 | spin_lock(&cinfo->card_lock); |
1231 | save_xir = (u_char) cy_readb(base_addr + (CyTIR << index)); | 1189 | save_xir = (u_char) readb(base_addr + (CyTIR << index)); |
1232 | channel = (u_short) (save_xir & CyIRChannel); | 1190 | channel = (u_short) (save_xir & CyIRChannel); |
1233 | i = channel + chip * 4 + cinfo->first_line; | 1191 | save_car = readb(base_addr + (CyCAR << index)); |
1234 | save_car = cy_readb(base_addr + (CyCAR << index)); | ||
1235 | cy_writeb(base_addr + (CyCAR << index), save_xir); | 1192 | cy_writeb(base_addr + (CyCAR << index), save_xir); |
1236 | 1193 | ||
1237 | /* validate the port# (as configured and open) */ | 1194 | /* validate the port# (as configured and open) */ |
1238 | if ((i < 0) || (NR_PORTS <= i)) { | 1195 | if (channel + chip * 4 >= cinfo->nports) { |
1239 | cy_writeb(base_addr + (CySRER << index), | 1196 | cy_writeb(base_addr + (CySRER << index), |
1240 | cy_readb(base_addr + (CySRER << index)) & | 1197 | readb(base_addr + (CySRER << index)) & |
1241 | ~CyTxRdy); | 1198 | ~CyTxRdy); |
1242 | goto txend; | 1199 | goto txend; |
1243 | } | 1200 | } |
1244 | info = &cy_port[i]; | 1201 | info = &cinfo->ports[channel + chip * 4]; |
1245 | info->last_active = jiffies; | 1202 | if (info->tty == NULL) { |
1246 | if (info->tty == 0) { | ||
1247 | cy_writeb(base_addr + (CySRER << index), | 1203 | cy_writeb(base_addr + (CySRER << index), |
1248 | cy_readb(base_addr + (CySRER << index)) & | 1204 | readb(base_addr + (CySRER << index)) & |
1249 | ~CyTxRdy); | 1205 | ~CyTxRdy); |
1250 | goto txdone; | 1206 | goto txdone; |
1251 | } | 1207 | } |
@@ -1278,29 +1234,29 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, | |||
1278 | 1234 | ||
1279 | while (char_count-- > 0) { | 1235 | while (char_count-- > 0) { |
1280 | if (!info->xmit_cnt) { | 1236 | if (!info->xmit_cnt) { |
1281 | if (cy_readb(base_addr + (CySRER << index)) & | 1237 | if (readb(base_addr + (CySRER << index)) & |
1282 | CyTxMpty) { | 1238 | CyTxMpty) { |
1283 | cy_writeb(base_addr + (CySRER << index), | 1239 | cy_writeb(base_addr + (CySRER << index), |
1284 | cy_readb(base_addr + | 1240 | readb(base_addr + |
1285 | (CySRER << index)) & | 1241 | (CySRER << index)) & |
1286 | ~CyTxMpty); | 1242 | ~CyTxMpty); |
1287 | } else { | 1243 | } else { |
1288 | cy_writeb(base_addr + (CySRER << index), | 1244 | cy_writeb(base_addr + (CySRER << index), |
1289 | (cy_readb(base_addr + | 1245 | (readb(base_addr + |
1290 | (CySRER << index)) & | 1246 | (CySRER << index)) & |
1291 | ~CyTxRdy) | CyTxMpty); | 1247 | ~CyTxRdy) | CyTxMpty); |
1292 | } | 1248 | } |
1293 | goto txdone; | 1249 | goto txdone; |
1294 | } | 1250 | } |
1295 | if (info->xmit_buf == 0) { | 1251 | if (info->xmit_buf == NULL) { |
1296 | cy_writeb(base_addr + (CySRER << index), | 1252 | cy_writeb(base_addr + (CySRER << index), |
1297 | cy_readb(base_addr + (CySRER << index))& | 1253 | readb(base_addr + (CySRER << index)) & |
1298 | ~CyTxRdy); | 1254 | ~CyTxRdy); |
1299 | goto txdone; | 1255 | goto txdone; |
1300 | } | 1256 | } |
1301 | if (info->tty->stopped || info->tty->hw_stopped) { | 1257 | if (info->tty->stopped || info->tty->hw_stopped) { |
1302 | cy_writeb(base_addr + (CySRER << index), | 1258 | cy_writeb(base_addr + (CySRER << index), |
1303 | cy_readb(base_addr + (CySRER << index))& | 1259 | readb(base_addr + (CySRER << index)) & |
1304 | ~CyTxRdy); | 1260 | ~CyTxRdy); |
1305 | goto txdone; | 1261 | goto txdone; |
1306 | } | 1262 | } |
@@ -1333,7 +1289,6 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, | |||
1333 | 0); | 1289 | 0); |
1334 | info->icount.tx++; | 1290 | info->icount.tx++; |
1335 | char_count--; | 1291 | char_count--; |
1336 | } else { | ||
1337 | } | 1292 | } |
1338 | } | 1293 | } |
1339 | } | 1294 | } |
@@ -1353,19 +1308,16 @@ txend: | |||
1353 | 1308 | ||
1354 | /* determine the channel & change to that context */ | 1309 | /* determine the channel & change to that context */ |
1355 | spin_lock(&cinfo->card_lock); | 1310 | spin_lock(&cinfo->card_lock); |
1356 | save_xir = (u_char) cy_readb(base_addr + (CyMIR << index)); | 1311 | save_xir = (u_char) readb(base_addr + (CyMIR << index)); |
1357 | channel = (u_short) (save_xir & CyIRChannel); | 1312 | channel = (u_short) (save_xir & CyIRChannel); |
1358 | info = &cy_port[channel + chip * 4 + cinfo->first_line]; | 1313 | info = &cinfo->ports[channel + chip * 4]; |
1359 | info->last_active = jiffies; | 1314 | save_car = readb(base_addr + (CyCAR << index)); |
1360 | save_car = cy_readb(base_addr + (CyCAR << index)); | ||
1361 | cy_writeb(base_addr + (CyCAR << index), save_xir); | 1315 | cy_writeb(base_addr + (CyCAR << index), save_xir); |
1362 | 1316 | ||
1363 | mdm_change = cy_readb(base_addr + (CyMISR << index)); | 1317 | mdm_change = readb(base_addr + (CyMISR << index)); |
1364 | mdm_status = cy_readb(base_addr + (CyMSVR1 << index)); | 1318 | mdm_status = readb(base_addr + (CyMSVR1 << index)); |
1365 | 1319 | ||
1366 | if (info->tty == 0) { /* no place for data, ignore it */ | 1320 | if (info->tty) { |
1367 | ; | ||
1368 | } else { | ||
1369 | if (mdm_change & CyANY_DELTA) { | 1321 | if (mdm_change & CyANY_DELTA) { |
1370 | /* For statistics only */ | 1322 | /* For statistics only */ |
1371 | if (mdm_change & CyDCD) | 1323 | if (mdm_change & CyDCD) |
@@ -1398,7 +1350,7 @@ txend: | |||
1398 | info->tty->hw_stopped = 0; | 1350 | info->tty->hw_stopped = 0; |
1399 | cy_writeb(base_addr + | 1351 | cy_writeb(base_addr + |
1400 | (CySRER << index), | 1352 | (CySRER << index), |
1401 | cy_readb(base_addr + | 1353 | readb(base_addr + |
1402 | (CySRER << | 1354 | (CySRER << |
1403 | index))| | 1355 | index))| |
1404 | CyTxRdy); | 1356 | CyTxRdy); |
@@ -1412,17 +1364,17 @@ txend: | |||
1412 | info->tty->hw_stopped = 1; | 1364 | info->tty->hw_stopped = 1; |
1413 | cy_writeb(base_addr + | 1365 | cy_writeb(base_addr + |
1414 | (CySRER << index), | 1366 | (CySRER << index), |
1415 | cy_readb(base_addr + | 1367 | readb(base_addr + |
1416 | (CySRER << | 1368 | (CySRER << |
1417 | index)) & | 1369 | index)) & |
1418 | ~CyTxRdy); | 1370 | ~CyTxRdy); |
1419 | } | 1371 | } |
1420 | } | 1372 | } |
1421 | } | 1373 | } |
1422 | if (mdm_change & CyDSR) { | 1374 | /* if (mdm_change & CyDSR) { |
1423 | } | 1375 | } |
1424 | if (mdm_change & CyRI) { | 1376 | if (mdm_change & CyRI) { |
1425 | } | 1377 | }*/ |
1426 | } | 1378 | } |
1427 | /* end of service */ | 1379 | /* end of service */ |
1428 | cy_writeb(base_addr + (CyMIR << index), (save_xir & 0x3f)); | 1380 | cy_writeb(base_addr + (CyMIR << index), (save_xir & 0x3f)); |
@@ -1438,16 +1390,16 @@ txend: | |||
1438 | static irqreturn_t cyy_interrupt(int irq, void *dev_id) | 1390 | static irqreturn_t cyy_interrupt(int irq, void *dev_id) |
1439 | { | 1391 | { |
1440 | int status; | 1392 | int status; |
1441 | struct cyclades_card *cinfo; | 1393 | struct cyclades_card *cinfo = dev_id; |
1442 | void __iomem *base_addr, *card_base_addr; | 1394 | void __iomem *base_addr, *card_base_addr; |
1443 | int chip; | 1395 | int chip; |
1444 | int index; | 1396 | int index; |
1445 | int too_many; | 1397 | int too_many; |
1446 | int had_work; | 1398 | int had_work; |
1447 | 1399 | ||
1448 | if ((cinfo = (struct cyclades_card *)dev_id) == 0) { | 1400 | if (unlikely(cinfo == NULL)) { |
1449 | #ifdef CY_DEBUG_INTERRUPTS | 1401 | #ifdef CY_DEBUG_INTERRUPTS |
1450 | printk("cyy_interrupt: spurious interrupt %d\n\r", irq); | 1402 | printk(KERN_DEBUG "cyy_interrupt: spurious interrupt %d\n",irq); |
1451 | #endif | 1403 | #endif |
1452 | return IRQ_NONE; /* spurious interrupt */ | 1404 | return IRQ_NONE; /* spurious interrupt */ |
1453 | } | 1405 | } |
@@ -1455,6 +1407,10 @@ static irqreturn_t cyy_interrupt(int irq, void *dev_id) | |||
1455 | card_base_addr = cinfo->base_addr; | 1407 | card_base_addr = cinfo->base_addr; |
1456 | index = cinfo->bus_index; | 1408 | index = cinfo->bus_index; |
1457 | 1409 | ||
1410 | /* card was not initialized yet (e.g. DEBUG_SHIRQ) */ | ||
1411 | if (unlikely(card_base_addr == NULL)) | ||
1412 | return IRQ_HANDLED; | ||
1413 | |||
1458 | /* This loop checks all chips in the card. Make a note whenever | 1414 | /* This loop checks all chips in the card. Make a note whenever |
1459 | _any_ chip had some work to do, as this is considered an | 1415 | _any_ chip had some work to do, as this is considered an |
1460 | indication that there will be more to do. Only when no chip | 1416 | indication that there will be more to do. Only when no chip |
@@ -1466,7 +1422,7 @@ static irqreturn_t cyy_interrupt(int irq, void *dev_id) | |||
1466 | base_addr = cinfo->base_addr + | 1422 | base_addr = cinfo->base_addr + |
1467 | (cy_chip_offset[chip] << index); | 1423 | (cy_chip_offset[chip] << index); |
1468 | too_many = 0; | 1424 | too_many = 0; |
1469 | while ((status = cy_readb(base_addr + | 1425 | while ((status = readb(base_addr + |
1470 | (CySVRR << index))) != 0x00) { | 1426 | (CySVRR << index))) != 0x00) { |
1471 | had_work++; | 1427 | had_work++; |
1472 | /* The purpose of the following test is to ensure that | 1428 | /* The purpose of the following test is to ensure that |
@@ -1498,7 +1454,7 @@ static irqreturn_t cyy_interrupt(int irq, void *dev_id) | |||
1498 | 1454 | ||
1499 | static int | 1455 | static int |
1500 | cyz_fetch_msg(struct cyclades_card *cinfo, | 1456 | cyz_fetch_msg(struct cyclades_card *cinfo, |
1501 | uclong * channel, ucchar * cmd, uclong * param) | 1457 | __u32 * channel, __u8 * cmd, __u32 * param) |
1502 | { | 1458 | { |
1503 | struct FIRM_ID __iomem *firm_id; | 1459 | struct FIRM_ID __iomem *firm_id; |
1504 | struct ZFW_CTRL __iomem *zfw_ctrl; | 1460 | struct ZFW_CTRL __iomem *zfw_ctrl; |
@@ -1509,16 +1465,15 @@ cyz_fetch_msg(struct cyclades_card *cinfo, | |||
1509 | if (!ISZLOADED(*cinfo)) { | 1465 | if (!ISZLOADED(*cinfo)) { |
1510 | return -1; | 1466 | return -1; |
1511 | } | 1467 | } |
1512 | zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & | 1468 | zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff); |
1513 | 0xfffff); | ||
1514 | board_ctrl = &zfw_ctrl->board_ctrl; | 1469 | board_ctrl = &zfw_ctrl->board_ctrl; |
1515 | 1470 | ||
1516 | loc_doorbell = cy_readl(&((struct RUNTIME_9060 __iomem *) | 1471 | loc_doorbell = readl(&((struct RUNTIME_9060 __iomem *) |
1517 | (cinfo->ctl_addr))->loc_doorbell); | 1472 | (cinfo->ctl_addr))->loc_doorbell); |
1518 | if (loc_doorbell) { | 1473 | if (loc_doorbell) { |
1519 | *cmd = (char)(0xff & loc_doorbell); | 1474 | *cmd = (char)(0xff & loc_doorbell); |
1520 | *channel = cy_readl(&board_ctrl->fwcmd_channel); | 1475 | *channel = readl(&board_ctrl->fwcmd_channel); |
1521 | *param = (uclong) cy_readl(&board_ctrl->fwcmd_param); | 1476 | *param = (__u32) readl(&board_ctrl->fwcmd_param); |
1522 | cy_writel(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))-> | 1477 | cy_writel(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))-> |
1523 | loc_doorbell, 0xffffffff); | 1478 | loc_doorbell, 0xffffffff); |
1524 | return 1; | 1479 | return 1; |
@@ -1528,28 +1483,27 @@ cyz_fetch_msg(struct cyclades_card *cinfo, | |||
1528 | 1483 | ||
1529 | static int | 1484 | static int |
1530 | cyz_issue_cmd(struct cyclades_card *cinfo, | 1485 | cyz_issue_cmd(struct cyclades_card *cinfo, |
1531 | uclong channel, ucchar cmd, uclong param) | 1486 | __u32 channel, __u8 cmd, __u32 param) |
1532 | { | 1487 | { |
1533 | struct FIRM_ID __iomem *firm_id; | 1488 | struct FIRM_ID __iomem *firm_id; |
1534 | struct ZFW_CTRL __iomem *zfw_ctrl; | 1489 | struct ZFW_CTRL __iomem *zfw_ctrl; |
1535 | struct BOARD_CTRL __iomem *board_ctrl; | 1490 | struct BOARD_CTRL __iomem *board_ctrl; |
1536 | unsigned long __iomem *pci_doorbell; | 1491 | __u32 __iomem *pci_doorbell; |
1537 | int index; | 1492 | int index; |
1538 | 1493 | ||
1539 | firm_id = cinfo->base_addr + ID_ADDRESS; | 1494 | firm_id = cinfo->base_addr + ID_ADDRESS; |
1540 | if (!ISZLOADED(*cinfo)) { | 1495 | if (!ISZLOADED(*cinfo)) { |
1541 | return -1; | 1496 | return -1; |
1542 | } | 1497 | } |
1543 | zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & | 1498 | zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff); |
1544 | 0xfffff); | ||
1545 | board_ctrl = &zfw_ctrl->board_ctrl; | 1499 | board_ctrl = &zfw_ctrl->board_ctrl; |
1546 | 1500 | ||
1547 | index = 0; | 1501 | index = 0; |
1548 | pci_doorbell = | 1502 | pci_doorbell = |
1549 | &((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->pci_doorbell; | 1503 | &((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->pci_doorbell; |
1550 | while ((cy_readl(pci_doorbell) & 0xff) != 0) { | 1504 | while ((readl(pci_doorbell) & 0xff) != 0) { |
1551 | if (index++ == 1000) { | 1505 | if (index++ == 1000) { |
1552 | return (int)(cy_readl(pci_doorbell) & 0xff); | 1506 | return (int)(readl(pci_doorbell) & 0xff); |
1553 | } | 1507 | } |
1554 | udelay(50L); | 1508 | udelay(50L); |
1555 | } | 1509 | } |
@@ -1561,34 +1515,30 @@ cyz_issue_cmd(struct cyclades_card *cinfo, | |||
1561 | } /* cyz_issue_cmd */ | 1515 | } /* cyz_issue_cmd */ |
1562 | 1516 | ||
1563 | static void | 1517 | static void |
1564 | cyz_handle_rx(struct cyclades_port *info, | 1518 | cyz_handle_rx(struct cyclades_port *info, struct CH_CTRL __iomem *ch_ctrl, |
1565 | volatile struct CH_CTRL __iomem * ch_ctrl, | 1519 | struct BUF_CTRL __iomem *buf_ctrl) |
1566 | volatile struct BUF_CTRL __iomem * buf_ctrl) | ||
1567 | { | 1520 | { |
1568 | struct cyclades_card *cinfo = &cy_card[info->card]; | 1521 | struct cyclades_card *cinfo = info->card; |
1569 | struct tty_struct *tty = info->tty; | 1522 | struct tty_struct *tty = info->tty; |
1570 | volatile int char_count; | 1523 | int char_count; |
1571 | int len; | 1524 | int len; |
1572 | #ifdef BLOCKMOVE | 1525 | #ifdef BLOCKMOVE |
1573 | int small_count; | 1526 | unsigned char *buf; |
1574 | #else | 1527 | #else |
1575 | char data; | 1528 | char data; |
1576 | #endif | 1529 | #endif |
1577 | volatile uclong rx_put, rx_get, new_rx_get, rx_bufsize, rx_bufaddr; | 1530 | __u32 rx_put, rx_get, new_rx_get, rx_bufsize, rx_bufaddr; |
1578 | 1531 | ||
1579 | rx_get = new_rx_get = cy_readl(&buf_ctrl->rx_get); | 1532 | rx_get = new_rx_get = readl(&buf_ctrl->rx_get); |
1580 | rx_put = cy_readl(&buf_ctrl->rx_put); | 1533 | rx_put = readl(&buf_ctrl->rx_put); |
1581 | rx_bufsize = cy_readl(&buf_ctrl->rx_bufsize); | 1534 | rx_bufsize = readl(&buf_ctrl->rx_bufsize); |
1582 | rx_bufaddr = cy_readl(&buf_ctrl->rx_bufaddr); | 1535 | rx_bufaddr = readl(&buf_ctrl->rx_bufaddr); |
1583 | if (rx_put >= rx_get) | 1536 | if (rx_put >= rx_get) |
1584 | char_count = rx_put - rx_get; | 1537 | char_count = rx_put - rx_get; |
1585 | else | 1538 | else |
1586 | char_count = rx_put - rx_get + rx_bufsize; | 1539 | char_count = rx_put - rx_get + rx_bufsize; |
1587 | 1540 | ||
1588 | if (char_count) { | 1541 | if (char_count) { |
1589 | info->last_active = jiffies; | ||
1590 | info->jiffies[1] = jiffies; | ||
1591 | |||
1592 | #ifdef CY_ENABLE_MONITORING | 1542 | #ifdef CY_ENABLE_MONITORING |
1593 | info->mon.int_count++; | 1543 | info->mon.int_count++; |
1594 | info->mon.char_count += char_count; | 1544 | info->mon.char_count += char_count; |
@@ -1596,7 +1546,7 @@ cyz_handle_rx(struct cyclades_port *info, | |||
1596 | info->mon.char_max = char_count; | 1546 | info->mon.char_max = char_count; |
1597 | info->mon.char_last = char_count; | 1547 | info->mon.char_last = char_count; |
1598 | #endif | 1548 | #endif |
1599 | if (tty == 0) { | 1549 | if (tty == NULL) { |
1600 | /* flush received characters */ | 1550 | /* flush received characters */ |
1601 | new_rx_get = (new_rx_get + char_count) & | 1551 | new_rx_get = (new_rx_get + char_count) & |
1602 | (rx_bufsize - 1); | 1552 | (rx_bufsize - 1); |
@@ -1606,30 +1556,28 @@ cyz_handle_rx(struct cyclades_port *info, | |||
1606 | /* we'd like to use memcpy(t, f, n) and memset(s, c, count) | 1556 | /* we'd like to use memcpy(t, f, n) and memset(s, c, count) |
1607 | for performance, but because of buffer boundaries, there | 1557 | for performance, but because of buffer boundaries, there |
1608 | may be several steps to the operation */ | 1558 | may be several steps to the operation */ |
1609 | while (0 < (small_count = min_t(unsigned int, | 1559 | while (1) { |
1610 | rx_bufsize - new_rx_get, | 1560 | len = tty_prepare_flip_string(tty, &buf, |
1611 | min_t(unsigned int, TTY_FLIPBUF_SIZE - | 1561 | char_count); |
1612 | tty->flip.count, char_count)))){ | 1562 | if (!len) |
1613 | memcpy_fromio(tty->flip.char_buf_ptr, | 1563 | break; |
1614 | (char *)(cinfo->base_addr + rx_bufaddr + | ||
1615 | new_rx_get), | ||
1616 | small_count); | ||
1617 | 1564 | ||
1618 | tty->flip.char_buf_ptr += small_count; | 1565 | len = min_t(unsigned int, min(len, char_count), |
1619 | memset(tty->flip.flag_buf_ptr, TTY_NORMAL, | 1566 | rx_bufsize - new_rx_get); |
1620 | small_count); | 1567 | |
1621 | tty->flip.flag_buf_ptr += small_count; | 1568 | memcpy_fromio(buf, cinfo->base_addr + |
1622 | new_rx_get = (new_rx_get + small_count) & | 1569 | rx_bufaddr + new_rx_get, len); |
1570 | |||
1571 | new_rx_get = (new_rx_get + len) & | ||
1623 | (rx_bufsize - 1); | 1572 | (rx_bufsize - 1); |
1624 | char_count -= small_count; | 1573 | char_count -= len; |
1625 | info->icount.rx += small_count; | 1574 | info->icount.rx += len; |
1626 | info->idle_stats.recv_bytes += small_count; | 1575 | info->idle_stats.recv_bytes += len; |
1627 | tty->flip.count += small_count; | ||
1628 | } | 1576 | } |
1629 | #else | 1577 | #else |
1630 | len = tty_buffer_request_room(tty, char_count); | 1578 | len = tty_buffer_request_room(tty, char_count); |
1631 | while (len--) { | 1579 | while (len--) { |
1632 | data = cy_readb(cinfo->base_addr + rx_bufaddr + | 1580 | data = readb(cinfo->base_addr + rx_bufaddr + |
1633 | new_rx_get); | 1581 | new_rx_get); |
1634 | new_rx_get = (new_rx_get + 1)& (rx_bufsize - 1); | 1582 | new_rx_get = (new_rx_get + 1)& (rx_bufsize - 1); |
1635 | tty_insert_flip_char(tty, data, TTY_NORMAL); | 1583 | tty_insert_flip_char(tty, data, TTY_NORMAL); |
@@ -1640,13 +1588,12 @@ cyz_handle_rx(struct cyclades_port *info, | |||
1640 | #ifdef CONFIG_CYZ_INTR | 1588 | #ifdef CONFIG_CYZ_INTR |
1641 | /* Recalculate the number of chars in the RX buffer and issue | 1589 | /* Recalculate the number of chars in the RX buffer and issue |
1642 | a cmd in case it's higher than the RX high water mark */ | 1590 | a cmd in case it's higher than the RX high water mark */ |
1643 | rx_put = cy_readl(&buf_ctrl->rx_put); | 1591 | rx_put = readl(&buf_ctrl->rx_put); |
1644 | if (rx_put >= rx_get) | 1592 | if (rx_put >= rx_get) |
1645 | char_count = rx_put - rx_get; | 1593 | char_count = rx_put - rx_get; |
1646 | else | 1594 | else |
1647 | char_count = rx_put - rx_get + rx_bufsize; | 1595 | char_count = rx_put - rx_get + rx_bufsize; |
1648 | if (char_count >= (int)cy_readl(&buf_ctrl-> | 1596 | if (char_count >= (int)readl(&buf_ctrl->rx_threshold)) { |
1649 | rx_threshold)) { | ||
1650 | cy_sched_event(info, Cy_EVENT_Z_RX_FULL); | 1597 | cy_sched_event(info, Cy_EVENT_Z_RX_FULL); |
1651 | } | 1598 | } |
1652 | #endif | 1599 | #endif |
@@ -1659,26 +1606,25 @@ cyz_handle_rx(struct cyclades_port *info, | |||
1659 | } | 1606 | } |
1660 | 1607 | ||
1661 | static void | 1608 | static void |
1662 | cyz_handle_tx(struct cyclades_port *info, | 1609 | cyz_handle_tx(struct cyclades_port *info, struct CH_CTRL __iomem *ch_ctrl, |
1663 | volatile struct CH_CTRL __iomem * ch_ctrl, | 1610 | struct BUF_CTRL __iomem *buf_ctrl) |
1664 | volatile struct BUF_CTRL __iomem * buf_ctrl) | ||
1665 | { | 1611 | { |
1666 | struct cyclades_card *cinfo = &cy_card[info->card]; | 1612 | struct cyclades_card *cinfo = info->card; |
1667 | struct tty_struct *tty = info->tty; | 1613 | struct tty_struct *tty = info->tty; |
1668 | char data; | 1614 | char data; |
1669 | volatile int char_count; | 1615 | int char_count; |
1670 | #ifdef BLOCKMOVE | 1616 | #ifdef BLOCKMOVE |
1671 | int small_count; | 1617 | int small_count; |
1672 | #endif | 1618 | #endif |
1673 | volatile uclong tx_put, tx_get, tx_bufsize, tx_bufaddr; | 1619 | __u32 tx_put, tx_get, tx_bufsize, tx_bufaddr; |
1674 | 1620 | ||
1675 | if (info->xmit_cnt <= 0) /* Nothing to transmit */ | 1621 | if (info->xmit_cnt <= 0) /* Nothing to transmit */ |
1676 | return; | 1622 | return; |
1677 | 1623 | ||
1678 | tx_get = cy_readl(&buf_ctrl->tx_get); | 1624 | tx_get = readl(&buf_ctrl->tx_get); |
1679 | tx_put = cy_readl(&buf_ctrl->tx_put); | 1625 | tx_put = readl(&buf_ctrl->tx_put); |
1680 | tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize); | 1626 | tx_bufsize = readl(&buf_ctrl->tx_bufsize); |
1681 | tx_bufaddr = cy_readl(&buf_ctrl->tx_bufaddr); | 1627 | tx_bufaddr = readl(&buf_ctrl->tx_bufaddr); |
1682 | if (tx_put >= tx_get) | 1628 | if (tx_put >= tx_get) |
1683 | char_count = tx_get - tx_put - 1 + tx_bufsize; | 1629 | char_count = tx_get - tx_put - 1 + tx_bufsize; |
1684 | else | 1630 | else |
@@ -1686,9 +1632,8 @@ cyz_handle_tx(struct cyclades_port *info, | |||
1686 | 1632 | ||
1687 | if (char_count) { | 1633 | if (char_count) { |
1688 | 1634 | ||
1689 | if (tty == 0) { | 1635 | if (tty == NULL) |
1690 | goto ztxdone; | 1636 | goto ztxdone; |
1691 | } | ||
1692 | 1637 | ||
1693 | if (info->x_char) { /* send special char */ | 1638 | if (info->x_char) { /* send special char */ |
1694 | data = info->x_char; | 1639 | data = info->x_char; |
@@ -1698,8 +1643,6 @@ cyz_handle_tx(struct cyclades_port *info, | |||
1698 | info->x_char = 0; | 1643 | info->x_char = 0; |
1699 | char_count--; | 1644 | char_count--; |
1700 | info->icount.tx++; | 1645 | info->icount.tx++; |
1701 | info->last_active = jiffies; | ||
1702 | info->jiffies[2] = jiffies; | ||
1703 | } | 1646 | } |
1704 | #ifdef BLOCKMOVE | 1647 | #ifdef BLOCKMOVE |
1705 | while (0 < (small_count = min_t(unsigned int, | 1648 | while (0 < (small_count = min_t(unsigned int, |
@@ -1719,8 +1662,6 @@ cyz_handle_tx(struct cyclades_port *info, | |||
1719 | info->xmit_cnt -= small_count; | 1662 | info->xmit_cnt -= small_count; |
1720 | info->xmit_tail = (info->xmit_tail + small_count) & | 1663 | info->xmit_tail = (info->xmit_tail + small_count) & |
1721 | (SERIAL_XMIT_SIZE - 1); | 1664 | (SERIAL_XMIT_SIZE - 1); |
1722 | info->last_active = jiffies; | ||
1723 | info->jiffies[2] = jiffies; | ||
1724 | } | 1665 | } |
1725 | #else | 1666 | #else |
1726 | while (info->xmit_cnt && char_count) { | 1667 | while (info->xmit_cnt && char_count) { |
@@ -1733,8 +1674,6 @@ cyz_handle_tx(struct cyclades_port *info, | |||
1733 | tx_put = (tx_put + 1) & (tx_bufsize - 1); | 1674 | tx_put = (tx_put + 1) & (tx_bufsize - 1); |
1734 | char_count--; | 1675 | char_count--; |
1735 | info->icount.tx++; | 1676 | info->icount.tx++; |
1736 | info->last_active = jiffies; | ||
1737 | info->jiffies[2] = jiffies; | ||
1738 | } | 1677 | } |
1739 | #endif | 1678 | #endif |
1740 | ztxdone: | 1679 | ztxdone: |
@@ -1750,33 +1689,32 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo) | |||
1750 | { | 1689 | { |
1751 | struct tty_struct *tty; | 1690 | struct tty_struct *tty; |
1752 | struct cyclades_port *info; | 1691 | struct cyclades_port *info; |
1753 | static volatile struct FIRM_ID __iomem *firm_id; | 1692 | static struct FIRM_ID __iomem *firm_id; |
1754 | static volatile struct ZFW_CTRL __iomem *zfw_ctrl; | 1693 | static struct ZFW_CTRL __iomem *zfw_ctrl; |
1755 | static volatile struct BOARD_CTRL __iomem *board_ctrl; | 1694 | static struct BOARD_CTRL __iomem *board_ctrl; |
1756 | static volatile struct CH_CTRL __iomem *ch_ctrl; | 1695 | static struct CH_CTRL __iomem *ch_ctrl; |
1757 | static volatile struct BUF_CTRL __iomem *buf_ctrl; | 1696 | static struct BUF_CTRL __iomem *buf_ctrl; |
1758 | uclong channel; | 1697 | __u32 channel; |
1759 | ucchar cmd; | 1698 | __u8 cmd; |
1760 | uclong param; | 1699 | __u32 param; |
1761 | uclong hw_ver, fw_ver; | 1700 | __u32 hw_ver, fw_ver; |
1762 | int special_count; | 1701 | int special_count; |
1763 | int delta_count; | 1702 | int delta_count; |
1764 | 1703 | ||
1765 | firm_id = cinfo->base_addr + ID_ADDRESS; | 1704 | firm_id = cinfo->base_addr + ID_ADDRESS; |
1766 | zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & | 1705 | zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff); |
1767 | 0xfffff); | ||
1768 | board_ctrl = &zfw_ctrl->board_ctrl; | 1706 | board_ctrl = &zfw_ctrl->board_ctrl; |
1769 | fw_ver = cy_readl(&board_ctrl->fw_version); | 1707 | fw_ver = readl(&board_ctrl->fw_version); |
1770 | hw_ver = cy_readl(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))-> | 1708 | hw_ver = readl(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))-> |
1771 | mail_box_0); | 1709 | mail_box_0); |
1772 | 1710 | ||
1773 | while (cyz_fetch_msg(cinfo, &channel, &cmd, ¶m) == 1) { | 1711 | while (cyz_fetch_msg(cinfo, &channel, &cmd, ¶m) == 1) { |
1774 | special_count = 0; | 1712 | special_count = 0; |
1775 | delta_count = 0; | 1713 | delta_count = 0; |
1776 | info = &cy_port[channel + cinfo->first_line]; | 1714 | info = &cinfo->ports[channel]; |
1777 | if ((tty = info->tty) == 0) { | 1715 | if ((tty = info->tty) == NULL) |
1778 | continue; | 1716 | continue; |
1779 | } | 1717 | |
1780 | ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); | 1718 | ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); |
1781 | buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]); | 1719 | buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]); |
1782 | 1720 | ||
@@ -1801,7 +1739,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo) | |||
1801 | delta_count++; | 1739 | delta_count++; |
1802 | if (info->flags & ASYNC_CHECK_CD) { | 1740 | if (info->flags & ASYNC_CHECK_CD) { |
1803 | if ((fw_ver > 241 ? ((u_long) param) : | 1741 | if ((fw_ver > 241 ? ((u_long) param) : |
1804 | cy_readl(&ch_ctrl->rs_status)) & | 1742 | readl(&ch_ctrl->rs_status)) & |
1805 | C_RS_DCD) { | 1743 | C_RS_DCD) { |
1806 | cy_sched_event(info, | 1744 | cy_sched_event(info, |
1807 | Cy_EVENT_OPEN_WAKEUP); | 1745 | Cy_EVENT_OPEN_WAKEUP); |
@@ -1833,8 +1771,8 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo) | |||
1833 | case C_CM_INTBACK2: | 1771 | case C_CM_INTBACK2: |
1834 | /* Reception Interrupt */ | 1772 | /* Reception Interrupt */ |
1835 | #ifdef CY_DEBUG_INTERRUPTS | 1773 | #ifdef CY_DEBUG_INTERRUPTS |
1836 | printk("cyz_interrupt: rcvd intr, card %d, " | 1774 | printk(KERN_DEBUG "cyz_interrupt: rcvd intr, card %d, " |
1837 | "port %ld\n\r", info->card, channel); | 1775 | "port %ld\n", info->card, channel); |
1838 | #endif | 1776 | #endif |
1839 | cyz_handle_rx(info, ch_ctrl, buf_ctrl); | 1777 | cyz_handle_rx(info, ch_ctrl, buf_ctrl); |
1840 | break; | 1778 | break; |
@@ -1843,8 +1781,8 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo) | |||
1843 | case C_CM_INTBACK: | 1781 | case C_CM_INTBACK: |
1844 | /* Transmission Interrupt */ | 1782 | /* Transmission Interrupt */ |
1845 | #ifdef CY_DEBUG_INTERRUPTS | 1783 | #ifdef CY_DEBUG_INTERRUPTS |
1846 | printk("cyz_interrupt: xmit intr, card %d, " | 1784 | printk(KERN_DEBUG "cyz_interrupt: xmit intr, card %d, " |
1847 | "port %ld\n\r", info->card, channel); | 1785 | "port %ld\n", info->card, channel); |
1848 | #endif | 1786 | #endif |
1849 | cyz_handle_tx(info, ch_ctrl, buf_ctrl); | 1787 | cyz_handle_tx(info, ch_ctrl, buf_ctrl); |
1850 | break; | 1788 | break; |
@@ -1865,18 +1803,19 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo) | |||
1865 | #ifdef CONFIG_CYZ_INTR | 1803 | #ifdef CONFIG_CYZ_INTR |
1866 | static irqreturn_t cyz_interrupt(int irq, void *dev_id) | 1804 | static irqreturn_t cyz_interrupt(int irq, void *dev_id) |
1867 | { | 1805 | { |
1868 | struct cyclades_card *cinfo; | 1806 | struct cyclades_card *cinfo = dev_id; |
1869 | 1807 | ||
1870 | if ((cinfo = (struct cyclades_card *)dev_id) == 0) { | 1808 | if (unlikely(cinfo == NULL)) { |
1871 | #ifdef CY_DEBUG_INTERRUPTS | 1809 | #ifdef CY_DEBUG_INTERRUPTS |
1872 | printk("cyz_interrupt: spurious interrupt %d\n\r", irq); | 1810 | printk(KERN_DEBUG "cyz_interrupt: spurious interrupt %d\n",irq); |
1873 | #endif | 1811 | #endif |
1874 | return IRQ_NONE; /* spurious interrupt */ | 1812 | return IRQ_NONE; /* spurious interrupt */ |
1875 | } | 1813 | } |
1876 | 1814 | ||
1877 | if (!ISZLOADED(*cinfo)) { | 1815 | if (unlikely(!ISZLOADED(*cinfo))) { |
1878 | #ifdef CY_DEBUG_INTERRUPTS | 1816 | #ifdef CY_DEBUG_INTERRUPTS |
1879 | printk("cyz_interrupt: board not yet loaded (IRQ%d).\n\r", irq); | 1817 | printk(KERN_DEBUG "cyz_interrupt: board not yet loaded " |
1818 | "(IRQ%d).\n", irq); | ||
1880 | #endif | 1819 | #endif |
1881 | return IRQ_NONE; | 1820 | return IRQ_NONE; |
1882 | } | 1821 | } |
@@ -1890,19 +1829,18 @@ static irqreturn_t cyz_interrupt(int irq, void *dev_id) | |||
1890 | static void cyz_rx_restart(unsigned long arg) | 1829 | static void cyz_rx_restart(unsigned long arg) |
1891 | { | 1830 | { |
1892 | struct cyclades_port *info = (struct cyclades_port *)arg; | 1831 | struct cyclades_port *info = (struct cyclades_port *)arg; |
1832 | struct cyclades_card *card = info->card; | ||
1893 | int retval; | 1833 | int retval; |
1894 | int card = info->card; | 1834 | __u32 channel = info->line - card->first_line; |
1895 | uclong channel = (info->line) - (cy_card[card].first_line); | ||
1896 | unsigned long flags; | 1835 | unsigned long flags; |
1897 | 1836 | ||
1898 | CY_LOCK(info, flags); | 1837 | spin_lock_irqsave(&card->card_lock, flags); |
1899 | retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK2, 0L); | 1838 | retval = cyz_issue_cmd(card, channel, C_CM_INTBACK2, 0L); |
1900 | if (retval != 0) { | 1839 | if (retval != 0) { |
1901 | printk("cyc:cyz_rx_restart retval on ttyC%d was %x\n", | 1840 | printk(KERN_ERR "cyc:cyz_rx_restart retval on ttyC%d was %x\n", |
1902 | info->line, retval); | 1841 | info->line, retval); |
1903 | } | 1842 | } |
1904 | cyz_rx_full_timer[info->line].function = NULL; | 1843 | spin_unlock_irqrestore(&card->card_lock, flags); |
1905 | CY_UNLOCK(info, flags); | ||
1906 | } | 1844 | } |
1907 | 1845 | ||
1908 | #else /* CONFIG_CYZ_INTR */ | 1846 | #else /* CONFIG_CYZ_INTR */ |
@@ -1912,14 +1850,14 @@ static void cyz_poll(unsigned long arg) | |||
1912 | struct cyclades_card *cinfo; | 1850 | struct cyclades_card *cinfo; |
1913 | struct cyclades_port *info; | 1851 | struct cyclades_port *info; |
1914 | struct tty_struct *tty; | 1852 | struct tty_struct *tty; |
1915 | static volatile struct FIRM_ID *firm_id; | 1853 | static struct FIRM_ID *firm_id; |
1916 | static volatile struct ZFW_CTRL *zfw_ctrl; | 1854 | static struct ZFW_CTRL *zfw_ctrl; |
1917 | static volatile struct BOARD_CTRL *board_ctrl; | 1855 | static struct BOARD_CTRL *board_ctrl; |
1918 | static volatile struct CH_CTRL *ch_ctrl; | 1856 | static struct CH_CTRL *ch_ctrl; |
1919 | static volatile struct BUF_CTRL *buf_ctrl; | 1857 | static struct BUF_CTRL *buf_ctrl; |
1858 | unsigned long expires = jiffies + HZ; | ||
1920 | int card, port; | 1859 | int card, port; |
1921 | 1860 | ||
1922 | cyz_timerlist.expires = jiffies + (HZ); | ||
1923 | for (card = 0; card < NR_CARDS; card++) { | 1861 | for (card = 0; card < NR_CARDS; card++) { |
1924 | cinfo = &cy_card[card]; | 1862 | cinfo = &cy_card[card]; |
1925 | 1863 | ||
@@ -1930,12 +1868,12 @@ static void cyz_poll(unsigned long arg) | |||
1930 | 1868 | ||
1931 | firm_id = cinfo->base_addr + ID_ADDRESS; | 1869 | firm_id = cinfo->base_addr + ID_ADDRESS; |
1932 | zfw_ctrl = cinfo->base_addr + | 1870 | zfw_ctrl = cinfo->base_addr + |
1933 | (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); | 1871 | (readl(&firm_id->zfwctrl_addr) & 0xfffff); |
1934 | board_ctrl = &(zfw_ctrl->board_ctrl); | 1872 | board_ctrl = &(zfw_ctrl->board_ctrl); |
1935 | 1873 | ||
1936 | /* Skip first polling cycle to avoid racing conditions with the FW */ | 1874 | /* Skip first polling cycle to avoid racing conditions with the FW */ |
1937 | if (!cinfo->intr_enabled) { | 1875 | if (!cinfo->intr_enabled) { |
1938 | cinfo->nports = (int)cy_readl(&board_ctrl->n_channel); | 1876 | cinfo->nports = (int)readl(&board_ctrl->n_channel); |
1939 | cinfo->intr_enabled = 1; | 1877 | cinfo->intr_enabled = 1; |
1940 | continue; | 1878 | continue; |
1941 | } | 1879 | } |
@@ -1943,7 +1881,7 @@ static void cyz_poll(unsigned long arg) | |||
1943 | cyz_handle_cmd(cinfo); | 1881 | cyz_handle_cmd(cinfo); |
1944 | 1882 | ||
1945 | for (port = 0; port < cinfo->nports; port++) { | 1883 | for (port = 0; port < cinfo->nports; port++) { |
1946 | info = &cy_port[port + cinfo->first_line]; | 1884 | info = &cinfo->ports[port]; |
1947 | tty = info->tty; | 1885 | tty = info->tty; |
1948 | ch_ctrl = &(zfw_ctrl->ch_ctrl[port]); | 1886 | ch_ctrl = &(zfw_ctrl->ch_ctrl[port]); |
1949 | buf_ctrl = &(zfw_ctrl->buf_ctrl[port]); | 1887 | buf_ctrl = &(zfw_ctrl->buf_ctrl[port]); |
@@ -1953,9 +1891,9 @@ static void cyz_poll(unsigned long arg) | |||
1953 | cyz_handle_tx(info, ch_ctrl, buf_ctrl); | 1891 | cyz_handle_tx(info, ch_ctrl, buf_ctrl); |
1954 | } | 1892 | } |
1955 | /* poll every 'cyz_polling_cycle' period */ | 1893 | /* poll every 'cyz_polling_cycle' period */ |
1956 | cyz_timerlist.expires = jiffies + cyz_polling_cycle; | 1894 | expires = jiffies + cyz_polling_cycle; |
1957 | } | 1895 | } |
1958 | add_timer(&cyz_timerlist); | 1896 | mod_timer(&cyz_timerlist, expires); |
1959 | } /* cyz_poll */ | 1897 | } /* cyz_poll */ |
1960 | 1898 | ||
1961 | #endif /* CONFIG_CYZ_INTR */ | 1899 | #endif /* CONFIG_CYZ_INTR */ |
@@ -1968,20 +1906,21 @@ static void cyz_poll(unsigned long arg) | |||
1968 | */ | 1906 | */ |
1969 | static int startup(struct cyclades_port *info) | 1907 | static int startup(struct cyclades_port *info) |
1970 | { | 1908 | { |
1909 | struct cyclades_card *card; | ||
1971 | unsigned long flags; | 1910 | unsigned long flags; |
1972 | int retval = 0; | 1911 | int retval = 0; |
1973 | void __iomem *base_addr; | 1912 | void __iomem *base_addr; |
1974 | int card, chip, channel, index; | 1913 | int chip, channel, index; |
1975 | unsigned long page; | 1914 | unsigned long page; |
1976 | 1915 | ||
1977 | card = info->card; | 1916 | card = info->card; |
1978 | channel = (info->line) - (cy_card[card].first_line); | 1917 | channel = info->line - card->first_line; |
1979 | 1918 | ||
1980 | page = get_zeroed_page(GFP_KERNEL); | 1919 | page = get_zeroed_page(GFP_KERNEL); |
1981 | if (!page) | 1920 | if (!page) |
1982 | return -ENOMEM; | 1921 | return -ENOMEM; |
1983 | 1922 | ||
1984 | CY_LOCK(info, flags); | 1923 | spin_lock_irqsave(&card->card_lock, flags); |
1985 | 1924 | ||
1986 | if (info->flags & ASYNC_INITIALIZED) { | 1925 | if (info->flags & ASYNC_INITIALIZED) { |
1987 | free_page(page); | 1926 | free_page(page); |
@@ -2001,24 +1940,22 @@ static int startup(struct cyclades_port *info) | |||
2001 | else | 1940 | else |
2002 | info->xmit_buf = (unsigned char *)page; | 1941 | info->xmit_buf = (unsigned char *)page; |
2003 | 1942 | ||
2004 | CY_UNLOCK(info, flags); | 1943 | spin_unlock_irqrestore(&card->card_lock, flags); |
2005 | 1944 | ||
2006 | set_line_char(info); | 1945 | set_line_char(info); |
2007 | 1946 | ||
2008 | if (!IS_CYC_Z(cy_card[card])) { | 1947 | if (!IS_CYC_Z(*card)) { |
2009 | chip = channel >> 2; | 1948 | chip = channel >> 2; |
2010 | channel &= 0x03; | 1949 | channel &= 0x03; |
2011 | index = cy_card[card].bus_index; | 1950 | index = card->bus_index; |
2012 | base_addr = cy_card[card].base_addr + | 1951 | base_addr = card->base_addr + (cy_chip_offset[chip] << index); |
2013 | (cy_chip_offset[chip] << index); | ||
2014 | 1952 | ||
2015 | #ifdef CY_DEBUG_OPEN | 1953 | #ifdef CY_DEBUG_OPEN |
2016 | printk("cyc startup card %d, chip %d, channel %d, " | 1954 | printk(KERN_DEBUG "cyc startup card %d, chip %d, channel %d, " |
2017 | "base_addr %lx\n", | 1955 | "base_addr %p\n", |
2018 | card, chip, channel, (long)base_addr); | 1956 | card, chip, channel, base_addr); |
2019 | /**/ | ||
2020 | #endif | 1957 | #endif |
2021 | CY_LOCK(info, flags); | 1958 | spin_lock_irqsave(&card->card_lock, flags); |
2022 | 1959 | ||
2023 | cy_writeb(base_addr + (CyCAR << index), (u_char) channel); | 1960 | cy_writeb(base_addr + (CyCAR << index), (u_char) channel); |
2024 | 1961 | ||
@@ -2034,14 +1971,14 @@ static int startup(struct cyclades_port *info) | |||
2034 | cy_writeb(base_addr + (CyMSVR2 << index), CyDTR); | 1971 | cy_writeb(base_addr + (CyMSVR2 << index), CyDTR); |
2035 | 1972 | ||
2036 | #ifdef CY_DEBUG_DTR | 1973 | #ifdef CY_DEBUG_DTR |
2037 | printk("cyc:startup raising DTR\n"); | 1974 | printk(KERN_DEBUG "cyc:startup raising DTR\n"); |
2038 | printk(" status: 0x%x, 0x%x\n", | 1975 | printk(KERN_DEBUG " status: 0x%x, 0x%x\n", |
2039 | cy_readb(base_addr + (CyMSVR1 << index)), | 1976 | readb(base_addr + (CyMSVR1 << index)), |
2040 | cy_readb(base_addr + (CyMSVR2 << index))); | 1977 | readb(base_addr + (CyMSVR2 << index))); |
2041 | #endif | 1978 | #endif |
2042 | 1979 | ||
2043 | cy_writeb(base_addr + (CySRER << index), | 1980 | cy_writeb(base_addr + (CySRER << index), |
2044 | cy_readb(base_addr + (CySRER << index)) | CyRxData); | 1981 | readb(base_addr + (CySRER << index)) | CyRxData); |
2045 | info->flags |= ASYNC_INITIALIZED; | 1982 | info->flags |= ASYNC_INITIALIZED; |
2046 | 1983 | ||
2047 | if (info->tty) { | 1984 | if (info->tty) { |
@@ -2054,7 +1991,7 @@ static int startup(struct cyclades_port *info) | |||
2054 | info->idle_stats.recv_idle = | 1991 | info->idle_stats.recv_idle = |
2055 | info->idle_stats.xmit_idle = jiffies; | 1992 | info->idle_stats.xmit_idle = jiffies; |
2056 | 1993 | ||
2057 | CY_UNLOCK(info, flags); | 1994 | spin_unlock_irqrestore(&card->card_lock, flags); |
2058 | 1995 | ||
2059 | } else { | 1996 | } else { |
2060 | struct FIRM_ID __iomem *firm_id; | 1997 | struct FIRM_ID __iomem *firm_id; |
@@ -2063,24 +2000,23 @@ static int startup(struct cyclades_port *info) | |||
2063 | struct CH_CTRL __iomem *ch_ctrl; | 2000 | struct CH_CTRL __iomem *ch_ctrl; |
2064 | int retval; | 2001 | int retval; |
2065 | 2002 | ||
2066 | base_addr = cy_card[card].base_addr; | 2003 | base_addr = card->base_addr; |
2067 | 2004 | ||
2068 | firm_id = base_addr + ID_ADDRESS; | 2005 | firm_id = base_addr + ID_ADDRESS; |
2069 | if (!ISZLOADED(cy_card[card])) { | 2006 | if (!ISZLOADED(*card)) { |
2070 | return -ENODEV; | 2007 | return -ENODEV; |
2071 | } | 2008 | } |
2072 | 2009 | ||
2073 | zfw_ctrl = cy_card[card].base_addr + | 2010 | zfw_ctrl = card->base_addr + |
2074 | (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); | 2011 | (readl(&firm_id->zfwctrl_addr) & 0xfffff); |
2075 | board_ctrl = &zfw_ctrl->board_ctrl; | 2012 | board_ctrl = &zfw_ctrl->board_ctrl; |
2076 | ch_ctrl = zfw_ctrl->ch_ctrl; | 2013 | ch_ctrl = zfw_ctrl->ch_ctrl; |
2077 | 2014 | ||
2078 | #ifdef CY_DEBUG_OPEN | 2015 | #ifdef CY_DEBUG_OPEN |
2079 | printk("cyc startup Z card %d, channel %d, base_addr %lx\n", | 2016 | printk(KERN_DEBUG "cyc startup Z card %d, channel %d, " |
2080 | card, channel, (long)base_addr); | 2017 | "base_addr %p\n", card, channel, base_addr); |
2081 | /**/ | ||
2082 | #endif | 2018 | #endif |
2083 | CY_LOCK(info, flags); | 2019 | spin_lock_irqsave(&card->card_lock, flags); |
2084 | 2020 | ||
2085 | cy_writel(&ch_ctrl[channel].op_mode, C_CH_ENABLE); | 2021 | cy_writel(&ch_ctrl[channel].op_mode, C_CH_ENABLE); |
2086 | #ifdef Z_WAKE | 2022 | #ifdef Z_WAKE |
@@ -2102,33 +2038,31 @@ static int startup(struct cyclades_port *info) | |||
2102 | #endif /* CONFIG_CYZ_INTR */ | 2038 | #endif /* CONFIG_CYZ_INTR */ |
2103 | #endif /* Z_WAKE */ | 2039 | #endif /* Z_WAKE */ |
2104 | 2040 | ||
2105 | retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L); | 2041 | retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L); |
2106 | if (retval != 0) { | 2042 | if (retval != 0) { |
2107 | printk("cyc:startup(1) retval on ttyC%d was %x\n", | 2043 | printk(KERN_ERR "cyc:startup(1) retval on ttyC%d was " |
2108 | info->line, retval); | 2044 | "%x\n", info->line, retval); |
2109 | } | 2045 | } |
2110 | 2046 | ||
2111 | /* Flush RX buffers before raising DTR and RTS */ | 2047 | /* Flush RX buffers before raising DTR and RTS */ |
2112 | retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_RX, | 2048 | retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_RX, 0L); |
2113 | 0L); | ||
2114 | if (retval != 0) { | 2049 | if (retval != 0) { |
2115 | printk("cyc:startup(2) retval on ttyC%d was %x\n", | 2050 | printk(KERN_ERR "cyc:startup(2) retval on ttyC%d was " |
2116 | info->line, retval); | 2051 | "%x\n", info->line, retval); |
2117 | } | 2052 | } |
2118 | 2053 | ||
2119 | /* set timeout !!! */ | 2054 | /* set timeout !!! */ |
2120 | /* set RTS and DTR !!! */ | 2055 | /* set RTS and DTR !!! */ |
2121 | cy_writel(&ch_ctrl[channel].rs_control, | 2056 | cy_writel(&ch_ctrl[channel].rs_control, |
2122 | cy_readl(&ch_ctrl[channel].rs_control) | C_RS_RTS | | 2057 | readl(&ch_ctrl[channel].rs_control) | C_RS_RTS | |
2123 | C_RS_DTR); | 2058 | C_RS_DTR); |
2124 | retval = cyz_issue_cmd(&cy_card[info->card], channel, | 2059 | retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L); |
2125 | C_CM_IOCTLM, 0L); | ||
2126 | if (retval != 0) { | 2060 | if (retval != 0) { |
2127 | printk("cyc:startup(3) retval on ttyC%d was %x\n", | 2061 | printk(KERN_ERR "cyc:startup(3) retval on ttyC%d was " |
2128 | info->line, retval); | 2062 | "%x\n", info->line, retval); |
2129 | } | 2063 | } |
2130 | #ifdef CY_DEBUG_DTR | 2064 | #ifdef CY_DEBUG_DTR |
2131 | printk("cyc:startup raising Z DTR\n"); | 2065 | printk(KERN_DEBUG "cyc:startup raising Z DTR\n"); |
2132 | #endif | 2066 | #endif |
2133 | 2067 | ||
2134 | /* enable send, recv, modem !!! */ | 2068 | /* enable send, recv, modem !!! */ |
@@ -2144,51 +2078,50 @@ static int startup(struct cyclades_port *info) | |||
2144 | info->idle_stats.recv_idle = | 2078 | info->idle_stats.recv_idle = |
2145 | info->idle_stats.xmit_idle = jiffies; | 2079 | info->idle_stats.xmit_idle = jiffies; |
2146 | 2080 | ||
2147 | CY_UNLOCK(info, flags); | 2081 | spin_unlock_irqrestore(&card->card_lock, flags); |
2148 | } | 2082 | } |
2149 | 2083 | ||
2150 | #ifdef CY_DEBUG_OPEN | 2084 | #ifdef CY_DEBUG_OPEN |
2151 | printk(" cyc startup done\n"); | 2085 | printk(KERN_DEBUG "cyc startup done\n"); |
2152 | #endif | 2086 | #endif |
2153 | return 0; | 2087 | return 0; |
2154 | 2088 | ||
2155 | errout: | 2089 | errout: |
2156 | CY_UNLOCK(info, flags); | 2090 | spin_unlock_irqrestore(&card->card_lock, flags); |
2157 | return retval; | 2091 | return retval; |
2158 | } /* startup */ | 2092 | } /* startup */ |
2159 | 2093 | ||
2160 | static void start_xmit(struct cyclades_port *info) | 2094 | static void start_xmit(struct cyclades_port *info) |
2161 | { | 2095 | { |
2096 | struct cyclades_card *card; | ||
2162 | unsigned long flags; | 2097 | unsigned long flags; |
2163 | void __iomem *base_addr; | 2098 | void __iomem *base_addr; |
2164 | int card, chip, channel, index; | 2099 | int chip, channel, index; |
2165 | 2100 | ||
2166 | card = info->card; | 2101 | card = info->card; |
2167 | channel = (info->line) - (cy_card[card].first_line); | 2102 | channel = info->line - card->first_line; |
2168 | if (!IS_CYC_Z(cy_card[card])) { | 2103 | if (!IS_CYC_Z(*card)) { |
2169 | chip = channel >> 2; | 2104 | chip = channel >> 2; |
2170 | channel &= 0x03; | 2105 | channel &= 0x03; |
2171 | index = cy_card[card].bus_index; | 2106 | index = card->bus_index; |
2172 | base_addr = cy_card[card].base_addr + | 2107 | base_addr = card->base_addr + (cy_chip_offset[chip] << index); |
2173 | (cy_chip_offset[chip] << index); | ||
2174 | 2108 | ||
2175 | CY_LOCK(info, flags); | 2109 | spin_lock_irqsave(&card->card_lock, flags); |
2176 | cy_writeb(base_addr + (CyCAR << index), channel); | 2110 | cy_writeb(base_addr + (CyCAR << index), channel); |
2177 | cy_writeb(base_addr + (CySRER << index), | 2111 | cy_writeb(base_addr + (CySRER << index), |
2178 | cy_readb(base_addr + (CySRER << index)) | CyTxRdy); | 2112 | readb(base_addr + (CySRER << index)) | CyTxRdy); |
2179 | CY_UNLOCK(info, flags); | 2113 | spin_unlock_irqrestore(&card->card_lock, flags); |
2180 | } else { | 2114 | } else { |
2181 | #ifdef CONFIG_CYZ_INTR | 2115 | #ifdef CONFIG_CYZ_INTR |
2182 | int retval; | 2116 | int retval; |
2183 | 2117 | ||
2184 | CY_LOCK(info, flags); | 2118 | spin_lock_irqsave(&card->card_lock, flags); |
2185 | retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK, | 2119 | retval = cyz_issue_cmd(card, channel, C_CM_INTBACK, 0L); |
2186 | 0L); | ||
2187 | if (retval != 0) { | 2120 | if (retval != 0) { |
2188 | printk("cyc:start_xmit retval on ttyC%d was %x\n", | 2121 | printk(KERN_ERR "cyc:start_xmit retval on ttyC%d was " |
2189 | info->line, retval); | 2122 | "%x\n", info->line, retval); |
2190 | } | 2123 | } |
2191 | CY_UNLOCK(info, flags); | 2124 | spin_unlock_irqrestore(&card->card_lock, flags); |
2192 | #else /* CONFIG_CYZ_INTR */ | 2125 | #else /* CONFIG_CYZ_INTR */ |
2193 | /* Don't have to do anything at this time */ | 2126 | /* Don't have to do anything at this time */ |
2194 | #endif /* CONFIG_CYZ_INTR */ | 2127 | #endif /* CONFIG_CYZ_INTR */ |
@@ -2201,30 +2134,30 @@ static void start_xmit(struct cyclades_port *info) | |||
2201 | */ | 2134 | */ |
2202 | static void shutdown(struct cyclades_port *info) | 2135 | static void shutdown(struct cyclades_port *info) |
2203 | { | 2136 | { |
2137 | struct cyclades_card *card; | ||
2204 | unsigned long flags; | 2138 | unsigned long flags; |
2205 | void __iomem *base_addr; | 2139 | void __iomem *base_addr; |
2206 | int card, chip, channel, index; | 2140 | int chip, channel, index; |
2207 | 2141 | ||
2208 | if (!(info->flags & ASYNC_INITIALIZED)) { | 2142 | if (!(info->flags & ASYNC_INITIALIZED)) { |
2209 | return; | 2143 | return; |
2210 | } | 2144 | } |
2211 | 2145 | ||
2212 | card = info->card; | 2146 | card = info->card; |
2213 | channel = info->line - cy_card[card].first_line; | 2147 | channel = info->line - card->first_line; |
2214 | if (!IS_CYC_Z(cy_card[card])) { | 2148 | if (!IS_CYC_Z(*card)) { |
2215 | chip = channel >> 2; | 2149 | chip = channel >> 2; |
2216 | channel &= 0x03; | 2150 | channel &= 0x03; |
2217 | index = cy_card[card].bus_index; | 2151 | index = card->bus_index; |
2218 | base_addr = cy_card[card].base_addr + | 2152 | base_addr = card->base_addr + (cy_chip_offset[chip] << index); |
2219 | (cy_chip_offset[chip] << index); | ||
2220 | 2153 | ||
2221 | #ifdef CY_DEBUG_OPEN | 2154 | #ifdef CY_DEBUG_OPEN |
2222 | printk("cyc shutdown Y card %d, chip %d, channel %d, " | 2155 | printk(KERN_DEBUG "cyc shutdown Y card %d, chip %d, " |
2223 | "base_addr %lx\n", | 2156 | "channel %d, base_addr %p\n", |
2224 | card, chip, channel, (long)base_addr); | 2157 | card, chip, channel, base_addr); |
2225 | #endif | 2158 | #endif |
2226 | 2159 | ||
2227 | CY_LOCK(info, flags); | 2160 | spin_lock_irqsave(&card->card_lock, flags); |
2228 | 2161 | ||
2229 | /* Clear delta_msr_wait queue to avoid mem leaks. */ | 2162 | /* Clear delta_msr_wait queue to avoid mem leaks. */ |
2230 | wake_up_interruptible(&info->delta_msr_wait); | 2163 | wake_up_interruptible(&info->delta_msr_wait); |
@@ -2240,10 +2173,10 @@ static void shutdown(struct cyclades_port *info) | |||
2240 | cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS); | 2173 | cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS); |
2241 | cy_writeb(base_addr + (CyMSVR2 << index), ~CyDTR); | 2174 | cy_writeb(base_addr + (CyMSVR2 << index), ~CyDTR); |
2242 | #ifdef CY_DEBUG_DTR | 2175 | #ifdef CY_DEBUG_DTR |
2243 | printk("cyc shutdown dropping DTR\n"); | 2176 | printk(KERN_DEBUG "cyc shutdown dropping DTR\n"); |
2244 | printk(" status: 0x%x, 0x%x\n", | 2177 | printk(KERN_DEBUG " status: 0x%x, 0x%x\n", |
2245 | cy_readb(base_addr + (CyMSVR1 << index)), | 2178 | readb(base_addr + (CyMSVR1 << index)), |
2246 | cy_readb(base_addr + (CyMSVR2 << index))); | 2179 | readb(base_addr + (CyMSVR2 << index))); |
2247 | #endif | 2180 | #endif |
2248 | } | 2181 | } |
2249 | cyy_issue_cmd(base_addr, CyCHAN_CTL | CyDIS_RCVR, index); | 2182 | cyy_issue_cmd(base_addr, CyCHAN_CTL | CyDIS_RCVR, index); |
@@ -2254,7 +2187,7 @@ static void shutdown(struct cyclades_port *info) | |||
2254 | set_bit(TTY_IO_ERROR, &info->tty->flags); | 2187 | set_bit(TTY_IO_ERROR, &info->tty->flags); |
2255 | } | 2188 | } |
2256 | info->flags &= ~ASYNC_INITIALIZED; | 2189 | info->flags &= ~ASYNC_INITIALIZED; |
2257 | CY_UNLOCK(info, flags); | 2190 | spin_unlock_irqrestore(&card->card_lock, flags); |
2258 | } else { | 2191 | } else { |
2259 | struct FIRM_ID __iomem *firm_id; | 2192 | struct FIRM_ID __iomem *firm_id; |
2260 | struct ZFW_CTRL __iomem *zfw_ctrl; | 2193 | struct ZFW_CTRL __iomem *zfw_ctrl; |
@@ -2262,23 +2195,23 @@ static void shutdown(struct cyclades_port *info) | |||
2262 | struct CH_CTRL __iomem *ch_ctrl; | 2195 | struct CH_CTRL __iomem *ch_ctrl; |
2263 | int retval; | 2196 | int retval; |
2264 | 2197 | ||
2265 | base_addr = cy_card[card].base_addr; | 2198 | base_addr = card->base_addr; |
2266 | #ifdef CY_DEBUG_OPEN | 2199 | #ifdef CY_DEBUG_OPEN |
2267 | printk("cyc shutdown Z card %d, channel %d, base_addr %lx\n", | 2200 | printk(KERN_DEBUG "cyc shutdown Z card %d, channel %d, " |
2268 | card, channel, (long)base_addr); | 2201 | "base_addr %p\n", card, channel, base_addr); |
2269 | #endif | 2202 | #endif |
2270 | 2203 | ||
2271 | firm_id = base_addr + ID_ADDRESS; | 2204 | firm_id = base_addr + ID_ADDRESS; |
2272 | if (!ISZLOADED(cy_card[card])) { | 2205 | if (!ISZLOADED(*card)) { |
2273 | return; | 2206 | return; |
2274 | } | 2207 | } |
2275 | 2208 | ||
2276 | zfw_ctrl = cy_card[card].base_addr + | 2209 | zfw_ctrl = card->base_addr + |
2277 | (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); | 2210 | (readl(&firm_id->zfwctrl_addr) & 0xfffff); |
2278 | board_ctrl = &zfw_ctrl->board_ctrl; | 2211 | board_ctrl = &zfw_ctrl->board_ctrl; |
2279 | ch_ctrl = zfw_ctrl->ch_ctrl; | 2212 | ch_ctrl = zfw_ctrl->ch_ctrl; |
2280 | 2213 | ||
2281 | CY_LOCK(info, flags); | 2214 | spin_lock_irqsave(&card->card_lock, flags); |
2282 | 2215 | ||
2283 | if (info->xmit_buf) { | 2216 | if (info->xmit_buf) { |
2284 | unsigned char *temp; | 2217 | unsigned char *temp; |
@@ -2289,16 +2222,16 @@ static void shutdown(struct cyclades_port *info) | |||
2289 | 2222 | ||
2290 | if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { | 2223 | if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { |
2291 | cy_writel(&ch_ctrl[channel].rs_control, | 2224 | cy_writel(&ch_ctrl[channel].rs_control, |
2292 | (uclong)(cy_readl(&ch_ctrl[channel].rs_control)& | 2225 | (__u32)(readl(&ch_ctrl[channel].rs_control) & |
2293 | ~(C_RS_RTS | C_RS_DTR))); | 2226 | ~(C_RS_RTS | C_RS_DTR))); |
2294 | retval = cyz_issue_cmd(&cy_card[info->card], channel, | 2227 | retval = cyz_issue_cmd(info->card, channel, |
2295 | C_CM_IOCTLM, 0L); | 2228 | C_CM_IOCTLM, 0L); |
2296 | if (retval != 0) { | 2229 | if (retval != 0) { |
2297 | printk("cyc:shutdown retval on ttyC%d was %x\n", | 2230 | printk(KERN_ERR"cyc:shutdown retval on ttyC%d " |
2298 | info->line, retval); | 2231 | "was %x\n", info->line, retval); |
2299 | } | 2232 | } |
2300 | #ifdef CY_DEBUG_DTR | 2233 | #ifdef CY_DEBUG_DTR |
2301 | printk("cyc:shutdown dropping Z DTR\n"); | 2234 | printk(KERN_DEBUG "cyc:shutdown dropping Z DTR\n"); |
2302 | #endif | 2235 | #endif |
2303 | } | 2236 | } |
2304 | 2237 | ||
@@ -2307,11 +2240,11 @@ static void shutdown(struct cyclades_port *info) | |||
2307 | } | 2240 | } |
2308 | info->flags &= ~ASYNC_INITIALIZED; | 2241 | info->flags &= ~ASYNC_INITIALIZED; |
2309 | 2242 | ||
2310 | CY_UNLOCK(info, flags); | 2243 | spin_unlock_irqrestore(&card->card_lock, flags); |
2311 | } | 2244 | } |
2312 | 2245 | ||
2313 | #ifdef CY_DEBUG_OPEN | 2246 | #ifdef CY_DEBUG_OPEN |
2314 | printk(" cyc shutdown done\n"); | 2247 | printk(KERN_DEBUG "cyc shutdown done\n"); |
2315 | #endif | 2248 | #endif |
2316 | } /* shutdown */ | 2249 | } /* shutdown */ |
2317 | 2250 | ||
@@ -2332,7 +2265,7 @@ block_til_ready(struct tty_struct *tty, struct file *filp, | |||
2332 | int retval; | 2265 | int retval; |
2333 | void __iomem *base_addr; | 2266 | void __iomem *base_addr; |
2334 | 2267 | ||
2335 | cinfo = &cy_card[info->card]; | 2268 | cinfo = info->card; |
2336 | channel = info->line - cinfo->first_line; | 2269 | channel = info->line - cinfo->first_line; |
2337 | 2270 | ||
2338 | /* | 2271 | /* |
@@ -2340,9 +2273,8 @@ block_til_ready(struct tty_struct *tty, struct file *filp, | |||
2340 | * until it's done, and then try again. | 2273 | * until it's done, and then try again. |
2341 | */ | 2274 | */ |
2342 | if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { | 2275 | if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { |
2343 | if (info->flags & ASYNC_CLOSING) { | 2276 | wait_event_interruptible(info->close_wait, |
2344 | interruptible_sleep_on(&info->close_wait); | 2277 | !(info->flags & ASYNC_CLOSING)); |
2345 | } | ||
2346 | return (info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; | 2278 | return (info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; |
2347 | } | 2279 | } |
2348 | 2280 | ||
@@ -2365,17 +2297,16 @@ block_til_ready(struct tty_struct *tty, struct file *filp, | |||
2365 | retval = 0; | 2297 | retval = 0; |
2366 | add_wait_queue(&info->open_wait, &wait); | 2298 | add_wait_queue(&info->open_wait, &wait); |
2367 | #ifdef CY_DEBUG_OPEN | 2299 | #ifdef CY_DEBUG_OPEN |
2368 | printk("cyc block_til_ready before block: ttyC%d, count = %d\n", | 2300 | printk(KERN_DEBUG "cyc block_til_ready before block: ttyC%d, " |
2369 | info->line, info->count); | 2301 | "count = %d\n", info->line, info->count); |
2370 | /**/ | ||
2371 | #endif | 2302 | #endif |
2372 | CY_LOCK(info, flags); | 2303 | spin_lock_irqsave(&cinfo->card_lock, flags); |
2373 | if (!tty_hung_up_p(filp)) | 2304 | if (!tty_hung_up_p(filp)) |
2374 | info->count--; | 2305 | info->count--; |
2375 | CY_UNLOCK(info, flags); | 2306 | spin_unlock_irqrestore(&cinfo->card_lock, flags); |
2376 | #ifdef CY_DEBUG_COUNT | 2307 | #ifdef CY_DEBUG_COUNT |
2377 | printk("cyc block_til_ready: (%d): decrementing count to %d\n", | 2308 | printk(KERN_DEBUG "cyc block_til_ready: (%d): decrementing count to " |
2378 | current->pid, info->count); | 2309 | "%d\n", current->pid, info->count); |
2379 | #endif | 2310 | #endif |
2380 | info->blocked_open++; | 2311 | info->blocked_open++; |
2381 | 2312 | ||
@@ -2386,7 +2317,7 @@ block_til_ready(struct tty_struct *tty, struct file *filp, | |||
2386 | base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index); | 2317 | base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index); |
2387 | 2318 | ||
2388 | while (1) { | 2319 | while (1) { |
2389 | CY_LOCK(info, flags); | 2320 | spin_lock_irqsave(&cinfo->card_lock, flags); |
2390 | if ((tty->termios->c_cflag & CBAUD)) { | 2321 | if ((tty->termios->c_cflag & CBAUD)) { |
2391 | cy_writeb(base_addr + (CyCAR << index), | 2322 | cy_writeb(base_addr + (CyCAR << index), |
2392 | (u_char) channel); | 2323 | (u_char) channel); |
@@ -2395,15 +2326,14 @@ block_til_ready(struct tty_struct *tty, struct file *filp, | |||
2395 | cy_writeb(base_addr + (CyMSVR2 << index), | 2326 | cy_writeb(base_addr + (CyMSVR2 << index), |
2396 | CyDTR); | 2327 | CyDTR); |
2397 | #ifdef CY_DEBUG_DTR | 2328 | #ifdef CY_DEBUG_DTR |
2398 | printk("cyc:block_til_ready raising DTR\n"); | 2329 | printk(KERN_DEBUG "cyc:block_til_ready raising " |
2399 | printk(" status: 0x%x, 0x%x\n", | 2330 | "DTR\n"); |
2400 | cy_readb(base_addr + | 2331 | printk(KERN_DEBUG " status: 0x%x, 0x%x\n", |
2401 | (CyMSVR1 << index)), | 2332 | readb(base_addr + (CyMSVR1 << index)), |
2402 | cy_readb(base_addr + | 2333 | readb(base_addr + (CyMSVR2 << index))); |
2403 | (CyMSVR2 << index))); | ||
2404 | #endif | 2334 | #endif |
2405 | } | 2335 | } |
2406 | CY_UNLOCK(info, flags); | 2336 | spin_unlock_irqrestore(&cinfo->card_lock, flags); |
2407 | 2337 | ||
2408 | set_current_state(TASK_INTERRUPTIBLE); | 2338 | set_current_state(TASK_INTERRUPTIBLE); |
2409 | if (tty_hung_up_p(filp) || | 2339 | if (tty_hung_up_p(filp) || |
@@ -2413,26 +2343,25 @@ block_til_ready(struct tty_struct *tty, struct file *filp, | |||
2413 | break; | 2343 | break; |
2414 | } | 2344 | } |
2415 | 2345 | ||
2416 | CY_LOCK(info, flags); | 2346 | spin_lock_irqsave(&cinfo->card_lock, flags); |
2417 | cy_writeb(base_addr + (CyCAR << index), | 2347 | cy_writeb(base_addr + (CyCAR << index), |
2418 | (u_char) channel); | 2348 | (u_char) channel); |
2419 | if (!(info->flags & ASYNC_CLOSING) && (C_CLOCAL(tty) || | 2349 | if (!(info->flags & ASYNC_CLOSING) && (C_CLOCAL(tty) || |
2420 | (cy_readb(base_addr + | 2350 | (readb(base_addr + |
2421 | (CyMSVR1 << index)) & CyDCD))) { | 2351 | (CyMSVR1 << index)) & CyDCD))) { |
2422 | CY_UNLOCK(info, flags); | 2352 | spin_unlock_irqrestore(&cinfo->card_lock, flags); |
2423 | break; | 2353 | break; |
2424 | } | 2354 | } |
2425 | CY_UNLOCK(info, flags); | 2355 | spin_unlock_irqrestore(&cinfo->card_lock, flags); |
2426 | 2356 | ||
2427 | if (signal_pending(current)) { | 2357 | if (signal_pending(current)) { |
2428 | retval = -ERESTARTSYS; | 2358 | retval = -ERESTARTSYS; |
2429 | break; | 2359 | break; |
2430 | } | 2360 | } |
2431 | #ifdef CY_DEBUG_OPEN | 2361 | #ifdef CY_DEBUG_OPEN |
2432 | printk("cyc block_til_ready blocking: ttyC%d, " | 2362 | printk(KERN_DEBUG "cyc block_til_ready blocking: " |
2433 | "count = %d\n", | 2363 | "ttyC%d, count = %d\n", |
2434 | info->line, info->count); | 2364 | info->line, info->count); |
2435 | /**/ | ||
2436 | #endif | 2365 | #endif |
2437 | schedule(); | 2366 | schedule(); |
2438 | } | 2367 | } |
@@ -2446,31 +2375,30 @@ block_til_ready(struct tty_struct *tty, struct file *filp, | |||
2446 | base_addr = cinfo->base_addr; | 2375 | base_addr = cinfo->base_addr; |
2447 | firm_id = base_addr + ID_ADDRESS; | 2376 | firm_id = base_addr + ID_ADDRESS; |
2448 | if (!ISZLOADED(*cinfo)) { | 2377 | if (!ISZLOADED(*cinfo)) { |
2449 | current->state = TASK_RUNNING; | 2378 | __set_current_state(TASK_RUNNING); |
2450 | remove_wait_queue(&info->open_wait, &wait); | 2379 | remove_wait_queue(&info->open_wait, &wait); |
2451 | return -EINVAL; | 2380 | return -EINVAL; |
2452 | } | 2381 | } |
2453 | 2382 | ||
2454 | zfw_ctrl = base_addr + (cy_readl(&firm_id->zfwctrl_addr) & | 2383 | zfw_ctrl = base_addr + (readl(&firm_id->zfwctrl_addr)& 0xfffff); |
2455 | 0xfffff); | ||
2456 | board_ctrl = &zfw_ctrl->board_ctrl; | 2384 | board_ctrl = &zfw_ctrl->board_ctrl; |
2457 | ch_ctrl = zfw_ctrl->ch_ctrl; | 2385 | ch_ctrl = zfw_ctrl->ch_ctrl; |
2458 | 2386 | ||
2459 | while (1) { | 2387 | while (1) { |
2460 | if ((tty->termios->c_cflag & CBAUD)) { | 2388 | if ((tty->termios->c_cflag & CBAUD)) { |
2461 | cy_writel(&ch_ctrl[channel].rs_control, | 2389 | cy_writel(&ch_ctrl[channel].rs_control, |
2462 | cy_readl(&ch_ctrl[channel]. | 2390 | readl(&ch_ctrl[channel].rs_control) | |
2463 | rs_control) | (C_RS_RTS | | 2391 | C_RS_RTS | C_RS_DTR); |
2464 | C_RS_DTR)); | 2392 | retval = cyz_issue_cmd(cinfo, |
2465 | retval = cyz_issue_cmd(&cy_card[info->card], | 2393 | channel, C_CM_IOCTLM, 0L); |
2466 | channel, C_CM_IOCTLM, 0L); | ||
2467 | if (retval != 0) { | 2394 | if (retval != 0) { |
2468 | printk("cyc:block_til_ready retval on " | 2395 | printk(KERN_ERR "cyc:block_til_ready " |
2469 | "ttyC%d was %x\n", | 2396 | "retval on ttyC%d was %x\n", |
2470 | info->line, retval); | 2397 | info->line, retval); |
2471 | } | 2398 | } |
2472 | #ifdef CY_DEBUG_DTR | 2399 | #ifdef CY_DEBUG_DTR |
2473 | printk("cyc:block_til_ready raising Z DTR\n"); | 2400 | printk(KERN_DEBUG "cyc:block_til_ready raising " |
2401 | "Z DTR\n"); | ||
2474 | #endif | 2402 | #endif |
2475 | } | 2403 | } |
2476 | 2404 | ||
@@ -2482,7 +2410,7 @@ block_til_ready(struct tty_struct *tty, struct file *filp, | |||
2482 | break; | 2410 | break; |
2483 | } | 2411 | } |
2484 | if (!(info->flags & ASYNC_CLOSING) && (C_CLOCAL(tty) || | 2412 | if (!(info->flags & ASYNC_CLOSING) && (C_CLOCAL(tty) || |
2485 | (cy_readl(&ch_ctrl[channel].rs_status) & | 2413 | (readl(&ch_ctrl[channel].rs_status) & |
2486 | C_RS_DCD))) { | 2414 | C_RS_DCD))) { |
2487 | break; | 2415 | break; |
2488 | } | 2416 | } |
@@ -2491,28 +2419,26 @@ block_til_ready(struct tty_struct *tty, struct file *filp, | |||
2491 | break; | 2419 | break; |
2492 | } | 2420 | } |
2493 | #ifdef CY_DEBUG_OPEN | 2421 | #ifdef CY_DEBUG_OPEN |
2494 | printk("cyc block_til_ready blocking: ttyC%d, " | 2422 | printk(KERN_DEBUG "cyc block_til_ready blocking: " |
2495 | "count = %d\n", | 2423 | "ttyC%d, count = %d\n", |
2496 | info->line, info->count); | 2424 | info->line, info->count); |
2497 | /**/ | ||
2498 | #endif | 2425 | #endif |
2499 | schedule(); | 2426 | schedule(); |
2500 | } | 2427 | } |
2501 | } | 2428 | } |
2502 | current->state = TASK_RUNNING; | 2429 | __set_current_state(TASK_RUNNING); |
2503 | remove_wait_queue(&info->open_wait, &wait); | 2430 | remove_wait_queue(&info->open_wait, &wait); |
2504 | if (!tty_hung_up_p(filp)) { | 2431 | if (!tty_hung_up_p(filp)) { |
2505 | info->count++; | 2432 | info->count++; |
2506 | #ifdef CY_DEBUG_COUNT | 2433 | #ifdef CY_DEBUG_COUNT |
2507 | printk("cyc:block_til_ready (%d): incrementing count to %d\n", | 2434 | printk(KERN_DEBUG "cyc:block_til_ready (%d): incrementing " |
2508 | current->pid, info->count); | 2435 | "count to %d\n", current->pid, info->count); |
2509 | #endif | 2436 | #endif |
2510 | } | 2437 | } |
2511 | info->blocked_open--; | 2438 | info->blocked_open--; |
2512 | #ifdef CY_DEBUG_OPEN | 2439 | #ifdef CY_DEBUG_OPEN |
2513 | printk("cyc:block_til_ready after blocking: ttyC%d, count = %d\n", | 2440 | printk(KERN_DEBUG "cyc:block_til_ready after blocking: ttyC%d, " |
2514 | info->line, info->count); | 2441 | "count = %d\n", info->line, info->count); |
2515 | /**/ | ||
2516 | #endif | 2442 | #endif |
2517 | if (retval) | 2443 | if (retval) |
2518 | return retval; | 2444 | return retval; |
@@ -2527,13 +2453,20 @@ block_til_ready(struct tty_struct *tty, struct file *filp, | |||
2527 | static int cy_open(struct tty_struct *tty, struct file *filp) | 2453 | static int cy_open(struct tty_struct *tty, struct file *filp) |
2528 | { | 2454 | { |
2529 | struct cyclades_port *info; | 2455 | struct cyclades_port *info; |
2456 | unsigned int i; | ||
2530 | int retval, line; | 2457 | int retval, line; |
2531 | 2458 | ||
2532 | line = tty->index; | 2459 | line = tty->index; |
2533 | if ((line < 0) || (NR_PORTS <= line)) { | 2460 | if ((line < 0) || (NR_PORTS <= line)) { |
2534 | return -ENODEV; | 2461 | return -ENODEV; |
2535 | } | 2462 | } |
2536 | info = &cy_port[line]; | 2463 | for (i = 0; i < NR_CARDS; i++) |
2464 | if (line < cy_card[i].first_line + cy_card[i].nports && | ||
2465 | line >= cy_card[i].first_line) | ||
2466 | break; | ||
2467 | if (i >= NR_CARDS) | ||
2468 | return -ENODEV; | ||
2469 | info = &cy_card[i].ports[line - cy_card[i].first_line]; | ||
2537 | if (info->line < 0) { | 2470 | if (info->line < 0) { |
2538 | return -ENODEV; | 2471 | return -ENODEV; |
2539 | } | 2472 | } |
@@ -2542,23 +2475,23 @@ static int cy_open(struct tty_struct *tty, struct file *filp) | |||
2542 | treat it as absent from the system. This | 2475 | treat it as absent from the system. This |
2543 | will make the user pay attention. | 2476 | will make the user pay attention. |
2544 | */ | 2477 | */ |
2545 | if (IS_CYC_Z(cy_card[info->card])) { | 2478 | if (IS_CYC_Z(*info->card)) { |
2546 | struct cyclades_card *cinfo = &cy_card[info->card]; | 2479 | struct cyclades_card *cinfo = info->card; |
2547 | struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS; | 2480 | struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS; |
2548 | 2481 | ||
2549 | if (!ISZLOADED(*cinfo)) { | 2482 | if (!ISZLOADED(*cinfo)) { |
2550 | if (((ZE_V1 == cy_readl( | 2483 | if (((ZE_V1 == readl(&((struct RUNTIME_9060 __iomem *) |
2551 | &((struct RUNTIME_9060 __iomem *) | ||
2552 | (cinfo->ctl_addr))->mail_box_0)) && | 2484 | (cinfo->ctl_addr))->mail_box_0)) && |
2553 | Z_FPGA_CHECK(*cinfo)) && | 2485 | Z_FPGA_CHECK(*cinfo)) && |
2554 | (ZFIRM_HLT == cy_readl( | 2486 | (ZFIRM_HLT == readl( |
2555 | &firm_id->signature))) { | 2487 | &firm_id->signature))) { |
2556 | printk("cyc:Cyclades-Z Error: you need an " | 2488 | printk(KERN_ERR "cyc:Cyclades-Z Error: you " |
2557 | "external power supply for this number " | 2489 | "need an external power supply for " |
2558 | "of ports.\n\rFirmware halted.\r\n"); | 2490 | "this number of ports.\nFirmware " |
2491 | "halted.\n"); | ||
2559 | } else { | 2492 | } else { |
2560 | printk("cyc:Cyclades-Z firmware not yet " | 2493 | printk(KERN_ERR "cyc:Cyclades-Z firmware not " |
2561 | "loaded\n"); | 2494 | "yet loaded\n"); |
2562 | } | 2495 | } |
2563 | return -ENODEV; | 2496 | return -ENODEV; |
2564 | } | 2497 | } |
@@ -2572,24 +2505,23 @@ static int cy_open(struct tty_struct *tty, struct file *filp) | |||
2572 | struct BOARD_CTRL __iomem *board_ctrl; | 2505 | struct BOARD_CTRL __iomem *board_ctrl; |
2573 | 2506 | ||
2574 | zfw_ctrl = cinfo->base_addr + | 2507 | zfw_ctrl = cinfo->base_addr + |
2575 | (cy_readl(&firm_id->zfwctrl_addr) & | 2508 | (readl(&firm_id->zfwctrl_addr) & |
2576 | 0xfffff); | 2509 | 0xfffff); |
2577 | 2510 | ||
2578 | board_ctrl = &zfw_ctrl->board_ctrl; | 2511 | board_ctrl = &zfw_ctrl->board_ctrl; |
2579 | 2512 | ||
2580 | /* Enable interrupts on the PLX chip */ | 2513 | /* Enable interrupts on the PLX chip */ |
2581 | cy_writew(cinfo->ctl_addr + 0x68, | 2514 | cy_writew(cinfo->ctl_addr + 0x68, |
2582 | cy_readw(cinfo->ctl_addr + | 2515 | readw(cinfo->ctl_addr + 0x68) | 0x0900); |
2583 | 0x68) | 0x0900); | ||
2584 | /* Enable interrupts on the FW */ | 2516 | /* Enable interrupts on the FW */ |
2585 | retval = cyz_issue_cmd(cinfo, 0, | 2517 | retval = cyz_issue_cmd(cinfo, 0, |
2586 | C_CM_IRQ_ENBL, 0L); | 2518 | C_CM_IRQ_ENBL, 0L); |
2587 | if (retval != 0) { | 2519 | if (retval != 0) { |
2588 | printk("cyc:IRQ enable retval was %x\n", | 2520 | printk(KERN_ERR "cyc:IRQ enable retval " |
2589 | retval); | 2521 | "was %x\n", retval); |
2590 | } | 2522 | } |
2591 | cinfo->nports = | 2523 | cinfo->nports = |
2592 | (int)cy_readl(&board_ctrl->n_channel); | 2524 | (int)readl(&board_ctrl->n_channel); |
2593 | cinfo->intr_enabled = 1; | 2525 | cinfo->intr_enabled = 1; |
2594 | } | 2526 | } |
2595 | } | 2527 | } |
@@ -2599,7 +2531,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp) | |||
2599 | return -ENODEV; | 2531 | return -ENODEV; |
2600 | } | 2532 | } |
2601 | #ifdef CY_DEBUG_OTHER | 2533 | #ifdef CY_DEBUG_OTHER |
2602 | printk("cyc:cy_open ttyC%d\n", info->line); /* */ | 2534 | printk(KERN_DEBUG "cyc:cy_open ttyC%d\n", info->line); |
2603 | #endif | 2535 | #endif |
2604 | tty->driver_data = info; | 2536 | tty->driver_data = info; |
2605 | info->tty = tty; | 2537 | info->tty = tty; |
@@ -2607,12 +2539,12 @@ static int cy_open(struct tty_struct *tty, struct file *filp) | |||
2607 | return -ENODEV; | 2539 | return -ENODEV; |
2608 | } | 2540 | } |
2609 | #ifdef CY_DEBUG_OPEN | 2541 | #ifdef CY_DEBUG_OPEN |
2610 | printk("cyc:cy_open ttyC%d, count = %d\n", info->line, info->count); | 2542 | printk(KERN_DEBUG "cyc:cy_open ttyC%d, count = %d\n", info->line, |
2611 | /**/ | 2543 | info->count); |
2612 | #endif | 2544 | #endif |
2613 | info->count++; | 2545 | info->count++; |
2614 | #ifdef CY_DEBUG_COUNT | 2546 | #ifdef CY_DEBUG_COUNT |
2615 | printk("cyc:cy_open (%d): incrementing count to %d\n", | 2547 | printk(KERN_DEBUG "cyc:cy_open (%d): incrementing count to %d\n", |
2616 | current->pid, info->count); | 2548 | current->pid, info->count); |
2617 | #endif | 2549 | #endif |
2618 | 2550 | ||
@@ -2620,8 +2552,8 @@ static int cy_open(struct tty_struct *tty, struct file *filp) | |||
2620 | * If the port is the middle of closing, bail out now | 2552 | * If the port is the middle of closing, bail out now |
2621 | */ | 2553 | */ |
2622 | if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { | 2554 | if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { |
2623 | if (info->flags & ASYNC_CLOSING) | 2555 | wait_event_interruptible(info->close_wait, |
2624 | interruptible_sleep_on(&info->close_wait); | 2556 | !(info->flags & ASYNC_CLOSING)); |
2625 | return (info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; | 2557 | return (info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; |
2626 | } | 2558 | } |
2627 | 2559 | ||
@@ -2636,8 +2568,8 @@ static int cy_open(struct tty_struct *tty, struct file *filp) | |||
2636 | retval = block_til_ready(tty, filp, info); | 2568 | retval = block_til_ready(tty, filp, info); |
2637 | if (retval) { | 2569 | if (retval) { |
2638 | #ifdef CY_DEBUG_OPEN | 2570 | #ifdef CY_DEBUG_OPEN |
2639 | printk("cyc:cy_open returning after block_til_ready with %d\n", | 2571 | printk(KERN_DEBUG "cyc:cy_open returning after block_til_ready " |
2640 | retval); | 2572 | "with %d\n", retval); |
2641 | #endif | 2573 | #endif |
2642 | return retval; | 2574 | return retval; |
2643 | } | 2575 | } |
@@ -2645,8 +2577,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp) | |||
2645 | info->throttle = 0; | 2577 | info->throttle = 0; |
2646 | 2578 | ||
2647 | #ifdef CY_DEBUG_OPEN | 2579 | #ifdef CY_DEBUG_OPEN |
2648 | printk(" cyc:cy_open done\n"); | 2580 | printk(KERN_DEBUG "cyc:cy_open done\n"); |
2649 | /**/ | ||
2650 | #endif | 2581 | #endif |
2651 | return 0; | 2582 | return 0; |
2652 | } /* cy_open */ | 2583 | } /* cy_open */ |
@@ -2656,9 +2587,10 @@ static int cy_open(struct tty_struct *tty, struct file *filp) | |||
2656 | */ | 2587 | */ |
2657 | static void cy_wait_until_sent(struct tty_struct *tty, int timeout) | 2588 | static void cy_wait_until_sent(struct tty_struct *tty, int timeout) |
2658 | { | 2589 | { |
2659 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 2590 | struct cyclades_card *card; |
2591 | struct cyclades_port *info = tty->driver_data; | ||
2660 | void __iomem *base_addr; | 2592 | void __iomem *base_addr; |
2661 | int card, chip, channel, index; | 2593 | int chip, channel, index; |
2662 | unsigned long orig_jiffies; | 2594 | unsigned long orig_jiffies; |
2663 | int char_time; | 2595 | int char_time; |
2664 | 2596 | ||
@@ -2697,20 +2629,19 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout) | |||
2697 | if (!timeout || timeout > 2 * info->timeout) | 2629 | if (!timeout || timeout > 2 * info->timeout) |
2698 | timeout = 2 * info->timeout; | 2630 | timeout = 2 * info->timeout; |
2699 | #ifdef CY_DEBUG_WAIT_UNTIL_SENT | 2631 | #ifdef CY_DEBUG_WAIT_UNTIL_SENT |
2700 | printk("In cy_wait_until_sent(%d) check=%lu...", timeout, char_time); | 2632 | printk(KERN_DEBUG "In cy_wait_until_sent(%d) check=%d, jiff=%lu...", |
2701 | printk("jiff=%lu...", jiffies); | 2633 | timeout, char_time, jiffies); |
2702 | #endif | 2634 | #endif |
2703 | card = info->card; | 2635 | card = info->card; |
2704 | channel = (info->line) - (cy_card[card].first_line); | 2636 | channel = (info->line) - (card->first_line); |
2705 | if (!IS_CYC_Z(cy_card[card])) { | 2637 | if (!IS_CYC_Z(*card)) { |
2706 | chip = channel >> 2; | 2638 | chip = channel >> 2; |
2707 | channel &= 0x03; | 2639 | channel &= 0x03; |
2708 | index = cy_card[card].bus_index; | 2640 | index = card->bus_index; |
2709 | base_addr = | 2641 | base_addr = card->base_addr + (cy_chip_offset[chip] << index); |
2710 | cy_card[card].base_addr + (cy_chip_offset[chip] << index); | 2642 | while (readb(base_addr + (CySRER << index)) & CyTxRdy) { |
2711 | while (cy_readb(base_addr + (CySRER << index)) & CyTxRdy) { | ||
2712 | #ifdef CY_DEBUG_WAIT_UNTIL_SENT | 2643 | #ifdef CY_DEBUG_WAIT_UNTIL_SENT |
2713 | printk("Not clean (jiff=%lu)...", jiffies); | 2644 | printk(KERN_DEBUG "Not clean (jiff=%lu)...", jiffies); |
2714 | #endif | 2645 | #endif |
2715 | if (msleep_interruptible(jiffies_to_msecs(char_time))) | 2646 | if (msleep_interruptible(jiffies_to_msecs(char_time))) |
2716 | break; | 2647 | break; |
@@ -2718,13 +2649,11 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout) | |||
2718 | timeout)) | 2649 | timeout)) |
2719 | break; | 2650 | break; |
2720 | } | 2651 | } |
2721 | } else { | ||
2722 | /* Nothing to do! */ | ||
2723 | } | 2652 | } |
2724 | /* Run one more char cycle */ | 2653 | /* Run one more char cycle */ |
2725 | msleep_interruptible(jiffies_to_msecs(char_time * 5)); | 2654 | msleep_interruptible(jiffies_to_msecs(char_time * 5)); |
2726 | #ifdef CY_DEBUG_WAIT_UNTIL_SENT | 2655 | #ifdef CY_DEBUG_WAIT_UNTIL_SENT |
2727 | printk("Clean (jiff=%lu)...done\n", jiffies); | 2656 | printk(KERN_DEBUG "Clean (jiff=%lu)...done\n", jiffies); |
2728 | #endif | 2657 | #endif |
2729 | } | 2658 | } |
2730 | 2659 | ||
@@ -2733,25 +2662,29 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout) | |||
2733 | */ | 2662 | */ |
2734 | static void cy_close(struct tty_struct *tty, struct file *filp) | 2663 | static void cy_close(struct tty_struct *tty, struct file *filp) |
2735 | { | 2664 | { |
2736 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 2665 | struct cyclades_port *info = tty->driver_data; |
2666 | struct cyclades_card *card; | ||
2737 | unsigned long flags; | 2667 | unsigned long flags; |
2738 | 2668 | ||
2739 | #ifdef CY_DEBUG_OTHER | 2669 | #ifdef CY_DEBUG_OTHER |
2740 | printk("cyc:cy_close ttyC%d\n", info->line); | 2670 | printk(KERN_DEBUG "cyc:cy_close ttyC%d\n", info->line); |
2741 | #endif | 2671 | #endif |
2742 | 2672 | ||
2743 | if (!info || serial_paranoia_check(info, tty->name, "cy_close")) { | 2673 | if (!info || serial_paranoia_check(info, tty->name, "cy_close")) { |
2744 | return; | 2674 | return; |
2745 | } | 2675 | } |
2746 | 2676 | ||
2747 | CY_LOCK(info, flags); | 2677 | card = info->card; |
2678 | |||
2679 | spin_lock_irqsave(&card->card_lock, flags); | ||
2748 | /* If the TTY is being hung up, nothing to do */ | 2680 | /* If the TTY is being hung up, nothing to do */ |
2749 | if (tty_hung_up_p(filp)) { | 2681 | if (tty_hung_up_p(filp)) { |
2750 | CY_UNLOCK(info, flags); | 2682 | spin_unlock_irqrestore(&card->card_lock, flags); |
2751 | return; | 2683 | return; |
2752 | } | 2684 | } |
2753 | #ifdef CY_DEBUG_OPEN | 2685 | #ifdef CY_DEBUG_OPEN |
2754 | printk("cyc:cy_close ttyC%d, count = %d\n", info->line, info->count); | 2686 | printk(KERN_DEBUG "cyc:cy_close ttyC%d, count = %d\n", info->line, |
2687 | info->count); | ||
2755 | #endif | 2688 | #endif |
2756 | if ((tty->count == 1) && (info->count != 1)) { | 2689 | if ((tty->count == 1) && (info->count != 1)) { |
2757 | /* | 2690 | /* |
@@ -2761,22 +2694,22 @@ static void cy_close(struct tty_struct *tty, struct file *filp) | |||
2761 | * one, we've got real problems, since it means the | 2694 | * one, we've got real problems, since it means the |
2762 | * serial port won't be shutdown. | 2695 | * serial port won't be shutdown. |
2763 | */ | 2696 | */ |
2764 | printk("cyc:cy_close: bad serial port count; tty->count is 1, " | 2697 | printk(KERN_ERR "cyc:cy_close: bad serial port count; " |
2765 | "info->count is %d\n", info->count); | 2698 | "tty->count is 1, info->count is %d\n", info->count); |
2766 | info->count = 1; | 2699 | info->count = 1; |
2767 | } | 2700 | } |
2768 | #ifdef CY_DEBUG_COUNT | 2701 | #ifdef CY_DEBUG_COUNT |
2769 | printk("cyc:cy_close at (%d): decrementing count to %d\n", | 2702 | printk(KERN_DEBUG "cyc:cy_close at (%d): decrementing count to %d\n", |
2770 | current->pid, info->count - 1); | 2703 | current->pid, info->count - 1); |
2771 | #endif | 2704 | #endif |
2772 | if (--info->count < 0) { | 2705 | if (--info->count < 0) { |
2773 | #ifdef CY_DEBUG_COUNT | 2706 | #ifdef CY_DEBUG_COUNT |
2774 | printk("cyc:cyc_close setting count to 0\n"); | 2707 | printk(KERN_DEBUG "cyc:cyc_close setting count to 0\n"); |
2775 | #endif | 2708 | #endif |
2776 | info->count = 0; | 2709 | info->count = 0; |
2777 | } | 2710 | } |
2778 | if (info->count) { | 2711 | if (info->count) { |
2779 | CY_UNLOCK(info, flags); | 2712 | spin_unlock_irqrestore(&card->card_lock, flags); |
2780 | return; | 2713 | return; |
2781 | } | 2714 | } |
2782 | info->flags |= ASYNC_CLOSING; | 2715 | info->flags |= ASYNC_CLOSING; |
@@ -2786,81 +2719,80 @@ static void cy_close(struct tty_struct *tty, struct file *filp) | |||
2786 | * the line discipline to only process XON/XOFF characters. | 2719 | * the line discipline to only process XON/XOFF characters. |
2787 | */ | 2720 | */ |
2788 | tty->closing = 1; | 2721 | tty->closing = 1; |
2789 | CY_UNLOCK(info, flags); | 2722 | spin_unlock_irqrestore(&card->card_lock, flags); |
2790 | if (info->closing_wait != CY_CLOSING_WAIT_NONE) { | 2723 | if (info->closing_wait != CY_CLOSING_WAIT_NONE) { |
2791 | tty_wait_until_sent(tty, info->closing_wait); | 2724 | tty_wait_until_sent(tty, info->closing_wait); |
2792 | } | 2725 | } |
2793 | CY_LOCK(info, flags); | 2726 | spin_lock_irqsave(&card->card_lock, flags); |
2794 | 2727 | ||
2795 | if (!IS_CYC_Z(cy_card[info->card])) { | 2728 | if (!IS_CYC_Z(*card)) { |
2796 | int channel = info->line - cy_card[info->card].first_line; | 2729 | int channel = info->line - card->first_line; |
2797 | int index = cy_card[info->card].bus_index; | 2730 | int index = card->bus_index; |
2798 | void __iomem *base_addr = cy_card[info->card].base_addr + | 2731 | void __iomem *base_addr = card->base_addr + |
2799 | (cy_chip_offset[channel >> 2] << index); | 2732 | (cy_chip_offset[channel >> 2] << index); |
2800 | /* Stop accepting input */ | 2733 | /* Stop accepting input */ |
2801 | channel &= 0x03; | 2734 | channel &= 0x03; |
2802 | cy_writeb(base_addr + (CyCAR << index), (u_char) channel); | 2735 | cy_writeb(base_addr + (CyCAR << index), (u_char) channel); |
2803 | cy_writeb(base_addr + (CySRER << index), | 2736 | cy_writeb(base_addr + (CySRER << index), |
2804 | cy_readb(base_addr + (CySRER << index)) & ~CyRxData); | 2737 | readb(base_addr + (CySRER << index)) & ~CyRxData); |
2805 | if (info->flags & ASYNC_INITIALIZED) { | 2738 | if (info->flags & ASYNC_INITIALIZED) { |
2806 | /* Waiting for on-board buffers to be empty before closing | 2739 | /* Waiting for on-board buffers to be empty before closing |
2807 | the port */ | 2740 | the port */ |
2808 | CY_UNLOCK(info, flags); | 2741 | spin_unlock_irqrestore(&card->card_lock, flags); |
2809 | cy_wait_until_sent(tty, info->timeout); | 2742 | cy_wait_until_sent(tty, info->timeout); |
2810 | CY_LOCK(info, flags); | 2743 | spin_lock_irqsave(&card->card_lock, flags); |
2811 | } | 2744 | } |
2812 | } else { | 2745 | } else { |
2813 | #ifdef Z_WAKE | 2746 | #ifdef Z_WAKE |
2814 | /* Waiting for on-board buffers to be empty before closing the port */ | 2747 | /* Waiting for on-board buffers to be empty before closing the port */ |
2815 | void __iomem *base_addr = cy_card[info->card].base_addr; | 2748 | void __iomem *base_addr = card->base_addr; |
2816 | struct FIRM_ID __iomem *firm_id = base_addr + ID_ADDRESS; | 2749 | struct FIRM_ID __iomem *firm_id = base_addr + ID_ADDRESS; |
2817 | struct ZFW_CTRL __iomem *zfw_ctrl = | 2750 | struct ZFW_CTRL __iomem *zfw_ctrl = |
2818 | base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); | 2751 | base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff); |
2819 | struct CH_CTRL __iomem *ch_ctrl = zfw_ctrl->ch_ctrl; | 2752 | struct CH_CTRL __iomem *ch_ctrl = zfw_ctrl->ch_ctrl; |
2820 | int channel = info->line - cy_card[info->card].first_line; | 2753 | int channel = info->line - card->first_line; |
2821 | int retval; | 2754 | int retval; |
2822 | 2755 | ||
2823 | if (cy_readl(&ch_ctrl[channel].flow_status) != C_FS_TXIDLE) { | 2756 | if (readl(&ch_ctrl[channel].flow_status) != C_FS_TXIDLE) { |
2824 | retval = cyz_issue_cmd(&cy_card[info->card], channel, | 2757 | retval = cyz_issue_cmd(card, channel, C_CM_IOCTLW, 0L); |
2825 | C_CM_IOCTLW, 0L); | ||
2826 | if (retval != 0) { | 2758 | if (retval != 0) { |
2827 | printk("cyc:cy_close retval on ttyC%d was %x\n", | 2759 | printk(KERN_DEBUG "cyc:cy_close retval on " |
2828 | info->line, retval); | 2760 | "ttyC%d was %x\n", info->line, retval); |
2829 | } | 2761 | } |
2830 | CY_UNLOCK(info, flags); | 2762 | spin_unlock_irqrestore(&card->card_lock, flags); |
2831 | interruptible_sleep_on(&info->shutdown_wait); | 2763 | wait_for_completion_interruptible(&info->shutdown_wait); |
2832 | CY_LOCK(info, flags); | 2764 | spin_lock_irqsave(&card->card_lock, flags); |
2833 | } | 2765 | } |
2834 | #endif | 2766 | #endif |
2835 | } | 2767 | } |
2836 | 2768 | ||
2837 | CY_UNLOCK(info, flags); | 2769 | spin_unlock_irqrestore(&card->card_lock, flags); |
2838 | shutdown(info); | 2770 | shutdown(info); |
2839 | if (tty->driver->flush_buffer) | 2771 | if (tty->driver->flush_buffer) |
2840 | tty->driver->flush_buffer(tty); | 2772 | tty->driver->flush_buffer(tty); |
2841 | tty_ldisc_flush(tty); | 2773 | tty_ldisc_flush(tty); |
2842 | CY_LOCK(info, flags); | 2774 | spin_lock_irqsave(&card->card_lock, flags); |
2843 | 2775 | ||
2844 | tty->closing = 0; | 2776 | tty->closing = 0; |
2845 | info->event = 0; | 2777 | info->event = 0; |
2846 | info->tty = NULL; | 2778 | info->tty = NULL; |
2847 | if (info->blocked_open) { | 2779 | if (info->blocked_open) { |
2848 | CY_UNLOCK(info, flags); | 2780 | spin_unlock_irqrestore(&card->card_lock, flags); |
2849 | if (info->close_delay) { | 2781 | if (info->close_delay) { |
2850 | msleep_interruptible(jiffies_to_msecs | 2782 | msleep_interruptible(jiffies_to_msecs |
2851 | (info->close_delay)); | 2783 | (info->close_delay)); |
2852 | } | 2784 | } |
2853 | wake_up_interruptible(&info->open_wait); | 2785 | wake_up_interruptible(&info->open_wait); |
2854 | CY_LOCK(info, flags); | 2786 | spin_lock_irqsave(&card->card_lock, flags); |
2855 | } | 2787 | } |
2856 | info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); | 2788 | info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); |
2857 | wake_up_interruptible(&info->close_wait); | 2789 | wake_up_interruptible(&info->close_wait); |
2858 | 2790 | ||
2859 | #ifdef CY_DEBUG_OTHER | 2791 | #ifdef CY_DEBUG_OTHER |
2860 | printk(" cyc:cy_close done\n"); | 2792 | printk(KERN_DEBUG "cyc:cy_close done\n"); |
2861 | #endif | 2793 | #endif |
2862 | 2794 | ||
2863 | CY_UNLOCK(info, flags); | 2795 | spin_unlock_irqrestore(&card->card_lock, flags); |
2864 | } /* cy_close */ | 2796 | } /* cy_close */ |
2865 | 2797 | ||
2866 | /* This routine gets called when tty_write has put something into | 2798 | /* This routine gets called when tty_write has put something into |
@@ -2878,12 +2810,12 @@ static void cy_close(struct tty_struct *tty, struct file *filp) | |||
2878 | */ | 2810 | */ |
2879 | static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count) | 2811 | static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count) |
2880 | { | 2812 | { |
2881 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 2813 | struct cyclades_port *info = tty->driver_data; |
2882 | unsigned long flags; | 2814 | unsigned long flags; |
2883 | int c, ret = 0; | 2815 | int c, ret = 0; |
2884 | 2816 | ||
2885 | #ifdef CY_DEBUG_IO | 2817 | #ifdef CY_DEBUG_IO |
2886 | printk("cyc:cy_write ttyC%d\n", info->line); /* */ | 2818 | printk(KERN_DEBUG "cyc:cy_write ttyC%d\n", info->line); |
2887 | #endif | 2819 | #endif |
2888 | 2820 | ||
2889 | if (serial_paranoia_check(info, tty->name, "cy_write")) { | 2821 | if (serial_paranoia_check(info, tty->name, "cy_write")) { |
@@ -2893,7 +2825,7 @@ static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count) | |||
2893 | if (!info->xmit_buf) | 2825 | if (!info->xmit_buf) |
2894 | return 0; | 2826 | return 0; |
2895 | 2827 | ||
2896 | CY_LOCK(info, flags); | 2828 | spin_lock_irqsave(&info->card->card_lock, flags); |
2897 | while (1) { | 2829 | while (1) { |
2898 | c = min(count, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1), | 2830 | c = min(count, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1), |
2899 | (int)(SERIAL_XMIT_SIZE - info->xmit_head))); | 2831 | (int)(SERIAL_XMIT_SIZE - info->xmit_head))); |
@@ -2909,7 +2841,7 @@ static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count) | |||
2909 | count -= c; | 2841 | count -= c; |
2910 | ret += c; | 2842 | ret += c; |
2911 | } | 2843 | } |
2912 | CY_UNLOCK(info, flags); | 2844 | spin_unlock_irqrestore(&info->card->card_lock, flags); |
2913 | 2845 | ||
2914 | info->idle_stats.xmit_bytes += ret; | 2846 | info->idle_stats.xmit_bytes += ret; |
2915 | info->idle_stats.xmit_idle = jiffies; | 2847 | info->idle_stats.xmit_idle = jiffies; |
@@ -2929,11 +2861,11 @@ static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count) | |||
2929 | */ | 2861 | */ |
2930 | static void cy_put_char(struct tty_struct *tty, unsigned char ch) | 2862 | static void cy_put_char(struct tty_struct *tty, unsigned char ch) |
2931 | { | 2863 | { |
2932 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 2864 | struct cyclades_port *info = tty->driver_data; |
2933 | unsigned long flags; | 2865 | unsigned long flags; |
2934 | 2866 | ||
2935 | #ifdef CY_DEBUG_IO | 2867 | #ifdef CY_DEBUG_IO |
2936 | printk("cyc:cy_put_char ttyC%d\n", info->line); | 2868 | printk(KERN_DEBUG "cyc:cy_put_char ttyC%d\n", info->line); |
2937 | #endif | 2869 | #endif |
2938 | 2870 | ||
2939 | if (serial_paranoia_check(info, tty->name, "cy_put_char")) | 2871 | if (serial_paranoia_check(info, tty->name, "cy_put_char")) |
@@ -2942,9 +2874,9 @@ static void cy_put_char(struct tty_struct *tty, unsigned char ch) | |||
2942 | if (!info->xmit_buf) | 2874 | if (!info->xmit_buf) |
2943 | return; | 2875 | return; |
2944 | 2876 | ||
2945 | CY_LOCK(info, flags); | 2877 | spin_lock_irqsave(&info->card->card_lock, flags); |
2946 | if (info->xmit_cnt >= (int)(SERIAL_XMIT_SIZE - 1)) { | 2878 | if (info->xmit_cnt >= (int)(SERIAL_XMIT_SIZE - 1)) { |
2947 | CY_UNLOCK(info, flags); | 2879 | spin_unlock_irqrestore(&info->card->card_lock, flags); |
2948 | return; | 2880 | return; |
2949 | } | 2881 | } |
2950 | 2882 | ||
@@ -2953,7 +2885,7 @@ static void cy_put_char(struct tty_struct *tty, unsigned char ch) | |||
2953 | info->xmit_cnt++; | 2885 | info->xmit_cnt++; |
2954 | info->idle_stats.xmit_bytes++; | 2886 | info->idle_stats.xmit_bytes++; |
2955 | info->idle_stats.xmit_idle = jiffies; | 2887 | info->idle_stats.xmit_idle = jiffies; |
2956 | CY_UNLOCK(info, flags); | 2888 | spin_unlock_irqrestore(&info->card->card_lock, flags); |
2957 | } /* cy_put_char */ | 2889 | } /* cy_put_char */ |
2958 | 2890 | ||
2959 | /* | 2891 | /* |
@@ -2962,10 +2894,10 @@ static void cy_put_char(struct tty_struct *tty, unsigned char ch) | |||
2962 | */ | 2894 | */ |
2963 | static void cy_flush_chars(struct tty_struct *tty) | 2895 | static void cy_flush_chars(struct tty_struct *tty) |
2964 | { | 2896 | { |
2965 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 2897 | struct cyclades_port *info = tty->driver_data; |
2966 | 2898 | ||
2967 | #ifdef CY_DEBUG_IO | 2899 | #ifdef CY_DEBUG_IO |
2968 | printk("cyc:cy_flush_chars ttyC%d\n", info->line); /* */ | 2900 | printk(KERN_DEBUG "cyc:cy_flush_chars ttyC%d\n", info->line); |
2969 | #endif | 2901 | #endif |
2970 | 2902 | ||
2971 | if (serial_paranoia_check(info, tty->name, "cy_flush_chars")) | 2903 | if (serial_paranoia_check(info, tty->name, "cy_flush_chars")) |
@@ -2986,11 +2918,11 @@ static void cy_flush_chars(struct tty_struct *tty) | |||
2986 | */ | 2918 | */ |
2987 | static int cy_write_room(struct tty_struct *tty) | 2919 | static int cy_write_room(struct tty_struct *tty) |
2988 | { | 2920 | { |
2989 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 2921 | struct cyclades_port *info = tty->driver_data; |
2990 | int ret; | 2922 | int ret; |
2991 | 2923 | ||
2992 | #ifdef CY_DEBUG_IO | 2924 | #ifdef CY_DEBUG_IO |
2993 | printk("cyc:cy_write_room ttyC%d\n", info->line); /* */ | 2925 | printk(KERN_DEBUG "cyc:cy_write_room ttyC%d\n", info->line); |
2994 | #endif | 2926 | #endif |
2995 | 2927 | ||
2996 | if (serial_paranoia_check(info, tty->name, "cy_write_room")) | 2928 | if (serial_paranoia_check(info, tty->name, "cy_write_room")) |
@@ -3003,46 +2935,49 @@ static int cy_write_room(struct tty_struct *tty) | |||
3003 | 2935 | ||
3004 | static int cy_chars_in_buffer(struct tty_struct *tty) | 2936 | static int cy_chars_in_buffer(struct tty_struct *tty) |
3005 | { | 2937 | { |
3006 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 2938 | struct cyclades_card *card; |
3007 | int card, channel; | 2939 | struct cyclades_port *info = tty->driver_data; |
2940 | int channel; | ||
3008 | 2941 | ||
3009 | if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer")) | 2942 | if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer")) |
3010 | return 0; | 2943 | return 0; |
3011 | 2944 | ||
3012 | card = info->card; | 2945 | card = info->card; |
3013 | channel = (info->line) - (cy_card[card].first_line); | 2946 | channel = (info->line) - (card->first_line); |
3014 | 2947 | ||
3015 | #ifdef Z_EXT_CHARS_IN_BUFFER | 2948 | #ifdef Z_EXT_CHARS_IN_BUFFER |
3016 | if (!IS_CYC_Z(cy_card[card])) { | 2949 | if (!IS_CYC_Z(cy_card[card])) { |
3017 | #endif /* Z_EXT_CHARS_IN_BUFFER */ | 2950 | #endif /* Z_EXT_CHARS_IN_BUFFER */ |
3018 | #ifdef CY_DEBUG_IO | 2951 | #ifdef CY_DEBUG_IO |
3019 | printk("cyc:cy_chars_in_buffer ttyC%d %d\n", info->line, info->xmit_cnt); /* */ | 2952 | printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n", |
2953 | info->line, info->xmit_cnt); | ||
3020 | #endif | 2954 | #endif |
3021 | return info->xmit_cnt; | 2955 | return info->xmit_cnt; |
3022 | #ifdef Z_EXT_CHARS_IN_BUFFER | 2956 | #ifdef Z_EXT_CHARS_IN_BUFFER |
3023 | } else { | 2957 | } else { |
3024 | static volatile struct FIRM_ID *firm_id; | 2958 | static struct FIRM_ID *firm_id; |
3025 | static volatile struct ZFW_CTRL *zfw_ctrl; | 2959 | static struct ZFW_CTRL *zfw_ctrl; |
3026 | static volatile struct CH_CTRL *ch_ctrl; | 2960 | static struct CH_CTRL *ch_ctrl; |
3027 | static volatile struct BUF_CTRL *buf_ctrl; | 2961 | static struct BUF_CTRL *buf_ctrl; |
3028 | int char_count; | 2962 | int char_count; |
3029 | volatile uclong tx_put, tx_get, tx_bufsize; | 2963 | __u32 tx_put, tx_get, tx_bufsize; |
3030 | 2964 | ||
3031 | firm_id = cy_card[card].base_addr + ID_ADDRESS; | 2965 | firm_id = card->base_addr + ID_ADDRESS; |
3032 | zfw_ctrl = cy_card[card].base_addr + | 2966 | zfw_ctrl = card->base_addr + |
3033 | (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); | 2967 | (readl(&firm_id->zfwctrl_addr) & 0xfffff); |
3034 | ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); | 2968 | ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); |
3035 | buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]); | 2969 | buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]); |
3036 | 2970 | ||
3037 | tx_get = cy_readl(&buf_ctrl->tx_get); | 2971 | tx_get = readl(&buf_ctrl->tx_get); |
3038 | tx_put = cy_readl(&buf_ctrl->tx_put); | 2972 | tx_put = readl(&buf_ctrl->tx_put); |
3039 | tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize); | 2973 | tx_bufsize = readl(&buf_ctrl->tx_bufsize); |
3040 | if (tx_put >= tx_get) | 2974 | if (tx_put >= tx_get) |
3041 | char_count = tx_put - tx_get; | 2975 | char_count = tx_put - tx_get; |
3042 | else | 2976 | else |
3043 | char_count = tx_put - tx_get + tx_bufsize; | 2977 | char_count = tx_put - tx_get + tx_bufsize; |
3044 | #ifdef CY_DEBUG_IO | 2978 | #ifdef CY_DEBUG_IO |
3045 | printk("cyc:cy_chars_in_buffer ttyC%d %d\n", info->line, info->xmit_cnt + char_count); /* */ | 2979 | printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n", |
2980 | info->line, info->xmit_cnt + char_count); | ||
3046 | #endif | 2981 | #endif |
3047 | return info->xmit_cnt + char_count; | 2982 | return info->xmit_cnt + char_count; |
3048 | } | 2983 | } |
@@ -3055,10 +2990,10 @@ static int cy_chars_in_buffer(struct tty_struct *tty) | |||
3055 | * ------------------------------------------------------------ | 2990 | * ------------------------------------------------------------ |
3056 | */ | 2991 | */ |
3057 | 2992 | ||
3058 | static void cyy_baud_calc(struct cyclades_port *info, uclong baud) | 2993 | static void cyy_baud_calc(struct cyclades_port *info, __u32 baud) |
3059 | { | 2994 | { |
3060 | int co, co_val, bpr; | 2995 | int co, co_val, bpr; |
3061 | uclong cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 : | 2996 | __u32 cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 : |
3062 | 25000000); | 2997 | 25000000); |
3063 | 2998 | ||
3064 | if (baud == 0) { | 2999 | if (baud == 0) { |
@@ -3086,9 +3021,10 @@ static void cyy_baud_calc(struct cyclades_port *info, uclong baud) | |||
3086 | */ | 3021 | */ |
3087 | static void set_line_char(struct cyclades_port *info) | 3022 | static void set_line_char(struct cyclades_port *info) |
3088 | { | 3023 | { |
3024 | struct cyclades_card *card; | ||
3089 | unsigned long flags; | 3025 | unsigned long flags; |
3090 | void __iomem *base_addr; | 3026 | void __iomem *base_addr; |
3091 | int card, chip, channel, index; | 3027 | int chip, channel, index; |
3092 | unsigned cflag, iflag; | 3028 | unsigned cflag, iflag; |
3093 | unsigned short chip_number; | 3029 | unsigned short chip_number; |
3094 | int baud, baud_rate = 0; | 3030 | int baud, baud_rate = 0; |
@@ -3118,12 +3054,12 @@ static void set_line_char(struct cyclades_port *info) | |||
3118 | } | 3054 | } |
3119 | 3055 | ||
3120 | card = info->card; | 3056 | card = info->card; |
3121 | channel = (info->line) - (cy_card[card].first_line); | 3057 | channel = info->line - card->first_line; |
3122 | chip_number = channel / 4; | 3058 | chip_number = channel / 4; |
3123 | 3059 | ||
3124 | if (!IS_CYC_Z(cy_card[card])) { | 3060 | if (!IS_CYC_Z(*card)) { |
3125 | 3061 | ||
3126 | index = cy_card[card].bus_index; | 3062 | index = card->bus_index; |
3127 | 3063 | ||
3128 | /* baud rate */ | 3064 | /* baud rate */ |
3129 | baud = tty_get_baud_rate(info->tty); | 3065 | baud = tty_get_baud_rate(info->tty); |
@@ -3241,10 +3177,9 @@ static void set_line_char(struct cyclades_port *info) | |||
3241 | 3177 | ||
3242 | chip = channel >> 2; | 3178 | chip = channel >> 2; |
3243 | channel &= 0x03; | 3179 | channel &= 0x03; |
3244 | base_addr = cy_card[card].base_addr + | 3180 | base_addr = card->base_addr + (cy_chip_offset[chip] << index); |
3245 | (cy_chip_offset[chip] << index); | ||
3246 | 3181 | ||
3247 | CY_LOCK(info, flags); | 3182 | spin_lock_irqsave(&card->card_lock, flags); |
3248 | cy_writeb(base_addr + (CyCAR << index), (u_char) channel); | 3183 | cy_writeb(base_addr + (CyCAR << index), (u_char) channel); |
3249 | 3184 | ||
3250 | /* tx and rx baud rate */ | 3185 | /* tx and rx baud rate */ |
@@ -3276,8 +3211,7 @@ static void set_line_char(struct cyclades_port *info) | |||
3276 | if (C_CLOCAL(info->tty)) { | 3211 | if (C_CLOCAL(info->tty)) { |
3277 | /* without modem intr */ | 3212 | /* without modem intr */ |
3278 | cy_writeb(base_addr + (CySRER << index), | 3213 | cy_writeb(base_addr + (CySRER << index), |
3279 | cy_readb(base_addr + | 3214 | readb(base_addr + (CySRER << index)) | CyMdmCh); |
3280 | (CySRER << index)) | CyMdmCh); | ||
3281 | /* act on 1->0 modem transitions */ | 3215 | /* act on 1->0 modem transitions */ |
3282 | if ((cflag & CRTSCTS) && info->rflow) { | 3216 | if ((cflag & CRTSCTS) && info->rflow) { |
3283 | cy_writeb(base_addr + (CyMCOR1 << index), | 3217 | cy_writeb(base_addr + (CyMCOR1 << index), |
@@ -3291,7 +3225,7 @@ static void set_line_char(struct cyclades_port *info) | |||
3291 | } else { | 3225 | } else { |
3292 | /* without modem intr */ | 3226 | /* without modem intr */ |
3293 | cy_writeb(base_addr + (CySRER << index), | 3227 | cy_writeb(base_addr + (CySRER << index), |
3294 | cy_readb(base_addr + | 3228 | readb(base_addr + |
3295 | (CySRER << index)) | CyMdmCh); | 3229 | (CySRER << index)) | CyMdmCh); |
3296 | /* act on 1->0 modem transitions */ | 3230 | /* act on 1->0 modem transitions */ |
3297 | if ((cflag & CRTSCTS) && info->rflow) { | 3231 | if ((cflag & CRTSCTS) && info->rflow) { |
@@ -3316,10 +3250,10 @@ static void set_line_char(struct cyclades_port *info) | |||
3316 | ~CyDTR); | 3250 | ~CyDTR); |
3317 | } | 3251 | } |
3318 | #ifdef CY_DEBUG_DTR | 3252 | #ifdef CY_DEBUG_DTR |
3319 | printk("cyc:set_line_char dropping DTR\n"); | 3253 | printk(KERN_DEBUG "cyc:set_line_char dropping DTR\n"); |
3320 | printk(" status: 0x%x, 0x%x\n", | 3254 | printk(KERN_DEBUG " status: 0x%x, 0x%x\n", |
3321 | cy_readb(base_addr + (CyMSVR1 << index)), | 3255 | readb(base_addr + (CyMSVR1 << index)), |
3322 | cy_readb(base_addr + (CyMSVR2 << index))); | 3256 | readb(base_addr + (CyMSVR2 << index))); |
3323 | #endif | 3257 | #endif |
3324 | } else { | 3258 | } else { |
3325 | if (info->rtsdtr_inv) { | 3259 | if (info->rtsdtr_inv) { |
@@ -3330,17 +3264,17 @@ static void set_line_char(struct cyclades_port *info) | |||
3330 | CyDTR); | 3264 | CyDTR); |
3331 | } | 3265 | } |
3332 | #ifdef CY_DEBUG_DTR | 3266 | #ifdef CY_DEBUG_DTR |
3333 | printk("cyc:set_line_char raising DTR\n"); | 3267 | printk(KERN_DEBUG "cyc:set_line_char raising DTR\n"); |
3334 | printk(" status: 0x%x, 0x%x\n", | 3268 | printk(KERN_DEBUG " status: 0x%x, 0x%x\n", |
3335 | cy_readb(base_addr + (CyMSVR1 << index)), | 3269 | readb(base_addr + (CyMSVR1 << index)), |
3336 | cy_readb(base_addr + (CyMSVR2 << index))); | 3270 | readb(base_addr + (CyMSVR2 << index))); |
3337 | #endif | 3271 | #endif |
3338 | } | 3272 | } |
3339 | 3273 | ||
3340 | if (info->tty) { | 3274 | if (info->tty) { |
3341 | clear_bit(TTY_IO_ERROR, &info->tty->flags); | 3275 | clear_bit(TTY_IO_ERROR, &info->tty->flags); |
3342 | } | 3276 | } |
3343 | CY_UNLOCK(info, flags); | 3277 | spin_unlock_irqrestore(&card->card_lock, flags); |
3344 | 3278 | ||
3345 | } else { | 3279 | } else { |
3346 | struct FIRM_ID __iomem *firm_id; | 3280 | struct FIRM_ID __iomem *firm_id; |
@@ -3348,16 +3282,16 @@ static void set_line_char(struct cyclades_port *info) | |||
3348 | struct BOARD_CTRL __iomem *board_ctrl; | 3282 | struct BOARD_CTRL __iomem *board_ctrl; |
3349 | struct CH_CTRL __iomem *ch_ctrl; | 3283 | struct CH_CTRL __iomem *ch_ctrl; |
3350 | struct BUF_CTRL __iomem *buf_ctrl; | 3284 | struct BUF_CTRL __iomem *buf_ctrl; |
3351 | uclong sw_flow; | 3285 | __u32 sw_flow; |
3352 | int retval; | 3286 | int retval; |
3353 | 3287 | ||
3354 | firm_id = cy_card[card].base_addr + ID_ADDRESS; | 3288 | firm_id = card->base_addr + ID_ADDRESS; |
3355 | if (!ISZLOADED(cy_card[card])) { | 3289 | if (!ISZLOADED(*card)) { |
3356 | return; | 3290 | return; |
3357 | } | 3291 | } |
3358 | 3292 | ||
3359 | zfw_ctrl = cy_card[card].base_addr + | 3293 | zfw_ctrl = card->base_addr + |
3360 | (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); | 3294 | (readl(&firm_id->zfwctrl_addr) & 0xfffff); |
3361 | board_ctrl = &zfw_ctrl->board_ctrl; | 3295 | board_ctrl = &zfw_ctrl->board_ctrl; |
3362 | ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); | 3296 | ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); |
3363 | buf_ctrl = &zfw_ctrl->buf_ctrl[channel]; | 3297 | buf_ctrl = &zfw_ctrl->buf_ctrl[channel]; |
@@ -3408,10 +3342,10 @@ static void set_line_char(struct cyclades_port *info) | |||
3408 | } | 3342 | } |
3409 | if (cflag & CSTOPB) { | 3343 | if (cflag & CSTOPB) { |
3410 | cy_writel(&ch_ctrl->comm_data_l, | 3344 | cy_writel(&ch_ctrl->comm_data_l, |
3411 | cy_readl(&ch_ctrl->comm_data_l) | C_DL_2STOP); | 3345 | readl(&ch_ctrl->comm_data_l) | C_DL_2STOP); |
3412 | } else { | 3346 | } else { |
3413 | cy_writel(&ch_ctrl->comm_data_l, | 3347 | cy_writel(&ch_ctrl->comm_data_l, |
3414 | cy_readl(&ch_ctrl->comm_data_l) | C_DL_1STOP); | 3348 | readl(&ch_ctrl->comm_data_l) | C_DL_1STOP); |
3415 | } | 3349 | } |
3416 | if (cflag & PARENB) { | 3350 | if (cflag & PARENB) { |
3417 | if (cflag & PARODD) { | 3351 | if (cflag & PARODD) { |
@@ -3426,12 +3360,10 @@ static void set_line_char(struct cyclades_port *info) | |||
3426 | /* CTS flow control flag */ | 3360 | /* CTS flow control flag */ |
3427 | if (cflag & CRTSCTS) { | 3361 | if (cflag & CRTSCTS) { |
3428 | cy_writel(&ch_ctrl->hw_flow, | 3362 | cy_writel(&ch_ctrl->hw_flow, |
3429 | cy_readl(&ch_ctrl-> | 3363 | readl(&ch_ctrl->hw_flow) | C_RS_CTS | C_RS_RTS); |
3430 | hw_flow) | C_RS_CTS | C_RS_RTS); | ||
3431 | } else { | 3364 | } else { |
3432 | cy_writel(&ch_ctrl->hw_flow, | 3365 | cy_writel(&ch_ctrl->hw_flow, readl(&ch_ctrl->hw_flow) & |
3433 | cy_readl(&ch_ctrl-> | 3366 | ~(C_RS_CTS | C_RS_RTS)); |
3434 | hw_flow) & ~(C_RS_CTS | C_RS_RTS)); | ||
3435 | } | 3367 | } |
3436 | /* As the HW flow control is done in firmware, the driver | 3368 | /* As the HW flow control is done in firmware, the driver |
3437 | doesn't need to care about it */ | 3369 | doesn't need to care about it */ |
@@ -3446,10 +3378,10 @@ static void set_line_char(struct cyclades_port *info) | |||
3446 | } | 3378 | } |
3447 | cy_writel(&ch_ctrl->sw_flow, sw_flow); | 3379 | cy_writel(&ch_ctrl->sw_flow, sw_flow); |
3448 | 3380 | ||
3449 | retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L); | 3381 | retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L); |
3450 | if (retval != 0) { | 3382 | if (retval != 0) { |
3451 | printk("cyc:set_line_char retval on ttyC%d was %x\n", | 3383 | printk(KERN_ERR "cyc:set_line_char retval on ttyC%d " |
3452 | info->line, retval); | 3384 | "was %x\n", info->line, retval); |
3453 | } | 3385 | } |
3454 | 3386 | ||
3455 | /* CD sensitivity */ | 3387 | /* CD sensitivity */ |
@@ -3461,22 +3393,22 @@ static void set_line_char(struct cyclades_port *info) | |||
3461 | 3393 | ||
3462 | if (baud == 0) { /* baud rate is zero, turn off line */ | 3394 | if (baud == 0) { /* baud rate is zero, turn off line */ |
3463 | cy_writel(&ch_ctrl->rs_control, | 3395 | cy_writel(&ch_ctrl->rs_control, |
3464 | cy_readl(&ch_ctrl->rs_control) & ~C_RS_DTR); | 3396 | readl(&ch_ctrl->rs_control) & ~C_RS_DTR); |
3465 | #ifdef CY_DEBUG_DTR | 3397 | #ifdef CY_DEBUG_DTR |
3466 | printk("cyc:set_line_char dropping Z DTR\n"); | 3398 | printk(KERN_DEBUG "cyc:set_line_char dropping Z DTR\n"); |
3467 | #endif | 3399 | #endif |
3468 | } else { | 3400 | } else { |
3469 | cy_writel(&ch_ctrl->rs_control, | 3401 | cy_writel(&ch_ctrl->rs_control, |
3470 | cy_readl(&ch_ctrl->rs_control) | C_RS_DTR); | 3402 | readl(&ch_ctrl->rs_control) | C_RS_DTR); |
3471 | #ifdef CY_DEBUG_DTR | 3403 | #ifdef CY_DEBUG_DTR |
3472 | printk("cyc:set_line_char raising Z DTR\n"); | 3404 | printk(KERN_DEBUG "cyc:set_line_char raising Z DTR\n"); |
3473 | #endif | 3405 | #endif |
3474 | } | 3406 | } |
3475 | 3407 | ||
3476 | retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTLM,0L); | 3408 | retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM,0L); |
3477 | if (retval != 0) { | 3409 | if (retval != 0) { |
3478 | printk("cyc:set_line_char(2) retval on ttyC%d was %x\n", | 3410 | printk(KERN_ERR "cyc:set_line_char(2) retval on ttyC%d " |
3479 | info->line, retval); | 3411 | "was %x\n", info->line, retval); |
3480 | } | 3412 | } |
3481 | 3413 | ||
3482 | if (info->tty) { | 3414 | if (info->tty) { |
@@ -3490,14 +3422,15 @@ get_serial_info(struct cyclades_port *info, | |||
3490 | struct serial_struct __user * retinfo) | 3422 | struct serial_struct __user * retinfo) |
3491 | { | 3423 | { |
3492 | struct serial_struct tmp; | 3424 | struct serial_struct tmp; |
3493 | struct cyclades_card *cinfo = &cy_card[info->card]; | 3425 | struct cyclades_card *cinfo = info->card; |
3494 | 3426 | ||
3495 | if (!retinfo) | 3427 | if (!retinfo) |
3496 | return -EFAULT; | 3428 | return -EFAULT; |
3497 | memset(&tmp, 0, sizeof(tmp)); | 3429 | memset(&tmp, 0, sizeof(tmp)); |
3498 | tmp.type = info->type; | 3430 | tmp.type = info->type; |
3499 | tmp.line = info->line; | 3431 | tmp.line = info->line; |
3500 | tmp.port = info->card * 0x100 + info->line - cinfo->first_line; | 3432 | tmp.port = (info->card - cy_card) * 0x100 + info->line - |
3433 | cinfo->first_line; | ||
3501 | tmp.irq = cinfo->irq; | 3434 | tmp.irq = cinfo->irq; |
3502 | tmp.flags = info->flags; | 3435 | tmp.flags = info->flags; |
3503 | tmp.close_delay = info->close_delay; | 3436 | tmp.close_delay = info->close_delay; |
@@ -3566,25 +3499,25 @@ check_and_exit: | |||
3566 | */ | 3499 | */ |
3567 | static int get_lsr_info(struct cyclades_port *info, unsigned int __user * value) | 3500 | static int get_lsr_info(struct cyclades_port *info, unsigned int __user * value) |
3568 | { | 3501 | { |
3569 | int card, chip, channel, index; | 3502 | struct cyclades_card *card; |
3503 | int chip, channel, index; | ||
3570 | unsigned char status; | 3504 | unsigned char status; |
3571 | unsigned int result; | 3505 | unsigned int result; |
3572 | unsigned long flags; | 3506 | unsigned long flags; |
3573 | void __iomem *base_addr; | 3507 | void __iomem *base_addr; |
3574 | 3508 | ||
3575 | card = info->card; | 3509 | card = info->card; |
3576 | channel = (info->line) - (cy_card[card].first_line); | 3510 | channel = (info->line) - (card->first_line); |
3577 | if (!IS_CYC_Z(cy_card[card])) { | 3511 | if (!IS_CYC_Z(*card)) { |
3578 | chip = channel >> 2; | 3512 | chip = channel >> 2; |
3579 | channel &= 0x03; | 3513 | channel &= 0x03; |
3580 | index = cy_card[card].bus_index; | 3514 | index = card->bus_index; |
3581 | base_addr = | 3515 | base_addr = card->base_addr + (cy_chip_offset[chip] << index); |
3582 | cy_card[card].base_addr + (cy_chip_offset[chip] << index); | ||
3583 | 3516 | ||
3584 | CY_LOCK(info, flags); | 3517 | spin_lock_irqsave(&card->card_lock, flags); |
3585 | status = cy_readb(base_addr + (CySRER << index)) & | 3518 | status = readb(base_addr + (CySRER << index)) & |
3586 | (CyTxRdy | CyTxMpty); | 3519 | (CyTxRdy | CyTxMpty); |
3587 | CY_UNLOCK(info, flags); | 3520 | spin_unlock_irqrestore(&card->card_lock, flags); |
3588 | result = (status ? 0 : TIOCSER_TEMT); | 3521 | result = (status ? 0 : TIOCSER_TEMT); |
3589 | } else { | 3522 | } else { |
3590 | /* Not supported yet */ | 3523 | /* Not supported yet */ |
@@ -3595,8 +3528,9 @@ static int get_lsr_info(struct cyclades_port *info, unsigned int __user * value) | |||
3595 | 3528 | ||
3596 | static int cy_tiocmget(struct tty_struct *tty, struct file *file) | 3529 | static int cy_tiocmget(struct tty_struct *tty, struct file *file) |
3597 | { | 3530 | { |
3598 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 3531 | struct cyclades_port *info = tty->driver_data; |
3599 | int card, chip, channel, index; | 3532 | struct cyclades_card *card; |
3533 | int chip, channel, index; | ||
3600 | void __iomem *base_addr; | 3534 | void __iomem *base_addr; |
3601 | unsigned long flags; | 3535 | unsigned long flags; |
3602 | unsigned char status; | 3536 | unsigned char status; |
@@ -3611,19 +3545,18 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file) | |||
3611 | return -ENODEV; | 3545 | return -ENODEV; |
3612 | 3546 | ||
3613 | card = info->card; | 3547 | card = info->card; |
3614 | channel = (info->line) - (cy_card[card].first_line); | 3548 | channel = info->line - card->first_line; |
3615 | if (!IS_CYC_Z(cy_card[card])) { | 3549 | if (!IS_CYC_Z(*card)) { |
3616 | chip = channel >> 2; | 3550 | chip = channel >> 2; |
3617 | channel &= 0x03; | 3551 | channel &= 0x03; |
3618 | index = cy_card[card].bus_index; | 3552 | index = card->bus_index; |
3619 | base_addr = | 3553 | base_addr = card->base_addr + (cy_chip_offset[chip] << index); |
3620 | cy_card[card].base_addr + (cy_chip_offset[chip] << index); | ||
3621 | 3554 | ||
3622 | CY_LOCK(info, flags); | 3555 | spin_lock_irqsave(&card->card_lock, flags); |
3623 | cy_writeb(base_addr + (CyCAR << index), (u_char) channel); | 3556 | cy_writeb(base_addr + (CyCAR << index), (u_char) channel); |
3624 | status = cy_readb(base_addr + (CyMSVR1 << index)); | 3557 | status = readb(base_addr + (CyMSVR1 << index)); |
3625 | status |= cy_readb(base_addr + (CyMSVR2 << index)); | 3558 | status |= readb(base_addr + (CyMSVR2 << index)); |
3626 | CY_UNLOCK(info, flags); | 3559 | spin_unlock_irqrestore(&card->card_lock, flags); |
3627 | 3560 | ||
3628 | if (info->rtsdtr_inv) { | 3561 | if (info->rtsdtr_inv) { |
3629 | result = ((status & CyRTS) ? TIOCM_DTR : 0) | | 3562 | result = ((status & CyRTS) ? TIOCM_DTR : 0) | |
@@ -3637,19 +3570,14 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file) | |||
3637 | ((status & CyDSR) ? TIOCM_DSR : 0) | | 3570 | ((status & CyDSR) ? TIOCM_DSR : 0) | |
3638 | ((status & CyCTS) ? TIOCM_CTS : 0); | 3571 | ((status & CyCTS) ? TIOCM_CTS : 0); |
3639 | } else { | 3572 | } else { |
3640 | base_addr = cy_card[card].base_addr; | 3573 | base_addr = card->base_addr; |
3641 | 3574 | firm_id = card->base_addr + ID_ADDRESS; | |
3642 | if (cy_card[card].num_chips != -1) { | 3575 | if (ISZLOADED(*card)) { |
3643 | return -EINVAL; | 3576 | zfw_ctrl = card->base_addr + |
3644 | } | 3577 | (readl(&firm_id->zfwctrl_addr) & 0xfffff); |
3645 | |||
3646 | firm_id = cy_card[card].base_addr + ID_ADDRESS; | ||
3647 | if (ISZLOADED(cy_card[card])) { | ||
3648 | zfw_ctrl = cy_card[card].base_addr + | ||
3649 | (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); | ||
3650 | board_ctrl = &zfw_ctrl->board_ctrl; | 3578 | board_ctrl = &zfw_ctrl->board_ctrl; |
3651 | ch_ctrl = zfw_ctrl->ch_ctrl; | 3579 | ch_ctrl = zfw_ctrl->ch_ctrl; |
3652 | lstatus = cy_readl(&ch_ctrl[channel].rs_status); | 3580 | lstatus = readl(&ch_ctrl[channel].rs_status); |
3653 | result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) | | 3581 | result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) | |
3654 | ((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) | | 3582 | ((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) | |
3655 | ((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) | | 3583 | ((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) | |
@@ -3669,8 +3597,9 @@ static int | |||
3669 | cy_tiocmset(struct tty_struct *tty, struct file *file, | 3597 | cy_tiocmset(struct tty_struct *tty, struct file *file, |
3670 | unsigned int set, unsigned int clear) | 3598 | unsigned int set, unsigned int clear) |
3671 | { | 3599 | { |
3672 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 3600 | struct cyclades_port *info = tty->driver_data; |
3673 | int card, chip, channel, index; | 3601 | struct cyclades_card *card; |
3602 | int chip, channel, index; | ||
3674 | void __iomem *base_addr; | 3603 | void __iomem *base_addr; |
3675 | unsigned long flags; | 3604 | unsigned long flags; |
3676 | struct FIRM_ID __iomem *firm_id; | 3605 | struct FIRM_ID __iomem *firm_id; |
@@ -3683,16 +3612,15 @@ cy_tiocmset(struct tty_struct *tty, struct file *file, | |||
3683 | return -ENODEV; | 3612 | return -ENODEV; |
3684 | 3613 | ||
3685 | card = info->card; | 3614 | card = info->card; |
3686 | channel = (info->line) - (cy_card[card].first_line); | 3615 | channel = (info->line) - (card->first_line); |
3687 | if (!IS_CYC_Z(cy_card[card])) { | 3616 | if (!IS_CYC_Z(*card)) { |
3688 | chip = channel >> 2; | 3617 | chip = channel >> 2; |
3689 | channel &= 0x03; | 3618 | channel &= 0x03; |
3690 | index = cy_card[card].bus_index; | 3619 | index = card->bus_index; |
3691 | base_addr = | 3620 | base_addr = card->base_addr + (cy_chip_offset[chip] << index); |
3692 | cy_card[card].base_addr + (cy_chip_offset[chip] << index); | ||
3693 | 3621 | ||
3694 | if (set & TIOCM_RTS) { | 3622 | if (set & TIOCM_RTS) { |
3695 | CY_LOCK(info, flags); | 3623 | spin_lock_irqsave(&card->card_lock, flags); |
3696 | cy_writeb(base_addr + (CyCAR << index), | 3624 | cy_writeb(base_addr + (CyCAR << index), |
3697 | (u_char) channel); | 3625 | (u_char) channel); |
3698 | if (info->rtsdtr_inv) { | 3626 | if (info->rtsdtr_inv) { |
@@ -3702,10 +3630,10 @@ cy_tiocmset(struct tty_struct *tty, struct file *file, | |||
3702 | cy_writeb(base_addr + (CyMSVR1 << index), | 3630 | cy_writeb(base_addr + (CyMSVR1 << index), |
3703 | CyRTS); | 3631 | CyRTS); |
3704 | } | 3632 | } |
3705 | CY_UNLOCK(info, flags); | 3633 | spin_unlock_irqrestore(&card->card_lock, flags); |
3706 | } | 3634 | } |
3707 | if (clear & TIOCM_RTS) { | 3635 | if (clear & TIOCM_RTS) { |
3708 | CY_LOCK(info, flags); | 3636 | spin_lock_irqsave(&card->card_lock, flags); |
3709 | cy_writeb(base_addr + (CyCAR << index), | 3637 | cy_writeb(base_addr + (CyCAR << index), |
3710 | (u_char) channel); | 3638 | (u_char) channel); |
3711 | if (info->rtsdtr_inv) { | 3639 | if (info->rtsdtr_inv) { |
@@ -3715,10 +3643,10 @@ cy_tiocmset(struct tty_struct *tty, struct file *file, | |||
3715 | cy_writeb(base_addr + (CyMSVR1 << index), | 3643 | cy_writeb(base_addr + (CyMSVR1 << index), |
3716 | ~CyRTS); | 3644 | ~CyRTS); |
3717 | } | 3645 | } |
3718 | CY_UNLOCK(info, flags); | 3646 | spin_unlock_irqrestore(&card->card_lock, flags); |
3719 | } | 3647 | } |
3720 | if (set & TIOCM_DTR) { | 3648 | if (set & TIOCM_DTR) { |
3721 | CY_LOCK(info, flags); | 3649 | spin_lock_irqsave(&card->card_lock, flags); |
3722 | cy_writeb(base_addr + (CyCAR << index), | 3650 | cy_writeb(base_addr + (CyCAR << index), |
3723 | (u_char) channel); | 3651 | (u_char) channel); |
3724 | if (info->rtsdtr_inv) { | 3652 | if (info->rtsdtr_inv) { |
@@ -3729,15 +3657,15 @@ cy_tiocmset(struct tty_struct *tty, struct file *file, | |||
3729 | CyDTR); | 3657 | CyDTR); |
3730 | } | 3658 | } |
3731 | #ifdef CY_DEBUG_DTR | 3659 | #ifdef CY_DEBUG_DTR |
3732 | printk("cyc:set_modem_info raising DTR\n"); | 3660 | printk(KERN_DEBUG "cyc:set_modem_info raising DTR\n"); |
3733 | printk(" status: 0x%x, 0x%x\n", | 3661 | printk(KERN_DEBUG " status: 0x%x, 0x%x\n", |
3734 | cy_readb(base_addr + (CyMSVR1 << index)), | 3662 | readb(base_addr + (CyMSVR1 << index)), |
3735 | cy_readb(base_addr + (CyMSVR2 << index))); | 3663 | readb(base_addr + (CyMSVR2 << index))); |
3736 | #endif | 3664 | #endif |
3737 | CY_UNLOCK(info, flags); | 3665 | spin_unlock_irqrestore(&card->card_lock, flags); |
3738 | } | 3666 | } |
3739 | if (clear & TIOCM_DTR) { | 3667 | if (clear & TIOCM_DTR) { |
3740 | CY_LOCK(info, flags); | 3668 | spin_lock_irqsave(&card->card_lock, flags); |
3741 | cy_writeb(base_addr + (CyCAR << index), | 3669 | cy_writeb(base_addr + (CyCAR << index), |
3742 | (u_char) channel); | 3670 | (u_char) channel); |
3743 | if (info->rtsdtr_inv) { | 3671 | if (info->rtsdtr_inv) { |
@@ -3749,68 +3677,69 @@ cy_tiocmset(struct tty_struct *tty, struct file *file, | |||
3749 | } | 3677 | } |
3750 | 3678 | ||
3751 | #ifdef CY_DEBUG_DTR | 3679 | #ifdef CY_DEBUG_DTR |
3752 | printk("cyc:set_modem_info dropping DTR\n"); | 3680 | printk(KERN_DEBUG "cyc:set_modem_info dropping DTR\n"); |
3753 | printk(" status: 0x%x, 0x%x\n", | 3681 | printk(KERN_DEBUG " status: 0x%x, 0x%x\n", |
3754 | cy_readb(base_addr + (CyMSVR1 << index)), | 3682 | readb(base_addr + (CyMSVR1 << index)), |
3755 | cy_readb(base_addr + (CyMSVR2 << index))); | 3683 | readb(base_addr + (CyMSVR2 << index))); |
3756 | #endif | 3684 | #endif |
3757 | CY_UNLOCK(info, flags); | 3685 | spin_unlock_irqrestore(&card->card_lock, flags); |
3758 | } | 3686 | } |
3759 | } else { | 3687 | } else { |
3760 | base_addr = cy_card[card].base_addr; | 3688 | base_addr = card->base_addr; |
3761 | 3689 | ||
3762 | firm_id = cy_card[card].base_addr + ID_ADDRESS; | 3690 | firm_id = card->base_addr + ID_ADDRESS; |
3763 | if (ISZLOADED(cy_card[card])) { | 3691 | if (ISZLOADED(*card)) { |
3764 | zfw_ctrl = cy_card[card].base_addr + | 3692 | zfw_ctrl = card->base_addr + |
3765 | (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); | 3693 | (readl(&firm_id->zfwctrl_addr) & 0xfffff); |
3766 | board_ctrl = &zfw_ctrl->board_ctrl; | 3694 | board_ctrl = &zfw_ctrl->board_ctrl; |
3767 | ch_ctrl = zfw_ctrl->ch_ctrl; | 3695 | ch_ctrl = zfw_ctrl->ch_ctrl; |
3768 | 3696 | ||
3769 | if (set & TIOCM_RTS) { | 3697 | if (set & TIOCM_RTS) { |
3770 | CY_LOCK(info, flags); | 3698 | spin_lock_irqsave(&card->card_lock, flags); |
3771 | cy_writel(&ch_ctrl[channel].rs_control, | 3699 | cy_writel(&ch_ctrl[channel].rs_control, |
3772 | cy_readl(&ch_ctrl[channel]. | 3700 | readl(&ch_ctrl[channel].rs_control) | |
3773 | rs_control) | C_RS_RTS); | 3701 | C_RS_RTS); |
3774 | CY_UNLOCK(info, flags); | 3702 | spin_unlock_irqrestore(&card->card_lock, flags); |
3775 | } | 3703 | } |
3776 | if (clear & TIOCM_RTS) { | 3704 | if (clear & TIOCM_RTS) { |
3777 | CY_LOCK(info, flags); | 3705 | spin_lock_irqsave(&card->card_lock, flags); |
3778 | cy_writel(&ch_ctrl[channel].rs_control, | 3706 | cy_writel(&ch_ctrl[channel].rs_control, |
3779 | cy_readl(&ch_ctrl[channel]. | 3707 | readl(&ch_ctrl[channel].rs_control) & |
3780 | rs_control) & ~C_RS_RTS); | 3708 | ~C_RS_RTS); |
3781 | CY_UNLOCK(info, flags); | 3709 | spin_unlock_irqrestore(&card->card_lock, flags); |
3782 | } | 3710 | } |
3783 | if (set & TIOCM_DTR) { | 3711 | if (set & TIOCM_DTR) { |
3784 | CY_LOCK(info, flags); | 3712 | spin_lock_irqsave(&card->card_lock, flags); |
3785 | cy_writel(&ch_ctrl[channel].rs_control, | 3713 | cy_writel(&ch_ctrl[channel].rs_control, |
3786 | cy_readl(&ch_ctrl[channel]. | 3714 | readl(&ch_ctrl[channel].rs_control) | |
3787 | rs_control) | C_RS_DTR); | 3715 | C_RS_DTR); |
3788 | #ifdef CY_DEBUG_DTR | 3716 | #ifdef CY_DEBUG_DTR |
3789 | printk("cyc:set_modem_info raising Z DTR\n"); | 3717 | printk(KERN_DEBUG "cyc:set_modem_info raising " |
3718 | "Z DTR\n"); | ||
3790 | #endif | 3719 | #endif |
3791 | CY_UNLOCK(info, flags); | 3720 | spin_unlock_irqrestore(&card->card_lock, flags); |
3792 | } | 3721 | } |
3793 | if (clear & TIOCM_DTR) { | 3722 | if (clear & TIOCM_DTR) { |
3794 | CY_LOCK(info, flags); | 3723 | spin_lock_irqsave(&card->card_lock, flags); |
3795 | cy_writel(&ch_ctrl[channel].rs_control, | 3724 | cy_writel(&ch_ctrl[channel].rs_control, |
3796 | cy_readl(&ch_ctrl[channel]. | 3725 | readl(&ch_ctrl[channel].rs_control) & |
3797 | rs_control) & ~C_RS_DTR); | 3726 | ~C_RS_DTR); |
3798 | #ifdef CY_DEBUG_DTR | 3727 | #ifdef CY_DEBUG_DTR |
3799 | printk("cyc:set_modem_info clearing Z DTR\n"); | 3728 | printk(KERN_DEBUG "cyc:set_modem_info clearing " |
3729 | "Z DTR\n"); | ||
3800 | #endif | 3730 | #endif |
3801 | CY_UNLOCK(info, flags); | 3731 | spin_unlock_irqrestore(&card->card_lock, flags); |
3802 | } | 3732 | } |
3803 | } else { | 3733 | } else { |
3804 | return -ENODEV; | 3734 | return -ENODEV; |
3805 | } | 3735 | } |
3806 | CY_LOCK(info, flags); | 3736 | spin_lock_irqsave(&card->card_lock, flags); |
3807 | retval = cyz_issue_cmd(&cy_card[info->card], | 3737 | retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L); |
3808 | channel, C_CM_IOCTLM, 0L); | ||
3809 | if (retval != 0) { | 3738 | if (retval != 0) { |
3810 | printk("cyc:set_modem_info retval on ttyC%d was %x\n", | 3739 | printk(KERN_ERR "cyc:set_modem_info retval on ttyC%d " |
3811 | info->line, retval); | 3740 | "was %x\n", info->line, retval); |
3812 | } | 3741 | } |
3813 | CY_UNLOCK(info, flags); | 3742 | spin_unlock_irqrestore(&card->card_lock, flags); |
3814 | } | 3743 | } |
3815 | return 0; | 3744 | return 0; |
3816 | } /* cy_tiocmset */ | 3745 | } /* cy_tiocmset */ |
@@ -3820,14 +3749,17 @@ cy_tiocmset(struct tty_struct *tty, struct file *file, | |||
3820 | */ | 3749 | */ |
3821 | static void cy_break(struct tty_struct *tty, int break_state) | 3750 | static void cy_break(struct tty_struct *tty, int break_state) |
3822 | { | 3751 | { |
3823 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 3752 | struct cyclades_port *info = tty->driver_data; |
3753 | struct cyclades_card *card; | ||
3824 | unsigned long flags; | 3754 | unsigned long flags; |
3825 | 3755 | ||
3826 | if (serial_paranoia_check(info, tty->name, "cy_break")) | 3756 | if (serial_paranoia_check(info, tty->name, "cy_break")) |
3827 | return; | 3757 | return; |
3828 | 3758 | ||
3829 | CY_LOCK(info, flags); | 3759 | card = info->card; |
3830 | if (!IS_CYC_Z(cy_card[info->card])) { | 3760 | |
3761 | spin_lock_irqsave(&card->card_lock, flags); | ||
3762 | if (!IS_CYC_Z(*card)) { | ||
3831 | /* Let the transmit ISR take care of this (since it | 3763 | /* Let the transmit ISR take care of this (since it |
3832 | requires stuffing characters into the output stream). | 3764 | requires stuffing characters into the output stream). |
3833 | */ | 3765 | */ |
@@ -3835,18 +3767,18 @@ static void cy_break(struct tty_struct *tty, int break_state) | |||
3835 | if (!info->breakon) { | 3767 | if (!info->breakon) { |
3836 | info->breakon = 1; | 3768 | info->breakon = 1; |
3837 | if (!info->xmit_cnt) { | 3769 | if (!info->xmit_cnt) { |
3838 | CY_UNLOCK(info, flags); | 3770 | spin_unlock_irqrestore(&card->card_lock, flags); |
3839 | start_xmit(info); | 3771 | start_xmit(info); |
3840 | CY_LOCK(info, flags); | 3772 | spin_lock_irqsave(&card->card_lock, flags); |
3841 | } | 3773 | } |
3842 | } | 3774 | } |
3843 | } else { | 3775 | } else { |
3844 | if (!info->breakoff) { | 3776 | if (!info->breakoff) { |
3845 | info->breakoff = 1; | 3777 | info->breakoff = 1; |
3846 | if (!info->xmit_cnt) { | 3778 | if (!info->xmit_cnt) { |
3847 | CY_UNLOCK(info, flags); | 3779 | spin_unlock_irqrestore(&card->card_lock, flags); |
3848 | start_xmit(info); | 3780 | start_xmit(info); |
3849 | CY_LOCK(info, flags); | 3781 | spin_lock_irqsave(&card->card_lock, flags); |
3850 | } | 3782 | } |
3851 | } | 3783 | } |
3852 | } | 3784 | } |
@@ -3854,24 +3786,25 @@ static void cy_break(struct tty_struct *tty, int break_state) | |||
3854 | int retval; | 3786 | int retval; |
3855 | 3787 | ||
3856 | if (break_state == -1) { | 3788 | if (break_state == -1) { |
3857 | retval = cyz_issue_cmd(&cy_card[info->card], | 3789 | retval = cyz_issue_cmd(card, |
3858 | info->line - cy_card[info->card].first_line, | 3790 | info->line - card->first_line, |
3859 | C_CM_SET_BREAK, 0L); | 3791 | C_CM_SET_BREAK, 0L); |
3860 | if (retval != 0) { | 3792 | if (retval != 0) { |
3861 | printk("cyc:cy_break (set) retval on ttyC%d " | 3793 | printk(KERN_ERR "cyc:cy_break (set) retval on " |
3862 | "was %x\n", info->line, retval); | 3794 | "ttyC%d was %x\n", info->line, retval); |
3863 | } | 3795 | } |
3864 | } else { | 3796 | } else { |
3865 | retval = cyz_issue_cmd(&cy_card[info->card], | 3797 | retval = cyz_issue_cmd(card, |
3866 | info->line - cy_card[info->card].first_line, | 3798 | info->line - card->first_line, |
3867 | C_CM_CLR_BREAK, 0L); | 3799 | C_CM_CLR_BREAK, 0L); |
3868 | if (retval != 0) { | 3800 | if (retval != 0) { |
3869 | printk("cyc:cy_break (clr) retval on ttyC%d " | 3801 | printk(KERN_DEBUG "cyc:cy_break (clr) retval " |
3870 | "was %x\n", info->line, retval); | 3802 | "on ttyC%d was %x\n", info->line, |
3803 | retval); | ||
3871 | } | 3804 | } |
3872 | } | 3805 | } |
3873 | } | 3806 | } |
3874 | CY_UNLOCK(info, flags); | 3807 | spin_unlock_irqrestore(&card->card_lock, flags); |
3875 | } /* cy_break */ | 3808 | } /* cy_break */ |
3876 | 3809 | ||
3877 | static int | 3810 | static int |
@@ -3889,28 +3822,27 @@ get_mon_info(struct cyclades_port *info, struct cyclades_monitor __user * mon) | |||
3889 | 3822 | ||
3890 | static int set_threshold(struct cyclades_port *info, unsigned long value) | 3823 | static int set_threshold(struct cyclades_port *info, unsigned long value) |
3891 | { | 3824 | { |
3825 | struct cyclades_card *card; | ||
3892 | void __iomem *base_addr; | 3826 | void __iomem *base_addr; |
3893 | int card, channel, chip, index; | 3827 | int channel, chip, index; |
3894 | unsigned long flags; | 3828 | unsigned long flags; |
3895 | 3829 | ||
3896 | card = info->card; | 3830 | card = info->card; |
3897 | channel = info->line - cy_card[card].first_line; | 3831 | channel = info->line - card->first_line; |
3898 | if (!IS_CYC_Z(cy_card[card])) { | 3832 | if (!IS_CYC_Z(*card)) { |
3899 | chip = channel >> 2; | 3833 | chip = channel >> 2; |
3900 | channel &= 0x03; | 3834 | channel &= 0x03; |
3901 | index = cy_card[card].bus_index; | 3835 | index = card->bus_index; |
3902 | base_addr = | 3836 | base_addr = |
3903 | cy_card[card].base_addr + (cy_chip_offset[chip] << index); | 3837 | card->base_addr + (cy_chip_offset[chip] << index); |
3904 | 3838 | ||
3905 | info->cor3 &= ~CyREC_FIFO; | 3839 | info->cor3 &= ~CyREC_FIFO; |
3906 | info->cor3 |= value & CyREC_FIFO; | 3840 | info->cor3 |= value & CyREC_FIFO; |
3907 | 3841 | ||
3908 | CY_LOCK(info, flags); | 3842 | spin_lock_irqsave(&card->card_lock, flags); |
3909 | cy_writeb(base_addr + (CyCOR3 << index), info->cor3); | 3843 | cy_writeb(base_addr + (CyCOR3 << index), info->cor3); |
3910 | cyy_issue_cmd(base_addr, CyCOR_CHANGE | CyCOR3ch, index); | 3844 | cyy_issue_cmd(base_addr, CyCOR_CHANGE | CyCOR3ch, index); |
3911 | CY_UNLOCK(info, flags); | 3845 | spin_unlock_irqrestore(&card->card_lock, flags); |
3912 | } else { | ||
3913 | /* Nothing to do! */ | ||
3914 | } | 3846 | } |
3915 | return 0; | 3847 | return 0; |
3916 | } /* set_threshold */ | 3848 | } /* set_threshold */ |
@@ -3918,25 +3850,23 @@ static int set_threshold(struct cyclades_port *info, unsigned long value) | |||
3918 | static int | 3850 | static int |
3919 | get_threshold(struct cyclades_port *info, unsigned long __user * value) | 3851 | get_threshold(struct cyclades_port *info, unsigned long __user * value) |
3920 | { | 3852 | { |
3853 | struct cyclades_card *card; | ||
3921 | void __iomem *base_addr; | 3854 | void __iomem *base_addr; |
3922 | int card, channel, chip, index; | 3855 | int channel, chip, index; |
3923 | unsigned long tmp; | 3856 | unsigned long tmp; |
3924 | 3857 | ||
3925 | card = info->card; | 3858 | card = info->card; |
3926 | channel = info->line - cy_card[card].first_line; | 3859 | channel = info->line - card->first_line; |
3927 | if (!IS_CYC_Z(cy_card[card])) { | 3860 | if (!IS_CYC_Z(*card)) { |
3928 | chip = channel >> 2; | 3861 | chip = channel >> 2; |
3929 | channel &= 0x03; | 3862 | channel &= 0x03; |
3930 | index = cy_card[card].bus_index; | 3863 | index = card->bus_index; |
3931 | base_addr = | 3864 | base_addr = card->base_addr + (cy_chip_offset[chip] << index); |
3932 | cy_card[card].base_addr + (cy_chip_offset[chip] << index); | ||
3933 | 3865 | ||
3934 | tmp = cy_readb(base_addr + (CyCOR3 << index)) & CyREC_FIFO; | 3866 | tmp = readb(base_addr + (CyCOR3 << index)) & CyREC_FIFO; |
3935 | return put_user(tmp, value); | 3867 | return put_user(tmp, value); |
3936 | } else { | ||
3937 | /* Nothing to do! */ | ||
3938 | return 0; | ||
3939 | } | 3868 | } |
3869 | return 0; | ||
3940 | } /* get_threshold */ | 3870 | } /* get_threshold */ |
3941 | 3871 | ||
3942 | static int | 3872 | static int |
@@ -3954,49 +3884,45 @@ get_default_threshold(struct cyclades_port *info, unsigned long __user * value) | |||
3954 | 3884 | ||
3955 | static int set_timeout(struct cyclades_port *info, unsigned long value) | 3885 | static int set_timeout(struct cyclades_port *info, unsigned long value) |
3956 | { | 3886 | { |
3887 | struct cyclades_card *card; | ||
3957 | void __iomem *base_addr; | 3888 | void __iomem *base_addr; |
3958 | int card, channel, chip, index; | 3889 | int channel, chip, index; |
3959 | unsigned long flags; | 3890 | unsigned long flags; |
3960 | 3891 | ||
3961 | card = info->card; | 3892 | card = info->card; |
3962 | channel = info->line - cy_card[card].first_line; | 3893 | channel = info->line - card->first_line; |
3963 | if (!IS_CYC_Z(cy_card[card])) { | 3894 | if (!IS_CYC_Z(*card)) { |
3964 | chip = channel >> 2; | 3895 | chip = channel >> 2; |
3965 | channel &= 0x03; | 3896 | channel &= 0x03; |
3966 | index = cy_card[card].bus_index; | 3897 | index = card->bus_index; |
3967 | base_addr = | 3898 | base_addr = card->base_addr + (cy_chip_offset[chip] << index); |
3968 | cy_card[card].base_addr + (cy_chip_offset[chip] << index); | ||
3969 | 3899 | ||
3970 | CY_LOCK(info, flags); | 3900 | spin_lock_irqsave(&card->card_lock, flags); |
3971 | cy_writeb(base_addr + (CyRTPR << index), value & 0xff); | 3901 | cy_writeb(base_addr + (CyRTPR << index), value & 0xff); |
3972 | CY_UNLOCK(info, flags); | 3902 | spin_unlock_irqrestore(&card->card_lock, flags); |
3973 | } else { | ||
3974 | /* Nothing to do! */ | ||
3975 | } | 3903 | } |
3976 | return 0; | 3904 | return 0; |
3977 | } /* set_timeout */ | 3905 | } /* set_timeout */ |
3978 | 3906 | ||
3979 | static int get_timeout(struct cyclades_port *info, unsigned long __user * value) | 3907 | static int get_timeout(struct cyclades_port *info, unsigned long __user * value) |
3980 | { | 3908 | { |
3909 | struct cyclades_card *card; | ||
3981 | void __iomem *base_addr; | 3910 | void __iomem *base_addr; |
3982 | int card, channel, chip, index; | 3911 | int channel, chip, index; |
3983 | unsigned long tmp; | 3912 | unsigned long tmp; |
3984 | 3913 | ||
3985 | card = info->card; | 3914 | card = info->card; |
3986 | channel = info->line - cy_card[card].first_line; | 3915 | channel = info->line - card->first_line; |
3987 | if (!IS_CYC_Z(cy_card[card])) { | 3916 | if (!IS_CYC_Z(*card)) { |
3988 | chip = channel >> 2; | 3917 | chip = channel >> 2; |
3989 | channel &= 0x03; | 3918 | channel &= 0x03; |
3990 | index = cy_card[card].bus_index; | 3919 | index = card->bus_index; |
3991 | base_addr = | 3920 | base_addr = card->base_addr + (cy_chip_offset[chip] << index); |
3992 | cy_card[card].base_addr + (cy_chip_offset[chip] << index); | ||
3993 | 3921 | ||
3994 | tmp = cy_readb(base_addr + (CyRTPR << index)); | 3922 | tmp = readb(base_addr + (CyRTPR << index)); |
3995 | return put_user(tmp, value); | 3923 | return put_user(tmp, value); |
3996 | } else { | ||
3997 | /* Nothing to do! */ | ||
3998 | return 0; | ||
3999 | } | 3924 | } |
3925 | return 0; | ||
4000 | } /* get_timeout */ | 3926 | } /* get_timeout */ |
4001 | 3927 | ||
4002 | static int set_default_timeout(struct cyclades_port *info, unsigned long value) | 3928 | static int set_default_timeout(struct cyclades_port *info, unsigned long value) |
@@ -4020,7 +3946,7 @@ static int | |||
4020 | cy_ioctl(struct tty_struct *tty, struct file *file, | 3946 | cy_ioctl(struct tty_struct *tty, struct file *file, |
4021 | unsigned int cmd, unsigned long arg) | 3947 | unsigned int cmd, unsigned long arg) |
4022 | { | 3948 | { |
4023 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 3949 | struct cyclades_port *info = tty->driver_data; |
4024 | struct cyclades_icount cprev, cnow; /* kernel counter temps */ | 3950 | struct cyclades_icount cprev, cnow; /* kernel counter temps */ |
4025 | struct serial_icounter_struct __user *p_cuser; /* user space */ | 3951 | struct serial_icounter_struct __user *p_cuser; /* user space */ |
4026 | int ret_val = 0; | 3952 | int ret_val = 0; |
@@ -4031,7 +3957,8 @@ cy_ioctl(struct tty_struct *tty, struct file *file, | |||
4031 | return -ENODEV; | 3957 | return -ENODEV; |
4032 | 3958 | ||
4033 | #ifdef CY_DEBUG_OTHER | 3959 | #ifdef CY_DEBUG_OTHER |
4034 | printk("cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n", info->line, cmd, arg); /* */ | 3960 | printk(KERN_DEBUG "cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n", |
3961 | info->line, cmd, arg); | ||
4035 | #endif | 3962 | #endif |
4036 | 3963 | ||
4037 | switch (cmd) { | 3964 | switch (cmd) { |
@@ -4076,14 +4003,6 @@ cy_ioctl(struct tty_struct *tty, struct file *file, | |||
4076 | case CYGETRTSDTR_INV: | 4003 | case CYGETRTSDTR_INV: |
4077 | ret_val = info->rtsdtr_inv; | 4004 | ret_val = info->rtsdtr_inv; |
4078 | break; | 4005 | break; |
4079 | case CYGETCARDINFO: | ||
4080 | if (copy_to_user(argp, &cy_card[info->card], | ||
4081 | sizeof(struct cyclades_card))) { | ||
4082 | ret_val = -EFAULT; | ||
4083 | break; | ||
4084 | } | ||
4085 | ret_val = 0; | ||
4086 | break; | ||
4087 | case CYGETCD1400VER: | 4006 | case CYGETCD1400VER: |
4088 | ret_val = info->chip_rev; | 4007 | ret_val = info->chip_rev; |
4089 | break; | 4008 | break; |
@@ -4119,34 +4038,22 @@ cy_ioctl(struct tty_struct *tty, struct file *file, | |||
4119 | * Caller should use TIOCGICOUNT to see which one it was | 4038 | * Caller should use TIOCGICOUNT to see which one it was |
4120 | */ | 4039 | */ |
4121 | case TIOCMIWAIT: | 4040 | case TIOCMIWAIT: |
4122 | CY_LOCK(info, flags); | 4041 | spin_lock_irqsave(&info->card->card_lock, flags); |
4123 | /* note the counters on entry */ | 4042 | /* note the counters on entry */ |
4124 | cprev = info->icount; | 4043 | cnow = info->icount; |
4125 | CY_UNLOCK(info, flags); | 4044 | spin_unlock_irqrestore(&info->card->card_lock, flags); |
4126 | while (1) { | 4045 | ret_val = wait_event_interruptible(info->delta_msr_wait, ({ |
4127 | interruptible_sleep_on(&info->delta_msr_wait); | 4046 | cprev = cnow; |
4128 | /* see if a signal did it */ | 4047 | spin_lock_irqsave(&info->card->card_lock, flags); |
4129 | if (signal_pending(current)) { | ||
4130 | return -ERESTARTSYS; | ||
4131 | } | ||
4132 | |||
4133 | CY_LOCK(info, flags); | ||
4134 | cnow = info->icount; /* atomic copy */ | 4048 | cnow = info->icount; /* atomic copy */ |
4135 | CY_UNLOCK(info, flags); | 4049 | spin_unlock_irqrestore(&info->card->card_lock, flags); |
4136 | 4050 | ||
4137 | if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && | 4051 | ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || |
4138 | cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) { | 4052 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || |
4139 | return -EIO; /* no change => error */ | 4053 | ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || |
4140 | } | 4054 | ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)); |
4141 | if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || | 4055 | })); |
4142 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || | 4056 | break; |
4143 | ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || | ||
4144 | ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { | ||
4145 | return 0; | ||
4146 | } | ||
4147 | cprev = cnow; | ||
4148 | } | ||
4149 | /* NOTREACHED */ | ||
4150 | 4057 | ||
4151 | /* | 4058 | /* |
4152 | * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) | 4059 | * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) |
@@ -4155,9 +4062,9 @@ cy_ioctl(struct tty_struct *tty, struct file *file, | |||
4155 | * RI where only 0->1 is counted. | 4062 | * RI where only 0->1 is counted. |
4156 | */ | 4063 | */ |
4157 | case TIOCGICOUNT: | 4064 | case TIOCGICOUNT: |
4158 | CY_LOCK(info, flags); | 4065 | spin_lock_irqsave(&info->card->card_lock, flags); |
4159 | cnow = info->icount; | 4066 | cnow = info->icount; |
4160 | CY_UNLOCK(info, flags); | 4067 | spin_unlock_irqrestore(&info->card->card_lock, flags); |
4161 | p_cuser = argp; | 4068 | p_cuser = argp; |
4162 | ret_val = put_user(cnow.cts, &p_cuser->cts); | 4069 | ret_val = put_user(cnow.cts, &p_cuser->cts); |
4163 | if (ret_val) | 4070 | if (ret_val) |
@@ -4199,7 +4106,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file, | |||
4199 | } | 4106 | } |
4200 | 4107 | ||
4201 | #ifdef CY_DEBUG_OTHER | 4108 | #ifdef CY_DEBUG_OTHER |
4202 | printk(" cyc:cy_ioctl done\n"); | 4109 | printk(KERN_DEBUG "cyc:cy_ioctl done\n"); |
4203 | #endif | 4110 | #endif |
4204 | 4111 | ||
4205 | return ret_val; | 4112 | return ret_val; |
@@ -4213,10 +4120,10 @@ cy_ioctl(struct tty_struct *tty, struct file *file, | |||
4213 | */ | 4120 | */ |
4214 | static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) | 4121 | static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) |
4215 | { | 4122 | { |
4216 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 4123 | struct cyclades_port *info = tty->driver_data; |
4217 | 4124 | ||
4218 | #ifdef CY_DEBUG_OTHER | 4125 | #ifdef CY_DEBUG_OTHER |
4219 | printk("cyc:cy_set_termios ttyC%d\n", info->line); | 4126 | printk(KERN_DEBUG "cyc:cy_set_termios ttyC%d\n", info->line); |
4220 | #endif | 4127 | #endif |
4221 | 4128 | ||
4222 | if (tty->termios->c_cflag == old_termios->c_cflag && | 4129 | if (tty->termios->c_cflag == old_termios->c_cflag && |
@@ -4248,8 +4155,9 @@ static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) | |||
4248 | */ | 4155 | */ |
4249 | static void cy_send_xchar(struct tty_struct *tty, char ch) | 4156 | static void cy_send_xchar(struct tty_struct *tty, char ch) |
4250 | { | 4157 | { |
4251 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 4158 | struct cyclades_port *info = tty->driver_data; |
4252 | int card, channel; | 4159 | struct cyclades_card *card; |
4160 | int channel; | ||
4253 | 4161 | ||
4254 | if (serial_paranoia_check(info, tty->name, "cy_send_xchar")) | 4162 | if (serial_paranoia_check(info, tty->name, "cy_send_xchar")) |
4255 | return; | 4163 | return; |
@@ -4260,15 +4168,13 @@ static void cy_send_xchar(struct tty_struct *tty, char ch) | |||
4260 | cy_start(tty); | 4168 | cy_start(tty); |
4261 | 4169 | ||
4262 | card = info->card; | 4170 | card = info->card; |
4263 | channel = info->line - cy_card[card].first_line; | 4171 | channel = info->line - card->first_line; |
4264 | 4172 | ||
4265 | if (IS_CYC_Z(cy_card[card])) { | 4173 | if (IS_CYC_Z(*card)) { |
4266 | if (ch == STOP_CHAR(tty)) | 4174 | if (ch == STOP_CHAR(tty)) |
4267 | cyz_issue_cmd(&cy_card[card], channel, C_CM_SENDXOFF, | 4175 | cyz_issue_cmd(card, channel, C_CM_SENDXOFF, 0L); |
4268 | 0L); | ||
4269 | else if (ch == START_CHAR(tty)) | 4176 | else if (ch == START_CHAR(tty)) |
4270 | cyz_issue_cmd(&cy_card[card], channel, C_CM_SENDXON, | 4177 | cyz_issue_cmd(card, channel, C_CM_SENDXON, 0L); |
4271 | 0L); | ||
4272 | } | 4178 | } |
4273 | } | 4179 | } |
4274 | 4180 | ||
@@ -4278,15 +4184,16 @@ static void cy_send_xchar(struct tty_struct *tty, char ch) | |||
4278 | */ | 4184 | */ |
4279 | static void cy_throttle(struct tty_struct *tty) | 4185 | static void cy_throttle(struct tty_struct *tty) |
4280 | { | 4186 | { |
4281 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 4187 | struct cyclades_port *info = tty->driver_data; |
4188 | struct cyclades_card *card; | ||
4282 | unsigned long flags; | 4189 | unsigned long flags; |
4283 | void __iomem *base_addr; | 4190 | void __iomem *base_addr; |
4284 | int card, chip, channel, index; | 4191 | int chip, channel, index; |
4285 | 4192 | ||
4286 | #ifdef CY_DEBUG_THROTTLE | 4193 | #ifdef CY_DEBUG_THROTTLE |
4287 | char buf[64]; | 4194 | char buf[64]; |
4288 | 4195 | ||
4289 | printk("cyc:throttle %s: %d....ttyC%d\n", tty_name(tty, buf), | 4196 | printk(KERN_DEBUG "cyc:throttle %s: %ld...ttyC%d\n", tty_name(tty, buf), |
4290 | tty->ldisc.chars_in_buffer(tty), info->line); | 4197 | tty->ldisc.chars_in_buffer(tty), info->line); |
4291 | #endif | 4198 | #endif |
4292 | 4199 | ||
@@ -4297,22 +4204,22 @@ static void cy_throttle(struct tty_struct *tty) | |||
4297 | card = info->card; | 4204 | card = info->card; |
4298 | 4205 | ||
4299 | if (I_IXOFF(tty)) { | 4206 | if (I_IXOFF(tty)) { |
4300 | if (!IS_CYC_Z(cy_card[card])) | 4207 | if (!IS_CYC_Z(*card)) |
4301 | cy_send_xchar(tty, STOP_CHAR(tty)); | 4208 | cy_send_xchar(tty, STOP_CHAR(tty)); |
4302 | else | 4209 | else |
4303 | info->throttle = 1; | 4210 | info->throttle = 1; |
4304 | } | 4211 | } |
4305 | 4212 | ||
4306 | if (tty->termios->c_cflag & CRTSCTS) { | 4213 | if (tty->termios->c_cflag & CRTSCTS) { |
4307 | channel = info->line - cy_card[card].first_line; | 4214 | channel = info->line - card->first_line; |
4308 | if (!IS_CYC_Z(cy_card[card])) { | 4215 | if (!IS_CYC_Z(*card)) { |
4309 | chip = channel >> 2; | 4216 | chip = channel >> 2; |
4310 | channel &= 0x03; | 4217 | channel &= 0x03; |
4311 | index = cy_card[card].bus_index; | 4218 | index = card->bus_index; |
4312 | base_addr = cy_card[card].base_addr + | 4219 | base_addr = card->base_addr + |
4313 | (cy_chip_offset[chip] << index); | 4220 | (cy_chip_offset[chip] << index); |
4314 | 4221 | ||
4315 | CY_LOCK(info, flags); | 4222 | spin_lock_irqsave(&card->card_lock, flags); |
4316 | cy_writeb(base_addr + (CyCAR << index), | 4223 | cy_writeb(base_addr + (CyCAR << index), |
4317 | (u_char) channel); | 4224 | (u_char) channel); |
4318 | if (info->rtsdtr_inv) { | 4225 | if (info->rtsdtr_inv) { |
@@ -4322,7 +4229,7 @@ static void cy_throttle(struct tty_struct *tty) | |||
4322 | cy_writeb(base_addr + (CyMSVR1 << index), | 4229 | cy_writeb(base_addr + (CyMSVR1 << index), |
4323 | ~CyRTS); | 4230 | ~CyRTS); |
4324 | } | 4231 | } |
4325 | CY_UNLOCK(info, flags); | 4232 | spin_unlock_irqrestore(&card->card_lock, flags); |
4326 | } else { | 4233 | } else { |
4327 | info->throttle = 1; | 4234 | info->throttle = 1; |
4328 | } | 4235 | } |
@@ -4336,16 +4243,17 @@ static void cy_throttle(struct tty_struct *tty) | |||
4336 | */ | 4243 | */ |
4337 | static void cy_unthrottle(struct tty_struct *tty) | 4244 | static void cy_unthrottle(struct tty_struct *tty) |
4338 | { | 4245 | { |
4339 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 4246 | struct cyclades_port *info = tty->driver_data; |
4247 | struct cyclades_card *card; | ||
4340 | unsigned long flags; | 4248 | unsigned long flags; |
4341 | void __iomem *base_addr; | 4249 | void __iomem *base_addr; |
4342 | int card, chip, channel, index; | 4250 | int chip, channel, index; |
4343 | 4251 | ||
4344 | #ifdef CY_DEBUG_THROTTLE | 4252 | #ifdef CY_DEBUG_THROTTLE |
4345 | char buf[64]; | 4253 | char buf[64]; |
4346 | 4254 | ||
4347 | printk("cyc:unthrottle %s: %d....ttyC%d\n", tty_name(tty, buf), | 4255 | printk(KERN_DEBUG "cyc:unthrottle %s: %ld...ttyC%d\n", |
4348 | tty->ldisc.chars_in_buffer(tty), info->line); | 4256 | tty_name(tty, buf), tty->ldisc.chars_in_buffer(tty),info->line); |
4349 | #endif | 4257 | #endif |
4350 | 4258 | ||
4351 | if (serial_paranoia_check(info, tty->name, "cy_unthrottle")) { | 4259 | if (serial_paranoia_check(info, tty->name, "cy_unthrottle")) { |
@@ -4361,15 +4269,15 @@ static void cy_unthrottle(struct tty_struct *tty) | |||
4361 | 4269 | ||
4362 | if (tty->termios->c_cflag & CRTSCTS) { | 4270 | if (tty->termios->c_cflag & CRTSCTS) { |
4363 | card = info->card; | 4271 | card = info->card; |
4364 | channel = info->line - cy_card[card].first_line; | 4272 | channel = info->line - card->first_line; |
4365 | if (!IS_CYC_Z(cy_card[card])) { | 4273 | if (!IS_CYC_Z(*card)) { |
4366 | chip = channel >> 2; | 4274 | chip = channel >> 2; |
4367 | channel &= 0x03; | 4275 | channel &= 0x03; |
4368 | index = cy_card[card].bus_index; | 4276 | index = card->bus_index; |
4369 | base_addr = cy_card[card].base_addr + | 4277 | base_addr = card->base_addr + |
4370 | (cy_chip_offset[chip] << index); | 4278 | (cy_chip_offset[chip] << index); |
4371 | 4279 | ||
4372 | CY_LOCK(info, flags); | 4280 | spin_lock_irqsave(&card->card_lock, flags); |
4373 | cy_writeb(base_addr + (CyCAR << index), | 4281 | cy_writeb(base_addr + (CyCAR << index), |
4374 | (u_char) channel); | 4282 | (u_char) channel); |
4375 | if (info->rtsdtr_inv) { | 4283 | if (info->rtsdtr_inv) { |
@@ -4379,7 +4287,7 @@ static void cy_unthrottle(struct tty_struct *tty) | |||
4379 | cy_writeb(base_addr + (CyMSVR1 << index), | 4287 | cy_writeb(base_addr + (CyMSVR1 << index), |
4380 | CyRTS); | 4288 | CyRTS); |
4381 | } | 4289 | } |
4382 | CY_UNLOCK(info, flags); | 4290 | spin_unlock_irqrestore(&card->card_lock, flags); |
4383 | } else { | 4291 | } else { |
4384 | info->throttle = 0; | 4292 | info->throttle = 0; |
4385 | } | 4293 | } |
@@ -4392,102 +4300,96 @@ static void cy_unthrottle(struct tty_struct *tty) | |||
4392 | static void cy_stop(struct tty_struct *tty) | 4300 | static void cy_stop(struct tty_struct *tty) |
4393 | { | 4301 | { |
4394 | struct cyclades_card *cinfo; | 4302 | struct cyclades_card *cinfo; |
4395 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 4303 | struct cyclades_port *info = tty->driver_data; |
4396 | void __iomem *base_addr; | 4304 | void __iomem *base_addr; |
4397 | int chip, channel, index; | 4305 | int chip, channel, index; |
4398 | unsigned long flags; | 4306 | unsigned long flags; |
4399 | 4307 | ||
4400 | #ifdef CY_DEBUG_OTHER | 4308 | #ifdef CY_DEBUG_OTHER |
4401 | printk("cyc:cy_stop ttyC%d\n", info->line); /* */ | 4309 | printk(KERN_DEBUG "cyc:cy_stop ttyC%d\n", info->line); |
4402 | #endif | 4310 | #endif |
4403 | 4311 | ||
4404 | if (serial_paranoia_check(info, tty->name, "cy_stop")) | 4312 | if (serial_paranoia_check(info, tty->name, "cy_stop")) |
4405 | return; | 4313 | return; |
4406 | 4314 | ||
4407 | cinfo = &cy_card[info->card]; | 4315 | cinfo = info->card; |
4408 | channel = info->line - cinfo->first_line; | 4316 | channel = info->line - cinfo->first_line; |
4409 | if (!IS_CYC_Z(*cinfo)) { | 4317 | if (!IS_CYC_Z(*cinfo)) { |
4410 | index = cinfo->bus_index; | 4318 | index = cinfo->bus_index; |
4411 | chip = channel >> 2; | 4319 | chip = channel >> 2; |
4412 | channel &= 0x03; | 4320 | channel &= 0x03; |
4413 | base_addr = cy_card[info->card].base_addr + | 4321 | base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index); |
4414 | (cy_chip_offset[chip] << index); | ||
4415 | 4322 | ||
4416 | CY_LOCK(info, flags); | 4323 | spin_lock_irqsave(&cinfo->card_lock, flags); |
4417 | cy_writeb(base_addr + (CyCAR << index), | 4324 | cy_writeb(base_addr + (CyCAR << index), |
4418 | (u_char)(channel & 0x0003)); /* index channel */ | 4325 | (u_char)(channel & 0x0003)); /* index channel */ |
4419 | cy_writeb(base_addr + (CySRER << index), | 4326 | cy_writeb(base_addr + (CySRER << index), |
4420 | cy_readb(base_addr + (CySRER << index)) & ~CyTxRdy); | 4327 | readb(base_addr + (CySRER << index)) & ~CyTxRdy); |
4421 | CY_UNLOCK(info, flags); | 4328 | spin_unlock_irqrestore(&cinfo->card_lock, flags); |
4422 | } else { | ||
4423 | /* Nothing to do! */ | ||
4424 | } | 4329 | } |
4425 | } /* cy_stop */ | 4330 | } /* cy_stop */ |
4426 | 4331 | ||
4427 | static void cy_start(struct tty_struct *tty) | 4332 | static void cy_start(struct tty_struct *tty) |
4428 | { | 4333 | { |
4429 | struct cyclades_card *cinfo; | 4334 | struct cyclades_card *cinfo; |
4430 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 4335 | struct cyclades_port *info = tty->driver_data; |
4431 | void __iomem *base_addr; | 4336 | void __iomem *base_addr; |
4432 | int chip, channel, index; | 4337 | int chip, channel, index; |
4433 | unsigned long flags; | 4338 | unsigned long flags; |
4434 | 4339 | ||
4435 | #ifdef CY_DEBUG_OTHER | 4340 | #ifdef CY_DEBUG_OTHER |
4436 | printk("cyc:cy_start ttyC%d\n", info->line); /* */ | 4341 | printk(KERN_DEBUG "cyc:cy_start ttyC%d\n", info->line); |
4437 | #endif | 4342 | #endif |
4438 | 4343 | ||
4439 | if (serial_paranoia_check(info, tty->name, "cy_start")) | 4344 | if (serial_paranoia_check(info, tty->name, "cy_start")) |
4440 | return; | 4345 | return; |
4441 | 4346 | ||
4442 | cinfo = &cy_card[info->card]; | 4347 | cinfo = info->card; |
4443 | channel = info->line - cinfo->first_line; | 4348 | channel = info->line - cinfo->first_line; |
4444 | index = cinfo->bus_index; | 4349 | index = cinfo->bus_index; |
4445 | if (!IS_CYC_Z(*cinfo)) { | 4350 | if (!IS_CYC_Z(*cinfo)) { |
4446 | chip = channel >> 2; | 4351 | chip = channel >> 2; |
4447 | channel &= 0x03; | 4352 | channel &= 0x03; |
4448 | base_addr = cy_card[info->card].base_addr + | 4353 | base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index); |
4449 | (cy_chip_offset[chip] << index); | ||
4450 | 4354 | ||
4451 | CY_LOCK(info, flags); | 4355 | spin_lock_irqsave(&cinfo->card_lock, flags); |
4452 | cy_writeb(base_addr + (CyCAR << index), (u_char) (channel & 0x0003)); /* index channel */ | 4356 | cy_writeb(base_addr + (CyCAR << index), (u_char) (channel & 0x0003)); /* index channel */ |
4453 | cy_writeb(base_addr + (CySRER << index), | 4357 | cy_writeb(base_addr + (CySRER << index), |
4454 | cy_readb(base_addr + (CySRER << index)) | CyTxRdy); | 4358 | readb(base_addr + (CySRER << index)) | CyTxRdy); |
4455 | CY_UNLOCK(info, flags); | 4359 | spin_unlock_irqrestore(&cinfo->card_lock, flags); |
4456 | } else { | ||
4457 | /* Nothing to do! */ | ||
4458 | } | 4360 | } |
4459 | } /* cy_start */ | 4361 | } /* cy_start */ |
4460 | 4362 | ||
4461 | static void cy_flush_buffer(struct tty_struct *tty) | 4363 | static void cy_flush_buffer(struct tty_struct *tty) |
4462 | { | 4364 | { |
4463 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 4365 | struct cyclades_port *info = tty->driver_data; |
4464 | int card, channel, retval; | 4366 | struct cyclades_card *card; |
4367 | int channel, retval; | ||
4465 | unsigned long flags; | 4368 | unsigned long flags; |
4466 | 4369 | ||
4467 | #ifdef CY_DEBUG_IO | 4370 | #ifdef CY_DEBUG_IO |
4468 | printk("cyc:cy_flush_buffer ttyC%d\n", info->line); /* */ | 4371 | printk(KERN_DEBUG "cyc:cy_flush_buffer ttyC%d\n", info->line); |
4469 | #endif | 4372 | #endif |
4470 | 4373 | ||
4471 | if (serial_paranoia_check(info, tty->name, "cy_flush_buffer")) | 4374 | if (serial_paranoia_check(info, tty->name, "cy_flush_buffer")) |
4472 | return; | 4375 | return; |
4473 | 4376 | ||
4474 | card = info->card; | 4377 | card = info->card; |
4475 | channel = (info->line) - (cy_card[card].first_line); | 4378 | channel = info->line - card->first_line; |
4476 | 4379 | ||
4477 | CY_LOCK(info, flags); | 4380 | spin_lock_irqsave(&card->card_lock, flags); |
4478 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | 4381 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; |
4479 | CY_UNLOCK(info, flags); | 4382 | spin_unlock_irqrestore(&card->card_lock, flags); |
4480 | 4383 | ||
4481 | if (IS_CYC_Z(cy_card[card])) { /* If it is a Z card, flush the on-board | 4384 | if (IS_CYC_Z(*card)) { /* If it is a Z card, flush the on-board |
4482 | buffers as well */ | 4385 | buffers as well */ |
4483 | CY_LOCK(info, flags); | 4386 | spin_lock_irqsave(&card->card_lock, flags); |
4484 | retval = | 4387 | retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L); |
4485 | cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_TX, 0L); | ||
4486 | if (retval != 0) { | 4388 | if (retval != 0) { |
4487 | printk("cyc: flush_buffer retval on ttyC%d was %x\n", | 4389 | printk(KERN_ERR "cyc: flush_buffer retval on ttyC%d " |
4488 | info->line, retval); | 4390 | "was %x\n", info->line, retval); |
4489 | } | 4391 | } |
4490 | CY_UNLOCK(info, flags); | 4392 | spin_unlock_irqrestore(&card->card_lock, flags); |
4491 | } | 4393 | } |
4492 | tty_wakeup(tty); | 4394 | tty_wakeup(tty); |
4493 | } /* cy_flush_buffer */ | 4395 | } /* cy_flush_buffer */ |
@@ -4497,10 +4399,10 @@ static void cy_flush_buffer(struct tty_struct *tty) | |||
4497 | */ | 4399 | */ |
4498 | static void cy_hangup(struct tty_struct *tty) | 4400 | static void cy_hangup(struct tty_struct *tty) |
4499 | { | 4401 | { |
4500 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 4402 | struct cyclades_port *info = tty->driver_data; |
4501 | 4403 | ||
4502 | #ifdef CY_DEBUG_OTHER | 4404 | #ifdef CY_DEBUG_OTHER |
4503 | printk("cyc:cy_hangup ttyC%d\n", info->line); /* */ | 4405 | printk(KERN_DEBUG "cyc:cy_hangup ttyC%d\n", info->line); |
4504 | #endif | 4406 | #endif |
4505 | 4407 | ||
4506 | if (serial_paranoia_check(info, tty->name, "cy_hangup")) | 4408 | if (serial_paranoia_check(info, tty->name, "cy_hangup")) |
@@ -4511,7 +4413,8 @@ static void cy_hangup(struct tty_struct *tty) | |||
4511 | info->event = 0; | 4413 | info->event = 0; |
4512 | info->count = 0; | 4414 | info->count = 0; |
4513 | #ifdef CY_DEBUG_COUNT | 4415 | #ifdef CY_DEBUG_COUNT |
4514 | printk("cyc:cy_hangup (%d): setting count to 0\n", current->pid); | 4416 | printk(KERN_DEBUG "cyc:cy_hangup (%d): setting count to 0\n", |
4417 | current->pid); | ||
4515 | #endif | 4418 | #endif |
4516 | info->tty = NULL; | 4419 | info->tty = NULL; |
4517 | info->flags &= ~ASYNC_NORMAL_ACTIVE; | 4420 | info->flags &= ~ASYNC_NORMAL_ACTIVE; |
@@ -4526,10 +4429,107 @@ static void cy_hangup(struct tty_struct *tty) | |||
4526 | * --------------------------------------------------------------------- | 4429 | * --------------------------------------------------------------------- |
4527 | */ | 4430 | */ |
4528 | 4431 | ||
4432 | static int __devinit cy_init_card(struct cyclades_card *cinfo) | ||
4433 | { | ||
4434 | struct cyclades_port *info; | ||
4435 | u32 mailbox; | ||
4436 | unsigned int nports; | ||
4437 | unsigned short chip_number; | ||
4438 | int index, port; | ||
4439 | |||
4440 | spin_lock_init(&cinfo->card_lock); | ||
4441 | |||
4442 | if (IS_CYC_Z(*cinfo)) { /* Cyclades-Z */ | ||
4443 | mailbox = readl(&((struct RUNTIME_9060 __iomem *) | ||
4444 | cinfo->ctl_addr)->mail_box_0); | ||
4445 | nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8; | ||
4446 | cinfo->intr_enabled = 0; | ||
4447 | cinfo->nports = 0; /* Will be correctly set later, after | ||
4448 | Z FW is loaded */ | ||
4449 | } else { | ||
4450 | index = cinfo->bus_index; | ||
4451 | nports = cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips; | ||
4452 | } | ||
4453 | |||
4454 | cinfo->ports = kzalloc(sizeof(*cinfo->ports) * nports, GFP_KERNEL); | ||
4455 | if (cinfo->ports == NULL) { | ||
4456 | printk(KERN_ERR "Cyclades: cannot allocate ports\n"); | ||
4457 | cinfo->nports = 0; | ||
4458 | return -ENOMEM; | ||
4459 | } | ||
4460 | |||
4461 | for (port = cinfo->first_line; port < cinfo->first_line + nports; | ||
4462 | port++) { | ||
4463 | info = &cinfo->ports[port - cinfo->first_line]; | ||
4464 | info->magic = CYCLADES_MAGIC; | ||
4465 | info->card = cinfo; | ||
4466 | info->line = port; | ||
4467 | info->flags = STD_COM_FLAGS; | ||
4468 | info->closing_wait = CLOSING_WAIT_DELAY; | ||
4469 | info->close_delay = 5 * HZ / 10; | ||
4470 | |||
4471 | INIT_WORK(&info->tqueue, do_softint); | ||
4472 | init_waitqueue_head(&info->open_wait); | ||
4473 | init_waitqueue_head(&info->close_wait); | ||
4474 | init_completion(&info->shutdown_wait); | ||
4475 | init_waitqueue_head(&info->delta_msr_wait); | ||
4476 | |||
4477 | if (IS_CYC_Z(*cinfo)) { | ||
4478 | info->type = PORT_STARTECH; | ||
4479 | if (mailbox == ZO_V1) | ||
4480 | info->xmit_fifo_size = CYZ_FIFO_SIZE; | ||
4481 | else | ||
4482 | info->xmit_fifo_size = 4 * CYZ_FIFO_SIZE; | ||
4483 | #ifdef CONFIG_CYZ_INTR | ||
4484 | setup_timer(&cyz_rx_full_timer[port], | ||
4485 | cyz_rx_restart, (unsigned long)info); | ||
4486 | #endif | ||
4487 | } else { | ||
4488 | info->type = PORT_CIRRUS; | ||
4489 | info->xmit_fifo_size = CyMAX_CHAR_FIFO; | ||
4490 | info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS; | ||
4491 | info->cor2 = CyETC; | ||
4492 | info->cor3 = 0x08; /* _very_ small rcv threshold */ | ||
4493 | |||
4494 | chip_number = (port - cinfo->first_line) / 4; | ||
4495 | if ((info->chip_rev = readb(cinfo->base_addr + | ||
4496 | (cy_chip_offset[chip_number] << | ||
4497 | index) + (CyGFRCR << index))) >= | ||
4498 | CD1400_REV_J) { | ||
4499 | /* It is a CD1400 rev. J or later */ | ||
4500 | info->tbpr = baud_bpr_60[13]; /* Tx BPR */ | ||
4501 | info->tco = baud_co_60[13]; /* Tx CO */ | ||
4502 | info->rbpr = baud_bpr_60[13]; /* Rx BPR */ | ||
4503 | info->rco = baud_co_60[13]; /* Rx CO */ | ||
4504 | info->rtsdtr_inv = 1; | ||
4505 | } else { | ||
4506 | info->tbpr = baud_bpr_25[13]; /* Tx BPR */ | ||
4507 | info->tco = baud_co_25[13]; /* Tx CO */ | ||
4508 | info->rbpr = baud_bpr_25[13]; /* Rx BPR */ | ||
4509 | info->rco = baud_co_25[13]; /* Rx CO */ | ||
4510 | info->rtsdtr_inv = 0; | ||
4511 | } | ||
4512 | info->read_status_mask = CyTIMEOUT | CySPECHAR | | ||
4513 | CyBREAK | CyPARITY | CyFRAME | CyOVERRUN; | ||
4514 | } | ||
4515 | |||
4516 | } | ||
4517 | |||
4518 | #ifndef CONFIG_CYZ_INTR | ||
4519 | if (IS_CYC_Z(*cinfo) && !timer_pending(&cyz_timerlist)) { | ||
4520 | mod_timer(&cyz_timerlist, jiffies + 1); | ||
4521 | #ifdef CY_PCI_DEBUG | ||
4522 | printk(KERN_DEBUG "Cyclades-Z polling initialized\n"); | ||
4523 | #endif | ||
4524 | } | ||
4525 | #endif | ||
4526 | return 0; | ||
4527 | } | ||
4528 | |||
4529 | /* initialize chips on Cyclom-Y card -- return number of valid | 4529 | /* initialize chips on Cyclom-Y card -- return number of valid |
4530 | chips (which is number of ports/4) */ | 4530 | chips (which is number of ports/4) */ |
4531 | static unsigned short __init | 4531 | static unsigned short __devinit cyy_init_card(void __iomem *true_base_addr, |
4532 | cyy_init_card(void __iomem * true_base_addr, int index) | 4532 | int index) |
4533 | { | 4533 | { |
4534 | unsigned int chip_number; | 4534 | unsigned int chip_number; |
4535 | void __iomem *base_addr; | 4535 | void __iomem *base_addr; |
@@ -4544,7 +4544,7 @@ cyy_init_card(void __iomem * true_base_addr, int index) | |||
4544 | base_addr = | 4544 | base_addr = |
4545 | true_base_addr + (cy_chip_offset[chip_number] << index); | 4545 | true_base_addr + (cy_chip_offset[chip_number] << index); |
4546 | mdelay(1); | 4546 | mdelay(1); |
4547 | if (cy_readb(base_addr + (CyCCR << index)) != 0x00) { | 4547 | if (readb(base_addr + (CyCCR << index)) != 0x00) { |
4548 | /************* | 4548 | /************* |
4549 | printk(" chip #%d at %#6lx is never idle (CCR != 0)\n", | 4549 | printk(" chip #%d at %#6lx is never idle (CCR != 0)\n", |
4550 | chip_number, (unsigned long)base_addr); | 4550 | chip_number, (unsigned long)base_addr); |
@@ -4561,7 +4561,7 @@ cyy_init_card(void __iomem * true_base_addr, int index) | |||
4561 | chip 4 GFRCR register appears at chip 0, there is no chip 4 | 4561 | chip 4 GFRCR register appears at chip 0, there is no chip 4 |
4562 | and this must be a Cyclom-16Y, not a Cyclom-32Ye. | 4562 | and this must be a Cyclom-16Y, not a Cyclom-32Ye. |
4563 | */ | 4563 | */ |
4564 | if (chip_number == 4 && cy_readb(true_base_addr + | 4564 | if (chip_number == 4 && readb(true_base_addr + |
4565 | (cy_chip_offset[0] << index) + | 4565 | (cy_chip_offset[0] << index) + |
4566 | (CyGFRCR << index)) == 0) { | 4566 | (CyGFRCR << index)) == 0) { |
4567 | return chip_number; | 4567 | return chip_number; |
@@ -4570,7 +4570,7 @@ cyy_init_card(void __iomem * true_base_addr, int index) | |||
4570 | cy_writeb(base_addr + (CyCCR << index), CyCHIP_RESET); | 4570 | cy_writeb(base_addr + (CyCCR << index), CyCHIP_RESET); |
4571 | mdelay(1); | 4571 | mdelay(1); |
4572 | 4572 | ||
4573 | if (cy_readb(base_addr + (CyGFRCR << index)) == 0x00) { | 4573 | if (readb(base_addr + (CyGFRCR << index)) == 0x00) { |
4574 | /* | 4574 | /* |
4575 | printk(" chip #%d at %#6lx is not responding ", | 4575 | printk(" chip #%d at %#6lx is not responding ", |
4576 | chip_number, (unsigned long)base_addr); | 4576 | chip_number, (unsigned long)base_addr); |
@@ -4578,7 +4578,7 @@ cyy_init_card(void __iomem * true_base_addr, int index) | |||
4578 | */ | 4578 | */ |
4579 | return chip_number; | 4579 | return chip_number; |
4580 | } | 4580 | } |
4581 | if ((0xf0 & (cy_readb(base_addr + (CyGFRCR << index)))) != | 4581 | if ((0xf0 & (readb(base_addr + (CyGFRCR << index)))) != |
4582 | 0x40) { | 4582 | 0x40) { |
4583 | /* | 4583 | /* |
4584 | printk(" chip #%d at %#6lx is not valid (GFRCR == " | 4584 | printk(" chip #%d at %#6lx is not valid (GFRCR == " |
@@ -4589,7 +4589,7 @@ cyy_init_card(void __iomem * true_base_addr, int index) | |||
4589 | return chip_number; | 4589 | return chip_number; |
4590 | } | 4590 | } |
4591 | cy_writeb(base_addr + (CyGCR << index), CyCH0_SERIAL); | 4591 | cy_writeb(base_addr + (CyGCR << index), CyCH0_SERIAL); |
4592 | if (cy_readb(base_addr + (CyGFRCR << index)) >= CD1400_REV_J) { | 4592 | if (readb(base_addr + (CyGFRCR << index)) >= CD1400_REV_J) { |
4593 | /* It is a CD1400 rev. J or later */ | 4593 | /* It is a CD1400 rev. J or later */ |
4594 | /* Impossible to reach 5ms with this chip. | 4594 | /* Impossible to reach 5ms with this chip. |
4595 | Changed to 2ms instead (f = 500 Hz). */ | 4595 | Changed to 2ms instead (f = 500 Hz). */ |
@@ -4602,7 +4602,7 @@ cyy_init_card(void __iomem * true_base_addr, int index) | |||
4602 | /* | 4602 | /* |
4603 | printk(" chip #%d at %#6lx is rev 0x%2x\n", | 4603 | printk(" chip #%d at %#6lx is rev 0x%2x\n", |
4604 | chip_number, (unsigned long)base_addr, | 4604 | chip_number, (unsigned long)base_addr, |
4605 | cy_readb(base_addr+(CyGFRCR<<index))); | 4605 | readb(base_addr+(CyGFRCR<<index))); |
4606 | */ | 4606 | */ |
4607 | } | 4607 | } |
4608 | return chip_number; | 4608 | return chip_number; |
@@ -4647,9 +4647,15 @@ static int __init cy_detect_isa(void) | |||
4647 | 4647 | ||
4648 | /* probe for CD1400... */ | 4648 | /* probe for CD1400... */ |
4649 | cy_isa_address = ioremap(isa_address, CyISA_Ywin); | 4649 | cy_isa_address = ioremap(isa_address, CyISA_Ywin); |
4650 | if (cy_isa_address == NULL) { | ||
4651 | printk(KERN_ERR "Cyclom-Y/ISA: can't remap base " | ||
4652 | "address\n"); | ||
4653 | continue; | ||
4654 | } | ||
4650 | cy_isa_nchan = CyPORTS_PER_CHIP * | 4655 | cy_isa_nchan = CyPORTS_PER_CHIP * |
4651 | cyy_init_card(cy_isa_address, 0); | 4656 | cyy_init_card(cy_isa_address, 0); |
4652 | if (cy_isa_nchan == 0) { | 4657 | if (cy_isa_nchan == 0) { |
4658 | iounmap(cy_isa_address); | ||
4653 | continue; | 4659 | continue; |
4654 | } | 4660 | } |
4655 | #ifdef MODULE | 4661 | #ifdef MODULE |
@@ -4660,40 +4666,42 @@ static int __init cy_detect_isa(void) | |||
4660 | /* find out the board's irq by probing */ | 4666 | /* find out the board's irq by probing */ |
4661 | cy_isa_irq = detect_isa_irq(cy_isa_address); | 4667 | cy_isa_irq = detect_isa_irq(cy_isa_address); |
4662 | if (cy_isa_irq == 0) { | 4668 | if (cy_isa_irq == 0) { |
4663 | printk("Cyclom-Y/ISA found at 0x%lx ", | 4669 | printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but the " |
4670 | "IRQ could not be detected.\n", | ||
4664 | (unsigned long)cy_isa_address); | 4671 | (unsigned long)cy_isa_address); |
4665 | printk("but the IRQ could not be detected.\n"); | 4672 | iounmap(cy_isa_address); |
4666 | continue; | 4673 | continue; |
4667 | } | 4674 | } |
4668 | 4675 | ||
4669 | if ((cy_next_channel + cy_isa_nchan) > NR_PORTS) { | 4676 | if ((cy_next_channel + cy_isa_nchan) > NR_PORTS) { |
4670 | printk("Cyclom-Y/ISA found at 0x%lx ", | 4677 | printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but no " |
4678 | "more channels are available. Change NR_PORTS " | ||
4679 | "in cyclades.c and recompile kernel.\n", | ||
4671 | (unsigned long)cy_isa_address); | 4680 | (unsigned long)cy_isa_address); |
4672 | printk("but no more channels are available.\n"); | 4681 | iounmap(cy_isa_address); |
4673 | printk("Change NR_PORTS in cyclades.c and recompile " | ||
4674 | "kernel.\n"); | ||
4675 | return nboard; | 4682 | return nboard; |
4676 | } | 4683 | } |
4677 | /* fill the next cy_card structure available */ | 4684 | /* fill the next cy_card structure available */ |
4678 | for (j = 0; j < NR_CARDS; j++) { | 4685 | for (j = 0; j < NR_CARDS; j++) { |
4679 | if (cy_card[j].base_addr == 0) | 4686 | if (cy_card[j].base_addr == NULL) |
4680 | break; | 4687 | break; |
4681 | } | 4688 | } |
4682 | if (j == NR_CARDS) { /* no more cy_cards available */ | 4689 | if (j == NR_CARDS) { /* no more cy_cards available */ |
4683 | printk("Cyclom-Y/ISA found at 0x%lx ", | 4690 | printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but no " |
4691 | "more cards can be used. Change NR_CARDS in " | ||
4692 | "cyclades.c and recompile kernel.\n", | ||
4684 | (unsigned long)cy_isa_address); | 4693 | (unsigned long)cy_isa_address); |
4685 | printk("but no more cards can be used .\n"); | 4694 | iounmap(cy_isa_address); |
4686 | printk("Change NR_CARDS in cyclades.c and recompile " | ||
4687 | "kernel.\n"); | ||
4688 | return nboard; | 4695 | return nboard; |
4689 | } | 4696 | } |
4690 | 4697 | ||
4691 | /* allocate IRQ */ | 4698 | /* allocate IRQ */ |
4692 | if (request_irq(cy_isa_irq, cyy_interrupt, | 4699 | if (request_irq(cy_isa_irq, cyy_interrupt, |
4693 | IRQF_DISABLED, "Cyclom-Y", &cy_card[j])) { | 4700 | IRQF_DISABLED, "Cyclom-Y", &cy_card[j])) { |
4694 | printk("Cyclom-Y/ISA found at 0x%lx ", | 4701 | printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but " |
4695 | (unsigned long)cy_isa_address); | 4702 | "could not allocate IRQ#%d.\n", |
4696 | printk("but could not allocate IRQ#%d.\n", cy_isa_irq); | 4703 | (unsigned long)cy_isa_address, cy_isa_irq); |
4704 | iounmap(cy_isa_address); | ||
4697 | return nboard; | 4705 | return nboard; |
4698 | } | 4706 | } |
4699 | 4707 | ||
@@ -4704,15 +4712,23 @@ static int __init cy_detect_isa(void) | |||
4704 | cy_card[j].bus_index = 0; | 4712 | cy_card[j].bus_index = 0; |
4705 | cy_card[j].first_line = cy_next_channel; | 4713 | cy_card[j].first_line = cy_next_channel; |
4706 | cy_card[j].num_chips = cy_isa_nchan / 4; | 4714 | cy_card[j].num_chips = cy_isa_nchan / 4; |
4715 | if (cy_init_card(&cy_card[j])) { | ||
4716 | cy_card[j].base_addr = NULL; | ||
4717 | free_irq(cy_isa_irq, &cy_card[j]); | ||
4718 | iounmap(cy_isa_address); | ||
4719 | continue; | ||
4720 | } | ||
4707 | nboard++; | 4721 | nboard++; |
4708 | 4722 | ||
4709 | /* print message */ | 4723 | printk(KERN_INFO "Cyclom-Y/ISA #%d: 0x%lx-0x%lx, IRQ%d found: " |
4710 | printk("Cyclom-Y/ISA #%d: 0x%lx-0x%lx, IRQ%d, ", | 4724 | "%d channels starting from port %d\n", |
4711 | j + 1, (unsigned long)cy_isa_address, | 4725 | j + 1, (unsigned long)cy_isa_address, |
4712 | (unsigned long)(cy_isa_address + (CyISA_Ywin - 1)), | 4726 | (unsigned long)(cy_isa_address + (CyISA_Ywin - 1)), |
4713 | cy_isa_irq); | 4727 | cy_isa_irq, cy_isa_nchan, cy_next_channel); |
4714 | printk("%d channels starting from port %d.\n", | 4728 | |
4715 | cy_isa_nchan, cy_next_channel); | 4729 | for (j = cy_next_channel; |
4730 | j < cy_next_channel + cy_isa_nchan; j++) | ||
4731 | tty_register_device(cy_serial_driver, j, NULL); | ||
4716 | cy_next_channel += cy_isa_nchan; | 4732 | cy_next_channel += cy_isa_nchan; |
4717 | } | 4733 | } |
4718 | return nboard; | 4734 | return nboard; |
@@ -4721,510 +4737,310 @@ static int __init cy_detect_isa(void) | |||
4721 | #endif /* CONFIG_ISA */ | 4737 | #endif /* CONFIG_ISA */ |
4722 | } /* cy_detect_isa */ | 4738 | } /* cy_detect_isa */ |
4723 | 4739 | ||
4724 | static void plx_init(void __iomem * addr, uclong initctl) | 4740 | #ifdef CONFIG_PCI |
4741 | static void __devinit plx_init(void __iomem * addr, __u32 initctl) | ||
4725 | { | 4742 | { |
4726 | /* Reset PLX */ | 4743 | /* Reset PLX */ |
4727 | cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x40000000); | 4744 | cy_writel(addr + initctl, readl(addr + initctl) | 0x40000000); |
4728 | udelay(100L); | 4745 | udelay(100L); |
4729 | cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x40000000); | 4746 | cy_writel(addr + initctl, readl(addr + initctl) & ~0x40000000); |
4730 | 4747 | ||
4731 | /* Reload Config. Registers from EEPROM */ | 4748 | /* Reload Config. Registers from EEPROM */ |
4732 | cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x20000000); | 4749 | cy_writel(addr + initctl, readl(addr + initctl) | 0x20000000); |
4733 | udelay(100L); | 4750 | udelay(100L); |
4734 | cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x20000000); | 4751 | cy_writel(addr + initctl, readl(addr + initctl) & ~0x20000000); |
4735 | } | 4752 | } |
4736 | 4753 | ||
4737 | /* | 4754 | static int __devinit cy_pci_probe(struct pci_dev *pdev, |
4738 | * --------------------------------------------------------------------- | 4755 | const struct pci_device_id *ent) |
4739 | * cy_detect_pci() - Test PCI bus presence and Cyclom-Ye/PCI. | ||
4740 | * sets global variables and return the number of PCI boards found. | ||
4741 | * --------------------------------------------------------------------- | ||
4742 | */ | ||
4743 | static int __init cy_detect_pci(void) | ||
4744 | { | 4756 | { |
4745 | #ifdef CONFIG_PCI | 4757 | void __iomem *addr0 = NULL, *addr2 = NULL; |
4746 | 4758 | char *card_name = NULL; | |
4747 | struct pci_dev *pdev = NULL; | 4759 | u32 mailbox; |
4748 | unsigned char cyy_rev_id; | 4760 | unsigned int device_id, nchan = 0, card_no, i; |
4749 | unsigned char cy_pci_irq = 0; | 4761 | unsigned char plx_ver; |
4750 | uclong cy_pci_phys0, cy_pci_phys2; | 4762 | int retval, irq; |
4751 | void __iomem *cy_pci_addr0, *cy_pci_addr2; | 4763 | |
4752 | unsigned short i, j, cy_pci_nchan, plx_ver; | 4764 | retval = pci_enable_device(pdev); |
4753 | unsigned short device_id, dev_index = 0; | 4765 | if (retval) { |
4754 | uclong mailbox; | 4766 | dev_err(&pdev->dev, "cannot enable device\n"); |
4755 | uclong ZeIndex = 0; | 4767 | goto err; |
4756 | void __iomem *Ze_addr0[NR_CARDS], *Ze_addr2[NR_CARDS]; | 4768 | } |
4757 | uclong Ze_phys0[NR_CARDS], Ze_phys2[NR_CARDS]; | ||
4758 | unsigned char Ze_irq[NR_CARDS]; | ||
4759 | struct pci_dev *Ze_pdev[NR_CARDS]; | ||
4760 | |||
4761 | for (i = 0; i < NR_CARDS; i++) { | ||
4762 | /* look for a Cyclades card by vendor and device id */ | ||
4763 | while ((device_id = cy_pci_dev_id[dev_index].device) != 0) { | ||
4764 | if ((pdev = pci_get_device(PCI_VENDOR_ID_CYCLADES, | ||
4765 | device_id, pdev)) == NULL) { | ||
4766 | dev_index++; /* try next device id */ | ||
4767 | } else { | ||
4768 | break; /* found a board */ | ||
4769 | } | ||
4770 | } | ||
4771 | |||
4772 | if (device_id == 0) | ||
4773 | break; | ||
4774 | |||
4775 | if (pci_enable_device(pdev)) | ||
4776 | continue; | ||
4777 | |||
4778 | /* read PCI configuration area */ | ||
4779 | cy_pci_irq = pdev->irq; | ||
4780 | cy_pci_phys0 = pci_resource_start(pdev, 0); | ||
4781 | cy_pci_phys2 = pci_resource_start(pdev, 2); | ||
4782 | pci_read_config_byte(pdev, PCI_REVISION_ID, &cyy_rev_id); | ||
4783 | 4769 | ||
4784 | device_id &= ~PCI_DEVICE_ID_MASK; | 4770 | /* read PCI configuration area */ |
4771 | irq = pdev->irq; | ||
4772 | device_id = pdev->device & ~PCI_DEVICE_ID_MASK; | ||
4785 | 4773 | ||
4786 | if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo || | 4774 | #if defined(__alpha__) |
4787 | device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { | 4775 | if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */ |
4788 | #ifdef CY_PCI_DEBUG | 4776 | dev_err(&pdev->dev, "Cyclom-Y/PCI not supported for low " |
4789 | printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ", | 4777 | "addresses on Alpha systems.\n"); |
4790 | pdev->bus->number, pdev->devfn); | 4778 | retval = -EIO; |
4791 | printk("rev_id=%d) IRQ%d\n", | 4779 | goto err_dis; |
4792 | cyy_rev_id, (int)cy_pci_irq); | 4780 | } |
4793 | printk("Cyclom-Y/PCI:found winaddr=0x%lx " | ||
4794 | "ctladdr=0x%lx\n", | ||
4795 | (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); | ||
4796 | #endif | 4781 | #endif |
4782 | if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo) { | ||
4783 | dev_err(&pdev->dev, "Cyclades-Z/PCI not supported for low " | ||
4784 | "addresses\n"); | ||
4785 | retval = -EIO; | ||
4786 | goto err_dis; | ||
4787 | } | ||
4797 | 4788 | ||
4798 | if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { | 4789 | if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { |
4799 | printk(" Warning: PCI I/O bit incorrectly " | 4790 | dev_warn(&pdev->dev, "PCI I/O bit incorrectly set. Ignoring " |
4800 | "set. Ignoring it...\n"); | 4791 | "it...\n"); |
4801 | pdev->resource[2].flags &= ~IORESOURCE_IO; | 4792 | pdev->resource[2].flags &= ~IORESOURCE_IO; |
4802 | } | 4793 | } |
4803 | 4794 | ||
4804 | /* Although we don't use this I/O region, we should | 4795 | retval = pci_request_regions(pdev, "cyclades"); |
4805 | request it from the kernel anyway, to avoid problems | 4796 | if (retval) { |
4806 | with other drivers accessing it. */ | 4797 | dev_err(&pdev->dev, "failed to reserve resources\n"); |
4807 | if (pci_request_regions(pdev, "Cyclom-Y") != 0) { | 4798 | goto err_dis; |
4808 | printk(KERN_ERR "cyclades: failed to reserve " | 4799 | } |
4809 | "PCI resources\n"); | ||
4810 | continue; | ||
4811 | } | ||
4812 | #if defined(__alpha__) | ||
4813 | if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */ | ||
4814 | printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ", | ||
4815 | pdev->bus->number, pdev->devfn); | ||
4816 | printk("rev_id=%d) IRQ%d\n", | ||
4817 | cyy_rev_id, (int)cy_pci_irq); | ||
4818 | printk("Cyclom-Y/PCI:found winaddr=0x%lx " | ||
4819 | "ctladdr=0x%lx\n", | ||
4820 | (ulong)cy_pci_phys2, | ||
4821 | (ulong)cy_pci_phys0); | ||
4822 | printk("Cyclom-Y/PCI not supported for low " | ||
4823 | "addresses in Alpha systems.\n"); | ||
4824 | i--; | ||
4825 | continue; | ||
4826 | } | ||
4827 | #endif | ||
4828 | cy_pci_addr0 = ioremap(cy_pci_phys0, CyPCI_Yctl); | ||
4829 | cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Ywin); | ||
4830 | 4800 | ||
4831 | #ifdef CY_PCI_DEBUG | 4801 | retval = -EIO; |
4832 | printk("Cyclom-Y/PCI: relocate winaddr=0x%lx " | 4802 | if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo || |
4833 | "ctladdr=0x%lx\n", | 4803 | device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { |
4834 | (u_long)cy_pci_addr2, (u_long)cy_pci_addr0); | 4804 | card_name = "Cyclom-Y"; |
4835 | #endif | ||
4836 | cy_pci_nchan = (unsigned short)(CyPORTS_PER_CHIP * | ||
4837 | cyy_init_card(cy_pci_addr2, 1)); | ||
4838 | if (cy_pci_nchan == 0) { | ||
4839 | printk("Cyclom-Y PCI host card with "); | ||
4840 | printk("no Serial-Modules at 0x%lx.\n", | ||
4841 | (ulong) cy_pci_phys2); | ||
4842 | i--; | ||
4843 | continue; | ||
4844 | } | ||
4845 | if ((cy_next_channel + cy_pci_nchan) > NR_PORTS) { | ||
4846 | printk("Cyclom-Y/PCI found at 0x%lx ", | ||
4847 | (ulong) cy_pci_phys2); | ||
4848 | printk("but no channels are available.\n"); | ||
4849 | printk("Change NR_PORTS in cyclades.c and " | ||
4850 | "recompile kernel.\n"); | ||
4851 | return i; | ||
4852 | } | ||
4853 | /* fill the next cy_card structure available */ | ||
4854 | for (j = 0; j < NR_CARDS; j++) { | ||
4855 | if (cy_card[j].base_addr == 0) | ||
4856 | break; | ||
4857 | } | ||
4858 | if (j == NR_CARDS) { /* no more cy_cards available */ | ||
4859 | printk("Cyclom-Y/PCI found at 0x%lx ", | ||
4860 | (ulong) cy_pci_phys2); | ||
4861 | printk("but no more cards can be used.\n"); | ||
4862 | printk("Change NR_CARDS in cyclades.c and " | ||
4863 | "recompile kernel.\n"); | ||
4864 | return i; | ||
4865 | } | ||
4866 | 4805 | ||
4867 | /* allocate IRQ */ | 4806 | addr0 = pci_iomap(pdev, 0, CyPCI_Yctl); |
4868 | if (request_irq(cy_pci_irq, cyy_interrupt, | 4807 | if (addr0 == NULL) { |
4869 | IRQF_SHARED, "Cyclom-Y", &cy_card[j])) { | 4808 | dev_err(&pdev->dev, "can't remap ctl region\n"); |
4870 | printk("Cyclom-Y/PCI found at 0x%lx ", | 4809 | goto err_reg; |
4871 | (ulong) cy_pci_phys2); | 4810 | } |
4872 | printk("but could not allocate IRQ%d.\n", | 4811 | addr2 = pci_iomap(pdev, 2, CyPCI_Ywin); |
4873 | cy_pci_irq); | 4812 | if (addr2 == NULL) { |
4874 | return i; | 4813 | dev_err(&pdev->dev, "can't remap base region\n"); |
4875 | } | 4814 | goto err_unmap; |
4815 | } | ||
4876 | 4816 | ||
4877 | /* set cy_card */ | 4817 | nchan = CyPORTS_PER_CHIP * cyy_init_card(addr2, 1); |
4878 | cy_card[j].base_phys = (ulong) cy_pci_phys2; | 4818 | if (nchan == 0) { |
4879 | cy_card[j].ctl_phys = (ulong) cy_pci_phys0; | 4819 | dev_err(&pdev->dev, "Cyclom-Y PCI host card with no " |
4880 | cy_card[j].base_addr = cy_pci_addr2; | 4820 | "Serial-Modules\n"); |
4881 | cy_card[j].ctl_addr = cy_pci_addr0; | 4821 | return -EIO; |
4882 | cy_card[j].irq = (int)cy_pci_irq; | 4822 | } |
4883 | cy_card[j].bus_index = 1; | 4823 | } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) { |
4884 | cy_card[j].first_line = cy_next_channel; | 4824 | struct RUNTIME_9060 __iomem *ctl_addr; |
4885 | cy_card[j].num_chips = cy_pci_nchan / 4; | ||
4886 | cy_card[j].pdev = pdev; | ||
4887 | |||
4888 | /* enable interrupts in the PCI interface */ | ||
4889 | plx_ver = cy_readb(cy_pci_addr2 + CyPLX_VER) & 0x0f; | ||
4890 | switch (plx_ver) { | ||
4891 | case PLX_9050: | ||
4892 | |||
4893 | cy_writeb(cy_pci_addr0 + 0x4c, 0x43); | ||
4894 | break; | ||
4895 | 4825 | ||
4896 | case PLX_9060: | 4826 | ctl_addr = addr0 = pci_iomap(pdev, 0, CyPCI_Zctl); |
4897 | case PLX_9080: | 4827 | if (addr0 == NULL) { |
4898 | default: /* Old boards, use PLX_9060 */ | 4828 | dev_err(&pdev->dev, "can't remap ctl region\n"); |
4899 | 4829 | goto err_reg; | |
4900 | plx_init(cy_pci_addr0, 0x6c); | 4830 | } |
4901 | /* For some yet unknown reason, once the PLX9060 reloads | ||
4902 | the EEPROM, the IRQ is lost and, thus, we have to | ||
4903 | re-write it to the PCI config. registers. | ||
4904 | This will remain here until we find a permanent | ||
4905 | fix. */ | ||
4906 | pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, | ||
4907 | cy_pci_irq); | ||
4908 | |||
4909 | cy_writew(cy_pci_addr0 + 0x68, | ||
4910 | cy_readw(cy_pci_addr0 + | ||
4911 | 0x68) | 0x0900); | ||
4912 | break; | ||
4913 | } | ||
4914 | 4831 | ||
4915 | /* print message */ | 4832 | /* Disable interrupts on the PLX before resetting it */ |
4916 | printk("Cyclom-Y/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", | 4833 | cy_writew(addr0 + 0x68, |
4917 | j + 1, (ulong)cy_pci_phys2, | 4834 | readw(addr0 + 0x68) & ~0x0900); |
4918 | (ulong) (cy_pci_phys2 + CyPCI_Ywin - 1), | 4835 | |
4919 | (int)cy_pci_irq); | 4836 | plx_init(addr0, 0x6c); |
4920 | printk("%d channels starting from port %d.\n", | 4837 | /* For some yet unknown reason, once the PLX9060 reloads |
4921 | cy_pci_nchan, cy_next_channel); | 4838 | the EEPROM, the IRQ is lost and, thus, we have to |
4922 | 4839 | re-write it to the PCI config. registers. | |
4923 | cy_next_channel += cy_pci_nchan; | 4840 | This will remain here until we find a permanent |
4924 | } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo) { | 4841 | fix. */ |
4925 | /* print message */ | 4842 | pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq); |
4926 | printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ", | 4843 | |
4927 | pdev->bus->number, pdev->devfn); | 4844 | mailbox = (u32)readl(&ctl_addr->mail_box_0); |
4928 | printk("rev_id=%d) IRQ%d\n", | 4845 | |
4929 | cyy_rev_id, (int)cy_pci_irq); | 4846 | addr2 = pci_iomap(pdev, 2, mailbox == ZE_V1 ? |
4930 | printk("Cyclades-Z/PCI: found winaddr=0x%lx " | 4847 | CyPCI_Ze_win : CyPCI_Zwin); |
4931 | "ctladdr=0x%lx\n", | 4848 | if (addr2 == NULL) { |
4932 | (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); | 4849 | dev_err(&pdev->dev, "can't remap base region\n"); |
4933 | printk("Cyclades-Z/PCI not supported for low " | 4850 | goto err_unmap; |
4934 | "addresses\n"); | 4851 | } |
4935 | break; | ||
4936 | } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) { | ||
4937 | #ifdef CY_PCI_DEBUG | ||
4938 | printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ", | ||
4939 | pdev->bus->number, pdev->devfn); | ||
4940 | printk("rev_id=%d) IRQ%d\n", | ||
4941 | cyy_rev_id, (int)cy_pci_irq); | ||
4942 | printk("Cyclades-Z/PCI: found winaddr=0x%lx " | ||
4943 | "ctladdr=0x%lx\n", | ||
4944 | (ulong) cy_pci_phys2, (ulong) cy_pci_phys0); | ||
4945 | #endif | ||
4946 | cy_pci_addr0 = ioremap(cy_pci_phys0, CyPCI_Zctl); | ||
4947 | |||
4948 | /* Disable interrupts on the PLX before resetting it */ | ||
4949 | cy_writew(cy_pci_addr0 + 0x68, | ||
4950 | cy_readw(cy_pci_addr0 + 0x68) & ~0x0900); | ||
4951 | |||
4952 | plx_init(cy_pci_addr0, 0x6c); | ||
4953 | /* For some yet unknown reason, once the PLX9060 reloads | ||
4954 | the EEPROM, the IRQ is lost and, thus, we have to | ||
4955 | re-write it to the PCI config. registers. | ||
4956 | This will remain here until we find a permanent | ||
4957 | fix. */ | ||
4958 | pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, | ||
4959 | cy_pci_irq); | ||
4960 | |||
4961 | mailbox = | ||
4962 | (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *) | ||
4963 | cy_pci_addr0)->mail_box_0); | ||
4964 | |||
4965 | if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { | ||
4966 | printk(" Warning: PCI I/O bit incorrectly " | ||
4967 | "set. Ignoring it...\n"); | ||
4968 | pdev->resource[2].flags &= ~IORESOURCE_IO; | ||
4969 | } | ||
4970 | 4852 | ||
4971 | /* Although we don't use this I/O region, we should | 4853 | if (mailbox == ZE_V1) { |
4972 | request it from the kernel anyway, to avoid problems | 4854 | card_name = "Cyclades-Ze"; |
4973 | with other drivers accessing it. */ | ||
4974 | if (pci_request_regions(pdev, "Cyclades-Z") != 0) { | ||
4975 | printk(KERN_ERR "cyclades: failed to reserve " | ||
4976 | "PCI resources\n"); | ||
4977 | continue; | ||
4978 | } | ||
4979 | 4855 | ||
4980 | if (mailbox == ZE_V1) { | 4856 | readl(&ctl_addr->mail_box_0); |
4981 | cy_pci_addr2 = ioremap(cy_pci_phys2, | 4857 | nchan = ZE_V1_NPORTS; |
4982 | CyPCI_Ze_win); | 4858 | } else { |
4983 | if (ZeIndex == NR_CARDS) { | 4859 | card_name = "Cyclades-8Zo"; |
4984 | printk("Cyclades-Ze/PCI found at " | ||
4985 | "0x%lx but no more cards can " | ||
4986 | "be used.\nChange NR_CARDS in " | ||
4987 | "cyclades.c and recompile " | ||
4988 | "kernel.\n", | ||
4989 | (ulong)cy_pci_phys2); | ||
4990 | } else { | ||
4991 | Ze_phys0[ZeIndex] = cy_pci_phys0; | ||
4992 | Ze_phys2[ZeIndex] = cy_pci_phys2; | ||
4993 | Ze_addr0[ZeIndex] = cy_pci_addr0; | ||
4994 | Ze_addr2[ZeIndex] = cy_pci_addr2; | ||
4995 | Ze_irq[ZeIndex] = cy_pci_irq; | ||
4996 | Ze_pdev[ZeIndex] = pdev; | ||
4997 | ZeIndex++; | ||
4998 | } | ||
4999 | i--; | ||
5000 | continue; | ||
5001 | } else { | ||
5002 | cy_pci_addr2 = ioremap(cy_pci_phys2,CyPCI_Zwin); | ||
5003 | } | ||
5004 | 4860 | ||
5005 | #ifdef CY_PCI_DEBUG | 4861 | #ifdef CY_PCI_DEBUG |
5006 | printk("Cyclades-Z/PCI: relocate winaddr=0x%lx " | ||
5007 | "ctladdr=0x%lx\n", | ||
5008 | (ulong) cy_pci_addr2, (ulong) cy_pci_addr0); | ||
5009 | if (mailbox == ZO_V1) { | 4862 | if (mailbox == ZO_V1) { |
5010 | cy_writel(&((struct RUNTIME_9060 *) | 4863 | cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); |
5011 | (cy_pci_addr0))->loc_addr_base, | 4864 | dev_info(&pdev->dev, "Cyclades-8Zo/PCI: FPGA " |
5012 | WIN_CREG); | 4865 | "id %lx, ver %lx\n", (ulong)(0xff & |
5013 | PAUSE; | 4866 | readl(&((struct CUSTOM_REG *)addr2)-> |
5014 | printk("Cyclades-8Zo/PCI: FPGA id %lx, ver " | 4867 | fpga_id)), (ulong)(0xff & |
5015 | "%lx\n", (ulong) (0xff & | 4868 | readl(&((struct CUSTOM_REG *)addr2)-> |
5016 | cy_readl(&((struct CUSTOM_REG *) | 4869 | fpga_version))); |
5017 | (cy_pci_addr2))->fpga_id)), | 4870 | cy_writel(&ctl_addr->loc_addr_base, WIN_RAM); |
5018 | (ulong)(0xff & | ||
5019 | cy_readl(&((struct CUSTOM_REG *) | ||
5020 | (cy_pci_addr2))-> | ||
5021 | fpga_version))); | ||
5022 | cy_writel(&((struct RUNTIME_9060 *) | ||
5023 | (cy_pci_addr0))->loc_addr_base, | ||
5024 | WIN_RAM); | ||
5025 | } else { | 4871 | } else { |
5026 | printk("Cyclades-Z/PCI: New Cyclades-Z board. " | 4872 | dev_info(&pdev->dev, "Cyclades-Z/PCI: New " |
5027 | "FPGA not loaded\n"); | 4873 | "Cyclades-Z board. FPGA not loaded\n"); |
5028 | } | 4874 | } |
5029 | #endif | 4875 | #endif |
5030 | /* The following clears the firmware id word. This | 4876 | /* The following clears the firmware id word. This |
5031 | ensures that the driver will not attempt to talk to | 4877 | ensures that the driver will not attempt to talk to |
5032 | the board until it has been properly initialized. | 4878 | the board until it has been properly initialized. |
5033 | */ | 4879 | */ |
5034 | PAUSE; | ||
5035 | if ((mailbox == ZO_V1) || (mailbox == ZO_V2)) | 4880 | if ((mailbox == ZO_V1) || (mailbox == ZO_V2)) |
5036 | cy_writel(cy_pci_addr2 + ID_ADDRESS, 0L); | 4881 | cy_writel(addr2 + ID_ADDRESS, 0L); |
5037 | 4882 | ||
5038 | /* This must be a Cyclades-8Zo/PCI. The extendable | 4883 | /* This must be a Cyclades-8Zo/PCI. The extendable |
5039 | version will have a different device_id and will | 4884 | version will have a different device_id and will |
5040 | be allocated its maximum number of ports. */ | 4885 | be allocated its maximum number of ports. */ |
5041 | cy_pci_nchan = 8; | 4886 | nchan = 8; |
5042 | |||
5043 | if ((cy_next_channel + cy_pci_nchan) > NR_PORTS) { | ||
5044 | printk("Cyclades-8Zo/PCI found at 0x%lx but" | ||
5045 | "no channels are available.\nChange " | ||
5046 | "NR_PORTS in cyclades.c and recompile " | ||
5047 | "kernel.\n", (ulong)cy_pci_phys2); | ||
5048 | return i; | ||
5049 | } | ||
5050 | |||
5051 | /* fill the next cy_card structure available */ | ||
5052 | for (j = 0; j < NR_CARDS; j++) { | ||
5053 | if (cy_card[j].base_addr == 0) | ||
5054 | break; | ||
5055 | } | ||
5056 | if (j == NR_CARDS) { /* no more cy_cards available */ | ||
5057 | printk("Cyclades-8Zo/PCI found at 0x%lx but" | ||
5058 | "no more cards can be used.\nChange " | ||
5059 | "NR_CARDS in cyclades.c and recompile " | ||
5060 | "kernel.\n", (ulong)cy_pci_phys2); | ||
5061 | return i; | ||
5062 | } | ||
5063 | #ifdef CONFIG_CYZ_INTR | ||
5064 | /* allocate IRQ only if board has an IRQ */ | ||
5065 | if ((cy_pci_irq != 0) && (cy_pci_irq != 255)) { | ||
5066 | if (request_irq(cy_pci_irq, cyz_interrupt, | ||
5067 | IRQF_SHARED, "Cyclades-Z", | ||
5068 | &cy_card[j])) { | ||
5069 | printk("Cyclom-8Zo/PCI found at 0x%lx " | ||
5070 | "but could not allocate " | ||
5071 | "IRQ%d.\n", (ulong)cy_pci_phys2, | ||
5072 | cy_pci_irq); | ||
5073 | return i; | ||
5074 | } | ||
5075 | } | ||
5076 | #endif /* CONFIG_CYZ_INTR */ | ||
5077 | |||
5078 | /* set cy_card */ | ||
5079 | cy_card[j].base_phys = cy_pci_phys2; | ||
5080 | cy_card[j].ctl_phys = cy_pci_phys0; | ||
5081 | cy_card[j].base_addr = cy_pci_addr2; | ||
5082 | cy_card[j].ctl_addr = cy_pci_addr0; | ||
5083 | cy_card[j].irq = (int)cy_pci_irq; | ||
5084 | cy_card[j].bus_index = 1; | ||
5085 | cy_card[j].first_line = cy_next_channel; | ||
5086 | cy_card[j].num_chips = -1; | ||
5087 | cy_card[j].pdev = pdev; | ||
5088 | |||
5089 | /* print message */ | ||
5090 | #ifdef CONFIG_CYZ_INTR | ||
5091 | /* don't report IRQ if board is no IRQ */ | ||
5092 | if ((cy_pci_irq != 0) && (cy_pci_irq != 255)) | ||
5093 | printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, " | ||
5094 | "IRQ%d, ", j + 1, (ulong)cy_pci_phys2, | ||
5095 | (ulong) (cy_pci_phys2 + CyPCI_Zwin - 1), | ||
5096 | (int)cy_pci_irq); | ||
5097 | else | ||
5098 | #endif /* CONFIG_CYZ_INTR */ | ||
5099 | printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, ", | ||
5100 | j + 1, (ulong)cy_pci_phys2, | ||
5101 | (ulong)(cy_pci_phys2 + CyPCI_Zwin - 1)); | ||
5102 | |||
5103 | printk("%d channels starting from port %d.\n", | ||
5104 | cy_pci_nchan, cy_next_channel); | ||
5105 | cy_next_channel += cy_pci_nchan; | ||
5106 | } | 4887 | } |
5107 | } | 4888 | } |
5108 | 4889 | ||
5109 | for (; ZeIndex != 0 && i < NR_CARDS; i++) { | 4890 | if ((cy_next_channel + nchan) > NR_PORTS) { |
5110 | cy_pci_phys0 = Ze_phys0[0]; | 4891 | dev_err(&pdev->dev, "Cyclades-8Zo/PCI found, but no " |
5111 | cy_pci_phys2 = Ze_phys2[0]; | 4892 | "channels are available. Change NR_PORTS in " |
5112 | cy_pci_addr0 = Ze_addr0[0]; | 4893 | "cyclades.c and recompile kernel.\n"); |
5113 | cy_pci_addr2 = Ze_addr2[0]; | 4894 | goto err_unmap; |
5114 | cy_pci_irq = Ze_irq[0]; | 4895 | } |
5115 | pdev = Ze_pdev[0]; | 4896 | /* fill the next cy_card structure available */ |
5116 | for (j = 0; j < ZeIndex - 1; j++) { | 4897 | for (card_no = 0; card_no < NR_CARDS; card_no++) { |
5117 | Ze_phys0[j] = Ze_phys0[j + 1]; | 4898 | if (cy_card[card_no].base_addr == NULL) |
5118 | Ze_phys2[j] = Ze_phys2[j + 1]; | 4899 | break; |
5119 | Ze_addr0[j] = Ze_addr0[j + 1]; | 4900 | } |
5120 | Ze_addr2[j] = Ze_addr2[j + 1]; | 4901 | if (card_no == NR_CARDS) { /* no more cy_cards available */ |
5121 | Ze_irq[j] = Ze_irq[j + 1]; | 4902 | dev_err(&pdev->dev, "Cyclades-8Zo/PCI found, but no " |
5122 | Ze_pdev[j] = Ze_pdev[j + 1]; | 4903 | "more cards can be used. Change NR_CARDS in " |
5123 | } | 4904 | "cyclades.c and recompile kernel.\n"); |
5124 | ZeIndex--; | 4905 | goto err_unmap; |
5125 | mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *) | 4906 | } |
5126 | cy_pci_addr0)->mail_box_0); | ||
5127 | #ifdef CY_PCI_DEBUG | ||
5128 | printk("Cyclades-Z/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n", | ||
5129 | (ulong)cy_pci_addr2, (ulong)cy_pci_addr0); | ||
5130 | printk("Cyclades-Z/PCI: New Cyclades-Z board. FPGA not " | ||
5131 | "loaded\n"); | ||
5132 | #endif | ||
5133 | PAUSE; | ||
5134 | /* This must be the new Cyclades-Ze/PCI. */ | ||
5135 | cy_pci_nchan = ZE_V1_NPORTS; | ||
5136 | |||
5137 | if ((cy_next_channel + cy_pci_nchan) > NR_PORTS) { | ||
5138 | printk("Cyclades-Ze/PCI found at 0x%lx but no channels " | ||
5139 | "are available.\nChange NR_PORTS in cyclades.c " | ||
5140 | "and recompile kernel.\n", | ||
5141 | (ulong) cy_pci_phys2); | ||
5142 | return i; | ||
5143 | } | ||
5144 | 4907 | ||
5145 | /* fill the next cy_card structure available */ | 4908 | if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo || |
5146 | for (j = 0; j < NR_CARDS; j++) { | 4909 | device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { |
5147 | if (cy_card[j].base_addr == 0) | 4910 | /* allocate IRQ */ |
5148 | break; | 4911 | retval = request_irq(irq, cyy_interrupt, |
5149 | } | 4912 | IRQF_SHARED, "Cyclom-Y", &cy_card[card_no]); |
5150 | if (j == NR_CARDS) { /* no more cy_cards available */ | 4913 | if (retval) { |
5151 | printk("Cyclades-Ze/PCI found at 0x%lx but no more " | 4914 | dev_err(&pdev->dev, "could not allocate IRQ\n"); |
5152 | "cards can be used.\nChange NR_CARDS in " | 4915 | goto err_unmap; |
5153 | "cyclades.c and recompile kernel.\n", | ||
5154 | (ulong) cy_pci_phys2); | ||
5155 | return i; | ||
5156 | } | 4916 | } |
4917 | cy_card[card_no].num_chips = nchan / 4; | ||
4918 | } else { | ||
5157 | #ifdef CONFIG_CYZ_INTR | 4919 | #ifdef CONFIG_CYZ_INTR |
5158 | /* allocate IRQ only if board has an IRQ */ | 4920 | /* allocate IRQ only if board has an IRQ */ |
5159 | if ((cy_pci_irq != 0) && (cy_pci_irq != 255)) { | 4921 | if (irq != 0 && irq != 255) { |
5160 | if (request_irq(cy_pci_irq, cyz_interrupt, | 4922 | retval = request_irq(irq, cyz_interrupt, |
5161 | IRQF_SHARED, "Cyclades-Z", | 4923 | IRQF_SHARED, "Cyclades-Z", |
5162 | &cy_card[j])) { | 4924 | &cy_card[card_no]); |
5163 | printk("Cyclom-Ze/PCI found at 0x%lx ", | 4925 | if (retval) { |
5164 | (ulong) cy_pci_phys2); | 4926 | dev_err(&pdev->dev, "could not allocate IRQ\n"); |
5165 | printk("but could not allocate IRQ%d.\n", | 4927 | goto err_unmap; |
5166 | cy_pci_irq); | ||
5167 | return i; | ||
5168 | } | 4928 | } |
5169 | } | 4929 | } |
5170 | #endif /* CONFIG_CYZ_INTR */ | 4930 | #endif /* CONFIG_CYZ_INTR */ |
4931 | cy_card[card_no].num_chips = -1; | ||
4932 | } | ||
5171 | 4933 | ||
5172 | /* set cy_card */ | 4934 | /* set cy_card */ |
5173 | cy_card[j].base_phys = cy_pci_phys2; | 4935 | cy_card[card_no].base_addr = addr2; |
5174 | cy_card[j].ctl_phys = cy_pci_phys0; | 4936 | cy_card[card_no].ctl_addr = addr0; |
5175 | cy_card[j].base_addr = cy_pci_addr2; | 4937 | cy_card[card_no].irq = irq; |
5176 | cy_card[j].ctl_addr = cy_pci_addr0; | 4938 | cy_card[card_no].bus_index = 1; |
5177 | cy_card[j].irq = (int)cy_pci_irq; | 4939 | cy_card[card_no].first_line = cy_next_channel; |
5178 | cy_card[j].bus_index = 1; | 4940 | retval = cy_init_card(&cy_card[card_no]); |
5179 | cy_card[j].first_line = cy_next_channel; | 4941 | if (retval) |
5180 | cy_card[j].num_chips = -1; | 4942 | goto err_null; |
5181 | cy_card[j].pdev = pdev; | ||
5182 | 4943 | ||
5183 | /* print message */ | 4944 | pci_set_drvdata(pdev, &cy_card[card_no]); |
5184 | #ifdef CONFIG_CYZ_INTR | ||
5185 | /* don't report IRQ if board is no IRQ */ | ||
5186 | if ((cy_pci_irq != 0) && (cy_pci_irq != 255)) | ||
5187 | printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", | ||
5188 | j + 1, (ulong) cy_pci_phys2, | ||
5189 | (ulong) (cy_pci_phys2 + CyPCI_Ze_win - 1), | ||
5190 | (int)cy_pci_irq); | ||
5191 | else | ||
5192 | #endif /* CONFIG_CYZ_INTR */ | ||
5193 | printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, ", | ||
5194 | j + 1, (ulong) cy_pci_phys2, | ||
5195 | (ulong) (cy_pci_phys2 + CyPCI_Ze_win - 1)); | ||
5196 | 4945 | ||
5197 | printk("%d channels starting from port %d.\n", | 4946 | if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo || |
5198 | cy_pci_nchan, cy_next_channel); | 4947 | device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { |
5199 | cy_next_channel += cy_pci_nchan; | 4948 | /* enable interrupts in the PCI interface */ |
5200 | } | 4949 | plx_ver = readb(addr2 + CyPLX_VER) & 0x0f; |
5201 | if (ZeIndex != 0) { | 4950 | switch (plx_ver) { |
5202 | printk("Cyclades-Ze/PCI found at 0x%x but no more cards can be " | 4951 | case PLX_9050: |
5203 | "used.\nChange NR_CARDS in cyclades.c and recompile " | 4952 | |
5204 | "kernel.\n", (unsigned int)Ze_phys2[0]); | 4953 | cy_writeb(addr0 + 0x4c, 0x43); |
4954 | break; | ||
4955 | |||
4956 | case PLX_9060: | ||
4957 | case PLX_9080: | ||
4958 | default: /* Old boards, use PLX_9060 */ | ||
4959 | |||
4960 | plx_init(addr0, 0x6c); | ||
4961 | /* For some yet unknown reason, once the PLX9060 reloads | ||
4962 | the EEPROM, the IRQ is lost and, thus, we have to | ||
4963 | re-write it to the PCI config. registers. | ||
4964 | This will remain here until we find a permanent | ||
4965 | fix. */ | ||
4966 | pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq); | ||
4967 | |||
4968 | cy_writew(addr0 + 0x68, readw(addr0 + 0x68) | 0x0900); | ||
4969 | break; | ||
4970 | } | ||
5205 | } | 4971 | } |
5206 | return i; | 4972 | |
5207 | #else | 4973 | dev_info(&pdev->dev, "%s/PCI #%d found: %d channels starting from " |
4974 | "port %d.\n", card_name, card_no + 1, nchan, cy_next_channel); | ||
4975 | for (i = cy_next_channel; i < cy_next_channel + nchan; i++) | ||
4976 | tty_register_device(cy_serial_driver, i, &pdev->dev); | ||
4977 | cy_next_channel += nchan; | ||
4978 | |||
5208 | return 0; | 4979 | return 0; |
5209 | #endif /* ifdef CONFIG_PCI */ | 4980 | err_null: |
5210 | } /* cy_detect_pci */ | 4981 | cy_card[card_no].base_addr = NULL; |
4982 | free_irq(irq, &cy_card[card_no]); | ||
4983 | err_unmap: | ||
4984 | pci_iounmap(pdev, addr0); | ||
4985 | if (addr2) | ||
4986 | pci_iounmap(pdev, addr2); | ||
4987 | err_reg: | ||
4988 | pci_release_regions(pdev); | ||
4989 | err_dis: | ||
4990 | pci_disable_device(pdev); | ||
4991 | err: | ||
4992 | return retval; | ||
4993 | } | ||
5211 | 4994 | ||
5212 | /* | 4995 | static void __devexit cy_pci_remove(struct pci_dev *pdev) |
5213 | * This routine prints out the appropriate serial driver version number | ||
5214 | * and identifies which options were configured into this driver. | ||
5215 | */ | ||
5216 | static inline void show_version(void) | ||
5217 | { | 4996 | { |
5218 | printk("Cyclades driver " CY_VERSION "\n"); | 4997 | struct cyclades_card *cinfo = pci_get_drvdata(pdev); |
5219 | printk(" built %s %s\n", __DATE__, __TIME__); | 4998 | unsigned int i; |
5220 | } /* show_version */ | 4999 | |
5000 | /* non-Z with old PLX */ | ||
5001 | if (!IS_CYC_Z(*cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) == | ||
5002 | PLX_9050) | ||
5003 | cy_writeb(cinfo->ctl_addr + 0x4c, 0); | ||
5004 | else | ||
5005 | #ifndef CONFIG_CYZ_INTR | ||
5006 | if (!IS_CYC_Z(*cinfo)) | ||
5007 | #endif | ||
5008 | cy_writew(cinfo->ctl_addr + 0x68, | ||
5009 | readw(cinfo->ctl_addr + 0x68) & ~0x0900); | ||
5010 | |||
5011 | pci_iounmap(pdev, cinfo->base_addr); | ||
5012 | if (cinfo->ctl_addr) | ||
5013 | pci_iounmap(pdev, cinfo->ctl_addr); | ||
5014 | if (cinfo->irq | ||
5015 | #ifndef CONFIG_CYZ_INTR | ||
5016 | && !IS_CYC_Z(*cinfo) | ||
5017 | #endif /* CONFIG_CYZ_INTR */ | ||
5018 | ) | ||
5019 | free_irq(cinfo->irq, cinfo); | ||
5020 | pci_release_regions(pdev); | ||
5021 | |||
5022 | cinfo->base_addr = NULL; | ||
5023 | for (i = cinfo->first_line; i < cinfo->first_line + | ||
5024 | cinfo->nports; i++) | ||
5025 | tty_unregister_device(cy_serial_driver, i); | ||
5026 | cinfo->nports = 0; | ||
5027 | kfree(cinfo->ports); | ||
5028 | } | ||
5029 | |||
5030 | static struct pci_driver cy_pci_driver = { | ||
5031 | .name = "cyclades", | ||
5032 | .id_table = cy_pci_dev_id, | ||
5033 | .probe = cy_pci_probe, | ||
5034 | .remove = __devexit_p(cy_pci_remove) | ||
5035 | }; | ||
5036 | #endif | ||
5221 | 5037 | ||
5222 | static int | 5038 | static int |
5223 | cyclades_get_proc_info(char *buf, char **start, off_t offset, int length, | 5039 | cyclades_get_proc_info(char *buf, char **start, off_t offset, int length, |
5224 | int *eof, void *data) | 5040 | int *eof, void *data) |
5225 | { | 5041 | { |
5226 | struct cyclades_port *info; | 5042 | struct cyclades_port *info; |
5227 | int i; | 5043 | unsigned int i, j; |
5228 | int len = 0; | 5044 | int len = 0; |
5229 | off_t begin = 0; | 5045 | off_t begin = 0; |
5230 | off_t pos = 0; | 5046 | off_t pos = 0; |
@@ -5238,33 +5054,34 @@ cyclades_get_proc_info(char *buf, char **start, off_t offset, int length, | |||
5238 | len += size; | 5054 | len += size; |
5239 | 5055 | ||
5240 | /* Output one line for each known port */ | 5056 | /* Output one line for each known port */ |
5241 | for (i = 0; i < NR_PORTS && cy_port[i].line >= 0; i++) { | 5057 | for (i = 0; i < NR_CARDS; i++) |
5242 | info = &cy_port[i]; | 5058 | for (j = 0; j < cy_card[i].nports; j++) { |
5243 | 5059 | info = &cy_card[i].ports[j]; | |
5244 | if (info->count) | 5060 | |
5245 | size = sprintf(buf + len, "%3d %8lu %10lu %8lu %10lu " | 5061 | if (info->count) |
5246 | "%8lu %9lu %6ld\n", info->line, | 5062 | size = sprintf(buf + len, "%3d %8lu %10lu %8lu " |
5247 | (cur_jifs - info->idle_stats.in_use) / HZ, | 5063 | "%10lu %8lu %9lu %6ld\n", info->line, |
5248 | info->idle_stats.xmit_bytes, | 5064 | (cur_jifs - info->idle_stats.in_use) / |
5249 | (cur_jifs - info->idle_stats.xmit_idle) / HZ, | 5065 | HZ, info->idle_stats.xmit_bytes, |
5250 | info->idle_stats.recv_bytes, | 5066 | (cur_jifs - info->idle_stats.xmit_idle)/ |
5251 | (cur_jifs - info->idle_stats.recv_idle) / HZ, | 5067 | HZ, info->idle_stats.recv_bytes, |
5252 | info->idle_stats.overruns, | 5068 | (cur_jifs - info->idle_stats.recv_idle)/ |
5253 | (long)info->tty->ldisc.num); | 5069 | HZ, info->idle_stats.overruns, |
5254 | else | 5070 | (long)info->tty->ldisc.num); |
5255 | size = sprintf(buf + len, "%3d %8lu %10lu %8lu %10lu " | 5071 | else |
5256 | "%8lu %9lu %6ld\n", | 5072 | size = sprintf(buf + len, "%3d %8lu %10lu %8lu " |
5257 | info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L); | 5073 | "%10lu %8lu %9lu %6ld\n", |
5258 | len += size; | 5074 | info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L); |
5259 | pos = begin + len; | 5075 | len += size; |
5260 | 5076 | pos = begin + len; | |
5261 | if (pos < offset) { | 5077 | |
5262 | len = 0; | 5078 | if (pos < offset) { |
5263 | begin = pos; | 5079 | len = 0; |
5080 | begin = pos; | ||
5081 | } | ||
5082 | if (pos > offset + length) | ||
5083 | goto done; | ||
5264 | } | 5084 | } |
5265 | if (pos > offset + length) | ||
5266 | goto done; | ||
5267 | } | ||
5268 | *eof = 1; | 5085 | *eof = 1; |
5269 | done: | 5086 | done: |
5270 | *start = buf + (offset - begin); /* Start of wanted data */ | 5087 | *start = buf + (offset - begin); /* Start of wanted data */ |
@@ -5319,18 +5136,15 @@ static const struct tty_operations cy_ops = { | |||
5319 | 5136 | ||
5320 | static int __init cy_init(void) | 5137 | static int __init cy_init(void) |
5321 | { | 5138 | { |
5322 | struct cyclades_port *info; | 5139 | unsigned int nboards; |
5323 | struct cyclades_card *cinfo; | 5140 | int retval = -ENOMEM; |
5324 | int number_z_boards = 0; | ||
5325 | int board, port, i, index; | ||
5326 | unsigned long mailbox; | ||
5327 | unsigned short chip_number; | ||
5328 | int nports; | ||
5329 | 5141 | ||
5330 | cy_serial_driver = alloc_tty_driver(NR_PORTS); | 5142 | cy_serial_driver = alloc_tty_driver(NR_PORTS); |
5331 | if (!cy_serial_driver) | 5143 | if (!cy_serial_driver) |
5332 | return -ENOMEM; | 5144 | goto err; |
5333 | show_version(); | 5145 | |
5146 | printk(KERN_INFO "Cyclades driver " CY_VERSION " (built %s %s)\n", | ||
5147 | __DATE__, __TIME__); | ||
5334 | 5148 | ||
5335 | /* Initialize the tty_driver structure */ | 5149 | /* Initialize the tty_driver structure */ |
5336 | 5150 | ||
@@ -5344,15 +5158,13 @@ static int __init cy_init(void) | |||
5344 | cy_serial_driver->init_termios = tty_std_termios; | 5158 | cy_serial_driver->init_termios = tty_std_termios; |
5345 | cy_serial_driver->init_termios.c_cflag = | 5159 | cy_serial_driver->init_termios.c_cflag = |
5346 | B9600 | CS8 | CREAD | HUPCL | CLOCAL; | 5160 | B9600 | CS8 | CREAD | HUPCL | CLOCAL; |
5347 | cy_serial_driver->flags = TTY_DRIVER_REAL_RAW; | 5161 | cy_serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; |
5348 | tty_set_operations(cy_serial_driver, &cy_ops); | 5162 | tty_set_operations(cy_serial_driver, &cy_ops); |
5349 | 5163 | ||
5350 | if (tty_register_driver(cy_serial_driver)) | 5164 | retval = tty_register_driver(cy_serial_driver); |
5351 | panic("Couldn't register Cyclades serial driver\n"); | 5165 | if (retval) { |
5352 | 5166 | printk(KERN_ERR "Couldn't register Cyclades serial driver\n"); | |
5353 | for (i = 0; i < NR_CARDS; i++) { | 5167 | goto err_frtty; |
5354 | /* base_addr=0 indicates board not found */ | ||
5355 | cy_card[i].base_addr = NULL; | ||
5356 | } | 5168 | } |
5357 | 5169 | ||
5358 | /* the code below is responsible to find the boards. Each different | 5170 | /* the code below is responsible to find the boards. Each different |
@@ -5363,223 +5175,68 @@ static int __init cy_init(void) | |||
5363 | the cy_next_channel. */ | 5175 | the cy_next_channel. */ |
5364 | 5176 | ||
5365 | /* look for isa boards */ | 5177 | /* look for isa boards */ |
5366 | cy_isa_nboard = cy_detect_isa(); | 5178 | nboards = cy_detect_isa(); |
5367 | 5179 | ||
5180 | #ifdef CONFIG_PCI | ||
5368 | /* look for pci boards */ | 5181 | /* look for pci boards */ |
5369 | cy_pci_nboard = cy_detect_pci(); | 5182 | retval = pci_register_driver(&cy_pci_driver); |
5370 | 5183 | if (retval && !nboards) | |
5371 | cy_nboard = cy_isa_nboard + cy_pci_nboard; | 5184 | goto err_unr; |
5372 | |||
5373 | /* invalidate remaining cy_card structures */ | ||
5374 | for (i = 0; i < NR_CARDS; i++) { | ||
5375 | if (cy_card[i].base_addr == 0) { | ||
5376 | cy_card[i].first_line = -1; | ||
5377 | cy_card[i].ctl_addr = NULL; | ||
5378 | cy_card[i].irq = 0; | ||
5379 | cy_card[i].bus_index = 0; | ||
5380 | cy_card[i].first_line = 0; | ||
5381 | cy_card[i].num_chips = 0; | ||
5382 | } | ||
5383 | } | ||
5384 | /* invalidate remaining cy_port structures */ | ||
5385 | for (i = cy_next_channel; i < NR_PORTS; i++) { | ||
5386 | cy_port[i].line = -1; | ||
5387 | cy_port[i].magic = -1; | ||
5388 | } | ||
5389 | |||
5390 | /* initialize per-port data structures for each valid board found */ | ||
5391 | for (board = 0; board < cy_nboard; board++) { | ||
5392 | cinfo = &cy_card[board]; | ||
5393 | if (cinfo->num_chips == -1) { /* Cyclades-Z */ | ||
5394 | number_z_boards++; | ||
5395 | mailbox = cy_readl(&((struct RUNTIME_9060 __iomem *) | ||
5396 | cy_card[board].ctl_addr)-> | ||
5397 | mail_box_0); | ||
5398 | nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8; | ||
5399 | cinfo->intr_enabled = 0; | ||
5400 | cinfo->nports = 0; /* Will be correctly set later, after | ||
5401 | Z FW is loaded */ | ||
5402 | spin_lock_init(&cinfo->card_lock); | ||
5403 | for (port = cinfo->first_line; | ||
5404 | port < cinfo->first_line + nports; port++) { | ||
5405 | info = &cy_port[port]; | ||
5406 | info->magic = CYCLADES_MAGIC; | ||
5407 | info->type = PORT_STARTECH; | ||
5408 | info->card = board; | ||
5409 | info->line = port; | ||
5410 | info->chip_rev = 0; | ||
5411 | info->flags = STD_COM_FLAGS; | ||
5412 | info->tty = NULL; | ||
5413 | if (mailbox == ZO_V1) | ||
5414 | info->xmit_fifo_size = CYZ_FIFO_SIZE; | ||
5415 | else | ||
5416 | info->xmit_fifo_size = | ||
5417 | 4 * CYZ_FIFO_SIZE; | ||
5418 | info->cor1 = 0; | ||
5419 | info->cor2 = 0; | ||
5420 | info->cor3 = 0; | ||
5421 | info->cor4 = 0; | ||
5422 | info->cor5 = 0; | ||
5423 | info->tbpr = 0; | ||
5424 | info->tco = 0; | ||
5425 | info->rbpr = 0; | ||
5426 | info->rco = 0; | ||
5427 | info->custom_divisor = 0; | ||
5428 | info->close_delay = 5 * HZ / 10; | ||
5429 | info->closing_wait = CLOSING_WAIT_DELAY; | ||
5430 | info->icount.cts = info->icount.dsr = | ||
5431 | info->icount.rng = info->icount.dcd = 0; | ||
5432 | info->icount.rx = info->icount.tx = 0; | ||
5433 | info->icount.frame = info->icount.parity = 0; | ||
5434 | info->icount.overrun = info->icount.brk = 0; | ||
5435 | info->x_char = 0; | ||
5436 | info->event = 0; | ||
5437 | info->count = 0; | ||
5438 | info->blocked_open = 0; | ||
5439 | info->default_threshold = 0; | ||
5440 | info->default_timeout = 0; | ||
5441 | INIT_WORK(&info->tqueue, do_softint); | ||
5442 | init_waitqueue_head(&info->open_wait); | ||
5443 | init_waitqueue_head(&info->close_wait); | ||
5444 | init_waitqueue_head(&info->shutdown_wait); | ||
5445 | init_waitqueue_head(&info->delta_msr_wait); | ||
5446 | /* info->session */ | ||
5447 | /* info->pgrp */ | ||
5448 | info->read_status_mask = 0; | ||
5449 | /* info->timeout */ | ||
5450 | /* Bentson's vars */ | ||
5451 | info->jiffies[0] = 0; | ||
5452 | info->jiffies[1] = 0; | ||
5453 | info->jiffies[2] = 0; | ||
5454 | info->rflush_count = 0; | ||
5455 | #ifdef CONFIG_CYZ_INTR | ||
5456 | init_timer(&cyz_rx_full_timer[port]); | ||
5457 | cyz_rx_full_timer[port].function = NULL; | ||
5458 | #endif | 5185 | #endif |
5459 | } | ||
5460 | continue; | ||
5461 | } else { /* Cyclom-Y of some kind */ | ||
5462 | index = cinfo->bus_index; | ||
5463 | spin_lock_init(&cinfo->card_lock); | ||
5464 | cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips; | ||
5465 | for (port = cinfo->first_line; | ||
5466 | port < cinfo->first_line + cinfo->nports; port++) { | ||
5467 | info = &cy_port[port]; | ||
5468 | info->magic = CYCLADES_MAGIC; | ||
5469 | info->type = PORT_CIRRUS; | ||
5470 | info->card = board; | ||
5471 | info->line = port; | ||
5472 | info->flags = STD_COM_FLAGS; | ||
5473 | info->tty = NULL; | ||
5474 | info->xmit_fifo_size = CyMAX_CHAR_FIFO; | ||
5475 | info->cor1 = | ||
5476 | CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS; | ||
5477 | info->cor2 = CyETC; | ||
5478 | info->cor3 = 0x08; /* _very_ small rcv threshold */ | ||
5479 | info->cor4 = 0; | ||
5480 | info->cor5 = 0; | ||
5481 | info->custom_divisor = 0; | ||
5482 | info->close_delay = 5 * HZ / 10; | ||
5483 | info->closing_wait = CLOSING_WAIT_DELAY; | ||
5484 | info->icount.cts = info->icount.dsr = | ||
5485 | info->icount.rng = info->icount.dcd = 0; | ||
5486 | info->icount.rx = info->icount.tx = 0; | ||
5487 | info->icount.frame = info->icount.parity = 0; | ||
5488 | info->icount.overrun = info->icount.brk = 0; | ||
5489 | chip_number = (port - cinfo->first_line) / 4; | ||
5490 | if ((info->chip_rev = | ||
5491 | cy_readb(cinfo->base_addr + | ||
5492 | (cy_chip_offset[chip_number] << | ||
5493 | index) + (CyGFRCR << index))) >= | ||
5494 | CD1400_REV_J) { | ||
5495 | /* It is a CD1400 rev. J or later */ | ||
5496 | info->tbpr = baud_bpr_60[13]; /* Tx BPR */ | ||
5497 | info->tco = baud_co_60[13]; /* Tx CO */ | ||
5498 | info->rbpr = baud_bpr_60[13]; /* Rx BPR */ | ||
5499 | info->rco = baud_co_60[13]; /* Rx CO */ | ||
5500 | info->rflow = 0; | ||
5501 | info->rtsdtr_inv = 1; | ||
5502 | } else { | ||
5503 | info->tbpr = baud_bpr_25[13]; /* Tx BPR */ | ||
5504 | info->tco = baud_co_25[13]; /* Tx CO */ | ||
5505 | info->rbpr = baud_bpr_25[13]; /* Rx BPR */ | ||
5506 | info->rco = baud_co_25[13]; /* Rx CO */ | ||
5507 | info->rflow = 0; | ||
5508 | info->rtsdtr_inv = 0; | ||
5509 | } | ||
5510 | info->x_char = 0; | ||
5511 | info->event = 0; | ||
5512 | info->count = 0; | ||
5513 | info->blocked_open = 0; | ||
5514 | info->default_threshold = 0; | ||
5515 | info->default_timeout = 0; | ||
5516 | INIT_WORK(&info->tqueue, do_softint); | ||
5517 | init_waitqueue_head(&info->open_wait); | ||
5518 | init_waitqueue_head(&info->close_wait); | ||
5519 | init_waitqueue_head(&info->shutdown_wait); | ||
5520 | init_waitqueue_head(&info->delta_msr_wait); | ||
5521 | /* info->session */ | ||
5522 | /* info->pgrp */ | ||
5523 | info->read_status_mask = | ||
5524 | CyTIMEOUT | CySPECHAR | CyBREAK | ||
5525 | | CyPARITY | CyFRAME | CyOVERRUN; | ||
5526 | /* info->timeout */ | ||
5527 | } | ||
5528 | } | ||
5529 | } | ||
5530 | |||
5531 | #ifndef CONFIG_CYZ_INTR | ||
5532 | if (number_z_boards && !cyz_timeron) { | ||
5533 | cyz_timeron++; | ||
5534 | cyz_timerlist.expires = jiffies + 1; | ||
5535 | add_timer(&cyz_timerlist); | ||
5536 | #ifdef CY_PCI_DEBUG | ||
5537 | printk("Cyclades-Z polling initialized\n"); | ||
5538 | #endif | ||
5539 | } | ||
5540 | #endif /* CONFIG_CYZ_INTR */ | ||
5541 | 5186 | ||
5542 | return 0; | 5187 | return 0; |
5543 | 5188 | err_unr: | |
5189 | tty_unregister_driver(cy_serial_driver); | ||
5190 | err_frtty: | ||
5191 | put_tty_driver(cy_serial_driver); | ||
5192 | err: | ||
5193 | return retval; | ||
5544 | } /* cy_init */ | 5194 | } /* cy_init */ |
5545 | 5195 | ||
5546 | static void __exit cy_cleanup_module(void) | 5196 | static void __exit cy_cleanup_module(void) |
5547 | { | 5197 | { |
5198 | struct cyclades_card *card; | ||
5548 | int i, e1; | 5199 | int i, e1; |
5549 | 5200 | ||
5550 | #ifndef CONFIG_CYZ_INTR | 5201 | #ifndef CONFIG_CYZ_INTR |
5551 | if (cyz_timeron){ | 5202 | del_timer_sync(&cyz_timerlist); |
5552 | cyz_timeron = 0; | ||
5553 | del_timer(&cyz_timerlist); | ||
5554 | } | ||
5555 | #endif /* CONFIG_CYZ_INTR */ | 5203 | #endif /* CONFIG_CYZ_INTR */ |
5556 | 5204 | ||
5557 | if ((e1 = tty_unregister_driver(cy_serial_driver))) | 5205 | if ((e1 = tty_unregister_driver(cy_serial_driver))) |
5558 | printk("cyc: failed to unregister Cyclades serial driver(%d)\n", | 5206 | printk(KERN_ERR "failed to unregister Cyclades serial " |
5559 | e1); | 5207 | "driver(%d)\n", e1); |
5560 | 5208 | ||
5561 | put_tty_driver(cy_serial_driver); | 5209 | #ifdef CONFIG_PCI |
5210 | pci_unregister_driver(&cy_pci_driver); | ||
5211 | #endif | ||
5562 | 5212 | ||
5563 | for (i = 0; i < NR_CARDS; i++) { | 5213 | for (i = 0; i < NR_CARDS; i++) { |
5564 | if (cy_card[i].base_addr) { | 5214 | card = &cy_card[i]; |
5565 | iounmap(cy_card[i].base_addr); | 5215 | if (card->base_addr) { |
5566 | if (cy_card[i].ctl_addr) | 5216 | /* clear interrupt */ |
5567 | iounmap(cy_card[i].ctl_addr); | 5217 | cy_writeb(card->base_addr + Cy_ClrIntr, 0); |
5568 | if (cy_card[i].irq | 5218 | iounmap(card->base_addr); |
5219 | if (card->ctl_addr) | ||
5220 | iounmap(card->ctl_addr); | ||
5221 | if (card->irq | ||
5569 | #ifndef CONFIG_CYZ_INTR | 5222 | #ifndef CONFIG_CYZ_INTR |
5570 | && cy_card[i].num_chips != -1 /* not a Z card */ | 5223 | && !IS_CYC_Z(*card) |
5571 | #endif /* CONFIG_CYZ_INTR */ | 5224 | #endif /* CONFIG_CYZ_INTR */ |
5572 | ) | 5225 | ) |
5573 | free_irq(cy_card[i].irq, &cy_card[i]); | 5226 | free_irq(card->irq, card); |
5574 | #ifdef CONFIG_PCI | 5227 | for (e1 = card->first_line; |
5575 | if (cy_card[i].pdev) | 5228 | e1 < card->first_line + |
5576 | pci_release_regions(cy_card[i].pdev); | 5229 | card->nports; e1++) |
5577 | #endif | 5230 | tty_unregister_device(cy_serial_driver, e1); |
5231 | kfree(card->ports); | ||
5578 | } | 5232 | } |
5579 | } | 5233 | } |
5234 | |||
5235 | put_tty_driver(cy_serial_driver); | ||
5580 | } /* cy_cleanup_module */ | 5236 | } /* cy_cleanup_module */ |
5581 | 5237 | ||
5582 | module_init(cy_init); | 5238 | module_init(cy_init); |
5583 | module_exit(cy_cleanup_module); | 5239 | module_exit(cy_cleanup_module); |
5584 | 5240 | ||
5585 | MODULE_LICENSE("GPL"); | 5241 | MODULE_LICENSE("GPL"); |
5242 | MODULE_VERSION(CY_VERSION); | ||
diff --git a/drivers/char/digi.h b/drivers/char/digi.h deleted file mode 100644 index 19df0e879b1b..000000000000 --- a/drivers/char/digi.h +++ /dev/null | |||
@@ -1,71 +0,0 @@ | |||
1 | /* Definitions for DigiBoard ditty(1) command. */ | ||
2 | |||
3 | #if !defined(TIOCMODG) | ||
4 | #define TIOCMODG (('d'<<8) | 250) /* get modem ctrl state */ | ||
5 | #define TIOCMODS (('d'<<8) | 251) /* set modem ctrl state */ | ||
6 | #endif | ||
7 | |||
8 | #if !defined(TIOCMSET) | ||
9 | #define TIOCMSET (('d'<<8) | 252) /* set modem ctrl state */ | ||
10 | #define TIOCMGET (('d'<<8) | 253) /* set modem ctrl state */ | ||
11 | #endif | ||
12 | |||
13 | #if !defined(TIOCMBIC) | ||
14 | #define TIOCMBIC (('d'<<8) | 254) /* set modem ctrl state */ | ||
15 | #define TIOCMBIS (('d'<<8) | 255) /* set modem ctrl state */ | ||
16 | #endif | ||
17 | |||
18 | #if !defined(TIOCSDTR) | ||
19 | #define TIOCSDTR (('e'<<8) | 0) /* set DTR */ | ||
20 | #define TIOCCDTR (('e'<<8) | 1) /* clear DTR */ | ||
21 | #endif | ||
22 | |||
23 | /************************************************************************ | ||
24 | * Ioctl command arguments for DIGI parameters. | ||
25 | ************************************************************************/ | ||
26 | #define DIGI_GETA (('e'<<8) | 94) /* Read params */ | ||
27 | |||
28 | #define DIGI_SETA (('e'<<8) | 95) /* Set params */ | ||
29 | #define DIGI_SETAW (('e'<<8) | 96) /* Drain & set params */ | ||
30 | #define DIGI_SETAF (('e'<<8) | 97) /* Drain, flush & set params */ | ||
31 | |||
32 | #define DIGI_GETFLOW (('e'<<8) | 99) /* Get startc/stopc flow */ | ||
33 | /* control characters */ | ||
34 | #define DIGI_SETFLOW (('e'<<8) | 100) /* Set startc/stopc flow */ | ||
35 | /* control characters */ | ||
36 | #define DIGI_GETAFLOW (('e'<<8) | 101) /* Get Aux. startc/stopc */ | ||
37 | /* flow control chars */ | ||
38 | #define DIGI_SETAFLOW (('e'<<8) | 102) /* Set Aux. startc/stopc */ | ||
39 | /* flow control chars */ | ||
40 | |||
41 | struct digiflow_struct { | ||
42 | unsigned char startc; /* flow cntl start char */ | ||
43 | unsigned char stopc; /* flow cntl stop char */ | ||
44 | }; | ||
45 | |||
46 | typedef struct digiflow_struct digiflow_t; | ||
47 | |||
48 | |||
49 | /************************************************************************ | ||
50 | * Values for digi_flags | ||
51 | ************************************************************************/ | ||
52 | #define DIGI_IXON 0x0001 /* Handle IXON in the FEP */ | ||
53 | #define DIGI_FAST 0x0002 /* Fast baud rates */ | ||
54 | #define RTSPACE 0x0004 /* RTS input flow control */ | ||
55 | #define CTSPACE 0x0008 /* CTS output flow control */ | ||
56 | #define DSRPACE 0x0010 /* DSR output flow control */ | ||
57 | #define DCDPACE 0x0020 /* DCD output flow control */ | ||
58 | #define DTRPACE 0x0040 /* DTR input flow control */ | ||
59 | #define DIGI_FORCEDCD 0x0100 /* Force carrier */ | ||
60 | #define DIGI_ALTPIN 0x0200 /* Alternate RJ-45 pin config */ | ||
61 | #define DIGI_AIXON 0x0400 /* Aux flow control in fep */ | ||
62 | |||
63 | |||
64 | /************************************************************************ | ||
65 | * Structure used with ioctl commands for DIGI parameters. | ||
66 | ************************************************************************/ | ||
67 | struct digi_struct { | ||
68 | unsigned short digi_flags; /* Flags (see above) */ | ||
69 | }; | ||
70 | |||
71 | typedef struct digi_struct digi_t; | ||
diff --git a/drivers/char/drm/README.drm b/drivers/char/drm/README.drm index 6441e01e587c..af74cd79a279 100644 --- a/drivers/char/drm/README.drm +++ b/drivers/char/drm/README.drm | |||
@@ -1,6 +1,6 @@ | |||
1 | ************************************************************ | 1 | ************************************************************ |
2 | * For the very latest on DRI development, please see: * | 2 | * For the very latest on DRI development, please see: * |
3 | * http://dri.sourceforge.net/ * | 3 | * http://dri.freedesktop.org/ * |
4 | ************************************************************ | 4 | ************************************************************ |
5 | 5 | ||
6 | The Direct Rendering Manager (drm) is a device-independent kernel-level | 6 | The Direct Rendering Manager (drm) is a device-independent kernel-level |
@@ -26,21 +26,19 @@ ways: | |||
26 | 26 | ||
27 | 27 | ||
28 | Documentation on the DRI is available from: | 28 | Documentation on the DRI is available from: |
29 | http://precisioninsight.com/piinsights.html | 29 | http://dri.freedesktop.org/wiki/Documentation |
30 | http://sourceforge.net/project/showfiles.php?group_id=387 | ||
31 | http://dri.sourceforge.net/doc/ | ||
30 | 32 | ||
31 | For specific information about kernel-level support, see: | 33 | For specific information about kernel-level support, see: |
32 | 34 | ||
33 | The Direct Rendering Manager, Kernel Support for the Direct Rendering | 35 | The Direct Rendering Manager, Kernel Support for the Direct Rendering |
34 | Infrastructure | 36 | Infrastructure |
35 | http://precisioninsight.com/dr/drm.html | 37 | http://dri.sourceforge.net/doc/drm_low_level.html |
36 | 38 | ||
37 | Hardware Locking for the Direct Rendering Infrastructure | 39 | Hardware Locking for the Direct Rendering Infrastructure |
38 | http://precisioninsight.com/dr/locking.html | 40 | http://dri.sourceforge.net/doc/hardware_locking_low_level.html |
39 | 41 | ||
40 | A Security Analysis of the Direct Rendering Infrastructure | 42 | A Security Analysis of the Direct Rendering Infrastructure |
41 | http://precisioninsight.com/dr/security.html | 43 | http://dri.sourceforge.net/doc/security_low_level.html |
42 | 44 | ||
43 | ************************************************************ | ||
44 | * For the very latest on DRI development, please see: * | ||
45 | * http://dri.sourceforge.net/ * | ||
46 | ************************************************************ | ||
diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c index bd7be09ea53d..5b91bc04ea4e 100644 --- a/drivers/char/drm/ati_pcigart.c +++ b/drivers/char/drm/ati_pcigart.c | |||
@@ -33,59 +33,44 @@ | |||
33 | 33 | ||
34 | #include "drmP.h" | 34 | #include "drmP.h" |
35 | 35 | ||
36 | #if PAGE_SIZE == 65536 | ||
37 | # define ATI_PCIGART_TABLE_ORDER 0 | ||
38 | # define ATI_PCIGART_TABLE_PAGES (1 << 0) | ||
39 | #elif PAGE_SIZE == 16384 | ||
40 | # define ATI_PCIGART_TABLE_ORDER 1 | ||
41 | # define ATI_PCIGART_TABLE_PAGES (1 << 1) | ||
42 | #elif PAGE_SIZE == 8192 | ||
43 | # define ATI_PCIGART_TABLE_ORDER 2 | ||
44 | # define ATI_PCIGART_TABLE_PAGES (1 << 2) | ||
45 | #elif PAGE_SIZE == 4096 | ||
46 | # define ATI_PCIGART_TABLE_ORDER 3 | ||
47 | # define ATI_PCIGART_TABLE_PAGES (1 << 3) | ||
48 | #else | ||
49 | # error - PAGE_SIZE not 64K, 16K, 8K or 4K | ||
50 | #endif | ||
51 | |||
52 | # define ATI_MAX_PCIGART_PAGES 8192 /**< 32 MB aperture, 4K pages */ | ||
53 | # define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */ | 36 | # define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */ |
54 | 37 | ||
55 | static void *drm_ati_alloc_pcigart_table(void) | 38 | static void *drm_ati_alloc_pcigart_table(int order) |
56 | { | 39 | { |
57 | unsigned long address; | 40 | unsigned long address; |
58 | struct page *page; | 41 | struct page *page; |
59 | int i; | 42 | int i; |
60 | DRM_DEBUG("%s\n", __FUNCTION__); | 43 | |
44 | DRM_DEBUG("%s: alloc %d order\n", __FUNCTION__, order); | ||
61 | 45 | ||
62 | address = __get_free_pages(GFP_KERNEL | __GFP_COMP, | 46 | address = __get_free_pages(GFP_KERNEL | __GFP_COMP, |
63 | ATI_PCIGART_TABLE_ORDER); | 47 | order); |
64 | if (address == 0UL) { | 48 | if (address == 0UL) { |
65 | return NULL; | 49 | return NULL; |
66 | } | 50 | } |
67 | 51 | ||
68 | page = virt_to_page(address); | 52 | page = virt_to_page(address); |
69 | 53 | ||
70 | for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) | 54 | for (i = 0; i < order; i++, page++) |
71 | SetPageReserved(page); | 55 | SetPageReserved(page); |
72 | 56 | ||
73 | DRM_DEBUG("%s: returning 0x%08lx\n", __FUNCTION__, address); | 57 | DRM_DEBUG("%s: returning 0x%08lx\n", __FUNCTION__, address); |
74 | return (void *)address; | 58 | return (void *)address; |
75 | } | 59 | } |
76 | 60 | ||
77 | static void drm_ati_free_pcigart_table(void *address) | 61 | static void drm_ati_free_pcigart_table(void *address, int order) |
78 | { | 62 | { |
79 | struct page *page; | 63 | struct page *page; |
80 | int i; | 64 | int i; |
65 | int num_pages = 1 << order; | ||
81 | DRM_DEBUG("%s\n", __FUNCTION__); | 66 | DRM_DEBUG("%s\n", __FUNCTION__); |
82 | 67 | ||
83 | page = virt_to_page((unsigned long)address); | 68 | page = virt_to_page((unsigned long)address); |
84 | 69 | ||
85 | for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) | 70 | for (i = 0; i < num_pages; i++, page++) |
86 | ClearPageReserved(page); | 71 | ClearPageReserved(page); |
87 | 72 | ||
88 | free_pages((unsigned long)address, ATI_PCIGART_TABLE_ORDER); | 73 | free_pages((unsigned long)address, order); |
89 | } | 74 | } |
90 | 75 | ||
91 | int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) | 76 | int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) |
@@ -93,6 +78,8 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) | |||
93 | drm_sg_mem_t *entry = dev->sg; | 78 | drm_sg_mem_t *entry = dev->sg; |
94 | unsigned long pages; | 79 | unsigned long pages; |
95 | int i; | 80 | int i; |
81 | int order; | ||
82 | int num_pages, max_pages; | ||
96 | 83 | ||
97 | /* we need to support large memory configurations */ | 84 | /* we need to support large memory configurations */ |
98 | if (!entry) { | 85 | if (!entry) { |
@@ -100,15 +87,19 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) | |||
100 | return 0; | 87 | return 0; |
101 | } | 88 | } |
102 | 89 | ||
90 | order = drm_order((gart_info->table_size + (PAGE_SIZE-1)) / PAGE_SIZE); | ||
91 | num_pages = 1 << order; | ||
92 | |||
103 | if (gart_info->bus_addr) { | 93 | if (gart_info->bus_addr) { |
104 | if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { | 94 | if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { |
105 | pci_unmap_single(dev->pdev, gart_info->bus_addr, | 95 | pci_unmap_single(dev->pdev, gart_info->bus_addr, |
106 | ATI_PCIGART_TABLE_PAGES * PAGE_SIZE, | 96 | num_pages * PAGE_SIZE, |
107 | PCI_DMA_TODEVICE); | 97 | PCI_DMA_TODEVICE); |
108 | } | 98 | } |
109 | 99 | ||
110 | pages = (entry->pages <= ATI_MAX_PCIGART_PAGES) | 100 | max_pages = (gart_info->table_size / sizeof(u32)); |
111 | ? entry->pages : ATI_MAX_PCIGART_PAGES; | 101 | pages = (entry->pages <= max_pages) |
102 | ? entry->pages : max_pages; | ||
112 | 103 | ||
113 | for (i = 0; i < pages; i++) { | 104 | for (i = 0; i < pages; i++) { |
114 | if (!entry->busaddr[i]) | 105 | if (!entry->busaddr[i]) |
@@ -123,13 +114,12 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) | |||
123 | 114 | ||
124 | if (gart_info->gart_table_location == DRM_ATI_GART_MAIN | 115 | if (gart_info->gart_table_location == DRM_ATI_GART_MAIN |
125 | && gart_info->addr) { | 116 | && gart_info->addr) { |
126 | drm_ati_free_pcigart_table(gart_info->addr); | 117 | drm_ati_free_pcigart_table(gart_info->addr, order); |
127 | gart_info->addr = NULL; | 118 | gart_info->addr = NULL; |
128 | } | 119 | } |
129 | 120 | ||
130 | return 1; | 121 | return 1; |
131 | } | 122 | } |
132 | |||
133 | EXPORT_SYMBOL(drm_ati_pcigart_cleanup); | 123 | EXPORT_SYMBOL(drm_ati_pcigart_cleanup); |
134 | 124 | ||
135 | int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) | 125 | int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) |
@@ -139,6 +129,9 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) | |||
139 | unsigned long pages; | 129 | unsigned long pages; |
140 | u32 *pci_gart, page_base, bus_address = 0; | 130 | u32 *pci_gart, page_base, bus_address = 0; |
141 | int i, j, ret = 0; | 131 | int i, j, ret = 0; |
132 | int order; | ||
133 | int max_pages; | ||
134 | int num_pages; | ||
142 | 135 | ||
143 | if (!entry) { | 136 | if (!entry) { |
144 | DRM_ERROR("no scatter/gather memory!\n"); | 137 | DRM_ERROR("no scatter/gather memory!\n"); |
@@ -148,7 +141,10 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) | |||
148 | if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { | 141 | if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { |
149 | DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n"); | 142 | DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n"); |
150 | 143 | ||
151 | address = drm_ati_alloc_pcigart_table(); | 144 | order = drm_order((gart_info->table_size + |
145 | (PAGE_SIZE-1)) / PAGE_SIZE); | ||
146 | num_pages = 1 << order; | ||
147 | address = drm_ati_alloc_pcigart_table(order); | ||
152 | if (!address) { | 148 | if (!address) { |
153 | DRM_ERROR("cannot allocate PCI GART page!\n"); | 149 | DRM_ERROR("cannot allocate PCI GART page!\n"); |
154 | goto done; | 150 | goto done; |
@@ -160,11 +156,13 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) | |||
160 | } | 156 | } |
161 | 157 | ||
162 | bus_address = pci_map_single(dev->pdev, address, | 158 | bus_address = pci_map_single(dev->pdev, address, |
163 | ATI_PCIGART_TABLE_PAGES * | 159 | num_pages * PAGE_SIZE, |
164 | PAGE_SIZE, PCI_DMA_TODEVICE); | 160 | PCI_DMA_TODEVICE); |
165 | if (bus_address == 0) { | 161 | if (bus_address == 0) { |
166 | DRM_ERROR("unable to map PCIGART pages!\n"); | 162 | DRM_ERROR("unable to map PCIGART pages!\n"); |
167 | drm_ati_free_pcigart_table(address); | 163 | order = drm_order((gart_info->table_size + |
164 | (PAGE_SIZE-1)) / PAGE_SIZE); | ||
165 | drm_ati_free_pcigart_table(address, order); | ||
168 | address = NULL; | 166 | address = NULL; |
169 | goto done; | 167 | goto done; |
170 | } | 168 | } |
@@ -177,10 +175,11 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) | |||
177 | 175 | ||
178 | pci_gart = (u32 *) address; | 176 | pci_gart = (u32 *) address; |
179 | 177 | ||
180 | pages = (entry->pages <= ATI_MAX_PCIGART_PAGES) | 178 | max_pages = (gart_info->table_size / sizeof(u32)); |
181 | ? entry->pages : ATI_MAX_PCIGART_PAGES; | 179 | pages = (entry->pages <= max_pages) |
180 | ? entry->pages : max_pages; | ||
182 | 181 | ||
183 | memset(pci_gart, 0, ATI_MAX_PCIGART_PAGES * sizeof(u32)); | 182 | memset(pci_gart, 0, max_pages * sizeof(u32)); |
184 | 183 | ||
185 | for (i = 0; i < pages; i++) { | 184 | for (i = 0; i < pages; i++) { |
186 | /* we need to support large memory configurations */ | 185 | /* we need to support large memory configurations */ |
@@ -198,10 +197,18 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) | |||
198 | page_base = (u32) entry->busaddr[i]; | 197 | page_base = (u32) entry->busaddr[i]; |
199 | 198 | ||
200 | for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) { | 199 | for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) { |
201 | if (gart_info->is_pcie) | 200 | switch(gart_info->gart_reg_if) { |
201 | case DRM_ATI_GART_IGP: | ||
202 | *pci_gart = cpu_to_le32((page_base) | 0xc); | ||
203 | break; | ||
204 | case DRM_ATI_GART_PCIE: | ||
202 | *pci_gart = cpu_to_le32((page_base >> 8) | 0xc); | 205 | *pci_gart = cpu_to_le32((page_base >> 8) | 0xc); |
203 | else | 206 | break; |
207 | default: | ||
208 | case DRM_ATI_GART_PCI: | ||
204 | *pci_gart = cpu_to_le32(page_base); | 209 | *pci_gart = cpu_to_le32(page_base); |
210 | break; | ||
211 | } | ||
205 | pci_gart++; | 212 | pci_gart++; |
206 | page_base += ATI_PCIGART_PAGE_SIZE; | 213 | page_base += ATI_PCIGART_PAGE_SIZE; |
207 | } | 214 | } |
@@ -220,5 +227,4 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) | |||
220 | gart_info->bus_addr = bus_address; | 227 | gart_info->bus_addr = bus_address; |
221 | return ret; | 228 | return ret; |
222 | } | 229 | } |
223 | |||
224 | EXPORT_SYMBOL(drm_ati_pcigart_init); | 230 | EXPORT_SYMBOL(drm_ati_pcigart_init); |
diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h index 8db9041e306c..089198491f16 100644 --- a/drivers/char/drm/drm.h +++ b/drivers/char/drm/drm.h | |||
@@ -654,11 +654,13 @@ typedef struct drm_set_version { | |||
654 | 654 | ||
655 | /** | 655 | /** |
656 | * Device specific ioctls should only be in their respective headers | 656 | * Device specific ioctls should only be in their respective headers |
657 | * The device specific ioctl range is from 0x40 to 0x79. | 657 | * The device specific ioctl range is from 0x40 to 0x99. |
658 | * Generic IOCTLS restart at 0xA0. | ||
658 | * | 659 | * |
659 | * \sa drmCommandNone(), drmCommandRead(), drmCommandWrite(), and | 660 | * \sa drmCommandNone(), drmCommandRead(), drmCommandWrite(), and |
660 | * drmCommandReadWrite(). | 661 | * drmCommandReadWrite(). |
661 | */ | 662 | */ |
662 | #define DRM_COMMAND_BASE 0x40 | 663 | #define DRM_COMMAND_BASE 0x40 |
664 | #define DRM_COMMAND_END 0xA0 | ||
663 | 665 | ||
664 | #endif | 666 | #endif |
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 85d99e21e188..d494315752a2 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h | |||
@@ -414,6 +414,10 @@ typedef struct drm_lock_data { | |||
414 | struct file *filp; /**< File descr of lock holder (0=kernel) */ | 414 | struct file *filp; /**< File descr of lock holder (0=kernel) */ |
415 | wait_queue_head_t lock_queue; /**< Queue of blocked processes */ | 415 | wait_queue_head_t lock_queue; /**< Queue of blocked processes */ |
416 | unsigned long lock_time; /**< Time of last lock in jiffies */ | 416 | unsigned long lock_time; /**< Time of last lock in jiffies */ |
417 | spinlock_t spinlock; | ||
418 | uint32_t kernel_waiters; | ||
419 | uint32_t user_waiters; | ||
420 | int idle_has_lock; | ||
417 | } drm_lock_data_t; | 421 | } drm_lock_data_t; |
418 | 422 | ||
419 | /** | 423 | /** |
@@ -515,12 +519,17 @@ typedef struct drm_vbl_sig { | |||
515 | #define DRM_ATI_GART_MAIN 1 | 519 | #define DRM_ATI_GART_MAIN 1 |
516 | #define DRM_ATI_GART_FB 2 | 520 | #define DRM_ATI_GART_FB 2 |
517 | 521 | ||
522 | #define DRM_ATI_GART_PCI 1 | ||
523 | #define DRM_ATI_GART_PCIE 2 | ||
524 | #define DRM_ATI_GART_IGP 3 | ||
525 | |||
518 | typedef struct ati_pcigart_info { | 526 | typedef struct ati_pcigart_info { |
519 | int gart_table_location; | 527 | int gart_table_location; |
520 | int is_pcie; | 528 | int gart_reg_if; |
521 | void *addr; | 529 | void *addr; |
522 | dma_addr_t bus_addr; | 530 | dma_addr_t bus_addr; |
523 | drm_local_map_t mapping; | 531 | drm_local_map_t mapping; |
532 | int table_size; | ||
524 | } drm_ati_pcigart_info; | 533 | } drm_ati_pcigart_info; |
525 | 534 | ||
526 | /* | 535 | /* |
@@ -590,6 +599,8 @@ struct drm_driver { | |||
590 | void (*reclaim_buffers) (struct drm_device * dev, struct file * filp); | 599 | void (*reclaim_buffers) (struct drm_device * dev, struct file * filp); |
591 | void (*reclaim_buffers_locked) (struct drm_device *dev, | 600 | void (*reclaim_buffers_locked) (struct drm_device *dev, |
592 | struct file *filp); | 601 | struct file *filp); |
602 | void (*reclaim_buffers_idlelocked) (struct drm_device *dev, | ||
603 | struct file * filp); | ||
593 | unsigned long (*get_map_ofs) (drm_map_t * map); | 604 | unsigned long (*get_map_ofs) (drm_map_t * map); |
594 | unsigned long (*get_reg_ofs) (struct drm_device * dev); | 605 | unsigned long (*get_reg_ofs) (struct drm_device * dev); |
595 | void (*set_version) (struct drm_device * dev, drm_set_version_t * sv); | 606 | void (*set_version) (struct drm_device * dev, drm_set_version_t * sv); |
@@ -764,7 +775,7 @@ static __inline__ int drm_core_check_feature(struct drm_device *dev, | |||
764 | } | 775 | } |
765 | 776 | ||
766 | #ifdef __alpha__ | 777 | #ifdef __alpha__ |
767 | #define drm_get_pci_domain(dev) dev->hose->bus->number | 778 | #define drm_get_pci_domain(dev) dev->hose->index |
768 | #else | 779 | #else |
769 | #define drm_get_pci_domain(dev) 0 | 780 | #define drm_get_pci_domain(dev) 0 |
770 | #endif | 781 | #endif |
@@ -915,9 +926,18 @@ extern int drm_lock(struct inode *inode, struct file *filp, | |||
915 | unsigned int cmd, unsigned long arg); | 926 | unsigned int cmd, unsigned long arg); |
916 | extern int drm_unlock(struct inode *inode, struct file *filp, | 927 | extern int drm_unlock(struct inode *inode, struct file *filp, |
917 | unsigned int cmd, unsigned long arg); | 928 | unsigned int cmd, unsigned long arg); |
918 | extern int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context); | 929 | extern int drm_lock_take(drm_lock_data_t *lock_data, unsigned int context); |
919 | extern int drm_lock_free(drm_device_t * dev, | 930 | extern int drm_lock_free(drm_lock_data_t *lock_data, unsigned int context); |
920 | __volatile__ unsigned int *lock, unsigned int context); | 931 | extern void drm_idlelock_take(drm_lock_data_t *lock_data); |
932 | extern void drm_idlelock_release(drm_lock_data_t *lock_data); | ||
933 | |||
934 | /* | ||
935 | * These are exported to drivers so that they can implement fencing using | ||
936 | * DMA quiscent + idle. DMA quiescent usually requires the hardware lock. | ||
937 | */ | ||
938 | |||
939 | extern int drm_i_have_hw_lock(struct file *filp); | ||
940 | extern int drm_kernel_take_hw_lock(struct file *filp); | ||
921 | 941 | ||
922 | /* Buffer management support (drm_bufs.h) */ | 942 | /* Buffer management support (drm_bufs.h) */ |
923 | extern int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request); | 943 | extern int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request); |
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index a6828cc14e58..c11345856ffe 100644 --- a/drivers/char/drm/drm_bufs.c +++ b/drivers/char/drm/drm_bufs.c | |||
@@ -57,7 +57,8 @@ static drm_map_list_t *drm_find_matching_map(drm_device_t *dev, | |||
57 | list_for_each(list, &dev->maplist->head) { | 57 | list_for_each(list, &dev->maplist->head) { |
58 | drm_map_list_t *entry = list_entry(list, drm_map_list_t, head); | 58 | drm_map_list_t *entry = list_entry(list, drm_map_list_t, head); |
59 | if (entry->map && map->type == entry->map->type && | 59 | if (entry->map && map->type == entry->map->type && |
60 | entry->map->offset == map->offset) { | 60 | ((entry->map->offset == map->offset) || |
61 | (map->type == _DRM_SHM && map->flags==_DRM_CONTAINS_LOCK))) { | ||
61 | return entry; | 62 | return entry; |
62 | } | 63 | } |
63 | } | 64 | } |
@@ -180,8 +181,20 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, | |||
180 | if (map->type == _DRM_REGISTERS) | 181 | if (map->type == _DRM_REGISTERS) |
181 | map->handle = ioremap(map->offset, map->size); | 182 | map->handle = ioremap(map->offset, map->size); |
182 | break; | 183 | break; |
183 | |||
184 | case _DRM_SHM: | 184 | case _DRM_SHM: |
185 | list = drm_find_matching_map(dev, map); | ||
186 | if (list != NULL) { | ||
187 | if(list->map->size != map->size) { | ||
188 | DRM_DEBUG("Matching maps of type %d with " | ||
189 | "mismatched sizes, (%ld vs %ld)\n", | ||
190 | map->type, map->size, list->map->size); | ||
191 | list->map->size = map->size; | ||
192 | } | ||
193 | |||
194 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | ||
195 | *maplist = list; | ||
196 | return 0; | ||
197 | } | ||
185 | map->handle = vmalloc_user(map->size); | 198 | map->handle = vmalloc_user(map->size); |
186 | DRM_DEBUG("%lu %d %p\n", | 199 | DRM_DEBUG("%lu %d %p\n", |
187 | map->size, drm_order(map->size), map->handle); | 200 | map->size, drm_order(map->size), map->handle); |
@@ -200,15 +213,45 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, | |||
200 | dev->sigdata.lock = dev->lock.hw_lock = map->handle; /* Pointer to lock */ | 213 | dev->sigdata.lock = dev->lock.hw_lock = map->handle; /* Pointer to lock */ |
201 | } | 214 | } |
202 | break; | 215 | break; |
203 | case _DRM_AGP: | 216 | case _DRM_AGP: { |
204 | if (drm_core_has_AGP(dev)) { | 217 | drm_agp_mem_t *entry; |
218 | int valid = 0; | ||
219 | |||
220 | if (!drm_core_has_AGP(dev)) { | ||
221 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | ||
222 | return -EINVAL; | ||
223 | } | ||
205 | #ifdef __alpha__ | 224 | #ifdef __alpha__ |
206 | map->offset += dev->hose->mem_space->start; | 225 | map->offset += dev->hose->mem_space->start; |
207 | #endif | 226 | #endif |
208 | map->offset += dev->agp->base; | 227 | /* Note: dev->agp->base may actually be 0 when the DRM |
209 | map->mtrr = dev->agp->agp_mtrr; /* for getmap */ | 228 | * is not in control of AGP space. But if user space is |
229 | * it should already have added the AGP base itself. | ||
230 | */ | ||
231 | map->offset += dev->agp->base; | ||
232 | map->mtrr = dev->agp->agp_mtrr; /* for getmap */ | ||
233 | |||
234 | /* This assumes the DRM is in total control of AGP space. | ||
235 | * It's not always the case as AGP can be in the control | ||
236 | * of user space (i.e. i810 driver). So this loop will get | ||
237 | * skipped and we double check that dev->agp->memory is | ||
238 | * actually set as well as being invalid before EPERM'ing | ||
239 | */ | ||
240 | for (entry = dev->agp->memory; entry; entry = entry->next) { | ||
241 | if ((map->offset >= entry->bound) && | ||
242 | (map->offset + map->size <= entry->bound + entry->pages * PAGE_SIZE)) { | ||
243 | valid = 1; | ||
244 | break; | ||
245 | } | ||
210 | } | 246 | } |
247 | if (dev->agp->memory && !valid) { | ||
248 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | ||
249 | return -EPERM; | ||
250 | } | ||
251 | DRM_DEBUG("AGP offset = 0x%08lx, size = 0x%08lx\n", map->offset, map->size); | ||
252 | |||
211 | break; | 253 | break; |
254 | } | ||
212 | case _DRM_SCATTER_GATHER: | 255 | case _DRM_SCATTER_GATHER: |
213 | if (!dev->sg) { | 256 | if (!dev->sg) { |
214 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | 257 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); |
@@ -267,7 +310,7 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, | |||
267 | 310 | ||
268 | *maplist = list; | 311 | *maplist = list; |
269 | return 0; | 312 | return 0; |
270 | } | 313 | } |
271 | 314 | ||
272 | int drm_addmap(drm_device_t * dev, unsigned int offset, | 315 | int drm_addmap(drm_device_t * dev, unsigned int offset, |
273 | unsigned int size, drm_map_type_t type, | 316 | unsigned int size, drm_map_type_t type, |
@@ -519,6 +562,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request) | |||
519 | { | 562 | { |
520 | drm_device_dma_t *dma = dev->dma; | 563 | drm_device_dma_t *dma = dev->dma; |
521 | drm_buf_entry_t *entry; | 564 | drm_buf_entry_t *entry; |
565 | drm_agp_mem_t *agp_entry; | ||
522 | drm_buf_t *buf; | 566 | drm_buf_t *buf; |
523 | unsigned long offset; | 567 | unsigned long offset; |
524 | unsigned long agp_offset; | 568 | unsigned long agp_offset; |
@@ -529,7 +573,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request) | |||
529 | int page_order; | 573 | int page_order; |
530 | int total; | 574 | int total; |
531 | int byte_count; | 575 | int byte_count; |
532 | int i; | 576 | int i, valid; |
533 | drm_buf_t **temp_buflist; | 577 | drm_buf_t **temp_buflist; |
534 | 578 | ||
535 | if (!dma) | 579 | if (!dma) |
@@ -560,6 +604,19 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request) | |||
560 | if (dev->queue_count) | 604 | if (dev->queue_count) |
561 | return -EBUSY; /* Not while in use */ | 605 | return -EBUSY; /* Not while in use */ |
562 | 606 | ||
607 | /* Make sure buffers are located in AGP memory that we own */ | ||
608 | valid = 0; | ||
609 | for (agp_entry = dev->agp->memory; agp_entry; agp_entry = agp_entry->next) { | ||
610 | if ((agp_offset >= agp_entry->bound) && | ||
611 | (agp_offset + total * count <= agp_entry->bound + agp_entry->pages * PAGE_SIZE)) { | ||
612 | valid = 1; | ||
613 | break; | ||
614 | } | ||
615 | } | ||
616 | if (dev->agp->memory && !valid) { | ||
617 | DRM_DEBUG("zone invalid\n"); | ||
618 | return -EINVAL; | ||
619 | } | ||
563 | spin_lock(&dev->count_lock); | 620 | spin_lock(&dev->count_lock); |
564 | if (dev->buf_use) { | 621 | if (dev->buf_use) { |
565 | spin_unlock(&dev->count_lock); | 622 | spin_unlock(&dev->count_lock); |
diff --git a/drivers/char/drm/drm_dma.c b/drivers/char/drm/drm_dma.c index 892db7096986..32ed19c9ec1c 100644 --- a/drivers/char/drm/drm_dma.c +++ b/drivers/char/drm/drm_dma.c | |||
@@ -65,7 +65,7 @@ int drm_dma_setup(drm_device_t * dev) | |||
65 | * \param dev DRM device. | 65 | * \param dev DRM device. |
66 | * | 66 | * |
67 | * Free all pages associated with DMA buffers, the buffers and pages lists, and | 67 | * Free all pages associated with DMA buffers, the buffers and pages lists, and |
68 | * finally the the drm_device::dma structure itself. | 68 | * finally the drm_device::dma structure itself. |
69 | */ | 69 | */ |
70 | void drm_dma_takedown(drm_device_t * dev) | 70 | void drm_dma_takedown(drm_device_t * dev) |
71 | { | 71 | { |
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c index f5b9b2480c14..8e77b7ed0f44 100644 --- a/drivers/char/drm/drm_drv.c +++ b/drivers/char/drm/drm_drv.c | |||
@@ -15,8 +15,6 @@ | |||
15 | * #define DRIVER_DESC "Matrox G200/G400" | 15 | * #define DRIVER_DESC "Matrox G200/G400" |
16 | * #define DRIVER_DATE "20001127" | 16 | * #define DRIVER_DATE "20001127" |
17 | * | 17 | * |
18 | * #define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( mga_ioctls ) | ||
19 | * | ||
20 | * #define drm_x mga_##x | 18 | * #define drm_x mga_##x |
21 | * \endcode | 19 | * \endcode |
22 | */ | 20 | */ |
@@ -120,7 +118,7 @@ static drm_ioctl_desc_t drm_ioctls[] = { | |||
120 | [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW)] = {drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, | 118 | [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW)] = {drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
121 | }; | 119 | }; |
122 | 120 | ||
123 | #define DRIVER_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) | 121 | #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) |
124 | 122 | ||
125 | /** | 123 | /** |
126 | * Take down the DRM device. | 124 | * Take down the DRM device. |
@@ -496,11 +494,14 @@ int drm_ioctl(struct inode *inode, struct file *filp, | |||
496 | (long)old_encode_dev(priv->head->device), | 494 | (long)old_encode_dev(priv->head->device), |
497 | priv->authenticated); | 495 | priv->authenticated); |
498 | 496 | ||
499 | if (nr < DRIVER_IOCTL_COUNT) | 497 | if ((nr >= DRM_CORE_IOCTL_COUNT) && |
500 | ioctl = &drm_ioctls[nr]; | 498 | ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END))) |
501 | else if ((nr >= DRM_COMMAND_BASE) | 499 | goto err_i1; |
502 | && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) | 500 | if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) && |
501 | (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) | ||
503 | ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE]; | 502 | ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE]; |
503 | else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) | ||
504 | ioctl = &drm_ioctls[nr]; | ||
504 | else | 505 | else |
505 | goto err_i1; | 506 | goto err_i1; |
506 | 507 | ||
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c index 898f47dafec0..3b159cab3bc8 100644 --- a/drivers/char/drm/drm_fops.c +++ b/drivers/char/drm/drm_fops.c | |||
@@ -46,6 +46,7 @@ static int drm_setup(drm_device_t * dev) | |||
46 | drm_local_map_t *map; | 46 | drm_local_map_t *map; |
47 | int i; | 47 | int i; |
48 | int ret; | 48 | int ret; |
49 | u32 sareapage; | ||
49 | 50 | ||
50 | if (dev->driver->firstopen) { | 51 | if (dev->driver->firstopen) { |
51 | ret = dev->driver->firstopen(dev); | 52 | ret = dev->driver->firstopen(dev); |
@@ -56,7 +57,8 @@ static int drm_setup(drm_device_t * dev) | |||
56 | dev->magicfree.next = NULL; | 57 | dev->magicfree.next = NULL; |
57 | 58 | ||
58 | /* prebuild the SAREA */ | 59 | /* prebuild the SAREA */ |
59 | i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM, _DRM_CONTAINS_LOCK, &map); | 60 | sareapage = max_t(unsigned, SAREA_MAX, PAGE_SIZE); |
61 | i = drm_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK, &map); | ||
60 | if (i != 0) | 62 | if (i != 0) |
61 | return i; | 63 | return i; |
62 | 64 | ||
@@ -84,7 +86,7 @@ static int drm_setup(drm_device_t * dev) | |||
84 | INIT_LIST_HEAD(&dev->ctxlist->head); | 86 | INIT_LIST_HEAD(&dev->ctxlist->head); |
85 | 87 | ||
86 | dev->vmalist = NULL; | 88 | dev->vmalist = NULL; |
87 | dev->sigdata.lock = dev->lock.hw_lock = NULL; | 89 | dev->sigdata.lock = NULL; |
88 | init_waitqueue_head(&dev->lock.lock_queue); | 90 | init_waitqueue_head(&dev->lock.lock_queue); |
89 | dev->queue_count = 0; | 91 | dev->queue_count = 0; |
90 | dev->queue_reserved = 0; | 92 | dev->queue_reserved = 0; |
@@ -354,58 +356,56 @@ int drm_release(struct inode *inode, struct file *filp) | |||
354 | current->pid, (long)old_encode_dev(priv->head->device), | 356 | current->pid, (long)old_encode_dev(priv->head->device), |
355 | dev->open_count); | 357 | dev->open_count); |
356 | 358 | ||
357 | if (priv->lock_count && dev->lock.hw_lock && | 359 | if (dev->driver->reclaim_buffers_locked && dev->lock.hw_lock) { |
358 | _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) && | 360 | if (drm_i_have_hw_lock(filp)) { |
359 | dev->lock.filp == filp) { | ||
360 | DRM_DEBUG("File %p released, freeing lock for context %d\n", | ||
361 | filp, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); | ||
362 | |||
363 | if (dev->driver->reclaim_buffers_locked) | ||
364 | dev->driver->reclaim_buffers_locked(dev, filp); | 361 | dev->driver->reclaim_buffers_locked(dev, filp); |
365 | 362 | } else { | |
366 | drm_lock_free(dev, &dev->lock.hw_lock->lock, | 363 | unsigned long _end=jiffies + 3*DRM_HZ; |
367 | _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); | 364 | int locked = 0; |
368 | 365 | ||
369 | /* FIXME: may require heavy-handed reset of | 366 | drm_idlelock_take(&dev->lock); |
370 | hardware at this point, possibly | 367 | |
371 | processed via a callback to the X | 368 | /* |
372 | server. */ | 369 | * Wait for a while. |
373 | } else if (dev->driver->reclaim_buffers_locked && priv->lock_count | 370 | */ |
374 | && dev->lock.hw_lock) { | 371 | |
375 | /* The lock is required to reclaim buffers */ | 372 | do{ |
376 | DECLARE_WAITQUEUE(entry, current); | 373 | spin_lock(&dev->lock.spinlock); |
377 | 374 | locked = dev->lock.idle_has_lock; | |
378 | add_wait_queue(&dev->lock.lock_queue, &entry); | 375 | spin_unlock(&dev->lock.spinlock); |
379 | for (;;) { | 376 | if (locked) |
380 | __set_current_state(TASK_INTERRUPTIBLE); | 377 | break; |
381 | if (!dev->lock.hw_lock) { | 378 | schedule(); |
382 | /* Device has been unregistered */ | 379 | } while (!time_after_eq(jiffies, _end)); |
383 | retcode = -EINTR; | 380 | |
384 | break; | 381 | if (!locked) { |
382 | DRM_ERROR("reclaim_buffers_locked() deadlock. Please rework this\n" | ||
383 | "\tdriver to use reclaim_buffers_idlelocked() instead.\n" | ||
384 | "\tI will go on reclaiming the buffers anyway.\n"); | ||
385 | } | 385 | } |
386 | if (drm_lock_take(&dev->lock.hw_lock->lock, | 386 | |
387 | DRM_KERNEL_CONTEXT)) { | ||
388 | dev->lock.filp = filp; | ||
389 | dev->lock.lock_time = jiffies; | ||
390 | atomic_inc(&dev->counts[_DRM_STAT_LOCKS]); | ||
391 | break; /* Got lock */ | ||
392 | } | ||
393 | /* Contention */ | ||
394 | schedule(); | ||
395 | if (signal_pending(current)) { | ||
396 | retcode = -ERESTARTSYS; | ||
397 | break; | ||
398 | } | ||
399 | } | ||
400 | __set_current_state(TASK_RUNNING); | ||
401 | remove_wait_queue(&dev->lock.lock_queue, &entry); | ||
402 | if (!retcode) { | ||
403 | dev->driver->reclaim_buffers_locked(dev, filp); | 387 | dev->driver->reclaim_buffers_locked(dev, filp); |
404 | drm_lock_free(dev, &dev->lock.hw_lock->lock, | 388 | drm_idlelock_release(&dev->lock); |
405 | DRM_KERNEL_CONTEXT); | ||
406 | } | 389 | } |
407 | } | 390 | } |
408 | 391 | ||
392 | if (dev->driver->reclaim_buffers_idlelocked && dev->lock.hw_lock) { | ||
393 | |||
394 | drm_idlelock_take(&dev->lock); | ||
395 | dev->driver->reclaim_buffers_idlelocked(dev, filp); | ||
396 | drm_idlelock_release(&dev->lock); | ||
397 | |||
398 | } | ||
399 | |||
400 | if (drm_i_have_hw_lock(filp)) { | ||
401 | DRM_DEBUG("File %p released, freeing lock for context %d\n", | ||
402 | filp, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); | ||
403 | |||
404 | drm_lock_free(&dev->lock, | ||
405 | _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); | ||
406 | } | ||
407 | |||
408 | |||
409 | if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && | 409 | if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && |
410 | !dev->driver->reclaim_buffers_locked) { | 410 | !dev->driver->reclaim_buffers_locked) { |
411 | dev->driver->reclaim_buffers(dev, filp); | 411 | dev->driver->reclaim_buffers(dev, filp); |
diff --git a/drivers/char/drm/drm_hashtab.c b/drivers/char/drm/drm_hashtab.c index a0b2d6802ae4..31acb621dcce 100644 --- a/drivers/char/drm/drm_hashtab.c +++ b/drivers/char/drm/drm_hashtab.c | |||
@@ -43,7 +43,16 @@ int drm_ht_create(drm_open_hash_t *ht, unsigned int order) | |||
43 | ht->size = 1 << order; | 43 | ht->size = 1 << order; |
44 | ht->order = order; | 44 | ht->order = order; |
45 | ht->fill = 0; | 45 | ht->fill = 0; |
46 | ht->table = vmalloc(ht->size*sizeof(*ht->table)); | 46 | ht->table = NULL; |
47 | ht->use_vmalloc = ((ht->size * sizeof(*ht->table)) > PAGE_SIZE); | ||
48 | if (!ht->use_vmalloc) { | ||
49 | ht->table = drm_calloc(ht->size, sizeof(*ht->table), | ||
50 | DRM_MEM_HASHTAB); | ||
51 | } | ||
52 | if (!ht->table) { | ||
53 | ht->use_vmalloc = 1; | ||
54 | ht->table = vmalloc(ht->size*sizeof(*ht->table)); | ||
55 | } | ||
47 | if (!ht->table) { | 56 | if (!ht->table) { |
48 | DRM_ERROR("Out of memory for hash table\n"); | 57 | DRM_ERROR("Out of memory for hash table\n"); |
49 | return -ENOMEM; | 58 | return -ENOMEM; |
@@ -183,7 +192,11 @@ int drm_ht_remove_item(drm_open_hash_t *ht, drm_hash_item_t *item) | |||
183 | void drm_ht_remove(drm_open_hash_t *ht) | 192 | void drm_ht_remove(drm_open_hash_t *ht) |
184 | { | 193 | { |
185 | if (ht->table) { | 194 | if (ht->table) { |
186 | vfree(ht->table); | 195 | if (ht->use_vmalloc) |
196 | vfree(ht->table); | ||
197 | else | ||
198 | drm_free(ht->table, ht->size * sizeof(*ht->table), | ||
199 | DRM_MEM_HASHTAB); | ||
187 | ht->table = NULL; | 200 | ht->table = NULL; |
188 | } | 201 | } |
189 | } | 202 | } |
diff --git a/drivers/char/drm/drm_hashtab.h b/drivers/char/drm/drm_hashtab.h index 40afec05bff8..613091c970af 100644 --- a/drivers/char/drm/drm_hashtab.h +++ b/drivers/char/drm/drm_hashtab.h | |||
@@ -47,6 +47,7 @@ typedef struct drm_open_hash{ | |||
47 | unsigned int order; | 47 | unsigned int order; |
48 | unsigned int fill; | 48 | unsigned int fill; |
49 | struct hlist_head *table; | 49 | struct hlist_head *table; |
50 | int use_vmalloc; | ||
50 | } drm_open_hash_t; | 51 | } drm_open_hash_t; |
51 | 52 | ||
52 | 53 | ||
diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c index 9d00c51fe2c4..2e75331fd83e 100644 --- a/drivers/char/drm/drm_irq.c +++ b/drivers/char/drm/drm_irq.c | |||
@@ -424,7 +424,7 @@ static void drm_locked_tasklet_func(unsigned long data) | |||
424 | spin_lock_irqsave(&dev->tasklet_lock, irqflags); | 424 | spin_lock_irqsave(&dev->tasklet_lock, irqflags); |
425 | 425 | ||
426 | if (!dev->locked_tasklet_func || | 426 | if (!dev->locked_tasklet_func || |
427 | !drm_lock_take(&dev->lock.hw_lock->lock, | 427 | !drm_lock_take(&dev->lock, |
428 | DRM_KERNEL_CONTEXT)) { | 428 | DRM_KERNEL_CONTEXT)) { |
429 | spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); | 429 | spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); |
430 | return; | 430 | return; |
@@ -435,7 +435,7 @@ static void drm_locked_tasklet_func(unsigned long data) | |||
435 | 435 | ||
436 | dev->locked_tasklet_func(dev); | 436 | dev->locked_tasklet_func(dev); |
437 | 437 | ||
438 | drm_lock_free(dev, &dev->lock.hw_lock->lock, | 438 | drm_lock_free(&dev->lock, |
439 | DRM_KERNEL_CONTEXT); | 439 | DRM_KERNEL_CONTEXT); |
440 | 440 | ||
441 | dev->locked_tasklet_func = NULL; | 441 | dev->locked_tasklet_func = NULL; |
diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c index e9993ba461a2..befd1af19dfe 100644 --- a/drivers/char/drm/drm_lock.c +++ b/drivers/char/drm/drm_lock.c | |||
@@ -35,9 +35,6 @@ | |||
35 | 35 | ||
36 | #include "drmP.h" | 36 | #include "drmP.h" |
37 | 37 | ||
38 | static int drm_lock_transfer(drm_device_t * dev, | ||
39 | __volatile__ unsigned int *lock, | ||
40 | unsigned int context); | ||
41 | static int drm_notifier(void *priv); | 38 | static int drm_notifier(void *priv); |
42 | 39 | ||
43 | /** | 40 | /** |
@@ -80,6 +77,9 @@ int drm_lock(struct inode *inode, struct file *filp, | |||
80 | return -EINVAL; | 77 | return -EINVAL; |
81 | 78 | ||
82 | add_wait_queue(&dev->lock.lock_queue, &entry); | 79 | add_wait_queue(&dev->lock.lock_queue, &entry); |
80 | spin_lock(&dev->lock.spinlock); | ||
81 | dev->lock.user_waiters++; | ||
82 | spin_unlock(&dev->lock.spinlock); | ||
83 | for (;;) { | 83 | for (;;) { |
84 | __set_current_state(TASK_INTERRUPTIBLE); | 84 | __set_current_state(TASK_INTERRUPTIBLE); |
85 | if (!dev->lock.hw_lock) { | 85 | if (!dev->lock.hw_lock) { |
@@ -87,7 +87,7 @@ int drm_lock(struct inode *inode, struct file *filp, | |||
87 | ret = -EINTR; | 87 | ret = -EINTR; |
88 | break; | 88 | break; |
89 | } | 89 | } |
90 | if (drm_lock_take(&dev->lock.hw_lock->lock, lock.context)) { | 90 | if (drm_lock_take(&dev->lock, lock.context)) { |
91 | dev->lock.filp = filp; | 91 | dev->lock.filp = filp; |
92 | dev->lock.lock_time = jiffies; | 92 | dev->lock.lock_time = jiffies; |
93 | atomic_inc(&dev->counts[_DRM_STAT_LOCKS]); | 93 | atomic_inc(&dev->counts[_DRM_STAT_LOCKS]); |
@@ -101,12 +101,14 @@ int drm_lock(struct inode *inode, struct file *filp, | |||
101 | break; | 101 | break; |
102 | } | 102 | } |
103 | } | 103 | } |
104 | spin_lock(&dev->lock.spinlock); | ||
105 | dev->lock.user_waiters--; | ||
106 | spin_unlock(&dev->lock.spinlock); | ||
104 | __set_current_state(TASK_RUNNING); | 107 | __set_current_state(TASK_RUNNING); |
105 | remove_wait_queue(&dev->lock.lock_queue, &entry); | 108 | remove_wait_queue(&dev->lock.lock_queue, &entry); |
106 | 109 | ||
107 | DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock"); | 110 | DRM_DEBUG( "%d %s\n", lock.context, ret ? "interrupted" : "has lock" ); |
108 | if (ret) | 111 | if (ret) return ret; |
109 | return ret; | ||
110 | 112 | ||
111 | sigemptyset(&dev->sigmask); | 113 | sigemptyset(&dev->sigmask); |
112 | sigaddset(&dev->sigmask, SIGSTOP); | 114 | sigaddset(&dev->sigmask, SIGSTOP); |
@@ -127,14 +129,12 @@ int drm_lock(struct inode *inode, struct file *filp, | |||
127 | } | 129 | } |
128 | } | 130 | } |
129 | 131 | ||
130 | /* dev->driver->kernel_context_switch isn't used by any of the x86 | ||
131 | * drivers but is used by the Sparc driver. | ||
132 | */ | ||
133 | if (dev->driver->kernel_context_switch && | 132 | if (dev->driver->kernel_context_switch && |
134 | dev->last_context != lock.context) { | 133 | dev->last_context != lock.context) { |
135 | dev->driver->kernel_context_switch(dev, dev->last_context, | 134 | dev->driver->kernel_context_switch(dev, dev->last_context, |
136 | lock.context); | 135 | lock.context); |
137 | } | 136 | } |
137 | |||
138 | return 0; | 138 | return 0; |
139 | } | 139 | } |
140 | 140 | ||
@@ -184,12 +184,8 @@ int drm_unlock(struct inode *inode, struct file *filp, | |||
184 | if (dev->driver->kernel_context_switch_unlock) | 184 | if (dev->driver->kernel_context_switch_unlock) |
185 | dev->driver->kernel_context_switch_unlock(dev); | 185 | dev->driver->kernel_context_switch_unlock(dev); |
186 | else { | 186 | else { |
187 | drm_lock_transfer(dev, &dev->lock.hw_lock->lock, | 187 | if (drm_lock_free(&dev->lock,lock.context)) { |
188 | DRM_KERNEL_CONTEXT); | 188 | /* FIXME: Should really bail out here. */ |
189 | |||
190 | if (drm_lock_free(dev, &dev->lock.hw_lock->lock, | ||
191 | DRM_KERNEL_CONTEXT)) { | ||
192 | DRM_ERROR("\n"); | ||
193 | } | 189 | } |
194 | } | 190 | } |
195 | 191 | ||
@@ -206,18 +202,26 @@ int drm_unlock(struct inode *inode, struct file *filp, | |||
206 | * | 202 | * |
207 | * Attempt to mark the lock as held by the given context, via the \p cmpxchg instruction. | 203 | * Attempt to mark the lock as held by the given context, via the \p cmpxchg instruction. |
208 | */ | 204 | */ |
209 | int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context) | 205 | int drm_lock_take(drm_lock_data_t *lock_data, |
206 | unsigned int context) | ||
210 | { | 207 | { |
211 | unsigned int old, new, prev; | 208 | unsigned int old, new, prev; |
209 | volatile unsigned int *lock = &lock_data->hw_lock->lock; | ||
212 | 210 | ||
211 | spin_lock(&lock_data->spinlock); | ||
213 | do { | 212 | do { |
214 | old = *lock; | 213 | old = *lock; |
215 | if (old & _DRM_LOCK_HELD) | 214 | if (old & _DRM_LOCK_HELD) |
216 | new = old | _DRM_LOCK_CONT; | 215 | new = old | _DRM_LOCK_CONT; |
217 | else | 216 | else { |
218 | new = context | _DRM_LOCK_HELD; | 217 | new = context | _DRM_LOCK_HELD | |
218 | ((lock_data->user_waiters + lock_data->kernel_waiters > 1) ? | ||
219 | _DRM_LOCK_CONT : 0); | ||
220 | } | ||
219 | prev = cmpxchg(lock, old, new); | 221 | prev = cmpxchg(lock, old, new); |
220 | } while (prev != old); | 222 | } while (prev != old); |
223 | spin_unlock(&lock_data->spinlock); | ||
224 | |||
221 | if (_DRM_LOCKING_CONTEXT(old) == context) { | 225 | if (_DRM_LOCKING_CONTEXT(old) == context) { |
222 | if (old & _DRM_LOCK_HELD) { | 226 | if (old & _DRM_LOCK_HELD) { |
223 | if (context != DRM_KERNEL_CONTEXT) { | 227 | if (context != DRM_KERNEL_CONTEXT) { |
@@ -227,7 +231,8 @@ int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context) | |||
227 | return 0; | 231 | return 0; |
228 | } | 232 | } |
229 | } | 233 | } |
230 | if (new == (context | _DRM_LOCK_HELD)) { | 234 | |
235 | if ((_DRM_LOCKING_CONTEXT(new)) == context && (new & _DRM_LOCK_HELD)) { | ||
231 | /* Have lock */ | 236 | /* Have lock */ |
232 | return 1; | 237 | return 1; |
233 | } | 238 | } |
@@ -246,13 +251,13 @@ int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context) | |||
246 | * Resets the lock file pointer. | 251 | * Resets the lock file pointer. |
247 | * Marks the lock as held by the given context, via the \p cmpxchg instruction. | 252 | * Marks the lock as held by the given context, via the \p cmpxchg instruction. |
248 | */ | 253 | */ |
249 | static int drm_lock_transfer(drm_device_t * dev, | 254 | static int drm_lock_transfer(drm_lock_data_t *lock_data, |
250 | __volatile__ unsigned int *lock, | ||
251 | unsigned int context) | 255 | unsigned int context) |
252 | { | 256 | { |
253 | unsigned int old, new, prev; | 257 | unsigned int old, new, prev; |
258 | volatile unsigned int *lock = &lock_data->hw_lock->lock; | ||
254 | 259 | ||
255 | dev->lock.filp = NULL; | 260 | lock_data->filp = NULL; |
256 | do { | 261 | do { |
257 | old = *lock; | 262 | old = *lock; |
258 | new = context | _DRM_LOCK_HELD; | 263 | new = context | _DRM_LOCK_HELD; |
@@ -272,23 +277,32 @@ static int drm_lock_transfer(drm_device_t * dev, | |||
272 | * Marks the lock as not held, via the \p cmpxchg instruction. Wakes any task | 277 | * Marks the lock as not held, via the \p cmpxchg instruction. Wakes any task |
273 | * waiting on the lock queue. | 278 | * waiting on the lock queue. |
274 | */ | 279 | */ |
275 | int drm_lock_free(drm_device_t * dev, | 280 | int drm_lock_free(drm_lock_data_t *lock_data, unsigned int context) |
276 | __volatile__ unsigned int *lock, unsigned int context) | ||
277 | { | 281 | { |
278 | unsigned int old, new, prev; | 282 | unsigned int old, new, prev; |
283 | volatile unsigned int *lock = &lock_data->hw_lock->lock; | ||
284 | |||
285 | spin_lock(&lock_data->spinlock); | ||
286 | if (lock_data->kernel_waiters != 0) { | ||
287 | drm_lock_transfer(lock_data, 0); | ||
288 | lock_data->idle_has_lock = 1; | ||
289 | spin_unlock(&lock_data->spinlock); | ||
290 | return 1; | ||
291 | } | ||
292 | spin_unlock(&lock_data->spinlock); | ||
279 | 293 | ||
280 | dev->lock.filp = NULL; | ||
281 | do { | 294 | do { |
282 | old = *lock; | 295 | old = *lock; |
283 | new = 0; | 296 | new = _DRM_LOCKING_CONTEXT(old); |
284 | prev = cmpxchg(lock, old, new); | 297 | prev = cmpxchg(lock, old, new); |
285 | } while (prev != old); | 298 | } while (prev != old); |
299 | |||
286 | if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) { | 300 | if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) { |
287 | DRM_ERROR("%d freed heavyweight lock held by %d\n", | 301 | DRM_ERROR("%d freed heavyweight lock held by %d\n", |
288 | context, _DRM_LOCKING_CONTEXT(old)); | 302 | context, _DRM_LOCKING_CONTEXT(old)); |
289 | return 1; | 303 | return 1; |
290 | } | 304 | } |
291 | wake_up_interruptible(&dev->lock.lock_queue); | 305 | wake_up_interruptible(&lock_data->lock_queue); |
292 | return 0; | 306 | return 0; |
293 | } | 307 | } |
294 | 308 | ||
@@ -322,3 +336,67 @@ static int drm_notifier(void *priv) | |||
322 | } while (prev != old); | 336 | } while (prev != old); |
323 | return 0; | 337 | return 0; |
324 | } | 338 | } |
339 | |||
340 | /** | ||
341 | * This function returns immediately and takes the hw lock | ||
342 | * with the kernel context if it is free, otherwise it gets the highest priority when and if | ||
343 | * it is eventually released. | ||
344 | * | ||
345 | * This guarantees that the kernel will _eventually_ have the lock _unless_ it is held | ||
346 | * by a blocked process. (In the latter case an explicit wait for the hardware lock would cause | ||
347 | * a deadlock, which is why the "idlelock" was invented). | ||
348 | * | ||
349 | * This should be sufficient to wait for GPU idle without | ||
350 | * having to worry about starvation. | ||
351 | */ | ||
352 | |||
353 | void drm_idlelock_take(drm_lock_data_t *lock_data) | ||
354 | { | ||
355 | int ret = 0; | ||
356 | |||
357 | spin_lock(&lock_data->spinlock); | ||
358 | lock_data->kernel_waiters++; | ||
359 | if (!lock_data->idle_has_lock) { | ||
360 | |||
361 | spin_unlock(&lock_data->spinlock); | ||
362 | ret = drm_lock_take(lock_data, DRM_KERNEL_CONTEXT); | ||
363 | spin_lock(&lock_data->spinlock); | ||
364 | |||
365 | if (ret == 1) | ||
366 | lock_data->idle_has_lock = 1; | ||
367 | } | ||
368 | spin_unlock(&lock_data->spinlock); | ||
369 | } | ||
370 | EXPORT_SYMBOL(drm_idlelock_take); | ||
371 | |||
372 | void drm_idlelock_release(drm_lock_data_t *lock_data) | ||
373 | { | ||
374 | unsigned int old, prev; | ||
375 | volatile unsigned int *lock = &lock_data->hw_lock->lock; | ||
376 | |||
377 | spin_lock(&lock_data->spinlock); | ||
378 | if (--lock_data->kernel_waiters == 0) { | ||
379 | if (lock_data->idle_has_lock) { | ||
380 | do { | ||
381 | old = *lock; | ||
382 | prev = cmpxchg(lock, old, DRM_KERNEL_CONTEXT); | ||
383 | } while (prev != old); | ||
384 | wake_up_interruptible(&lock_data->lock_queue); | ||
385 | lock_data->idle_has_lock = 0; | ||
386 | } | ||
387 | } | ||
388 | spin_unlock(&lock_data->spinlock); | ||
389 | } | ||
390 | EXPORT_SYMBOL(drm_idlelock_release); | ||
391 | |||
392 | |||
393 | int drm_i_have_hw_lock(struct file *filp) | ||
394 | { | ||
395 | DRM_DEVICE; | ||
396 | |||
397 | return (priv->lock_count && dev->lock.hw_lock && | ||
398 | _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) && | ||
399 | dev->lock.filp == filp); | ||
400 | } | ||
401 | |||
402 | EXPORT_SYMBOL(drm_i_have_hw_lock); | ||
diff --git a/drivers/char/drm/drm_mm.c b/drivers/char/drm/drm_mm.c index 9b46b85027d0..2ec1d9f26264 100644 --- a/drivers/char/drm/drm_mm.c +++ b/drivers/char/drm/drm_mm.c | |||
@@ -274,7 +274,6 @@ int drm_mm_init(drm_mm_t * mm, unsigned long start, unsigned long size) | |||
274 | return drm_mm_create_tail_node(mm, start, size); | 274 | return drm_mm_create_tail_node(mm, start, size); |
275 | } | 275 | } |
276 | 276 | ||
277 | EXPORT_SYMBOL(drm_mm_init); | ||
278 | 277 | ||
279 | void drm_mm_takedown(drm_mm_t * mm) | 278 | void drm_mm_takedown(drm_mm_t * mm) |
280 | { | 279 | { |
@@ -295,4 +294,3 @@ void drm_mm_takedown(drm_mm_t * mm) | |||
295 | drm_free(entry, sizeof(*entry), DRM_MEM_MM); | 294 | drm_free(entry, sizeof(*entry), DRM_MEM_MM); |
296 | } | 295 | } |
297 | 296 | ||
298 | EXPORT_SYMBOL(drm_mm_takedown); | ||
diff --git a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h index 2908b72daa6e..0fe7b4497927 100644 --- a/drivers/char/drm/drm_os_linux.h +++ b/drivers/char/drm/drm_os_linux.h | |||
@@ -70,9 +70,6 @@ static __inline__ int mtrr_del(int reg, unsigned long base, unsigned long size) | |||
70 | 70 | ||
71 | #endif | 71 | #endif |
72 | 72 | ||
73 | /** Task queue handler arguments */ | ||
74 | #define DRM_TASKQUEUE_ARGS void *arg | ||
75 | |||
76 | /** For data going into the kernel through the ioctl argument */ | 73 | /** For data going into the kernel through the ioctl argument */ |
77 | #define DRM_COPY_FROM_USER_IOCTL(arg1, arg2, arg3) \ | 74 | #define DRM_COPY_FROM_USER_IOCTL(arg1, arg2, arg3) \ |
78 | if ( copy_from_user(&arg1, arg2, arg3) ) \ | 75 | if ( copy_from_user(&arg1, arg2, arg3) ) \ |
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h index ad54b845978b..31cdde83713b 100644 --- a/drivers/char/drm/drm_pciids.h +++ b/drivers/char/drm/drm_pciids.h | |||
@@ -102,6 +102,7 @@ | |||
102 | {0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ | 102 | {0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ |
103 | {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP}, \ | 103 | {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP}, \ |
104 | {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \ | 104 | {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \ |
105 | {0x1002, 0x5955, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \ | ||
105 | {0x1002, 0x5960, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ | 106 | {0x1002, 0x5960, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ |
106 | {0x1002, 0x5961, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ | 107 | {0x1002, 0x5961, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ |
107 | {0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ | 108 | {0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ |
@@ -230,10 +231,10 @@ | |||
230 | {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 231 | {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
231 | {0x1106, 0x3108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 232 | {0x1106, 0x3108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
232 | {0x1106, 0x3304, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 233 | {0x1106, 0x3304, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
233 | {0x1106, 0x3157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
234 | {0x1106, 0x3344, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 234 | {0x1106, 0x3344, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
235 | {0x1106, 0x3343, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 235 | {0x1106, 0x3343, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
236 | {0x1106, 0x3230, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_DX9_0}, \ | 236 | {0x1106, 0x3230, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_DX9_0}, \ |
237 | {0x1106, 0x3157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_PRO_GROUP_A}, \ | ||
237 | {0, 0, 0} | 238 | {0, 0, 0} |
238 | 239 | ||
239 | #define i810_PCI_IDS \ | 240 | #define i810_PCI_IDS \ |
@@ -296,5 +297,6 @@ | |||
296 | {0x8086, 0x2982, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 297 | {0x8086, 0x2982, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
297 | {0x8086, 0x2992, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 298 | {0x8086, 0x2992, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
298 | {0x8086, 0x29a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 299 | {0x8086, 0x29a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
300 | {0x8086, 0x2a02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
299 | {0, 0, 0} | 301 | {0, 0, 0} |
300 | 302 | ||
diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c index 7fd0da712142..b204498d1a28 100644 --- a/drivers/char/drm/drm_proc.c +++ b/drivers/char/drm/drm_proc.c | |||
@@ -72,7 +72,7 @@ static struct drm_proc_list { | |||
72 | #endif | 72 | #endif |
73 | }; | 73 | }; |
74 | 74 | ||
75 | #define DRM_PROC_ENTRIES (sizeof(drm_proc_list)/sizeof(drm_proc_list[0])) | 75 | #define DRM_PROC_ENTRIES ARRAY_SIZE(drm_proc_list) |
76 | 76 | ||
77 | /** | 77 | /** |
78 | * Initialize the DRI proc filesystem for a device. | 78 | * Initialize the DRI proc filesystem for a device. |
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c index 120d10256feb..19408adcc775 100644 --- a/drivers/char/drm/drm_stub.c +++ b/drivers/char/drm/drm_stub.c | |||
@@ -62,6 +62,7 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev, | |||
62 | spin_lock_init(&dev->count_lock); | 62 | spin_lock_init(&dev->count_lock); |
63 | spin_lock_init(&dev->drw_lock); | 63 | spin_lock_init(&dev->drw_lock); |
64 | spin_lock_init(&dev->tasklet_lock); | 64 | spin_lock_init(&dev->tasklet_lock); |
65 | spin_lock_init(&dev->lock.spinlock); | ||
65 | init_timer(&dev->timer); | 66 | init_timer(&dev->timer); |
66 | mutex_init(&dev->struct_mutex); | 67 | mutex_init(&dev->struct_mutex); |
67 | mutex_init(&dev->ctxlist_mutex); | 68 | mutex_init(&dev->ctxlist_mutex); |
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c index 54a632848955..b5c5b9fa84c3 100644 --- a/drivers/char/drm/drm_vm.c +++ b/drivers/char/drm/drm_vm.c | |||
@@ -41,6 +41,30 @@ | |||
41 | static void drm_vm_open(struct vm_area_struct *vma); | 41 | static void drm_vm_open(struct vm_area_struct *vma); |
42 | static void drm_vm_close(struct vm_area_struct *vma); | 42 | static void drm_vm_close(struct vm_area_struct *vma); |
43 | 43 | ||
44 | static pgprot_t drm_io_prot(uint32_t map_type, struct vm_area_struct *vma) | ||
45 | { | ||
46 | pgprot_t tmp = vm_get_page_prot(vma->vm_flags); | ||
47 | |||
48 | #if defined(__i386__) || defined(__x86_64__) | ||
49 | if (boot_cpu_data.x86 > 3 && map_type != _DRM_AGP) { | ||
50 | pgprot_val(tmp) |= _PAGE_PCD; | ||
51 | pgprot_val(tmp) &= ~_PAGE_PWT; | ||
52 | } | ||
53 | #elif defined(__powerpc__) | ||
54 | pgprot_val(tmp) |= _PAGE_NO_CACHE; | ||
55 | if (map_type == _DRM_REGISTERS) | ||
56 | pgprot_val(tmp) |= _PAGE_GUARDED; | ||
57 | #endif | ||
58 | #if defined(__ia64__) | ||
59 | if (efi_range_is_wc(vma->vm_start, vma->vm_end - | ||
60 | vma->vm_start)) | ||
61 | tmp = pgprot_writecombine(tmp); | ||
62 | else | ||
63 | tmp = pgprot_noncached(tmp); | ||
64 | #endif | ||
65 | return tmp; | ||
66 | } | ||
67 | |||
44 | /** | 68 | /** |
45 | * \c nopage method for AGP virtual memory. | 69 | * \c nopage method for AGP virtual memory. |
46 | * | 70 | * |
@@ -133,7 +157,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, | |||
133 | * \param address access address. | 157 | * \param address access address. |
134 | * \return pointer to the page structure. | 158 | * \return pointer to the page structure. |
135 | * | 159 | * |
136 | * Get the the mapping, find the real physical page to map, get the page, and | 160 | * Get the mapping, find the real physical page to map, get the page, and |
137 | * return it. | 161 | * return it. |
138 | */ | 162 | */ |
139 | static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma, | 163 | static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma, |
@@ -151,8 +175,7 @@ static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma, | |||
151 | 175 | ||
152 | offset = address - vma->vm_start; | 176 | offset = address - vma->vm_start; |
153 | i = (unsigned long)map->handle + offset; | 177 | i = (unsigned long)map->handle + offset; |
154 | page = (map->type == _DRM_CONSISTENT) ? | 178 | page = vmalloc_to_page((void *)i); |
155 | virt_to_page((void *)i) : vmalloc_to_page((void *)i); | ||
156 | if (!page) | 179 | if (!page) |
157 | return NOPAGE_SIGBUS; | 180 | return NOPAGE_SIGBUS; |
158 | get_page(page); | 181 | get_page(page); |
@@ -389,7 +412,7 @@ static struct vm_operations_struct drm_vm_sg_ops = { | |||
389 | * Create a new drm_vma_entry structure as the \p vma private data entry and | 412 | * Create a new drm_vma_entry structure as the \p vma private data entry and |
390 | * add it to drm_device::vmalist. | 413 | * add it to drm_device::vmalist. |
391 | */ | 414 | */ |
392 | static void drm_vm_open(struct vm_area_struct *vma) | 415 | static void drm_vm_open_locked(struct vm_area_struct *vma) |
393 | { | 416 | { |
394 | drm_file_t *priv = vma->vm_file->private_data; | 417 | drm_file_t *priv = vma->vm_file->private_data; |
395 | drm_device_t *dev = priv->head->dev; | 418 | drm_device_t *dev = priv->head->dev; |
@@ -401,15 +424,23 @@ static void drm_vm_open(struct vm_area_struct *vma) | |||
401 | 424 | ||
402 | vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS); | 425 | vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS); |
403 | if (vma_entry) { | 426 | if (vma_entry) { |
404 | mutex_lock(&dev->struct_mutex); | ||
405 | vma_entry->vma = vma; | 427 | vma_entry->vma = vma; |
406 | vma_entry->next = dev->vmalist; | 428 | vma_entry->next = dev->vmalist; |
407 | vma_entry->pid = current->pid; | 429 | vma_entry->pid = current->pid; |
408 | dev->vmalist = vma_entry; | 430 | dev->vmalist = vma_entry; |
409 | mutex_unlock(&dev->struct_mutex); | ||
410 | } | 431 | } |
411 | } | 432 | } |
412 | 433 | ||
434 | static void drm_vm_open(struct vm_area_struct *vma) | ||
435 | { | ||
436 | drm_file_t *priv = vma->vm_file->private_data; | ||
437 | drm_device_t *dev = priv->head->dev; | ||
438 | |||
439 | mutex_lock(&dev->struct_mutex); | ||
440 | drm_vm_open_locked(vma); | ||
441 | mutex_unlock(&dev->struct_mutex); | ||
442 | } | ||
443 | |||
413 | /** | 444 | /** |
414 | * \c close method for all virtual memory types. | 445 | * \c close method for all virtual memory types. |
415 | * | 446 | * |
@@ -460,7 +491,6 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) | |||
460 | drm_device_dma_t *dma; | 491 | drm_device_dma_t *dma; |
461 | unsigned long length = vma->vm_end - vma->vm_start; | 492 | unsigned long length = vma->vm_end - vma->vm_start; |
462 | 493 | ||
463 | lock_kernel(); | ||
464 | dev = priv->head->dev; | 494 | dev = priv->head->dev; |
465 | dma = dev->dma; | 495 | dma = dev->dma; |
466 | DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n", | 496 | DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n", |
@@ -468,10 +498,8 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) | |||
468 | 498 | ||
469 | /* Length must match exact page count */ | 499 | /* Length must match exact page count */ |
470 | if (!dma || (length >> PAGE_SHIFT) != dma->page_count) { | 500 | if (!dma || (length >> PAGE_SHIFT) != dma->page_count) { |
471 | unlock_kernel(); | ||
472 | return -EINVAL; | 501 | return -EINVAL; |
473 | } | 502 | } |
474 | unlock_kernel(); | ||
475 | 503 | ||
476 | if (!capable(CAP_SYS_ADMIN) && | 504 | if (!capable(CAP_SYS_ADMIN) && |
477 | (dma->flags & _DRM_DMA_USE_PCI_RO)) { | 505 | (dma->flags & _DRM_DMA_USE_PCI_RO)) { |
@@ -494,7 +522,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) | |||
494 | vma->vm_flags |= VM_RESERVED; /* Don't swap */ | 522 | vma->vm_flags |= VM_RESERVED; /* Don't swap */ |
495 | 523 | ||
496 | vma->vm_file = filp; /* Needed for drm_vm_open() */ | 524 | vma->vm_file = filp; /* Needed for drm_vm_open() */ |
497 | drm_vm_open(vma); | 525 | drm_vm_open_locked(vma); |
498 | return 0; | 526 | return 0; |
499 | } | 527 | } |
500 | 528 | ||
@@ -529,7 +557,7 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs); | |||
529 | * according to the mapping type and remaps the pages. Finally sets the file | 557 | * according to the mapping type and remaps the pages. Finally sets the file |
530 | * pointer and calls vm_open(). | 558 | * pointer and calls vm_open(). |
531 | */ | 559 | */ |
532 | int drm_mmap(struct file *filp, struct vm_area_struct *vma) | 560 | static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) |
533 | { | 561 | { |
534 | drm_file_t *priv = filp->private_data; | 562 | drm_file_t *priv = filp->private_data; |
535 | drm_device_t *dev = priv->head->dev; | 563 | drm_device_t *dev = priv->head->dev; |
@@ -565,7 +593,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
565 | return -EPERM; | 593 | return -EPERM; |
566 | 594 | ||
567 | /* Check for valid size. */ | 595 | /* Check for valid size. */ |
568 | if (map->size != vma->vm_end - vma->vm_start) | 596 | if (map->size < vma->vm_end - vma->vm_start) |
569 | return -EINVAL; | 597 | return -EINVAL; |
570 | 598 | ||
571 | if (!capable(CAP_SYS_ADMIN) && (map->flags & _DRM_READ_ONLY)) { | 599 | if (!capable(CAP_SYS_ADMIN) && (map->flags & _DRM_READ_ONLY)) { |
@@ -600,37 +628,16 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
600 | /* fall through to _DRM_FRAME_BUFFER... */ | 628 | /* fall through to _DRM_FRAME_BUFFER... */ |
601 | case _DRM_FRAME_BUFFER: | 629 | case _DRM_FRAME_BUFFER: |
602 | case _DRM_REGISTERS: | 630 | case _DRM_REGISTERS: |
603 | #if defined(__i386__) || defined(__x86_64__) | ||
604 | if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) { | ||
605 | pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; | ||
606 | pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT; | ||
607 | } | ||
608 | #elif defined(__powerpc__) | ||
609 | pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE; | ||
610 | if (map->type == _DRM_REGISTERS) | ||
611 | pgprot_val(vma->vm_page_prot) |= _PAGE_GUARDED; | ||
612 | #endif | ||
613 | vma->vm_flags |= VM_IO; /* not in core dump */ | ||
614 | #if defined(__ia64__) | ||
615 | if (efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start)) | ||
616 | vma->vm_page_prot = | ||
617 | pgprot_writecombine(vma->vm_page_prot); | ||
618 | else | ||
619 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | ||
620 | #endif | ||
621 | offset = dev->driver->get_reg_ofs(dev); | 631 | offset = dev->driver->get_reg_ofs(dev); |
632 | vma->vm_flags |= VM_IO; /* not in core dump */ | ||
633 | vma->vm_page_prot = drm_io_prot(map->type, vma); | ||
622 | #ifdef __sparc__ | 634 | #ifdef __sparc__ |
623 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | 635 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
636 | #endif | ||
624 | if (io_remap_pfn_range(vma, vma->vm_start, | 637 | if (io_remap_pfn_range(vma, vma->vm_start, |
625 | (map->offset + offset) >> PAGE_SHIFT, | 638 | (map->offset + offset) >> PAGE_SHIFT, |
626 | vma->vm_end - vma->vm_start, | 639 | vma->vm_end - vma->vm_start, |
627 | vma->vm_page_prot)) | 640 | vma->vm_page_prot)) |
628 | #else | ||
629 | if (io_remap_pfn_range(vma, vma->vm_start, | ||
630 | (map->offset + offset) >> PAGE_SHIFT, | ||
631 | vma->vm_end - vma->vm_start, | ||
632 | vma->vm_page_prot)) | ||
633 | #endif | ||
634 | return -EAGAIN; | 641 | return -EAGAIN; |
635 | DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx," | 642 | DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx," |
636 | " offset = 0x%lx\n", | 643 | " offset = 0x%lx\n", |
@@ -638,10 +645,15 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
638 | vma->vm_start, vma->vm_end, map->offset + offset); | 645 | vma->vm_start, vma->vm_end, map->offset + offset); |
639 | vma->vm_ops = &drm_vm_ops; | 646 | vma->vm_ops = &drm_vm_ops; |
640 | break; | 647 | break; |
641 | case _DRM_SHM: | ||
642 | case _DRM_CONSISTENT: | 648 | case _DRM_CONSISTENT: |
643 | /* Consistent memory is really like shared memory. It's only | 649 | /* Consistent memory is really like shared memory. But |
644 | * allocate in a different way */ | 650 | * it's allocated in a different way, so avoid nopage */ |
651 | if (remap_pfn_range(vma, vma->vm_start, | ||
652 | page_to_pfn(virt_to_page(map->handle)), | ||
653 | vma->vm_end - vma->vm_start, vma->vm_page_prot)) | ||
654 | return -EAGAIN; | ||
655 | /* fall through to _DRM_SHM */ | ||
656 | case _DRM_SHM: | ||
645 | vma->vm_ops = &drm_vm_shm_ops; | 657 | vma->vm_ops = &drm_vm_shm_ops; |
646 | vma->vm_private_data = (void *)map; | 658 | vma->vm_private_data = (void *)map; |
647 | /* Don't let this area swap. Change when | 659 | /* Don't let this area swap. Change when |
@@ -659,8 +671,20 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
659 | vma->vm_flags |= VM_RESERVED; /* Don't swap */ | 671 | vma->vm_flags |= VM_RESERVED; /* Don't swap */ |
660 | 672 | ||
661 | vma->vm_file = filp; /* Needed for drm_vm_open() */ | 673 | vma->vm_file = filp; /* Needed for drm_vm_open() */ |
662 | drm_vm_open(vma); | 674 | drm_vm_open_locked(vma); |
663 | return 0; | 675 | return 0; |
664 | } | 676 | } |
665 | 677 | ||
678 | int drm_mmap(struct file *filp, struct vm_area_struct *vma) | ||
679 | { | ||
680 | drm_file_t *priv = filp->private_data; | ||
681 | drm_device_t *dev = priv->head->dev; | ||
682 | int ret; | ||
683 | |||
684 | mutex_lock(&dev->struct_mutex); | ||
685 | ret = drm_mmap_locked(filp, vma); | ||
686 | mutex_unlock(&dev->struct_mutex); | ||
687 | |||
688 | return ret; | ||
689 | } | ||
666 | EXPORT_SYMBOL(drm_mmap); | 690 | EXPORT_SYMBOL(drm_mmap); |
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c index 9354ce3b0093..1ba15d9a171a 100644 --- a/drivers/char/drm/i915_dma.c +++ b/drivers/char/drm/i915_dma.c | |||
@@ -34,7 +34,8 @@ | |||
34 | #define IS_I965G(dev) (dev->pci_device == 0x2972 || \ | 34 | #define IS_I965G(dev) (dev->pci_device == 0x2972 || \ |
35 | dev->pci_device == 0x2982 || \ | 35 | dev->pci_device == 0x2982 || \ |
36 | dev->pci_device == 0x2992 || \ | 36 | dev->pci_device == 0x2992 || \ |
37 | dev->pci_device == 0x29A2) | 37 | dev->pci_device == 0x29A2 || \ |
38 | dev->pci_device == 0x2A02) | ||
38 | 39 | ||
39 | /* Really want an OS-independent resettable timer. Would like to have | 40 | /* Really want an OS-independent resettable timer. Would like to have |
40 | * this loop run for (eg) 3 sec, but have the timer reset every time | 41 | * this loop run for (eg) 3 sec, but have the timer reset every time |
diff --git a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c index db5a60450e68..1014602c43a7 100644 --- a/drivers/char/drm/r128_cce.c +++ b/drivers/char/drm/r128_cce.c | |||
@@ -560,9 +560,10 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init) | |||
560 | if (dev_priv->is_pci) { | 560 | if (dev_priv->is_pci) { |
561 | #endif | 561 | #endif |
562 | dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN; | 562 | dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN; |
563 | dev_priv->gart_info.table_size = R128_PCIGART_TABLE_SIZE; | ||
563 | dev_priv->gart_info.addr = NULL; | 564 | dev_priv->gart_info.addr = NULL; |
564 | dev_priv->gart_info.bus_addr = 0; | 565 | dev_priv->gart_info.bus_addr = 0; |
565 | dev_priv->gart_info.is_pcie = 0; | 566 | dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI; |
566 | if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) { | 567 | if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) { |
567 | DRM_ERROR("failed to init PCI GART!\n"); | 568 | DRM_ERROR("failed to init PCI GART!\n"); |
568 | dev->dev_private = (void *)dev_priv; | 569 | dev->dev_private = (void *)dev_priv; |
diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h index f1efb49de8df..9086835686dc 100644 --- a/drivers/char/drm/r128_drv.h +++ b/drivers/char/drm/r128_drv.h | |||
@@ -383,6 +383,8 @@ extern long r128_compat_ioctl(struct file *filp, unsigned int cmd, | |||
383 | 383 | ||
384 | #define R128_PERFORMANCE_BOXES 0 | 384 | #define R128_PERFORMANCE_BOXES 0 |
385 | 385 | ||
386 | #define R128_PCIGART_TABLE_SIZE 32768 | ||
387 | |||
386 | #define R128_READ(reg) DRM_READ32( dev_priv->mmio, (reg) ) | 388 | #define R128_READ(reg) DRM_READ32( dev_priv->mmio, (reg) ) |
387 | #define R128_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) ) | 389 | #define R128_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) ) |
388 | #define R128_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) ) | 390 | #define R128_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) ) |
diff --git a/drivers/char/drm/r300_reg.h b/drivers/char/drm/r300_reg.h index a881f96c983e..ecda760ae8c0 100644 --- a/drivers/char/drm/r300_reg.h +++ b/drivers/char/drm/r300_reg.h | |||
@@ -293,7 +293,7 @@ I am fairly certain that they are correct unless stated otherwise in comments. | |||
293 | # define R300_PVS_CNTL_1_PROGRAM_START_SHIFT 0 | 293 | # define R300_PVS_CNTL_1_PROGRAM_START_SHIFT 0 |
294 | # define R300_PVS_CNTL_1_POS_END_SHIFT 10 | 294 | # define R300_PVS_CNTL_1_POS_END_SHIFT 10 |
295 | # define R300_PVS_CNTL_1_PROGRAM_END_SHIFT 20 | 295 | # define R300_PVS_CNTL_1_PROGRAM_END_SHIFT 20 |
296 | /* Addresses are relative the the vertex program parameters area. */ | 296 | /* Addresses are relative to the vertex program parameters area. */ |
297 | #define R300_VAP_PVS_CNTL_2 0x22D4 | 297 | #define R300_VAP_PVS_CNTL_2 0x22D4 |
298 | # define R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT 0 | 298 | # define R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT 0 |
299 | # define R300_PVS_CNTL_2_PARAM_COUNT_SHIFT 16 | 299 | # define R300_PVS_CNTL_2_PARAM_COUNT_SHIFT 16 |
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c index 5ed965688293..68338389d836 100644 --- a/drivers/char/drm/radeon_cp.c +++ b/drivers/char/drm/radeon_cp.c | |||
@@ -830,6 +830,15 @@ static int RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr) | |||
830 | return RADEON_READ(RADEON_PCIE_DATA); | 830 | return RADEON_READ(RADEON_PCIE_DATA); |
831 | } | 831 | } |
832 | 832 | ||
833 | static u32 RADEON_READ_IGPGART(drm_radeon_private_t *dev_priv, int addr) | ||
834 | { | ||
835 | u32 ret; | ||
836 | RADEON_WRITE(RADEON_IGPGART_INDEX, addr & 0x7f); | ||
837 | ret = RADEON_READ(RADEON_IGPGART_DATA); | ||
838 | RADEON_WRITE(RADEON_IGPGART_INDEX, 0x7f); | ||
839 | return ret; | ||
840 | } | ||
841 | |||
833 | #if RADEON_FIFO_DEBUG | 842 | #if RADEON_FIFO_DEBUG |
834 | static void radeon_status(drm_radeon_private_t * dev_priv) | 843 | static void radeon_status(drm_radeon_private_t * dev_priv) |
835 | { | 844 | { |
@@ -1267,7 +1276,44 @@ static void radeon_test_writeback(drm_radeon_private_t * dev_priv) | |||
1267 | } | 1276 | } |
1268 | } | 1277 | } |
1269 | 1278 | ||
1270 | /* Enable or disable PCI-E GART on the chip */ | 1279 | /* Enable or disable IGP GART on the chip */ |
1280 | static void radeon_set_igpgart(drm_radeon_private_t * dev_priv, int on) | ||
1281 | { | ||
1282 | u32 temp, tmp; | ||
1283 | |||
1284 | tmp = RADEON_READ(RADEON_AIC_CNTL); | ||
1285 | if (on) { | ||
1286 | DRM_DEBUG("programming igpgart %08X %08lX %08X\n", | ||
1287 | dev_priv->gart_vm_start, | ||
1288 | (long)dev_priv->gart_info.bus_addr, | ||
1289 | dev_priv->gart_size); | ||
1290 | |||
1291 | RADEON_WRITE_IGPGART(RADEON_IGPGART_UNK_18, 0x1000); | ||
1292 | RADEON_WRITE_IGPGART(RADEON_IGPGART_ENABLE, 0x1); | ||
1293 | RADEON_WRITE_IGPGART(RADEON_IGPGART_CTRL, 0x42040800); | ||
1294 | RADEON_WRITE_IGPGART(RADEON_IGPGART_BASE_ADDR, | ||
1295 | dev_priv->gart_info.bus_addr); | ||
1296 | |||
1297 | temp = RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_UNK_39); | ||
1298 | RADEON_WRITE_IGPGART(RADEON_IGPGART_UNK_39, temp); | ||
1299 | |||
1300 | RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev_priv->gart_vm_start); | ||
1301 | dev_priv->gart_size = 32*1024*1024; | ||
1302 | RADEON_WRITE(RADEON_MC_AGP_LOCATION, | ||
1303 | (((dev_priv->gart_vm_start - 1 + | ||
1304 | dev_priv->gart_size) & 0xffff0000) | | ||
1305 | (dev_priv->gart_vm_start >> 16))); | ||
1306 | |||
1307 | temp = RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_ENABLE); | ||
1308 | RADEON_WRITE_IGPGART(RADEON_IGPGART_ENABLE, temp); | ||
1309 | |||
1310 | RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_FLUSH); | ||
1311 | RADEON_WRITE_IGPGART(RADEON_IGPGART_FLUSH, 0x1); | ||
1312 | RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_FLUSH); | ||
1313 | RADEON_WRITE_IGPGART(RADEON_IGPGART_FLUSH, 0x0); | ||
1314 | } | ||
1315 | } | ||
1316 | |||
1271 | static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on) | 1317 | static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on) |
1272 | { | 1318 | { |
1273 | u32 tmp = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_TX_GART_CNTL); | 1319 | u32 tmp = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_TX_GART_CNTL); |
@@ -1302,6 +1348,11 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on) | |||
1302 | { | 1348 | { |
1303 | u32 tmp; | 1349 | u32 tmp; |
1304 | 1350 | ||
1351 | if (dev_priv->flags & RADEON_IS_IGPGART) { | ||
1352 | radeon_set_igpgart(dev_priv, on); | ||
1353 | return; | ||
1354 | } | ||
1355 | |||
1305 | if (dev_priv->flags & RADEON_IS_PCIE) { | 1356 | if (dev_priv->flags & RADEON_IS_PCIE) { |
1306 | radeon_set_pciegart(dev_priv, on); | 1357 | radeon_set_pciegart(dev_priv, on); |
1307 | return; | 1358 | return; |
@@ -1560,8 +1611,8 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
1560 | if (dev_priv->flags & RADEON_IS_AGP) { | 1611 | if (dev_priv->flags & RADEON_IS_AGP) { |
1561 | base = dev->agp->base; | 1612 | base = dev->agp->base; |
1562 | /* Check if valid */ | 1613 | /* Check if valid */ |
1563 | if ((base + dev_priv->gart_size) > dev_priv->fb_location && | 1614 | if ((base + dev_priv->gart_size - 1) >= dev_priv->fb_location && |
1564 | base < (dev_priv->fb_location + dev_priv->fb_size)) { | 1615 | base < (dev_priv->fb_location + dev_priv->fb_size - 1)) { |
1565 | DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n", | 1616 | DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n", |
1566 | dev->agp->base); | 1617 | dev->agp->base); |
1567 | base = 0; | 1618 | base = 0; |
@@ -1571,8 +1622,8 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
1571 | /* If not or if AGP is at 0 (Macs), try to put it elsewhere */ | 1622 | /* If not or if AGP is at 0 (Macs), try to put it elsewhere */ |
1572 | if (base == 0) { | 1623 | if (base == 0) { |
1573 | base = dev_priv->fb_location + dev_priv->fb_size; | 1624 | base = dev_priv->fb_location + dev_priv->fb_size; |
1574 | if (((base + dev_priv->gart_size) & 0xfffffffful) | 1625 | if (base < dev_priv->fb_location || |
1575 | < base) | 1626 | ((base + dev_priv->gart_size) & 0xfffffffful) < base) |
1576 | base = dev_priv->fb_location | 1627 | base = dev_priv->fb_location |
1577 | - dev_priv->gart_size; | 1628 | - dev_priv->gart_size; |
1578 | } | 1629 | } |
@@ -1620,20 +1671,22 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
1620 | #endif | 1671 | #endif |
1621 | { | 1672 | { |
1622 | /* if we have an offset set from userspace */ | 1673 | /* if we have an offset set from userspace */ |
1623 | if (dev_priv->pcigart_offset) { | 1674 | if (dev_priv->pcigart_offset_set) { |
1624 | dev_priv->gart_info.bus_addr = | 1675 | dev_priv->gart_info.bus_addr = |
1625 | dev_priv->pcigart_offset + dev_priv->fb_location; | 1676 | dev_priv->pcigart_offset + dev_priv->fb_location; |
1626 | dev_priv->gart_info.mapping.offset = | 1677 | dev_priv->gart_info.mapping.offset = |
1627 | dev_priv->gart_info.bus_addr; | 1678 | dev_priv->gart_info.bus_addr; |
1628 | dev_priv->gart_info.mapping.size = | 1679 | dev_priv->gart_info.mapping.size = |
1629 | RADEON_PCIGART_TABLE_SIZE; | 1680 | dev_priv->gart_info.table_size; |
1630 | 1681 | ||
1631 | drm_core_ioremap(&dev_priv->gart_info.mapping, dev); | 1682 | drm_core_ioremap(&dev_priv->gart_info.mapping, dev); |
1632 | dev_priv->gart_info.addr = | 1683 | dev_priv->gart_info.addr = |
1633 | dev_priv->gart_info.mapping.handle; | 1684 | dev_priv->gart_info.mapping.handle; |
1634 | 1685 | ||
1635 | dev_priv->gart_info.is_pcie = | 1686 | if (dev_priv->flags & RADEON_IS_PCIE) |
1636 | !!(dev_priv->flags & RADEON_IS_PCIE); | 1687 | dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCIE; |
1688 | else | ||
1689 | dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI; | ||
1637 | dev_priv->gart_info.gart_table_location = | 1690 | dev_priv->gart_info.gart_table_location = |
1638 | DRM_ATI_GART_FB; | 1691 | DRM_ATI_GART_FB; |
1639 | 1692 | ||
@@ -1641,6 +1694,10 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
1641 | dev_priv->gart_info.addr, | 1694 | dev_priv->gart_info.addr, |
1642 | dev_priv->pcigart_offset); | 1695 | dev_priv->pcigart_offset); |
1643 | } else { | 1696 | } else { |
1697 | if (dev_priv->flags & RADEON_IS_IGPGART) | ||
1698 | dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_IGP; | ||
1699 | else | ||
1700 | dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI; | ||
1644 | dev_priv->gart_info.gart_table_location = | 1701 | dev_priv->gart_info.gart_table_location = |
1645 | DRM_ATI_GART_MAIN; | 1702 | DRM_ATI_GART_MAIN; |
1646 | dev_priv->gart_info.addr = NULL; | 1703 | dev_priv->gart_info.addr = NULL; |
@@ -1714,7 +1771,7 @@ static int radeon_do_cleanup_cp(drm_device_t * dev) | |||
1714 | if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) | 1771 | if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) |
1715 | { | 1772 | { |
1716 | drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev); | 1773 | drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev); |
1717 | dev_priv->gart_info.addr = NULL; | 1774 | dev_priv->gart_info.addr = 0; |
1718 | } | 1775 | } |
1719 | } | 1776 | } |
1720 | /* only clear to the start of flags */ | 1777 | /* only clear to the start of flags */ |
@@ -2222,6 +2279,8 @@ int radeon_driver_firstopen(struct drm_device *dev) | |||
2222 | drm_local_map_t *map; | 2279 | drm_local_map_t *map; |
2223 | drm_radeon_private_t *dev_priv = dev->dev_private; | 2280 | drm_radeon_private_t *dev_priv = dev->dev_private; |
2224 | 2281 | ||
2282 | dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; | ||
2283 | |||
2225 | ret = drm_addmap(dev, drm_get_resource_start(dev, 2), | 2284 | ret = drm_addmap(dev, drm_get_resource_start(dev, 2), |
2226 | drm_get_resource_len(dev, 2), _DRM_REGISTERS, | 2285 | drm_get_resource_len(dev, 2), _DRM_REGISTERS, |
2227 | _DRM_READ_ONLY, &dev_priv->mmio); | 2286 | _DRM_READ_ONLY, &dev_priv->mmio); |
diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h index 8d6350dd5360..66c4b6fed04f 100644 --- a/drivers/char/drm/radeon_drm.h +++ b/drivers/char/drm/radeon_drm.h | |||
@@ -707,6 +707,7 @@ typedef struct drm_radeon_setparam { | |||
707 | #define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */ | 707 | #define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */ |
708 | #define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */ | 708 | #define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */ |
709 | #define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */ | 709 | #define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */ |
710 | #define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5 /* PCI GART Table Size */ | ||
710 | 711 | ||
711 | /* 1.14: Clients can allocate/free a surface | 712 | /* 1.14: Clients can allocate/free a surface |
712 | */ | 713 | */ |
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h index 8b105f1460a7..54f49ef4bef0 100644 --- a/drivers/char/drm/radeon_drv.h +++ b/drivers/char/drm/radeon_drv.h | |||
@@ -95,9 +95,11 @@ | |||
95 | * 1.24- Add general-purpose packet for manipulating scratch registers (r300) | 95 | * 1.24- Add general-purpose packet for manipulating scratch registers (r300) |
96 | * 1.25- Add support for r200 vertex programs (R200_EMIT_VAP_PVS_CNTL, | 96 | * 1.25- Add support for r200 vertex programs (R200_EMIT_VAP_PVS_CNTL, |
97 | * new packet type) | 97 | * new packet type) |
98 | * 1.26- Add support for variable size PCI(E) gart aperture | ||
99 | * 1.27- Add support for IGP GART | ||
98 | */ | 100 | */ |
99 | #define DRIVER_MAJOR 1 | 101 | #define DRIVER_MAJOR 1 |
100 | #define DRIVER_MINOR 25 | 102 | #define DRIVER_MINOR 27 |
101 | #define DRIVER_PATCHLEVEL 0 | 103 | #define DRIVER_PATCHLEVEL 0 |
102 | 104 | ||
103 | /* | 105 | /* |
@@ -143,6 +145,7 @@ enum radeon_chip_flags { | |||
143 | RADEON_IS_PCIE = 0x00200000UL, | 145 | RADEON_IS_PCIE = 0x00200000UL, |
144 | RADEON_NEW_MEMMAP = 0x00400000UL, | 146 | RADEON_NEW_MEMMAP = 0x00400000UL, |
145 | RADEON_IS_PCI = 0x00800000UL, | 147 | RADEON_IS_PCI = 0x00800000UL, |
148 | RADEON_IS_IGPGART = 0x01000000UL, | ||
146 | }; | 149 | }; |
147 | 150 | ||
148 | #define GET_RING_HEAD(dev_priv) (dev_priv->writeback_works ? \ | 151 | #define GET_RING_HEAD(dev_priv) (dev_priv->writeback_works ? \ |
@@ -240,7 +243,6 @@ typedef struct drm_radeon_private { | |||
240 | 243 | ||
241 | int do_boxes; | 244 | int do_boxes; |
242 | int page_flipping; | 245 | int page_flipping; |
243 | int current_page; | ||
244 | 246 | ||
245 | u32 color_fmt; | 247 | u32 color_fmt; |
246 | unsigned int front_offset; | 248 | unsigned int front_offset; |
@@ -280,6 +282,7 @@ typedef struct drm_radeon_private { | |||
280 | struct radeon_virt_surface virt_surfaces[2 * RADEON_MAX_SURFACES]; | 282 | struct radeon_virt_surface virt_surfaces[2 * RADEON_MAX_SURFACES]; |
281 | 283 | ||
282 | unsigned long pcigart_offset; | 284 | unsigned long pcigart_offset; |
285 | unsigned int pcigart_offset_set; | ||
283 | drm_ati_pcigart_info gart_info; | 286 | drm_ati_pcigart_info gart_info; |
284 | 287 | ||
285 | u32 scratch_ages[5]; | 288 | u32 scratch_ages[5]; |
@@ -432,6 +435,15 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp, | |||
432 | #define RADEON_PCIE_TX_GART_END_LO 0x16 | 435 | #define RADEON_PCIE_TX_GART_END_LO 0x16 |
433 | #define RADEON_PCIE_TX_GART_END_HI 0x17 | 436 | #define RADEON_PCIE_TX_GART_END_HI 0x17 |
434 | 437 | ||
438 | #define RADEON_IGPGART_INDEX 0x168 | ||
439 | #define RADEON_IGPGART_DATA 0x16c | ||
440 | #define RADEON_IGPGART_UNK_18 0x18 | ||
441 | #define RADEON_IGPGART_CTRL 0x2b | ||
442 | #define RADEON_IGPGART_BASE_ADDR 0x2c | ||
443 | #define RADEON_IGPGART_FLUSH 0x2e | ||
444 | #define RADEON_IGPGART_ENABLE 0x38 | ||
445 | #define RADEON_IGPGART_UNK_39 0x39 | ||
446 | |||
435 | #define RADEON_MPP_TB_CONFIG 0x01c0 | 447 | #define RADEON_MPP_TB_CONFIG 0x01c0 |
436 | #define RADEON_MEM_CNTL 0x0140 | 448 | #define RADEON_MEM_CNTL 0x0140 |
437 | #define RADEON_MEM_SDRAM_MODE_REG 0x0158 | 449 | #define RADEON_MEM_SDRAM_MODE_REG 0x0158 |
@@ -964,6 +976,14 @@ do { \ | |||
964 | RADEON_WRITE( RADEON_CLOCK_CNTL_DATA, (val) ); \ | 976 | RADEON_WRITE( RADEON_CLOCK_CNTL_DATA, (val) ); \ |
965 | } while (0) | 977 | } while (0) |
966 | 978 | ||
979 | #define RADEON_WRITE_IGPGART( addr, val ) \ | ||
980 | do { \ | ||
981 | RADEON_WRITE( RADEON_IGPGART_INDEX, \ | ||
982 | ((addr) & 0x7f) | (1 << 8)); \ | ||
983 | RADEON_WRITE( RADEON_IGPGART_DATA, (val) ); \ | ||
984 | RADEON_WRITE( RADEON_IGPGART_INDEX, 0x7f ); \ | ||
985 | } while (0) | ||
986 | |||
967 | #define RADEON_WRITE_PCIE( addr, val ) \ | 987 | #define RADEON_WRITE_PCIE( addr, val ) \ |
968 | do { \ | 988 | do { \ |
969 | RADEON_WRITE8( RADEON_PCIE_INDEX, \ | 989 | RADEON_WRITE8( RADEON_PCIE_INDEX, \ |
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c index 938eccb78cc0..98c5f1d3a8e7 100644 --- a/drivers/char/drm/radeon_state.c +++ b/drivers/char/drm/radeon_state.c | |||
@@ -773,7 +773,7 @@ static void radeon_clear_box(drm_radeon_private_t * dev_priv, | |||
773 | RADEON_GMC_SRC_DATATYPE_COLOR | | 773 | RADEON_GMC_SRC_DATATYPE_COLOR | |
774 | RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS); | 774 | RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS); |
775 | 775 | ||
776 | if (dev_priv->page_flipping && dev_priv->current_page == 1) { | 776 | if (dev_priv->sarea_priv->pfCurrentPage == 1) { |
777 | OUT_RING(dev_priv->front_pitch_offset); | 777 | OUT_RING(dev_priv->front_pitch_offset); |
778 | } else { | 778 | } else { |
779 | OUT_RING(dev_priv->back_pitch_offset); | 779 | OUT_RING(dev_priv->back_pitch_offset); |
@@ -861,7 +861,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev, | |||
861 | 861 | ||
862 | dev_priv->stats.clears++; | 862 | dev_priv->stats.clears++; |
863 | 863 | ||
864 | if (dev_priv->page_flipping && dev_priv->current_page == 1) { | 864 | if (dev_priv->sarea_priv->pfCurrentPage == 1) { |
865 | unsigned int tmp = flags; | 865 | unsigned int tmp = flags; |
866 | 866 | ||
867 | flags &= ~(RADEON_FRONT | RADEON_BACK); | 867 | flags &= ~(RADEON_FRONT | RADEON_BACK); |
@@ -1382,7 +1382,7 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev) | |||
1382 | /* Make this work even if front & back are flipped: | 1382 | /* Make this work even if front & back are flipped: |
1383 | */ | 1383 | */ |
1384 | OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1)); | 1384 | OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1)); |
1385 | if (dev_priv->current_page == 0) { | 1385 | if (dev_priv->sarea_priv->pfCurrentPage == 0) { |
1386 | OUT_RING(dev_priv->back_pitch_offset); | 1386 | OUT_RING(dev_priv->back_pitch_offset); |
1387 | OUT_RING(dev_priv->front_pitch_offset); | 1387 | OUT_RING(dev_priv->front_pitch_offset); |
1388 | } else { | 1388 | } else { |
@@ -1416,12 +1416,12 @@ static void radeon_cp_dispatch_flip(drm_device_t * dev) | |||
1416 | { | 1416 | { |
1417 | drm_radeon_private_t *dev_priv = dev->dev_private; | 1417 | drm_radeon_private_t *dev_priv = dev->dev_private; |
1418 | drm_sarea_t *sarea = (drm_sarea_t *) dev_priv->sarea->handle; | 1418 | drm_sarea_t *sarea = (drm_sarea_t *) dev_priv->sarea->handle; |
1419 | int offset = (dev_priv->current_page == 1) | 1419 | int offset = (dev_priv->sarea_priv->pfCurrentPage == 1) |
1420 | ? dev_priv->front_offset : dev_priv->back_offset; | 1420 | ? dev_priv->front_offset : dev_priv->back_offset; |
1421 | RING_LOCALS; | 1421 | RING_LOCALS; |
1422 | DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n", | 1422 | DRM_DEBUG("%s: pfCurrentPage=%d\n", |
1423 | __FUNCTION__, | 1423 | __FUNCTION__, |
1424 | dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage); | 1424 | dev_priv->sarea_priv->pfCurrentPage); |
1425 | 1425 | ||
1426 | /* Do some trivial performance monitoring... | 1426 | /* Do some trivial performance monitoring... |
1427 | */ | 1427 | */ |
@@ -1449,8 +1449,8 @@ static void radeon_cp_dispatch_flip(drm_device_t * dev) | |||
1449 | * performing the swapbuffer ioctl. | 1449 | * performing the swapbuffer ioctl. |
1450 | */ | 1450 | */ |
1451 | dev_priv->sarea_priv->last_frame++; | 1451 | dev_priv->sarea_priv->last_frame++; |
1452 | dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page = | 1452 | dev_priv->sarea_priv->pfCurrentPage = |
1453 | 1 - dev_priv->current_page; | 1453 | 1 - dev_priv->sarea_priv->pfCurrentPage; |
1454 | 1454 | ||
1455 | BEGIN_RING(2); | 1455 | BEGIN_RING(2); |
1456 | 1456 | ||
@@ -2152,24 +2152,10 @@ static int radeon_do_init_pageflip(drm_device_t * dev) | |||
2152 | ADVANCE_RING(); | 2152 | ADVANCE_RING(); |
2153 | 2153 | ||
2154 | dev_priv->page_flipping = 1; | 2154 | dev_priv->page_flipping = 1; |
2155 | dev_priv->current_page = 0; | ||
2156 | dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page; | ||
2157 | 2155 | ||
2158 | return 0; | 2156 | if (dev_priv->sarea_priv->pfCurrentPage != 1) |
2159 | } | 2157 | dev_priv->sarea_priv->pfCurrentPage = 0; |
2160 | |||
2161 | /* Called whenever a client dies, from drm_release. | ||
2162 | * NOTE: Lock isn't necessarily held when this is called! | ||
2163 | */ | ||
2164 | static int radeon_do_cleanup_pageflip(drm_device_t * dev) | ||
2165 | { | ||
2166 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
2167 | DRM_DEBUG("\n"); | ||
2168 | |||
2169 | if (dev_priv->current_page != 0) | ||
2170 | radeon_cp_dispatch_flip(dev); | ||
2171 | 2158 | ||
2172 | dev_priv->page_flipping = 0; | ||
2173 | return 0; | 2159 | return 0; |
2174 | } | 2160 | } |
2175 | 2161 | ||
@@ -3145,10 +3131,16 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS) | |||
3145 | break; | 3131 | break; |
3146 | case RADEON_SETPARAM_PCIGART_LOCATION: | 3132 | case RADEON_SETPARAM_PCIGART_LOCATION: |
3147 | dev_priv->pcigart_offset = sp.value; | 3133 | dev_priv->pcigart_offset = sp.value; |
3134 | dev_priv->pcigart_offset_set = 1; | ||
3148 | break; | 3135 | break; |
3149 | case RADEON_SETPARAM_NEW_MEMMAP: | 3136 | case RADEON_SETPARAM_NEW_MEMMAP: |
3150 | dev_priv->new_memmap = sp.value; | 3137 | dev_priv->new_memmap = sp.value; |
3151 | break; | 3138 | break; |
3139 | case RADEON_SETPARAM_PCIGART_TABLE_SIZE: | ||
3140 | dev_priv->gart_info.table_size = sp.value; | ||
3141 | if (dev_priv->gart_info.table_size < RADEON_PCIGART_TABLE_SIZE) | ||
3142 | dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; | ||
3143 | break; | ||
3152 | default: | 3144 | default: |
3153 | DRM_DEBUG("Invalid parameter %d\n", sp.param); | 3145 | DRM_DEBUG("Invalid parameter %d\n", sp.param); |
3154 | return DRM_ERR(EINVAL); | 3146 | return DRM_ERR(EINVAL); |
@@ -3168,9 +3160,7 @@ void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp) | |||
3168 | { | 3160 | { |
3169 | if (dev->dev_private) { | 3161 | if (dev->dev_private) { |
3170 | drm_radeon_private_t *dev_priv = dev->dev_private; | 3162 | drm_radeon_private_t *dev_priv = dev->dev_private; |
3171 | if (dev_priv->page_flipping) { | 3163 | dev_priv->page_flipping = 0; |
3172 | radeon_do_cleanup_pageflip(dev); | ||
3173 | } | ||
3174 | radeon_mem_release(filp, dev_priv->gart_heap); | 3164 | radeon_mem_release(filp, dev_priv->gart_heap); |
3175 | radeon_mem_release(filp, dev_priv->fb_heap); | 3165 | radeon_mem_release(filp, dev_priv->fb_heap); |
3176 | radeon_surfaces_release(filp, dev_priv); | 3166 | radeon_surfaces_release(filp, dev_priv); |
@@ -3179,6 +3169,14 @@ void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp) | |||
3179 | 3169 | ||
3180 | void radeon_driver_lastclose(drm_device_t * dev) | 3170 | void radeon_driver_lastclose(drm_device_t * dev) |
3181 | { | 3171 | { |
3172 | if (dev->dev_private) { | ||
3173 | drm_radeon_private_t *dev_priv = dev->dev_private; | ||
3174 | |||
3175 | if (dev_priv->sarea_priv && | ||
3176 | dev_priv->sarea_priv->pfCurrentPage != 0) | ||
3177 | radeon_cp_dispatch_flip(dev); | ||
3178 | } | ||
3179 | |||
3182 | radeon_do_release(dev); | 3180 | radeon_do_release(dev); |
3183 | } | 3181 | } |
3184 | 3182 | ||
diff --git a/drivers/char/drm/sis_drv.c b/drivers/char/drm/sis_drv.c index 3d5b3218b6ff..690e0af8e7c2 100644 --- a/drivers/char/drm/sis_drv.c +++ b/drivers/char/drm/sis_drv.c | |||
@@ -71,7 +71,7 @@ static struct drm_driver driver = { | |||
71 | .context_dtor = NULL, | 71 | .context_dtor = NULL, |
72 | .dma_quiescent = sis_idle, | 72 | .dma_quiescent = sis_idle, |
73 | .reclaim_buffers = NULL, | 73 | .reclaim_buffers = NULL, |
74 | .reclaim_buffers_locked = sis_reclaim_buffers_locked, | 74 | .reclaim_buffers_idlelocked = sis_reclaim_buffers_locked, |
75 | .lastclose = sis_lastclose, | 75 | .lastclose = sis_lastclose, |
76 | .get_map_ofs = drm_core_get_map_ofs, | 76 | .get_map_ofs = drm_core_get_map_ofs, |
77 | .get_reg_ofs = drm_core_get_reg_ofs, | 77 | .get_reg_ofs = drm_core_get_reg_ofs, |
diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c index c0539c6299cf..13a9c5ca4593 100644 --- a/drivers/char/drm/via_dma.c +++ b/drivers/char/drm/via_dma.c | |||
@@ -252,7 +252,7 @@ static int via_dma_init(DRM_IOCTL_ARGS) | |||
252 | break; | 252 | break; |
253 | case VIA_DMA_INITIALIZED: | 253 | case VIA_DMA_INITIALIZED: |
254 | retcode = (dev_priv->ring.virtual_start != NULL) ? | 254 | retcode = (dev_priv->ring.virtual_start != NULL) ? |
255 | 0 : DRM_ERR(EFAULT); | 255 | 0 : DRM_ERR(EFAULT); |
256 | break; | 256 | break; |
257 | default: | 257 | default: |
258 | retcode = DRM_ERR(EINVAL); | 258 | retcode = DRM_ERR(EINVAL); |
@@ -432,56 +432,34 @@ static int via_hook_segment(drm_via_private_t * dev_priv, | |||
432 | { | 432 | { |
433 | int paused, count; | 433 | int paused, count; |
434 | volatile uint32_t *paused_at = dev_priv->last_pause_ptr; | 434 | volatile uint32_t *paused_at = dev_priv->last_pause_ptr; |
435 | uint32_t reader,ptr; | ||
435 | 436 | ||
437 | paused = 0; | ||
436 | via_flush_write_combine(); | 438 | via_flush_write_combine(); |
437 | while (!*(via_get_dma(dev_priv) - 1)) ; | 439 | (void) *(volatile uint32_t *)(via_get_dma(dev_priv) -1); |
438 | *dev_priv->last_pause_ptr = pause_addr_lo; | 440 | *paused_at = pause_addr_lo; |
439 | via_flush_write_combine(); | 441 | via_flush_write_combine(); |
440 | 442 | (void) *paused_at; | |
441 | /* | 443 | reader = *(dev_priv->hw_addr_ptr); |
442 | * The below statement is inserted to really force the flush. | 444 | ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) + |
443 | * Not sure it is needed. | 445 | dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4; |
444 | */ | ||
445 | |||
446 | while (!*dev_priv->last_pause_ptr) ; | ||
447 | dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1; | 446 | dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1; |
448 | while (!*dev_priv->last_pause_ptr) ; | ||
449 | 447 | ||
450 | paused = 0; | 448 | if ((ptr - reader) <= dev_priv->dma_diff ) { |
451 | count = 20; | 449 | count = 10000000; |
452 | 450 | while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--); | |
453 | while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--) ; | ||
454 | if ((count <= 8) && (count >= 0)) { | ||
455 | uint32_t rgtr, ptr; | ||
456 | rgtr = *(dev_priv->hw_addr_ptr); | ||
457 | ptr = ((volatile char *)dev_priv->last_pause_ptr - | ||
458 | dev_priv->dma_ptr) + dev_priv->dma_offset + | ||
459 | (uint32_t) dev_priv->agpAddr + 4 - CMDBUF_ALIGNMENT_SIZE; | ||
460 | if (rgtr <= ptr) { | ||
461 | DRM_ERROR | ||
462 | ("Command regulator\npaused at count %d, address %x, " | ||
463 | "while current pause address is %x.\n" | ||
464 | "Please mail this message to " | ||
465 | "<unichrome-devel@lists.sourceforge.net>\n", count, | ||
466 | rgtr, ptr); | ||
467 | } | ||
468 | } | 451 | } |
469 | 452 | ||
470 | if (paused && !no_pci_fire) { | 453 | if (paused && !no_pci_fire) { |
471 | uint32_t rgtr, ptr; | 454 | reader = *(dev_priv->hw_addr_ptr); |
472 | uint32_t ptr_low; | 455 | if ((ptr - reader) == dev_priv->dma_diff) { |
473 | 456 | ||
474 | count = 1000000; | 457 | /* |
475 | while ((VIA_READ(VIA_REG_STATUS) & VIA_CMD_RGTR_BUSY) | 458 | * There is a concern that these writes may stall the PCI bus |
476 | && count--) ; | 459 | * if the GPU is not idle. However, idling the GPU first |
460 | * doesn't make a difference. | ||
461 | */ | ||
477 | 462 | ||
478 | rgtr = *(dev_priv->hw_addr_ptr); | ||
479 | ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) + | ||
480 | dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4; | ||
481 | |||
482 | ptr_low = (ptr > 3 * CMDBUF_ALIGNMENT_SIZE) ? | ||
483 | ptr - 3 * CMDBUF_ALIGNMENT_SIZE : 0; | ||
484 | if (rgtr <= ptr && rgtr >= ptr_low) { | ||
485 | VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); | 463 | VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); |
486 | VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); | 464 | VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); |
487 | VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); | 465 | VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); |
@@ -494,6 +472,9 @@ static int via_hook_segment(drm_via_private_t * dev_priv, | |||
494 | static int via_wait_idle(drm_via_private_t * dev_priv) | 472 | static int via_wait_idle(drm_via_private_t * dev_priv) |
495 | { | 473 | { |
496 | int count = 10000000; | 474 | int count = 10000000; |
475 | |||
476 | while (!(VIA_READ(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && count--); | ||
477 | |||
497 | while (count-- && (VIA_READ(VIA_REG_STATUS) & | 478 | while (count-- && (VIA_READ(VIA_REG_STATUS) & |
498 | (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | | 479 | (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | |
499 | VIA_3D_ENG_BUSY))) ; | 480 | VIA_3D_ENG_BUSY))) ; |
@@ -537,6 +518,9 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv) | |||
537 | uint32_t end_addr, end_addr_lo; | 518 | uint32_t end_addr, end_addr_lo; |
538 | uint32_t command; | 519 | uint32_t command; |
539 | uint32_t agp_base; | 520 | uint32_t agp_base; |
521 | uint32_t ptr; | ||
522 | uint32_t reader; | ||
523 | int count; | ||
540 | 524 | ||
541 | dev_priv->dma_low = 0; | 525 | dev_priv->dma_low = 0; |
542 | 526 | ||
@@ -554,7 +538,7 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv) | |||
554 | &pause_addr_hi, &pause_addr_lo, 1) - 1; | 538 | &pause_addr_hi, &pause_addr_lo, 1) - 1; |
555 | 539 | ||
556 | via_flush_write_combine(); | 540 | via_flush_write_combine(); |
557 | while (!*dev_priv->last_pause_ptr) ; | 541 | (void) *(volatile uint32_t *)dev_priv->last_pause_ptr; |
558 | 542 | ||
559 | VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); | 543 | VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); |
560 | VIA_WRITE(VIA_REG_TRANSPACE, command); | 544 | VIA_WRITE(VIA_REG_TRANSPACE, command); |
@@ -566,6 +550,24 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv) | |||
566 | DRM_WRITEMEMORYBARRIER(); | 550 | DRM_WRITEMEMORYBARRIER(); |
567 | VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK); | 551 | VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK); |
568 | VIA_READ(VIA_REG_TRANSPACE); | 552 | VIA_READ(VIA_REG_TRANSPACE); |
553 | |||
554 | dev_priv->dma_diff = 0; | ||
555 | |||
556 | count = 10000000; | ||
557 | while (!(VIA_READ(0x41c) & 0x80000000) && count--); | ||
558 | |||
559 | reader = *(dev_priv->hw_addr_ptr); | ||
560 | ptr = ((volatile char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) + | ||
561 | dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4; | ||
562 | |||
563 | /* | ||
564 | * This is the difference between where we tell the | ||
565 | * command reader to pause and where it actually pauses. | ||
566 | * This differs between hw implementation so we need to | ||
567 | * detect it. | ||
568 | */ | ||
569 | |||
570 | dev_priv->dma_diff = ptr - reader; | ||
569 | } | 571 | } |
570 | 572 | ||
571 | static void via_pad_cache(drm_via_private_t * dev_priv, int qwords) | 573 | static void via_pad_cache(drm_via_private_t * dev_priv, int qwords) |
@@ -592,7 +594,6 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv) | |||
592 | uint32_t pause_addr_lo, pause_addr_hi; | 594 | uint32_t pause_addr_lo, pause_addr_hi; |
593 | uint32_t jump_addr_lo, jump_addr_hi; | 595 | uint32_t jump_addr_lo, jump_addr_hi; |
594 | volatile uint32_t *last_pause_ptr; | 596 | volatile uint32_t *last_pause_ptr; |
595 | uint32_t dma_low_save1, dma_low_save2; | ||
596 | 597 | ||
597 | agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; | 598 | agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; |
598 | via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi, | 599 | via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi, |
@@ -619,31 +620,11 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv) | |||
619 | &pause_addr_lo, 0); | 620 | &pause_addr_lo, 0); |
620 | 621 | ||
621 | *last_pause_ptr = pause_addr_lo; | 622 | *last_pause_ptr = pause_addr_lo; |
622 | dma_low_save1 = dev_priv->dma_low; | ||
623 | |||
624 | /* | ||
625 | * Now, set a trap that will pause the regulator if it tries to rerun the old | ||
626 | * command buffer. (Which may happen if via_hook_segment detecs a command regulator pause | ||
627 | * and reissues the jump command over PCI, while the regulator has already taken the jump | ||
628 | * and actually paused at the current buffer end). | ||
629 | * There appears to be no other way to detect this condition, since the hw_addr_pointer | ||
630 | * does not seem to get updated immediately when a jump occurs. | ||
631 | */ | ||
632 | 623 | ||
633 | last_pause_ptr = | 624 | via_hook_segment( dev_priv, jump_addr_hi, jump_addr_lo, 0); |
634 | via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, | ||
635 | &pause_addr_lo, 0) - 1; | ||
636 | via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, | ||
637 | &pause_addr_lo, 0); | ||
638 | *last_pause_ptr = pause_addr_lo; | ||
639 | |||
640 | dma_low_save2 = dev_priv->dma_low; | ||
641 | dev_priv->dma_low = dma_low_save1; | ||
642 | via_hook_segment(dev_priv, jump_addr_hi, jump_addr_lo, 0); | ||
643 | dev_priv->dma_low = dma_low_save2; | ||
644 | via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0); | ||
645 | } | 625 | } |
646 | 626 | ||
627 | |||
647 | static void via_cmdbuf_rewind(drm_via_private_t * dev_priv) | 628 | static void via_cmdbuf_rewind(drm_via_private_t * dev_priv) |
648 | { | 629 | { |
649 | via_cmdbuf_jump(dev_priv); | 630 | via_cmdbuf_jump(dev_priv); |
diff --git a/drivers/char/drm/via_drv.c b/drivers/char/drm/via_drv.c index bb9dde8b1911..2d4957ab256a 100644 --- a/drivers/char/drm/via_drv.c +++ b/drivers/char/drm/via_drv.c | |||
@@ -52,7 +52,8 @@ static struct drm_driver driver = { | |||
52 | .dma_quiescent = via_driver_dma_quiescent, | 52 | .dma_quiescent = via_driver_dma_quiescent, |
53 | .dri_library_name = dri_library_name, | 53 | .dri_library_name = dri_library_name, |
54 | .reclaim_buffers = drm_core_reclaim_buffers, | 54 | .reclaim_buffers = drm_core_reclaim_buffers, |
55 | .reclaim_buffers_locked = via_reclaim_buffers_locked, | 55 | .reclaim_buffers_locked = NULL, |
56 | .reclaim_buffers_idlelocked = via_reclaim_buffers_locked, | ||
56 | .lastclose = via_lastclose, | 57 | .lastclose = via_lastclose, |
57 | .get_map_ofs = drm_core_get_map_ofs, | 58 | .get_map_ofs = drm_core_get_map_ofs, |
58 | .get_reg_ofs = drm_core_get_reg_ofs, | 59 | .get_reg_ofs = drm_core_get_reg_ofs, |
diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h index 8b8778d4a423..b46ca8e6306d 100644 --- a/drivers/char/drm/via_drv.h +++ b/drivers/char/drm/via_drv.h | |||
@@ -29,11 +29,11 @@ | |||
29 | 29 | ||
30 | #define DRIVER_NAME "via" | 30 | #define DRIVER_NAME "via" |
31 | #define DRIVER_DESC "VIA Unichrome / Pro" | 31 | #define DRIVER_DESC "VIA Unichrome / Pro" |
32 | #define DRIVER_DATE "20061227" | 32 | #define DRIVER_DATE "20070202" |
33 | 33 | ||
34 | #define DRIVER_MAJOR 2 | 34 | #define DRIVER_MAJOR 2 |
35 | #define DRIVER_MINOR 11 | 35 | #define DRIVER_MINOR 11 |
36 | #define DRIVER_PATCHLEVEL 0 | 36 | #define DRIVER_PATCHLEVEL 1 |
37 | 37 | ||
38 | #include "via_verifier.h" | 38 | #include "via_verifier.h" |
39 | 39 | ||
@@ -93,6 +93,7 @@ typedef struct drm_via_private { | |||
93 | unsigned long vram_offset; | 93 | unsigned long vram_offset; |
94 | unsigned long agp_offset; | 94 | unsigned long agp_offset; |
95 | drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES]; | 95 | drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES]; |
96 | uint32_t dma_diff; | ||
96 | } drm_via_private_t; | 97 | } drm_via_private_t; |
97 | 98 | ||
98 | enum via_family { | 99 | enum via_family { |
diff --git a/drivers/char/drm/via_mm.h b/drivers/char/drm/via_mm.h deleted file mode 100644 index d57efda57c76..000000000000 --- a/drivers/char/drm/via_mm.h +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. | ||
4 | * | ||
5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
6 | * copy of this software and associated documentation files (the "Software"), | ||
7 | * to deal in the Software without restriction, including without limitation | ||
8 | * the rights to use, copy, modify, merge, publish, distribute, sub license, | ||
9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
10 | * Software is furnished to do so, subject to the following conditions: | ||
11 | * | ||
12 | * The above copyright notice and this permission notice (including the | ||
13 | * next paragraph) shall be included in all copies or substantial portions | ||
14 | * of the Software. | ||
15 | * | ||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
19 | * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
22 | * DEALINGS IN THE SOFTWARE. | ||
23 | */ | ||
24 | #ifndef _via_drm_mm_h_ | ||
25 | #define _via_drm_mm_h_ | ||
26 | |||
27 | typedef struct { | ||
28 | unsigned int context; | ||
29 | unsigned int size; | ||
30 | unsigned long offset; | ||
31 | unsigned long free; | ||
32 | } drm_via_mm_t; | ||
33 | |||
34 | typedef struct { | ||
35 | unsigned int size; | ||
36 | unsigned long handle; | ||
37 | void *virtual; | ||
38 | } drm_via_dma_t; | ||
39 | |||
40 | #endif | ||
diff --git a/drivers/char/ds1620.c b/drivers/char/ds1620.c index 3d7efc26aad6..334ad5bbe6b6 100644 --- a/drivers/char/ds1620.c +++ b/drivers/char/ds1620.c | |||
@@ -4,7 +4,6 @@ | |||
4 | */ | 4 | */ |
5 | #include <linux/module.h> | 5 | #include <linux/module.h> |
6 | #include <linux/miscdevice.h> | 6 | #include <linux/miscdevice.h> |
7 | #include <linux/smp_lock.h> | ||
8 | #include <linux/delay.h> | 7 | #include <linux/delay.h> |
9 | #include <linux/proc_fs.h> | 8 | #include <linux/proc_fs.h> |
10 | #include <linux/capability.h> | 9 | #include <linux/capability.h> |
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c index db984e481d4c..9b8278e1f4f8 100644 --- a/drivers/char/dsp56k.c +++ b/drivers/char/dsp56k.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <linux/fs.h> | 32 | #include <linux/fs.h> |
33 | #include <linux/mm.h> | 33 | #include <linux/mm.h> |
34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
35 | #include <linux/smp_lock.h> | ||
36 | #include <linux/device.h> | 35 | #include <linux/device.h> |
37 | 36 | ||
38 | #include <asm/atarihw.h> | 37 | #include <asm/atarihw.h> |
diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c index d8dbdb916232..abde6ddefe69 100644 --- a/drivers/char/dtlk.c +++ b/drivers/char/dtlk.c | |||
@@ -62,7 +62,6 @@ | |||
62 | #include <linux/init.h> /* for __init, module_{init,exit} */ | 62 | #include <linux/init.h> /* for __init, module_{init,exit} */ |
63 | #include <linux/poll.h> /* for POLLIN, etc. */ | 63 | #include <linux/poll.h> /* for POLLIN, etc. */ |
64 | #include <linux/dtlk.h> /* local header file for DoubleTalk values */ | 64 | #include <linux/dtlk.h> /* local header file for DoubleTalk values */ |
65 | #include <linux/smp_lock.h> | ||
66 | 65 | ||
67 | #ifdef TRACING | 66 | #ifdef TRACING |
68 | #define TRACE_TEXT(str) printk(str); | 67 | #define TRACE_TEXT(str) printk(str); |
@@ -325,16 +324,22 @@ static int dtlk_release(struct inode *inode, struct file *file) | |||
325 | 324 | ||
326 | static int __init dtlk_init(void) | 325 | static int __init dtlk_init(void) |
327 | { | 326 | { |
327 | int err; | ||
328 | |||
328 | dtlk_port_lpc = 0; | 329 | dtlk_port_lpc = 0; |
329 | dtlk_port_tts = 0; | 330 | dtlk_port_tts = 0; |
330 | dtlk_busy = 0; | 331 | dtlk_busy = 0; |
331 | dtlk_major = register_chrdev(0, "dtlk", &dtlk_fops); | 332 | dtlk_major = register_chrdev(0, "dtlk", &dtlk_fops); |
332 | if (dtlk_major == 0) { | 333 | if (dtlk_major < 0) { |
333 | printk(KERN_ERR "DoubleTalk PC - cannot register device\n"); | 334 | printk(KERN_ERR "DoubleTalk PC - cannot register device\n"); |
334 | return 0; | 335 | return dtlk_major; |
336 | } | ||
337 | err = dtlk_dev_probe(); | ||
338 | if (err) { | ||
339 | unregister_chrdev(dtlk_major, "dtlk"); | ||
340 | return err; | ||
335 | } | 341 | } |
336 | if (dtlk_dev_probe() == 0) | 342 | printk(", MAJOR %d\n", dtlk_major); |
337 | printk(", MAJOR %d\n", dtlk_major); | ||
338 | 343 | ||
339 | init_waitqueue_head(&dtlk_process_list); | 344 | init_waitqueue_head(&dtlk_process_list); |
340 | 345 | ||
diff --git a/drivers/char/ec3104_keyb.c b/drivers/char/ec3104_keyb.c index 77f58ed6d59a..020011495d91 100644 --- a/drivers/char/ec3104_keyb.c +++ b/drivers/char/ec3104_keyb.c | |||
@@ -41,7 +41,6 @@ | |||
41 | #include <linux/miscdevice.h> | 41 | #include <linux/miscdevice.h> |
42 | #include <linux/slab.h> | 42 | #include <linux/slab.h> |
43 | #include <linux/kbd_kern.h> | 43 | #include <linux/kbd_kern.h> |
44 | #include <linux/smp_lock.h> | ||
45 | #include <linux/bitops.h> | 44 | #include <linux/bitops.h> |
46 | 45 | ||
47 | #include <asm/keyboard.h> | 46 | #include <asm/keyboard.h> |
diff --git a/drivers/char/epca.c b/drivers/char/epca.c index de5be30484ad..c6c56fb8ba50 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c | |||
@@ -949,7 +949,7 @@ static int block_til_ready(struct tty_struct *tty, | |||
949 | 949 | ||
950 | } /* End forever while */ | 950 | } /* End forever while */ |
951 | 951 | ||
952 | current->state = TASK_RUNNING; | 952 | __set_current_state(TASK_RUNNING); |
953 | remove_wait_queue(&ch->open_wait, &wait); | 953 | remove_wait_queue(&ch->open_wait, &wait); |
954 | if (!tty_hung_up_p(filp)) | 954 | if (!tty_hung_up_p(filp)) |
955 | ch->count++; | 955 | ch->count++; |
diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c index 23b25ada65ea..9e1fc02967ff 100644 --- a/drivers/char/genrtc.c +++ b/drivers/char/genrtc.c | |||
@@ -12,7 +12,7 @@ | |||
12 | * | 12 | * |
13 | * This driver allows use of the real time clock (built into | 13 | * This driver allows use of the real time clock (built into |
14 | * nearly all computers) from user space. It exports the /dev/rtc | 14 | * nearly all computers) from user space. It exports the /dev/rtc |
15 | * interface supporting various ioctl() and also the /proc/dev/rtc | 15 | * interface supporting various ioctl() and also the /proc/driver/rtc |
16 | * pseudo-file for status information. | 16 | * pseudo-file for status information. |
17 | * | 17 | * |
18 | * The ioctls can be used to set the interrupt behaviour where | 18 | * The ioctls can be used to set the interrupt behaviour where |
@@ -207,7 +207,7 @@ static ssize_t gen_rtc_read(struct file *file, char __user *buf, | |||
207 | sizeof(unsigned long); | 207 | sizeof(unsigned long); |
208 | } | 208 | } |
209 | out: | 209 | out: |
210 | current->state = TASK_RUNNING; | 210 | __set_current_state(TASK_RUNNING); |
211 | remove_wait_queue(&gen_rtc_wait, &wait); | 211 | remove_wait_queue(&gen_rtc_wait, &wait); |
212 | 212 | ||
213 | return retval; | 213 | return retval; |
@@ -377,7 +377,7 @@ static int gen_rtc_release(struct inode *inode, struct file *file) | |||
377 | #ifdef CONFIG_PROC_FS | 377 | #ifdef CONFIG_PROC_FS |
378 | 378 | ||
379 | /* | 379 | /* |
380 | * Info exported via "/proc/rtc". | 380 | * Info exported via "/proc/driver/rtc". |
381 | */ | 381 | */ |
382 | 382 | ||
383 | static int gen_rtc_proc_output(char *buf) | 383 | static int gen_rtc_proc_output(char *buf) |
diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c index ae76a9ffe89f..f0e7263dfcde 100644 --- a/drivers/char/hangcheck-timer.c +++ b/drivers/char/hangcheck-timer.c | |||
@@ -44,7 +44,6 @@ | |||
44 | #include <linux/fs.h> | 44 | #include <linux/fs.h> |
45 | #include <linux/mm.h> | 45 | #include <linux/mm.h> |
46 | #include <linux/reboot.h> | 46 | #include <linux/reboot.h> |
47 | #include <linux/smp_lock.h> | ||
48 | #include <linux/init.h> | 47 | #include <linux/init.h> |
49 | #include <linux/delay.h> | 48 | #include <linux/delay.h> |
50 | #include <asm/uaccess.h> | 49 | #include <asm/uaccess.h> |
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 0f9ed7b46a6d..322bc5f7d86b 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c | |||
@@ -111,7 +111,7 @@ static int last_hvc = -1; | |||
111 | * lock held. If successful, this function increments the kobject reference | 111 | * lock held. If successful, this function increments the kobject reference |
112 | * count against the target hvc_struct so it should be released when finished. | 112 | * count against the target hvc_struct so it should be released when finished. |
113 | */ | 113 | */ |
114 | struct hvc_struct *hvc_get_by_index(int index) | 114 | static struct hvc_struct *hvc_get_by_index(int index) |
115 | { | 115 | { |
116 | struct hvc_struct *hp; | 116 | struct hvc_struct *hp; |
117 | unsigned long flags; | 117 | unsigned long flags; |
@@ -150,7 +150,8 @@ static uint32_t vtermnos[MAX_NR_HVC_CONSOLES] = | |||
150 | * hvc_console_setup() finds adapters. | 150 | * hvc_console_setup() finds adapters. |
151 | */ | 151 | */ |
152 | 152 | ||
153 | void hvc_console_print(struct console *co, const char *b, unsigned count) | 153 | static void hvc_console_print(struct console *co, const char *b, |
154 | unsigned count) | ||
154 | { | 155 | { |
155 | char c[N_OUTBUF] __ALIGNED__; | 156 | char c[N_OUTBUF] __ALIGNED__; |
156 | unsigned i = 0, n = 0; | 157 | unsigned i = 0, n = 0; |
@@ -208,7 +209,7 @@ static int __init hvc_console_setup(struct console *co, char *options) | |||
208 | return 0; | 209 | return 0; |
209 | } | 210 | } |
210 | 211 | ||
211 | struct console hvc_con_driver = { | 212 | static struct console hvc_con_driver = { |
212 | .name = "hvc", | 213 | .name = "hvc", |
213 | .write = hvc_console_print, | 214 | .write = hvc_console_print, |
214 | .device = hvc_console_device, | 215 | .device = hvc_console_device, |
@@ -278,7 +279,6 @@ int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops) | |||
278 | 279 | ||
279 | return 0; | 280 | return 0; |
280 | } | 281 | } |
281 | EXPORT_SYMBOL(hvc_instantiate); | ||
282 | 282 | ||
283 | /* Wake the sleeping khvcd */ | 283 | /* Wake the sleeping khvcd */ |
284 | static void hvc_kick(void) | 284 | static void hvc_kick(void) |
@@ -792,7 +792,6 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq, | |||
792 | 792 | ||
793 | return hp; | 793 | return hp; |
794 | } | 794 | } |
795 | EXPORT_SYMBOL(hvc_alloc); | ||
796 | 795 | ||
797 | int __devexit hvc_remove(struct hvc_struct *hp) | 796 | int __devexit hvc_remove(struct hvc_struct *hp) |
798 | { | 797 | { |
@@ -828,11 +827,10 @@ int __devexit hvc_remove(struct hvc_struct *hp) | |||
828 | tty_hangup(tty); | 827 | tty_hangup(tty); |
829 | return 0; | 828 | return 0; |
830 | } | 829 | } |
831 | EXPORT_SYMBOL(hvc_remove); | ||
832 | 830 | ||
833 | /* Driver initialization. Follow console initialization. This is where the TTY | 831 | /* Driver initialization. Follow console initialization. This is where the TTY |
834 | * interfaces start to become available. */ | 832 | * interfaces start to become available. */ |
835 | int __init hvc_init(void) | 833 | static int __init hvc_init(void) |
836 | { | 834 | { |
837 | struct tty_driver *drv; | 835 | struct tty_driver *drv; |
838 | 836 | ||
diff --git a/drivers/char/hvc_iseries.c b/drivers/char/hvc_iseries.c index ec420fe8a908..b37f1d5a5be6 100644 --- a/drivers/char/hvc_iseries.c +++ b/drivers/char/hvc_iseries.c | |||
@@ -579,7 +579,7 @@ static int hvc_find_vtys(void) | |||
579 | if (!vtermno) | 579 | if (!vtermno) |
580 | continue; | 580 | continue; |
581 | 581 | ||
582 | if (!device_is_compatible(vty, "IBM,iSeries-vty")) | 582 | if (!of_device_is_compatible(vty, "IBM,iSeries-vty")) |
583 | continue; | 583 | continue; |
584 | 584 | ||
585 | if (num_found == 0) | 585 | if (num_found == 0) |
diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c index 94a542e20efb..79711aa4b41d 100644 --- a/drivers/char/hvc_vio.c +++ b/drivers/char/hvc_vio.c | |||
@@ -157,7 +157,7 @@ static int hvc_find_vtys(void) | |||
157 | if (!vtermno) | 157 | if (!vtermno) |
158 | continue; | 158 | continue; |
159 | 159 | ||
160 | if (device_is_compatible(vty, "hvterm1")) { | 160 | if (of_device_is_compatible(vty, "hvterm1")) { |
161 | hvc_instantiate(*vtermno, num_found, &hvc_get_put_ops); | 161 | hvc_instantiate(*vtermno, num_found, &hvc_get_put_ops); |
162 | ++num_found; | 162 | ++num_found; |
163 | } | 163 | } |
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 5f3acd8e64b8..7cda04b33534 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig | |||
@@ -91,3 +91,17 @@ config HW_RANDOM_OMAP | |||
91 | module will be called omap-rng. | 91 | module will be called omap-rng. |
92 | 92 | ||
93 | If unsure, say Y. | 93 | If unsure, say Y. |
94 | |||
95 | config HW_RANDOM_PASEMI | ||
96 | tristate "PA Semi HW Random Number Generator support" | ||
97 | depends on HW_RANDOM && PPC_PASEMI | ||
98 | default HW_RANDOM | ||
99 | ---help--- | ||
100 | This driver provides kernel-side support for the Random Number | ||
101 | Generator hardware found on PA6T-1682M processor. | ||
102 | |||
103 | To compile this driver as a module, choose M here: the | ||
104 | module will be called pasemi-rng. | ||
105 | |||
106 | If unsure, say Y. | ||
107 | |||
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index c41fa19454e3..c8b7300e2fb1 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile | |||
@@ -10,3 +10,4 @@ obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o | |||
10 | obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o | 10 | obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o |
11 | obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o | 11 | obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o |
12 | obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o | 12 | obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o |
13 | obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o | ||
diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c index cc1046e6ee02..4ae9811d1a6c 100644 --- a/drivers/char/hw_random/intel-rng.c +++ b/drivers/char/hw_random/intel-rng.c | |||
@@ -24,10 +24,11 @@ | |||
24 | * warranty of any kind, whether express or implied. | 24 | * warranty of any kind, whether express or implied. |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <linux/module.h> | 27 | #include <linux/hw_random.h> |
28 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
29 | #include <linux/module.h> | ||
29 | #include <linux/pci.h> | 30 | #include <linux/pci.h> |
30 | #include <linux/hw_random.h> | 31 | #include <linux/stop_machine.h> |
31 | #include <asm/io.h> | 32 | #include <asm/io.h> |
32 | 33 | ||
33 | 34 | ||
@@ -217,30 +218,117 @@ static struct hwrng intel_rng = { | |||
217 | .data_read = intel_rng_data_read, | 218 | .data_read = intel_rng_data_read, |
218 | }; | 219 | }; |
219 | 220 | ||
221 | struct intel_rng_hw { | ||
222 | struct pci_dev *dev; | ||
223 | void __iomem *mem; | ||
224 | u8 bios_cntl_off; | ||
225 | u8 bios_cntl_val; | ||
226 | u8 fwh_dec_en1_off; | ||
227 | u8 fwh_dec_en1_val; | ||
228 | }; | ||
220 | 229 | ||
221 | #ifdef CONFIG_SMP | 230 | static int __init intel_rng_hw_init(void *_intel_rng_hw) |
222 | static char __initdata waitflag; | 231 | { |
232 | struct intel_rng_hw *intel_rng_hw = _intel_rng_hw; | ||
233 | u8 mfc, dvc; | ||
234 | |||
235 | /* interrupts disabled in stop_machine_run call */ | ||
236 | |||
237 | if (!(intel_rng_hw->fwh_dec_en1_val & FWH_F8_EN_MASK)) | ||
238 | pci_write_config_byte(intel_rng_hw->dev, | ||
239 | intel_rng_hw->fwh_dec_en1_off, | ||
240 | intel_rng_hw->fwh_dec_en1_val | | ||
241 | FWH_F8_EN_MASK); | ||
242 | if (!(intel_rng_hw->bios_cntl_val & BIOS_CNTL_WRITE_ENABLE_MASK)) | ||
243 | pci_write_config_byte(intel_rng_hw->dev, | ||
244 | intel_rng_hw->bios_cntl_off, | ||
245 | intel_rng_hw->bios_cntl_val | | ||
246 | BIOS_CNTL_WRITE_ENABLE_MASK); | ||
247 | |||
248 | writeb(INTEL_FWH_RESET_CMD, intel_rng_hw->mem); | ||
249 | writeb(INTEL_FWH_READ_ID_CMD, intel_rng_hw->mem); | ||
250 | mfc = readb(intel_rng_hw->mem + INTEL_FWH_MANUFACTURER_CODE_ADDRESS); | ||
251 | dvc = readb(intel_rng_hw->mem + INTEL_FWH_DEVICE_CODE_ADDRESS); | ||
252 | writeb(INTEL_FWH_RESET_CMD, intel_rng_hw->mem); | ||
253 | |||
254 | if (!(intel_rng_hw->bios_cntl_val & | ||
255 | (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK))) | ||
256 | pci_write_config_byte(intel_rng_hw->dev, | ||
257 | intel_rng_hw->bios_cntl_off, | ||
258 | intel_rng_hw->bios_cntl_val); | ||
259 | if (!(intel_rng_hw->fwh_dec_en1_val & FWH_F8_EN_MASK)) | ||
260 | pci_write_config_byte(intel_rng_hw->dev, | ||
261 | intel_rng_hw->fwh_dec_en1_off, | ||
262 | intel_rng_hw->fwh_dec_en1_val); | ||
223 | 263 | ||
224 | static void __init intel_init_wait(void *unused) | 264 | if (mfc != INTEL_FWH_MANUFACTURER_CODE || |
265 | (dvc != INTEL_FWH_DEVICE_CODE_8M && | ||
266 | dvc != INTEL_FWH_DEVICE_CODE_4M)) { | ||
267 | printk(KERN_ERR PFX "FWH not detected\n"); | ||
268 | return -ENODEV; | ||
269 | } | ||
270 | |||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | static int __init intel_init_hw_struct(struct intel_rng_hw *intel_rng_hw, | ||
275 | struct pci_dev *dev) | ||
225 | { | 276 | { |
226 | while (waitflag) | 277 | intel_rng_hw->bios_cntl_val = 0xff; |
227 | cpu_relax(); | 278 | intel_rng_hw->fwh_dec_en1_val = 0xff; |
279 | intel_rng_hw->dev = dev; | ||
280 | |||
281 | /* Check for Intel 82802 */ | ||
282 | if (dev->device < 0x2640) { | ||
283 | intel_rng_hw->fwh_dec_en1_off = FWH_DEC_EN1_REG_OLD; | ||
284 | intel_rng_hw->bios_cntl_off = BIOS_CNTL_REG_OLD; | ||
285 | } else { | ||
286 | intel_rng_hw->fwh_dec_en1_off = FWH_DEC_EN1_REG_NEW; | ||
287 | intel_rng_hw->bios_cntl_off = BIOS_CNTL_REG_NEW; | ||
288 | } | ||
289 | |||
290 | pci_read_config_byte(dev, intel_rng_hw->fwh_dec_en1_off, | ||
291 | &intel_rng_hw->fwh_dec_en1_val); | ||
292 | pci_read_config_byte(dev, intel_rng_hw->bios_cntl_off, | ||
293 | &intel_rng_hw->bios_cntl_val); | ||
294 | |||
295 | if ((intel_rng_hw->bios_cntl_val & | ||
296 | (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)) | ||
297 | == BIOS_CNTL_LOCK_ENABLE_MASK) { | ||
298 | static __initdata /*const*/ char warning[] = | ||
299 | KERN_WARNING PFX "Firmware space is locked read-only. " | ||
300 | KERN_WARNING PFX "If you can't or\n don't want to " | ||
301 | KERN_WARNING PFX "disable this in firmware setup, and " | ||
302 | KERN_WARNING PFX "if\n you are certain that your " | ||
303 | KERN_WARNING PFX "system has a functional\n RNG, try" | ||
304 | KERN_WARNING PFX "using the 'no_fwh_detect' option.\n"; | ||
305 | |||
306 | if (no_fwh_detect) | ||
307 | return -ENODEV; | ||
308 | printk(warning); | ||
309 | return -EBUSY; | ||
310 | } | ||
311 | |||
312 | intel_rng_hw->mem = ioremap_nocache(INTEL_FWH_ADDR, INTEL_FWH_ADDR_LEN); | ||
313 | if (intel_rng_hw->mem == NULL) | ||
314 | return -EBUSY; | ||
315 | |||
316 | return 0; | ||
228 | } | 317 | } |
229 | #endif | 318 | |
230 | 319 | ||
231 | static int __init mod_init(void) | 320 | static int __init mod_init(void) |
232 | { | 321 | { |
233 | int err = -ENODEV; | 322 | int err = -ENODEV; |
234 | unsigned i; | 323 | int i; |
235 | struct pci_dev *dev = NULL; | 324 | struct pci_dev *dev = NULL; |
236 | void __iomem *mem; | 325 | void __iomem *mem = mem; |
237 | unsigned long flags; | 326 | u8 hw_status; |
238 | u8 bios_cntl_off, fwh_dec_en1_off; | 327 | struct intel_rng_hw *intel_rng_hw; |
239 | u8 bios_cntl_val = 0xff, fwh_dec_en1_val = 0xff; | ||
240 | u8 hw_status, mfc, dvc; | ||
241 | 328 | ||
242 | for (i = 0; !dev && pci_tbl[i].vendor; ++i) | 329 | for (i = 0; !dev && pci_tbl[i].vendor; ++i) |
243 | dev = pci_get_device(pci_tbl[i].vendor, pci_tbl[i].device, NULL); | 330 | dev = pci_get_device(pci_tbl[i].vendor, pci_tbl[i].device, |
331 | NULL); | ||
244 | 332 | ||
245 | if (!dev) | 333 | if (!dev) |
246 | goto out; /* Device not found. */ | 334 | goto out; /* Device not found. */ |
@@ -250,39 +338,18 @@ static int __init mod_init(void) | |||
250 | goto fwh_done; | 338 | goto fwh_done; |
251 | } | 339 | } |
252 | 340 | ||
253 | /* Check for Intel 82802 */ | 341 | intel_rng_hw = kmalloc(sizeof(*intel_rng_hw), GFP_KERNEL); |
254 | if (dev->device < 0x2640) { | 342 | if (!intel_rng_hw) { |
255 | fwh_dec_en1_off = FWH_DEC_EN1_REG_OLD; | ||
256 | bios_cntl_off = BIOS_CNTL_REG_OLD; | ||
257 | } else { | ||
258 | fwh_dec_en1_off = FWH_DEC_EN1_REG_NEW; | ||
259 | bios_cntl_off = BIOS_CNTL_REG_NEW; | ||
260 | } | ||
261 | |||
262 | pci_read_config_byte(dev, fwh_dec_en1_off, &fwh_dec_en1_val); | ||
263 | pci_read_config_byte(dev, bios_cntl_off, &bios_cntl_val); | ||
264 | |||
265 | if ((bios_cntl_val & | ||
266 | (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)) | ||
267 | == BIOS_CNTL_LOCK_ENABLE_MASK) { | ||
268 | static __initdata /*const*/ char warning[] = | ||
269 | KERN_WARNING PFX "Firmware space is locked read-only. If you can't or\n" | ||
270 | KERN_WARNING PFX "don't want to disable this in firmware setup, and if\n" | ||
271 | KERN_WARNING PFX "you are certain that your system has a functional\n" | ||
272 | KERN_WARNING PFX "RNG, try using the 'no_fwh_detect' option.\n"; | ||
273 | |||
274 | pci_dev_put(dev); | 343 | pci_dev_put(dev); |
275 | if (no_fwh_detect) | ||
276 | goto fwh_done; | ||
277 | printk(warning); | ||
278 | err = -EBUSY; | ||
279 | goto out; | 344 | goto out; |
280 | } | 345 | } |
281 | 346 | ||
282 | mem = ioremap_nocache(INTEL_FWH_ADDR, INTEL_FWH_ADDR_LEN); | 347 | err = intel_init_hw_struct(intel_rng_hw, dev); |
283 | if (mem == NULL) { | 348 | if (err) { |
284 | pci_dev_put(dev); | 349 | pci_dev_put(dev); |
285 | err = -EBUSY; | 350 | kfree(intel_rng_hw); |
351 | if (err == -ENODEV) | ||
352 | goto fwh_done; | ||
286 | goto out; | 353 | goto out; |
287 | } | 354 | } |
288 | 355 | ||
@@ -290,59 +357,18 @@ static int __init mod_init(void) | |||
290 | * Since the BIOS code/data is going to disappear from its normal | 357 | * Since the BIOS code/data is going to disappear from its normal |
291 | * location with the Read ID command, all activity on the system | 358 | * location with the Read ID command, all activity on the system |
292 | * must be stopped until the state is back to normal. | 359 | * must be stopped until the state is back to normal. |
360 | * | ||
361 | * Use stop_machine_run because IPIs can be blocked by disabling | ||
362 | * interrupts. | ||
293 | */ | 363 | */ |
294 | #ifdef CONFIG_SMP | 364 | err = stop_machine_run(intel_rng_hw_init, intel_rng_hw, NR_CPUS); |
295 | set_mb(waitflag, 1); | ||
296 | if (smp_call_function(intel_init_wait, NULL, 1, 0) != 0) { | ||
297 | set_mb(waitflag, 0); | ||
298 | pci_dev_put(dev); | ||
299 | printk(KERN_ERR PFX "cannot run on all processors\n"); | ||
300 | err = -EAGAIN; | ||
301 | goto err_unmap; | ||
302 | } | ||
303 | #endif | ||
304 | local_irq_save(flags); | ||
305 | |||
306 | if (!(fwh_dec_en1_val & FWH_F8_EN_MASK)) | ||
307 | pci_write_config_byte(dev, | ||
308 | fwh_dec_en1_off, | ||
309 | fwh_dec_en1_val | FWH_F8_EN_MASK); | ||
310 | if (!(bios_cntl_val & BIOS_CNTL_WRITE_ENABLE_MASK)) | ||
311 | pci_write_config_byte(dev, | ||
312 | bios_cntl_off, | ||
313 | bios_cntl_val | BIOS_CNTL_WRITE_ENABLE_MASK); | ||
314 | |||
315 | writeb(INTEL_FWH_RESET_CMD, mem); | ||
316 | writeb(INTEL_FWH_READ_ID_CMD, mem); | ||
317 | mfc = readb(mem + INTEL_FWH_MANUFACTURER_CODE_ADDRESS); | ||
318 | dvc = readb(mem + INTEL_FWH_DEVICE_CODE_ADDRESS); | ||
319 | writeb(INTEL_FWH_RESET_CMD, mem); | ||
320 | |||
321 | if (!(bios_cntl_val & | ||
322 | (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK))) | ||
323 | pci_write_config_byte(dev, bios_cntl_off, bios_cntl_val); | ||
324 | if (!(fwh_dec_en1_val & FWH_F8_EN_MASK)) | ||
325 | pci_write_config_byte(dev, fwh_dec_en1_off, fwh_dec_en1_val); | ||
326 | |||
327 | local_irq_restore(flags); | ||
328 | #ifdef CONFIG_SMP | ||
329 | /* Tell other CPUs to resume. */ | ||
330 | set_mb(waitflag, 0); | ||
331 | #endif | ||
332 | |||
333 | iounmap(mem); | ||
334 | pci_dev_put(dev); | 365 | pci_dev_put(dev); |
335 | 366 | iounmap(intel_rng_hw->mem); | |
336 | if (mfc != INTEL_FWH_MANUFACTURER_CODE || | 367 | kfree(intel_rng_hw); |
337 | (dvc != INTEL_FWH_DEVICE_CODE_8M && | 368 | if (err) |
338 | dvc != INTEL_FWH_DEVICE_CODE_4M)) { | ||
339 | printk(KERN_ERR PFX "FWH not detected\n"); | ||
340 | err = -ENODEV; | ||
341 | goto out; | 369 | goto out; |
342 | } | ||
343 | 370 | ||
344 | fwh_done: | 371 | fwh_done: |
345 | |||
346 | err = -ENOMEM; | 372 | err = -ENOMEM; |
347 | mem = ioremap(INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN); | 373 | mem = ioremap(INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN); |
348 | if (!mem) | 374 | if (!mem) |
@@ -352,22 +378,21 @@ fwh_done: | |||
352 | /* Check for Random Number Generator */ | 378 | /* Check for Random Number Generator */ |
353 | err = -ENODEV; | 379 | err = -ENODEV; |
354 | hw_status = hwstatus_get(mem); | 380 | hw_status = hwstatus_get(mem); |
355 | if ((hw_status & INTEL_RNG_PRESENT) == 0) | 381 | if ((hw_status & INTEL_RNG_PRESENT) == 0) { |
356 | goto err_unmap; | 382 | iounmap(mem); |
383 | goto out; | ||
384 | } | ||
357 | 385 | ||
358 | printk(KERN_INFO "Intel 82802 RNG detected\n"); | 386 | printk(KERN_INFO "Intel 82802 RNG detected\n"); |
359 | err = hwrng_register(&intel_rng); | 387 | err = hwrng_register(&intel_rng); |
360 | if (err) { | 388 | if (err) { |
361 | printk(KERN_ERR PFX "RNG registering failed (%d)\n", | 389 | printk(KERN_ERR PFX "RNG registering failed (%d)\n", |
362 | err); | 390 | err); |
363 | goto err_unmap; | 391 | iounmap(mem); |
364 | } | 392 | } |
365 | out: | 393 | out: |
366 | return err; | 394 | return err; |
367 | 395 | ||
368 | err_unmap: | ||
369 | iounmap(mem); | ||
370 | goto out; | ||
371 | } | 396 | } |
372 | 397 | ||
373 | static void __exit mod_exit(void) | 398 | static void __exit mod_exit(void) |
diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c new file mode 100644 index 000000000000..fa6040b6c8f2 --- /dev/null +++ b/drivers/char/hw_random/pasemi-rng.c | |||
@@ -0,0 +1,156 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2006-2007 PA Semi, Inc | ||
3 | * | ||
4 | * Maintained by: Olof Johansson <olof@lixom.net> | ||
5 | * | ||
6 | * Driver for the PWRficient onchip rng | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/hw_random.h> | ||
26 | #include <asm/of_platform.h> | ||
27 | #include <asm/io.h> | ||
28 | |||
29 | #define SDCRNG_CTL_REG 0x00 | ||
30 | #define SDCRNG_CTL_FVLD_M 0x0000f000 | ||
31 | #define SDCRNG_CTL_FVLD_S 12 | ||
32 | #define SDCRNG_CTL_KSZ 0x00000800 | ||
33 | #define SDCRNG_CTL_RSRC_CRG 0x00000010 | ||
34 | #define SDCRNG_CTL_RSRC_RRG 0x00000000 | ||
35 | #define SDCRNG_CTL_CE 0x00000004 | ||
36 | #define SDCRNG_CTL_RE 0x00000002 | ||
37 | #define SDCRNG_CTL_DR 0x00000001 | ||
38 | #define SDCRNG_CTL_SELECT_RRG_RNG (SDCRNG_CTL_RE | SDCRNG_CTL_RSRC_RRG) | ||
39 | #define SDCRNG_CTL_SELECT_CRG_RNG (SDCRNG_CTL_CE | SDCRNG_CTL_RSRC_CRG) | ||
40 | #define SDCRNG_VAL_REG 0x20 | ||
41 | |||
42 | #define MODULE_NAME "pasemi_rng" | ||
43 | |||
44 | static int pasemi_rng_data_present(struct hwrng *rng) | ||
45 | { | ||
46 | void __iomem *rng_regs = (void __iomem *)rng->priv; | ||
47 | |||
48 | return (in_le32(rng_regs + SDCRNG_CTL_REG) | ||
49 | & SDCRNG_CTL_FVLD_M) ? 1 : 0; | ||
50 | } | ||
51 | |||
52 | static int pasemi_rng_data_read(struct hwrng *rng, u32 *data) | ||
53 | { | ||
54 | void __iomem *rng_regs = (void __iomem *)rng->priv; | ||
55 | *data = in_le32(rng_regs + SDCRNG_VAL_REG); | ||
56 | return 4; | ||
57 | } | ||
58 | |||
59 | static int pasemi_rng_init(struct hwrng *rng) | ||
60 | { | ||
61 | void __iomem *rng_regs = (void __iomem *)rng->priv; | ||
62 | u32 ctl; | ||
63 | |||
64 | ctl = SDCRNG_CTL_DR | SDCRNG_CTL_SELECT_RRG_RNG | SDCRNG_CTL_KSZ; | ||
65 | out_le32(rng_regs + SDCRNG_CTL_REG, ctl); | ||
66 | out_le32(rng_regs + SDCRNG_CTL_REG, ctl & ~SDCRNG_CTL_DR); | ||
67 | |||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | static void pasemi_rng_cleanup(struct hwrng *rng) | ||
72 | { | ||
73 | void __iomem *rng_regs = (void __iomem *)rng->priv; | ||
74 | u32 ctl; | ||
75 | |||
76 | ctl = SDCRNG_CTL_RE | SDCRNG_CTL_CE; | ||
77 | out_le32(rng_regs + SDCRNG_CTL_REG, | ||
78 | in_le32(rng_regs + SDCRNG_CTL_REG) & ~ctl); | ||
79 | } | ||
80 | |||
81 | static struct hwrng pasemi_rng = { | ||
82 | .name = MODULE_NAME, | ||
83 | .init = pasemi_rng_init, | ||
84 | .cleanup = pasemi_rng_cleanup, | ||
85 | .data_present = pasemi_rng_data_present, | ||
86 | .data_read = pasemi_rng_data_read, | ||
87 | }; | ||
88 | |||
89 | static int __devinit rng_probe(struct of_device *ofdev, | ||
90 | const struct of_device_id *match) | ||
91 | { | ||
92 | void __iomem *rng_regs; | ||
93 | struct device_node *rng_np = ofdev->node; | ||
94 | struct resource res; | ||
95 | int err = 0; | ||
96 | |||
97 | err = of_address_to_resource(rng_np, 0, &res); | ||
98 | if (err) | ||
99 | return -ENODEV; | ||
100 | |||
101 | rng_regs = ioremap(res.start, 0x100); | ||
102 | |||
103 | if (!rng_regs) | ||
104 | return -ENOMEM; | ||
105 | |||
106 | pasemi_rng.priv = (unsigned long)rng_regs; | ||
107 | |||
108 | printk(KERN_INFO "Registering PA Semi RNG\n"); | ||
109 | |||
110 | err = hwrng_register(&pasemi_rng); | ||
111 | |||
112 | if (err) | ||
113 | iounmap(rng_regs); | ||
114 | |||
115 | return err; | ||
116 | } | ||
117 | |||
118 | static int __devexit rng_remove(struct of_device *dev) | ||
119 | { | ||
120 | void __iomem *rng_regs = (void __iomem *)pasemi_rng.priv; | ||
121 | |||
122 | hwrng_unregister(&pasemi_rng); | ||
123 | iounmap(rng_regs); | ||
124 | |||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | static struct of_device_id rng_match[] = { | ||
129 | { | ||
130 | .compatible = "1682m-rng", | ||
131 | }, | ||
132 | {}, | ||
133 | }; | ||
134 | |||
135 | static struct of_platform_driver rng_driver = { | ||
136 | .name = "pasemi-rng", | ||
137 | .match_table = rng_match, | ||
138 | .probe = rng_probe, | ||
139 | .remove = rng_remove, | ||
140 | }; | ||
141 | |||
142 | static int __init rng_init(void) | ||
143 | { | ||
144 | return of_register_platform_driver(&rng_driver); | ||
145 | } | ||
146 | module_init(rng_init); | ||
147 | |||
148 | static void __exit rng_exit(void) | ||
149 | { | ||
150 | of_unregister_platform_driver(&rng_driver); | ||
151 | } | ||
152 | module_exit(rng_exit); | ||
153 | |||
154 | MODULE_LICENSE("GPL"); | ||
155 | MODULE_AUTHOR("Egor Martovetsky <egor@pasemi.com>"); | ||
156 | MODULE_DESCRIPTION("H/W RNG driver for PA Semi processor"); | ||
diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c index 9ebf84d18655..ec435cb25c4f 100644 --- a/drivers/char/hw_random/via-rng.c +++ b/drivers/char/hw_random/via-rng.c | |||
@@ -26,7 +26,6 @@ | |||
26 | 26 | ||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
29 | #include <linux/pci.h> | ||
30 | #include <linux/hw_random.h> | 29 | #include <linux/hw_random.h> |
31 | #include <asm/io.h> | 30 | #include <asm/io.h> |
32 | #include <asm/msr.h> | 31 | #include <asm/msr.h> |
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c index 353d9f3cf8d7..0289705967de 100644 --- a/drivers/char/i8k.c +++ b/drivers/char/i8k.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/proc_fs.h> | 22 | #include <linux/proc_fs.h> |
23 | #include <linux/seq_file.h> | 23 | #include <linux/seq_file.h> |
24 | #include <linux/dmi.h> | 24 | #include <linux/dmi.h> |
25 | #include <linux/capability.h> | ||
25 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
26 | #include <asm/io.h> | 27 | #include <asm/io.h> |
27 | 28 | ||
diff --git a/drivers/char/ip27-rtc.c b/drivers/char/ip27-rtc.c index a48da02aad2f..932264a657d0 100644 --- a/drivers/char/ip27-rtc.c +++ b/drivers/char/ip27-rtc.c | |||
@@ -35,7 +35,6 @@ | |||
35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
36 | #include <linux/poll.h> | 36 | #include <linux/poll.h> |
37 | #include <linux/proc_fs.h> | 37 | #include <linux/proc_fs.h> |
38 | #include <linux/smp_lock.h> | ||
39 | 38 | ||
40 | #include <asm/m48t35.h> | 39 | #include <asm/m48t35.h> |
41 | #include <asm/sn/ioc3.h> | 40 | #include <asm/sn/ioc3.h> |
diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig index a6dcb2918157..b894f67fdf14 100644 --- a/drivers/char/ipmi/Kconfig +++ b/drivers/char/ipmi/Kconfig | |||
@@ -3,6 +3,8 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | menu "IPMI" | 5 | menu "IPMI" |
6 | depends on HAS_IOMEM | ||
7 | |||
6 | config IPMI_HANDLER | 8 | config IPMI_HANDLER |
7 | tristate 'IPMI top-level message handler' | 9 | tristate 'IPMI top-level message handler' |
8 | help | 10 | help |
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index e22146546add..6c5d15de3317 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -9,6 +9,7 @@ | |||
9 | * source@mvista.com | 9 | * source@mvista.com |
10 | * | 10 | * |
11 | * Copyright 2002 MontaVista Software Inc. | 11 | * Copyright 2002 MontaVista Software Inc. |
12 | * Copyright 2006 IBM Corp., Christian Krafft <krafft@de.ibm.com> | ||
12 | * | 13 | * |
13 | * This program is free software; you can redistribute it and/or modify it | 14 | * This program is free software; you can redistribute it and/or modify it |
14 | * under the terms of the GNU General Public License as published by the | 15 | * under the terms of the GNU General Public License as published by the |
@@ -64,6 +65,11 @@ | |||
64 | #include <linux/string.h> | 65 | #include <linux/string.h> |
65 | #include <linux/ctype.h> | 66 | #include <linux/ctype.h> |
66 | 67 | ||
68 | #ifdef CONFIG_PPC_OF | ||
69 | #include <asm/of_device.h> | ||
70 | #include <asm/of_platform.h> | ||
71 | #endif | ||
72 | |||
67 | #define PFX "ipmi_si: " | 73 | #define PFX "ipmi_si: " |
68 | 74 | ||
69 | /* Measure times between events in the driver. */ | 75 | /* Measure times between events in the driver. */ |
@@ -76,6 +82,12 @@ | |||
76 | #define SI_SHORT_TIMEOUT_USEC 250 /* .25ms when the SM request a | 82 | #define SI_SHORT_TIMEOUT_USEC 250 /* .25ms when the SM request a |
77 | short timeout */ | 83 | short timeout */ |
78 | 84 | ||
85 | /* Bit for BMC global enables. */ | ||
86 | #define IPMI_BMC_RCV_MSG_INTR 0x01 | ||
87 | #define IPMI_BMC_EVT_MSG_INTR 0x02 | ||
88 | #define IPMI_BMC_EVT_MSG_BUFF 0x04 | ||
89 | #define IPMI_BMC_SYS_LOG 0x08 | ||
90 | |||
79 | enum si_intf_state { | 91 | enum si_intf_state { |
80 | SI_NORMAL, | 92 | SI_NORMAL, |
81 | SI_GETTING_FLAGS, | 93 | SI_GETTING_FLAGS, |
@@ -84,7 +96,9 @@ enum si_intf_state { | |||
84 | SI_CLEARING_FLAGS_THEN_SET_IRQ, | 96 | SI_CLEARING_FLAGS_THEN_SET_IRQ, |
85 | SI_GETTING_MESSAGES, | 97 | SI_GETTING_MESSAGES, |
86 | SI_ENABLE_INTERRUPTS1, | 98 | SI_ENABLE_INTERRUPTS1, |
87 | SI_ENABLE_INTERRUPTS2 | 99 | SI_ENABLE_INTERRUPTS2, |
100 | SI_DISABLE_INTERRUPTS1, | ||
101 | SI_DISABLE_INTERRUPTS2 | ||
88 | /* FIXME - add watchdog stuff. */ | 102 | /* FIXME - add watchdog stuff. */ |
89 | }; | 103 | }; |
90 | 104 | ||
@@ -333,6 +347,17 @@ static void start_enable_irq(struct smi_info *smi_info) | |||
333 | smi_info->si_state = SI_ENABLE_INTERRUPTS1; | 347 | smi_info->si_state = SI_ENABLE_INTERRUPTS1; |
334 | } | 348 | } |
335 | 349 | ||
350 | static void start_disable_irq(struct smi_info *smi_info) | ||
351 | { | ||
352 | unsigned char msg[2]; | ||
353 | |||
354 | msg[0] = (IPMI_NETFN_APP_REQUEST << 2); | ||
355 | msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD; | ||
356 | |||
357 | smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2); | ||
358 | smi_info->si_state = SI_DISABLE_INTERRUPTS1; | ||
359 | } | ||
360 | |||
336 | static void start_clear_flags(struct smi_info *smi_info) | 361 | static void start_clear_flags(struct smi_info *smi_info) |
337 | { | 362 | { |
338 | unsigned char msg[3]; | 363 | unsigned char msg[3]; |
@@ -353,7 +378,7 @@ static void start_clear_flags(struct smi_info *smi_info) | |||
353 | static inline void disable_si_irq(struct smi_info *smi_info) | 378 | static inline void disable_si_irq(struct smi_info *smi_info) |
354 | { | 379 | { |
355 | if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { | 380 | if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { |
356 | disable_irq_nosync(smi_info->irq); | 381 | start_disable_irq(smi_info); |
357 | smi_info->interrupt_disabled = 1; | 382 | smi_info->interrupt_disabled = 1; |
358 | } | 383 | } |
359 | } | 384 | } |
@@ -361,7 +386,7 @@ static inline void disable_si_irq(struct smi_info *smi_info) | |||
361 | static inline void enable_si_irq(struct smi_info *smi_info) | 386 | static inline void enable_si_irq(struct smi_info *smi_info) |
362 | { | 387 | { |
363 | if ((smi_info->irq) && (smi_info->interrupt_disabled)) { | 388 | if ((smi_info->irq) && (smi_info->interrupt_disabled)) { |
364 | enable_irq(smi_info->irq); | 389 | start_enable_irq(smi_info); |
365 | smi_info->interrupt_disabled = 0; | 390 | smi_info->interrupt_disabled = 0; |
366 | } | 391 | } |
367 | } | 392 | } |
@@ -583,7 +608,9 @@ static void handle_transaction_done(struct smi_info *smi_info) | |||
583 | } else { | 608 | } else { |
584 | msg[0] = (IPMI_NETFN_APP_REQUEST << 2); | 609 | msg[0] = (IPMI_NETFN_APP_REQUEST << 2); |
585 | msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD; | 610 | msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD; |
586 | msg[2] = msg[3] | 1; /* enable msg queue int */ | 611 | msg[2] = (msg[3] | |
612 | IPMI_BMC_RCV_MSG_INTR | | ||
613 | IPMI_BMC_EVT_MSG_INTR); | ||
587 | smi_info->handlers->start_transaction( | 614 | smi_info->handlers->start_transaction( |
588 | smi_info->si_sm, msg, 3); | 615 | smi_info->si_sm, msg, 3); |
589 | smi_info->si_state = SI_ENABLE_INTERRUPTS2; | 616 | smi_info->si_state = SI_ENABLE_INTERRUPTS2; |
@@ -605,6 +632,45 @@ static void handle_transaction_done(struct smi_info *smi_info) | |||
605 | smi_info->si_state = SI_NORMAL; | 632 | smi_info->si_state = SI_NORMAL; |
606 | break; | 633 | break; |
607 | } | 634 | } |
635 | |||
636 | case SI_DISABLE_INTERRUPTS1: | ||
637 | { | ||
638 | unsigned char msg[4]; | ||
639 | |||
640 | /* We got the flags from the SMI, now handle them. */ | ||
641 | smi_info->handlers->get_result(smi_info->si_sm, msg, 4); | ||
642 | if (msg[2] != 0) { | ||
643 | printk(KERN_WARNING | ||
644 | "ipmi_si: Could not disable interrupts" | ||
645 | ", failed get.\n"); | ||
646 | smi_info->si_state = SI_NORMAL; | ||
647 | } else { | ||
648 | msg[0] = (IPMI_NETFN_APP_REQUEST << 2); | ||
649 | msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD; | ||
650 | msg[2] = (msg[3] & | ||
651 | ~(IPMI_BMC_RCV_MSG_INTR | | ||
652 | IPMI_BMC_EVT_MSG_INTR)); | ||
653 | smi_info->handlers->start_transaction( | ||
654 | smi_info->si_sm, msg, 3); | ||
655 | smi_info->si_state = SI_DISABLE_INTERRUPTS2; | ||
656 | } | ||
657 | break; | ||
658 | } | ||
659 | |||
660 | case SI_DISABLE_INTERRUPTS2: | ||
661 | { | ||
662 | unsigned char msg[4]; | ||
663 | |||
664 | /* We got the flags from the SMI, now handle them. */ | ||
665 | smi_info->handlers->get_result(smi_info->si_sm, msg, 4); | ||
666 | if (msg[2] != 0) { | ||
667 | printk(KERN_WARNING | ||
668 | "ipmi_si: Could not disable interrupts" | ||
669 | ", failed set.\n"); | ||
670 | } | ||
671 | smi_info->si_state = SI_NORMAL; | ||
672 | break; | ||
673 | } | ||
608 | } | 674 | } |
609 | } | 675 | } |
610 | 676 | ||
@@ -858,9 +924,6 @@ static void smi_timeout(unsigned long data) | |||
858 | struct timeval t; | 924 | struct timeval t; |
859 | #endif | 925 | #endif |
860 | 926 | ||
861 | if (atomic_read(&smi_info->stop_operation)) | ||
862 | return; | ||
863 | |||
864 | spin_lock_irqsave(&(smi_info->si_lock), flags); | 927 | spin_lock_irqsave(&(smi_info->si_lock), flags); |
865 | #ifdef DEBUG_TIMING | 928 | #ifdef DEBUG_TIMING |
866 | do_gettimeofday(&t); | 929 | do_gettimeofday(&t); |
@@ -916,15 +979,11 @@ static irqreturn_t si_irq_handler(int irq, void *data) | |||
916 | smi_info->interrupts++; | 979 | smi_info->interrupts++; |
917 | spin_unlock(&smi_info->count_lock); | 980 | spin_unlock(&smi_info->count_lock); |
918 | 981 | ||
919 | if (atomic_read(&smi_info->stop_operation)) | ||
920 | goto out; | ||
921 | |||
922 | #ifdef DEBUG_TIMING | 982 | #ifdef DEBUG_TIMING |
923 | do_gettimeofday(&t); | 983 | do_gettimeofday(&t); |
924 | printk("**Interrupt: %d.%9.9d\n", t.tv_sec, t.tv_usec); | 984 | printk("**Interrupt: %d.%9.9d\n", t.tv_sec, t.tv_usec); |
925 | #endif | 985 | #endif |
926 | smi_event_handler(smi_info, 0); | 986 | smi_event_handler(smi_info, 0); |
927 | out: | ||
928 | spin_unlock_irqrestore(&(smi_info->si_lock), flags); | 987 | spin_unlock_irqrestore(&(smi_info->si_lock), flags); |
929 | return IRQ_HANDLED; | 988 | return IRQ_HANDLED; |
930 | } | 989 | } |
@@ -1006,6 +1065,7 @@ static DEFINE_MUTEX(smi_infos_lock); | |||
1006 | static int smi_num; /* Used to sequence the SMIs */ | 1065 | static int smi_num; /* Used to sequence the SMIs */ |
1007 | 1066 | ||
1008 | #define DEFAULT_REGSPACING 1 | 1067 | #define DEFAULT_REGSPACING 1 |
1068 | #define DEFAULT_REGSIZE 1 | ||
1009 | 1069 | ||
1010 | static int si_trydefaults = 1; | 1070 | static int si_trydefaults = 1; |
1011 | static char *si_type[SI_MAX_PARMS]; | 1071 | static char *si_type[SI_MAX_PARMS]; |
@@ -1111,7 +1171,7 @@ static int std_irq_setup(struct smi_info *info) | |||
1111 | if (info->si_type == SI_BT) { | 1171 | if (info->si_type == SI_BT) { |
1112 | rv = request_irq(info->irq, | 1172 | rv = request_irq(info->irq, |
1113 | si_bt_irq_handler, | 1173 | si_bt_irq_handler, |
1114 | IRQF_DISABLED, | 1174 | IRQF_SHARED | IRQF_DISABLED, |
1115 | DEVICE_NAME, | 1175 | DEVICE_NAME, |
1116 | info); | 1176 | info); |
1117 | if (!rv) | 1177 | if (!rv) |
@@ -1121,7 +1181,7 @@ static int std_irq_setup(struct smi_info *info) | |||
1121 | } else | 1181 | } else |
1122 | rv = request_irq(info->irq, | 1182 | rv = request_irq(info->irq, |
1123 | si_irq_handler, | 1183 | si_irq_handler, |
1124 | IRQF_DISABLED, | 1184 | IRQF_SHARED | IRQF_DISABLED, |
1125 | DEVICE_NAME, | 1185 | DEVICE_NAME, |
1126 | info); | 1186 | info); |
1127 | if (rv) { | 1187 | if (rv) { |
@@ -1701,15 +1761,11 @@ static u32 ipmi_acpi_gpe(void *context) | |||
1701 | smi_info->interrupts++; | 1761 | smi_info->interrupts++; |
1702 | spin_unlock(&smi_info->count_lock); | 1762 | spin_unlock(&smi_info->count_lock); |
1703 | 1763 | ||
1704 | if (atomic_read(&smi_info->stop_operation)) | ||
1705 | goto out; | ||
1706 | |||
1707 | #ifdef DEBUG_TIMING | 1764 | #ifdef DEBUG_TIMING |
1708 | do_gettimeofday(&t); | 1765 | do_gettimeofday(&t); |
1709 | printk("**ACPI_GPE: %d.%9.9d\n", t.tv_sec, t.tv_usec); | 1766 | printk("**ACPI_GPE: %d.%9.9d\n", t.tv_sec, t.tv_usec); |
1710 | #endif | 1767 | #endif |
1711 | smi_event_handler(smi_info, 0); | 1768 | smi_event_handler(smi_info, 0); |
1712 | out: | ||
1713 | spin_unlock_irqrestore(&(smi_info->si_lock), flags); | 1769 | spin_unlock_irqrestore(&(smi_info->si_lock), flags); |
1714 | 1770 | ||
1715 | return ACPI_INTERRUPT_HANDLED; | 1771 | return ACPI_INTERRUPT_HANDLED; |
@@ -2133,12 +2189,15 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev, | |||
2133 | info->irq_setup = std_irq_setup; | 2189 | info->irq_setup = std_irq_setup; |
2134 | 2190 | ||
2135 | info->dev = &pdev->dev; | 2191 | info->dev = &pdev->dev; |
2192 | pci_set_drvdata(pdev, info); | ||
2136 | 2193 | ||
2137 | return try_smi_init(info); | 2194 | return try_smi_init(info); |
2138 | } | 2195 | } |
2139 | 2196 | ||
2140 | static void __devexit ipmi_pci_remove(struct pci_dev *pdev) | 2197 | static void __devexit ipmi_pci_remove(struct pci_dev *pdev) |
2141 | { | 2198 | { |
2199 | struct smi_info *info = pci_get_drvdata(pdev); | ||
2200 | cleanup_one_si(info); | ||
2142 | } | 2201 | } |
2143 | 2202 | ||
2144 | #ifdef CONFIG_PM | 2203 | #ifdef CONFIG_PM |
@@ -2172,6 +2231,99 @@ static struct pci_driver ipmi_pci_driver = { | |||
2172 | #endif /* CONFIG_PCI */ | 2231 | #endif /* CONFIG_PCI */ |
2173 | 2232 | ||
2174 | 2233 | ||
2234 | #ifdef CONFIG_PPC_OF | ||
2235 | static int __devinit ipmi_of_probe(struct of_device *dev, | ||
2236 | const struct of_device_id *match) | ||
2237 | { | ||
2238 | struct smi_info *info; | ||
2239 | struct resource resource; | ||
2240 | const int *regsize, *regspacing, *regshift; | ||
2241 | struct device_node *np = dev->node; | ||
2242 | int ret; | ||
2243 | int proplen; | ||
2244 | |||
2245 | dev_info(&dev->dev, PFX "probing via device tree\n"); | ||
2246 | |||
2247 | ret = of_address_to_resource(np, 0, &resource); | ||
2248 | if (ret) { | ||
2249 | dev_warn(&dev->dev, PFX "invalid address from OF\n"); | ||
2250 | return ret; | ||
2251 | } | ||
2252 | |||
2253 | regsize = get_property(np, "reg-size", &proplen); | ||
2254 | if (regsize && proplen != 4) { | ||
2255 | dev_warn(&dev->dev, PFX "invalid regsize from OF\n"); | ||
2256 | return -EINVAL; | ||
2257 | } | ||
2258 | |||
2259 | regspacing = get_property(np, "reg-spacing", &proplen); | ||
2260 | if (regspacing && proplen != 4) { | ||
2261 | dev_warn(&dev->dev, PFX "invalid regspacing from OF\n"); | ||
2262 | return -EINVAL; | ||
2263 | } | ||
2264 | |||
2265 | regshift = get_property(np, "reg-shift", &proplen); | ||
2266 | if (regshift && proplen != 4) { | ||
2267 | dev_warn(&dev->dev, PFX "invalid regshift from OF\n"); | ||
2268 | return -EINVAL; | ||
2269 | } | ||
2270 | |||
2271 | info = kzalloc(sizeof(*info), GFP_KERNEL); | ||
2272 | |||
2273 | if (!info) { | ||
2274 | dev_err(&dev->dev, | ||
2275 | PFX "could not allocate memory for OF probe\n"); | ||
2276 | return -ENOMEM; | ||
2277 | } | ||
2278 | |||
2279 | info->si_type = (enum si_type) match->data; | ||
2280 | info->addr_source = "device-tree"; | ||
2281 | info->io_setup = mem_setup; | ||
2282 | info->irq_setup = std_irq_setup; | ||
2283 | |||
2284 | info->io.addr_type = IPMI_MEM_ADDR_SPACE; | ||
2285 | info->io.addr_data = resource.start; | ||
2286 | |||
2287 | info->io.regsize = regsize ? *regsize : DEFAULT_REGSIZE; | ||
2288 | info->io.regspacing = regspacing ? *regspacing : DEFAULT_REGSPACING; | ||
2289 | info->io.regshift = regshift ? *regshift : 0; | ||
2290 | |||
2291 | info->irq = irq_of_parse_and_map(dev->node, 0); | ||
2292 | info->dev = &dev->dev; | ||
2293 | |||
2294 | dev_dbg(&dev->dev, "addr 0x%lx regsize %ld spacing %ld irq %x\n", | ||
2295 | info->io.addr_data, info->io.regsize, info->io.regspacing, | ||
2296 | info->irq); | ||
2297 | |||
2298 | dev->dev.driver_data = (void*) info; | ||
2299 | |||
2300 | return try_smi_init(info); | ||
2301 | } | ||
2302 | |||
2303 | static int __devexit ipmi_of_remove(struct of_device *dev) | ||
2304 | { | ||
2305 | cleanup_one_si(dev->dev.driver_data); | ||
2306 | return 0; | ||
2307 | } | ||
2308 | |||
2309 | static struct of_device_id ipmi_match[] = | ||
2310 | { | ||
2311 | { .type = "ipmi", .compatible = "ipmi-kcs", .data = (void *)(unsigned long) SI_KCS }, | ||
2312 | { .type = "ipmi", .compatible = "ipmi-smic", .data = (void *)(unsigned long) SI_SMIC }, | ||
2313 | { .type = "ipmi", .compatible = "ipmi-bt", .data = (void *)(unsigned long) SI_BT }, | ||
2314 | {}, | ||
2315 | }; | ||
2316 | |||
2317 | static struct of_platform_driver ipmi_of_platform_driver = | ||
2318 | { | ||
2319 | .name = "ipmi", | ||
2320 | .match_table = ipmi_match, | ||
2321 | .probe = ipmi_of_probe, | ||
2322 | .remove = __devexit_p(ipmi_of_remove), | ||
2323 | }; | ||
2324 | #endif /* CONFIG_PPC_OF */ | ||
2325 | |||
2326 | |||
2175 | static int try_get_dev_id(struct smi_info *smi_info) | 2327 | static int try_get_dev_id(struct smi_info *smi_info) |
2176 | { | 2328 | { |
2177 | unsigned char msg[2]; | 2329 | unsigned char msg[2]; |
@@ -2801,6 +2953,10 @@ static __devinit int init_ipmi_si(void) | |||
2801 | } | 2953 | } |
2802 | #endif | 2954 | #endif |
2803 | 2955 | ||
2956 | #ifdef CONFIG_PPC_OF | ||
2957 | of_register_platform_driver(&ipmi_of_platform_driver); | ||
2958 | #endif | ||
2959 | |||
2804 | if (si_trydefaults) { | 2960 | if (si_trydefaults) { |
2805 | mutex_lock(&smi_infos_lock); | 2961 | mutex_lock(&smi_infos_lock); |
2806 | if (list_empty(&smi_infos)) { | 2962 | if (list_empty(&smi_infos)) { |
@@ -2838,28 +2994,33 @@ static void cleanup_one_si(struct smi_info *to_clean) | |||
2838 | 2994 | ||
2839 | list_del(&to_clean->link); | 2995 | list_del(&to_clean->link); |
2840 | 2996 | ||
2841 | /* Tell the timer and interrupt handlers that we are shutting | 2997 | /* Tell the driver that we are shutting down. */ |
2842 | down. */ | ||
2843 | spin_lock_irqsave(&(to_clean->si_lock), flags); | ||
2844 | spin_lock(&(to_clean->msg_lock)); | ||
2845 | |||
2846 | atomic_inc(&to_clean->stop_operation); | 2998 | atomic_inc(&to_clean->stop_operation); |
2847 | 2999 | ||
2848 | if (to_clean->irq_cleanup) | 3000 | /* Make sure the timer and thread are stopped and will not run |
2849 | to_clean->irq_cleanup(to_clean); | 3001 | again. */ |
2850 | |||
2851 | spin_unlock(&(to_clean->msg_lock)); | ||
2852 | spin_unlock_irqrestore(&(to_clean->si_lock), flags); | ||
2853 | |||
2854 | /* Wait until we know that we are out of any interrupt | ||
2855 | handlers might have been running before we freed the | ||
2856 | interrupt. */ | ||
2857 | synchronize_sched(); | ||
2858 | |||
2859 | wait_for_timer_and_thread(to_clean); | 3002 | wait_for_timer_and_thread(to_clean); |
2860 | 3003 | ||
2861 | /* Interrupts and timeouts are stopped, now make sure the | 3004 | /* Timeouts are stopped, now make sure the interrupts are off |
2862 | interface is in a clean state. */ | 3005 | for the device. A little tricky with locks to make sure |
3006 | there are no races. */ | ||
3007 | spin_lock_irqsave(&to_clean->si_lock, flags); | ||
3008 | while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) { | ||
3009 | spin_unlock_irqrestore(&to_clean->si_lock, flags); | ||
3010 | poll(to_clean); | ||
3011 | schedule_timeout_uninterruptible(1); | ||
3012 | spin_lock_irqsave(&to_clean->si_lock, flags); | ||
3013 | } | ||
3014 | disable_si_irq(to_clean); | ||
3015 | spin_unlock_irqrestore(&to_clean->si_lock, flags); | ||
3016 | while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) { | ||
3017 | poll(to_clean); | ||
3018 | schedule_timeout_uninterruptible(1); | ||
3019 | } | ||
3020 | |||
3021 | /* Clean up interrupts and make sure that everything is done. */ | ||
3022 | if (to_clean->irq_cleanup) | ||
3023 | to_clean->irq_cleanup(to_clean); | ||
2863 | while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) { | 3024 | while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) { |
2864 | poll(to_clean); | 3025 | poll(to_clean); |
2865 | schedule_timeout_uninterruptible(1); | 3026 | schedule_timeout_uninterruptible(1); |
@@ -2898,6 +3059,10 @@ static __exit void cleanup_ipmi_si(void) | |||
2898 | pci_unregister_driver(&ipmi_pci_driver); | 3059 | pci_unregister_driver(&ipmi_pci_driver); |
2899 | #endif | 3060 | #endif |
2900 | 3061 | ||
3062 | #ifdef CONFIG_PPC_OF | ||
3063 | of_unregister_platform_driver(&ipmi_of_platform_driver); | ||
3064 | #endif | ||
3065 | |||
2901 | mutex_lock(&smi_infos_lock); | 3066 | mutex_lock(&smi_infos_lock); |
2902 | list_for_each_entry_safe(e, tmp_e, &smi_infos, link) | 3067 | list_for_each_entry_safe(e, tmp_e, &smi_infos, link) |
2903 | cleanup_one_si(e); | 3068 | cleanup_one_si(e); |
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 6b634e8d9519..147c12047cf3 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/miscdevice.h> | 39 | #include <linux/miscdevice.h> |
40 | #include <linux/init.h> | 40 | #include <linux/init.h> |
41 | #include <linux/completion.h> | 41 | #include <linux/completion.h> |
42 | #include <linux/kdebug.h> | ||
42 | #include <linux/rwsem.h> | 43 | #include <linux/rwsem.h> |
43 | #include <linux/errno.h> | 44 | #include <linux/errno.h> |
44 | #include <asm/uaccess.h> | 45 | #include <asm/uaccess.h> |
@@ -49,9 +50,18 @@ | |||
49 | #include <linux/poll.h> | 50 | #include <linux/poll.h> |
50 | #include <linux/string.h> | 51 | #include <linux/string.h> |
51 | #include <linux/ctype.h> | 52 | #include <linux/ctype.h> |
53 | #include <linux/delay.h> | ||
52 | #include <asm/atomic.h> | 54 | #include <asm/atomic.h> |
53 | #ifdef CONFIG_X86_LOCAL_APIC | 55 | |
54 | #include <asm/apic.h> | 56 | #ifdef CONFIG_X86 |
57 | /* This is ugly, but I've determined that x86 is the only architecture | ||
58 | that can reasonably support the IPMI NMI watchdog timeout at this | ||
59 | time. If another architecture adds this capability somehow, it | ||
60 | will have to be a somewhat different mechanism and I have no idea | ||
61 | how it will work. So in the unlikely event that another | ||
62 | architecture supports this, we can figure out a good generic | ||
63 | mechanism for it at that time. */ | ||
64 | #define HAVE_DIE_NMI_POST | ||
55 | #endif | 65 | #endif |
56 | 66 | ||
57 | #define PFX "IPMI Watchdog: " | 67 | #define PFX "IPMI Watchdog: " |
@@ -317,6 +327,11 @@ static unsigned char ipmi_version_minor; | |||
317 | /* If a pretimeout occurs, this is used to allow only one panic to happen. */ | 327 | /* If a pretimeout occurs, this is used to allow only one panic to happen. */ |
318 | static atomic_t preop_panic_excl = ATOMIC_INIT(-1); | 328 | static atomic_t preop_panic_excl = ATOMIC_INIT(-1); |
319 | 329 | ||
330 | #ifdef HAVE_DIE_NMI_POST | ||
331 | static int testing_nmi; | ||
332 | static int nmi_handler_registered; | ||
333 | #endif | ||
334 | |||
320 | static int ipmi_heartbeat(void); | 335 | static int ipmi_heartbeat(void); |
321 | static void panic_halt_ipmi_heartbeat(void); | 336 | static void panic_halt_ipmi_heartbeat(void); |
322 | 337 | ||
@@ -358,6 +373,10 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg, | |||
358 | int hbnow = 0; | 373 | int hbnow = 0; |
359 | 374 | ||
360 | 375 | ||
376 | /* These can be cleared as we are setting the timeout. */ | ||
377 | ipmi_start_timer_on_heartbeat = 0; | ||
378 | pretimeout_since_last_heartbeat = 0; | ||
379 | |||
361 | data[0] = 0; | 380 | data[0] = 0; |
362 | WDOG_SET_TIMER_USE(data[0], WDOG_TIMER_USE_SMS_OS); | 381 | WDOG_SET_TIMER_USE(data[0], WDOG_TIMER_USE_SMS_OS); |
363 | 382 | ||
@@ -432,13 +451,12 @@ static int ipmi_set_timeout(int do_heartbeat) | |||
432 | 451 | ||
433 | wait_for_completion(&set_timeout_wait); | 452 | wait_for_completion(&set_timeout_wait); |
434 | 453 | ||
454 | mutex_unlock(&set_timeout_lock); | ||
455 | |||
435 | if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB) | 456 | if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB) |
436 | || ((send_heartbeat_now) | 457 | || ((send_heartbeat_now) |
437 | && (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY))) | 458 | && (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY))) |
438 | { | ||
439 | rv = ipmi_heartbeat(); | 459 | rv = ipmi_heartbeat(); |
440 | } | ||
441 | mutex_unlock(&set_timeout_lock); | ||
442 | 460 | ||
443 | out: | 461 | out: |
444 | return rv; | 462 | return rv; |
@@ -518,12 +536,10 @@ static int ipmi_heartbeat(void) | |||
518 | int rv; | 536 | int rv; |
519 | struct ipmi_system_interface_addr addr; | 537 | struct ipmi_system_interface_addr addr; |
520 | 538 | ||
521 | if (ipmi_ignore_heartbeat) { | 539 | if (ipmi_ignore_heartbeat) |
522 | return 0; | 540 | return 0; |
523 | } | ||
524 | 541 | ||
525 | if (ipmi_start_timer_on_heartbeat) { | 542 | if (ipmi_start_timer_on_heartbeat) { |
526 | ipmi_start_timer_on_heartbeat = 0; | ||
527 | ipmi_watchdog_state = action_val; | 543 | ipmi_watchdog_state = action_val; |
528 | return ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB); | 544 | return ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB); |
529 | } else if (pretimeout_since_last_heartbeat) { | 545 | } else if (pretimeout_since_last_heartbeat) { |
@@ -531,7 +547,6 @@ static int ipmi_heartbeat(void) | |||
531 | We don't want to set the action, though, we want to | 547 | We don't want to set the action, though, we want to |
532 | leave that alone (thus it can't be combined with the | 548 | leave that alone (thus it can't be combined with the |
533 | above operation. */ | 549 | above operation. */ |
534 | pretimeout_since_last_heartbeat = 0; | ||
535 | return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); | 550 | return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); |
536 | } | 551 | } |
537 | 552 | ||
@@ -919,6 +934,45 @@ static void ipmi_register_watchdog(int ipmi_intf) | |||
919 | printk(KERN_CRIT PFX "Unable to register misc device\n"); | 934 | printk(KERN_CRIT PFX "Unable to register misc device\n"); |
920 | } | 935 | } |
921 | 936 | ||
937 | #ifdef HAVE_DIE_NMI_POST | ||
938 | if (nmi_handler_registered) { | ||
939 | int old_pretimeout = pretimeout; | ||
940 | int old_timeout = timeout; | ||
941 | int old_preop_val = preop_val; | ||
942 | |||
943 | /* Set the pretimeout to go off in a second and give | ||
944 | ourselves plenty of time to stop the timer. */ | ||
945 | ipmi_watchdog_state = WDOG_TIMEOUT_RESET; | ||
946 | preop_val = WDOG_PREOP_NONE; /* Make sure nothing happens */ | ||
947 | pretimeout = 99; | ||
948 | timeout = 100; | ||
949 | |||
950 | testing_nmi = 1; | ||
951 | |||
952 | rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB); | ||
953 | if (rv) { | ||
954 | printk(KERN_WARNING PFX "Error starting timer to" | ||
955 | " test NMI: 0x%x. The NMI pretimeout will" | ||
956 | " likely not work\n", rv); | ||
957 | rv = 0; | ||
958 | goto out_restore; | ||
959 | } | ||
960 | |||
961 | msleep(1500); | ||
962 | |||
963 | if (testing_nmi != 2) { | ||
964 | printk(KERN_WARNING PFX "IPMI NMI didn't seem to" | ||
965 | " occur. The NMI pretimeout will" | ||
966 | " likely not work\n"); | ||
967 | } | ||
968 | out_restore: | ||
969 | testing_nmi = 0; | ||
970 | preop_val = old_preop_val; | ||
971 | pretimeout = old_pretimeout; | ||
972 | timeout = old_timeout; | ||
973 | } | ||
974 | #endif | ||
975 | |||
922 | out: | 976 | out: |
923 | up_write(®ister_sem); | 977 | up_write(®ister_sem); |
924 | 978 | ||
@@ -928,6 +982,10 @@ static void ipmi_register_watchdog(int ipmi_intf) | |||
928 | ipmi_watchdog_state = action_val; | 982 | ipmi_watchdog_state = action_val; |
929 | ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB); | 983 | ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB); |
930 | printk(KERN_INFO PFX "Starting now!\n"); | 984 | printk(KERN_INFO PFX "Starting now!\n"); |
985 | } else { | ||
986 | /* Stop the timer now. */ | ||
987 | ipmi_watchdog_state = WDOG_TIMEOUT_NONE; | ||
988 | ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB); | ||
931 | } | 989 | } |
932 | } | 990 | } |
933 | 991 | ||
@@ -964,17 +1022,28 @@ static void ipmi_unregister_watchdog(int ipmi_intf) | |||
964 | up_write(®ister_sem); | 1022 | up_write(®ister_sem); |
965 | } | 1023 | } |
966 | 1024 | ||
967 | #ifdef HAVE_NMI_HANDLER | 1025 | #ifdef HAVE_DIE_NMI_POST |
968 | static int | 1026 | static int |
969 | ipmi_nmi(void *dev_id, int cpu, int handled) | 1027 | ipmi_nmi(struct notifier_block *self, unsigned long val, void *data) |
970 | { | 1028 | { |
1029 | if (val != DIE_NMI_POST) | ||
1030 | return NOTIFY_OK; | ||
1031 | |||
1032 | if (testing_nmi) { | ||
1033 | testing_nmi = 2; | ||
1034 | return NOTIFY_STOP; | ||
1035 | } | ||
1036 | |||
971 | /* If we are not expecting a timeout, ignore it. */ | 1037 | /* If we are not expecting a timeout, ignore it. */ |
972 | if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) | 1038 | if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) |
973 | return NOTIFY_DONE; | 1039 | return NOTIFY_OK; |
1040 | |||
1041 | if (preaction_val != WDOG_PRETIMEOUT_NMI) | ||
1042 | return NOTIFY_OK; | ||
974 | 1043 | ||
975 | /* If no one else handled the NMI, we assume it was the IPMI | 1044 | /* If no one else handled the NMI, we assume it was the IPMI |
976 | watchdog. */ | 1045 | watchdog. */ |
977 | if ((!handled) && (preop_val == WDOG_PREOP_PANIC)) { | 1046 | if (preop_val == WDOG_PREOP_PANIC) { |
978 | /* On some machines, the heartbeat will give | 1047 | /* On some machines, the heartbeat will give |
979 | an error and not work unless we re-enable | 1048 | an error and not work unless we re-enable |
980 | the timer. So do so. */ | 1049 | the timer. So do so. */ |
@@ -983,18 +1052,12 @@ ipmi_nmi(void *dev_id, int cpu, int handled) | |||
983 | panic(PFX "pre-timeout"); | 1052 | panic(PFX "pre-timeout"); |
984 | } | 1053 | } |
985 | 1054 | ||
986 | return NOTIFY_DONE; | 1055 | return NOTIFY_STOP; |
987 | } | 1056 | } |
988 | 1057 | ||
989 | static struct nmi_handler ipmi_nmi_handler = | 1058 | static struct notifier_block ipmi_nmi_handler = { |
990 | { | 1059 | .notifier_call = ipmi_nmi |
991 | .link = LIST_HEAD_INIT(ipmi_nmi_handler.link), | ||
992 | .dev_name = "ipmi_watchdog", | ||
993 | .dev_id = NULL, | ||
994 | .handler = ipmi_nmi, | ||
995 | .priority = 0, /* Call us last. */ | ||
996 | }; | 1060 | }; |
997 | int nmi_handler_registered; | ||
998 | #endif | 1061 | #endif |
999 | 1062 | ||
1000 | static int wdog_reboot_handler(struct notifier_block *this, | 1063 | static int wdog_reboot_handler(struct notifier_block *this, |
@@ -1111,7 +1174,7 @@ static int preaction_op(const char *inval, char *outval) | |||
1111 | preaction_val = WDOG_PRETIMEOUT_NONE; | 1174 | preaction_val = WDOG_PRETIMEOUT_NONE; |
1112 | else if (strcmp(inval, "pre_smi") == 0) | 1175 | else if (strcmp(inval, "pre_smi") == 0) |
1113 | preaction_val = WDOG_PRETIMEOUT_SMI; | 1176 | preaction_val = WDOG_PRETIMEOUT_SMI; |
1114 | #ifdef HAVE_NMI_HANDLER | 1177 | #ifdef HAVE_DIE_NMI_POST |
1115 | else if (strcmp(inval, "pre_nmi") == 0) | 1178 | else if (strcmp(inval, "pre_nmi") == 0) |
1116 | preaction_val = WDOG_PRETIMEOUT_NMI; | 1179 | preaction_val = WDOG_PRETIMEOUT_NMI; |
1117 | #endif | 1180 | #endif |
@@ -1145,7 +1208,7 @@ static int preop_op(const char *inval, char *outval) | |||
1145 | 1208 | ||
1146 | static void check_parms(void) | 1209 | static void check_parms(void) |
1147 | { | 1210 | { |
1148 | #ifdef HAVE_NMI_HANDLER | 1211 | #ifdef HAVE_DIE_NMI_POST |
1149 | int do_nmi = 0; | 1212 | int do_nmi = 0; |
1150 | int rv; | 1213 | int rv; |
1151 | 1214 | ||
@@ -1158,20 +1221,9 @@ static void check_parms(void) | |||
1158 | preop_op("preop_none", NULL); | 1221 | preop_op("preop_none", NULL); |
1159 | do_nmi = 0; | 1222 | do_nmi = 0; |
1160 | } | 1223 | } |
1161 | #ifdef CONFIG_X86_LOCAL_APIC | ||
1162 | if (nmi_watchdog == NMI_IO_APIC) { | ||
1163 | printk(KERN_WARNING PFX "nmi_watchdog is set to IO APIC" | ||
1164 | " mode (value is %d), that is incompatible" | ||
1165 | " with using NMI in the IPMI watchdog." | ||
1166 | " Disabling IPMI nmi pretimeout.\n", | ||
1167 | nmi_watchdog); | ||
1168 | preaction_val = WDOG_PRETIMEOUT_NONE; | ||
1169 | do_nmi = 0; | ||
1170 | } | ||
1171 | #endif | ||
1172 | } | 1224 | } |
1173 | if (do_nmi && !nmi_handler_registered) { | 1225 | if (do_nmi && !nmi_handler_registered) { |
1174 | rv = request_nmi(&ipmi_nmi_handler); | 1226 | rv = register_die_notifier(&ipmi_nmi_handler); |
1175 | if (rv) { | 1227 | if (rv) { |
1176 | printk(KERN_WARNING PFX | 1228 | printk(KERN_WARNING PFX |
1177 | "Can't register nmi handler\n"); | 1229 | "Can't register nmi handler\n"); |
@@ -1179,7 +1231,7 @@ static void check_parms(void) | |||
1179 | } else | 1231 | } else |
1180 | nmi_handler_registered = 1; | 1232 | nmi_handler_registered = 1; |
1181 | } else if (!do_nmi && nmi_handler_registered) { | 1233 | } else if (!do_nmi && nmi_handler_registered) { |
1182 | release_nmi(&ipmi_nmi_handler); | 1234 | unregister_die_notifier(&ipmi_nmi_handler); |
1183 | nmi_handler_registered = 0; | 1235 | nmi_handler_registered = 0; |
1184 | } | 1236 | } |
1185 | #endif | 1237 | #endif |
@@ -1215,9 +1267,9 @@ static int __init ipmi_wdog_init(void) | |||
1215 | 1267 | ||
1216 | rv = ipmi_smi_watcher_register(&smi_watcher); | 1268 | rv = ipmi_smi_watcher_register(&smi_watcher); |
1217 | if (rv) { | 1269 | if (rv) { |
1218 | #ifdef HAVE_NMI_HANDLER | 1270 | #ifdef HAVE_DIE_NMI_POST |
1219 | if (preaction_val == WDOG_PRETIMEOUT_NMI) | 1271 | if (nmi_handler_registered) |
1220 | release_nmi(&ipmi_nmi_handler); | 1272 | unregister_die_notifier(&ipmi_nmi_handler); |
1221 | #endif | 1273 | #endif |
1222 | atomic_notifier_chain_unregister(&panic_notifier_list, | 1274 | atomic_notifier_chain_unregister(&panic_notifier_list, |
1223 | &wdog_panic_notifier); | 1275 | &wdog_panic_notifier); |
@@ -1236,9 +1288,9 @@ static void __exit ipmi_wdog_exit(void) | |||
1236 | ipmi_smi_watcher_unregister(&smi_watcher); | 1288 | ipmi_smi_watcher_unregister(&smi_watcher); |
1237 | ipmi_unregister_watchdog(watchdog_ifnum); | 1289 | ipmi_unregister_watchdog(watchdog_ifnum); |
1238 | 1290 | ||
1239 | #ifdef HAVE_NMI_HANDLER | 1291 | #ifdef HAVE_DIE_NMI_POST |
1240 | if (nmi_handler_registered) | 1292 | if (nmi_handler_registered) |
1241 | release_nmi(&ipmi_nmi_handler); | 1293 | unregister_die_notifier(&ipmi_nmi_handler); |
1242 | #endif | 1294 | #endif |
1243 | 1295 | ||
1244 | atomic_notifier_chain_unregister(&panic_notifier_list, | 1296 | atomic_notifier_chain_unregister(&panic_notifier_list, |
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 43ab9edc76f5..761f77740d67 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c | |||
@@ -137,11 +137,10 @@ | |||
137 | #define InterruptTheCard(base) outw(0, (base) + 0xc) | 137 | #define InterruptTheCard(base) outw(0, (base) + 0xc) |
138 | #define ClearInterrupt(base) inw((base) + 0x0a) | 138 | #define ClearInterrupt(base) inw((base) + 0x0a) |
139 | 139 | ||
140 | #define pr_dbg(str...) pr_debug("ISICOM: " str) | ||
140 | #ifdef DEBUG | 141 | #ifdef DEBUG |
141 | #define pr_dbg(str...) printk(KERN_DEBUG "ISICOM: " str) | ||
142 | #define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c)) | 142 | #define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c)) |
143 | #else | 143 | #else |
144 | #define pr_dbg(str...) do { } while (0) | ||
145 | #define isicom_paranoia_check(a, b, c) 0 | 144 | #define isicom_paranoia_check(a, b, c) 0 |
146 | #endif | 145 | #endif |
147 | 146 | ||
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index cb8d691576da..1b094509b1d2 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c | |||
@@ -41,7 +41,6 @@ | |||
41 | #include <linux/input.h> | 41 | #include <linux/input.h> |
42 | #include <linux/reboot.h> | 42 | #include <linux/reboot.h> |
43 | 43 | ||
44 | static void kbd_disconnect(struct input_handle *handle); | ||
45 | extern void ctrl_alt_del(void); | 44 | extern void ctrl_alt_del(void); |
46 | 45 | ||
47 | /* | 46 | /* |
@@ -110,7 +109,7 @@ struct kbd_struct kbd_table[MAX_NR_CONSOLES]; | |||
110 | static struct kbd_struct *kbd = kbd_table; | 109 | static struct kbd_struct *kbd = kbd_table; |
111 | 110 | ||
112 | struct vt_spawn_console vt_spawn_con = { | 111 | struct vt_spawn_console vt_spawn_con = { |
113 | .lock = SPIN_LOCK_UNLOCKED, | 112 | .lock = __SPIN_LOCK_UNLOCKED(vt_spawn_con.lock), |
114 | .pid = NULL, | 113 | .pid = NULL, |
115 | .sig = 0, | 114 | .sig = 0, |
116 | }; | 115 | }; |
@@ -159,65 +158,41 @@ static int sysrq_alt_use; | |||
159 | static int sysrq_alt; | 158 | static int sysrq_alt; |
160 | 159 | ||
161 | /* | 160 | /* |
162 | * Translation of scancodes to keycodes. We set them on only the first attached | 161 | * Translation of scancodes to keycodes. We set them on only the first |
163 | * keyboard - for per-keyboard setting, /dev/input/event is more useful. | 162 | * keyboard in the list that accepts the scancode and keycode. |
163 | * Explanation for not choosing the first attached keyboard anymore: | ||
164 | * USB keyboards for example have two event devices: one for all "normal" | ||
165 | * keys and one for extra function keys (like "volume up", "make coffee", | ||
166 | * etc.). So this means that scancodes for the extra function keys won't | ||
167 | * be valid for the first event device, but will be for the second. | ||
164 | */ | 168 | */ |
165 | int getkeycode(unsigned int scancode) | 169 | int getkeycode(unsigned int scancode) |
166 | { | 170 | { |
167 | struct list_head *node; | 171 | struct input_handle *handle; |
168 | struct input_dev *dev = NULL; | 172 | int keycode; |
173 | int error = -ENODEV; | ||
169 | 174 | ||
170 | list_for_each(node, &kbd_handler.h_list) { | 175 | list_for_each_entry(handle, &kbd_handler.h_list, h_node) { |
171 | struct input_handle *handle = to_handle_h(node); | 176 | error = handle->dev->getkeycode(handle->dev, scancode, &keycode); |
172 | if (handle->dev->keycodesize) { | 177 | if (!error) |
173 | dev = handle->dev; | 178 | return keycode; |
174 | break; | ||
175 | } | ||
176 | } | 179 | } |
177 | 180 | ||
178 | if (!dev) | 181 | return error; |
179 | return -ENODEV; | ||
180 | |||
181 | if (scancode >= dev->keycodemax) | ||
182 | return -EINVAL; | ||
183 | |||
184 | return INPUT_KEYCODE(dev, scancode); | ||
185 | } | 182 | } |
186 | 183 | ||
187 | int setkeycode(unsigned int scancode, unsigned int keycode) | 184 | int setkeycode(unsigned int scancode, unsigned int keycode) |
188 | { | 185 | { |
189 | struct list_head *node; | 186 | struct input_handle *handle; |
190 | struct input_dev *dev = NULL; | 187 | int error = -ENODEV; |
191 | unsigned int i, oldkey; | ||
192 | 188 | ||
193 | list_for_each(node, &kbd_handler.h_list) { | 189 | list_for_each_entry(handle, &kbd_handler.h_list, h_node) { |
194 | struct input_handle *handle = to_handle_h(node); | 190 | error = handle->dev->setkeycode(handle->dev, scancode, keycode); |
195 | if (handle->dev->keycodesize) { | 191 | if (!error) |
196 | dev = handle->dev; | ||
197 | break; | 192 | break; |
198 | } | ||
199 | } | 193 | } |
200 | 194 | ||
201 | if (!dev) | 195 | return error; |
202 | return -ENODEV; | ||
203 | |||
204 | if (scancode >= dev->keycodemax) | ||
205 | return -EINVAL; | ||
206 | if (keycode < 0 || keycode > KEY_MAX) | ||
207 | return -EINVAL; | ||
208 | if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8))) | ||
209 | return -EINVAL; | ||
210 | |||
211 | oldkey = SET_INPUT_KEYCODE(dev, scancode, keycode); | ||
212 | |||
213 | clear_bit(oldkey, dev->keybit); | ||
214 | set_bit(keycode, dev->keybit); | ||
215 | |||
216 | for (i = 0; i < dev->keycodemax; i++) | ||
217 | if (INPUT_KEYCODE(dev,i) == oldkey) | ||
218 | set_bit(oldkey, dev->keybit); | ||
219 | |||
220 | return 0; | ||
221 | } | 196 | } |
222 | 197 | ||
223 | /* | 198 | /* |
@@ -225,10 +200,9 @@ int setkeycode(unsigned int scancode, unsigned int keycode) | |||
225 | */ | 200 | */ |
226 | static void kd_nosound(unsigned long ignored) | 201 | static void kd_nosound(unsigned long ignored) |
227 | { | 202 | { |
228 | struct list_head *node; | 203 | struct input_handle *handle; |
229 | 204 | ||
230 | list_for_each(node, &kbd_handler.h_list) { | 205 | list_for_each_entry(handle, &kbd_handler.h_list, h_node) { |
231 | struct input_handle *handle = to_handle_h(node); | ||
232 | if (test_bit(EV_SND, handle->dev->evbit)) { | 206 | if (test_bit(EV_SND, handle->dev->evbit)) { |
233 | if (test_bit(SND_TONE, handle->dev->sndbit)) | 207 | if (test_bit(SND_TONE, handle->dev->sndbit)) |
234 | input_inject_event(handle, EV_SND, SND_TONE, 0); | 208 | input_inject_event(handle, EV_SND, SND_TONE, 0); |
@@ -1161,7 +1135,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) | |||
1161 | 1135 | ||
1162 | if ((raw_mode = (kbd->kbdmode == VC_RAW)) && !hw_raw) | 1136 | if ((raw_mode = (kbd->kbdmode == VC_RAW)) && !hw_raw) |
1163 | if (emulate_raw(vc, keycode, !down << 7)) | 1137 | if (emulate_raw(vc, keycode, !down << 7)) |
1164 | if (keycode < BTN_MISC) | 1138 | if (keycode < BTN_MISC && printk_ratelimit()) |
1165 | printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode); | 1139 | printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode); |
1166 | 1140 | ||
1167 | #ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */ | 1141 | #ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */ |
@@ -1285,11 +1259,11 @@ static void kbd_event(struct input_handle *handle, unsigned int event_type, | |||
1285 | * likes it, it can open it and get events from it. In this (kbd_connect) | 1259 | * likes it, it can open it and get events from it. In this (kbd_connect) |
1286 | * function, we should decide which VT to bind that keyboard to initially. | 1260 | * function, we should decide which VT to bind that keyboard to initially. |
1287 | */ | 1261 | */ |
1288 | static struct input_handle *kbd_connect(struct input_handler *handler, | 1262 | static int kbd_connect(struct input_handler *handler, struct input_dev *dev, |
1289 | struct input_dev *dev, | 1263 | const struct input_device_id *id) |
1290 | const struct input_device_id *id) | ||
1291 | { | 1264 | { |
1292 | struct input_handle *handle; | 1265 | struct input_handle *handle; |
1266 | int error; | ||
1293 | int i; | 1267 | int i; |
1294 | 1268 | ||
1295 | for (i = KEY_RESERVED; i < BTN_MISC; i++) | 1269 | for (i = KEY_RESERVED; i < BTN_MISC; i++) |
@@ -1297,24 +1271,37 @@ static struct input_handle *kbd_connect(struct input_handler *handler, | |||
1297 | break; | 1271 | break; |
1298 | 1272 | ||
1299 | if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit)) | 1273 | if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit)) |
1300 | return NULL; | 1274 | return -ENODEV; |
1301 | 1275 | ||
1302 | handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); | 1276 | handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); |
1303 | if (!handle) | 1277 | if (!handle) |
1304 | return NULL; | 1278 | return -ENOMEM; |
1305 | 1279 | ||
1306 | handle->dev = dev; | 1280 | handle->dev = dev; |
1307 | handle->handler = handler; | 1281 | handle->handler = handler; |
1308 | handle->name = "kbd"; | 1282 | handle->name = "kbd"; |
1309 | 1283 | ||
1310 | input_open_device(handle); | 1284 | error = input_register_handle(handle); |
1285 | if (error) | ||
1286 | goto err_free_handle; | ||
1287 | |||
1288 | error = input_open_device(handle); | ||
1289 | if (error) | ||
1290 | goto err_unregister_handle; | ||
1291 | |||
1292 | return 0; | ||
1311 | 1293 | ||
1312 | return handle; | 1294 | err_unregister_handle: |
1295 | input_unregister_handle(handle); | ||
1296 | err_free_handle: | ||
1297 | kfree(handle); | ||
1298 | return error; | ||
1313 | } | 1299 | } |
1314 | 1300 | ||
1315 | static void kbd_disconnect(struct input_handle *handle) | 1301 | static void kbd_disconnect(struct input_handle *handle) |
1316 | { | 1302 | { |
1317 | input_close_device(handle); | 1303 | input_close_device(handle); |
1304 | input_unregister_handle(handle); | ||
1318 | kfree(handle); | 1305 | kfree(handle); |
1319 | } | 1306 | } |
1320 | 1307 | ||
diff --git a/drivers/char/lp.c b/drivers/char/lp.c index b51d08be0bcf..62051f8b0910 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c | |||
@@ -118,7 +118,6 @@ | |||
118 | #include <linux/kernel.h> | 118 | #include <linux/kernel.h> |
119 | #include <linux/major.h> | 119 | #include <linux/major.h> |
120 | #include <linux/sched.h> | 120 | #include <linux/sched.h> |
121 | #include <linux/smp_lock.h> | ||
122 | #include <linux/slab.h> | 121 | #include <linux/slab.h> |
123 | #include <linux/fcntl.h> | 122 | #include <linux/fcntl.h> |
124 | #include <linux/delay.h> | 123 | #include <linux/delay.h> |
@@ -139,9 +138,6 @@ | |||
139 | /* if you have more than 8 printers, remember to increase LP_NO */ | 138 | /* if you have more than 8 printers, remember to increase LP_NO */ |
140 | #define LP_NO 8 | 139 | #define LP_NO 8 |
141 | 140 | ||
142 | /* ROUND_UP macro from fs/select.c */ | ||
143 | #define ROUND_UP(x,y) (((x)+(y)-1)/(y)) | ||
144 | |||
145 | static struct lp_struct lp_table[LP_NO]; | 141 | static struct lp_struct lp_table[LP_NO]; |
146 | 142 | ||
147 | static unsigned int lp_count = 0; | 143 | static unsigned int lp_count = 0; |
@@ -652,7 +648,7 @@ static int lp_ioctl(struct inode *inode, struct file *file, | |||
652 | (par_timeout.tv_usec < 0)) { | 648 | (par_timeout.tv_usec < 0)) { |
653 | return -EINVAL; | 649 | return -EINVAL; |
654 | } | 650 | } |
655 | to_jiffies = ROUND_UP(par_timeout.tv_usec, 1000000/HZ); | 651 | to_jiffies = DIV_ROUND_UP(par_timeout.tv_usec, 1000000/HZ); |
656 | to_jiffies += par_timeout.tv_sec * (long) HZ; | 652 | to_jiffies += par_timeout.tv_sec * (long) HZ; |
657 | if (to_jiffies <= 0) { | 653 | if (to_jiffies <= 0) { |
658 | return -EINVAL; | 654 | return -EINVAL; |
@@ -803,7 +799,7 @@ static int lp_register(int nr, struct parport *port) | |||
803 | if (reset) | 799 | if (reset) |
804 | lp_reset(nr); | 800 | lp_reset(nr); |
805 | 801 | ||
806 | class_device_create(lp_class, NULL, MKDEV(LP_MAJOR, nr), NULL, | 802 | class_device_create(lp_class, NULL, MKDEV(LP_MAJOR, nr), port->dev, |
807 | "lp%d", nr); | 803 | "lp%d", nr); |
808 | 804 | ||
809 | printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name, | 805 | printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name, |
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 5f066963f171..cc9a9d0df979 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <linux/raw.h> | 18 | #include <linux/raw.h> |
19 | #include <linux/tty.h> | 19 | #include <linux/tty.h> |
20 | #include <linux/capability.h> | 20 | #include <linux/capability.h> |
21 | #include <linux/smp_lock.h> | ||
22 | #include <linux/ptrace.h> | 21 | #include <linux/ptrace.h> |
23 | #include <linux/device.h> | 22 | #include <linux/device.h> |
24 | #include <linux/highmem.h> | 23 | #include <linux/highmem.h> |
@@ -552,7 +551,7 @@ static ssize_t write_kmem(struct file * file, const char __user * buf, | |||
552 | return virtr + wrote; | 551 | return virtr + wrote; |
553 | } | 552 | } |
554 | 553 | ||
555 | #if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__) | 554 | #ifdef CONFIG_DEVPORT |
556 | static ssize_t read_port(struct file * file, char __user * buf, | 555 | static ssize_t read_port(struct file * file, char __user * buf, |
557 | size_t count, loff_t *ppos) | 556 | size_t count, loff_t *ppos) |
558 | { | 557 | { |
@@ -835,7 +834,7 @@ static const struct file_operations null_fops = { | |||
835 | .splice_write = splice_write_null, | 834 | .splice_write = splice_write_null, |
836 | }; | 835 | }; |
837 | 836 | ||
838 | #if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__) | 837 | #ifdef CONFIG_DEVPORT |
839 | static const struct file_operations port_fops = { | 838 | static const struct file_operations port_fops = { |
840 | .llseek = memory_lseek, | 839 | .llseek = memory_lseek, |
841 | .read = read_port, | 840 | .read = read_port, |
@@ -913,7 +912,7 @@ static int memory_open(struct inode * inode, struct file * filp) | |||
913 | case 3: | 912 | case 3: |
914 | filp->f_op = &null_fops; | 913 | filp->f_op = &null_fops; |
915 | break; | 914 | break; |
916 | #if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__) | 915 | #ifdef CONFIG_DEVPORT |
917 | case 4: | 916 | case 4: |
918 | filp->f_op = &port_fops; | 917 | filp->f_op = &port_fops; |
919 | break; | 918 | break; |
@@ -960,7 +959,7 @@ static const struct { | |||
960 | {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops}, | 959 | {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops}, |
961 | {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops}, | 960 | {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops}, |
962 | {3, "null", S_IRUGO | S_IWUGO, &null_fops}, | 961 | {3, "null", S_IRUGO | S_IWUGO, &null_fops}, |
963 | #if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__) | 962 | #ifdef CONFIG_DEVPORT |
964 | {4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops}, | 963 | {4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops}, |
965 | #endif | 964 | #endif |
966 | {5, "zero", S_IRUGO | S_IWUGO, &zero_fops}, | 965 | {5, "zero", S_IRUGO | S_IWUGO, &zero_fops}, |
diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 7e975f606924..4e6fb9651a16 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/kernel.h> | 41 | #include <linux/kernel.h> |
42 | #include <linux/major.h> | 42 | #include <linux/major.h> |
43 | #include <linux/slab.h> | 43 | #include <linux/slab.h> |
44 | #include <linux/mutex.h> | ||
44 | #include <linux/proc_fs.h> | 45 | #include <linux/proc_fs.h> |
45 | #include <linux/seq_file.h> | 46 | #include <linux/seq_file.h> |
46 | #include <linux/stat.h> | 47 | #include <linux/stat.h> |
@@ -53,7 +54,7 @@ | |||
53 | * Head entry for the doubly linked miscdevice list | 54 | * Head entry for the doubly linked miscdevice list |
54 | */ | 55 | */ |
55 | static LIST_HEAD(misc_list); | 56 | static LIST_HEAD(misc_list); |
56 | static DECLARE_MUTEX(misc_sem); | 57 | static DEFINE_MUTEX(misc_mtx); |
57 | 58 | ||
58 | /* | 59 | /* |
59 | * Assigned numbers, used for dynamic minors | 60 | * Assigned numbers, used for dynamic minors |
@@ -69,7 +70,7 @@ static void *misc_seq_start(struct seq_file *seq, loff_t *pos) | |||
69 | struct miscdevice *p; | 70 | struct miscdevice *p; |
70 | loff_t off = 0; | 71 | loff_t off = 0; |
71 | 72 | ||
72 | down(&misc_sem); | 73 | mutex_lock(&misc_mtx); |
73 | list_for_each_entry(p, &misc_list, list) { | 74 | list_for_each_entry(p, &misc_list, list) { |
74 | if (*pos == off++) | 75 | if (*pos == off++) |
75 | return p; | 76 | return p; |
@@ -89,7 +90,7 @@ static void *misc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
89 | 90 | ||
90 | static void misc_seq_stop(struct seq_file *seq, void *v) | 91 | static void misc_seq_stop(struct seq_file *seq, void *v) |
91 | { | 92 | { |
92 | up(&misc_sem); | 93 | mutex_unlock(&misc_mtx); |
93 | } | 94 | } |
94 | 95 | ||
95 | static int misc_seq_show(struct seq_file *seq, void *v) | 96 | static int misc_seq_show(struct seq_file *seq, void *v) |
@@ -129,7 +130,7 @@ static int misc_open(struct inode * inode, struct file * file) | |||
129 | int err = -ENODEV; | 130 | int err = -ENODEV; |
130 | const struct file_operations *old_fops, *new_fops = NULL; | 131 | const struct file_operations *old_fops, *new_fops = NULL; |
131 | 132 | ||
132 | down(&misc_sem); | 133 | mutex_lock(&misc_mtx); |
133 | 134 | ||
134 | list_for_each_entry(c, &misc_list, list) { | 135 | list_for_each_entry(c, &misc_list, list) { |
135 | if (c->minor == minor) { | 136 | if (c->minor == minor) { |
@@ -139,9 +140,9 @@ static int misc_open(struct inode * inode, struct file * file) | |||
139 | } | 140 | } |
140 | 141 | ||
141 | if (!new_fops) { | 142 | if (!new_fops) { |
142 | up(&misc_sem); | 143 | mutex_unlock(&misc_mtx); |
143 | request_module("char-major-%d-%d", MISC_MAJOR, minor); | 144 | request_module("char-major-%d-%d", MISC_MAJOR, minor); |
144 | down(&misc_sem); | 145 | mutex_lock(&misc_mtx); |
145 | 146 | ||
146 | list_for_each_entry(c, &misc_list, list) { | 147 | list_for_each_entry(c, &misc_list, list) { |
147 | if (c->minor == minor) { | 148 | if (c->minor == minor) { |
@@ -165,7 +166,7 @@ static int misc_open(struct inode * inode, struct file * file) | |||
165 | } | 166 | } |
166 | fops_put(old_fops); | 167 | fops_put(old_fops); |
167 | fail: | 168 | fail: |
168 | up(&misc_sem); | 169 | mutex_unlock(&misc_mtx); |
169 | return err; | 170 | return err; |
170 | } | 171 | } |
171 | 172 | ||
@@ -201,10 +202,10 @@ int misc_register(struct miscdevice * misc) | |||
201 | 202 | ||
202 | INIT_LIST_HEAD(&misc->list); | 203 | INIT_LIST_HEAD(&misc->list); |
203 | 204 | ||
204 | down(&misc_sem); | 205 | mutex_lock(&misc_mtx); |
205 | list_for_each_entry(c, &misc_list, list) { | 206 | list_for_each_entry(c, &misc_list, list) { |
206 | if (c->minor == misc->minor) { | 207 | if (c->minor == misc->minor) { |
207 | up(&misc_sem); | 208 | mutex_unlock(&misc_mtx); |
208 | return -EBUSY; | 209 | return -EBUSY; |
209 | } | 210 | } |
210 | } | 211 | } |
@@ -215,7 +216,7 @@ int misc_register(struct miscdevice * misc) | |||
215 | if ( (misc_minors[i>>3] & (1 << (i&7))) == 0) | 216 | if ( (misc_minors[i>>3] & (1 << (i&7))) == 0) |
216 | break; | 217 | break; |
217 | if (i<0) { | 218 | if (i<0) { |
218 | up(&misc_sem); | 219 | mutex_unlock(&misc_mtx); |
219 | return -EBUSY; | 220 | return -EBUSY; |
220 | } | 221 | } |
221 | misc->minor = i; | 222 | misc->minor = i; |
@@ -238,7 +239,7 @@ int misc_register(struct miscdevice * misc) | |||
238 | */ | 239 | */ |
239 | list_add(&misc->list, &misc_list); | 240 | list_add(&misc->list, &misc_list); |
240 | out: | 241 | out: |
241 | up(&misc_sem); | 242 | mutex_unlock(&misc_mtx); |
242 | return err; | 243 | return err; |
243 | } | 244 | } |
244 | 245 | ||
@@ -259,13 +260,13 @@ int misc_deregister(struct miscdevice * misc) | |||
259 | if (list_empty(&misc->list)) | 260 | if (list_empty(&misc->list)) |
260 | return -EINVAL; | 261 | return -EINVAL; |
261 | 262 | ||
262 | down(&misc_sem); | 263 | mutex_lock(&misc_mtx); |
263 | list_del(&misc->list); | 264 | list_del(&misc->list); |
264 | device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor)); | 265 | device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor)); |
265 | if (i < DYNAMIC_MINORS && i>0) { | 266 | if (i < DYNAMIC_MINORS && i>0) { |
266 | misc_minors[i>>3] &= ~(1 << (misc->minor & 7)); | 267 | misc_minors[i>>3] &= ~(1 << (misc->minor & 7)); |
267 | } | 268 | } |
268 | up(&misc_sem); | 269 | mutex_unlock(&misc_mtx); |
269 | return 0; | 270 | return 0; |
270 | } | 271 | } |
271 | 272 | ||
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c index c09160383a53..6e55cfb9c65a 100644 --- a/drivers/char/mmtimer.c +++ b/drivers/char/mmtimer.c | |||
@@ -705,15 +705,13 @@ static int __init mmtimer_init(void) | |||
705 | maxn++; | 705 | maxn++; |
706 | 706 | ||
707 | /* Allocate list of node ptrs to mmtimer_t's */ | 707 | /* Allocate list of node ptrs to mmtimer_t's */ |
708 | timers = kmalloc(sizeof(mmtimer_t *)*maxn, GFP_KERNEL); | 708 | timers = kzalloc(sizeof(mmtimer_t *)*maxn, GFP_KERNEL); |
709 | if (timers == NULL) { | 709 | if (timers == NULL) { |
710 | printk(KERN_ERR "%s: failed to allocate memory for device\n", | 710 | printk(KERN_ERR "%s: failed to allocate memory for device\n", |
711 | MMTIMER_NAME); | 711 | MMTIMER_NAME); |
712 | goto out3; | 712 | goto out3; |
713 | } | 713 | } |
714 | 714 | ||
715 | memset(timers,0,(sizeof(mmtimer_t *)*maxn)); | ||
716 | |||
717 | /* Allocate mmtimer_t's for each online node */ | 715 | /* Allocate mmtimer_t's for each online node */ |
718 | for_each_online_node(node) { | 716 | for_each_online_node(node) { |
719 | timers[node] = kmalloc_node(sizeof(mmtimer_t)*NUM_COMPARATORS, GFP_KERNEL, node); | 717 | timers[node] = kmalloc_node(sizeof(mmtimer_t)*NUM_COMPARATORS, GFP_KERNEL, node); |
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index 7dbaee8d9402..e0d35c20c04f 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c | |||
@@ -1582,7 +1582,7 @@ copy: | |||
1582 | 1582 | ||
1583 | if(copy_from_user(&dltmp, argp, sizeof(struct dl_str))) | 1583 | if(copy_from_user(&dltmp, argp, sizeof(struct dl_str))) |
1584 | return -EFAULT; | 1584 | return -EFAULT; |
1585 | if(dltmp.cardno < 0 || dltmp.cardno >= MAX_BOARDS) | 1585 | if(dltmp.cardno < 0 || dltmp.cardno >= MAX_BOARDS || dltmp.len < 0) |
1586 | return -EINVAL; | 1586 | return -EINVAL; |
1587 | 1587 | ||
1588 | switch(cmd) | 1588 | switch(cmd) |
@@ -2529,6 +2529,8 @@ static int moxaloadbios(int cardno, unsigned char __user *tmp, int len) | |||
2529 | void __iomem *baseAddr; | 2529 | void __iomem *baseAddr; |
2530 | int i; | 2530 | int i; |
2531 | 2531 | ||
2532 | if(len < 0 || len > sizeof(moxaBuff)) | ||
2533 | return -EINVAL; | ||
2532 | if(copy_from_user(moxaBuff, tmp, len)) | 2534 | if(copy_from_user(moxaBuff, tmp, len)) |
2533 | return -EFAULT; | 2535 | return -EFAULT; |
2534 | baseAddr = moxa_boards[cardno].basemem; | 2536 | baseAddr = moxa_boards[cardno].basemem; |
@@ -2576,7 +2578,7 @@ static int moxaload320b(int cardno, unsigned char __user *tmp, int len) | |||
2576 | void __iomem *baseAddr; | 2578 | void __iomem *baseAddr; |
2577 | int i; | 2579 | int i; |
2578 | 2580 | ||
2579 | if(len > sizeof(moxaBuff)) | 2581 | if(len < 0 || len > sizeof(moxaBuff)) |
2580 | return -EINVAL; | 2582 | return -EINVAL; |
2581 | if(copy_from_user(moxaBuff, tmp, len)) | 2583 | if(copy_from_user(moxaBuff, tmp, len)) |
2582 | return -EFAULT; | 2584 | return -EFAULT; |
@@ -2596,6 +2598,8 @@ static int moxaloadcode(int cardno, unsigned char __user *tmp, int len) | |||
2596 | void __iomem *baseAddr, *ofsAddr; | 2598 | void __iomem *baseAddr, *ofsAddr; |
2597 | int retval, port, i; | 2599 | int retval, port, i; |
2598 | 2600 | ||
2601 | if(len < 0 || len > sizeof(moxaBuff)) | ||
2602 | return -EINVAL; | ||
2599 | if(copy_from_user(moxaBuff, tmp, len)) | 2603 | if(copy_from_user(moxaBuff, tmp, len)) |
2600 | return -EFAULT; | 2604 | return -EFAULT; |
2601 | baseAddr = moxa_boards[cardno].basemem; | 2605 | baseAddr = moxa_boards[cardno].basemem; |
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 80a01150b86c..5953a45d7e96 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
@@ -54,7 +54,6 @@ | |||
54 | #include <linux/gfp.h> | 54 | #include <linux/gfp.h> |
55 | #include <linux/ioport.h> | 55 | #include <linux/ioport.h> |
56 | #include <linux/mm.h> | 56 | #include <linux/mm.h> |
57 | #include <linux/smp_lock.h> | ||
58 | #include <linux/delay.h> | 57 | #include <linux/delay.h> |
59 | #include <linux/pci.h> | 58 | #include <linux/pci.h> |
60 | 59 | ||
diff --git a/drivers/char/mxser_new.c b/drivers/char/mxser_new.c index f7603b6aeb87..6cde448cd5b2 100644 --- a/drivers/char/mxser_new.c +++ b/drivers/char/mxser_new.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include <linux/gfp.h> | 37 | #include <linux/gfp.h> |
38 | #include <linux/ioport.h> | 38 | #include <linux/ioport.h> |
39 | #include <linux/mm.h> | 39 | #include <linux/mm.h> |
40 | #include <linux/smp_lock.h> | ||
41 | #include <linux/delay.h> | 40 | #include <linux/delay.h> |
42 | #include <linux/pci.h> | 41 | #include <linux/pci.h> |
43 | 42 | ||
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index 65f2d3a96b85..14557a4822c0 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c | |||
@@ -1088,13 +1088,13 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | |||
1088 | /* block until there is a message: */ | 1088 | /* block until there is a message: */ |
1089 | add_wait_queue(&pInfo->read_wait, &wait); | 1089 | add_wait_queue(&pInfo->read_wait, &wait); |
1090 | repeat: | 1090 | repeat: |
1091 | current->state = TASK_INTERRUPTIBLE; | 1091 | __set_current_state(TASK_INTERRUPTIBLE); |
1092 | pMsg = remove_msg(pInfo, pClient); | 1092 | pMsg = remove_msg(pInfo, pClient); |
1093 | if (!pMsg && !signal_pending(current)) { | 1093 | if (!pMsg && !signal_pending(current)) { |
1094 | schedule(); | 1094 | schedule(); |
1095 | goto repeat; | 1095 | goto repeat; |
1096 | } | 1096 | } |
1097 | current->state = TASK_RUNNING; | 1097 | __set_current_state(TASK_RUNNING); |
1098 | remove_wait_queue(&pInfo->read_wait, &wait); | 1098 | remove_wait_queue(&pInfo->read_wait, &wait); |
1099 | } | 1099 | } |
1100 | 1100 | ||
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 6ac3ca4c723c..b3d4ccc33a47 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c | |||
@@ -1544,21 +1544,18 @@ static unsigned int normal_poll(struct tty_struct * tty, struct file * file, pol | |||
1544 | } | 1544 | } |
1545 | 1545 | ||
1546 | struct tty_ldisc tty_ldisc_N_TTY = { | 1546 | struct tty_ldisc tty_ldisc_N_TTY = { |
1547 | TTY_LDISC_MAGIC, /* magic */ | 1547 | .magic = TTY_LDISC_MAGIC, |
1548 | "n_tty", /* name */ | 1548 | .name = "n_tty", |
1549 | 0, /* num */ | 1549 | .open = n_tty_open, |
1550 | 0, /* flags */ | 1550 | .close = n_tty_close, |
1551 | n_tty_open, /* open */ | 1551 | .flush_buffer = n_tty_flush_buffer, |
1552 | n_tty_close, /* close */ | 1552 | .chars_in_buffer = n_tty_chars_in_buffer, |
1553 | n_tty_flush_buffer, /* flush_buffer */ | 1553 | .read = read_chan, |
1554 | n_tty_chars_in_buffer, /* chars_in_buffer */ | 1554 | .write = write_chan, |
1555 | read_chan, /* read */ | 1555 | .ioctl = n_tty_ioctl, |
1556 | write_chan, /* write */ | 1556 | .set_termios = n_tty_set_termios, |
1557 | n_tty_ioctl, /* ioctl */ | 1557 | .poll = normal_poll, |
1558 | n_tty_set_termios, /* set_termios */ | 1558 | .receive_buf = n_tty_receive_buf, |
1559 | normal_poll, /* poll */ | 1559 | .write_wakeup = n_tty_write_wakeup |
1560 | NULL, /* hangup */ | ||
1561 | n_tty_receive_buf, /* receive_buf */ | ||
1562 | n_tty_write_wakeup /* write_wakeup */ | ||
1563 | }; | 1560 | }; |
1564 | 1561 | ||
diff --git a/drivers/char/pcmcia/Kconfig b/drivers/char/pcmcia/Kconfig index 27c1179ee527..f25facd97bb4 100644 --- a/drivers/char/pcmcia/Kconfig +++ b/drivers/char/pcmcia/Kconfig | |||
@@ -21,6 +21,7 @@ config SYNCLINK_CS | |||
21 | config CARDMAN_4000 | 21 | config CARDMAN_4000 |
22 | tristate "Omnikey Cardman 4000 support" | 22 | tristate "Omnikey Cardman 4000 support" |
23 | depends on PCMCIA | 23 | depends on PCMCIA |
24 | select BITREVERSE | ||
24 | help | 25 | help |
25 | Enable support for the Omnikey Cardman 4000 PCMCIA Smartcard | 26 | Enable support for the Omnikey Cardman 4000 PCMCIA Smartcard |
26 | reader. | 27 | reader. |
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index e91b43a014b0..fee58e03dbe2 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/fs.h> | 32 | #include <linux/fs.h> |
33 | #include <linux/delay.h> | 33 | #include <linux/delay.h> |
34 | #include <linux/bitrev.h> | ||
34 | #include <asm/uaccess.h> | 35 | #include <asm/uaccess.h> |
35 | #include <asm/io.h> | 36 | #include <asm/io.h> |
36 | 37 | ||
@@ -194,41 +195,17 @@ static inline unsigned char xinb(unsigned short port) | |||
194 | } | 195 | } |
195 | #endif | 196 | #endif |
196 | 197 | ||
197 | #define b_0000 15 | 198 | static inline unsigned char invert_revert(unsigned char ch) |
198 | #define b_0001 14 | 199 | { |
199 | #define b_0010 13 | 200 | return bitrev8(~ch); |
200 | #define b_0011 12 | 201 | } |
201 | #define b_0100 11 | ||
202 | #define b_0101 10 | ||
203 | #define b_0110 9 | ||
204 | #define b_0111 8 | ||
205 | #define b_1000 7 | ||
206 | #define b_1001 6 | ||
207 | #define b_1010 5 | ||
208 | #define b_1011 4 | ||
209 | #define b_1100 3 | ||
210 | #define b_1101 2 | ||
211 | #define b_1110 1 | ||
212 | #define b_1111 0 | ||
213 | |||
214 | static unsigned char irtab[16] = { | ||
215 | b_0000, b_1000, b_0100, b_1100, | ||
216 | b_0010, b_1010, b_0110, b_1110, | ||
217 | b_0001, b_1001, b_0101, b_1101, | ||
218 | b_0011, b_1011, b_0111, b_1111 | ||
219 | }; | ||
220 | 202 | ||
221 | static void str_invert_revert(unsigned char *b, int len) | 203 | static void str_invert_revert(unsigned char *b, int len) |
222 | { | 204 | { |
223 | int i; | 205 | int i; |
224 | 206 | ||
225 | for (i = 0; i < len; i++) | 207 | for (i = 0; i < len; i++) |
226 | b[i] = (irtab[b[i] & 0x0f] << 4) | irtab[b[i] >> 4]; | 208 | b[i] = invert_revert(b[i]); |
227 | } | ||
228 | |||
229 | static unsigned char invert_revert(unsigned char ch) | ||
230 | { | ||
231 | return (irtab[ch & 0x0f] << 4) | irtab[ch >> 4]; | ||
232 | } | 209 | } |
233 | 210 | ||
234 | #define ATRLENCK(dev,pos) \ | 211 | #define ATRLENCK(dev,pos) \ |
@@ -1114,7 +1091,7 @@ static ssize_t cmm_write(struct file *filp, const char __user *buf, | |||
1114 | /* | 1091 | /* |
1115 | * wait for atr to become valid. | 1092 | * wait for atr to become valid. |
1116 | * note: it is important to lock this code. if we dont, the monitor | 1093 | * note: it is important to lock this code. if we dont, the monitor |
1117 | * could be run between test_bit and the the call the sleep on the | 1094 | * could be run between test_bit and the call to sleep on the |
1118 | * atr-queue. if *then* the monitor detects atr valid, it will wake up | 1095 | * atr-queue. if *then* the monitor detects atr valid, it will wake up |
1119 | * any process on the atr-queue, *but* since we have been interrupted, | 1096 | * any process on the atr-queue, *but* since we have been interrupted, |
1120 | * we do not yet sleep on this queue. this would result in a missed | 1097 | * we do not yet sleep on this queue. this would result in a missed |
@@ -1881,8 +1858,11 @@ static int cm4000_probe(struct pcmcia_device *link) | |||
1881 | init_waitqueue_head(&dev->readq); | 1858 | init_waitqueue_head(&dev->readq); |
1882 | 1859 | ||
1883 | ret = cm4000_config(link, i); | 1860 | ret = cm4000_config(link, i); |
1884 | if (ret) | 1861 | if (ret) { |
1862 | dev_table[i] = NULL; | ||
1863 | kfree(dev); | ||
1885 | return ret; | 1864 | return ret; |
1865 | } | ||
1886 | 1866 | ||
1887 | class_device_create(cmm_class, NULL, MKDEV(major, i), NULL, | 1867 | class_device_create(cmm_class, NULL, MKDEV(major, i), NULL, |
1888 | "cmm%d", i); | 1868 | "cmm%d", i); |
@@ -1907,7 +1887,7 @@ static void cm4000_detach(struct pcmcia_device *link) | |||
1907 | cm4000_release(link); | 1887 | cm4000_release(link); |
1908 | 1888 | ||
1909 | dev_table[devno] = NULL; | 1889 | dev_table[devno] = NULL; |
1910 | kfree(dev); | 1890 | kfree(dev); |
1911 | 1891 | ||
1912 | class_device_destroy(cmm_class, MKDEV(major, devno)); | 1892 | class_device_destroy(cmm_class, MKDEV(major, devno)); |
1913 | 1893 | ||
@@ -1956,12 +1936,14 @@ static int __init cmm_init(void) | |||
1956 | if (major < 0) { | 1936 | if (major < 0) { |
1957 | printk(KERN_WARNING MODULE_NAME | 1937 | printk(KERN_WARNING MODULE_NAME |
1958 | ": could not get major number\n"); | 1938 | ": could not get major number\n"); |
1939 | class_destroy(cmm_class); | ||
1959 | return major; | 1940 | return major; |
1960 | } | 1941 | } |
1961 | 1942 | ||
1962 | rc = pcmcia_register_driver(&cm4000_driver); | 1943 | rc = pcmcia_register_driver(&cm4000_driver); |
1963 | if (rc < 0) { | 1944 | if (rc < 0) { |
1964 | unregister_chrdev(major, DEVICE_NAME); | 1945 | unregister_chrdev(major, DEVICE_NAME); |
1946 | class_destroy(cmm_class); | ||
1965 | return rc; | 1947 | return rc; |
1966 | } | 1948 | } |
1967 | 1949 | ||
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index f2e4ec4fd407..af88181a17f4 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c | |||
@@ -636,8 +636,11 @@ static int reader_probe(struct pcmcia_device *link) | |||
636 | setup_timer(&dev->poll_timer, cm4040_do_poll, 0); | 636 | setup_timer(&dev->poll_timer, cm4040_do_poll, 0); |
637 | 637 | ||
638 | ret = reader_config(link, i); | 638 | ret = reader_config(link, i); |
639 | if (ret) | 639 | if (ret) { |
640 | dev_table[i] = NULL; | ||
641 | kfree(dev); | ||
640 | return ret; | 642 | return ret; |
643 | } | ||
641 | 644 | ||
642 | class_device_create(cmx_class, NULL, MKDEV(major, i), NULL, | 645 | class_device_create(cmx_class, NULL, MKDEV(major, i), NULL, |
643 | "cmx%d", i); | 646 | "cmx%d", i); |
@@ -708,12 +711,14 @@ static int __init cm4040_init(void) | |||
708 | if (major < 0) { | 711 | if (major < 0) { |
709 | printk(KERN_WARNING MODULE_NAME | 712 | printk(KERN_WARNING MODULE_NAME |
710 | ": could not get major number\n"); | 713 | ": could not get major number\n"); |
714 | class_destroy(cmx_class); | ||
711 | return major; | 715 | return major; |
712 | } | 716 | } |
713 | 717 | ||
714 | rc = pcmcia_register_driver(&reader_driver); | 718 | rc = pcmcia_register_driver(&reader_driver); |
715 | if (rc < 0) { | 719 | if (rc < 0) { |
716 | unregister_chrdev(major, DEVICE_NAME); | 720 | unregister_chrdev(major, DEVICE_NAME); |
721 | class_destroy(cmx_class); | ||
717 | return rc; | 722 | return rc; |
718 | } | 723 | } |
719 | 724 | ||
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 157b1d09ab55..13808f6083a0 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
@@ -42,7 +42,6 @@ | |||
42 | #include <linux/timer.h> | 42 | #include <linux/timer.h> |
43 | #include <linux/time.h> | 43 | #include <linux/time.h> |
44 | #include <linux/interrupt.h> | 44 | #include <linux/interrupt.h> |
45 | #include <linux/pci.h> | ||
46 | #include <linux/tty.h> | 45 | #include <linux/tty.h> |
47 | #include <linux/tty_flip.h> | 46 | #include <linux/tty_flip.h> |
48 | #include <linux/serial.h> | 47 | #include <linux/serial.h> |
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 4abd1eff61d6..84ac64fc48a1 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c | |||
@@ -66,7 +66,6 @@ | |||
66 | #include <linux/poll.h> | 66 | #include <linux/poll.h> |
67 | #include <linux/major.h> | 67 | #include <linux/major.h> |
68 | #include <linux/ppdev.h> | 68 | #include <linux/ppdev.h> |
69 | #include <linux/smp_lock.h> | ||
70 | #include <linux/device.h> | 69 | #include <linux/device.h> |
71 | #include <asm/uaccess.h> | 70 | #include <asm/uaccess.h> |
72 | 71 | ||
@@ -752,7 +751,7 @@ static const struct file_operations pp_fops = { | |||
752 | 751 | ||
753 | static void pp_attach(struct parport *port) | 752 | static void pp_attach(struct parport *port) |
754 | { | 753 | { |
755 | device_create(ppdev_class, NULL, MKDEV(PP_MAJOR, port->number), | 754 | device_create(ppdev_class, port->dev, MKDEV(PP_MAJOR, port->number), |
756 | "parport%d", port->number); | 755 | "parport%d", port->number); |
757 | } | 756 | } |
758 | 757 | ||
diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c index 245f03195b7c..8cc60b693460 100644 --- a/drivers/char/rio/riocmd.c +++ b/drivers/char/rio/riocmd.c | |||
@@ -402,7 +402,7 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, struc | |||
402 | rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Host number %Zd, name ``%s''\n", HostP - p->RIOHosts, HostP->Name); | 402 | rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Host number %Zd, name ``%s''\n", HostP - p->RIOHosts, HostP->Name); |
403 | rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Rup number 0x%x\n", rup); | 403 | rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Rup number 0x%x\n", rup); |
404 | 404 | ||
405 | if (Rup >= (unsigned short) MAX_RUP) { | 405 | if (Rup < (unsigned short) MAX_RUP) { |
406 | rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for RTA ``%s''\n", HostP->Mapping[Rup].Name); | 406 | rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for RTA ``%s''\n", HostP->Mapping[Rup].Name); |
407 | } else | 407 | } else |
408 | rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n", ('A' + Rup - MAX_RUP), HostP->Name); | 408 | rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n", ('A' + Rup - MAX_RUP), HostP->Name); |
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 70145254fb9d..3494e3fc44bf 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c | |||
@@ -980,7 +980,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
980 | } | 980 | } |
981 | schedule(); | 981 | schedule(); |
982 | } | 982 | } |
983 | current->state = TASK_RUNNING; | 983 | __set_current_state(TASK_RUNNING); |
984 | remove_wait_queue(&port->open_wait, &wait); | 984 | remove_wait_queue(&port->open_wait, &wait); |
985 | if (!tty_hung_up_p(filp)) | 985 | if (!tty_hung_up_p(filp)) |
986 | port->count++; | 986 | port->count++; |
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 76357c855ce3..a3fd7e7ba5a9 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c | |||
@@ -65,10 +65,6 @@ | |||
65 | 65 | ||
66 | /****** Kernel includes ******/ | 66 | /****** Kernel includes ******/ |
67 | 67 | ||
68 | #ifdef MODVERSIONS | ||
69 | #include <config/modversions.h> | ||
70 | #endif | ||
71 | |||
72 | #include <linux/module.h> | 68 | #include <linux/module.h> |
73 | #include <linux/errno.h> | 69 | #include <linux/errno.h> |
74 | #include <linux/major.h> | 70 | #include <linux/major.h> |
@@ -85,6 +81,7 @@ | |||
85 | #include <linux/string.h> | 81 | #include <linux/string.h> |
86 | #include <linux/fcntl.h> | 82 | #include <linux/fcntl.h> |
87 | #include <linux/ptrace.h> | 83 | #include <linux/ptrace.h> |
84 | #include <linux/mutex.h> | ||
88 | #include <linux/ioport.h> | 85 | #include <linux/ioport.h> |
89 | #include <linux/delay.h> | 86 | #include <linux/delay.h> |
90 | #include <linux/wait.h> | 87 | #include <linux/wait.h> |
@@ -93,7 +90,6 @@ | |||
93 | #include <asm/atomic.h> | 90 | #include <asm/atomic.h> |
94 | #include <linux/bitops.h> | 91 | #include <linux/bitops.h> |
95 | #include <linux/spinlock.h> | 92 | #include <linux/spinlock.h> |
96 | #include <asm/semaphore.h> | ||
97 | #include <linux/init.h> | 93 | #include <linux/init.h> |
98 | 94 | ||
99 | /****** RocketPort includes ******/ | 95 | /****** RocketPort includes ******/ |
@@ -702,7 +698,7 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev) | |||
702 | } | 698 | } |
703 | } | 699 | } |
704 | spin_lock_init(&info->slock); | 700 | spin_lock_init(&info->slock); |
705 | sema_init(&info->write_sem, 1); | 701 | mutex_init(&info->write_mtx); |
706 | rp_table[line] = info; | 702 | rp_table[line] = info; |
707 | if (pci_dev) | 703 | if (pci_dev) |
708 | tty_register_device(rocket_driver, line, &pci_dev->dev); | 704 | tty_register_device(rocket_driver, line, &pci_dev->dev); |
@@ -947,7 +943,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
947 | #endif | 943 | #endif |
948 | schedule(); /* Don't hold spinlock here, will hang PC */ | 944 | schedule(); /* Don't hold spinlock here, will hang PC */ |
949 | } | 945 | } |
950 | current->state = TASK_RUNNING; | 946 | __set_current_state(TASK_RUNNING); |
951 | remove_wait_queue(&info->open_wait, &wait); | 947 | remove_wait_queue(&info->open_wait, &wait); |
952 | 948 | ||
953 | spin_lock_irqsave(&info->slock, flags); | 949 | spin_lock_irqsave(&info->slock, flags); |
@@ -1018,9 +1014,6 @@ static int rp_open(struct tty_struct *tty, struct file *filp) | |||
1018 | /* | 1014 | /* |
1019 | * Info->count is now 1; so it's safe to sleep now. | 1015 | * Info->count is now 1; so it's safe to sleep now. |
1020 | */ | 1016 | */ |
1021 | info->session = process_session(current); | ||
1022 | info->pgrp = process_group(current); | ||
1023 | |||
1024 | if ((info->flags & ROCKET_INITIALIZED) == 0) { | 1017 | if ((info->flags & ROCKET_INITIALIZED) == 0) { |
1025 | cp = &info->channel; | 1018 | cp = &info->channel; |
1026 | sSetRxTrigger(cp, TRIG_1); | 1019 | sSetRxTrigger(cp, TRIG_1); |
@@ -1602,7 +1595,7 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1602 | if (signal_pending(current)) | 1595 | if (signal_pending(current)) |
1603 | break; | 1596 | break; |
1604 | } | 1597 | } |
1605 | current->state = TASK_RUNNING; | 1598 | __set_current_state(TASK_RUNNING); |
1606 | #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT | 1599 | #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT |
1607 | printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies); | 1600 | printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies); |
1608 | #endif | 1601 | #endif |
@@ -1661,8 +1654,11 @@ static void rp_put_char(struct tty_struct *tty, unsigned char ch) | |||
1661 | if (rocket_paranoia_check(info, "rp_put_char")) | 1654 | if (rocket_paranoia_check(info, "rp_put_char")) |
1662 | return; | 1655 | return; |
1663 | 1656 | ||
1664 | /* Grab the port write semaphore, locking out other processes that try to write to this port */ | 1657 | /* |
1665 | down(&info->write_sem); | 1658 | * Grab the port write mutex, locking out other processes that try to |
1659 | * write to this port | ||
1660 | */ | ||
1661 | mutex_lock(&info->write_mtx); | ||
1666 | 1662 | ||
1667 | #ifdef ROCKET_DEBUG_WRITE | 1663 | #ifdef ROCKET_DEBUG_WRITE |
1668 | printk(KERN_INFO "rp_put_char %c...", ch); | 1664 | printk(KERN_INFO "rp_put_char %c...", ch); |
@@ -1684,12 +1680,12 @@ static void rp_put_char(struct tty_struct *tty, unsigned char ch) | |||
1684 | info->xmit_fifo_room--; | 1680 | info->xmit_fifo_room--; |
1685 | } | 1681 | } |
1686 | spin_unlock_irqrestore(&info->slock, flags); | 1682 | spin_unlock_irqrestore(&info->slock, flags); |
1687 | up(&info->write_sem); | 1683 | mutex_unlock(&info->write_mtx); |
1688 | } | 1684 | } |
1689 | 1685 | ||
1690 | /* | 1686 | /* |
1691 | * Exception handler - write routine, called when user app writes to the device. | 1687 | * Exception handler - write routine, called when user app writes to the device. |
1692 | * A per port write semaphore is used to protect from another process writing to | 1688 | * A per port write mutex is used to protect from another process writing to |
1693 | * this port at the same time. This other process could be running on the other CPU | 1689 | * this port at the same time. This other process could be running on the other CPU |
1694 | * or get control of the CPU if the copy_from_user() blocks due to a page fault (swapped out). | 1690 | * or get control of the CPU if the copy_from_user() blocks due to a page fault (swapped out). |
1695 | * Spinlocks protect the info xmit members. | 1691 | * Spinlocks protect the info xmit members. |
@@ -1706,7 +1702,7 @@ static int rp_write(struct tty_struct *tty, | |||
1706 | if (count <= 0 || rocket_paranoia_check(info, "rp_write")) | 1702 | if (count <= 0 || rocket_paranoia_check(info, "rp_write")) |
1707 | return 0; | 1703 | return 0; |
1708 | 1704 | ||
1709 | down_interruptible(&info->write_sem); | 1705 | mutex_lock_interruptible(&info->write_mtx); |
1710 | 1706 | ||
1711 | #ifdef ROCKET_DEBUG_WRITE | 1707 | #ifdef ROCKET_DEBUG_WRITE |
1712 | printk(KERN_INFO "rp_write %d chars...", count); | 1708 | printk(KERN_INFO "rp_write %d chars...", count); |
@@ -1777,7 +1773,7 @@ end: | |||
1777 | wake_up_interruptible(&tty->poll_wait); | 1773 | wake_up_interruptible(&tty->poll_wait); |
1778 | #endif | 1774 | #endif |
1779 | } | 1775 | } |
1780 | up(&info->write_sem); | 1776 | mutex_unlock(&info->write_mtx); |
1781 | return retval; | 1777 | return retval; |
1782 | } | 1778 | } |
1783 | 1779 | ||
@@ -1852,6 +1848,12 @@ static void rp_flush_buffer(struct tty_struct *tty) | |||
1852 | 1848 | ||
1853 | #ifdef CONFIG_PCI | 1849 | #ifdef CONFIG_PCI |
1854 | 1850 | ||
1851 | static struct pci_device_id __devinitdata rocket_pci_ids[] = { | ||
1852 | { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_ANY_ID) }, | ||
1853 | { } | ||
1854 | }; | ||
1855 | MODULE_DEVICE_TABLE(pci, rocket_pci_ids); | ||
1856 | |||
1855 | /* | 1857 | /* |
1856 | * Called when a PCI card is found. Retrieves and stores model information, | 1858 | * Called when a PCI card is found. Retrieves and stores model information, |
1857 | * init's aiopic and serial port hardware. | 1859 | * init's aiopic and serial port hardware. |
diff --git a/drivers/char/rocket_int.h b/drivers/char/rocket_int.h index 3a8bcc85bc14..b4c53dfa7951 100644 --- a/drivers/char/rocket_int.h +++ b/drivers/char/rocket_int.h | |||
@@ -15,6 +15,8 @@ | |||
15 | #define ROCKET_TYPE_MODEMIII 3 | 15 | #define ROCKET_TYPE_MODEMIII 3 |
16 | #define ROCKET_TYPE_PC104 4 | 16 | #define ROCKET_TYPE_PC104 4 |
17 | 17 | ||
18 | #include <linux/mutex.h> | ||
19 | |||
18 | #include <asm/io.h> | 20 | #include <asm/io.h> |
19 | #include <asm/byteorder.h> | 21 | #include <asm/byteorder.h> |
20 | 22 | ||
@@ -1156,8 +1158,6 @@ struct r_port { | |||
1156 | int xmit_head; | 1158 | int xmit_head; |
1157 | int xmit_tail; | 1159 | int xmit_tail; |
1158 | int xmit_cnt; | 1160 | int xmit_cnt; |
1159 | int session; | ||
1160 | int pgrp; | ||
1161 | int cd_status; | 1161 | int cd_status; |
1162 | int ignore_status_mask; | 1162 | int ignore_status_mask; |
1163 | int read_status_mask; | 1163 | int read_status_mask; |
@@ -1171,7 +1171,7 @@ struct r_port { | |||
1171 | struct wait_queue *close_wait; | 1171 | struct wait_queue *close_wait; |
1172 | #endif | 1172 | #endif |
1173 | spinlock_t slock; | 1173 | spinlock_t slock; |
1174 | struct semaphore write_sem; | 1174 | struct mutex write_mtx; |
1175 | }; | 1175 | }; |
1176 | 1176 | ||
1177 | #define RPORT_MAGIC 0x525001 | 1177 | #define RPORT_MAGIC 0x525001 |
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index c7dac9b13351..20380a2c4dee 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c | |||
@@ -388,7 +388,7 @@ static ssize_t rtc_read(struct file *file, char __user *buf, | |||
388 | if (!retval) | 388 | if (!retval) |
389 | retval = count; | 389 | retval = count; |
390 | out: | 390 | out: |
391 | current->state = TASK_RUNNING; | 391 | __set_current_state(TASK_RUNNING); |
392 | remove_wait_queue(&rtc_wait, &wait); | 392 | remove_wait_queue(&rtc_wait, &wait); |
393 | 393 | ||
394 | return retval; | 394 | return retval; |
diff --git a/drivers/char/selection.c b/drivers/char/selection.c index 74cff839c857..a69f094d1ed3 100644 --- a/drivers/char/selection.c +++ b/drivers/char/selection.c | |||
@@ -299,7 +299,7 @@ int paste_selection(struct tty_struct *tty) | |||
299 | pasted += count; | 299 | pasted += count; |
300 | } | 300 | } |
301 | remove_wait_queue(&vc->paste_wait, &wait); | 301 | remove_wait_queue(&vc->paste_wait, &wait); |
302 | current->state = TASK_RUNNING; | 302 | __set_current_state(TASK_RUNNING); |
303 | 303 | ||
304 | tty_ldisc_deref(ld); | 304 | tty_ldisc_deref(ld); |
305 | return 0; | 305 | return 0; |
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index 5fd314adc1f2..c585b4738f86 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c | |||
@@ -1892,7 +1892,7 @@ block_til_ready(struct tty_struct *tty, struct file *filp, | |||
1892 | #endif | 1892 | #endif |
1893 | schedule(); | 1893 | schedule(); |
1894 | } | 1894 | } |
1895 | current->state = TASK_RUNNING; | 1895 | __set_current_state(TASK_RUNNING); |
1896 | remove_wait_queue(&info->open_wait, &wait); | 1896 | remove_wait_queue(&info->open_wait, &wait); |
1897 | if (!tty_hung_up_p(filp)) { | 1897 | if (!tty_hung_up_p(filp)) { |
1898 | info->count++; | 1898 | info->count++; |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index ce4db6f52362..f02a0795983f 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
@@ -4010,8 +4010,13 @@ static int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info) | |||
4010 | for ( i=0; i<info->num_tx_holding_buffers; ++i) { | 4010 | for ( i=0; i<info->num_tx_holding_buffers; ++i) { |
4011 | info->tx_holding_buffers[i].buffer = | 4011 | info->tx_holding_buffers[i].buffer = |
4012 | kmalloc(info->max_frame_size, GFP_KERNEL); | 4012 | kmalloc(info->max_frame_size, GFP_KERNEL); |
4013 | if ( info->tx_holding_buffers[i].buffer == NULL ) | 4013 | if (info->tx_holding_buffers[i].buffer == NULL) { |
4014 | for (--i; i >= 0; i--) { | ||
4015 | kfree(info->tx_holding_buffers[i].buffer); | ||
4016 | info->tx_holding_buffers[i].buffer = NULL; | ||
4017 | } | ||
4014 | return -ENOMEM; | 4018 | return -ENOMEM; |
4019 | } | ||
4015 | } | 4020 | } |
4016 | 4021 | ||
4017 | return 0; | 4022 | return 0; |
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 0a367cd4121f..02b49bc00028 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -1171,6 +1171,112 @@ static int ioctl(struct tty_struct *tty, struct file *file, | |||
1171 | } | 1171 | } |
1172 | 1172 | ||
1173 | /* | 1173 | /* |
1174 | * support for 32 bit ioctl calls on 64 bit systems | ||
1175 | */ | ||
1176 | #ifdef CONFIG_COMPAT | ||
1177 | static long get_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *user_params) | ||
1178 | { | ||
1179 | struct MGSL_PARAMS32 tmp_params; | ||
1180 | |||
1181 | DBGINFO(("%s get_params32\n", info->device_name)); | ||
1182 | tmp_params.mode = (compat_ulong_t)info->params.mode; | ||
1183 | tmp_params.loopback = info->params.loopback; | ||
1184 | tmp_params.flags = info->params.flags; | ||
1185 | tmp_params.encoding = info->params.encoding; | ||
1186 | tmp_params.clock_speed = (compat_ulong_t)info->params.clock_speed; | ||
1187 | tmp_params.addr_filter = info->params.addr_filter; | ||
1188 | tmp_params.crc_type = info->params.crc_type; | ||
1189 | tmp_params.preamble_length = info->params.preamble_length; | ||
1190 | tmp_params.preamble = info->params.preamble; | ||
1191 | tmp_params.data_rate = (compat_ulong_t)info->params.data_rate; | ||
1192 | tmp_params.data_bits = info->params.data_bits; | ||
1193 | tmp_params.stop_bits = info->params.stop_bits; | ||
1194 | tmp_params.parity = info->params.parity; | ||
1195 | if (copy_to_user(user_params, &tmp_params, sizeof(struct MGSL_PARAMS32))) | ||
1196 | return -EFAULT; | ||
1197 | return 0; | ||
1198 | } | ||
1199 | |||
1200 | static long set_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *new_params) | ||
1201 | { | ||
1202 | struct MGSL_PARAMS32 tmp_params; | ||
1203 | |||
1204 | DBGINFO(("%s set_params32\n", info->device_name)); | ||
1205 | if (copy_from_user(&tmp_params, new_params, sizeof(struct MGSL_PARAMS32))) | ||
1206 | return -EFAULT; | ||
1207 | |||
1208 | spin_lock(&info->lock); | ||
1209 | info->params.mode = tmp_params.mode; | ||
1210 | info->params.loopback = tmp_params.loopback; | ||
1211 | info->params.flags = tmp_params.flags; | ||
1212 | info->params.encoding = tmp_params.encoding; | ||
1213 | info->params.clock_speed = tmp_params.clock_speed; | ||
1214 | info->params.addr_filter = tmp_params.addr_filter; | ||
1215 | info->params.crc_type = tmp_params.crc_type; | ||
1216 | info->params.preamble_length = tmp_params.preamble_length; | ||
1217 | info->params.preamble = tmp_params.preamble; | ||
1218 | info->params.data_rate = tmp_params.data_rate; | ||
1219 | info->params.data_bits = tmp_params.data_bits; | ||
1220 | info->params.stop_bits = tmp_params.stop_bits; | ||
1221 | info->params.parity = tmp_params.parity; | ||
1222 | spin_unlock(&info->lock); | ||
1223 | |||
1224 | change_params(info); | ||
1225 | |||
1226 | return 0; | ||
1227 | } | ||
1228 | |||
1229 | static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file, | ||
1230 | unsigned int cmd, unsigned long arg) | ||
1231 | { | ||
1232 | struct slgt_info *info = tty->driver_data; | ||
1233 | int rc = -ENOIOCTLCMD; | ||
1234 | |||
1235 | if (sanity_check(info, tty->name, "compat_ioctl")) | ||
1236 | return -ENODEV; | ||
1237 | DBGINFO(("%s compat_ioctl() cmd=%08X\n", info->device_name, cmd)); | ||
1238 | |||
1239 | switch (cmd) { | ||
1240 | |||
1241 | case MGSL_IOCSPARAMS32: | ||
1242 | rc = set_params32(info, compat_ptr(arg)); | ||
1243 | break; | ||
1244 | |||
1245 | case MGSL_IOCGPARAMS32: | ||
1246 | rc = get_params32(info, compat_ptr(arg)); | ||
1247 | break; | ||
1248 | |||
1249 | case MGSL_IOCGPARAMS: | ||
1250 | case MGSL_IOCSPARAMS: | ||
1251 | case MGSL_IOCGTXIDLE: | ||
1252 | case MGSL_IOCGSTATS: | ||
1253 | case MGSL_IOCWAITEVENT: | ||
1254 | case MGSL_IOCGIF: | ||
1255 | case MGSL_IOCSGPIO: | ||
1256 | case MGSL_IOCGGPIO: | ||
1257 | case MGSL_IOCWAITGPIO: | ||
1258 | case TIOCGICOUNT: | ||
1259 | rc = ioctl(tty, file, cmd, (unsigned long)(compat_ptr(arg))); | ||
1260 | break; | ||
1261 | |||
1262 | case MGSL_IOCSTXIDLE: | ||
1263 | case MGSL_IOCTXENABLE: | ||
1264 | case MGSL_IOCRXENABLE: | ||
1265 | case MGSL_IOCTXABORT: | ||
1266 | case TIOCMIWAIT: | ||
1267 | case MGSL_IOCSIF: | ||
1268 | rc = ioctl(tty, file, cmd, arg); | ||
1269 | break; | ||
1270 | } | ||
1271 | |||
1272 | DBGINFO(("%s compat_ioctl() cmd=%08X rc=%d\n", info->device_name, cmd, rc)); | ||
1273 | return rc; | ||
1274 | } | ||
1275 | #else | ||
1276 | #define slgt_compat_ioctl NULL | ||
1277 | #endif /* ifdef CONFIG_COMPAT */ | ||
1278 | |||
1279 | /* | ||
1174 | * proc fs support | 1280 | * proc fs support |
1175 | */ | 1281 | */ |
1176 | static inline int line_info(char *buf, struct slgt_info *info) | 1282 | static inline int line_info(char *buf, struct slgt_info *info) |
@@ -3415,6 +3521,9 @@ static void device_init(int adapter_num, struct pci_dev *pdev) | |||
3415 | } | 3521 | } |
3416 | } | 3522 | } |
3417 | } | 3523 | } |
3524 | |||
3525 | for (i=0; i < port_count; ++i) | ||
3526 | tty_register_device(serial_driver, port_array[i]->line, &(port_array[i]->pdev->dev)); | ||
3418 | } | 3527 | } |
3419 | 3528 | ||
3420 | static int __devinit init_one(struct pci_dev *dev, | 3529 | static int __devinit init_one(struct pci_dev *dev, |
@@ -3443,6 +3552,7 @@ static const struct tty_operations ops = { | |||
3443 | .chars_in_buffer = chars_in_buffer, | 3552 | .chars_in_buffer = chars_in_buffer, |
3444 | .flush_buffer = flush_buffer, | 3553 | .flush_buffer = flush_buffer, |
3445 | .ioctl = ioctl, | 3554 | .ioctl = ioctl, |
3555 | .compat_ioctl = slgt_compat_ioctl, | ||
3446 | .throttle = throttle, | 3556 | .throttle = throttle, |
3447 | .unthrottle = unthrottle, | 3557 | .unthrottle = unthrottle, |
3448 | .send_xchar = send_xchar, | 3558 | .send_xchar = send_xchar, |
@@ -3466,6 +3576,8 @@ static void slgt_cleanup(void) | |||
3466 | printk("unload %s %s\n", driver_name, driver_version); | 3576 | printk("unload %s %s\n", driver_name, driver_version); |
3467 | 3577 | ||
3468 | if (serial_driver) { | 3578 | if (serial_driver) { |
3579 | for (info=slgt_device_list ; info != NULL ; info=info->next_device) | ||
3580 | tty_unregister_device(serial_driver, info->line); | ||
3469 | if ((rc = tty_unregister_driver(serial_driver))) | 3581 | if ((rc = tty_unregister_driver(serial_driver))) |
3470 | DBGERR(("tty_unregister_driver error=%d\n", rc)); | 3582 | DBGERR(("tty_unregister_driver error=%d\n", rc)); |
3471 | put_tty_driver(serial_driver); | 3583 | put_tty_driver(serial_driver); |
@@ -3506,23 +3618,10 @@ static int __init slgt_init(void) | |||
3506 | 3618 | ||
3507 | printk("%s %s\n", driver_name, driver_version); | 3619 | printk("%s %s\n", driver_name, driver_version); |
3508 | 3620 | ||
3509 | slgt_device_count = 0; | ||
3510 | if ((rc = pci_register_driver(&pci_driver)) < 0) { | ||
3511 | printk("%s pci_register_driver error=%d\n", driver_name, rc); | ||
3512 | return rc; | ||
3513 | } | ||
3514 | pci_registered = 1; | ||
3515 | |||
3516 | if (!slgt_device_list) { | ||
3517 | printk("%s no devices found\n",driver_name); | ||
3518 | pci_unregister_driver(&pci_driver); | ||
3519 | return -ENODEV; | ||
3520 | } | ||
3521 | |||
3522 | serial_driver = alloc_tty_driver(MAX_DEVICES); | 3621 | serial_driver = alloc_tty_driver(MAX_DEVICES); |
3523 | if (!serial_driver) { | 3622 | if (!serial_driver) { |
3524 | rc = -ENOMEM; | 3623 | printk("%s can't allocate tty driver\n", driver_name); |
3525 | goto error; | 3624 | return -ENOMEM; |
3526 | } | 3625 | } |
3527 | 3626 | ||
3528 | /* Initialize the tty_driver structure */ | 3627 | /* Initialize the tty_driver structure */ |
@@ -3539,7 +3638,7 @@ static int __init slgt_init(void) | |||
3539 | B9600 | CS8 | CREAD | HUPCL | CLOCAL; | 3638 | B9600 | CS8 | CREAD | HUPCL | CLOCAL; |
3540 | serial_driver->init_termios.c_ispeed = 9600; | 3639 | serial_driver->init_termios.c_ispeed = 9600; |
3541 | serial_driver->init_termios.c_ospeed = 9600; | 3640 | serial_driver->init_termios.c_ospeed = 9600; |
3542 | serial_driver->flags = TTY_DRIVER_REAL_RAW; | 3641 | serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; |
3543 | tty_set_operations(serial_driver, &ops); | 3642 | tty_set_operations(serial_driver, &ops); |
3544 | if ((rc = tty_register_driver(serial_driver)) < 0) { | 3643 | if ((rc = tty_register_driver(serial_driver)) < 0) { |
3545 | DBGERR(("%s can't register serial driver\n", driver_name)); | 3644 | DBGERR(("%s can't register serial driver\n", driver_name)); |
@@ -3552,6 +3651,16 @@ static int __init slgt_init(void) | |||
3552 | driver_name, driver_version, | 3651 | driver_name, driver_version, |
3553 | serial_driver->major); | 3652 | serial_driver->major); |
3554 | 3653 | ||
3654 | slgt_device_count = 0; | ||
3655 | if ((rc = pci_register_driver(&pci_driver)) < 0) { | ||
3656 | printk("%s pci_register_driver error=%d\n", driver_name, rc); | ||
3657 | goto error; | ||
3658 | } | ||
3659 | pci_registered = 1; | ||
3660 | |||
3661 | if (!slgt_device_list) | ||
3662 | printk("%s no devices found\n",driver_name); | ||
3663 | |||
3555 | return 0; | 3664 | return 0; |
3556 | 3665 | ||
3557 | error: | 3666 | error: |
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 1d8c4ae61551..39cc318011ea 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/sysrq.h> | 24 | #include <linux/sysrq.h> |
25 | #include <linux/kbd_kern.h> | 25 | #include <linux/kbd_kern.h> |
26 | #include <linux/quotaops.h> | 26 | #include <linux/quotaops.h> |
27 | #include <linux/smp_lock.h> | ||
28 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
29 | #include <linux/module.h> | 28 | #include <linux/module.h> |
30 | #include <linux/suspend.h> | 29 | #include <linux/suspend.h> |
diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c index 47fb20f69695..35b40b996534 100644 --- a/drivers/char/tipar.c +++ b/drivers/char/tipar.c | |||
@@ -442,7 +442,7 @@ tipar_register(int nr, struct parport *port) | |||
442 | } | 442 | } |
443 | 443 | ||
444 | class_device_create(tipar_class, NULL, MKDEV(TIPAR_MAJOR, | 444 | class_device_create(tipar_class, NULL, MKDEV(TIPAR_MAJOR, |
445 | TIPAR_MINOR + nr), NULL, "par%d", nr); | 445 | TIPAR_MINOR + nr), port->dev, "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 == |
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index fe00c7dfb649..dc4e1ff7f56f 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig | |||
@@ -3,6 +3,7 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | menu "TPM devices" | 5 | menu "TPM devices" |
6 | depends on HAS_IOMEM | ||
6 | 7 | ||
7 | config TCG_TPM | 8 | config TCG_TPM |
8 | tristate "TPM Hardware Support" | 9 | tristate "TPM Hardware Support" |
@@ -33,7 +34,7 @@ config TCG_NSC | |||
33 | tristate "National Semiconductor TPM Interface" | 34 | tristate "National Semiconductor TPM Interface" |
34 | depends on TCG_TPM && PNPACPI | 35 | depends on TCG_TPM && PNPACPI |
35 | ---help--- | 36 | ---help--- |
36 | If you have a TPM security chip from National Semicondutor | 37 | If you have a TPM security chip from National Semiconductor |
37 | say Yes and it will be accessible from within Linux. To | 38 | say Yes and it will be accessible from within Linux. To |
38 | compile this driver as a module, choose M here; the module | 39 | compile this driver as a module, choose M here; the module |
39 | will be called tpm_nsc. | 40 | will be called tpm_nsc. |
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index e5a254a434f8..9bb542913b86 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -24,7 +24,9 @@ | |||
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <linux/poll.h> | 26 | #include <linux/poll.h> |
27 | #include <linux/mutex.h> | ||
27 | #include <linux/spinlock.h> | 28 | #include <linux/spinlock.h> |
29 | |||
28 | #include "tpm.h" | 30 | #include "tpm.h" |
29 | 31 | ||
30 | enum tpm_const { | 32 | enum tpm_const { |
@@ -328,10 +330,10 @@ static void timeout_work(struct work_struct *work) | |||
328 | { | 330 | { |
329 | struct tpm_chip *chip = container_of(work, struct tpm_chip, work); | 331 | struct tpm_chip *chip = container_of(work, struct tpm_chip, work); |
330 | 332 | ||
331 | down(&chip->buffer_mutex); | 333 | mutex_lock(&chip->buffer_mutex); |
332 | atomic_set(&chip->data_pending, 0); | 334 | atomic_set(&chip->data_pending, 0); |
333 | memset(chip->data_buffer, 0, TPM_BUFSIZE); | 335 | memset(chip->data_buffer, 0, TPM_BUFSIZE); |
334 | up(&chip->buffer_mutex); | 336 | mutex_unlock(&chip->buffer_mutex); |
335 | } | 337 | } |
336 | 338 | ||
337 | /* | 339 | /* |
@@ -380,7 +382,7 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, | |||
380 | return -E2BIG; | 382 | return -E2BIG; |
381 | } | 383 | } |
382 | 384 | ||
383 | down(&chip->tpm_mutex); | 385 | mutex_lock(&chip->tpm_mutex); |
384 | 386 | ||
385 | if ((rc = chip->vendor.send(chip, (u8 *) buf, count)) < 0) { | 387 | if ((rc = chip->vendor.send(chip, (u8 *) buf, count)) < 0) { |
386 | dev_err(chip->dev, | 388 | dev_err(chip->dev, |
@@ -419,7 +421,7 @@ out_recv: | |||
419 | dev_err(chip->dev, | 421 | dev_err(chip->dev, |
420 | "tpm_transmit: tpm_recv: error %zd\n", rc); | 422 | "tpm_transmit: tpm_recv: error %zd\n", rc); |
421 | out: | 423 | out: |
422 | up(&chip->tpm_mutex); | 424 | mutex_unlock(&chip->tpm_mutex); |
423 | return rc; | 425 | return rc; |
424 | } | 426 | } |
425 | 427 | ||
@@ -942,12 +944,12 @@ int tpm_release(struct inode *inode, struct file *file) | |||
942 | { | 944 | { |
943 | struct tpm_chip *chip = file->private_data; | 945 | struct tpm_chip *chip = file->private_data; |
944 | 946 | ||
947 | flush_scheduled_work(); | ||
945 | spin_lock(&driver_lock); | 948 | spin_lock(&driver_lock); |
946 | file->private_data = NULL; | 949 | file->private_data = NULL; |
947 | chip->num_opens--; | ||
948 | del_singleshot_timer_sync(&chip->user_read_timer); | 950 | del_singleshot_timer_sync(&chip->user_read_timer); |
949 | flush_scheduled_work(); | ||
950 | atomic_set(&chip->data_pending, 0); | 951 | atomic_set(&chip->data_pending, 0); |
952 | chip->num_opens--; | ||
951 | put_device(chip->dev); | 953 | put_device(chip->dev); |
952 | kfree(chip->data_buffer); | 954 | kfree(chip->data_buffer); |
953 | spin_unlock(&driver_lock); | 955 | spin_unlock(&driver_lock); |
@@ -966,14 +968,14 @@ ssize_t tpm_write(struct file *file, const char __user *buf, | |||
966 | while (atomic_read(&chip->data_pending) != 0) | 968 | while (atomic_read(&chip->data_pending) != 0) |
967 | msleep(TPM_TIMEOUT); | 969 | msleep(TPM_TIMEOUT); |
968 | 970 | ||
969 | down(&chip->buffer_mutex); | 971 | mutex_lock(&chip->buffer_mutex); |
970 | 972 | ||
971 | if (in_size > TPM_BUFSIZE) | 973 | if (in_size > TPM_BUFSIZE) |
972 | in_size = TPM_BUFSIZE; | 974 | in_size = TPM_BUFSIZE; |
973 | 975 | ||
974 | if (copy_from_user | 976 | if (copy_from_user |
975 | (chip->data_buffer, (void __user *) buf, in_size)) { | 977 | (chip->data_buffer, (void __user *) buf, in_size)) { |
976 | up(&chip->buffer_mutex); | 978 | mutex_unlock(&chip->buffer_mutex); |
977 | return -EFAULT; | 979 | return -EFAULT; |
978 | } | 980 | } |
979 | 981 | ||
@@ -981,7 +983,7 @@ ssize_t tpm_write(struct file *file, const char __user *buf, | |||
981 | out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE); | 983 | out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE); |
982 | 984 | ||
983 | atomic_set(&chip->data_pending, out_size); | 985 | atomic_set(&chip->data_pending, out_size); |
984 | up(&chip->buffer_mutex); | 986 | mutex_unlock(&chip->buffer_mutex); |
985 | 987 | ||
986 | /* Set a timeout by which the reader must come claim the result */ | 988 | /* Set a timeout by which the reader must come claim the result */ |
987 | mod_timer(&chip->user_read_timer, jiffies + (60 * HZ)); | 989 | mod_timer(&chip->user_read_timer, jiffies + (60 * HZ)); |
@@ -1004,10 +1006,10 @@ ssize_t tpm_read(struct file *file, char __user *buf, | |||
1004 | if (size < ret_size) | 1006 | if (size < ret_size) |
1005 | ret_size = size; | 1007 | ret_size = size; |
1006 | 1008 | ||
1007 | down(&chip->buffer_mutex); | 1009 | mutex_lock(&chip->buffer_mutex); |
1008 | if (copy_to_user(buf, chip->data_buffer, ret_size)) | 1010 | if (copy_to_user(buf, chip->data_buffer, ret_size)) |
1009 | ret_size = -EFAULT; | 1011 | ret_size = -EFAULT; |
1010 | up(&chip->buffer_mutex); | 1012 | mutex_unlock(&chip->buffer_mutex); |
1011 | } | 1013 | } |
1012 | 1014 | ||
1013 | return ret_size; | 1015 | return ret_size; |
@@ -1097,11 +1099,16 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend | |||
1097 | 1099 | ||
1098 | /* Driver specific per-device data */ | 1100 | /* Driver specific per-device data */ |
1099 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | 1101 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); |
1100 | if (chip == NULL) | 1102 | devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL); |
1103 | |||
1104 | if (chip == NULL || devname == NULL) { | ||
1105 | kfree(chip); | ||
1106 | kfree(devname); | ||
1101 | return NULL; | 1107 | return NULL; |
1108 | } | ||
1102 | 1109 | ||
1103 | init_MUTEX(&chip->buffer_mutex); | 1110 | mutex_init(&chip->buffer_mutex); |
1104 | init_MUTEX(&chip->tpm_mutex); | 1111 | mutex_init(&chip->tpm_mutex); |
1105 | INIT_LIST_HEAD(&chip->list); | 1112 | INIT_LIST_HEAD(&chip->list); |
1106 | 1113 | ||
1107 | INIT_WORK(&chip->work, timeout_work); | 1114 | INIT_WORK(&chip->work, timeout_work); |
@@ -1124,7 +1131,6 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend | |||
1124 | 1131 | ||
1125 | set_bit(chip->dev_num, dev_mask); | 1132 | set_bit(chip->dev_num, dev_mask); |
1126 | 1133 | ||
1127 | devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL); | ||
1128 | scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num); | 1134 | scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num); |
1129 | chip->vendor.miscdev.name = devname; | 1135 | chip->vendor.miscdev.name = devname; |
1130 | 1136 | ||
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index bb9a43c6cf3d..b2e2b002a1bb 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -19,9 +19,9 @@ | |||
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/pci.h> | ||
23 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
24 | #include <linux/fs.h> | 23 | #include <linux/fs.h> |
24 | #include <linux/mutex.h> | ||
25 | #include <linux/sched.h> | 25 | #include <linux/sched.h> |
26 | #include <linux/miscdevice.h> | 26 | #include <linux/miscdevice.h> |
27 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
@@ -95,11 +95,11 @@ struct tpm_chip { | |||
95 | /* Data passed to and from the tpm via the read/write calls */ | 95 | /* Data passed to and from the tpm via the read/write calls */ |
96 | u8 *data_buffer; | 96 | u8 *data_buffer; |
97 | atomic_t data_pending; | 97 | atomic_t data_pending; |
98 | struct semaphore buffer_mutex; | 98 | struct mutex buffer_mutex; |
99 | 99 | ||
100 | struct timer_list user_read_timer; /* user needs to claim result */ | 100 | struct timer_list user_read_timer; /* user needs to claim result */ |
101 | struct work_struct work; | 101 | struct work_struct work; |
102 | struct semaphore tpm_mutex; /* tpm is processing */ | 102 | struct mutex tpm_mutex; /* tpm is processing */ |
103 | 103 | ||
104 | struct tpm_vendor_specific vendor; | 104 | struct tpm_vendor_specific vendor; |
105 | 105 | ||
diff --git a/drivers/char/tpm/tpm_atmel.h b/drivers/char/tpm/tpm_atmel.h index 3c852009196e..c912d8691cbd 100644 --- a/drivers/char/tpm/tpm_atmel.h +++ b/drivers/char/tpm/tpm_atmel.h | |||
@@ -47,12 +47,12 @@ static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size) | |||
47 | if (!dn) | 47 | if (!dn) |
48 | return NULL; | 48 | return NULL; |
49 | 49 | ||
50 | if (!device_is_compatible(dn, "AT97SC3201")) { | 50 | if (!of_device_is_compatible(dn, "AT97SC3201")) { |
51 | of_node_put(dn); | 51 | of_node_put(dn); |
52 | return NULL; | 52 | return NULL; |
53 | } | 53 | } |
54 | 54 | ||
55 | reg = get_property(dn, "reg", ®len); | 55 | reg = of_get_property(dn, "reg", ®len); |
56 | naddrc = of_n_addr_cells(dn); | 56 | naddrc = of_n_addr_cells(dn); |
57 | nsizec = of_n_size_cells(dn); | 57 | nsizec = of_n_size_cells(dn); |
58 | 58 | ||
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c index 1353b5a6bae8..967002a5a1e5 100644 --- a/drivers/char/tpm/tpm_infineon.c +++ b/drivers/char/tpm/tpm_infineon.c | |||
@@ -30,12 +30,60 @@ | |||
30 | #define TPM_MAX_TRIES 5000 | 30 | #define TPM_MAX_TRIES 5000 |
31 | #define TPM_INFINEON_DEV_VEN_VALUE 0x15D1 | 31 | #define TPM_INFINEON_DEV_VEN_VALUE 0x15D1 |
32 | 32 | ||
33 | /* These values will be filled after PnP-call */ | 33 | #define TPM_INF_IO_PORT 0x0 |
34 | static int TPM_INF_DATA; | 34 | #define TPM_INF_IO_MEM 0x1 |
35 | static int TPM_INF_ADDR; | 35 | |
36 | static int TPM_INF_BASE; | 36 | #define TPM_INF_ADDR 0x0 |
37 | static int TPM_INF_ADDR_LEN; | 37 | #define TPM_INF_DATA 0x1 |
38 | static int TPM_INF_PORT_LEN; | 38 | |
39 | struct tpm_inf_dev { | ||
40 | int iotype; | ||
41 | |||
42 | void __iomem *mem_base; /* MMIO ioremap'd addr */ | ||
43 | unsigned long map_base; /* phys MMIO base */ | ||
44 | unsigned long map_size; /* MMIO region size */ | ||
45 | unsigned int index_off; /* index register offset */ | ||
46 | |||
47 | unsigned int data_regs; /* Data registers */ | ||
48 | unsigned int data_size; | ||
49 | |||
50 | unsigned int config_port; /* IO Port config index reg */ | ||
51 | unsigned int config_size; | ||
52 | }; | ||
53 | |||
54 | static struct tpm_inf_dev tpm_dev; | ||
55 | |||
56 | static inline void tpm_data_out(unsigned char data, unsigned char offset) | ||
57 | { | ||
58 | if (tpm_dev.iotype == TPM_INF_IO_PORT) | ||
59 | outb(data, tpm_dev.data_regs + offset); | ||
60 | else | ||
61 | writeb(data, tpm_dev.mem_base + tpm_dev.data_regs + offset); | ||
62 | } | ||
63 | |||
64 | static inline unsigned char tpm_data_in(unsigned char offset) | ||
65 | { | ||
66 | if (tpm_dev.iotype == TPM_INF_IO_PORT) | ||
67 | return inb(tpm_dev.data_regs + offset); | ||
68 | else | ||
69 | return readb(tpm_dev.mem_base + tpm_dev.data_regs + offset); | ||
70 | } | ||
71 | |||
72 | static inline void tpm_config_out(unsigned char data, unsigned char offset) | ||
73 | { | ||
74 | if (tpm_dev.iotype == TPM_INF_IO_PORT) | ||
75 | outb(data, tpm_dev.config_port + offset); | ||
76 | else | ||
77 | writeb(data, tpm_dev.mem_base + tpm_dev.index_off + offset); | ||
78 | } | ||
79 | |||
80 | static inline unsigned char tpm_config_in(unsigned char offset) | ||
81 | { | ||
82 | if (tpm_dev.iotype == TPM_INF_IO_PORT) | ||
83 | return inb(tpm_dev.config_port + offset); | ||
84 | else | ||
85 | return readb(tpm_dev.mem_base + tpm_dev.index_off + offset); | ||
86 | } | ||
39 | 87 | ||
40 | /* TPM header definitions */ | 88 | /* TPM header definitions */ |
41 | enum infineon_tpm_header { | 89 | enum infineon_tpm_header { |
@@ -105,7 +153,7 @@ static int empty_fifo(struct tpm_chip *chip, int clear_wrfifo) | |||
105 | 153 | ||
106 | if (clear_wrfifo) { | 154 | if (clear_wrfifo) { |
107 | for (i = 0; i < 4096; i++) { | 155 | for (i = 0; i < 4096; i++) { |
108 | status = inb(chip->vendor.base + WRFIFO); | 156 | status = tpm_data_in(WRFIFO); |
109 | if (status == 0xff) { | 157 | if (status == 0xff) { |
110 | if (check == 5) | 158 | if (check == 5) |
111 | break; | 159 | break; |
@@ -125,8 +173,8 @@ static int empty_fifo(struct tpm_chip *chip, int clear_wrfifo) | |||
125 | */ | 173 | */ |
126 | i = 0; | 174 | i = 0; |
127 | do { | 175 | do { |
128 | status = inb(chip->vendor.base + RDFIFO); | 176 | status = tpm_data_in(RDFIFO); |
129 | status = inb(chip->vendor.base + STAT); | 177 | status = tpm_data_in(STAT); |
130 | i++; | 178 | i++; |
131 | if (i == TPM_MAX_TRIES) | 179 | if (i == TPM_MAX_TRIES) |
132 | return -EIO; | 180 | return -EIO; |
@@ -139,7 +187,7 @@ static int wait(struct tpm_chip *chip, int wait_for_bit) | |||
139 | int status; | 187 | int status; |
140 | int i; | 188 | int i; |
141 | for (i = 0; i < TPM_MAX_TRIES; i++) { | 189 | for (i = 0; i < TPM_MAX_TRIES; i++) { |
142 | status = inb(chip->vendor.base + STAT); | 190 | status = tpm_data_in(STAT); |
143 | /* check the status-register if wait_for_bit is set */ | 191 | /* check the status-register if wait_for_bit is set */ |
144 | if (status & 1 << wait_for_bit) | 192 | if (status & 1 << wait_for_bit) |
145 | break; | 193 | break; |
@@ -158,7 +206,7 @@ static int wait(struct tpm_chip *chip, int wait_for_bit) | |||
158 | static void wait_and_send(struct tpm_chip *chip, u8 sendbyte) | 206 | static void wait_and_send(struct tpm_chip *chip, u8 sendbyte) |
159 | { | 207 | { |
160 | wait(chip, STAT_XFE); | 208 | wait(chip, STAT_XFE); |
161 | outb(sendbyte, chip->vendor.base + WRFIFO); | 209 | tpm_data_out(sendbyte, WRFIFO); |
162 | } | 210 | } |
163 | 211 | ||
164 | /* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more | 212 | /* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more |
@@ -205,7 +253,7 @@ recv_begin: | |||
205 | ret = wait(chip, STAT_RDA); | 253 | ret = wait(chip, STAT_RDA); |
206 | if (ret) | 254 | if (ret) |
207 | return -EIO; | 255 | return -EIO; |
208 | buf[i] = inb(chip->vendor.base + RDFIFO); | 256 | buf[i] = tpm_data_in(RDFIFO); |
209 | } | 257 | } |
210 | 258 | ||
211 | if (buf[0] != TPM_VL_VER) { | 259 | if (buf[0] != TPM_VL_VER) { |
@@ -220,7 +268,7 @@ recv_begin: | |||
220 | 268 | ||
221 | for (i = 0; i < size; i++) { | 269 | for (i = 0; i < size; i++) { |
222 | wait(chip, STAT_RDA); | 270 | wait(chip, STAT_RDA); |
223 | buf[i] = inb(chip->vendor.base + RDFIFO); | 271 | buf[i] = tpm_data_in(RDFIFO); |
224 | } | 272 | } |
225 | 273 | ||
226 | if ((size == 0x6D00) && (buf[1] == 0x80)) { | 274 | if ((size == 0x6D00) && (buf[1] == 0x80)) { |
@@ -269,7 +317,7 @@ static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count) | |||
269 | u8 count_high, count_low, count_4, count_3, count_2, count_1; | 317 | u8 count_high, count_low, count_4, count_3, count_2, count_1; |
270 | 318 | ||
271 | /* Disabling Reset, LP and IRQC */ | 319 | /* Disabling Reset, LP and IRQC */ |
272 | outb(RESET_LP_IRQC_DISABLE, chip->vendor.base + CMD); | 320 | tpm_data_out(RESET_LP_IRQC_DISABLE, CMD); |
273 | 321 | ||
274 | ret = empty_fifo(chip, 1); | 322 | ret = empty_fifo(chip, 1); |
275 | if (ret) { | 323 | if (ret) { |
@@ -320,7 +368,7 @@ static void tpm_inf_cancel(struct tpm_chip *chip) | |||
320 | 368 | ||
321 | static u8 tpm_inf_status(struct tpm_chip *chip) | 369 | static u8 tpm_inf_status(struct tpm_chip *chip) |
322 | { | 370 | { |
323 | return inb(chip->vendor.base + STAT); | 371 | return tpm_data_in(STAT); |
324 | } | 372 | } |
325 | 373 | ||
326 | static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); | 374 | static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); |
@@ -381,51 +429,88 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, | |||
381 | /* read IO-ports through PnP */ | 429 | /* read IO-ports through PnP */ |
382 | if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && | 430 | if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && |
383 | !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) { | 431 | !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) { |
384 | TPM_INF_ADDR = pnp_port_start(dev, 0); | 432 | |
385 | TPM_INF_ADDR_LEN = pnp_port_len(dev, 0); | 433 | tpm_dev.iotype = TPM_INF_IO_PORT; |
386 | TPM_INF_DATA = (TPM_INF_ADDR + 1); | 434 | |
387 | TPM_INF_BASE = pnp_port_start(dev, 1); | 435 | tpm_dev.config_port = pnp_port_start(dev, 0); |
388 | TPM_INF_PORT_LEN = pnp_port_len(dev, 1); | 436 | tpm_dev.config_size = pnp_port_len(dev, 0); |
389 | if ((TPM_INF_PORT_LEN < 4) || (TPM_INF_ADDR_LEN < 2)) { | 437 | tpm_dev.data_regs = pnp_port_start(dev, 1); |
438 | tpm_dev.data_size = pnp_port_len(dev, 1); | ||
439 | if ((tpm_dev.data_size < 4) || (tpm_dev.config_size < 2)) { | ||
390 | rc = -EINVAL; | 440 | rc = -EINVAL; |
391 | goto err_last; | 441 | goto err_last; |
392 | } | 442 | } |
393 | dev_info(&dev->dev, "Found %s with ID %s\n", | 443 | dev_info(&dev->dev, "Found %s with ID %s\n", |
394 | dev->name, dev_id->id); | 444 | dev->name, dev_id->id); |
395 | if (!((TPM_INF_BASE >> 8) & 0xff)) { | 445 | if (!((tpm_dev.data_regs >> 8) & 0xff)) { |
396 | rc = -EINVAL; | 446 | rc = -EINVAL; |
397 | goto err_last; | 447 | goto err_last; |
398 | } | 448 | } |
399 | /* publish my base address and request region */ | 449 | /* publish my base address and request region */ |
400 | if (request_region | 450 | if (request_region(tpm_dev.data_regs, tpm_dev.data_size, |
401 | (TPM_INF_BASE, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) { | 451 | "tpm_infineon0") == NULL) { |
402 | rc = -EINVAL; | 452 | rc = -EINVAL; |
403 | goto err_last; | 453 | goto err_last; |
404 | } | 454 | } |
405 | if (request_region | 455 | if (request_region(tpm_dev.config_port, tpm_dev.config_size, |
406 | (TPM_INF_ADDR, TPM_INF_ADDR_LEN, "tpm_infineon0") == NULL) { | 456 | "tpm_infineon0") == NULL) { |
457 | release_region(tpm_dev.data_regs, tpm_dev.data_size); | ||
407 | rc = -EINVAL; | 458 | rc = -EINVAL; |
408 | goto err_last; | 459 | goto err_last; |
409 | } | 460 | } |
461 | } else if (pnp_mem_valid(dev, 0) && | ||
462 | !(pnp_mem_flags(dev, 0) & IORESOURCE_DISABLED)) { | ||
463 | |||
464 | tpm_dev.iotype = TPM_INF_IO_MEM; | ||
465 | |||
466 | tpm_dev.map_base = pnp_mem_start(dev, 0); | ||
467 | tpm_dev.map_size = pnp_mem_len(dev, 0); | ||
468 | |||
469 | dev_info(&dev->dev, "Found %s with ID %s\n", | ||
470 | dev->name, dev_id->id); | ||
471 | |||
472 | /* publish my base address and request region */ | ||
473 | if (request_mem_region(tpm_dev.map_base, tpm_dev.map_size, | ||
474 | "tpm_infineon0") == NULL) { | ||
475 | rc = -EINVAL; | ||
476 | goto err_last; | ||
477 | } | ||
478 | |||
479 | tpm_dev.mem_base = ioremap(tpm_dev.map_base, tpm_dev.map_size); | ||
480 | if (tpm_dev.mem_base == NULL) { | ||
481 | release_mem_region(tpm_dev.map_base, tpm_dev.map_size); | ||
482 | rc = -EINVAL; | ||
483 | goto err_last; | ||
484 | } | ||
485 | |||
486 | /* | ||
487 | * The only known MMIO based Infineon TPM system provides | ||
488 | * a single large mem region with the device config | ||
489 | * registers at the default TPM_ADDR. The data registers | ||
490 | * seem like they could be placed anywhere within the MMIO | ||
491 | * region, but lets just put them at zero offset. | ||
492 | */ | ||
493 | tpm_dev.index_off = TPM_ADDR; | ||
494 | tpm_dev.data_regs = 0x0; | ||
410 | } else { | 495 | } else { |
411 | rc = -EINVAL; | 496 | rc = -EINVAL; |
412 | goto err_last; | 497 | goto err_last; |
413 | } | 498 | } |
414 | 499 | ||
415 | /* query chip for its vendor, its version number a.s.o. */ | 500 | /* query chip for its vendor, its version number a.s.o. */ |
416 | outb(ENABLE_REGISTER_PAIR, TPM_INF_ADDR); | 501 | tpm_config_out(ENABLE_REGISTER_PAIR, TPM_INF_ADDR); |
417 | outb(IDVENL, TPM_INF_ADDR); | 502 | tpm_config_out(IDVENL, TPM_INF_ADDR); |
418 | vendorid[1] = inb(TPM_INF_DATA); | 503 | vendorid[1] = tpm_config_in(TPM_INF_DATA); |
419 | outb(IDVENH, TPM_INF_ADDR); | 504 | tpm_config_out(IDVENH, TPM_INF_ADDR); |
420 | vendorid[0] = inb(TPM_INF_DATA); | 505 | vendorid[0] = tpm_config_in(TPM_INF_DATA); |
421 | outb(IDPDL, TPM_INF_ADDR); | 506 | tpm_config_out(IDPDL, TPM_INF_ADDR); |
422 | productid[1] = inb(TPM_INF_DATA); | 507 | productid[1] = tpm_config_in(TPM_INF_DATA); |
423 | outb(IDPDH, TPM_INF_ADDR); | 508 | tpm_config_out(IDPDH, TPM_INF_ADDR); |
424 | productid[0] = inb(TPM_INF_DATA); | 509 | productid[0] = tpm_config_in(TPM_INF_DATA); |
425 | outb(CHIP_ID1, TPM_INF_ADDR); | 510 | tpm_config_out(CHIP_ID1, TPM_INF_ADDR); |
426 | version[1] = inb(TPM_INF_DATA); | 511 | version[1] = tpm_config_in(TPM_INF_DATA); |
427 | outb(CHIP_ID2, TPM_INF_ADDR); | 512 | tpm_config_out(CHIP_ID2, TPM_INF_ADDR); |
428 | version[0] = inb(TPM_INF_DATA); | 513 | version[0] = tpm_config_in(TPM_INF_DATA); |
429 | 514 | ||
430 | switch ((productid[0] << 8) | productid[1]) { | 515 | switch ((productid[0] << 8) | productid[1]) { |
431 | case 6: | 516 | case 6: |
@@ -442,51 +527,54 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, | |||
442 | if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) { | 527 | if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) { |
443 | 528 | ||
444 | /* configure TPM with IO-ports */ | 529 | /* configure TPM with IO-ports */ |
445 | outb(IOLIMH, TPM_INF_ADDR); | 530 | tpm_config_out(IOLIMH, TPM_INF_ADDR); |
446 | outb(((TPM_INF_BASE >> 8) & 0xff), TPM_INF_DATA); | 531 | tpm_config_out((tpm_dev.data_regs >> 8) & 0xff, TPM_INF_DATA); |
447 | outb(IOLIML, TPM_INF_ADDR); | 532 | tpm_config_out(IOLIML, TPM_INF_ADDR); |
448 | outb((TPM_INF_BASE & 0xff), TPM_INF_DATA); | 533 | tpm_config_out((tpm_dev.data_regs & 0xff), TPM_INF_DATA); |
449 | 534 | ||
450 | /* control if IO-ports are set correctly */ | 535 | /* control if IO-ports are set correctly */ |
451 | outb(IOLIMH, TPM_INF_ADDR); | 536 | tpm_config_out(IOLIMH, TPM_INF_ADDR); |
452 | ioh = inb(TPM_INF_DATA); | 537 | ioh = tpm_config_in(TPM_INF_DATA); |
453 | outb(IOLIML, TPM_INF_ADDR); | 538 | tpm_config_out(IOLIML, TPM_INF_ADDR); |
454 | iol = inb(TPM_INF_DATA); | 539 | iol = tpm_config_in(TPM_INF_DATA); |
455 | 540 | ||
456 | if ((ioh << 8 | iol) != TPM_INF_BASE) { | 541 | if ((ioh << 8 | iol) != tpm_dev.data_regs) { |
457 | dev_err(&dev->dev, | 542 | dev_err(&dev->dev, |
458 | "Could not set IO-ports to 0x%x\n", | 543 | "Could not set IO-data registers to 0x%x\n", |
459 | TPM_INF_BASE); | 544 | tpm_dev.data_regs); |
460 | rc = -EIO; | 545 | rc = -EIO; |
461 | goto err_release_region; | 546 | goto err_release_region; |
462 | } | 547 | } |
463 | 548 | ||
464 | /* activate register */ | 549 | /* activate register */ |
465 | outb(TPM_DAR, TPM_INF_ADDR); | 550 | tpm_config_out(TPM_DAR, TPM_INF_ADDR); |
466 | outb(0x01, TPM_INF_DATA); | 551 | tpm_config_out(0x01, TPM_INF_DATA); |
467 | outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR); | 552 | tpm_config_out(DISABLE_REGISTER_PAIR, TPM_INF_ADDR); |
468 | 553 | ||
469 | /* disable RESET, LP and IRQC */ | 554 | /* disable RESET, LP and IRQC */ |
470 | outb(RESET_LP_IRQC_DISABLE, TPM_INF_BASE + CMD); | 555 | tpm_data_out(RESET_LP_IRQC_DISABLE, CMD); |
471 | 556 | ||
472 | /* Finally, we're done, print some infos */ | 557 | /* Finally, we're done, print some infos */ |
473 | dev_info(&dev->dev, "TPM found: " | 558 | dev_info(&dev->dev, "TPM found: " |
474 | "config base 0x%x, " | 559 | "config base 0x%lx, " |
475 | "io base 0x%x, " | 560 | "data base 0x%lx, " |
476 | "chip version 0x%02x%02x, " | 561 | "chip version 0x%02x%02x, " |
477 | "vendor id 0x%x%x (Infineon), " | 562 | "vendor id 0x%x%x (Infineon), " |
478 | "product id 0x%02x%02x" | 563 | "product id 0x%02x%02x" |
479 | "%s\n", | 564 | "%s\n", |
480 | TPM_INF_ADDR, | 565 | tpm_dev.iotype == TPM_INF_IO_PORT ? |
481 | TPM_INF_BASE, | 566 | tpm_dev.config_port : |
567 | tpm_dev.map_base + tpm_dev.index_off, | ||
568 | tpm_dev.iotype == TPM_INF_IO_PORT ? | ||
569 | tpm_dev.data_regs : | ||
570 | tpm_dev.map_base + tpm_dev.data_regs, | ||
482 | version[0], version[1], | 571 | version[0], version[1], |
483 | vendorid[0], vendorid[1], | 572 | vendorid[0], vendorid[1], |
484 | productid[0], productid[1], chipname); | 573 | productid[0], productid[1], chipname); |
485 | 574 | ||
486 | if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf))) { | 575 | if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf))) |
487 | goto err_release_region; | 576 | goto err_release_region; |
488 | } | 577 | |
489 | chip->vendor.base = TPM_INF_BASE; | ||
490 | return 0; | 578 | return 0; |
491 | } else { | 579 | } else { |
492 | rc = -ENODEV; | 580 | rc = -ENODEV; |
@@ -494,8 +582,13 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, | |||
494 | } | 582 | } |
495 | 583 | ||
496 | err_release_region: | 584 | err_release_region: |
497 | release_region(TPM_INF_BASE, TPM_INF_PORT_LEN); | 585 | if (tpm_dev.iotype == TPM_INF_IO_PORT) { |
498 | release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN); | 586 | release_region(tpm_dev.data_regs, tpm_dev.data_size); |
587 | release_region(tpm_dev.config_port, tpm_dev.config_size); | ||
588 | } else { | ||
589 | iounmap(tpm_dev.mem_base); | ||
590 | release_mem_region(tpm_dev.map_base, tpm_dev.map_size); | ||
591 | } | ||
499 | 592 | ||
500 | err_last: | 593 | err_last: |
501 | return rc; | 594 | return rc; |
@@ -506,8 +599,14 @@ static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev) | |||
506 | struct tpm_chip *chip = pnp_get_drvdata(dev); | 599 | struct tpm_chip *chip = pnp_get_drvdata(dev); |
507 | 600 | ||
508 | if (chip) { | 601 | if (chip) { |
509 | release_region(TPM_INF_BASE, TPM_INF_PORT_LEN); | 602 | if (tpm_dev.iotype == TPM_INF_IO_PORT) { |
510 | release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN); | 603 | release_region(tpm_dev.data_regs, tpm_dev.data_size); |
604 | release_region(tpm_dev.config_port, | ||
605 | tpm_dev.config_size); | ||
606 | } else { | ||
607 | iounmap(tpm_dev.mem_base); | ||
608 | release_mem_region(tpm_dev.map_base, tpm_dev.map_size); | ||
609 | } | ||
511 | tpm_remove_hardware(chip->dev); | 610 | tpm_remove_hardware(chip->dev); |
512 | } | 611 | } |
513 | } | 612 | } |
@@ -539,5 +638,5 @@ module_exit(cleanup_inf); | |||
539 | 638 | ||
540 | MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>"); | 639 | MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>"); |
541 | MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2"); | 640 | MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2"); |
542 | MODULE_VERSION("1.8"); | 641 | MODULE_VERSION("1.9"); |
543 | MODULE_LICENSE("GPL"); | 642 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 7a32df594907..fe62c2170d01 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -141,8 +141,6 @@ static DECLARE_MUTEX(allocated_ptys_lock); | |||
141 | static int ptmx_open(struct inode *, struct file *); | 141 | static int ptmx_open(struct inode *, struct file *); |
142 | #endif | 142 | #endif |
143 | 143 | ||
144 | extern void disable_early_printk(void); | ||
145 | |||
146 | static void initialize_tty_struct(struct tty_struct *tty); | 144 | static void initialize_tty_struct(struct tty_struct *tty); |
147 | 145 | ||
148 | static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *); | 146 | static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *); |
@@ -153,10 +151,16 @@ static int tty_open(struct inode *, struct file *); | |||
153 | static int tty_release(struct inode *, struct file *); | 151 | static int tty_release(struct inode *, struct file *); |
154 | int tty_ioctl(struct inode * inode, struct file * file, | 152 | int tty_ioctl(struct inode * inode, struct file * file, |
155 | unsigned int cmd, unsigned long arg); | 153 | unsigned int cmd, unsigned long arg); |
154 | #ifdef CONFIG_COMPAT | ||
155 | static long tty_compat_ioctl(struct file * file, unsigned int cmd, | ||
156 | unsigned long arg); | ||
157 | #else | ||
158 | #define tty_compat_ioctl NULL | ||
159 | #endif | ||
156 | static int tty_fasync(int fd, struct file * filp, int on); | 160 | static int tty_fasync(int fd, struct file * filp, int on); |
157 | static void release_tty(struct tty_struct *tty, int idx); | 161 | static void release_tty(struct tty_struct *tty, int idx); |
158 | static struct pid *__proc_set_tty(struct task_struct *tsk, | 162 | static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty); |
159 | struct tty_struct *tty); | 163 | static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty); |
160 | 164 | ||
161 | /** | 165 | /** |
162 | * alloc_tty_struct - allocate a tty object | 166 | * alloc_tty_struct - allocate a tty object |
@@ -936,13 +940,6 @@ restart: | |||
936 | return -EINVAL; | 940 | return -EINVAL; |
937 | 941 | ||
938 | /* | 942 | /* |
939 | * No more input please, we are switching. The new ldisc | ||
940 | * will update this value in the ldisc open function | ||
941 | */ | ||
942 | |||
943 | tty->receive_room = 0; | ||
944 | |||
945 | /* | ||
946 | * Problem: What do we do if this blocks ? | 943 | * Problem: What do we do if this blocks ? |
947 | */ | 944 | */ |
948 | 945 | ||
@@ -953,6 +950,13 @@ restart: | |||
953 | return 0; | 950 | return 0; |
954 | } | 951 | } |
955 | 952 | ||
953 | /* | ||
954 | * No more input please, we are switching. The new ldisc | ||
955 | * will update this value in the ldisc open function | ||
956 | */ | ||
957 | |||
958 | tty->receive_room = 0; | ||
959 | |||
956 | o_ldisc = tty->ldisc; | 960 | o_ldisc = tty->ldisc; |
957 | o_tty = tty->link; | 961 | o_tty = tty->link; |
958 | 962 | ||
@@ -1145,8 +1149,8 @@ static unsigned int hung_up_tty_poll(struct file * filp, poll_table * wait) | |||
1145 | return POLLIN | POLLOUT | POLLERR | POLLHUP | POLLRDNORM | POLLWRNORM; | 1149 | return POLLIN | POLLOUT | POLLERR | POLLHUP | POLLRDNORM | POLLWRNORM; |
1146 | } | 1150 | } |
1147 | 1151 | ||
1148 | static int hung_up_tty_ioctl(struct inode * inode, struct file * file, | 1152 | static long hung_up_tty_ioctl(struct file * file, |
1149 | unsigned int cmd, unsigned long arg) | 1153 | unsigned int cmd, unsigned long arg) |
1150 | { | 1154 | { |
1151 | return cmd == TIOCSPGRP ? -ENOTTY : -EIO; | 1155 | return cmd == TIOCSPGRP ? -ENOTTY : -EIO; |
1152 | } | 1156 | } |
@@ -1157,6 +1161,7 @@ static const struct file_operations tty_fops = { | |||
1157 | .write = tty_write, | 1161 | .write = tty_write, |
1158 | .poll = tty_poll, | 1162 | .poll = tty_poll, |
1159 | .ioctl = tty_ioctl, | 1163 | .ioctl = tty_ioctl, |
1164 | .compat_ioctl = tty_compat_ioctl, | ||
1160 | .open = tty_open, | 1165 | .open = tty_open, |
1161 | .release = tty_release, | 1166 | .release = tty_release, |
1162 | .fasync = tty_fasync, | 1167 | .fasync = tty_fasync, |
@@ -1169,6 +1174,7 @@ static const struct file_operations ptmx_fops = { | |||
1169 | .write = tty_write, | 1174 | .write = tty_write, |
1170 | .poll = tty_poll, | 1175 | .poll = tty_poll, |
1171 | .ioctl = tty_ioctl, | 1176 | .ioctl = tty_ioctl, |
1177 | .compat_ioctl = tty_compat_ioctl, | ||
1172 | .open = ptmx_open, | 1178 | .open = ptmx_open, |
1173 | .release = tty_release, | 1179 | .release = tty_release, |
1174 | .fasync = tty_fasync, | 1180 | .fasync = tty_fasync, |
@@ -1181,6 +1187,7 @@ static const struct file_operations console_fops = { | |||
1181 | .write = redirected_tty_write, | 1187 | .write = redirected_tty_write, |
1182 | .poll = tty_poll, | 1188 | .poll = tty_poll, |
1183 | .ioctl = tty_ioctl, | 1189 | .ioctl = tty_ioctl, |
1190 | .compat_ioctl = tty_compat_ioctl, | ||
1184 | .open = tty_open, | 1191 | .open = tty_open, |
1185 | .release = tty_release, | 1192 | .release = tty_release, |
1186 | .fasync = tty_fasync, | 1193 | .fasync = tty_fasync, |
@@ -1191,7 +1198,8 @@ static const struct file_operations hung_up_tty_fops = { | |||
1191 | .read = hung_up_tty_read, | 1198 | .read = hung_up_tty_read, |
1192 | .write = hung_up_tty_write, | 1199 | .write = hung_up_tty_write, |
1193 | .poll = hung_up_tty_poll, | 1200 | .poll = hung_up_tty_poll, |
1194 | .ioctl = hung_up_tty_ioctl, | 1201 | .unlocked_ioctl = hung_up_tty_ioctl, |
1202 | .compat_ioctl = hung_up_tty_ioctl, | ||
1195 | .release = tty_release, | 1203 | .release = tty_release, |
1196 | }; | 1204 | }; |
1197 | 1205 | ||
@@ -1534,10 +1542,9 @@ void disassociate_ctty(int on_exit) | |||
1534 | } | 1542 | } |
1535 | 1543 | ||
1536 | spin_lock_irq(¤t->sighand->siglock); | 1544 | spin_lock_irq(¤t->sighand->siglock); |
1537 | tty_pgrp = current->signal->tty_old_pgrp; | 1545 | put_pid(current->signal->tty_old_pgrp); |
1538 | current->signal->tty_old_pgrp = NULL; | 1546 | current->signal->tty_old_pgrp = NULL; |
1539 | spin_unlock_irq(¤t->sighand->siglock); | 1547 | spin_unlock_irq(¤t->sighand->siglock); |
1540 | put_pid(tty_pgrp); | ||
1541 | 1548 | ||
1542 | mutex_lock(&tty_mutex); | 1549 | mutex_lock(&tty_mutex); |
1543 | /* It is possible that do_tty_hangup has free'd this tty */ | 1550 | /* It is possible that do_tty_hangup has free'd this tty */ |
@@ -1562,13 +1569,25 @@ void disassociate_ctty(int on_exit) | |||
1562 | unlock_kernel(); | 1569 | unlock_kernel(); |
1563 | } | 1570 | } |
1564 | 1571 | ||
1572 | /** | ||
1573 | * | ||
1574 | * no_tty - Ensure the current process does not have a controlling tty | ||
1575 | */ | ||
1576 | void no_tty(void) | ||
1577 | { | ||
1578 | struct task_struct *tsk = current; | ||
1579 | if (tsk->signal->leader) | ||
1580 | disassociate_ctty(0); | ||
1581 | proc_clear_tty(tsk); | ||
1582 | } | ||
1583 | |||
1565 | 1584 | ||
1566 | /** | 1585 | /** |
1567 | * stop_tty - propogate flow control | 1586 | * stop_tty - propagate flow control |
1568 | * @tty: tty to stop | 1587 | * @tty: tty to stop |
1569 | * | 1588 | * |
1570 | * Perform flow control to the driver. For PTY/TTY pairs we | 1589 | * Perform flow control to the driver. For PTY/TTY pairs we |
1571 | * must also propogate the TIOCKPKT status. May be called | 1590 | * must also propagate the TIOCKPKT status. May be called |
1572 | * on an already stopped device and will not re-call the driver | 1591 | * on an already stopped device and will not re-call the driver |
1573 | * method. | 1592 | * method. |
1574 | * | 1593 | * |
@@ -1598,11 +1617,11 @@ void stop_tty(struct tty_struct *tty) | |||
1598 | EXPORT_SYMBOL(stop_tty); | 1617 | EXPORT_SYMBOL(stop_tty); |
1599 | 1618 | ||
1600 | /** | 1619 | /** |
1601 | * start_tty - propogate flow control | 1620 | * start_tty - propagate flow control |
1602 | * @tty: tty to start | 1621 | * @tty: tty to start |
1603 | * | 1622 | * |
1604 | * Start a tty that has been stopped if at all possible. Perform | 1623 | * Start a tty that has been stopped if at all possible. Perform |
1605 | * any neccessary wakeups and propogate the TIOCPKT status. If this | 1624 | * any neccessary wakeups and propagate the TIOCPKT status. If this |
1606 | * is the tty was previous stopped and is being started then the | 1625 | * is the tty was previous stopped and is being started then the |
1607 | * driver start method is invoked and the line discipline woken. | 1626 | * driver start method is invoked and the line discipline woken. |
1608 | * | 1627 | * |
@@ -2508,7 +2527,6 @@ static int tty_open(struct inode * inode, struct file * filp) | |||
2508 | int index; | 2527 | int index; |
2509 | dev_t device = inode->i_rdev; | 2528 | dev_t device = inode->i_rdev; |
2510 | unsigned short saved_flags = filp->f_flags; | 2529 | unsigned short saved_flags = filp->f_flags; |
2511 | struct pid *old_pgrp; | ||
2512 | 2530 | ||
2513 | nonseekable_open(inode, filp); | 2531 | nonseekable_open(inode, filp); |
2514 | 2532 | ||
@@ -2602,17 +2620,15 @@ got_driver: | |||
2602 | goto retry_open; | 2620 | goto retry_open; |
2603 | } | 2621 | } |
2604 | 2622 | ||
2605 | old_pgrp = NULL; | ||
2606 | mutex_lock(&tty_mutex); | 2623 | mutex_lock(&tty_mutex); |
2607 | spin_lock_irq(¤t->sighand->siglock); | 2624 | spin_lock_irq(¤t->sighand->siglock); |
2608 | if (!noctty && | 2625 | if (!noctty && |
2609 | current->signal->leader && | 2626 | current->signal->leader && |
2610 | !current->signal->tty && | 2627 | !current->signal->tty && |
2611 | tty->session == NULL) | 2628 | tty->session == NULL) |
2612 | old_pgrp = __proc_set_tty(current, tty); | 2629 | __proc_set_tty(current, tty); |
2613 | spin_unlock_irq(¤t->sighand->siglock); | 2630 | spin_unlock_irq(¤t->sighand->siglock); |
2614 | mutex_unlock(&tty_mutex); | 2631 | mutex_unlock(&tty_mutex); |
2615 | put_pid(old_pgrp); | ||
2616 | return 0; | 2632 | return 0; |
2617 | } | 2633 | } |
2618 | 2634 | ||
@@ -3287,9 +3303,7 @@ int tty_ioctl(struct inode * inode, struct file * file, | |||
3287 | case TIOCNOTTY: | 3303 | case TIOCNOTTY: |
3288 | if (current->signal->tty != tty) | 3304 | if (current->signal->tty != tty) |
3289 | return -ENOTTY; | 3305 | return -ENOTTY; |
3290 | if (current->signal->leader) | 3306 | no_tty(); |
3291 | disassociate_ctty(0); | ||
3292 | proc_clear_tty(current); | ||
3293 | return 0; | 3307 | return 0; |
3294 | case TIOCSCTTY: | 3308 | case TIOCSCTTY: |
3295 | return tiocsctty(tty, arg); | 3309 | return tiocsctty(tty, arg); |
@@ -3353,6 +3367,32 @@ int tty_ioctl(struct inode * inode, struct file * file, | |||
3353 | return retval; | 3367 | return retval; |
3354 | } | 3368 | } |
3355 | 3369 | ||
3370 | #ifdef CONFIG_COMPAT | ||
3371 | static long tty_compat_ioctl(struct file * file, unsigned int cmd, | ||
3372 | unsigned long arg) | ||
3373 | { | ||
3374 | struct inode *inode = file->f_dentry->d_inode; | ||
3375 | struct tty_struct *tty = file->private_data; | ||
3376 | struct tty_ldisc *ld; | ||
3377 | int retval = -ENOIOCTLCMD; | ||
3378 | |||
3379 | if (tty_paranoia_check(tty, inode, "tty_ioctl")) | ||
3380 | return -EINVAL; | ||
3381 | |||
3382 | if (tty->driver->compat_ioctl) { | ||
3383 | retval = (tty->driver->compat_ioctl)(tty, file, cmd, arg); | ||
3384 | if (retval != -ENOIOCTLCMD) | ||
3385 | return retval; | ||
3386 | } | ||
3387 | |||
3388 | ld = tty_ldisc_ref_wait(tty); | ||
3389 | if (ld->compat_ioctl) | ||
3390 | retval = ld->compat_ioctl(tty, file, cmd, arg); | ||
3391 | tty_ldisc_deref(ld); | ||
3392 | |||
3393 | return retval; | ||
3394 | } | ||
3395 | #endif | ||
3356 | 3396 | ||
3357 | /* | 3397 | /* |
3358 | * This implements the "Secure Attention Key" --- the idea is to | 3398 | * This implements the "Secure Attention Key" --- the idea is to |
@@ -3685,6 +3725,7 @@ void tty_set_operations(struct tty_driver *driver, | |||
3685 | driver->write_room = op->write_room; | 3725 | driver->write_room = op->write_room; |
3686 | driver->chars_in_buffer = op->chars_in_buffer; | 3726 | driver->chars_in_buffer = op->chars_in_buffer; |
3687 | driver->ioctl = op->ioctl; | 3727 | driver->ioctl = op->ioctl; |
3728 | driver->compat_ioctl = op->compat_ioctl; | ||
3688 | driver->set_termios = op->set_termios; | 3729 | driver->set_termios = op->set_termios; |
3689 | driver->throttle = op->throttle; | 3730 | driver->throttle = op->throttle; |
3690 | driver->unthrottle = op->unthrottle; | 3731 | driver->unthrottle = op->unthrottle; |
@@ -3720,11 +3761,10 @@ int tty_register_driver(struct tty_driver *driver) | |||
3720 | if (driver->flags & TTY_DRIVER_INSTALLED) | 3761 | if (driver->flags & TTY_DRIVER_INSTALLED) |
3721 | return 0; | 3762 | return 0; |
3722 | 3763 | ||
3723 | if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM)) { | 3764 | if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) { |
3724 | p = kmalloc(driver->num * 3 * sizeof(void *), GFP_KERNEL); | 3765 | p = kzalloc(driver->num * 3 * sizeof(void *), GFP_KERNEL); |
3725 | if (!p) | 3766 | if (!p) |
3726 | return -ENOMEM; | 3767 | return -ENOMEM; |
3727 | memset(p, 0, driver->num * 3 * sizeof(void *)); | ||
3728 | } | 3768 | } |
3729 | 3769 | ||
3730 | if (!driver->major) { | 3770 | if (!driver->major) { |
@@ -3767,7 +3807,9 @@ int tty_register_driver(struct tty_driver *driver) | |||
3767 | if (!driver->put_char) | 3807 | if (!driver->put_char) |
3768 | driver->put_char = tty_default_put_char; | 3808 | driver->put_char = tty_default_put_char; |
3769 | 3809 | ||
3810 | mutex_lock(&tty_mutex); | ||
3770 | list_add(&driver->tty_drivers, &tty_drivers); | 3811 | list_add(&driver->tty_drivers, &tty_drivers); |
3812 | mutex_unlock(&tty_mutex); | ||
3771 | 3813 | ||
3772 | if ( !(driver->flags & TTY_DRIVER_DYNAMIC_DEV) ) { | 3814 | if ( !(driver->flags & TTY_DRIVER_DYNAMIC_DEV) ) { |
3773 | for(i = 0; i < driver->num; i++) | 3815 | for(i = 0; i < driver->num; i++) |
@@ -3793,8 +3835,9 @@ int tty_unregister_driver(struct tty_driver *driver) | |||
3793 | 3835 | ||
3794 | unregister_chrdev_region(MKDEV(driver->major, driver->minor_start), | 3836 | unregister_chrdev_region(MKDEV(driver->major, driver->minor_start), |
3795 | driver->num); | 3837 | driver->num); |
3796 | 3838 | mutex_lock(&tty_mutex); | |
3797 | list_del(&driver->tty_drivers); | 3839 | list_del(&driver->tty_drivers); |
3840 | mutex_unlock(&tty_mutex); | ||
3798 | 3841 | ||
3799 | /* | 3842 | /* |
3800 | * Free the termios and termios_locked structures because | 3843 | * Free the termios and termios_locked structures because |
@@ -3837,11 +3880,9 @@ void proc_clear_tty(struct task_struct *p) | |||
3837 | p->signal->tty = NULL; | 3880 | p->signal->tty = NULL; |
3838 | spin_unlock_irq(&p->sighand->siglock); | 3881 | spin_unlock_irq(&p->sighand->siglock); |
3839 | } | 3882 | } |
3840 | EXPORT_SYMBOL(proc_clear_tty); | ||
3841 | 3883 | ||
3842 | static struct pid *__proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) | 3884 | static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) |
3843 | { | 3885 | { |
3844 | struct pid *old_pgrp; | ||
3845 | if (tty) { | 3886 | if (tty) { |
3846 | /* We should not have a session or pgrp to here but.... */ | 3887 | /* We should not have a session or pgrp to here but.... */ |
3847 | put_pid(tty->session); | 3888 | put_pid(tty->session); |
@@ -3849,21 +3890,16 @@ static struct pid *__proc_set_tty(struct task_struct *tsk, struct tty_struct *tt | |||
3849 | tty->session = get_pid(task_session(tsk)); | 3890 | tty->session = get_pid(task_session(tsk)); |
3850 | tty->pgrp = get_pid(task_pgrp(tsk)); | 3891 | tty->pgrp = get_pid(task_pgrp(tsk)); |
3851 | } | 3892 | } |
3852 | old_pgrp = tsk->signal->tty_old_pgrp; | 3893 | put_pid(tsk->signal->tty_old_pgrp); |
3853 | tsk->signal->tty = tty; | 3894 | tsk->signal->tty = tty; |
3854 | tsk->signal->tty_old_pgrp = NULL; | 3895 | tsk->signal->tty_old_pgrp = NULL; |
3855 | return old_pgrp; | ||
3856 | } | 3896 | } |
3857 | 3897 | ||
3858 | void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) | 3898 | static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) |
3859 | { | 3899 | { |
3860 | struct pid *old_pgrp; | ||
3861 | |||
3862 | spin_lock_irq(&tsk->sighand->siglock); | 3900 | spin_lock_irq(&tsk->sighand->siglock); |
3863 | old_pgrp = __proc_set_tty(tsk, tty); | 3901 | __proc_set_tty(tsk, tty); |
3864 | spin_unlock_irq(&tsk->sighand->siglock); | 3902 | spin_unlock_irq(&tsk->sighand->siglock); |
3865 | |||
3866 | put_pid(old_pgrp); | ||
3867 | } | 3903 | } |
3868 | 3904 | ||
3869 | struct tty_struct *get_current_tty(void) | 3905 | struct tty_struct *get_current_tty(void) |
@@ -3898,9 +3934,6 @@ void __init console_init(void) | |||
3898 | * set up the console device so that later boot sequences can | 3934 | * set up the console device so that later boot sequences can |
3899 | * inform about problems etc.. | 3935 | * inform about problems etc.. |
3900 | */ | 3936 | */ |
3901 | #ifdef CONFIG_EARLY_PRINTK | ||
3902 | disable_early_printk(); | ||
3903 | #endif | ||
3904 | call = __con_initcall_start; | 3937 | call = __con_initcall_start; |
3905 | while (call < __con_initcall_end) { | 3938 | while (call < __con_initcall_end) { |
3906 | (*call)(); | 3939 | (*call)(); |
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c index 791930320a13..83aeedda200c 100644 --- a/drivers/char/vc_screen.c +++ b/drivers/char/vc_screen.c | |||
@@ -28,12 +28,13 @@ | |||
28 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
29 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <linux/mutex.h> | ||
31 | #include <linux/vt_kern.h> | 32 | #include <linux/vt_kern.h> |
32 | #include <linux/selection.h> | 33 | #include <linux/selection.h> |
33 | #include <linux/kbd_kern.h> | 34 | #include <linux/kbd_kern.h> |
34 | #include <linux/console.h> | 35 | #include <linux/console.h> |
35 | #include <linux/smp_lock.h> | ||
36 | #include <linux/device.h> | 36 | #include <linux/device.h> |
37 | |||
37 | #include <asm/uaccess.h> | 38 | #include <asm/uaccess.h> |
38 | #include <asm/byteorder.h> | 39 | #include <asm/byteorder.h> |
39 | #include <asm/unaligned.h> | 40 | #include <asm/unaligned.h> |
@@ -70,11 +71,11 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig) | |||
70 | { | 71 | { |
71 | int size; | 72 | int size; |
72 | 73 | ||
73 | down(&con_buf_sem); | 74 | mutex_lock(&con_buf_mtx); |
74 | size = vcs_size(file->f_path.dentry->d_inode); | 75 | size = vcs_size(file->f_path.dentry->d_inode); |
75 | switch (orig) { | 76 | switch (orig) { |
76 | default: | 77 | default: |
77 | up(&con_buf_sem); | 78 | mutex_unlock(&con_buf_mtx); |
78 | return -EINVAL; | 79 | return -EINVAL; |
79 | case 2: | 80 | case 2: |
80 | offset += size; | 81 | offset += size; |
@@ -85,11 +86,11 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig) | |||
85 | break; | 86 | break; |
86 | } | 87 | } |
87 | if (offset < 0 || offset > size) { | 88 | if (offset < 0 || offset > size) { |
88 | up(&con_buf_sem); | 89 | mutex_unlock(&con_buf_mtx); |
89 | return -EINVAL; | 90 | return -EINVAL; |
90 | } | 91 | } |
91 | file->f_pos = offset; | 92 | file->f_pos = offset; |
92 | up(&con_buf_sem); | 93 | mutex_unlock(&con_buf_mtx); |
93 | return file->f_pos; | 94 | return file->f_pos; |
94 | } | 95 | } |
95 | 96 | ||
@@ -106,7 +107,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
106 | unsigned short *org = NULL; | 107 | unsigned short *org = NULL; |
107 | ssize_t ret; | 108 | ssize_t ret; |
108 | 109 | ||
109 | down(&con_buf_sem); | 110 | mutex_lock(&con_buf_mtx); |
110 | 111 | ||
111 | pos = *ppos; | 112 | pos = *ppos; |
112 | 113 | ||
@@ -263,7 +264,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
263 | ret = read; | 264 | ret = read; |
264 | unlock_out: | 265 | unlock_out: |
265 | release_console_sem(); | 266 | release_console_sem(); |
266 | up(&con_buf_sem); | 267 | mutex_unlock(&con_buf_mtx); |
267 | return ret; | 268 | return ret; |
268 | } | 269 | } |
269 | 270 | ||
@@ -280,7 +281,7 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | |||
280 | u16 *org0 = NULL, *org = NULL; | 281 | u16 *org0 = NULL, *org = NULL; |
281 | size_t ret; | 282 | size_t ret; |
282 | 283 | ||
283 | down(&con_buf_sem); | 284 | mutex_lock(&con_buf_mtx); |
284 | 285 | ||
285 | pos = *ppos; | 286 | pos = *ppos; |
286 | 287 | ||
@@ -450,7 +451,7 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | |||
450 | unlock_out: | 451 | unlock_out: |
451 | release_console_sem(); | 452 | release_console_sem(); |
452 | 453 | ||
453 | up(&con_buf_sem); | 454 | mutex_unlock(&con_buf_mtx); |
454 | 455 | ||
455 | return ret; | 456 | return ret; |
456 | } | 457 | } |
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 1bbb45b937fd..bbd9fc412877 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -86,6 +86,7 @@ | |||
86 | #include <linux/mm.h> | 86 | #include <linux/mm.h> |
87 | #include <linux/console.h> | 87 | #include <linux/console.h> |
88 | #include <linux/init.h> | 88 | #include <linux/init.h> |
89 | #include <linux/mutex.h> | ||
89 | #include <linux/vt_kern.h> | 90 | #include <linux/vt_kern.h> |
90 | #include <linux/selection.h> | 91 | #include <linux/selection.h> |
91 | #include <linux/tiocl.h> | 92 | #include <linux/tiocl.h> |
@@ -157,6 +158,8 @@ static void blank_screen_t(unsigned long dummy); | |||
157 | static void set_palette(struct vc_data *vc); | 158 | static void set_palette(struct vc_data *vc); |
158 | 159 | ||
159 | static int printable; /* Is console ready for printing? */ | 160 | static int printable; /* Is console ready for printing? */ |
161 | static int default_utf8; | ||
162 | module_param(default_utf8, int, S_IRUGO | S_IWUSR); | ||
160 | 163 | ||
161 | /* | 164 | /* |
162 | * ignore_poke: don't unblank the screen when things are typed. This is | 165 | * ignore_poke: don't unblank the screen when things are typed. This is |
@@ -348,10 +351,12 @@ void update_region(struct vc_data *vc, unsigned long start, int count) | |||
348 | 351 | ||
349 | /* Structure of attributes is hardware-dependent */ | 352 | /* Structure of attributes is hardware-dependent */ |
350 | 353 | ||
351 | static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink, u8 _underline, u8 _reverse) | 354 | static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink, |
355 | u8 _underline, u8 _reverse, u8 _italic) | ||
352 | { | 356 | { |
353 | if (vc->vc_sw->con_build_attr) | 357 | if (vc->vc_sw->con_build_attr) |
354 | return vc->vc_sw->con_build_attr(vc, _color, _intensity, _blink, _underline, _reverse); | 358 | return vc->vc_sw->con_build_attr(vc, _color, _intensity, |
359 | _blink, _underline, _reverse, _italic); | ||
355 | 360 | ||
356 | #ifndef VT_BUF_VRAM_ONLY | 361 | #ifndef VT_BUF_VRAM_ONLY |
357 | /* | 362 | /* |
@@ -368,10 +373,13 @@ static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink, u8 | |||
368 | u8 a = vc->vc_color; | 373 | u8 a = vc->vc_color; |
369 | if (!vc->vc_can_do_color) | 374 | if (!vc->vc_can_do_color) |
370 | return _intensity | | 375 | return _intensity | |
376 | (_italic ? 2 : 0) | | ||
371 | (_underline ? 4 : 0) | | 377 | (_underline ? 4 : 0) | |
372 | (_reverse ? 8 : 0) | | 378 | (_reverse ? 8 : 0) | |
373 | (_blink ? 0x80 : 0); | 379 | (_blink ? 0x80 : 0); |
374 | if (_underline) | 380 | if (_italic) |
381 | a = (a & 0xF0) | vc->vc_itcolor; | ||
382 | else if (_underline) | ||
375 | a = (a & 0xf0) | vc->vc_ulcolor; | 383 | a = (a & 0xf0) | vc->vc_ulcolor; |
376 | else if (_intensity == 0) | 384 | else if (_intensity == 0) |
377 | a = (a & 0xf0) | vc->vc_ulcolor; | 385 | a = (a & 0xf0) | vc->vc_ulcolor; |
@@ -392,8 +400,10 @@ static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink, u8 | |||
392 | 400 | ||
393 | static void update_attr(struct vc_data *vc) | 401 | static void update_attr(struct vc_data *vc) |
394 | { | 402 | { |
395 | vc->vc_attr = build_attr(vc, vc->vc_color, vc->vc_intensity, vc->vc_blink, vc->vc_underline, vc->vc_reverse ^ vc->vc_decscnm); | 403 | vc->vc_attr = build_attr(vc, vc->vc_color, vc->vc_intensity, |
396 | vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1, vc->vc_blink, 0, vc->vc_decscnm) << 8) | ' '; | 404 | vc->vc_blink, vc->vc_underline, |
405 | vc->vc_reverse ^ vc->vc_decscnm, vc->vc_italic); | ||
406 | vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1, vc->vc_blink, 0, vc->vc_decscnm, 0) << 8) | ' '; | ||
397 | } | 407 | } |
398 | 408 | ||
399 | /* Note: inverting the screen twice should revert to the original state */ | 409 | /* Note: inverting the screen twice should revert to the original state */ |
@@ -934,6 +944,10 @@ int default_grn[] = {0x00,0x00,0xaa,0x55,0x00,0x00,0xaa,0xaa, | |||
934 | int default_blu[] = {0x00,0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa, | 944 | int default_blu[] = {0x00,0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa, |
935 | 0x55,0x55,0x55,0x55,0xff,0xff,0xff,0xff}; | 945 | 0x55,0x55,0x55,0x55,0xff,0xff,0xff,0xff}; |
936 | 946 | ||
947 | module_param_array(default_red, int, NULL, S_IRUGO | S_IWUSR); | ||
948 | module_param_array(default_grn, int, NULL, S_IRUGO | S_IWUSR); | ||
949 | module_param_array(default_blu, int, NULL, S_IRUGO | S_IWUSR); | ||
950 | |||
937 | /* | 951 | /* |
938 | * gotoxy() must verify all boundaries, because the arguments | 952 | * gotoxy() must verify all boundaries, because the arguments |
939 | * might also be negative. If the given position is out of | 953 | * might also be negative. If the given position is out of |
@@ -1132,6 +1146,7 @@ static void csi_X(struct vc_data *vc, int vpar) /* erase the following vpar posi | |||
1132 | static void default_attr(struct vc_data *vc) | 1146 | static void default_attr(struct vc_data *vc) |
1133 | { | 1147 | { |
1134 | vc->vc_intensity = 1; | 1148 | vc->vc_intensity = 1; |
1149 | vc->vc_italic = 0; | ||
1135 | vc->vc_underline = 0; | 1150 | vc->vc_underline = 0; |
1136 | vc->vc_reverse = 0; | 1151 | vc->vc_reverse = 0; |
1137 | vc->vc_blink = 0; | 1152 | vc->vc_blink = 0; |
@@ -1154,6 +1169,9 @@ static void csi_m(struct vc_data *vc) | |||
1154 | case 2: | 1169 | case 2: |
1155 | vc->vc_intensity = 0; | 1170 | vc->vc_intensity = 0; |
1156 | break; | 1171 | break; |
1172 | case 3: | ||
1173 | vc->vc_italic = 1; | ||
1174 | break; | ||
1157 | case 4: | 1175 | case 4: |
1158 | vc->vc_underline = 1; | 1176 | vc->vc_underline = 1; |
1159 | break; | 1177 | break; |
@@ -1194,6 +1212,9 @@ static void csi_m(struct vc_data *vc) | |||
1194 | case 22: | 1212 | case 22: |
1195 | vc->vc_intensity = 1; | 1213 | vc->vc_intensity = 1; |
1196 | break; | 1214 | break; |
1215 | case 23: | ||
1216 | vc->vc_italic = 0; | ||
1217 | break; | ||
1197 | case 24: | 1218 | case 24: |
1198 | vc->vc_underline = 0; | 1219 | vc->vc_underline = 0; |
1199 | break; | 1220 | break; |
@@ -1454,6 +1475,7 @@ static void save_cur(struct vc_data *vc) | |||
1454 | vc->vc_saved_x = vc->vc_x; | 1475 | vc->vc_saved_x = vc->vc_x; |
1455 | vc->vc_saved_y = vc->vc_y; | 1476 | vc->vc_saved_y = vc->vc_y; |
1456 | vc->vc_s_intensity = vc->vc_intensity; | 1477 | vc->vc_s_intensity = vc->vc_intensity; |
1478 | vc->vc_s_italic = vc->vc_italic; | ||
1457 | vc->vc_s_underline = vc->vc_underline; | 1479 | vc->vc_s_underline = vc->vc_underline; |
1458 | vc->vc_s_blink = vc->vc_blink; | 1480 | vc->vc_s_blink = vc->vc_blink; |
1459 | vc->vc_s_reverse = vc->vc_reverse; | 1481 | vc->vc_s_reverse = vc->vc_reverse; |
@@ -1468,6 +1490,7 @@ static void restore_cur(struct vc_data *vc) | |||
1468 | { | 1490 | { |
1469 | gotoxy(vc, vc->vc_saved_x, vc->vc_saved_y); | 1491 | gotoxy(vc, vc->vc_saved_x, vc->vc_saved_y); |
1470 | vc->vc_intensity = vc->vc_s_intensity; | 1492 | vc->vc_intensity = vc->vc_s_intensity; |
1493 | vc->vc_italic = vc->vc_s_italic; | ||
1471 | vc->vc_underline = vc->vc_s_underline; | 1494 | vc->vc_underline = vc->vc_s_underline; |
1472 | vc->vc_blink = vc->vc_s_blink; | 1495 | vc->vc_blink = vc->vc_s_blink; |
1473 | vc->vc_reverse = vc->vc_s_reverse; | 1496 | vc->vc_reverse = vc->vc_s_reverse; |
@@ -1497,7 +1520,7 @@ static void reset_terminal(struct vc_data *vc, int do_clear) | |||
1497 | vc->vc_charset = 0; | 1520 | vc->vc_charset = 0; |
1498 | vc->vc_need_wrap = 0; | 1521 | vc->vc_need_wrap = 0; |
1499 | vc->vc_report_mouse = 0; | 1522 | vc->vc_report_mouse = 0; |
1500 | vc->vc_utf = 0; | 1523 | vc->vc_utf = default_utf8; |
1501 | vc->vc_utf_count = 0; | 1524 | vc->vc_utf_count = 0; |
1502 | 1525 | ||
1503 | vc->vc_disp_ctrl = 0; | 1526 | vc->vc_disp_ctrl = 0; |
@@ -1930,7 +1953,47 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) | |||
1930 | * kernel memory allocation is available. | 1953 | * kernel memory allocation is available. |
1931 | */ | 1954 | */ |
1932 | char con_buf[CON_BUF_SIZE]; | 1955 | char con_buf[CON_BUF_SIZE]; |
1933 | DECLARE_MUTEX(con_buf_sem); | 1956 | DEFINE_MUTEX(con_buf_mtx); |
1957 | |||
1958 | /* is_double_width() is based on the wcwidth() implementation by | ||
1959 | * Markus Kuhn -- 2003-05-20 (Unicode 4.0) | ||
1960 | * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c | ||
1961 | */ | ||
1962 | struct interval { | ||
1963 | uint32_t first; | ||
1964 | uint32_t last; | ||
1965 | }; | ||
1966 | |||
1967 | static int bisearch(uint32_t ucs, const struct interval *table, int max) | ||
1968 | { | ||
1969 | int min = 0; | ||
1970 | int mid; | ||
1971 | |||
1972 | if (ucs < table[0].first || ucs > table[max].last) | ||
1973 | return 0; | ||
1974 | while (max >= min) { | ||
1975 | mid = (min + max) / 2; | ||
1976 | if (ucs > table[mid].last) | ||
1977 | min = mid + 1; | ||
1978 | else if (ucs < table[mid].first) | ||
1979 | max = mid - 1; | ||
1980 | else | ||
1981 | return 1; | ||
1982 | } | ||
1983 | return 0; | ||
1984 | } | ||
1985 | |||
1986 | static int is_double_width(uint32_t ucs) | ||
1987 | { | ||
1988 | static const struct interval double_width[] = { | ||
1989 | { 0x1100, 0x115F }, { 0x2329, 0x232A }, { 0x2E80, 0x303E }, | ||
1990 | { 0x3040, 0xA4CF }, { 0xAC00, 0xD7A3 }, { 0xF900, 0xFAFF }, | ||
1991 | { 0xFE30, 0xFE6F }, { 0xFF00, 0xFF60 }, { 0xFFE0, 0xFFE6 }, | ||
1992 | { 0x20000, 0x2FFFD }, { 0x30000, 0x3FFFD } | ||
1993 | }; | ||
1994 | return bisearch(ucs, double_width, | ||
1995 | sizeof(double_width) / sizeof(*double_width) - 1); | ||
1996 | } | ||
1934 | 1997 | ||
1935 | /* acquires console_sem */ | 1998 | /* acquires console_sem */ |
1936 | static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int count) | 1999 | static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int count) |
@@ -1948,6 +2011,10 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co | |||
1948 | unsigned int currcons; | 2011 | unsigned int currcons; |
1949 | unsigned long draw_from = 0, draw_to = 0; | 2012 | unsigned long draw_from = 0, draw_to = 0; |
1950 | struct vc_data *vc; | 2013 | struct vc_data *vc; |
2014 | unsigned char vc_attr; | ||
2015 | uint8_t rescan; | ||
2016 | uint8_t inverse; | ||
2017 | uint8_t width; | ||
1951 | u16 himask, charmask; | 2018 | u16 himask, charmask; |
1952 | const unsigned char *orig_buf = NULL; | 2019 | const unsigned char *orig_buf = NULL; |
1953 | int orig_count; | 2020 | int orig_count; |
@@ -1983,7 +2050,7 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co | |||
1983 | 2050 | ||
1984 | /* At this point 'buf' is guaranteed to be a kernel buffer | 2051 | /* At this point 'buf' is guaranteed to be a kernel buffer |
1985 | * and therefore no access to userspace (and therefore sleeping) | 2052 | * and therefore no access to userspace (and therefore sleeping) |
1986 | * will be needed. The con_buf_sem serializes all tty based | 2053 | * will be needed. The con_buf_mtx serializes all tty based |
1987 | * console rendering and vcs write/read operations. We hold | 2054 | * console rendering and vcs write/read operations. We hold |
1988 | * the console spinlock during the entire write. | 2055 | * the console spinlock during the entire write. |
1989 | */ | 2056 | */ |
@@ -2010,53 +2077,86 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co | |||
2010 | buf++; | 2077 | buf++; |
2011 | n++; | 2078 | n++; |
2012 | count--; | 2079 | count--; |
2080 | rescan = 0; | ||
2081 | inverse = 0; | ||
2082 | width = 1; | ||
2013 | 2083 | ||
2014 | /* Do no translation at all in control states */ | 2084 | /* Do no translation at all in control states */ |
2015 | if (vc->vc_state != ESnormal) { | 2085 | if (vc->vc_state != ESnormal) { |
2016 | tc = c; | 2086 | tc = c; |
2017 | } else if (vc->vc_utf && !vc->vc_disp_ctrl) { | 2087 | } else if (vc->vc_utf && !vc->vc_disp_ctrl) { |
2018 | /* Combine UTF-8 into Unicode */ | 2088 | /* Combine UTF-8 into Unicode in vc_utf_char. |
2019 | /* Malformed sequences as sequences of replacement glyphs */ | 2089 | * vc_utf_count is the number of continuation bytes still |
2090 | * expected to arrive. | ||
2091 | * vc_npar is the number of continuation bytes arrived so | ||
2092 | * far | ||
2093 | */ | ||
2020 | rescan_last_byte: | 2094 | rescan_last_byte: |
2021 | if(c > 0x7f) { | 2095 | if ((c & 0xc0) == 0x80) { |
2096 | /* Continuation byte received */ | ||
2097 | static const uint32_t utf8_length_changes[] = { 0x0000007f, 0x000007ff, 0x0000ffff, 0x001fffff, 0x03ffffff, 0x7fffffff }; | ||
2022 | if (vc->vc_utf_count) { | 2098 | if (vc->vc_utf_count) { |
2023 | if ((c & 0xc0) == 0x80) { | 2099 | vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f); |
2024 | vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f); | 2100 | vc->vc_npar++; |
2025 | if (--vc->vc_utf_count) { | 2101 | if (--vc->vc_utf_count) { |
2026 | vc->vc_npar++; | 2102 | /* Still need some bytes */ |
2027 | continue; | ||
2028 | } | ||
2029 | tc = c = vc->vc_utf_char; | ||
2030 | } else | ||
2031 | goto replacement_glyph; | ||
2032 | } else { | ||
2033 | vc->vc_npar = 0; | ||
2034 | if ((c & 0xe0) == 0xc0) { | ||
2035 | vc->vc_utf_count = 1; | ||
2036 | vc->vc_utf_char = (c & 0x1f); | ||
2037 | } else if ((c & 0xf0) == 0xe0) { | ||
2038 | vc->vc_utf_count = 2; | ||
2039 | vc->vc_utf_char = (c & 0x0f); | ||
2040 | } else if ((c & 0xf8) == 0xf0) { | ||
2041 | vc->vc_utf_count = 3; | ||
2042 | vc->vc_utf_char = (c & 0x07); | ||
2043 | } else if ((c & 0xfc) == 0xf8) { | ||
2044 | vc->vc_utf_count = 4; | ||
2045 | vc->vc_utf_char = (c & 0x03); | ||
2046 | } else if ((c & 0xfe) == 0xfc) { | ||
2047 | vc->vc_utf_count = 5; | ||
2048 | vc->vc_utf_char = (c & 0x01); | ||
2049 | } else | ||
2050 | goto replacement_glyph; | ||
2051 | continue; | 2103 | continue; |
2052 | } | 2104 | } |
2105 | /* Got a whole character */ | ||
2106 | c = vc->vc_utf_char; | ||
2107 | /* Reject overlong sequences */ | ||
2108 | if (c <= utf8_length_changes[vc->vc_npar - 1] || | ||
2109 | c > utf8_length_changes[vc->vc_npar]) | ||
2110 | c = 0xfffd; | ||
2111 | } else { | ||
2112 | /* Unexpected continuation byte */ | ||
2113 | vc->vc_utf_count = 0; | ||
2114 | c = 0xfffd; | ||
2115 | } | ||
2053 | } else { | 2116 | } else { |
2054 | if (vc->vc_utf_count) | 2117 | /* Single ASCII byte or first byte of a sequence received */ |
2055 | goto replacement_glyph; | 2118 | if (vc->vc_utf_count) { |
2056 | tc = c; | 2119 | /* Continuation byte expected */ |
2120 | rescan = 1; | ||
2121 | vc->vc_utf_count = 0; | ||
2122 | c = 0xfffd; | ||
2123 | } else if (c > 0x7f) { | ||
2124 | /* First byte of a multibyte sequence received */ | ||
2125 | vc->vc_npar = 0; | ||
2126 | if ((c & 0xe0) == 0xc0) { | ||
2127 | vc->vc_utf_count = 1; | ||
2128 | vc->vc_utf_char = (c & 0x1f); | ||
2129 | } else if ((c & 0xf0) == 0xe0) { | ||
2130 | vc->vc_utf_count = 2; | ||
2131 | vc->vc_utf_char = (c & 0x0f); | ||
2132 | } else if ((c & 0xf8) == 0xf0) { | ||
2133 | vc->vc_utf_count = 3; | ||
2134 | vc->vc_utf_char = (c & 0x07); | ||
2135 | } else if ((c & 0xfc) == 0xf8) { | ||
2136 | vc->vc_utf_count = 4; | ||
2137 | vc->vc_utf_char = (c & 0x03); | ||
2138 | } else if ((c & 0xfe) == 0xfc) { | ||
2139 | vc->vc_utf_count = 5; | ||
2140 | vc->vc_utf_char = (c & 0x01); | ||
2141 | } else { | ||
2142 | /* 254 and 255 are invalid */ | ||
2143 | c = 0xfffd; | ||
2144 | } | ||
2145 | if (vc->vc_utf_count) { | ||
2146 | /* Still need some bytes */ | ||
2147 | continue; | ||
2148 | } | ||
2149 | } | ||
2150 | /* Nothing to do if an ASCII byte was received */ | ||
2057 | } | 2151 | } |
2152 | /* End of UTF-8 decoding. */ | ||
2153 | /* c is the received character, or U+FFFD for invalid sequences. */ | ||
2154 | /* Replace invalid Unicode code points with U+FFFD too */ | ||
2155 | if ((c >= 0xd800 && c <= 0xdfff) || c == 0xfffe || c == 0xffff) | ||
2156 | c = 0xfffd; | ||
2157 | tc = c; | ||
2058 | } else { /* no utf or alternate charset mode */ | 2158 | } else { /* no utf or alternate charset mode */ |
2059 | tc = vc->vc_translate[vc->vc_toggle_meta ? (c | 0x80) : c]; | 2159 | tc = vc->vc_translate[vc->vc_toggle_meta ? (c | 0x80) : c]; |
2060 | } | 2160 | } |
2061 | 2161 | ||
2062 | /* If the original code was a control character we | 2162 | /* If the original code was a control character we |
@@ -2076,56 +2176,80 @@ rescan_last_byte: | |||
2076 | && (c != 128+27); | 2176 | && (c != 128+27); |
2077 | 2177 | ||
2078 | if (vc->vc_state == ESnormal && ok) { | 2178 | if (vc->vc_state == ESnormal && ok) { |
2179 | if (vc->vc_utf && !vc->vc_disp_ctrl) { | ||
2180 | if (is_double_width(c)) | ||
2181 | width = 2; | ||
2182 | } | ||
2079 | /* Now try to find out how to display it */ | 2183 | /* Now try to find out how to display it */ |
2080 | tc = conv_uni_to_pc(vc, tc); | 2184 | tc = conv_uni_to_pc(vc, tc); |
2081 | if (tc & ~charmask) { | 2185 | if (tc & ~charmask) { |
2082 | if ( tc == -4 ) { | 2186 | if (tc == -1 || tc == -2) { |
2083 | /* If we got -4 (not found) then see if we have | 2187 | continue; /* nothing to display */ |
2084 | defined a replacement character (U+FFFD) */ | 2188 | } |
2085 | replacement_glyph: | 2189 | /* Glyph not found */ |
2086 | tc = conv_uni_to_pc(vc, 0xfffd); | 2190 | if (!(vc->vc_utf && !vc->vc_disp_ctrl) && !(c & ~charmask)) { |
2087 | if (!(tc & ~charmask)) | 2191 | /* In legacy mode use the glyph we get by a 1:1 mapping. |
2088 | goto display_glyph; | 2192 | This would make absolutely no sense with Unicode in mind. */ |
2089 | } else if ( tc != -3 ) | 2193 | tc = c; |
2090 | continue; /* nothing to display */ | 2194 | } else { |
2091 | /* no hash table or no replacement -- | 2195 | /* Display U+FFFD. If it's not found, display an inverse question mark. */ |
2092 | * hope for the best */ | 2196 | tc = conv_uni_to_pc(vc, 0xfffd); |
2093 | if ( c & ~charmask ) | 2197 | if (tc < 0) { |
2094 | tc = '?'; | 2198 | inverse = 1; |
2095 | else | 2199 | tc = conv_uni_to_pc(vc, '?'); |
2096 | tc = c; | 2200 | if (tc < 0) tc = '?'; |
2201 | } | ||
2202 | } | ||
2097 | } | 2203 | } |
2098 | 2204 | ||
2099 | display_glyph: | 2205 | if (!inverse) { |
2100 | if (vc->vc_need_wrap || vc->vc_decim) | 2206 | vc_attr = vc->vc_attr; |
2101 | FLUSH | ||
2102 | if (vc->vc_need_wrap) { | ||
2103 | cr(vc); | ||
2104 | lf(vc); | ||
2105 | } | ||
2106 | if (vc->vc_decim) | ||
2107 | insert_char(vc, 1); | ||
2108 | scr_writew(himask ? | ||
2109 | ((vc->vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) : | ||
2110 | (vc->vc_attr << 8) + tc, | ||
2111 | (u16 *) vc->vc_pos); | ||
2112 | if (DO_UPDATE(vc) && draw_x < 0) { | ||
2113 | draw_x = vc->vc_x; | ||
2114 | draw_from = vc->vc_pos; | ||
2115 | } | ||
2116 | if (vc->vc_x == vc->vc_cols - 1) { | ||
2117 | vc->vc_need_wrap = vc->vc_decawm; | ||
2118 | draw_to = vc->vc_pos + 2; | ||
2119 | } else { | 2207 | } else { |
2120 | vc->vc_x++; | 2208 | /* invert vc_attr */ |
2121 | draw_to = (vc->vc_pos += 2); | 2209 | if (!vc->vc_can_do_color) { |
2210 | vc_attr = (vc->vc_attr) ^ 0x08; | ||
2211 | } else if (vc->vc_hi_font_mask == 0x100) { | ||
2212 | vc_attr = ((vc->vc_attr) & 0x11) | (((vc->vc_attr) & 0xe0) >> 4) | (((vc->vc_attr) & 0x0e) << 4); | ||
2213 | } else { | ||
2214 | vc_attr = ((vc->vc_attr) & 0x88) | (((vc->vc_attr) & 0x70) >> 4) | (((vc->vc_attr) & 0x07) << 4); | ||
2215 | } | ||
2122 | } | 2216 | } |
2123 | if (vc->vc_utf_count) { | 2217 | |
2124 | if (vc->vc_npar) { | 2218 | while (1) { |
2125 | vc->vc_npar--; | 2219 | if (vc->vc_need_wrap || vc->vc_decim) |
2126 | goto display_glyph; | 2220 | FLUSH |
2221 | if (vc->vc_need_wrap) { | ||
2222 | cr(vc); | ||
2223 | lf(vc); | ||
2224 | } | ||
2225 | if (vc->vc_decim) | ||
2226 | insert_char(vc, 1); | ||
2227 | scr_writew(himask ? | ||
2228 | ((vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) : | ||
2229 | (vc_attr << 8) + tc, | ||
2230 | (u16 *) vc->vc_pos); | ||
2231 | if (DO_UPDATE(vc) && draw_x < 0) { | ||
2232 | draw_x = vc->vc_x; | ||
2233 | draw_from = vc->vc_pos; | ||
2234 | } | ||
2235 | if (vc->vc_x == vc->vc_cols - 1) { | ||
2236 | vc->vc_need_wrap = vc->vc_decawm; | ||
2237 | draw_to = vc->vc_pos + 2; | ||
2238 | } else { | ||
2239 | vc->vc_x++; | ||
2240 | draw_to = (vc->vc_pos += 2); | ||
2127 | } | 2241 | } |
2128 | vc->vc_utf_count = 0; | 2242 | |
2243 | if (!--width) break; | ||
2244 | |||
2245 | tc = conv_uni_to_pc(vc, ' '); /* A space is printed in the second column */ | ||
2246 | if (tc < 0) tc = ' '; | ||
2247 | } | ||
2248 | |||
2249 | if (rescan) { | ||
2250 | rescan = 0; | ||
2251 | inverse = 0; | ||
2252 | width = 1; | ||
2129 | c = orig; | 2253 | c = orig; |
2130 | goto rescan_last_byte; | 2254 | goto rescan_last_byte; |
2131 | } | 2255 | } |
@@ -2581,6 +2705,11 @@ static void con_close(struct tty_struct *tty, struct file *filp) | |||
2581 | mutex_unlock(&tty_mutex); | 2705 | mutex_unlock(&tty_mutex); |
2582 | } | 2706 | } |
2583 | 2707 | ||
2708 | static int default_italic_color = 2; // green (ASCII) | ||
2709 | static int default_underline_color = 3; // cyan (ASCII) | ||
2710 | module_param_named(italic, default_italic_color, int, S_IRUGO | S_IWUSR); | ||
2711 | module_param_named(underline, default_underline_color, int, S_IRUGO | S_IWUSR); | ||
2712 | |||
2584 | static void vc_init(struct vc_data *vc, unsigned int rows, | 2713 | static void vc_init(struct vc_data *vc, unsigned int rows, |
2585 | unsigned int cols, int do_clear) | 2714 | unsigned int cols, int do_clear) |
2586 | { | 2715 | { |
@@ -2600,7 +2729,8 @@ static void vc_init(struct vc_data *vc, unsigned int rows, | |||
2600 | vc->vc_palette[k++] = default_blu[j] ; | 2729 | vc->vc_palette[k++] = default_blu[j] ; |
2601 | } | 2730 | } |
2602 | vc->vc_def_color = 0x07; /* white */ | 2731 | vc->vc_def_color = 0x07; /* white */ |
2603 | vc->vc_ulcolor = 0x0f; /* bold white */ | 2732 | vc->vc_ulcolor = default_underline_color; |
2733 | vc->vc_itcolor = default_italic_color; | ||
2604 | vc->vc_halfcolor = 0x08; /* grey */ | 2734 | vc->vc_halfcolor = 0x08; /* grey */ |
2605 | init_waitqueue_head(&vc->paste_wait); | 2735 | init_waitqueue_head(&vc->paste_wait); |
2606 | reset_terminal(vc, do_clear); | 2736 | reset_terminal(vc, do_clear); |
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index c9f2dd620e87..c6f6f4209739 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c | |||
@@ -1061,7 +1061,7 @@ int vt_waitactive(int vt) | |||
1061 | schedule(); | 1061 | schedule(); |
1062 | } | 1062 | } |
1063 | remove_wait_queue(&vt_activate_queue, &wait); | 1063 | remove_wait_queue(&vt_activate_queue, &wait); |
1064 | current->state = TASK_RUNNING; | 1064 | __set_current_state(TASK_RUNNING); |
1065 | return retval; | 1065 | return retval; |
1066 | } | 1066 | } |
1067 | 1067 | ||
diff --git a/drivers/char/watchdog/omap_wdt.c b/drivers/char/watchdog/omap_wdt.c index 84074a697dce..b36fa8de2131 100644 --- a/drivers/char/watchdog/omap_wdt.c +++ b/drivers/char/watchdog/omap_wdt.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/miscdevice.h> | 34 | #include <linux/miscdevice.h> |
35 | #include <linux/watchdog.h> | 35 | #include <linux/watchdog.h> |
36 | #include <linux/reboot.h> | 36 | #include <linux/reboot.h> |
37 | #include <linux/smp_lock.h> | ||
38 | #include <linux/init.h> | 37 | #include <linux/init.h> |
39 | #include <linux/err.h> | 38 | #include <linux/err.h> |
40 | #include <linux/platform_device.h> | 39 | #include <linux/platform_device.h> |
diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c index 1e4a8d751a71..2f7ba7a514fe 100644 --- a/drivers/char/watchdog/sc1200wdt.c +++ b/drivers/char/watchdog/sc1200wdt.c | |||
@@ -38,7 +38,6 @@ | |||
38 | #include <linux/init.h> | 38 | #include <linux/init.h> |
39 | #include <linux/pnp.h> | 39 | #include <linux/pnp.h> |
40 | #include <linux/fs.h> | 40 | #include <linux/fs.h> |
41 | #include <linux/pci.h> | ||
42 | 41 | ||
43 | #include <asm/semaphore.h> | 42 | #include <asm/semaphore.h> |
44 | #include <asm/io.h> | 43 | #include <asm/io.h> |
diff --git a/drivers/char/watchdog/scx200_wdt.c b/drivers/char/watchdog/scx200_wdt.c index fc0e0347f9d2..d4fd0fa2f176 100644 --- a/drivers/char/watchdog/scx200_wdt.c +++ b/drivers/char/watchdog/scx200_wdt.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <linux/notifier.h> | 25 | #include <linux/notifier.h> |
26 | #include <linux/reboot.h> | 26 | #include <linux/reboot.h> |
27 | #include <linux/fs.h> | 27 | #include <linux/fs.h> |
28 | #include <linux/pci.h> | 28 | #include <linux/ioport.h> |
29 | #include <linux/scx200.h> | 29 | #include <linux/scx200.h> |
30 | 30 | ||
31 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |