diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2006-02-09 00:58:59 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2006-02-09 00:58:59 -0500 |
commit | cac0e8e8bb2e7a086643bdd00c41d900a79bb4fa (patch) | |
tree | 73cd85e5529a01fa2338ab6d58b99c36dd666cbe /drivers | |
parent | ddef9bb367b19383df627e388cb4c01c86ddba6c (diff) | |
parent | 0bdd340c092b0936f78a54bdbd3927463ed4fca3 (diff) |
Merge branch 'master'
Diffstat (limited to 'drivers')
282 files changed, 8086 insertions, 4451 deletions
diff --git a/drivers/Makefile b/drivers/Makefile index 619dd964c51c..5c69b86db624 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
@@ -69,7 +69,7 @@ obj-$(CONFIG_EISA) += eisa/ | |||
69 | obj-$(CONFIG_CPU_FREQ) += cpufreq/ | 69 | obj-$(CONFIG_CPU_FREQ) += cpufreq/ |
70 | obj-$(CONFIG_MMC) += mmc/ | 70 | obj-$(CONFIG_MMC) += mmc/ |
71 | obj-$(CONFIG_INFINIBAND) += infiniband/ | 71 | obj-$(CONFIG_INFINIBAND) += infiniband/ |
72 | obj-$(CONFIG_SGI_IOC4) += sn/ | 72 | obj-$(CONFIG_SGI_SN) += sn/ |
73 | obj-y += firmware/ | 73 | obj-y += firmware/ |
74 | obj-$(CONFIG_CRYPTO) += crypto/ | 74 | obj-$(CONFIG_CRYPTO) += crypto/ |
75 | obj-$(CONFIG_SUPERH) += sh/ | 75 | obj-$(CONFIG_SUPERH) += sh/ |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index be2dae52f6fa..eb730a80952c 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -94,7 +94,9 @@ static int set_max_cstate(struct dmi_system_id *id) | |||
94 | return 0; | 94 | return 0; |
95 | } | 95 | } |
96 | 96 | ||
97 | static struct dmi_system_id __initdata processor_power_dmi_table[] = { | 97 | /* Actually this shouldn't be __cpuinitdata, would be better to fix the |
98 | callers to only run once -AK */ | ||
99 | static struct dmi_system_id __cpuinitdata processor_power_dmi_table[] = { | ||
98 | { set_max_cstate, "IBM ThinkPad R40e", { | 100 | { set_max_cstate, "IBM ThinkPad R40e", { |
99 | DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), | 101 | DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), |
100 | DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW")}, (void *)1}, | 102 | DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW")}, (void *)1}, |
@@ -899,7 +901,7 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) | |||
899 | case ACPI_STATE_C3: | 901 | case ACPI_STATE_C3: |
900 | acpi_processor_power_verify_c3(pr, cx); | 902 | acpi_processor_power_verify_c3(pr, cx); |
901 | #ifdef ARCH_APICTIMER_STOPS_ON_C3 | 903 | #ifdef ARCH_APICTIMER_STOPS_ON_C3 |
902 | if (c->x86_vendor == X86_VENDOR_INTEL) { | 904 | if (cx->valid && c->x86_vendor == X86_VENDOR_INTEL) { |
903 | on_each_cpu(switch_APIC_timer_to_ipi, | 905 | on_each_cpu(switch_APIC_timer_to_ipi, |
904 | &mask, 1, 1); | 906 | &mask, 1, 1); |
905 | } | 907 | } |
diff --git a/drivers/base/Makefile b/drivers/base/Makefile index f12898d53078..e99471d3232b 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile | |||
@@ -8,6 +8,7 @@ obj-y += power/ | |||
8 | obj-$(CONFIG_FW_LOADER) += firmware_class.o | 8 | obj-$(CONFIG_FW_LOADER) += firmware_class.o |
9 | obj-$(CONFIG_NUMA) += node.o | 9 | obj-$(CONFIG_NUMA) += node.o |
10 | obj-$(CONFIG_MEMORY_HOTPLUG) += memory.o | 10 | obj-$(CONFIG_MEMORY_HOTPLUG) += memory.o |
11 | obj-$(CONFIG_SMP) += topology.o | ||
11 | 12 | ||
12 | ifeq ($(CONFIG_DEBUG_DRIVER),y) | 13 | ifeq ($(CONFIG_DEBUG_DRIVER),y) |
13 | EXTRA_CFLAGS += -DDEBUG | 14 | EXTRA_CFLAGS += -DDEBUG |
diff --git a/drivers/base/base.h b/drivers/base/base.h index e3b548d46cff..5735b38582d0 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h | |||
@@ -19,6 +19,10 @@ extern void bus_remove_driver(struct device_driver *); | |||
19 | extern void driver_detach(struct device_driver * drv); | 19 | extern void driver_detach(struct device_driver * drv); |
20 | extern int driver_probe_device(struct device_driver *, struct device *); | 20 | extern int driver_probe_device(struct device_driver *, struct device *); |
21 | 21 | ||
22 | extern void sysdev_shutdown(void); | ||
23 | extern int sysdev_suspend(pm_message_t state); | ||
24 | extern int sysdev_resume(void); | ||
25 | |||
22 | static inline struct class_device *to_class_dev(struct kobject *obj) | 26 | static inline struct class_device *to_class_dev(struct kobject *obj) |
23 | { | 27 | { |
24 | return container_of(obj, struct class_device, kobj); | 28 | return container_of(obj, struct class_device, kobj); |
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 29f6af554e71..c3141565d59d 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
@@ -133,6 +133,8 @@ static struct kobj_type ktype_bus = { | |||
133 | decl_subsys(bus, &ktype_bus, NULL); | 133 | decl_subsys(bus, &ktype_bus, NULL); |
134 | 134 | ||
135 | 135 | ||
136 | #ifdef CONFIG_HOTPLUG | ||
137 | |||
136 | /* Manually detach a device from its associated driver. */ | 138 | /* Manually detach a device from its associated driver. */ |
137 | static int driver_helper(struct device *dev, void *data) | 139 | static int driver_helper(struct device *dev, void *data) |
138 | { | 140 | { |
@@ -193,6 +195,7 @@ static ssize_t driver_bind(struct device_driver *drv, | |||
193 | } | 195 | } |
194 | static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind); | 196 | static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind); |
195 | 197 | ||
198 | #endif | ||
196 | 199 | ||
197 | static struct device * next_device(struct klist_iter * i) | 200 | static struct device * next_device(struct klist_iter * i) |
198 | { | 201 | { |
diff --git a/drivers/base/memory.c b/drivers/base/memory.c index d1a05224627e..105a0d61eb1f 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c | |||
@@ -303,7 +303,7 @@ static int block_size_init(void) | |||
303 | */ | 303 | */ |
304 | #ifdef CONFIG_ARCH_MEMORY_PROBE | 304 | #ifdef CONFIG_ARCH_MEMORY_PROBE |
305 | static ssize_t | 305 | static ssize_t |
306 | memory_probe_store(struct class *class, const char __user *buf, size_t count) | 306 | memory_probe_store(struct class *class, const char *buf, size_t count) |
307 | { | 307 | { |
308 | u64 phys_addr; | 308 | u64 phys_addr; |
309 | int ret; | 309 | int ret; |
diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c index 0a7aa07b9a2a..317edbf0feca 100644 --- a/drivers/base/power/resume.c +++ b/drivers/base/power/resume.c | |||
@@ -9,10 +9,9 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/device.h> | 11 | #include <linux/device.h> |
12 | #include "../base.h" | ||
12 | #include "power.h" | 13 | #include "power.h" |
13 | 14 | ||
14 | extern int sysdev_resume(void); | ||
15 | |||
16 | 15 | ||
17 | /** | 16 | /** |
18 | * resume_device - Restore state for one device. | 17 | * resume_device - Restore state for one device. |
diff --git a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c index c2475f3134ea..8826a5b6673e 100644 --- a/drivers/base/power/shutdown.c +++ b/drivers/base/power/shutdown.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/device.h> | 12 | #include <linux/device.h> |
13 | #include <asm/semaphore.h> | 13 | #include <asm/semaphore.h> |
14 | 14 | ||
15 | #include "../base.h" | ||
15 | #include "power.h" | 16 | #include "power.h" |
16 | 17 | ||
17 | #define to_dev(node) container_of(node, struct device, kobj.entry) | 18 | #define to_dev(node) container_of(node, struct device, kobj.entry) |
@@ -28,7 +29,6 @@ extern struct subsystem devices_subsys; | |||
28 | * they only get one called once when interrupts are disabled. | 29 | * they only get one called once when interrupts are disabled. |
29 | */ | 30 | */ |
30 | 31 | ||
31 | extern int sysdev_shutdown(void); | ||
32 | 32 | ||
33 | /** | 33 | /** |
34 | * device_shutdown - call ->shutdown() on each device to shutdown. | 34 | * device_shutdown - call ->shutdown() on each device to shutdown. |
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c index 50501764d050..8660779fb288 100644 --- a/drivers/base/power/suspend.c +++ b/drivers/base/power/suspend.c | |||
@@ -9,10 +9,9 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/device.h> | 11 | #include <linux/device.h> |
12 | #include "../base.h" | ||
12 | #include "power.h" | 13 | #include "power.h" |
13 | 14 | ||
14 | extern int sysdev_suspend(pm_message_t state); | ||
15 | |||
16 | /* | 15 | /* |
17 | * The entries in the dpm_active list are in a depth first order, simply | 16 | * The entries in the dpm_active list are in a depth first order, simply |
18 | * because children are guaranteed to be discovered after parents, and | 17 | * because children are guaranteed to be discovered after parents, and |
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index f3a0c562bcb5..40d7242a07c1 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c | |||
@@ -27,22 +27,30 @@ | |||
27 | 27 | ||
28 | static ssize_t state_show(struct device * dev, struct device_attribute *attr, char * buf) | 28 | static ssize_t state_show(struct device * dev, struct device_attribute *attr, char * buf) |
29 | { | 29 | { |
30 | return sprintf(buf, "%u\n", dev->power.power_state.event); | 30 | if (dev->power.power_state.event) |
31 | return sprintf(buf, "2\n"); | ||
32 | else | ||
33 | return sprintf(buf, "0\n"); | ||
31 | } | 34 | } |
32 | 35 | ||
33 | static ssize_t state_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t n) | 36 | static ssize_t state_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t n) |
34 | { | 37 | { |
35 | pm_message_t state; | 38 | pm_message_t state; |
36 | char * rest; | 39 | int error = -EINVAL; |
37 | int error = 0; | ||
38 | 40 | ||
39 | state.event = simple_strtoul(buf, &rest, 10); | 41 | state.event = PM_EVENT_SUSPEND; |
40 | if (*rest) | 42 | /* Older apps expected to write "3" here - confused with PCI D3 */ |
41 | return -EINVAL; | 43 | if ((n == 1) && !strcmp(buf, "3")) |
42 | if (state.event) | ||
43 | error = dpm_runtime_suspend(dev, state); | 44 | error = dpm_runtime_suspend(dev, state); |
44 | else | 45 | |
46 | if ((n == 1) && !strcmp(buf, "2")) | ||
47 | error = dpm_runtime_suspend(dev, state); | ||
48 | |||
49 | if ((n == 1) && !strcmp(buf, "0")) { | ||
45 | dpm_runtime_resume(dev); | 50 | dpm_runtime_resume(dev); |
51 | error = 0; | ||
52 | } | ||
53 | |||
46 | return error ? error : n; | 54 | return error ? error : n; |
47 | } | 55 | } |
48 | 56 | ||
diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 66ed8f2fece5..6fc23ab127bd 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c | |||
@@ -21,8 +21,11 @@ | |||
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/string.h> | 22 | #include <linux/string.h> |
23 | #include <linux/pm.h> | 23 | #include <linux/pm.h> |
24 | #include <linux/device.h> | ||
24 | #include <asm/semaphore.h> | 25 | #include <asm/semaphore.h> |
25 | 26 | ||
27 | #include "base.h" | ||
28 | |||
26 | extern struct subsystem devices_subsys; | 29 | extern struct subsystem devices_subsys; |
27 | 30 | ||
28 | #define to_sysdev(k) container_of(k, struct sys_device, kobj) | 31 | #define to_sysdev(k) container_of(k, struct sys_device, kobj) |
diff --git a/drivers/base/topology.c b/drivers/base/topology.c new file mode 100644 index 000000000000..915810f6237e --- /dev/null +++ b/drivers/base/topology.c | |||
@@ -0,0 +1,148 @@ | |||
1 | /* | ||
2 | * driver/base/topology.c - Populate sysfs with cpu topology information | ||
3 | * | ||
4 | * Written by: Zhang Yanmin, Intel Corporation | ||
5 | * | ||
6 | * Copyright (C) 2006, Intel Corp. | ||
7 | * | ||
8 | * All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but | ||
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
18 | * NON INFRINGEMENT. See the GNU General Public License for more | ||
19 | * details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | * | ||
25 | */ | ||
26 | #include <linux/sysdev.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/mm.h> | ||
29 | #include <linux/cpu.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/topology.h> | ||
32 | |||
33 | #define define_one_ro(_name) \ | ||
34 | static SYSDEV_ATTR(_name, 0444, show_##_name, NULL) | ||
35 | |||
36 | #define define_id_show_func(name) \ | ||
37 | static ssize_t show_##name(struct sys_device *dev, char *buf) \ | ||
38 | { \ | ||
39 | unsigned int cpu = dev->id; \ | ||
40 | return sprintf(buf, "%d\n", topology_##name(cpu)); \ | ||
41 | } | ||
42 | |||
43 | #define define_siblings_show_func(name) \ | ||
44 | static ssize_t show_##name(struct sys_device *dev, char *buf) \ | ||
45 | { \ | ||
46 | ssize_t len = -1; \ | ||
47 | unsigned int cpu = dev->id; \ | ||
48 | len = cpumask_scnprintf(buf, NR_CPUS+1, topology_##name(cpu)); \ | ||
49 | return (len + sprintf(buf + len, "\n")); \ | ||
50 | } | ||
51 | |||
52 | #ifdef topology_physical_package_id | ||
53 | define_id_show_func(physical_package_id); | ||
54 | define_one_ro(physical_package_id); | ||
55 | #define ref_physical_package_id_attr &attr_physical_package_id.attr, | ||
56 | #else | ||
57 | #define ref_physical_package_id_attr | ||
58 | #endif | ||
59 | |||
60 | #ifdef topology_core_id | ||
61 | define_id_show_func(core_id); | ||
62 | define_one_ro(core_id); | ||
63 | #define ref_core_id_attr &attr_core_id.attr, | ||
64 | #else | ||
65 | #define ref_core_id_attr | ||
66 | #endif | ||
67 | |||
68 | #ifdef topology_thread_siblings | ||
69 | define_siblings_show_func(thread_siblings); | ||
70 | define_one_ro(thread_siblings); | ||
71 | #define ref_thread_siblings_attr &attr_thread_siblings.attr, | ||
72 | #else | ||
73 | #define ref_thread_siblings_attr | ||
74 | #endif | ||
75 | |||
76 | #ifdef topology_core_siblings | ||
77 | define_siblings_show_func(core_siblings); | ||
78 | define_one_ro(core_siblings); | ||
79 | #define ref_core_siblings_attr &attr_core_siblings.attr, | ||
80 | #else | ||
81 | #define ref_core_siblings_attr | ||
82 | #endif | ||
83 | |||
84 | static struct attribute *default_attrs[] = { | ||
85 | ref_physical_package_id_attr | ||
86 | ref_core_id_attr | ||
87 | ref_thread_siblings_attr | ||
88 | ref_core_siblings_attr | ||
89 | NULL | ||
90 | }; | ||
91 | |||
92 | static struct attribute_group topology_attr_group = { | ||
93 | .attrs = default_attrs, | ||
94 | .name = "topology" | ||
95 | }; | ||
96 | |||
97 | /* Add/Remove cpu_topology interface for CPU device */ | ||
98 | static int __cpuinit topology_add_dev(struct sys_device * sys_dev) | ||
99 | { | ||
100 | sysfs_create_group(&sys_dev->kobj, &topology_attr_group); | ||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static int __cpuinit topology_remove_dev(struct sys_device * sys_dev) | ||
105 | { | ||
106 | sysfs_remove_group(&sys_dev->kobj, &topology_attr_group); | ||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static int __cpuinit topology_cpu_callback(struct notifier_block *nfb, | ||
111 | unsigned long action, void *hcpu) | ||
112 | { | ||
113 | unsigned int cpu = (unsigned long)hcpu; | ||
114 | struct sys_device *sys_dev; | ||
115 | |||
116 | sys_dev = get_cpu_sysdev(cpu); | ||
117 | switch (action) { | ||
118 | case CPU_ONLINE: | ||
119 | topology_add_dev(sys_dev); | ||
120 | break; | ||
121 | case CPU_DEAD: | ||
122 | topology_remove_dev(sys_dev); | ||
123 | break; | ||
124 | } | ||
125 | return NOTIFY_OK; | ||
126 | } | ||
127 | |||
128 | static struct notifier_block topology_cpu_notifier = | ||
129 | { | ||
130 | .notifier_call = topology_cpu_callback, | ||
131 | }; | ||
132 | |||
133 | static int __cpuinit topology_sysfs_init(void) | ||
134 | { | ||
135 | int i; | ||
136 | |||
137 | for_each_online_cpu(i) { | ||
138 | topology_cpu_callback(&topology_cpu_notifier, CPU_ONLINE, | ||
139 | (void *)(long)i); | ||
140 | } | ||
141 | |||
142 | register_cpu_notifier(&topology_cpu_notifier); | ||
143 | |||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | device_initcall(topology_sysfs_init); | ||
148 | |||
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 139cbba76180..8b1331677407 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig | |||
@@ -433,12 +433,12 @@ config CDROM_PKTCDVD_BUFFERS | |||
433 | This controls the maximum number of active concurrent packets. More | 433 | This controls the maximum number of active concurrent packets. More |
434 | concurrent packets can increase write performance, but also require | 434 | concurrent packets can increase write performance, but also require |
435 | more memory. Each concurrent packet will require approximately 64Kb | 435 | more memory. Each concurrent packet will require approximately 64Kb |
436 | of non-swappable kernel memory, memory which will be allocated at | 436 | of non-swappable kernel memory, memory which will be allocated when |
437 | pktsetup time. | 437 | a disc is opened for writing. |
438 | 438 | ||
439 | config CDROM_PKTCDVD_WCACHE | 439 | config CDROM_PKTCDVD_WCACHE |
440 | bool "Enable write caching" | 440 | bool "Enable write caching (EXPERIMENTAL)" |
441 | depends on CDROM_PKTCDVD | 441 | depends on CDROM_PKTCDVD && EXPERIMENTAL |
442 | help | 442 | help |
443 | If enabled, write caching will be set for the CD-R/W device. For now | 443 | If enabled, write caching will be set for the CD-R/W device. For now |
444 | this option is dangerous unless the CD-RW media is known good, as we | 444 | this option is dangerous unless the CD-RW media is known good, as we |
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 12d7b9bdfa93..0d65394707db 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -2183,6 +2183,7 @@ static void cciss_softirq_done(struct request *rq) | |||
2183 | { | 2183 | { |
2184 | CommandList_struct *cmd = rq->completion_data; | 2184 | CommandList_struct *cmd = rq->completion_data; |
2185 | ctlr_info_t *h = hba[cmd->ctlr]; | 2185 | ctlr_info_t *h = hba[cmd->ctlr]; |
2186 | unsigned long flags; | ||
2186 | u64bit temp64; | 2187 | u64bit temp64; |
2187 | int i, ddir; | 2188 | int i, ddir; |
2188 | 2189 | ||
@@ -2205,10 +2206,10 @@ static void cciss_softirq_done(struct request *rq) | |||
2205 | printk("Done with %p\n", rq); | 2206 | printk("Done with %p\n", rq); |
2206 | #endif /* CCISS_DEBUG */ | 2207 | #endif /* CCISS_DEBUG */ |
2207 | 2208 | ||
2208 | spin_lock_irq(&h->lock); | 2209 | spin_lock_irqsave(&h->lock, flags); |
2209 | end_that_request_last(rq, rq->errors); | 2210 | end_that_request_last(rq, rq->errors); |
2210 | cmd_free(h, cmd,1); | 2211 | cmd_free(h, cmd,1); |
2211 | spin_unlock_irq(&h->lock); | 2212 | spin_unlock_irqrestore(&h->lock, flags); |
2212 | } | 2213 | } |
2213 | 2214 | ||
2214 | /* checks the status of the job and calls complete buffers to mark all | 2215 | /* checks the status of the job and calls complete buffers to mark all |
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 93affeeef7bd..4e7dbcc425ff 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c | |||
@@ -43,8 +43,6 @@ | |||
43 | * | 43 | * |
44 | *************************************************************************/ | 44 | *************************************************************************/ |
45 | 45 | ||
46 | #define VERSION_CODE "v0.2.0a 2004-07-14 Jens Axboe (axboe@suse.de) and petero2@telia.com" | ||
47 | |||
48 | #include <linux/pktcdvd.h> | 46 | #include <linux/pktcdvd.h> |
49 | #include <linux/config.h> | 47 | #include <linux/config.h> |
50 | #include <linux/module.h> | 48 | #include <linux/module.h> |
@@ -131,7 +129,7 @@ static struct bio *pkt_bio_alloc(int nr_iovecs) | |||
131 | /* | 129 | /* |
132 | * Allocate a packet_data struct | 130 | * Allocate a packet_data struct |
133 | */ | 131 | */ |
134 | static struct packet_data *pkt_alloc_packet_data(void) | 132 | static struct packet_data *pkt_alloc_packet_data(int frames) |
135 | { | 133 | { |
136 | int i; | 134 | int i; |
137 | struct packet_data *pkt; | 135 | struct packet_data *pkt; |
@@ -140,11 +138,12 @@ static struct packet_data *pkt_alloc_packet_data(void) | |||
140 | if (!pkt) | 138 | if (!pkt) |
141 | goto no_pkt; | 139 | goto no_pkt; |
142 | 140 | ||
143 | pkt->w_bio = pkt_bio_alloc(PACKET_MAX_SIZE); | 141 | pkt->frames = frames; |
142 | pkt->w_bio = pkt_bio_alloc(frames); | ||
144 | if (!pkt->w_bio) | 143 | if (!pkt->w_bio) |
145 | goto no_bio; | 144 | goto no_bio; |
146 | 145 | ||
147 | for (i = 0; i < PAGES_PER_PACKET; i++) { | 146 | for (i = 0; i < frames / FRAMES_PER_PAGE; i++) { |
148 | pkt->pages[i] = alloc_page(GFP_KERNEL|__GFP_ZERO); | 147 | pkt->pages[i] = alloc_page(GFP_KERNEL|__GFP_ZERO); |
149 | if (!pkt->pages[i]) | 148 | if (!pkt->pages[i]) |
150 | goto no_page; | 149 | goto no_page; |
@@ -152,7 +151,7 @@ static struct packet_data *pkt_alloc_packet_data(void) | |||
152 | 151 | ||
153 | spin_lock_init(&pkt->lock); | 152 | spin_lock_init(&pkt->lock); |
154 | 153 | ||
155 | for (i = 0; i < PACKET_MAX_SIZE; i++) { | 154 | for (i = 0; i < frames; i++) { |
156 | struct bio *bio = pkt_bio_alloc(1); | 155 | struct bio *bio = pkt_bio_alloc(1); |
157 | if (!bio) | 156 | if (!bio) |
158 | goto no_rd_bio; | 157 | goto no_rd_bio; |
@@ -162,14 +161,14 @@ static struct packet_data *pkt_alloc_packet_data(void) | |||
162 | return pkt; | 161 | return pkt; |
163 | 162 | ||
164 | no_rd_bio: | 163 | no_rd_bio: |
165 | for (i = 0; i < PACKET_MAX_SIZE; i++) { | 164 | for (i = 0; i < frames; i++) { |
166 | struct bio *bio = pkt->r_bios[i]; | 165 | struct bio *bio = pkt->r_bios[i]; |
167 | if (bio) | 166 | if (bio) |
168 | bio_put(bio); | 167 | bio_put(bio); |
169 | } | 168 | } |
170 | 169 | ||
171 | no_page: | 170 | no_page: |
172 | for (i = 0; i < PAGES_PER_PACKET; i++) | 171 | for (i = 0; i < frames / FRAMES_PER_PAGE; i++) |
173 | if (pkt->pages[i]) | 172 | if (pkt->pages[i]) |
174 | __free_page(pkt->pages[i]); | 173 | __free_page(pkt->pages[i]); |
175 | bio_put(pkt->w_bio); | 174 | bio_put(pkt->w_bio); |
@@ -186,12 +185,12 @@ static void pkt_free_packet_data(struct packet_data *pkt) | |||
186 | { | 185 | { |
187 | int i; | 186 | int i; |
188 | 187 | ||
189 | for (i = 0; i < PACKET_MAX_SIZE; i++) { | 188 | for (i = 0; i < pkt->frames; i++) { |
190 | struct bio *bio = pkt->r_bios[i]; | 189 | struct bio *bio = pkt->r_bios[i]; |
191 | if (bio) | 190 | if (bio) |
192 | bio_put(bio); | 191 | bio_put(bio); |
193 | } | 192 | } |
194 | for (i = 0; i < PAGES_PER_PACKET; i++) | 193 | for (i = 0; i < pkt->frames / FRAMES_PER_PAGE; i++) |
195 | __free_page(pkt->pages[i]); | 194 | __free_page(pkt->pages[i]); |
196 | bio_put(pkt->w_bio); | 195 | bio_put(pkt->w_bio); |
197 | kfree(pkt); | 196 | kfree(pkt); |
@@ -206,17 +205,17 @@ static void pkt_shrink_pktlist(struct pktcdvd_device *pd) | |||
206 | list_for_each_entry_safe(pkt, next, &pd->cdrw.pkt_free_list, list) { | 205 | list_for_each_entry_safe(pkt, next, &pd->cdrw.pkt_free_list, list) { |
207 | pkt_free_packet_data(pkt); | 206 | pkt_free_packet_data(pkt); |
208 | } | 207 | } |
208 | INIT_LIST_HEAD(&pd->cdrw.pkt_free_list); | ||
209 | } | 209 | } |
210 | 210 | ||
211 | static int pkt_grow_pktlist(struct pktcdvd_device *pd, int nr_packets) | 211 | static int pkt_grow_pktlist(struct pktcdvd_device *pd, int nr_packets) |
212 | { | 212 | { |
213 | struct packet_data *pkt; | 213 | struct packet_data *pkt; |
214 | 214 | ||
215 | INIT_LIST_HEAD(&pd->cdrw.pkt_free_list); | 215 | BUG_ON(!list_empty(&pd->cdrw.pkt_free_list)); |
216 | INIT_LIST_HEAD(&pd->cdrw.pkt_active_list); | 216 | |
217 | spin_lock_init(&pd->cdrw.active_list_lock); | ||
218 | while (nr_packets > 0) { | 217 | while (nr_packets > 0) { |
219 | pkt = pkt_alloc_packet_data(); | 218 | pkt = pkt_alloc_packet_data(pd->settings.size >> 2); |
220 | if (!pkt) { | 219 | if (!pkt) { |
221 | pkt_shrink_pktlist(pd); | 220 | pkt_shrink_pktlist(pd); |
222 | return 0; | 221 | return 0; |
@@ -951,7 +950,7 @@ try_next_bio: | |||
951 | 950 | ||
952 | pd->current_sector = zone + pd->settings.size; | 951 | pd->current_sector = zone + pd->settings.size; |
953 | pkt->sector = zone; | 952 | pkt->sector = zone; |
954 | pkt->frames = pd->settings.size >> 2; | 953 | BUG_ON(pkt->frames != pd->settings.size >> 2); |
955 | pkt->write_size = 0; | 954 | pkt->write_size = 0; |
956 | 955 | ||
957 | /* | 956 | /* |
@@ -1639,7 +1638,7 @@ static int pkt_probe_settings(struct pktcdvd_device *pd) | |||
1639 | pd->settings.size = be32_to_cpu(ti.fixed_packet_size) << 2; | 1638 | pd->settings.size = be32_to_cpu(ti.fixed_packet_size) << 2; |
1640 | if (pd->settings.size == 0) { | 1639 | if (pd->settings.size == 0) { |
1641 | printk("pktcdvd: detected zero packet size!\n"); | 1640 | printk("pktcdvd: detected zero packet size!\n"); |
1642 | pd->settings.size = 128; | 1641 | return -ENXIO; |
1643 | } | 1642 | } |
1644 | if (pd->settings.size > PACKET_MAX_SECTORS) { | 1643 | if (pd->settings.size > PACKET_MAX_SECTORS) { |
1645 | printk("pktcdvd: packet size is too big\n"); | 1644 | printk("pktcdvd: packet size is too big\n"); |
@@ -1987,8 +1986,14 @@ static int pkt_open_dev(struct pktcdvd_device *pd, int write) | |||
1987 | if ((ret = pkt_set_segment_merging(pd, q))) | 1986 | if ((ret = pkt_set_segment_merging(pd, q))) |
1988 | goto out_unclaim; | 1987 | goto out_unclaim; |
1989 | 1988 | ||
1990 | if (write) | 1989 | if (write) { |
1990 | if (!pkt_grow_pktlist(pd, CONFIG_CDROM_PKTCDVD_BUFFERS)) { | ||
1991 | printk("pktcdvd: not enough memory for buffers\n"); | ||
1992 | ret = -ENOMEM; | ||
1993 | goto out_unclaim; | ||
1994 | } | ||
1991 | printk("pktcdvd: %lukB available on disc\n", lba << 1); | 1995 | printk("pktcdvd: %lukB available on disc\n", lba << 1); |
1996 | } | ||
1992 | 1997 | ||
1993 | return 0; | 1998 | return 0; |
1994 | 1999 | ||
@@ -2014,6 +2019,8 @@ static void pkt_release_dev(struct pktcdvd_device *pd, int flush) | |||
2014 | pkt_set_speed(pd, MAX_SPEED, MAX_SPEED); | 2019 | pkt_set_speed(pd, MAX_SPEED, MAX_SPEED); |
2015 | bd_release(pd->bdev); | 2020 | bd_release(pd->bdev); |
2016 | blkdev_put(pd->bdev); | 2021 | blkdev_put(pd->bdev); |
2022 | |||
2023 | pkt_shrink_pktlist(pd); | ||
2017 | } | 2024 | } |
2018 | 2025 | ||
2019 | static struct pktcdvd_device *pkt_find_dev_from_minor(int dev_minor) | 2026 | static struct pktcdvd_device *pkt_find_dev_from_minor(int dev_minor) |
@@ -2379,12 +2386,6 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev) | |||
2379 | /* This is safe, since we have a reference from open(). */ | 2386 | /* This is safe, since we have a reference from open(). */ |
2380 | __module_get(THIS_MODULE); | 2387 | __module_get(THIS_MODULE); |
2381 | 2388 | ||
2382 | if (!pkt_grow_pktlist(pd, CONFIG_CDROM_PKTCDVD_BUFFERS)) { | ||
2383 | printk("pktcdvd: not enough memory for buffers\n"); | ||
2384 | ret = -ENOMEM; | ||
2385 | goto out_mem; | ||
2386 | } | ||
2387 | |||
2388 | pd->bdev = bdev; | 2389 | pd->bdev = bdev; |
2389 | set_blocksize(bdev, CD_FRAMESIZE); | 2390 | set_blocksize(bdev, CD_FRAMESIZE); |
2390 | 2391 | ||
@@ -2395,7 +2396,7 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev) | |||
2395 | if (IS_ERR(pd->cdrw.thread)) { | 2396 | if (IS_ERR(pd->cdrw.thread)) { |
2396 | printk("pktcdvd: can't start kernel thread\n"); | 2397 | printk("pktcdvd: can't start kernel thread\n"); |
2397 | ret = -ENOMEM; | 2398 | ret = -ENOMEM; |
2398 | goto out_thread; | 2399 | goto out_mem; |
2399 | } | 2400 | } |
2400 | 2401 | ||
2401 | proc = create_proc_entry(pd->name, 0, pkt_proc); | 2402 | proc = create_proc_entry(pd->name, 0, pkt_proc); |
@@ -2406,8 +2407,6 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev) | |||
2406 | DPRINTK("pktcdvd: writer %s mapped to %s\n", pd->name, bdevname(bdev, b)); | 2407 | DPRINTK("pktcdvd: writer %s mapped to %s\n", pd->name, bdevname(bdev, b)); |
2407 | return 0; | 2408 | return 0; |
2408 | 2409 | ||
2409 | out_thread: | ||
2410 | pkt_shrink_pktlist(pd); | ||
2411 | out_mem: | 2410 | out_mem: |
2412 | blkdev_put(bdev); | 2411 | blkdev_put(bdev); |
2413 | /* This is safe: open() is still holding a reference. */ | 2412 | /* This is safe: open() is still holding a reference. */ |
@@ -2503,6 +2502,10 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd) | |||
2503 | goto out_mem; | 2502 | goto out_mem; |
2504 | pd->disk = disk; | 2503 | pd->disk = disk; |
2505 | 2504 | ||
2505 | INIT_LIST_HEAD(&pd->cdrw.pkt_free_list); | ||
2506 | INIT_LIST_HEAD(&pd->cdrw.pkt_active_list); | ||
2507 | spin_lock_init(&pd->cdrw.active_list_lock); | ||
2508 | |||
2506 | spin_lock_init(&pd->lock); | 2509 | spin_lock_init(&pd->lock); |
2507 | spin_lock_init(&pd->iosched.lock); | 2510 | spin_lock_init(&pd->iosched.lock); |
2508 | sprintf(pd->name, "pktcdvd%d", idx); | 2511 | sprintf(pd->name, "pktcdvd%d", idx); |
@@ -2567,8 +2570,6 @@ static int pkt_remove_dev(struct pkt_ctrl_command *ctrl_cmd) | |||
2567 | 2570 | ||
2568 | blkdev_put(pd->bdev); | 2571 | blkdev_put(pd->bdev); |
2569 | 2572 | ||
2570 | pkt_shrink_pktlist(pd); | ||
2571 | |||
2572 | remove_proc_entry(pd->name, pkt_proc); | 2573 | remove_proc_entry(pd->name, pkt_proc); |
2573 | DPRINTK("pktcdvd: writer %s unmapped\n", pd->name); | 2574 | DPRINTK("pktcdvd: writer %s unmapped\n", pd->name); |
2574 | 2575 | ||
@@ -2678,7 +2679,6 @@ static int __init pkt_init(void) | |||
2678 | 2679 | ||
2679 | pkt_proc = proc_mkdir("pktcdvd", proc_root_driver); | 2680 | pkt_proc = proc_mkdir("pktcdvd", proc_root_driver); |
2680 | 2681 | ||
2681 | DPRINTK("pktcdvd: %s\n", VERSION_CODE); | ||
2682 | return 0; | 2682 | return 0; |
2683 | 2683 | ||
2684 | out: | 2684 | out: |
diff --git a/drivers/block/umem.c b/drivers/block/umem.c index a3614e6a68d0..4ada1268b40d 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c | |||
@@ -882,7 +882,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i | |||
882 | card->card_number, dev->bus->number, dev->devfn); | 882 | card->card_number, dev->bus->number, dev->devfn); |
883 | 883 | ||
884 | if (pci_set_dma_mask(dev, 0xffffffffffffffffLL) && | 884 | if (pci_set_dma_mask(dev, 0xffffffffffffffffLL) && |
885 | !pci_set_dma_mask(dev, 0xffffffffLL)) { | 885 | pci_set_dma_mask(dev, 0xffffffffLL)) { |
886 | printk(KERN_WARNING "MM%d: NO suitable DMA found\n",num_cards); | 886 | printk(KERN_WARNING "MM%d: NO suitable DMA found\n",num_cards); |
887 | return -ENOMEM; | 887 | return -ENOMEM; |
888 | } | 888 | } |
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index 193446e6a08a..e27617259552 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c | |||
@@ -42,8 +42,6 @@ | |||
42 | #include <linux/proc_fs.h> | 42 | #include <linux/proc_fs.h> |
43 | #include <linux/seq_file.h> | 43 | #include <linux/seq_file.h> |
44 | 44 | ||
45 | #include <asm/bug.h> | ||
46 | |||
47 | #include <asm/vio.h> | 45 | #include <asm/vio.h> |
48 | #include <asm/scatterlist.h> | 46 | #include <asm/scatterlist.h> |
49 | #include <asm/iseries/hv_types.h> | 47 | #include <asm/iseries/hv_types.h> |
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 4c67727d75b1..05ba410682a3 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -222,7 +222,7 @@ config SYNCLINKMP | |||
222 | 222 | ||
223 | config SYNCLINK_GT | 223 | config SYNCLINK_GT |
224 | tristate "SyncLink GT/AC support" | 224 | tristate "SyncLink GT/AC support" |
225 | depends on SERIAL_NONSTANDARD | 225 | depends on SERIAL_NONSTANDARD && PCI |
226 | help | 226 | help |
227 | Support for SyncLink GT and SyncLink AC families of | 227 | Support for SyncLink GT and SyncLink AC families of |
228 | synchronous and asynchronous serial adapters | 228 | synchronous and asynchronous serial adapters |
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 39c61a71176e..cc7acf877dc0 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c | |||
@@ -1233,7 +1233,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
1233 | } | 1233 | } |
1234 | info->idle_stats.recv_idle = jiffies; | 1234 | info->idle_stats.recv_idle = jiffies; |
1235 | } | 1235 | } |
1236 | schedule_delayed_work(&tty->buf.work, 1); | 1236 | tty_schedule_flip(tty); |
1237 | } | 1237 | } |
1238 | /* end of service */ | 1238 | /* end of service */ |
1239 | cy_writeb(base_addr+(CyRIR<<index), (save_xir & 0x3f)); | 1239 | cy_writeb(base_addr+(CyRIR<<index), (save_xir & 0x3f)); |
@@ -1606,7 +1606,7 @@ cyz_handle_rx(struct cyclades_port *info, | |||
1606 | } | 1606 | } |
1607 | #endif | 1607 | #endif |
1608 | info->idle_stats.recv_idle = jiffies; | 1608 | info->idle_stats.recv_idle = jiffies; |
1609 | schedule_delayed_work(&tty->buf.work, 1); | 1609 | tty_schedule_flip(tty); |
1610 | } | 1610 | } |
1611 | /* Update rx_get */ | 1611 | /* Update rx_get */ |
1612 | cy_writel(&buf_ctrl->rx_get, new_rx_get); | 1612 | cy_writel(&buf_ctrl->rx_get, new_rx_get); |
@@ -1809,7 +1809,7 @@ cyz_handle_cmd(struct cyclades_card *cinfo) | |||
1809 | if(delta_count) | 1809 | if(delta_count) |
1810 | cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP); | 1810 | cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP); |
1811 | if(special_count) | 1811 | if(special_count) |
1812 | schedule_delayed_work(&tty->buf.work, 1); | 1812 | tty_schedule_flip(tty); |
1813 | } | 1813 | } |
1814 | } | 1814 | } |
1815 | 1815 | ||
diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c index 5485382cadec..bd7be09ea53d 100644 --- a/drivers/char/drm/ati_pcigart.c +++ b/drivers/char/drm/ati_pcigart.c | |||
@@ -59,17 +59,16 @@ static void *drm_ati_alloc_pcigart_table(void) | |||
59 | int i; | 59 | int i; |
60 | DRM_DEBUG("%s\n", __FUNCTION__); | 60 | DRM_DEBUG("%s\n", __FUNCTION__); |
61 | 61 | ||
62 | address = __get_free_pages(GFP_KERNEL, ATI_PCIGART_TABLE_ORDER); | 62 | address = __get_free_pages(GFP_KERNEL | __GFP_COMP, |
63 | ATI_PCIGART_TABLE_ORDER); | ||
63 | if (address == 0UL) { | 64 | if (address == 0UL) { |
64 | return 0; | 65 | return NULL; |
65 | } | 66 | } |
66 | 67 | ||
67 | page = virt_to_page(address); | 68 | page = virt_to_page(address); |
68 | 69 | ||
69 | for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) { | 70 | for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) |
70 | get_page(page); | ||
71 | SetPageReserved(page); | 71 | SetPageReserved(page); |
72 | } | ||
73 | 72 | ||
74 | DRM_DEBUG("%s: returning 0x%08lx\n", __FUNCTION__, address); | 73 | DRM_DEBUG("%s: returning 0x%08lx\n", __FUNCTION__, address); |
75 | return (void *)address; | 74 | return (void *)address; |
@@ -83,10 +82,8 @@ static void drm_ati_free_pcigart_table(void *address) | |||
83 | 82 | ||
84 | page = virt_to_page((unsigned long)address); | 83 | page = virt_to_page((unsigned long)address); |
85 | 84 | ||
86 | for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) { | 85 | for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) |
87 | __put_page(page); | ||
88 | ClearPageReserved(page); | 86 | ClearPageReserved(page); |
89 | } | ||
90 | 87 | ||
91 | free_pages((unsigned long)address, ATI_PCIGART_TABLE_ORDER); | 88 | free_pages((unsigned long)address, ATI_PCIGART_TABLE_ORDER); |
92 | } | 89 | } |
@@ -127,7 +124,7 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) | |||
127 | if (gart_info->gart_table_location == DRM_ATI_GART_MAIN | 124 | if (gart_info->gart_table_location == DRM_ATI_GART_MAIN |
128 | && gart_info->addr) { | 125 | && gart_info->addr) { |
129 | drm_ati_free_pcigart_table(gart_info->addr); | 126 | drm_ati_free_pcigart_table(gart_info->addr); |
130 | gart_info->addr = 0; | 127 | gart_info->addr = NULL; |
131 | } | 128 | } |
132 | 129 | ||
133 | return 1; | 130 | return 1; |
@@ -168,7 +165,7 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) | |||
168 | if (bus_address == 0) { | 165 | if (bus_address == 0) { |
169 | DRM_ERROR("unable to map PCIGART pages!\n"); | 166 | DRM_ERROR("unable to map PCIGART pages!\n"); |
170 | drm_ati_free_pcigart_table(address); | 167 | drm_ati_free_pcigart_table(address); |
171 | address = 0; | 168 | address = NULL; |
172 | goto done; | 169 | goto done; |
173 | } | 170 | } |
174 | } else { | 171 | } else { |
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 54b561e69486..107df9fdba4e 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h | |||
@@ -57,6 +57,7 @@ | |||
57 | #include <linux/smp_lock.h> /* For (un)lock_kernel */ | 57 | #include <linux/smp_lock.h> /* For (un)lock_kernel */ |
58 | #include <linux/mm.h> | 58 | #include <linux/mm.h> |
59 | #include <linux/cdev.h> | 59 | #include <linux/cdev.h> |
60 | #include <linux/mutex.h> | ||
60 | #if defined(__alpha__) || defined(__powerpc__) | 61 | #if defined(__alpha__) || defined(__powerpc__) |
61 | #include <asm/pgtable.h> /* For pte_wrprotect */ | 62 | #include <asm/pgtable.h> /* For pte_wrprotect */ |
62 | #endif | 63 | #endif |
@@ -623,7 +624,7 @@ typedef struct drm_device { | |||
623 | /** \name Locks */ | 624 | /** \name Locks */ |
624 | /*@{ */ | 625 | /*@{ */ |
625 | spinlock_t count_lock; /**< For inuse, drm_device::open_count, drm_device::buf_use */ | 626 | spinlock_t count_lock; /**< For inuse, drm_device::open_count, drm_device::buf_use */ |
626 | struct semaphore struct_sem; /**< For others */ | 627 | struct mutex struct_mutex; /**< For others */ |
627 | /*@} */ | 628 | /*@} */ |
628 | 629 | ||
629 | /** \name Usage Counters */ | 630 | /** \name Usage Counters */ |
@@ -658,7 +659,7 @@ typedef struct drm_device { | |||
658 | /*@{ */ | 659 | /*@{ */ |
659 | drm_ctx_list_t *ctxlist; /**< Linked list of context handles */ | 660 | drm_ctx_list_t *ctxlist; /**< Linked list of context handles */ |
660 | int ctx_count; /**< Number of context handles */ | 661 | int ctx_count; /**< Number of context handles */ |
661 | struct semaphore ctxlist_sem; /**< For ctxlist */ | 662 | struct mutex ctxlist_mutex; /**< For ctxlist */ |
662 | 663 | ||
663 | drm_map_t **context_sareas; /**< per-context SAREA's */ | 664 | drm_map_t **context_sareas; /**< per-context SAREA's */ |
664 | int max_context; | 665 | int max_context; |
@@ -979,7 +980,7 @@ extern int drm_put_head(drm_head_t * head); | |||
979 | extern unsigned int drm_debug; | 980 | extern unsigned int drm_debug; |
980 | extern unsigned int drm_cards_limit; | 981 | extern unsigned int drm_cards_limit; |
981 | extern drm_head_t **drm_heads; | 982 | extern drm_head_t **drm_heads; |
982 | extern struct drm_sysfs_class *drm_class; | 983 | extern struct class *drm_class; |
983 | extern struct proc_dir_entry *drm_proc_root; | 984 | extern struct proc_dir_entry *drm_proc_root; |
984 | 985 | ||
985 | /* Proc support (drm_proc.h) */ | 986 | /* Proc support (drm_proc.h) */ |
@@ -1010,11 +1011,9 @@ extern void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah); | |||
1010 | extern void drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah); | 1011 | extern void drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah); |
1011 | 1012 | ||
1012 | /* sysfs support (drm_sysfs.c) */ | 1013 | /* sysfs support (drm_sysfs.c) */ |
1013 | struct drm_sysfs_class; | 1014 | extern struct class *drm_sysfs_create(struct module *owner, char *name); |
1014 | extern struct drm_sysfs_class *drm_sysfs_create(struct module *owner, | 1015 | extern void drm_sysfs_destroy(struct class *cs); |
1015 | char *name); | 1016 | extern struct class_device *drm_sysfs_device_add(struct class *cs, |
1016 | extern void drm_sysfs_destroy(struct drm_sysfs_class *cs); | ||
1017 | extern struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs, | ||
1018 | drm_head_t *head); | 1017 | drm_head_t *head); |
1019 | extern void drm_sysfs_device_remove(struct class_device *class_dev); | 1018 | extern void drm_sysfs_device_remove(struct class_device *class_dev); |
1020 | 1019 | ||
diff --git a/drivers/char/drm/drm_auth.c b/drivers/char/drm/drm_auth.c index a47b502bc7cc..2a37586a7ee8 100644 --- a/drivers/char/drm/drm_auth.c +++ b/drivers/char/drm/drm_auth.c | |||
@@ -56,7 +56,7 @@ static int drm_hash_magic(drm_magic_t magic) | |||
56 | * \param magic magic number. | 56 | * \param magic magic number. |
57 | * | 57 | * |
58 | * Searches in drm_device::magiclist within all files with the same hash key | 58 | * Searches in drm_device::magiclist within all files with the same hash key |
59 | * the one with matching magic number, while holding the drm_device::struct_sem | 59 | * the one with matching magic number, while holding the drm_device::struct_mutex |
60 | * lock. | 60 | * lock. |
61 | */ | 61 | */ |
62 | static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic) | 62 | static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic) |
@@ -65,14 +65,14 @@ static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic) | |||
65 | drm_magic_entry_t *pt; | 65 | drm_magic_entry_t *pt; |
66 | int hash = drm_hash_magic(magic); | 66 | int hash = drm_hash_magic(magic); |
67 | 67 | ||
68 | down(&dev->struct_sem); | 68 | mutex_lock(&dev->struct_mutex); |
69 | for (pt = dev->magiclist[hash].head; pt; pt = pt->next) { | 69 | for (pt = dev->magiclist[hash].head; pt; pt = pt->next) { |
70 | if (pt->magic == magic) { | 70 | if (pt->magic == magic) { |
71 | retval = pt->priv; | 71 | retval = pt->priv; |
72 | break; | 72 | break; |
73 | } | 73 | } |
74 | } | 74 | } |
75 | up(&dev->struct_sem); | 75 | mutex_unlock(&dev->struct_mutex); |
76 | return retval; | 76 | return retval; |
77 | } | 77 | } |
78 | 78 | ||
@@ -85,7 +85,7 @@ static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic) | |||
85 | * | 85 | * |
86 | * Creates a drm_magic_entry structure and appends to the linked list | 86 | * Creates a drm_magic_entry structure and appends to the linked list |
87 | * associated the magic number hash key in drm_device::magiclist, while holding | 87 | * associated the magic number hash key in drm_device::magiclist, while holding |
88 | * the drm_device::struct_sem lock. | 88 | * the drm_device::struct_mutex lock. |
89 | */ | 89 | */ |
90 | static int drm_add_magic(drm_device_t * dev, drm_file_t * priv, | 90 | static int drm_add_magic(drm_device_t * dev, drm_file_t * priv, |
91 | drm_magic_t magic) | 91 | drm_magic_t magic) |
@@ -104,7 +104,7 @@ static int drm_add_magic(drm_device_t * dev, drm_file_t * priv, | |||
104 | entry->priv = priv; | 104 | entry->priv = priv; |
105 | entry->next = NULL; | 105 | entry->next = NULL; |
106 | 106 | ||
107 | down(&dev->struct_sem); | 107 | mutex_lock(&dev->struct_mutex); |
108 | if (dev->magiclist[hash].tail) { | 108 | if (dev->magiclist[hash].tail) { |
109 | dev->magiclist[hash].tail->next = entry; | 109 | dev->magiclist[hash].tail->next = entry; |
110 | dev->magiclist[hash].tail = entry; | 110 | dev->magiclist[hash].tail = entry; |
@@ -112,7 +112,7 @@ static int drm_add_magic(drm_device_t * dev, drm_file_t * priv, | |||
112 | dev->magiclist[hash].head = entry; | 112 | dev->magiclist[hash].head = entry; |
113 | dev->magiclist[hash].tail = entry; | 113 | dev->magiclist[hash].tail = entry; |
114 | } | 114 | } |
115 | up(&dev->struct_sem); | 115 | mutex_unlock(&dev->struct_mutex); |
116 | 116 | ||
117 | return 0; | 117 | return 0; |
118 | } | 118 | } |
@@ -124,7 +124,7 @@ static int drm_add_magic(drm_device_t * dev, drm_file_t * priv, | |||
124 | * \param magic magic number. | 124 | * \param magic magic number. |
125 | * | 125 | * |
126 | * Searches and unlinks the entry in drm_device::magiclist with the magic | 126 | * Searches and unlinks the entry in drm_device::magiclist with the magic |
127 | * number hash key, while holding the drm_device::struct_sem lock. | 127 | * number hash key, while holding the drm_device::struct_mutex lock. |
128 | */ | 128 | */ |
129 | static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic) | 129 | static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic) |
130 | { | 130 | { |
@@ -135,7 +135,7 @@ static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic) | |||
135 | DRM_DEBUG("%d\n", magic); | 135 | DRM_DEBUG("%d\n", magic); |
136 | hash = drm_hash_magic(magic); | 136 | hash = drm_hash_magic(magic); |
137 | 137 | ||
138 | down(&dev->struct_sem); | 138 | mutex_lock(&dev->struct_mutex); |
139 | for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) { | 139 | for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) { |
140 | if (pt->magic == magic) { | 140 | if (pt->magic == magic) { |
141 | if (dev->magiclist[hash].head == pt) { | 141 | if (dev->magiclist[hash].head == pt) { |
@@ -147,11 +147,11 @@ static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic) | |||
147 | if (prev) { | 147 | if (prev) { |
148 | prev->next = pt->next; | 148 | prev->next = pt->next; |
149 | } | 149 | } |
150 | up(&dev->struct_sem); | 150 | mutex_unlock(&dev->struct_mutex); |
151 | return 0; | 151 | return 0; |
152 | } | 152 | } |
153 | } | 153 | } |
154 | up(&dev->struct_sem); | 154 | mutex_unlock(&dev->struct_mutex); |
155 | 155 | ||
156 | drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); | 156 | drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); |
157 | 157 | ||
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index 1db12dcb6802..e2637b4d51de 100644 --- a/drivers/char/drm/drm_bufs.c +++ b/drivers/char/drm/drm_bufs.c | |||
@@ -255,14 +255,14 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, | |||
255 | memset(list, 0, sizeof(*list)); | 255 | memset(list, 0, sizeof(*list)); |
256 | list->map = map; | 256 | list->map = map; |
257 | 257 | ||
258 | down(&dev->struct_sem); | 258 | mutex_lock(&dev->struct_mutex); |
259 | list_add(&list->head, &dev->maplist->head); | 259 | list_add(&list->head, &dev->maplist->head); |
260 | /* Assign a 32-bit handle */ | 260 | /* Assign a 32-bit handle */ |
261 | /* We do it here so that dev->struct_sem protects the increment */ | 261 | /* We do it here so that dev->struct_mutex protects the increment */ |
262 | list->user_token = HandleID(map->type == _DRM_SHM | 262 | list->user_token = HandleID(map->type == _DRM_SHM |
263 | ? (unsigned long)map->handle | 263 | ? (unsigned long)map->handle |
264 | : map->offset, dev); | 264 | : map->offset, dev); |
265 | up(&dev->struct_sem); | 265 | mutex_unlock(&dev->struct_mutex); |
266 | 266 | ||
267 | *maplist = list; | 267 | *maplist = list; |
268 | return 0; | 268 | return 0; |
@@ -392,9 +392,9 @@ int drm_rmmap(drm_device_t *dev, drm_local_map_t *map) | |||
392 | { | 392 | { |
393 | int ret; | 393 | int ret; |
394 | 394 | ||
395 | down(&dev->struct_sem); | 395 | mutex_lock(&dev->struct_mutex); |
396 | ret = drm_rmmap_locked(dev, map); | 396 | ret = drm_rmmap_locked(dev, map); |
397 | up(&dev->struct_sem); | 397 | mutex_unlock(&dev->struct_mutex); |
398 | 398 | ||
399 | return ret; | 399 | return ret; |
400 | } | 400 | } |
@@ -423,7 +423,7 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp, | |||
423 | return -EFAULT; | 423 | return -EFAULT; |
424 | } | 424 | } |
425 | 425 | ||
426 | down(&dev->struct_sem); | 426 | mutex_lock(&dev->struct_mutex); |
427 | list_for_each(list, &dev->maplist->head) { | 427 | list_for_each(list, &dev->maplist->head) { |
428 | drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head); | 428 | drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head); |
429 | 429 | ||
@@ -439,7 +439,7 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp, | |||
439 | * find anything. | 439 | * find anything. |
440 | */ | 440 | */ |
441 | if (list == (&dev->maplist->head)) { | 441 | if (list == (&dev->maplist->head)) { |
442 | up(&dev->struct_sem); | 442 | mutex_unlock(&dev->struct_mutex); |
443 | return -EINVAL; | 443 | return -EINVAL; |
444 | } | 444 | } |
445 | 445 | ||
@@ -448,13 +448,13 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp, | |||
448 | 448 | ||
449 | /* Register and framebuffer maps are permanent */ | 449 | /* Register and framebuffer maps are permanent */ |
450 | if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) { | 450 | if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) { |
451 | up(&dev->struct_sem); | 451 | mutex_unlock(&dev->struct_mutex); |
452 | return 0; | 452 | return 0; |
453 | } | 453 | } |
454 | 454 | ||
455 | ret = drm_rmmap_locked(dev, map); | 455 | ret = drm_rmmap_locked(dev, map); |
456 | 456 | ||
457 | up(&dev->struct_sem); | 457 | mutex_unlock(&dev->struct_mutex); |
458 | 458 | ||
459 | return ret; | 459 | return ret; |
460 | } | 460 | } |
@@ -566,16 +566,16 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request) | |||
566 | atomic_inc(&dev->buf_alloc); | 566 | atomic_inc(&dev->buf_alloc); |
567 | spin_unlock(&dev->count_lock); | 567 | spin_unlock(&dev->count_lock); |
568 | 568 | ||
569 | down(&dev->struct_sem); | 569 | mutex_lock(&dev->struct_mutex); |
570 | entry = &dma->bufs[order]; | 570 | entry = &dma->bufs[order]; |
571 | if (entry->buf_count) { | 571 | if (entry->buf_count) { |
572 | up(&dev->struct_sem); | 572 | mutex_unlock(&dev->struct_mutex); |
573 | atomic_dec(&dev->buf_alloc); | 573 | atomic_dec(&dev->buf_alloc); |
574 | return -ENOMEM; /* May only call once for each order */ | 574 | return -ENOMEM; /* May only call once for each order */ |
575 | } | 575 | } |
576 | 576 | ||
577 | if (count < 0 || count > 4096) { | 577 | if (count < 0 || count > 4096) { |
578 | up(&dev->struct_sem); | 578 | mutex_unlock(&dev->struct_mutex); |
579 | atomic_dec(&dev->buf_alloc); | 579 | atomic_dec(&dev->buf_alloc); |
580 | return -EINVAL; | 580 | return -EINVAL; |
581 | } | 581 | } |
@@ -583,7 +583,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request) | |||
583 | entry->buflist = drm_alloc(count * sizeof(*entry->buflist), | 583 | entry->buflist = drm_alloc(count * sizeof(*entry->buflist), |
584 | DRM_MEM_BUFS); | 584 | DRM_MEM_BUFS); |
585 | if (!entry->buflist) { | 585 | if (!entry->buflist) { |
586 | up(&dev->struct_sem); | 586 | mutex_unlock(&dev->struct_mutex); |
587 | atomic_dec(&dev->buf_alloc); | 587 | atomic_dec(&dev->buf_alloc); |
588 | return -ENOMEM; | 588 | return -ENOMEM; |
589 | } | 589 | } |
@@ -616,7 +616,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request) | |||
616 | /* Set count correctly so we free the proper amount. */ | 616 | /* Set count correctly so we free the proper amount. */ |
617 | entry->buf_count = count; | 617 | entry->buf_count = count; |
618 | drm_cleanup_buf_error(dev, entry); | 618 | drm_cleanup_buf_error(dev, entry); |
619 | up(&dev->struct_sem); | 619 | mutex_unlock(&dev->struct_mutex); |
620 | atomic_dec(&dev->buf_alloc); | 620 | atomic_dec(&dev->buf_alloc); |
621 | return -ENOMEM; | 621 | return -ENOMEM; |
622 | } | 622 | } |
@@ -638,7 +638,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request) | |||
638 | if (!temp_buflist) { | 638 | if (!temp_buflist) { |
639 | /* Free the entry because it isn't valid */ | 639 | /* Free the entry because it isn't valid */ |
640 | drm_cleanup_buf_error(dev, entry); | 640 | drm_cleanup_buf_error(dev, entry); |
641 | up(&dev->struct_sem); | 641 | mutex_unlock(&dev->struct_mutex); |
642 | atomic_dec(&dev->buf_alloc); | 642 | atomic_dec(&dev->buf_alloc); |
643 | return -ENOMEM; | 643 | return -ENOMEM; |
644 | } | 644 | } |
@@ -656,7 +656,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request) | |||
656 | DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count); | 656 | DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count); |
657 | DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count); | 657 | DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count); |
658 | 658 | ||
659 | up(&dev->struct_sem); | 659 | mutex_unlock(&dev->struct_mutex); |
660 | 660 | ||
661 | request->count = entry->buf_count; | 661 | request->count = entry->buf_count; |
662 | request->size = size; | 662 | request->size = size; |
@@ -722,16 +722,16 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) | |||
722 | atomic_inc(&dev->buf_alloc); | 722 | atomic_inc(&dev->buf_alloc); |
723 | spin_unlock(&dev->count_lock); | 723 | spin_unlock(&dev->count_lock); |
724 | 724 | ||
725 | down(&dev->struct_sem); | 725 | mutex_lock(&dev->struct_mutex); |
726 | entry = &dma->bufs[order]; | 726 | entry = &dma->bufs[order]; |
727 | if (entry->buf_count) { | 727 | if (entry->buf_count) { |
728 | up(&dev->struct_sem); | 728 | mutex_unlock(&dev->struct_mutex); |
729 | atomic_dec(&dev->buf_alloc); | 729 | atomic_dec(&dev->buf_alloc); |
730 | return -ENOMEM; /* May only call once for each order */ | 730 | return -ENOMEM; /* May only call once for each order */ |
731 | } | 731 | } |
732 | 732 | ||
733 | if (count < 0 || count > 4096) { | 733 | if (count < 0 || count > 4096) { |
734 | up(&dev->struct_sem); | 734 | mutex_unlock(&dev->struct_mutex); |
735 | atomic_dec(&dev->buf_alloc); | 735 | atomic_dec(&dev->buf_alloc); |
736 | return -EINVAL; | 736 | return -EINVAL; |
737 | } | 737 | } |
@@ -739,7 +739,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) | |||
739 | entry->buflist = drm_alloc(count * sizeof(*entry->buflist), | 739 | entry->buflist = drm_alloc(count * sizeof(*entry->buflist), |
740 | DRM_MEM_BUFS); | 740 | DRM_MEM_BUFS); |
741 | if (!entry->buflist) { | 741 | if (!entry->buflist) { |
742 | up(&dev->struct_sem); | 742 | mutex_unlock(&dev->struct_mutex); |
743 | atomic_dec(&dev->buf_alloc); | 743 | atomic_dec(&dev->buf_alloc); |
744 | return -ENOMEM; | 744 | return -ENOMEM; |
745 | } | 745 | } |
@@ -750,7 +750,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) | |||
750 | if (!entry->seglist) { | 750 | if (!entry->seglist) { |
751 | drm_free(entry->buflist, | 751 | drm_free(entry->buflist, |
752 | count * sizeof(*entry->buflist), DRM_MEM_BUFS); | 752 | count * sizeof(*entry->buflist), DRM_MEM_BUFS); |
753 | up(&dev->struct_sem); | 753 | mutex_unlock(&dev->struct_mutex); |
754 | atomic_dec(&dev->buf_alloc); | 754 | atomic_dec(&dev->buf_alloc); |
755 | return -ENOMEM; | 755 | return -ENOMEM; |
756 | } | 756 | } |
@@ -766,7 +766,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) | |||
766 | count * sizeof(*entry->buflist), DRM_MEM_BUFS); | 766 | count * sizeof(*entry->buflist), DRM_MEM_BUFS); |
767 | drm_free(entry->seglist, | 767 | drm_free(entry->seglist, |
768 | count * sizeof(*entry->seglist), DRM_MEM_SEGS); | 768 | count * sizeof(*entry->seglist), DRM_MEM_SEGS); |
769 | up(&dev->struct_sem); | 769 | mutex_unlock(&dev->struct_mutex); |
770 | atomic_dec(&dev->buf_alloc); | 770 | atomic_dec(&dev->buf_alloc); |
771 | return -ENOMEM; | 771 | return -ENOMEM; |
772 | } | 772 | } |
@@ -790,7 +790,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) | |||
790 | drm_free(temp_pagelist, | 790 | drm_free(temp_pagelist, |
791 | (dma->page_count + (count << page_order)) | 791 | (dma->page_count + (count << page_order)) |
792 | * sizeof(*dma->pagelist), DRM_MEM_PAGES); | 792 | * sizeof(*dma->pagelist), DRM_MEM_PAGES); |
793 | up(&dev->struct_sem); | 793 | mutex_unlock(&dev->struct_mutex); |
794 | atomic_dec(&dev->buf_alloc); | 794 | atomic_dec(&dev->buf_alloc); |
795 | return -ENOMEM; | 795 | return -ENOMEM; |
796 | } | 796 | } |
@@ -831,7 +831,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) | |||
831 | (count << page_order)) | 831 | (count << page_order)) |
832 | * sizeof(*dma->pagelist), | 832 | * sizeof(*dma->pagelist), |
833 | DRM_MEM_PAGES); | 833 | DRM_MEM_PAGES); |
834 | up(&dev->struct_sem); | 834 | mutex_unlock(&dev->struct_mutex); |
835 | atomic_dec(&dev->buf_alloc); | 835 | atomic_dec(&dev->buf_alloc); |
836 | return -ENOMEM; | 836 | return -ENOMEM; |
837 | } | 837 | } |
@@ -853,7 +853,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) | |||
853 | drm_free(temp_pagelist, | 853 | drm_free(temp_pagelist, |
854 | (dma->page_count + (count << page_order)) | 854 | (dma->page_count + (count << page_order)) |
855 | * sizeof(*dma->pagelist), DRM_MEM_PAGES); | 855 | * sizeof(*dma->pagelist), DRM_MEM_PAGES); |
856 | up(&dev->struct_sem); | 856 | mutex_unlock(&dev->struct_mutex); |
857 | atomic_dec(&dev->buf_alloc); | 857 | atomic_dec(&dev->buf_alloc); |
858 | return -ENOMEM; | 858 | return -ENOMEM; |
859 | } | 859 | } |
@@ -878,7 +878,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) | |||
878 | dma->page_count += entry->seg_count << page_order; | 878 | dma->page_count += entry->seg_count << page_order; |
879 | dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order); | 879 | dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order); |
880 | 880 | ||
881 | up(&dev->struct_sem); | 881 | mutex_unlock(&dev->struct_mutex); |
882 | 882 | ||
883 | request->count = entry->buf_count; | 883 | request->count = entry->buf_count; |
884 | request->size = size; | 884 | request->size = size; |
@@ -948,16 +948,16 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request) | |||
948 | atomic_inc(&dev->buf_alloc); | 948 | atomic_inc(&dev->buf_alloc); |
949 | spin_unlock(&dev->count_lock); | 949 | spin_unlock(&dev->count_lock); |
950 | 950 | ||
951 | down(&dev->struct_sem); | 951 | mutex_lock(&dev->struct_mutex); |
952 | entry = &dma->bufs[order]; | 952 | entry = &dma->bufs[order]; |
953 | if (entry->buf_count) { | 953 | if (entry->buf_count) { |
954 | up(&dev->struct_sem); | 954 | mutex_unlock(&dev->struct_mutex); |
955 | atomic_dec(&dev->buf_alloc); | 955 | atomic_dec(&dev->buf_alloc); |
956 | return -ENOMEM; /* May only call once for each order */ | 956 | return -ENOMEM; /* May only call once for each order */ |
957 | } | 957 | } |
958 | 958 | ||
959 | if (count < 0 || count > 4096) { | 959 | if (count < 0 || count > 4096) { |
960 | up(&dev->struct_sem); | 960 | mutex_unlock(&dev->struct_mutex); |
961 | atomic_dec(&dev->buf_alloc); | 961 | atomic_dec(&dev->buf_alloc); |
962 | return -EINVAL; | 962 | return -EINVAL; |
963 | } | 963 | } |
@@ -965,7 +965,7 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request) | |||
965 | entry->buflist = drm_alloc(count * sizeof(*entry->buflist), | 965 | entry->buflist = drm_alloc(count * sizeof(*entry->buflist), |
966 | DRM_MEM_BUFS); | 966 | DRM_MEM_BUFS); |
967 | if (!entry->buflist) { | 967 | if (!entry->buflist) { |
968 | up(&dev->struct_sem); | 968 | mutex_unlock(&dev->struct_mutex); |
969 | atomic_dec(&dev->buf_alloc); | 969 | atomic_dec(&dev->buf_alloc); |
970 | return -ENOMEM; | 970 | return -ENOMEM; |
971 | } | 971 | } |
@@ -999,7 +999,7 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request) | |||
999 | /* Set count correctly so we free the proper amount. */ | 999 | /* Set count correctly so we free the proper amount. */ |
1000 | entry->buf_count = count; | 1000 | entry->buf_count = count; |
1001 | drm_cleanup_buf_error(dev, entry); | 1001 | drm_cleanup_buf_error(dev, entry); |
1002 | up(&dev->struct_sem); | 1002 | mutex_unlock(&dev->struct_mutex); |
1003 | atomic_dec(&dev->buf_alloc); | 1003 | atomic_dec(&dev->buf_alloc); |
1004 | return -ENOMEM; | 1004 | return -ENOMEM; |
1005 | } | 1005 | } |
@@ -1022,7 +1022,7 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request) | |||
1022 | if (!temp_buflist) { | 1022 | if (!temp_buflist) { |
1023 | /* Free the entry because it isn't valid */ | 1023 | /* Free the entry because it isn't valid */ |
1024 | drm_cleanup_buf_error(dev, entry); | 1024 | drm_cleanup_buf_error(dev, entry); |
1025 | up(&dev->struct_sem); | 1025 | mutex_unlock(&dev->struct_mutex); |
1026 | atomic_dec(&dev->buf_alloc); | 1026 | atomic_dec(&dev->buf_alloc); |
1027 | return -ENOMEM; | 1027 | return -ENOMEM; |
1028 | } | 1028 | } |
@@ -1040,7 +1040,7 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request) | |||
1040 | DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count); | 1040 | DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count); |
1041 | DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count); | 1041 | DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count); |
1042 | 1042 | ||
1043 | up(&dev->struct_sem); | 1043 | mutex_unlock(&dev->struct_mutex); |
1044 | 1044 | ||
1045 | request->count = entry->buf_count; | 1045 | request->count = entry->buf_count; |
1046 | request->size = size; | 1046 | request->size = size; |
@@ -1110,16 +1110,16 @@ int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request) | |||
1110 | atomic_inc(&dev->buf_alloc); | 1110 | atomic_inc(&dev->buf_alloc); |
1111 | spin_unlock(&dev->count_lock); | 1111 | spin_unlock(&dev->count_lock); |
1112 | 1112 | ||
1113 | down(&dev->struct_sem); | 1113 | mutex_lock(&dev->struct_mutex); |
1114 | entry = &dma->bufs[order]; | 1114 | entry = &dma->bufs[order]; |
1115 | if (entry->buf_count) { | 1115 | if (entry->buf_count) { |
1116 | up(&dev->struct_sem); | 1116 | mutex_unlock(&dev->struct_mutex); |
1117 | atomic_dec(&dev->buf_alloc); | 1117 | atomic_dec(&dev->buf_alloc); |
1118 | return -ENOMEM; /* May only call once for each order */ | 1118 | return -ENOMEM; /* May only call once for each order */ |
1119 | } | 1119 | } |
1120 | 1120 | ||
1121 | if (count < 0 || count > 4096) { | 1121 | if (count < 0 || count > 4096) { |
1122 | up(&dev->struct_sem); | 1122 | mutex_unlock(&dev->struct_mutex); |
1123 | atomic_dec(&dev->buf_alloc); | 1123 | atomic_dec(&dev->buf_alloc); |
1124 | return -EINVAL; | 1124 | return -EINVAL; |
1125 | } | 1125 | } |
@@ -1127,7 +1127,7 @@ int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request) | |||
1127 | entry->buflist = drm_alloc(count * sizeof(*entry->buflist), | 1127 | entry->buflist = drm_alloc(count * sizeof(*entry->buflist), |
1128 | DRM_MEM_BUFS); | 1128 | DRM_MEM_BUFS); |
1129 | if (!entry->buflist) { | 1129 | if (!entry->buflist) { |
1130 | up(&dev->struct_sem); | 1130 | mutex_unlock(&dev->struct_mutex); |
1131 | atomic_dec(&dev->buf_alloc); | 1131 | atomic_dec(&dev->buf_alloc); |
1132 | return -ENOMEM; | 1132 | return -ENOMEM; |
1133 | } | 1133 | } |
@@ -1160,7 +1160,7 @@ int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request) | |||
1160 | /* Set count correctly so we free the proper amount. */ | 1160 | /* Set count correctly so we free the proper amount. */ |
1161 | entry->buf_count = count; | 1161 | entry->buf_count = count; |
1162 | drm_cleanup_buf_error(dev, entry); | 1162 | drm_cleanup_buf_error(dev, entry); |
1163 | up(&dev->struct_sem); | 1163 | mutex_unlock(&dev->struct_mutex); |
1164 | atomic_dec(&dev->buf_alloc); | 1164 | atomic_dec(&dev->buf_alloc); |
1165 | return -ENOMEM; | 1165 | return -ENOMEM; |
1166 | } | 1166 | } |
@@ -1182,7 +1182,7 @@ int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request) | |||
1182 | if (!temp_buflist) { | 1182 | if (!temp_buflist) { |
1183 | /* Free the entry because it isn't valid */ | 1183 | /* Free the entry because it isn't valid */ |
1184 | drm_cleanup_buf_error(dev, entry); | 1184 | drm_cleanup_buf_error(dev, entry); |
1185 | up(&dev->struct_sem); | 1185 | mutex_unlock(&dev->struct_mutex); |
1186 | atomic_dec(&dev->buf_alloc); | 1186 | atomic_dec(&dev->buf_alloc); |
1187 | return -ENOMEM; | 1187 | return -ENOMEM; |
1188 | } | 1188 | } |
@@ -1200,7 +1200,7 @@ int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request) | |||
1200 | DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count); | 1200 | DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count); |
1201 | DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count); | 1201 | DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count); |
1202 | 1202 | ||
1203 | up(&dev->struct_sem); | 1203 | mutex_unlock(&dev->struct_mutex); |
1204 | 1204 | ||
1205 | request->count = entry->buf_count; | 1205 | request->count = entry->buf_count; |
1206 | request->size = size; | 1206 | request->size = size; |
diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c index f84254526949..83094c73da67 100644 --- a/drivers/char/drm/drm_context.c +++ b/drivers/char/drm/drm_context.c | |||
@@ -53,7 +53,7 @@ | |||
53 | * \param ctx_handle context handle. | 53 | * \param ctx_handle context handle. |
54 | * | 54 | * |
55 | * Clears the bit specified by \p ctx_handle in drm_device::ctx_bitmap and the entry | 55 | * Clears the bit specified by \p ctx_handle in drm_device::ctx_bitmap and the entry |
56 | * in drm_device::context_sareas, while holding the drm_device::struct_sem | 56 | * in drm_device::context_sareas, while holding the drm_device::struct_mutex |
57 | * lock. | 57 | * lock. |
58 | */ | 58 | */ |
59 | void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle) | 59 | void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle) |
@@ -64,10 +64,10 @@ void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle) | |||
64 | goto failed; | 64 | goto failed; |
65 | 65 | ||
66 | if (ctx_handle < DRM_MAX_CTXBITMAP) { | 66 | if (ctx_handle < DRM_MAX_CTXBITMAP) { |
67 | down(&dev->struct_sem); | 67 | mutex_lock(&dev->struct_mutex); |
68 | clear_bit(ctx_handle, dev->ctx_bitmap); | 68 | clear_bit(ctx_handle, dev->ctx_bitmap); |
69 | dev->context_sareas[ctx_handle] = NULL; | 69 | dev->context_sareas[ctx_handle] = NULL; |
70 | up(&dev->struct_sem); | 70 | mutex_unlock(&dev->struct_mutex); |
71 | return; | 71 | return; |
72 | } | 72 | } |
73 | failed: | 73 | failed: |
@@ -83,7 +83,7 @@ void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle) | |||
83 | * | 83 | * |
84 | * Find the first zero bit in drm_device::ctx_bitmap and (re)allocates | 84 | * Find the first zero bit in drm_device::ctx_bitmap and (re)allocates |
85 | * drm_device::context_sareas to accommodate the new entry while holding the | 85 | * drm_device::context_sareas to accommodate the new entry while holding the |
86 | * drm_device::struct_sem lock. | 86 | * drm_device::struct_mutex lock. |
87 | */ | 87 | */ |
88 | static int drm_ctxbitmap_next(drm_device_t * dev) | 88 | static int drm_ctxbitmap_next(drm_device_t * dev) |
89 | { | 89 | { |
@@ -92,7 +92,7 @@ static int drm_ctxbitmap_next(drm_device_t * dev) | |||
92 | if (!dev->ctx_bitmap) | 92 | if (!dev->ctx_bitmap) |
93 | return -1; | 93 | return -1; |
94 | 94 | ||
95 | down(&dev->struct_sem); | 95 | mutex_lock(&dev->struct_mutex); |
96 | bit = find_first_zero_bit(dev->ctx_bitmap, DRM_MAX_CTXBITMAP); | 96 | bit = find_first_zero_bit(dev->ctx_bitmap, DRM_MAX_CTXBITMAP); |
97 | if (bit < DRM_MAX_CTXBITMAP) { | 97 | if (bit < DRM_MAX_CTXBITMAP) { |
98 | set_bit(bit, dev->ctx_bitmap); | 98 | set_bit(bit, dev->ctx_bitmap); |
@@ -113,7 +113,7 @@ static int drm_ctxbitmap_next(drm_device_t * dev) | |||
113 | DRM_MEM_MAPS); | 113 | DRM_MEM_MAPS); |
114 | if (!ctx_sareas) { | 114 | if (!ctx_sareas) { |
115 | clear_bit(bit, dev->ctx_bitmap); | 115 | clear_bit(bit, dev->ctx_bitmap); |
116 | up(&dev->struct_sem); | 116 | mutex_unlock(&dev->struct_mutex); |
117 | return -1; | 117 | return -1; |
118 | } | 118 | } |
119 | dev->context_sareas = ctx_sareas; | 119 | dev->context_sareas = ctx_sareas; |
@@ -126,16 +126,16 @@ static int drm_ctxbitmap_next(drm_device_t * dev) | |||
126 | DRM_MEM_MAPS); | 126 | DRM_MEM_MAPS); |
127 | if (!dev->context_sareas) { | 127 | if (!dev->context_sareas) { |
128 | clear_bit(bit, dev->ctx_bitmap); | 128 | clear_bit(bit, dev->ctx_bitmap); |
129 | up(&dev->struct_sem); | 129 | mutex_unlock(&dev->struct_mutex); |
130 | return -1; | 130 | return -1; |
131 | } | 131 | } |
132 | dev->context_sareas[bit] = NULL; | 132 | dev->context_sareas[bit] = NULL; |
133 | } | 133 | } |
134 | } | 134 | } |
135 | up(&dev->struct_sem); | 135 | mutex_unlock(&dev->struct_mutex); |
136 | return bit; | 136 | return bit; |
137 | } | 137 | } |
138 | up(&dev->struct_sem); | 138 | mutex_unlock(&dev->struct_mutex); |
139 | return -1; | 139 | return -1; |
140 | } | 140 | } |
141 | 141 | ||
@@ -145,24 +145,24 @@ static int drm_ctxbitmap_next(drm_device_t * dev) | |||
145 | * \param dev DRM device. | 145 | * \param dev DRM device. |
146 | * | 146 | * |
147 | * Allocates and initialize drm_device::ctx_bitmap and drm_device::context_sareas, while holding | 147 | * Allocates and initialize drm_device::ctx_bitmap and drm_device::context_sareas, while holding |
148 | * the drm_device::struct_sem lock. | 148 | * the drm_device::struct_mutex lock. |
149 | */ | 149 | */ |
150 | int drm_ctxbitmap_init(drm_device_t * dev) | 150 | int drm_ctxbitmap_init(drm_device_t * dev) |
151 | { | 151 | { |
152 | int i; | 152 | int i; |
153 | int temp; | 153 | int temp; |
154 | 154 | ||
155 | down(&dev->struct_sem); | 155 | mutex_lock(&dev->struct_mutex); |
156 | dev->ctx_bitmap = (unsigned long *)drm_alloc(PAGE_SIZE, | 156 | dev->ctx_bitmap = (unsigned long *)drm_alloc(PAGE_SIZE, |
157 | DRM_MEM_CTXBITMAP); | 157 | DRM_MEM_CTXBITMAP); |
158 | if (dev->ctx_bitmap == NULL) { | 158 | if (dev->ctx_bitmap == NULL) { |
159 | up(&dev->struct_sem); | 159 | mutex_unlock(&dev->struct_mutex); |
160 | return -ENOMEM; | 160 | return -ENOMEM; |
161 | } | 161 | } |
162 | memset((void *)dev->ctx_bitmap, 0, PAGE_SIZE); | 162 | memset((void *)dev->ctx_bitmap, 0, PAGE_SIZE); |
163 | dev->context_sareas = NULL; | 163 | dev->context_sareas = NULL; |
164 | dev->max_context = -1; | 164 | dev->max_context = -1; |
165 | up(&dev->struct_sem); | 165 | mutex_unlock(&dev->struct_mutex); |
166 | 166 | ||
167 | for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { | 167 | for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { |
168 | temp = drm_ctxbitmap_next(dev); | 168 | temp = drm_ctxbitmap_next(dev); |
@@ -178,17 +178,17 @@ int drm_ctxbitmap_init(drm_device_t * dev) | |||
178 | * \param dev DRM device. | 178 | * \param dev DRM device. |
179 | * | 179 | * |
180 | * Frees drm_device::ctx_bitmap and drm_device::context_sareas, while holding | 180 | * Frees drm_device::ctx_bitmap and drm_device::context_sareas, while holding |
181 | * the drm_device::struct_sem lock. | 181 | * the drm_device::struct_mutex lock. |
182 | */ | 182 | */ |
183 | void drm_ctxbitmap_cleanup(drm_device_t * dev) | 183 | void drm_ctxbitmap_cleanup(drm_device_t * dev) |
184 | { | 184 | { |
185 | down(&dev->struct_sem); | 185 | mutex_lock(&dev->struct_mutex); |
186 | if (dev->context_sareas) | 186 | if (dev->context_sareas) |
187 | drm_free(dev->context_sareas, | 187 | drm_free(dev->context_sareas, |
188 | sizeof(*dev->context_sareas) * | 188 | sizeof(*dev->context_sareas) * |
189 | dev->max_context, DRM_MEM_MAPS); | 189 | dev->max_context, DRM_MEM_MAPS); |
190 | drm_free((void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP); | 190 | drm_free((void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP); |
191 | up(&dev->struct_sem); | 191 | mutex_unlock(&dev->struct_mutex); |
192 | } | 192 | } |
193 | 193 | ||
194 | /*@}*/ | 194 | /*@}*/ |
@@ -222,15 +222,15 @@ int drm_getsareactx(struct inode *inode, struct file *filp, | |||
222 | if (copy_from_user(&request, argp, sizeof(request))) | 222 | if (copy_from_user(&request, argp, sizeof(request))) |
223 | return -EFAULT; | 223 | return -EFAULT; |
224 | 224 | ||
225 | down(&dev->struct_sem); | 225 | mutex_lock(&dev->struct_mutex); |
226 | if (dev->max_context < 0 | 226 | if (dev->max_context < 0 |
227 | || request.ctx_id >= (unsigned)dev->max_context) { | 227 | || request.ctx_id >= (unsigned)dev->max_context) { |
228 | up(&dev->struct_sem); | 228 | mutex_unlock(&dev->struct_mutex); |
229 | return -EINVAL; | 229 | return -EINVAL; |
230 | } | 230 | } |
231 | 231 | ||
232 | map = dev->context_sareas[request.ctx_id]; | 232 | map = dev->context_sareas[request.ctx_id]; |
233 | up(&dev->struct_sem); | 233 | mutex_unlock(&dev->struct_mutex); |
234 | 234 | ||
235 | request.handle = NULL; | 235 | request.handle = NULL; |
236 | list_for_each_entry(_entry, &dev->maplist->head, head) { | 236 | list_for_each_entry(_entry, &dev->maplist->head, head) { |
@@ -274,7 +274,7 @@ int drm_setsareactx(struct inode *inode, struct file *filp, | |||
274 | (drm_ctx_priv_map_t __user *) arg, sizeof(request))) | 274 | (drm_ctx_priv_map_t __user *) arg, sizeof(request))) |
275 | return -EFAULT; | 275 | return -EFAULT; |
276 | 276 | ||
277 | down(&dev->struct_sem); | 277 | mutex_lock(&dev->struct_mutex); |
278 | list_for_each(list, &dev->maplist->head) { | 278 | list_for_each(list, &dev->maplist->head) { |
279 | r_list = list_entry(list, drm_map_list_t, head); | 279 | r_list = list_entry(list, drm_map_list_t, head); |
280 | if (r_list->map | 280 | if (r_list->map |
@@ -282,7 +282,7 @@ int drm_setsareactx(struct inode *inode, struct file *filp, | |||
282 | goto found; | 282 | goto found; |
283 | } | 283 | } |
284 | bad: | 284 | bad: |
285 | up(&dev->struct_sem); | 285 | mutex_unlock(&dev->struct_mutex); |
286 | return -EINVAL; | 286 | return -EINVAL; |
287 | 287 | ||
288 | found: | 288 | found: |
@@ -294,7 +294,7 @@ int drm_setsareactx(struct inode *inode, struct file *filp, | |||
294 | if (request.ctx_id >= (unsigned)dev->max_context) | 294 | if (request.ctx_id >= (unsigned)dev->max_context) |
295 | goto bad; | 295 | goto bad; |
296 | dev->context_sareas[request.ctx_id] = map; | 296 | dev->context_sareas[request.ctx_id] = map; |
297 | up(&dev->struct_sem); | 297 | mutex_unlock(&dev->struct_mutex); |
298 | return 0; | 298 | return 0; |
299 | } | 299 | } |
300 | 300 | ||
@@ -448,10 +448,10 @@ int drm_addctx(struct inode *inode, struct file *filp, | |||
448 | ctx_entry->handle = ctx.handle; | 448 | ctx_entry->handle = ctx.handle; |
449 | ctx_entry->tag = priv; | 449 | ctx_entry->tag = priv; |
450 | 450 | ||
451 | down(&dev->ctxlist_sem); | 451 | mutex_lock(&dev->ctxlist_mutex); |
452 | list_add(&ctx_entry->head, &dev->ctxlist->head); | 452 | list_add(&ctx_entry->head, &dev->ctxlist->head); |
453 | ++dev->ctx_count; | 453 | ++dev->ctx_count; |
454 | up(&dev->ctxlist_sem); | 454 | mutex_unlock(&dev->ctxlist_mutex); |
455 | 455 | ||
456 | if (copy_to_user(argp, &ctx, sizeof(ctx))) | 456 | if (copy_to_user(argp, &ctx, sizeof(ctx))) |
457 | return -EFAULT; | 457 | return -EFAULT; |
@@ -574,7 +574,7 @@ int drm_rmctx(struct inode *inode, struct file *filp, | |||
574 | drm_ctxbitmap_free(dev, ctx.handle); | 574 | drm_ctxbitmap_free(dev, ctx.handle); |
575 | } | 575 | } |
576 | 576 | ||
577 | down(&dev->ctxlist_sem); | 577 | mutex_lock(&dev->ctxlist_mutex); |
578 | if (!list_empty(&dev->ctxlist->head)) { | 578 | if (!list_empty(&dev->ctxlist->head)) { |
579 | drm_ctx_list_t *pos, *n; | 579 | drm_ctx_list_t *pos, *n; |
580 | 580 | ||
@@ -586,7 +586,7 @@ int drm_rmctx(struct inode *inode, struct file *filp, | |||
586 | } | 586 | } |
587 | } | 587 | } |
588 | } | 588 | } |
589 | up(&dev->ctxlist_sem); | 589 | mutex_unlock(&dev->ctxlist_mutex); |
590 | 590 | ||
591 | return 0; | 591 | return 0; |
592 | } | 592 | } |
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c index c4fa5a29582b..dc6bbe8a18dc 100644 --- a/drivers/char/drm/drm_drv.c +++ b/drivers/char/drm/drm_drv.c | |||
@@ -151,7 +151,7 @@ int drm_lastclose(drm_device_t * dev) | |||
151 | if (dev->irq_enabled) | 151 | if (dev->irq_enabled) |
152 | drm_irq_uninstall(dev); | 152 | drm_irq_uninstall(dev); |
153 | 153 | ||
154 | down(&dev->struct_sem); | 154 | mutex_lock(&dev->struct_mutex); |
155 | del_timer(&dev->timer); | 155 | del_timer(&dev->timer); |
156 | 156 | ||
157 | /* Clear pid list */ | 157 | /* Clear pid list */ |
@@ -231,7 +231,7 @@ int drm_lastclose(drm_device_t * dev) | |||
231 | dev->lock.filp = NULL; | 231 | dev->lock.filp = NULL; |
232 | wake_up_interruptible(&dev->lock.lock_queue); | 232 | wake_up_interruptible(&dev->lock.lock_queue); |
233 | } | 233 | } |
234 | up(&dev->struct_sem); | 234 | mutex_unlock(&dev->struct_mutex); |
235 | 235 | ||
236 | DRM_DEBUG("lastclose completed\n"); | 236 | DRM_DEBUG("lastclose completed\n"); |
237 | return 0; | 237 | return 0; |
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c index 403f44a1bf01..641f7633878c 100644 --- a/drivers/char/drm/drm_fops.c +++ b/drivers/char/drm/drm_fops.c | |||
@@ -262,7 +262,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, | |||
262 | goto out_free; | 262 | goto out_free; |
263 | } | 263 | } |
264 | 264 | ||
265 | down(&dev->struct_sem); | 265 | mutex_lock(&dev->struct_mutex); |
266 | if (!dev->file_last) { | 266 | if (!dev->file_last) { |
267 | priv->next = NULL; | 267 | priv->next = NULL; |
268 | priv->prev = NULL; | 268 | priv->prev = NULL; |
@@ -276,7 +276,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, | |||
276 | dev->file_last->next = priv; | 276 | dev->file_last->next = priv; |
277 | dev->file_last = priv; | 277 | dev->file_last = priv; |
278 | } | 278 | } |
279 | up(&dev->struct_sem); | 279 | mutex_unlock(&dev->struct_mutex); |
280 | 280 | ||
281 | #ifdef __alpha__ | 281 | #ifdef __alpha__ |
282 | /* | 282 | /* |
@@ -413,7 +413,7 @@ int drm_release(struct inode *inode, struct file *filp) | |||
413 | 413 | ||
414 | drm_fasync(-1, filp, 0); | 414 | drm_fasync(-1, filp, 0); |
415 | 415 | ||
416 | down(&dev->ctxlist_sem); | 416 | mutex_lock(&dev->ctxlist_mutex); |
417 | if (dev->ctxlist && (!list_empty(&dev->ctxlist->head))) { | 417 | if (dev->ctxlist && (!list_empty(&dev->ctxlist->head))) { |
418 | drm_ctx_list_t *pos, *n; | 418 | drm_ctx_list_t *pos, *n; |
419 | 419 | ||
@@ -432,9 +432,9 @@ int drm_release(struct inode *inode, struct file *filp) | |||
432 | } | 432 | } |
433 | } | 433 | } |
434 | } | 434 | } |
435 | up(&dev->ctxlist_sem); | 435 | mutex_unlock(&dev->ctxlist_mutex); |
436 | 436 | ||
437 | down(&dev->struct_sem); | 437 | mutex_lock(&dev->struct_mutex); |
438 | if (priv->remove_auth_on_close == 1) { | 438 | if (priv->remove_auth_on_close == 1) { |
439 | drm_file_t *temp = dev->file_first; | 439 | drm_file_t *temp = dev->file_first; |
440 | while (temp) { | 440 | while (temp) { |
@@ -452,7 +452,7 @@ int drm_release(struct inode *inode, struct file *filp) | |||
452 | } else { | 452 | } else { |
453 | dev->file_last = priv->prev; | 453 | dev->file_last = priv->prev; |
454 | } | 454 | } |
455 | up(&dev->struct_sem); | 455 | mutex_unlock(&dev->struct_mutex); |
456 | 456 | ||
457 | if (dev->driver->postclose) | 457 | if (dev->driver->postclose) |
458 | dev->driver->postclose(dev, priv); | 458 | dev->driver->postclose(dev, priv); |
diff --git a/drivers/char/drm/drm_ioctl.c b/drivers/char/drm/drm_ioctl.c index bcd4e604d3ec..555f323b8a32 100644 --- a/drivers/char/drm/drm_ioctl.c +++ b/drivers/char/drm/drm_ioctl.c | |||
@@ -194,9 +194,9 @@ int drm_getmap(struct inode *inode, struct file *filp, | |||
194 | return -EFAULT; | 194 | return -EFAULT; |
195 | idx = map.offset; | 195 | idx = map.offset; |
196 | 196 | ||
197 | down(&dev->struct_sem); | 197 | mutex_lock(&dev->struct_mutex); |
198 | if (idx < 0) { | 198 | if (idx < 0) { |
199 | up(&dev->struct_sem); | 199 | mutex_unlock(&dev->struct_mutex); |
200 | return -EINVAL; | 200 | return -EINVAL; |
201 | } | 201 | } |
202 | 202 | ||
@@ -209,7 +209,7 @@ int drm_getmap(struct inode *inode, struct file *filp, | |||
209 | i++; | 209 | i++; |
210 | } | 210 | } |
211 | if (!r_list || !r_list->map) { | 211 | if (!r_list || !r_list->map) { |
212 | up(&dev->struct_sem); | 212 | mutex_unlock(&dev->struct_mutex); |
213 | return -EINVAL; | 213 | return -EINVAL; |
214 | } | 214 | } |
215 | 215 | ||
@@ -219,7 +219,7 @@ int drm_getmap(struct inode *inode, struct file *filp, | |||
219 | map.flags = r_list->map->flags; | 219 | map.flags = r_list->map->flags; |
220 | map.handle = (void *)(unsigned long)r_list->user_token; | 220 | map.handle = (void *)(unsigned long)r_list->user_token; |
221 | map.mtrr = r_list->map->mtrr; | 221 | map.mtrr = r_list->map->mtrr; |
222 | up(&dev->struct_sem); | 222 | mutex_unlock(&dev->struct_mutex); |
223 | 223 | ||
224 | if (copy_to_user(argp, &map, sizeof(map))) | 224 | if (copy_to_user(argp, &map, sizeof(map))) |
225 | return -EFAULT; | 225 | return -EFAULT; |
@@ -253,11 +253,11 @@ int drm_getclient(struct inode *inode, struct file *filp, | |||
253 | if (copy_from_user(&client, argp, sizeof(client))) | 253 | if (copy_from_user(&client, argp, sizeof(client))) |
254 | return -EFAULT; | 254 | return -EFAULT; |
255 | idx = client.idx; | 255 | idx = client.idx; |
256 | down(&dev->struct_sem); | 256 | mutex_lock(&dev->struct_mutex); |
257 | for (i = 0, pt = dev->file_first; i < idx && pt; i++, pt = pt->next) ; | 257 | for (i = 0, pt = dev->file_first; i < idx && pt; i++, pt = pt->next) ; |
258 | 258 | ||
259 | if (!pt) { | 259 | if (!pt) { |
260 | up(&dev->struct_sem); | 260 | mutex_unlock(&dev->struct_mutex); |
261 | return -EINVAL; | 261 | return -EINVAL; |
262 | } | 262 | } |
263 | client.auth = pt->authenticated; | 263 | client.auth = pt->authenticated; |
@@ -265,7 +265,7 @@ int drm_getclient(struct inode *inode, struct file *filp, | |||
265 | client.uid = pt->uid; | 265 | client.uid = pt->uid; |
266 | client.magic = pt->magic; | 266 | client.magic = pt->magic; |
267 | client.iocs = pt->ioctl_count; | 267 | client.iocs = pt->ioctl_count; |
268 | up(&dev->struct_sem); | 268 | mutex_unlock(&dev->struct_mutex); |
269 | 269 | ||
270 | if (copy_to_user(argp, &client, sizeof(client))) | 270 | if (copy_to_user(argp, &client, sizeof(client))) |
271 | return -EFAULT; | 271 | return -EFAULT; |
@@ -292,7 +292,7 @@ int drm_getstats(struct inode *inode, struct file *filp, | |||
292 | 292 | ||
293 | memset(&stats, 0, sizeof(stats)); | 293 | memset(&stats, 0, sizeof(stats)); |
294 | 294 | ||
295 | down(&dev->struct_sem); | 295 | mutex_lock(&dev->struct_mutex); |
296 | 296 | ||
297 | for (i = 0; i < dev->counters; i++) { | 297 | for (i = 0; i < dev->counters; i++) { |
298 | if (dev->types[i] == _DRM_STAT_LOCK) | 298 | if (dev->types[i] == _DRM_STAT_LOCK) |
@@ -305,7 +305,7 @@ int drm_getstats(struct inode *inode, struct file *filp, | |||
305 | 305 | ||
306 | stats.count = dev->counters; | 306 | stats.count = dev->counters; |
307 | 307 | ||
308 | up(&dev->struct_sem); | 308 | mutex_unlock(&dev->struct_mutex); |
309 | 309 | ||
310 | if (copy_to_user((drm_stats_t __user *) arg, &stats, sizeof(stats))) | 310 | if (copy_to_user((drm_stats_t __user *) arg, &stats, sizeof(stats))) |
311 | return -EFAULT; | 311 | return -EFAULT; |
diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c index b0d4b236e837..611a1173091d 100644 --- a/drivers/char/drm/drm_irq.c +++ b/drivers/char/drm/drm_irq.c | |||
@@ -98,20 +98,20 @@ static int drm_irq_install(drm_device_t * dev) | |||
98 | if (dev->irq == 0) | 98 | if (dev->irq == 0) |
99 | return -EINVAL; | 99 | return -EINVAL; |
100 | 100 | ||
101 | down(&dev->struct_sem); | 101 | mutex_lock(&dev->struct_mutex); |
102 | 102 | ||
103 | /* Driver must have been initialized */ | 103 | /* Driver must have been initialized */ |
104 | if (!dev->dev_private) { | 104 | if (!dev->dev_private) { |
105 | up(&dev->struct_sem); | 105 | mutex_unlock(&dev->struct_mutex); |
106 | return -EINVAL; | 106 | return -EINVAL; |
107 | } | 107 | } |
108 | 108 | ||
109 | if (dev->irq_enabled) { | 109 | if (dev->irq_enabled) { |
110 | up(&dev->struct_sem); | 110 | mutex_unlock(&dev->struct_mutex); |
111 | return -EBUSY; | 111 | return -EBUSY; |
112 | } | 112 | } |
113 | dev->irq_enabled = 1; | 113 | dev->irq_enabled = 1; |
114 | up(&dev->struct_sem); | 114 | mutex_unlock(&dev->struct_mutex); |
115 | 115 | ||
116 | DRM_DEBUG("%s: irq=%d\n", __FUNCTION__, dev->irq); | 116 | DRM_DEBUG("%s: irq=%d\n", __FUNCTION__, dev->irq); |
117 | 117 | ||
@@ -135,9 +135,9 @@ static int drm_irq_install(drm_device_t * dev) | |||
135 | ret = request_irq(dev->irq, dev->driver->irq_handler, | 135 | ret = request_irq(dev->irq, dev->driver->irq_handler, |
136 | sh_flags, dev->devname, dev); | 136 | sh_flags, dev->devname, dev); |
137 | if (ret < 0) { | 137 | if (ret < 0) { |
138 | down(&dev->struct_sem); | 138 | mutex_lock(&dev->struct_mutex); |
139 | dev->irq_enabled = 0; | 139 | dev->irq_enabled = 0; |
140 | up(&dev->struct_sem); | 140 | mutex_unlock(&dev->struct_mutex); |
141 | return ret; | 141 | return ret; |
142 | } | 142 | } |
143 | 143 | ||
@@ -161,10 +161,10 @@ int drm_irq_uninstall(drm_device_t * dev) | |||
161 | if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) | 161 | if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) |
162 | return -EINVAL; | 162 | return -EINVAL; |
163 | 163 | ||
164 | down(&dev->struct_sem); | 164 | mutex_lock(&dev->struct_mutex); |
165 | irq_enabled = dev->irq_enabled; | 165 | irq_enabled = dev->irq_enabled; |
166 | dev->irq_enabled = 0; | 166 | dev->irq_enabled = 0; |
167 | up(&dev->struct_sem); | 167 | mutex_unlock(&dev->struct_mutex); |
168 | 168 | ||
169 | if (!irq_enabled) | 169 | if (!irq_enabled) |
170 | return -EINVAL; | 170 | return -EINVAL; |
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h index 5b1d3a04458d..8fd6357a48da 100644 --- a/drivers/char/drm/drm_pciids.h +++ b/drivers/char/drm/drm_pciids.h | |||
@@ -3,6 +3,7 @@ | |||
3 | Please contact dri-devel@lists.sf.net to add new cards to this list | 3 | Please contact dri-devel@lists.sf.net to add new cards to this list |
4 | */ | 4 | */ |
5 | #define radeon_PCI_IDS \ | 5 | #define radeon_PCI_IDS \ |
6 | {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350},\ | ||
6 | {0x1002, 0x4136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP}, \ | 7 | {0x1002, 0x4136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP}, \ |
7 | {0x1002, 0x4137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \ | 8 | {0x1002, 0x4137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \ |
8 | {0x1002, 0x4144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ | 9 | {0x1002, 0x4144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ |
@@ -242,5 +243,6 @@ | |||
242 | {0x8086, 0x2582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 243 | {0x8086, 0x2582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
243 | {0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 244 | {0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
244 | {0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 245 | {0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
246 | {0x8086, 0x27a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
245 | {0, 0, 0} | 247 | {0, 0, 0} |
246 | 248 | ||
diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c index 6f943e3309ef..362a270af0f1 100644 --- a/drivers/char/drm/drm_proc.c +++ b/drivers/char/drm/drm_proc.c | |||
@@ -258,7 +258,7 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request, | |||
258 | } | 258 | } |
259 | 259 | ||
260 | /** | 260 | /** |
261 | * Simply calls _vm_info() while holding the drm_device::struct_sem lock. | 261 | * Simply calls _vm_info() while holding the drm_device::struct_mutex lock. |
262 | */ | 262 | */ |
263 | static int drm_vm_info(char *buf, char **start, off_t offset, int request, | 263 | static int drm_vm_info(char *buf, char **start, off_t offset, int request, |
264 | int *eof, void *data) | 264 | int *eof, void *data) |
@@ -266,9 +266,9 @@ static int drm_vm_info(char *buf, char **start, off_t offset, int request, | |||
266 | drm_device_t *dev = (drm_device_t *) data; | 266 | drm_device_t *dev = (drm_device_t *) data; |
267 | int ret; | 267 | int ret; |
268 | 268 | ||
269 | down(&dev->struct_sem); | 269 | mutex_lock(&dev->struct_mutex); |
270 | ret = drm__vm_info(buf, start, offset, request, eof, data); | 270 | ret = drm__vm_info(buf, start, offset, request, eof, data); |
271 | up(&dev->struct_sem); | 271 | mutex_unlock(&dev->struct_mutex); |
272 | return ret; | 272 | return ret; |
273 | } | 273 | } |
274 | 274 | ||
@@ -331,7 +331,7 @@ static int drm__queues_info(char *buf, char **start, off_t offset, | |||
331 | } | 331 | } |
332 | 332 | ||
333 | /** | 333 | /** |
334 | * Simply calls _queues_info() while holding the drm_device::struct_sem lock. | 334 | * Simply calls _queues_info() while holding the drm_device::struct_mutex lock. |
335 | */ | 335 | */ |
336 | static int drm_queues_info(char *buf, char **start, off_t offset, int request, | 336 | static int drm_queues_info(char *buf, char **start, off_t offset, int request, |
337 | int *eof, void *data) | 337 | int *eof, void *data) |
@@ -339,9 +339,9 @@ static int drm_queues_info(char *buf, char **start, off_t offset, int request, | |||
339 | drm_device_t *dev = (drm_device_t *) data; | 339 | drm_device_t *dev = (drm_device_t *) data; |
340 | int ret; | 340 | int ret; |
341 | 341 | ||
342 | down(&dev->struct_sem); | 342 | mutex_lock(&dev->struct_mutex); |
343 | ret = drm__queues_info(buf, start, offset, request, eof, data); | 343 | ret = drm__queues_info(buf, start, offset, request, eof, data); |
344 | up(&dev->struct_sem); | 344 | mutex_unlock(&dev->struct_mutex); |
345 | return ret; | 345 | return ret; |
346 | } | 346 | } |
347 | 347 | ||
@@ -403,7 +403,7 @@ static int drm__bufs_info(char *buf, char **start, off_t offset, int request, | |||
403 | } | 403 | } |
404 | 404 | ||
405 | /** | 405 | /** |
406 | * Simply calls _bufs_info() while holding the drm_device::struct_sem lock. | 406 | * Simply calls _bufs_info() while holding the drm_device::struct_mutex lock. |
407 | */ | 407 | */ |
408 | static int drm_bufs_info(char *buf, char **start, off_t offset, int request, | 408 | static int drm_bufs_info(char *buf, char **start, off_t offset, int request, |
409 | int *eof, void *data) | 409 | int *eof, void *data) |
@@ -411,9 +411,9 @@ static int drm_bufs_info(char *buf, char **start, off_t offset, int request, | |||
411 | drm_device_t *dev = (drm_device_t *) data; | 411 | drm_device_t *dev = (drm_device_t *) data; |
412 | int ret; | 412 | int ret; |
413 | 413 | ||
414 | down(&dev->struct_sem); | 414 | mutex_lock(&dev->struct_mutex); |
415 | ret = drm__bufs_info(buf, start, offset, request, eof, data); | 415 | ret = drm__bufs_info(buf, start, offset, request, eof, data); |
416 | up(&dev->struct_sem); | 416 | mutex_unlock(&dev->struct_mutex); |
417 | return ret; | 417 | return ret; |
418 | } | 418 | } |
419 | 419 | ||
@@ -459,7 +459,7 @@ static int drm__clients_info(char *buf, char **start, off_t offset, | |||
459 | } | 459 | } |
460 | 460 | ||
461 | /** | 461 | /** |
462 | * Simply calls _clients_info() while holding the drm_device::struct_sem lock. | 462 | * Simply calls _clients_info() while holding the drm_device::struct_mutex lock. |
463 | */ | 463 | */ |
464 | static int drm_clients_info(char *buf, char **start, off_t offset, | 464 | static int drm_clients_info(char *buf, char **start, off_t offset, |
465 | int request, int *eof, void *data) | 465 | int request, int *eof, void *data) |
@@ -467,9 +467,9 @@ static int drm_clients_info(char *buf, char **start, off_t offset, | |||
467 | drm_device_t *dev = (drm_device_t *) data; | 467 | drm_device_t *dev = (drm_device_t *) data; |
468 | int ret; | 468 | int ret; |
469 | 469 | ||
470 | down(&dev->struct_sem); | 470 | mutex_lock(&dev->struct_mutex); |
471 | ret = drm__clients_info(buf, start, offset, request, eof, data); | 471 | ret = drm__clients_info(buf, start, offset, request, eof, data); |
472 | up(&dev->struct_sem); | 472 | mutex_unlock(&dev->struct_mutex); |
473 | return ret; | 473 | return ret; |
474 | } | 474 | } |
475 | 475 | ||
@@ -540,9 +540,9 @@ static int drm_vma_info(char *buf, char **start, off_t offset, int request, | |||
540 | drm_device_t *dev = (drm_device_t *) data; | 540 | drm_device_t *dev = (drm_device_t *) data; |
541 | int ret; | 541 | int ret; |
542 | 542 | ||
543 | down(&dev->struct_sem); | 543 | mutex_lock(&dev->struct_mutex); |
544 | ret = drm__vma_info(buf, start, offset, request, eof, data); | 544 | ret = drm__vma_info(buf, start, offset, request, eof, data); |
545 | up(&dev->struct_sem); | 545 | mutex_unlock(&dev->struct_mutex); |
546 | return ret; | 546 | return ret; |
547 | } | 547 | } |
548 | #endif | 548 | #endif |
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c index 42d766359caa..68073e14fdec 100644 --- a/drivers/char/drm/drm_stub.c +++ b/drivers/char/drm/drm_stub.c | |||
@@ -50,7 +50,7 @@ module_param_named(cards_limit, drm_cards_limit, int, 0444); | |||
50 | module_param_named(debug, drm_debug, int, 0600); | 50 | module_param_named(debug, drm_debug, int, 0600); |
51 | 51 | ||
52 | drm_head_t **drm_heads; | 52 | drm_head_t **drm_heads; |
53 | struct drm_sysfs_class *drm_class; | 53 | struct class *drm_class; |
54 | struct proc_dir_entry *drm_proc_root; | 54 | struct proc_dir_entry *drm_proc_root; |
55 | 55 | ||
56 | static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev, | 56 | static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev, |
@@ -61,8 +61,8 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev, | |||
61 | 61 | ||
62 | spin_lock_init(&dev->count_lock); | 62 | spin_lock_init(&dev->count_lock); |
63 | init_timer(&dev->timer); | 63 | init_timer(&dev->timer); |
64 | sema_init(&dev->struct_sem, 1); | 64 | mutex_init(&dev->struct_mutex); |
65 | sema_init(&dev->ctxlist_sem, 1); | 65 | mutex_init(&dev->ctxlist_mutex); |
66 | 66 | ||
67 | dev->pdev = pdev; | 67 | dev->pdev = pdev; |
68 | 68 | ||
diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c index 68e43ddc16ae..0b9f98a7eb10 100644 --- a/drivers/char/drm/drm_sysfs.c +++ b/drivers/char/drm/drm_sysfs.c | |||
@@ -1,3 +1,4 @@ | |||
1 | |||
1 | /* | 2 | /* |
2 | * drm_sysfs.c - Modifications to drm_sysfs_class.c to support | 3 | * drm_sysfs.c - Modifications to drm_sysfs_class.c to support |
3 | * extra sysfs attribute from DRM. Normal drm_sysfs_class | 4 | * extra sysfs attribute from DRM. Normal drm_sysfs_class |
@@ -19,36 +20,6 @@ | |||
19 | #include "drm_core.h" | 20 | #include "drm_core.h" |
20 | #include "drmP.h" | 21 | #include "drmP.h" |
21 | 22 | ||
22 | struct drm_sysfs_class { | ||
23 | struct class_device_attribute attr; | ||
24 | struct class class; | ||
25 | }; | ||
26 | #define to_drm_sysfs_class(d) container_of(d, struct drm_sysfs_class, class) | ||
27 | |||
28 | struct simple_dev { | ||
29 | dev_t dev; | ||
30 | struct class_device class_dev; | ||
31 | }; | ||
32 | #define to_simple_dev(d) container_of(d, struct simple_dev, class_dev) | ||
33 | |||
34 | static void release_simple_dev(struct class_device *class_dev) | ||
35 | { | ||
36 | struct simple_dev *s_dev = to_simple_dev(class_dev); | ||
37 | kfree(s_dev); | ||
38 | } | ||
39 | |||
40 | static ssize_t show_dev(struct class_device *class_dev, char *buf) | ||
41 | { | ||
42 | struct simple_dev *s_dev = to_simple_dev(class_dev); | ||
43 | return print_dev_t(buf, s_dev->dev); | ||
44 | } | ||
45 | |||
46 | static void drm_sysfs_class_release(struct class *class) | ||
47 | { | ||
48 | struct drm_sysfs_class *cs = to_drm_sysfs_class(class); | ||
49 | kfree(cs); | ||
50 | } | ||
51 | |||
52 | /* Display the version of drm_core. This doesn't work right in current design */ | 23 | /* Display the version of drm_core. This doesn't work right in current design */ |
53 | static ssize_t version_show(struct class *dev, char *buf) | 24 | static ssize_t version_show(struct class *dev, char *buf) |
54 | { | 25 | { |
@@ -69,38 +40,16 @@ static CLASS_ATTR(version, S_IRUGO, version_show, NULL); | |||
69 | * Note, the pointer created here is to be destroyed when finished by making a | 40 | * Note, the pointer created here is to be destroyed when finished by making a |
70 | * call to drm_sysfs_destroy(). | 41 | * call to drm_sysfs_destroy(). |
71 | */ | 42 | */ |
72 | struct drm_sysfs_class *drm_sysfs_create(struct module *owner, char *name) | 43 | struct class *drm_sysfs_create(struct module *owner, char *name) |
73 | { | 44 | { |
74 | struct drm_sysfs_class *cs; | 45 | struct class *class; |
75 | int retval; | 46 | |
76 | 47 | class = class_create(owner, name); | |
77 | cs = kmalloc(sizeof(*cs), GFP_KERNEL); | 48 | if (!class) |
78 | if (!cs) { | 49 | return class; |
79 | retval = -ENOMEM; | 50 | |
80 | goto error; | 51 | class_create_file(class, &class_attr_version); |
81 | } | 52 | return class; |
82 | memset(cs, 0x00, sizeof(*cs)); | ||
83 | |||
84 | cs->class.name = name; | ||
85 | cs->class.class_release = drm_sysfs_class_release; | ||
86 | cs->class.release = release_simple_dev; | ||
87 | |||
88 | cs->attr.attr.name = "dev"; | ||
89 | cs->attr.attr.mode = S_IRUGO; | ||
90 | cs->attr.attr.owner = owner; | ||
91 | cs->attr.show = show_dev; | ||
92 | cs->attr.store = NULL; | ||
93 | |||
94 | retval = class_register(&cs->class); | ||
95 | if (retval) | ||
96 | goto error; | ||
97 | class_create_file(&cs->class, &class_attr_version); | ||
98 | |||
99 | return cs; | ||
100 | |||
101 | error: | ||
102 | kfree(cs); | ||
103 | return ERR_PTR(retval); | ||
104 | } | 53 | } |
105 | 54 | ||
106 | /** | 55 | /** |
@@ -110,12 +59,13 @@ struct drm_sysfs_class *drm_sysfs_create(struct module *owner, char *name) | |||
110 | * Note, the pointer to be destroyed must have been created with a call to | 59 | * Note, the pointer to be destroyed must have been created with a call to |
111 | * drm_sysfs_create(). | 60 | * drm_sysfs_create(). |
112 | */ | 61 | */ |
113 | void drm_sysfs_destroy(struct drm_sysfs_class *cs) | 62 | void drm_sysfs_destroy(struct class *class) |
114 | { | 63 | { |
115 | if ((cs == NULL) || (IS_ERR(cs))) | 64 | if ((class == NULL) || (IS_ERR(class))) |
116 | return; | 65 | return; |
117 | 66 | ||
118 | class_unregister(&cs->class); | 67 | class_remove_file(class, &class_attr_version); |
68 | class_destroy(class); | ||
119 | } | 69 | } |
120 | 70 | ||
121 | static ssize_t show_dri(struct class_device *class_device, char *buf) | 71 | static ssize_t show_dri(struct class_device *class_device, char *buf) |
@@ -132,7 +82,7 @@ static struct class_device_attribute class_device_attrs[] = { | |||
132 | 82 | ||
133 | /** | 83 | /** |
134 | * drm_sysfs_device_add - adds a class device to sysfs for a character driver | 84 | * drm_sysfs_device_add - adds a class device to sysfs for a character driver |
135 | * @cs: pointer to the struct drm_sysfs_class that this device should be registered to. | 85 | * @cs: pointer to the struct class that this device should be registered to. |
136 | * @dev: the dev_t for the device to be added. | 86 | * @dev: the dev_t for the device to be added. |
137 | * @device: a pointer to a struct device that is assiociated with this class device. | 87 | * @device: a pointer to a struct device that is assiociated with this class device. |
138 | * @fmt: string for the class device's name | 88 | * @fmt: string for the class device's name |
@@ -141,46 +91,26 @@ static struct class_device_attribute class_device_attrs[] = { | |||
141 | * class. A "dev" file will be created, showing the dev_t for the device. The | 91 | * class. A "dev" file will be created, showing the dev_t for the device. The |
142 | * pointer to the struct class_device will be returned from the call. Any further | 92 | * pointer to the struct class_device will be returned from the call. Any further |
143 | * sysfs files that might be required can be created using this pointer. | 93 | * sysfs files that might be required can be created using this pointer. |
144 | * Note: the struct drm_sysfs_class passed to this function must have previously been | 94 | * Note: the struct class passed to this function must have previously been |
145 | * created with a call to drm_sysfs_create(). | 95 | * created with a call to drm_sysfs_create(). |
146 | */ | 96 | */ |
147 | struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs, | 97 | struct class_device *drm_sysfs_device_add(struct class *cs, drm_head_t *head) |
148 | drm_head_t *head) | ||
149 | { | 98 | { |
150 | struct simple_dev *s_dev = NULL; | 99 | struct class_device *class_dev; |
151 | int i, retval; | 100 | int i; |
152 | |||
153 | if ((cs == NULL) || (IS_ERR(cs))) { | ||
154 | retval = -ENODEV; | ||
155 | goto error; | ||
156 | } | ||
157 | |||
158 | s_dev = kmalloc(sizeof(*s_dev), GFP_KERNEL); | ||
159 | if (!s_dev) { | ||
160 | retval = -ENOMEM; | ||
161 | goto error; | ||
162 | } | ||
163 | memset(s_dev, 0x00, sizeof(*s_dev)); | ||
164 | |||
165 | s_dev->dev = MKDEV(DRM_MAJOR, head->minor); | ||
166 | s_dev->class_dev.dev = &(head->dev->pdev)->dev; | ||
167 | s_dev->class_dev.class = &cs->class; | ||
168 | 101 | ||
169 | snprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, "card%d", head->minor); | 102 | class_dev = class_device_create(cs, NULL, |
170 | retval = class_device_register(&s_dev->class_dev); | 103 | MKDEV(DRM_MAJOR, head->minor), |
171 | if (retval) | 104 | &(head->dev->pdev)->dev, |
172 | goto error; | 105 | "card%d", head->minor); |
106 | if (!class_dev) | ||
107 | return NULL; | ||
173 | 108 | ||
174 | class_device_create_file(&s_dev->class_dev, &cs->attr); | 109 | class_set_devdata(class_dev, head); |
175 | class_set_devdata(&s_dev->class_dev, head); | ||
176 | 110 | ||
177 | for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) | 111 | for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) |
178 | class_device_create_file(&s_dev->class_dev, &class_device_attrs[i]); | 112 | class_device_create_file(class_dev, &class_device_attrs[i]); |
179 | return &s_dev->class_dev; | 113 | return class_dev; |
180 | |||
181 | error: | ||
182 | kfree(s_dev); | ||
183 | return ERR_PTR(retval); | ||
184 | } | 114 | } |
185 | 115 | ||
186 | /** | 116 | /** |
@@ -192,10 +122,9 @@ error: | |||
192 | */ | 122 | */ |
193 | void drm_sysfs_device_remove(struct class_device *class_dev) | 123 | void drm_sysfs_device_remove(struct class_device *class_dev) |
194 | { | 124 | { |
195 | struct simple_dev *s_dev = to_simple_dev(class_dev); | ||
196 | int i; | 125 | int i; |
197 | 126 | ||
198 | for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) | 127 | for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) |
199 | class_device_remove_file(&s_dev->class_dev, &class_device_attrs[i]); | 128 | class_device_remove_file(class_dev, &class_device_attrs[i]); |
200 | class_device_unregister(&s_dev->class_dev); | 129 | class_device_unregister(class_dev); |
201 | } | 130 | } |
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c index 3f73aa774c80..0291cd62c69f 100644 --- a/drivers/char/drm/drm_vm.c +++ b/drivers/char/drm/drm_vm.c | |||
@@ -188,7 +188,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma) | |||
188 | 188 | ||
189 | map = vma->vm_private_data; | 189 | map = vma->vm_private_data; |
190 | 190 | ||
191 | down(&dev->struct_sem); | 191 | mutex_lock(&dev->struct_mutex); |
192 | for (pt = dev->vmalist, prev = NULL; pt; pt = next) { | 192 | for (pt = dev->vmalist, prev = NULL; pt; pt = next) { |
193 | next = pt->next; | 193 | next = pt->next; |
194 | if (pt->vma->vm_private_data == map) | 194 | if (pt->vma->vm_private_data == map) |
@@ -248,7 +248,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma) | |||
248 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | 248 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); |
249 | } | 249 | } |
250 | } | 250 | } |
251 | up(&dev->struct_sem); | 251 | mutex_unlock(&dev->struct_mutex); |
252 | } | 252 | } |
253 | 253 | ||
254 | /** | 254 | /** |
@@ -404,12 +404,12 @@ static void drm_vm_open(struct vm_area_struct *vma) | |||
404 | 404 | ||
405 | vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS); | 405 | vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS); |
406 | if (vma_entry) { | 406 | if (vma_entry) { |
407 | down(&dev->struct_sem); | 407 | mutex_lock(&dev->struct_mutex); |
408 | vma_entry->vma = vma; | 408 | vma_entry->vma = vma; |
409 | vma_entry->next = dev->vmalist; | 409 | vma_entry->next = dev->vmalist; |
410 | vma_entry->pid = current->pid; | 410 | vma_entry->pid = current->pid; |
411 | dev->vmalist = vma_entry; | 411 | dev->vmalist = vma_entry; |
412 | up(&dev->struct_sem); | 412 | mutex_unlock(&dev->struct_mutex); |
413 | } | 413 | } |
414 | } | 414 | } |
415 | 415 | ||
@@ -431,7 +431,7 @@ static void drm_vm_close(struct vm_area_struct *vma) | |||
431 | vma->vm_start, vma->vm_end - vma->vm_start); | 431 | vma->vm_start, vma->vm_end - vma->vm_start); |
432 | atomic_dec(&dev->vma_count); | 432 | atomic_dec(&dev->vma_count); |
433 | 433 | ||
434 | down(&dev->struct_sem); | 434 | mutex_lock(&dev->struct_mutex); |
435 | for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) { | 435 | for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) { |
436 | if (pt->vma == vma) { | 436 | if (pt->vma == vma) { |
437 | if (prev) { | 437 | if (prev) { |
@@ -443,7 +443,7 @@ static void drm_vm_close(struct vm_area_struct *vma) | |||
443 | break; | 443 | break; |
444 | } | 444 | } |
445 | } | 445 | } |
446 | up(&dev->struct_sem); | 446 | mutex_unlock(&dev->struct_mutex); |
447 | } | 447 | } |
448 | 448 | ||
449 | /** | 449 | /** |
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c index cc1b89086876..ae0aa6d7e0bb 100644 --- a/drivers/char/drm/i810_dma.c +++ b/drivers/char/drm/i810_dma.c | |||
@@ -958,7 +958,7 @@ static int i810_flush_queue(drm_device_t * dev) | |||
958 | } | 958 | } |
959 | 959 | ||
960 | /* Must be called with the lock held */ | 960 | /* Must be called with the lock held */ |
961 | void i810_reclaim_buffers(drm_device_t * dev, struct file *filp) | 961 | static void i810_reclaim_buffers(drm_device_t * dev, struct file *filp) |
962 | { | 962 | { |
963 | drm_device_dma_t *dma = dev->dma; | 963 | drm_device_dma_t *dma = dev->dma; |
964 | int i; | 964 | int i; |
diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h index a18b80d91920..e8cf3ff606f0 100644 --- a/drivers/char/drm/i810_drv.h +++ b/drivers/char/drm/i810_drv.h | |||
@@ -113,8 +113,6 @@ typedef struct drm_i810_private { | |||
113 | } drm_i810_private_t; | 113 | } drm_i810_private_t; |
114 | 114 | ||
115 | /* i810_dma.c */ | 115 | /* i810_dma.c */ |
116 | extern void i810_reclaim_buffers(drm_device_t * dev, struct file *filp); | ||
117 | |||
118 | extern int i810_driver_dma_quiescent(drm_device_t * dev); | 116 | extern int i810_driver_dma_quiescent(drm_device_t * dev); |
119 | extern void i810_driver_reclaim_buffers_locked(drm_device_t * dev, | 117 | extern void i810_driver_reclaim_buffers_locked(drm_device_t * dev, |
120 | struct file *filp); | 118 | struct file *filp); |
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c index 4fea32aed6d2..163f2cbfe60d 100644 --- a/drivers/char/drm/i830_dma.c +++ b/drivers/char/drm/i830_dma.c | |||
@@ -1239,7 +1239,7 @@ static int i830_flush_queue(drm_device_t * dev) | |||
1239 | } | 1239 | } |
1240 | 1240 | ||
1241 | /* Must be called with the lock held */ | 1241 | /* Must be called with the lock held */ |
1242 | void i830_reclaim_buffers(drm_device_t * dev, struct file *filp) | 1242 | static void i830_reclaim_buffers(drm_device_t * dev, struct file *filp) |
1243 | { | 1243 | { |
1244 | drm_device_dma_t *dma = dev->dma; | 1244 | drm_device_dma_t *dma = dev->dma; |
1245 | int i; | 1245 | int i; |
diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h index bf9075b576bd..85bc5be6f916 100644 --- a/drivers/char/drm/i830_drv.h +++ b/drivers/char/drm/i830_drv.h | |||
@@ -123,9 +123,6 @@ typedef struct drm_i830_private { | |||
123 | extern drm_ioctl_desc_t i830_ioctls[]; | 123 | extern drm_ioctl_desc_t i830_ioctls[]; |
124 | extern int i830_max_ioctl; | 124 | extern int i830_max_ioctl; |
125 | 125 | ||
126 | /* i830_dma.c */ | ||
127 | extern void i830_reclaim_buffers(drm_device_t * dev, struct file *filp); | ||
128 | |||
129 | /* i830_irq.c */ | 126 | /* i830_irq.c */ |
130 | extern int i830_irq_emit(struct inode *inode, struct file *filp, | 127 | extern int i830_irq_emit(struct inode *inode, struct file *filp, |
131 | unsigned int cmd, unsigned long arg); | 128 | unsigned int cmd, unsigned long arg); |
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c index 9140703da1ba..1ff4c7ca0bff 100644 --- a/drivers/char/drm/i915_dma.c +++ b/drivers/char/drm/i915_dma.c | |||
@@ -344,18 +344,20 @@ static int i915_emit_cmds(drm_device_t * dev, int __user * buffer, int dwords) | |||
344 | int i; | 344 | int i; |
345 | RING_LOCALS; | 345 | RING_LOCALS; |
346 | 346 | ||
347 | if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8) | ||
348 | return DRM_ERR(EINVAL); | ||
349 | |||
350 | BEGIN_LP_RING(((dwords+1)&~1)); | ||
351 | |||
347 | for (i = 0; i < dwords;) { | 352 | for (i = 0; i < dwords;) { |
348 | int cmd, sz; | 353 | int cmd, sz; |
349 | 354 | ||
350 | if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd))) | 355 | if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd))) |
351 | return DRM_ERR(EINVAL); | 356 | return DRM_ERR(EINVAL); |
352 | 357 | ||
353 | /* printk("%d/%d ", i, dwords); */ | ||
354 | |||
355 | if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords) | 358 | if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords) |
356 | return DRM_ERR(EINVAL); | 359 | return DRM_ERR(EINVAL); |
357 | 360 | ||
358 | BEGIN_LP_RING(sz); | ||
359 | OUT_RING(cmd); | 361 | OUT_RING(cmd); |
360 | 362 | ||
361 | while (++i, --sz) { | 363 | while (++i, --sz) { |
@@ -365,9 +367,13 @@ static int i915_emit_cmds(drm_device_t * dev, int __user * buffer, int dwords) | |||
365 | } | 367 | } |
366 | OUT_RING(cmd); | 368 | OUT_RING(cmd); |
367 | } | 369 | } |
368 | ADVANCE_LP_RING(); | ||
369 | } | 370 | } |
370 | 371 | ||
372 | if (dwords & 1) | ||
373 | OUT_RING(0); | ||
374 | |||
375 | ADVANCE_LP_RING(); | ||
376 | |||
371 | return 0; | 377 | return 0; |
372 | } | 378 | } |
373 | 379 | ||
@@ -401,6 +407,21 @@ static int i915_emit_box(drm_device_t * dev, | |||
401 | return 0; | 407 | return 0; |
402 | } | 408 | } |
403 | 409 | ||
410 | static void i915_emit_breadcrumb(drm_device_t *dev) | ||
411 | { | ||
412 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
413 | RING_LOCALS; | ||
414 | |||
415 | dev_priv->sarea_priv->last_enqueue = dev_priv->counter++; | ||
416 | |||
417 | BEGIN_LP_RING(4); | ||
418 | OUT_RING(CMD_STORE_DWORD_IDX); | ||
419 | OUT_RING(20); | ||
420 | OUT_RING(dev_priv->counter); | ||
421 | OUT_RING(0); | ||
422 | ADVANCE_LP_RING(); | ||
423 | } | ||
424 | |||
404 | static int i915_dispatch_cmdbuffer(drm_device_t * dev, | 425 | static int i915_dispatch_cmdbuffer(drm_device_t * dev, |
405 | drm_i915_cmdbuffer_t * cmd) | 426 | drm_i915_cmdbuffer_t * cmd) |
406 | { | 427 | { |
@@ -429,6 +450,7 @@ static int i915_dispatch_cmdbuffer(drm_device_t * dev, | |||
429 | return ret; | 450 | return ret; |
430 | } | 451 | } |
431 | 452 | ||
453 | i915_emit_breadcrumb(dev); | ||
432 | return 0; | 454 | return 0; |
433 | } | 455 | } |
434 | 456 | ||
@@ -475,12 +497,7 @@ static int i915_dispatch_batchbuffer(drm_device_t * dev, | |||
475 | 497 | ||
476 | dev_priv->sarea_priv->last_enqueue = dev_priv->counter++; | 498 | dev_priv->sarea_priv->last_enqueue = dev_priv->counter++; |
477 | 499 | ||
478 | BEGIN_LP_RING(4); | 500 | i915_emit_breadcrumb(dev); |
479 | OUT_RING(CMD_STORE_DWORD_IDX); | ||
480 | OUT_RING(20); | ||
481 | OUT_RING(dev_priv->counter); | ||
482 | OUT_RING(0); | ||
483 | ADVANCE_LP_RING(); | ||
484 | 501 | ||
485 | return 0; | 502 | return 0; |
486 | } | 503 | } |
@@ -657,7 +674,7 @@ static int i915_getparam(DRM_IOCTL_ARGS) | |||
657 | value = READ_BREADCRUMB(dev_priv); | 674 | value = READ_BREADCRUMB(dev_priv); |
658 | break; | 675 | break; |
659 | default: | 676 | default: |
660 | DRM_ERROR("Unkown parameter %d\n", param.param); | 677 | DRM_ERROR("Unknown parameter %d\n", param.param); |
661 | return DRM_ERR(EINVAL); | 678 | return DRM_ERR(EINVAL); |
662 | } | 679 | } |
663 | 680 | ||
@@ -742,7 +759,8 @@ drm_ioctl_desc_t i915_ioctls[] = { | |||
742 | [DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, DRM_AUTH}, | 759 | [DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, DRM_AUTH}, |
743 | [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, DRM_AUTH}, | 760 | [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, DRM_AUTH}, |
744 | [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, | 761 | [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
745 | [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, DRM_AUTH} | 762 | [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, DRM_AUTH}, |
763 | [DRM_IOCTL_NR(DRM_I915_DESTROY_HEAP)] = { i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY } | ||
746 | }; | 764 | }; |
747 | 765 | ||
748 | int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); | 766 | int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); |
diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h index 77412ddac007..4cb3da578330 100644 --- a/drivers/char/drm/i915_drm.h +++ b/drivers/char/drm/i915_drm.h | |||
@@ -74,6 +74,30 @@ typedef struct _drm_i915_sarea { | |||
74 | int pf_active; | 74 | int pf_active; |
75 | int pf_current_page; /* which buffer is being displayed? */ | 75 | int pf_current_page; /* which buffer is being displayed? */ |
76 | int perf_boxes; /* performance boxes to be displayed */ | 76 | int perf_boxes; /* performance boxes to be displayed */ |
77 | int width, height; /* screen size in pixels */ | ||
78 | |||
79 | drm_handle_t front_handle; | ||
80 | int front_offset; | ||
81 | int front_size; | ||
82 | |||
83 | drm_handle_t back_handle; | ||
84 | int back_offset; | ||
85 | int back_size; | ||
86 | |||
87 | drm_handle_t depth_handle; | ||
88 | int depth_offset; | ||
89 | int depth_size; | ||
90 | |||
91 | drm_handle_t tex_handle; | ||
92 | int tex_offset; | ||
93 | int tex_size; | ||
94 | int log_tex_granularity; | ||
95 | int pitch; | ||
96 | int rotation; /* 0, 90, 180 or 270 */ | ||
97 | int rotated_offset; | ||
98 | int rotated_size; | ||
99 | int rotated_pitch; | ||
100 | int virtualX, virtualY; | ||
77 | } drm_i915_sarea_t; | 101 | } drm_i915_sarea_t; |
78 | 102 | ||
79 | /* Flags for perf_boxes | 103 | /* Flags for perf_boxes |
@@ -99,6 +123,7 @@ typedef struct _drm_i915_sarea { | |||
99 | #define DRM_I915_FREE 0x09 | 123 | #define DRM_I915_FREE 0x09 |
100 | #define DRM_I915_INIT_HEAP 0x0a | 124 | #define DRM_I915_INIT_HEAP 0x0a |
101 | #define DRM_I915_CMDBUFFER 0x0b | 125 | #define DRM_I915_CMDBUFFER 0x0b |
126 | #define DRM_I915_DESTROY_HEAP 0x0c | ||
102 | 127 | ||
103 | #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) | 128 | #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) |
104 | #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) | 129 | #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) |
@@ -112,6 +137,7 @@ typedef struct _drm_i915_sarea { | |||
112 | #define DRM_IOCTL_I915_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FREE, drm_i915_mem_free_t) | 137 | #define DRM_IOCTL_I915_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FREE, drm_i915_mem_free_t) |
113 | #define DRM_IOCTL_I915_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT_HEAP, drm_i915_mem_init_heap_t) | 138 | #define DRM_IOCTL_I915_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT_HEAP, drm_i915_mem_init_heap_t) |
114 | #define DRM_IOCTL_I915_CMDBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_CMDBUFFER, drm_i915_cmdbuffer_t) | 139 | #define DRM_IOCTL_I915_CMDBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_CMDBUFFER, drm_i915_cmdbuffer_t) |
140 | #define DRM_IOCTL_I915_DESTROY_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t) | ||
115 | 141 | ||
116 | /* Allow drivers to submit batchbuffers directly to hardware, relying | 142 | /* Allow drivers to submit batchbuffers directly to hardware, relying |
117 | * on the security mechanisms provided by hardware. | 143 | * on the security mechanisms provided by hardware. |
@@ -191,4 +217,11 @@ typedef struct drm_i915_mem_init_heap { | |||
191 | int start; | 217 | int start; |
192 | } drm_i915_mem_init_heap_t; | 218 | } drm_i915_mem_init_heap_t; |
193 | 219 | ||
220 | /* Allow memory manager to be torn down and re-initialized (eg on | ||
221 | * rotate): | ||
222 | */ | ||
223 | typedef struct drm_i915_mem_destroy_heap { | ||
224 | int region; | ||
225 | } drm_i915_mem_destroy_heap_t; | ||
226 | |||
194 | #endif /* _I915_DRM_H_ */ | 227 | #endif /* _I915_DRM_H_ */ |
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h index c6c71b45f101..7a65666899e4 100644 --- a/drivers/char/drm/i915_drv.h +++ b/drivers/char/drm/i915_drv.h | |||
@@ -37,16 +37,17 @@ | |||
37 | 37 | ||
38 | #define DRIVER_NAME "i915" | 38 | #define DRIVER_NAME "i915" |
39 | #define DRIVER_DESC "Intel Graphics" | 39 | #define DRIVER_DESC "Intel Graphics" |
40 | #define DRIVER_DATE "20051209" | 40 | #define DRIVER_DATE "20060119" |
41 | 41 | ||
42 | /* Interface history: | 42 | /* Interface history: |
43 | * | 43 | * |
44 | * 1.1: Original. | 44 | * 1.1: Original. |
45 | * 1.2: Add Power Management | 45 | * 1.2: Add Power Management |
46 | * 1.3: Add vblank support | 46 | * 1.3: Add vblank support |
47 | * 1.4: Fix cmdbuffer path, add heap destroy | ||
47 | */ | 48 | */ |
48 | #define DRIVER_MAJOR 1 | 49 | #define DRIVER_MAJOR 1 |
49 | #define DRIVER_MINOR 3 | 50 | #define DRIVER_MINOR 4 |
50 | #define DRIVER_PATCHLEVEL 0 | 51 | #define DRIVER_PATCHLEVEL 0 |
51 | 52 | ||
52 | typedef struct _drm_i915_ring_buffer { | 53 | typedef struct _drm_i915_ring_buffer { |
@@ -123,6 +124,7 @@ extern void i915_driver_irq_uninstall(drm_device_t * dev); | |||
123 | extern int i915_mem_alloc(DRM_IOCTL_ARGS); | 124 | extern int i915_mem_alloc(DRM_IOCTL_ARGS); |
124 | extern int i915_mem_free(DRM_IOCTL_ARGS); | 125 | extern int i915_mem_free(DRM_IOCTL_ARGS); |
125 | extern int i915_mem_init_heap(DRM_IOCTL_ARGS); | 126 | extern int i915_mem_init_heap(DRM_IOCTL_ARGS); |
127 | extern int i915_mem_destroy_heap(DRM_IOCTL_ARGS); | ||
126 | extern void i915_mem_takedown(struct mem_block **heap); | 128 | extern void i915_mem_takedown(struct mem_block **heap); |
127 | extern void i915_mem_release(drm_device_t * dev, | 129 | extern void i915_mem_release(drm_device_t * dev, |
128 | DRMFILE filp, struct mem_block *heap); | 130 | DRMFILE filp, struct mem_block *heap); |
diff --git a/drivers/char/drm/i915_mem.c b/drivers/char/drm/i915_mem.c index ba87ff17ff64..52c67324df58 100644 --- a/drivers/char/drm/i915_mem.c +++ b/drivers/char/drm/i915_mem.c | |||
@@ -365,3 +365,34 @@ int i915_mem_init_heap(DRM_IOCTL_ARGS) | |||
365 | 365 | ||
366 | return init_heap(heap, initheap.start, initheap.size); | 366 | return init_heap(heap, initheap.start, initheap.size); |
367 | } | 367 | } |
368 | |||
369 | int i915_mem_destroy_heap( DRM_IOCTL_ARGS ) | ||
370 | { | ||
371 | DRM_DEVICE; | ||
372 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
373 | drm_i915_mem_destroy_heap_t destroyheap; | ||
374 | struct mem_block **heap; | ||
375 | |||
376 | if ( !dev_priv ) { | ||
377 | DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); | ||
378 | return DRM_ERR(EINVAL); | ||
379 | } | ||
380 | |||
381 | DRM_COPY_FROM_USER_IOCTL( destroyheap, (drm_i915_mem_destroy_heap_t *)data, | ||
382 | sizeof(destroyheap) ); | ||
383 | |||
384 | heap = get_heap( dev_priv, destroyheap.region ); | ||
385 | if (!heap) { | ||
386 | DRM_ERROR("get_heap failed"); | ||
387 | return DRM_ERR(EFAULT); | ||
388 | } | ||
389 | |||
390 | if (!*heap) { | ||
391 | DRM_ERROR("heap not initialized?"); | ||
392 | return DRM_ERR(EFAULT); | ||
393 | } | ||
394 | |||
395 | i915_mem_takedown( heap ); | ||
396 | return 0; | ||
397 | } | ||
398 | |||
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c index 915665c7fe7c..9bb8ae0c1c27 100644 --- a/drivers/char/drm/radeon_cp.c +++ b/drivers/char/drm/radeon_cp.c | |||
@@ -1640,7 +1640,7 @@ static int radeon_do_cleanup_cp(drm_device_t * dev) | |||
1640 | if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) | 1640 | if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) |
1641 | { | 1641 | { |
1642 | drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev); | 1642 | drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev); |
1643 | dev_priv->gart_info.addr = 0; | 1643 | dev_priv->gart_info.addr = NULL; |
1644 | } | 1644 | } |
1645 | } | 1645 | } |
1646 | /* only clear to the start of flags */ | 1646 | /* only clear to the start of flags */ |
diff --git a/drivers/char/drm/savage_bci.c b/drivers/char/drm/savage_bci.c index 0d426deeefec..59c7520bf9a2 100644 --- a/drivers/char/drm/savage_bci.c +++ b/drivers/char/drm/savage_bci.c | |||
@@ -32,6 +32,8 @@ | |||
32 | #define SAVAGE_EVENT_USEC_TIMEOUT 5000000 /* 5s */ | 32 | #define SAVAGE_EVENT_USEC_TIMEOUT 5000000 /* 5s */ |
33 | #define SAVAGE_FREELIST_DEBUG 0 | 33 | #define SAVAGE_FREELIST_DEBUG 0 |
34 | 34 | ||
35 | static int savage_do_cleanup_bci(drm_device_t *dev); | ||
36 | |||
35 | static int | 37 | static int |
36 | savage_bci_wait_fifo_shadow(drm_savage_private_t * dev_priv, unsigned int n) | 38 | savage_bci_wait_fifo_shadow(drm_savage_private_t * dev_priv, unsigned int n) |
37 | { | 39 | { |
@@ -895,7 +897,7 @@ static int savage_do_init_bci(drm_device_t * dev, drm_savage_init_t * init) | |||
895 | return 0; | 897 | return 0; |
896 | } | 898 | } |
897 | 899 | ||
898 | int savage_do_cleanup_bci(drm_device_t * dev) | 900 | static int savage_do_cleanup_bci(drm_device_t * dev) |
899 | { | 901 | { |
900 | drm_savage_private_t *dev_priv = dev->dev_private; | 902 | drm_savage_private_t *dev_priv = dev->dev_private; |
901 | 903 | ||
diff --git a/drivers/char/drm/savage_drv.h b/drivers/char/drm/savage_drv.h index dd46cb85439c..8f04b3d82292 100644 --- a/drivers/char/drm/savage_drv.h +++ b/drivers/char/drm/savage_drv.h | |||
@@ -212,7 +212,6 @@ extern int savage_driver_load(drm_device_t *dev, unsigned long chipset); | |||
212 | extern int savage_driver_firstopen(drm_device_t *dev); | 212 | extern int savage_driver_firstopen(drm_device_t *dev); |
213 | extern void savage_driver_lastclose(drm_device_t *dev); | 213 | extern void savage_driver_lastclose(drm_device_t *dev); |
214 | extern int savage_driver_unload(drm_device_t *dev); | 214 | extern int savage_driver_unload(drm_device_t *dev); |
215 | extern int savage_do_cleanup_bci(drm_device_t * dev); | ||
216 | extern void savage_reclaim_buffers(drm_device_t * dev, DRMFILE filp); | 215 | extern void savage_reclaim_buffers(drm_device_t * dev, DRMFILE filp); |
217 | 216 | ||
218 | /* state functions */ | 217 | /* state functions */ |
diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c index 593c0b8f650a..a691ae74129d 100644 --- a/drivers/char/drm/via_dma.c +++ b/drivers/char/drm/via_dma.c | |||
@@ -222,7 +222,7 @@ static int via_initialize(drm_device_t * dev, | |||
222 | return 0; | 222 | return 0; |
223 | } | 223 | } |
224 | 224 | ||
225 | int via_dma_init(DRM_IOCTL_ARGS) | 225 | static int via_dma_init(DRM_IOCTL_ARGS) |
226 | { | 226 | { |
227 | DRM_DEVICE; | 227 | DRM_DEVICE; |
228 | drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; | 228 | drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; |
@@ -321,7 +321,7 @@ int via_driver_dma_quiescent(drm_device_t * dev) | |||
321 | return 0; | 321 | return 0; |
322 | } | 322 | } |
323 | 323 | ||
324 | int via_flush_ioctl(DRM_IOCTL_ARGS) | 324 | static int via_flush_ioctl(DRM_IOCTL_ARGS) |
325 | { | 325 | { |
326 | DRM_DEVICE; | 326 | DRM_DEVICE; |
327 | 327 | ||
@@ -330,7 +330,7 @@ int via_flush_ioctl(DRM_IOCTL_ARGS) | |||
330 | return via_driver_dma_quiescent(dev); | 330 | return via_driver_dma_quiescent(dev); |
331 | } | 331 | } |
332 | 332 | ||
333 | int via_cmdbuffer(DRM_IOCTL_ARGS) | 333 | static int via_cmdbuffer(DRM_IOCTL_ARGS) |
334 | { | 334 | { |
335 | DRM_DEVICE; | 335 | DRM_DEVICE; |
336 | drm_via_cmdbuffer_t cmdbuf; | 336 | drm_via_cmdbuffer_t cmdbuf; |
@@ -375,7 +375,7 @@ static int via_dispatch_pci_cmdbuffer(drm_device_t * dev, | |||
375 | return ret; | 375 | return ret; |
376 | } | 376 | } |
377 | 377 | ||
378 | int via_pci_cmdbuffer(DRM_IOCTL_ARGS) | 378 | static int via_pci_cmdbuffer(DRM_IOCTL_ARGS) |
379 | { | 379 | { |
380 | DRM_DEVICE; | 380 | DRM_DEVICE; |
381 | drm_via_cmdbuffer_t cmdbuf; | 381 | drm_via_cmdbuffer_t cmdbuf; |
@@ -665,7 +665,7 @@ static void via_cmdbuf_reset(drm_via_private_t * dev_priv) | |||
665 | * User interface to the space and lag functions. | 665 | * User interface to the space and lag functions. |
666 | */ | 666 | */ |
667 | 667 | ||
668 | int via_cmdbuf_size(DRM_IOCTL_ARGS) | 668 | static int via_cmdbuf_size(DRM_IOCTL_ARGS) |
669 | { | 669 | { |
670 | DRM_DEVICE; | 670 | DRM_DEVICE; |
671 | drm_via_cmdbuf_size_t d_siz; | 671 | drm_via_cmdbuf_size_t d_siz; |
diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c index 9d5e027dae0e..b7f17457b424 100644 --- a/drivers/char/drm/via_dmablit.c +++ b/drivers/char/drm/via_dmablit.c | |||
@@ -108,7 +108,7 @@ via_map_blit_for_device(struct pci_dev *pdev, | |||
108 | int num_desc = 0; | 108 | int num_desc = 0; |
109 | int cur_line; | 109 | int cur_line; |
110 | dma_addr_t next = 0 | VIA_DMA_DPR_EC; | 110 | dma_addr_t next = 0 | VIA_DMA_DPR_EC; |
111 | drm_via_descriptor_t *desc_ptr = 0; | 111 | drm_via_descriptor_t *desc_ptr = NULL; |
112 | 112 | ||
113 | if (mode == 1) | 113 | if (mode == 1) |
114 | desc_ptr = vsg->desc_pages[cur_descriptor_page]; | 114 | desc_ptr = vsg->desc_pages[cur_descriptor_page]; |
@@ -167,7 +167,7 @@ via_map_blit_for_device(struct pci_dev *pdev, | |||
167 | */ | 167 | */ |
168 | 168 | ||
169 | 169 | ||
170 | void | 170 | static void |
171 | via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t *vsg) | 171 | via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t *vsg) |
172 | { | 172 | { |
173 | struct page *page; | 173 | struct page *page; |
@@ -581,7 +581,7 @@ via_build_sg_info(drm_device_t *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t * | |||
581 | int ret = 0; | 581 | int ret = 0; |
582 | 582 | ||
583 | vsg->direction = (draw) ? DMA_TO_DEVICE : DMA_FROM_DEVICE; | 583 | vsg->direction = (draw) ? DMA_TO_DEVICE : DMA_FROM_DEVICE; |
584 | vsg->bounce_buffer = 0; | 584 | vsg->bounce_buffer = NULL; |
585 | 585 | ||
586 | vsg->state = dr_via_sg_init; | 586 | vsg->state = dr_via_sg_init; |
587 | 587 | ||
diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h index aad4f99f5405..52bcc7b1ba45 100644 --- a/drivers/char/drm/via_drv.h +++ b/drivers/char/drm/via_drv.h | |||
@@ -110,11 +110,6 @@ extern int via_mem_free(DRM_IOCTL_ARGS); | |||
110 | extern int via_agp_init(DRM_IOCTL_ARGS); | 110 | extern int via_agp_init(DRM_IOCTL_ARGS); |
111 | extern int via_map_init(DRM_IOCTL_ARGS); | 111 | extern int via_map_init(DRM_IOCTL_ARGS); |
112 | extern int via_decoder_futex(DRM_IOCTL_ARGS); | 112 | extern int via_decoder_futex(DRM_IOCTL_ARGS); |
113 | extern int via_dma_init(DRM_IOCTL_ARGS); | ||
114 | extern int via_cmdbuffer(DRM_IOCTL_ARGS); | ||
115 | extern int via_flush_ioctl(DRM_IOCTL_ARGS); | ||
116 | extern int via_pci_cmdbuffer(DRM_IOCTL_ARGS); | ||
117 | extern int via_cmdbuf_size(DRM_IOCTL_ARGS); | ||
118 | extern int via_wait_irq(DRM_IOCTL_ARGS); | 113 | extern int via_wait_irq(DRM_IOCTL_ARGS); |
119 | extern int via_dma_blit_sync( DRM_IOCTL_ARGS ); | 114 | extern int via_dma_blit_sync( DRM_IOCTL_ARGS ); |
120 | extern int via_dma_blit( DRM_IOCTL_ARGS ); | 115 | extern int via_dma_blit( DRM_IOCTL_ARGS ); |
@@ -139,8 +134,6 @@ extern int via_driver_dma_quiescent(drm_device_t * dev); | |||
139 | extern void via_init_futex(drm_via_private_t * dev_priv); | 134 | extern void via_init_futex(drm_via_private_t * dev_priv); |
140 | extern void via_cleanup_futex(drm_via_private_t * dev_priv); | 135 | extern void via_cleanup_futex(drm_via_private_t * dev_priv); |
141 | extern void via_release_futex(drm_via_private_t * dev_priv, int context); | 136 | extern void via_release_futex(drm_via_private_t * dev_priv, int context); |
142 | extern int via_driver_irq_wait(drm_device_t * dev, unsigned int irq, | ||
143 | int force_sequence, unsigned int *sequence); | ||
144 | 137 | ||
145 | extern void via_dmablit_handler(drm_device_t *dev, int engine, int from_irq); | 138 | extern void via_dmablit_handler(drm_device_t *dev, int engine, int from_irq); |
146 | extern void via_init_dmablit(drm_device_t *dev); | 139 | extern void via_init_dmablit(drm_device_t *dev); |
diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c index 56d7e3daea12..6152415644e9 100644 --- a/drivers/char/drm/via_irq.c +++ b/drivers/char/drm/via_irq.c | |||
@@ -190,7 +190,7 @@ int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence) | |||
190 | return ret; | 190 | return ret; |
191 | } | 191 | } |
192 | 192 | ||
193 | int | 193 | static int |
194 | via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence, | 194 | via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence, |
195 | unsigned int *sequence) | 195 | unsigned int *sequence) |
196 | { | 196 | { |
diff --git a/drivers/char/esp.c b/drivers/char/esp.c index 3f3ac039f4d9..57539d8f9f7c 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c | |||
@@ -359,7 +359,7 @@ static inline void receive_chars_pio(struct esp_struct *info, int num_bytes) | |||
359 | } | 359 | } |
360 | } | 360 | } |
361 | 361 | ||
362 | schedule_delayed_work(&tty->buf.work, 1); | 362 | tty_schedule_flip(tty); |
363 | 363 | ||
364 | info->stat_flags &= ~ESP_STAT_RX_TIMEOUT; | 364 | info->stat_flags &= ~ESP_STAT_RX_TIMEOUT; |
365 | release_pio_buffer(pio_buf); | 365 | release_pio_buffer(pio_buf); |
@@ -426,7 +426,7 @@ static inline void receive_chars_dma_done(struct esp_struct *info, | |||
426 | } | 426 | } |
427 | tty_insert_flip_char(tty, dma_buffer[num_bytes - 1], statflag); | 427 | tty_insert_flip_char(tty, dma_buffer[num_bytes - 1], statflag); |
428 | } | 428 | } |
429 | schedule_delayed_work(&tty->buf.work, 1); | 429 | tty_schedule_flip(tty); |
430 | } | 430 | } |
431 | 431 | ||
432 | if (dma_bytes != num_bytes) { | 432 | if (dma_bytes != num_bytes) { |
diff --git a/drivers/char/ip2/i2cmd.c b/drivers/char/ip2/i2cmd.c index cb8f4198e9a3..e7af647800b6 100644 --- a/drivers/char/ip2/i2cmd.c +++ b/drivers/char/ip2/i2cmd.c | |||
@@ -139,7 +139,6 @@ static UCHAR ct79[] = { 2, BYP, 0x4F,0 }; // XMIT_NOW | |||
139 | //static UCHAR ct86[]={ 2, BTH, 0x56,0 }; // RCV_ENABLE | 139 | //static UCHAR ct86[]={ 2, BTH, 0x56,0 }; // RCV_ENABLE |
140 | static UCHAR ct87[] = { 1, BYP, 0x57 }; // HW_TEST | 140 | static UCHAR ct87[] = { 1, BYP, 0x57 }; // HW_TEST |
141 | //static UCHAR ct88[]={ 3, BTH, 0x58,0,0 }; // RCV_THRESHOLD | 141 | //static UCHAR ct88[]={ 3, BTH, 0x58,0,0 }; // RCV_THRESHOLD |
142 | static UCHAR ct89[]={ 1, BYP, 0x59 }; // DSS_NOW | ||
143 | //static UCHAR ct90[]={ 3, BYP, 0x5A,0,0 }; // Set SILO | 142 | //static UCHAR ct90[]={ 3, BYP, 0x5A,0,0 }; // Set SILO |
144 | //static UCHAR ct91[]={ 2, BYP, 0x5B,0 }; // timed break | 143 | //static UCHAR ct91[]={ 2, BYP, 0x5B,0 }; // timed break |
145 | 144 | ||
diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c index 56e93a5a1e24..48fcfba37bfa 100644 --- a/drivers/char/ip2main.c +++ b/drivers/char/ip2main.c | |||
@@ -2906,65 +2906,16 @@ ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg ) | |||
2906 | rc = -EINVAL; | 2906 | rc = -EINVAL; |
2907 | break; | 2907 | break; |
2908 | case 3: // Trace device | 2908 | case 3: // Trace device |
2909 | if ( cmd == 1 ) { | 2909 | /* |
2910 | rc = put_user(iiSendPendingMail, pIndex++ ); | 2910 | * akpm: This used to write a whole bunch of function addresses |
2911 | rc = put_user(i2InitChannels, pIndex++ ); | 2911 | * to userspace, which generated lots of put_user() warnings. |
2912 | rc = put_user(i2QueueNeeds, pIndex++ ); | 2912 | * I killed it all. Just return "success" and don't do |
2913 | rc = put_user(i2QueueCommands, pIndex++ ); | 2913 | * anything. |
2914 | rc = put_user(i2GetStatus, pIndex++ ); | 2914 | */ |
2915 | rc = put_user(i2Input, pIndex++ ); | 2915 | if (cmd == 1) |
2916 | rc = put_user(i2InputFlush, pIndex++ ); | 2916 | rc = 0; |
2917 | rc = put_user(i2Output, pIndex++ ); | 2917 | else |
2918 | rc = put_user(i2FlushOutput, pIndex++ ); | ||
2919 | rc = put_user(i2DrainWakeup, pIndex++ ); | ||
2920 | rc = put_user(i2DrainOutput, pIndex++ ); | ||
2921 | rc = put_user(i2OutputFree, pIndex++ ); | ||
2922 | rc = put_user(i2StripFifo, pIndex++ ); | ||
2923 | rc = put_user(i2StuffFifoBypass, pIndex++ ); | ||
2924 | rc = put_user(i2StuffFifoFlow, pIndex++ ); | ||
2925 | rc = put_user(i2StuffFifoInline, pIndex++ ); | ||
2926 | rc = put_user(i2ServiceBoard, pIndex++ ); | ||
2927 | rc = put_user(serviceOutgoingFifo, pIndex++ ); | ||
2928 | // rc = put_user(ip2_init, pIndex++ ); | ||
2929 | rc = put_user(ip2_init_board, pIndex++ ); | ||
2930 | rc = put_user(find_eisa_board, pIndex++ ); | ||
2931 | rc = put_user(set_irq, pIndex++ ); | ||
2932 | rc = put_user(ip2_interrupt, pIndex++ ); | ||
2933 | rc = put_user(ip2_poll, pIndex++ ); | ||
2934 | rc = put_user(service_all_boards, pIndex++ ); | ||
2935 | rc = put_user(do_input, pIndex++ ); | ||
2936 | rc = put_user(do_status, pIndex++ ); | ||
2937 | #ifndef IP2DEBUG_OPEN | ||
2938 | rc = put_user(0, pIndex++ ); | ||
2939 | #else | ||
2940 | rc = put_user(open_sanity_check, pIndex++ ); | ||
2941 | #endif | ||
2942 | rc = put_user(ip2_open, pIndex++ ); | ||
2943 | rc = put_user(ip2_close, pIndex++ ); | ||
2944 | rc = put_user(ip2_hangup, pIndex++ ); | ||
2945 | rc = put_user(ip2_write, pIndex++ ); | ||
2946 | rc = put_user(ip2_putchar, pIndex++ ); | ||
2947 | rc = put_user(ip2_flush_chars, pIndex++ ); | ||
2948 | rc = put_user(ip2_write_room, pIndex++ ); | ||
2949 | rc = put_user(ip2_chars_in_buf, pIndex++ ); | ||
2950 | rc = put_user(ip2_flush_buffer, pIndex++ ); | ||
2951 | |||
2952 | //rc = put_user(ip2_wait_until_sent, pIndex++ ); | ||
2953 | rc = put_user(0, pIndex++ ); | ||
2954 | |||
2955 | rc = put_user(ip2_throttle, pIndex++ ); | ||
2956 | rc = put_user(ip2_unthrottle, pIndex++ ); | ||
2957 | rc = put_user(ip2_ioctl, pIndex++ ); | ||
2958 | rc = put_user(0, pIndex++ ); | ||
2959 | rc = put_user(get_serial_info, pIndex++ ); | ||
2960 | rc = put_user(set_serial_info, pIndex++ ); | ||
2961 | rc = put_user(ip2_set_termios, pIndex++ ); | ||
2962 | rc = put_user(ip2_set_line_discipline, pIndex++ ); | ||
2963 | rc = put_user(set_params, pIndex++ ); | ||
2964 | } else { | ||
2965 | rc = -EINVAL; | 2918 | rc = -EINVAL; |
2966 | } | ||
2967 | |||
2968 | break; | 2919 | break; |
2969 | 2920 | ||
2970 | default: | 2921 | default: |
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 0097f06fa67b..d745004281d0 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -481,7 +481,7 @@ int ipmi_validate_addr(struct ipmi_addr *addr, int len) | |||
481 | } | 481 | } |
482 | 482 | ||
483 | if ((addr->channel == IPMI_BMC_CHANNEL) | 483 | if ((addr->channel == IPMI_BMC_CHANNEL) |
484 | || (addr->channel >= IPMI_NUM_CHANNELS) | 484 | || (addr->channel >= IPMI_MAX_CHANNELS) |
485 | || (addr->channel < 0)) | 485 | || (addr->channel < 0)) |
486 | return -EINVAL; | 486 | return -EINVAL; |
487 | 487 | ||
@@ -1321,7 +1321,7 @@ static int i_ipmi_request(ipmi_user_t user, | |||
1321 | unsigned char ipmb_seq; | 1321 | unsigned char ipmb_seq; |
1322 | long seqid; | 1322 | long seqid; |
1323 | 1323 | ||
1324 | if (addr->channel >= IPMI_NUM_CHANNELS) { | 1324 | if (addr->channel >= IPMI_MAX_CHANNELS) { |
1325 | spin_lock_irqsave(&intf->counter_lock, flags); | 1325 | spin_lock_irqsave(&intf->counter_lock, flags); |
1326 | intf->sent_invalid_commands++; | 1326 | intf->sent_invalid_commands++; |
1327 | spin_unlock_irqrestore(&intf->counter_lock, flags); | 1327 | spin_unlock_irqrestore(&intf->counter_lock, flags); |
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 6ed213bd702c..e59b638766ef 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -1270,36 +1270,36 @@ static int try_init_port(int intf_num, struct smi_info **new_info) | |||
1270 | return 0; | 1270 | return 0; |
1271 | } | 1271 | } |
1272 | 1272 | ||
1273 | static unsigned char mem_inb(struct si_sm_io *io, unsigned int offset) | 1273 | static unsigned char intf_mem_inb(struct si_sm_io *io, unsigned int offset) |
1274 | { | 1274 | { |
1275 | return readb((io->addr)+(offset * io->regspacing)); | 1275 | return readb((io->addr)+(offset * io->regspacing)); |
1276 | } | 1276 | } |
1277 | 1277 | ||
1278 | static void mem_outb(struct si_sm_io *io, unsigned int offset, | 1278 | static void intf_mem_outb(struct si_sm_io *io, unsigned int offset, |
1279 | unsigned char b) | 1279 | unsigned char b) |
1280 | { | 1280 | { |
1281 | writeb(b, (io->addr)+(offset * io->regspacing)); | 1281 | writeb(b, (io->addr)+(offset * io->regspacing)); |
1282 | } | 1282 | } |
1283 | 1283 | ||
1284 | static unsigned char mem_inw(struct si_sm_io *io, unsigned int offset) | 1284 | static unsigned char intf_mem_inw(struct si_sm_io *io, unsigned int offset) |
1285 | { | 1285 | { |
1286 | return (readw((io->addr)+(offset * io->regspacing)) >> io->regshift) | 1286 | return (readw((io->addr)+(offset * io->regspacing)) >> io->regshift) |
1287 | && 0xff; | 1287 | && 0xff; |
1288 | } | 1288 | } |
1289 | 1289 | ||
1290 | static void mem_outw(struct si_sm_io *io, unsigned int offset, | 1290 | static void intf_mem_outw(struct si_sm_io *io, unsigned int offset, |
1291 | unsigned char b) | 1291 | unsigned char b) |
1292 | { | 1292 | { |
1293 | writeb(b << io->regshift, (io->addr)+(offset * io->regspacing)); | 1293 | writeb(b << io->regshift, (io->addr)+(offset * io->regspacing)); |
1294 | } | 1294 | } |
1295 | 1295 | ||
1296 | static unsigned char mem_inl(struct si_sm_io *io, unsigned int offset) | 1296 | static unsigned char intf_mem_inl(struct si_sm_io *io, unsigned int offset) |
1297 | { | 1297 | { |
1298 | return (readl((io->addr)+(offset * io->regspacing)) >> io->regshift) | 1298 | return (readl((io->addr)+(offset * io->regspacing)) >> io->regshift) |
1299 | && 0xff; | 1299 | && 0xff; |
1300 | } | 1300 | } |
1301 | 1301 | ||
1302 | static void mem_outl(struct si_sm_io *io, unsigned int offset, | 1302 | static void intf_mem_outl(struct si_sm_io *io, unsigned int offset, |
1303 | unsigned char b) | 1303 | unsigned char b) |
1304 | { | 1304 | { |
1305 | writel(b << io->regshift, (io->addr)+(offset * io->regspacing)); | 1305 | writel(b << io->regshift, (io->addr)+(offset * io->regspacing)); |
@@ -1349,16 +1349,16 @@ static int mem_setup(struct smi_info *info) | |||
1349 | upon the register size. */ | 1349 | upon the register size. */ |
1350 | switch (info->io.regsize) { | 1350 | switch (info->io.regsize) { |
1351 | case 1: | 1351 | case 1: |
1352 | info->io.inputb = mem_inb; | 1352 | info->io.inputb = intf_mem_inb; |
1353 | info->io.outputb = mem_outb; | 1353 | info->io.outputb = intf_mem_outb; |
1354 | break; | 1354 | break; |
1355 | case 2: | 1355 | case 2: |
1356 | info->io.inputb = mem_inw; | 1356 | info->io.inputb = intf_mem_inw; |
1357 | info->io.outputb = mem_outw; | 1357 | info->io.outputb = intf_mem_outw; |
1358 | break; | 1358 | break; |
1359 | case 4: | 1359 | case 4: |
1360 | info->io.inputb = mem_inl; | 1360 | info->io.inputb = intf_mem_inl; |
1361 | info->io.outputb = mem_outl; | 1361 | info->io.outputb = intf_mem_outl; |
1362 | break; | 1362 | break; |
1363 | #ifdef readq | 1363 | #ifdef readq |
1364 | case 8: | 1364 | case 8: |
diff --git a/drivers/char/rio/cirrus.h b/drivers/char/rio/cirrus.h index 217ff09f2fa1..89bd94eb45be 100644 --- a/drivers/char/rio/cirrus.h +++ b/drivers/char/rio/cirrus.h | |||
@@ -40,148 +40,6 @@ | |||
40 | #endif | 40 | #endif |
41 | #define _cirrus_h 1 | 41 | #define _cirrus_h 1 |
42 | 42 | ||
43 | #ifdef RTA | ||
44 | #define TO_UART RX | ||
45 | #define TO_DRIVER TX | ||
46 | #endif | ||
47 | |||
48 | #ifdef HOST | ||
49 | #define TO_UART TX | ||
50 | #define TO_DRIVER RX | ||
51 | #endif | ||
52 | #ifdef RTA | ||
53 | /* Miscellaneous defines for CIRRUS addresses and related logic for | ||
54 | interrupts etc. | ||
55 | */ | ||
56 | #define MAP(a) ((short *)(cirrus_base + (a))) | ||
57 | #define outp(a,b) (*MAP (a) =(b)) | ||
58 | #define inp(a) ((*MAP (a)) & 0xff) | ||
59 | #define CIRRUS_FIRST (short*)0x7300 | ||
60 | #define CIRRUS_SECOND (short*)0x7200 | ||
61 | #define CIRRUS_THIRD (short*)0x7100 | ||
62 | #define CIRRUS_FOURTH (short*)0x7000 | ||
63 | #define PORTS_ON_CIRRUS 4 | ||
64 | #define CIRRUS_FIFO_SIZE 12 | ||
65 | #define SPACE 0x20 | ||
66 | #define TAB 0x09 | ||
67 | #define LINE_FEED 0x0a | ||
68 | #define CARRIAGE_RETURN 0x0d | ||
69 | #define BACKSPACE 0x08 | ||
70 | #define SPACES_IN_TABS 8 | ||
71 | #define SEND_ESCAPE 0x00 | ||
72 | #define START_BREAK 0x81 | ||
73 | #define TIMER_TICK 0x82 | ||
74 | #define STOP_BREAK 0x83 | ||
75 | #define BASE(a) ((a) < 4 ? (short*)CIRRUS_FIRST : ((a) < 8 ? (short *)CIRRUS_SECOND : ((a) < 12 ? (short*)CIRRUS_THIRD : (short *)CIRRUS_FOURTH))) | ||
76 | #define txack1 ((short *)0x7104) | ||
77 | #define rxack1 ((short *)0x7102) | ||
78 | #define mdack1 ((short *)0x7106) | ||
79 | #define txack2 ((short *)0x7006) | ||
80 | #define rxack2 ((short *)0x7004) | ||
81 | #define mdack2 ((short *)0x7100) | ||
82 | #define int_latch ((short *) 0x7800) | ||
83 | #define int_status ((short *) 0x7c00) | ||
84 | #define tx1_pending 0x20 | ||
85 | #define rx1_pending 0x10 | ||
86 | #define md1_pending 0x40 | ||
87 | #define tx2_pending 0x02 | ||
88 | #define rx2_pending 0x01 | ||
89 | #define md2_pending 0x40 | ||
90 | #define module1_bits 0x07 | ||
91 | #define module1_modern 0x08 | ||
92 | #define module2_bits 0x70 | ||
93 | #define module2_modern 0x80 | ||
94 | #define module_blank 0xf | ||
95 | #define rs232_d25 0x0 | ||
96 | #define rs232_rj45 0x1 | ||
97 | #define rs422_d25 0x3 | ||
98 | #define parallel 0x5 | ||
99 | |||
100 | #define CLK0 0x00 | ||
101 | #define CLK1 0x01 | ||
102 | #define CLK2 0x02 | ||
103 | #define CLK3 0x03 | ||
104 | #define CLK4 0x04 | ||
105 | |||
106 | #define CIRRUS_REVC 0x42 | ||
107 | #define CIRRUS_REVE 0x44 | ||
108 | |||
109 | #define TURNON 1 | ||
110 | #define TURNOFF 0 | ||
111 | |||
112 | /* The list of CIRRUS registers. | ||
113 | NB. These registers are relative values on 8 bit boundaries whereas | ||
114 | on the RTA's the CIRRUS registers are on word boundaries. Use pointer | ||
115 | arithmetic (short *) to obtain the real addresses required */ | ||
116 | #define ccr 0x05 /* Channel Command Register */ | ||
117 | #define ier 0x06 /* Interrupt Enable Register */ | ||
118 | #define cor1 0x08 /* Channel Option Register 1 */ | ||
119 | #define cor2 0x09 /* Channel Option Register 2 */ | ||
120 | #define cor3 0x0a /* Channel Option Register 3 */ | ||
121 | #define cor4 0x1e /* Channel Option Register 4 */ | ||
122 | #define cor5 0x1f /* Channel Option Register 5 */ | ||
123 | |||
124 | #define ccsr 0x0b /* Channel Control Status Register */ | ||
125 | #define rdcr 0x0e /* Receive Data Count Register */ | ||
126 | #define tdcr 0x12 /* Transmit Data Count Register */ | ||
127 | #define mcor1 0x15 /* Modem Change Option Register 1 */ | ||
128 | #define mcor2 0x16 /* Modem Change Option Regsiter 2 */ | ||
129 | |||
130 | #define livr 0x18 /* Local Interrupt Vector Register */ | ||
131 | #define schr1 0x1a /* Special Character Register 1 */ | ||
132 | #define schr2 0x1b /* Special Character Register 2 */ | ||
133 | #define schr3 0x1c /* Special Character Register 3 */ | ||
134 | #define schr4 0x1d /* Special Character Register 4 */ | ||
135 | |||
136 | #define rtr 0x20 /* Receive Timer Register */ | ||
137 | #define rtpr 0x21 /* Receive Timeout Period Register */ | ||
138 | #define lnc 0x24 /* Lnext character */ | ||
139 | |||
140 | #define rivr 0x43 /* Receive Interrupt Vector Register */ | ||
141 | #define tivr 0x42 /* Transmit Interrupt Vector Register */ | ||
142 | #define mivr 0x41 /* Modem Interrupt Vector Register */ | ||
143 | #define gfrcr 0x40 /* Global Firmware Revision code Reg */ | ||
144 | #define ricr 0x44 /* Receive Interrupting Channel Reg */ | ||
145 | #define ticr 0x45 /* Transmit Interrupting Channel Reg */ | ||
146 | #define micr 0x46 /* Modem Interrupting Channel Register */ | ||
147 | |||
148 | #define gcr 0x4b /* Global configuration register */ | ||
149 | #define misr 0x4c /* Modem interrupt status register */ | ||
150 | |||
151 | #define rbusr 0x59 | ||
152 | #define tbusr 0x5a | ||
153 | #define mbusr 0x5b | ||
154 | |||
155 | #define eoir 0x60 /* End Of Interrupt Register */ | ||
156 | #define rdsr 0x62 /* Receive Data / Status Register */ | ||
157 | #define tdr 0x63 /* Transmit Data Register */ | ||
158 | #define svrr 0x67 /* Service Request Register */ | ||
159 | |||
160 | #define car 0x68 /* Channel Access Register */ | ||
161 | #define mir 0x69 /* Modem Interrupt Register */ | ||
162 | #define tir 0x6a /* Transmit Interrupt Register */ | ||
163 | #define rir 0x6b /* Receive Interrupt Register */ | ||
164 | #define msvr1 0x6c /* Modem Signal Value Register 1 */ | ||
165 | #define msvr2 0x6d /* Modem Signal Value Register 2 */ | ||
166 | #define psvr 0x6f /* Printer Signal Value Register */ | ||
167 | |||
168 | #define tbpr 0x72 /* Transmit Baud Rate Period Register */ | ||
169 | #define tcor 0x76 /* Transmit Clock Option Register */ | ||
170 | |||
171 | #define rbpr 0x78 /* Receive Baud Rate Period Register */ | ||
172 | #define rber 0x7a /* Receive Baud Rate Extension Register */ | ||
173 | #define rcor 0x7c /* Receive Clock Option Register */ | ||
174 | #define ppr 0x7e /* Prescalar Period Register */ | ||
175 | |||
176 | /* Misc registers used for forcing the 1400 out of its reset woes */ | ||
177 | #define airl 0x6d | ||
178 | #define airm 0x6e | ||
179 | #define airh 0x6f | ||
180 | #define btcr 0x66 | ||
181 | #define mtcr 0x6c | ||
182 | #define tber 0x74 | ||
183 | |||
184 | #endif /* #ifdef RTA */ | ||
185 | 43 | ||
186 | 44 | ||
187 | /* Bit fields for particular registers */ | 45 | /* Bit fields for particular registers */ |
diff --git a/drivers/char/rio/defaults.h b/drivers/char/rio/defaults.h index 5b600c32ac02..d55c2f6a9877 100644 --- a/drivers/char/rio/defaults.h +++ b/drivers/char/rio/defaults.h | |||
@@ -45,13 +45,6 @@ static char *_rio_defaults_h_sccs = "@(#)defaults.h 1.1"; | |||
45 | #define MILLISECOND (int) (1000/64) /* 15.625 low ticks */ | 45 | #define MILLISECOND (int) (1000/64) /* 15.625 low ticks */ |
46 | #define SECOND (int) 15625 /* Low priority ticks */ | 46 | #define SECOND (int) 15625 /* Low priority ticks */ |
47 | 47 | ||
48 | #ifdef RTA | ||
49 | #define RX_LIMIT (ushort) 3 | ||
50 | #endif | ||
51 | #ifdef HOST | ||
52 | #define RX_LIMIT (ushort) 1 | ||
53 | #endif | ||
54 | |||
55 | #define LINK_TIMEOUT (int) (POLL_PERIOD / 2) | 48 | #define LINK_TIMEOUT (int) (POLL_PERIOD / 2) |
56 | 49 | ||
57 | 50 | ||
diff --git a/drivers/char/rio/link.h b/drivers/char/rio/link.h index bfba5b0c033e..48d68ca7f825 100644 --- a/drivers/char/rio/link.h +++ b/drivers/char/rio/link.h | |||
@@ -102,30 +102,14 @@ | |||
102 | /* | 102 | /* |
103 | ** LED stuff | 103 | ** LED stuff |
104 | */ | 104 | */ |
105 | #if defined(RTA) | ||
106 | #define LED_OFF ((ushort) 0) /* LED off */ | ||
107 | #define LED_RED ((ushort) 1) /* LED Red */ | ||
108 | #define LED_GREEN ((ushort) 2) /* LED Green */ | ||
109 | #define LED_ORANGE ((ushort) 4) /* LED Orange */ | ||
110 | #define LED_1TO8_OPEN ((ushort) 1) /* Port 1->8 LED on */ | ||
111 | #define LED_9TO16_OPEN ((ushort) 2) /* Port 9->16 LED on */ | ||
112 | #define LED_SET_COLOUR(colour) (link->led = (colour)) | ||
113 | #define LED_OR_COLOUR(colour) (link->led |= (colour)) | ||
114 | #define LED_TIMEOUT(time) (link->led_timeout = RioTimePlus(RioTime(),(time))) | ||
115 | #else | ||
116 | #define LED_SET_COLOUR(colour) | 105 | #define LED_SET_COLOUR(colour) |
117 | #define LED_OR_COLOUR(colour) | 106 | #define LED_OR_COLOUR(colour) |
118 | #define LED_TIMEOUT(time) | 107 | #define LED_TIMEOUT(time) |
119 | #endif /* RTA */ | ||
120 | 108 | ||
121 | struct LPB { | 109 | struct LPB { |
122 | WORD link_number; /* Link Number */ | 110 | WORD link_number; /* Link Number */ |
123 | Channel_ptr in_ch; /* Link In Channel */ | 111 | Channel_ptr in_ch; /* Link In Channel */ |
124 | Channel_ptr out_ch; /* Link Out Channel */ | 112 | Channel_ptr out_ch; /* Link Out Channel */ |
125 | #ifdef RTA | ||
126 | uchar stat_led; /* Port open leds */ | ||
127 | uchar led; /* True, light led! */ | ||
128 | #endif | ||
129 | BYTE attached_serial[4]; /* Attached serial number */ | 113 | BYTE attached_serial[4]; /* Attached serial number */ |
130 | BYTE attached_host_serial[4]; | 114 | BYTE attached_host_serial[4]; |
131 | /* Serial number of Host who | 115 | /* Serial number of Host who |
@@ -144,30 +128,12 @@ struct LPB { | |||
144 | WORD WaitNoBoot; /* Secs to hold off booting */ | 128 | WORD WaitNoBoot; /* Secs to hold off booting */ |
145 | PKT_ptr add_packet_list; /* Add packets to here */ | 129 | PKT_ptr add_packet_list; /* Add packets to here */ |
146 | PKT_ptr remove_packet_list; /* Send packets from here */ | 130 | PKT_ptr remove_packet_list; /* Send packets from here */ |
147 | #ifdef RTA | ||
148 | #ifdef DCIRRUS | ||
149 | #define QBUFS_PER_REDIRECT (4 / PKTS_PER_BUFFER + 1) | ||
150 | #else | ||
151 | #define QBUFS_PER_REDIRECT (8 / PKTS_PER_BUFFER + 1) | ||
152 | #endif | ||
153 | PKT_ptr_ptr rd_add; /* Add a new Packet here */ | ||
154 | Q_BUF_ptr rd_add_qb; /* Pointer to the add Q buf */ | ||
155 | PKT_ptr_ptr rd_add_st_qbb; /* Pointer to start of the Q's buf */ | ||
156 | PKT_ptr_ptr rd_add_end_qbb; /* Pointer to the end of the Q's buf */ | ||
157 | PKT_ptr_ptr rd_remove; /* Remove a Packet here */ | ||
158 | Q_BUF_ptr rd_remove_qb; /* Pointer to the remove Q buf */ | ||
159 | PKT_ptr_ptr rd_remove_st_qbb; /* Pointer to the start of the Q buf */ | ||
160 | PKT_ptr_ptr rd_remove_end_qbb; /* Pointer to the end of the Q buf */ | ||
161 | ushort pkts_in_q; /* Packets in queue */ | ||
162 | #endif | ||
163 | 131 | ||
164 | Channel_ptr lrt_fail_chan; /* Lrt's failure channel */ | 132 | Channel_ptr lrt_fail_chan; /* Lrt's failure channel */ |
165 | Channel_ptr ltt_fail_chan; /* Ltt's failure channel */ | 133 | Channel_ptr ltt_fail_chan; /* Ltt's failure channel */ |
166 | 134 | ||
167 | #if defined (HOST) || defined (INKERNEL) | ||
168 | /* RUP structure for HOST to driver communications */ | 135 | /* RUP structure for HOST to driver communications */ |
169 | struct RUP rup; | 136 | struct RUP rup; |
170 | #endif | ||
171 | struct RUP link_rup; /* RUP for the link (POLL, | 137 | struct RUP link_rup; /* RUP for the link (POLL, |
172 | topology etc.) */ | 138 | topology etc.) */ |
173 | WORD attached_link; /* Number of attached link */ | 139 | WORD attached_link; /* Number of attached link */ |
diff --git a/drivers/char/rio/list.h b/drivers/char/rio/list.h index 36aad4c9cb3a..79b853140ae5 100644 --- a/drivers/char/rio/list.h +++ b/drivers/char/rio/list.h | |||
@@ -44,8 +44,6 @@ static char *_rio_list_h_sccs = "@(#)list.h 1.9"; | |||
44 | 44 | ||
45 | #define PKT_IN_USE 0x1 | 45 | #define PKT_IN_USE 0x1 |
46 | 46 | ||
47 | #ifdef INKERNEL | ||
48 | |||
49 | #define ZERO_PTR (ushort) 0x8000 | 47 | #define ZERO_PTR (ushort) 0x8000 |
50 | #define CaD PortP->Caddr | 48 | #define CaD PortP->Caddr |
51 | 49 | ||
@@ -54,143 +52,5 @@ static char *_rio_list_h_sccs = "@(#)list.h 1.9"; | |||
54 | ** to by the TxAdd pointer has PKT_IN_USE clear in its address. | 52 | ** to by the TxAdd pointer has PKT_IN_USE clear in its address. |
55 | */ | 53 | */ |
56 | 54 | ||
57 | #ifndef linux | ||
58 | #if defined( MIPS ) && !defined( MIPSEISA ) | ||
59 | /* May the shoes of the Devil dance on your grave for creating this */ | ||
60 | #define can_add_transmit(PacketP,PortP) \ | ||
61 | (!((uint)(PacketP = (struct PKT *)RIO_PTR(CaD,RINDW(PortP->TxAdd))) \ | ||
62 | & (PKT_IN_USE<<2))) | ||
63 | |||
64 | #elif defined(MIPSEISA) || defined(nx6000) || \ | ||
65 | defined(drs6000) || defined(UWsparc) | ||
66 | |||
67 | #define can_add_transmit(PacketP,PortP) \ | ||
68 | (!((uint)(PacketP = (struct PKT *)RIO_PTR(CaD,RINDW(PortP->TxAdd))) \ | ||
69 | & PKT_IN_USE)) | ||
70 | |||
71 | #else | ||
72 | #define can_add_transmit(PacketP,PortP) \ | ||
73 | (!((uint)(PacketP = (struct PKT *)RIO_PTR(CaD,*PortP->TxAdd)) \ | ||
74 | & PKT_IN_USE)) | ||
75 | #endif | ||
76 | |||
77 | /* | ||
78 | ** To add a packet to the queue, you set the PKT_IN_USE bit in the address, | ||
79 | ** and then move the TxAdd pointer along one position to point to the next | ||
80 | ** packet pointer. You must wrap the pointer from the end back to the start. | ||
81 | */ | ||
82 | #if defined(MIPS) || defined(nx6000) || defined(drs6000) || defined(UWsparc) | ||
83 | # define add_transmit(PortP) \ | ||
84 | WINDW(PortP->TxAdd,RINDW(PortP->TxAdd) | PKT_IN_USE);\ | ||
85 | if (PortP->TxAdd == PortP->TxEnd)\ | ||
86 | PortP->TxAdd = PortP->TxStart;\ | ||
87 | else\ | ||
88 | PortP->TxAdd++;\ | ||
89 | WWORD(PortP->PhbP->tx_add , RIO_OFF(CaD,PortP->TxAdd)); | ||
90 | #elif defined(AIX) | ||
91 | # define add_transmit(PortP) \ | ||
92 | {\ | ||
93 | register ushort *TxAddP = (ushort *)RIO_PTR(Cad,PortP->TxAddO);\ | ||
94 | WINDW( TxAddP, RINDW( TxAddP ) | PKT_IN_USE );\ | ||
95 | if (PortP->TxAddO == PortP->TxEndO )\ | ||
96 | PortP->TxAddO = PortP->TxStartO;\ | ||
97 | else\ | ||
98 | PortP->TxAddO += sizeof(ushort);\ | ||
99 | WWORD(((PHB *)RIO_PTR(Cad,PortP->PhbO))->tx_add , PortP->TxAddO );\ | ||
100 | } | ||
101 | #else | ||
102 | # define add_transmit(PortP) \ | ||
103 | *PortP->TxAdd |= PKT_IN_USE;\ | ||
104 | if (PortP->TxAdd == PortP->TxEnd)\ | ||
105 | PortP->TxAdd = PortP->TxStart;\ | ||
106 | else\ | ||
107 | PortP->TxAdd++;\ | ||
108 | PortP->PhbP->tx_add = RIO_OFF(CaD,PortP->TxAdd); | ||
109 | #endif | ||
110 | |||
111 | /* | ||
112 | ** can_remove_receive( PacketP, PortP ) returns non-zero if PKT_IN_USE is set | ||
113 | ** for the next packet on the queue. It will also set PacketP to point to the | ||
114 | ** relevant packet, [having cleared the PKT_IN_USE bit]. If PKT_IN_USE is clear, | ||
115 | ** then can_remove_receive() returns 0. | ||
116 | */ | ||
117 | #if defined(MIPS) || defined(nx6000) || defined(drs6000) || defined(UWsparc) | ||
118 | # define can_remove_receive(PacketP,PortP) \ | ||
119 | ((RINDW(PortP->RxRemove) & PKT_IN_USE) ? \ | ||
120 | (PacketP=(struct PKT *)RIO_PTR(CaD,(RINDW(PortP->RxRemove) & ~PKT_IN_USE))):0) | ||
121 | #elif defined(AIX) | ||
122 | # define can_remove_receive(PacketP,PortP) \ | ||
123 | ((RINDW((ushort *)RIO_PTR(Cad,PortP->RxRemoveO)) & PKT_IN_USE) ? \ | ||
124 | (PacketP=(struct PKT *)RIO_PTR(Cad,RINDW((ushort *)RIO_PTR(Cad,PortP->RxRemoveO)) & ~PKT_IN_USE)):0) | ||
125 | #else | ||
126 | # define can_remove_receive(PacketP,PortP) \ | ||
127 | ((*PortP->RxRemove & PKT_IN_USE) ? \ | ||
128 | (PacketP=(struct PKT *)RIO_PTR(CaD,(*PortP->RxRemove & ~PKT_IN_USE))):0) | ||
129 | #endif | ||
130 | |||
131 | |||
132 | /* | ||
133 | ** Will God see it within his heart to forgive us for this thing that | ||
134 | ** we have created? To remove a packet from the receive queue you clear | ||
135 | ** its PKT_IN_USE bit, and then bump the pointers. Once the pointers | ||
136 | ** get to the end, they must be wrapped back to the start. | ||
137 | */ | ||
138 | #if defined(MIPS) || defined(nx6000) || defined(drs6000) || defined(UWsparc) | ||
139 | # define remove_receive(PortP) \ | ||
140 | WINDW(PortP->RxRemove, (RINDW(PortP->RxRemove) & ~PKT_IN_USE));\ | ||
141 | if (PortP->RxRemove == PortP->RxEnd)\ | ||
142 | PortP->RxRemove = PortP->RxStart;\ | ||
143 | else\ | ||
144 | PortP->RxRemove++;\ | ||
145 | WWORD(PortP->PhbP->rx_remove , RIO_OFF(CaD,PortP->RxRemove)); | ||
146 | #elif defined(AIX) | ||
147 | # define remove_receive(PortP) \ | ||
148 | {\ | ||
149 | register ushort *RxRemoveP = (ushort *)RIO_PTR(Cad,PortP->RxRemoveO);\ | ||
150 | WINDW( RxRemoveP, RINDW( RxRemoveP ) & ~PKT_IN_USE );\ | ||
151 | if (PortP->RxRemoveO == PortP->RxEndO)\ | ||
152 | PortP->RxRemoveO = PortP->RxStartO;\ | ||
153 | else\ | ||
154 | PortP->RxRemoveO += sizeof(ushort);\ | ||
155 | WWORD(((PHB *)RIO_PTR(Cad,PortP->PhbO))->rx_remove, PortP->RxRemoveO );\ | ||
156 | } | ||
157 | #else | ||
158 | # define remove_receive(PortP) \ | ||
159 | *PortP->RxRemove &= ~PKT_IN_USE;\ | ||
160 | if (PortP->RxRemove == PortP->RxEnd)\ | ||
161 | PortP->RxRemove = PortP->RxStart;\ | ||
162 | else\ | ||
163 | PortP->RxRemove++;\ | ||
164 | PortP->PhbP->rx_remove = RIO_OFF(CaD,PortP->RxRemove); | ||
165 | #endif | ||
166 | #endif | ||
167 | |||
168 | |||
169 | #else /* !IN_KERNEL */ | ||
170 | |||
171 | #define ZERO_PTR NULL | ||
172 | |||
173 | |||
174 | #ifdef HOST | ||
175 | /* #define can_remove_transmit(pkt,phb) ((((char*)pkt = (*(char**)(phb->tx_remove))-1) || 1)) && (*phb->u3.s2.tx_remove_ptr & PKT_IN_USE)) */ | ||
176 | #define remove_transmit(phb) *phb->u3.s2.tx_remove_ptr &= ~(ushort)PKT_IN_USE;\ | ||
177 | if (phb->tx_remove == phb->tx_end)\ | ||
178 | phb->tx_remove = phb->tx_start;\ | ||
179 | else\ | ||
180 | phb->tx_remove++; | ||
181 | #define can_add_receive(phb) !(*phb->u4.s2.rx_add_ptr & PKT_IN_USE) | ||
182 | #define add_receive(pkt,phb) *phb->rx_add = pkt;\ | ||
183 | *phb->u4.s2.rx_add_ptr |= PKT_IN_USE;\ | ||
184 | if (phb->rx_add == phb->rx_end)\ | ||
185 | phb->rx_add = phb->rx_start;\ | ||
186 | else\ | ||
187 | phb->rx_add++; | ||
188 | #endif | ||
189 | #endif | ||
190 | |||
191 | #ifdef RTA | ||
192 | #define splx(oldspl) if ((oldspl) == 0) spl0() | ||
193 | #endif | ||
194 | |||
195 | #endif /* ifndef _list.h */ | 55 | #endif /* ifndef _list.h */ |
196 | /*********** end of file ***********/ | 56 | /*********** end of file ***********/ |
diff --git a/drivers/char/rio/parmmap.h b/drivers/char/rio/parmmap.h index fe4e00567065..e24acc1d1844 100644 --- a/drivers/char/rio/parmmap.h +++ b/drivers/char/rio/parmmap.h | |||
@@ -78,14 +78,9 @@ struct PARM_MAP { | |||
78 | WORD idle_count; /* Idle time counter */ | 78 | WORD idle_count; /* Idle time counter */ |
79 | WORD busy_count; /* Busy counter */ | 79 | WORD busy_count; /* Busy counter */ |
80 | WORD idle_control; /* Control Idle Process */ | 80 | WORD idle_control; /* Control Idle Process */ |
81 | #if defined(HOST) || defined(INKERNEL) | ||
82 | WORD tx_intr; /* TX interrupt pending */ | 81 | WORD tx_intr; /* TX interrupt pending */ |
83 | WORD rx_intr; /* RX interrupt pending */ | 82 | WORD rx_intr; /* RX interrupt pending */ |
84 | WORD rup_intr; /* RUP interrupt pending */ | 83 | WORD rup_intr; /* RUP interrupt pending */ |
85 | #endif | ||
86 | #if defined(RTA) | ||
87 | WORD dying_count; /* Count of processes dead */ | ||
88 | #endif | ||
89 | }; | 84 | }; |
90 | 85 | ||
91 | #endif | 86 | #endif |
diff --git a/drivers/char/rio/phb.h b/drivers/char/rio/phb.h index 3baebf8513af..2663ca0306e2 100644 --- a/drivers/char/rio/phb.h +++ b/drivers/char/rio/phb.h | |||
@@ -44,17 +44,6 @@ | |||
44 | #endif | 44 | #endif |
45 | 45 | ||
46 | 46 | ||
47 | /************************************************* | ||
48 | * Set the LIMIT values. | ||
49 | ************************************************/ | ||
50 | #ifdef RTA | ||
51 | #define RX_LIMIT (ushort) 3 | ||
52 | #endif | ||
53 | #ifdef HOST | ||
54 | #define RX_LIMIT (ushort) 1 | ||
55 | #endif | ||
56 | |||
57 | |||
58 | /************************************************* | 47 | /************************************************* |
59 | * Handshake asserted. Deasserted by the LTT(s) | 48 | * Handshake asserted. Deasserted by the LTT(s) |
60 | ************************************************/ | 49 | ************************************************/ |
@@ -69,11 +58,7 @@ | |||
69 | /************************************************* | 58 | /************************************************* |
70 | * Maximum number of PHB's | 59 | * Maximum number of PHB's |
71 | ************************************************/ | 60 | ************************************************/ |
72 | #if defined (HOST) || defined (INKERNEL) | ||
73 | #define MAX_PHB ((ushort) 128) /* range 0-127 */ | 61 | #define MAX_PHB ((ushort) 128) /* range 0-127 */ |
74 | #else | ||
75 | #define MAX_PHB ((ushort) 8) /* range 0-7 */ | ||
76 | #endif | ||
77 | 62 | ||
78 | /************************************************* | 63 | /************************************************* |
79 | * Defines for the mode fields | 64 | * Defines for the mode fields |
@@ -139,141 +124,23 @@ | |||
139 | * the start. The pointer tx_add points to a SPACE to put a Packet. | 124 | * the start. The pointer tx_add points to a SPACE to put a Packet. |
140 | * The pointer tx_remove points to the next Packet to remove | 125 | * The pointer tx_remove points to the next Packet to remove |
141 | *************************************************************************/ | 126 | *************************************************************************/ |
142 | #ifndef INKERNEL | ||
143 | #define src_unit u2.s2.unit | ||
144 | #define src_port u2.s2.port | ||
145 | #define dest_unit u1.s1.unit | ||
146 | #define dest_port u1.s1.port | ||
147 | #endif | ||
148 | #ifdef HOST | ||
149 | #define tx_start u3.s1.tx_start_ptr_ptr | ||
150 | #define tx_add u3.s1.tx_add_ptr_ptr | ||
151 | #define tx_end u3.s1.tx_end_ptr_ptr | ||
152 | #define tx_remove u3.s1.tx_remove_ptr_ptr | ||
153 | #define rx_start u4.s1.rx_start_ptr_ptr | ||
154 | #define rx_add u4.s1.rx_add_ptr_ptr | ||
155 | #define rx_end u4.s1.rx_end_ptr_ptr | ||
156 | #define rx_remove u4.s1.rx_remove_ptr_ptr | ||
157 | #endif | ||
158 | typedef struct PHB PHB; | 127 | typedef struct PHB PHB; |
159 | struct PHB { | 128 | struct PHB { |
160 | #ifdef RTA | ||
161 | ushort port; | ||
162 | #endif | ||
163 | #ifdef INKERNEL | ||
164 | WORD source; | 129 | WORD source; |
165 | #else | ||
166 | union { | ||
167 | ushort source; /* Complete source */ | ||
168 | struct { | ||
169 | unsigned char unit; /* Source unit */ | ||
170 | unsigned char port; /* Source port */ | ||
171 | } s2; | ||
172 | } u2; | ||
173 | #endif | ||
174 | WORD handshake; | 130 | WORD handshake; |
175 | WORD status; | 131 | WORD status; |
176 | NUMBER timeout; /* Maximum of 1.9 seconds */ | 132 | NUMBER timeout; /* Maximum of 1.9 seconds */ |
177 | WORD link; /* Send down this link */ | 133 | WORD link; /* Send down this link */ |
178 | #ifdef INKERNEL | ||
179 | WORD destination; | 134 | WORD destination; |
180 | #else | ||
181 | union { | ||
182 | ushort destination; /* Complete destination */ | ||
183 | struct { | ||
184 | unsigned char unit; /* Destination unit */ | ||
185 | unsigned char port; /* Destination port */ | ||
186 | } s1; | ||
187 | } u1; | ||
188 | #endif | ||
189 | #ifdef RTA | ||
190 | ushort tx_pkts_added; | ||
191 | ushort tx_pkts_removed; | ||
192 | Q_BUF_ptr tx_q_start; /* Start of the Q list chain */ | ||
193 | short num_tx_q_bufs; /* Number of Q buffers in the chain */ | ||
194 | PKT_ptr_ptr tx_add; /* Add a new Packet here */ | ||
195 | Q_BUF_ptr tx_add_qb; /* Pointer to the add Q buf */ | ||
196 | PKT_ptr_ptr tx_add_st_qbb; /* Pointer to start of the Q's buf */ | ||
197 | PKT_ptr_ptr tx_add_end_qbb; /* Pointer to the end of the Q's buf */ | ||
198 | PKT_ptr_ptr tx_remove; /* Remove a Packet here */ | ||
199 | Q_BUF_ptr tx_remove_qb; /* Pointer to the remove Q buf */ | ||
200 | PKT_ptr_ptr tx_remove_st_qbb; /* Pointer to the start of the Q buf */ | ||
201 | PKT_ptr_ptr tx_remove_end_qbb; /* Pointer to the end of the Q buf */ | ||
202 | #endif | ||
203 | #ifdef INKERNEL | ||
204 | PKT_ptr_ptr tx_start; | 135 | PKT_ptr_ptr tx_start; |
205 | PKT_ptr_ptr tx_end; | 136 | PKT_ptr_ptr tx_end; |
206 | PKT_ptr_ptr tx_add; | 137 | PKT_ptr_ptr tx_add; |
207 | PKT_ptr_ptr tx_remove; | 138 | PKT_ptr_ptr tx_remove; |
208 | #endif | ||
209 | #ifdef HOST | ||
210 | union { | ||
211 | struct { | ||
212 | PKT_ptr_ptr tx_start_ptr_ptr; | ||
213 | PKT_ptr_ptr tx_end_ptr_ptr; | ||
214 | PKT_ptr_ptr tx_add_ptr_ptr; | ||
215 | PKT_ptr_ptr tx_remove_ptr_ptr; | ||
216 | } s1; | ||
217 | struct { | ||
218 | ushort *tx_start_ptr; | ||
219 | ushort *tx_end_ptr; | ||
220 | ushort *tx_add_ptr; | ||
221 | ushort *tx_remove_ptr; | ||
222 | } s2; | ||
223 | } u3; | ||
224 | #endif | ||
225 | 139 | ||
226 | #ifdef RTA | ||
227 | ushort rx_pkts_added; | ||
228 | ushort rx_pkts_removed; | ||
229 | Q_BUF_ptr rx_q_start; /* Start of the Q list chain */ | ||
230 | short num_rx_q_bufs; /* Number of Q buffers in the chain */ | ||
231 | PKT_ptr_ptr rx_add; /* Add a new Packet here */ | ||
232 | Q_BUF_ptr rx_add_qb; /* Pointer to the add Q buf */ | ||
233 | PKT_ptr_ptr rx_add_st_qbb; /* Pointer to start of the Q's buf */ | ||
234 | PKT_ptr_ptr rx_add_end_qbb; /* Pointer to the end of the Q's buf */ | ||
235 | PKT_ptr_ptr rx_remove; /* Remove a Packet here */ | ||
236 | Q_BUF_ptr rx_remove_qb; /* Pointer to the remove Q buf */ | ||
237 | PKT_ptr_ptr rx_remove_st_qbb; /* Pointer to the start of the Q buf */ | ||
238 | PKT_ptr_ptr rx_remove_end_qbb; /* Pointer to the end of the Q buf */ | ||
239 | #endif | ||
240 | #ifdef INKERNEL | ||
241 | PKT_ptr_ptr rx_start; | 140 | PKT_ptr_ptr rx_start; |
242 | PKT_ptr_ptr rx_end; | 141 | PKT_ptr_ptr rx_end; |
243 | PKT_ptr_ptr rx_add; | 142 | PKT_ptr_ptr rx_add; |
244 | PKT_ptr_ptr rx_remove; | 143 | PKT_ptr_ptr rx_remove; |
245 | #endif | ||
246 | #ifdef HOST | ||
247 | union { | ||
248 | struct { | ||
249 | PKT_ptr_ptr rx_start_ptr_ptr; | ||
250 | PKT_ptr_ptr rx_end_ptr_ptr; | ||
251 | PKT_ptr_ptr rx_add_ptr_ptr; | ||
252 | PKT_ptr_ptr rx_remove_ptr_ptr; | ||
253 | } s1; | ||
254 | struct { | ||
255 | ushort *rx_start_ptr; | ||
256 | ushort *rx_end_ptr; | ||
257 | ushort *rx_add_ptr; | ||
258 | ushort *rx_remove_ptr; | ||
259 | } s2; | ||
260 | } u4; | ||
261 | #endif | ||
262 | |||
263 | #ifdef RTA /* some fields for the remotes */ | ||
264 | ushort flush_count; /* Count of write flushes */ | ||
265 | ushort txmode; /* Modes for tx */ | ||
266 | ushort rxmode; /* Modes for rx */ | ||
267 | ushort portmode; /* Generic modes */ | ||
268 | ushort column; /* TAB3 column count */ | ||
269 | ushort tx_subscript; /* (TX) Subscript into data field */ | ||
270 | ushort rx_subscript; /* (RX) Subscript into data field */ | ||
271 | PKT_ptr rx_incomplete; /* Hold an incomplete packet here */ | ||
272 | ushort modem_bits; /* Modem bits to mask */ | ||
273 | ushort lastModem; /* Modem control lines. */ | ||
274 | ushort addr; /* Address for sub commands */ | ||
275 | ushort MonitorTstate; /* TRUE if monitoring tstop */ | ||
276 | #endif | ||
277 | 144 | ||
278 | }; | 145 | }; |
279 | 146 | ||
diff --git a/drivers/char/rio/pkt.h b/drivers/char/rio/pkt.h index 882fd429ac2e..7011e52e82db 100644 --- a/drivers/char/rio/pkt.h +++ b/drivers/char/rio/pkt.h | |||
@@ -70,39 +70,12 @@ | |||
70 | #define CONTROL_DATA_WNDW (DATA_WNDW << 8) | 70 | #define CONTROL_DATA_WNDW (DATA_WNDW << 8) |
71 | 71 | ||
72 | struct PKT { | 72 | struct PKT { |
73 | #ifdef INKERNEL | ||
74 | BYTE dest_unit; /* Destination Unit Id */ | 73 | BYTE dest_unit; /* Destination Unit Id */ |
75 | BYTE dest_port; /* Destination POrt */ | 74 | BYTE dest_port; /* Destination POrt */ |
76 | BYTE src_unit; /* Source Unit Id */ | 75 | BYTE src_unit; /* Source Unit Id */ |
77 | BYTE src_port; /* Source POrt */ | 76 | BYTE src_port; /* Source POrt */ |
78 | #else | ||
79 | union { | ||
80 | ushort destination; /* Complete destination */ | ||
81 | struct { | ||
82 | unsigned char unit; /* Destination unit */ | ||
83 | unsigned char port; /* Destination port */ | ||
84 | } s1; | ||
85 | } u1; | ||
86 | union { | ||
87 | ushort source; /* Complete source */ | ||
88 | struct { | ||
89 | unsigned char unit; /* Source unit */ | ||
90 | unsigned char port; /* Source port */ | ||
91 | } s2; | ||
92 | } u2; | ||
93 | #endif | ||
94 | #ifdef INKERNEL | ||
95 | BYTE len; | 77 | BYTE len; |
96 | BYTE control; | 78 | BYTE control; |
97 | #else | ||
98 | union { | ||
99 | ushort control; | ||
100 | struct { | ||
101 | unsigned char len; | ||
102 | unsigned char control; | ||
103 | } s3; | ||
104 | } u3; | ||
105 | #endif | ||
106 | BYTE data[PKT_MAX_DATA_LEN]; | 79 | BYTE data[PKT_MAX_DATA_LEN]; |
107 | /* Actual data :-) */ | 80 | /* Actual data :-) */ |
108 | WORD csum; /* C-SUM */ | 81 | WORD csum; /* C-SUM */ |
diff --git a/drivers/char/rio/qbuf.h b/drivers/char/rio/qbuf.h index acd9e8e5307d..391ffc335535 100644 --- a/drivers/char/rio/qbuf.h +++ b/drivers/char/rio/qbuf.h | |||
@@ -46,11 +46,7 @@ static char *_rio_qbuf_h_sccs = "@(#)qbuf.h 1.1"; | |||
46 | 46 | ||
47 | 47 | ||
48 | 48 | ||
49 | #ifdef HOST | ||
50 | #define PKTS_PER_BUFFER 1 | ||
51 | #else | ||
52 | #define PKTS_PER_BUFFER (220 / PKT_LENGTH) | 49 | #define PKTS_PER_BUFFER (220 / PKT_LENGTH) |
53 | #endif | ||
54 | 50 | ||
55 | typedef struct Q_BUF Q_BUF; | 51 | typedef struct Q_BUF Q_BUF; |
56 | struct Q_BUF { | 52 | struct Q_BUF { |
diff --git a/drivers/char/rio/riotypes.h b/drivers/char/rio/riotypes.h index 9b67e2468bec..46084d5c7e98 100644 --- a/drivers/char/rio/riotypes.h +++ b/drivers/char/rio/riotypes.h | |||
@@ -43,9 +43,6 @@ | |||
43 | #endif | 43 | #endif |
44 | #endif | 44 | #endif |
45 | 45 | ||
46 | #ifdef INKERNEL | ||
47 | |||
48 | #if !defined(MIPSAT) | ||
49 | typedef unsigned short NUMBER_ptr; | 46 | typedef unsigned short NUMBER_ptr; |
50 | typedef unsigned short WORD_ptr; | 47 | typedef unsigned short WORD_ptr; |
51 | typedef unsigned short BYTE_ptr; | 48 | typedef unsigned short BYTE_ptr; |
@@ -65,69 +62,6 @@ typedef unsigned short RUP_ptr; | |||
65 | typedef unsigned short short_ptr; | 62 | typedef unsigned short short_ptr; |
66 | typedef unsigned short u_short_ptr; | 63 | typedef unsigned short u_short_ptr; |
67 | typedef unsigned short ushort_ptr; | 64 | typedef unsigned short ushort_ptr; |
68 | #else | ||
69 | /* MIPSAT types */ | ||
70 | typedef char RIO_POINTER[8]; | ||
71 | typedef RIO_POINTER NUMBER_ptr; | ||
72 | typedef RIO_POINTER WORD_ptr; | ||
73 | typedef RIO_POINTER BYTE_ptr; | ||
74 | typedef RIO_POINTER char_ptr; | ||
75 | typedef RIO_POINTER Channel_ptr; | ||
76 | typedef RIO_POINTER FREE_LIST_ptr_ptr; | ||
77 | typedef RIO_POINTER FREE_LIST_ptr; | ||
78 | typedef RIO_POINTER LPB_ptr; | ||
79 | typedef RIO_POINTER Process_ptr; | ||
80 | typedef RIO_POINTER PHB_ptr; | ||
81 | typedef RIO_POINTER PKT_ptr; | ||
82 | typedef RIO_POINTER PKT_ptr_ptr; | ||
83 | typedef RIO_POINTER Q_BUF_ptr; | ||
84 | typedef RIO_POINTER Q_BUF_ptr_ptr; | ||
85 | typedef RIO_POINTER ROUTE_STR_ptr; | ||
86 | typedef RIO_POINTER RUP_ptr; | ||
87 | typedef RIO_POINTER short_ptr; | ||
88 | typedef RIO_POINTER u_short_ptr; | ||
89 | typedef RIO_POINTER ushort_ptr; | ||
90 | #endif | ||
91 | |||
92 | #else /* not INKERNEL */ | ||
93 | typedef unsigned char BYTE; | ||
94 | typedef unsigned short WORD; | ||
95 | typedef unsigned long DWORD; | ||
96 | typedef short NUMBER; | ||
97 | typedef short *NUMBER_ptr; | ||
98 | typedef unsigned short *WORD_ptr; | ||
99 | typedef unsigned char *BYTE_ptr; | ||
100 | typedef unsigned char uchar; | ||
101 | typedef unsigned short ushort; | ||
102 | typedef unsigned int uint; | ||
103 | typedef unsigned long ulong; | ||
104 | typedef unsigned char u_char; | ||
105 | typedef unsigned short u_short; | ||
106 | typedef unsigned int u_int; | ||
107 | typedef unsigned long u_long; | ||
108 | typedef unsigned short ERROR; | ||
109 | typedef unsigned long ID; | ||
110 | typedef char *char_ptr; | ||
111 | typedef Channel *Channel_ptr; | ||
112 | typedef struct FREE_LIST *FREE_LIST_ptr; | ||
113 | typedef struct FREE_LIST **FREE_LIST_ptr_ptr; | ||
114 | typedef struct LPB *LPB_ptr; | ||
115 | typedef struct Process *Process_ptr; | ||
116 | typedef struct PHB *PHB_ptr; | ||
117 | typedef struct PKT *PKT_ptr; | ||
118 | typedef struct PKT **PKT_ptr_ptr; | ||
119 | typedef struct Q_BUF *Q_BUF_ptr; | ||
120 | typedef struct Q_BUF **Q_BUF_ptr_ptr; | ||
121 | typedef struct ROUTE_STR *ROUTE_STR_ptr; | ||
122 | typedef struct RUP *RUP_ptr; | ||
123 | typedef short *short_ptr; | ||
124 | typedef u_short *u_short_ptr; | ||
125 | typedef ushort *ushort_ptr; | ||
126 | typedef struct PKT PKT; | ||
127 | typedef struct LPB LPB; | ||
128 | typedef struct RUP RUP; | ||
129 | #endif | ||
130 | |||
131 | 65 | ||
132 | #endif /* __riotypes__ */ | 66 | #endif /* __riotypes__ */ |
133 | 67 | ||
diff --git a/drivers/char/rio/rup.h b/drivers/char/rio/rup.h index 8d44fec91dd5..f74f67c6f702 100644 --- a/drivers/char/rio/rup.h +++ b/drivers/char/rio/rup.h | |||
@@ -43,12 +43,7 @@ | |||
43 | #endif | 43 | #endif |
44 | #endif | 44 | #endif |
45 | 45 | ||
46 | #if defined( HOST ) || defined( INKERNEL ) | ||
47 | #define MAX_RUP ((short) 16) | 46 | #define MAX_RUP ((short) 16) |
48 | #endif | ||
49 | #ifdef RTA | ||
50 | #define MAX_RUP ((short) 1) | ||
51 | #endif | ||
52 | 47 | ||
53 | #define PKTS_PER_RUP ((short) 2) /* They are always used in pairs */ | 48 | #define PKTS_PER_RUP ((short) 2) /* They are always used in pairs */ |
54 | 49 | ||
diff --git a/drivers/char/rio/sam.h b/drivers/char/rio/sam.h index 31494054b213..6f754e19015d 100644 --- a/drivers/char/rio/sam.h +++ b/drivers/char/rio/sam.h | |||
@@ -43,10 +43,6 @@ | |||
43 | #endif | 43 | #endif |
44 | 44 | ||
45 | 45 | ||
46 | #if !defined( HOST ) && !defined( INKERNEL ) | ||
47 | #define RTA 1 | ||
48 | #endif | ||
49 | |||
50 | #define NUM_FREE_LIST_UNITS 500 | 46 | #define NUM_FREE_LIST_UNITS 500 |
51 | 47 | ||
52 | #ifndef FALSE | 48 | #ifndef FALSE |
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 0949dcef0697..7edc6a4dbdc4 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c | |||
@@ -433,7 +433,7 @@ static void rp_do_receive(struct r_port *info, | |||
433 | count += ToRecv; | 433 | count += ToRecv; |
434 | } | 434 | } |
435 | /* Push the data up to the tty layer */ | 435 | /* Push the data up to the tty layer */ |
436 | ld->receive_buf(tty, cbuf, fbuf, count); | 436 | ld->receive_buf(tty, chead, fhead, count); |
437 | done: | 437 | done: |
438 | tty_ldisc_deref(ld); | 438 | tty_ldisc_deref(ld); |
439 | } | 439 | } |
diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c index 80a5b840e22f..fee68cc895f8 100644 --- a/drivers/char/ser_a2232.c +++ b/drivers/char/ser_a2232.c | |||
@@ -103,6 +103,7 @@ | |||
103 | 103 | ||
104 | #include <linux/serial.h> | 104 | #include <linux/serial.h> |
105 | #include <linux/generic_serial.h> | 105 | #include <linux/generic_serial.h> |
106 | #include <linux/tty_flip.h> | ||
106 | 107 | ||
107 | #include "ser_a2232.h" | 108 | #include "ser_a2232.h" |
108 | #include "ser_a2232fw.h" | 109 | #include "ser_a2232fw.h" |
diff --git a/drivers/char/sx.c b/drivers/char/sx.c index 64bf89cb574f..c2490e270f1f 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c | |||
@@ -931,7 +931,7 @@ static int sx_set_real_termios (void *ptr) | |||
931 | case CS6:sx_write_channel_byte (port, hi_mask, 0x3f);break; | 931 | case CS6:sx_write_channel_byte (port, hi_mask, 0x3f);break; |
932 | case CS5:sx_write_channel_byte (port, hi_mask, 0x1f);break; | 932 | case CS5:sx_write_channel_byte (port, hi_mask, 0x1f);break; |
933 | default: | 933 | default: |
934 | printk (KERN_INFO "sx: Invalid wordsize: %d\n", CFLAG & CSIZE); | 934 | printk (KERN_INFO "sx: Invalid wordsize: %u\n", CFLAG & CSIZE); |
935 | break; | 935 | break; |
936 | } | 936 | } |
937 | 937 | ||
@@ -958,7 +958,7 @@ static int sx_set_real_termios (void *ptr) | |||
958 | } else { | 958 | } else { |
959 | set_bit(TTY_HW_COOK_IN, &port->gs.tty->flags); | 959 | set_bit(TTY_HW_COOK_IN, &port->gs.tty->flags); |
960 | } | 960 | } |
961 | sx_dprintk (SX_DEBUG_TERMIOS, "iflags: %x(%d) ", | 961 | sx_dprintk (SX_DEBUG_TERMIOS, "iflags: %x(%d) ", |
962 | port->gs.tty->termios->c_iflag, | 962 | port->gs.tty->termios->c_iflag, |
963 | I_OTHER(port->gs.tty)); | 963 | I_OTHER(port->gs.tty)); |
964 | 964 | ||
@@ -973,7 +973,7 @@ static int sx_set_real_termios (void *ptr) | |||
973 | } else { | 973 | } else { |
974 | clear_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags); | 974 | clear_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags); |
975 | } | 975 | } |
976 | sx_dprintk (SX_DEBUG_TERMIOS, "oflags: %x(%d)\n", | 976 | sx_dprintk (SX_DEBUG_TERMIOS, "oflags: %x(%d)\n", |
977 | port->gs.tty->termios->c_oflag, | 977 | port->gs.tty->termios->c_oflag, |
978 | O_OTHER(port->gs.tty)); | 978 | O_OTHER(port->gs.tty)); |
979 | /* port->c_dcd = sx_get_CD (port); */ | 979 | /* port->c_dcd = sx_get_CD (port); */ |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index eb8b5be4e249..076e07c1da38 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -253,6 +253,7 @@ static void tty_buffer_free_all(struct tty_struct *tty) | |||
253 | 253 | ||
254 | static void tty_buffer_init(struct tty_struct *tty) | 254 | static void tty_buffer_init(struct tty_struct *tty) |
255 | { | 255 | { |
256 | spin_lock_init(&tty->buf.lock); | ||
256 | tty->buf.head = NULL; | 257 | tty->buf.head = NULL; |
257 | tty->buf.tail = NULL; | 258 | tty->buf.tail = NULL; |
258 | tty->buf.free = NULL; | 259 | tty->buf.free = NULL; |
@@ -266,6 +267,7 @@ static struct tty_buffer *tty_buffer_alloc(size_t size) | |||
266 | p->used = 0; | 267 | p->used = 0; |
267 | p->size = size; | 268 | p->size = size; |
268 | p->next = NULL; | 269 | p->next = NULL; |
270 | p->active = 0; | ||
269 | p->char_buf_ptr = (char *)(p->data); | 271 | p->char_buf_ptr = (char *)(p->data); |
270 | p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size; | 272 | p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size; |
271 | /* printk("Flip create %p\n", p); */ | 273 | /* printk("Flip create %p\n", p); */ |
@@ -312,25 +314,36 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size) | |||
312 | 314 | ||
313 | int tty_buffer_request_room(struct tty_struct *tty, size_t size) | 315 | int tty_buffer_request_room(struct tty_struct *tty, size_t size) |
314 | { | 316 | { |
315 | struct tty_buffer *b = tty->buf.tail, *n; | 317 | struct tty_buffer *b, *n; |
316 | int left = 0; | 318 | int left; |
319 | unsigned long flags; | ||
320 | |||
321 | spin_lock_irqsave(&tty->buf.lock, flags); | ||
317 | 322 | ||
318 | /* OPTIMISATION: We could keep a per tty "zero" sized buffer to | 323 | /* OPTIMISATION: We could keep a per tty "zero" sized buffer to |
319 | remove this conditional if its worth it. This would be invisible | 324 | remove this conditional if its worth it. This would be invisible |
320 | to the callers */ | 325 | to the callers */ |
321 | if(b != NULL) | 326 | if ((b = tty->buf.tail) != NULL) { |
322 | left = b->size - b->used; | 327 | left = b->size - b->used; |
323 | if(left >= size) | 328 | b->active = 1; |
324 | return size; | 329 | } else |
325 | /* This is the slow path - looking for new buffers to use */ | 330 | left = 0; |
326 | n = tty_buffer_find(tty, size); | 331 | |
327 | if(n == NULL) | 332 | if (left < size) { |
328 | return left; | 333 | /* This is the slow path - looking for new buffers to use */ |
329 | if(b != NULL) | 334 | if ((n = tty_buffer_find(tty, size)) != NULL) { |
330 | b->next = n; | 335 | if (b != NULL) { |
331 | else | 336 | b->next = n; |
332 | tty->buf.head = n; | 337 | b->active = 0; |
333 | tty->buf.tail = n; | 338 | } else |
339 | tty->buf.head = n; | ||
340 | tty->buf.tail = n; | ||
341 | n->active = 1; | ||
342 | } else | ||
343 | size = left; | ||
344 | } | ||
345 | |||
346 | spin_unlock_irqrestore(&tty->buf.lock, flags); | ||
334 | return size; | 347 | return size; |
335 | } | 348 | } |
336 | 349 | ||
@@ -396,10 +409,12 @@ EXPORT_SYMBOL_GPL(tty_insert_flip_string_flags); | |||
396 | int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size) | 409 | int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size) |
397 | { | 410 | { |
398 | int space = tty_buffer_request_room(tty, size); | 411 | int space = tty_buffer_request_room(tty, size); |
399 | struct tty_buffer *tb = tty->buf.tail; | 412 | if (likely(space)) { |
400 | *chars = tb->char_buf_ptr + tb->used; | 413 | struct tty_buffer *tb = tty->buf.tail; |
401 | memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space); | 414 | *chars = tb->char_buf_ptr + tb->used; |
402 | tb->used += space; | 415 | memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space); |
416 | tb->used += space; | ||
417 | } | ||
403 | return space; | 418 | return space; |
404 | } | 419 | } |
405 | 420 | ||
@@ -416,10 +431,12 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string); | |||
416 | int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size) | 431 | int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size) |
417 | { | 432 | { |
418 | int space = tty_buffer_request_room(tty, size); | 433 | int space = tty_buffer_request_room(tty, size); |
419 | struct tty_buffer *tb = tty->buf.tail; | 434 | if (likely(space)) { |
420 | *chars = tb->char_buf_ptr + tb->used; | 435 | struct tty_buffer *tb = tty->buf.tail; |
421 | *flags = tb->flag_buf_ptr + tb->used; | 436 | *chars = tb->char_buf_ptr + tb->used; |
422 | tb->used += space; | 437 | *flags = tb->flag_buf_ptr + tb->used; |
438 | tb->used += space; | ||
439 | } | ||
423 | return space; | 440 | return space; |
424 | } | 441 | } |
425 | 442 | ||
@@ -2747,20 +2764,20 @@ static void flush_to_ldisc(void *private_) | |||
2747 | schedule_delayed_work(&tty->buf.work, 1); | 2764 | schedule_delayed_work(&tty->buf.work, 1); |
2748 | goto out; | 2765 | goto out; |
2749 | } | 2766 | } |
2750 | spin_lock_irqsave(&tty->read_lock, flags); | 2767 | spin_lock_irqsave(&tty->buf.lock, flags); |
2751 | while((tbuf = tty->buf.head) != NULL) { | 2768 | while((tbuf = tty->buf.head) != NULL && !tbuf->active) { |
2752 | tty->buf.head = tbuf->next; | 2769 | tty->buf.head = tbuf->next; |
2753 | if (tty->buf.head == NULL) | 2770 | if (tty->buf.head == NULL) |
2754 | tty->buf.tail = NULL; | 2771 | tty->buf.tail = NULL; |
2755 | spin_unlock_irqrestore(&tty->read_lock, flags); | 2772 | spin_unlock_irqrestore(&tty->buf.lock, flags); |
2756 | /* printk("Process buffer %p for %d\n", tbuf, tbuf->used); */ | 2773 | /* printk("Process buffer %p for %d\n", tbuf, tbuf->used); */ |
2757 | disc->receive_buf(tty, tbuf->char_buf_ptr, | 2774 | disc->receive_buf(tty, tbuf->char_buf_ptr, |
2758 | tbuf->flag_buf_ptr, | 2775 | tbuf->flag_buf_ptr, |
2759 | tbuf->used); | 2776 | tbuf->used); |
2760 | spin_lock_irqsave(&tty->read_lock, flags); | 2777 | spin_lock_irqsave(&tty->buf.lock, flags); |
2761 | tty_buffer_free(tty, tbuf); | 2778 | tty_buffer_free(tty, tbuf); |
2762 | } | 2779 | } |
2763 | spin_unlock_irqrestore(&tty->read_lock, flags); | 2780 | spin_unlock_irqrestore(&tty->buf.lock, flags); |
2764 | out: | 2781 | out: |
2765 | tty_ldisc_deref(disc); | 2782 | tty_ldisc_deref(disc); |
2766 | } | 2783 | } |
@@ -2852,6 +2869,12 @@ EXPORT_SYMBOL(tty_get_baud_rate); | |||
2852 | 2869 | ||
2853 | void tty_flip_buffer_push(struct tty_struct *tty) | 2870 | void tty_flip_buffer_push(struct tty_struct *tty) |
2854 | { | 2871 | { |
2872 | unsigned long flags; | ||
2873 | spin_lock_irqsave(&tty->buf.lock, flags); | ||
2874 | if (tty->buf.tail != NULL) | ||
2875 | tty->buf.tail->active = 0; | ||
2876 | spin_unlock_irqrestore(&tty->buf.lock, flags); | ||
2877 | |||
2855 | if (tty->low_latency) | 2878 | if (tty->low_latency) |
2856 | flush_to_ldisc((void *) tty); | 2879 | flush_to_ldisc((void *) tty); |
2857 | else | 2880 | else |
diff --git a/drivers/char/watchdog/sbc_epx_c3.c b/drivers/char/watchdog/sbc_epx_c3.c index 951764614ebf..837b1ec3ffe3 100644 --- a/drivers/char/watchdog/sbc_epx_c3.c +++ b/drivers/char/watchdog/sbc_epx_c3.c | |||
@@ -25,6 +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/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/ioport.h> | ||
28 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
29 | #include <asm/io.h> | 30 | #include <asm/io.h> |
30 | 31 | ||
@@ -91,7 +92,7 @@ static int epx_c3_release(struct inode *inode, struct file *file) | |||
91 | return 0; | 92 | return 0; |
92 | } | 93 | } |
93 | 94 | ||
94 | static ssize_t epx_c3_write(struct file *file, const char *data, | 95 | static ssize_t epx_c3_write(struct file *file, const char __user *data, |
95 | size_t len, loff_t *ppos) | 96 | size_t len, loff_t *ppos) |
96 | { | 97 | { |
97 | /* Refresh the timer. */ | 98 | /* Refresh the timer. */ |
@@ -104,6 +105,7 @@ static int epx_c3_ioctl(struct inode *inode, struct file *file, | |||
104 | unsigned int cmd, unsigned long arg) | 105 | unsigned int cmd, unsigned long arg) |
105 | { | 106 | { |
106 | int options, retval = -EINVAL; | 107 | int options, retval = -EINVAL; |
108 | int __user *argp = (void __user *)arg; | ||
107 | static struct watchdog_info ident = { | 109 | static struct watchdog_info ident = { |
108 | .options = WDIOF_KEEPALIVEPING | | 110 | .options = WDIOF_KEEPALIVEPING | |
109 | WDIOF_MAGICCLOSE, | 111 | WDIOF_MAGICCLOSE, |
@@ -113,20 +115,19 @@ static int epx_c3_ioctl(struct inode *inode, struct file *file, | |||
113 | 115 | ||
114 | switch (cmd) { | 116 | switch (cmd) { |
115 | case WDIOC_GETSUPPORT: | 117 | case WDIOC_GETSUPPORT: |
116 | if (copy_to_user((struct watchdog_info *)arg, | 118 | if (copy_to_user(argp, &ident, sizeof(ident))) |
117 | &ident, sizeof(ident))) | ||
118 | return -EFAULT; | 119 | return -EFAULT; |
119 | return 0; | 120 | return 0; |
120 | case WDIOC_GETSTATUS: | 121 | case WDIOC_GETSTATUS: |
121 | case WDIOC_GETBOOTSTATUS: | 122 | case WDIOC_GETBOOTSTATUS: |
122 | return put_user(0,(int *)arg); | 123 | return put_user(0, argp); |
123 | case WDIOC_KEEPALIVE: | 124 | case WDIOC_KEEPALIVE: |
124 | epx_c3_pet(); | 125 | epx_c3_pet(); |
125 | return 0; | 126 | return 0; |
126 | case WDIOC_GETTIMEOUT: | 127 | case WDIOC_GETTIMEOUT: |
127 | return put_user(WATCHDOG_TIMEOUT,(int *)arg); | 128 | return put_user(WATCHDOG_TIMEOUT, argp); |
128 | case WDIOC_SETOPTIONS: { | 129 | case WDIOC_SETOPTIONS: |
129 | if (get_user(options, (int *)arg)) | 130 | if (get_user(options, argp)) |
130 | return -EFAULT; | 131 | return -EFAULT; |
131 | 132 | ||
132 | if (options & WDIOS_DISABLECARD) { | 133 | if (options & WDIOS_DISABLECARD) { |
@@ -140,7 +141,6 @@ static int epx_c3_ioctl(struct inode *inode, struct file *file, | |||
140 | } | 141 | } |
141 | 142 | ||
142 | return retval; | 143 | return retval; |
143 | } | ||
144 | default: | 144 | default: |
145 | return -ENOIOCTLCMD; | 145 | return -ENOIOCTLCMD; |
146 | } | 146 | } |
@@ -181,11 +181,14 @@ static int __init watchdog_init(void) | |||
181 | { | 181 | { |
182 | int ret; | 182 | int ret; |
183 | 183 | ||
184 | if (!request_region(EPXC3_WATCHDOG_CTL_REG, 2, "epxc3_watchdog")) | ||
185 | return -EBUSY; | ||
186 | |||
184 | ret = register_reboot_notifier(&epx_c3_notifier); | 187 | ret = register_reboot_notifier(&epx_c3_notifier); |
185 | if (ret) { | 188 | if (ret) { |
186 | printk(KERN_ERR PFX "cannot register reboot notifier " | 189 | printk(KERN_ERR PFX "cannot register reboot notifier " |
187 | "(err=%d)\n", ret); | 190 | "(err=%d)\n", ret); |
188 | return ret; | 191 | goto out; |
189 | } | 192 | } |
190 | 193 | ||
191 | ret = misc_register(&epx_c3_miscdev); | 194 | ret = misc_register(&epx_c3_miscdev); |
@@ -193,18 +196,23 @@ static int __init watchdog_init(void) | |||
193 | printk(KERN_ERR PFX "cannot register miscdev on minor=%d " | 196 | printk(KERN_ERR PFX "cannot register miscdev on minor=%d " |
194 | "(err=%d)\n", WATCHDOG_MINOR, ret); | 197 | "(err=%d)\n", WATCHDOG_MINOR, ret); |
195 | unregister_reboot_notifier(&epx_c3_notifier); | 198 | unregister_reboot_notifier(&epx_c3_notifier); |
196 | return ret; | 199 | goto out; |
197 | } | 200 | } |
198 | 201 | ||
199 | printk(banner); | 202 | printk(banner); |
200 | 203 | ||
201 | return 0; | 204 | return 0; |
205 | |||
206 | out: | ||
207 | release_region(EPXC3_WATCHDOG_CTL_REG, 2); | ||
208 | return ret; | ||
202 | } | 209 | } |
203 | 210 | ||
204 | static void __exit watchdog_exit(void) | 211 | static void __exit watchdog_exit(void) |
205 | { | 212 | { |
206 | misc_deregister(&epx_c3_miscdev); | 213 | misc_deregister(&epx_c3_miscdev); |
207 | unregister_reboot_notifier(&epx_c3_notifier); | 214 | unregister_reboot_notifier(&epx_c3_notifier); |
215 | release_region(EPXC3_WATCHDOG_CTL_REG, 2); | ||
208 | } | 216 | } |
209 | 217 | ||
210 | module_init(watchdog_init); | 218 | module_init(watchdog_init); |
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 4819e7fc00dd..18a455651121 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig | |||
@@ -11,7 +11,6 @@ menu 'EDAC - error detection and reporting (RAS)' | |||
11 | config EDAC | 11 | config EDAC |
12 | tristate "EDAC core system error reporting" | 12 | tristate "EDAC core system error reporting" |
13 | depends on X86 | 13 | depends on X86 |
14 | default y | ||
15 | help | 14 | help |
16 | EDAC is designed to report errors in the core system. | 15 | EDAC is designed to report errors in the core system. |
17 | These are low-level errors that are reported in the CPU or | 16 | These are low-level errors that are reported in the CPU or |
@@ -46,7 +45,7 @@ config EDAC_MM_EDAC | |||
46 | 45 | ||
47 | config EDAC_AMD76X | 46 | config EDAC_AMD76X |
48 | tristate "AMD 76x (760, 762, 768)" | 47 | tristate "AMD 76x (760, 762, 768)" |
49 | depends on EDAC_MM_EDAC && PCI | 48 | depends on EDAC_MM_EDAC && PCI && X86_32 |
50 | help | 49 | help |
51 | Support for error detection and correction on the AMD 76x | 50 | Support for error detection and correction on the AMD 76x |
52 | series of chipsets used with the Athlon processor. | 51 | series of chipsets used with the Athlon processor. |
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index 770a5a633079..c454ded2b060 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c | |||
@@ -1039,10 +1039,10 @@ MODULE_DEVICE_TABLE(pci, e752x_pci_tbl); | |||
1039 | 1039 | ||
1040 | 1040 | ||
1041 | static struct pci_driver e752x_driver = { | 1041 | static struct pci_driver e752x_driver = { |
1042 | name: BS_MOD_STR, | 1042 | .name = BS_MOD_STR, |
1043 | probe: e752x_init_one, | 1043 | .probe = e752x_init_one, |
1044 | remove: __devexit_p(e752x_remove_one), | 1044 | .remove = __devexit_p(e752x_remove_one), |
1045 | id_table: e752x_pci_tbl, | 1045 | .id_table = e752x_pci_tbl, |
1046 | }; | 1046 | }; |
1047 | 1047 | ||
1048 | 1048 | ||
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 4be9bd0a1267..b10ee4698b1d 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c | |||
@@ -14,7 +14,6 @@ | |||
14 | 14 | ||
15 | 15 | ||
16 | #include <linux/config.h> | 16 | #include <linux/config.h> |
17 | #include <linux/version.h> | ||
18 | #include <linux/module.h> | 17 | #include <linux/module.h> |
19 | #include <linux/proc_fs.h> | 18 | #include <linux/proc_fs.h> |
20 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index 009c08fe5d69..1991f94af753 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c | |||
@@ -159,7 +159,7 @@ enum i82875p_chips { | |||
159 | 159 | ||
160 | struct i82875p_pvt { | 160 | struct i82875p_pvt { |
161 | struct pci_dev *ovrfl_pdev; | 161 | struct pci_dev *ovrfl_pdev; |
162 | void *ovrfl_window; | 162 | void __iomem *ovrfl_window; |
163 | }; | 163 | }; |
164 | 164 | ||
165 | 165 | ||
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index c58295914365..7230d4e08196 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -113,6 +113,16 @@ config SENSORS_DS1621 | |||
113 | This driver can also be built as a module. If so, the module | 113 | This driver can also be built as a module. If so, the module |
114 | will be called ds1621. | 114 | will be called ds1621. |
115 | 115 | ||
116 | config SENSORS_F71805F | ||
117 | tristate "Fintek F71805F/FG" | ||
118 | depends on HWMON && EXPERIMENTAL | ||
119 | help | ||
120 | If you say yes here you get support for hardware monitoring | ||
121 | features of the Fintek F71805F/FG chips. | ||
122 | |||
123 | This driver can also be built as a module. If so, the module | ||
124 | will be called f71805f. | ||
125 | |||
116 | config SENSORS_FSCHER | 126 | config SENSORS_FSCHER |
117 | tristate "FSC Hermes" | 127 | tristate "FSC Hermes" |
118 | depends on HWMON && I2C && EXPERIMENTAL | 128 | depends on HWMON && I2C && EXPERIMENTAL |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 06d4a1d14105..fbdb8d911a72 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
@@ -18,6 +18,7 @@ obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o | |||
18 | obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o | 18 | obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o |
19 | obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o | 19 | obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o |
20 | obj-$(CONFIG_SENSORS_DS1621) += ds1621.o | 20 | obj-$(CONFIG_SENSORS_DS1621) += ds1621.o |
21 | obj-$(CONFIG_SENSORS_F71805F) += f71805f.o | ||
21 | obj-$(CONFIG_SENSORS_FSCHER) += fscher.o | 22 | obj-$(CONFIG_SENSORS_FSCHER) += fscher.o |
22 | obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o | 23 | obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o |
23 | obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o | 24 | obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o |
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c new file mode 100644 index 000000000000..e029e0a94ecc --- /dev/null +++ b/drivers/hwmon/f71805f.c | |||
@@ -0,0 +1,908 @@ | |||
1 | /* | ||
2 | * f71805f.c - driver for the Fintek F71805F/FG Super-I/O chip integrated | ||
3 | * hardware monitoring features | ||
4 | * Copyright (C) 2005 Jean Delvare <khali@linux-fr.org> | ||
5 | * | ||
6 | * The F71805F/FG is a LPC Super-I/O chip made by Fintek. It integrates | ||
7 | * complete hardware monitoring features: voltage, fan and temperature | ||
8 | * sensors, and manual and automatic fan speed control. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | */ | ||
24 | |||
25 | #include <linux/module.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/jiffies.h> | ||
29 | #include <linux/platform_device.h> | ||
30 | #include <linux/hwmon.h> | ||
31 | #include <linux/hwmon-sysfs.h> | ||
32 | #include <linux/err.h> | ||
33 | #include <asm/io.h> | ||
34 | |||
35 | static struct platform_device *pdev; | ||
36 | |||
37 | #define DRVNAME "f71805f" | ||
38 | |||
39 | /* | ||
40 | * Super-I/O constants and functions | ||
41 | */ | ||
42 | |||
43 | #define F71805F_LD_HWM 0x04 | ||
44 | |||
45 | #define SIO_REG_LDSEL 0x07 /* Logical device select */ | ||
46 | #define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ | ||
47 | #define SIO_REG_DEVREV 0x22 /* Device revision */ | ||
48 | #define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */ | ||
49 | #define SIO_REG_ENABLE 0x30 /* Logical device enable */ | ||
50 | #define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ | ||
51 | |||
52 | #define SIO_FINTEK_ID 0x1934 | ||
53 | #define SIO_F71805F_ID 0x0406 | ||
54 | |||
55 | static inline int | ||
56 | superio_inb(int base, int reg) | ||
57 | { | ||
58 | outb(reg, base); | ||
59 | return inb(base + 1); | ||
60 | } | ||
61 | |||
62 | static int | ||
63 | superio_inw(int base, int reg) | ||
64 | { | ||
65 | int val; | ||
66 | outb(reg++, base); | ||
67 | val = inb(base + 1) << 8; | ||
68 | outb(reg, base); | ||
69 | val |= inb(base + 1); | ||
70 | return val; | ||
71 | } | ||
72 | |||
73 | static inline void | ||
74 | superio_select(int base, int ld) | ||
75 | { | ||
76 | outb(SIO_REG_LDSEL, base); | ||
77 | outb(ld, base + 1); | ||
78 | } | ||
79 | |||
80 | static inline void | ||
81 | superio_enter(int base) | ||
82 | { | ||
83 | outb(0x87, base); | ||
84 | outb(0x87, base); | ||
85 | } | ||
86 | |||
87 | static inline void | ||
88 | superio_exit(int base) | ||
89 | { | ||
90 | outb(0xaa, base); | ||
91 | } | ||
92 | |||
93 | /* | ||
94 | * ISA constants | ||
95 | */ | ||
96 | |||
97 | #define REGION_LENGTH 2 | ||
98 | #define ADDR_REG_OFFSET 0 | ||
99 | #define DATA_REG_OFFSET 1 | ||
100 | |||
101 | static struct resource f71805f_resource __initdata = { | ||
102 | .flags = IORESOURCE_IO, | ||
103 | }; | ||
104 | |||
105 | /* | ||
106 | * Registers | ||
107 | */ | ||
108 | |||
109 | /* in nr from 0 to 8 (8-bit values) */ | ||
110 | #define F71805F_REG_IN(nr) (0x10 + (nr)) | ||
111 | #define F71805F_REG_IN_HIGH(nr) (0x40 + 2 * (nr)) | ||
112 | #define F71805F_REG_IN_LOW(nr) (0x41 + 2 * (nr)) | ||
113 | /* fan nr from 0 to 2 (12-bit values, two registers) */ | ||
114 | #define F71805F_REG_FAN(nr) (0x20 + 2 * (nr)) | ||
115 | #define F71805F_REG_FAN_LOW(nr) (0x28 + 2 * (nr)) | ||
116 | #define F71805F_REG_FAN_CTRL(nr) (0x60 + 16 * (nr)) | ||
117 | /* temp nr from 0 to 2 (8-bit values) */ | ||
118 | #define F71805F_REG_TEMP(nr) (0x1B + (nr)) | ||
119 | #define F71805F_REG_TEMP_HIGH(nr) (0x54 + 2 * (nr)) | ||
120 | #define F71805F_REG_TEMP_HYST(nr) (0x55 + 2 * (nr)) | ||
121 | #define F71805F_REG_TEMP_MODE 0x01 | ||
122 | |||
123 | #define F71805F_REG_START 0x00 | ||
124 | /* status nr from 0 to 2 */ | ||
125 | #define F71805F_REG_STATUS(nr) (0x36 + (nr)) | ||
126 | |||
127 | /* | ||
128 | * Data structures and manipulation thereof | ||
129 | */ | ||
130 | |||
131 | struct f71805f_data { | ||
132 | unsigned short addr; | ||
133 | const char *name; | ||
134 | struct semaphore lock; | ||
135 | struct class_device *class_dev; | ||
136 | |||
137 | struct semaphore update_lock; | ||
138 | char valid; /* !=0 if following fields are valid */ | ||
139 | unsigned long last_updated; /* In jiffies */ | ||
140 | unsigned long last_limits; /* In jiffies */ | ||
141 | |||
142 | /* Register values */ | ||
143 | u8 in[9]; | ||
144 | u8 in_high[9]; | ||
145 | u8 in_low[9]; | ||
146 | u16 fan[3]; | ||
147 | u16 fan_low[3]; | ||
148 | u8 fan_enabled; /* Read once at init time */ | ||
149 | u8 temp[3]; | ||
150 | u8 temp_high[3]; | ||
151 | u8 temp_hyst[3]; | ||
152 | u8 temp_mode; | ||
153 | u8 alarms[3]; | ||
154 | }; | ||
155 | |||
156 | static inline long in_from_reg(u8 reg) | ||
157 | { | ||
158 | return (reg * 8); | ||
159 | } | ||
160 | |||
161 | /* The 2 least significant bits are not used */ | ||
162 | static inline u8 in_to_reg(long val) | ||
163 | { | ||
164 | if (val <= 0) | ||
165 | return 0; | ||
166 | if (val >= 2016) | ||
167 | return 0xfc; | ||
168 | return (((val + 16) / 32) << 2); | ||
169 | } | ||
170 | |||
171 | /* in0 is downscaled by a factor 2 internally */ | ||
172 | static inline long in0_from_reg(u8 reg) | ||
173 | { | ||
174 | return (reg * 16); | ||
175 | } | ||
176 | |||
177 | static inline u8 in0_to_reg(long val) | ||
178 | { | ||
179 | if (val <= 0) | ||
180 | return 0; | ||
181 | if (val >= 4032) | ||
182 | return 0xfc; | ||
183 | return (((val + 32) / 64) << 2); | ||
184 | } | ||
185 | |||
186 | /* The 4 most significant bits are not used */ | ||
187 | static inline long fan_from_reg(u16 reg) | ||
188 | { | ||
189 | reg &= 0xfff; | ||
190 | if (!reg || reg == 0xfff) | ||
191 | return 0; | ||
192 | return (1500000 / reg); | ||
193 | } | ||
194 | |||
195 | static inline u16 fan_to_reg(long rpm) | ||
196 | { | ||
197 | /* If the low limit is set below what the chip can measure, | ||
198 | store the largest possible 12-bit value in the registers, | ||
199 | so that no alarm will ever trigger. */ | ||
200 | if (rpm < 367) | ||
201 | return 0xfff; | ||
202 | return (1500000 / rpm); | ||
203 | } | ||
204 | |||
205 | static inline long temp_from_reg(u8 reg) | ||
206 | { | ||
207 | return (reg * 1000); | ||
208 | } | ||
209 | |||
210 | static inline u8 temp_to_reg(long val) | ||
211 | { | ||
212 | if (val < 0) | ||
213 | val = 0; | ||
214 | else if (val > 1000 * 0xff) | ||
215 | val = 0xff; | ||
216 | return ((val + 500) / 1000); | ||
217 | } | ||
218 | |||
219 | /* | ||
220 | * Device I/O access | ||
221 | */ | ||
222 | |||
223 | static u8 f71805f_read8(struct f71805f_data *data, u8 reg) | ||
224 | { | ||
225 | u8 val; | ||
226 | |||
227 | down(&data->lock); | ||
228 | outb(reg, data->addr + ADDR_REG_OFFSET); | ||
229 | val = inb(data->addr + DATA_REG_OFFSET); | ||
230 | up(&data->lock); | ||
231 | |||
232 | return val; | ||
233 | } | ||
234 | |||
235 | static void f71805f_write8(struct f71805f_data *data, u8 reg, u8 val) | ||
236 | { | ||
237 | down(&data->lock); | ||
238 | outb(reg, data->addr + ADDR_REG_OFFSET); | ||
239 | outb(val, data->addr + DATA_REG_OFFSET); | ||
240 | up(&data->lock); | ||
241 | } | ||
242 | |||
243 | /* It is important to read the MSB first, because doing so latches the | ||
244 | value of the LSB, so we are sure both bytes belong to the same value. */ | ||
245 | static u16 f71805f_read16(struct f71805f_data *data, u8 reg) | ||
246 | { | ||
247 | u16 val; | ||
248 | |||
249 | down(&data->lock); | ||
250 | outb(reg, data->addr + ADDR_REG_OFFSET); | ||
251 | val = inb(data->addr + DATA_REG_OFFSET) << 8; | ||
252 | outb(++reg, data->addr + ADDR_REG_OFFSET); | ||
253 | val |= inb(data->addr + DATA_REG_OFFSET); | ||
254 | up(&data->lock); | ||
255 | |||
256 | return val; | ||
257 | } | ||
258 | |||
259 | static void f71805f_write16(struct f71805f_data *data, u8 reg, u16 val) | ||
260 | { | ||
261 | down(&data->lock); | ||
262 | outb(reg, data->addr + ADDR_REG_OFFSET); | ||
263 | outb(val >> 8, data->addr + DATA_REG_OFFSET); | ||
264 | outb(++reg, data->addr + ADDR_REG_OFFSET); | ||
265 | outb(val & 0xff, data->addr + DATA_REG_OFFSET); | ||
266 | up(&data->lock); | ||
267 | } | ||
268 | |||
269 | static struct f71805f_data *f71805f_update_device(struct device *dev) | ||
270 | { | ||
271 | struct f71805f_data *data = dev_get_drvdata(dev); | ||
272 | int nr; | ||
273 | |||
274 | down(&data->update_lock); | ||
275 | |||
276 | /* Limit registers cache is refreshed after 60 seconds */ | ||
277 | if (time_after(jiffies, data->last_updated + 60 * HZ) | ||
278 | || !data->valid) { | ||
279 | for (nr = 0; nr < 9; nr++) { | ||
280 | data->in_high[nr] = f71805f_read8(data, | ||
281 | F71805F_REG_IN_HIGH(nr)); | ||
282 | data->in_low[nr] = f71805f_read8(data, | ||
283 | F71805F_REG_IN_LOW(nr)); | ||
284 | } | ||
285 | for (nr = 0; nr < 3; nr++) { | ||
286 | if (data->fan_enabled & (1 << nr)) | ||
287 | data->fan_low[nr] = f71805f_read16(data, | ||
288 | F71805F_REG_FAN_LOW(nr)); | ||
289 | } | ||
290 | for (nr = 0; nr < 3; nr++) { | ||
291 | data->temp_high[nr] = f71805f_read8(data, | ||
292 | F71805F_REG_TEMP_HIGH(nr)); | ||
293 | data->temp_hyst[nr] = f71805f_read8(data, | ||
294 | F71805F_REG_TEMP_HYST(nr)); | ||
295 | } | ||
296 | data->temp_mode = f71805f_read8(data, F71805F_REG_TEMP_MODE); | ||
297 | |||
298 | data->last_limits = jiffies; | ||
299 | } | ||
300 | |||
301 | /* Measurement registers cache is refreshed after 1 second */ | ||
302 | if (time_after(jiffies, data->last_updated + HZ) | ||
303 | || !data->valid) { | ||
304 | for (nr = 0; nr < 9; nr++) { | ||
305 | data->in[nr] = f71805f_read8(data, | ||
306 | F71805F_REG_IN(nr)); | ||
307 | } | ||
308 | for (nr = 0; nr < 3; nr++) { | ||
309 | if (data->fan_enabled & (1 << nr)) | ||
310 | data->fan[nr] = f71805f_read16(data, | ||
311 | F71805F_REG_FAN(nr)); | ||
312 | } | ||
313 | for (nr = 0; nr < 3; nr++) { | ||
314 | data->temp[nr] = f71805f_read8(data, | ||
315 | F71805F_REG_TEMP(nr)); | ||
316 | } | ||
317 | for (nr = 0; nr < 3; nr++) { | ||
318 | data->alarms[nr] = f71805f_read8(data, | ||
319 | F71805F_REG_STATUS(nr)); | ||
320 | } | ||
321 | |||
322 | data->last_updated = jiffies; | ||
323 | data->valid = 1; | ||
324 | } | ||
325 | |||
326 | up(&data->update_lock); | ||
327 | |||
328 | return data; | ||
329 | } | ||
330 | |||
331 | /* | ||
332 | * Sysfs interface | ||
333 | */ | ||
334 | |||
335 | static ssize_t show_in0(struct device *dev, struct device_attribute *devattr, | ||
336 | char *buf) | ||
337 | { | ||
338 | struct f71805f_data *data = f71805f_update_device(dev); | ||
339 | |||
340 | return sprintf(buf, "%ld\n", in0_from_reg(data->in[0])); | ||
341 | } | ||
342 | |||
343 | static ssize_t show_in0_max(struct device *dev, struct device_attribute | ||
344 | *devattr, char *buf) | ||
345 | { | ||
346 | struct f71805f_data *data = f71805f_update_device(dev); | ||
347 | |||
348 | return sprintf(buf, "%ld\n", in0_from_reg(data->in_high[0])); | ||
349 | } | ||
350 | |||
351 | static ssize_t show_in0_min(struct device *dev, struct device_attribute | ||
352 | *devattr, char *buf) | ||
353 | { | ||
354 | struct f71805f_data *data = f71805f_update_device(dev); | ||
355 | |||
356 | return sprintf(buf, "%ld\n", in0_from_reg(data->in_low[0])); | ||
357 | } | ||
358 | |||
359 | static ssize_t set_in0_max(struct device *dev, struct device_attribute | ||
360 | *devattr, const char *buf, size_t count) | ||
361 | { | ||
362 | struct f71805f_data *data = dev_get_drvdata(dev); | ||
363 | long val = simple_strtol(buf, NULL, 10); | ||
364 | |||
365 | down(&data->update_lock); | ||
366 | data->in_high[0] = in0_to_reg(val); | ||
367 | f71805f_write8(data, F71805F_REG_IN_HIGH(0), data->in_high[0]); | ||
368 | up(&data->update_lock); | ||
369 | |||
370 | return count; | ||
371 | } | ||
372 | |||
373 | static ssize_t set_in0_min(struct device *dev, struct device_attribute | ||
374 | *devattr, const char *buf, size_t count) | ||
375 | { | ||
376 | struct f71805f_data *data = dev_get_drvdata(dev); | ||
377 | long val = simple_strtol(buf, NULL, 10); | ||
378 | |||
379 | down(&data->update_lock); | ||
380 | data->in_low[0] = in0_to_reg(val); | ||
381 | f71805f_write8(data, F71805F_REG_IN_LOW(0), data->in_low[0]); | ||
382 | up(&data->update_lock); | ||
383 | |||
384 | return count; | ||
385 | } | ||
386 | |||
387 | static DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL); | ||
388 | static DEVICE_ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max); | ||
389 | static DEVICE_ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min); | ||
390 | |||
391 | static ssize_t show_in(struct device *dev, struct device_attribute *devattr, | ||
392 | char *buf) | ||
393 | { | ||
394 | struct f71805f_data *data = f71805f_update_device(dev); | ||
395 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
396 | int nr = attr->index; | ||
397 | |||
398 | return sprintf(buf, "%ld\n", in_from_reg(data->in[nr])); | ||
399 | } | ||
400 | |||
401 | static ssize_t show_in_max(struct device *dev, struct device_attribute | ||
402 | *devattr, char *buf) | ||
403 | { | ||
404 | struct f71805f_data *data = f71805f_update_device(dev); | ||
405 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
406 | int nr = attr->index; | ||
407 | |||
408 | return sprintf(buf, "%ld\n", in_from_reg(data->in_high[nr])); | ||
409 | } | ||
410 | |||
411 | static ssize_t show_in_min(struct device *dev, struct device_attribute | ||
412 | *devattr, char *buf) | ||
413 | { | ||
414 | struct f71805f_data *data = f71805f_update_device(dev); | ||
415 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
416 | int nr = attr->index; | ||
417 | |||
418 | return sprintf(buf, "%ld\n", in_from_reg(data->in_low[nr])); | ||
419 | } | ||
420 | |||
421 | static ssize_t set_in_max(struct device *dev, struct device_attribute | ||
422 | *devattr, const char *buf, size_t count) | ||
423 | { | ||
424 | struct f71805f_data *data = dev_get_drvdata(dev); | ||
425 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
426 | int nr = attr->index; | ||
427 | long val = simple_strtol(buf, NULL, 10); | ||
428 | |||
429 | down(&data->update_lock); | ||
430 | data->in_high[nr] = in_to_reg(val); | ||
431 | f71805f_write8(data, F71805F_REG_IN_HIGH(nr), data->in_high[nr]); | ||
432 | up(&data->update_lock); | ||
433 | |||
434 | return count; | ||
435 | } | ||
436 | |||
437 | static ssize_t set_in_min(struct device *dev, struct device_attribute | ||
438 | *devattr, const char *buf, size_t count) | ||
439 | { | ||
440 | struct f71805f_data *data = dev_get_drvdata(dev); | ||
441 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
442 | int nr = attr->index; | ||
443 | long val = simple_strtol(buf, NULL, 10); | ||
444 | |||
445 | down(&data->update_lock); | ||
446 | data->in_low[nr] = in_to_reg(val); | ||
447 | f71805f_write8(data, F71805F_REG_IN_LOW(nr), data->in_low[nr]); | ||
448 | up(&data->update_lock); | ||
449 | |||
450 | return count; | ||
451 | } | ||
452 | |||
453 | #define sysfs_in(offset) \ | ||
454 | static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ | ||
455 | show_in, NULL, offset); \ | ||
456 | static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ | ||
457 | show_in_max, set_in_max, offset); \ | ||
458 | static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ | ||
459 | show_in_min, set_in_min, offset) | ||
460 | |||
461 | sysfs_in(1); | ||
462 | sysfs_in(2); | ||
463 | sysfs_in(3); | ||
464 | sysfs_in(4); | ||
465 | sysfs_in(5); | ||
466 | sysfs_in(6); | ||
467 | sysfs_in(7); | ||
468 | sysfs_in(8); | ||
469 | |||
470 | static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, | ||
471 | char *buf) | ||
472 | { | ||
473 | struct f71805f_data *data = f71805f_update_device(dev); | ||
474 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
475 | int nr = attr->index; | ||
476 | |||
477 | return sprintf(buf, "%ld\n", fan_from_reg(data->fan[nr])); | ||
478 | } | ||
479 | |||
480 | static ssize_t show_fan_min(struct device *dev, struct device_attribute | ||
481 | *devattr, char *buf) | ||
482 | { | ||
483 | struct f71805f_data *data = f71805f_update_device(dev); | ||
484 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
485 | int nr = attr->index; | ||
486 | |||
487 | return sprintf(buf, "%ld\n", fan_from_reg(data->fan_low[nr])); | ||
488 | } | ||
489 | |||
490 | static ssize_t set_fan_min(struct device *dev, struct device_attribute | ||
491 | *devattr, const char *buf, size_t count) | ||
492 | { | ||
493 | struct f71805f_data *data = dev_get_drvdata(dev); | ||
494 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
495 | int nr = attr->index; | ||
496 | long val = simple_strtol(buf, NULL, 10); | ||
497 | |||
498 | down(&data->update_lock); | ||
499 | data->fan_low[nr] = fan_to_reg(val); | ||
500 | f71805f_write16(data, F71805F_REG_FAN_LOW(nr), data->fan_low[nr]); | ||
501 | up(&data->update_lock); | ||
502 | |||
503 | return count; | ||
504 | } | ||
505 | |||
506 | #define sysfs_fan(offset) \ | ||
507 | static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ | ||
508 | show_fan, NULL, offset - 1); \ | ||
509 | static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ | ||
510 | show_fan_min, set_fan_min, offset - 1) | ||
511 | |||
512 | sysfs_fan(1); | ||
513 | sysfs_fan(2); | ||
514 | sysfs_fan(3); | ||
515 | |||
516 | static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, | ||
517 | char *buf) | ||
518 | { | ||
519 | struct f71805f_data *data = f71805f_update_device(dev); | ||
520 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
521 | int nr = attr->index; | ||
522 | |||
523 | return sprintf(buf, "%ld\n", temp_from_reg(data->temp[nr])); | ||
524 | } | ||
525 | |||
526 | static ssize_t show_temp_max(struct device *dev, struct device_attribute | ||
527 | *devattr, char *buf) | ||
528 | { | ||
529 | struct f71805f_data *data = f71805f_update_device(dev); | ||
530 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
531 | int nr = attr->index; | ||
532 | |||
533 | return sprintf(buf, "%ld\n", temp_from_reg(data->temp_high[nr])); | ||
534 | } | ||
535 | |||
536 | static ssize_t show_temp_hyst(struct device *dev, struct device_attribute | ||
537 | *devattr, char *buf) | ||
538 | { | ||
539 | struct f71805f_data *data = f71805f_update_device(dev); | ||
540 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
541 | int nr = attr->index; | ||
542 | |||
543 | return sprintf(buf, "%ld\n", temp_from_reg(data->temp_hyst[nr])); | ||
544 | } | ||
545 | |||
546 | static ssize_t show_temp_type(struct device *dev, struct device_attribute | ||
547 | *devattr, char *buf) | ||
548 | { | ||
549 | struct f71805f_data *data = f71805f_update_device(dev); | ||
550 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
551 | int nr = attr->index; | ||
552 | |||
553 | /* 3 is diode, 4 is thermistor */ | ||
554 | return sprintf(buf, "%u\n", (data->temp_mode & (1 << nr)) ? 3 : 4); | ||
555 | } | ||
556 | |||
557 | static ssize_t set_temp_max(struct device *dev, struct device_attribute | ||
558 | *devattr, const char *buf, size_t count) | ||
559 | { | ||
560 | struct f71805f_data *data = dev_get_drvdata(dev); | ||
561 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
562 | int nr = attr->index; | ||
563 | long val = simple_strtol(buf, NULL, 10); | ||
564 | |||
565 | down(&data->update_lock); | ||
566 | data->temp_high[nr] = temp_to_reg(val); | ||
567 | f71805f_write8(data, F71805F_REG_TEMP_HIGH(nr), data->temp_high[nr]); | ||
568 | up(&data->update_lock); | ||
569 | |||
570 | return count; | ||
571 | } | ||
572 | |||
573 | static ssize_t set_temp_hyst(struct device *dev, struct device_attribute | ||
574 | *devattr, const char *buf, size_t count) | ||
575 | { | ||
576 | struct f71805f_data *data = dev_get_drvdata(dev); | ||
577 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
578 | int nr = attr->index; | ||
579 | long val = simple_strtol(buf, NULL, 10); | ||
580 | |||
581 | down(&data->update_lock); | ||
582 | data->temp_hyst[nr] = temp_to_reg(val); | ||
583 | f71805f_write8(data, F71805F_REG_TEMP_HYST(nr), data->temp_hyst[nr]); | ||
584 | up(&data->update_lock); | ||
585 | |||
586 | return count; | ||
587 | } | ||
588 | |||
589 | #define sysfs_temp(offset) \ | ||
590 | static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ | ||
591 | show_temp, NULL, offset - 1); \ | ||
592 | static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ | ||
593 | show_temp_max, set_temp_max, offset - 1); \ | ||
594 | static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \ | ||
595 | show_temp_hyst, set_temp_hyst, offset - 1); \ | ||
596 | static SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO, \ | ||
597 | show_temp_type, NULL, offset - 1) | ||
598 | |||
599 | sysfs_temp(1); | ||
600 | sysfs_temp(2); | ||
601 | sysfs_temp(3); | ||
602 | |||
603 | static ssize_t show_alarms_in(struct device *dev, struct device_attribute | ||
604 | *devattr, char *buf) | ||
605 | { | ||
606 | struct f71805f_data *data = f71805f_update_device(dev); | ||
607 | |||
608 | return sprintf(buf, "%d\n", data->alarms[0] | | ||
609 | ((data->alarms[1] & 0x01) << 8)); | ||
610 | } | ||
611 | |||
612 | static ssize_t show_alarms_fan(struct device *dev, struct device_attribute | ||
613 | *devattr, char *buf) | ||
614 | { | ||
615 | struct f71805f_data *data = f71805f_update_device(dev); | ||
616 | |||
617 | return sprintf(buf, "%d\n", data->alarms[2] & 0x07); | ||
618 | } | ||
619 | |||
620 | static ssize_t show_alarms_temp(struct device *dev, struct device_attribute | ||
621 | *devattr, char *buf) | ||
622 | { | ||
623 | struct f71805f_data *data = f71805f_update_device(dev); | ||
624 | |||
625 | return sprintf(buf, "%d\n", (data->alarms[1] >> 3) & 0x07); | ||
626 | } | ||
627 | |||
628 | static DEVICE_ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL); | ||
629 | static DEVICE_ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL); | ||
630 | static DEVICE_ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL); | ||
631 | |||
632 | static ssize_t show_name(struct device *dev, struct device_attribute | ||
633 | *devattr, char *buf) | ||
634 | { | ||
635 | struct f71805f_data *data = dev_get_drvdata(dev); | ||
636 | |||
637 | return sprintf(buf, "%s\n", data->name); | ||
638 | } | ||
639 | |||
640 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | ||
641 | |||
642 | /* | ||
643 | * Device registration and initialization | ||
644 | */ | ||
645 | |||
646 | static void __devinit f71805f_init_device(struct f71805f_data *data) | ||
647 | { | ||
648 | u8 reg; | ||
649 | int i; | ||
650 | |||
651 | reg = f71805f_read8(data, F71805F_REG_START); | ||
652 | if ((reg & 0x41) != 0x01) { | ||
653 | printk(KERN_DEBUG DRVNAME ": Starting monitoring " | ||
654 | "operations\n"); | ||
655 | f71805f_write8(data, F71805F_REG_START, (reg | 0x01) & ~0x40); | ||
656 | } | ||
657 | |||
658 | /* Fan monitoring can be disabled. If it is, we won't be polling | ||
659 | the register values, and won't create the related sysfs files. */ | ||
660 | for (i = 0; i < 3; i++) { | ||
661 | reg = f71805f_read8(data, F71805F_REG_FAN_CTRL(i)); | ||
662 | if (!(reg & 0x80)) | ||
663 | data->fan_enabled |= (1 << i); | ||
664 | } | ||
665 | } | ||
666 | |||
667 | static int __devinit f71805f_probe(struct platform_device *pdev) | ||
668 | { | ||
669 | struct f71805f_data *data; | ||
670 | struct resource *res; | ||
671 | int err; | ||
672 | |||
673 | if (!(data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL))) { | ||
674 | err = -ENOMEM; | ||
675 | printk(KERN_ERR DRVNAME ": Out of memory\n"); | ||
676 | goto exit; | ||
677 | } | ||
678 | |||
679 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
680 | data->addr = res->start; | ||
681 | init_MUTEX(&data->lock); | ||
682 | data->name = "f71805f"; | ||
683 | init_MUTEX(&data->update_lock); | ||
684 | |||
685 | platform_set_drvdata(pdev, data); | ||
686 | |||
687 | data->class_dev = hwmon_device_register(&pdev->dev); | ||
688 | if (IS_ERR(data->class_dev)) { | ||
689 | err = PTR_ERR(data->class_dev); | ||
690 | dev_err(&pdev->dev, "Class registration failed (%d)\n", err); | ||
691 | goto exit_free; | ||
692 | } | ||
693 | |||
694 | /* Initialize the F71805F chip */ | ||
695 | f71805f_init_device(data); | ||
696 | |||
697 | /* Register sysfs interface files */ | ||
698 | device_create_file(&pdev->dev, &dev_attr_in0_input); | ||
699 | device_create_file(&pdev->dev, &dev_attr_in0_max); | ||
700 | device_create_file(&pdev->dev, &dev_attr_in0_min); | ||
701 | device_create_file(&pdev->dev, &sensor_dev_attr_in1_input.dev_attr); | ||
702 | device_create_file(&pdev->dev, &sensor_dev_attr_in2_input.dev_attr); | ||
703 | device_create_file(&pdev->dev, &sensor_dev_attr_in3_input.dev_attr); | ||
704 | device_create_file(&pdev->dev, &sensor_dev_attr_in4_input.dev_attr); | ||
705 | device_create_file(&pdev->dev, &sensor_dev_attr_in5_input.dev_attr); | ||
706 | device_create_file(&pdev->dev, &sensor_dev_attr_in6_input.dev_attr); | ||
707 | device_create_file(&pdev->dev, &sensor_dev_attr_in7_input.dev_attr); | ||
708 | device_create_file(&pdev->dev, &sensor_dev_attr_in8_input.dev_attr); | ||
709 | device_create_file(&pdev->dev, &sensor_dev_attr_in1_max.dev_attr); | ||
710 | device_create_file(&pdev->dev, &sensor_dev_attr_in2_max.dev_attr); | ||
711 | device_create_file(&pdev->dev, &sensor_dev_attr_in3_max.dev_attr); | ||
712 | device_create_file(&pdev->dev, &sensor_dev_attr_in4_max.dev_attr); | ||
713 | device_create_file(&pdev->dev, &sensor_dev_attr_in5_max.dev_attr); | ||
714 | device_create_file(&pdev->dev, &sensor_dev_attr_in6_max.dev_attr); | ||
715 | device_create_file(&pdev->dev, &sensor_dev_attr_in7_max.dev_attr); | ||
716 | device_create_file(&pdev->dev, &sensor_dev_attr_in8_max.dev_attr); | ||
717 | device_create_file(&pdev->dev, &sensor_dev_attr_in1_min.dev_attr); | ||
718 | device_create_file(&pdev->dev, &sensor_dev_attr_in2_min.dev_attr); | ||
719 | device_create_file(&pdev->dev, &sensor_dev_attr_in3_min.dev_attr); | ||
720 | device_create_file(&pdev->dev, &sensor_dev_attr_in4_min.dev_attr); | ||
721 | device_create_file(&pdev->dev, &sensor_dev_attr_in5_min.dev_attr); | ||
722 | device_create_file(&pdev->dev, &sensor_dev_attr_in6_min.dev_attr); | ||
723 | device_create_file(&pdev->dev, &sensor_dev_attr_in7_min.dev_attr); | ||
724 | device_create_file(&pdev->dev, &sensor_dev_attr_in8_min.dev_attr); | ||
725 | if (data->fan_enabled & (1 << 0)) { | ||
726 | device_create_file(&pdev->dev, | ||
727 | &sensor_dev_attr_fan1_input.dev_attr); | ||
728 | device_create_file(&pdev->dev, | ||
729 | &sensor_dev_attr_fan1_min.dev_attr); | ||
730 | } | ||
731 | if (data->fan_enabled & (1 << 1)) { | ||
732 | device_create_file(&pdev->dev, | ||
733 | &sensor_dev_attr_fan2_input.dev_attr); | ||
734 | device_create_file(&pdev->dev, | ||
735 | &sensor_dev_attr_fan2_min.dev_attr); | ||
736 | } | ||
737 | if (data->fan_enabled & (1 << 2)) { | ||
738 | device_create_file(&pdev->dev, | ||
739 | &sensor_dev_attr_fan3_input.dev_attr); | ||
740 | device_create_file(&pdev->dev, | ||
741 | &sensor_dev_attr_fan3_min.dev_attr); | ||
742 | } | ||
743 | device_create_file(&pdev->dev, | ||
744 | &sensor_dev_attr_temp1_input.dev_attr); | ||
745 | device_create_file(&pdev->dev, | ||
746 | &sensor_dev_attr_temp2_input.dev_attr); | ||
747 | device_create_file(&pdev->dev, | ||
748 | &sensor_dev_attr_temp3_input.dev_attr); | ||
749 | device_create_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr); | ||
750 | device_create_file(&pdev->dev, &sensor_dev_attr_temp2_max.dev_attr); | ||
751 | device_create_file(&pdev->dev, &sensor_dev_attr_temp3_max.dev_attr); | ||
752 | device_create_file(&pdev->dev, | ||
753 | &sensor_dev_attr_temp1_max_hyst.dev_attr); | ||
754 | device_create_file(&pdev->dev, | ||
755 | &sensor_dev_attr_temp2_max_hyst.dev_attr); | ||
756 | device_create_file(&pdev->dev, | ||
757 | &sensor_dev_attr_temp3_max_hyst.dev_attr); | ||
758 | device_create_file(&pdev->dev, &sensor_dev_attr_temp1_type.dev_attr); | ||
759 | device_create_file(&pdev->dev, &sensor_dev_attr_temp2_type.dev_attr); | ||
760 | device_create_file(&pdev->dev, &sensor_dev_attr_temp3_type.dev_attr); | ||
761 | device_create_file(&pdev->dev, &dev_attr_alarms_in); | ||
762 | device_create_file(&pdev->dev, &dev_attr_alarms_fan); | ||
763 | device_create_file(&pdev->dev, &dev_attr_alarms_temp); | ||
764 | device_create_file(&pdev->dev, &dev_attr_name); | ||
765 | |||
766 | return 0; | ||
767 | |||
768 | exit_free: | ||
769 | kfree(data); | ||
770 | exit: | ||
771 | return err; | ||
772 | } | ||
773 | |||
774 | static int __devexit f71805f_remove(struct platform_device *pdev) | ||
775 | { | ||
776 | struct f71805f_data *data = platform_get_drvdata(pdev); | ||
777 | |||
778 | platform_set_drvdata(pdev, NULL); | ||
779 | hwmon_device_unregister(data->class_dev); | ||
780 | kfree(data); | ||
781 | |||
782 | return 0; | ||
783 | } | ||
784 | |||
785 | static struct platform_driver f71805f_driver = { | ||
786 | .driver = { | ||
787 | .owner = THIS_MODULE, | ||
788 | .name = DRVNAME, | ||
789 | }, | ||
790 | .probe = f71805f_probe, | ||
791 | .remove = __devexit_p(f71805f_remove), | ||
792 | }; | ||
793 | |||
794 | static int __init f71805f_device_add(unsigned short address) | ||
795 | { | ||
796 | int err; | ||
797 | |||
798 | pdev = platform_device_alloc(DRVNAME, address); | ||
799 | if (!pdev) { | ||
800 | err = -ENOMEM; | ||
801 | printk(KERN_ERR DRVNAME ": Device allocation failed\n"); | ||
802 | goto exit; | ||
803 | } | ||
804 | |||
805 | f71805f_resource.start = address; | ||
806 | f71805f_resource.end = address + REGION_LENGTH - 1; | ||
807 | f71805f_resource.name = pdev->name; | ||
808 | err = platform_device_add_resources(pdev, &f71805f_resource, 1); | ||
809 | if (err) { | ||
810 | printk(KERN_ERR DRVNAME ": Device resource addition failed " | ||
811 | "(%d)\n", err); | ||
812 | goto exit_device_put; | ||
813 | } | ||
814 | |||
815 | err = platform_device_add(pdev); | ||
816 | if (err) { | ||
817 | printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", | ||
818 | err); | ||
819 | goto exit_device_put; | ||
820 | } | ||
821 | |||
822 | return 0; | ||
823 | |||
824 | exit_device_put: | ||
825 | platform_device_put(pdev); | ||
826 | exit: | ||
827 | return err; | ||
828 | } | ||
829 | |||
830 | static int __init f71805f_find(int sioaddr, unsigned short *address) | ||
831 | { | ||
832 | int err = -ENODEV; | ||
833 | u16 devid; | ||
834 | |||
835 | superio_enter(sioaddr); | ||
836 | |||
837 | devid = superio_inw(sioaddr, SIO_REG_MANID); | ||
838 | if (devid != SIO_FINTEK_ID) | ||
839 | goto exit; | ||
840 | |||
841 | devid = superio_inw(sioaddr, SIO_REG_DEVID); | ||
842 | if (devid != SIO_F71805F_ID) { | ||
843 | printk(KERN_INFO DRVNAME ": Unsupported Fintek device, " | ||
844 | "skipping\n"); | ||
845 | goto exit; | ||
846 | } | ||
847 | |||
848 | superio_select(sioaddr, F71805F_LD_HWM); | ||
849 | if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) { | ||
850 | printk(KERN_WARNING DRVNAME ": Device not activated, " | ||
851 | "skipping\n"); | ||
852 | goto exit; | ||
853 | } | ||
854 | |||
855 | *address = superio_inw(sioaddr, SIO_REG_ADDR); | ||
856 | if (*address == 0) { | ||
857 | printk(KERN_WARNING DRVNAME ": Base address not set, " | ||
858 | "skipping\n"); | ||
859 | goto exit; | ||
860 | } | ||
861 | |||
862 | err = 0; | ||
863 | printk(KERN_INFO DRVNAME ": Found F71805F chip at %#x, revision %u\n", | ||
864 | *address, superio_inb(sioaddr, SIO_REG_DEVREV)); | ||
865 | |||
866 | exit: | ||
867 | superio_exit(sioaddr); | ||
868 | return err; | ||
869 | } | ||
870 | |||
871 | static int __init f71805f_init(void) | ||
872 | { | ||
873 | int err; | ||
874 | unsigned short address; | ||
875 | |||
876 | if (f71805f_find(0x2e, &address) | ||
877 | && f71805f_find(0x4e, &address)) | ||
878 | return -ENODEV; | ||
879 | |||
880 | err = platform_driver_register(&f71805f_driver); | ||
881 | if (err) | ||
882 | goto exit; | ||
883 | |||
884 | /* Sets global pdev as a side effect */ | ||
885 | err = f71805f_device_add(address); | ||
886 | if (err) | ||
887 | goto exit_driver; | ||
888 | |||
889 | return 0; | ||
890 | |||
891 | exit_driver: | ||
892 | platform_driver_unregister(&f71805f_driver); | ||
893 | exit: | ||
894 | return err; | ||
895 | } | ||
896 | |||
897 | static void __exit f71805f_exit(void) | ||
898 | { | ||
899 | platform_device_unregister(pdev); | ||
900 | platform_driver_unregister(&f71805f_driver); | ||
901 | } | ||
902 | |||
903 | MODULE_AUTHOR("Jean Delvare <khali@linux-fr>"); | ||
904 | MODULE_LICENSE("GPL"); | ||
905 | MODULE_DESCRIPTION("F71805F hardware monitoring driver"); | ||
906 | |||
907 | module_init(f71805f_init); | ||
908 | module_exit(f71805f_exit); | ||
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 0da7c9c508c3..e87d52c59940 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c | |||
@@ -45,8 +45,7 @@ | |||
45 | 45 | ||
46 | 46 | ||
47 | /* Addresses to scan */ | 47 | /* Addresses to scan */ |
48 | static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, | 48 | static unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END }; |
49 | 0x2e, 0x2f, I2C_CLIENT_END }; | ||
50 | static unsigned short isa_address; | 49 | static unsigned short isa_address; |
51 | 50 | ||
52 | /* Insmod parameters */ | 51 | /* Insmod parameters */ |
@@ -830,6 +829,11 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind) | |||
830 | if ((err = i2c_attach_client(new_client))) | 829 | if ((err = i2c_attach_client(new_client))) |
831 | goto ERROR2; | 830 | goto ERROR2; |
832 | 831 | ||
832 | if (!is_isa) | ||
833 | dev_info(&new_client->dev, "The I2C interface to IT87xxF " | ||
834 | "hardware monitoring chips is deprecated. Please " | ||
835 | "report if you still rely on it.\n"); | ||
836 | |||
833 | /* Check PWM configuration */ | 837 | /* Check PWM configuration */ |
834 | enable_pwm_interface = it87_check_pwm(new_client); | 838 | enable_pwm_interface = it87_check_pwm(new_client); |
835 | 839 | ||
diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c index a2f420d01fb7..df9e02aaa70a 100644 --- a/drivers/hwmon/lm77.c +++ b/drivers/hwmon/lm77.c | |||
@@ -87,15 +87,15 @@ static struct i2c_driver lm77_driver = { | |||
87 | 87 | ||
88 | /* In the temperature registers, the low 3 bits are not part of the | 88 | /* In the temperature registers, the low 3 bits are not part of the |
89 | temperature values; they are the status bits. */ | 89 | temperature values; they are the status bits. */ |
90 | static inline u16 LM77_TEMP_TO_REG(int temp) | 90 | static inline s16 LM77_TEMP_TO_REG(int temp) |
91 | { | 91 | { |
92 | int ntemp = SENSORS_LIMIT(temp, LM77_TEMP_MIN, LM77_TEMP_MAX); | 92 | int ntemp = SENSORS_LIMIT(temp, LM77_TEMP_MIN, LM77_TEMP_MAX); |
93 | return (u16)((ntemp / 500) * 8); | 93 | return (ntemp / 500) * 8; |
94 | } | 94 | } |
95 | 95 | ||
96 | static inline int LM77_TEMP_FROM_REG(u16 reg) | 96 | static inline int LM77_TEMP_FROM_REG(s16 reg) |
97 | { | 97 | { |
98 | return ((int)reg / 8) * 500; | 98 | return (reg / 8) * 500; |
99 | } | 99 | } |
100 | 100 | ||
101 | /* sysfs stuff */ | 101 | /* sysfs stuff */ |
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index b176bf0c4c7b..a2f6bb676235 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c | |||
@@ -303,10 +303,6 @@ struct w83792d_data { | |||
303 | static int w83792d_attach_adapter(struct i2c_adapter *adapter); | 303 | static int w83792d_attach_adapter(struct i2c_adapter *adapter); |
304 | static int w83792d_detect(struct i2c_adapter *adapter, int address, int kind); | 304 | static int w83792d_detect(struct i2c_adapter *adapter, int address, int kind); |
305 | static int w83792d_detach_client(struct i2c_client *client); | 305 | static int w83792d_detach_client(struct i2c_client *client); |
306 | |||
307 | static int w83792d_read_value(struct i2c_client *client, u8 register); | ||
308 | static int w83792d_write_value(struct i2c_client *client, u8 register, | ||
309 | u8 value); | ||
310 | static struct w83792d_data *w83792d_update_device(struct device *dev); | 306 | static struct w83792d_data *w83792d_update_device(struct device *dev); |
311 | 307 | ||
312 | #ifdef DEBUG | 308 | #ifdef DEBUG |
@@ -329,6 +325,20 @@ static inline long in_count_from_reg(int nr, struct w83792d_data *data) | |||
329 | return ((data->in[nr] << 2) | ((data->low_bits >> (2 * nr)) & 0x03)); | 325 | return ((data->in[nr] << 2) | ((data->low_bits >> (2 * nr)) & 0x03)); |
330 | } | 326 | } |
331 | 327 | ||
328 | /* The SMBus locks itself. The Winbond W83792D chip has a bank register, | ||
329 | but the driver only accesses registers in bank 0, so we don't have | ||
330 | to switch banks and lock access between switches. */ | ||
331 | static inline int w83792d_read_value(struct i2c_client *client, u8 reg) | ||
332 | { | ||
333 | return i2c_smbus_read_byte_data(client, reg); | ||
334 | } | ||
335 | |||
336 | static inline int | ||
337 | w83792d_write_value(struct i2c_client *client, u8 reg, u8 value) | ||
338 | { | ||
339 | return i2c_smbus_write_byte_data(client, reg, value); | ||
340 | } | ||
341 | |||
332 | /* following are the sysfs callback functions */ | 342 | /* following are the sysfs callback functions */ |
333 | static ssize_t show_in(struct device *dev, struct device_attribute *attr, | 343 | static ssize_t show_in(struct device *dev, struct device_attribute *attr, |
334 | char *buf) | 344 | char *buf) |
@@ -1386,19 +1396,6 @@ w83792d_detach_client(struct i2c_client *client) | |||
1386 | return 0; | 1396 | return 0; |
1387 | } | 1397 | } |
1388 | 1398 | ||
1389 | /* The SMBus locks itself. The Winbond W83792D chip has a bank register, | ||
1390 | but the driver only accesses registers in bank 0, so we don't have | ||
1391 | to switch banks and lock access between switches. */ | ||
1392 | static int w83792d_read_value(struct i2c_client *client, u8 reg) | ||
1393 | { | ||
1394 | return i2c_smbus_read_byte_data(client, reg); | ||
1395 | } | ||
1396 | |||
1397 | static int w83792d_write_value(struct i2c_client *client, u8 reg, u8 value) | ||
1398 | { | ||
1399 | return i2c_smbus_write_byte_data(client, reg, value); | ||
1400 | } | ||
1401 | |||
1402 | static void | 1399 | static void |
1403 | w83792d_init_client(struct i2c_client *client) | 1400 | w83792d_init_client(struct i2c_client *client) |
1404 | { | 1401 | { |
diff --git a/drivers/i2c/algos/i2c-algo-sibyte.c b/drivers/i2c/algos/i2c-algo-sibyte.c index 938848ae162d..3df3f09995c2 100644 --- a/drivers/i2c/algos/i2c-algo-sibyte.c +++ b/drivers/i2c/algos/i2c-algo-sibyte.c | |||
@@ -202,7 +202,7 @@ EXPORT_SYMBOL(i2c_sibyte_del_bus); | |||
202 | #ifdef MODULE | 202 | #ifdef MODULE |
203 | MODULE_AUTHOR("Kip Walker, Broadcom Corp."); | 203 | MODULE_AUTHOR("Kip Walker, Broadcom Corp."); |
204 | MODULE_DESCRIPTION("SiByte I2C-Bus algorithm"); | 204 | MODULE_DESCRIPTION("SiByte I2C-Bus algorithm"); |
205 | MODULE_PARM(bit_scan, "i"); | 205 | module_param(bit_scan, int, 0); |
206 | MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus"); | 206 | MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus"); |
207 | MODULE_LICENSE("GPL"); | 207 | MODULE_LICENSE("GPL"); |
208 | 208 | ||
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 08d5b8fed2dc..ff92735c7c85 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig | |||
@@ -124,6 +124,7 @@ config I2C_I801 | |||
124 | ICH6 | 124 | ICH6 |
125 | ICH7 | 125 | ICH7 |
126 | ESB2 | 126 | ESB2 |
127 | ICH8 | ||
127 | 128 | ||
128 | This driver can also be built as a module. If so, the module | 129 | This driver can also be built as a module. If so, the module |
129 | will be called i2c-i801. | 130 | will be called i2c-i801. |
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 1c752ddc10e2..8e0f3158215f 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c | |||
@@ -32,6 +32,7 @@ | |||
32 | ICH6 266A | 32 | ICH6 266A |
33 | ICH7 27DA | 33 | ICH7 27DA |
34 | ESB2 269B | 34 | ESB2 269B |
35 | ICH8 283E | ||
35 | This driver supports several versions of Intel's I/O Controller Hubs (ICH). | 36 | This driver supports several versions of Intel's I/O Controller Hubs (ICH). |
36 | For SMBus support, they are similar to the PIIX4 and are part | 37 | For SMBus support, they are similar to the PIIX4 and are part |
37 | of Intel's '810' and other chipsets. | 38 | of Intel's '810' and other chipsets. |
@@ -527,6 +528,7 @@ static struct pci_device_id i801_ids[] = { | |||
527 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) }, | 528 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) }, |
528 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) }, | 529 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) }, |
529 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) }, | 530 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) }, |
531 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) }, | ||
530 | { 0, } | 532 | { 0, } |
531 | }; | 533 | }; |
532 | 534 | ||
diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c index 3e5eba9fcacb..c63025a4c861 100644 --- a/drivers/i2c/busses/i2c-parport-light.c +++ b/drivers/i2c/busses/i2c-parport-light.c | |||
@@ -121,14 +121,11 @@ static struct i2c_adapter parport_adapter = { | |||
121 | 121 | ||
122 | static int __init i2c_parport_init(void) | 122 | static int __init i2c_parport_init(void) |
123 | { | 123 | { |
124 | int type_count; | 124 | if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) { |
125 | |||
126 | type_count = sizeof(adapter_parm)/sizeof(struct adapter_parm); | ||
127 | if (type < 0 || type >= type_count) { | ||
128 | printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type); | 125 | printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type); |
129 | type = 0; | 126 | type = 0; |
130 | } | 127 | } |
131 | 128 | ||
132 | if (base == 0) { | 129 | if (base == 0) { |
133 | printk(KERN_INFO "i2c-parport: using default base 0x%x\n", DEFAULT_BASE); | 130 | printk(KERN_INFO "i2c-parport: using default base 0x%x\n", DEFAULT_BASE); |
134 | base = DEFAULT_BASE; | 131 | base = DEFAULT_BASE; |
@@ -152,7 +149,7 @@ static int __init i2c_parport_init(void) | |||
152 | release_region(base, 3); | 149 | release_region(base, 3); |
153 | return -ENODEV; | 150 | return -ENODEV; |
154 | } | 151 | } |
155 | 152 | ||
156 | return 0; | 153 | return 0; |
157 | } | 154 | } |
158 | 155 | ||
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c index 2854d858fc9b..7e2e8cd1c14a 100644 --- a/drivers/i2c/busses/i2c-parport.c +++ b/drivers/i2c/busses/i2c-parport.c | |||
@@ -241,14 +241,11 @@ static struct parport_driver i2c_parport_driver = { | |||
241 | 241 | ||
242 | static int __init i2c_parport_init(void) | 242 | static int __init i2c_parport_init(void) |
243 | { | 243 | { |
244 | int type_count; | 244 | if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) { |
245 | |||
246 | type_count = sizeof(adapter_parm)/sizeof(struct adapter_parm); | ||
247 | if (type < 0 || type >= type_count) { | ||
248 | printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type); | 245 | printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type); |
249 | type = 0; | 246 | type = 0; |
250 | } | 247 | } |
251 | 248 | ||
252 | return parport_register_driver(&i2c_parport_driver); | 249 | return parport_register_driver(&i2c_parport_driver); |
253 | } | 250 | } |
254 | 251 | ||
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 86e2234faf80..7579f4b256a8 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c | |||
@@ -861,7 +861,7 @@ static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id, struct pt_regs *r | |||
861 | decode_ISR(isr); | 861 | decode_ISR(isr); |
862 | } | 862 | } |
863 | 863 | ||
864 | if (i2c->irqlogidx < sizeof(i2c->isrlog)/sizeof(u32)) | 864 | if (i2c->irqlogidx < ARRAY_SIZE(i2c->isrlog)) |
865 | i2c->isrlog[i2c->irqlogidx++] = isr; | 865 | i2c->isrlog[i2c->irqlogidx++] = isr; |
866 | 866 | ||
867 | show_state(i2c); | 867 | show_state(i2c); |
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 0ce58b506046..1a2c9ab5d9e3 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
@@ -946,6 +946,20 @@ s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *val | |||
946 | } | 946 | } |
947 | } | 947 | } |
948 | 948 | ||
949 | s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command, | ||
950 | u8 length, u8 *values) | ||
951 | { | ||
952 | union i2c_smbus_data data; | ||
953 | |||
954 | if (length > I2C_SMBUS_BLOCK_MAX) | ||
955 | length = I2C_SMBUS_BLOCK_MAX; | ||
956 | data.block[0] = length; | ||
957 | memcpy(data.block + 1, values, length); | ||
958 | return i2c_smbus_xfer(client->adapter, client->addr, client->flags, | ||
959 | I2C_SMBUS_WRITE, command, | ||
960 | I2C_SMBUS_I2C_BLOCK_DATA, &data); | ||
961 | } | ||
962 | |||
949 | /* Simulate a SMBus command using the i2c protocol | 963 | /* Simulate a SMBus command using the i2c protocol |
950 | No checking of parameters is done! */ | 964 | No checking of parameters is done! */ |
951 | static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, | 965 | static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, |
@@ -1150,6 +1164,7 @@ EXPORT_SYMBOL(i2c_smbus_read_word_data); | |||
1150 | EXPORT_SYMBOL(i2c_smbus_write_word_data); | 1164 | EXPORT_SYMBOL(i2c_smbus_write_word_data); |
1151 | EXPORT_SYMBOL(i2c_smbus_write_block_data); | 1165 | EXPORT_SYMBOL(i2c_smbus_write_block_data); |
1152 | EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data); | 1166 | EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data); |
1167 | EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data); | ||
1153 | 1168 | ||
1154 | MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>"); | 1169 | MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>"); |
1155 | MODULE_DESCRIPTION("I2C-Bus main module"); | 1170 | MODULE_DESCRIPTION("I2C-Bus main module"); |
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 1c81174595b3..d633081fa4c5 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig | |||
@@ -52,9 +52,9 @@ config IDE | |||
52 | 52 | ||
53 | if IDE | 53 | if IDE |
54 | 54 | ||
55 | config IDE_MAX_HWIFS | 55 | config IDE_MAX_HWIFS |
56 | int "Max IDE interfaces" | 56 | int "Max IDE interfaces" |
57 | depends on ALPHA || SUPERH | 57 | depends on ALPHA || SUPERH || IA64 |
58 | default 4 | 58 | default 4 |
59 | help | 59 | help |
60 | This is the maximum number of IDE hardware interfaces that will | 60 | This is the maximum number of IDE hardware interfaces that will |
@@ -162,8 +162,8 @@ config BLK_DEV_IDECS | |||
162 | tristate "PCMCIA IDE support" | 162 | tristate "PCMCIA IDE support" |
163 | depends on PCMCIA | 163 | depends on PCMCIA |
164 | help | 164 | help |
165 | Support for outboard IDE disks, tape drives, and CD-ROM drives | 165 | Support for Compact Flash cards, outboard IDE disks, tape drives, |
166 | connected through a PCMCIA card. | 166 | and CD-ROM drives connected through a PCMCIA card. |
167 | 167 | ||
168 | config BLK_DEV_IDECD | 168 | config BLK_DEV_IDECD |
169 | tristate "Include IDE/ATAPI CDROM support" | 169 | tristate "Include IDE/ATAPI CDROM support" |
@@ -267,7 +267,7 @@ config IDE_TASK_IOCTL | |||
267 | help | 267 | help |
268 | This is a direct raw access to the media. It is a complex but | 268 | This is a direct raw access to the media. It is a complex but |
269 | elegant solution to test and validate the domain of the hardware and | 269 | elegant solution to test and validate the domain of the hardware and |
270 | perform below the driver data recover if needed. This is the most | 270 | perform below the driver data recovery if needed. This is the most |
271 | basic form of media-forensics. | 271 | basic form of media-forensics. |
272 | 272 | ||
273 | If you are unsure, say N here. | 273 | If you are unsure, say N here. |
@@ -525,7 +525,7 @@ config BLK_DEV_CS5520 | |||
525 | tristate "Cyrix CS5510/20 MediaGX chipset support (VERY EXPERIMENTAL)" | 525 | tristate "Cyrix CS5510/20 MediaGX chipset support (VERY EXPERIMENTAL)" |
526 | depends on EXPERIMENTAL | 526 | depends on EXPERIMENTAL |
527 | help | 527 | help |
528 | Include support for PIO tuning an virtual DMA on the Cyrix MediaGX | 528 | Include support for PIO tuning and virtual DMA on the Cyrix MediaGX |
529 | 5510/5520 chipset. This will automatically be detected and | 529 | 5510/5520 chipset. This will automatically be detected and |
530 | configured if found. | 530 | configured if found. |
531 | 531 | ||
@@ -662,7 +662,7 @@ config PDC202XX_BURST | |||
662 | 662 | ||
663 | It was originally designed for the PDC20246/Ultra33, whose BIOS will | 663 | It was originally designed for the PDC20246/Ultra33, whose BIOS will |
664 | only setup UDMA on the first two PDC20246 cards. It has also been | 664 | only setup UDMA on the first two PDC20246 cards. It has also been |
665 | used succesfully on a PDC20265/Ultra100, allowing use of UDMA modes | 665 | used successfully on a PDC20265/Ultra100, allowing use of UDMA modes |
666 | when the PDC20265 BIOS has been disabled (for faster boot up). | 666 | when the PDC20265 BIOS has been disabled (for faster boot up). |
667 | 667 | ||
668 | Please read the comments at the top of | 668 | Please read the comments at the top of |
@@ -673,13 +673,6 @@ config PDC202XX_BURST | |||
673 | config BLK_DEV_PDC202XX_NEW | 673 | config BLK_DEV_PDC202XX_NEW |
674 | tristate "PROMISE PDC202{68|69|70|71|75|76|77} support" | 674 | tristate "PROMISE PDC202{68|69|70|71|75|76|77} support" |
675 | 675 | ||
676 | # FIXME - probably wants to be one for old and for new | ||
677 | config PDC202XX_FORCE | ||
678 | bool "Enable controller even if disabled by BIOS" | ||
679 | depends on BLK_DEV_PDC202XX_NEW | ||
680 | help | ||
681 | Enable the PDC202xx controller even if it has been disabled in the BIOS setup. | ||
682 | |||
683 | config BLK_DEV_SVWKS | 676 | config BLK_DEV_SVWKS |
684 | tristate "ServerWorks OSB4/CSB5/CSB6 chipsets support" | 677 | tristate "ServerWorks OSB4/CSB5/CSB6 chipsets support" |
685 | help | 678 | help |
@@ -722,7 +715,7 @@ config BLK_DEV_SIS5513 | |||
722 | config BLK_DEV_SLC90E66 | 715 | config BLK_DEV_SLC90E66 |
723 | tristate "SLC90E66 chipset support" | 716 | tristate "SLC90E66 chipset support" |
724 | help | 717 | help |
725 | This driver ensures (U)DMA support for Victroy66 SouthBridges for | 718 | This driver ensures (U)DMA support for Victory66 SouthBridges for |
726 | SMsC with Intel NorthBridges. This is an Ultra66 based chipset. | 719 | SMsC with Intel NorthBridges. This is an Ultra66 based chipset. |
727 | The nice thing about it is that you can mix Ultra/DMA/PIO devices | 720 | The nice thing about it is that you can mix Ultra/DMA/PIO devices |
728 | and it will handle timing cycles. Since this is an improved | 721 | and it will handle timing cycles. Since this is an improved |
@@ -1060,7 +1053,7 @@ config IDEDMA_IVB | |||
1060 | in that mode with an 80c ribbon. | 1053 | in that mode with an 80c ribbon. |
1061 | 1054 | ||
1062 | If you are experiencing compatibility or performance problems, you | 1055 | If you are experiencing compatibility or performance problems, you |
1063 | MAY try to answering Y here. However, it does not necessarily solve | 1056 | MAY try to answer Y here. However, it does not necessarily solve |
1064 | any of your problems, it could even cause more of them. | 1057 | any of your problems, it could even cause more of them. |
1065 | 1058 | ||
1066 | It is normally safe to answer Y; however, the default is N. | 1059 | It is normally safe to answer Y; however, the default is N. |
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index ca25f9e3d0f4..09086b8b6486 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c | |||
@@ -190,7 +190,8 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, | |||
190 | if (lba48) { | 190 | if (lba48) { |
191 | task_ioreg_t tasklets[10]; | 191 | task_ioreg_t tasklets[10]; |
192 | 192 | ||
193 | pr_debug("%s: LBA=0x%012llx\n", drive->name, block); | 193 | pr_debug("%s: LBA=0x%012llx\n", drive->name, |
194 | (unsigned long long)block); | ||
194 | 195 | ||
195 | tasklets[0] = 0; | 196 | tasklets[0] = 0; |
196 | tasklets[1] = 0; | 197 | tasklets[1] = 0; |
@@ -317,7 +318,8 @@ static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, s | |||
317 | 318 | ||
318 | pr_debug("%s: %sing: block=%llu, sectors=%lu, buffer=0x%08lx\n", | 319 | pr_debug("%s: %sing: block=%llu, sectors=%lu, buffer=0x%08lx\n", |
319 | drive->name, rq_data_dir(rq) == READ ? "read" : "writ", | 320 | drive->name, rq_data_dir(rq) == READ ? "read" : "writ", |
320 | block, rq->nr_sectors, (unsigned long)rq->buffer); | 321 | (unsigned long long)block, rq->nr_sectors, |
322 | (unsigned long)rq->buffer); | ||
321 | 323 | ||
322 | if (hwif->rw_disk) | 324 | if (hwif->rw_disk) |
323 | hwif->rw_disk(drive, rq); | 325 | hwif->rw_disk(drive, rq); |
@@ -776,7 +778,7 @@ static void update_ordered(ide_drive_t *drive) | |||
776 | ide_id_has_flush_cache_ext(id)); | 778 | ide_id_has_flush_cache_ext(id)); |
777 | 779 | ||
778 | printk(KERN_INFO "%s: cache flushes %ssupported\n", | 780 | printk(KERN_INFO "%s: cache flushes %ssupported\n", |
779 | drive->name, barrier ? "" : "not"); | 781 | drive->name, barrier ? "" : "not "); |
780 | 782 | ||
781 | if (barrier) { | 783 | if (barrier) { |
782 | ordered = QUEUE_ORDERED_DRAIN_FLUSH; | 784 | ordered = QUEUE_ORDERED_DRAIN_FLUSH; |
@@ -889,11 +891,7 @@ static void idedisk_setup (ide_drive_t *drive) | |||
889 | if (drive->id_read == 0) | 891 | if (drive->id_read == 0) |
890 | return; | 892 | return; |
891 | 893 | ||
892 | /* | 894 | if (drive->removable) { |
893 | * CompactFlash cards and their brethern look just like hard drives | ||
894 | * to us, but they are removable and don't have a doorlock mechanism. | ||
895 | */ | ||
896 | if (drive->removable && !(drive->is_flash)) { | ||
897 | /* | 895 | /* |
898 | * Removable disks (eg. SYQUEST); ignore 'WD' drives | 896 | * Removable disks (eg. SYQUEST); ignore 'WD' drives |
899 | */ | 897 | */ |
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 8d50df4526a4..c01615dec202 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c | |||
@@ -55,8 +55,8 @@ | |||
55 | #include <asm/io.h> | 55 | #include <asm/io.h> |
56 | #include <asm/bitops.h> | 56 | #include <asm/bitops.h> |
57 | 57 | ||
58 | int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate, | 58 | static int __ide_end_request(ide_drive_t *drive, struct request *rq, |
59 | int nr_sectors) | 59 | int uptodate, int nr_sectors) |
60 | { | 60 | { |
61 | int ret = 1; | 61 | int ret = 1; |
62 | 62 | ||
@@ -91,7 +91,6 @@ int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate, | |||
91 | 91 | ||
92 | return ret; | 92 | return ret; |
93 | } | 93 | } |
94 | EXPORT_SYMBOL(__ide_end_request); | ||
95 | 94 | ||
96 | /** | 95 | /** |
97 | * ide_end_request - complete an IDE I/O | 96 | * ide_end_request - complete an IDE I/O |
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index af7af958ab3e..b72dde70840a 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c | |||
@@ -1243,6 +1243,7 @@ int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout) | |||
1243 | */ | 1243 | */ |
1244 | if (stat == 0xff) | 1244 | if (stat == 0xff) |
1245 | return -ENODEV; | 1245 | return -ENODEV; |
1246 | touch_softlockup_watchdog(); | ||
1246 | } | 1247 | } |
1247 | return -EBUSY; | 1248 | return -EBUSY; |
1248 | } | 1249 | } |
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index e7425546b4b1..427d1c204174 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
@@ -125,45 +125,6 @@ static void ide_disk_init_mult_count(ide_drive_t *drive) | |||
125 | } | 125 | } |
126 | 126 | ||
127 | /** | 127 | /** |
128 | * drive_is_flashcard - check for compact flash | ||
129 | * @drive: drive to check | ||
130 | * | ||
131 | * CompactFlash cards and their brethern pretend to be removable | ||
132 | * hard disks, except: | ||
133 | * (1) they never have a slave unit, and | ||
134 | * (2) they don't have doorlock mechanisms. | ||
135 | * This test catches them, and is invoked elsewhere when setting | ||
136 | * appropriate config bits. | ||
137 | * | ||
138 | * FIXME: This treatment is probably applicable for *all* PCMCIA (PC CARD) | ||
139 | * devices, so in linux 2.3.x we should change this to just treat all | ||
140 | * PCMCIA drives this way, and get rid of the model-name tests below | ||
141 | * (too big of an interface change for 2.4.x). | ||
142 | * At that time, we might also consider parameterizing the timeouts and | ||
143 | * retries, since these are MUCH faster than mechanical drives. -M.Lord | ||
144 | */ | ||
145 | |||
146 | static inline int drive_is_flashcard (ide_drive_t *drive) | ||
147 | { | ||
148 | struct hd_driveid *id = drive->id; | ||
149 | |||
150 | if (drive->removable) { | ||
151 | if (id->config == 0x848a) return 1; /* CompactFlash */ | ||
152 | if (!strncmp(id->model, "KODAK ATA_FLASH", 15) /* Kodak */ | ||
153 | || !strncmp(id->model, "Hitachi CV", 10) /* Hitachi */ | ||
154 | || !strncmp(id->model, "SunDisk SDCFB", 13) /* old SanDisk */ | ||
155 | || !strncmp(id->model, "SanDisk SDCFB", 13) /* SanDisk */ | ||
156 | || !strncmp(id->model, "HAGIWARA HPC", 12) /* Hagiwara */ | ||
157 | || !strncmp(id->model, "LEXAR ATA_FLASH", 15) /* Lexar */ | ||
158 | || !strncmp(id->model, "ATA_FLASH", 9)) /* Simple Tech */ | ||
159 | { | ||
160 | return 1; /* yes, it is a flash memory card */ | ||
161 | } | ||
162 | } | ||
163 | return 0; /* no, it is not a flash memory card */ | ||
164 | } | ||
165 | |||
166 | /** | ||
167 | * do_identify - identify a drive | 128 | * do_identify - identify a drive |
168 | * @drive: drive to identify | 129 | * @drive: drive to identify |
169 | * @cmd: command used | 130 | * @cmd: command used |
@@ -278,13 +239,17 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) | |||
278 | /* | 239 | /* |
279 | * Not an ATAPI device: looks like a "regular" hard disk | 240 | * Not an ATAPI device: looks like a "regular" hard disk |
280 | */ | 241 | */ |
281 | if (id->config & (1<<7)) | 242 | |
243 | /* | ||
244 | * 0x848a = CompactFlash device | ||
245 | * These are *not* removable in Linux definition of the term | ||
246 | */ | ||
247 | |||
248 | if ((id->config != 0x848a) && (id->config & (1<<7))) | ||
282 | drive->removable = 1; | 249 | drive->removable = 1; |
283 | 250 | ||
284 | if (drive_is_flashcard(drive)) | ||
285 | drive->is_flash = 1; | ||
286 | drive->media = ide_disk; | 251 | drive->media = ide_disk; |
287 | printk("%s DISK drive\n", (drive->is_flash) ? "CFA" : "ATA" ); | 252 | printk("%s DISK drive\n", (id->config == 0x848a) ? "CFA" : "ATA" ); |
288 | QUIRK_LIST(drive); | 253 | QUIRK_LIST(drive); |
289 | return; | 254 | return; |
290 | 255 | ||
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index afeb02bbb722..b2cc43702f65 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c | |||
@@ -242,7 +242,6 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index) | |||
242 | drive->name[2] = 'a' + (index * MAX_DRIVES) + unit; | 242 | drive->name[2] = 'a' + (index * MAX_DRIVES) + unit; |
243 | drive->max_failures = IDE_DEFAULT_MAX_FAILURES; | 243 | drive->max_failures = IDE_DEFAULT_MAX_FAILURES; |
244 | drive->using_dma = 0; | 244 | drive->using_dma = 0; |
245 | drive->is_flash = 0; | ||
246 | drive->vdma = 0; | 245 | drive->vdma = 0; |
247 | INIT_LIST_HEAD(&drive->list); | 246 | INIT_LIST_HEAD(&drive->list); |
248 | init_completion(&drive->gendev_rel_comp); | 247 | init_completion(&drive->gendev_rel_comp); |
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c index a21b1e11eef4..c743e68c33aa 100644 --- a/drivers/ide/pci/aec62xx.c +++ b/drivers/ide/pci/aec62xx.c | |||
@@ -262,6 +262,21 @@ static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const ch | |||
262 | else | 262 | else |
263 | pci_set_drvdata(dev, (void *) aec6xxx_34_base); | 263 | pci_set_drvdata(dev, (void *) aec6xxx_34_base); |
264 | 264 | ||
265 | /* These are necessary to get AEC6280 Macintosh cards to work */ | ||
266 | if ((dev->device == PCI_DEVICE_ID_ARTOP_ATP865) || | ||
267 | (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R)) { | ||
268 | u8 reg49h = 0, reg4ah = 0; | ||
269 | /* Clear reset and test bits. */ | ||
270 | pci_read_config_byte(dev, 0x49, ®49h); | ||
271 | pci_write_config_byte(dev, 0x49, reg49h & ~0x30); | ||
272 | /* Enable chip interrupt output. */ | ||
273 | pci_read_config_byte(dev, 0x4a, ®4ah); | ||
274 | pci_write_config_byte(dev, 0x4a, reg4ah & ~0x01); | ||
275 | /* Enable burst mode. */ | ||
276 | pci_read_config_byte(dev, 0x4a, ®4ah); | ||
277 | pci_write_config_byte(dev, 0x4a, reg4ah | 0x80); | ||
278 | } | ||
279 | |||
265 | return dev->irq; | 280 | return dev->irq; |
266 | } | 281 | } |
267 | 282 | ||
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 7b589d948bf9..940bdd4c5784 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c | |||
@@ -1288,6 +1288,10 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) | |||
1288 | goto init_hpt37X_done; | 1288 | goto init_hpt37X_done; |
1289 | } | 1289 | } |
1290 | } | 1290 | } |
1291 | if (!pci_get_drvdata(dev)) { | ||
1292 | printk("No Clock Stabilization!!!\n"); | ||
1293 | return; | ||
1294 | } | ||
1291 | pll_recal: | 1295 | pll_recal: |
1292 | if (adjust & 1) | 1296 | if (adjust & 1) |
1293 | pll -= (adjust >> 1); | 1297 | pll -= (adjust >> 1); |
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c index 108fda83fea4..38f41b377ff6 100644 --- a/drivers/ide/pci/it821x.c +++ b/drivers/ide/pci/it821x.c | |||
@@ -733,7 +733,7 @@ static void __devinit it8212_disable_raid(struct pci_dev *dev) | |||
733 | 733 | ||
734 | pci_write_config_dword(dev,0x4C, 0x02040204); | 734 | pci_write_config_dword(dev,0x4C, 0x02040204); |
735 | pci_write_config_byte(dev, 0x42, 0x36); | 735 | pci_write_config_byte(dev, 0x42, 0x36); |
736 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0); | 736 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); |
737 | } | 737 | } |
738 | 738 | ||
739 | static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev, const char *name) | 739 | static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev, const char *name) |
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index fe06ebb0e5bf..acd63173199b 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c | |||
@@ -420,9 +420,6 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { | |||
420 | .init_hwif = init_hwif_pdc202new, | 420 | .init_hwif = init_hwif_pdc202new, |
421 | .channels = 2, | 421 | .channels = 2, |
422 | .autodma = AUTODMA, | 422 | .autodma = AUTODMA, |
423 | #ifndef CONFIG_PDC202XX_FORCE | ||
424 | .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, | ||
425 | #endif | ||
426 | .bootable = OFF_BOARD, | 423 | .bootable = OFF_BOARD, |
427 | },{ /* 3 */ | 424 | },{ /* 3 */ |
428 | .name = "PDC20271", | 425 | .name = "PDC20271", |
@@ -447,9 +444,6 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { | |||
447 | .init_hwif = init_hwif_pdc202new, | 444 | .init_hwif = init_hwif_pdc202new, |
448 | .channels = 2, | 445 | .channels = 2, |
449 | .autodma = AUTODMA, | 446 | .autodma = AUTODMA, |
450 | #ifndef CONFIG_PDC202XX_FORCE | ||
451 | .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, | ||
452 | #endif | ||
453 | .bootable = OFF_BOARD, | 447 | .bootable = OFF_BOARD, |
454 | },{ /* 6 */ | 448 | },{ /* 6 */ |
455 | .name = "PDC20277", | 449 | .name = "PDC20277", |
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c index ad9d95817f95..6f8f8645b02c 100644 --- a/drivers/ide/pci/pdc202xx_old.c +++ b/drivers/ide/pci/pdc202xx_old.c | |||
@@ -786,9 +786,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { | |||
786 | .init_dma = init_dma_pdc202xx, | 786 | .init_dma = init_dma_pdc202xx, |
787 | .channels = 2, | 787 | .channels = 2, |
788 | .autodma = AUTODMA, | 788 | .autodma = AUTODMA, |
789 | #ifndef CONFIG_PDC202XX_FORCE | ||
790 | .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, | ||
791 | #endif | ||
792 | .bootable = OFF_BOARD, | 789 | .bootable = OFF_BOARD, |
793 | .extra = 16, | 790 | .extra = 16, |
794 | },{ /* 1 */ | 791 | },{ /* 1 */ |
@@ -799,9 +796,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { | |||
799 | .init_dma = init_dma_pdc202xx, | 796 | .init_dma = init_dma_pdc202xx, |
800 | .channels = 2, | 797 | .channels = 2, |
801 | .autodma = AUTODMA, | 798 | .autodma = AUTODMA, |
802 | #ifndef CONFIG_PDC202XX_FORCE | ||
803 | .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, | ||
804 | #endif | ||
805 | .bootable = OFF_BOARD, | 799 | .bootable = OFF_BOARD, |
806 | .extra = 48, | 800 | .extra = 48, |
807 | .flags = IDEPCI_FLAG_FORCE_PDC, | 801 | .flags = IDEPCI_FLAG_FORCE_PDC, |
@@ -813,9 +807,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { | |||
813 | .init_dma = init_dma_pdc202xx, | 807 | .init_dma = init_dma_pdc202xx, |
814 | .channels = 2, | 808 | .channels = 2, |
815 | .autodma = AUTODMA, | 809 | .autodma = AUTODMA, |
816 | #ifndef CONFIG_PDC202XX_FORCE | ||
817 | .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, | ||
818 | #endif | ||
819 | .bootable = OFF_BOARD, | 810 | .bootable = OFF_BOARD, |
820 | .extra = 48, | 811 | .extra = 48, |
821 | },{ /* 3 */ | 812 | },{ /* 3 */ |
@@ -826,9 +817,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { | |||
826 | .init_dma = init_dma_pdc202xx, | 817 | .init_dma = init_dma_pdc202xx, |
827 | .channels = 2, | 818 | .channels = 2, |
828 | .autodma = AUTODMA, | 819 | .autodma = AUTODMA, |
829 | #ifndef CONFIG_PDC202XX_FORCE | ||
830 | .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, | ||
831 | #endif | ||
832 | .bootable = OFF_BOARD, | 820 | .bootable = OFF_BOARD, |
833 | .extra = 48, | 821 | .extra = 48, |
834 | .flags = IDEPCI_FLAG_FORCE_PDC, | 822 | .flags = IDEPCI_FLAG_FORCE_PDC, |
@@ -840,9 +828,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { | |||
840 | .init_dma = init_dma_pdc202xx, | 828 | .init_dma = init_dma_pdc202xx, |
841 | .channels = 2, | 829 | .channels = 2, |
842 | .autodma = AUTODMA, | 830 | .autodma = AUTODMA, |
843 | #ifndef CONFIG_PDC202XX_FORCE | ||
844 | .enablebits = {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, | ||
845 | #endif | ||
846 | .bootable = OFF_BOARD, | 831 | .bootable = OFF_BOARD, |
847 | .extra = 48, | 832 | .extra = 48, |
848 | } | 833 | } |
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c index b3e77df63cef..e9b83e1a3028 100644 --- a/drivers/ide/pci/piix.c +++ b/drivers/ide/pci/piix.c | |||
@@ -135,6 +135,7 @@ static u8 piix_ratemask (ide_drive_t *drive) | |||
135 | case PCI_DEVICE_ID_INTEL_ICH6_19: | 135 | case PCI_DEVICE_ID_INTEL_ICH6_19: |
136 | case PCI_DEVICE_ID_INTEL_ICH7_21: | 136 | case PCI_DEVICE_ID_INTEL_ICH7_21: |
137 | case PCI_DEVICE_ID_INTEL_ESB2_18: | 137 | case PCI_DEVICE_ID_INTEL_ESB2_18: |
138 | case PCI_DEVICE_ID_INTEL_ICH8_6: | ||
138 | mode = 3; | 139 | mode = 3; |
139 | break; | 140 | break; |
140 | /* UDMA 66 capable */ | 141 | /* UDMA 66 capable */ |
@@ -449,6 +450,7 @@ static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char | |||
449 | case PCI_DEVICE_ID_INTEL_ICH6_19: | 450 | case PCI_DEVICE_ID_INTEL_ICH6_19: |
450 | case PCI_DEVICE_ID_INTEL_ICH7_21: | 451 | case PCI_DEVICE_ID_INTEL_ICH7_21: |
451 | case PCI_DEVICE_ID_INTEL_ESB2_18: | 452 | case PCI_DEVICE_ID_INTEL_ESB2_18: |
453 | case PCI_DEVICE_ID_INTEL_ICH8_6: | ||
452 | { | 454 | { |
453 | unsigned int extra = 0; | 455 | unsigned int extra = 0; |
454 | pci_read_config_dword(dev, 0x54, &extra); | 456 | pci_read_config_dword(dev, 0x54, &extra); |
@@ -575,6 +577,7 @@ static ide_pci_device_t piix_pci_info[] __devinitdata = { | |||
575 | /* 21 */ DECLARE_PIIX_DEV("ICH7"), | 577 | /* 21 */ DECLARE_PIIX_DEV("ICH7"), |
576 | /* 22 */ DECLARE_PIIX_DEV("ICH4"), | 578 | /* 22 */ DECLARE_PIIX_DEV("ICH4"), |
577 | /* 23 */ DECLARE_PIIX_DEV("ESB2"), | 579 | /* 23 */ DECLARE_PIIX_DEV("ESB2"), |
580 | /* 24 */ DECLARE_PIIX_DEV("ICH8M"), | ||
578 | }; | 581 | }; |
579 | 582 | ||
580 | /** | 583 | /** |
@@ -651,6 +654,7 @@ static struct pci_device_id piix_pci_tbl[] = { | |||
651 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 21}, | 654 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 21}, |
652 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 22}, | 655 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 22}, |
653 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_18, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 23}, | 656 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_18, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 23}, |
657 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 24}, | ||
654 | { 0, }, | 658 | { 0, }, |
655 | }; | 659 | }; |
656 | MODULE_DEVICE_TABLE(pci, piix_pci_tbl); | 660 | MODULE_DEVICE_TABLE(pci, piix_pci_tbl); |
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index 4ee597d08797..2b286e865163 100644 --- a/drivers/ide/pci/sgiioc4.c +++ b/drivers/ide/pci/sgiioc4.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2003 Silicon Graphics, Inc. All Rights Reserved. | 2 | * Copyright (c) 2003-2006 Silicon Graphics, Inc. All Rights Reserved. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms of version 2 of the GNU General Public License | 5 | * under the terms of version 2 of the GNU General Public License |
@@ -510,7 +510,7 @@ sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, int ddir) | |||
510 | drive->name); | 510 | drive->name); |
511 | goto use_pio_instead; | 511 | goto use_pio_instead; |
512 | } else { | 512 | } else { |
513 | u32 xcount, bcount = | 513 | u32 bcount = |
514 | 0x10000 - (cur_addr & 0xffff); | 514 | 0x10000 - (cur_addr & 0xffff); |
515 | 515 | ||
516 | if (bcount > cur_len) | 516 | if (bcount > cur_len) |
@@ -525,8 +525,7 @@ sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, int ddir) | |||
525 | *table = 0x0; | 525 | *table = 0x0; |
526 | table++; | 526 | table++; |
527 | 527 | ||
528 | xcount = bcount & 0xffff; | 528 | *table = cpu_to_be32(bcount); |
529 | *table = cpu_to_be32(xcount); | ||
530 | table++; | 529 | table++; |
531 | 530 | ||
532 | cur_addr += bcount; | 531 | cur_addr += bcount; |
@@ -680,7 +679,7 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d) | |||
680 | return -EIO; | 679 | return -EIO; |
681 | 680 | ||
682 | /* Create /proc/ide entries */ | 681 | /* Create /proc/ide entries */ |
683 | create_proc_ide_interfaces(); | 682 | create_proc_ide_interfaces(); |
684 | 683 | ||
685 | return 0; | 684 | return 0; |
686 | } | 685 | } |
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c index e95c4293a496..f6a05965a4e8 100644 --- a/drivers/infiniband/core/ucm.c +++ b/drivers/infiniband/core/ucm.c | |||
@@ -1319,15 +1319,6 @@ static struct class ucm_class = { | |||
1319 | .release = ib_ucm_release_class_dev | 1319 | .release = ib_ucm_release_class_dev |
1320 | }; | 1320 | }; |
1321 | 1321 | ||
1322 | static ssize_t show_dev(struct class_device *class_dev, char *buf) | ||
1323 | { | ||
1324 | struct ib_ucm_device *dev; | ||
1325 | |||
1326 | dev = container_of(class_dev, struct ib_ucm_device, class_dev); | ||
1327 | return print_dev_t(buf, dev->dev.dev); | ||
1328 | } | ||
1329 | static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL); | ||
1330 | |||
1331 | static ssize_t show_ibdev(struct class_device *class_dev, char *buf) | 1322 | static ssize_t show_ibdev(struct class_device *class_dev, char *buf) |
1332 | { | 1323 | { |
1333 | struct ib_ucm_device *dev; | 1324 | struct ib_ucm_device *dev; |
@@ -1364,15 +1355,13 @@ static void ib_ucm_add_one(struct ib_device *device) | |||
1364 | 1355 | ||
1365 | ucm_dev->class_dev.class = &ucm_class; | 1356 | ucm_dev->class_dev.class = &ucm_class; |
1366 | ucm_dev->class_dev.dev = device->dma_device; | 1357 | ucm_dev->class_dev.dev = device->dma_device; |
1358 | ucm_dev->class_dev.devt = ucm_dev->dev.dev; | ||
1367 | snprintf(ucm_dev->class_dev.class_id, BUS_ID_SIZE, "ucm%d", | 1359 | snprintf(ucm_dev->class_dev.class_id, BUS_ID_SIZE, "ucm%d", |
1368 | ucm_dev->devnum); | 1360 | ucm_dev->devnum); |
1369 | if (class_device_register(&ucm_dev->class_dev)) | 1361 | if (class_device_register(&ucm_dev->class_dev)) |
1370 | goto err_cdev; | 1362 | goto err_cdev; |
1371 | 1363 | ||
1372 | if (class_device_create_file(&ucm_dev->class_dev, | 1364 | if (class_device_create_file(&ucm_dev->class_dev, |
1373 | &class_device_attr_dev)) | ||
1374 | goto err_class; | ||
1375 | if (class_device_create_file(&ucm_dev->class_dev, | ||
1376 | &class_device_attr_ibdev)) | 1365 | &class_device_attr_ibdev)) |
1377 | goto err_class; | 1366 | goto err_class; |
1378 | 1367 | ||
diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig index 0ef560144be3..6dfc94122dd9 100644 --- a/drivers/isdn/hisax/Kconfig +++ b/drivers/isdn/hisax/Kconfig | |||
@@ -351,7 +351,7 @@ config HISAX_ENTERNOW_PCI | |||
351 | 351 | ||
352 | config HISAX_AMD7930 | 352 | config HISAX_AMD7930 |
353 | bool "Am7930 (EXPERIMENTAL)" | 353 | bool "Am7930 (EXPERIMENTAL)" |
354 | depends on EXPERIMENTAL && SPARC | 354 | depends on EXPERIMENTAL && SPARC && BROKEN |
355 | help | 355 | help |
356 | This enables HiSax support for the AMD7930 chips on some SPARCs. | 356 | This enables HiSax support for the AMD7930 chips on some SPARCs. |
357 | This code is not finished yet. | 357 | This code is not finished yet. |
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h index 1b85ce166af8..11fe537e2f6f 100644 --- a/drivers/isdn/hisax/hisax.h +++ b/drivers/isdn/hisax/hisax.h | |||
@@ -216,7 +216,7 @@ struct Layer1 { | |||
216 | #define GROUP_TEI 127 | 216 | #define GROUP_TEI 127 |
217 | #define TEI_SAPI 63 | 217 | #define TEI_SAPI 63 |
218 | #define CTRL_SAPI 0 | 218 | #define CTRL_SAPI 0 |
219 | #define PACKET_NOACK 250 | 219 | #define PACKET_NOACK 7 |
220 | 220 | ||
221 | /* Layer2 Flags */ | 221 | /* Layer2 Flags */ |
222 | 222 | ||
diff --git a/drivers/isdn/sc/ioctl.c b/drivers/isdn/sc/ioctl.c index 3314a5a19854..94c9afb7017c 100644 --- a/drivers/isdn/sc/ioctl.c +++ b/drivers/isdn/sc/ioctl.c | |||
@@ -71,14 +71,14 @@ int sc_ioctl(int card, scs_ioctl *data) | |||
71 | /* | 71 | /* |
72 | * Get the SRec from user space | 72 | * Get the SRec from user space |
73 | */ | 73 | */ |
74 | if (copy_from_user(srec, data->dataptr, sizeof(srec))) { | 74 | if (copy_from_user(srec, data->dataptr, SCIOC_SRECSIZE)) { |
75 | kfree(rcvmsg); | 75 | kfree(rcvmsg); |
76 | kfree(srec); | 76 | kfree(srec); |
77 | return -EFAULT; | 77 | return -EFAULT; |
78 | } | 78 | } |
79 | 79 | ||
80 | status = send_and_receive(card, CMPID, cmReqType2, cmReqClass0, cmReqLoadProc, | 80 | status = send_and_receive(card, CMPID, cmReqType2, cmReqClass0, cmReqLoadProc, |
81 | 0, sizeof(srec), srec, rcvmsg, SAR_TIMEOUT); | 81 | 0, SCIOC_SRECSIZE, srec, rcvmsg, SAR_TIMEOUT); |
82 | kfree(rcvmsg); | 82 | kfree(rcvmsg); |
83 | kfree(srec); | 83 | kfree(srec); |
84 | 84 | ||
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig index 7d4a0ac28c06..12ad462737ba 100644 --- a/drivers/macintosh/Kconfig +++ b/drivers/macintosh/Kconfig | |||
@@ -187,6 +187,14 @@ config WINDFARM_PM91 | |||
187 | This driver provides thermal control for the PowerMac9,1 | 187 | This driver provides thermal control for the PowerMac9,1 |
188 | which is the recent (SMU based) single CPU desktop G5 | 188 | which is the recent (SMU based) single CPU desktop G5 |
189 | 189 | ||
190 | config WINDFARM_PM112 | ||
191 | tristate "Support for thermal management on PowerMac11,2" | ||
192 | depends on WINDFARM && I2C && PMAC_SMU | ||
193 | select I2C_POWERMAC | ||
194 | help | ||
195 | This driver provides thermal control for the PowerMac11,2 | ||
196 | which are the recent dual and quad G5 machines using the | ||
197 | 970MP dual-core processor. | ||
190 | 198 | ||
191 | config ANSLCD | 199 | config ANSLCD |
192 | tristate "Support for ANS LCD display" | 200 | tristate "Support for ANS LCD display" |
diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile index f4657aa81fb0..6081acdea404 100644 --- a/drivers/macintosh/Makefile +++ b/drivers/macintosh/Makefile | |||
@@ -35,3 +35,8 @@ obj-$(CONFIG_WINDFARM_PM91) += windfarm_smu_controls.o \ | |||
35 | windfarm_smu_sensors.o \ | 35 | windfarm_smu_sensors.o \ |
36 | windfarm_lm75_sensor.o windfarm_pid.o \ | 36 | windfarm_lm75_sensor.o windfarm_pid.o \ |
37 | windfarm_cpufreq_clamp.o windfarm_pm91.o | 37 | windfarm_cpufreq_clamp.o windfarm_pm91.o |
38 | obj-$(CONFIG_WINDFARM_PM112) += windfarm_pm112.o windfarm_smu_sat.o \ | ||
39 | windfarm_smu_controls.o \ | ||
40 | windfarm_smu_sensors.o \ | ||
41 | windfarm_max6690_sensor.o \ | ||
42 | windfarm_lm75_sensor.o windfarm_pid.o | ||
diff --git a/drivers/macintosh/windfarm.h b/drivers/macintosh/windfarm.h index 3f0cb0312ea3..7a2482cc26a7 100644 --- a/drivers/macintosh/windfarm.h +++ b/drivers/macintosh/windfarm.h | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/list.h> | 14 | #include <linux/list.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/notifier.h> | 16 | #include <linux/notifier.h> |
17 | #include <linux/device.h> | ||
17 | 18 | ||
18 | /* Display a 16.16 fixed point value */ | 19 | /* Display a 16.16 fixed point value */ |
19 | #define FIX32TOPRINT(f) ((f) >> 16),((((f) & 0xffff) * 1000) >> 16) | 20 | #define FIX32TOPRINT(f) ((f) >> 16),((((f) & 0xffff) * 1000) >> 16) |
@@ -39,6 +40,7 @@ struct wf_control { | |||
39 | char *name; | 40 | char *name; |
40 | int type; | 41 | int type; |
41 | struct kref ref; | 42 | struct kref ref; |
43 | struct device_attribute attr; | ||
42 | }; | 44 | }; |
43 | 45 | ||
44 | #define WF_CONTROL_TYPE_GENERIC 0 | 46 | #define WF_CONTROL_TYPE_GENERIC 0 |
@@ -87,6 +89,7 @@ struct wf_sensor { | |||
87 | struct wf_sensor_ops *ops; | 89 | struct wf_sensor_ops *ops; |
88 | char *name; | 90 | char *name; |
89 | struct kref ref; | 91 | struct kref ref; |
92 | struct device_attribute attr; | ||
90 | }; | 93 | }; |
91 | 94 | ||
92 | /* Same lifetime rules as controls */ | 95 | /* Same lifetime rules as controls */ |
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c index 6c2a471ea6c0..bb8d5efe19bf 100644 --- a/drivers/macintosh/windfarm_core.c +++ b/drivers/macintosh/windfarm_core.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/reboot.h> | 33 | #include <linux/reboot.h> |
34 | #include <linux/device.h> | 34 | #include <linux/device.h> |
35 | #include <linux/platform_device.h> | 35 | #include <linux/platform_device.h> |
36 | #include <linux/mutex.h> | ||
36 | 37 | ||
37 | #include "windfarm.h" | 38 | #include "windfarm.h" |
38 | 39 | ||
@@ -48,13 +49,17 @@ | |||
48 | 49 | ||
49 | static LIST_HEAD(wf_controls); | 50 | static LIST_HEAD(wf_controls); |
50 | static LIST_HEAD(wf_sensors); | 51 | static LIST_HEAD(wf_sensors); |
51 | static DECLARE_MUTEX(wf_lock); | 52 | static DEFINE_MUTEX(wf_lock); |
52 | static struct notifier_block *wf_client_list; | 53 | static struct notifier_block *wf_client_list; |
53 | static int wf_client_count; | 54 | static int wf_client_count; |
54 | static unsigned int wf_overtemp; | 55 | static unsigned int wf_overtemp; |
55 | static unsigned int wf_overtemp_counter; | 56 | static unsigned int wf_overtemp_counter; |
56 | struct task_struct *wf_thread; | 57 | struct task_struct *wf_thread; |
57 | 58 | ||
59 | static struct platform_device wf_platform_device = { | ||
60 | .name = "windfarm", | ||
61 | }; | ||
62 | |||
58 | /* | 63 | /* |
59 | * Utilities & tick thread | 64 | * Utilities & tick thread |
60 | */ | 65 | */ |
@@ -156,26 +161,67 @@ static void wf_control_release(struct kref *kref) | |||
156 | kfree(ct); | 161 | kfree(ct); |
157 | } | 162 | } |
158 | 163 | ||
164 | static ssize_t wf_show_control(struct device *dev, | ||
165 | struct device_attribute *attr, char *buf) | ||
166 | { | ||
167 | struct wf_control *ctrl = container_of(attr, struct wf_control, attr); | ||
168 | s32 val = 0; | ||
169 | int err; | ||
170 | |||
171 | err = ctrl->ops->get_value(ctrl, &val); | ||
172 | if (err < 0) | ||
173 | return err; | ||
174 | return sprintf(buf, "%d\n", val); | ||
175 | } | ||
176 | |||
177 | /* This is really only for debugging... */ | ||
178 | static ssize_t wf_store_control(struct device *dev, | ||
179 | struct device_attribute *attr, | ||
180 | const char *buf, size_t count) | ||
181 | { | ||
182 | struct wf_control *ctrl = container_of(attr, struct wf_control, attr); | ||
183 | int val; | ||
184 | int err; | ||
185 | char *endp; | ||
186 | |||
187 | val = simple_strtoul(buf, &endp, 0); | ||
188 | while (endp < buf + count && (*endp == ' ' || *endp == '\n')) | ||
189 | ++endp; | ||
190 | if (endp - buf < count) | ||
191 | return -EINVAL; | ||
192 | err = ctrl->ops->set_value(ctrl, val); | ||
193 | if (err < 0) | ||
194 | return err; | ||
195 | return count; | ||
196 | } | ||
197 | |||
159 | int wf_register_control(struct wf_control *new_ct) | 198 | int wf_register_control(struct wf_control *new_ct) |
160 | { | 199 | { |
161 | struct wf_control *ct; | 200 | struct wf_control *ct; |
162 | 201 | ||
163 | down(&wf_lock); | 202 | mutex_lock(&wf_lock); |
164 | list_for_each_entry(ct, &wf_controls, link) { | 203 | list_for_each_entry(ct, &wf_controls, link) { |
165 | if (!strcmp(ct->name, new_ct->name)) { | 204 | if (!strcmp(ct->name, new_ct->name)) { |
166 | printk(KERN_WARNING "windfarm: trying to register" | 205 | printk(KERN_WARNING "windfarm: trying to register" |
167 | " duplicate control %s\n", ct->name); | 206 | " duplicate control %s\n", ct->name); |
168 | up(&wf_lock); | 207 | mutex_unlock(&wf_lock); |
169 | return -EEXIST; | 208 | return -EEXIST; |
170 | } | 209 | } |
171 | } | 210 | } |
172 | kref_init(&new_ct->ref); | 211 | kref_init(&new_ct->ref); |
173 | list_add(&new_ct->link, &wf_controls); | 212 | list_add(&new_ct->link, &wf_controls); |
174 | 213 | ||
214 | new_ct->attr.attr.name = new_ct->name; | ||
215 | new_ct->attr.attr.owner = THIS_MODULE; | ||
216 | new_ct->attr.attr.mode = 0644; | ||
217 | new_ct->attr.show = wf_show_control; | ||
218 | new_ct->attr.store = wf_store_control; | ||
219 | device_create_file(&wf_platform_device.dev, &new_ct->attr); | ||
220 | |||
175 | DBG("wf: Registered control %s\n", new_ct->name); | 221 | DBG("wf: Registered control %s\n", new_ct->name); |
176 | 222 | ||
177 | wf_notify(WF_EVENT_NEW_CONTROL, new_ct); | 223 | wf_notify(WF_EVENT_NEW_CONTROL, new_ct); |
178 | up(&wf_lock); | 224 | mutex_unlock(&wf_lock); |
179 | 225 | ||
180 | return 0; | 226 | return 0; |
181 | } | 227 | } |
@@ -183,9 +229,9 @@ EXPORT_SYMBOL_GPL(wf_register_control); | |||
183 | 229 | ||
184 | void wf_unregister_control(struct wf_control *ct) | 230 | void wf_unregister_control(struct wf_control *ct) |
185 | { | 231 | { |
186 | down(&wf_lock); | 232 | mutex_lock(&wf_lock); |
187 | list_del(&ct->link); | 233 | list_del(&ct->link); |
188 | up(&wf_lock); | 234 | mutex_unlock(&wf_lock); |
189 | 235 | ||
190 | DBG("wf: Unregistered control %s\n", ct->name); | 236 | DBG("wf: Unregistered control %s\n", ct->name); |
191 | 237 | ||
@@ -197,16 +243,16 @@ struct wf_control * wf_find_control(const char *name) | |||
197 | { | 243 | { |
198 | struct wf_control *ct; | 244 | struct wf_control *ct; |
199 | 245 | ||
200 | down(&wf_lock); | 246 | mutex_lock(&wf_lock); |
201 | list_for_each_entry(ct, &wf_controls, link) { | 247 | list_for_each_entry(ct, &wf_controls, link) { |
202 | if (!strcmp(ct->name, name)) { | 248 | if (!strcmp(ct->name, name)) { |
203 | if (wf_get_control(ct)) | 249 | if (wf_get_control(ct)) |
204 | ct = NULL; | 250 | ct = NULL; |
205 | up(&wf_lock); | 251 | mutex_unlock(&wf_lock); |
206 | return ct; | 252 | return ct; |
207 | } | 253 | } |
208 | } | 254 | } |
209 | up(&wf_lock); | 255 | mutex_unlock(&wf_lock); |
210 | return NULL; | 256 | return NULL; |
211 | } | 257 | } |
212 | EXPORT_SYMBOL_GPL(wf_find_control); | 258 | EXPORT_SYMBOL_GPL(wf_find_control); |
@@ -246,26 +292,46 @@ static void wf_sensor_release(struct kref *kref) | |||
246 | kfree(sr); | 292 | kfree(sr); |
247 | } | 293 | } |
248 | 294 | ||
295 | static ssize_t wf_show_sensor(struct device *dev, | ||
296 | struct device_attribute *attr, char *buf) | ||
297 | { | ||
298 | struct wf_sensor *sens = container_of(attr, struct wf_sensor, attr); | ||
299 | s32 val = 0; | ||
300 | int err; | ||
301 | |||
302 | err = sens->ops->get_value(sens, &val); | ||
303 | if (err < 0) | ||
304 | return err; | ||
305 | return sprintf(buf, "%d.%03d\n", FIX32TOPRINT(val)); | ||
306 | } | ||
307 | |||
249 | int wf_register_sensor(struct wf_sensor *new_sr) | 308 | int wf_register_sensor(struct wf_sensor *new_sr) |
250 | { | 309 | { |
251 | struct wf_sensor *sr; | 310 | struct wf_sensor *sr; |
252 | 311 | ||
253 | down(&wf_lock); | 312 | mutex_lock(&wf_lock); |
254 | list_for_each_entry(sr, &wf_sensors, link) { | 313 | list_for_each_entry(sr, &wf_sensors, link) { |
255 | if (!strcmp(sr->name, new_sr->name)) { | 314 | if (!strcmp(sr->name, new_sr->name)) { |
256 | printk(KERN_WARNING "windfarm: trying to register" | 315 | printk(KERN_WARNING "windfarm: trying to register" |
257 | " duplicate sensor %s\n", sr->name); | 316 | " duplicate sensor %s\n", sr->name); |
258 | up(&wf_lock); | 317 | mutex_unlock(&wf_lock); |
259 | return -EEXIST; | 318 | return -EEXIST; |
260 | } | 319 | } |
261 | } | 320 | } |
262 | kref_init(&new_sr->ref); | 321 | kref_init(&new_sr->ref); |
263 | list_add(&new_sr->link, &wf_sensors); | 322 | list_add(&new_sr->link, &wf_sensors); |
264 | 323 | ||
324 | new_sr->attr.attr.name = new_sr->name; | ||
325 | new_sr->attr.attr.owner = THIS_MODULE; | ||
326 | new_sr->attr.attr.mode = 0444; | ||
327 | new_sr->attr.show = wf_show_sensor; | ||
328 | new_sr->attr.store = NULL; | ||
329 | device_create_file(&wf_platform_device.dev, &new_sr->attr); | ||
330 | |||
265 | DBG("wf: Registered sensor %s\n", new_sr->name); | 331 | DBG("wf: Registered sensor %s\n", new_sr->name); |
266 | 332 | ||
267 | wf_notify(WF_EVENT_NEW_SENSOR, new_sr); | 333 | wf_notify(WF_EVENT_NEW_SENSOR, new_sr); |
268 | up(&wf_lock); | 334 | mutex_unlock(&wf_lock); |
269 | 335 | ||
270 | return 0; | 336 | return 0; |
271 | } | 337 | } |
@@ -273,9 +339,9 @@ EXPORT_SYMBOL_GPL(wf_register_sensor); | |||
273 | 339 | ||
274 | void wf_unregister_sensor(struct wf_sensor *sr) | 340 | void wf_unregister_sensor(struct wf_sensor *sr) |
275 | { | 341 | { |
276 | down(&wf_lock); | 342 | mutex_lock(&wf_lock); |
277 | list_del(&sr->link); | 343 | list_del(&sr->link); |
278 | up(&wf_lock); | 344 | mutex_unlock(&wf_lock); |
279 | 345 | ||
280 | DBG("wf: Unregistered sensor %s\n", sr->name); | 346 | DBG("wf: Unregistered sensor %s\n", sr->name); |
281 | 347 | ||
@@ -287,16 +353,16 @@ struct wf_sensor * wf_find_sensor(const char *name) | |||
287 | { | 353 | { |
288 | struct wf_sensor *sr; | 354 | struct wf_sensor *sr; |
289 | 355 | ||
290 | down(&wf_lock); | 356 | mutex_lock(&wf_lock); |
291 | list_for_each_entry(sr, &wf_sensors, link) { | 357 | list_for_each_entry(sr, &wf_sensors, link) { |
292 | if (!strcmp(sr->name, name)) { | 358 | if (!strcmp(sr->name, name)) { |
293 | if (wf_get_sensor(sr)) | 359 | if (wf_get_sensor(sr)) |
294 | sr = NULL; | 360 | sr = NULL; |
295 | up(&wf_lock); | 361 | mutex_unlock(&wf_lock); |
296 | return sr; | 362 | return sr; |
297 | } | 363 | } |
298 | } | 364 | } |
299 | up(&wf_lock); | 365 | mutex_unlock(&wf_lock); |
300 | return NULL; | 366 | return NULL; |
301 | } | 367 | } |
302 | EXPORT_SYMBOL_GPL(wf_find_sensor); | 368 | EXPORT_SYMBOL_GPL(wf_find_sensor); |
@@ -329,7 +395,7 @@ int wf_register_client(struct notifier_block *nb) | |||
329 | struct wf_control *ct; | 395 | struct wf_control *ct; |
330 | struct wf_sensor *sr; | 396 | struct wf_sensor *sr; |
331 | 397 | ||
332 | down(&wf_lock); | 398 | mutex_lock(&wf_lock); |
333 | rc = notifier_chain_register(&wf_client_list, nb); | 399 | rc = notifier_chain_register(&wf_client_list, nb); |
334 | if (rc != 0) | 400 | if (rc != 0) |
335 | goto bail; | 401 | goto bail; |
@@ -341,19 +407,19 @@ int wf_register_client(struct notifier_block *nb) | |||
341 | if (wf_client_count == 1) | 407 | if (wf_client_count == 1) |
342 | wf_start_thread(); | 408 | wf_start_thread(); |
343 | bail: | 409 | bail: |
344 | up(&wf_lock); | 410 | mutex_unlock(&wf_lock); |
345 | return rc; | 411 | return rc; |
346 | } | 412 | } |
347 | EXPORT_SYMBOL_GPL(wf_register_client); | 413 | EXPORT_SYMBOL_GPL(wf_register_client); |
348 | 414 | ||
349 | int wf_unregister_client(struct notifier_block *nb) | 415 | int wf_unregister_client(struct notifier_block *nb) |
350 | { | 416 | { |
351 | down(&wf_lock); | 417 | mutex_lock(&wf_lock); |
352 | notifier_chain_unregister(&wf_client_list, nb); | 418 | notifier_chain_unregister(&wf_client_list, nb); |
353 | wf_client_count++; | 419 | wf_client_count++; |
354 | if (wf_client_count == 0) | 420 | if (wf_client_count == 0) |
355 | wf_stop_thread(); | 421 | wf_stop_thread(); |
356 | up(&wf_lock); | 422 | mutex_unlock(&wf_lock); |
357 | 423 | ||
358 | return 0; | 424 | return 0; |
359 | } | 425 | } |
@@ -361,23 +427,23 @@ EXPORT_SYMBOL_GPL(wf_unregister_client); | |||
361 | 427 | ||
362 | void wf_set_overtemp(void) | 428 | void wf_set_overtemp(void) |
363 | { | 429 | { |
364 | down(&wf_lock); | 430 | mutex_lock(&wf_lock); |
365 | wf_overtemp++; | 431 | wf_overtemp++; |
366 | if (wf_overtemp == 1) { | 432 | if (wf_overtemp == 1) { |
367 | printk(KERN_WARNING "windfarm: Overtemp condition detected !\n"); | 433 | printk(KERN_WARNING "windfarm: Overtemp condition detected !\n"); |
368 | wf_overtemp_counter = 0; | 434 | wf_overtemp_counter = 0; |
369 | wf_notify(WF_EVENT_OVERTEMP, NULL); | 435 | wf_notify(WF_EVENT_OVERTEMP, NULL); |
370 | } | 436 | } |
371 | up(&wf_lock); | 437 | mutex_unlock(&wf_lock); |
372 | } | 438 | } |
373 | EXPORT_SYMBOL_GPL(wf_set_overtemp); | 439 | EXPORT_SYMBOL_GPL(wf_set_overtemp); |
374 | 440 | ||
375 | void wf_clear_overtemp(void) | 441 | void wf_clear_overtemp(void) |
376 | { | 442 | { |
377 | down(&wf_lock); | 443 | mutex_lock(&wf_lock); |
378 | WARN_ON(wf_overtemp == 0); | 444 | WARN_ON(wf_overtemp == 0); |
379 | if (wf_overtemp == 0) { | 445 | if (wf_overtemp == 0) { |
380 | up(&wf_lock); | 446 | mutex_unlock(&wf_lock); |
381 | return; | 447 | return; |
382 | } | 448 | } |
383 | wf_overtemp--; | 449 | wf_overtemp--; |
@@ -385,7 +451,7 @@ void wf_clear_overtemp(void) | |||
385 | printk(KERN_WARNING "windfarm: Overtemp condition cleared !\n"); | 451 | printk(KERN_WARNING "windfarm: Overtemp condition cleared !\n"); |
386 | wf_notify(WF_EVENT_NORMALTEMP, NULL); | 452 | wf_notify(WF_EVENT_NORMALTEMP, NULL); |
387 | } | 453 | } |
388 | up(&wf_lock); | 454 | mutex_unlock(&wf_lock); |
389 | } | 455 | } |
390 | EXPORT_SYMBOL_GPL(wf_clear_overtemp); | 456 | EXPORT_SYMBOL_GPL(wf_clear_overtemp); |
391 | 457 | ||
@@ -395,10 +461,6 @@ int wf_is_overtemp(void) | |||
395 | } | 461 | } |
396 | EXPORT_SYMBOL_GPL(wf_is_overtemp); | 462 | EXPORT_SYMBOL_GPL(wf_is_overtemp); |
397 | 463 | ||
398 | static struct platform_device wf_platform_device = { | ||
399 | .name = "windfarm", | ||
400 | }; | ||
401 | |||
402 | static int __init windfarm_core_init(void) | 464 | static int __init windfarm_core_init(void) |
403 | { | 465 | { |
404 | DBG("wf: core loaded\n"); | 466 | DBG("wf: core loaded\n"); |
diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c new file mode 100644 index 000000000000..5b9ad6ca7cba --- /dev/null +++ b/drivers/macintosh/windfarm_max6690_sensor.c | |||
@@ -0,0 +1,169 @@ | |||
1 | /* | ||
2 | * Windfarm PowerMac thermal control. MAX6690 sensor. | ||
3 | * | ||
4 | * Copyright (C) 2005 Paul Mackerras, IBM Corp. <paulus@samba.org> | ||
5 | * | ||
6 | * Use and redistribute under the terms of the GNU GPL v2. | ||
7 | */ | ||
8 | #include <linux/types.h> | ||
9 | #include <linux/errno.h> | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/i2c-dev.h> | ||
15 | #include <asm/prom.h> | ||
16 | #include <asm/pmac_low_i2c.h> | ||
17 | |||
18 | #include "windfarm.h" | ||
19 | |||
20 | #define VERSION "0.1" | ||
21 | |||
22 | /* This currently only exports the external temperature sensor, | ||
23 | since that's all the control loops need. */ | ||
24 | |||
25 | /* Some MAX6690 register numbers */ | ||
26 | #define MAX6690_INTERNAL_TEMP 0 | ||
27 | #define MAX6690_EXTERNAL_TEMP 1 | ||
28 | |||
29 | struct wf_6690_sensor { | ||
30 | struct i2c_client i2c; | ||
31 | struct wf_sensor sens; | ||
32 | }; | ||
33 | |||
34 | #define wf_to_6690(x) container_of((x), struct wf_6690_sensor, sens) | ||
35 | #define i2c_to_6690(x) container_of((x), struct wf_6690_sensor, i2c) | ||
36 | |||
37 | static int wf_max6690_attach(struct i2c_adapter *adapter); | ||
38 | static int wf_max6690_detach(struct i2c_client *client); | ||
39 | |||
40 | static struct i2c_driver wf_max6690_driver = { | ||
41 | .driver = { | ||
42 | .name = "wf_max6690", | ||
43 | }, | ||
44 | .attach_adapter = wf_max6690_attach, | ||
45 | .detach_client = wf_max6690_detach, | ||
46 | }; | ||
47 | |||
48 | static int wf_max6690_get(struct wf_sensor *sr, s32 *value) | ||
49 | { | ||
50 | struct wf_6690_sensor *max = wf_to_6690(sr); | ||
51 | s32 data; | ||
52 | |||
53 | if (max->i2c.adapter == NULL) | ||
54 | return -ENODEV; | ||
55 | |||
56 | /* chip gets initialized by firmware */ | ||
57 | data = i2c_smbus_read_byte_data(&max->i2c, MAX6690_EXTERNAL_TEMP); | ||
58 | if (data < 0) | ||
59 | return data; | ||
60 | *value = data << 16; | ||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | static void wf_max6690_release(struct wf_sensor *sr) | ||
65 | { | ||
66 | struct wf_6690_sensor *max = wf_to_6690(sr); | ||
67 | |||
68 | if (max->i2c.adapter) { | ||
69 | i2c_detach_client(&max->i2c); | ||
70 | max->i2c.adapter = NULL; | ||
71 | } | ||
72 | kfree(max); | ||
73 | } | ||
74 | |||
75 | static struct wf_sensor_ops wf_max6690_ops = { | ||
76 | .get_value = wf_max6690_get, | ||
77 | .release = wf_max6690_release, | ||
78 | .owner = THIS_MODULE, | ||
79 | }; | ||
80 | |||
81 | static void wf_max6690_create(struct i2c_adapter *adapter, u8 addr) | ||
82 | { | ||
83 | struct wf_6690_sensor *max; | ||
84 | char *name = "u4-temp"; | ||
85 | |||
86 | max = kzalloc(sizeof(struct wf_6690_sensor), GFP_KERNEL); | ||
87 | if (max == NULL) { | ||
88 | printk(KERN_ERR "windfarm: Couldn't create MAX6690 sensor %s: " | ||
89 | "no memory\n", name); | ||
90 | return; | ||
91 | } | ||
92 | |||
93 | max->sens.ops = &wf_max6690_ops; | ||
94 | max->sens.name = name; | ||
95 | max->i2c.addr = addr >> 1; | ||
96 | max->i2c.adapter = adapter; | ||
97 | max->i2c.driver = &wf_max6690_driver; | ||
98 | strncpy(max->i2c.name, name, I2C_NAME_SIZE-1); | ||
99 | |||
100 | if (i2c_attach_client(&max->i2c)) { | ||
101 | printk(KERN_ERR "windfarm: failed to attach MAX6690 sensor\n"); | ||
102 | goto fail; | ||
103 | } | ||
104 | |||
105 | if (wf_register_sensor(&max->sens)) { | ||
106 | i2c_detach_client(&max->i2c); | ||
107 | goto fail; | ||
108 | } | ||
109 | |||
110 | return; | ||
111 | |||
112 | fail: | ||
113 | kfree(max); | ||
114 | } | ||
115 | |||
116 | static int wf_max6690_attach(struct i2c_adapter *adapter) | ||
117 | { | ||
118 | struct device_node *busnode, *dev = NULL; | ||
119 | struct pmac_i2c_bus *bus; | ||
120 | const char *loc; | ||
121 | u32 *reg; | ||
122 | |||
123 | bus = pmac_i2c_adapter_to_bus(adapter); | ||
124 | if (bus == NULL) | ||
125 | return -ENODEV; | ||
126 | busnode = pmac_i2c_get_bus_node(bus); | ||
127 | |||
128 | while ((dev = of_get_next_child(busnode, dev)) != NULL) { | ||
129 | if (!device_is_compatible(dev, "max6690")) | ||
130 | continue; | ||
131 | loc = get_property(dev, "hwsensor-location", NULL); | ||
132 | reg = (u32 *) get_property(dev, "reg", NULL); | ||
133 | if (!loc || !reg) | ||
134 | continue; | ||
135 | printk("found max6690, loc=%s reg=%x\n", loc, *reg); | ||
136 | if (strcmp(loc, "BACKSIDE")) | ||
137 | continue; | ||
138 | wf_max6690_create(adapter, *reg); | ||
139 | } | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static int wf_max6690_detach(struct i2c_client *client) | ||
145 | { | ||
146 | struct wf_6690_sensor *max = i2c_to_6690(client); | ||
147 | |||
148 | max->i2c.adapter = NULL; | ||
149 | wf_unregister_sensor(&max->sens); | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | static int __init wf_max6690_sensor_init(void) | ||
155 | { | ||
156 | return i2c_add_driver(&wf_max6690_driver); | ||
157 | } | ||
158 | |||
159 | static void __exit wf_max6690_sensor_exit(void) | ||
160 | { | ||
161 | i2c_del_driver(&wf_max6690_driver); | ||
162 | } | ||
163 | |||
164 | module_init(wf_max6690_sensor_init); | ||
165 | module_exit(wf_max6690_sensor_exit); | ||
166 | |||
167 | MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>"); | ||
168 | MODULE_DESCRIPTION("MAX6690 sensor objects for PowerMac thermal control"); | ||
169 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/macintosh/windfarm_pid.c b/drivers/macintosh/windfarm_pid.c index 2e803b368757..0842432e27ad 100644 --- a/drivers/macintosh/windfarm_pid.c +++ b/drivers/macintosh/windfarm_pid.c | |||
@@ -88,8 +88,8 @@ EXPORT_SYMBOL_GPL(wf_cpu_pid_init); | |||
88 | 88 | ||
89 | s32 wf_cpu_pid_run(struct wf_cpu_pid_state *st, s32 new_power, s32 new_temp) | 89 | s32 wf_cpu_pid_run(struct wf_cpu_pid_state *st, s32 new_power, s32 new_temp) |
90 | { | 90 | { |
91 | s64 error, integ, deriv, prop; | 91 | s64 integ, deriv, prop; |
92 | s32 target, sval, adj; | 92 | s32 error, target, sval, adj; |
93 | int i, hlen = st->param.history_len; | 93 | int i, hlen = st->param.history_len; |
94 | 94 | ||
95 | /* Calculate error term */ | 95 | /* Calculate error term */ |
@@ -117,7 +117,7 @@ s32 wf_cpu_pid_run(struct wf_cpu_pid_state *st, s32 new_power, s32 new_temp) | |||
117 | integ += st->errors[(st->index + hlen - i) % hlen]; | 117 | integ += st->errors[(st->index + hlen - i) % hlen]; |
118 | integ *= st->param.interval; | 118 | integ *= st->param.interval; |
119 | integ *= st->param.gr; | 119 | integ *= st->param.gr; |
120 | sval = st->param.tmax - ((integ >> 20) & 0xffffffff); | 120 | sval = st->param.tmax - (s32)(integ >> 20); |
121 | adj = min(st->param.ttarget, sval); | 121 | adj = min(st->param.ttarget, sval); |
122 | 122 | ||
123 | DBG("integ: %lx, sval: %lx, adj: %lx\n", integ, sval, adj); | 123 | DBG("integ: %lx, sval: %lx, adj: %lx\n", integ, sval, adj); |
@@ -129,7 +129,7 @@ s32 wf_cpu_pid_run(struct wf_cpu_pid_state *st, s32 new_power, s32 new_temp) | |||
129 | deriv *= st->param.gd; | 129 | deriv *= st->param.gd; |
130 | 130 | ||
131 | /* Calculate proportional term */ | 131 | /* Calculate proportional term */ |
132 | prop = (new_temp - adj); | 132 | prop = st->last_delta = (new_temp - adj); |
133 | prop *= st->param.gp; | 133 | prop *= st->param.gp; |
134 | 134 | ||
135 | DBG("deriv: %lx, prop: %lx\n", deriv, prop); | 135 | DBG("deriv: %lx, prop: %lx\n", deriv, prop); |
diff --git a/drivers/macintosh/windfarm_pid.h b/drivers/macintosh/windfarm_pid.h index a364c2a2499c..bbccc22d42b8 100644 --- a/drivers/macintosh/windfarm_pid.h +++ b/drivers/macintosh/windfarm_pid.h | |||
@@ -72,6 +72,7 @@ struct wf_cpu_pid_state { | |||
72 | int index; /* index of current power */ | 72 | int index; /* index of current power */ |
73 | int tindex; /* index of current temp */ | 73 | int tindex; /* index of current temp */ |
74 | s32 target; /* current target value */ | 74 | s32 target; /* current target value */ |
75 | s32 last_delta; /* last Tactual - Ttarget */ | ||
75 | s32 powers[WF_PID_MAX_HISTORY]; /* power history buffer */ | 76 | s32 powers[WF_PID_MAX_HISTORY]; /* power history buffer */ |
76 | s32 errors[WF_PID_MAX_HISTORY]; /* error history buffer */ | 77 | s32 errors[WF_PID_MAX_HISTORY]; /* error history buffer */ |
77 | s32 temps[2]; /* temp. history buffer */ | 78 | s32 temps[2]; /* temp. history buffer */ |
diff --git a/drivers/macintosh/windfarm_pm112.c b/drivers/macintosh/windfarm_pm112.c new file mode 100644 index 000000000000..c2a4e689c784 --- /dev/null +++ b/drivers/macintosh/windfarm_pm112.c | |||
@@ -0,0 +1,698 @@ | |||
1 | /* | ||
2 | * Windfarm PowerMac thermal control. | ||
3 | * Control loops for machines with SMU and PPC970MP processors. | ||
4 | * | ||
5 | * Copyright (C) 2005 Paul Mackerras, IBM Corp. <paulus@samba.org> | ||
6 | * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp. | ||
7 | * | ||
8 | * Use and redistribute under the terms of the GNU GPL v2. | ||
9 | */ | ||
10 | #include <linux/types.h> | ||
11 | #include <linux/errno.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/device.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/reboot.h> | ||
16 | #include <asm/prom.h> | ||
17 | #include <asm/smu.h> | ||
18 | |||
19 | #include "windfarm.h" | ||
20 | #include "windfarm_pid.h" | ||
21 | |||
22 | #define VERSION "0.2" | ||
23 | |||
24 | #define DEBUG | ||
25 | #undef LOTSA_DEBUG | ||
26 | |||
27 | #ifdef DEBUG | ||
28 | #define DBG(args...) printk(args) | ||
29 | #else | ||
30 | #define DBG(args...) do { } while(0) | ||
31 | #endif | ||
32 | |||
33 | #ifdef LOTSA_DEBUG | ||
34 | #define DBG_LOTS(args...) printk(args) | ||
35 | #else | ||
36 | #define DBG_LOTS(args...) do { } while(0) | ||
37 | #endif | ||
38 | |||
39 | /* define this to force CPU overtemp to 60 degree, useful for testing | ||
40 | * the overtemp code | ||
41 | */ | ||
42 | #undef HACKED_OVERTEMP | ||
43 | |||
44 | /* We currently only handle 2 chips, 4 cores... */ | ||
45 | #define NR_CHIPS 2 | ||
46 | #define NR_CORES 4 | ||
47 | #define NR_CPU_FANS 3 * NR_CHIPS | ||
48 | |||
49 | /* Controls and sensors */ | ||
50 | static struct wf_sensor *sens_cpu_temp[NR_CORES]; | ||
51 | static struct wf_sensor *sens_cpu_power[NR_CORES]; | ||
52 | static struct wf_sensor *hd_temp; | ||
53 | static struct wf_sensor *slots_power; | ||
54 | static struct wf_sensor *u4_temp; | ||
55 | |||
56 | static struct wf_control *cpu_fans[NR_CPU_FANS]; | ||
57 | static char *cpu_fan_names[NR_CPU_FANS] = { | ||
58 | "cpu-rear-fan-0", | ||
59 | "cpu-rear-fan-1", | ||
60 | "cpu-front-fan-0", | ||
61 | "cpu-front-fan-1", | ||
62 | "cpu-pump-0", | ||
63 | "cpu-pump-1", | ||
64 | }; | ||
65 | static struct wf_control *cpufreq_clamp; | ||
66 | |||
67 | /* Second pump isn't required (and isn't actually present) */ | ||
68 | #define CPU_FANS_REQD (NR_CPU_FANS - 2) | ||
69 | #define FIRST_PUMP 4 | ||
70 | #define LAST_PUMP 5 | ||
71 | |||
72 | /* We keep a temperature history for average calculation of 180s */ | ||
73 | #define CPU_TEMP_HIST_SIZE 180 | ||
74 | |||
75 | /* Scale factor for fan speed, *100 */ | ||
76 | static int cpu_fan_scale[NR_CPU_FANS] = { | ||
77 | 100, | ||
78 | 100, | ||
79 | 97, /* inlet fans run at 97% of exhaust fan */ | ||
80 | 97, | ||
81 | 100, /* updated later */ | ||
82 | 100, /* updated later */ | ||
83 | }; | ||
84 | |||
85 | static struct wf_control *backside_fan; | ||
86 | static struct wf_control *slots_fan; | ||
87 | static struct wf_control *drive_bay_fan; | ||
88 | |||
89 | /* PID loop state */ | ||
90 | static struct wf_cpu_pid_state cpu_pid[NR_CORES]; | ||
91 | static u32 cpu_thist[CPU_TEMP_HIST_SIZE]; | ||
92 | static int cpu_thist_pt; | ||
93 | static s64 cpu_thist_total; | ||
94 | static s32 cpu_all_tmax = 100 << 16; | ||
95 | static int cpu_last_target; | ||
96 | static struct wf_pid_state backside_pid; | ||
97 | static int backside_tick; | ||
98 | static struct wf_pid_state slots_pid; | ||
99 | static int slots_started; | ||
100 | static struct wf_pid_state drive_bay_pid; | ||
101 | static int drive_bay_tick; | ||
102 | |||
103 | static int nr_cores; | ||
104 | static int have_all_controls; | ||
105 | static int have_all_sensors; | ||
106 | static int started; | ||
107 | |||
108 | static int failure_state; | ||
109 | #define FAILURE_SENSOR 1 | ||
110 | #define FAILURE_FAN 2 | ||
111 | #define FAILURE_PERM 4 | ||
112 | #define FAILURE_LOW_OVERTEMP 8 | ||
113 | #define FAILURE_HIGH_OVERTEMP 16 | ||
114 | |||
115 | /* Overtemp values */ | ||
116 | #define LOW_OVER_AVERAGE 0 | ||
117 | #define LOW_OVER_IMMEDIATE (10 << 16) | ||
118 | #define LOW_OVER_CLEAR ((-10) << 16) | ||
119 | #define HIGH_OVER_IMMEDIATE (14 << 16) | ||
120 | #define HIGH_OVER_AVERAGE (10 << 16) | ||
121 | #define HIGH_OVER_IMMEDIATE (14 << 16) | ||
122 | |||
123 | |||
124 | /* Implementation... */ | ||
125 | static int create_cpu_loop(int cpu) | ||
126 | { | ||
127 | int chip = cpu / 2; | ||
128 | int core = cpu & 1; | ||
129 | struct smu_sdbp_header *hdr; | ||
130 | struct smu_sdbp_cpupiddata *piddata; | ||
131 | struct wf_cpu_pid_param pid; | ||
132 | struct wf_control *main_fan = cpu_fans[0]; | ||
133 | s32 tmax; | ||
134 | int fmin; | ||
135 | |||
136 | /* Get PID params from the appropriate SAT */ | ||
137 | hdr = smu_sat_get_sdb_partition(chip, 0xC8 + core, NULL); | ||
138 | if (hdr == NULL) { | ||
139 | printk(KERN_WARNING"windfarm: can't get CPU PID fan config\n"); | ||
140 | return -EINVAL; | ||
141 | } | ||
142 | piddata = (struct smu_sdbp_cpupiddata *)&hdr[1]; | ||
143 | |||
144 | /* Get FVT params to get Tmax; if not found, assume default */ | ||
145 | hdr = smu_sat_get_sdb_partition(chip, 0xC4 + core, NULL); | ||
146 | if (hdr) { | ||
147 | struct smu_sdbp_fvt *fvt = (struct smu_sdbp_fvt *)&hdr[1]; | ||
148 | tmax = fvt->maxtemp << 16; | ||
149 | } else | ||
150 | tmax = 95 << 16; /* default to 95 degrees C */ | ||
151 | |||
152 | /* We keep a global tmax for overtemp calculations */ | ||
153 | if (tmax < cpu_all_tmax) | ||
154 | cpu_all_tmax = tmax; | ||
155 | |||
156 | /* | ||
157 | * Darwin has a minimum fan speed of 1000 rpm for the 4-way and | ||
158 | * 515 for the 2-way. That appears to be overkill, so for now, | ||
159 | * impose a minimum of 750 or 515. | ||
160 | */ | ||
161 | fmin = (nr_cores > 2) ? 750 : 515; | ||
162 | |||
163 | /* Initialize PID loop */ | ||
164 | pid.interval = 1; /* seconds */ | ||
165 | pid.history_len = piddata->history_len; | ||
166 | pid.gd = piddata->gd; | ||
167 | pid.gp = piddata->gp; | ||
168 | pid.gr = piddata->gr / piddata->history_len; | ||
169 | pid.pmaxadj = (piddata->max_power << 16) - (piddata->power_adj << 8); | ||
170 | pid.ttarget = tmax - (piddata->target_temp_delta << 16); | ||
171 | pid.tmax = tmax; | ||
172 | pid.min = main_fan->ops->get_min(main_fan); | ||
173 | pid.max = main_fan->ops->get_max(main_fan); | ||
174 | if (pid.min < fmin) | ||
175 | pid.min = fmin; | ||
176 | |||
177 | wf_cpu_pid_init(&cpu_pid[cpu], &pid); | ||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | static void cpu_max_all_fans(void) | ||
182 | { | ||
183 | int i; | ||
184 | |||
185 | /* We max all CPU fans in case of a sensor error. We also do the | ||
186 | * cpufreq clamping now, even if it's supposedly done later by the | ||
187 | * generic code anyway, we do it earlier here to react faster | ||
188 | */ | ||
189 | if (cpufreq_clamp) | ||
190 | wf_control_set_max(cpufreq_clamp); | ||
191 | for (i = 0; i < NR_CPU_FANS; ++i) | ||
192 | if (cpu_fans[i]) | ||
193 | wf_control_set_max(cpu_fans[i]); | ||
194 | } | ||
195 | |||
196 | static int cpu_check_overtemp(s32 temp) | ||
197 | { | ||
198 | int new_state = 0; | ||
199 | s32 t_avg, t_old; | ||
200 | |||
201 | /* First check for immediate overtemps */ | ||
202 | if (temp >= (cpu_all_tmax + LOW_OVER_IMMEDIATE)) { | ||
203 | new_state |= FAILURE_LOW_OVERTEMP; | ||
204 | if ((failure_state & FAILURE_LOW_OVERTEMP) == 0) | ||
205 | printk(KERN_ERR "windfarm: Overtemp due to immediate CPU" | ||
206 | " temperature !\n"); | ||
207 | } | ||
208 | if (temp >= (cpu_all_tmax + HIGH_OVER_IMMEDIATE)) { | ||
209 | new_state |= FAILURE_HIGH_OVERTEMP; | ||
210 | if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0) | ||
211 | printk(KERN_ERR "windfarm: Critical overtemp due to" | ||
212 | " immediate CPU temperature !\n"); | ||
213 | } | ||
214 | |||
215 | /* We calculate a history of max temperatures and use that for the | ||
216 | * overtemp management | ||
217 | */ | ||
218 | t_old = cpu_thist[cpu_thist_pt]; | ||
219 | cpu_thist[cpu_thist_pt] = temp; | ||
220 | cpu_thist_pt = (cpu_thist_pt + 1) % CPU_TEMP_HIST_SIZE; | ||
221 | cpu_thist_total -= t_old; | ||
222 | cpu_thist_total += temp; | ||
223 | t_avg = cpu_thist_total / CPU_TEMP_HIST_SIZE; | ||
224 | |||
225 | DBG_LOTS("t_avg = %d.%03d (out: %d.%03d, in: %d.%03d)\n", | ||
226 | FIX32TOPRINT(t_avg), FIX32TOPRINT(t_old), FIX32TOPRINT(temp)); | ||
227 | |||
228 | /* Now check for average overtemps */ | ||
229 | if (t_avg >= (cpu_all_tmax + LOW_OVER_AVERAGE)) { | ||
230 | new_state |= FAILURE_LOW_OVERTEMP; | ||
231 | if ((failure_state & FAILURE_LOW_OVERTEMP) == 0) | ||
232 | printk(KERN_ERR "windfarm: Overtemp due to average CPU" | ||
233 | " temperature !\n"); | ||
234 | } | ||
235 | if (t_avg >= (cpu_all_tmax + HIGH_OVER_AVERAGE)) { | ||
236 | new_state |= FAILURE_HIGH_OVERTEMP; | ||
237 | if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0) | ||
238 | printk(KERN_ERR "windfarm: Critical overtemp due to" | ||
239 | " average CPU temperature !\n"); | ||
240 | } | ||
241 | |||
242 | /* Now handle overtemp conditions. We don't currently use the windfarm | ||
243 | * overtemp handling core as it's not fully suited to the needs of those | ||
244 | * new machine. This will be fixed later. | ||
245 | */ | ||
246 | if (new_state) { | ||
247 | /* High overtemp -> immediate shutdown */ | ||
248 | if (new_state & FAILURE_HIGH_OVERTEMP) | ||
249 | machine_power_off(); | ||
250 | if ((failure_state & new_state) != new_state) | ||
251 | cpu_max_all_fans(); | ||
252 | failure_state |= new_state; | ||
253 | } else if ((failure_state & FAILURE_LOW_OVERTEMP) && | ||
254 | (temp < (cpu_all_tmax + LOW_OVER_CLEAR))) { | ||
255 | printk(KERN_ERR "windfarm: Overtemp condition cleared !\n"); | ||
256 | failure_state &= ~FAILURE_LOW_OVERTEMP; | ||
257 | } | ||
258 | |||
259 | return failure_state & (FAILURE_LOW_OVERTEMP | FAILURE_HIGH_OVERTEMP); | ||
260 | } | ||
261 | |||
262 | static void cpu_fans_tick(void) | ||
263 | { | ||
264 | int err, cpu; | ||
265 | s32 greatest_delta = 0; | ||
266 | s32 temp, power, t_max = 0; | ||
267 | int i, t, target = 0; | ||
268 | struct wf_sensor *sr; | ||
269 | struct wf_control *ct; | ||
270 | struct wf_cpu_pid_state *sp; | ||
271 | |||
272 | DBG_LOTS(KERN_DEBUG); | ||
273 | for (cpu = 0; cpu < nr_cores; ++cpu) { | ||
274 | /* Get CPU core temperature */ | ||
275 | sr = sens_cpu_temp[cpu]; | ||
276 | err = sr->ops->get_value(sr, &temp); | ||
277 | if (err) { | ||
278 | DBG("\n"); | ||
279 | printk(KERN_WARNING "windfarm: CPU %d temperature " | ||
280 | "sensor error %d\n", cpu, err); | ||
281 | failure_state |= FAILURE_SENSOR; | ||
282 | cpu_max_all_fans(); | ||
283 | return; | ||
284 | } | ||
285 | |||
286 | /* Keep track of highest temp */ | ||
287 | t_max = max(t_max, temp); | ||
288 | |||
289 | /* Get CPU power */ | ||
290 | sr = sens_cpu_power[cpu]; | ||
291 | err = sr->ops->get_value(sr, &power); | ||
292 | if (err) { | ||
293 | DBG("\n"); | ||
294 | printk(KERN_WARNING "windfarm: CPU %d power " | ||
295 | "sensor error %d\n", cpu, err); | ||
296 | failure_state |= FAILURE_SENSOR; | ||
297 | cpu_max_all_fans(); | ||
298 | return; | ||
299 | } | ||
300 | |||
301 | /* Run PID */ | ||
302 | sp = &cpu_pid[cpu]; | ||
303 | t = wf_cpu_pid_run(sp, power, temp); | ||
304 | |||
305 | if (cpu == 0 || sp->last_delta > greatest_delta) { | ||
306 | greatest_delta = sp->last_delta; | ||
307 | target = t; | ||
308 | } | ||
309 | DBG_LOTS("[%d] P=%d.%.3d T=%d.%.3d ", | ||
310 | cpu, FIX32TOPRINT(power), FIX32TOPRINT(temp)); | ||
311 | } | ||
312 | DBG_LOTS("fans = %d, t_max = %d.%03d\n", target, FIX32TOPRINT(t_max)); | ||
313 | |||
314 | /* Darwin limits decrease to 20 per iteration */ | ||
315 | if (target < (cpu_last_target - 20)) | ||
316 | target = cpu_last_target - 20; | ||
317 | cpu_last_target = target; | ||
318 | for (cpu = 0; cpu < nr_cores; ++cpu) | ||
319 | cpu_pid[cpu].target = target; | ||
320 | |||
321 | /* Handle possible overtemps */ | ||
322 | if (cpu_check_overtemp(t_max)) | ||
323 | return; | ||
324 | |||
325 | /* Set fans */ | ||
326 | for (i = 0; i < NR_CPU_FANS; ++i) { | ||
327 | ct = cpu_fans[i]; | ||
328 | if (ct == NULL) | ||
329 | continue; | ||
330 | err = ct->ops->set_value(ct, target * cpu_fan_scale[i] / 100); | ||
331 | if (err) { | ||
332 | printk(KERN_WARNING "windfarm: fan %s reports " | ||
333 | "error %d\n", ct->name, err); | ||
334 | failure_state |= FAILURE_FAN; | ||
335 | break; | ||
336 | } | ||
337 | } | ||
338 | } | ||
339 | |||
340 | /* Backside/U4 fan */ | ||
341 | static struct wf_pid_param backside_param = { | ||
342 | .interval = 5, | ||
343 | .history_len = 2, | ||
344 | .gd = 48 << 20, | ||
345 | .gp = 5 << 20, | ||
346 | .gr = 0, | ||
347 | .itarget = 64 << 16, | ||
348 | .additive = 1, | ||
349 | }; | ||
350 | |||
351 | static void backside_fan_tick(void) | ||
352 | { | ||
353 | s32 temp; | ||
354 | int speed; | ||
355 | int err; | ||
356 | |||
357 | if (!backside_fan || !u4_temp) | ||
358 | return; | ||
359 | if (!backside_tick) { | ||
360 | /* first time; initialize things */ | ||
361 | backside_param.min = backside_fan->ops->get_min(backside_fan); | ||
362 | backside_param.max = backside_fan->ops->get_max(backside_fan); | ||
363 | wf_pid_init(&backside_pid, &backside_param); | ||
364 | backside_tick = 1; | ||
365 | } | ||
366 | if (--backside_tick > 0) | ||
367 | return; | ||
368 | backside_tick = backside_pid.param.interval; | ||
369 | |||
370 | err = u4_temp->ops->get_value(u4_temp, &temp); | ||
371 | if (err) { | ||
372 | printk(KERN_WARNING "windfarm: U4 temp sensor error %d\n", | ||
373 | err); | ||
374 | failure_state |= FAILURE_SENSOR; | ||
375 | wf_control_set_max(backside_fan); | ||
376 | return; | ||
377 | } | ||
378 | speed = wf_pid_run(&backside_pid, temp); | ||
379 | DBG_LOTS("backside PID temp=%d.%.3d speed=%d\n", | ||
380 | FIX32TOPRINT(temp), speed); | ||
381 | |||
382 | err = backside_fan->ops->set_value(backside_fan, speed); | ||
383 | if (err) { | ||
384 | printk(KERN_WARNING "windfarm: backside fan error %d\n", err); | ||
385 | failure_state |= FAILURE_FAN; | ||
386 | } | ||
387 | } | ||
388 | |||
389 | /* Drive bay fan */ | ||
390 | static struct wf_pid_param drive_bay_prm = { | ||
391 | .interval = 5, | ||
392 | .history_len = 2, | ||
393 | .gd = 30 << 20, | ||
394 | .gp = 5 << 20, | ||
395 | .gr = 0, | ||
396 | .itarget = 40 << 16, | ||
397 | .additive = 1, | ||
398 | }; | ||
399 | |||
400 | static void drive_bay_fan_tick(void) | ||
401 | { | ||
402 | s32 temp; | ||
403 | int speed; | ||
404 | int err; | ||
405 | |||
406 | if (!drive_bay_fan || !hd_temp) | ||
407 | return; | ||
408 | if (!drive_bay_tick) { | ||
409 | /* first time; initialize things */ | ||
410 | drive_bay_prm.min = drive_bay_fan->ops->get_min(drive_bay_fan); | ||
411 | drive_bay_prm.max = drive_bay_fan->ops->get_max(drive_bay_fan); | ||
412 | wf_pid_init(&drive_bay_pid, &drive_bay_prm); | ||
413 | drive_bay_tick = 1; | ||
414 | } | ||
415 | if (--drive_bay_tick > 0) | ||
416 | return; | ||
417 | drive_bay_tick = drive_bay_pid.param.interval; | ||
418 | |||
419 | err = hd_temp->ops->get_value(hd_temp, &temp); | ||
420 | if (err) { | ||
421 | printk(KERN_WARNING "windfarm: drive bay temp sensor " | ||
422 | "error %d\n", err); | ||
423 | failure_state |= FAILURE_SENSOR; | ||
424 | wf_control_set_max(drive_bay_fan); | ||
425 | return; | ||
426 | } | ||
427 | speed = wf_pid_run(&drive_bay_pid, temp); | ||
428 | DBG_LOTS("drive_bay PID temp=%d.%.3d speed=%d\n", | ||
429 | FIX32TOPRINT(temp), speed); | ||
430 | |||
431 | err = drive_bay_fan->ops->set_value(drive_bay_fan, speed); | ||
432 | if (err) { | ||
433 | printk(KERN_WARNING "windfarm: drive bay fan error %d\n", err); | ||
434 | failure_state |= FAILURE_FAN; | ||
435 | } | ||
436 | } | ||
437 | |||
438 | /* PCI slots area fan */ | ||
439 | /* This makes the fan speed proportional to the power consumed */ | ||
440 | static struct wf_pid_param slots_param = { | ||
441 | .interval = 1, | ||
442 | .history_len = 2, | ||
443 | .gd = 0, | ||
444 | .gp = 0, | ||
445 | .gr = 0x1277952, | ||
446 | .itarget = 0, | ||
447 | .min = 1560, | ||
448 | .max = 3510, | ||
449 | }; | ||
450 | |||
451 | static void slots_fan_tick(void) | ||
452 | { | ||
453 | s32 power; | ||
454 | int speed; | ||
455 | int err; | ||
456 | |||
457 | if (!slots_fan || !slots_power) | ||
458 | return; | ||
459 | if (!slots_started) { | ||
460 | /* first time; initialize things */ | ||
461 | wf_pid_init(&slots_pid, &slots_param); | ||
462 | slots_started = 1; | ||
463 | } | ||
464 | |||
465 | err = slots_power->ops->get_value(slots_power, &power); | ||
466 | if (err) { | ||
467 | printk(KERN_WARNING "windfarm: slots power sensor error %d\n", | ||
468 | err); | ||
469 | failure_state |= FAILURE_SENSOR; | ||
470 | wf_control_set_max(slots_fan); | ||
471 | return; | ||
472 | } | ||
473 | speed = wf_pid_run(&slots_pid, power); | ||
474 | DBG_LOTS("slots PID power=%d.%.3d speed=%d\n", | ||
475 | FIX32TOPRINT(power), speed); | ||
476 | |||
477 | err = slots_fan->ops->set_value(slots_fan, speed); | ||
478 | if (err) { | ||
479 | printk(KERN_WARNING "windfarm: slots fan error %d\n", err); | ||
480 | failure_state |= FAILURE_FAN; | ||
481 | } | ||
482 | } | ||
483 | |||
484 | static void set_fail_state(void) | ||
485 | { | ||
486 | int i; | ||
487 | |||
488 | if (cpufreq_clamp) | ||
489 | wf_control_set_max(cpufreq_clamp); | ||
490 | for (i = 0; i < NR_CPU_FANS; ++i) | ||
491 | if (cpu_fans[i]) | ||
492 | wf_control_set_max(cpu_fans[i]); | ||
493 | if (backside_fan) | ||
494 | wf_control_set_max(backside_fan); | ||
495 | if (slots_fan) | ||
496 | wf_control_set_max(slots_fan); | ||
497 | if (drive_bay_fan) | ||
498 | wf_control_set_max(drive_bay_fan); | ||
499 | } | ||
500 | |||
501 | static void pm112_tick(void) | ||
502 | { | ||
503 | int i, last_failure; | ||
504 | |||
505 | if (!started) { | ||
506 | started = 1; | ||
507 | for (i = 0; i < nr_cores; ++i) { | ||
508 | if (create_cpu_loop(i) < 0) { | ||
509 | failure_state = FAILURE_PERM; | ||
510 | set_fail_state(); | ||
511 | break; | ||
512 | } | ||
513 | } | ||
514 | DBG_LOTS("cpu_all_tmax=%d.%03d\n", FIX32TOPRINT(cpu_all_tmax)); | ||
515 | |||
516 | #ifdef HACKED_OVERTEMP | ||
517 | cpu_all_tmax = 60 << 16; | ||
518 | #endif | ||
519 | } | ||
520 | |||
521 | /* Permanent failure, bail out */ | ||
522 | if (failure_state & FAILURE_PERM) | ||
523 | return; | ||
524 | /* Clear all failure bits except low overtemp which will be eventually | ||
525 | * cleared by the control loop itself | ||
526 | */ | ||
527 | last_failure = failure_state; | ||
528 | failure_state &= FAILURE_LOW_OVERTEMP; | ||
529 | cpu_fans_tick(); | ||
530 | backside_fan_tick(); | ||
531 | slots_fan_tick(); | ||
532 | drive_bay_fan_tick(); | ||
533 | |||
534 | DBG_LOTS("last_failure: 0x%x, failure_state: %x\n", | ||
535 | last_failure, failure_state); | ||
536 | |||
537 | /* Check for failures. Any failure causes cpufreq clamping */ | ||
538 | if (failure_state && last_failure == 0 && cpufreq_clamp) | ||
539 | wf_control_set_max(cpufreq_clamp); | ||
540 | if (failure_state == 0 && last_failure && cpufreq_clamp) | ||
541 | wf_control_set_min(cpufreq_clamp); | ||
542 | |||
543 | /* That's it for now, we might want to deal with other failures | ||
544 | * differently in the future though | ||
545 | */ | ||
546 | } | ||
547 | |||
548 | static void pm112_new_control(struct wf_control *ct) | ||
549 | { | ||
550 | int i, max_exhaust; | ||
551 | |||
552 | if (cpufreq_clamp == NULL && !strcmp(ct->name, "cpufreq-clamp")) { | ||
553 | if (wf_get_control(ct) == 0) | ||
554 | cpufreq_clamp = ct; | ||
555 | } | ||
556 | |||
557 | for (i = 0; i < NR_CPU_FANS; ++i) { | ||
558 | if (!strcmp(ct->name, cpu_fan_names[i])) { | ||
559 | if (cpu_fans[i] == NULL && wf_get_control(ct) == 0) | ||
560 | cpu_fans[i] = ct; | ||
561 | break; | ||
562 | } | ||
563 | } | ||
564 | if (i >= NR_CPU_FANS) { | ||
565 | /* not a CPU fan, try the others */ | ||
566 | if (!strcmp(ct->name, "backside-fan")) { | ||
567 | if (backside_fan == NULL && wf_get_control(ct) == 0) | ||
568 | backside_fan = ct; | ||
569 | } else if (!strcmp(ct->name, "slots-fan")) { | ||
570 | if (slots_fan == NULL && wf_get_control(ct) == 0) | ||
571 | slots_fan = ct; | ||
572 | } else if (!strcmp(ct->name, "drive-bay-fan")) { | ||
573 | if (drive_bay_fan == NULL && wf_get_control(ct) == 0) | ||
574 | drive_bay_fan = ct; | ||
575 | } | ||
576 | return; | ||
577 | } | ||
578 | |||
579 | for (i = 0; i < CPU_FANS_REQD; ++i) | ||
580 | if (cpu_fans[i] == NULL) | ||
581 | return; | ||
582 | |||
583 | /* work out pump scaling factors */ | ||
584 | max_exhaust = cpu_fans[0]->ops->get_max(cpu_fans[0]); | ||
585 | for (i = FIRST_PUMP; i <= LAST_PUMP; ++i) | ||
586 | if ((ct = cpu_fans[i]) != NULL) | ||
587 | cpu_fan_scale[i] = | ||
588 | ct->ops->get_max(ct) * 100 / max_exhaust; | ||
589 | |||
590 | have_all_controls = 1; | ||
591 | } | ||
592 | |||
593 | static void pm112_new_sensor(struct wf_sensor *sr) | ||
594 | { | ||
595 | unsigned int i; | ||
596 | |||
597 | if (have_all_sensors) | ||
598 | return; | ||
599 | if (!strncmp(sr->name, "cpu-temp-", 9)) { | ||
600 | i = sr->name[9] - '0'; | ||
601 | if (sr->name[10] == 0 && i < NR_CORES && | ||
602 | sens_cpu_temp[i] == NULL && wf_get_sensor(sr) == 0) | ||
603 | sens_cpu_temp[i] = sr; | ||
604 | |||
605 | } else if (!strncmp(sr->name, "cpu-power-", 10)) { | ||
606 | i = sr->name[10] - '0'; | ||
607 | if (sr->name[11] == 0 && i < NR_CORES && | ||
608 | sens_cpu_power[i] == NULL && wf_get_sensor(sr) == 0) | ||
609 | sens_cpu_power[i] = sr; | ||
610 | } else if (!strcmp(sr->name, "hd-temp")) { | ||
611 | if (hd_temp == NULL && wf_get_sensor(sr) == 0) | ||
612 | hd_temp = sr; | ||
613 | } else if (!strcmp(sr->name, "slots-power")) { | ||
614 | if (slots_power == NULL && wf_get_sensor(sr) == 0) | ||
615 | slots_power = sr; | ||
616 | } else if (!strcmp(sr->name, "u4-temp")) { | ||
617 | if (u4_temp == NULL && wf_get_sensor(sr) == 0) | ||
618 | u4_temp = sr; | ||
619 | } else | ||
620 | return; | ||
621 | |||
622 | /* check if we have all the sensors we need */ | ||
623 | for (i = 0; i < nr_cores; ++i) | ||
624 | if (sens_cpu_temp[i] == NULL || sens_cpu_power[i] == NULL) | ||
625 | return; | ||
626 | |||
627 | have_all_sensors = 1; | ||
628 | } | ||
629 | |||
630 | static int pm112_wf_notify(struct notifier_block *self, | ||
631 | unsigned long event, void *data) | ||
632 | { | ||
633 | switch (event) { | ||
634 | case WF_EVENT_NEW_SENSOR: | ||
635 | pm112_new_sensor(data); | ||
636 | break; | ||
637 | case WF_EVENT_NEW_CONTROL: | ||
638 | pm112_new_control(data); | ||
639 | break; | ||
640 | case WF_EVENT_TICK: | ||
641 | if (have_all_controls && have_all_sensors) | ||
642 | pm112_tick(); | ||
643 | } | ||
644 | return 0; | ||
645 | } | ||
646 | |||
647 | static struct notifier_block pm112_events = { | ||
648 | .notifier_call = pm112_wf_notify, | ||
649 | }; | ||
650 | |||
651 | static int wf_pm112_probe(struct device *dev) | ||
652 | { | ||
653 | wf_register_client(&pm112_events); | ||
654 | return 0; | ||
655 | } | ||
656 | |||
657 | static int wf_pm112_remove(struct device *dev) | ||
658 | { | ||
659 | wf_unregister_client(&pm112_events); | ||
660 | /* should release all sensors and controls */ | ||
661 | return 0; | ||
662 | } | ||
663 | |||
664 | static struct device_driver wf_pm112_driver = { | ||
665 | .name = "windfarm", | ||
666 | .bus = &platform_bus_type, | ||
667 | .probe = wf_pm112_probe, | ||
668 | .remove = wf_pm112_remove, | ||
669 | }; | ||
670 | |||
671 | static int __init wf_pm112_init(void) | ||
672 | { | ||
673 | struct device_node *cpu; | ||
674 | |||
675 | if (!machine_is_compatible("PowerMac11,2")) | ||
676 | return -ENODEV; | ||
677 | |||
678 | /* Count the number of CPU cores */ | ||
679 | nr_cores = 0; | ||
680 | for (cpu = NULL; (cpu = of_find_node_by_type(cpu, "cpu")) != NULL; ) | ||
681 | ++nr_cores; | ||
682 | |||
683 | printk(KERN_INFO "windfarm: initializing for dual-core desktop G5\n"); | ||
684 | driver_register(&wf_pm112_driver); | ||
685 | return 0; | ||
686 | } | ||
687 | |||
688 | static void __exit wf_pm112_exit(void) | ||
689 | { | ||
690 | driver_unregister(&wf_pm112_driver); | ||
691 | } | ||
692 | |||
693 | module_init(wf_pm112_init); | ||
694 | module_exit(wf_pm112_exit); | ||
695 | |||
696 | MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>"); | ||
697 | MODULE_DESCRIPTION("Thermal control for PowerMac11,2"); | ||
698 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/macintosh/windfarm_pm81.c b/drivers/macintosh/windfarm_pm81.c index eb69a601e765..f1df6efcbe68 100644 --- a/drivers/macintosh/windfarm_pm81.c +++ b/drivers/macintosh/windfarm_pm81.c | |||
@@ -538,45 +538,6 @@ static void wf_smu_cpu_fans_tick(struct wf_smu_cpu_fans_state *st) | |||
538 | } | 538 | } |
539 | } | 539 | } |
540 | 540 | ||
541 | |||
542 | /* | ||
543 | * ****** Attributes ****** | ||
544 | * | ||
545 | */ | ||
546 | |||
547 | #define BUILD_SHOW_FUNC_FIX(name, data) \ | ||
548 | static ssize_t show_##name(struct device *dev, \ | ||
549 | struct device_attribute *attr, \ | ||
550 | char *buf) \ | ||
551 | { \ | ||
552 | ssize_t r; \ | ||
553 | s32 val = 0; \ | ||
554 | data->ops->get_value(data, &val); \ | ||
555 | r = sprintf(buf, "%d.%03d", FIX32TOPRINT(val)); \ | ||
556 | return r; \ | ||
557 | } \ | ||
558 | static DEVICE_ATTR(name,S_IRUGO,show_##name, NULL); | ||
559 | |||
560 | |||
561 | #define BUILD_SHOW_FUNC_INT(name, data) \ | ||
562 | static ssize_t show_##name(struct device *dev, \ | ||
563 | struct device_attribute *attr, \ | ||
564 | char *buf) \ | ||
565 | { \ | ||
566 | s32 val = 0; \ | ||
567 | data->ops->get_value(data, &val); \ | ||
568 | return sprintf(buf, "%d", val); \ | ||
569 | } \ | ||
570 | static DEVICE_ATTR(name,S_IRUGO,show_##name, NULL); | ||
571 | |||
572 | BUILD_SHOW_FUNC_INT(cpu_fan, fan_cpu_main); | ||
573 | BUILD_SHOW_FUNC_INT(sys_fan, fan_system); | ||
574 | BUILD_SHOW_FUNC_INT(hd_fan, fan_hd); | ||
575 | |||
576 | BUILD_SHOW_FUNC_FIX(cpu_temp, sensor_cpu_temp); | ||
577 | BUILD_SHOW_FUNC_FIX(cpu_power, sensor_cpu_power); | ||
578 | BUILD_SHOW_FUNC_FIX(hd_temp, sensor_hd_temp); | ||
579 | |||
580 | /* | 541 | /* |
581 | * ****** Setup / Init / Misc ... ****** | 542 | * ****** Setup / Init / Misc ... ****** |
582 | * | 543 | * |
@@ -654,17 +615,13 @@ static void wf_smu_new_control(struct wf_control *ct) | |||
654 | return; | 615 | return; |
655 | 616 | ||
656 | if (fan_cpu_main == NULL && !strcmp(ct->name, "cpu-fan")) { | 617 | if (fan_cpu_main == NULL && !strcmp(ct->name, "cpu-fan")) { |
657 | if (wf_get_control(ct) == 0) { | 618 | if (wf_get_control(ct) == 0) |
658 | fan_cpu_main = ct; | 619 | fan_cpu_main = ct; |
659 | device_create_file(wf_smu_dev, &dev_attr_cpu_fan); | ||
660 | } | ||
661 | } | 620 | } |
662 | 621 | ||
663 | if (fan_system == NULL && !strcmp(ct->name, "system-fan")) { | 622 | if (fan_system == NULL && !strcmp(ct->name, "system-fan")) { |
664 | if (wf_get_control(ct) == 0) { | 623 | if (wf_get_control(ct) == 0) |
665 | fan_system = ct; | 624 | fan_system = ct; |
666 | device_create_file(wf_smu_dev, &dev_attr_sys_fan); | ||
667 | } | ||
668 | } | 625 | } |
669 | 626 | ||
670 | if (cpufreq_clamp == NULL && !strcmp(ct->name, "cpufreq-clamp")) { | 627 | if (cpufreq_clamp == NULL && !strcmp(ct->name, "cpufreq-clamp")) { |
@@ -683,10 +640,8 @@ static void wf_smu_new_control(struct wf_control *ct) | |||
683 | } | 640 | } |
684 | 641 | ||
685 | if (fan_hd == NULL && !strcmp(ct->name, "drive-bay-fan")) { | 642 | if (fan_hd == NULL && !strcmp(ct->name, "drive-bay-fan")) { |
686 | if (wf_get_control(ct) == 0) { | 643 | if (wf_get_control(ct) == 0) |
687 | fan_hd = ct; | 644 | fan_hd = ct; |
688 | device_create_file(wf_smu_dev, &dev_attr_hd_fan); | ||
689 | } | ||
690 | } | 645 | } |
691 | 646 | ||
692 | if (fan_system && fan_hd && fan_cpu_main && cpufreq_clamp) | 647 | if (fan_system && fan_hd && fan_cpu_main && cpufreq_clamp) |
@@ -699,24 +654,18 @@ static void wf_smu_new_sensor(struct wf_sensor *sr) | |||
699 | return; | 654 | return; |
700 | 655 | ||
701 | if (sensor_cpu_power == NULL && !strcmp(sr->name, "cpu-power")) { | 656 | if (sensor_cpu_power == NULL && !strcmp(sr->name, "cpu-power")) { |
702 | if (wf_get_sensor(sr) == 0) { | 657 | if (wf_get_sensor(sr) == 0) |
703 | sensor_cpu_power = sr; | 658 | sensor_cpu_power = sr; |
704 | device_create_file(wf_smu_dev, &dev_attr_cpu_power); | ||
705 | } | ||
706 | } | 659 | } |
707 | 660 | ||
708 | if (sensor_cpu_temp == NULL && !strcmp(sr->name, "cpu-temp")) { | 661 | if (sensor_cpu_temp == NULL && !strcmp(sr->name, "cpu-temp")) { |
709 | if (wf_get_sensor(sr) == 0) { | 662 | if (wf_get_sensor(sr) == 0) |
710 | sensor_cpu_temp = sr; | 663 | sensor_cpu_temp = sr; |
711 | device_create_file(wf_smu_dev, &dev_attr_cpu_temp); | ||
712 | } | ||
713 | } | 664 | } |
714 | 665 | ||
715 | if (sensor_hd_temp == NULL && !strcmp(sr->name, "hd-temp")) { | 666 | if (sensor_hd_temp == NULL && !strcmp(sr->name, "hd-temp")) { |
716 | if (wf_get_sensor(sr) == 0) { | 667 | if (wf_get_sensor(sr) == 0) |
717 | sensor_hd_temp = sr; | 668 | sensor_hd_temp = sr; |
718 | device_create_file(wf_smu_dev, &dev_attr_hd_temp); | ||
719 | } | ||
720 | } | 669 | } |
721 | 670 | ||
722 | if (sensor_cpu_power && sensor_cpu_temp && sensor_hd_temp) | 671 | if (sensor_cpu_power && sensor_cpu_temp && sensor_hd_temp) |
@@ -794,32 +743,20 @@ static int wf_smu_remove(struct device *ddev) | |||
794 | * with that except by adding locks all over... I'll do that | 743 | * with that except by adding locks all over... I'll do that |
795 | * eventually but heh, who ever rmmod this module anyway ? | 744 | * eventually but heh, who ever rmmod this module anyway ? |
796 | */ | 745 | */ |
797 | if (sensor_cpu_power) { | 746 | if (sensor_cpu_power) |
798 | device_remove_file(wf_smu_dev, &dev_attr_cpu_power); | ||
799 | wf_put_sensor(sensor_cpu_power); | 747 | wf_put_sensor(sensor_cpu_power); |
800 | } | 748 | if (sensor_cpu_temp) |
801 | if (sensor_cpu_temp) { | ||
802 | device_remove_file(wf_smu_dev, &dev_attr_cpu_temp); | ||
803 | wf_put_sensor(sensor_cpu_temp); | 749 | wf_put_sensor(sensor_cpu_temp); |
804 | } | 750 | if (sensor_hd_temp) |
805 | if (sensor_hd_temp) { | ||
806 | device_remove_file(wf_smu_dev, &dev_attr_hd_temp); | ||
807 | wf_put_sensor(sensor_hd_temp); | 751 | wf_put_sensor(sensor_hd_temp); |
808 | } | ||
809 | 752 | ||
810 | /* Release all controls */ | 753 | /* Release all controls */ |
811 | if (fan_cpu_main) { | 754 | if (fan_cpu_main) |
812 | device_remove_file(wf_smu_dev, &dev_attr_cpu_fan); | ||
813 | wf_put_control(fan_cpu_main); | 755 | wf_put_control(fan_cpu_main); |
814 | } | 756 | if (fan_hd) |
815 | if (fan_hd) { | ||
816 | device_remove_file(wf_smu_dev, &dev_attr_hd_fan); | ||
817 | wf_put_control(fan_hd); | 757 | wf_put_control(fan_hd); |
818 | } | 758 | if (fan_system) |
819 | if (fan_system) { | ||
820 | device_remove_file(wf_smu_dev, &dev_attr_sys_fan); | ||
821 | wf_put_control(fan_system); | 759 | wf_put_control(fan_system); |
822 | } | ||
823 | if (cpufreq_clamp) | 760 | if (cpufreq_clamp) |
824 | wf_put_control(cpufreq_clamp); | 761 | wf_put_control(cpufreq_clamp); |
825 | 762 | ||
diff --git a/drivers/macintosh/windfarm_pm91.c b/drivers/macintosh/windfarm_pm91.c index 43243cf7410b..0d6372e96d32 100644 --- a/drivers/macintosh/windfarm_pm91.c +++ b/drivers/macintosh/windfarm_pm91.c | |||
@@ -458,45 +458,6 @@ static void wf_smu_slots_fans_tick(struct wf_smu_slots_fans_state *st) | |||
458 | 458 | ||
459 | 459 | ||
460 | /* | 460 | /* |
461 | * ****** Attributes ****** | ||
462 | * | ||
463 | */ | ||
464 | |||
465 | #define BUILD_SHOW_FUNC_FIX(name, data) \ | ||
466 | static ssize_t show_##name(struct device *dev, \ | ||
467 | struct device_attribute *attr, \ | ||
468 | char *buf) \ | ||
469 | { \ | ||
470 | ssize_t r; \ | ||
471 | s32 val = 0; \ | ||
472 | data->ops->get_value(data, &val); \ | ||
473 | r = sprintf(buf, "%d.%03d", FIX32TOPRINT(val)); \ | ||
474 | return r; \ | ||
475 | } \ | ||
476 | static DEVICE_ATTR(name,S_IRUGO,show_##name, NULL); | ||
477 | |||
478 | |||
479 | #define BUILD_SHOW_FUNC_INT(name, data) \ | ||
480 | static ssize_t show_##name(struct device *dev, \ | ||
481 | struct device_attribute *attr, \ | ||
482 | char *buf) \ | ||
483 | { \ | ||
484 | s32 val = 0; \ | ||
485 | data->ops->get_value(data, &val); \ | ||
486 | return sprintf(buf, "%d", val); \ | ||
487 | } \ | ||
488 | static DEVICE_ATTR(name,S_IRUGO,show_##name, NULL); | ||
489 | |||
490 | BUILD_SHOW_FUNC_INT(cpu_fan, fan_cpu_main); | ||
491 | BUILD_SHOW_FUNC_INT(hd_fan, fan_hd); | ||
492 | BUILD_SHOW_FUNC_INT(slots_fan, fan_slots); | ||
493 | |||
494 | BUILD_SHOW_FUNC_FIX(cpu_temp, sensor_cpu_temp); | ||
495 | BUILD_SHOW_FUNC_FIX(cpu_power, sensor_cpu_power); | ||
496 | BUILD_SHOW_FUNC_FIX(hd_temp, sensor_hd_temp); | ||
497 | BUILD_SHOW_FUNC_FIX(slots_power, sensor_slots_power); | ||
498 | |||
499 | /* | ||
500 | * ****** Setup / Init / Misc ... ****** | 461 | * ****** Setup / Init / Misc ... ****** |
501 | * | 462 | * |
502 | */ | 463 | */ |
@@ -581,10 +542,8 @@ static void wf_smu_new_control(struct wf_control *ct) | |||
581 | return; | 542 | return; |
582 | 543 | ||
583 | if (fan_cpu_main == NULL && !strcmp(ct->name, "cpu-rear-fan-0")) { | 544 | if (fan_cpu_main == NULL && !strcmp(ct->name, "cpu-rear-fan-0")) { |
584 | if (wf_get_control(ct) == 0) { | 545 | if (wf_get_control(ct) == 0) |
585 | fan_cpu_main = ct; | 546 | fan_cpu_main = ct; |
586 | device_create_file(wf_smu_dev, &dev_attr_cpu_fan); | ||
587 | } | ||
588 | } | 547 | } |
589 | 548 | ||
590 | if (fan_cpu_second == NULL && !strcmp(ct->name, "cpu-rear-fan-1")) { | 549 | if (fan_cpu_second == NULL && !strcmp(ct->name, "cpu-rear-fan-1")) { |
@@ -603,17 +562,13 @@ static void wf_smu_new_control(struct wf_control *ct) | |||
603 | } | 562 | } |
604 | 563 | ||
605 | if (fan_hd == NULL && !strcmp(ct->name, "drive-bay-fan")) { | 564 | if (fan_hd == NULL && !strcmp(ct->name, "drive-bay-fan")) { |
606 | if (wf_get_control(ct) == 0) { | 565 | if (wf_get_control(ct) == 0) |
607 | fan_hd = ct; | 566 | fan_hd = ct; |
608 | device_create_file(wf_smu_dev, &dev_attr_hd_fan); | ||
609 | } | ||
610 | } | 567 | } |
611 | 568 | ||
612 | if (fan_slots == NULL && !strcmp(ct->name, "slots-fan")) { | 569 | if (fan_slots == NULL && !strcmp(ct->name, "slots-fan")) { |
613 | if (wf_get_control(ct) == 0) { | 570 | if (wf_get_control(ct) == 0) |
614 | fan_slots = ct; | 571 | fan_slots = ct; |
615 | device_create_file(wf_smu_dev, &dev_attr_slots_fan); | ||
616 | } | ||
617 | } | 572 | } |
618 | 573 | ||
619 | if (fan_cpu_main && (fan_cpu_second || fan_cpu_third) && fan_hd && | 574 | if (fan_cpu_main && (fan_cpu_second || fan_cpu_third) && fan_hd && |
@@ -627,31 +582,23 @@ static void wf_smu_new_sensor(struct wf_sensor *sr) | |||
627 | return; | 582 | return; |
628 | 583 | ||
629 | if (sensor_cpu_power == NULL && !strcmp(sr->name, "cpu-power")) { | 584 | if (sensor_cpu_power == NULL && !strcmp(sr->name, "cpu-power")) { |
630 | if (wf_get_sensor(sr) == 0) { | 585 | if (wf_get_sensor(sr) == 0) |
631 | sensor_cpu_power = sr; | 586 | sensor_cpu_power = sr; |
632 | device_create_file(wf_smu_dev, &dev_attr_cpu_power); | ||
633 | } | ||
634 | } | 587 | } |
635 | 588 | ||
636 | if (sensor_cpu_temp == NULL && !strcmp(sr->name, "cpu-temp")) { | 589 | if (sensor_cpu_temp == NULL && !strcmp(sr->name, "cpu-temp")) { |
637 | if (wf_get_sensor(sr) == 0) { | 590 | if (wf_get_sensor(sr) == 0) |
638 | sensor_cpu_temp = sr; | 591 | sensor_cpu_temp = sr; |
639 | device_create_file(wf_smu_dev, &dev_attr_cpu_temp); | ||
640 | } | ||
641 | } | 592 | } |
642 | 593 | ||
643 | if (sensor_hd_temp == NULL && !strcmp(sr->name, "hd-temp")) { | 594 | if (sensor_hd_temp == NULL && !strcmp(sr->name, "hd-temp")) { |
644 | if (wf_get_sensor(sr) == 0) { | 595 | if (wf_get_sensor(sr) == 0) |
645 | sensor_hd_temp = sr; | 596 | sensor_hd_temp = sr; |
646 | device_create_file(wf_smu_dev, &dev_attr_hd_temp); | ||
647 | } | ||
648 | } | 597 | } |
649 | 598 | ||
650 | if (sensor_slots_power == NULL && !strcmp(sr->name, "slots-power")) { | 599 | if (sensor_slots_power == NULL && !strcmp(sr->name, "slots-power")) { |
651 | if (wf_get_sensor(sr) == 0) { | 600 | if (wf_get_sensor(sr) == 0) |
652 | sensor_slots_power = sr; | 601 | sensor_slots_power = sr; |
653 | device_create_file(wf_smu_dev, &dev_attr_slots_power); | ||
654 | } | ||
655 | } | 602 | } |
656 | 603 | ||
657 | if (sensor_cpu_power && sensor_cpu_temp && | 604 | if (sensor_cpu_power && sensor_cpu_temp && |
@@ -720,40 +667,26 @@ static int wf_smu_remove(struct device *ddev) | |||
720 | * with that except by adding locks all over... I'll do that | 667 | * with that except by adding locks all over... I'll do that |
721 | * eventually but heh, who ever rmmod this module anyway ? | 668 | * eventually but heh, who ever rmmod this module anyway ? |
722 | */ | 669 | */ |
723 | if (sensor_cpu_power) { | 670 | if (sensor_cpu_power) |
724 | device_remove_file(wf_smu_dev, &dev_attr_cpu_power); | ||
725 | wf_put_sensor(sensor_cpu_power); | 671 | wf_put_sensor(sensor_cpu_power); |
726 | } | 672 | if (sensor_cpu_temp) |
727 | if (sensor_cpu_temp) { | ||
728 | device_remove_file(wf_smu_dev, &dev_attr_cpu_temp); | ||
729 | wf_put_sensor(sensor_cpu_temp); | 673 | wf_put_sensor(sensor_cpu_temp); |
730 | } | 674 | if (sensor_hd_temp) |
731 | if (sensor_hd_temp) { | ||
732 | device_remove_file(wf_smu_dev, &dev_attr_hd_temp); | ||
733 | wf_put_sensor(sensor_hd_temp); | 675 | wf_put_sensor(sensor_hd_temp); |
734 | } | 676 | if (sensor_slots_power) |
735 | if (sensor_slots_power) { | ||
736 | device_remove_file(wf_smu_dev, &dev_attr_slots_power); | ||
737 | wf_put_sensor(sensor_slots_power); | 677 | wf_put_sensor(sensor_slots_power); |
738 | } | ||
739 | 678 | ||
740 | /* Release all controls */ | 679 | /* Release all controls */ |
741 | if (fan_cpu_main) { | 680 | if (fan_cpu_main) |
742 | device_remove_file(wf_smu_dev, &dev_attr_cpu_fan); | ||
743 | wf_put_control(fan_cpu_main); | 681 | wf_put_control(fan_cpu_main); |
744 | } | ||
745 | if (fan_cpu_second) | 682 | if (fan_cpu_second) |
746 | wf_put_control(fan_cpu_second); | 683 | wf_put_control(fan_cpu_second); |
747 | if (fan_cpu_third) | 684 | if (fan_cpu_third) |
748 | wf_put_control(fan_cpu_third); | 685 | wf_put_control(fan_cpu_third); |
749 | if (fan_hd) { | 686 | if (fan_hd) |
750 | device_remove_file(wf_smu_dev, &dev_attr_hd_fan); | ||
751 | wf_put_control(fan_hd); | 687 | wf_put_control(fan_hd); |
752 | } | 688 | if (fan_slots) |
753 | if (fan_slots) { | ||
754 | device_remove_file(wf_smu_dev, &dev_attr_slots_fan); | ||
755 | wf_put_control(fan_slots); | 689 | wf_put_control(fan_slots); |
756 | } | ||
757 | if (cpufreq_clamp) | 690 | if (cpufreq_clamp) |
758 | wf_put_control(cpufreq_clamp); | 691 | wf_put_control(cpufreq_clamp); |
759 | 692 | ||
diff --git a/drivers/macintosh/windfarm_smu_controls.c b/drivers/macintosh/windfarm_smu_controls.c index 4d811600bdab..a9e88edc0c72 100644 --- a/drivers/macintosh/windfarm_smu_controls.c +++ b/drivers/macintosh/windfarm_smu_controls.c | |||
@@ -24,7 +24,7 @@ | |||
24 | 24 | ||
25 | #include "windfarm.h" | 25 | #include "windfarm.h" |
26 | 26 | ||
27 | #define VERSION "0.3" | 27 | #define VERSION "0.4" |
28 | 28 | ||
29 | #undef DEBUG | 29 | #undef DEBUG |
30 | 30 | ||
@@ -34,6 +34,8 @@ | |||
34 | #define DBG(args...) do { } while(0) | 34 | #define DBG(args...) do { } while(0) |
35 | #endif | 35 | #endif |
36 | 36 | ||
37 | static int smu_supports_new_fans_ops = 1; | ||
38 | |||
37 | /* | 39 | /* |
38 | * SMU fans control object | 40 | * SMU fans control object |
39 | */ | 41 | */ |
@@ -59,23 +61,49 @@ static int smu_set_fan(int pwm, u8 id, u16 value) | |||
59 | 61 | ||
60 | /* Fill SMU command structure */ | 62 | /* Fill SMU command structure */ |
61 | cmd.cmd = SMU_CMD_FAN_COMMAND; | 63 | cmd.cmd = SMU_CMD_FAN_COMMAND; |
62 | cmd.data_len = 14; | 64 | |
65 | /* The SMU has an "old" and a "new" way of setting the fan speed | ||
66 | * Unfortunately, I found no reliable way to know which one works | ||
67 | * on a given machine model. After some investigations it appears | ||
68 | * that MacOS X just tries the new one, and if it fails fallbacks | ||
69 | * to the old ones ... Ugh. | ||
70 | */ | ||
71 | retry: | ||
72 | if (smu_supports_new_fans_ops) { | ||
73 | buffer[0] = 0x30; | ||
74 | buffer[1] = id; | ||
75 | *((u16 *)(&buffer[2])) = value; | ||
76 | cmd.data_len = 4; | ||
77 | } else { | ||
78 | if (id > 7) | ||
79 | return -EINVAL; | ||
80 | /* Fill argument buffer */ | ||
81 | memset(buffer, 0, 16); | ||
82 | buffer[0] = pwm ? 0x10 : 0x00; | ||
83 | buffer[1] = 0x01 << id; | ||
84 | *((u16 *)&buffer[2 + id * 2]) = value; | ||
85 | cmd.data_len = 14; | ||
86 | } | ||
87 | |||
63 | cmd.reply_len = 16; | 88 | cmd.reply_len = 16; |
64 | cmd.data_buf = cmd.reply_buf = buffer; | 89 | cmd.data_buf = cmd.reply_buf = buffer; |
65 | cmd.status = 0; | 90 | cmd.status = 0; |
66 | cmd.done = smu_done_complete; | 91 | cmd.done = smu_done_complete; |
67 | cmd.misc = ∁ | 92 | cmd.misc = ∁ |
68 | 93 | ||
69 | /* Fill argument buffer */ | ||
70 | memset(buffer, 0, 16); | ||
71 | buffer[0] = pwm ? 0x10 : 0x00; | ||
72 | buffer[1] = 0x01 << id; | ||
73 | *((u16 *)&buffer[2 + id * 2]) = value; | ||
74 | |||
75 | rc = smu_queue_cmd(&cmd); | 94 | rc = smu_queue_cmd(&cmd); |
76 | if (rc) | 95 | if (rc) |
77 | return rc; | 96 | return rc; |
78 | wait_for_completion(&comp); | 97 | wait_for_completion(&comp); |
98 | |||
99 | /* Handle fallback (see coment above) */ | ||
100 | if (cmd.status != 0 && smu_supports_new_fans_ops) { | ||
101 | printk(KERN_WARNING "windfarm: SMU failed new fan command " | ||
102 | "falling back to old method\n"); | ||
103 | smu_supports_new_fans_ops = 0; | ||
104 | goto retry; | ||
105 | } | ||
106 | |||
79 | return cmd.status; | 107 | return cmd.status; |
80 | } | 108 | } |
81 | 109 | ||
@@ -158,19 +186,29 @@ static struct smu_fan_control *smu_fan_create(struct device_node *node, | |||
158 | 186 | ||
159 | /* Names used on desktop models */ | 187 | /* Names used on desktop models */ |
160 | if (!strcmp(l, "Rear Fan 0") || !strcmp(l, "Rear Fan") || | 188 | if (!strcmp(l, "Rear Fan 0") || !strcmp(l, "Rear Fan") || |
161 | !strcmp(l, "Rear fan 0") || !strcmp(l, "Rear fan")) | 189 | !strcmp(l, "Rear fan 0") || !strcmp(l, "Rear fan") || |
190 | !strcmp(l, "CPU A EXHAUST")) | ||
162 | fct->ctrl.name = "cpu-rear-fan-0"; | 191 | fct->ctrl.name = "cpu-rear-fan-0"; |
163 | else if (!strcmp(l, "Rear Fan 1") || !strcmp(l, "Rear fan 1")) | 192 | else if (!strcmp(l, "Rear Fan 1") || !strcmp(l, "Rear fan 1") || |
193 | !strcmp(l, "CPU B EXHAUST")) | ||
164 | fct->ctrl.name = "cpu-rear-fan-1"; | 194 | fct->ctrl.name = "cpu-rear-fan-1"; |
165 | else if (!strcmp(l, "Front Fan 0") || !strcmp(l, "Front Fan") || | 195 | else if (!strcmp(l, "Front Fan 0") || !strcmp(l, "Front Fan") || |
166 | !strcmp(l, "Front fan 0") || !strcmp(l, "Front fan")) | 196 | !strcmp(l, "Front fan 0") || !strcmp(l, "Front fan") || |
197 | !strcmp(l, "CPU A INTAKE")) | ||
167 | fct->ctrl.name = "cpu-front-fan-0"; | 198 | fct->ctrl.name = "cpu-front-fan-0"; |
168 | else if (!strcmp(l, "Front Fan 1") || !strcmp(l, "Front fan 1")) | 199 | else if (!strcmp(l, "Front Fan 1") || !strcmp(l, "Front fan 1") || |
200 | !strcmp(l, "CPU B INTAKE")) | ||
169 | fct->ctrl.name = "cpu-front-fan-1"; | 201 | fct->ctrl.name = "cpu-front-fan-1"; |
170 | else if (!strcmp(l, "Slots Fan") || !strcmp(l, "Slots fan")) | 202 | else if (!strcmp(l, "CPU A PUMP")) |
203 | fct->ctrl.name = "cpu-pump-0"; | ||
204 | else if (!strcmp(l, "Slots Fan") || !strcmp(l, "Slots fan") || | ||
205 | !strcmp(l, "EXPANSION SLOTS INTAKE")) | ||
171 | fct->ctrl.name = "slots-fan"; | 206 | fct->ctrl.name = "slots-fan"; |
172 | else if (!strcmp(l, "Drive Bay") || !strcmp(l, "Drive bay")) | 207 | else if (!strcmp(l, "Drive Bay") || !strcmp(l, "Drive bay") || |
208 | !strcmp(l, "DRIVE BAY A INTAKE")) | ||
173 | fct->ctrl.name = "drive-bay-fan"; | 209 | fct->ctrl.name = "drive-bay-fan"; |
210 | else if (!strcmp(l, "BACKSIDE")) | ||
211 | fct->ctrl.name = "backside-fan"; | ||
174 | 212 | ||
175 | /* Names used on iMac models */ | 213 | /* Names used on iMac models */ |
176 | if (!strcmp(l, "System Fan") || !strcmp(l, "System fan")) | 214 | if (!strcmp(l, "System Fan") || !strcmp(l, "System fan")) |
@@ -223,7 +261,8 @@ static int __init smu_controls_init(void) | |||
223 | 261 | ||
224 | /* Look for RPM fans */ | 262 | /* Look for RPM fans */ |
225 | for (fans = NULL; (fans = of_get_next_child(smu, fans)) != NULL;) | 263 | for (fans = NULL; (fans = of_get_next_child(smu, fans)) != NULL;) |
226 | if (!strcmp(fans->name, "rpm-fans")) | 264 | if (!strcmp(fans->name, "rpm-fans") || |
265 | device_is_compatible(fans, "smu-rpm-fans")) | ||
227 | break; | 266 | break; |
228 | for (fan = NULL; | 267 | for (fan = NULL; |
229 | fans && (fan = of_get_next_child(fans, fan)) != NULL;) { | 268 | fans && (fan = of_get_next_child(fans, fan)) != NULL;) { |
diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c new file mode 100644 index 000000000000..3a32c59494f2 --- /dev/null +++ b/drivers/macintosh/windfarm_smu_sat.c | |||
@@ -0,0 +1,418 @@ | |||
1 | /* | ||
2 | * Windfarm PowerMac thermal control. SMU "satellite" controller sensors. | ||
3 | * | ||
4 | * Copyright (C) 2005 Paul Mackerras, IBM Corp. <paulus@samba.org> | ||
5 | * | ||
6 | * Released under the terms of the GNU GPL v2. | ||
7 | */ | ||
8 | |||
9 | #include <linux/types.h> | ||
10 | #include <linux/errno.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/wait.h> | ||
15 | #include <linux/i2c.h> | ||
16 | #include <linux/i2c-dev.h> | ||
17 | #include <asm/semaphore.h> | ||
18 | #include <asm/prom.h> | ||
19 | #include <asm/smu.h> | ||
20 | #include <asm/pmac_low_i2c.h> | ||
21 | |||
22 | #include "windfarm.h" | ||
23 | |||
24 | #define VERSION "0.2" | ||
25 | |||
26 | #define DEBUG | ||
27 | |||
28 | #ifdef DEBUG | ||
29 | #define DBG(args...) printk(args) | ||
30 | #else | ||
31 | #define DBG(args...) do { } while(0) | ||
32 | #endif | ||
33 | |||
34 | /* If the cache is older than 800ms we'll refetch it */ | ||
35 | #define MAX_AGE msecs_to_jiffies(800) | ||
36 | |||
37 | struct wf_sat { | ||
38 | int nr; | ||
39 | atomic_t refcnt; | ||
40 | struct semaphore mutex; | ||
41 | unsigned long last_read; /* jiffies when cache last updated */ | ||
42 | u8 cache[16]; | ||
43 | struct i2c_client i2c; | ||
44 | struct device_node *node; | ||
45 | }; | ||
46 | |||
47 | static struct wf_sat *sats[2]; | ||
48 | |||
49 | struct wf_sat_sensor { | ||
50 | int index; | ||
51 | int index2; /* used for power sensors */ | ||
52 | int shift; | ||
53 | struct wf_sat *sat; | ||
54 | struct wf_sensor sens; | ||
55 | }; | ||
56 | |||
57 | #define wf_to_sat(c) container_of(c, struct wf_sat_sensor, sens) | ||
58 | #define i2c_to_sat(c) container_of(c, struct wf_sat, i2c) | ||
59 | |||
60 | static int wf_sat_attach(struct i2c_adapter *adapter); | ||
61 | static int wf_sat_detach(struct i2c_client *client); | ||
62 | |||
63 | static struct i2c_driver wf_sat_driver = { | ||
64 | .driver = { | ||
65 | .name = "wf_smu_sat", | ||
66 | }, | ||
67 | .attach_adapter = wf_sat_attach, | ||
68 | .detach_client = wf_sat_detach, | ||
69 | }; | ||
70 | |||
71 | /* | ||
72 | * XXX i2c_smbus_read_i2c_block_data doesn't pass the requested | ||
73 | * length down to the low-level driver, so we use this, which | ||
74 | * works well enough with the SMU i2c driver code... | ||
75 | */ | ||
76 | static int sat_read_block(struct i2c_client *client, u8 command, | ||
77 | u8 *values, int len) | ||
78 | { | ||
79 | union i2c_smbus_data data; | ||
80 | int err; | ||
81 | |||
82 | data.block[0] = len; | ||
83 | err = i2c_smbus_xfer(client->adapter, client->addr, client->flags, | ||
84 | I2C_SMBUS_READ, command, I2C_SMBUS_I2C_BLOCK_DATA, | ||
85 | &data); | ||
86 | if (!err) | ||
87 | memcpy(values, data.block, len); | ||
88 | return err; | ||
89 | } | ||
90 | |||
91 | struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id, | ||
92 | unsigned int *size) | ||
93 | { | ||
94 | struct wf_sat *sat; | ||
95 | int err; | ||
96 | unsigned int i, len; | ||
97 | u8 *buf; | ||
98 | u8 data[4]; | ||
99 | |||
100 | /* TODO: Add the resulting partition to the device-tree */ | ||
101 | |||
102 | if (sat_id > 1 || (sat = sats[sat_id]) == NULL) | ||
103 | return NULL; | ||
104 | |||
105 | err = i2c_smbus_write_word_data(&sat->i2c, 8, id << 8); | ||
106 | if (err) { | ||
107 | printk(KERN_ERR "smu_sat_get_sdb_part wr error %d\n", err); | ||
108 | return NULL; | ||
109 | } | ||
110 | |||
111 | len = i2c_smbus_read_word_data(&sat->i2c, 9); | ||
112 | if (len < 0) { | ||
113 | printk(KERN_ERR "smu_sat_get_sdb_part rd len error\n"); | ||
114 | return NULL; | ||
115 | } | ||
116 | if (len == 0) { | ||
117 | printk(KERN_ERR "smu_sat_get_sdb_part no partition %x\n", id); | ||
118 | return NULL; | ||
119 | } | ||
120 | |||
121 | len = le16_to_cpu(len); | ||
122 | len = (len + 3) & ~3; | ||
123 | buf = kmalloc(len, GFP_KERNEL); | ||
124 | if (buf == NULL) | ||
125 | return NULL; | ||
126 | |||
127 | for (i = 0; i < len; i += 4) { | ||
128 | err = sat_read_block(&sat->i2c, 0xa, data, 4); | ||
129 | if (err) { | ||
130 | printk(KERN_ERR "smu_sat_get_sdb_part rd err %d\n", | ||
131 | err); | ||
132 | goto fail; | ||
133 | } | ||
134 | buf[i] = data[1]; | ||
135 | buf[i+1] = data[0]; | ||
136 | buf[i+2] = data[3]; | ||
137 | buf[i+3] = data[2]; | ||
138 | } | ||
139 | #ifdef DEBUG | ||
140 | DBG(KERN_DEBUG "sat %d partition %x:", sat_id, id); | ||
141 | for (i = 0; i < len; ++i) | ||
142 | DBG(" %x", buf[i]); | ||
143 | DBG("\n"); | ||
144 | #endif | ||
145 | |||
146 | if (size) | ||
147 | *size = len; | ||
148 | return (struct smu_sdbp_header *) buf; | ||
149 | |||
150 | fail: | ||
151 | kfree(buf); | ||
152 | return NULL; | ||
153 | } | ||
154 | |||
155 | /* refresh the cache */ | ||
156 | static int wf_sat_read_cache(struct wf_sat *sat) | ||
157 | { | ||
158 | int err; | ||
159 | |||
160 | err = sat_read_block(&sat->i2c, 0x3f, sat->cache, 16); | ||
161 | if (err) | ||
162 | return err; | ||
163 | sat->last_read = jiffies; | ||
164 | #ifdef LOTSA_DEBUG | ||
165 | { | ||
166 | int i; | ||
167 | DBG(KERN_DEBUG "wf_sat_get: data is"); | ||
168 | for (i = 0; i < 16; ++i) | ||
169 | DBG(" %.2x", sat->cache[i]); | ||
170 | DBG("\n"); | ||
171 | } | ||
172 | #endif | ||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static int wf_sat_get(struct wf_sensor *sr, s32 *value) | ||
177 | { | ||
178 | struct wf_sat_sensor *sens = wf_to_sat(sr); | ||
179 | struct wf_sat *sat = sens->sat; | ||
180 | int i, err; | ||
181 | s32 val; | ||
182 | |||
183 | if (sat->i2c.adapter == NULL) | ||
184 | return -ENODEV; | ||
185 | |||
186 | down(&sat->mutex); | ||
187 | if (time_after(jiffies, (sat->last_read + MAX_AGE))) { | ||
188 | err = wf_sat_read_cache(sat); | ||
189 | if (err) | ||
190 | goto fail; | ||
191 | } | ||
192 | |||
193 | i = sens->index * 2; | ||
194 | val = ((sat->cache[i] << 8) + sat->cache[i+1]) << sens->shift; | ||
195 | if (sens->index2 >= 0) { | ||
196 | i = sens->index2 * 2; | ||
197 | /* 4.12 * 8.8 -> 12.20; shift right 4 to get 16.16 */ | ||
198 | val = (val * ((sat->cache[i] << 8) + sat->cache[i+1])) >> 4; | ||
199 | } | ||
200 | |||
201 | *value = val; | ||
202 | err = 0; | ||
203 | |||
204 | fail: | ||
205 | up(&sat->mutex); | ||
206 | return err; | ||
207 | } | ||
208 | |||
209 | static void wf_sat_release(struct wf_sensor *sr) | ||
210 | { | ||
211 | struct wf_sat_sensor *sens = wf_to_sat(sr); | ||
212 | struct wf_sat *sat = sens->sat; | ||
213 | |||
214 | if (atomic_dec_and_test(&sat->refcnt)) { | ||
215 | if (sat->i2c.adapter) { | ||
216 | i2c_detach_client(&sat->i2c); | ||
217 | sat->i2c.adapter = NULL; | ||
218 | } | ||
219 | if (sat->nr >= 0) | ||
220 | sats[sat->nr] = NULL; | ||
221 | kfree(sat); | ||
222 | } | ||
223 | kfree(sens); | ||
224 | } | ||
225 | |||
226 | static struct wf_sensor_ops wf_sat_ops = { | ||
227 | .get_value = wf_sat_get, | ||
228 | .release = wf_sat_release, | ||
229 | .owner = THIS_MODULE, | ||
230 | }; | ||
231 | |||
232 | static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev) | ||
233 | { | ||
234 | struct wf_sat *sat; | ||
235 | struct wf_sat_sensor *sens; | ||
236 | u32 *reg; | ||
237 | char *loc, *type; | ||
238 | u8 addr, chip, core; | ||
239 | struct device_node *child; | ||
240 | int shift, cpu, index; | ||
241 | char *name; | ||
242 | int vsens[2], isens[2]; | ||
243 | |||
244 | reg = (u32 *) get_property(dev, "reg", NULL); | ||
245 | if (reg == NULL) | ||
246 | return; | ||
247 | addr = *reg; | ||
248 | DBG(KERN_DEBUG "wf_sat: creating sat at address %x\n", addr); | ||
249 | |||
250 | sat = kzalloc(sizeof(struct wf_sat), GFP_KERNEL); | ||
251 | if (sat == NULL) | ||
252 | return; | ||
253 | sat->nr = -1; | ||
254 | sat->node = of_node_get(dev); | ||
255 | atomic_set(&sat->refcnt, 0); | ||
256 | init_MUTEX(&sat->mutex); | ||
257 | sat->i2c.addr = (addr >> 1) & 0x7f; | ||
258 | sat->i2c.adapter = adapter; | ||
259 | sat->i2c.driver = &wf_sat_driver; | ||
260 | strncpy(sat->i2c.name, "smu-sat", I2C_NAME_SIZE-1); | ||
261 | |||
262 | if (i2c_attach_client(&sat->i2c)) { | ||
263 | printk(KERN_ERR "windfarm: failed to attach smu-sat to i2c\n"); | ||
264 | goto fail; | ||
265 | } | ||
266 | |||
267 | vsens[0] = vsens[1] = -1; | ||
268 | isens[0] = isens[1] = -1; | ||
269 | child = NULL; | ||
270 | while ((child = of_get_next_child(dev, child)) != NULL) { | ||
271 | reg = (u32 *) get_property(child, "reg", NULL); | ||
272 | type = get_property(child, "device_type", NULL); | ||
273 | loc = get_property(child, "location", NULL); | ||
274 | if (reg == NULL || loc == NULL) | ||
275 | continue; | ||
276 | |||
277 | /* the cooked sensors are between 0x30 and 0x37 */ | ||
278 | if (*reg < 0x30 || *reg > 0x37) | ||
279 | continue; | ||
280 | index = *reg - 0x30; | ||
281 | |||
282 | /* expect location to be CPU [AB][01] ... */ | ||
283 | if (strncmp(loc, "CPU ", 4) != 0) | ||
284 | continue; | ||
285 | chip = loc[4] - 'A'; | ||
286 | core = loc[5] - '0'; | ||
287 | if (chip > 1 || core > 1) { | ||
288 | printk(KERN_ERR "wf_sat_create: don't understand " | ||
289 | "location %s for %s\n", loc, child->full_name); | ||
290 | continue; | ||
291 | } | ||
292 | cpu = 2 * chip + core; | ||
293 | if (sat->nr < 0) | ||
294 | sat->nr = chip; | ||
295 | else if (sat->nr != chip) { | ||
296 | printk(KERN_ERR "wf_sat_create: can't cope with " | ||
297 | "multiple CPU chips on one SAT (%s)\n", loc); | ||
298 | continue; | ||
299 | } | ||
300 | |||
301 | if (strcmp(type, "voltage-sensor") == 0) { | ||
302 | name = "cpu-voltage"; | ||
303 | shift = 4; | ||
304 | vsens[core] = index; | ||
305 | } else if (strcmp(type, "current-sensor") == 0) { | ||
306 | name = "cpu-current"; | ||
307 | shift = 8; | ||
308 | isens[core] = index; | ||
309 | } else if (strcmp(type, "temp-sensor") == 0) { | ||
310 | name = "cpu-temp"; | ||
311 | shift = 10; | ||
312 | } else | ||
313 | continue; /* hmmm shouldn't happen */ | ||
314 | |||
315 | /* the +16 is enough for "cpu-voltage-n" */ | ||
316 | sens = kzalloc(sizeof(struct wf_sat_sensor) + 16, GFP_KERNEL); | ||
317 | if (sens == NULL) { | ||
318 | printk(KERN_ERR "wf_sat_create: couldn't create " | ||
319 | "%s sensor %d (no memory)\n", name, cpu); | ||
320 | continue; | ||
321 | } | ||
322 | sens->index = index; | ||
323 | sens->index2 = -1; | ||
324 | sens->shift = shift; | ||
325 | sens->sat = sat; | ||
326 | atomic_inc(&sat->refcnt); | ||
327 | sens->sens.ops = &wf_sat_ops; | ||
328 | sens->sens.name = (char *) (sens + 1); | ||
329 | snprintf(sens->sens.name, 16, "%s-%d", name, cpu); | ||
330 | |||
331 | if (wf_register_sensor(&sens->sens)) { | ||
332 | atomic_dec(&sat->refcnt); | ||
333 | kfree(sens); | ||
334 | } | ||
335 | } | ||
336 | |||
337 | /* make the power sensors */ | ||
338 | for (core = 0; core < 2; ++core) { | ||
339 | if (vsens[core] < 0 || isens[core] < 0) | ||
340 | continue; | ||
341 | cpu = 2 * sat->nr + core; | ||
342 | sens = kzalloc(sizeof(struct wf_sat_sensor) + 16, GFP_KERNEL); | ||
343 | if (sens == NULL) { | ||
344 | printk(KERN_ERR "wf_sat_create: couldn't create power " | ||
345 | "sensor %d (no memory)\n", cpu); | ||
346 | continue; | ||
347 | } | ||
348 | sens->index = vsens[core]; | ||
349 | sens->index2 = isens[core]; | ||
350 | sens->shift = 0; | ||
351 | sens->sat = sat; | ||
352 | atomic_inc(&sat->refcnt); | ||
353 | sens->sens.ops = &wf_sat_ops; | ||
354 | sens->sens.name = (char *) (sens + 1); | ||
355 | snprintf(sens->sens.name, 16, "cpu-power-%d", cpu); | ||
356 | |||
357 | if (wf_register_sensor(&sens->sens)) { | ||
358 | atomic_dec(&sat->refcnt); | ||
359 | kfree(sens); | ||
360 | } | ||
361 | } | ||
362 | |||
363 | if (sat->nr >= 0) | ||
364 | sats[sat->nr] = sat; | ||
365 | |||
366 | return; | ||
367 | |||
368 | fail: | ||
369 | kfree(sat); | ||
370 | } | ||
371 | |||
372 | static int wf_sat_attach(struct i2c_adapter *adapter) | ||
373 | { | ||
374 | struct device_node *busnode, *dev = NULL; | ||
375 | struct pmac_i2c_bus *bus; | ||
376 | |||
377 | bus = pmac_i2c_adapter_to_bus(adapter); | ||
378 | if (bus == NULL) | ||
379 | return -ENODEV; | ||
380 | busnode = pmac_i2c_get_bus_node(bus); | ||
381 | |||
382 | while ((dev = of_get_next_child(busnode, dev)) != NULL) | ||
383 | if (device_is_compatible(dev, "smu-sat")) | ||
384 | wf_sat_create(adapter, dev); | ||
385 | return 0; | ||
386 | } | ||
387 | |||
388 | static int wf_sat_detach(struct i2c_client *client) | ||
389 | { | ||
390 | struct wf_sat *sat = i2c_to_sat(client); | ||
391 | |||
392 | /* XXX TODO */ | ||
393 | |||
394 | sat->i2c.adapter = NULL; | ||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | static int __init sat_sensors_init(void) | ||
399 | { | ||
400 | int err; | ||
401 | |||
402 | err = i2c_add_driver(&wf_sat_driver); | ||
403 | if (err < 0) | ||
404 | return err; | ||
405 | return 0; | ||
406 | } | ||
407 | |||
408 | static void __exit sat_sensors_exit(void) | ||
409 | { | ||
410 | i2c_del_driver(&wf_sat_driver); | ||
411 | } | ||
412 | |||
413 | module_init(sat_sensors_init); | ||
414 | /*module_exit(sat_sensors_exit); Uncomment when cleanup is implemented */ | ||
415 | |||
416 | MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>"); | ||
417 | MODULE_DESCRIPTION("SMU satellite sensors for PowerMac thermal control"); | ||
418 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/macintosh/windfarm_smu_sensors.c b/drivers/macintosh/windfarm_smu_sensors.c index 1a00d9c75a23..bed25dcf8a1e 100644 --- a/drivers/macintosh/windfarm_smu_sensors.c +++ b/drivers/macintosh/windfarm_smu_sensors.c | |||
@@ -220,14 +220,29 @@ static struct smu_ad_sensor *smu_ads_create(struct device_node *node) | |||
220 | !strcmp(l, "CPU T-Diode")) { | 220 | !strcmp(l, "CPU T-Diode")) { |
221 | ads->sens.ops = &smu_cputemp_ops; | 221 | ads->sens.ops = &smu_cputemp_ops; |
222 | ads->sens.name = "cpu-temp"; | 222 | ads->sens.name = "cpu-temp"; |
223 | if (cpudiode == NULL) { | ||
224 | DBG("wf: cpudiode partition (%02x) not found\n", | ||
225 | SMU_SDB_CPUDIODE_ID); | ||
226 | goto fail; | ||
227 | } | ||
223 | } else if (!strcmp(c, "current-sensor") && | 228 | } else if (!strcmp(c, "current-sensor") && |
224 | !strcmp(l, "CPU Current")) { | 229 | !strcmp(l, "CPU Current")) { |
225 | ads->sens.ops = &smu_cpuamp_ops; | 230 | ads->sens.ops = &smu_cpuamp_ops; |
226 | ads->sens.name = "cpu-current"; | 231 | ads->sens.name = "cpu-current"; |
232 | if (cpuvcp == NULL) { | ||
233 | DBG("wf: cpuvcp partition (%02x) not found\n", | ||
234 | SMU_SDB_CPUVCP_ID); | ||
235 | goto fail; | ||
236 | } | ||
227 | } else if (!strcmp(c, "voltage-sensor") && | 237 | } else if (!strcmp(c, "voltage-sensor") && |
228 | !strcmp(l, "CPU Voltage")) { | 238 | !strcmp(l, "CPU Voltage")) { |
229 | ads->sens.ops = &smu_cpuvolt_ops; | 239 | ads->sens.ops = &smu_cpuvolt_ops; |
230 | ads->sens.name = "cpu-voltage"; | 240 | ads->sens.name = "cpu-voltage"; |
241 | if (cpuvcp == NULL) { | ||
242 | DBG("wf: cpuvcp partition (%02x) not found\n", | ||
243 | SMU_SDB_CPUVCP_ID); | ||
244 | goto fail; | ||
245 | } | ||
231 | } else if (!strcmp(c, "power-sensor") && | 246 | } else if (!strcmp(c, "power-sensor") && |
232 | !strcmp(l, "Slots Power")) { | 247 | !strcmp(l, "Slots Power")) { |
233 | ads->sens.ops = &smu_slotspow_ops; | 248 | ads->sens.ops = &smu_slotspow_ops; |
@@ -365,29 +380,22 @@ smu_cpu_power_create(struct wf_sensor *volts, struct wf_sensor *amps) | |||
365 | return NULL; | 380 | return NULL; |
366 | } | 381 | } |
367 | 382 | ||
368 | static int smu_fetch_param_partitions(void) | 383 | static void smu_fetch_param_partitions(void) |
369 | { | 384 | { |
370 | struct smu_sdbp_header *hdr; | 385 | struct smu_sdbp_header *hdr; |
371 | 386 | ||
372 | /* Get CPU voltage/current/power calibration data */ | 387 | /* Get CPU voltage/current/power calibration data */ |
373 | hdr = smu_get_sdb_partition(SMU_SDB_CPUVCP_ID, NULL); | 388 | hdr = smu_get_sdb_partition(SMU_SDB_CPUVCP_ID, NULL); |
374 | if (hdr == NULL) { | 389 | if (hdr != NULL) { |
375 | DBG("wf: cpuvcp partition (%02x) not found\n", | 390 | cpuvcp = (struct smu_sdbp_cpuvcp *)&hdr[1]; |
376 | SMU_SDB_CPUVCP_ID); | 391 | /* Keep version around */ |
377 | return -ENODEV; | 392 | cpuvcp_version = hdr->version; |
378 | } | 393 | } |
379 | cpuvcp = (struct smu_sdbp_cpuvcp *)&hdr[1]; | ||
380 | /* Keep version around */ | ||
381 | cpuvcp_version = hdr->version; | ||
382 | 394 | ||
383 | /* Get CPU diode calibration data */ | 395 | /* Get CPU diode calibration data */ |
384 | hdr = smu_get_sdb_partition(SMU_SDB_CPUDIODE_ID, NULL); | 396 | hdr = smu_get_sdb_partition(SMU_SDB_CPUDIODE_ID, NULL); |
385 | if (hdr == NULL) { | 397 | if (hdr != NULL) |
386 | DBG("wf: cpudiode partition (%02x) not found\n", | 398 | cpudiode = (struct smu_sdbp_cpudiode *)&hdr[1]; |
387 | SMU_SDB_CPUDIODE_ID); | ||
388 | return -ENODEV; | ||
389 | } | ||
390 | cpudiode = (struct smu_sdbp_cpudiode *)&hdr[1]; | ||
391 | 399 | ||
392 | /* Get slots power calibration data if any */ | 400 | /* Get slots power calibration data if any */ |
393 | hdr = smu_get_sdb_partition(SMU_SDB_SLOTSPOW_ID, NULL); | 401 | hdr = smu_get_sdb_partition(SMU_SDB_SLOTSPOW_ID, NULL); |
@@ -398,23 +406,18 @@ static int smu_fetch_param_partitions(void) | |||
398 | hdr = smu_get_sdb_partition(SMU_SDB_DEBUG_SWITCHES_ID, NULL); | 406 | hdr = smu_get_sdb_partition(SMU_SDB_DEBUG_SWITCHES_ID, NULL); |
399 | if (hdr != NULL) | 407 | if (hdr != NULL) |
400 | debugswitches = (u8 *)&hdr[1]; | 408 | debugswitches = (u8 *)&hdr[1]; |
401 | |||
402 | return 0; | ||
403 | } | 409 | } |
404 | 410 | ||
405 | static int __init smu_sensors_init(void) | 411 | static int __init smu_sensors_init(void) |
406 | { | 412 | { |
407 | struct device_node *smu, *sensors, *s; | 413 | struct device_node *smu, *sensors, *s; |
408 | struct smu_ad_sensor *volt_sensor = NULL, *curr_sensor = NULL; | 414 | struct smu_ad_sensor *volt_sensor = NULL, *curr_sensor = NULL; |
409 | int rc; | ||
410 | 415 | ||
411 | if (!smu_present()) | 416 | if (!smu_present()) |
412 | return -ENODEV; | 417 | return -ENODEV; |
413 | 418 | ||
414 | /* Get parameters partitions */ | 419 | /* Get parameters partitions */ |
415 | rc = smu_fetch_param_partitions(); | 420 | smu_fetch_param_partitions(); |
416 | if (rc) | ||
417 | return rc; | ||
418 | 421 | ||
419 | smu = of_find_node_by_type(NULL, "smu"); | 422 | smu = of_find_node_by_type(NULL, "smu"); |
420 | if (smu == NULL) | 423 | if (smu == NULL) |
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c index 74039db846ba..d73779a42417 100644 --- a/drivers/md/dm-log.c +++ b/drivers/md/dm-log.c | |||
@@ -545,7 +545,8 @@ static int core_get_resync_work(struct dirty_log *log, region_t *region) | |||
545 | return 0; | 545 | return 0; |
546 | 546 | ||
547 | do { | 547 | do { |
548 | *region = find_next_zero_bit((unsigned long *) lc->sync_bits, | 548 | *region = ext2_find_next_zero_bit( |
549 | (unsigned long *) lc->sync_bits, | ||
549 | lc->region_count, | 550 | lc->region_count, |
550 | lc->sync_search); | 551 | lc->sync_search); |
551 | lc->sync_search = *region + 1; | 552 | lc->sync_search = *region + 1; |
diff --git a/drivers/md/md.c b/drivers/md/md.c index 7145cd150f7b..d05e3125d298 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -1024,7 +1024,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version) | |||
1024 | rdev-> sb_size = (rdev->sb_size | bmask)+1; | 1024 | rdev-> sb_size = (rdev->sb_size | bmask)+1; |
1025 | 1025 | ||
1026 | if (refdev == 0) | 1026 | if (refdev == 0) |
1027 | return 1; | 1027 | ret = 1; |
1028 | else { | 1028 | else { |
1029 | __u64 ev1, ev2; | 1029 | __u64 ev1, ev2; |
1030 | struct mdp_superblock_1 *refsb = | 1030 | struct mdp_superblock_1 *refsb = |
@@ -1044,7 +1044,9 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version) | |||
1044 | ev2 = le64_to_cpu(refsb->events); | 1044 | ev2 = le64_to_cpu(refsb->events); |
1045 | 1045 | ||
1046 | if (ev1 > ev2) | 1046 | if (ev1 > ev2) |
1047 | return 1; | 1047 | ret = 1; |
1048 | else | ||
1049 | ret = 0; | ||
1048 | } | 1050 | } |
1049 | if (minor_version) | 1051 | if (minor_version) |
1050 | rdev->size = ((rdev->bdev->bd_inode->i_size>>9) - le64_to_cpu(sb->data_offset)) / 2; | 1052 | rdev->size = ((rdev->bdev->bd_inode->i_size>>9) - le64_to_cpu(sb->data_offset)) / 2; |
@@ -1058,7 +1060,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version) | |||
1058 | 1060 | ||
1059 | if (le32_to_cpu(sb->size) > rdev->size*2) | 1061 | if (le32_to_cpu(sb->size) > rdev->size*2) |
1060 | return -EINVAL; | 1062 | return -EINVAL; |
1061 | return 0; | 1063 | return ret; |
1062 | } | 1064 | } |
1063 | 1065 | ||
1064 | static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) | 1066 | static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) |
@@ -1081,7 +1083,7 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) | |||
1081 | mddev->size = le64_to_cpu(sb->size)/2; | 1083 | mddev->size = le64_to_cpu(sb->size)/2; |
1082 | mddev->events = le64_to_cpu(sb->events); | 1084 | mddev->events = le64_to_cpu(sb->events); |
1083 | mddev->bitmap_offset = 0; | 1085 | mddev->bitmap_offset = 0; |
1084 | mddev->default_bitmap_offset = 1024; | 1086 | mddev->default_bitmap_offset = 1024 >> 9; |
1085 | 1087 | ||
1086 | mddev->recovery_cp = le64_to_cpu(sb->resync_offset); | 1088 | mddev->recovery_cp = le64_to_cpu(sb->resync_offset); |
1087 | memcpy(mddev->uuid, sb->set_uuid, 16); | 1089 | memcpy(mddev->uuid, sb->set_uuid, 16); |
@@ -1161,6 +1163,9 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev) | |||
1161 | 1163 | ||
1162 | sb->cnt_corrected_read = atomic_read(&rdev->corrected_errors); | 1164 | sb->cnt_corrected_read = atomic_read(&rdev->corrected_errors); |
1163 | 1165 | ||
1166 | sb->raid_disks = cpu_to_le32(mddev->raid_disks); | ||
1167 | sb->size = cpu_to_le64(mddev->size<<1); | ||
1168 | |||
1164 | if (mddev->bitmap && mddev->bitmap_file == NULL) { | 1169 | if (mddev->bitmap && mddev->bitmap_file == NULL) { |
1165 | sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset); | 1170 | sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset); |
1166 | sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET); | 1171 | sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET); |
@@ -2686,14 +2691,6 @@ static int do_md_stop(mddev_t * mddev, int ro) | |||
2686 | set_disk_ro(disk, 1); | 2691 | set_disk_ro(disk, 1); |
2687 | } | 2692 | } |
2688 | 2693 | ||
2689 | bitmap_destroy(mddev); | ||
2690 | if (mddev->bitmap_file) { | ||
2691 | atomic_set(&mddev->bitmap_file->f_dentry->d_inode->i_writecount, 1); | ||
2692 | fput(mddev->bitmap_file); | ||
2693 | mddev->bitmap_file = NULL; | ||
2694 | } | ||
2695 | mddev->bitmap_offset = 0; | ||
2696 | |||
2697 | /* | 2694 | /* |
2698 | * Free resources if final stop | 2695 | * Free resources if final stop |
2699 | */ | 2696 | */ |
@@ -2703,6 +2700,14 @@ static int do_md_stop(mddev_t * mddev, int ro) | |||
2703 | struct gendisk *disk; | 2700 | struct gendisk *disk; |
2704 | printk(KERN_INFO "md: %s stopped.\n", mdname(mddev)); | 2701 | printk(KERN_INFO "md: %s stopped.\n", mdname(mddev)); |
2705 | 2702 | ||
2703 | bitmap_destroy(mddev); | ||
2704 | if (mddev->bitmap_file) { | ||
2705 | atomic_set(&mddev->bitmap_file->f_dentry->d_inode->i_writecount, 1); | ||
2706 | fput(mddev->bitmap_file); | ||
2707 | mddev->bitmap_file = NULL; | ||
2708 | } | ||
2709 | mddev->bitmap_offset = 0; | ||
2710 | |||
2706 | ITERATE_RDEV(mddev,rdev,tmp) | 2711 | ITERATE_RDEV(mddev,rdev,tmp) |
2707 | if (rdev->raid_disk >= 0) { | 2712 | if (rdev->raid_disk >= 0) { |
2708 | char nm[20]; | 2713 | char nm[20]; |
@@ -2939,6 +2944,8 @@ static int get_array_info(mddev_t * mddev, void __user * arg) | |||
2939 | info.ctime = mddev->ctime; | 2944 | info.ctime = mddev->ctime; |
2940 | info.level = mddev->level; | 2945 | info.level = mddev->level; |
2941 | info.size = mddev->size; | 2946 | info.size = mddev->size; |
2947 | if (info.size != mddev->size) /* overflow */ | ||
2948 | info.size = -1; | ||
2942 | info.nr_disks = nr; | 2949 | info.nr_disks = nr; |
2943 | info.raid_disks = mddev->raid_disks; | 2950 | info.raid_disks = mddev->raid_disks; |
2944 | info.md_minor = mddev->md_minor; | 2951 | info.md_minor = mddev->md_minor; |
@@ -3465,7 +3472,7 @@ static int update_size(mddev_t *mddev, unsigned long size) | |||
3465 | bdev = bdget_disk(mddev->gendisk, 0); | 3472 | bdev = bdget_disk(mddev->gendisk, 0); |
3466 | if (bdev) { | 3473 | if (bdev) { |
3467 | mutex_lock(&bdev->bd_inode->i_mutex); | 3474 | mutex_lock(&bdev->bd_inode->i_mutex); |
3468 | i_size_write(bdev->bd_inode, mddev->array_size << 10); | 3475 | i_size_write(bdev->bd_inode, (loff_t)mddev->array_size << 10); |
3469 | mutex_unlock(&bdev->bd_inode->i_mutex); | 3476 | mutex_unlock(&bdev->bd_inode->i_mutex); |
3470 | bdput(bdev); | 3477 | bdput(bdev); |
3471 | } | 3478 | } |
@@ -3485,17 +3492,6 @@ static int update_raid_disks(mddev_t *mddev, int raid_disks) | |||
3485 | if (mddev->sync_thread) | 3492 | if (mddev->sync_thread) |
3486 | return -EBUSY; | 3493 | return -EBUSY; |
3487 | rv = mddev->pers->reshape(mddev, raid_disks); | 3494 | rv = mddev->pers->reshape(mddev, raid_disks); |
3488 | if (!rv) { | ||
3489 | struct block_device *bdev; | ||
3490 | |||
3491 | bdev = bdget_disk(mddev->gendisk, 0); | ||
3492 | if (bdev) { | ||
3493 | mutex_lock(&bdev->bd_inode->i_mutex); | ||
3494 | i_size_write(bdev->bd_inode, mddev->array_size << 10); | ||
3495 | mutex_unlock(&bdev->bd_inode->i_mutex); | ||
3496 | bdput(bdev); | ||
3497 | } | ||
3498 | } | ||
3499 | return rv; | 3495 | return rv; |
3500 | } | 3496 | } |
3501 | 3497 | ||
@@ -3531,7 +3527,7 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info) | |||
3531 | ) | 3527 | ) |
3532 | return -EINVAL; | 3528 | return -EINVAL; |
3533 | /* Check there is only one change */ | 3529 | /* Check there is only one change */ |
3534 | if (mddev->size != info->size) cnt++; | 3530 | if (info->size >= 0 && mddev->size != info->size) cnt++; |
3535 | if (mddev->raid_disks != info->raid_disks) cnt++; | 3531 | if (mddev->raid_disks != info->raid_disks) cnt++; |
3536 | if (mddev->layout != info->layout) cnt++; | 3532 | if (mddev->layout != info->layout) cnt++; |
3537 | if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) cnt++; | 3533 | if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) cnt++; |
@@ -3548,7 +3544,7 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info) | |||
3548 | else | 3544 | else |
3549 | return mddev->pers->reconfig(mddev, info->layout, -1); | 3545 | return mddev->pers->reconfig(mddev, info->layout, -1); |
3550 | } | 3546 | } |
3551 | if (mddev->size != info->size) | 3547 | if (info->size >= 0 && mddev->size != info->size) |
3552 | rv = update_size(mddev, info->size); | 3548 | rv = update_size(mddev, info->size); |
3553 | 3549 | ||
3554 | if (mddev->raid_disks != info->raid_disks) | 3550 | if (mddev->raid_disks != info->raid_disks) |
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index d03f99cf4b7d..678f4dbbea1d 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c | |||
@@ -372,7 +372,7 @@ out_free_conf: | |||
372 | kfree(conf); | 372 | kfree(conf); |
373 | mddev->private = NULL; | 373 | mddev->private = NULL; |
374 | out: | 374 | out: |
375 | return 1; | 375 | return -ENOMEM; |
376 | } | 376 | } |
377 | 377 | ||
378 | static int raid0_stop (mddev_t *mddev) | 378 | static int raid0_stop (mddev_t *mddev) |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 9130d051b474..ab90a6d12020 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -565,6 +565,8 @@ rb_out: | |||
565 | 565 | ||
566 | if (disk >= 0 && (rdev=rcu_dereference(conf->mirrors[disk].rdev))!= NULL) | 566 | if (disk >= 0 && (rdev=rcu_dereference(conf->mirrors[disk].rdev))!= NULL) |
567 | atomic_inc(&conf->mirrors[disk].rdev->nr_pending); | 567 | atomic_inc(&conf->mirrors[disk].rdev->nr_pending); |
568 | else | ||
569 | disk = -1; | ||
568 | rcu_read_unlock(); | 570 | rcu_read_unlock(); |
569 | 571 | ||
570 | return disk; | 572 | return disk; |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 25976bfb6f9c..2dba305daf3c 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -350,7 +350,8 @@ static void shrink_stripes(raid5_conf_t *conf) | |||
350 | while (drop_one_stripe(conf)) | 350 | while (drop_one_stripe(conf)) |
351 | ; | 351 | ; |
352 | 352 | ||
353 | kmem_cache_destroy(conf->slab_cache); | 353 | if (conf->slab_cache) |
354 | kmem_cache_destroy(conf->slab_cache); | ||
354 | conf->slab_cache = NULL; | 355 | conf->slab_cache = NULL; |
355 | } | 356 | } |
356 | 357 | ||
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c index f618a53b98be..cd477ebf2ee4 100644 --- a/drivers/md/raid6main.c +++ b/drivers/md/raid6main.c | |||
@@ -115,7 +115,7 @@ static void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh) | |||
115 | list_add_tail(&sh->lru, &conf->inactive_list); | 115 | list_add_tail(&sh->lru, &conf->inactive_list); |
116 | atomic_dec(&conf->active_stripes); | 116 | atomic_dec(&conf->active_stripes); |
117 | if (!conf->inactive_blocked || | 117 | if (!conf->inactive_blocked || |
118 | atomic_read(&conf->active_stripes) < (NR_STRIPES*3/4)) | 118 | atomic_read(&conf->active_stripes) < (conf->max_nr_stripes*3/4)) |
119 | wake_up(&conf->wait_for_stripe); | 119 | wake_up(&conf->wait_for_stripe); |
120 | } | 120 | } |
121 | } | 121 | } |
@@ -273,7 +273,8 @@ static struct stripe_head *get_active_stripe(raid6_conf_t *conf, sector_t sector | |||
273 | conf->inactive_blocked = 1; | 273 | conf->inactive_blocked = 1; |
274 | wait_event_lock_irq(conf->wait_for_stripe, | 274 | wait_event_lock_irq(conf->wait_for_stripe, |
275 | !list_empty(&conf->inactive_list) && | 275 | !list_empty(&conf->inactive_list) && |
276 | (atomic_read(&conf->active_stripes) < (NR_STRIPES *3/4) | 276 | (atomic_read(&conf->active_stripes) |
277 | < (conf->max_nr_stripes *3/4) | ||
277 | || !conf->inactive_blocked), | 278 | || !conf->inactive_blocked), |
278 | conf->device_lock, | 279 | conf->device_lock, |
279 | unplug_slaves(conf->mddev); | 280 | unplug_slaves(conf->mddev); |
@@ -302,9 +303,31 @@ static struct stripe_head *get_active_stripe(raid6_conf_t *conf, sector_t sector | |||
302 | return sh; | 303 | return sh; |
303 | } | 304 | } |
304 | 305 | ||
305 | static int grow_stripes(raid6_conf_t *conf, int num) | 306 | static int grow_one_stripe(raid6_conf_t *conf) |
306 | { | 307 | { |
307 | struct stripe_head *sh; | 308 | struct stripe_head *sh; |
309 | sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL); | ||
310 | if (!sh) | ||
311 | return 0; | ||
312 | memset(sh, 0, sizeof(*sh) + (conf->raid_disks-1)*sizeof(struct r5dev)); | ||
313 | sh->raid_conf = conf; | ||
314 | spin_lock_init(&sh->lock); | ||
315 | |||
316 | if (grow_buffers(sh, conf->raid_disks)) { | ||
317 | shrink_buffers(sh, conf->raid_disks); | ||
318 | kmem_cache_free(conf->slab_cache, sh); | ||
319 | return 0; | ||
320 | } | ||
321 | /* we just created an active stripe so... */ | ||
322 | atomic_set(&sh->count, 1); | ||
323 | atomic_inc(&conf->active_stripes); | ||
324 | INIT_LIST_HEAD(&sh->lru); | ||
325 | release_stripe(sh); | ||
326 | return 1; | ||
327 | } | ||
328 | |||
329 | static int grow_stripes(raid6_conf_t *conf, int num) | ||
330 | { | ||
308 | kmem_cache_t *sc; | 331 | kmem_cache_t *sc; |
309 | int devs = conf->raid_disks; | 332 | int devs = conf->raid_disks; |
310 | 333 | ||
@@ -316,45 +339,35 @@ static int grow_stripes(raid6_conf_t *conf, int num) | |||
316 | if (!sc) | 339 | if (!sc) |
317 | return 1; | 340 | return 1; |
318 | conf->slab_cache = sc; | 341 | conf->slab_cache = sc; |
319 | while (num--) { | 342 | while (num--) |
320 | sh = kmem_cache_alloc(sc, GFP_KERNEL); | 343 | if (!grow_one_stripe(conf)) |
321 | if (!sh) | ||
322 | return 1; | ||
323 | memset(sh, 0, sizeof(*sh) + (devs-1)*sizeof(struct r5dev)); | ||
324 | sh->raid_conf = conf; | ||
325 | spin_lock_init(&sh->lock); | ||
326 | |||
327 | if (grow_buffers(sh, conf->raid_disks)) { | ||
328 | shrink_buffers(sh, conf->raid_disks); | ||
329 | kmem_cache_free(sc, sh); | ||
330 | return 1; | 344 | return 1; |
331 | } | ||
332 | /* we just created an active stripe so... */ | ||
333 | atomic_set(&sh->count, 1); | ||
334 | atomic_inc(&conf->active_stripes); | ||
335 | INIT_LIST_HEAD(&sh->lru); | ||
336 | release_stripe(sh); | ||
337 | } | ||
338 | return 0; | 345 | return 0; |
339 | } | 346 | } |
340 | 347 | ||
341 | static void shrink_stripes(raid6_conf_t *conf) | 348 | static int drop_one_stripe(raid6_conf_t *conf) |
342 | { | 349 | { |
343 | struct stripe_head *sh; | 350 | struct stripe_head *sh; |
351 | spin_lock_irq(&conf->device_lock); | ||
352 | sh = get_free_stripe(conf); | ||
353 | spin_unlock_irq(&conf->device_lock); | ||
354 | if (!sh) | ||
355 | return 0; | ||
356 | if (atomic_read(&sh->count)) | ||
357 | BUG(); | ||
358 | shrink_buffers(sh, conf->raid_disks); | ||
359 | kmem_cache_free(conf->slab_cache, sh); | ||
360 | atomic_dec(&conf->active_stripes); | ||
361 | return 1; | ||
362 | } | ||
344 | 363 | ||
345 | while (1) { | 364 | static void shrink_stripes(raid6_conf_t *conf) |
346 | spin_lock_irq(&conf->device_lock); | 365 | { |
347 | sh = get_free_stripe(conf); | 366 | while (drop_one_stripe(conf)) |
348 | spin_unlock_irq(&conf->device_lock); | 367 | ; |
349 | if (!sh) | 368 | |
350 | break; | 369 | if (conf->slab_cache) |
351 | if (atomic_read(&sh->count)) | 370 | kmem_cache_destroy(conf->slab_cache); |
352 | BUG(); | ||
353 | shrink_buffers(sh, conf->raid_disks); | ||
354 | kmem_cache_free(conf->slab_cache, sh); | ||
355 | atomic_dec(&conf->active_stripes); | ||
356 | } | ||
357 | kmem_cache_destroy(conf->slab_cache); | ||
358 | conf->slab_cache = NULL; | 371 | conf->slab_cache = NULL; |
359 | } | 372 | } |
360 | 373 | ||
@@ -1912,6 +1925,74 @@ static void raid6d (mddev_t *mddev) | |||
1912 | PRINTK("--- raid6d inactive\n"); | 1925 | PRINTK("--- raid6d inactive\n"); |
1913 | } | 1926 | } |
1914 | 1927 | ||
1928 | static ssize_t | ||
1929 | raid6_show_stripe_cache_size(mddev_t *mddev, char *page) | ||
1930 | { | ||
1931 | raid6_conf_t *conf = mddev_to_conf(mddev); | ||
1932 | if (conf) | ||
1933 | return sprintf(page, "%d\n", conf->max_nr_stripes); | ||
1934 | else | ||
1935 | return 0; | ||
1936 | } | ||
1937 | |||
1938 | static ssize_t | ||
1939 | raid6_store_stripe_cache_size(mddev_t *mddev, const char *page, size_t len) | ||
1940 | { | ||
1941 | raid6_conf_t *conf = mddev_to_conf(mddev); | ||
1942 | char *end; | ||
1943 | int new; | ||
1944 | if (len >= PAGE_SIZE) | ||
1945 | return -EINVAL; | ||
1946 | if (!conf) | ||
1947 | return -ENODEV; | ||
1948 | |||
1949 | new = simple_strtoul(page, &end, 10); | ||
1950 | if (!*page || (*end && *end != '\n') ) | ||
1951 | return -EINVAL; | ||
1952 | if (new <= 16 || new > 32768) | ||
1953 | return -EINVAL; | ||
1954 | while (new < conf->max_nr_stripes) { | ||
1955 | if (drop_one_stripe(conf)) | ||
1956 | conf->max_nr_stripes--; | ||
1957 | else | ||
1958 | break; | ||
1959 | } | ||
1960 | while (new > conf->max_nr_stripes) { | ||
1961 | if (grow_one_stripe(conf)) | ||
1962 | conf->max_nr_stripes++; | ||
1963 | else break; | ||
1964 | } | ||
1965 | return len; | ||
1966 | } | ||
1967 | |||
1968 | static struct md_sysfs_entry | ||
1969 | raid6_stripecache_size = __ATTR(stripe_cache_size, S_IRUGO | S_IWUSR, | ||
1970 | raid6_show_stripe_cache_size, | ||
1971 | raid6_store_stripe_cache_size); | ||
1972 | |||
1973 | static ssize_t | ||
1974 | stripe_cache_active_show(mddev_t *mddev, char *page) | ||
1975 | { | ||
1976 | raid6_conf_t *conf = mddev_to_conf(mddev); | ||
1977 | if (conf) | ||
1978 | return sprintf(page, "%d\n", atomic_read(&conf->active_stripes)); | ||
1979 | else | ||
1980 | return 0; | ||
1981 | } | ||
1982 | |||
1983 | static struct md_sysfs_entry | ||
1984 | raid6_stripecache_active = __ATTR_RO(stripe_cache_active); | ||
1985 | |||
1986 | static struct attribute *raid6_attrs[] = { | ||
1987 | &raid6_stripecache_size.attr, | ||
1988 | &raid6_stripecache_active.attr, | ||
1989 | NULL, | ||
1990 | }; | ||
1991 | static struct attribute_group raid6_attrs_group = { | ||
1992 | .name = NULL, | ||
1993 | .attrs = raid6_attrs, | ||
1994 | }; | ||
1995 | |||
1915 | static int run(mddev_t *mddev) | 1996 | static int run(mddev_t *mddev) |
1916 | { | 1997 | { |
1917 | raid6_conf_t *conf; | 1998 | raid6_conf_t *conf; |
@@ -2095,6 +2176,7 @@ static int stop (mddev_t *mddev) | |||
2095 | shrink_stripes(conf); | 2176 | shrink_stripes(conf); |
2096 | kfree(conf->stripe_hashtbl); | 2177 | kfree(conf->stripe_hashtbl); |
2097 | blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ | 2178 | blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ |
2179 | sysfs_remove_group(&mddev->kobj, &raid6_attrs_group); | ||
2098 | kfree(conf); | 2180 | kfree(conf); |
2099 | mddev->private = NULL; | 2181 | mddev->private = NULL; |
2100 | return 0; | 2182 | return 0; |
diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig index 2583a865a58e..2963605c0ecc 100644 --- a/drivers/media/dvb/b2c2/Kconfig +++ b/drivers/media/dvb/b2c2/Kconfig | |||
@@ -4,7 +4,7 @@ config DVB_B2C2_FLEXCOP | |||
4 | select DVB_STV0299 | 4 | select DVB_STV0299 |
5 | select DVB_MT352 | 5 | select DVB_MT352 |
6 | select DVB_MT312 | 6 | select DVB_MT312 |
7 | select DVB_NXT2002 | 7 | select DVB_NXT200X |
8 | select DVB_STV0297 | 8 | select DVB_STV0297 |
9 | select DVB_BCM3510 | 9 | select DVB_BCM3510 |
10 | select DVB_LGDT330X | 10 | select DVB_LGDT330X |
diff --git a/drivers/media/dvb/b2c2/flexcop-common.h b/drivers/media/dvb/b2c2/flexcop-common.h index 344a3c898460..7d7e1613c5a7 100644 --- a/drivers/media/dvb/b2c2/flexcop-common.h +++ b/drivers/media/dvb/b2c2/flexcop-common.h | |||
@@ -116,11 +116,9 @@ void flexcop_dma_free(struct flexcop_dma *dma); | |||
116 | 116 | ||
117 | int flexcop_dma_control_timer_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff); | 117 | int flexcop_dma_control_timer_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff); |
118 | int flexcop_dma_control_size_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff); | 118 | int flexcop_dma_control_size_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff); |
119 | int flexcop_dma_control_packet_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff); | ||
120 | int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, flexcop_dma_index_t dma_idx); | 119 | int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, flexcop_dma_index_t dma_idx); |
121 | int flexcop_dma_xfer_control(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, flexcop_dma_addr_index_t index, int onoff); | 120 | int flexcop_dma_xfer_control(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, flexcop_dma_addr_index_t index, int onoff); |
122 | int flexcop_dma_config_timer(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 cycles); | 121 | int flexcop_dma_config_timer(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 cycles); |
123 | int flexcop_dma_config_packet_count(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 packets); | ||
124 | 122 | ||
125 | /* from flexcop-eeprom.c */ | 123 | /* from flexcop-eeprom.c */ |
126 | /* the PCI part uses this call to get the MAC address, the USB part has its own */ | 124 | /* the PCI part uses this call to get the MAC address, the USB part has its own */ |
diff --git a/drivers/media/dvb/b2c2/flexcop-dma.c b/drivers/media/dvb/b2c2/flexcop-dma.c index cf4ed1df6086..6f592bc32d22 100644 --- a/drivers/media/dvb/b2c2/flexcop-dma.c +++ b/drivers/media/dvb/b2c2/flexcop-dma.c | |||
@@ -169,38 +169,3 @@ int flexcop_dma_config_timer(struct flexcop_device *fc, | |||
169 | } | 169 | } |
170 | EXPORT_SYMBOL(flexcop_dma_config_timer); | 170 | EXPORT_SYMBOL(flexcop_dma_config_timer); |
171 | 171 | ||
172 | /* packet IRQ does not exist in FCII or FCIIb - according to data book and tests */ | ||
173 | int flexcop_dma_control_packet_irq(struct flexcop_device *fc, | ||
174 | flexcop_dma_index_t no, | ||
175 | int onoff) | ||
176 | { | ||
177 | flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208); | ||
178 | |||
179 | deb_rdump("reg: %03x: %x\n",ctrl_208,v.raw); | ||
180 | if (no & FC_DMA_1) | ||
181 | v.ctrl_208.DMA1_Size_IRQ_Enable_sig = onoff; | ||
182 | |||
183 | if (no & FC_DMA_2) | ||
184 | v.ctrl_208.DMA2_Size_IRQ_Enable_sig = onoff; | ||
185 | |||
186 | fc->write_ibi_reg(fc,ctrl_208,v); | ||
187 | deb_rdump("reg: %03x: %x\n",ctrl_208,v.raw); | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | EXPORT_SYMBOL(flexcop_dma_control_packet_irq); | ||
192 | |||
193 | int flexcop_dma_config_packet_count(struct flexcop_device *fc, | ||
194 | flexcop_dma_index_t dma_idx, | ||
195 | u8 packets) | ||
196 | { | ||
197 | flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014; | ||
198 | flexcop_ibi_value v = fc->read_ibi_reg(fc,r); | ||
199 | |||
200 | flexcop_dma_remap(fc,dma_idx,1); | ||
201 | |||
202 | v.dma_0x4_remap.DMA_maxpackets = packets; | ||
203 | fc->write_ibi_reg(fc,r,v); | ||
204 | return 0; | ||
205 | } | ||
206 | EXPORT_SYMBOL(flexcop_dma_config_packet_count); | ||
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index 0b940e152b79..390cc3a99ce6 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c | |||
@@ -9,7 +9,7 @@ | |||
9 | 9 | ||
10 | #include "stv0299.h" | 10 | #include "stv0299.h" |
11 | #include "mt352.h" | 11 | #include "mt352.h" |
12 | #include "nxt2002.h" | 12 | #include "nxt200x.h" |
13 | #include "bcm3510.h" | 13 | #include "bcm3510.h" |
14 | #include "stv0297.h" | 14 | #include "stv0297.h" |
15 | #include "mt312.h" | 15 | #include "mt312.h" |
@@ -343,9 +343,10 @@ static struct lgdt330x_config air2pc_atsc_hd5000_config = { | |||
343 | .clock_polarity_flip = 1, | 343 | .clock_polarity_flip = 1, |
344 | }; | 344 | }; |
345 | 345 | ||
346 | static struct nxt2002_config samsung_tbmv_config = { | 346 | static struct nxt200x_config samsung_tbmv_config = { |
347 | .demod_address = 0x0a, | 347 | .demod_address = 0x0a, |
348 | .request_firmware = flexcop_fe_request_firmware, | 348 | .pll_address = 0xc2, |
349 | .pll_desc = &dvb_pll_samsung_tbmv, | ||
349 | }; | 350 | }; |
350 | 351 | ||
351 | static struct bcm3510_config air2pc_atsc_first_gen_config = { | 352 | static struct bcm3510_config air2pc_atsc_first_gen_config = { |
@@ -505,7 +506,7 @@ int flexcop_frontend_init(struct flexcop_device *fc) | |||
505 | info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address); | 506 | info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address); |
506 | } else | 507 | } else |
507 | /* try the air atsc 2nd generation (nxt2002) */ | 508 | /* try the air atsc 2nd generation (nxt2002) */ |
508 | if ((fc->fe = nxt2002_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) { | 509 | if ((fc->fe = nxt200x_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) { |
509 | fc->dev_type = FC_AIR_ATSC2; | 510 | fc->dev_type = FC_AIR_ATSC2; |
510 | info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address); | 511 | info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address); |
511 | } else | 512 | } else |
diff --git a/drivers/media/dvb/b2c2/flexcop-misc.c b/drivers/media/dvb/b2c2/flexcop-misc.c index 62282d8dbfa8..167583bf0621 100644 --- a/drivers/media/dvb/b2c2/flexcop-misc.c +++ b/drivers/media/dvb/b2c2/flexcop-misc.c | |||
@@ -36,14 +36,14 @@ void flexcop_determine_revision(struct flexcop_device *fc) | |||
36 | /* bus parts have to decide if hw pid filtering is used or not. */ | 36 | /* bus parts have to decide if hw pid filtering is used or not. */ |
37 | } | 37 | } |
38 | 38 | ||
39 | const char *flexcop_revision_names[] = { | 39 | static const char *flexcop_revision_names[] = { |
40 | "Unkown chip", | 40 | "Unkown chip", |
41 | "FlexCopII", | 41 | "FlexCopII", |
42 | "FlexCopIIb", | 42 | "FlexCopIIb", |
43 | "FlexCopIII", | 43 | "FlexCopIII", |
44 | }; | 44 | }; |
45 | 45 | ||
46 | const char *flexcop_device_names[] = { | 46 | static const char *flexcop_device_names[] = { |
47 | "Unkown device", | 47 | "Unkown device", |
48 | "Air2PC/AirStar 2 DVB-T", | 48 | "Air2PC/AirStar 2 DVB-T", |
49 | "Air2PC/AirStar 2 ATSC 1st generation", | 49 | "Air2PC/AirStar 2 ATSC 1st generation", |
@@ -54,7 +54,7 @@ const char *flexcop_device_names[] = { | |||
54 | "Air2PC/AirStar 2 ATSC 3rd generation (HD5000)", | 54 | "Air2PC/AirStar 2 ATSC 3rd generation (HD5000)", |
55 | }; | 55 | }; |
56 | 56 | ||
57 | const char *flexcop_bus_names[] = { | 57 | static const char *flexcop_bus_names[] = { |
58 | "USB", | 58 | "USB", |
59 | "PCI", | 59 | "PCI", |
60 | }; | 60 | }; |
diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c index 2f76eb3fea40..9bc40bdcc282 100644 --- a/drivers/media/dvb/b2c2/flexcop-pci.c +++ b/drivers/media/dvb/b2c2/flexcop-pci.c | |||
@@ -161,8 +161,10 @@ static irqreturn_t flexcop_pci_isr(int irq, void *dev_id, struct pt_regs *regs) | |||
161 | fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2; | 161 | fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2; |
162 | u32 cur_pos = cur_addr - fc_pci->dma[0].dma_addr0; | 162 | u32 cur_pos = cur_addr - fc_pci->dma[0].dma_addr0; |
163 | 163 | ||
164 | deb_irq("%u irq: %08x cur_addr: %08x: cur_pos: %08x, last_cur_pos: %08x ", | 164 | deb_irq("%u irq: %08x cur_addr: %llx: cur_pos: %08x, last_cur_pos: %08x ", |
165 | jiffies_to_usecs(jiffies - fc_pci->last_irq),v.raw,cur_addr,cur_pos,fc_pci->last_dma1_cur_pos); | 165 | jiffies_to_usecs(jiffies - fc_pci->last_irq), |
166 | v.raw, (unsigned long long)cur_addr, cur_pos, | ||
167 | fc_pci->last_dma1_cur_pos); | ||
166 | fc_pci->last_irq = jiffies; | 168 | fc_pci->last_irq = jiffies; |
167 | 169 | ||
168 | /* buffer end was reached, restarted from the beginning | 170 | /* buffer end was reached, restarted from the beginning |
diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h index 3153f9513c63..491f9bd6e195 100644 --- a/drivers/media/dvb/b2c2/flexcop-reg.h +++ b/drivers/media/dvb/b2c2/flexcop-reg.h | |||
@@ -16,8 +16,6 @@ typedef enum { | |||
16 | FLEXCOP_III, | 16 | FLEXCOP_III, |
17 | } flexcop_revision_t; | 17 | } flexcop_revision_t; |
18 | 18 | ||
19 | extern const char *flexcop_revision_names[]; | ||
20 | |||
21 | typedef enum { | 19 | typedef enum { |
22 | FC_UNK = 0, | 20 | FC_UNK = 0, |
23 | FC_AIR_DVB, | 21 | FC_AIR_DVB, |
@@ -34,8 +32,6 @@ typedef enum { | |||
34 | FC_PCI, | 32 | FC_PCI, |
35 | } flexcop_bus_t; | 33 | } flexcop_bus_t; |
36 | 34 | ||
37 | extern const char *flexcop_device_names[]; | ||
38 | |||
39 | /* FlexCop IBI Registers */ | 35 | /* FlexCop IBI Registers */ |
40 | #if defined(__LITTLE_ENDIAN) | 36 | #if defined(__LITTLE_ENDIAN) |
41 | #include "flexcop_ibi_value_le.h" | 37 | #include "flexcop_ibi_value_le.h" |
diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c index a04bb61f21f4..34c3189a1a33 100644 --- a/drivers/media/dvb/bt8xx/bt878.c +++ b/drivers/media/dvb/bt8xx/bt878.c | |||
@@ -381,6 +381,23 @@ bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet * | |||
381 | 381 | ||
382 | EXPORT_SYMBOL(bt878_device_control); | 382 | EXPORT_SYMBOL(bt878_device_control); |
383 | 383 | ||
384 | |||
385 | struct cards card_list[] __devinitdata = { | ||
386 | |||
387 | { 0x01010071, BTTV_BOARD_NEBULA_DIGITV, "Nebula Electronics DigiTV" }, | ||
388 | { 0x07611461, BTTV_BOARD_AVDVBT_761, "AverMedia AverTV DVB-T 761" }, | ||
389 | { 0x001c11bd, BTTV_BOARD_PINNACLESAT, "Pinnacle PCTV Sat" }, | ||
390 | { 0x002611bd, BTTV_BOARD_TWINHAN_DST, "Pinnacle PCTV SAT CI" }, | ||
391 | { 0x00011822, BTTV_BOARD_TWINHAN_DST, "Twinhan VisionPlus DVB" }, | ||
392 | { 0xfc00270f, BTTV_BOARD_TWINHAN_DST, "ChainTech digitop DST-1000 DVB-S" }, | ||
393 | { 0x07711461, BTTV_BOARD_AVDVBT_771, "AVermedia AverTV DVB-T 771" }, | ||
394 | { 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" }, | ||
395 | { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" }, | ||
396 | { 0x20007063, BTTV_BOARD_PC_HDTV, "pcHDTV HD-2000 TV"}, | ||
397 | { 0, -1, NULL } | ||
398 | }; | ||
399 | |||
400 | |||
384 | /***********************/ | 401 | /***********************/ |
385 | /* PCI device handling */ | 402 | /* PCI device handling */ |
386 | /***********************/ | 403 | /***********************/ |
@@ -388,18 +405,41 @@ EXPORT_SYMBOL(bt878_device_control); | |||
388 | static int __devinit bt878_probe(struct pci_dev *dev, | 405 | static int __devinit bt878_probe(struct pci_dev *dev, |
389 | const struct pci_device_id *pci_id) | 406 | const struct pci_device_id *pci_id) |
390 | { | 407 | { |
391 | int result; | 408 | int result = 0, has_dvb = 0, i; |
392 | unsigned char lat; | 409 | unsigned char lat; |
393 | struct bt878 *bt; | 410 | struct bt878 *bt; |
394 | #if defined(__powerpc__) | 411 | #if defined(__powerpc__) |
395 | unsigned int cmd; | 412 | unsigned int cmd; |
396 | #endif | 413 | #endif |
414 | unsigned int cardid; | ||
415 | unsigned short id; | ||
416 | struct cards *dvb_cards; | ||
397 | 417 | ||
398 | printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n", | 418 | printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n", |
399 | bt878_num); | 419 | bt878_num); |
400 | if (pci_enable_device(dev)) | 420 | if (pci_enable_device(dev)) |
401 | return -EIO; | 421 | return -EIO; |
402 | 422 | ||
423 | pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &id); | ||
424 | cardid = id << 16; | ||
425 | pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID, &id); | ||
426 | cardid |= id; | ||
427 | |||
428 | for (i = 0, dvb_cards = card_list; i < ARRAY_SIZE(card_list); i++, dvb_cards++) { | ||
429 | if (cardid == dvb_cards->pci_id) { | ||
430 | printk("%s: card id=[0x%x],[ %s ] has DVB functions.\n", | ||
431 | __func__, cardid, dvb_cards->name); | ||
432 | has_dvb = 1; | ||
433 | } | ||
434 | } | ||
435 | |||
436 | if (!has_dvb) { | ||
437 | printk("%s: card id=[0x%x], Unknown card.\nExiting..\n", __func__, cardid); | ||
438 | result = -EINVAL; | ||
439 | |||
440 | goto fail0; | ||
441 | } | ||
442 | |||
403 | bt = &bt878[bt878_num]; | 443 | bt = &bt878[bt878_num]; |
404 | bt->dev = dev; | 444 | bt->dev = dev; |
405 | bt->nr = bt878_num; | 445 | bt->nr = bt878_num; |
@@ -416,6 +456,8 @@ static int __devinit bt878_probe(struct pci_dev *dev, | |||
416 | 456 | ||
417 | pci_read_config_byte(dev, PCI_CLASS_REVISION, &bt->revision); | 457 | pci_read_config_byte(dev, PCI_CLASS_REVISION, &bt->revision); |
418 | pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); | 458 | pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); |
459 | |||
460 | |||
419 | printk(KERN_INFO "bt878(%d): Bt%x (rev %d) at %02x:%02x.%x, ", | 461 | printk(KERN_INFO "bt878(%d): Bt%x (rev %d) at %02x:%02x.%x, ", |
420 | bt878_num, bt->id, bt->revision, dev->bus->number, | 462 | bt878_num, bt->id, bt->revision, dev->bus->number, |
421 | PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); | 463 | PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); |
diff --git a/drivers/media/dvb/bt8xx/bt878.h b/drivers/media/dvb/bt8xx/bt878.h index a73baf00ca39..9faf93770d08 100644 --- a/drivers/media/dvb/bt8xx/bt878.h +++ b/drivers/media/dvb/bt8xx/bt878.h | |||
@@ -88,6 +88,23 @@ | |||
88 | 88 | ||
89 | #define BT878_RISC_SYNC_MASK (1 << 15) | 89 | #define BT878_RISC_SYNC_MASK (1 << 15) |
90 | 90 | ||
91 | |||
92 | #define BTTV_BOARD_UNKNOWN 0x00 | ||
93 | #define BTTV_BOARD_PINNACLESAT 0x5e | ||
94 | #define BTTV_BOARD_NEBULA_DIGITV 0x68 | ||
95 | #define BTTV_BOARD_PC_HDTV 0x70 | ||
96 | #define BTTV_BOARD_TWINHAN_DST 0x71 | ||
97 | #define BTTV_BOARD_AVDVBT_771 0x7b | ||
98 | #define BTTV_BOARD_AVDVBT_761 0x7c | ||
99 | #define BTTV_BOARD_DVICO_DVBT_LITE 0x80 | ||
100 | #define BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE 0x87 | ||
101 | |||
102 | struct cards { | ||
103 | __u32 pci_id; | ||
104 | __u16 card_id; | ||
105 | char *name; | ||
106 | }; | ||
107 | |||
91 | extern int bt878_num; | 108 | extern int bt878_num; |
92 | 109 | ||
93 | struct bt878 { | 110 | struct bt878 { |
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 90a69d343b79..d3df12039b06 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig | |||
@@ -83,12 +83,18 @@ config DVB_USB_UMT_010 | |||
83 | Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver. | 83 | Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver. |
84 | 84 | ||
85 | config DVB_USB_CXUSB | 85 | config DVB_USB_CXUSB |
86 | tristate "Medion MD95700 hybrid USB2.0 (Conexant) support" | 86 | tristate "Conexant USB2.0 hybrid reference design support" |
87 | depends on DVB_USB | 87 | depends on DVB_USB |
88 | select DVB_CX22702 | 88 | select DVB_CX22702 |
89 | select DVB_LGDT330X | ||
90 | select DVB_MT352 | ||
89 | help | 91 | help |
90 | Say Y here to support the Medion MD95700 hybrid USB2.0 device. Currently | 92 | Say Y here to support the Conexant USB2.0 hybrid reference design. |
91 | only the DVB-T part is supported. | 93 | Currently, only DVB and ATSC modes are supported, analog mode |
94 | shall be added in the future. Devices that require this module: | ||
95 | |||
96 | Medion MD95700 hybrid USB2.0 device. | ||
97 | DViCO FusionHDTV (Bluebird) USB2.0 devices | ||
92 | 98 | ||
93 | config DVB_USB_DIGITV | 99 | config DVB_USB_DIGITV |
94 | tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support" | 100 | tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support" |
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index a7fb06f4cd34..f327fac1688e 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c | |||
@@ -184,7 +184,7 @@ static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
184 | return 0; | 184 | return 0; |
185 | } | 185 | } |
186 | 186 | ||
187 | struct dvb_usb_rc_key dvico_mce_rc_keys[] = { | 187 | static struct dvb_usb_rc_key dvico_mce_rc_keys[] = { |
188 | { 0xfe, 0x02, KEY_TV }, | 188 | { 0xfe, 0x02, KEY_TV }, |
189 | { 0xfe, 0x0e, KEY_MP3 }, | 189 | { 0xfe, 0x0e, KEY_MP3 }, |
190 | { 0xfe, 0x1a, KEY_DVD }, | 190 | { 0xfe, 0x1a, KEY_DVD }, |
@@ -234,7 +234,7 @@ struct dvb_usb_rc_key dvico_mce_rc_keys[] = { | |||
234 | 234 | ||
235 | static int cxusb_dee1601_demod_init(struct dvb_frontend* fe) | 235 | static int cxusb_dee1601_demod_init(struct dvb_frontend* fe) |
236 | { | 236 | { |
237 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x38 }; | 237 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 }; |
238 | static u8 reset [] = { RESET, 0x80 }; | 238 | static u8 reset [] = { RESET, 0x80 }; |
239 | static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; | 239 | static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; |
240 | static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 }; | 240 | static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 }; |
@@ -255,7 +255,7 @@ static int cxusb_dee1601_demod_init(struct dvb_frontend* fe) | |||
255 | 255 | ||
256 | static int cxusb_mt352_demod_init(struct dvb_frontend* fe) | 256 | static int cxusb_mt352_demod_init(struct dvb_frontend* fe) |
257 | { /* used in both lgz201 and th7579 */ | 257 | { /* used in both lgz201 and th7579 */ |
258 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 }; | 258 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x29 }; |
259 | static u8 reset [] = { RESET, 0x80 }; | 259 | static u8 reset [] = { RESET, 0x80 }; |
260 | static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; | 260 | static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; |
261 | static u8 agc_cfg [] = { AGC_TARGET, 0x24, 0x20 }; | 261 | static u8 agc_cfg [] = { AGC_TARGET, 0x24, 0x20 }; |
@@ -273,7 +273,7 @@ static int cxusb_mt352_demod_init(struct dvb_frontend* fe) | |||
273 | return 0; | 273 | return 0; |
274 | } | 274 | } |
275 | 275 | ||
276 | struct cx22702_config cxusb_cx22702_config = { | 276 | static struct cx22702_config cxusb_cx22702_config = { |
277 | .demod_address = 0x63, | 277 | .demod_address = 0x63, |
278 | 278 | ||
279 | .output_mode = CX22702_PARALLEL_OUTPUT, | 279 | .output_mode = CX22702_PARALLEL_OUTPUT, |
@@ -282,13 +282,13 @@ struct cx22702_config cxusb_cx22702_config = { | |||
282 | .pll_set = dvb_usb_pll_set_i2c, | 282 | .pll_set = dvb_usb_pll_set_i2c, |
283 | }; | 283 | }; |
284 | 284 | ||
285 | struct lgdt330x_config cxusb_lgdt330x_config = { | 285 | static struct lgdt330x_config cxusb_lgdt330x_config = { |
286 | .demod_address = 0x0e, | 286 | .demod_address = 0x0e, |
287 | .demod_chip = LGDT3303, | 287 | .demod_chip = LGDT3303, |
288 | .pll_set = dvb_usb_pll_set_i2c, | 288 | .pll_set = dvb_usb_pll_set_i2c, |
289 | }; | 289 | }; |
290 | 290 | ||
291 | struct mt352_config cxusb_dee1601_config = { | 291 | static struct mt352_config cxusb_dee1601_config = { |
292 | .demod_address = 0x0f, | 292 | .demod_address = 0x0f, |
293 | .demod_init = cxusb_dee1601_demod_init, | 293 | .demod_init = cxusb_dee1601_demod_init, |
294 | .pll_set = dvb_usb_pll_set, | 294 | .pll_set = dvb_usb_pll_set, |
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c index e6c55c9c9417..caa1346e3063 100644 --- a/drivers/media/dvb/dvb-usb/digitv.c +++ b/drivers/media/dvb/dvb-usb/digitv.c | |||
@@ -175,11 +175,13 @@ static int digitv_probe(struct usb_interface *intf, | |||
175 | if ((ret = dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE,&d)) == 0) { | 175 | if ((ret = dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE,&d)) == 0) { |
176 | u8 b[4] = { 0 }; | 176 | u8 b[4] = { 0 }; |
177 | 177 | ||
178 | b[0] = 1; | 178 | if (d != NULL) { /* do that only when the firmware is loaded */ |
179 | digitv_ctrl_msg(d,USB_WRITE_REMOTE_TYPE,0,b,4,NULL,0); | 179 | b[0] = 1; |
180 | digitv_ctrl_msg(d,USB_WRITE_REMOTE_TYPE,0,b,4,NULL,0); | ||
180 | 181 | ||
181 | b[0] = 0; | 182 | b[0] = 0; |
182 | digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0); | 183 | digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0); |
184 | } | ||
183 | } | 185 | } |
184 | return ret; | 186 | return ret; |
185 | } | 187 | } |
@@ -194,7 +196,7 @@ static struct dvb_usb_properties digitv_properties = { | |||
194 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | 196 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, |
195 | 197 | ||
196 | .usb_ctrl = CYPRESS_FX2, | 198 | .usb_ctrl = CYPRESS_FX2, |
197 | .firmware = "dvb-usb-digitv-01.fw", | 199 | .firmware = "dvb-usb-digitv-02.fw", |
198 | 200 | ||
199 | .size_of_priv = 0, | 201 | .size_of_priv = 0, |
200 | 202 | ||
@@ -229,6 +231,7 @@ static struct dvb_usb_properties digitv_properties = { | |||
229 | { &digitv_table[0], NULL }, | 231 | { &digitv_table[0], NULL }, |
230 | { NULL }, | 232 | { NULL }, |
231 | }, | 233 | }, |
234 | { NULL }, | ||
232 | } | 235 | } |
233 | }; | 236 | }; |
234 | 237 | ||
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c index 130ea7f21f5e..12ebaf8bddca 100644 --- a/drivers/media/dvb/dvb-usb/dtt200u.c +++ b/drivers/media/dvb/dvb-usb/dtt200u.c | |||
@@ -151,7 +151,7 @@ static struct dvb_usb_properties dtt200u_properties = { | |||
151 | .cold_ids = { &dtt200u_usb_table[0], NULL }, | 151 | .cold_ids = { &dtt200u_usb_table[0], NULL }, |
152 | .warm_ids = { &dtt200u_usb_table[1], NULL }, | 152 | .warm_ids = { &dtt200u_usb_table[1], NULL }, |
153 | }, | 153 | }, |
154 | { 0 }, | 154 | { NULL }, |
155 | } | 155 | } |
156 | }; | 156 | }; |
157 | 157 | ||
@@ -192,7 +192,7 @@ static struct dvb_usb_properties wt220u_properties = { | |||
192 | .cold_ids = { &dtt200u_usb_table[2], NULL }, | 192 | .cold_ids = { &dtt200u_usb_table[2], NULL }, |
193 | .warm_ids = { &dtt200u_usb_table[3], NULL }, | 193 | .warm_ids = { &dtt200u_usb_table[3], NULL }, |
194 | }, | 194 | }, |
195 | { 0 }, | 195 | { NULL }, |
196 | } | 196 | } |
197 | }; | 197 | }; |
198 | 198 | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c index 8535895819fb..9222b0a81f74 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c | |||
@@ -24,6 +24,9 @@ static struct usb_cypress_controller cypress[] = { | |||
24 | { .id = CYPRESS_FX2, .name = "Cypress FX2", .cpu_cs_register = 0xe600 }, | 24 | { .id = CYPRESS_FX2, .name = "Cypress FX2", .cpu_cs_register = 0xe600 }, |
25 | }; | 25 | }; |
26 | 26 | ||
27 | static int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, | ||
28 | int *pos); | ||
29 | |||
27 | /* | 30 | /* |
28 | * load a firmware packet to the device | 31 | * load a firmware packet to the device |
29 | */ | 32 | */ |
@@ -112,7 +115,8 @@ int dvb_usb_download_firmware(struct usb_device *udev, struct dvb_usb_properties | |||
112 | return ret; | 115 | return ret; |
113 | } | 116 | } |
114 | 117 | ||
115 | int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, int *pos) | 118 | static int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, |
119 | int *pos) | ||
116 | { | 120 | { |
117 | u8 *b = (u8 *) &fw->data[*pos]; | 121 | u8 *b = (u8 *) &fw->data[*pos]; |
118 | int data_offs = 4; | 122 | int data_offs = 4; |
@@ -142,5 +146,3 @@ int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, int *pos) | |||
142 | 146 | ||
143 | return *pos; | 147 | return *pos; |
144 | } | 148 | } |
145 | EXPORT_SYMBOL(dvb_usb_get_hexline); | ||
146 | |||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h index dd568396e594..5e5d21ad93c9 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb.h | |||
@@ -341,7 +341,6 @@ struct hexline { | |||
341 | u8 data[255]; | 341 | u8 data[255]; |
342 | u8 chk; | 342 | u8 chk; |
343 | }; | 343 | }; |
344 | extern int dvb_usb_get_hexline(const struct firmware *, struct hexline *, int *); | ||
345 | extern int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type); | 344 | extern int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type); |
346 | 345 | ||
347 | #endif | 346 | #endif |
diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c index afa00fdb5ec0..4a95eca81c5c 100644 --- a/drivers/media/dvb/dvb-usb/vp702x.c +++ b/drivers/media/dvb/dvb-usb/vp702x.c | |||
@@ -53,7 +53,8 @@ int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 | |||
53 | return ret; | 53 | return ret; |
54 | } | 54 | } |
55 | 55 | ||
56 | int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) | 56 | static int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, |
57 | u16 index, u8 *b, int blen) | ||
57 | { | 58 | { |
58 | deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index); | 59 | deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index); |
59 | debug_dump(b,blen,deb_xfer); | 60 | debug_dump(b,blen,deb_xfer); |
@@ -88,7 +89,8 @@ unlock: | |||
88 | return ret; | 89 | return ret; |
89 | } | 90 | } |
90 | 91 | ||
91 | int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, int olen, u8 *i, int ilen, int msec) | 92 | static int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, |
93 | int olen, u8 *i, int ilen, int msec) | ||
92 | { | 94 | { |
93 | u8 bout[olen+2]; | 95 | u8 bout[olen+2]; |
94 | u8 bin[ilen+1]; | 96 | u8 bin[ilen+1]; |
diff --git a/drivers/media/dvb/dvb-usb/vp702x.h b/drivers/media/dvb/dvb-usb/vp702x.h index a808d48e7bf2..c2f97f96c21f 100644 --- a/drivers/media/dvb/dvb-usb/vp702x.h +++ b/drivers/media/dvb/dvb-usb/vp702x.h | |||
@@ -101,8 +101,6 @@ extern int dvb_usb_vp702x_debug; | |||
101 | extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d); | 101 | extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d); |
102 | 102 | ||
103 | extern int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec); | 103 | extern int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec); |
104 | extern int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, int olen, u8 *i, int ilen, int msec); | ||
105 | extern int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen); | 104 | extern int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen); |
106 | extern int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen); | ||
107 | 105 | ||
108 | #endif | 106 | #endif |
diff --git a/drivers/media/dvb/dvb-usb/vp7045-fe.c b/drivers/media/dvb/dvb-usb/vp7045-fe.c index 5242cca5db4a..9999336aeeb6 100644 --- a/drivers/media/dvb/dvb-usb/vp7045-fe.c +++ b/drivers/media/dvb/dvb-usb/vp7045-fe.c | |||
@@ -23,10 +23,11 @@ | |||
23 | 23 | ||
24 | struct vp7045_fe_state { | 24 | struct vp7045_fe_state { |
25 | struct dvb_frontend fe; | 25 | struct dvb_frontend fe; |
26 | struct dvb_frontend_ops ops; | ||
27 | |||
26 | struct dvb_usb_device *d; | 28 | struct dvb_usb_device *d; |
27 | }; | 29 | }; |
28 | 30 | ||
29 | |||
30 | static int vp7045_fe_read_status(struct dvb_frontend* fe, fe_status_t *status) | 31 | static int vp7045_fe_read_status(struct dvb_frontend* fe, fe_status_t *status) |
31 | { | 32 | { |
32 | struct vp7045_fe_state *state = fe->demodulator_priv; | 33 | struct vp7045_fe_state *state = fe->demodulator_priv; |
@@ -150,7 +151,8 @@ struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d) | |||
150 | goto error; | 151 | goto error; |
151 | 152 | ||
152 | s->d = d; | 153 | s->d = d; |
153 | s->fe.ops = &vp7045_fe_ops; | 154 | memcpy(&s->ops, &vp7045_fe_ops, sizeof(struct dvb_frontend_ops)); |
155 | s->fe.ops = &s->ops; | ||
154 | s->fe.demodulator_priv = s; | 156 | s->fe.demodulator_priv = s; |
155 | 157 | ||
156 | goto success; | 158 | goto success; |
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c index 028204956bb0..3835235b68df 100644 --- a/drivers/media/dvb/dvb-usb/vp7045.c +++ b/drivers/media/dvb/dvb-usb/vp7045.c | |||
@@ -247,7 +247,7 @@ static struct dvb_usb_properties vp7045_properties = { | |||
247 | .cold_ids = { &vp7045_usb_table[2], NULL }, | 247 | .cold_ids = { &vp7045_usb_table[2], NULL }, |
248 | .warm_ids = { &vp7045_usb_table[3], NULL }, | 248 | .warm_ids = { &vp7045_usb_table[3], NULL }, |
249 | }, | 249 | }, |
250 | { 0 }, | 250 | { NULL }, |
251 | } | 251 | } |
252 | }; | 252 | }; |
253 | 253 | ||
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index db3a8b40031e..76b6a2aef32f 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig | |||
@@ -28,12 +28,6 @@ config DVB_TDA8083 | |||
28 | help | 28 | help |
29 | A DVB-S tuner module. Say Y when you want to support this frontend. | 29 | A DVB-S tuner module. Say Y when you want to support this frontend. |
30 | 30 | ||
31 | config DVB_TDA80XX | ||
32 | tristate "Philips TDA8044 or TDA8083 based" | ||
33 | depends on DVB_CORE | ||
34 | help | ||
35 | A DVB-S tuner module. Say Y when you want to support this frontend. | ||
36 | |||
37 | config DVB_MT312 | 31 | config DVB_MT312 |
38 | tristate "Zarlink MT312 based" | 32 | tristate "Zarlink MT312 based" |
39 | depends on DVB_CORE | 33 | depends on DVB_CORE |
@@ -139,12 +133,6 @@ config DVB_DIB3000MC | |||
139 | comment "DVB-C (cable) frontends" | 133 | comment "DVB-C (cable) frontends" |
140 | depends on DVB_CORE | 134 | depends on DVB_CORE |
141 | 135 | ||
142 | config DVB_ATMEL_AT76C651 | ||
143 | tristate "Atmel AT76C651 based" | ||
144 | depends on DVB_CORE | ||
145 | help | ||
146 | A DVB-C tuner module. Say Y when you want to support this frontend. | ||
147 | |||
148 | config DVB_VES1820 | 136 | config DVB_VES1820 |
149 | tristate "VLSI VES1820 based" | 137 | tristate "VLSI VES1820 based" |
150 | depends on DVB_CORE | 138 | depends on DVB_CORE |
@@ -166,18 +154,6 @@ config DVB_STV0297 | |||
166 | comment "ATSC (North American/Korean Terresterial DTV) frontends" | 154 | comment "ATSC (North American/Korean Terresterial DTV) frontends" |
167 | depends on DVB_CORE | 155 | depends on DVB_CORE |
168 | 156 | ||
169 | config DVB_NXT2002 | ||
170 | tristate "Nxt2002 based" | ||
171 | depends on DVB_CORE | ||
172 | select FW_LOADER | ||
173 | help | ||
174 | An ATSC 8VSB tuner module. Say Y when you want to support this frontend. | ||
175 | |||
176 | This driver needs external firmware. Please use the command | ||
177 | "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" to | ||
178 | download/extract it, and then copy it to /usr/lib/hotplug/firmware | ||
179 | or /lib/firmware (depending on configuration of firmware hotplug). | ||
180 | |||
181 | config DVB_NXT200X | 157 | config DVB_NXT200X |
182 | tristate "Nextwave NXT2002/NXT2004 based" | 158 | tristate "Nextwave NXT2002/NXT2004 based" |
183 | depends on DVB_CORE | 159 | depends on DVB_CORE |
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 615ec830e1c9..1af769cd90c0 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile | |||
@@ -8,7 +8,6 @@ obj-$(CONFIG_DVB_CORE) += dvb-pll.o | |||
8 | obj-$(CONFIG_DVB_STV0299) += stv0299.o | 8 | obj-$(CONFIG_DVB_STV0299) += stv0299.o |
9 | obj-$(CONFIG_DVB_SP8870) += sp8870.o | 9 | obj-$(CONFIG_DVB_SP8870) += sp8870.o |
10 | obj-$(CONFIG_DVB_CX22700) += cx22700.o | 10 | obj-$(CONFIG_DVB_CX22700) += cx22700.o |
11 | obj-$(CONFIG_DVB_ATMEL_AT76C651) += at76c651.o | ||
12 | obj-$(CONFIG_DVB_CX24110) += cx24110.o | 11 | obj-$(CONFIG_DVB_CX24110) += cx24110.o |
13 | obj-$(CONFIG_DVB_TDA8083) += tda8083.o | 12 | obj-$(CONFIG_DVB_TDA8083) += tda8083.o |
14 | obj-$(CONFIG_DVB_L64781) += l64781.o | 13 | obj-$(CONFIG_DVB_L64781) += l64781.o |
@@ -22,10 +21,8 @@ obj-$(CONFIG_DVB_SP887X) += sp887x.o | |||
22 | obj-$(CONFIG_DVB_NXT6000) += nxt6000.o | 21 | obj-$(CONFIG_DVB_NXT6000) += nxt6000.o |
23 | obj-$(CONFIG_DVB_MT352) += mt352.o | 22 | obj-$(CONFIG_DVB_MT352) += mt352.o |
24 | obj-$(CONFIG_DVB_CX22702) += cx22702.o | 23 | obj-$(CONFIG_DVB_CX22702) += cx22702.o |
25 | obj-$(CONFIG_DVB_TDA80XX) += tda80xx.o | ||
26 | obj-$(CONFIG_DVB_TDA10021) += tda10021.o | 24 | obj-$(CONFIG_DVB_TDA10021) += tda10021.o |
27 | obj-$(CONFIG_DVB_STV0297) += stv0297.o | 25 | obj-$(CONFIG_DVB_STV0297) += stv0297.o |
28 | obj-$(CONFIG_DVB_NXT2002) += nxt2002.o | ||
29 | obj-$(CONFIG_DVB_NXT200X) += nxt200x.o | 26 | obj-$(CONFIG_DVB_NXT200X) += nxt200x.o |
30 | obj-$(CONFIG_DVB_OR51211) += or51211.o | 27 | obj-$(CONFIG_DVB_OR51211) += or51211.o |
31 | obj-$(CONFIG_DVB_OR51132) += or51132.o | 28 | obj-$(CONFIG_DVB_OR51132) += or51132.o |
diff --git a/drivers/media/dvb/frontends/at76c651.c b/drivers/media/dvb/frontends/at76c651.c deleted file mode 100644 index 8e0f4b3a1417..000000000000 --- a/drivers/media/dvb/frontends/at76c651.c +++ /dev/null | |||
@@ -1,450 +0,0 @@ | |||
1 | /* | ||
2 | * at76c651.c | ||
3 | * | ||
4 | * Atmel DVB-C Frontend Driver (at76c651/tua6010xs) | ||
5 | * | ||
6 | * Copyright (C) 2001 fnbrd <fnbrd@gmx.de> | ||
7 | * & 2002-2004 Andreas Oberritter <obi@linuxtv.org> | ||
8 | * & 2003 Wolfram Joost <dbox2@frokaschwei.de> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | * | ||
24 | * AT76C651 | ||
25 | * http://www.nalanda.nitc.ac.in/industry/datasheets/atmel/acrobat/doc1293.pdf | ||
26 | * http://www.atmel.com/atmel/acrobat/doc1320.pdf | ||
27 | */ | ||
28 | |||
29 | #include <linux/init.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/moduleparam.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/string.h> | ||
34 | #include <linux/slab.h> | ||
35 | #include <linux/bitops.h> | ||
36 | #include "dvb_frontend.h" | ||
37 | #include "at76c651.h" | ||
38 | |||
39 | |||
40 | struct at76c651_state { | ||
41 | |||
42 | struct i2c_adapter* i2c; | ||
43 | |||
44 | struct dvb_frontend_ops ops; | ||
45 | |||
46 | const struct at76c651_config* config; | ||
47 | |||
48 | struct dvb_frontend frontend; | ||
49 | |||
50 | /* revision of the chip */ | ||
51 | u8 revision; | ||
52 | |||
53 | /* last QAM value set */ | ||
54 | u8 qam; | ||
55 | }; | ||
56 | |||
57 | static int debug; | ||
58 | #define dprintk(args...) \ | ||
59 | do { \ | ||
60 | if (debug) printk(KERN_DEBUG "at76c651: " args); \ | ||
61 | } while (0) | ||
62 | |||
63 | |||
64 | #if ! defined(__powerpc__) | ||
65 | static __inline__ int __ilog2(unsigned long x) | ||
66 | { | ||
67 | int i; | ||
68 | |||
69 | if (x == 0) | ||
70 | return -1; | ||
71 | |||
72 | for (i = 0; x != 0; i++) | ||
73 | x >>= 1; | ||
74 | |||
75 | return i - 1; | ||
76 | } | ||
77 | #endif | ||
78 | |||
79 | static int at76c651_writereg(struct at76c651_state* state, u8 reg, u8 data) | ||
80 | { | ||
81 | int ret; | ||
82 | u8 buf[] = { reg, data }; | ||
83 | struct i2c_msg msg = | ||
84 | { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 }; | ||
85 | |||
86 | ret = i2c_transfer(state->i2c, &msg, 1); | ||
87 | |||
88 | if (ret != 1) | ||
89 | dprintk("%s: writereg error " | ||
90 | "(reg == 0x%02x, val == 0x%02x, ret == %i)\n", | ||
91 | __FUNCTION__, reg, data, ret); | ||
92 | |||
93 | msleep(10); | ||
94 | |||
95 | return (ret != 1) ? -EREMOTEIO : 0; | ||
96 | } | ||
97 | |||
98 | static u8 at76c651_readreg(struct at76c651_state* state, u8 reg) | ||
99 | { | ||
100 | int ret; | ||
101 | u8 val; | ||
102 | struct i2c_msg msg[] = { | ||
103 | { .addr = state->config->demod_address, .flags = 0, .buf = ®, .len = 1 }, | ||
104 | { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = &val, .len = 1 } | ||
105 | }; | ||
106 | |||
107 | ret = i2c_transfer(state->i2c, msg, 2); | ||
108 | |||
109 | if (ret != 2) | ||
110 | dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); | ||
111 | |||
112 | return val; | ||
113 | } | ||
114 | |||
115 | static int at76c651_reset(struct at76c651_state* state) | ||
116 | { | ||
117 | return at76c651_writereg(state, 0x07, 0x01); | ||
118 | } | ||
119 | |||
120 | static void at76c651_disable_interrupts(struct at76c651_state* state) | ||
121 | { | ||
122 | at76c651_writereg(state, 0x0b, 0x00); | ||
123 | } | ||
124 | |||
125 | static int at76c651_set_auto_config(struct at76c651_state *state) | ||
126 | { | ||
127 | /* | ||
128 | * Autoconfig | ||
129 | */ | ||
130 | |||
131 | at76c651_writereg(state, 0x06, 0x01); | ||
132 | |||
133 | /* | ||
134 | * Performance optimizations, should be done after autoconfig | ||
135 | */ | ||
136 | |||
137 | at76c651_writereg(state, 0x10, 0x06); | ||
138 | at76c651_writereg(state, 0x11, ((state->qam == 5) || (state->qam == 7)) ? 0x12 : 0x10); | ||
139 | at76c651_writereg(state, 0x15, 0x28); | ||
140 | at76c651_writereg(state, 0x20, 0x09); | ||
141 | at76c651_writereg(state, 0x24, ((state->qam == 5) || (state->qam == 7)) ? 0xC0 : 0x90); | ||
142 | at76c651_writereg(state, 0x30, 0x90); | ||
143 | if (state->qam == 5) | ||
144 | at76c651_writereg(state, 0x35, 0x2A); | ||
145 | |||
146 | /* | ||
147 | * Initialize A/D-converter | ||
148 | */ | ||
149 | |||
150 | if (state->revision == 0x11) { | ||
151 | at76c651_writereg(state, 0x2E, 0x38); | ||
152 | at76c651_writereg(state, 0x2F, 0x13); | ||
153 | } | ||
154 | |||
155 | at76c651_disable_interrupts(state); | ||
156 | |||
157 | /* | ||
158 | * Restart operation | ||
159 | */ | ||
160 | |||
161 | at76c651_reset(state); | ||
162 | |||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | static void at76c651_set_bbfreq(struct at76c651_state* state) | ||
167 | { | ||
168 | at76c651_writereg(state, 0x04, 0x3f); | ||
169 | at76c651_writereg(state, 0x05, 0xee); | ||
170 | } | ||
171 | |||
172 | static int at76c651_set_symbol_rate(struct at76c651_state* state, u32 symbol_rate) | ||
173 | { | ||
174 | u8 exponent; | ||
175 | u32 mantissa; | ||
176 | |||
177 | if (symbol_rate > 9360000) | ||
178 | return -EINVAL; | ||
179 | |||
180 | /* | ||
181 | * FREF = 57800 kHz | ||
182 | * exponent = 10 + floor (log2(symbol_rate / FREF)) | ||
183 | * mantissa = (symbol_rate / FREF) * (1 << (30 - exponent)) | ||
184 | */ | ||
185 | |||
186 | exponent = __ilog2((symbol_rate << 4) / 903125); | ||
187 | mantissa = ((symbol_rate / 3125) * (1 << (24 - exponent))) / 289; | ||
188 | |||
189 | at76c651_writereg(state, 0x00, mantissa >> 13); | ||
190 | at76c651_writereg(state, 0x01, mantissa >> 5); | ||
191 | at76c651_writereg(state, 0x02, (mantissa << 3) | exponent); | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | static int at76c651_set_qam(struct at76c651_state *state, fe_modulation_t qam) | ||
197 | { | ||
198 | switch (qam) { | ||
199 | case QPSK: | ||
200 | state->qam = 0x02; | ||
201 | break; | ||
202 | case QAM_16: | ||
203 | state->qam = 0x04; | ||
204 | break; | ||
205 | case QAM_32: | ||
206 | state->qam = 0x05; | ||
207 | break; | ||
208 | case QAM_64: | ||
209 | state->qam = 0x06; | ||
210 | break; | ||
211 | case QAM_128: | ||
212 | state->qam = 0x07; | ||
213 | break; | ||
214 | case QAM_256: | ||
215 | state->qam = 0x08; | ||
216 | break; | ||
217 | #if 0 | ||
218 | case QAM_512: | ||
219 | state->qam = 0x09; | ||
220 | break; | ||
221 | case QAM_1024: | ||
222 | state->qam = 0x0A; | ||
223 | break; | ||
224 | #endif | ||
225 | default: | ||
226 | return -EINVAL; | ||
227 | |||
228 | } | ||
229 | |||
230 | return at76c651_writereg(state, 0x03, state->qam); | ||
231 | } | ||
232 | |||
233 | static int at76c651_set_inversion(struct at76c651_state* state, fe_spectral_inversion_t inversion) | ||
234 | { | ||
235 | u8 feciqinv = at76c651_readreg(state, 0x60); | ||
236 | |||
237 | switch (inversion) { | ||
238 | case INVERSION_OFF: | ||
239 | feciqinv |= 0x02; | ||
240 | feciqinv &= 0xFE; | ||
241 | break; | ||
242 | |||
243 | case INVERSION_ON: | ||
244 | feciqinv |= 0x03; | ||
245 | break; | ||
246 | |||
247 | case INVERSION_AUTO: | ||
248 | feciqinv &= 0xFC; | ||
249 | break; | ||
250 | |||
251 | default: | ||
252 | return -EINVAL; | ||
253 | } | ||
254 | |||
255 | return at76c651_writereg(state, 0x60, feciqinv); | ||
256 | } | ||
257 | |||
258 | static int at76c651_set_parameters(struct dvb_frontend* fe, | ||
259 | struct dvb_frontend_parameters *p) | ||
260 | { | ||
261 | int ret; | ||
262 | struct at76c651_state* state = fe->demodulator_priv; | ||
263 | |||
264 | at76c651_writereg(state, 0x0c, 0xc3); | ||
265 | state->config->pll_set(fe, p); | ||
266 | at76c651_writereg(state, 0x0c, 0xc2); | ||
267 | |||
268 | if ((ret = at76c651_set_symbol_rate(state, p->u.qam.symbol_rate))) | ||
269 | return ret; | ||
270 | |||
271 | if ((ret = at76c651_set_inversion(state, p->inversion))) | ||
272 | return ret; | ||
273 | |||
274 | return at76c651_set_auto_config(state); | ||
275 | } | ||
276 | |||
277 | static int at76c651_set_defaults(struct dvb_frontend* fe) | ||
278 | { | ||
279 | struct at76c651_state* state = fe->demodulator_priv; | ||
280 | |||
281 | at76c651_set_symbol_rate(state, 6900000); | ||
282 | at76c651_set_qam(state, QAM_64); | ||
283 | at76c651_set_bbfreq(state); | ||
284 | at76c651_set_auto_config(state); | ||
285 | |||
286 | if (state->config->pll_init) { | ||
287 | at76c651_writereg(state, 0x0c, 0xc3); | ||
288 | state->config->pll_init(fe); | ||
289 | at76c651_writereg(state, 0x0c, 0xc2); | ||
290 | } | ||
291 | |||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | static int at76c651_read_status(struct dvb_frontend* fe, fe_status_t* status) | ||
296 | { | ||
297 | struct at76c651_state* state = fe->demodulator_priv; | ||
298 | u8 sync; | ||
299 | |||
300 | /* | ||
301 | * Bits: FEC, CAR, EQU, TIM, AGC2, AGC1, ADC, PLL (PLL=0) | ||
302 | */ | ||
303 | sync = at76c651_readreg(state, 0x80); | ||
304 | *status = 0; | ||
305 | |||
306 | if (sync & (0x04 | 0x10)) /* AGC1 || TIM */ | ||
307 | *status |= FE_HAS_SIGNAL; | ||
308 | if (sync & 0x10) /* TIM */ | ||
309 | *status |= FE_HAS_CARRIER; | ||
310 | if (sync & 0x80) /* FEC */ | ||
311 | *status |= FE_HAS_VITERBI; | ||
312 | if (sync & 0x40) /* CAR */ | ||
313 | *status |= FE_HAS_SYNC; | ||
314 | if ((sync & 0xF0) == 0xF0) /* TIM && EQU && CAR && FEC */ | ||
315 | *status |= FE_HAS_LOCK; | ||
316 | |||
317 | return 0; | ||
318 | } | ||
319 | |||
320 | static int at76c651_read_ber(struct dvb_frontend* fe, u32* ber) | ||
321 | { | ||
322 | struct at76c651_state* state = fe->demodulator_priv; | ||
323 | |||
324 | *ber = (at76c651_readreg(state, 0x81) & 0x0F) << 16; | ||
325 | *ber |= at76c651_readreg(state, 0x82) << 8; | ||
326 | *ber |= at76c651_readreg(state, 0x83); | ||
327 | *ber *= 10; | ||
328 | |||
329 | return 0; | ||
330 | } | ||
331 | |||
332 | static int at76c651_read_signal_strength(struct dvb_frontend* fe, u16* strength) | ||
333 | { | ||
334 | struct at76c651_state* state = fe->demodulator_priv; | ||
335 | |||
336 | u8 gain = ~at76c651_readreg(state, 0x91); | ||
337 | *strength = (gain << 8) | gain; | ||
338 | |||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | static int at76c651_read_snr(struct dvb_frontend* fe, u16* snr) | ||
343 | { | ||
344 | struct at76c651_state* state = fe->demodulator_priv; | ||
345 | |||
346 | *snr = 0xFFFF - | ||
347 | ((at76c651_readreg(state, 0x8F) << 8) | | ||
348 | at76c651_readreg(state, 0x90)); | ||
349 | |||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | static int at76c651_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) | ||
354 | { | ||
355 | struct at76c651_state* state = fe->demodulator_priv; | ||
356 | |||
357 | *ucblocks = at76c651_readreg(state, 0x82); | ||
358 | |||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | static int at76c651_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *fesettings) | ||
363 | { | ||
364 | fesettings->min_delay_ms = 50; | ||
365 | fesettings->step_size = 0; | ||
366 | fesettings->max_drift = 0; | ||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | static void at76c651_release(struct dvb_frontend* fe) | ||
371 | { | ||
372 | struct at76c651_state* state = fe->demodulator_priv; | ||
373 | kfree(state); | ||
374 | } | ||
375 | |||
376 | static struct dvb_frontend_ops at76c651_ops; | ||
377 | |||
378 | struct dvb_frontend* at76c651_attach(const struct at76c651_config* config, | ||
379 | struct i2c_adapter* i2c) | ||
380 | { | ||
381 | struct at76c651_state* state = NULL; | ||
382 | |||
383 | /* allocate memory for the internal state */ | ||
384 | state = kmalloc(sizeof(struct at76c651_state), GFP_KERNEL); | ||
385 | if (state == NULL) goto error; | ||
386 | |||
387 | /* setup the state */ | ||
388 | state->config = config; | ||
389 | state->qam = 0; | ||
390 | |||
391 | /* check if the demod is there */ | ||
392 | if (at76c651_readreg(state, 0x0e) != 0x65) goto error; | ||
393 | |||
394 | /* finalise state setup */ | ||
395 | state->i2c = i2c; | ||
396 | state->revision = at76c651_readreg(state, 0x0f) & 0xfe; | ||
397 | memcpy(&state->ops, &at76c651_ops, sizeof(struct dvb_frontend_ops)); | ||
398 | |||
399 | /* create dvb_frontend */ | ||
400 | state->frontend.ops = &state->ops; | ||
401 | state->frontend.demodulator_priv = state; | ||
402 | return &state->frontend; | ||
403 | |||
404 | error: | ||
405 | kfree(state); | ||
406 | return NULL; | ||
407 | } | ||
408 | |||
409 | static struct dvb_frontend_ops at76c651_ops = { | ||
410 | |||
411 | .info = { | ||
412 | .name = "Atmel AT76C651B DVB-C", | ||
413 | .type = FE_QAM, | ||
414 | .frequency_min = 48250000, | ||
415 | .frequency_max = 863250000, | ||
416 | .frequency_stepsize = 62500, | ||
417 | /*.frequency_tolerance = */ /* FIXME: 12% of SR */ | ||
418 | .symbol_rate_min = 0, /* FIXME */ | ||
419 | .symbol_rate_max = 9360000, /* FIXME */ | ||
420 | .symbol_rate_tolerance = 4000, | ||
421 | .caps = FE_CAN_INVERSION_AUTO | | ||
422 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
423 | FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | | ||
424 | FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | | ||
425 | FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | FE_CAN_QAM_128 | | ||
426 | FE_CAN_MUTE_TS | FE_CAN_QAM_256 | FE_CAN_RECOVER | ||
427 | }, | ||
428 | |||
429 | .release = at76c651_release, | ||
430 | |||
431 | .init = at76c651_set_defaults, | ||
432 | |||
433 | .set_frontend = at76c651_set_parameters, | ||
434 | .get_tune_settings = at76c651_get_tune_settings, | ||
435 | |||
436 | .read_status = at76c651_read_status, | ||
437 | .read_ber = at76c651_read_ber, | ||
438 | .read_signal_strength = at76c651_read_signal_strength, | ||
439 | .read_snr = at76c651_read_snr, | ||
440 | .read_ucblocks = at76c651_read_ucblocks, | ||
441 | }; | ||
442 | |||
443 | module_param(debug, int, 0644); | ||
444 | MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); | ||
445 | |||
446 | MODULE_DESCRIPTION("Atmel AT76C651 DVB-C Demodulator Driver"); | ||
447 | MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>"); | ||
448 | MODULE_LICENSE("GPL"); | ||
449 | |||
450 | EXPORT_SYMBOL(at76c651_attach); | ||
diff --git a/drivers/media/dvb/frontends/at76c651.h b/drivers/media/dvb/frontends/at76c651.h deleted file mode 100644 index 34054df93608..000000000000 --- a/drivers/media/dvb/frontends/at76c651.h +++ /dev/null | |||
@@ -1,47 +0,0 @@ | |||
1 | /* | ||
2 | * at76c651.c | ||
3 | * | ||
4 | * Atmel DVB-C Frontend Driver (at76c651) | ||
5 | * | ||
6 | * Copyright (C) 2001 fnbrd <fnbrd@gmx.de> | ||
7 | * & 2002-2004 Andreas Oberritter <obi@linuxtv.org> | ||
8 | * & 2003 Wolfram Joost <dbox2@frokaschwei.de> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | * | ||
24 | * AT76C651 | ||
25 | * http://www.nalanda.nitc.ac.in/industry/datasheets/atmel/acrobat/doc1293.pdf | ||
26 | * http://www.atmel.com/atmel/acrobat/doc1320.pdf | ||
27 | */ | ||
28 | |||
29 | #ifndef AT76C651_H | ||
30 | #define AT76C651_H | ||
31 | |||
32 | #include <linux/dvb/frontend.h> | ||
33 | |||
34 | struct at76c651_config | ||
35 | { | ||
36 | /* the demodulator's i2c address */ | ||
37 | u8 demod_address; | ||
38 | |||
39 | /* PLL maintenance */ | ||
40 | int (*pll_init)(struct dvb_frontend* fe); | ||
41 | int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); | ||
42 | }; | ||
43 | |||
44 | extern struct dvb_frontend* at76c651_attach(const struct at76c651_config* config, | ||
45 | struct i2c_adapter* i2c); | ||
46 | |||
47 | #endif // AT76C651_H | ||
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 1b9934ea5b06..4dcb6050d4fa 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c | |||
@@ -326,11 +326,11 @@ struct dvb_pll_desc dvb_pll_tuv1236d = { | |||
326 | }; | 326 | }; |
327 | EXPORT_SYMBOL(dvb_pll_tuv1236d); | 327 | EXPORT_SYMBOL(dvb_pll_tuv1236d); |
328 | 328 | ||
329 | /* Samsung TBMV30111IN | 329 | /* Samsung TBMV30111IN / TBMV30712IN1 |
330 | * used in Air2PC ATSC - 2nd generation (nxt2002) | 330 | * used in Air2PC ATSC - 2nd generation (nxt2002) |
331 | */ | 331 | */ |
332 | struct dvb_pll_desc dvb_pll_tbmv30111in = { | 332 | struct dvb_pll_desc dvb_pll_samsung_tbmv = { |
333 | .name = "Samsung TBMV30111IN", | 333 | .name = "Samsung TBMV30111IN / TBMV30712IN1", |
334 | .min = 54000000, | 334 | .min = 54000000, |
335 | .max = 860000000, | 335 | .max = 860000000, |
336 | .count = 6, | 336 | .count = 6, |
@@ -343,7 +343,7 @@ struct dvb_pll_desc dvb_pll_tbmv30111in = { | |||
343 | { 999999999, 44000000, 166666, 0xfc, 0x02 }, | 343 | { 999999999, 44000000, 166666, 0xfc, 0x02 }, |
344 | } | 344 | } |
345 | }; | 345 | }; |
346 | EXPORT_SYMBOL(dvb_pll_tbmv30111in); | 346 | EXPORT_SYMBOL(dvb_pll_samsung_tbmv); |
347 | 347 | ||
348 | /* | 348 | /* |
349 | * Philips SD1878 Tuner. | 349 | * Philips SD1878 Tuner. |
diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index f682c09189b3..bb8d4b4eb183 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h | |||
@@ -38,7 +38,7 @@ extern struct dvb_pll_desc dvb_pll_tded4; | |||
38 | 38 | ||
39 | extern struct dvb_pll_desc dvb_pll_tuv1236d; | 39 | extern struct dvb_pll_desc dvb_pll_tuv1236d; |
40 | extern struct dvb_pll_desc dvb_pll_tdhu2; | 40 | extern struct dvb_pll_desc dvb_pll_tdhu2; |
41 | extern struct dvb_pll_desc dvb_pll_tbmv30111in; | 41 | extern struct dvb_pll_desc dvb_pll_samsung_tbmv; |
42 | extern struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261; | 42 | extern struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261; |
43 | 43 | ||
44 | int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, | 44 | int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, |
diff --git a/drivers/media/dvb/frontends/nxt2002.c b/drivers/media/dvb/frontends/nxt2002.c deleted file mode 100644 index 4f263e65ba14..000000000000 --- a/drivers/media/dvb/frontends/nxt2002.c +++ /dev/null | |||
@@ -1,706 +0,0 @@ | |||
1 | /* | ||
2 | Support for B2C2/BBTI Technisat Air2PC - ATSC | ||
3 | |||
4 | Copyright (C) 2004 Taylor Jacob <rtjacob@earthlink.net> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | |||
20 | */ | ||
21 | |||
22 | /* | ||
23 | * This driver needs external firmware. Please use the command | ||
24 | * "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" to | ||
25 | * download/extract it, and then copy it to /usr/lib/hotplug/firmware | ||
26 | * or /lib/firmware (depending on configuration of firmware hotplug). | ||
27 | */ | ||
28 | #define NXT2002_DEFAULT_FIRMWARE "dvb-fe-nxt2002.fw" | ||
29 | #define CRC_CCIT_MASK 0x1021 | ||
30 | |||
31 | #include <linux/init.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/moduleparam.h> | ||
34 | #include <linux/device.h> | ||
35 | #include <linux/firmware.h> | ||
36 | #include <linux/string.h> | ||
37 | #include <linux/slab.h> | ||
38 | |||
39 | #include "dvb_frontend.h" | ||
40 | #include "nxt2002.h" | ||
41 | |||
42 | struct nxt2002_state { | ||
43 | |||
44 | struct i2c_adapter* i2c; | ||
45 | struct dvb_frontend_ops ops; | ||
46 | const struct nxt2002_config* config; | ||
47 | struct dvb_frontend frontend; | ||
48 | |||
49 | /* demodulator private data */ | ||
50 | u8 initialised:1; | ||
51 | }; | ||
52 | |||
53 | static int debug; | ||
54 | #define dprintk(args...) \ | ||
55 | do { \ | ||
56 | if (debug) printk(KERN_DEBUG "nxt2002: " args); \ | ||
57 | } while (0) | ||
58 | |||
59 | static int i2c_writebytes (struct nxt2002_state* state, u8 reg, u8 *buf, u8 len) | ||
60 | { | ||
61 | /* probbably a much better way or doing this */ | ||
62 | u8 buf2 [256],x; | ||
63 | int err; | ||
64 | struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf2, .len = len + 1 }; | ||
65 | |||
66 | buf2[0] = reg; | ||
67 | for (x = 0 ; x < len ; x++) | ||
68 | buf2[x+1] = buf[x]; | ||
69 | |||
70 | if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) { | ||
71 | printk ("%s: i2c write error (addr %02x, err == %i)\n", | ||
72 | __FUNCTION__, state->config->demod_address, err); | ||
73 | return -EREMOTEIO; | ||
74 | } | ||
75 | |||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static u8 i2c_readbytes (struct nxt2002_state* state, u8 reg, u8* buf, u8 len) | ||
80 | { | ||
81 | u8 reg2 [] = { reg }; | ||
82 | |||
83 | struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = reg2, .len = 1 }, | ||
84 | { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len } }; | ||
85 | |||
86 | int err; | ||
87 | |||
88 | if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) { | ||
89 | printk ("%s: i2c read error (addr %02x, err == %i)\n", | ||
90 | __FUNCTION__, state->config->demod_address, err); | ||
91 | return -EREMOTEIO; | ||
92 | } | ||
93 | |||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | static u16 nxt2002_crc(u16 crc, u8 c) | ||
98 | { | ||
99 | |||
100 | u8 i; | ||
101 | u16 input = (u16) c & 0xFF; | ||
102 | |||
103 | input<<=8; | ||
104 | for(i=0 ;i<8 ;i++) { | ||
105 | if((crc ^ input) & 0x8000) | ||
106 | crc=(crc<<1)^CRC_CCIT_MASK; | ||
107 | else | ||
108 | crc<<=1; | ||
109 | input<<=1; | ||
110 | } | ||
111 | return crc; | ||
112 | } | ||
113 | |||
114 | static int nxt2002_writereg_multibyte (struct nxt2002_state* state, u8 reg, u8* data, u8 len) | ||
115 | { | ||
116 | u8 buf; | ||
117 | dprintk("%s\n", __FUNCTION__); | ||
118 | |||
119 | /* set multi register length */ | ||
120 | i2c_writebytes(state,0x34,&len,1); | ||
121 | |||
122 | /* set mutli register register */ | ||
123 | i2c_writebytes(state,0x35,®,1); | ||
124 | |||
125 | /* send the actual data */ | ||
126 | i2c_writebytes(state,0x36,data,len); | ||
127 | |||
128 | /* toggle the multireg write bit*/ | ||
129 | buf = 0x02; | ||
130 | i2c_writebytes(state,0x21,&buf,1); | ||
131 | |||
132 | i2c_readbytes(state,0x21,&buf,1); | ||
133 | |||
134 | if ((buf & 0x02) == 0) | ||
135 | return 0; | ||
136 | |||
137 | dprintk("Error writing multireg register %02X\n",reg); | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static int nxt2002_readreg_multibyte (struct nxt2002_state* state, u8 reg, u8* data, u8 len) | ||
143 | { | ||
144 | u8 len2; | ||
145 | dprintk("%s\n", __FUNCTION__); | ||
146 | |||
147 | /* set multi register length */ | ||
148 | len2 = len & 0x80; | ||
149 | i2c_writebytes(state,0x34,&len2,1); | ||
150 | |||
151 | /* set mutli register register */ | ||
152 | i2c_writebytes(state,0x35,®,1); | ||
153 | |||
154 | /* send the actual data */ | ||
155 | i2c_readbytes(state,reg,data,len); | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static void nxt2002_microcontroller_stop (struct nxt2002_state* state) | ||
161 | { | ||
162 | u8 buf[2],counter = 0; | ||
163 | dprintk("%s\n", __FUNCTION__); | ||
164 | |||
165 | buf[0] = 0x80; | ||
166 | i2c_writebytes(state,0x22,buf,1); | ||
167 | |||
168 | while (counter < 20) { | ||
169 | i2c_readbytes(state,0x31,buf,1); | ||
170 | if (buf[0] & 0x40) | ||
171 | return; | ||
172 | msleep(10); | ||
173 | counter++; | ||
174 | } | ||
175 | |||
176 | dprintk("Timeout waiting for micro to stop.. This is ok after firmware upload\n"); | ||
177 | return; | ||
178 | } | ||
179 | |||
180 | static void nxt2002_microcontroller_start (struct nxt2002_state* state) | ||
181 | { | ||
182 | u8 buf; | ||
183 | dprintk("%s\n", __FUNCTION__); | ||
184 | |||
185 | buf = 0x00; | ||
186 | i2c_writebytes(state,0x22,&buf,1); | ||
187 | } | ||
188 | |||
189 | static int nxt2002_writetuner (struct nxt2002_state* state, u8* data) | ||
190 | { | ||
191 | u8 buf,count = 0; | ||
192 | |||
193 | dprintk("Tuner Bytes: %02X %02X %02X %02X\n",data[0],data[1],data[2],data[3]); | ||
194 | |||
195 | dprintk("%s\n", __FUNCTION__); | ||
196 | /* stop the micro first */ | ||
197 | nxt2002_microcontroller_stop(state); | ||
198 | |||
199 | /* set the i2c transfer speed to the tuner */ | ||
200 | buf = 0x03; | ||
201 | i2c_writebytes(state,0x20,&buf,1); | ||
202 | |||
203 | /* setup to transfer 4 bytes via i2c */ | ||
204 | buf = 0x04; | ||
205 | i2c_writebytes(state,0x34,&buf,1); | ||
206 | |||
207 | /* write actual tuner bytes */ | ||
208 | i2c_writebytes(state,0x36,data,4); | ||
209 | |||
210 | /* set tuner i2c address */ | ||
211 | buf = 0xC2; | ||
212 | i2c_writebytes(state,0x35,&buf,1); | ||
213 | |||
214 | /* write UC Opmode to begin transfer */ | ||
215 | buf = 0x80; | ||
216 | i2c_writebytes(state,0x21,&buf,1); | ||
217 | |||
218 | while (count < 20) { | ||
219 | i2c_readbytes(state,0x21,&buf,1); | ||
220 | if ((buf & 0x80)== 0x00) | ||
221 | return 0; | ||
222 | msleep(100); | ||
223 | count++; | ||
224 | } | ||
225 | |||
226 | printk("nxt2002: timeout error writing tuner\n"); | ||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | static void nxt2002_agc_reset(struct nxt2002_state* state) | ||
231 | { | ||
232 | u8 buf; | ||
233 | dprintk("%s\n", __FUNCTION__); | ||
234 | |||
235 | buf = 0x08; | ||
236 | i2c_writebytes(state,0x08,&buf,1); | ||
237 | |||
238 | buf = 0x00; | ||
239 | i2c_writebytes(state,0x08,&buf,1); | ||
240 | |||
241 | return; | ||
242 | } | ||
243 | |||
244 | static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware *fw) | ||
245 | { | ||
246 | |||
247 | struct nxt2002_state* state = fe->demodulator_priv; | ||
248 | u8 buf[256],written = 0,chunkpos = 0; | ||
249 | u16 rambase,position,crc = 0; | ||
250 | |||
251 | dprintk("%s\n", __FUNCTION__); | ||
252 | dprintk("Firmware is %zu bytes\n",fw->size); | ||
253 | |||
254 | /* Get the RAM base for this nxt2002 */ | ||
255 | i2c_readbytes(state,0x10,buf,1); | ||
256 | |||
257 | if (buf[0] & 0x10) | ||
258 | rambase = 0x1000; | ||
259 | else | ||
260 | rambase = 0x0000; | ||
261 | |||
262 | dprintk("rambase on this nxt2002 is %04X\n",rambase); | ||
263 | |||
264 | /* Hold the micro in reset while loading firmware */ | ||
265 | buf[0] = 0x80; | ||
266 | i2c_writebytes(state,0x2B,buf,1); | ||
267 | |||
268 | for (position = 0; position < fw->size ; position++) { | ||
269 | if (written == 0) { | ||
270 | crc = 0; | ||
271 | chunkpos = 0x28; | ||
272 | buf[0] = ((rambase + position) >> 8); | ||
273 | buf[1] = (rambase + position) & 0xFF; | ||
274 | buf[2] = 0x81; | ||
275 | /* write starting address */ | ||
276 | i2c_writebytes(state,0x29,buf,3); | ||
277 | } | ||
278 | written++; | ||
279 | chunkpos++; | ||
280 | |||
281 | if ((written % 4) == 0) | ||
282 | i2c_writebytes(state,chunkpos,&fw->data[position-3],4); | ||
283 | |||
284 | crc = nxt2002_crc(crc,fw->data[position]); | ||
285 | |||
286 | if ((written == 255) || (position+1 == fw->size)) { | ||
287 | /* write remaining bytes of firmware */ | ||
288 | i2c_writebytes(state, chunkpos+4-(written %4), | ||
289 | &fw->data[position-(written %4) + 1], | ||
290 | written %4); | ||
291 | buf[0] = crc << 8; | ||
292 | buf[1] = crc & 0xFF; | ||
293 | |||
294 | /* write crc */ | ||
295 | i2c_writebytes(state,0x2C,buf,2); | ||
296 | |||
297 | /* do a read to stop things */ | ||
298 | i2c_readbytes(state,0x2A,buf,1); | ||
299 | |||
300 | /* set transfer mode to complete */ | ||
301 | buf[0] = 0x80; | ||
302 | i2c_writebytes(state,0x2B,buf,1); | ||
303 | |||
304 | written = 0; | ||
305 | } | ||
306 | } | ||
307 | |||
308 | printk ("done.\n"); | ||
309 | return 0; | ||
310 | }; | ||
311 | |||
312 | static int nxt2002_setup_frontend_parameters (struct dvb_frontend* fe, | ||
313 | struct dvb_frontend_parameters *p) | ||
314 | { | ||
315 | struct nxt2002_state* state = fe->demodulator_priv; | ||
316 | u32 freq = 0; | ||
317 | u16 tunerfreq = 0; | ||
318 | u8 buf[4]; | ||
319 | |||
320 | freq = 44000 + ( p->frequency / 1000 ); | ||
321 | |||
322 | dprintk("freq = %d p->frequency = %d\n",freq,p->frequency); | ||
323 | |||
324 | tunerfreq = freq * 24/4000; | ||
325 | |||
326 | buf[0] = (tunerfreq >> 8) & 0x7F; | ||
327 | buf[1] = (tunerfreq & 0xFF); | ||
328 | |||
329 | if (p->frequency <= 214000000) { | ||
330 | buf[2] = 0x84 + (0x06 << 3); | ||
331 | buf[3] = (p->frequency <= 172000000) ? 0x01 : 0x02; | ||
332 | } else if (p->frequency <= 721000000) { | ||
333 | buf[2] = 0x84 + (0x07 << 3); | ||
334 | buf[3] = (p->frequency <= 467000000) ? 0x02 : 0x08; | ||
335 | } else if (p->frequency <= 841000000) { | ||
336 | buf[2] = 0x84 + (0x0E << 3); | ||
337 | buf[3] = 0x08; | ||
338 | } else { | ||
339 | buf[2] = 0x84 + (0x0F << 3); | ||
340 | buf[3] = 0x02; | ||
341 | } | ||
342 | |||
343 | /* write frequency information */ | ||
344 | nxt2002_writetuner(state,buf); | ||
345 | |||
346 | /* reset the agc now that tuning has been completed */ | ||
347 | nxt2002_agc_reset(state); | ||
348 | |||
349 | /* set target power level */ | ||
350 | switch (p->u.vsb.modulation) { | ||
351 | case QAM_64: | ||
352 | case QAM_256: | ||
353 | buf[0] = 0x74; | ||
354 | break; | ||
355 | case VSB_8: | ||
356 | buf[0] = 0x70; | ||
357 | break; | ||
358 | default: | ||
359 | return -EINVAL; | ||
360 | break; | ||
361 | } | ||
362 | i2c_writebytes(state,0x42,buf,1); | ||
363 | |||
364 | /* configure sdm */ | ||
365 | buf[0] = 0x87; | ||
366 | i2c_writebytes(state,0x57,buf,1); | ||
367 | |||
368 | /* write sdm1 input */ | ||
369 | buf[0] = 0x10; | ||
370 | buf[1] = 0x00; | ||
371 | nxt2002_writereg_multibyte(state,0x58,buf,2); | ||
372 | |||
373 | /* write sdmx input */ | ||
374 | switch (p->u.vsb.modulation) { | ||
375 | case QAM_64: | ||
376 | buf[0] = 0x68; | ||
377 | break; | ||
378 | case QAM_256: | ||
379 | buf[0] = 0x64; | ||
380 | break; | ||
381 | case VSB_8: | ||
382 | buf[0] = 0x60; | ||
383 | break; | ||
384 | default: | ||
385 | return -EINVAL; | ||
386 | break; | ||
387 | } | ||
388 | buf[1] = 0x00; | ||
389 | nxt2002_writereg_multibyte(state,0x5C,buf,2); | ||
390 | |||
391 | /* write adc power lpf fc */ | ||
392 | buf[0] = 0x05; | ||
393 | i2c_writebytes(state,0x43,buf,1); | ||
394 | |||
395 | /* write adc power lpf fc */ | ||
396 | buf[0] = 0x05; | ||
397 | i2c_writebytes(state,0x43,buf,1); | ||
398 | |||
399 | /* write accumulator2 input */ | ||
400 | buf[0] = 0x80; | ||
401 | buf[1] = 0x00; | ||
402 | nxt2002_writereg_multibyte(state,0x4B,buf,2); | ||
403 | |||
404 | /* write kg1 */ | ||
405 | buf[0] = 0x00; | ||
406 | i2c_writebytes(state,0x4D,buf,1); | ||
407 | |||
408 | /* write sdm12 lpf fc */ | ||
409 | buf[0] = 0x44; | ||
410 | i2c_writebytes(state,0x55,buf,1); | ||
411 | |||
412 | /* write agc control reg */ | ||
413 | buf[0] = 0x04; | ||
414 | i2c_writebytes(state,0x41,buf,1); | ||
415 | |||
416 | /* write agc ucgp0 */ | ||
417 | switch (p->u.vsb.modulation) { | ||
418 | case QAM_64: | ||
419 | buf[0] = 0x02; | ||
420 | break; | ||
421 | case QAM_256: | ||
422 | buf[0] = 0x03; | ||
423 | break; | ||
424 | case VSB_8: | ||
425 | buf[0] = 0x00; | ||
426 | break; | ||
427 | default: | ||
428 | return -EINVAL; | ||
429 | break; | ||
430 | } | ||
431 | i2c_writebytes(state,0x30,buf,1); | ||
432 | |||
433 | /* write agc control reg */ | ||
434 | buf[0] = 0x00; | ||
435 | i2c_writebytes(state,0x41,buf,1); | ||
436 | |||
437 | /* write accumulator2 input */ | ||
438 | buf[0] = 0x80; | ||
439 | buf[1] = 0x00; | ||
440 | nxt2002_writereg_multibyte(state,0x49,buf,2); | ||
441 | nxt2002_writereg_multibyte(state,0x4B,buf,2); | ||
442 | |||
443 | /* write agc control reg */ | ||
444 | buf[0] = 0x04; | ||
445 | i2c_writebytes(state,0x41,buf,1); | ||
446 | |||
447 | nxt2002_microcontroller_start(state); | ||
448 | |||
449 | /* adjacent channel detection should be done here, but I don't | ||
450 | have any stations with this need so I cannot test it */ | ||
451 | |||
452 | return 0; | ||
453 | } | ||
454 | |||
455 | static int nxt2002_read_status(struct dvb_frontend* fe, fe_status_t* status) | ||
456 | { | ||
457 | struct nxt2002_state* state = fe->demodulator_priv; | ||
458 | u8 lock; | ||
459 | i2c_readbytes(state,0x31,&lock,1); | ||
460 | |||
461 | *status = 0; | ||
462 | if (lock & 0x20) { | ||
463 | *status |= FE_HAS_SIGNAL; | ||
464 | *status |= FE_HAS_CARRIER; | ||
465 | *status |= FE_HAS_VITERBI; | ||
466 | *status |= FE_HAS_SYNC; | ||
467 | *status |= FE_HAS_LOCK; | ||
468 | } | ||
469 | return 0; | ||
470 | } | ||
471 | |||
472 | static int nxt2002_read_ber(struct dvb_frontend* fe, u32* ber) | ||
473 | { | ||
474 | struct nxt2002_state* state = fe->demodulator_priv; | ||
475 | u8 b[3]; | ||
476 | |||
477 | nxt2002_readreg_multibyte(state,0xE6,b,3); | ||
478 | |||
479 | *ber = ((b[0] << 8) + b[1]) * 8; | ||
480 | |||
481 | return 0; | ||
482 | } | ||
483 | |||
484 | static int nxt2002_read_signal_strength(struct dvb_frontend* fe, u16* strength) | ||
485 | { | ||
486 | struct nxt2002_state* state = fe->demodulator_priv; | ||
487 | u8 b[2]; | ||
488 | u16 temp = 0; | ||
489 | |||
490 | /* setup to read cluster variance */ | ||
491 | b[0] = 0x00; | ||
492 | i2c_writebytes(state,0xA1,b,1); | ||
493 | |||
494 | /* get multreg val */ | ||
495 | nxt2002_readreg_multibyte(state,0xA6,b,2); | ||
496 | |||
497 | temp = (b[0] << 8) | b[1]; | ||
498 | *strength = ((0x7FFF - temp) & 0x0FFF) * 16; | ||
499 | |||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | static int nxt2002_read_snr(struct dvb_frontend* fe, u16* snr) | ||
504 | { | ||
505 | |||
506 | struct nxt2002_state* state = fe->demodulator_priv; | ||
507 | u8 b[2]; | ||
508 | u16 temp = 0, temp2; | ||
509 | u32 snrdb = 0; | ||
510 | |||
511 | /* setup to read cluster variance */ | ||
512 | b[0] = 0x00; | ||
513 | i2c_writebytes(state,0xA1,b,1); | ||
514 | |||
515 | /* get multreg val from 0xA6 */ | ||
516 | nxt2002_readreg_multibyte(state,0xA6,b,2); | ||
517 | |||
518 | temp = (b[0] << 8) | b[1]; | ||
519 | temp2 = 0x7FFF - temp; | ||
520 | |||
521 | /* snr will be in db */ | ||
522 | if (temp2 > 0x7F00) | ||
523 | snrdb = 1000*24 + ( 1000*(30-24) * ( temp2 - 0x7F00 ) / ( 0x7FFF - 0x7F00 ) ); | ||
524 | else if (temp2 > 0x7EC0) | ||
525 | snrdb = 1000*18 + ( 1000*(24-18) * ( temp2 - 0x7EC0 ) / ( 0x7F00 - 0x7EC0 ) ); | ||
526 | else if (temp2 > 0x7C00) | ||
527 | snrdb = 1000*12 + ( 1000*(18-12) * ( temp2 - 0x7C00 ) / ( 0x7EC0 - 0x7C00 ) ); | ||
528 | else | ||
529 | snrdb = 1000*0 + ( 1000*(12-0) * ( temp2 - 0 ) / ( 0x7C00 - 0 ) ); | ||
530 | |||
531 | /* the value reported back from the frontend will be FFFF=32db 0000=0db */ | ||
532 | |||
533 | *snr = snrdb * (0xFFFF/32000); | ||
534 | |||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | static int nxt2002_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) | ||
539 | { | ||
540 | struct nxt2002_state* state = fe->demodulator_priv; | ||
541 | u8 b[3]; | ||
542 | |||
543 | nxt2002_readreg_multibyte(state,0xE6,b,3); | ||
544 | *ucblocks = b[2]; | ||
545 | |||
546 | return 0; | ||
547 | } | ||
548 | |||
549 | static int nxt2002_sleep(struct dvb_frontend* fe) | ||
550 | { | ||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | static int nxt2002_init(struct dvb_frontend* fe) | ||
555 | { | ||
556 | struct nxt2002_state* state = fe->demodulator_priv; | ||
557 | const struct firmware *fw; | ||
558 | int ret; | ||
559 | u8 buf[2]; | ||
560 | |||
561 | if (!state->initialised) { | ||
562 | /* request the firmware, this will block until someone uploads it */ | ||
563 | printk("nxt2002: Waiting for firmware upload (%s)...\n", NXT2002_DEFAULT_FIRMWARE); | ||
564 | ret = state->config->request_firmware(fe, &fw, NXT2002_DEFAULT_FIRMWARE); | ||
565 | printk("nxt2002: Waiting for firmware upload(2)...\n"); | ||
566 | if (ret) { | ||
567 | printk("nxt2002: no firmware upload (timeout or file not found?)\n"); | ||
568 | return ret; | ||
569 | } | ||
570 | |||
571 | ret = nxt2002_load_firmware(fe, fw); | ||
572 | if (ret) { | ||
573 | printk("nxt2002: writing firmware to device failed\n"); | ||
574 | release_firmware(fw); | ||
575 | return ret; | ||
576 | } | ||
577 | printk("nxt2002: firmware upload complete\n"); | ||
578 | |||
579 | /* Put the micro into reset */ | ||
580 | nxt2002_microcontroller_stop(state); | ||
581 | |||
582 | /* ensure transfer is complete */ | ||
583 | buf[0]=0; | ||
584 | i2c_writebytes(state,0x2B,buf,1); | ||
585 | |||
586 | /* Put the micro into reset for real this time */ | ||
587 | nxt2002_microcontroller_stop(state); | ||
588 | |||
589 | /* soft reset everything (agc,frontend,eq,fec)*/ | ||
590 | buf[0] = 0x0F; | ||
591 | i2c_writebytes(state,0x08,buf,1); | ||
592 | buf[0] = 0x00; | ||
593 | i2c_writebytes(state,0x08,buf,1); | ||
594 | |||
595 | /* write agc sdm configure */ | ||
596 | buf[0] = 0xF1; | ||
597 | i2c_writebytes(state,0x57,buf,1); | ||
598 | |||
599 | /* write mod output format */ | ||
600 | buf[0] = 0x20; | ||
601 | i2c_writebytes(state,0x09,buf,1); | ||
602 | |||
603 | /* write fec mpeg mode */ | ||
604 | buf[0] = 0x7E; | ||
605 | buf[1] = 0x00; | ||
606 | i2c_writebytes(state,0xE9,buf,2); | ||
607 | |||
608 | /* write mux selection */ | ||
609 | buf[0] = 0x00; | ||
610 | i2c_writebytes(state,0xCC,buf,1); | ||
611 | |||
612 | state->initialised = 1; | ||
613 | } | ||
614 | |||
615 | return 0; | ||
616 | } | ||
617 | |||
618 | static int nxt2002_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings) | ||
619 | { | ||
620 | fesettings->min_delay_ms = 500; | ||
621 | fesettings->step_size = 0; | ||
622 | fesettings->max_drift = 0; | ||
623 | return 0; | ||
624 | } | ||
625 | |||
626 | static void nxt2002_release(struct dvb_frontend* fe) | ||
627 | { | ||
628 | struct nxt2002_state* state = fe->demodulator_priv; | ||
629 | kfree(state); | ||
630 | } | ||
631 | |||
632 | static struct dvb_frontend_ops nxt2002_ops; | ||
633 | |||
634 | struct dvb_frontend* nxt2002_attach(const struct nxt2002_config* config, | ||
635 | struct i2c_adapter* i2c) | ||
636 | { | ||
637 | struct nxt2002_state* state = NULL; | ||
638 | u8 buf [] = {0,0,0,0,0}; | ||
639 | |||
640 | /* allocate memory for the internal state */ | ||
641 | state = kmalloc(sizeof(struct nxt2002_state), GFP_KERNEL); | ||
642 | if (state == NULL) goto error; | ||
643 | |||
644 | /* setup the state */ | ||
645 | state->config = config; | ||
646 | state->i2c = i2c; | ||
647 | memcpy(&state->ops, &nxt2002_ops, sizeof(struct dvb_frontend_ops)); | ||
648 | state->initialised = 0; | ||
649 | |||
650 | /* Check the first 5 registers to ensure this a revision we can handle */ | ||
651 | |||
652 | i2c_readbytes(state, 0x00, buf, 5); | ||
653 | if (buf[0] != 0x04) goto error; /* device id */ | ||
654 | if (buf[1] != 0x02) goto error; /* fab id */ | ||
655 | if (buf[2] != 0x11) goto error; /* month */ | ||
656 | if (buf[3] != 0x20) goto error; /* year msb */ | ||
657 | if (buf[4] != 0x00) goto error; /* year lsb */ | ||
658 | |||
659 | /* create dvb_frontend */ | ||
660 | state->frontend.ops = &state->ops; | ||
661 | state->frontend.demodulator_priv = state; | ||
662 | return &state->frontend; | ||
663 | |||
664 | error: | ||
665 | kfree(state); | ||
666 | return NULL; | ||
667 | } | ||
668 | |||
669 | static struct dvb_frontend_ops nxt2002_ops = { | ||
670 | |||
671 | .info = { | ||
672 | .name = "Nextwave nxt2002 VSB/QAM frontend", | ||
673 | .type = FE_ATSC, | ||
674 | .frequency_min = 54000000, | ||
675 | .frequency_max = 860000000, | ||
676 | /* stepsize is just a guess */ | ||
677 | .frequency_stepsize = 166666, | ||
678 | .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
679 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
680 | FE_CAN_8VSB | FE_CAN_QAM_64 | FE_CAN_QAM_256 | ||
681 | }, | ||
682 | |||
683 | .release = nxt2002_release, | ||
684 | |||
685 | .init = nxt2002_init, | ||
686 | .sleep = nxt2002_sleep, | ||
687 | |||
688 | .set_frontend = nxt2002_setup_frontend_parameters, | ||
689 | .get_tune_settings = nxt2002_get_tune_settings, | ||
690 | |||
691 | .read_status = nxt2002_read_status, | ||
692 | .read_ber = nxt2002_read_ber, | ||
693 | .read_signal_strength = nxt2002_read_signal_strength, | ||
694 | .read_snr = nxt2002_read_snr, | ||
695 | .read_ucblocks = nxt2002_read_ucblocks, | ||
696 | |||
697 | }; | ||
698 | |||
699 | module_param(debug, int, 0644); | ||
700 | MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); | ||
701 | |||
702 | MODULE_DESCRIPTION("NXT2002 ATSC (8VSB & ITU J83 AnnexB FEC QAM64/256) demodulator driver"); | ||
703 | MODULE_AUTHOR("Taylor Jacob"); | ||
704 | MODULE_LICENSE("GPL"); | ||
705 | |||
706 | EXPORT_SYMBOL(nxt2002_attach); | ||
diff --git a/drivers/media/dvb/frontends/nxt2002.h b/drivers/media/dvb/frontends/nxt2002.h deleted file mode 100644 index 462301f577ee..000000000000 --- a/drivers/media/dvb/frontends/nxt2002.h +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | /* | ||
2 | Driver for the Nxt2002 demodulator | ||
3 | */ | ||
4 | |||
5 | #ifndef NXT2002_H | ||
6 | #define NXT2002_H | ||
7 | |||
8 | #include <linux/dvb/frontend.h> | ||
9 | #include <linux/firmware.h> | ||
10 | |||
11 | struct nxt2002_config | ||
12 | { | ||
13 | /* the demodulator's i2c address */ | ||
14 | u8 demod_address; | ||
15 | |||
16 | /* request firmware for device */ | ||
17 | int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name); | ||
18 | }; | ||
19 | |||
20 | extern struct dvb_frontend* nxt2002_attach(const struct nxt2002_config* config, | ||
21 | struct i2c_adapter* i2c); | ||
22 | |||
23 | #endif // NXT2002_H | ||
diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c index 78d2b93d35b9..9e3535394509 100644 --- a/drivers/media/dvb/frontends/nxt200x.c +++ b/drivers/media/dvb/frontends/nxt200x.c | |||
@@ -1,9 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * Support for NXT2002 and NXT2004 - VSB/QAM | 2 | * Support for NXT2002 and NXT2004 - VSB/QAM |
3 | * | 3 | * |
4 | * Copyright (C) 2005 Kirk Lapray (kirk.lapray@gmail.com) | 4 | * Copyright (C) 2005 Kirk Lapray <kirk.lapray@gmail.com> |
5 | * Copyright (C) 2006 Michael Krufky <mkrufky@m1k.net> | ||
5 | * based on nxt2002 by Taylor Jacob <rtjacob@earthlink.net> | 6 | * based on nxt2002 by Taylor Jacob <rtjacob@earthlink.net> |
6 | * and nxt2004 by Jean-Francois Thibert (jeanfrancois@sagetv.com) | 7 | * and nxt2004 by Jean-Francois Thibert <jeanfrancois@sagetv.com> |
7 | * | 8 | * |
8 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 10 | * it under the terms of the GNU General Public License as published by |
@@ -614,7 +615,17 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe, | |||
614 | /* write sdm1 input */ | 615 | /* write sdm1 input */ |
615 | buf[0] = 0x10; | 616 | buf[0] = 0x10; |
616 | buf[1] = 0x00; | 617 | buf[1] = 0x00; |
617 | nxt200x_writebytes(state, 0x58, buf, 2); | 618 | switch (state->demod_chip) { |
619 | case NXT2002: | ||
620 | nxt200x_writereg_multibyte(state, 0x58, buf, 2); | ||
621 | break; | ||
622 | case NXT2004: | ||
623 | nxt200x_writebytes(state, 0x58, buf, 2); | ||
624 | break; | ||
625 | default: | ||
626 | return -EINVAL; | ||
627 | break; | ||
628 | } | ||
618 | 629 | ||
619 | /* write sdmx input */ | 630 | /* write sdmx input */ |
620 | switch (p->u.vsb.modulation) { | 631 | switch (p->u.vsb.modulation) { |
@@ -632,7 +643,17 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe, | |||
632 | break; | 643 | break; |
633 | } | 644 | } |
634 | buf[1] = 0x00; | 645 | buf[1] = 0x00; |
635 | nxt200x_writebytes(state, 0x5C, buf, 2); | 646 | switch (state->demod_chip) { |
647 | case NXT2002: | ||
648 | nxt200x_writereg_multibyte(state, 0x5C, buf, 2); | ||
649 | break; | ||
650 | case NXT2004: | ||
651 | nxt200x_writebytes(state, 0x5C, buf, 2); | ||
652 | break; | ||
653 | default: | ||
654 | return -EINVAL; | ||
655 | break; | ||
656 | } | ||
636 | 657 | ||
637 | /* write adc power lpf fc */ | 658 | /* write adc power lpf fc */ |
638 | buf[0] = 0x05; | 659 | buf[0] = 0x05; |
@@ -648,7 +669,17 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe, | |||
648 | /* write accumulator2 input */ | 669 | /* write accumulator2 input */ |
649 | buf[0] = 0x80; | 670 | buf[0] = 0x80; |
650 | buf[1] = 0x00; | 671 | buf[1] = 0x00; |
651 | nxt200x_writebytes(state, 0x4B, buf, 2); | 672 | switch (state->demod_chip) { |
673 | case NXT2002: | ||
674 | nxt200x_writereg_multibyte(state, 0x4B, buf, 2); | ||
675 | break; | ||
676 | case NXT2004: | ||
677 | nxt200x_writebytes(state, 0x4B, buf, 2); | ||
678 | break; | ||
679 | default: | ||
680 | return -EINVAL; | ||
681 | break; | ||
682 | } | ||
652 | 683 | ||
653 | /* write kg1 */ | 684 | /* write kg1 */ |
654 | buf[0] = 0x00; | 685 | buf[0] = 0x00; |
@@ -714,8 +745,19 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe, | |||
714 | /* write accumulator2 input */ | 745 | /* write accumulator2 input */ |
715 | buf[0] = 0x80; | 746 | buf[0] = 0x80; |
716 | buf[1] = 0x00; | 747 | buf[1] = 0x00; |
717 | nxt200x_writebytes(state, 0x49, buf,2); | 748 | switch (state->demod_chip) { |
718 | nxt200x_writebytes(state, 0x4B, buf,2); | 749 | case NXT2002: |
750 | nxt200x_writereg_multibyte(state, 0x49, buf, 2); | ||
751 | nxt200x_writereg_multibyte(state, 0x4B, buf, 2); | ||
752 | break; | ||
753 | case NXT2004: | ||
754 | nxt200x_writebytes(state, 0x49, buf, 2); | ||
755 | nxt200x_writebytes(state, 0x4B, buf, 2); | ||
756 | break; | ||
757 | default: | ||
758 | return -EINVAL; | ||
759 | break; | ||
760 | } | ||
719 | 761 | ||
720 | /* write agc control reg */ | 762 | /* write agc control reg */ |
721 | buf[0] = 0x04; | 763 | buf[0] = 0x04; |
@@ -1199,7 +1241,7 @@ module_param(debug, int, 0644); | |||
1199 | MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); | 1241 | MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); |
1200 | 1242 | ||
1201 | MODULE_DESCRIPTION("NXT200X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver"); | 1243 | MODULE_DESCRIPTION("NXT200X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver"); |
1202 | MODULE_AUTHOR("Kirk Lapray, Jean-Francois Thibert, and Taylor Jacob"); | 1244 | MODULE_AUTHOR("Kirk Lapray, Michael Krufky, Jean-Francois Thibert, and Taylor Jacob"); |
1203 | MODULE_LICENSE("GPL"); | 1245 | MODULE_LICENSE("GPL"); |
1204 | 1246 | ||
1205 | EXPORT_SYMBOL(nxt200x_attach); | 1247 | EXPORT_SYMBOL(nxt200x_attach); |
diff --git a/drivers/media/dvb/frontends/tda80xx.c b/drivers/media/dvb/frontends/tda80xx.c deleted file mode 100644 index d1cabb6a0a13..000000000000 --- a/drivers/media/dvb/frontends/tda80xx.c +++ /dev/null | |||
@@ -1,734 +0,0 @@ | |||
1 | /* | ||
2 | * tda80xx.c | ||
3 | * | ||
4 | * Philips TDA8044 / TDA8083 QPSK demodulator driver | ||
5 | * | ||
6 | * Copyright (C) 2001 Felix Domke <tmbinc@elitedvb.net> | ||
7 | * Copyright (C) 2002-2004 Andreas Oberritter <obi@linuxtv.org> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/config.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/spinlock.h> | ||
28 | #include <linux/threads.h> | ||
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/slab.h> | ||
33 | #include <asm/irq.h> | ||
34 | #include <asm/div64.h> | ||
35 | |||
36 | #include "dvb_frontend.h" | ||
37 | #include "tda80xx.h" | ||
38 | |||
39 | enum { | ||
40 | ID_TDA8044 = 0x04, | ||
41 | ID_TDA8083 = 0x05, | ||
42 | }; | ||
43 | |||
44 | |||
45 | struct tda80xx_state { | ||
46 | |||
47 | struct i2c_adapter* i2c; | ||
48 | |||
49 | struct dvb_frontend_ops ops; | ||
50 | |||
51 | /* configuration settings */ | ||
52 | const struct tda80xx_config* config; | ||
53 | |||
54 | struct dvb_frontend frontend; | ||
55 | |||
56 | u32 clk; | ||
57 | int afc_loop; | ||
58 | struct work_struct worklet; | ||
59 | fe_code_rate_t code_rate; | ||
60 | fe_spectral_inversion_t spectral_inversion; | ||
61 | fe_status_t status; | ||
62 | u8 id; | ||
63 | }; | ||
64 | |||
65 | static int debug = 1; | ||
66 | #define dprintk if (debug) printk | ||
67 | |||
68 | static u8 tda8044_inittab_pre[] = { | ||
69 | 0x02, 0x00, 0x6f, 0xb5, 0x86, 0x22, 0x00, 0xea, | ||
70 | 0x30, 0x42, 0x98, 0x68, 0x70, 0x42, 0x99, 0x58, | ||
71 | 0x95, 0x10, 0xf5, 0xe7, 0x93, 0x0b, 0x15, 0x68, | ||
72 | 0x9a, 0x90, 0x61, 0x80, 0x00, 0xe0, 0x40, 0x00, | ||
73 | 0x0f, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
74 | 0x00, 0x00 | ||
75 | }; | ||
76 | |||
77 | static u8 tda8044_inittab_post[] = { | ||
78 | 0x04, 0x00, 0x6f, 0xb5, 0x86, 0x22, 0x00, 0xea, | ||
79 | 0x30, 0x42, 0x98, 0x68, 0x70, 0x42, 0x99, 0x50, | ||
80 | 0x95, 0x10, 0xf5, 0xe7, 0x93, 0x0b, 0x15, 0x68, | ||
81 | 0x9a, 0x90, 0x61, 0x80, 0x00, 0xe0, 0x40, 0x6c, | ||
82 | 0x0f, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
83 | 0x00, 0x00 | ||
84 | }; | ||
85 | |||
86 | static u8 tda8083_inittab[] = { | ||
87 | 0x04, 0x00, 0x4a, 0x79, 0x04, 0x00, 0xff, 0xea, | ||
88 | 0x48, 0x42, 0x79, 0x60, 0x70, 0x52, 0x9a, 0x10, | ||
89 | 0x0e, 0x10, 0xf2, 0xa7, 0x93, 0x0b, 0x05, 0xc8, | ||
90 | 0x9d, 0x00, 0x42, 0x80, 0x00, 0x60, 0x40, 0x00, | ||
91 | 0x00, 0x75, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, | ||
92 | 0x00, 0x00, 0x00, 0x00 | ||
93 | }; | ||
94 | |||
95 | static __inline__ u32 tda80xx_div(u32 a, u32 b) | ||
96 | { | ||
97 | return (a + (b / 2)) / b; | ||
98 | } | ||
99 | |||
100 | static __inline__ u32 tda80xx_gcd(u32 a, u32 b) | ||
101 | { | ||
102 | u32 r; | ||
103 | |||
104 | while ((r = a % b)) { | ||
105 | a = b; | ||
106 | b = r; | ||
107 | } | ||
108 | |||
109 | return b; | ||
110 | } | ||
111 | |||
112 | static int tda80xx_read(struct tda80xx_state* state, u8 reg, u8 *buf, u8 len) | ||
113 | { | ||
114 | int ret; | ||
115 | struct i2c_msg msg[] = { { .addr = state->config->demod_address, .flags = 0, .buf = ®, .len = 1 }, | ||
116 | { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len } }; | ||
117 | |||
118 | ret = i2c_transfer(state->i2c, msg, 2); | ||
119 | |||
120 | if (ret != 2) | ||
121 | dprintk("%s: readreg error (reg %02x, ret == %i)\n", | ||
122 | __FUNCTION__, reg, ret); | ||
123 | |||
124 | mdelay(10); | ||
125 | |||
126 | return (ret == 2) ? 0 : -EREMOTEIO; | ||
127 | } | ||
128 | |||
129 | static int tda80xx_write(struct tda80xx_state* state, u8 reg, const u8 *buf, u8 len) | ||
130 | { | ||
131 | int ret; | ||
132 | u8 wbuf[len + 1]; | ||
133 | struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = wbuf, .len = len + 1 }; | ||
134 | |||
135 | wbuf[0] = reg; | ||
136 | memcpy(&wbuf[1], buf, len); | ||
137 | |||
138 | ret = i2c_transfer(state->i2c, &msg, 1); | ||
139 | |||
140 | if (ret != 1) | ||
141 | dprintk("%s: i2c xfer error (ret == %i)\n", __FUNCTION__, ret); | ||
142 | |||
143 | mdelay(10); | ||
144 | |||
145 | return (ret == 1) ? 0 : -EREMOTEIO; | ||
146 | } | ||
147 | |||
148 | static __inline__ u8 tda80xx_readreg(struct tda80xx_state* state, u8 reg) | ||
149 | { | ||
150 | u8 val; | ||
151 | |||
152 | tda80xx_read(state, reg, &val, 1); | ||
153 | |||
154 | return val; | ||
155 | } | ||
156 | |||
157 | static __inline__ int tda80xx_writereg(struct tda80xx_state* state, u8 reg, u8 data) | ||
158 | { | ||
159 | return tda80xx_write(state, reg, &data, 1); | ||
160 | } | ||
161 | |||
162 | static int tda80xx_set_parameters(struct tda80xx_state* state, | ||
163 | fe_spectral_inversion_t inversion, | ||
164 | u32 symbol_rate, | ||
165 | fe_code_rate_t fec_inner) | ||
166 | { | ||
167 | u8 buf[15]; | ||
168 | u64 ratio; | ||
169 | u32 clk; | ||
170 | u32 k; | ||
171 | u32 sr = symbol_rate; | ||
172 | u32 gcd; | ||
173 | u8 scd; | ||
174 | |||
175 | if (symbol_rate > (state->clk * 3) / 16) | ||
176 | scd = 0; | ||
177 | else if (symbol_rate > (state->clk * 3) / 32) | ||
178 | scd = 1; | ||
179 | else if (symbol_rate > (state->clk * 3) / 64) | ||
180 | scd = 2; | ||
181 | else | ||
182 | scd = 3; | ||
183 | |||
184 | clk = scd ? (state->clk / (scd * 2)) : state->clk; | ||
185 | |||
186 | /* | ||
187 | * Viterbi decoder: | ||
188 | * Differential decoding off | ||
189 | * Spectral inversion unknown | ||
190 | * QPSK modulation | ||
191 | */ | ||
192 | if (inversion == INVERSION_ON) | ||
193 | buf[0] = 0x60; | ||
194 | else if (inversion == INVERSION_OFF) | ||
195 | buf[0] = 0x20; | ||
196 | else | ||
197 | buf[0] = 0x00; | ||
198 | |||
199 | /* | ||
200 | * CLK ratio: | ||
201 | * system clock frequency is up to 64 or 96 MHz | ||
202 | * | ||
203 | * formula: | ||
204 | * r = k * clk / symbol_rate | ||
205 | * | ||
206 | * k: 2^21 for caa 0..3, | ||
207 | * 2^20 for caa 4..5, | ||
208 | * 2^19 for caa 6..7 | ||
209 | */ | ||
210 | if (symbol_rate <= (clk * 3) / 32) | ||
211 | k = (1 << 19); | ||
212 | else if (symbol_rate <= (clk * 3) / 16) | ||
213 | k = (1 << 20); | ||
214 | else | ||
215 | k = (1 << 21); | ||
216 | |||
217 | gcd = tda80xx_gcd(clk, sr); | ||
218 | clk /= gcd; | ||
219 | sr /= gcd; | ||
220 | |||
221 | gcd = tda80xx_gcd(k, sr); | ||
222 | k /= gcd; | ||
223 | sr /= gcd; | ||
224 | |||
225 | ratio = (u64)k * (u64)clk; | ||
226 | do_div(ratio, sr); | ||
227 | |||
228 | buf[1] = ratio >> 16; | ||
229 | buf[2] = ratio >> 8; | ||
230 | buf[3] = ratio; | ||
231 | |||
232 | /* nyquist filter roll-off factor 35% */ | ||
233 | buf[4] = 0x20; | ||
234 | |||
235 | clk = scd ? (state->clk / (scd * 2)) : state->clk; | ||
236 | |||
237 | /* Anti Alias Filter */ | ||
238 | if (symbol_rate < (clk * 3) / 64) | ||
239 | printk("tda80xx: unsupported symbol rate: %u\n", symbol_rate); | ||
240 | else if (symbol_rate <= clk / 16) | ||
241 | buf[4] |= 0x07; | ||
242 | else if (symbol_rate <= (clk * 3) / 32) | ||
243 | buf[4] |= 0x06; | ||
244 | else if (symbol_rate <= clk / 8) | ||
245 | buf[4] |= 0x05; | ||
246 | else if (symbol_rate <= (clk * 3) / 16) | ||
247 | buf[4] |= 0x04; | ||
248 | else if (symbol_rate <= clk / 4) | ||
249 | buf[4] |= 0x03; | ||
250 | else if (symbol_rate <= (clk * 3) / 8) | ||
251 | buf[4] |= 0x02; | ||
252 | else if (symbol_rate <= clk / 2) | ||
253 | buf[4] |= 0x01; | ||
254 | else | ||
255 | buf[4] |= 0x00; | ||
256 | |||
257 | /* Sigma Delta converter */ | ||
258 | buf[5] = 0x00; | ||
259 | |||
260 | /* FEC: Possible puncturing rates */ | ||
261 | if (fec_inner == FEC_NONE) | ||
262 | buf[6] = 0x00; | ||
263 | else if ((fec_inner >= FEC_1_2) && (fec_inner <= FEC_8_9)) | ||
264 | buf[6] = (1 << (8 - fec_inner)); | ||
265 | else if (fec_inner == FEC_AUTO) | ||
266 | buf[6] = 0xff; | ||
267 | else | ||
268 | return -EINVAL; | ||
269 | |||
270 | /* carrier lock detector threshold value */ | ||
271 | buf[7] = 0x30; | ||
272 | /* AFC1: proportional part settings */ | ||
273 | buf[8] = 0x42; | ||
274 | /* AFC1: integral part settings */ | ||
275 | buf[9] = 0x98; | ||
276 | /* PD: Leaky integrator SCPC mode */ | ||
277 | buf[10] = 0x28; | ||
278 | /* AFC2, AFC1 controls */ | ||
279 | buf[11] = 0x30; | ||
280 | /* PD: proportional part settings */ | ||
281 | buf[12] = 0x42; | ||
282 | /* PD: integral part settings */ | ||
283 | buf[13] = 0x99; | ||
284 | /* AGC */ | ||
285 | buf[14] = 0x50 | scd; | ||
286 | |||
287 | printk("symbol_rate=%u clk=%u\n", symbol_rate, clk); | ||
288 | |||
289 | return tda80xx_write(state, 0x01, buf, sizeof(buf)); | ||
290 | } | ||
291 | |||
292 | static int tda80xx_set_clk(struct tda80xx_state* state) | ||
293 | { | ||
294 | u8 buf[2]; | ||
295 | |||
296 | /* CLK proportional part */ | ||
297 | buf[0] = (0x06 << 5) | 0x08; /* CMP[2:0], CSP[4:0] */ | ||
298 | /* CLK integral part */ | ||
299 | buf[1] = (0x04 << 5) | 0x1a; /* CMI[2:0], CSI[4:0] */ | ||
300 | |||
301 | return tda80xx_write(state, 0x17, buf, sizeof(buf)); | ||
302 | } | ||
303 | |||
304 | #if 0 | ||
305 | static int tda80xx_set_scpc_freq_offset(struct tda80xx_state* state) | ||
306 | { | ||
307 | /* a constant value is nonsense here imho */ | ||
308 | return tda80xx_writereg(state, 0x22, 0xf9); | ||
309 | } | ||
310 | #endif | ||
311 | |||
312 | static int tda80xx_close_loop(struct tda80xx_state* state) | ||
313 | { | ||
314 | u8 buf[2]; | ||
315 | |||
316 | /* PD: Loop closed, LD: lock detect enable, SCPC: Sweep mode - AFC1 loop closed */ | ||
317 | buf[0] = 0x68; | ||
318 | /* AFC1: Loop closed, CAR Feedback: 8192 */ | ||
319 | buf[1] = 0x70; | ||
320 | |||
321 | return tda80xx_write(state, 0x0b, buf, sizeof(buf)); | ||
322 | } | ||
323 | |||
324 | static irqreturn_t tda80xx_irq(int irq, void *priv, struct pt_regs *pt) | ||
325 | { | ||
326 | schedule_work(priv); | ||
327 | |||
328 | return IRQ_HANDLED; | ||
329 | } | ||
330 | |||
331 | static void tda80xx_read_status_int(struct tda80xx_state* state) | ||
332 | { | ||
333 | u8 val; | ||
334 | |||
335 | static const fe_spectral_inversion_t inv_tab[] = { | ||
336 | INVERSION_OFF, INVERSION_ON | ||
337 | }; | ||
338 | |||
339 | static const fe_code_rate_t fec_tab[] = { | ||
340 | FEC_8_9, FEC_1_2, FEC_2_3, FEC_3_4, | ||
341 | FEC_4_5, FEC_5_6, FEC_6_7, FEC_7_8, | ||
342 | }; | ||
343 | |||
344 | val = tda80xx_readreg(state, 0x02); | ||
345 | |||
346 | state->status = 0; | ||
347 | |||
348 | if (val & 0x01) /* demodulator lock */ | ||
349 | state->status |= FE_HAS_SIGNAL; | ||
350 | if (val & 0x02) /* clock recovery lock */ | ||
351 | state->status |= FE_HAS_CARRIER; | ||
352 | if (val & 0x04) /* viterbi lock */ | ||
353 | state->status |= FE_HAS_VITERBI; | ||
354 | if (val & 0x08) /* deinterleaver lock (packet sync) */ | ||
355 | state->status |= FE_HAS_SYNC; | ||
356 | if (val & 0x10) /* derandomizer lock (frame sync) */ | ||
357 | state->status |= FE_HAS_LOCK; | ||
358 | if (val & 0x20) /* frontend can not lock */ | ||
359 | state->status |= FE_TIMEDOUT; | ||
360 | |||
361 | if ((state->status & (FE_HAS_CARRIER)) && (state->afc_loop)) { | ||
362 | printk("tda80xx: closing loop\n"); | ||
363 | tda80xx_close_loop(state); | ||
364 | state->afc_loop = 0; | ||
365 | } | ||
366 | |||
367 | if (state->status & (FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK)) { | ||
368 | val = tda80xx_readreg(state, 0x0e); | ||
369 | state->code_rate = fec_tab[val & 0x07]; | ||
370 | if (state->status & (FE_HAS_SYNC | FE_HAS_LOCK)) | ||
371 | state->spectral_inversion = inv_tab[(val >> 7) & 0x01]; | ||
372 | else | ||
373 | state->spectral_inversion = INVERSION_AUTO; | ||
374 | } | ||
375 | else { | ||
376 | state->code_rate = FEC_AUTO; | ||
377 | } | ||
378 | } | ||
379 | |||
380 | static void tda80xx_worklet(void *priv) | ||
381 | { | ||
382 | struct tda80xx_state *state = priv; | ||
383 | |||
384 | tda80xx_writereg(state, 0x00, 0x04); | ||
385 | enable_irq(state->config->irq); | ||
386 | |||
387 | tda80xx_read_status_int(state); | ||
388 | } | ||
389 | |||
390 | static void tda80xx_wait_diseqc_fifo(struct tda80xx_state* state) | ||
391 | { | ||
392 | size_t i; | ||
393 | |||
394 | for (i = 0; i < 100; i++) { | ||
395 | if (tda80xx_readreg(state, 0x02) & 0x80) | ||
396 | break; | ||
397 | msleep(10); | ||
398 | } | ||
399 | } | ||
400 | |||
401 | static int tda8044_init(struct dvb_frontend* fe) | ||
402 | { | ||
403 | struct tda80xx_state* state = fe->demodulator_priv; | ||
404 | int ret; | ||
405 | |||
406 | /* | ||
407 | * this function is a mess... | ||
408 | */ | ||
409 | |||
410 | if ((ret = tda80xx_write(state, 0x00, tda8044_inittab_pre, sizeof(tda8044_inittab_pre)))) | ||
411 | return ret; | ||
412 | |||
413 | tda80xx_writereg(state, 0x0f, 0x50); | ||
414 | #if 1 | ||
415 | tda80xx_writereg(state, 0x20, 0x8F); /* FIXME */ | ||
416 | tda80xx_writereg(state, 0x20, state->config->volt18setting); /* FIXME */ | ||
417 | //tda80xx_writereg(state, 0x00, 0x04); | ||
418 | tda80xx_writereg(state, 0x00, 0x0C); | ||
419 | #endif | ||
420 | //tda80xx_writereg(state, 0x00, 0x08); /* Reset AFC1 loop filter */ | ||
421 | |||
422 | tda80xx_write(state, 0x00, tda8044_inittab_post, sizeof(tda8044_inittab_post)); | ||
423 | |||
424 | if (state->config->pll_init) { | ||
425 | tda80xx_writereg(state, 0x1c, 0x80); | ||
426 | state->config->pll_init(fe); | ||
427 | tda80xx_writereg(state, 0x1c, 0x00); | ||
428 | } | ||
429 | |||
430 | return 0; | ||
431 | } | ||
432 | |||
433 | static int tda8083_init(struct dvb_frontend* fe) | ||
434 | { | ||
435 | struct tda80xx_state* state = fe->demodulator_priv; | ||
436 | |||
437 | tda80xx_write(state, 0x00, tda8083_inittab, sizeof(tda8083_inittab)); | ||
438 | |||
439 | if (state->config->pll_init) { | ||
440 | tda80xx_writereg(state, 0x1c, 0x80); | ||
441 | state->config->pll_init(fe); | ||
442 | tda80xx_writereg(state, 0x1c, 0x00); | ||
443 | } | ||
444 | |||
445 | return 0; | ||
446 | } | ||
447 | |||
448 | static int tda80xx_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) | ||
449 | { | ||
450 | struct tda80xx_state* state = fe->demodulator_priv; | ||
451 | |||
452 | switch (voltage) { | ||
453 | case SEC_VOLTAGE_13: | ||
454 | return tda80xx_writereg(state, 0x20, state->config->volt13setting); | ||
455 | case SEC_VOLTAGE_18: | ||
456 | return tda80xx_writereg(state, 0x20, state->config->volt18setting); | ||
457 | case SEC_VOLTAGE_OFF: | ||
458 | return tda80xx_writereg(state, 0x20, 0); | ||
459 | default: | ||
460 | return -EINVAL; | ||
461 | } | ||
462 | } | ||
463 | |||
464 | static int tda80xx_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) | ||
465 | { | ||
466 | struct tda80xx_state* state = fe->demodulator_priv; | ||
467 | |||
468 | switch (tone) { | ||
469 | case SEC_TONE_OFF: | ||
470 | return tda80xx_writereg(state, 0x29, 0x00); | ||
471 | case SEC_TONE_ON: | ||
472 | return tda80xx_writereg(state, 0x29, 0x80); | ||
473 | default: | ||
474 | return -EINVAL; | ||
475 | } | ||
476 | } | ||
477 | |||
478 | static int tda80xx_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd) | ||
479 | { | ||
480 | struct tda80xx_state* state = fe->demodulator_priv; | ||
481 | |||
482 | if (cmd->msg_len > 6) | ||
483 | return -EINVAL; | ||
484 | |||
485 | tda80xx_writereg(state, 0x29, 0x08 | (cmd->msg_len - 3)); | ||
486 | tda80xx_write(state, 0x23, cmd->msg, cmd->msg_len); | ||
487 | tda80xx_writereg(state, 0x29, 0x0c | (cmd->msg_len - 3)); | ||
488 | tda80xx_wait_diseqc_fifo(state); | ||
489 | |||
490 | return 0; | ||
491 | } | ||
492 | |||
493 | static int tda80xx_send_diseqc_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t cmd) | ||
494 | { | ||
495 | struct tda80xx_state* state = fe->demodulator_priv; | ||
496 | |||
497 | switch (cmd) { | ||
498 | case SEC_MINI_A: | ||
499 | tda80xx_writereg(state, 0x29, 0x14); | ||
500 | break; | ||
501 | case SEC_MINI_B: | ||
502 | tda80xx_writereg(state, 0x29, 0x1c); | ||
503 | break; | ||
504 | default: | ||
505 | return -EINVAL; | ||
506 | } | ||
507 | |||
508 | tda80xx_wait_diseqc_fifo(state); | ||
509 | |||
510 | return 0; | ||
511 | } | ||
512 | |||
513 | static int tda80xx_sleep(struct dvb_frontend* fe) | ||
514 | { | ||
515 | struct tda80xx_state* state = fe->demodulator_priv; | ||
516 | |||
517 | tda80xx_writereg(state, 0x00, 0x02); /* enter standby */ | ||
518 | |||
519 | return 0; | ||
520 | } | ||
521 | |||
522 | static int tda80xx_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) | ||
523 | { | ||
524 | struct tda80xx_state* state = fe->demodulator_priv; | ||
525 | |||
526 | tda80xx_writereg(state, 0x1c, 0x80); | ||
527 | state->config->pll_set(fe, p); | ||
528 | tda80xx_writereg(state, 0x1c, 0x00); | ||
529 | |||
530 | tda80xx_set_parameters(state, p->inversion, p->u.qpsk.symbol_rate, p->u.qpsk.fec_inner); | ||
531 | tda80xx_set_clk(state); | ||
532 | //tda80xx_set_scpc_freq_offset(state); | ||
533 | state->afc_loop = 1; | ||
534 | |||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | static int tda80xx_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) | ||
539 | { | ||
540 | struct tda80xx_state* state = fe->demodulator_priv; | ||
541 | |||
542 | if (!state->config->irq) | ||
543 | tda80xx_read_status_int(state); | ||
544 | |||
545 | p->inversion = state->spectral_inversion; | ||
546 | p->u.qpsk.fec_inner = state->code_rate; | ||
547 | |||
548 | return 0; | ||
549 | } | ||
550 | |||
551 | static int tda80xx_read_status(struct dvb_frontend* fe, fe_status_t* status) | ||
552 | { | ||
553 | struct tda80xx_state* state = fe->demodulator_priv; | ||
554 | |||
555 | if (!state->config->irq) | ||
556 | tda80xx_read_status_int(state); | ||
557 | *status = state->status; | ||
558 | |||
559 | return 0; | ||
560 | } | ||
561 | |||
562 | static int tda80xx_read_ber(struct dvb_frontend* fe, u32* ber) | ||
563 | { | ||
564 | struct tda80xx_state* state = fe->demodulator_priv; | ||
565 | int ret; | ||
566 | u8 buf[3]; | ||
567 | |||
568 | if ((ret = tda80xx_read(state, 0x0b, buf, sizeof(buf)))) | ||
569 | return ret; | ||
570 | |||
571 | *ber = ((buf[0] & 0x1f) << 16) | (buf[1] << 8) | buf[2]; | ||
572 | |||
573 | return 0; | ||
574 | } | ||
575 | |||
576 | static int tda80xx_read_signal_strength(struct dvb_frontend* fe, u16* strength) | ||
577 | { | ||
578 | struct tda80xx_state* state = fe->demodulator_priv; | ||
579 | |||
580 | u8 gain = ~tda80xx_readreg(state, 0x01); | ||
581 | *strength = (gain << 8) | gain; | ||
582 | |||
583 | return 0; | ||
584 | } | ||
585 | |||
586 | static int tda80xx_read_snr(struct dvb_frontend* fe, u16* snr) | ||
587 | { | ||
588 | struct tda80xx_state* state = fe->demodulator_priv; | ||
589 | |||
590 | u8 quality = tda80xx_readreg(state, 0x08); | ||
591 | *snr = (quality << 8) | quality; | ||
592 | |||
593 | return 0; | ||
594 | } | ||
595 | |||
596 | static int tda80xx_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) | ||
597 | { | ||
598 | struct tda80xx_state* state = fe->demodulator_priv; | ||
599 | |||
600 | *ucblocks = tda80xx_readreg(state, 0x0f); | ||
601 | if (*ucblocks == 0xff) | ||
602 | *ucblocks = 0xffffffff; | ||
603 | |||
604 | return 0; | ||
605 | } | ||
606 | |||
607 | static int tda80xx_init(struct dvb_frontend* fe) | ||
608 | { | ||
609 | struct tda80xx_state* state = fe->demodulator_priv; | ||
610 | |||
611 | switch(state->id) { | ||
612 | case ID_TDA8044: | ||
613 | return tda8044_init(fe); | ||
614 | |||
615 | case ID_TDA8083: | ||
616 | return tda8083_init(fe); | ||
617 | } | ||
618 | return 0; | ||
619 | } | ||
620 | |||
621 | static void tda80xx_release(struct dvb_frontend* fe) | ||
622 | { | ||
623 | struct tda80xx_state* state = fe->demodulator_priv; | ||
624 | |||
625 | if (state->config->irq) | ||
626 | free_irq(state->config->irq, &state->worklet); | ||
627 | |||
628 | kfree(state); | ||
629 | } | ||
630 | |||
631 | static struct dvb_frontend_ops tda80xx_ops; | ||
632 | |||
633 | struct dvb_frontend* tda80xx_attach(const struct tda80xx_config* config, | ||
634 | struct i2c_adapter* i2c) | ||
635 | { | ||
636 | struct tda80xx_state* state = NULL; | ||
637 | int ret; | ||
638 | |||
639 | /* allocate memory for the internal state */ | ||
640 | state = kmalloc(sizeof(struct tda80xx_state), GFP_KERNEL); | ||
641 | if (state == NULL) goto error; | ||
642 | |||
643 | /* setup the state */ | ||
644 | state->config = config; | ||
645 | state->i2c = i2c; | ||
646 | memcpy(&state->ops, &tda80xx_ops, sizeof(struct dvb_frontend_ops)); | ||
647 | state->spectral_inversion = INVERSION_AUTO; | ||
648 | state->code_rate = FEC_AUTO; | ||
649 | state->status = 0; | ||
650 | state->afc_loop = 0; | ||
651 | |||
652 | /* check if the demod is there */ | ||
653 | if (tda80xx_writereg(state, 0x89, 0x00) < 0) goto error; | ||
654 | state->id = tda80xx_readreg(state, 0x00); | ||
655 | |||
656 | switch (state->id) { | ||
657 | case ID_TDA8044: | ||
658 | state->clk = 96000000; | ||
659 | printk("tda80xx: Detected tda8044\n"); | ||
660 | break; | ||
661 | |||
662 | case ID_TDA8083: | ||
663 | state->clk = 64000000; | ||
664 | printk("tda80xx: Detected tda8083\n"); | ||
665 | break; | ||
666 | |||
667 | default: | ||
668 | goto error; | ||
669 | } | ||
670 | |||
671 | /* setup IRQ */ | ||
672 | if (state->config->irq) { | ||
673 | INIT_WORK(&state->worklet, tda80xx_worklet, state); | ||
674 | if ((ret = request_irq(state->config->irq, tda80xx_irq, SA_ONESHOT, "tda80xx", &state->worklet)) < 0) { | ||
675 | printk(KERN_ERR "tda80xx: request_irq failed (%d)\n", ret); | ||
676 | goto error; | ||
677 | } | ||
678 | } | ||
679 | |||
680 | /* create dvb_frontend */ | ||
681 | state->frontend.ops = &state->ops; | ||
682 | state->frontend.demodulator_priv = state; | ||
683 | return &state->frontend; | ||
684 | |||
685 | error: | ||
686 | kfree(state); | ||
687 | return NULL; | ||
688 | } | ||
689 | |||
690 | static struct dvb_frontend_ops tda80xx_ops = { | ||
691 | |||
692 | .info = { | ||
693 | .name = "Philips TDA80xx DVB-S", | ||
694 | .type = FE_QPSK, | ||
695 | .frequency_min = 500000, | ||
696 | .frequency_max = 2700000, | ||
697 | .frequency_stepsize = 125, | ||
698 | .symbol_rate_min = 4500000, | ||
699 | .symbol_rate_max = 45000000, | ||
700 | .caps = FE_CAN_INVERSION_AUTO | | ||
701 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
702 | FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | | ||
703 | FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | | ||
704 | FE_CAN_QPSK | | ||
705 | FE_CAN_MUTE_TS | ||
706 | }, | ||
707 | |||
708 | .release = tda80xx_release, | ||
709 | |||
710 | .init = tda80xx_init, | ||
711 | .sleep = tda80xx_sleep, | ||
712 | |||
713 | .set_frontend = tda80xx_set_frontend, | ||
714 | .get_frontend = tda80xx_get_frontend, | ||
715 | |||
716 | .read_status = tda80xx_read_status, | ||
717 | .read_ber = tda80xx_read_ber, | ||
718 | .read_signal_strength = tda80xx_read_signal_strength, | ||
719 | .read_snr = tda80xx_read_snr, | ||
720 | .read_ucblocks = tda80xx_read_ucblocks, | ||
721 | |||
722 | .diseqc_send_master_cmd = tda80xx_send_diseqc_msg, | ||
723 | .diseqc_send_burst = tda80xx_send_diseqc_burst, | ||
724 | .set_tone = tda80xx_set_tone, | ||
725 | .set_voltage = tda80xx_set_voltage, | ||
726 | }; | ||
727 | |||
728 | module_param(debug, int, 0644); | ||
729 | |||
730 | MODULE_DESCRIPTION("Philips TDA8044 / TDA8083 DVB-S Demodulator driver"); | ||
731 | MODULE_AUTHOR("Felix Domke, Andreas Oberritter"); | ||
732 | MODULE_LICENSE("GPL"); | ||
733 | |||
734 | EXPORT_SYMBOL(tda80xx_attach); | ||
diff --git a/drivers/media/dvb/frontends/tda80xx.h b/drivers/media/dvb/frontends/tda80xx.h deleted file mode 100644 index cd639a0aad55..000000000000 --- a/drivers/media/dvb/frontends/tda80xx.h +++ /dev/null | |||
@@ -1,51 +0,0 @@ | |||
1 | /* | ||
2 | * tda80xx.c | ||
3 | * | ||
4 | * Philips TDA8044 / TDA8083 QPSK demodulator driver | ||
5 | * | ||
6 | * Copyright (C) 2001 Felix Domke <tmbinc@elitedvb.net> | ||
7 | * Copyright (C) 2002-2004 Andreas Oberritter <obi@linuxtv.org> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #ifndef TDA80XX_H | ||
25 | #define TDA80XX_H | ||
26 | |||
27 | #include <linux/dvb/frontend.h> | ||
28 | |||
29 | struct tda80xx_config | ||
30 | { | ||
31 | /* the demodulator's i2c address */ | ||
32 | u8 demod_address; | ||
33 | |||
34 | /* IRQ to use (0=>no IRQ used) */ | ||
35 | u32 irq; | ||
36 | |||
37 | /* Register setting to use for 13v */ | ||
38 | u8 volt13setting; | ||
39 | |||
40 | /* Register setting to use for 18v */ | ||
41 | u8 volt18setting; | ||
42 | |||
43 | /* PLL maintenance */ | ||
44 | int (*pll_init)(struct dvb_frontend* fe); | ||
45 | int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); | ||
46 | }; | ||
47 | |||
48 | extern struct dvb_frontend* tda80xx_attach(const struct tda80xx_config* config, | ||
49 | struct i2c_adapter* i2c); | ||
50 | |||
51 | #endif // TDA80XX_H | ||
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 27494901975f..d36369e9e88f 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c | |||
@@ -2329,6 +2329,17 @@ static int frontend_init(struct av7110 *av7110) | |||
2329 | av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110)); | 2329 | av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110)); |
2330 | break; | 2330 | break; |
2331 | 2331 | ||
2332 | case 0x0004: // Galaxis DVB-S rev1.3 | ||
2333 | /* ALPS BSRV2 */ | ||
2334 | av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap); | ||
2335 | if (av7110->fe) { | ||
2336 | av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; | ||
2337 | av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; | ||
2338 | av7110->fe->ops->set_tone = av7110_set_tone; | ||
2339 | av7110->recover = dvb_s_recover; | ||
2340 | } | ||
2341 | break; | ||
2342 | |||
2332 | case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */ | 2343 | case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */ |
2333 | /* Grundig 29504-451 */ | 2344 | /* Grundig 29504-451 */ |
2334 | av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap); | 2345 | av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap); |
@@ -2930,6 +2941,7 @@ MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV DVB-S rev1.3 SE"); | |||
2930 | MAKE_AV7110_INFO(ttt, "Technotrend/Hauppauge DVB-T"); | 2941 | MAKE_AV7110_INFO(ttt, "Technotrend/Hauppauge DVB-T"); |
2931 | MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C"); | 2942 | MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C"); |
2932 | MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6"); | 2943 | MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6"); |
2944 | MAKE_AV7110_INFO(gxs_1_3, "Galaxis DVB-S rev1.3"); | ||
2933 | 2945 | ||
2934 | static struct pci_device_id pci_tbl[] = { | 2946 | static struct pci_device_id pci_tbl[] = { |
2935 | MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000), | 2947 | MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000), |
@@ -2937,13 +2949,13 @@ static struct pci_device_id pci_tbl[] = { | |||
2937 | MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001), | 2949 | MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001), |
2938 | MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002), | 2950 | MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002), |
2939 | MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003), | 2951 | MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003), |
2952 | MAKE_EXTENSION_PCI(gxs_1_3, 0x13c2, 0x0004), | ||
2940 | MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006), | 2953 | MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006), |
2941 | MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008), | 2954 | MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008), |
2942 | MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a), | 2955 | MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a), |
2943 | MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e), | 2956 | MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e), |
2944 | MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002), | 2957 | MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002), |
2945 | 2958 | ||
2946 | /* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0004), UNDEFINED CARD */ // Galaxis DVB PC-Sat-Carte | ||
2947 | /* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1 | 2959 | /* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1 |
2948 | /* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v???? | 2960 | /* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v???? |
2949 | 2961 | ||
diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h index 6ea30df2e823..fafd25fab835 100644 --- a/drivers/media/dvb/ttpci/av7110.h +++ b/drivers/media/dvb/ttpci/av7110.h | |||
@@ -273,8 +273,6 @@ struct av7110 { | |||
273 | extern int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid, | 273 | extern int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid, |
274 | u16 subpid, u16 pcrpid); | 274 | u16 subpid, u16 pcrpid); |
275 | 275 | ||
276 | extern int av7110_setup_irc_config (struct av7110 *av7110, u32 ir_config); | ||
277 | |||
278 | extern int av7110_ir_init(struct av7110 *av7110); | 276 | extern int av7110_ir_init(struct av7110 *av7110); |
279 | extern void av7110_ir_exit(struct av7110 *av7110); | 277 | extern void av7110_ir_exit(struct av7110 *av7110); |
280 | 278 | ||
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c index 9138132ad25f..617e4f6c0ed7 100644 --- a/drivers/media/dvb/ttpci/av7110_ir.c +++ b/drivers/media/dvb/ttpci/av7110_ir.c | |||
@@ -155,6 +155,19 @@ static void input_repeat_key(unsigned long data) | |||
155 | } | 155 | } |
156 | 156 | ||
157 | 157 | ||
158 | static int av7110_setup_irc_config(struct av7110 *av7110, u32 ir_config) | ||
159 | { | ||
160 | int ret = 0; | ||
161 | |||
162 | dprintk(4, "%p\n", av7110); | ||
163 | if (av7110) { | ||
164 | ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, ir_config); | ||
165 | av7110->ir_config = ir_config; | ||
166 | } | ||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | |||
158 | static int av7110_ir_write_proc(struct file *file, const char __user *buffer, | 171 | static int av7110_ir_write_proc(struct file *file, const char __user *buffer, |
159 | unsigned long count, void *data) | 172 | unsigned long count, void *data) |
160 | { | 173 | { |
@@ -187,19 +200,6 @@ static int av7110_ir_write_proc(struct file *file, const char __user *buffer, | |||
187 | } | 200 | } |
188 | 201 | ||
189 | 202 | ||
190 | int av7110_setup_irc_config(struct av7110 *av7110, u32 ir_config) | ||
191 | { | ||
192 | int ret = 0; | ||
193 | |||
194 | dprintk(4, "%p\n", av7110); | ||
195 | if (av7110) { | ||
196 | ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, ir_config); | ||
197 | av7110->ir_config = ir_config; | ||
198 | } | ||
199 | return ret; | ||
200 | } | ||
201 | |||
202 | |||
203 | static void ir_handler(struct av7110 *av7110, u32 ircom) | 203 | static void ir_handler(struct av7110 *av7110, u32 ircom) |
204 | { | 204 | { |
205 | dprintk(4, "ircommand = %08x\n", ircom); | 205 | dprintk(4, "ircommand = %08x\n", ircom); |
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index aa4c4c521880..578b20085082 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c | |||
@@ -214,7 +214,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = { | |||
214 | we can capture, of the first and second field. */ | 214 | we can capture, of the first and second field. */ |
215 | .vbistart = { 7,320 }, | 215 | .vbistart = { 7,320 }, |
216 | },{ | 216 | },{ |
217 | .v4l2_id = V4L2_STD_NTSC_M, | 217 | .v4l2_id = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR, |
218 | .name = "NTSC", | 218 | .name = "NTSC", |
219 | .Fsc = 28636363, | 219 | .Fsc = 28636363, |
220 | .swidth = 768, | 220 | .swidth = 768, |
diff --git a/drivers/media/video/compat_ioctl32.c b/drivers/media/video/compat_ioctl32.c index 297c32ab51e3..840fe0177121 100644 --- a/drivers/media/video/compat_ioctl32.c +++ b/drivers/media/video/compat_ioctl32.c | |||
@@ -167,29 +167,32 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user | |||
167 | if (kp->clipcount > 2048) | 167 | if (kp->clipcount > 2048) |
168 | return -EINVAL; | 168 | return -EINVAL; |
169 | if (kp->clipcount) { | 169 | if (kp->clipcount) { |
170 | struct v4l2_clip32 *uclips = compat_ptr(up->clips); | 170 | struct v4l2_clip32 __user *uclips; |
171 | struct v4l2_clip *kclips; | 171 | struct v4l2_clip __user *kclips; |
172 | int n = kp->clipcount; | 172 | int n = kp->clipcount; |
173 | compat_caddr_t p; | ||
173 | 174 | ||
175 | if (get_user(p, &up->clips)) | ||
176 | return -EFAULT; | ||
177 | uclips = compat_ptr(p); | ||
174 | kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip)); | 178 | kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip)); |
175 | kp->clips = kclips; | 179 | kp->clips = kclips; |
176 | while (--n >= 0) { | 180 | while (--n >= 0) { |
177 | if (!access_ok(VERIFY_READ, &uclips->c, sizeof(uclips->c)) || | 181 | if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c))) |
178 | copy_from_user(&kclips->c, &uclips->c, sizeof(uclips->c))) | 182 | return -EFAULT; |
183 | if (put_user(n ? kclips + 1 : NULL, &kclips->next)) | ||
179 | return -EFAULT; | 184 | return -EFAULT; |
180 | kclips->next = n ? kclips + 1 : 0; | ||
181 | uclips += 1; | 185 | uclips += 1; |
182 | kclips += 1; | 186 | kclips += 1; |
183 | } | 187 | } |
184 | } else | 188 | } else |
185 | kp->clips = 0; | 189 | kp->clips = NULL; |
186 | return 0; | 190 | return 0; |
187 | } | 191 | } |
188 | 192 | ||
189 | static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) | 193 | static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) |
190 | { | 194 | { |
191 | if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_window32)) || | 195 | if (copy_to_user(&up->w, &kp->w, sizeof(up->w)) || |
192 | copy_to_user(&up->w, &kp->w, sizeof(up->w)) || | ||
193 | put_user(kp->field, &up->field) || | 196 | put_user(kp->field, &up->field) || |
194 | put_user(kp->chromakey, &up->chromakey) || | 197 | put_user(kp->chromakey, &up->chromakey) || |
195 | put_user(kp->clipcount, &up->clipcount)) | 198 | put_user(kp->clipcount, &up->clipcount)) |
@@ -199,33 +202,29 @@ static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user | |||
199 | 202 | ||
200 | static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) | 203 | static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) |
201 | { | 204 | { |
202 | if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_pix_format)) || | 205 | if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format))) |
203 | copy_from_user(kp, up, sizeof(struct v4l2_pix_format))) | 206 | return -EFAULT; |
204 | return -EFAULT; | ||
205 | return 0; | 207 | return 0; |
206 | } | 208 | } |
207 | 209 | ||
208 | static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) | 210 | static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) |
209 | { | 211 | { |
210 | if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_pix_format)) || | 212 | if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format))) |
211 | copy_to_user(up, kp, sizeof(struct v4l2_pix_format))) | 213 | return -EFAULT; |
212 | return -EFAULT; | ||
213 | return 0; | 214 | return 0; |
214 | } | 215 | } |
215 | 216 | ||
216 | static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) | 217 | static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) |
217 | { | 218 | { |
218 | if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_vbi_format)) || | 219 | if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format))) |
219 | copy_from_user(kp, up, sizeof(struct v4l2_vbi_format))) | 220 | return -EFAULT; |
220 | return -EFAULT; | ||
221 | return 0; | 221 | return 0; |
222 | } | 222 | } |
223 | 223 | ||
224 | static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) | 224 | static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) |
225 | { | 225 | { |
226 | if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_vbi_format)) || | 226 | if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format))) |
227 | copy_to_user(up, kp, sizeof(struct v4l2_vbi_format))) | 227 | return -EFAULT; |
228 | return -EFAULT; | ||
229 | return 0; | 228 | return 0; |
230 | } | 229 | } |
231 | 230 | ||
@@ -279,18 +278,16 @@ static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user | |||
279 | 278 | ||
280 | static inline int get_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up) | 279 | static inline int get_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up) |
281 | { | 280 | { |
282 | if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard)) || | 281 | if (copy_from_user(kp, up, sizeof(struct v4l2_standard))) |
283 | copy_from_user(kp, up, sizeof(struct v4l2_standard))) | 282 | return -EFAULT; |
284 | return -EFAULT; | ||
285 | return 0; | 283 | return 0; |
286 | 284 | ||
287 | } | 285 | } |
288 | 286 | ||
289 | static inline int put_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up) | 287 | static inline int put_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up) |
290 | { | 288 | { |
291 | if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard)) || | 289 | if (copy_to_user(up, kp, sizeof(struct v4l2_standard))) |
292 | copy_to_user(up, kp, sizeof(struct v4l2_standard))) | 290 | return -EFAULT; |
293 | return -EFAULT; | ||
294 | return 0; | 291 | return 0; |
295 | } | 292 | } |
296 | 293 | ||
@@ -328,18 +325,16 @@ static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 | |||
328 | 325 | ||
329 | static inline int get_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up) | 326 | static inline int get_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up) |
330 | { | 327 | { |
331 | if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_tuner)) || | 328 | if (copy_from_user(kp, up, sizeof(struct v4l2_tuner))) |
332 | copy_from_user(kp, up, sizeof(struct v4l2_tuner))) | 329 | return -EFAULT; |
333 | return -EFAULT; | ||
334 | return 0; | 330 | return 0; |
335 | 331 | ||
336 | } | 332 | } |
337 | 333 | ||
338 | static inline int put_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up) | 334 | static inline int put_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up) |
339 | { | 335 | { |
340 | if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_tuner)) || | 336 | if (copy_to_user(up, kp, sizeof(struct v4l2_tuner))) |
341 | copy_to_user(up, kp, sizeof(struct v4l2_tuner))) | 337 | return -EFAULT; |
342 | return -EFAULT; | ||
343 | return 0; | 338 | return 0; |
344 | } | 339 | } |
345 | 340 | ||
@@ -380,11 +375,13 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user | |||
380 | break; | 375 | break; |
381 | case V4L2_MEMORY_USERPTR: | 376 | case V4L2_MEMORY_USERPTR: |
382 | { | 377 | { |
383 | unsigned long tmp = (unsigned long)compat_ptr(up->m.userptr); | 378 | compat_long_t tmp; |
384 | 379 | ||
385 | if(get_user(kp->length, &up->length) || | 380 | if (get_user(kp->length, &up->length) || |
386 | get_user(kp->m.userptr, &tmp)) | 381 | get_user(tmp, &up->m.userptr)) |
387 | return -EFAULT; | 382 | return -EFAULT; |
383 | |||
384 | kp->m.userptr = (unsigned long)compat_ptr(tmp); | ||
388 | } | 385 | } |
389 | break; | 386 | break; |
390 | case V4L2_MEMORY_OVERLAY: | 387 | case V4L2_MEMORY_OVERLAY: |
@@ -468,33 +465,29 @@ static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_frame | |||
468 | 465 | ||
469 | static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up) | 466 | static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up) |
470 | { | 467 | { |
471 | if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_input) - 4) || | 468 | if (copy_from_user(kp, up, sizeof(struct v4l2_input) - 4)) |
472 | copy_from_user(kp, up, sizeof(struct v4l2_input) - 4)) | 469 | return -EFAULT; |
473 | return -EFAULT; | ||
474 | return 0; | 470 | return 0; |
475 | } | 471 | } |
476 | 472 | ||
477 | static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up) | 473 | static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up) |
478 | { | 474 | { |
479 | if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_input) - 4) || | 475 | if (copy_to_user(up, kp, sizeof(struct v4l2_input) - 4)) |
480 | copy_to_user(up, kp, sizeof(struct v4l2_input) - 4)) | 476 | return -EFAULT; |
481 | return -EFAULT; | ||
482 | return 0; | 477 | return 0; |
483 | } | 478 | } |
484 | 479 | ||
485 | static inline int get_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up) | 480 | static inline int get_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up) |
486 | { | 481 | { |
487 | if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_input)) || | 482 | if (copy_from_user(kp, up, sizeof(struct v4l2_input))) |
488 | copy_from_user(kp, up, sizeof(struct v4l2_input))) | 483 | return -EFAULT; |
489 | return -EFAULT; | ||
490 | return 0; | 484 | return 0; |
491 | } | 485 | } |
492 | 486 | ||
493 | static inline int put_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up) | 487 | static inline int put_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up) |
494 | { | 488 | { |
495 | if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_input)) || | 489 | if (copy_to_user(up, kp, sizeof(struct v4l2_input))) |
496 | copy_to_user(up, kp, sizeof(struct v4l2_input))) | 490 | return -EFAULT; |
497 | return -EFAULT; | ||
498 | return 0; | 491 | return 0; |
499 | } | 492 | } |
500 | 493 | ||
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index c66c2c1f4809..08ffd1f325fc 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c | |||
@@ -220,33 +220,23 @@ static void input_change(struct i2c_client *client) | |||
220 | cx25840_write(client, 0x808, 0xff); | 220 | cx25840_write(client, 0x808, 0xff); |
221 | cx25840_write(client, 0x80b, 0x10); | 221 | cx25840_write(client, 0x80b, 0x10); |
222 | } else if (std & V4L2_STD_NTSC) { | 222 | } else if (std & V4L2_STD_NTSC) { |
223 | /* NTSC */ | 223 | /* Certain Hauppauge PVR150 models have a hardware bug |
224 | if (state->pvr150_workaround) { | 224 | that causes audio to drop out. For these models the |
225 | /* Certain Hauppauge PVR150 models have a hardware bug | 225 | audio standard must be set explicitly. |
226 | that causes audio to drop out. For these models the | 226 | To be precise: it affects cards with tuner models |
227 | audio standard must be set explicitly. | 227 | 85, 99 and 112 (model numbers from tveeprom). */ |
228 | To be precise: it affects cards with tuner models | 228 | int hw_fix = state->pvr150_workaround; |
229 | 85, 99 and 112 (model numbers from tveeprom). */ | 229 | |
230 | if (std == V4L2_STD_NTSC_M_JP) { | 230 | if (std == V4L2_STD_NTSC_M_JP) { |
231 | /* Japan uses EIAJ audio standard */ | ||
232 | cx25840_write(client, 0x808, 0x2f); | ||
233 | } else { | ||
234 | /* Others use the BTSC audio standard */ | ||
235 | cx25840_write(client, 0x808, 0x1f); | ||
236 | } | ||
237 | /* South Korea uses the A2-M (aka Zweiton M) audio | ||
238 | standard, and should set 0x808 to 0x3f, but I don't | ||
239 | know how to detect this. */ | ||
240 | } else if (std == V4L2_STD_NTSC_M_JP) { | ||
241 | /* Japan uses EIAJ audio standard */ | 231 | /* Japan uses EIAJ audio standard */ |
242 | cx25840_write(client, 0x808, 0xf7); | 232 | cx25840_write(client, 0x808, hw_fix ? 0x2f : 0xf7); |
233 | } else if (std == V4L2_STD_NTSC_M_KR) { | ||
234 | /* South Korea uses A2 audio standard */ | ||
235 | cx25840_write(client, 0x808, hw_fix ? 0x3f : 0xf8); | ||
243 | } else { | 236 | } else { |
244 | /* Others use the BTSC audio standard */ | 237 | /* Others use the BTSC audio standard */ |
245 | cx25840_write(client, 0x808, 0xf6); | 238 | cx25840_write(client, 0x808, hw_fix ? 0x1f : 0xf6); |
246 | } | 239 | } |
247 | /* South Korea uses the A2-M (aka Zweiton M) audio standard, | ||
248 | and should set 0x808 to 0xf8, but I don't know how to | ||
249 | detect this. */ | ||
250 | cx25840_write(client, 0x80b, 0x00); | 240 | cx25840_write(client, 0x80b, 0x00); |
251 | } | 241 | } |
252 | 242 | ||
@@ -330,17 +320,17 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std) | |||
330 | u8 fmt=0; /* zero is autodetect */ | 320 | u8 fmt=0; /* zero is autodetect */ |
331 | 321 | ||
332 | /* First tests should be against specific std */ | 322 | /* First tests should be against specific std */ |
333 | if (std & V4L2_STD_NTSC_M_JP) { | 323 | if (std == V4L2_STD_NTSC_M_JP) { |
334 | fmt=0x2; | 324 | fmt=0x2; |
335 | } else if (std & V4L2_STD_NTSC_443) { | 325 | } else if (std == V4L2_STD_NTSC_443) { |
336 | fmt=0x3; | 326 | fmt=0x3; |
337 | } else if (std & V4L2_STD_PAL_M) { | 327 | } else if (std == V4L2_STD_PAL_M) { |
338 | fmt=0x5; | 328 | fmt=0x5; |
339 | } else if (std & V4L2_STD_PAL_N) { | 329 | } else if (std == V4L2_STD_PAL_N) { |
340 | fmt=0x6; | 330 | fmt=0x6; |
341 | } else if (std & V4L2_STD_PAL_Nc) { | 331 | } else if (std == V4L2_STD_PAL_Nc) { |
342 | fmt=0x7; | 332 | fmt=0x7; |
343 | } else if (std & V4L2_STD_PAL_60) { | 333 | } else if (std == V4L2_STD_PAL_60) { |
344 | fmt=0x8; | 334 | fmt=0x8; |
345 | } else { | 335 | } else { |
346 | /* Then, test against generic ones */ | 336 | /* Then, test against generic ones */ |
@@ -369,7 +359,7 @@ v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client) | |||
369 | } | 359 | } |
370 | 360 | ||
371 | switch (fmt) { | 361 | switch (fmt) { |
372 | case 0x1: return V4L2_STD_NTSC_M; | 362 | case 0x1: return V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR; |
373 | case 0x2: return V4L2_STD_NTSC_M_JP; | 363 | case 0x2: return V4L2_STD_NTSC_M_JP; |
374 | case 0x3: return V4L2_STD_NTSC_443; | 364 | case 0x3: return V4L2_STD_NTSC_443; |
375 | case 0x4: return V4L2_STD_PAL; | 365 | case 0x4: return V4L2_STD_PAL; |
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 53308911ae6e..e99dfbbf3e95 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig | |||
@@ -32,6 +32,7 @@ config VIDEO_CX88_DVB | |||
32 | config VIDEO_CX88_ALSA | 32 | config VIDEO_CX88_ALSA |
33 | tristate "ALSA DMA audio support" | 33 | tristate "ALSA DMA audio support" |
34 | depends on VIDEO_CX88 && SND && EXPERIMENTAL | 34 | depends on VIDEO_CX88 && SND && EXPERIMENTAL |
35 | select SND_PCM | ||
35 | ---help--- | 36 | ---help--- |
36 | This is a video4linux driver for direct (DMA) audio on | 37 | This is a video4linux driver for direct (DMA) audio on |
37 | Conexant 2388x based TV cards. | 38 | Conexant 2388x based TV cards. |
@@ -48,6 +49,7 @@ config VIDEO_CX88_DVB_ALL_FRONTENDS | |||
48 | default y | 49 | default y |
49 | depends on VIDEO_CX88_DVB | 50 | depends on VIDEO_CX88_DVB |
50 | select DVB_MT352 | 51 | select DVB_MT352 |
52 | select VIDEO_CX88_VP3054 | ||
51 | select DVB_OR51132 | 53 | select DVB_OR51132 |
52 | select DVB_CX22702 | 54 | select DVB_CX22702 |
53 | select DVB_LGDT330X | 55 | select DVB_LGDT330X |
@@ -69,6 +71,16 @@ config VIDEO_CX88_DVB_MT352 | |||
69 | This adds DVB-T support for cards based on the | 71 | This adds DVB-T support for cards based on the |
70 | Connexant 2388x chip and the MT352 demodulator. | 72 | Connexant 2388x chip and the MT352 demodulator. |
71 | 73 | ||
74 | config VIDEO_CX88_VP3054 | ||
75 | tristate "VP-3054 Secondary I2C Bus Support" | ||
76 | default m | ||
77 | depends on DVB_MT352 | ||
78 | ---help--- | ||
79 | This adds DVB-T support for cards based on the | ||
80 | Connexant 2388x chip and the MT352 demodulator, | ||
81 | which also require support for the VP-3054 | ||
82 | Secondary I2C bus, such at DNTV Live! DVB-T Pro. | ||
83 | |||
72 | config VIDEO_CX88_DVB_OR51132 | 84 | config VIDEO_CX88_DVB_OR51132 |
73 | bool "OR51132 ATSC Support" | 85 | bool "OR51132 ATSC Support" |
74 | default y | 86 | default y |
diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile index 6e5eaa22619e..2b902784facc 100644 --- a/drivers/media/video/cx88/Makefile +++ b/drivers/media/video/cx88/Makefile | |||
@@ -4,8 +4,9 @@ cx8800-objs := cx88-video.o cx88-vbi.o | |||
4 | cx8802-objs := cx88-mpeg.o | 4 | cx8802-objs := cx88-mpeg.o |
5 | 5 | ||
6 | obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o cx8802.o cx88-blackbird.o | 6 | obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o cx8802.o cx88-blackbird.o |
7 | obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o cx88-vp3054-i2c.o | 7 | obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o |
8 | obj-$(CONFIG_VIDEO_CX88_ALSA) += cx88-alsa.o | 8 | obj-$(CONFIG_VIDEO_CX88_ALSA) += cx88-alsa.o |
9 | obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o | ||
9 | 10 | ||
10 | EXTRA_CFLAGS += -I$(src)/.. | 11 | EXTRA_CFLAGS += -I$(src)/.. |
11 | EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core | 12 | EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core |
@@ -18,6 +19,6 @@ extra-cflags-$(CONFIG_DVB_LGDT330X) += -DHAVE_LGDT330X=1 | |||
18 | extra-cflags-$(CONFIG_DVB_MT352) += -DHAVE_MT352=1 | 19 | extra-cflags-$(CONFIG_DVB_MT352) += -DHAVE_MT352=1 |
19 | extra-cflags-$(CONFIG_DVB_NXT200X) += -DHAVE_NXT200X=1 | 20 | extra-cflags-$(CONFIG_DVB_NXT200X) += -DHAVE_NXT200X=1 |
20 | extra-cflags-$(CONFIG_DVB_CX24123) += -DHAVE_CX24123=1 | 21 | extra-cflags-$(CONFIG_DVB_CX24123) += -DHAVE_CX24123=1 |
21 | extra-cflags-$(CONFIG_VIDEO_CX88_DVB)+= -DHAVE_VP3054_I2C=1 | 22 | extra-cflags-$(CONFIG_VIDEO_CX88_VP3054)+= -DHAVE_VP3054_I2C=1 |
22 | 23 | ||
23 | EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m) | 24 | EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m) |
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index a2e36a1e5f59..2acccd6d49bc 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c | |||
@@ -128,7 +128,7 @@ MODULE_PARM_DESC(debug,"enable debug messages"); | |||
128 | * BOARD Specific: Sets audio DMA | 128 | * BOARD Specific: Sets audio DMA |
129 | */ | 129 | */ |
130 | 130 | ||
131 | int _cx88_start_audio_dma(snd_cx88_card_t *chip) | 131 | static int _cx88_start_audio_dma(snd_cx88_card_t *chip) |
132 | { | 132 | { |
133 | struct cx88_buffer *buf = chip->buf; | 133 | struct cx88_buffer *buf = chip->buf; |
134 | struct cx88_core *core=chip->core; | 134 | struct cx88_core *core=chip->core; |
@@ -173,7 +173,7 @@ int _cx88_start_audio_dma(snd_cx88_card_t *chip) | |||
173 | /* | 173 | /* |
174 | * BOARD Specific: Resets audio DMA | 174 | * BOARD Specific: Resets audio DMA |
175 | */ | 175 | */ |
176 | int _cx88_stop_audio_dma(snd_cx88_card_t *chip) | 176 | static int _cx88_stop_audio_dma(snd_cx88_card_t *chip) |
177 | { | 177 | { |
178 | struct cx88_core *core=chip->core; | 178 | struct cx88_core *core=chip->core; |
179 | dprintk(1, "Stopping audio DMA\n"); | 179 | dprintk(1, "Stopping audio DMA\n"); |
@@ -613,7 +613,7 @@ static snd_kcontrol_new_t snd_cx88_capture_volume = { | |||
613 | * Only boards with eeprom and byte 1 at eeprom=1 have it | 613 | * Only boards with eeprom and byte 1 at eeprom=1 have it |
614 | */ | 614 | */ |
615 | 615 | ||
616 | struct pci_device_id cx88_audio_pci_tbl[] = { | 616 | static struct pci_device_id cx88_audio_pci_tbl[] = { |
617 | {0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, | 617 | {0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, |
618 | {0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, | 618 | {0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, |
619 | {0, } | 619 | {0, } |
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index ad2f565f522c..1bc999247fdc 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c | |||
@@ -1246,6 +1246,11 @@ struct cx88_subid cx88_subids[] = { | |||
1246 | .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL, | 1246 | .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL, |
1247 | },{ | 1247 | },{ |
1248 | .subvendor = 0x18ac, | 1248 | .subvendor = 0x18ac, |
1249 | .subdevice = 0xdb54, | ||
1250 | .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL, | ||
1251 | /* Re-branded DViCO: DigitalNow DVB-T Dual */ | ||
1252 | },{ | ||
1253 | .subvendor = 0x18ac, | ||
1249 | .subdevice = 0xdb11, | 1254 | .subdevice = 0xdb11, |
1250 | .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS, | 1255 | .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS, |
1251 | /* Re-branded DViCO: UltraView DVB-T Plus */ | 1256 | /* Re-branded DViCO: UltraView DVB-T Plus */ |
@@ -1293,6 +1298,7 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) | |||
1293 | switch (tv.model) | 1298 | switch (tv.model) |
1294 | { | 1299 | { |
1295 | case 28552: /* WinTV-PVR 'Roslyn' (No IR) */ | 1300 | case 28552: /* WinTV-PVR 'Roslyn' (No IR) */ |
1301 | case 34519: /* WinTV-PCI-FM */ | ||
1296 | case 90002: /* Nova-T-PCI (9002) */ | 1302 | case 90002: /* Nova-T-PCI (9002) */ |
1297 | case 92001: /* Nova-S-Plus (Video and IR) */ | 1303 | case 92001: /* Nova-S-Plus (Video and IR) */ |
1298 | case 92002: /* Nova-S-Plus (Video and IR) */ | 1304 | case 92002: /* Nova-S-Plus (Video and IR) */ |
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index 8d6d6a6cf785..3720f24a25cf 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c | |||
@@ -787,12 +787,14 @@ static int set_pll(struct cx88_core *core, int prescale, u32 ofreq) | |||
787 | 787 | ||
788 | int cx88_start_audio_dma(struct cx88_core *core) | 788 | int cx88_start_audio_dma(struct cx88_core *core) |
789 | { | 789 | { |
790 | /* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */ | ||
791 | int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4; | ||
790 | /* setup fifo + format */ | 792 | /* setup fifo + format */ |
791 | cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0); | 793 | cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0); |
792 | cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0); | 794 | cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0); |
793 | 795 | ||
794 | cx_write(MO_AUDD_LNGTH, 128); /* fifo bpl size */ | 796 | cx_write(MO_AUDD_LNGTH, bpl); /* fifo bpl size */ |
795 | cx_write(MO_AUDR_LNGTH, 128); /* fifo bpl size */ | 797 | cx_write(MO_AUDR_LNGTH, bpl); /* fifo bpl size */ |
796 | 798 | ||
797 | /* start dma */ | 799 | /* start dma */ |
798 | cx_write(MO_AUD_DMACNTRL, 0x0003); /* Up and Down fifo enable */ | 800 | cx_write(MO_AUD_DMACNTRL, 0x0003); /* Up and Down fifo enable */ |
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index da2ad5c4b553..165d948624a3 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c | |||
@@ -482,6 +482,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
482 | switch (core->board) { | 482 | switch (core->board) { |
483 | case CX88_BOARD_DNTV_LIVE_DVB_T: | 483 | case CX88_BOARD_DNTV_LIVE_DVB_T: |
484 | case CX88_BOARD_KWORLD_DVB_T: | 484 | case CX88_BOARD_KWORLD_DVB_T: |
485 | case CX88_BOARD_KWORLD_DVB_T_CX22702: | ||
485 | ir_codes = ir_codes_dntv_live_dvb_t; | 486 | ir_codes = ir_codes_dntv_live_dvb_t; |
486 | ir->gpio_addr = MO_GP1_IO; | 487 | ir->gpio_addr = MO_GP1_IO; |
487 | ir->mask_keycode = 0x1f; | 488 | ir->mask_keycode = 0x1f; |
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index dff3893f32fd..e5ee8bceb210 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c | |||
@@ -139,6 +139,9 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, | |||
139 | { | 139 | { |
140 | int ret, byte; | 140 | int ret, byte; |
141 | 141 | ||
142 | if (dev->state & DEV_DISCONNECTED) | ||
143 | return(-ENODEV); | ||
144 | |||
142 | em28xx_regdbg("req=%02x, reg=%02x ", req, reg); | 145 | em28xx_regdbg("req=%02x, reg=%02x ", req, reg); |
143 | 146 | ||
144 | ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, | 147 | ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, |
@@ -165,6 +168,9 @@ int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg) | |||
165 | u8 val; | 168 | u8 val; |
166 | int ret; | 169 | int ret; |
167 | 170 | ||
171 | if (dev->state & DEV_DISCONNECTED) | ||
172 | return(-ENODEV); | ||
173 | |||
168 | em28xx_regdbg("req=%02x, reg=%02x:", req, reg); | 174 | em28xx_regdbg("req=%02x, reg=%02x:", req, reg); |
169 | 175 | ||
170 | ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, | 176 | ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, |
@@ -195,7 +201,12 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, | |||
195 | int ret; | 201 | int ret; |
196 | 202 | ||
197 | /*usb_control_msg seems to expect a kmalloced buffer */ | 203 | /*usb_control_msg seems to expect a kmalloced buffer */ |
198 | unsigned char *bufs = kmalloc(len, GFP_KERNEL); | 204 | unsigned char *bufs; |
205 | |||
206 | if (dev->state & DEV_DISCONNECTED) | ||
207 | return(-ENODEV); | ||
208 | |||
209 | bufs = kmalloc(len, GFP_KERNEL); | ||
199 | 210 | ||
200 | em28xx_regdbg("req=%02x reg=%02x:", req, reg); | 211 | em28xx_regdbg("req=%02x reg=%02x:", req, reg); |
201 | 212 | ||
@@ -212,7 +223,7 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, | |||
212 | ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req, | 223 | ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req, |
213 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 224 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
214 | 0x0000, reg, bufs, len, HZ); | 225 | 0x0000, reg, bufs, len, HZ); |
215 | mdelay(5); /* FIXME: magic number */ | 226 | msleep(5); /* FIXME: magic number */ |
216 | kfree(bufs); | 227 | kfree(bufs); |
217 | return ret; | 228 | return ret; |
218 | } | 229 | } |
@@ -253,7 +264,7 @@ int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 * val) | |||
253 | if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0) | 264 | if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0) |
254 | return ret; | 265 | return ret; |
255 | else if (((u8) ret) & 0x01) { | 266 | else if (((u8) ret) & 0x01) { |
256 | em28xx_warn ("AC97 command still being exectuted: not handled properly!\n"); | 267 | em28xx_warn ("AC97 command still being executed: not handled properly!\n"); |
257 | } | 268 | } |
258 | return 0; | 269 | return 0; |
259 | } | 270 | } |
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 0591a705b7a1..6ca8631bc36d 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c | |||
@@ -78,7 +78,7 @@ static int em2800_i2c_send_max4(struct em28xx *dev, unsigned char addr, | |||
78 | ret = dev->em28xx_read_reg(dev, 0x05); | 78 | ret = dev->em28xx_read_reg(dev, 0x05); |
79 | if (ret == 0x80 + len - 1) | 79 | if (ret == 0x80 + len - 1) |
80 | return len; | 80 | return len; |
81 | mdelay(5); | 81 | msleep(5); |
82 | } | 82 | } |
83 | em28xx_warn("i2c write timed out\n"); | 83 | em28xx_warn("i2c write timed out\n"); |
84 | return -EIO; | 84 | return -EIO; |
@@ -138,7 +138,7 @@ static int em2800_i2c_check_for_device(struct em28xx *dev, unsigned char addr) | |||
138 | return -ENODEV; | 138 | return -ENODEV; |
139 | else if (msg == 0x84) | 139 | else if (msg == 0x84) |
140 | return 0; | 140 | return 0; |
141 | mdelay(5); | 141 | msleep(5); |
142 | } | 142 | } |
143 | return -ENODEV; | 143 | return -ENODEV; |
144 | } | 144 | } |
@@ -278,9 +278,9 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap, | |||
278 | msgs[i].buf, | 278 | msgs[i].buf, |
279 | msgs[i].len, | 279 | msgs[i].len, |
280 | i == num - 1); | 280 | i == num - 1); |
281 | if (rc < 0) | ||
282 | goto err; | ||
283 | } | 281 | } |
282 | if (rc < 0) | ||
283 | goto err; | ||
284 | if (i2c_debug>=2) | 284 | if (i2c_debug>=2) |
285 | printk("\n"); | 285 | printk("\n"); |
286 | } | 286 | } |
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index eea304f75176..94a14a2bb6d6 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -6,6 +6,9 @@ | |||
6 | Mauro Carvalho Chehab <mchehab@brturbo.com.br> | 6 | Mauro Carvalho Chehab <mchehab@brturbo.com.br> |
7 | Sascha Sommer <saschasommer@freenet.de> | 7 | Sascha Sommer <saschasommer@freenet.de> |
8 | 8 | ||
9 | Some parts based on SN9C10x PC Camera Controllers GPL driver made | ||
10 | by Luca Risolia <luca.risolia@studio.unibo.it> | ||
11 | |||
9 | This program is free software; you can redistribute it and/or modify | 12 | This program is free software; you can redistribute it and/or modify |
10 | it under the terms of the GNU General Public License as published by | 13 | it under the terms of the GNU General Public License as published by |
11 | the Free Software Foundation; either version 2 of the License, or | 14 | the Free Software Foundation; either version 2 of the License, or |
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index c64718aec9cb..5a35d3b6550d 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c | |||
@@ -136,7 +136,7 @@ struct saa7134_board saa7134_boards[] = { | |||
136 | }, | 136 | }, |
137 | [SAA7134_BOARD_FLYVIDEO2000] = { | 137 | [SAA7134_BOARD_FLYVIDEO2000] = { |
138 | /* "TC Wan" <tcwan@cs.usm.my> */ | 138 | /* "TC Wan" <tcwan@cs.usm.my> */ |
139 | .name = "LifeView FlyVIDEO2000", | 139 | .name = "LifeView/Typhoon FlyVIDEO2000", |
140 | .audio_clock = 0x00200000, | 140 | .audio_clock = 0x00200000, |
141 | .tuner_type = TUNER_LG_PAL_NEW_TAPC, | 141 | .tuner_type = TUNER_LG_PAL_NEW_TAPC, |
142 | .radio_type = UNSET, | 142 | .radio_type = UNSET, |
@@ -1884,44 +1884,38 @@ struct saa7134_board saa7134_boards[] = { | |||
1884 | .gpio = 0x000, | 1884 | .gpio = 0x000, |
1885 | }, | 1885 | }, |
1886 | }, | 1886 | }, |
1887 | [SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS] = { | 1887 | [SAA7134_BOARD_FLYDVBT_DUO_CARDBUS] = { |
1888 | .name = "Typhoon DVB-T Duo Digital/Analog Cardbus", | 1888 | .name = "LifeView/Typhoon FlyDVB-T Duo Cardbus", |
1889 | .audio_clock = 0x00200000, | 1889 | .audio_clock = 0x00200000, |
1890 | .tuner_type = TUNER_PHILIPS_TDA8290, | 1890 | .tuner_type = TUNER_PHILIPS_TDA8290, |
1891 | .radio_type = UNSET, | 1891 | .radio_type = UNSET, |
1892 | .tuner_addr = ADDR_UNSET, | 1892 | .tuner_addr = ADDR_UNSET, |
1893 | .radio_addr = ADDR_UNSET, | 1893 | .radio_addr = ADDR_UNSET, |
1894 | .mpeg = SAA7134_MPEG_DVB, | 1894 | .mpeg = SAA7134_MPEG_DVB, |
1895 | /* .gpiomask = 0xe000, */ | 1895 | .gpiomask = 0x00200000, |
1896 | .inputs = {{ | 1896 | .inputs = {{ |
1897 | .name = name_tv, | 1897 | .name = name_tv, |
1898 | .vmux = 1, | 1898 | .vmux = 1, |
1899 | .amux = TV, | 1899 | .amux = TV, |
1900 | /* .gpio = 0x0000, */ | 1900 | .gpio = 0x200000, /* GPIO21=High for TV input */ |
1901 | .tv = 1, | 1901 | .tv = 1, |
1902 | },{ | 1902 | },{ |
1903 | .name = name_svideo, /* S-Video signal on S-Video input */ | ||
1904 | .vmux = 8, | ||
1905 | .amux = LINE2, | ||
1906 | },{ | ||
1903 | .name = name_comp1, /* Composite signal on S-Video input */ | 1907 | .name = name_comp1, /* Composite signal on S-Video input */ |
1904 | .vmux = 0, | 1908 | .vmux = 0, |
1905 | .amux = LINE2, | 1909 | .amux = LINE2, |
1906 | /* .gpio = 0x4000, */ | ||
1907 | },{ | 1910 | },{ |
1908 | .name = name_comp2, /* Composite input */ | 1911 | .name = name_comp2, /* Composite input */ |
1909 | .vmux = 3, | 1912 | .vmux = 3, |
1910 | .amux = LINE2, | 1913 | .amux = LINE2, |
1911 | /* .gpio = 0x4000, */ | ||
1912 | },{ | ||
1913 | .name = name_svideo, /* S-Video signal on S-Video input */ | ||
1914 | .vmux = 8, | ||
1915 | .amux = LINE2, | ||
1916 | /* .gpio = 0x4000, */ | ||
1917 | }}, | 1914 | }}, |
1918 | .radio = { | 1915 | .radio = { |
1919 | .name = name_radio, | 1916 | .name = name_radio, |
1920 | .amux = LINE2, | 1917 | .amux = TV, |
1921 | }, | 1918 | .gpio = 0x000000, /* GPIO21=Low for FM radio antenna */ |
1922 | .mute = { | ||
1923 | .name = name_mute, | ||
1924 | .amux = LINE1, | ||
1925 | }, | 1919 | }, |
1926 | }, | 1920 | }, |
1927 | [SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII] = { | 1921 | [SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII] = { |
@@ -2701,6 +2695,12 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
2701 | .driver_data = SAA7134_BOARD_FLYVIDEO2000, | 2695 | .driver_data = SAA7134_BOARD_FLYVIDEO2000, |
2702 | },{ | 2696 | },{ |
2703 | .vendor = PCI_VENDOR_ID_PHILIPS, | 2697 | .vendor = PCI_VENDOR_ID_PHILIPS, |
2698 | .device = PCI_DEVICE_ID_PHILIPS_SAA7130, | ||
2699 | .subvendor = 0x4e42, /* Typhoon */ | ||
2700 | .subdevice = 0x0138, /* LifeView FlyTV Prime30 OEM */ | ||
2701 | .driver_data = SAA7134_BOARD_FLYVIDEO2000, | ||
2702 | },{ | ||
2703 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
2704 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | 2704 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, |
2705 | .subvendor = 0x5168, | 2705 | .subvendor = 0x5168, |
2706 | .subdevice = 0x0212, /* minipci, LR212 */ | 2706 | .subdevice = 0x0212, /* minipci, LR212 */ |
@@ -2935,7 +2935,7 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
2935 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | 2935 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, |
2936 | .subvendor = 0x5168, | 2936 | .subvendor = 0x5168, |
2937 | .subdevice = 0x0502, /* Cardbus version */ | 2937 | .subdevice = 0x0502, /* Cardbus version */ |
2938 | .driver_data = SAA7134_BOARD_FLYDVBTDUO, | 2938 | .driver_data = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS, |
2939 | },{ | 2939 | },{ |
2940 | .vendor = PCI_VENDOR_ID_PHILIPS, | 2940 | .vendor = PCI_VENDOR_ID_PHILIPS, |
2941 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | 2941 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, |
@@ -2980,12 +2980,12 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
2980 | .subdevice = 0x1370, /* cardbus version */ | 2980 | .subdevice = 0x1370, /* cardbus version */ |
2981 | .driver_data = SAA7134_BOARD_ADS_INSTANT_TV, | 2981 | .driver_data = SAA7134_BOARD_ADS_INSTANT_TV, |
2982 | 2982 | ||
2983 | },{ /* Typhoon DVB-T Duo Digital/Analog Cardbus */ | 2983 | },{ |
2984 | .vendor = PCI_VENDOR_ID_PHILIPS, | 2984 | .vendor = PCI_VENDOR_ID_PHILIPS, |
2985 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | 2985 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, |
2986 | .subvendor = 0x4e42, | 2986 | .subvendor = 0x4e42, /* Typhoon */ |
2987 | .subdevice = 0x0502, | 2987 | .subdevice = 0x0502, /* LifeView LR502 OEM */ |
2988 | .driver_data = SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS, | 2988 | .driver_data = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS, |
2989 | },{ | 2989 | },{ |
2990 | .vendor = PCI_VENDOR_ID_PHILIPS, | 2990 | .vendor = PCI_VENDOR_ID_PHILIPS, |
2991 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | 2991 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, |
@@ -3206,8 +3206,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
3206 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00040000, 0x00040000); | 3206 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00040000, 0x00040000); |
3207 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000004); | 3207 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000004); |
3208 | break; | 3208 | break; |
3209 | case SAA7134_BOARD_FLYDVBTDUO: | 3209 | case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS: |
3210 | case SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS: | ||
3211 | /* turn the fan on */ | 3210 | /* turn the fan on */ |
3212 | saa_writeb(SAA7134_GPIO_GPMODE3, 0x08); | 3211 | saa_writeb(SAA7134_GPIO_GPMODE3, 0x08); |
3213 | saa_writeb(SAA7134_GPIO_GPSTATUS3, 0x06); | 3212 | saa_writeb(SAA7134_GPIO_GPSTATUS3, 0x06); |
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 399f9952596c..1a536e865277 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c | |||
@@ -861,7 +861,7 @@ static int dvb_init(struct saa7134_dev *dev) | |||
861 | dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config, | 861 | dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config, |
862 | &dev->i2c_adap); | 862 | &dev->i2c_adap); |
863 | break; | 863 | break; |
864 | case SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS: | 864 | case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS: |
865 | dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config, | 865 | dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config, |
866 | &dev->i2c_adap); | 866 | &dev->i2c_adap); |
867 | break; | 867 | break; |
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index e70eae8d29bb..3261d8bebdd1 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h | |||
@@ -185,7 +185,7 @@ struct saa7134_format { | |||
185 | #define SAA7134_BOARD_AVERMEDIA_GO_007_FM 57 | 185 | #define SAA7134_BOARD_AVERMEDIA_GO_007_FM 57 |
186 | #define SAA7134_BOARD_ADS_INSTANT_TV 58 | 186 | #define SAA7134_BOARD_ADS_INSTANT_TV 58 |
187 | #define SAA7134_BOARD_KWORLD_VSTREAM_XPERT 59 | 187 | #define SAA7134_BOARD_KWORLD_VSTREAM_XPERT 59 |
188 | #define SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS 60 | 188 | #define SAA7134_BOARD_FLYDVBT_DUO_CARDBUS 60 |
189 | #define SAA7134_BOARD_PHILIPS_TOUGH 61 | 189 | #define SAA7134_BOARD_PHILIPS_TOUGH 61 |
190 | #define SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII 62 | 190 | #define SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII 62 |
191 | #define SAA7134_BOARD_KWORLD_XPERT 63 | 191 | #define SAA7134_BOARD_KWORLD_XPERT 63 |
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c index 54fc33011ffb..9d769264a329 100644 --- a/drivers/media/video/stradis.c +++ b/drivers/media/video/stradis.c | |||
@@ -2012,7 +2012,6 @@ static int __devinit init_saa7146(struct pci_dev *pdev) | |||
2012 | { | 2012 | { |
2013 | struct saa7146 *saa = pci_get_drvdata(pdev); | 2013 | struct saa7146 *saa = pci_get_drvdata(pdev); |
2014 | 2014 | ||
2015 | memset(saa, 0, sizeof(*saa)); | ||
2016 | saa->user = 0; | 2015 | saa->user = 0; |
2017 | /* reset the saa7146 */ | 2016 | /* reset the saa7146 */ |
2018 | saawrite(0xffff0000, SAA7146_MC1); | 2017 | saawrite(0xffff0000, SAA7146_MC1); |
@@ -2062,16 +2061,16 @@ static int __devinit init_saa7146(struct pci_dev *pdev) | |||
2062 | } | 2061 | } |
2063 | if (saa->audbuf == NULL && (saa->audbuf = vmalloc(65536)) == NULL) { | 2062 | if (saa->audbuf == NULL && (saa->audbuf = vmalloc(65536)) == NULL) { |
2064 | dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr); | 2063 | dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr); |
2065 | goto errvid; | 2064 | goto errfree; |
2066 | } | 2065 | } |
2067 | if (saa->osdbuf == NULL && (saa->osdbuf = vmalloc(131072)) == NULL) { | 2066 | if (saa->osdbuf == NULL && (saa->osdbuf = vmalloc(131072)) == NULL) { |
2068 | dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr); | 2067 | dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr); |
2069 | goto erraud; | 2068 | goto errfree; |
2070 | } | 2069 | } |
2071 | /* allocate 81920 byte buffer for clipping */ | 2070 | /* allocate 81920 byte buffer for clipping */ |
2072 | if ((saa->dmavid2 = kzalloc(VIDEO_CLIPMAP_SIZE, GFP_KERNEL)) == NULL) { | 2071 | if ((saa->dmavid2 = kzalloc(VIDEO_CLIPMAP_SIZE, GFP_KERNEL)) == NULL) { |
2073 | dev_err(&pdev->dev, "%d: clip kmalloc failed\n", saa->nr); | 2072 | dev_err(&pdev->dev, "%d: clip kmalloc failed\n", saa->nr); |
2074 | goto errosd; | 2073 | goto errfree; |
2075 | } | 2074 | } |
2076 | /* setup clipping registers */ | 2075 | /* setup clipping registers */ |
2077 | saawrite(virt_to_bus(saa->dmavid2), SAA7146_BASE_EVEN2); | 2076 | saawrite(virt_to_bus(saa->dmavid2), SAA7146_BASE_EVEN2); |
@@ -2085,15 +2084,11 @@ static int __devinit init_saa7146(struct pci_dev *pdev) | |||
2085 | I2CBusScan(saa); | 2084 | I2CBusScan(saa); |
2086 | 2085 | ||
2087 | return 0; | 2086 | return 0; |
2088 | errosd: | 2087 | errfree: |
2089 | vfree(saa->osdbuf); | 2088 | vfree(saa->osdbuf); |
2090 | saa->osdbuf = NULL; | ||
2091 | erraud: | ||
2092 | vfree(saa->audbuf); | 2089 | vfree(saa->audbuf); |
2093 | saa->audbuf = NULL; | ||
2094 | errvid: | ||
2095 | vfree(saa->vidbuf); | 2090 | vfree(saa->vidbuf); |
2096 | saa->vidbuf = NULL; | 2091 | saa->audbuf = saa->osdbuf = saa->vidbuf = NULL; |
2097 | err: | 2092 | err: |
2098 | return -ENOMEM; | 2093 | return -ENOMEM; |
2099 | } | 2094 | } |
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 5815649bdc78..0d54f6c1982b 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c | |||
@@ -231,7 +231,7 @@ static struct tvnorm tvnorms[] = { | |||
231 | cAudioIF_6_5 | | 231 | cAudioIF_6_5 | |
232 | cVideoIF_38_90 ), | 232 | cVideoIF_38_90 ), |
233 | },{ | 233 | },{ |
234 | .std = V4L2_STD_NTSC_M, | 234 | .std = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR, |
235 | .name = "NTSC-M", | 235 | .name = "NTSC-M", |
236 | .b = ( cNegativeFmTV | | 236 | .b = ( cNegativeFmTV | |
237 | cQSS ), | 237 | cQSS ), |
@@ -619,6 +619,11 @@ static int tda9887_fixup_std(struct tda9887 *t) | |||
619 | tda9887_dbg("insmod fixup: NTSC => NTSC_M_JP\n"); | 619 | tda9887_dbg("insmod fixup: NTSC => NTSC_M_JP\n"); |
620 | t->std = V4L2_STD_NTSC_M_JP; | 620 | t->std = V4L2_STD_NTSC_M_JP; |
621 | break; | 621 | break; |
622 | case 'k': | ||
623 | case 'K': | ||
624 | tda9887_dbg("insmod fixup: NTSC => NTSC_M_KR\n"); | ||
625 | t->std = V4L2_STD_NTSC_M_KR; | ||
626 | break; | ||
622 | case '-': | 627 | case '-': |
623 | /* default parameter, do nothing */ | 628 | /* default parameter, do nothing */ |
624 | break; | 629 | break; |
@@ -876,7 +881,7 @@ static int tda9887_resume(struct device * dev) | |||
876 | /* ----------------------------------------------------------------------- */ | 881 | /* ----------------------------------------------------------------------- */ |
877 | 882 | ||
878 | static struct i2c_driver driver = { | 883 | static struct i2c_driver driver = { |
879 | .id = -1, /* FIXME */ | 884 | .id = I2C_DRIVERID_TDA9887, |
880 | .attach_adapter = tda9887_probe, | 885 | .attach_adapter = tda9887_probe, |
881 | .detach_client = tda9887_detach, | 886 | .detach_client = tda9887_detach, |
882 | .command = tda9887_command, | 887 | .command = tda9887_command, |
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 2995b22acb43..e7ee619d62c5 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c | |||
@@ -216,6 +216,7 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
216 | buffer[3] = 0xa4; | 216 | buffer[3] = 0xa4; |
217 | i2c_master_send(c,buffer,4); | 217 | i2c_master_send(c,buffer,4); |
218 | default_tuner_init(c); | 218 | default_tuner_init(c); |
219 | break; | ||
219 | default: | 220 | default: |
220 | default_tuner_init(c); | 221 | default_tuner_init(c); |
221 | break; | 222 | break; |
@@ -365,6 +366,11 @@ static int tuner_fixup_std(struct tuner *t) | |||
365 | tuner_dbg("insmod fixup: NTSC => NTSC_M_JP\n"); | 366 | tuner_dbg("insmod fixup: NTSC => NTSC_M_JP\n"); |
366 | t->std = V4L2_STD_NTSC_M_JP; | 367 | t->std = V4L2_STD_NTSC_M_JP; |
367 | break; | 368 | break; |
369 | case 'k': | ||
370 | case 'K': | ||
371 | tuner_dbg("insmod fixup: NTSC => NTSC_M_KR\n"); | ||
372 | t->std = V4L2_STD_NTSC_M_KR; | ||
373 | break; | ||
368 | case '-': | 374 | case '-': |
369 | /* default parameter, do nothing */ | 375 | /* default parameter, do nothing */ |
370 | break; | 376 | break; |
@@ -448,7 +454,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) | |||
448 | printk("%02x ",buffer[i]); | 454 | printk("%02x ",buffer[i]); |
449 | printk("\n"); | 455 | printk("\n"); |
450 | } | 456 | } |
451 | /* TEA5767 autodetection code - only for addr = 0xc0 */ | 457 | /* autodetection code based on the i2c addr */ |
452 | if (!no_autodetect) { | 458 | if (!no_autodetect) { |
453 | switch (addr) { | 459 | switch (addr) { |
454 | case 0x42: | 460 | case 0x42: |
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 6d03b9b05c6e..c8e5ad0e8185 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c | |||
@@ -390,6 +390,14 @@ static void tda9840_setmode(struct CHIPSTATE *chip, int mode) | |||
390 | chip_write(chip, TDA9840_SW, t); | 390 | chip_write(chip, TDA9840_SW, t); |
391 | } | 391 | } |
392 | 392 | ||
393 | static int tda9840_checkit(struct CHIPSTATE *chip) | ||
394 | { | ||
395 | int rc; | ||
396 | rc = chip_read(chip); | ||
397 | /* lower 5 bits should be 0 */ | ||
398 | return ((rc & 0x1f) == 0) ? 1 : 0; | ||
399 | } | ||
400 | |||
393 | /* ---------------------------------------------------------------------- */ | 401 | /* ---------------------------------------------------------------------- */ |
394 | /* audio chip descriptions - defines+functions for tda985x */ | 402 | /* audio chip descriptions - defines+functions for tda985x */ |
395 | 403 | ||
@@ -1264,6 +1272,7 @@ static struct CHIPDESC chiplist[] = { | |||
1264 | .addr_hi = I2C_TDA9840 >> 1, | 1272 | .addr_hi = I2C_TDA9840 >> 1, |
1265 | .registers = 5, | 1273 | .registers = 5, |
1266 | 1274 | ||
1275 | .checkit = tda9840_checkit, | ||
1267 | .getmode = tda9840_getmode, | 1276 | .getmode = tda9840_getmode, |
1268 | .setmode = tda9840_setmode, | 1277 | .setmode = tda9840_setmode, |
1269 | .checkmode = generic_checkmode, | 1278 | .checkmode = generic_checkmode, |
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index fad9ea0ae4f2..1864423b3046 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c | |||
@@ -746,24 +746,27 @@ static int tvp5150_set_std(struct i2c_client *c, v4l2_std_id std) | |||
746 | 746 | ||
747 | static inline void tvp5150_reset(struct i2c_client *c) | 747 | static inline void tvp5150_reset(struct i2c_client *c) |
748 | { | 748 | { |
749 | u8 type, ver_656, msb_id, lsb_id, msb_rom, lsb_rom; | 749 | u8 msb_id, lsb_id, msb_rom, lsb_rom; |
750 | struct tvp5150 *decoder = i2c_get_clientdata(c); | 750 | struct tvp5150 *decoder = i2c_get_clientdata(c); |
751 | 751 | ||
752 | type=tvp5150_read(c,TVP5150_AUTOSW_MSK); | ||
753 | msb_id=tvp5150_read(c,TVP5150_MSB_DEV_ID); | 752 | msb_id=tvp5150_read(c,TVP5150_MSB_DEV_ID); |
754 | lsb_id=tvp5150_read(c,TVP5150_LSB_DEV_ID); | 753 | lsb_id=tvp5150_read(c,TVP5150_LSB_DEV_ID); |
755 | msb_rom=tvp5150_read(c,TVP5150_ROM_MAJOR_VER); | 754 | msb_rom=tvp5150_read(c,TVP5150_ROM_MAJOR_VER); |
756 | lsb_rom=tvp5150_read(c,TVP5150_ROM_MINOR_VER); | 755 | lsb_rom=tvp5150_read(c,TVP5150_ROM_MINOR_VER); |
757 | 756 | ||
758 | if (type==0xdc) { | 757 | if ((msb_rom==4)&&(lsb_rom==0)) { /* Is TVP5150AM1 */ |
759 | ver_656=tvp5150_read(c,TVP5150_REV_SELECT); | 758 | tvp5150_info("tvp%02x%02xam1 detected.\n",msb_id, lsb_id); |
760 | tvp5150_info("tvp%02x%02xam1 detected 656 version is %d.\n",msb_id, lsb_id,ver_656); | 759 | |
761 | } else if (type==0xfc) { | 760 | /* ITU-T BT.656.4 timing */ |
762 | tvp5150_info("tvp%02x%02xa detected.\n",msb_id, lsb_id); | 761 | tvp5150_write(c,TVP5150_REV_SELECT,0); |
763 | } else { | 762 | } else { |
764 | tvp5150_info("unknown tvp%02x%02x chip detected(%d).\n",msb_id,lsb_id,type); | 763 | if ((msb_rom==3)||(lsb_rom==0x21)) { /* Is TVP5150A */ |
764 | tvp5150_info("tvp%02x%02xa detected.\n",msb_id, lsb_id); | ||
765 | } else { | ||
766 | tvp5150_info("*** unknown tvp%02x%02x chip detected.\n",msb_id,lsb_id); | ||
767 | tvp5150_info("*** Rom ver is %d.%d\n",msb_rom,lsb_rom); | ||
768 | } | ||
765 | } | 769 | } |
766 | tvp5150_info("Rom ver is %d.%d\n",msb_rom,lsb_rom); | ||
767 | 770 | ||
768 | /* Initializes TVP5150 to its default values */ | 771 | /* Initializes TVP5150 to its default values */ |
769 | tvp5150_write_inittab(c, tvp5150_init_default); | 772 | tvp5150_write_inittab(c, tvp5150_init_default); |
@@ -893,6 +896,17 @@ static int tvp5150_command(struct i2c_client *c, | |||
893 | } | 896 | } |
894 | case DECODER_GET_STATUS: | 897 | case DECODER_GET_STATUS: |
895 | { | 898 | { |
899 | int *iarg = arg; | ||
900 | int status; | ||
901 | int res=0; | ||
902 | status = tvp5150_read(c, 0x88); | ||
903 | if(status&0x08){ | ||
904 | res |= DECODER_STATUS_COLOR; | ||
905 | } | ||
906 | if(status&0x04 && status&0x02){ | ||
907 | res |= DECODER_STATUS_GOOD; | ||
908 | } | ||
909 | *iarg=res; | ||
896 | break; | 910 | break; |
897 | } | 911 | } |
898 | 912 | ||
diff --git a/drivers/message/i2o/core.h b/drivers/message/i2o/core.h index 90628562851e..184974cc734d 100644 --- a/drivers/message/i2o/core.h +++ b/drivers/message/i2o/core.h | |||
@@ -60,4 +60,7 @@ extern void i2o_iop_remove(struct i2o_controller *); | |||
60 | #define I2O_IN_PORT 0x40 | 60 | #define I2O_IN_PORT 0x40 |
61 | #define I2O_OUT_PORT 0x44 | 61 | #define I2O_OUT_PORT 0x44 |
62 | 62 | ||
63 | /* Motorola/Freescale specific register offset */ | ||
64 | #define I2O_MOTOROLA_PORT_OFFSET 0x10400 | ||
65 | |||
63 | #define I2O_IRQ_OUTBOUND_POST 0x00000008 | 66 | #define I2O_IRQ_OUTBOUND_POST 0x00000008 |
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c index f9e5a23697a1..c08ddac3717d 100644 --- a/drivers/message/i2o/i2o_scsi.c +++ b/drivers/message/i2o/i2o_scsi.c | |||
@@ -732,7 +732,7 @@ static int i2o_scsi_abort(struct scsi_cmnd *SCpnt) | |||
732 | cpu_to_le32(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid); | 732 | cpu_to_le32(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid); |
733 | msg->body[0] = cpu_to_le32(i2o_cntxt_list_get_ptr(c, SCpnt)); | 733 | msg->body[0] = cpu_to_le32(i2o_cntxt_list_get_ptr(c, SCpnt)); |
734 | 734 | ||
735 | if (i2o_msg_post_wait(c, msg, I2O_TIMEOUT_SCSI_SCB_ABORT)) | 735 | if (!i2o_msg_post_wait(c, msg, I2O_TIMEOUT_SCSI_SCB_ABORT)) |
736 | status = SUCCESS; | 736 | status = SUCCESS; |
737 | 737 | ||
738 | return status; | 738 | return status; |
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c index d698d7709c31..4f1515cae5dc 100644 --- a/drivers/message/i2o/pci.c +++ b/drivers/message/i2o/pci.c | |||
@@ -88,6 +88,11 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) | |||
88 | struct device *dev = &pdev->dev; | 88 | struct device *dev = &pdev->dev; |
89 | int i; | 89 | int i; |
90 | 90 | ||
91 | if (pci_request_regions(pdev, OSM_DESCRIPTION)) { | ||
92 | printk(KERN_ERR "%s: device already claimed\n", c->name); | ||
93 | return -ENODEV; | ||
94 | } | ||
95 | |||
91 | for (i = 0; i < 6; i++) { | 96 | for (i = 0; i < 6; i++) { |
92 | /* Skip I/O spaces */ | 97 | /* Skip I/O spaces */ |
93 | if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) { | 98 | if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) { |
@@ -163,6 +168,24 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) | |||
163 | c->in_port = c->base.virt + I2O_IN_PORT; | 168 | c->in_port = c->base.virt + I2O_IN_PORT; |
164 | c->out_port = c->base.virt + I2O_OUT_PORT; | 169 | c->out_port = c->base.virt + I2O_OUT_PORT; |
165 | 170 | ||
171 | /* Motorola/Freescale chip does not follow spec */ | ||
172 | if (pdev->vendor == PCI_VENDOR_ID_MOTOROLA && pdev->device == 0x18c0) { | ||
173 | /* Check if CPU is enabled */ | ||
174 | if (be32_to_cpu(readl(c->base.virt + 0x10000)) & 0x10000000) { | ||
175 | printk(KERN_INFO "%s: MPC82XX needs CPU running to " | ||
176 | "service I2O.\n", c->name); | ||
177 | i2o_pci_free(c); | ||
178 | return -ENODEV; | ||
179 | } else { | ||
180 | c->irq_status += I2O_MOTOROLA_PORT_OFFSET; | ||
181 | c->irq_mask += I2O_MOTOROLA_PORT_OFFSET; | ||
182 | c->in_port += I2O_MOTOROLA_PORT_OFFSET; | ||
183 | c->out_port += I2O_MOTOROLA_PORT_OFFSET; | ||
184 | printk(KERN_INFO "%s: MPC82XX workarounds activated.\n", | ||
185 | c->name); | ||
186 | } | ||
187 | } | ||
188 | |||
166 | if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) { | 189 | if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) { |
167 | i2o_pci_free(c); | 190 | i2o_pci_free(c); |
168 | return -ENOMEM; | 191 | return -ENOMEM; |
@@ -298,7 +321,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, | |||
298 | struct i2o_controller *c; | 321 | struct i2o_controller *c; |
299 | int rc; | 322 | int rc; |
300 | struct pci_dev *i960 = NULL; | 323 | struct pci_dev *i960 = NULL; |
301 | int pci_dev_busy = 0; | 324 | int enabled = pdev->is_enabled; |
302 | 325 | ||
303 | printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n"); | 326 | printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n"); |
304 | 327 | ||
@@ -308,16 +331,12 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, | |||
308 | return -ENODEV; | 331 | return -ENODEV; |
309 | } | 332 | } |
310 | 333 | ||
311 | if ((rc = pci_enable_device(pdev))) { | 334 | if (!enabled) |
312 | printk(KERN_WARNING "i2o: couldn't enable device %s\n", | 335 | if ((rc = pci_enable_device(pdev))) { |
313 | pci_name(pdev)); | 336 | printk(KERN_WARNING "i2o: couldn't enable device %s\n", |
314 | return rc; | 337 | pci_name(pdev)); |
315 | } | 338 | return rc; |
316 | 339 | } | |
317 | if (pci_request_regions(pdev, OSM_DESCRIPTION)) { | ||
318 | printk(KERN_ERR "i2o: device already claimed\n"); | ||
319 | return -ENODEV; | ||
320 | } | ||
321 | 340 | ||
322 | if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { | 341 | if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { |
323 | printk(KERN_WARNING "i2o: no suitable DMA found for %s\n", | 342 | printk(KERN_WARNING "i2o: no suitable DMA found for %s\n", |
@@ -395,9 +414,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, | |||
395 | 414 | ||
396 | if ((rc = i2o_pci_alloc(c))) { | 415 | if ((rc = i2o_pci_alloc(c))) { |
397 | printk(KERN_ERR "%s: DMA / IO allocation for I2O controller " | 416 | printk(KERN_ERR "%s: DMA / IO allocation for I2O controller " |
398 | " failed\n", c->name); | 417 | "failed\n", c->name); |
399 | if (rc == -ENODEV) | ||
400 | pci_dev_busy = 1; | ||
401 | goto free_controller; | 418 | goto free_controller; |
402 | } | 419 | } |
403 | 420 | ||
@@ -425,7 +442,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, | |||
425 | i2o_iop_free(c); | 442 | i2o_iop_free(c); |
426 | 443 | ||
427 | disable: | 444 | disable: |
428 | if (!pci_dev_busy) | 445 | if (!enabled) |
429 | pci_disable_device(pdev); | 446 | pci_disable_device(pdev); |
430 | 447 | ||
431 | return rc; | 448 | return rc; |
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index c483a863b116..5d397b7a5497 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig | |||
@@ -65,7 +65,7 @@ config MMC_AU1X | |||
65 | depends on SOC_AU1X00 && MMC | 65 | depends on SOC_AU1X00 && MMC |
66 | help | 66 | help |
67 | This selects the AMD Alchemy(R) Multimedia card interface. | 67 | This selects the AMD Alchemy(R) Multimedia card interface. |
68 | iIf you have a Alchemy platform with a MMC slot, say Y or M here. | 68 | If you have a Alchemy platform with a MMC slot, say Y or M here. |
69 | 69 | ||
70 | If unsure, say N. | 70 | If unsure, say N. |
71 | 71 | ||
diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c index aaf04638054e..227c39a7c1b4 100644 --- a/drivers/mmc/au1xmmc.c +++ b/drivers/mmc/au1xmmc.c | |||
@@ -194,7 +194,7 @@ static int au1xmmc_send_command(struct au1xmmc_host *host, int wait, | |||
194 | 194 | ||
195 | u32 mmccmd = (cmd->opcode << SD_CMD_CI_SHIFT); | 195 | u32 mmccmd = (cmd->opcode << SD_CMD_CI_SHIFT); |
196 | 196 | ||
197 | switch(cmd->flags) { | 197 | switch (mmc_rsp_type(cmd->flags)) { |
198 | case MMC_RSP_R1: | 198 | case MMC_RSP_R1: |
199 | mmccmd |= SD_CMD_RT_1; | 199 | mmccmd |= SD_CMD_RT_1; |
200 | break; | 200 | break; |
@@ -483,34 +483,35 @@ static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status) | |||
483 | cmd = mrq->cmd; | 483 | cmd = mrq->cmd; |
484 | cmd->error = MMC_ERR_NONE; | 484 | cmd->error = MMC_ERR_NONE; |
485 | 485 | ||
486 | if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_SHORT) { | 486 | if (cmd->flags & MMC_RSP_PRESENT) { |
487 | 487 | if (cmd->flags & MMC_RSP_136) { | |
488 | /* Techincally, we should be getting all 48 bits of the response | 488 | u32 r[4]; |
489 | * (SD_RESP1 + SD_RESP2), but because our response omits the CRC, | 489 | int i; |
490 | * our data ends up being shifted 8 bits to the right. In this case, | 490 | |
491 | * that means that the OSR data starts at bit 31, so we can just | 491 | r[0] = au_readl(host->iobase + SD_RESP3); |
492 | * read RESP0 and return that | 492 | r[1] = au_readl(host->iobase + SD_RESP2); |
493 | */ | 493 | r[2] = au_readl(host->iobase + SD_RESP1); |
494 | 494 | r[3] = au_readl(host->iobase + SD_RESP0); | |
495 | cmd->resp[0] = au_readl(host->iobase + SD_RESP0); | 495 | |
496 | } | 496 | /* The CRC is omitted from the response, so really |
497 | else if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_LONG) { | 497 | * we only got 120 bytes, but the engine expects |
498 | u32 r[4]; | 498 | * 128 bits, so we have to shift things up |
499 | int i; | 499 | */ |
500 | 500 | ||
501 | r[0] = au_readl(host->iobase + SD_RESP3); | 501 | for(i = 0; i < 4; i++) { |
502 | r[1] = au_readl(host->iobase + SD_RESP2); | 502 | cmd->resp[i] = (r[i] & 0x00FFFFFF) << 8; |
503 | r[2] = au_readl(host->iobase + SD_RESP1); | 503 | if (i != 3) |
504 | r[3] = au_readl(host->iobase + SD_RESP0); | 504 | cmd->resp[i] |= (r[i + 1] & 0xFF000000) >> 24; |
505 | 505 | } | |
506 | /* The CRC is omitted from the response, so really we only got | 506 | } else { |
507 | * 120 bytes, but the engine expects 128 bits, so we have to shift | 507 | /* Techincally, we should be getting all 48 bits of |
508 | * things up | 508 | * the response (SD_RESP1 + SD_RESP2), but because |
509 | */ | 509 | * our response omits the CRC, our data ends up |
510 | 510 | * being shifted 8 bits to the right. In this case, | |
511 | for(i = 0; i < 4; i++) { | 511 | * that means that the OSR data starts at bit 31, |
512 | cmd->resp[i] = (r[i] & 0x00FFFFFF) << 8; | 512 | * so we can just read RESP0 and return that |
513 | if (i != 3) cmd->resp[i] |= (r[i + 1] & 0xFF000000) >> 24; | 513 | */ |
514 | cmd->resp[0] = au_readl(host->iobase + SD_RESP0); | ||
514 | } | 515 | } |
515 | } | 516 | } |
516 | 517 | ||
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index bfca5c176e88..1888060c5e0c 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c | |||
@@ -211,7 +211,7 @@ int mmc_wait_for_app_cmd(struct mmc_host *host, unsigned int rca, | |||
211 | 211 | ||
212 | appcmd.opcode = MMC_APP_CMD; | 212 | appcmd.opcode = MMC_APP_CMD; |
213 | appcmd.arg = rca << 16; | 213 | appcmd.arg = rca << 16; |
214 | appcmd.flags = MMC_RSP_R1; | 214 | appcmd.flags = MMC_RSP_R1 | MMC_CMD_AC; |
215 | appcmd.retries = 0; | 215 | appcmd.retries = 0; |
216 | memset(appcmd.resp, 0, sizeof(appcmd.resp)); | 216 | memset(appcmd.resp, 0, sizeof(appcmd.resp)); |
217 | appcmd.data = NULL; | 217 | appcmd.data = NULL; |
@@ -331,7 +331,7 @@ static int mmc_select_card(struct mmc_host *host, struct mmc_card *card) | |||
331 | 331 | ||
332 | cmd.opcode = MMC_SELECT_CARD; | 332 | cmd.opcode = MMC_SELECT_CARD; |
333 | cmd.arg = card->rca << 16; | 333 | cmd.arg = card->rca << 16; |
334 | cmd.flags = MMC_RSP_R1; | 334 | cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; |
335 | 335 | ||
336 | err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); | 336 | err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); |
337 | if (err != MMC_ERR_NONE) | 337 | if (err != MMC_ERR_NONE) |
@@ -358,7 +358,7 @@ static int mmc_select_card(struct mmc_host *host, struct mmc_card *card) | |||
358 | struct mmc_command cmd; | 358 | struct mmc_command cmd; |
359 | cmd.opcode = SD_APP_SET_BUS_WIDTH; | 359 | cmd.opcode = SD_APP_SET_BUS_WIDTH; |
360 | cmd.arg = SD_BUS_WIDTH_4; | 360 | cmd.arg = SD_BUS_WIDTH_4; |
361 | cmd.flags = MMC_RSP_R1; | 361 | cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; |
362 | 362 | ||
363 | err = mmc_wait_for_app_cmd(host, card->rca, &cmd, | 363 | err = mmc_wait_for_app_cmd(host, card->rca, &cmd, |
364 | CMD_RETRIES); | 364 | CMD_RETRIES); |
@@ -386,7 +386,7 @@ static void mmc_deselect_cards(struct mmc_host *host) | |||
386 | 386 | ||
387 | cmd.opcode = MMC_SELECT_CARD; | 387 | cmd.opcode = MMC_SELECT_CARD; |
388 | cmd.arg = 0; | 388 | cmd.arg = 0; |
389 | cmd.flags = MMC_RSP_NONE; | 389 | cmd.flags = MMC_RSP_NONE | MMC_CMD_AC; |
390 | 390 | ||
391 | mmc_wait_for_cmd(host, &cmd, 0); | 391 | mmc_wait_for_cmd(host, &cmd, 0); |
392 | } | 392 | } |
@@ -677,7 +677,7 @@ static void mmc_idle_cards(struct mmc_host *host) | |||
677 | 677 | ||
678 | cmd.opcode = MMC_GO_IDLE_STATE; | 678 | cmd.opcode = MMC_GO_IDLE_STATE; |
679 | cmd.arg = 0; | 679 | cmd.arg = 0; |
680 | cmd.flags = MMC_RSP_NONE; | 680 | cmd.flags = MMC_RSP_NONE | MMC_CMD_BC; |
681 | 681 | ||
682 | mmc_wait_for_cmd(host, &cmd, 0); | 682 | mmc_wait_for_cmd(host, &cmd, 0); |
683 | 683 | ||
@@ -738,7 +738,7 @@ static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) | |||
738 | 738 | ||
739 | cmd.opcode = MMC_SEND_OP_COND; | 739 | cmd.opcode = MMC_SEND_OP_COND; |
740 | cmd.arg = ocr; | 740 | cmd.arg = ocr; |
741 | cmd.flags = MMC_RSP_R3; | 741 | cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR; |
742 | 742 | ||
743 | for (i = 100; i; i--) { | 743 | for (i = 100; i; i--) { |
744 | err = mmc_wait_for_cmd(host, &cmd, 0); | 744 | err = mmc_wait_for_cmd(host, &cmd, 0); |
@@ -766,7 +766,7 @@ static int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) | |||
766 | 766 | ||
767 | cmd.opcode = SD_APP_OP_COND; | 767 | cmd.opcode = SD_APP_OP_COND; |
768 | cmd.arg = ocr; | 768 | cmd.arg = ocr; |
769 | cmd.flags = MMC_RSP_R3; | 769 | cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR; |
770 | 770 | ||
771 | for (i = 100; i; i--) { | 771 | for (i = 100; i; i--) { |
772 | err = mmc_wait_for_app_cmd(host, 0, &cmd, CMD_RETRIES); | 772 | err = mmc_wait_for_app_cmd(host, 0, &cmd, CMD_RETRIES); |
@@ -805,7 +805,7 @@ static void mmc_discover_cards(struct mmc_host *host) | |||
805 | 805 | ||
806 | cmd.opcode = MMC_ALL_SEND_CID; | 806 | cmd.opcode = MMC_ALL_SEND_CID; |
807 | cmd.arg = 0; | 807 | cmd.arg = 0; |
808 | cmd.flags = MMC_RSP_R2; | 808 | cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR; |
809 | 809 | ||
810 | err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); | 810 | err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); |
811 | if (err == MMC_ERR_TIMEOUT) { | 811 | if (err == MMC_ERR_TIMEOUT) { |
@@ -835,7 +835,7 @@ static void mmc_discover_cards(struct mmc_host *host) | |||
835 | 835 | ||
836 | cmd.opcode = SD_SEND_RELATIVE_ADDR; | 836 | cmd.opcode = SD_SEND_RELATIVE_ADDR; |
837 | cmd.arg = 0; | 837 | cmd.arg = 0; |
838 | cmd.flags = MMC_RSP_R6; | 838 | cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR; |
839 | 839 | ||
840 | err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); | 840 | err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); |
841 | if (err != MMC_ERR_NONE) | 841 | if (err != MMC_ERR_NONE) |
@@ -856,7 +856,7 @@ static void mmc_discover_cards(struct mmc_host *host) | |||
856 | } else { | 856 | } else { |
857 | cmd.opcode = MMC_SET_RELATIVE_ADDR; | 857 | cmd.opcode = MMC_SET_RELATIVE_ADDR; |
858 | cmd.arg = card->rca << 16; | 858 | cmd.arg = card->rca << 16; |
859 | cmd.flags = MMC_RSP_R1; | 859 | cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; |
860 | 860 | ||
861 | err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); | 861 | err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); |
862 | if (err != MMC_ERR_NONE) | 862 | if (err != MMC_ERR_NONE) |
@@ -878,7 +878,7 @@ static void mmc_read_csds(struct mmc_host *host) | |||
878 | 878 | ||
879 | cmd.opcode = MMC_SEND_CSD; | 879 | cmd.opcode = MMC_SEND_CSD; |
880 | cmd.arg = card->rca << 16; | 880 | cmd.arg = card->rca << 16; |
881 | cmd.flags = MMC_RSP_R2; | 881 | cmd.flags = MMC_RSP_R2 | MMC_CMD_AC; |
882 | 882 | ||
883 | err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); | 883 | err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); |
884 | if (err != MMC_ERR_NONE) { | 884 | if (err != MMC_ERR_NONE) { |
@@ -920,7 +920,7 @@ static void mmc_read_scrs(struct mmc_host *host) | |||
920 | 920 | ||
921 | cmd.opcode = MMC_APP_CMD; | 921 | cmd.opcode = MMC_APP_CMD; |
922 | cmd.arg = card->rca << 16; | 922 | cmd.arg = card->rca << 16; |
923 | cmd.flags = MMC_RSP_R1; | 923 | cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; |
924 | 924 | ||
925 | err = mmc_wait_for_cmd(host, &cmd, 0); | 925 | err = mmc_wait_for_cmd(host, &cmd, 0); |
926 | if ((err != MMC_ERR_NONE) || !(cmd.resp[0] & R1_APP_CMD)) { | 926 | if ((err != MMC_ERR_NONE) || !(cmd.resp[0] & R1_APP_CMD)) { |
@@ -932,7 +932,7 @@ static void mmc_read_scrs(struct mmc_host *host) | |||
932 | 932 | ||
933 | cmd.opcode = SD_APP_SEND_SCR; | 933 | cmd.opcode = SD_APP_SEND_SCR; |
934 | cmd.arg = 0; | 934 | cmd.arg = 0; |
935 | cmd.flags = MMC_RSP_R1; | 935 | cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; |
936 | 936 | ||
937 | memset(&data, 0, sizeof(struct mmc_data)); | 937 | memset(&data, 0, sizeof(struct mmc_data)); |
938 | 938 | ||
@@ -1003,7 +1003,7 @@ static void mmc_check_cards(struct mmc_host *host) | |||
1003 | 1003 | ||
1004 | cmd.opcode = MMC_SEND_STATUS; | 1004 | cmd.opcode = MMC_SEND_STATUS; |
1005 | cmd.arg = card->rca << 16; | 1005 | cmd.arg = card->rca << 16; |
1006 | cmd.flags = MMC_RSP_R1; | 1006 | cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; |
1007 | 1007 | ||
1008 | err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); | 1008 | err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); |
1009 | if (err == MMC_ERR_NONE) | 1009 | if (err == MMC_ERR_NONE) |
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c index 5b014c370e80..8eb2a2ede64b 100644 --- a/drivers/mmc/mmc_block.c +++ b/drivers/mmc/mmc_block.c | |||
@@ -171,14 +171,14 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
171 | brq.mrq.data = &brq.data; | 171 | brq.mrq.data = &brq.data; |
172 | 172 | ||
173 | brq.cmd.arg = req->sector << 9; | 173 | brq.cmd.arg = req->sector << 9; |
174 | brq.cmd.flags = MMC_RSP_R1; | 174 | brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; |
175 | brq.data.timeout_ns = card->csd.tacc_ns * 10; | 175 | brq.data.timeout_ns = card->csd.tacc_ns * 10; |
176 | brq.data.timeout_clks = card->csd.tacc_clks * 10; | 176 | brq.data.timeout_clks = card->csd.tacc_clks * 10; |
177 | brq.data.blksz_bits = md->block_bits; | 177 | brq.data.blksz_bits = md->block_bits; |
178 | brq.data.blocks = req->nr_sectors >> (md->block_bits - 9); | 178 | brq.data.blocks = req->nr_sectors >> (md->block_bits - 9); |
179 | brq.stop.opcode = MMC_STOP_TRANSMISSION; | 179 | brq.stop.opcode = MMC_STOP_TRANSMISSION; |
180 | brq.stop.arg = 0; | 180 | brq.stop.arg = 0; |
181 | brq.stop.flags = MMC_RSP_R1B; | 181 | brq.stop.flags = MMC_RSP_R1B | MMC_CMD_AC; |
182 | 182 | ||
183 | if (rq_data_dir(req) == READ) { | 183 | if (rq_data_dir(req) == READ) { |
184 | brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK; | 184 | brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK; |
@@ -223,7 +223,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
223 | 223 | ||
224 | cmd.opcode = MMC_SEND_STATUS; | 224 | cmd.opcode = MMC_SEND_STATUS; |
225 | cmd.arg = card->rca << 16; | 225 | cmd.arg = card->rca << 16; |
226 | cmd.flags = MMC_RSP_R1; | 226 | cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; |
227 | err = mmc_wait_for_cmd(card->host, &cmd, 5); | 227 | err = mmc_wait_for_cmd(card->host, &cmd, 5); |
228 | if (err) { | 228 | if (err) { |
229 | printk(KERN_ERR "%s: error %d requesting status\n", | 229 | printk(KERN_ERR "%s: error %d requesting status\n", |
@@ -430,7 +430,7 @@ mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card) | |||
430 | mmc_card_claim_host(card); | 430 | mmc_card_claim_host(card); |
431 | cmd.opcode = MMC_SET_BLOCKLEN; | 431 | cmd.opcode = MMC_SET_BLOCKLEN; |
432 | cmd.arg = 1 << md->block_bits; | 432 | cmd.arg = 1 << md->block_bits; |
433 | cmd.flags = MMC_RSP_R1; | 433 | cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; |
434 | err = mmc_wait_for_cmd(card->host, &cmd, 5); | 434 | err = mmc_wait_for_cmd(card->host, &cmd, 5); |
435 | mmc_card_release_host(card); | 435 | mmc_card_release_host(card); |
436 | 436 | ||
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c index 634ef53e85a5..37ee7f8dc82f 100644 --- a/drivers/mmc/mmci.c +++ b/drivers/mmc/mmci.c | |||
@@ -124,15 +124,10 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c) | |||
124 | } | 124 | } |
125 | 125 | ||
126 | c |= cmd->opcode | MCI_CPSM_ENABLE; | 126 | c |= cmd->opcode | MCI_CPSM_ENABLE; |
127 | switch (cmd->flags & MMC_RSP_MASK) { | 127 | if (cmd->flags & MMC_RSP_PRESENT) { |
128 | case MMC_RSP_NONE: | 128 | if (cmd->flags & MMC_RSP_136) |
129 | default: | 129 | c |= MCI_CPSM_LONGRSP; |
130 | break; | ||
131 | case MMC_RSP_LONG: | ||
132 | c |= MCI_CPSM_LONGRSP; | ||
133 | case MMC_RSP_SHORT: | ||
134 | c |= MCI_CPSM_RESPONSE; | 130 | c |= MCI_CPSM_RESPONSE; |
135 | break; | ||
136 | } | 131 | } |
137 | if (/*interrupt*/0) | 132 | if (/*interrupt*/0) |
138 | c |= MCI_CPSM_INTERRUPT; | 133 | c |= MCI_CPSM_INTERRUPT; |
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c index ee8f8a0420d1..285d7d068097 100644 --- a/drivers/mmc/pxamci.c +++ b/drivers/mmc/pxamci.c | |||
@@ -178,14 +178,15 @@ static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd, | |||
178 | if (cmd->flags & MMC_RSP_BUSY) | 178 | if (cmd->flags & MMC_RSP_BUSY) |
179 | cmdat |= CMDAT_BUSY; | 179 | cmdat |= CMDAT_BUSY; |
180 | 180 | ||
181 | switch (cmd->flags & (MMC_RSP_MASK | MMC_RSP_CRC)) { | 181 | #define RSP_TYPE(x) ((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE)) |
182 | case MMC_RSP_SHORT | MMC_RSP_CRC: | 182 | switch (RSP_TYPE(mmc_resp_type(cmd))) { |
183 | case RSP_TYPE(MMC_RSP_R1): /* r1, r1b, r6 */ | ||
183 | cmdat |= CMDAT_RESP_SHORT; | 184 | cmdat |= CMDAT_RESP_SHORT; |
184 | break; | 185 | break; |
185 | case MMC_RSP_SHORT: | 186 | case RSP_TYPE(MMC_RSP_R3): |
186 | cmdat |= CMDAT_RESP_R3; | 187 | cmdat |= CMDAT_RESP_R3; |
187 | break; | 188 | break; |
188 | case MMC_RSP_LONG | MMC_RSP_CRC: | 189 | case RSP_TYPE(MMC_RSP_R2): |
189 | cmdat |= CMDAT_RESP_R2; | 190 | cmdat |= CMDAT_RESP_R2; |
190 | break; | 191 | break; |
191 | default: | 192 | default: |
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index f25757625361..3be397d436fa 100644 --- a/drivers/mmc/wbsd.c +++ b/drivers/mmc/wbsd.c | |||
@@ -459,7 +459,7 @@ static void wbsd_send_command(struct wbsd_host *host, struct mmc_command *cmd) | |||
459 | /* | 459 | /* |
460 | * Do we expect a reply? | 460 | * Do we expect a reply? |
461 | */ | 461 | */ |
462 | if ((cmd->flags & MMC_RSP_MASK) != MMC_RSP_NONE) { | 462 | if (cmd->flags & MMC_RSP_PRESENT) { |
463 | /* | 463 | /* |
464 | * Read back status. | 464 | * Read back status. |
465 | */ | 465 | */ |
@@ -476,10 +476,10 @@ static void wbsd_send_command(struct wbsd_host *host, struct mmc_command *cmd) | |||
476 | cmd->error = MMC_ERR_BADCRC; | 476 | cmd->error = MMC_ERR_BADCRC; |
477 | /* All ok */ | 477 | /* All ok */ |
478 | else { | 478 | else { |
479 | if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_SHORT) | 479 | if (cmd->flags & MMC_RSP_136) |
480 | wbsd_get_short_reply(host, cmd); | ||
481 | else | ||
482 | wbsd_get_long_reply(host, cmd); | 480 | wbsd_get_long_reply(host, cmd); |
481 | else | ||
482 | wbsd_get_short_reply(host, cmd); | ||
483 | } | 483 | } |
484 | } | 484 | } |
485 | 485 | ||
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig index effa0d7a73ac..205bb7083335 100644 --- a/drivers/mtd/chips/Kconfig +++ b/drivers/mtd/chips/Kconfig | |||
@@ -301,7 +301,7 @@ config MTD_JEDEC | |||
301 | 301 | ||
302 | config MTD_XIP | 302 | config MTD_XIP |
303 | bool "XIP aware MTD support" | 303 | bool "XIP aware MTD support" |
304 | depends on !SMP && (MTD_CFI_INTELEXT || MTD_CFI_AMDSTD) && EXPERIMENTAL && ARM | 304 | depends on !SMP && (MTD_CFI_INTELEXT || MTD_CFI_AMDSTD) && EXPERIMENTAL && ARCH_MTD_XIP |
305 | default y if XIP_KERNEL | 305 | default y if XIP_KERNEL |
306 | help | 306 | help |
307 | This allows MTD support to work with flash memory which is also | 307 | This allows MTD support to work with flash memory which is also |
diff --git a/drivers/mtd/maps/dc21285.c b/drivers/mtd/maps/dc21285.c index 701620b6baed..8b3784e2de89 100644 --- a/drivers/mtd/maps/dc21285.c +++ b/drivers/mtd/maps/dc21285.c | |||
@@ -110,8 +110,9 @@ static void dc21285_copy_to_32(struct map_info *map, unsigned long to, const voi | |||
110 | { | 110 | { |
111 | while (len > 0) { | 111 | while (len > 0) { |
112 | map_word d; | 112 | map_word d; |
113 | d.x[0] = *((uint32_t*)from)++; | 113 | d.x[0] = *((uint32_t*)from); |
114 | dc21285_write32(map, d, to); | 114 | dc21285_write32(map, d, to); |
115 | from += 4; | ||
115 | to += 4; | 116 | to += 4; |
116 | len -= 4; | 117 | len -= 4; |
117 | } | 118 | } |
@@ -121,8 +122,9 @@ static void dc21285_copy_to_16(struct map_info *map, unsigned long to, const voi | |||
121 | { | 122 | { |
122 | while (len > 0) { | 123 | while (len > 0) { |
123 | map_word d; | 124 | map_word d; |
124 | d.x[0] = *((uint16_t*)from)++; | 125 | d.x[0] = *((uint16_t*)from); |
125 | dc21285_write16(map, d, to); | 126 | dc21285_write16(map, d, to); |
127 | from += 2; | ||
126 | to += 2; | 128 | to += 2; |
127 | len -= 2; | 129 | len -= 2; |
128 | } | 130 | } |
@@ -131,8 +133,9 @@ static void dc21285_copy_to_16(struct map_info *map, unsigned long to, const voi | |||
131 | static void dc21285_copy_to_8(struct map_info *map, unsigned long to, const void *from, ssize_t len) | 133 | static void dc21285_copy_to_8(struct map_info *map, unsigned long to, const void *from, ssize_t len) |
132 | { | 134 | { |
133 | map_word d; | 135 | map_word d; |
134 | d.x[0] = *((uint8_t*)from)++; | 136 | d.x[0] = *((uint8_t*)from); |
135 | dc21285_write8(map, d, to); | 137 | dc21285_write8(map, d, to); |
138 | from++; | ||
136 | to++; | 139 | to++; |
137 | len--; | 140 | len--; |
138 | } | 141 | } |
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 7488ee7f7caf..7f47124f118d 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c | |||
@@ -753,9 +753,11 @@ enum tx_desc_status { | |||
753 | enum ChipCaps { CapBusMaster=0x20, CapPwrMgmt=0x2000 }; | 753 | enum ChipCaps { CapBusMaster=0x20, CapPwrMgmt=0x2000 }; |
754 | 754 | ||
755 | struct vortex_extra_stats { | 755 | struct vortex_extra_stats { |
756 | unsigned long tx_deferred; | 756 | unsigned long tx_deferred; |
757 | unsigned long tx_multiple_collisions; | 757 | unsigned long tx_max_collisions; |
758 | unsigned long rx_bad_ssd; | 758 | unsigned long tx_multiple_collisions; |
759 | unsigned long tx_single_collisions; | ||
760 | unsigned long rx_bad_ssd; | ||
759 | }; | 761 | }; |
760 | 762 | ||
761 | struct vortex_private { | 763 | struct vortex_private { |
@@ -863,12 +865,14 @@ static struct { | |||
863 | const char str[ETH_GSTRING_LEN]; | 865 | const char str[ETH_GSTRING_LEN]; |
864 | } ethtool_stats_keys[] = { | 866 | } ethtool_stats_keys[] = { |
865 | { "tx_deferred" }, | 867 | { "tx_deferred" }, |
868 | { "tx_max_collisions" }, | ||
866 | { "tx_multiple_collisions" }, | 869 | { "tx_multiple_collisions" }, |
870 | { "tx_single_collisions" }, | ||
867 | { "rx_bad_ssd" }, | 871 | { "rx_bad_ssd" }, |
868 | }; | 872 | }; |
869 | 873 | ||
870 | /* number of ETHTOOL_GSTATS u64's */ | 874 | /* number of ETHTOOL_GSTATS u64's */ |
871 | #define VORTEX_NUM_STATS 3 | 875 | #define VORTEX_NUM_STATS 5 |
872 | 876 | ||
873 | static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq, | 877 | static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq, |
874 | int chip_idx, int card_idx); | 878 | int chip_idx, int card_idx); |
@@ -2108,9 +2112,12 @@ vortex_error(struct net_device *dev, int status) | |||
2108 | iowrite8(0, ioaddr + TxStatus); | 2112 | iowrite8(0, ioaddr + TxStatus); |
2109 | if (tx_status & 0x30) { /* txJabber or txUnderrun */ | 2113 | if (tx_status & 0x30) { /* txJabber or txUnderrun */ |
2110 | do_tx_reset = 1; | 2114 | do_tx_reset = 1; |
2111 | } else if ((tx_status & 0x08) && (vp->drv_flags & MAX_COLLISION_RESET)) { /* maxCollisions */ | 2115 | } else if (tx_status & 0x08) { /* maxCollisions */ |
2112 | do_tx_reset = 1; | 2116 | vp->xstats.tx_max_collisions++; |
2113 | reset_mask = 0x0108; /* Reset interface logic, but not download logic */ | 2117 | if (vp->drv_flags & MAX_COLLISION_RESET) { |
2118 | do_tx_reset = 1; | ||
2119 | reset_mask = 0x0108; /* Reset interface logic, but not download logic */ | ||
2120 | } | ||
2114 | } else { /* Merely re-enable the transmitter. */ | 2121 | } else { /* Merely re-enable the transmitter. */ |
2115 | iowrite16(TxEnable, ioaddr + EL3_CMD); | 2122 | iowrite16(TxEnable, ioaddr + EL3_CMD); |
2116 | } | 2123 | } |
@@ -2926,7 +2933,6 @@ static void update_stats(void __iomem *ioaddr, struct net_device *dev) | |||
2926 | EL3WINDOW(6); | 2933 | EL3WINDOW(6); |
2927 | vp->stats.tx_carrier_errors += ioread8(ioaddr + 0); | 2934 | vp->stats.tx_carrier_errors += ioread8(ioaddr + 0); |
2928 | vp->stats.tx_heartbeat_errors += ioread8(ioaddr + 1); | 2935 | vp->stats.tx_heartbeat_errors += ioread8(ioaddr + 1); |
2929 | vp->stats.collisions += ioread8(ioaddr + 3); | ||
2930 | vp->stats.tx_window_errors += ioread8(ioaddr + 4); | 2936 | vp->stats.tx_window_errors += ioread8(ioaddr + 4); |
2931 | vp->stats.rx_fifo_errors += ioread8(ioaddr + 5); | 2937 | vp->stats.rx_fifo_errors += ioread8(ioaddr + 5); |
2932 | vp->stats.tx_packets += ioread8(ioaddr + 6); | 2938 | vp->stats.tx_packets += ioread8(ioaddr + 6); |
@@ -2939,10 +2945,15 @@ static void update_stats(void __iomem *ioaddr, struct net_device *dev) | |||
2939 | vp->stats.tx_bytes += ioread16(ioaddr + 12); | 2945 | vp->stats.tx_bytes += ioread16(ioaddr + 12); |
2940 | /* Extra stats for get_ethtool_stats() */ | 2946 | /* Extra stats for get_ethtool_stats() */ |
2941 | vp->xstats.tx_multiple_collisions += ioread8(ioaddr + 2); | 2947 | vp->xstats.tx_multiple_collisions += ioread8(ioaddr + 2); |
2948 | vp->xstats.tx_single_collisions += ioread8(ioaddr + 3); | ||
2942 | vp->xstats.tx_deferred += ioread8(ioaddr + 8); | 2949 | vp->xstats.tx_deferred += ioread8(ioaddr + 8); |
2943 | EL3WINDOW(4); | 2950 | EL3WINDOW(4); |
2944 | vp->xstats.rx_bad_ssd += ioread8(ioaddr + 12); | 2951 | vp->xstats.rx_bad_ssd += ioread8(ioaddr + 12); |
2945 | 2952 | ||
2953 | vp->stats.collisions = vp->xstats.tx_multiple_collisions | ||
2954 | + vp->xstats.tx_single_collisions | ||
2955 | + vp->xstats.tx_max_collisions; | ||
2956 | |||
2946 | { | 2957 | { |
2947 | u8 up = ioread8(ioaddr + 13); | 2958 | u8 up = ioread8(ioaddr + 13); |
2948 | vp->stats.rx_bytes += (up & 0x0f) << 16; | 2959 | vp->stats.rx_bytes += (up & 0x0f) << 16; |
@@ -3036,8 +3047,10 @@ static void vortex_get_ethtool_stats(struct net_device *dev, | |||
3036 | spin_unlock_irqrestore(&vp->lock, flags); | 3047 | spin_unlock_irqrestore(&vp->lock, flags); |
3037 | 3048 | ||
3038 | data[0] = vp->xstats.tx_deferred; | 3049 | data[0] = vp->xstats.tx_deferred; |
3039 | data[1] = vp->xstats.tx_multiple_collisions; | 3050 | data[1] = vp->xstats.tx_max_collisions; |
3040 | data[2] = vp->xstats.rx_bad_ssd; | 3051 | data[2] = vp->xstats.tx_multiple_collisions; |
3052 | data[3] = vp->xstats.tx_single_collisions; | ||
3053 | data[4] = vp->xstats.rx_bad_ssd; | ||
3041 | } | 3054 | } |
3042 | 3055 | ||
3043 | 3056 | ||
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index adfba44dac5a..2beac55b57d6 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c | |||
@@ -586,6 +586,7 @@ struct rtl8139_private { | |||
586 | dma_addr_t tx_bufs_dma; | 586 | dma_addr_t tx_bufs_dma; |
587 | signed char phys[4]; /* MII device addresses. */ | 587 | signed char phys[4]; /* MII device addresses. */ |
588 | char twistie, twist_row, twist_col; /* Twister tune state. */ | 588 | char twistie, twist_row, twist_col; /* Twister tune state. */ |
589 | unsigned int watchdog_fired : 1; | ||
589 | unsigned int default_port : 4; /* Last dev->if_port value. */ | 590 | unsigned int default_port : 4; /* Last dev->if_port value. */ |
590 | unsigned int have_thread : 1; | 591 | unsigned int have_thread : 1; |
591 | spinlock_t lock; | 592 | spinlock_t lock; |
@@ -638,6 +639,7 @@ static void rtl8139_set_rx_mode (struct net_device *dev); | |||
638 | static void __set_rx_mode (struct net_device *dev); | 639 | static void __set_rx_mode (struct net_device *dev); |
639 | static void rtl8139_hw_start (struct net_device *dev); | 640 | static void rtl8139_hw_start (struct net_device *dev); |
640 | static void rtl8139_thread (void *_data); | 641 | static void rtl8139_thread (void *_data); |
642 | static void rtl8139_tx_timeout_task(void *_data); | ||
641 | static struct ethtool_ops rtl8139_ethtool_ops; | 643 | static struct ethtool_ops rtl8139_ethtool_ops; |
642 | 644 | ||
643 | /* write MMIO register, with flush */ | 645 | /* write MMIO register, with flush */ |
@@ -1598,13 +1600,14 @@ static void rtl8139_thread (void *_data) | |||
1598 | { | 1600 | { |
1599 | struct net_device *dev = _data; | 1601 | struct net_device *dev = _data; |
1600 | struct rtl8139_private *tp = netdev_priv(dev); | 1602 | struct rtl8139_private *tp = netdev_priv(dev); |
1601 | unsigned long thr_delay; | 1603 | unsigned long thr_delay = next_tick; |
1602 | 1604 | ||
1603 | if (rtnl_shlock_nowait() == 0) { | 1605 | if (tp->watchdog_fired) { |
1606 | tp->watchdog_fired = 0; | ||
1607 | rtl8139_tx_timeout_task(_data); | ||
1608 | } else if (rtnl_shlock_nowait() == 0) { | ||
1604 | rtl8139_thread_iter (dev, tp, tp->mmio_addr); | 1609 | rtl8139_thread_iter (dev, tp, tp->mmio_addr); |
1605 | rtnl_unlock (); | 1610 | rtnl_unlock (); |
1606 | |||
1607 | thr_delay = next_tick; | ||
1608 | } else { | 1611 | } else { |
1609 | /* unlikely race. mitigate with fast poll. */ | 1612 | /* unlikely race. mitigate with fast poll. */ |
1610 | thr_delay = HZ / 2; | 1613 | thr_delay = HZ / 2; |
@@ -1631,7 +1634,8 @@ static void rtl8139_stop_thread(struct rtl8139_private *tp) | |||
1631 | if (tp->have_thread) { | 1634 | if (tp->have_thread) { |
1632 | cancel_rearming_delayed_work(&tp->thread); | 1635 | cancel_rearming_delayed_work(&tp->thread); |
1633 | tp->have_thread = 0; | 1636 | tp->have_thread = 0; |
1634 | } | 1637 | } else |
1638 | flush_scheduled_work(); | ||
1635 | } | 1639 | } |
1636 | 1640 | ||
1637 | static inline void rtl8139_tx_clear (struct rtl8139_private *tp) | 1641 | static inline void rtl8139_tx_clear (struct rtl8139_private *tp) |
@@ -1642,14 +1646,13 @@ static inline void rtl8139_tx_clear (struct rtl8139_private *tp) | |||
1642 | /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ | 1646 | /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ |
1643 | } | 1647 | } |
1644 | 1648 | ||
1645 | 1649 | static void rtl8139_tx_timeout_task (void *_data) | |
1646 | static void rtl8139_tx_timeout (struct net_device *dev) | ||
1647 | { | 1650 | { |
1651 | struct net_device *dev = _data; | ||
1648 | struct rtl8139_private *tp = netdev_priv(dev); | 1652 | struct rtl8139_private *tp = netdev_priv(dev); |
1649 | void __iomem *ioaddr = tp->mmio_addr; | 1653 | void __iomem *ioaddr = tp->mmio_addr; |
1650 | int i; | 1654 | int i; |
1651 | u8 tmp8; | 1655 | u8 tmp8; |
1652 | unsigned long flags; | ||
1653 | 1656 | ||
1654 | printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " | 1657 | printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " |
1655 | "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), | 1658 | "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), |
@@ -1670,23 +1673,34 @@ static void rtl8139_tx_timeout (struct net_device *dev) | |||
1670 | if (tmp8 & CmdTxEnb) | 1673 | if (tmp8 & CmdTxEnb) |
1671 | RTL_W8 (ChipCmd, CmdRxEnb); | 1674 | RTL_W8 (ChipCmd, CmdRxEnb); |
1672 | 1675 | ||
1673 | spin_lock(&tp->rx_lock); | 1676 | spin_lock_bh(&tp->rx_lock); |
1674 | /* Disable interrupts by clearing the interrupt mask. */ | 1677 | /* Disable interrupts by clearing the interrupt mask. */ |
1675 | RTL_W16 (IntrMask, 0x0000); | 1678 | RTL_W16 (IntrMask, 0x0000); |
1676 | 1679 | ||
1677 | /* Stop a shared interrupt from scavenging while we are. */ | 1680 | /* Stop a shared interrupt from scavenging while we are. */ |
1678 | spin_lock_irqsave (&tp->lock, flags); | 1681 | spin_lock_irq(&tp->lock); |
1679 | rtl8139_tx_clear (tp); | 1682 | rtl8139_tx_clear (tp); |
1680 | spin_unlock_irqrestore (&tp->lock, flags); | 1683 | spin_unlock_irq(&tp->lock); |
1681 | 1684 | ||
1682 | /* ...and finally, reset everything */ | 1685 | /* ...and finally, reset everything */ |
1683 | if (netif_running(dev)) { | 1686 | if (netif_running(dev)) { |
1684 | rtl8139_hw_start (dev); | 1687 | rtl8139_hw_start (dev); |
1685 | netif_wake_queue (dev); | 1688 | netif_wake_queue (dev); |
1686 | } | 1689 | } |
1687 | spin_unlock(&tp->rx_lock); | 1690 | spin_unlock_bh(&tp->rx_lock); |
1688 | } | 1691 | } |
1689 | 1692 | ||
1693 | static void rtl8139_tx_timeout (struct net_device *dev) | ||
1694 | { | ||
1695 | struct rtl8139_private *tp = netdev_priv(dev); | ||
1696 | |||
1697 | if (!tp->have_thread) { | ||
1698 | INIT_WORK(&tp->thread, rtl8139_tx_timeout_task, dev); | ||
1699 | schedule_delayed_work(&tp->thread, next_tick); | ||
1700 | } else | ||
1701 | tp->watchdog_fired = 1; | ||
1702 | |||
1703 | } | ||
1690 | 1704 | ||
1691 | static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) | 1705 | static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) |
1692 | { | 1706 | { |
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 6a6a08441804..47c72a63dfe1 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -4,9 +4,9 @@ | |||
4 | # | 4 | # |
5 | 5 | ||
6 | menu "Network device support" | 6 | menu "Network device support" |
7 | depends on NET | ||
7 | 8 | ||
8 | config NETDEVICES | 9 | config NETDEVICES |
9 | depends on NET | ||
10 | default y if UML | 10 | default y if UML |
11 | bool "Network device support" | 11 | bool "Network device support" |
12 | ---help--- | 12 | ---help--- |
@@ -24,9 +24,6 @@ config NETDEVICES | |||
24 | 24 | ||
25 | If unsure, say Y. | 25 | If unsure, say Y. |
26 | 26 | ||
27 | # All the following symbols are dependent on NETDEVICES - do not repeat | ||
28 | # that for each of the symbols. | ||
29 | if NETDEVICES | ||
30 | 27 | ||
31 | config IFB | 28 | config IFB |
32 | tristate "Intermediate Functional Block support" | 29 | tristate "Intermediate Functional Block support" |
@@ -2718,8 +2715,6 @@ config NETCONSOLE | |||
2718 | If you want to log kernel messages over the network, enable this. | 2715 | If you want to log kernel messages over the network, enable this. |
2719 | See <file:Documentation/networking/netconsole.txt> for details. | 2716 | See <file:Documentation/networking/netconsole.txt> for details. |
2720 | 2717 | ||
2721 | endif #NETDEVICES | ||
2722 | |||
2723 | config NETPOLL | 2718 | config NETPOLL |
2724 | def_bool NETCONSOLE | 2719 | def_bool NETCONSOLE |
2725 | 2720 | ||
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 4ff006c37626..e0f51afec778 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -1145,7 +1145,8 @@ int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1145 | } | 1145 | } |
1146 | 1146 | ||
1147 | #define BOND_INTERSECT_FEATURES \ | 1147 | #define BOND_INTERSECT_FEATURES \ |
1148 | (NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM) | 1148 | (NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM|\ |
1149 | NETIF_F_TSO|NETIF_F_UFO) | ||
1149 | 1150 | ||
1150 | /* | 1151 | /* |
1151 | * Compute the common dev->feature set available to all slaves. Some | 1152 | * Compute the common dev->feature set available to all slaves. Some |
@@ -1168,6 +1169,16 @@ static int bond_compute_features(struct bonding *bond) | |||
1168 | NETIF_F_HW_CSUM))) | 1169 | NETIF_F_HW_CSUM))) |
1169 | features &= ~NETIF_F_SG; | 1170 | features &= ~NETIF_F_SG; |
1170 | 1171 | ||
1172 | /* | ||
1173 | * features will include NETIF_F_TSO (NETIF_F_UFO) iff all | ||
1174 | * slave devices support NETIF_F_TSO (NETIF_F_UFO), which | ||
1175 | * implies that all slaves also support scatter-gather | ||
1176 | * (NETIF_F_SG), which implies that features also includes | ||
1177 | * NETIF_F_SG. So no need to check whether we have an | ||
1178 | * illegal combination of NETIF_F_{TSO,UFO} and | ||
1179 | * !NETIF_F_SG | ||
1180 | */ | ||
1181 | |||
1171 | features |= (bond_dev->features & ~BOND_INTERSECT_FEATURES); | 1182 | features |= (bond_dev->features & ~BOND_INTERSECT_FEATURES); |
1172 | bond_dev->features = features; | 1183 | bond_dev->features = features; |
1173 | 1184 | ||
@@ -4080,6 +4091,8 @@ static void bond_ethtool_get_drvinfo(struct net_device *bond_dev, | |||
4080 | 4091 | ||
4081 | static struct ethtool_ops bond_ethtool_ops = { | 4092 | static struct ethtool_ops bond_ethtool_ops = { |
4082 | .get_tx_csum = ethtool_op_get_tx_csum, | 4093 | .get_tx_csum = ethtool_op_get_tx_csum, |
4094 | .get_tso = ethtool_op_get_tso, | ||
4095 | .get_ufo = ethtool_op_get_ufo, | ||
4083 | .get_sg = ethtool_op_get_sg, | 4096 | .get_sg = ethtool_op_get_sg, |
4084 | .get_drvinfo = bond_ethtool_get_drvinfo, | 4097 | .get_drvinfo = bond_ethtool_get_drvinfo, |
4085 | }; | 4098 | }; |
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 32d13da43a0b..041bcc583557 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c | |||
@@ -260,7 +260,7 @@ static ssize_t bonding_store_slaves(struct class_device *cd, const char *buffer, | |||
260 | char *ifname; | 260 | char *ifname; |
261 | int i, res, found, ret = count; | 261 | int i, res, found, ret = count; |
262 | struct slave *slave; | 262 | struct slave *slave; |
263 | struct net_device *dev = 0; | 263 | struct net_device *dev = NULL; |
264 | struct bonding *bond = to_bond(cd); | 264 | struct bonding *bond = to_bond(cd); |
265 | 265 | ||
266 | /* Quick sanity check -- is the bond interface up? */ | 266 | /* Quick sanity check -- is the bond interface up? */ |
@@ -995,7 +995,7 @@ static ssize_t bonding_store_primary(struct class_device *cd, const char *buf, s | |||
995 | printk(KERN_INFO DRV_NAME | 995 | printk(KERN_INFO DRV_NAME |
996 | ": %s: Setting primary slave to None.\n", | 996 | ": %s: Setting primary slave to None.\n", |
997 | bond->dev->name); | 997 | bond->dev->name); |
998 | bond->primary_slave = 0; | 998 | bond->primary_slave = NULL; |
999 | bond_select_active_slave(bond); | 999 | bond_select_active_slave(bond); |
1000 | } else { | 1000 | } else { |
1001 | printk(KERN_INFO DRV_NAME | 1001 | printk(KERN_INFO DRV_NAME |
@@ -1123,7 +1123,7 @@ static ssize_t bonding_store_active_slave(struct class_device *cd, const char *b | |||
1123 | printk(KERN_INFO DRV_NAME | 1123 | printk(KERN_INFO DRV_NAME |
1124 | ": %s: Setting active slave to None.\n", | 1124 | ": %s: Setting active slave to None.\n", |
1125 | bond->dev->name); | 1125 | bond->dev->name); |
1126 | bond->primary_slave = 0; | 1126 | bond->primary_slave = NULL; |
1127 | bond_select_active_slave(bond); | 1127 | bond_select_active_slave(bond); |
1128 | } else { | 1128 | } else { |
1129 | printk(KERN_INFO DRV_NAME | 1129 | printk(KERN_INFO DRV_NAME |
diff --git a/drivers/net/e100.c b/drivers/net/e100.c index bf1fd2b98bf8..24253c807e55 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c | |||
@@ -2752,8 +2752,6 @@ static int e100_resume(struct pci_dev *pdev) | |||
2752 | retval = pci_enable_wake(pdev, 0, 0); | 2752 | retval = pci_enable_wake(pdev, 0, 0); |
2753 | if (retval) | 2753 | if (retval) |
2754 | DPRINTK(PROBE,ERR, "Error clearing wake events\n"); | 2754 | DPRINTK(PROBE,ERR, "Error clearing wake events\n"); |
2755 | if(e100_hw_init(nic)) | ||
2756 | DPRINTK(HW, ERR, "e100_hw_init failed\n"); | ||
2757 | 2755 | ||
2758 | netif_device_attach(netdev); | 2756 | netif_device_attach(netdev); |
2759 | if(netif_running(netdev)) | 2757 | if(netif_running(netdev)) |
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 0c18dbd67d3b..0e8e3fcde9ff 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
@@ -199,8 +199,7 @@ static int gfar_probe(struct platform_device *pdev) | |||
199 | 199 | ||
200 | /* get a pointer to the register memory */ | 200 | /* get a pointer to the register memory */ |
201 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 201 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
202 | priv->regs = (struct gfar *) | 202 | priv->regs = ioremap(r->start, sizeof (struct gfar)); |
203 | ioremap(r->start, sizeof (struct gfar)); | ||
204 | 203 | ||
205 | if (NULL == priv->regs) { | 204 | if (NULL == priv->regs) { |
206 | err = -ENOMEM; | 205 | err = -ENOMEM; |
@@ -369,7 +368,7 @@ static int gfar_probe(struct platform_device *pdev) | |||
369 | return 0; | 368 | return 0; |
370 | 369 | ||
371 | register_fail: | 370 | register_fail: |
372 | iounmap((void *) priv->regs); | 371 | iounmap(priv->regs); |
373 | regs_fail: | 372 | regs_fail: |
374 | free_netdev(dev); | 373 | free_netdev(dev); |
375 | return err; | 374 | return err; |
@@ -382,7 +381,7 @@ static int gfar_remove(struct platform_device *pdev) | |||
382 | 381 | ||
383 | platform_set_drvdata(pdev, NULL); | 382 | platform_set_drvdata(pdev, NULL); |
384 | 383 | ||
385 | iounmap((void *) priv->regs); | 384 | iounmap(priv->regs); |
386 | free_netdev(dev); | 385 | free_netdev(dev); |
387 | 386 | ||
388 | return 0; | 387 | return 0; |
@@ -454,8 +453,7 @@ static void init_registers(struct net_device *dev) | |||
454 | 453 | ||
455 | /* Zero out the rmon mib registers if it has them */ | 454 | /* Zero out the rmon mib registers if it has them */ |
456 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { | 455 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { |
457 | memset((void *) &(priv->regs->rmon), 0, | 456 | memset_io(&(priv->regs->rmon), 0, sizeof (struct rmon_mib)); |
458 | sizeof (struct rmon_mib)); | ||
459 | 457 | ||
460 | /* Mask off the CAM interrupts */ | 458 | /* Mask off the CAM interrupts */ |
461 | gfar_write(&priv->regs->rmon.cam1, 0xffffffff); | 459 | gfar_write(&priv->regs->rmon.cam1, 0xffffffff); |
@@ -477,7 +475,7 @@ static void init_registers(struct net_device *dev) | |||
477 | void gfar_halt(struct net_device *dev) | 475 | void gfar_halt(struct net_device *dev) |
478 | { | 476 | { |
479 | struct gfar_private *priv = netdev_priv(dev); | 477 | struct gfar_private *priv = netdev_priv(dev); |
480 | struct gfar *regs = priv->regs; | 478 | struct gfar __iomem *regs = priv->regs; |
481 | u32 tempval; | 479 | u32 tempval; |
482 | 480 | ||
483 | /* Mask all interrupts */ | 481 | /* Mask all interrupts */ |
@@ -507,7 +505,7 @@ void gfar_halt(struct net_device *dev) | |||
507 | void stop_gfar(struct net_device *dev) | 505 | void stop_gfar(struct net_device *dev) |
508 | { | 506 | { |
509 | struct gfar_private *priv = netdev_priv(dev); | 507 | struct gfar_private *priv = netdev_priv(dev); |
510 | struct gfar *regs = priv->regs; | 508 | struct gfar __iomem *regs = priv->regs; |
511 | unsigned long flags; | 509 | unsigned long flags; |
512 | 510 | ||
513 | phy_stop(priv->phydev); | 511 | phy_stop(priv->phydev); |
@@ -590,7 +588,7 @@ static void free_skb_resources(struct gfar_private *priv) | |||
590 | void gfar_start(struct net_device *dev) | 588 | void gfar_start(struct net_device *dev) |
591 | { | 589 | { |
592 | struct gfar_private *priv = netdev_priv(dev); | 590 | struct gfar_private *priv = netdev_priv(dev); |
593 | struct gfar *regs = priv->regs; | 591 | struct gfar __iomem *regs = priv->regs; |
594 | u32 tempval; | 592 | u32 tempval; |
595 | 593 | ||
596 | /* Enable Rx and Tx in MACCFG1 */ | 594 | /* Enable Rx and Tx in MACCFG1 */ |
@@ -624,7 +622,7 @@ int startup_gfar(struct net_device *dev) | |||
624 | unsigned long vaddr; | 622 | unsigned long vaddr; |
625 | int i; | 623 | int i; |
626 | struct gfar_private *priv = netdev_priv(dev); | 624 | struct gfar_private *priv = netdev_priv(dev); |
627 | struct gfar *regs = priv->regs; | 625 | struct gfar __iomem *regs = priv->regs; |
628 | int err = 0; | 626 | int err = 0; |
629 | u32 rctrl = 0; | 627 | u32 rctrl = 0; |
630 | u32 attrs = 0; | 628 | u32 attrs = 0; |
@@ -1622,7 +1620,7 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
1622 | static void adjust_link(struct net_device *dev) | 1620 | static void adjust_link(struct net_device *dev) |
1623 | { | 1621 | { |
1624 | struct gfar_private *priv = netdev_priv(dev); | 1622 | struct gfar_private *priv = netdev_priv(dev); |
1625 | struct gfar *regs = priv->regs; | 1623 | struct gfar __iomem *regs = priv->regs; |
1626 | unsigned long flags; | 1624 | unsigned long flags; |
1627 | struct phy_device *phydev = priv->phydev; | 1625 | struct phy_device *phydev = priv->phydev; |
1628 | int new_state = 0; | 1626 | int new_state = 0; |
@@ -1703,7 +1701,7 @@ static void gfar_set_multi(struct net_device *dev) | |||
1703 | { | 1701 | { |
1704 | struct dev_mc_list *mc_ptr; | 1702 | struct dev_mc_list *mc_ptr; |
1705 | struct gfar_private *priv = netdev_priv(dev); | 1703 | struct gfar_private *priv = netdev_priv(dev); |
1706 | struct gfar *regs = priv->regs; | 1704 | struct gfar __iomem *regs = priv->regs; |
1707 | u32 tempval; | 1705 | u32 tempval; |
1708 | 1706 | ||
1709 | if(dev->flags & IFF_PROMISC) { | 1707 | if(dev->flags & IFF_PROMISC) { |
@@ -1842,7 +1840,7 @@ static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr) | |||
1842 | int idx; | 1840 | int idx; |
1843 | char tmpbuf[MAC_ADDR_LEN]; | 1841 | char tmpbuf[MAC_ADDR_LEN]; |
1844 | u32 tempval; | 1842 | u32 tempval; |
1845 | u32 *macptr = &priv->regs->macstnaddr1; | 1843 | u32 __iomem *macptr = &priv->regs->macstnaddr1; |
1846 | 1844 | ||
1847 | macptr += num*2; | 1845 | macptr += num*2; |
1848 | 1846 | ||
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index cb9d66ac3ab9..d37d5401be6e 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h | |||
@@ -682,8 +682,8 @@ struct gfar_private { | |||
682 | struct rxbd8 *cur_rx; /* Next free rx ring entry */ | 682 | struct rxbd8 *cur_rx; /* Next free rx ring entry */ |
683 | struct txbd8 *cur_tx; /* Next free ring entry */ | 683 | struct txbd8 *cur_tx; /* Next free ring entry */ |
684 | struct txbd8 *dirty_tx; /* The Ring entry to be freed. */ | 684 | struct txbd8 *dirty_tx; /* The Ring entry to be freed. */ |
685 | struct gfar *regs; /* Pointer to the GFAR memory mapped Registers */ | 685 | struct gfar __iomem *regs; /* Pointer to the GFAR memory mapped Registers */ |
686 | u32 *hash_regs[16]; | 686 | u32 __iomem *hash_regs[16]; |
687 | int hash_width; | 687 | int hash_width; |
688 | struct net_device_stats stats; /* linux network statistics */ | 688 | struct net_device_stats stats; /* linux network statistics */ |
689 | struct gfar_extra_stats extra_stats; | 689 | struct gfar_extra_stats extra_stats; |
@@ -718,14 +718,14 @@ struct gfar_private { | |||
718 | uint32_t msg_enable; | 718 | uint32_t msg_enable; |
719 | }; | 719 | }; |
720 | 720 | ||
721 | static inline u32 gfar_read(volatile unsigned *addr) | 721 | static inline u32 gfar_read(volatile unsigned __iomem *addr) |
722 | { | 722 | { |
723 | u32 val; | 723 | u32 val; |
724 | val = in_be32(addr); | 724 | val = in_be32(addr); |
725 | return val; | 725 | return val; |
726 | } | 726 | } |
727 | 727 | ||
728 | static inline void gfar_write(volatile unsigned *addr, u32 val) | 728 | static inline void gfar_write(volatile unsigned __iomem *addr, u32 val) |
729 | { | 729 | { |
730 | out_be32(addr, val); | 730 | out_be32(addr, val); |
731 | } | 731 | } |
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index 765e810620fe..5de7b2e259dc 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c | |||
@@ -144,11 +144,11 @@ static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, | |||
144 | u64 *extra = (u64 *) & priv->extra_stats; | 144 | u64 *extra = (u64 *) & priv->extra_stats; |
145 | 145 | ||
146 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { | 146 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { |
147 | u32 *rmon = (u32 *) & priv->regs->rmon; | 147 | u32 __iomem *rmon = (u32 __iomem *) & priv->regs->rmon; |
148 | struct gfar_stats *stats = (struct gfar_stats *) buf; | 148 | struct gfar_stats *stats = (struct gfar_stats *) buf; |
149 | 149 | ||
150 | for (i = 0; i < GFAR_RMON_LEN; i++) | 150 | for (i = 0; i < GFAR_RMON_LEN; i++) |
151 | stats->rmon[i] = (u64) (rmon[i]); | 151 | stats->rmon[i] = (u64) gfar_read(&rmon[i]); |
152 | 152 | ||
153 | for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) | 153 | for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) |
154 | stats->extra[i] = extra[i]; | 154 | stats->extra[i] = extra[i]; |
@@ -221,11 +221,11 @@ static void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, voi | |||
221 | { | 221 | { |
222 | int i; | 222 | int i; |
223 | struct gfar_private *priv = netdev_priv(dev); | 223 | struct gfar_private *priv = netdev_priv(dev); |
224 | u32 *theregs = (u32 *) priv->regs; | 224 | u32 __iomem *theregs = (u32 __iomem *) priv->regs; |
225 | u32 *buf = (u32 *) regbuf; | 225 | u32 *buf = (u32 *) regbuf; |
226 | 226 | ||
227 | for (i = 0; i < sizeof (struct gfar) / sizeof (u32); i++) | 227 | for (i = 0; i < sizeof (struct gfar) / sizeof (u32); i++) |
228 | buf[i] = theregs[i]; | 228 | buf[i] = gfar_read(&theregs[i]); |
229 | } | 229 | } |
230 | 230 | ||
231 | /* Convert microseconds to ethernet clock ticks, which changes | 231 | /* Convert microseconds to ethernet clock ticks, which changes |
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c index 74e52fcbf806..c6b725529af5 100644 --- a/drivers/net/gianfar_mii.c +++ b/drivers/net/gianfar_mii.c | |||
@@ -50,7 +50,7 @@ | |||
50 | * All PHY configuration is done through the TSEC1 MIIM regs */ | 50 | * All PHY configuration is done through the TSEC1 MIIM regs */ |
51 | int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) | 51 | int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) |
52 | { | 52 | { |
53 | struct gfar_mii *regs = bus->priv; | 53 | struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; |
54 | 54 | ||
55 | /* Set the PHY address and the register address we want to write */ | 55 | /* Set the PHY address and the register address we want to write */ |
56 | gfar_write(®s->miimadd, (mii_id << 8) | regnum); | 56 | gfar_write(®s->miimadd, (mii_id << 8) | regnum); |
@@ -70,7 +70,7 @@ int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) | |||
70 | * configuration has to be done through the TSEC1 MIIM regs */ | 70 | * configuration has to be done through the TSEC1 MIIM regs */ |
71 | int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum) | 71 | int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum) |
72 | { | 72 | { |
73 | struct gfar_mii *regs = bus->priv; | 73 | struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; |
74 | u16 value; | 74 | u16 value; |
75 | 75 | ||
76 | /* Set the PHY address and the register address we want to read */ | 76 | /* Set the PHY address and the register address we want to read */ |
@@ -94,7 +94,7 @@ int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum) | |||
94 | /* Reset the MIIM registers, and wait for the bus to free */ | 94 | /* Reset the MIIM registers, and wait for the bus to free */ |
95 | int gfar_mdio_reset(struct mii_bus *bus) | 95 | int gfar_mdio_reset(struct mii_bus *bus) |
96 | { | 96 | { |
97 | struct gfar_mii *regs = bus->priv; | 97 | struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; |
98 | unsigned int timeout = PHY_INIT_TIMEOUT; | 98 | unsigned int timeout = PHY_INIT_TIMEOUT; |
99 | 99 | ||
100 | spin_lock_bh(&bus->mdio_lock); | 100 | spin_lock_bh(&bus->mdio_lock); |
@@ -126,7 +126,7 @@ int gfar_mdio_probe(struct device *dev) | |||
126 | { | 126 | { |
127 | struct platform_device *pdev = to_platform_device(dev); | 127 | struct platform_device *pdev = to_platform_device(dev); |
128 | struct gianfar_mdio_data *pdata; | 128 | struct gianfar_mdio_data *pdata; |
129 | struct gfar_mii *regs; | 129 | struct gfar_mii __iomem *regs; |
130 | struct mii_bus *new_bus; | 130 | struct mii_bus *new_bus; |
131 | struct resource *r; | 131 | struct resource *r; |
132 | int err = 0; | 132 | int err = 0; |
@@ -155,15 +155,14 @@ int gfar_mdio_probe(struct device *dev) | |||
155 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 155 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
156 | 156 | ||
157 | /* Set the PHY base address */ | 157 | /* Set the PHY base address */ |
158 | regs = (struct gfar_mii *) ioremap(r->start, | 158 | regs = ioremap(r->start, sizeof (struct gfar_mii)); |
159 | sizeof (struct gfar_mii)); | ||
160 | 159 | ||
161 | if (NULL == regs) { | 160 | if (NULL == regs) { |
162 | err = -ENOMEM; | 161 | err = -ENOMEM; |
163 | goto reg_map_fail; | 162 | goto reg_map_fail; |
164 | } | 163 | } |
165 | 164 | ||
166 | new_bus->priv = regs; | 165 | new_bus->priv = (void __force *)regs; |
167 | 166 | ||
168 | new_bus->irq = pdata->irq; | 167 | new_bus->irq = pdata->irq; |
169 | 168 | ||
@@ -181,7 +180,7 @@ int gfar_mdio_probe(struct device *dev) | |||
181 | return 0; | 180 | return 0; |
182 | 181 | ||
183 | bus_register_fail: | 182 | bus_register_fail: |
184 | iounmap((void *) regs); | 183 | iounmap(regs); |
185 | reg_map_fail: | 184 | reg_map_fail: |
186 | kfree(new_bus); | 185 | kfree(new_bus); |
187 | 186 | ||
@@ -197,7 +196,7 @@ int gfar_mdio_remove(struct device *dev) | |||
197 | 196 | ||
198 | dev_set_drvdata(dev, NULL); | 197 | dev_set_drvdata(dev, NULL); |
199 | 198 | ||
200 | iounmap((void *) (&bus->priv)); | 199 | iounmap((void __iomem *)bus->priv); |
201 | bus->priv = NULL; | 200 | bus->priv = NULL; |
202 | kfree(bus); | 201 | kfree(bus); |
203 | 202 | ||
diff --git a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.c index 3b1bef1ee215..77411a00d1ee 100644 --- a/drivers/net/hamradio/baycom_par.c +++ b/drivers/net/hamradio/baycom_par.c | |||
@@ -86,7 +86,6 @@ | |||
86 | #include <linux/bitops.h> | 86 | #include <linux/bitops.h> |
87 | #include <linux/jiffies.h> | 87 | #include <linux/jiffies.h> |
88 | 88 | ||
89 | #include <asm/bug.h> | ||
90 | #include <asm/system.h> | 89 | #include <asm/system.h> |
91 | #include <asm/uaccess.h> | 90 | #include <asm/uaccess.h> |
92 | 91 | ||
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 7ef4b0434a3f..c0998ef938e0 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c | |||
@@ -32,6 +32,8 @@ | |||
32 | */ | 32 | */ |
33 | #include <linux/init.h> | 33 | #include <linux/init.h> |
34 | #include <linux/dma-mapping.h> | 34 | #include <linux/dma-mapping.h> |
35 | #include <linux/in.h> | ||
36 | #include <linux/ip.h> | ||
35 | #include <linux/tcp.h> | 37 | #include <linux/tcp.h> |
36 | #include <linux/udp.h> | 38 | #include <linux/udp.h> |
37 | #include <linux/etherdevice.h> | 39 | #include <linux/etherdevice.h> |
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 1c6d328165bb..0245e40b51a1 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c | |||
@@ -1610,6 +1610,8 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) | |||
1610 | } | 1610 | } |
1611 | else if (!pskb_may_pull(skb, skb->len)) | 1611 | else if (!pskb_may_pull(skb, skb->len)) |
1612 | goto err; | 1612 | goto err; |
1613 | else | ||
1614 | skb->ip_summed = CHECKSUM_NONE; | ||
1613 | 1615 | ||
1614 | len = slhc_uncompress(ppp->vj, skb->data + 2, skb->len - 2); | 1616 | len = slhc_uncompress(ppp->vj, skb->data + 2, skb->len - 2); |
1615 | if (len <= 0) { | 1617 | if (len <= 0) { |
@@ -1690,6 +1692,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) | |||
1690 | kfree_skb(skb); | 1692 | kfree_skb(skb); |
1691 | } else { | 1693 | } else { |
1692 | skb_pull(skb, 2); /* chop off protocol */ | 1694 | skb_pull(skb, 2); /* chop off protocol */ |
1695 | skb_postpull_rcsum(skb, skb->data - 2, 2); | ||
1693 | skb->dev = ppp->dev; | 1696 | skb->dev = ppp->dev; |
1694 | skb->protocol = htons(npindex_to_ethertype[npi]); | 1697 | skb->protocol = htons(npindex_to_ethertype[npi]); |
1695 | skb->mac.raw = skb->data; | 1698 | skb->mac.raw = skb->data; |
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 2e1bed153c39..6e1018448eea 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c | |||
@@ -484,13 +484,12 @@ static void mdio_write(void __iomem *ioaddr, int RegAddr, int value) | |||
484 | int i; | 484 | int i; |
485 | 485 | ||
486 | RTL_W32(PHYAR, 0x80000000 | (RegAddr & 0xFF) << 16 | value); | 486 | RTL_W32(PHYAR, 0x80000000 | (RegAddr & 0xFF) << 16 | value); |
487 | udelay(1000); | ||
488 | 487 | ||
489 | for (i = 2000; i > 0; i--) { | 488 | for (i = 20; i > 0; i--) { |
490 | /* Check if the RTL8169 has completed writing to the specified MII register */ | 489 | /* Check if the RTL8169 has completed writing to the specified MII register */ |
491 | if (!(RTL_R32(PHYAR) & 0x80000000)) | 490 | if (!(RTL_R32(PHYAR) & 0x80000000)) |
492 | break; | 491 | break; |
493 | udelay(100); | 492 | udelay(25); |
494 | } | 493 | } |
495 | } | 494 | } |
496 | 495 | ||
@@ -499,15 +498,14 @@ static int mdio_read(void __iomem *ioaddr, int RegAddr) | |||
499 | int i, value = -1; | 498 | int i, value = -1; |
500 | 499 | ||
501 | RTL_W32(PHYAR, 0x0 | (RegAddr & 0xFF) << 16); | 500 | RTL_W32(PHYAR, 0x0 | (RegAddr & 0xFF) << 16); |
502 | udelay(1000); | ||
503 | 501 | ||
504 | for (i = 2000; i > 0; i--) { | 502 | for (i = 20; i > 0; i--) { |
505 | /* Check if the RTL8169 has completed retrieving data from the specified MII register */ | 503 | /* Check if the RTL8169 has completed retrieving data from the specified MII register */ |
506 | if (RTL_R32(PHYAR) & 0x80000000) { | 504 | if (RTL_R32(PHYAR) & 0x80000000) { |
507 | value = (int) (RTL_R32(PHYAR) & 0xFFFF); | 505 | value = (int) (RTL_R32(PHYAR) & 0xFFFF); |
508 | break; | 506 | break; |
509 | } | 507 | } |
510 | udelay(100); | 508 | udelay(25); |
511 | } | 509 | } |
512 | return value; | 510 | return value; |
513 | } | 511 | } |
@@ -677,6 +675,9 @@ static int rtl8169_set_speed_xmii(struct net_device *dev, | |||
677 | 675 | ||
678 | if (duplex == DUPLEX_HALF) | 676 | if (duplex == DUPLEX_HALF) |
679 | auto_nego &= ~(PHY_Cap_10_Full | PHY_Cap_100_Full); | 677 | auto_nego &= ~(PHY_Cap_10_Full | PHY_Cap_100_Full); |
678 | |||
679 | if (duplex == DUPLEX_FULL) | ||
680 | auto_nego &= ~(PHY_Cap_10_Half | PHY_Cap_100_Half); | ||
680 | } | 681 | } |
681 | 682 | ||
682 | tp->phy_auto_nego_reg = auto_nego; | 683 | tp->phy_auto_nego_reg = auto_nego; |
diff --git a/drivers/net/sis900.h b/drivers/net/sis900.h index 4233ea55670f..50323941e3c0 100644 --- a/drivers/net/sis900.h +++ b/drivers/net/sis900.h | |||
@@ -33,7 +33,6 @@ enum sis900_registers { | |||
33 | rxcfg=0x34, //Receive Configuration Register | 33 | rxcfg=0x34, //Receive Configuration Register |
34 | flctrl=0x38, //Flow Control Register | 34 | flctrl=0x38, //Flow Control Register |
35 | rxlen=0x3c, //Receive Packet Length Register | 35 | rxlen=0x3c, //Receive Packet Length Register |
36 | cfgpmcsr=0x44, //Configuration Power Management Control/Status Register | ||
37 | rfcr=0x48, //Receive Filter Control Register | 36 | rfcr=0x48, //Receive Filter Control Register |
38 | rfdr=0x4C, //Receive Filter Data Register | 37 | rfdr=0x4C, //Receive Filter Data Register |
39 | pmctrl=0xB0, //Power Management Control Register | 38 | pmctrl=0xB0, //Power Management Control Register |
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index f8b973a04b65..cae2edf23004 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -23,12 +23,6 @@ | |||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
24 | */ | 24 | */ |
25 | 25 | ||
26 | /* | ||
27 | * TOTEST | ||
28 | * - speed setting | ||
29 | * - suspend/resume | ||
30 | */ | ||
31 | |||
32 | #include <linux/config.h> | 26 | #include <linux/config.h> |
33 | #include <linux/crc32.h> | 27 | #include <linux/crc32.h> |
34 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
@@ -57,7 +51,7 @@ | |||
57 | #include "sky2.h" | 51 | #include "sky2.h" |
58 | 52 | ||
59 | #define DRV_NAME "sky2" | 53 | #define DRV_NAME "sky2" |
60 | #define DRV_VERSION "0.13" | 54 | #define DRV_VERSION "0.15" |
61 | #define PFX DRV_NAME " " | 55 | #define PFX DRV_NAME " " |
62 | 56 | ||
63 | /* | 57 | /* |
@@ -102,6 +96,10 @@ static int copybreak __read_mostly = 256; | |||
102 | module_param(copybreak, int, 0); | 96 | module_param(copybreak, int, 0); |
103 | MODULE_PARM_DESC(copybreak, "Receive copy threshold"); | 97 | MODULE_PARM_DESC(copybreak, "Receive copy threshold"); |
104 | 98 | ||
99 | static int disable_msi = 0; | ||
100 | module_param(disable_msi, int, 0); | ||
101 | MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); | ||
102 | |||
105 | static const struct pci_device_id sky2_id_table[] = { | 103 | static const struct pci_device_id sky2_id_table[] = { |
106 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, | 104 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, |
107 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, | 105 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, |
@@ -198,7 +196,7 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) | |||
198 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); | 196 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); |
199 | 197 | ||
200 | pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_PMC, &power_control); | 198 | pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_PMC, &power_control); |
201 | vaux = (sky2_read8(hw, B0_CTST) & Y2_VAUX_AVAIL) && | 199 | vaux = (sky2_read16(hw, B0_CTST) & Y2_VAUX_AVAIL) && |
202 | (power_control & PCI_PM_CAP_PME_D3cold); | 200 | (power_control & PCI_PM_CAP_PME_D3cold); |
203 | 201 | ||
204 | pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_CTRL, &power_control); | 202 | pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_CTRL, &power_control); |
@@ -1834,6 +1832,8 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
1834 | u16 hwidx; | 1832 | u16 hwidx; |
1835 | u16 tx_done[2] = { TX_NO_STATUS, TX_NO_STATUS }; | 1833 | u16 tx_done[2] = { TX_NO_STATUS, TX_NO_STATUS }; |
1836 | 1834 | ||
1835 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | ||
1836 | |||
1837 | hwidx = sky2_read16(hw, STAT_PUT_IDX); | 1837 | hwidx = sky2_read16(hw, STAT_PUT_IDX); |
1838 | BUG_ON(hwidx >= STATUS_RING_SIZE); | 1838 | BUG_ON(hwidx >= STATUS_RING_SIZE); |
1839 | rmb(); | 1839 | rmb(); |
@@ -1913,12 +1913,10 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
1913 | } | 1913 | } |
1914 | 1914 | ||
1915 | exit_loop: | 1915 | exit_loop: |
1916 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | ||
1917 | |||
1918 | sky2_tx_check(hw, 0, tx_done[0]); | 1916 | sky2_tx_check(hw, 0, tx_done[0]); |
1919 | sky2_tx_check(hw, 1, tx_done[1]); | 1917 | sky2_tx_check(hw, 1, tx_done[1]); |
1920 | 1918 | ||
1921 | if (sky2_read16(hw, STAT_PUT_IDX) == hw->st_idx) { | 1919 | if (likely(work_done < to_do)) { |
1922 | /* need to restart TX timer */ | 1920 | /* need to restart TX timer */ |
1923 | if (is_ec_a1(hw)) { | 1921 | if (is_ec_a1(hw)) { |
1924 | sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); | 1922 | sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); |
@@ -2141,14 +2139,12 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk) | |||
2141 | 2139 | ||
2142 | static int sky2_reset(struct sky2_hw *hw) | 2140 | static int sky2_reset(struct sky2_hw *hw) |
2143 | { | 2141 | { |
2144 | u32 ctst; | ||
2145 | u16 status; | 2142 | u16 status; |
2146 | u8 t8, pmd_type; | 2143 | u8 t8, pmd_type; |
2147 | int i; | 2144 | int i, err; |
2148 | |||
2149 | ctst = sky2_read32(hw, B0_CTST); | ||
2150 | 2145 | ||
2151 | sky2_write8(hw, B0_CTST, CS_RST_CLR); | 2146 | sky2_write8(hw, B0_CTST, CS_RST_CLR); |
2147 | |||
2152 | hw->chip_id = sky2_read8(hw, B2_CHIP_ID); | 2148 | hw->chip_id = sky2_read8(hw, B2_CHIP_ID); |
2153 | if (hw->chip_id < CHIP_ID_YUKON_XL || hw->chip_id > CHIP_ID_YUKON_FE) { | 2149 | if (hw->chip_id < CHIP_ID_YUKON_XL || hw->chip_id > CHIP_ID_YUKON_FE) { |
2154 | printk(KERN_ERR PFX "%s: unsupported chip type 0x%x\n", | 2150 | printk(KERN_ERR PFX "%s: unsupported chip type 0x%x\n", |
@@ -2156,12 +2152,6 @@ static int sky2_reset(struct sky2_hw *hw) | |||
2156 | return -EOPNOTSUPP; | 2152 | return -EOPNOTSUPP; |
2157 | } | 2153 | } |
2158 | 2154 | ||
2159 | /* ring for status responses */ | ||
2160 | hw->st_le = pci_alloc_consistent(hw->pdev, STATUS_LE_BYTES, | ||
2161 | &hw->st_dma); | ||
2162 | if (!hw->st_le) | ||
2163 | return -ENOMEM; | ||
2164 | |||
2165 | /* disable ASF */ | 2155 | /* disable ASF */ |
2166 | if (hw->chip_id <= CHIP_ID_YUKON_EC) { | 2156 | if (hw->chip_id <= CHIP_ID_YUKON_EC) { |
2167 | sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); | 2157 | sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); |
@@ -2173,19 +2163,24 @@ static int sky2_reset(struct sky2_hw *hw) | |||
2173 | sky2_write8(hw, B0_CTST, CS_RST_CLR); | 2163 | sky2_write8(hw, B0_CTST, CS_RST_CLR); |
2174 | 2164 | ||
2175 | /* clear PCI errors, if any */ | 2165 | /* clear PCI errors, if any */ |
2176 | pci_read_config_word(hw->pdev, PCI_STATUS, &status); | 2166 | err = pci_read_config_word(hw->pdev, PCI_STATUS, &status); |
2167 | if (err) | ||
2168 | goto pci_err; | ||
2169 | |||
2177 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); | 2170 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); |
2178 | pci_write_config_word(hw->pdev, PCI_STATUS, | 2171 | err = pci_write_config_word(hw->pdev, PCI_STATUS, |
2179 | status | PCI_STATUS_ERROR_BITS); | 2172 | status | PCI_STATUS_ERROR_BITS); |
2173 | if (err) | ||
2174 | goto pci_err; | ||
2180 | 2175 | ||
2181 | sky2_write8(hw, B0_CTST, CS_MRST_CLR); | 2176 | sky2_write8(hw, B0_CTST, CS_MRST_CLR); |
2182 | 2177 | ||
2183 | /* clear any PEX errors */ | 2178 | /* clear any PEX errors */ |
2184 | if (is_pciex(hw)) { | 2179 | if (pci_find_capability(hw->pdev, PCI_CAP_ID_EXP)) { |
2185 | u16 lstat; | 2180 | err = pci_write_config_dword(hw->pdev, PEX_UNC_ERR_STAT, |
2186 | pci_write_config_dword(hw->pdev, PEX_UNC_ERR_STAT, | 2181 | 0xffffffffUL); |
2187 | 0xffffffffUL); | 2182 | if (err) |
2188 | pci_read_config_word(hw->pdev, PEX_LNK_STAT, &lstat); | 2183 | goto pci_err; |
2189 | } | 2184 | } |
2190 | 2185 | ||
2191 | pmd_type = sky2_read8(hw, B2_PMD_TYP); | 2186 | pmd_type = sky2_read8(hw, B2_PMD_TYP); |
@@ -2297,6 +2292,14 @@ static int sky2_reset(struct sky2_hw *hw) | |||
2297 | sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START); | 2292 | sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START); |
2298 | 2293 | ||
2299 | return 0; | 2294 | return 0; |
2295 | |||
2296 | pci_err: | ||
2297 | /* This is to catch a BIOS bug workaround where | ||
2298 | * mmconfig table doesn't have other buses. | ||
2299 | */ | ||
2300 | printk(KERN_ERR PFX "%s: can't access PCI config space\n", | ||
2301 | pci_name(hw->pdev)); | ||
2302 | return err; | ||
2300 | } | 2303 | } |
2301 | 2304 | ||
2302 | static u32 sky2_supported_modes(const struct sky2_hw *hw) | 2305 | static u32 sky2_supported_modes(const struct sky2_hw *hw) |
@@ -2551,19 +2554,24 @@ static struct net_device_stats *sky2_get_stats(struct net_device *dev) | |||
2551 | static int sky2_set_mac_address(struct net_device *dev, void *p) | 2554 | static int sky2_set_mac_address(struct net_device *dev, void *p) |
2552 | { | 2555 | { |
2553 | struct sky2_port *sky2 = netdev_priv(dev); | 2556 | struct sky2_port *sky2 = netdev_priv(dev); |
2554 | struct sockaddr *addr = p; | 2557 | struct sky2_hw *hw = sky2->hw; |
2558 | unsigned port = sky2->port; | ||
2559 | const struct sockaddr *addr = p; | ||
2555 | 2560 | ||
2556 | if (!is_valid_ether_addr(addr->sa_data)) | 2561 | if (!is_valid_ether_addr(addr->sa_data)) |
2557 | return -EADDRNOTAVAIL; | 2562 | return -EADDRNOTAVAIL; |
2558 | 2563 | ||
2559 | memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); | 2564 | memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); |
2560 | memcpy_toio(sky2->hw->regs + B2_MAC_1 + sky2->port * 8, | 2565 | memcpy_toio(hw->regs + B2_MAC_1 + port * 8, |
2561 | dev->dev_addr, ETH_ALEN); | 2566 | dev->dev_addr, ETH_ALEN); |
2562 | memcpy_toio(sky2->hw->regs + B2_MAC_2 + sky2->port * 8, | 2567 | memcpy_toio(hw->regs + B2_MAC_2 + port * 8, |
2563 | dev->dev_addr, ETH_ALEN); | 2568 | dev->dev_addr, ETH_ALEN); |
2564 | 2569 | ||
2565 | if (netif_running(dev)) | 2570 | /* virtual address for data */ |
2566 | sky2_phy_reinit(sky2); | 2571 | gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr); |
2572 | |||
2573 | /* physical address: used for pause frames */ | ||
2574 | gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr); | ||
2567 | 2575 | ||
2568 | return 0; | 2576 | return 0; |
2569 | } | 2577 | } |
@@ -2843,7 +2851,7 @@ static int sky2_set_coalesce(struct net_device *dev, | |||
2843 | if (ecmd->rx_coalesce_usecs_irq == 0) | 2851 | if (ecmd->rx_coalesce_usecs_irq == 0) |
2844 | sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_STOP); | 2852 | sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_STOP); |
2845 | else { | 2853 | else { |
2846 | sky2_write32(hw, STAT_TX_TIMER_INI, | 2854 | sky2_write32(hw, STAT_ISR_TIMER_INI, |
2847 | sky2_us2clk(hw, ecmd->rx_coalesce_usecs_irq)); | 2855 | sky2_us2clk(hw, ecmd->rx_coalesce_usecs_irq)); |
2848 | sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START); | 2856 | sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START); |
2849 | } | 2857 | } |
@@ -3055,6 +3063,61 @@ static void __devinit sky2_show_addr(struct net_device *dev) | |||
3055 | dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); | 3063 | dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); |
3056 | } | 3064 | } |
3057 | 3065 | ||
3066 | /* Handle software interrupt used during MSI test */ | ||
3067 | static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id, | ||
3068 | struct pt_regs *regs) | ||
3069 | { | ||
3070 | struct sky2_hw *hw = dev_id; | ||
3071 | u32 status = sky2_read32(hw, B0_Y2_SP_ISRC2); | ||
3072 | |||
3073 | if (status == 0) | ||
3074 | return IRQ_NONE; | ||
3075 | |||
3076 | if (status & Y2_IS_IRQ_SW) { | ||
3077 | sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ); | ||
3078 | hw->msi = 1; | ||
3079 | } | ||
3080 | sky2_write32(hw, B0_Y2_SP_ICR, 2); | ||
3081 | |||
3082 | sky2_read32(hw, B0_IMSK); | ||
3083 | return IRQ_HANDLED; | ||
3084 | } | ||
3085 | |||
3086 | /* Test interrupt path by forcing a a software IRQ */ | ||
3087 | static int __devinit sky2_test_msi(struct sky2_hw *hw) | ||
3088 | { | ||
3089 | struct pci_dev *pdev = hw->pdev; | ||
3090 | int i, err; | ||
3091 | |||
3092 | sky2_write32(hw, B0_IMSK, Y2_IS_IRQ_SW); | ||
3093 | |||
3094 | err = request_irq(pdev->irq, sky2_test_intr, SA_SHIRQ, DRV_NAME, hw); | ||
3095 | if (err) { | ||
3096 | printk(KERN_ERR PFX "%s: cannot assign irq %d\n", | ||
3097 | pci_name(pdev), pdev->irq); | ||
3098 | return err; | ||
3099 | } | ||
3100 | |||
3101 | sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ); | ||
3102 | wmb(); | ||
3103 | |||
3104 | for (i = 0; i < 10; i++) { | ||
3105 | barrier(); | ||
3106 | if (hw->msi) | ||
3107 | goto found; | ||
3108 | mdelay(1); | ||
3109 | } | ||
3110 | |||
3111 | err = -EOPNOTSUPP; | ||
3112 | sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ); | ||
3113 | found: | ||
3114 | sky2_write32(hw, B0_IMSK, 0); | ||
3115 | |||
3116 | free_irq(pdev->irq, hw); | ||
3117 | |||
3118 | return err; | ||
3119 | } | ||
3120 | |||
3058 | static int __devinit sky2_probe(struct pci_dev *pdev, | 3121 | static int __devinit sky2_probe(struct pci_dev *pdev, |
3059 | const struct pci_device_id *ent) | 3122 | const struct pci_device_id *ent) |
3060 | { | 3123 | { |
@@ -3135,6 +3198,12 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
3135 | } | 3198 | } |
3136 | hw->pm_cap = pm_cap; | 3199 | hw->pm_cap = pm_cap; |
3137 | 3200 | ||
3201 | /* ring for status responses */ | ||
3202 | hw->st_le = pci_alloc_consistent(hw->pdev, STATUS_LE_BYTES, | ||
3203 | &hw->st_dma); | ||
3204 | if (!hw->st_le) | ||
3205 | goto err_out_iounmap; | ||
3206 | |||
3138 | err = sky2_reset(hw); | 3207 | err = sky2_reset(hw); |
3139 | if (err) | 3208 | if (err) |
3140 | goto err_out_iounmap; | 3209 | goto err_out_iounmap; |
@@ -3169,7 +3238,22 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
3169 | } | 3238 | } |
3170 | } | 3239 | } |
3171 | 3240 | ||
3172 | err = request_irq(pdev->irq, sky2_intr, SA_SHIRQ, DRV_NAME, hw); | 3241 | if (!disable_msi && pci_enable_msi(pdev) == 0) { |
3242 | err = sky2_test_msi(hw); | ||
3243 | if (err == -EOPNOTSUPP) { | ||
3244 | /* MSI test failed, go back to INTx mode */ | ||
3245 | printk(KERN_WARNING PFX "%s: No interrupt was generated using MSI, " | ||
3246 | "switching to INTx mode. Please report this failure to " | ||
3247 | "the PCI maintainer and include system chipset information.\n", | ||
3248 | pci_name(pdev)); | ||
3249 | pci_disable_msi(pdev); | ||
3250 | } | ||
3251 | else if (err) | ||
3252 | goto err_out_unregister; | ||
3253 | } | ||
3254 | |||
3255 | err = request_irq(pdev->irq, sky2_intr, SA_SHIRQ | SA_SAMPLE_RANDOM, | ||
3256 | DRV_NAME, hw); | ||
3173 | if (err) { | 3257 | if (err) { |
3174 | printk(KERN_ERR PFX "%s: cannot assign irq %d\n", | 3258 | printk(KERN_ERR PFX "%s: cannot assign irq %d\n", |
3175 | pci_name(pdev), pdev->irq); | 3259 | pci_name(pdev), pdev->irq); |
@@ -3184,6 +3268,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
3184 | return 0; | 3268 | return 0; |
3185 | 3269 | ||
3186 | err_out_unregister: | 3270 | err_out_unregister: |
3271 | if (hw->msi) | ||
3272 | pci_disable_msi(pdev); | ||
3187 | if (dev1) { | 3273 | if (dev1) { |
3188 | unregister_netdev(dev1); | 3274 | unregister_netdev(dev1); |
3189 | free_netdev(dev1); | 3275 | free_netdev(dev1); |
@@ -3226,6 +3312,8 @@ static void __devexit sky2_remove(struct pci_dev *pdev) | |||
3226 | sky2_read8(hw, B0_CTST); | 3312 | sky2_read8(hw, B0_CTST); |
3227 | 3313 | ||
3228 | free_irq(pdev->irq, hw); | 3314 | free_irq(pdev->irq, hw); |
3315 | if (hw->msi) | ||
3316 | pci_disable_msi(pdev); | ||
3229 | pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma); | 3317 | pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma); |
3230 | pci_release_regions(pdev); | 3318 | pci_release_regions(pdev); |
3231 | pci_disable_device(pdev); | 3319 | pci_disable_device(pdev); |
@@ -3263,25 +3351,33 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state) | |||
3263 | static int sky2_resume(struct pci_dev *pdev) | 3351 | static int sky2_resume(struct pci_dev *pdev) |
3264 | { | 3352 | { |
3265 | struct sky2_hw *hw = pci_get_drvdata(pdev); | 3353 | struct sky2_hw *hw = pci_get_drvdata(pdev); |
3266 | int i; | 3354 | int i, err; |
3267 | 3355 | ||
3268 | pci_restore_state(pdev); | 3356 | pci_restore_state(pdev); |
3269 | pci_enable_wake(pdev, PCI_D0, 0); | 3357 | pci_enable_wake(pdev, PCI_D0, 0); |
3270 | sky2_set_power_state(hw, PCI_D0); | 3358 | err = sky2_set_power_state(hw, PCI_D0); |
3359 | if (err) | ||
3360 | goto out; | ||
3271 | 3361 | ||
3272 | sky2_reset(hw); | 3362 | err = sky2_reset(hw); |
3363 | if (err) | ||
3364 | goto out; | ||
3273 | 3365 | ||
3274 | for (i = 0; i < 2; i++) { | 3366 | for (i = 0; i < 2; i++) { |
3275 | struct net_device *dev = hw->dev[i]; | 3367 | struct net_device *dev = hw->dev[i]; |
3276 | if (dev) { | 3368 | if (dev && netif_running(dev)) { |
3277 | if (netif_running(dev)) { | 3369 | netif_device_attach(dev); |
3278 | netif_device_attach(dev); | 3370 | err = sky2_up(dev); |
3279 | if (sky2_up(dev)) | 3371 | if (err) { |
3280 | dev_close(dev); | 3372 | printk(KERN_ERR PFX "%s: could not up: %d\n", |
3373 | dev->name, err); | ||
3374 | dev_close(dev); | ||
3375 | break; | ||
3281 | } | 3376 | } |
3282 | } | 3377 | } |
3283 | } | 3378 | } |
3284 | return 0; | 3379 | out: |
3380 | return err; | ||
3285 | } | 3381 | } |
3286 | #endif | 3382 | #endif |
3287 | 3383 | ||
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 95518921001c..fd12c289a238 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h | |||
@@ -1841,6 +1841,7 @@ struct sky2_hw { | |||
1841 | struct net_device *dev[2]; | 1841 | struct net_device *dev[2]; |
1842 | 1842 | ||
1843 | int pm_cap; | 1843 | int pm_cap; |
1844 | int msi; | ||
1844 | u8 chip_id; | 1845 | u8 chip_id; |
1845 | u8 chip_rev; | 1846 | u8 chip_rev; |
1846 | u8 copper; | 1847 | u8 copper; |
@@ -1867,14 +1868,6 @@ static inline u8 sky2_read8(const struct sky2_hw *hw, unsigned reg) | |||
1867 | return readb(hw->regs + reg); | 1868 | return readb(hw->regs + reg); |
1868 | } | 1869 | } |
1869 | 1870 | ||
1870 | /* This should probably go away, bus based tweeks suck */ | ||
1871 | static inline int is_pciex(const struct sky2_hw *hw) | ||
1872 | { | ||
1873 | u32 status; | ||
1874 | pci_read_config_dword(hw->pdev, PCI_DEV_STATUS, &status); | ||
1875 | return (status & PCI_OS_PCI_X) == 0; | ||
1876 | } | ||
1877 | |||
1878 | static inline void sky2_write32(const struct sky2_hw *hw, unsigned reg, u32 val) | 1871 | static inline void sky2_write32(const struct sky2_hw *hw, unsigned reg, u32 val) |
1879 | { | 1872 | { |
1880 | writel(val, hw->regs + reg); | 1873 | writel(val, hw->regs + reg); |
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index f2d1dafde087..e7dc653d5bd6 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -69,8 +69,8 @@ | |||
69 | 69 | ||
70 | #define DRV_MODULE_NAME "tg3" | 70 | #define DRV_MODULE_NAME "tg3" |
71 | #define PFX DRV_MODULE_NAME ": " | 71 | #define PFX DRV_MODULE_NAME ": " |
72 | #define DRV_MODULE_VERSION "3.48" | 72 | #define DRV_MODULE_VERSION "3.49" |
73 | #define DRV_MODULE_RELDATE "Jan 16, 2006" | 73 | #define DRV_MODULE_RELDATE "Feb 2, 2006" |
74 | 74 | ||
75 | #define TG3_DEF_MAC_MODE 0 | 75 | #define TG3_DEF_MAC_MODE 0 |
76 | #define TG3_DEF_RX_MODE 0 | 76 | #define TG3_DEF_RX_MODE 0 |
@@ -3482,6 +3482,17 @@ static void tg3_reset_task(void *_data) | |||
3482 | struct tg3 *tp = _data; | 3482 | struct tg3 *tp = _data; |
3483 | unsigned int restart_timer; | 3483 | unsigned int restart_timer; |
3484 | 3484 | ||
3485 | tg3_full_lock(tp, 0); | ||
3486 | tp->tg3_flags |= TG3_FLAG_IN_RESET_TASK; | ||
3487 | |||
3488 | if (!netif_running(tp->dev)) { | ||
3489 | tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK; | ||
3490 | tg3_full_unlock(tp); | ||
3491 | return; | ||
3492 | } | ||
3493 | |||
3494 | tg3_full_unlock(tp); | ||
3495 | |||
3485 | tg3_netif_stop(tp); | 3496 | tg3_netif_stop(tp); |
3486 | 3497 | ||
3487 | tg3_full_lock(tp, 1); | 3498 | tg3_full_lock(tp, 1); |
@@ -3494,10 +3505,12 @@ static void tg3_reset_task(void *_data) | |||
3494 | 3505 | ||
3495 | tg3_netif_start(tp); | 3506 | tg3_netif_start(tp); |
3496 | 3507 | ||
3497 | tg3_full_unlock(tp); | ||
3498 | |||
3499 | if (restart_timer) | 3508 | if (restart_timer) |
3500 | mod_timer(&tp->timer, jiffies + 1); | 3509 | mod_timer(&tp->timer, jiffies + 1); |
3510 | |||
3511 | tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK; | ||
3512 | |||
3513 | tg3_full_unlock(tp); | ||
3501 | } | 3514 | } |
3502 | 3515 | ||
3503 | static void tg3_tx_timeout(struct net_device *dev) | 3516 | static void tg3_tx_timeout(struct net_device *dev) |
@@ -6786,6 +6799,13 @@ static int tg3_close(struct net_device *dev) | |||
6786 | { | 6799 | { |
6787 | struct tg3 *tp = netdev_priv(dev); | 6800 | struct tg3 *tp = netdev_priv(dev); |
6788 | 6801 | ||
6802 | /* Calling flush_scheduled_work() may deadlock because | ||
6803 | * linkwatch_event() may be on the workqueue and it will try to get | ||
6804 | * the rtnl_lock which we are holding. | ||
6805 | */ | ||
6806 | while (tp->tg3_flags & TG3_FLAG_IN_RESET_TASK) | ||
6807 | msleep(1); | ||
6808 | |||
6789 | netif_stop_queue(dev); | 6809 | netif_stop_queue(dev); |
6790 | 6810 | ||
6791 | del_timer_sync(&tp->timer); | 6811 | del_timer_sync(&tp->timer); |
@@ -10880,6 +10900,7 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev) | |||
10880 | if (dev) { | 10900 | if (dev) { |
10881 | struct tg3 *tp = netdev_priv(dev); | 10901 | struct tg3 *tp = netdev_priv(dev); |
10882 | 10902 | ||
10903 | flush_scheduled_work(); | ||
10883 | unregister_netdev(dev); | 10904 | unregister_netdev(dev); |
10884 | if (tp->regs) { | 10905 | if (tp->regs) { |
10885 | iounmap(tp->regs); | 10906 | iounmap(tp->regs); |
@@ -10901,6 +10922,7 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state) | |||
10901 | if (!netif_running(dev)) | 10922 | if (!netif_running(dev)) |
10902 | return 0; | 10923 | return 0; |
10903 | 10924 | ||
10925 | flush_scheduled_work(); | ||
10904 | tg3_netif_stop(tp); | 10926 | tg3_netif_stop(tp); |
10905 | 10927 | ||
10906 | del_timer_sync(&tp->timer); | 10928 | del_timer_sync(&tp->timer); |
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index e8243305f0e8..7f4b7f6ac40d 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h | |||
@@ -2162,6 +2162,7 @@ struct tg3 { | |||
2162 | #define TG3_FLAG_JUMBO_RING_ENABLE 0x00800000 | 2162 | #define TG3_FLAG_JUMBO_RING_ENABLE 0x00800000 |
2163 | #define TG3_FLAG_10_100_ONLY 0x01000000 | 2163 | #define TG3_FLAG_10_100_ONLY 0x01000000 |
2164 | #define TG3_FLAG_PAUSE_AUTONEG 0x02000000 | 2164 | #define TG3_FLAG_PAUSE_AUTONEG 0x02000000 |
2165 | #define TG3_FLAG_IN_RESET_TASK 0x04000000 | ||
2165 | #define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000 | 2166 | #define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000 |
2166 | #define TG3_FLAG_GOT_SERDES_FLOWCTL 0x20000000 | 2167 | #define TG3_FLAG_GOT_SERDES_FLOWCTL 0x20000000 |
2167 | #define TG3_FLAG_SPLIT_MODE 0x40000000 | 2168 | #define TG3_FLAG_SPLIT_MODE 0x40000000 |
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c index 983981666800..238e9c72cb3a 100644 --- a/drivers/net/tulip/uli526x.c +++ b/drivers/net/tulip/uli526x.c | |||
@@ -214,7 +214,7 @@ static u32 uli526x_cr6_user_set; | |||
214 | /* For module input parameter */ | 214 | /* For module input parameter */ |
215 | static int debug; | 215 | static int debug; |
216 | static u32 cr6set; | 216 | static u32 cr6set; |
217 | static unsigned char mode = 8; | 217 | static int mode = 8; |
218 | 218 | ||
219 | /* function declaration ------------------------------------- */ | 219 | /* function declaration ------------------------------------- */ |
220 | static int uli526x_open(struct net_device *); | 220 | static int uli526x_open(struct net_device *); |
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index 2f61a47b4716..1ff5de076d21 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c | |||
@@ -1943,7 +1943,7 @@ static int dscc4_init_ring(struct net_device *dev) | |||
1943 | (++i%TX_RING_SIZE)*sizeof(*tx_fd)); | 1943 | (++i%TX_RING_SIZE)*sizeof(*tx_fd)); |
1944 | } while (i < TX_RING_SIZE); | 1944 | } while (i < TX_RING_SIZE); |
1945 | 1945 | ||
1946 | if (dscc4_init_dummy_skb(dpriv) < 0) | 1946 | if (!dscc4_init_dummy_skb(dpriv)) |
1947 | goto err_free_dma_tx; | 1947 | goto err_free_dma_tx; |
1948 | 1948 | ||
1949 | memset(dpriv->rx_skbuff, 0, sizeof(struct sk_buff *)*RX_RING_SIZE); | 1949 | memset(dpriv->rx_skbuff, 0, sizeof(struct sk_buff *)*RX_RING_SIZE); |
diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c index 8dea07b47999..eba8e5cfacc2 100644 --- a/drivers/net/wan/pci200syn.c +++ b/drivers/net/wan/pci200syn.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <linux/netdevice.h> | 29 | #include <linux/netdevice.h> |
30 | #include <linux/hdlc.h> | 30 | #include <linux/hdlc.h> |
31 | #include <linux/pci.h> | 31 | #include <linux/pci.h> |
32 | #include <asm/delay.h> | 32 | #include <linux/delay.h> |
33 | #include <asm/io.h> | 33 | #include <asm/io.h> |
34 | 34 | ||
35 | #include "hd64572.h" | 35 | #include "hd64572.h" |
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c index 9c1e10602f2b..9d3b51c3ef54 100644 --- a/drivers/net/wan/wanxl.c +++ b/drivers/net/wan/wanxl.c | |||
@@ -27,8 +27,8 @@ | |||
27 | #include <linux/hdlc.h> | 27 | #include <linux/hdlc.h> |
28 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
29 | #include <linux/dma-mapping.h> | 29 | #include <linux/dma-mapping.h> |
30 | #include <linux/delay.h> | ||
30 | #include <asm/io.h> | 31 | #include <asm/io.h> |
31 | #include <asm/delay.h> | ||
32 | 32 | ||
33 | #include "wanxl.h" | 33 | #include "wanxl.h" |
34 | 34 | ||
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index c5cd61c7f927..e5bb9f5ae429 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c | |||
@@ -748,7 +748,7 @@ prism54_get_essid(struct net_device *ndev, struct iw_request_info *info, | |||
748 | if (essid->length) { | 748 | if (essid->length) { |
749 | dwrq->flags = 1; /* set ESSID to ON for Wireless Extensions */ | 749 | dwrq->flags = 1; /* set ESSID to ON for Wireless Extensions */ |
750 | /* if it is to big, trunk it */ | 750 | /* if it is to big, trunk it */ |
751 | dwrq->length = min(IW_ESSID_MAX_SIZE, essid->length); | 751 | dwrq->length = min((u8)IW_ESSID_MAX_SIZE, essid->length); |
752 | } else { | 752 | } else { |
753 | dwrq->flags = 0; | 753 | dwrq->flags = 0; |
754 | dwrq->length = 0; | 754 | dwrq->length = 0; |
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index 9e0229f7e25f..f46e8438e0d2 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c | |||
@@ -1423,7 +1423,7 @@ static void __init ccio_init_resources(struct ioc *ioc) | |||
1423 | struct resource *res = ioc->mmio_region; | 1423 | struct resource *res = ioc->mmio_region; |
1424 | char *name = kmalloc(14, GFP_KERNEL); | 1424 | char *name = kmalloc(14, GFP_KERNEL); |
1425 | 1425 | ||
1426 | sprintf(name, "GSC Bus [%d/]", ioc->hw_path); | 1426 | snprintf(name, 14, "GSC Bus [%d/]", ioc->hw_path); |
1427 | 1427 | ||
1428 | ccio_init_resource(res, name, &ioc->ioc_regs->io_io_low); | 1428 | ccio_init_resource(res, name, &ioc->ioc_regs->io_io_low); |
1429 | ccio_init_resource(res + 1, name, &ioc->ioc_regs->io_io_low_hv); | 1429 | ccio_init_resource(res + 1, name, &ioc->ioc_regs->io_io_low_hv); |
@@ -1557,12 +1557,11 @@ static int ccio_probe(struct parisc_device *dev) | |||
1557 | int i; | 1557 | int i; |
1558 | struct ioc *ioc, **ioc_p = &ioc_list; | 1558 | struct ioc *ioc, **ioc_p = &ioc_list; |
1559 | 1559 | ||
1560 | ioc = kmalloc(sizeof(struct ioc), GFP_KERNEL); | 1560 | ioc = kzalloc(sizeof(struct ioc), GFP_KERNEL); |
1561 | if (ioc == NULL) { | 1561 | if (ioc == NULL) { |
1562 | printk(KERN_ERR MODULE_NAME ": memory allocation failure\n"); | 1562 | printk(KERN_ERR MODULE_NAME ": memory allocation failure\n"); |
1563 | return 1; | 1563 | return 1; |
1564 | } | 1564 | } |
1565 | memset(ioc, 0, sizeof(struct ioc)); | ||
1566 | 1565 | ||
1567 | ioc->name = dev->id.hversion == U2_IOA_RUNWAY ? "U2" : "UTurn"; | 1566 | ioc->name = dev->id.hversion == U2_IOA_RUNWAY ? "U2" : "UTurn"; |
1568 | 1567 | ||
@@ -1578,7 +1577,7 @@ static int ccio_probe(struct parisc_device *dev) | |||
1578 | ccio_ioc_init(ioc); | 1577 | ccio_ioc_init(ioc); |
1579 | ccio_init_resources(ioc); | 1578 | ccio_init_resources(ioc); |
1580 | hppa_dma_ops = &ccio_ops; | 1579 | hppa_dma_ops = &ccio_ops; |
1581 | dev->dev.platform_data = kmalloc(sizeof(struct pci_hba_data), GFP_KERNEL); | 1580 | dev->dev.platform_data = kzalloc(sizeof(struct pci_hba_data), GFP_KERNEL); |
1582 | 1581 | ||
1583 | /* if this fails, no I/O cards will work, so may as well bug */ | 1582 | /* if this fails, no I/O cards will work, so may as well bug */ |
1584 | BUG_ON(dev->dev.platform_data == NULL); | 1583 | BUG_ON(dev->dev.platform_data == NULL); |
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index 216d1d859326..3d1a7f98c676 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c | |||
@@ -989,14 +989,12 @@ static int __init dino_probe(struct parisc_device *dev) | |||
989 | */ | 989 | */ |
990 | } | 990 | } |
991 | 991 | ||
992 | dino_dev = kmalloc(sizeof(struct dino_device), GFP_KERNEL); | 992 | dino_dev = kzalloc(sizeof(struct dino_device), GFP_KERNEL); |
993 | if (!dino_dev) { | 993 | if (!dino_dev) { |
994 | printk("dino_init_chip - couldn't alloc dino_device\n"); | 994 | printk("dino_init_chip - couldn't alloc dino_device\n"); |
995 | return 1; | 995 | return 1; |
996 | } | 996 | } |
997 | 997 | ||
998 | memset(dino_dev, 0, sizeof(struct dino_device)); | ||
999 | |||
1000 | dino_dev->hba.dev = dev; | 998 | dino_dev->hba.dev = dev; |
1001 | dino_dev->hba.base_addr = ioremap(hpa, 4096); | 999 | dino_dev->hba.base_addr = ioremap(hpa, 4096); |
1002 | dino_dev->hba.lmmio_space_offset = 0; /* CPU addrs == bus addrs */ | 1000 | dino_dev->hba.lmmio_space_offset = 0; /* CPU addrs == bus addrs */ |
diff --git a/drivers/parisc/hppb.c b/drivers/parisc/hppb.c index 5edf93f80757..07dc2b6d4e93 100644 --- a/drivers/parisc/hppb.c +++ b/drivers/parisc/hppb.c | |||
@@ -60,12 +60,11 @@ static int hppb_probe(struct parisc_device *dev) | |||
60 | } | 60 | } |
61 | 61 | ||
62 | if(card->hpa) { | 62 | if(card->hpa) { |
63 | card->next = kmalloc(sizeof(struct hppb_card), GFP_KERNEL); | 63 | card->next = kzalloc(sizeof(struct hppb_card), GFP_KERNEL); |
64 | if(!card->next) { | 64 | if(!card->next) { |
65 | printk(KERN_ERR "HP-PB: Unable to allocate memory.\n"); | 65 | printk(KERN_ERR "HP-PB: Unable to allocate memory.\n"); |
66 | return 1; | 66 | return 1; |
67 | } | 67 | } |
68 | memset(card->next, '\0', sizeof(struct hppb_card)); | ||
69 | card = card->next; | 68 | card = card->next; |
70 | } | 69 | } |
71 | printk(KERN_INFO "Found GeckoBoa at 0x%lx\n", dev->hpa.start); | 70 | printk(KERN_INFO "Found GeckoBoa at 0x%lx\n", dev->hpa.start); |
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 19657efa8dc3..8d7a36392eb8 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c | |||
@@ -873,28 +873,24 @@ void *iosapic_register(unsigned long hpa) | |||
873 | return NULL; | 873 | return NULL; |
874 | } | 874 | } |
875 | 875 | ||
876 | isi = (struct iosapic_info *)kmalloc(sizeof(struct iosapic_info), GFP_KERNEL); | 876 | isi = (struct iosapic_info *)kzalloc(sizeof(struct iosapic_info), GFP_KERNEL); |
877 | if (!isi) { | 877 | if (!isi) { |
878 | BUG(); | 878 | BUG(); |
879 | return NULL; | 879 | return NULL; |
880 | } | 880 | } |
881 | 881 | ||
882 | memset(isi, 0, sizeof(struct iosapic_info)); | ||
883 | |||
884 | isi->addr = ioremap(hpa, 4096); | 882 | isi->addr = ioremap(hpa, 4096); |
885 | isi->isi_hpa = hpa; | 883 | isi->isi_hpa = hpa; |
886 | isi->isi_version = iosapic_rd_version(isi); | 884 | isi->isi_version = iosapic_rd_version(isi); |
887 | isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1; | 885 | isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1; |
888 | 886 | ||
889 | vip = isi->isi_vector = (struct vector_info *) | 887 | vip = isi->isi_vector = (struct vector_info *) |
890 | kmalloc(sizeof(struct vector_info) * isi->isi_num_vectors, GFP_KERNEL); | 888 | kzalloc(sizeof(struct vector_info) * isi->isi_num_vectors, GFP_KERNEL); |
891 | if (vip == NULL) { | 889 | if (vip == NULL) { |
892 | kfree(isi); | 890 | kfree(isi); |
893 | return NULL; | 891 | return NULL; |
894 | } | 892 | } |
895 | 893 | ||
896 | memset(vip, 0, sizeof(struct vector_info) * isi->isi_num_vectors); | ||
897 | |||
898 | for (cnt=0; cnt < isi->isi_num_vectors; cnt++, vip++) { | 894 | for (cnt=0; cnt < isi->isi_num_vectors; cnt++, vip++) { |
899 | vip->irqline = (unsigned char) cnt; | 895 | vip->irqline = (unsigned char) cnt; |
900 | vip->iosapic = isi; | 896 | vip->iosapic = isi; |
diff --git a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c index 2b3ba1dcf332..cb3d28176129 100644 --- a/drivers/parisc/lasi.c +++ b/drivers/parisc/lasi.c | |||
@@ -166,11 +166,12 @@ static void lasi_power_off(void) | |||
166 | int __init | 166 | int __init |
167 | lasi_init_chip(struct parisc_device *dev) | 167 | lasi_init_chip(struct parisc_device *dev) |
168 | { | 168 | { |
169 | extern void (*chassis_power_off)(void); | ||
169 | struct gsc_asic *lasi; | 170 | struct gsc_asic *lasi; |
170 | struct gsc_irq gsc_irq; | 171 | struct gsc_irq gsc_irq; |
171 | int ret; | 172 | int ret; |
172 | 173 | ||
173 | lasi = kmalloc(sizeof(*lasi), GFP_KERNEL); | 174 | lasi = kzalloc(sizeof(*lasi), GFP_KERNEL); |
174 | if (!lasi) | 175 | if (!lasi) |
175 | return -ENOMEM; | 176 | return -ENOMEM; |
176 | 177 | ||
@@ -222,7 +223,7 @@ lasi_init_chip(struct parisc_device *dev) | |||
222 | * ensure that only the first LASI (the one controlling the power off) | 223 | * ensure that only the first LASI (the one controlling the power off) |
223 | * should set the HPA here */ | 224 | * should set the HPA here */ |
224 | lasi_power_off_hpa = lasi->hpa; | 225 | lasi_power_off_hpa = lasi->hpa; |
225 | pm_power_off = lasi_power_off; | 226 | chassis_power_off = lasi_power_off; |
226 | 227 | ||
227 | return ret; | 228 | return ret; |
228 | } | 229 | } |
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index cbae8c8963fa..e8a2a4a852f5 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c | |||
@@ -1565,7 +1565,7 @@ lba_driver_probe(struct parisc_device *dev) | |||
1565 | } else if (IS_MERCURY(dev) || IS_QUICKSILVER(dev)) { | 1565 | } else if (IS_MERCURY(dev) || IS_QUICKSILVER(dev)) { |
1566 | func_class &= 0xff; | 1566 | func_class &= 0xff; |
1567 | version = kmalloc(6, GFP_KERNEL); | 1567 | version = kmalloc(6, GFP_KERNEL); |
1568 | sprintf(version,"TR%d.%d",(func_class >> 4),(func_class & 0xf)); | 1568 | snprintf(version, 6, "TR%d.%d",(func_class >> 4),(func_class & 0xf)); |
1569 | /* We could use one printk for both Elroy and Mercury, | 1569 | /* We could use one printk for both Elroy and Mercury, |
1570 | * but for the mask for func_class. | 1570 | * but for the mask for func_class. |
1571 | */ | 1571 | */ |
@@ -1586,14 +1586,12 @@ lba_driver_probe(struct parisc_device *dev) | |||
1586 | ** have an IRT entry will get NULL back from iosapic code. | 1586 | ** have an IRT entry will get NULL back from iosapic code. |
1587 | */ | 1587 | */ |
1588 | 1588 | ||
1589 | lba_dev = kmalloc(sizeof(struct lba_device), GFP_KERNEL); | 1589 | lba_dev = kzalloc(sizeof(struct lba_device), GFP_KERNEL); |
1590 | if (!lba_dev) { | 1590 | if (!lba_dev) { |
1591 | printk(KERN_ERR "lba_init_chip - couldn't alloc lba_device\n"); | 1591 | printk(KERN_ERR "lba_init_chip - couldn't alloc lba_device\n"); |
1592 | return(1); | 1592 | return(1); |
1593 | } | 1593 | } |
1594 | 1594 | ||
1595 | memset(lba_dev, 0, sizeof(struct lba_device)); | ||
1596 | |||
1597 | 1595 | ||
1598 | /* ---------- First : initialize data we already have --------- */ | 1596 | /* ---------- First : initialize data we already have --------- */ |
1599 | 1597 | ||
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c index 42a3c54e8e6c..a28e17898fbd 100644 --- a/drivers/parisc/pdc_stable.c +++ b/drivers/parisc/pdc_stable.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Interfaces to retrieve and set PDC Stable options (firmware) | 2 | * Interfaces to retrieve and set PDC Stable options (firmware) |
3 | * | 3 | * |
4 | * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org> | 4 | * Copyright (C) 2005-2006 Thibaut VARENE <varenet@parisc-linux.org> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
@@ -26,11 +26,19 @@ | |||
26 | * | 26 | * |
27 | * Since locations between 96 and 192 are the various paths, most (if not | 27 | * Since locations between 96 and 192 are the various paths, most (if not |
28 | * all) PA-RISC machines should have them. Anyway, for safety reasons, the | 28 | * all) PA-RISC machines should have them. Anyway, for safety reasons, the |
29 | * following code can deal with only 96 bytes of Stable Storage, and all | 29 | * following code can deal with just 96 bytes of Stable Storage, and all |
30 | * sizes between 96 and 192 bytes (provided they are multiple of struct | 30 | * sizes between 96 and 192 bytes (provided they are multiple of struct |
31 | * device_path size, eg: 128, 160 and 192) to provide full information. | 31 | * device_path size, eg: 128, 160 and 192) to provide full information. |
32 | * The code makes no use of data above 192 bytes. One last word: there's one | 32 | * The code makes no use of data above 192 bytes. One last word: there's one |
33 | * path we can always count on: the primary path. | 33 | * path we can always count on: the primary path. |
34 | * | ||
35 | * The current policy wrt file permissions is: | ||
36 | * - write: root only | ||
37 | * - read: (reading triggers PDC calls) ? root only : everyone | ||
38 | * The rationale is that PDC calls could hog (DoS) the machine. | ||
39 | * | ||
40 | * TODO: | ||
41 | * - timer/fastsize write calls | ||
34 | */ | 42 | */ |
35 | 43 | ||
36 | #undef PDCS_DEBUG | 44 | #undef PDCS_DEBUG |
@@ -50,13 +58,15 @@ | |||
50 | #include <linux/kobject.h> | 58 | #include <linux/kobject.h> |
51 | #include <linux/device.h> | 59 | #include <linux/device.h> |
52 | #include <linux/errno.h> | 60 | #include <linux/errno.h> |
61 | #include <linux/spinlock.h> | ||
53 | 62 | ||
54 | #include <asm/pdc.h> | 63 | #include <asm/pdc.h> |
55 | #include <asm/page.h> | 64 | #include <asm/page.h> |
56 | #include <asm/uaccess.h> | 65 | #include <asm/uaccess.h> |
57 | #include <asm/hardware.h> | 66 | #include <asm/hardware.h> |
58 | 67 | ||
59 | #define PDCS_VERSION "0.10" | 68 | #define PDCS_VERSION "0.22" |
69 | #define PDCS_PREFIX "PDC Stable Storage" | ||
60 | 70 | ||
61 | #define PDCS_ADDR_PPRI 0x00 | 71 | #define PDCS_ADDR_PPRI 0x00 |
62 | #define PDCS_ADDR_OSID 0x40 | 72 | #define PDCS_ADDR_OSID 0x40 |
@@ -70,10 +80,12 @@ MODULE_DESCRIPTION("sysfs interface to HP PDC Stable Storage data"); | |||
70 | MODULE_LICENSE("GPL"); | 80 | MODULE_LICENSE("GPL"); |
71 | MODULE_VERSION(PDCS_VERSION); | 81 | MODULE_VERSION(PDCS_VERSION); |
72 | 82 | ||
83 | /* holds Stable Storage size. Initialized once and for all, no lock needed */ | ||
73 | static unsigned long pdcs_size __read_mostly; | 84 | static unsigned long pdcs_size __read_mostly; |
74 | 85 | ||
75 | /* This struct defines what we need to deal with a parisc pdc path entry */ | 86 | /* This struct defines what we need to deal with a parisc pdc path entry */ |
76 | struct pdcspath_entry { | 87 | struct pdcspath_entry { |
88 | rwlock_t rw_lock; /* to protect path entry access */ | ||
77 | short ready; /* entry record is valid if != 0 */ | 89 | short ready; /* entry record is valid if != 0 */ |
78 | unsigned long addr; /* entry address in stable storage */ | 90 | unsigned long addr; /* entry address in stable storage */ |
79 | char *name; /* entry name */ | 91 | char *name; /* entry name */ |
@@ -121,6 +133,8 @@ struct pdcspath_attribute paths_attr_##_name = { \ | |||
121 | * content of the stable storage WRT various paths in these structs. We read | 133 | * content of the stable storage WRT various paths in these structs. We read |
122 | * these structs when reading the files, and we will write to these structs when | 134 | * these structs when reading the files, and we will write to these structs when |
123 | * writing to the files, and only then write them back to the Stable Storage. | 135 | * writing to the files, and only then write them back to the Stable Storage. |
136 | * | ||
137 | * This function expects to be called with @entry->rw_lock write-hold. | ||
124 | */ | 138 | */ |
125 | static int | 139 | static int |
126 | pdcspath_fetch(struct pdcspath_entry *entry) | 140 | pdcspath_fetch(struct pdcspath_entry *entry) |
@@ -160,14 +174,15 @@ pdcspath_fetch(struct pdcspath_entry *entry) | |||
160 | * pointer, from which it'll find out the corresponding hardware path. | 174 | * pointer, from which it'll find out the corresponding hardware path. |
161 | * For now we do not handle the case where there's an error in writing to the | 175 | * For now we do not handle the case where there's an error in writing to the |
162 | * Stable Storage area, so you'd better not mess up the data :P | 176 | * Stable Storage area, so you'd better not mess up the data :P |
177 | * | ||
178 | * This function expects to be called with @entry->rw_lock write-hold. | ||
163 | */ | 179 | */ |
164 | static int | 180 | static void |
165 | pdcspath_store(struct pdcspath_entry *entry) | 181 | pdcspath_store(struct pdcspath_entry *entry) |
166 | { | 182 | { |
167 | struct device_path *devpath; | 183 | struct device_path *devpath; |
168 | 184 | ||
169 | if (!entry) | 185 | BUG_ON(!entry); |
170 | return -EINVAL; | ||
171 | 186 | ||
172 | devpath = &entry->devpath; | 187 | devpath = &entry->devpath; |
173 | 188 | ||
@@ -176,10 +191,8 @@ pdcspath_store(struct pdcspath_entry *entry) | |||
176 | First case, we don't have a preset hwpath... */ | 191 | First case, we don't have a preset hwpath... */ |
177 | if (!entry->ready) { | 192 | if (!entry->ready) { |
178 | /* ...but we have a device, map it */ | 193 | /* ...but we have a device, map it */ |
179 | if (entry->dev) | 194 | BUG_ON(!entry->dev); |
180 | device_to_hwpath(entry->dev, (struct hardware_path *)devpath); | 195 | device_to_hwpath(entry->dev, (struct hardware_path *)devpath); |
181 | else | ||
182 | return -EINVAL; | ||
183 | } | 196 | } |
184 | /* else, we expect the provided hwpath to be valid. */ | 197 | /* else, we expect the provided hwpath to be valid. */ |
185 | 198 | ||
@@ -191,15 +204,13 @@ pdcspath_store(struct pdcspath_entry *entry) | |||
191 | printk(KERN_ERR "%s: an error occured when writing to PDC.\n" | 204 | printk(KERN_ERR "%s: an error occured when writing to PDC.\n" |
192 | "It is likely that the Stable Storage data has been corrupted.\n" | 205 | "It is likely that the Stable Storage data has been corrupted.\n" |
193 | "Please check it carefully upon next reboot.\n", __func__); | 206 | "Please check it carefully upon next reboot.\n", __func__); |
194 | return -EIO; | 207 | WARN_ON(1); |
195 | } | 208 | } |
196 | 209 | ||
197 | /* kobject is already registered */ | 210 | /* kobject is already registered */ |
198 | entry->ready = 2; | 211 | entry->ready = 2; |
199 | 212 | ||
200 | DPRINTK("%s: device: 0x%p\n", __func__, entry->dev); | 213 | DPRINTK("%s: device: 0x%p\n", __func__, entry->dev); |
201 | |||
202 | return 0; | ||
203 | } | 214 | } |
204 | 215 | ||
205 | /** | 216 | /** |
@@ -214,14 +225,17 @@ pdcspath_hwpath_read(struct pdcspath_entry *entry, char *buf) | |||
214 | { | 225 | { |
215 | char *out = buf; | 226 | char *out = buf; |
216 | struct device_path *devpath; | 227 | struct device_path *devpath; |
217 | unsigned short i; | 228 | short i; |
218 | 229 | ||
219 | if (!entry || !buf) | 230 | if (!entry || !buf) |
220 | return -EINVAL; | 231 | return -EINVAL; |
221 | 232 | ||
233 | read_lock(&entry->rw_lock); | ||
222 | devpath = &entry->devpath; | 234 | devpath = &entry->devpath; |
235 | i = entry->ready; | ||
236 | read_unlock(&entry->rw_lock); | ||
223 | 237 | ||
224 | if (!entry->ready) | 238 | if (!i) /* entry is not ready */ |
225 | return -ENODATA; | 239 | return -ENODATA; |
226 | 240 | ||
227 | for (i = 0; i < 6; i++) { | 241 | for (i = 0; i < 6; i++) { |
@@ -242,7 +256,7 @@ pdcspath_hwpath_read(struct pdcspath_entry *entry, char *buf) | |||
242 | * | 256 | * |
243 | * We will call this function to change the current hardware path. | 257 | * We will call this function to change the current hardware path. |
244 | * Hardware paths are to be given '/'-delimited, without brackets. | 258 | * Hardware paths are to be given '/'-delimited, without brackets. |
245 | * We take care to make sure that the provided path actually maps to an existing | 259 | * We make sure that the provided path actually maps to an existing |
246 | * device, BUT nothing would prevent some foolish user to set the path to some | 260 | * device, BUT nothing would prevent some foolish user to set the path to some |
247 | * PCI bridge or even a CPU... | 261 | * PCI bridge or even a CPU... |
248 | * A better work around would be to make sure we are at the end of a device tree | 262 | * A better work around would be to make sure we are at the end of a device tree |
@@ -298,17 +312,19 @@ pdcspath_hwpath_write(struct pdcspath_entry *entry, const char *buf, size_t coun | |||
298 | } | 312 | } |
299 | 313 | ||
300 | /* So far so good, let's get in deep */ | 314 | /* So far so good, let's get in deep */ |
315 | write_lock(&entry->rw_lock); | ||
301 | entry->ready = 0; | 316 | entry->ready = 0; |
302 | entry->dev = dev; | 317 | entry->dev = dev; |
303 | 318 | ||
304 | /* Now, dive in. Write back to the hardware */ | 319 | /* Now, dive in. Write back to the hardware */ |
305 | WARN_ON(pdcspath_store(entry)); /* this warn should *NEVER* happen */ | 320 | pdcspath_store(entry); |
306 | 321 | ||
307 | /* Update the symlink to the real device */ | 322 | /* Update the symlink to the real device */ |
308 | sysfs_remove_link(&entry->kobj, "device"); | 323 | sysfs_remove_link(&entry->kobj, "device"); |
309 | sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device"); | 324 | sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device"); |
325 | write_unlock(&entry->rw_lock); | ||
310 | 326 | ||
311 | printk(KERN_INFO "PDC Stable Storage: changed \"%s\" path to \"%s\"\n", | 327 | printk(KERN_INFO PDCS_PREFIX ": changed \"%s\" path to \"%s\"\n", |
312 | entry->name, buf); | 328 | entry->name, buf); |
313 | 329 | ||
314 | return count; | 330 | return count; |
@@ -326,14 +342,17 @@ pdcspath_layer_read(struct pdcspath_entry *entry, char *buf) | |||
326 | { | 342 | { |
327 | char *out = buf; | 343 | char *out = buf; |
328 | struct device_path *devpath; | 344 | struct device_path *devpath; |
329 | unsigned short i; | 345 | short i; |
330 | 346 | ||
331 | if (!entry || !buf) | 347 | if (!entry || !buf) |
332 | return -EINVAL; | 348 | return -EINVAL; |
333 | 349 | ||
350 | read_lock(&entry->rw_lock); | ||
334 | devpath = &entry->devpath; | 351 | devpath = &entry->devpath; |
352 | i = entry->ready; | ||
353 | read_unlock(&entry->rw_lock); | ||
335 | 354 | ||
336 | if (!entry->ready) | 355 | if (!i) /* entry is not ready */ |
337 | return -ENODATA; | 356 | return -ENODATA; |
338 | 357 | ||
339 | for (i = 0; devpath->layers[i] && (likely(i < 6)); i++) | 358 | for (i = 0; devpath->layers[i] && (likely(i < 6)); i++) |
@@ -388,15 +407,17 @@ pdcspath_layer_write(struct pdcspath_entry *entry, const char *buf, size_t count | |||
388 | } | 407 | } |
389 | 408 | ||
390 | /* So far so good, let's get in deep */ | 409 | /* So far so good, let's get in deep */ |
410 | write_lock(&entry->rw_lock); | ||
391 | 411 | ||
392 | /* First, overwrite the current layers with the new ones, not touching | 412 | /* First, overwrite the current layers with the new ones, not touching |
393 | the hardware path. */ | 413 | the hardware path. */ |
394 | memcpy(&entry->devpath.layers, &layers, sizeof(layers)); | 414 | memcpy(&entry->devpath.layers, &layers, sizeof(layers)); |
395 | 415 | ||
396 | /* Now, dive in. Write back to the hardware */ | 416 | /* Now, dive in. Write back to the hardware */ |
397 | WARN_ON(pdcspath_store(entry)); /* this warn should *NEVER* happen */ | 417 | pdcspath_store(entry); |
418 | write_unlock(&entry->rw_lock); | ||
398 | 419 | ||
399 | printk(KERN_INFO "PDC Stable Storage: changed \"%s\" layers to \"%s\"\n", | 420 | printk(KERN_INFO PDCS_PREFIX ": changed \"%s\" layers to \"%s\"\n", |
400 | entry->name, buf); | 421 | entry->name, buf); |
401 | 422 | ||
402 | return count; | 423 | return count; |
@@ -415,9 +436,6 @@ pdcspath_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) | |||
415 | struct pdcspath_attribute *pdcs_attr = to_pdcspath_attribute(attr); | 436 | struct pdcspath_attribute *pdcs_attr = to_pdcspath_attribute(attr); |
416 | ssize_t ret = 0; | 437 | ssize_t ret = 0; |
417 | 438 | ||
418 | if (!capable(CAP_SYS_ADMIN)) | ||
419 | return -EACCES; | ||
420 | |||
421 | if (pdcs_attr->show) | 439 | if (pdcs_attr->show) |
422 | ret = pdcs_attr->show(entry, buf); | 440 | ret = pdcs_attr->show(entry, buf); |
423 | 441 | ||
@@ -454,8 +472,8 @@ static struct sysfs_ops pdcspath_attr_ops = { | |||
454 | }; | 472 | }; |
455 | 473 | ||
456 | /* These are the two attributes of any PDC path. */ | 474 | /* These are the two attributes of any PDC path. */ |
457 | static PATHS_ATTR(hwpath, 0600, pdcspath_hwpath_read, pdcspath_hwpath_write); | 475 | static PATHS_ATTR(hwpath, 0644, pdcspath_hwpath_read, pdcspath_hwpath_write); |
458 | static PATHS_ATTR(layer, 0600, pdcspath_layer_read, pdcspath_layer_write); | 476 | static PATHS_ATTR(layer, 0644, pdcspath_layer_read, pdcspath_layer_write); |
459 | 477 | ||
460 | static struct attribute *paths_subsys_attrs[] = { | 478 | static struct attribute *paths_subsys_attrs[] = { |
461 | &paths_attr_hwpath.attr, | 479 | &paths_attr_hwpath.attr, |
@@ -484,36 +502,119 @@ static struct pdcspath_entry *pdcspath_entries[] = { | |||
484 | NULL, | 502 | NULL, |
485 | }; | 503 | }; |
486 | 504 | ||
505 | |||
506 | /* For more insight of what's going on here, refer to PDC Procedures doc, | ||
507 | * Section PDC_STABLE */ | ||
508 | |||
487 | /** | 509 | /** |
488 | * pdcs_info_read - Pretty printing of the remaining useful data. | 510 | * pdcs_size_read - Stable Storage size output. |
489 | * @entry: An allocated and populated subsytem struct. We don't use it tho. | 511 | * @entry: An allocated and populated subsytem struct. We don't use it tho. |
490 | * @buf: The output buffer to write to. | 512 | * @buf: The output buffer to write to. |
491 | * | ||
492 | * We will call this function to format the output of the 'info' attribute file. | ||
493 | * Please refer to PDC Procedures documentation, section PDC_STABLE to get a | ||
494 | * better insight of what we're doing here. | ||
495 | */ | 513 | */ |
496 | static ssize_t | 514 | static ssize_t |
497 | pdcs_info_read(struct subsystem *entry, char *buf) | 515 | pdcs_size_read(struct subsystem *entry, char *buf) |
498 | { | 516 | { |
499 | char *out = buf; | 517 | char *out = buf; |
500 | __u32 result; | ||
501 | struct device_path devpath; | ||
502 | char *tmpstr = NULL; | ||
503 | 518 | ||
504 | if (!entry || !buf) | 519 | if (!entry || !buf) |
505 | return -EINVAL; | 520 | return -EINVAL; |
506 | 521 | ||
507 | /* show the size of the stable storage */ | 522 | /* show the size of the stable storage */ |
508 | out += sprintf(out, "Stable Storage size: %ld bytes\n", pdcs_size); | 523 | out += sprintf(out, "%ld\n", pdcs_size); |
509 | 524 | ||
510 | /* deal with flags */ | 525 | return out - buf; |
511 | if (pdc_stable_read(PDCS_ADDR_PPRI, &devpath, sizeof(devpath)) != PDC_OK) | 526 | } |
512 | return -EIO; | 527 | |
528 | /** | ||
529 | * pdcs_auto_read - Stable Storage autoboot/search flag output. | ||
530 | * @entry: An allocated and populated subsytem struct. We don't use it tho. | ||
531 | * @buf: The output buffer to write to. | ||
532 | * @knob: The PF_AUTOBOOT or PF_AUTOSEARCH flag | ||
533 | */ | ||
534 | static ssize_t | ||
535 | pdcs_auto_read(struct subsystem *entry, char *buf, int knob) | ||
536 | { | ||
537 | char *out = buf; | ||
538 | struct pdcspath_entry *pathentry; | ||
513 | 539 | ||
514 | out += sprintf(out, "Autoboot: %s\n", (devpath.flags & PF_AUTOBOOT) ? "On" : "Off"); | 540 | if (!entry || !buf) |
515 | out += sprintf(out, "Autosearch: %s\n", (devpath.flags & PF_AUTOSEARCH) ? "On" : "Off"); | 541 | return -EINVAL; |
516 | out += sprintf(out, "Timer: %u s\n", (devpath.flags & PF_TIMER) ? (1 << (devpath.flags & PF_TIMER)) : 0); | 542 | |
543 | /* Current flags are stored in primary boot path entry */ | ||
544 | pathentry = &pdcspath_entry_primary; | ||
545 | |||
546 | read_lock(&pathentry->rw_lock); | ||
547 | out += sprintf(out, "%s\n", (pathentry->devpath.flags & knob) ? | ||
548 | "On" : "Off"); | ||
549 | read_unlock(&pathentry->rw_lock); | ||
550 | |||
551 | return out - buf; | ||
552 | } | ||
553 | |||
554 | /** | ||
555 | * pdcs_autoboot_read - Stable Storage autoboot flag output. | ||
556 | * @entry: An allocated and populated subsytem struct. We don't use it tho. | ||
557 | * @buf: The output buffer to write to. | ||
558 | */ | ||
559 | static inline ssize_t | ||
560 | pdcs_autoboot_read(struct subsystem *entry, char *buf) | ||
561 | { | ||
562 | return pdcs_auto_read(entry, buf, PF_AUTOBOOT); | ||
563 | } | ||
564 | |||
565 | /** | ||
566 | * pdcs_autosearch_read - Stable Storage autoboot flag output. | ||
567 | * @entry: An allocated and populated subsytem struct. We don't use it tho. | ||
568 | * @buf: The output buffer to write to. | ||
569 | */ | ||
570 | static inline ssize_t | ||
571 | pdcs_autosearch_read(struct subsystem *entry, char *buf) | ||
572 | { | ||
573 | return pdcs_auto_read(entry, buf, PF_AUTOSEARCH); | ||
574 | } | ||
575 | |||
576 | /** | ||
577 | * pdcs_timer_read - Stable Storage timer count output (in seconds). | ||
578 | * @entry: An allocated and populated subsytem struct. We don't use it tho. | ||
579 | * @buf: The output buffer to write to. | ||
580 | * | ||
581 | * The value of the timer field correponds to a number of seconds in powers of 2. | ||
582 | */ | ||
583 | static ssize_t | ||
584 | pdcs_timer_read(struct subsystem *entry, char *buf) | ||
585 | { | ||
586 | char *out = buf; | ||
587 | struct pdcspath_entry *pathentry; | ||
588 | |||
589 | if (!entry || !buf) | ||
590 | return -EINVAL; | ||
591 | |||
592 | /* Current flags are stored in primary boot path entry */ | ||
593 | pathentry = &pdcspath_entry_primary; | ||
594 | |||
595 | /* print the timer value in seconds */ | ||
596 | read_lock(&pathentry->rw_lock); | ||
597 | out += sprintf(out, "%u\n", (pathentry->devpath.flags & PF_TIMER) ? | ||
598 | (1 << (pathentry->devpath.flags & PF_TIMER)) : 0); | ||
599 | read_unlock(&pathentry->rw_lock); | ||
600 | |||
601 | return out - buf; | ||
602 | } | ||
603 | |||
604 | /** | ||
605 | * pdcs_osid_read - Stable Storage OS ID register output. | ||
606 | * @entry: An allocated and populated subsytem struct. We don't use it tho. | ||
607 | * @buf: The output buffer to write to. | ||
608 | */ | ||
609 | static ssize_t | ||
610 | pdcs_osid_read(struct subsystem *entry, char *buf) | ||
611 | { | ||
612 | char *out = buf; | ||
613 | __u32 result; | ||
614 | char *tmpstr = NULL; | ||
615 | |||
616 | if (!entry || !buf) | ||
617 | return -EINVAL; | ||
517 | 618 | ||
518 | /* get OSID */ | 619 | /* get OSID */ |
519 | if (pdc_stable_read(PDCS_ADDR_OSID, &result, sizeof(result)) != PDC_OK) | 620 | if (pdc_stable_read(PDCS_ADDR_OSID, &result, sizeof(result)) != PDC_OK) |
@@ -529,13 +630,31 @@ pdcs_info_read(struct subsystem *entry, char *buf) | |||
529 | case 0x0005: tmpstr = "Novell Netware dependent data"; break; | 630 | case 0x0005: tmpstr = "Novell Netware dependent data"; break; |
530 | default: tmpstr = "Unknown"; break; | 631 | default: tmpstr = "Unknown"; break; |
531 | } | 632 | } |
532 | out += sprintf(out, "OS ID: %s (0x%.4x)\n", tmpstr, (result >> 16)); | 633 | out += sprintf(out, "%s (0x%.4x)\n", tmpstr, (result >> 16)); |
634 | |||
635 | return out - buf; | ||
636 | } | ||
637 | |||
638 | /** | ||
639 | * pdcs_fastsize_read - Stable Storage FastSize register output. | ||
640 | * @entry: An allocated and populated subsytem struct. We don't use it tho. | ||
641 | * @buf: The output buffer to write to. | ||
642 | * | ||
643 | * This register holds the amount of system RAM to be tested during boot sequence. | ||
644 | */ | ||
645 | static ssize_t | ||
646 | pdcs_fastsize_read(struct subsystem *entry, char *buf) | ||
647 | { | ||
648 | char *out = buf; | ||
649 | __u32 result; | ||
650 | |||
651 | if (!entry || !buf) | ||
652 | return -EINVAL; | ||
533 | 653 | ||
534 | /* get fast-size */ | 654 | /* get fast-size */ |
535 | if (pdc_stable_read(PDCS_ADDR_FSIZ, &result, sizeof(result)) != PDC_OK) | 655 | if (pdc_stable_read(PDCS_ADDR_FSIZ, &result, sizeof(result)) != PDC_OK) |
536 | return -EIO; | 656 | return -EIO; |
537 | 657 | ||
538 | out += sprintf(out, "Memory tested: "); | ||
539 | if ((result & 0x0F) < 0x0E) | 658 | if ((result & 0x0F) < 0x0E) |
540 | out += sprintf(out, "%d kB", (1<<(result & 0x0F))*256); | 659 | out += sprintf(out, "%d kB", (1<<(result & 0x0F))*256); |
541 | else | 660 | else |
@@ -546,22 +665,18 @@ pdcs_info_read(struct subsystem *entry, char *buf) | |||
546 | } | 665 | } |
547 | 666 | ||
548 | /** | 667 | /** |
549 | * pdcs_info_write - This function handles boot flag modifying. | 668 | * pdcs_auto_write - This function handles autoboot/search flag modifying. |
550 | * @entry: An allocated and populated subsytem struct. We don't use it tho. | 669 | * @entry: An allocated and populated subsytem struct. We don't use it tho. |
551 | * @buf: The input buffer to read from. | 670 | * @buf: The input buffer to read from. |
552 | * @count: The number of bytes to be read. | 671 | * @count: The number of bytes to be read. |
672 | * @knob: The PF_AUTOBOOT or PF_AUTOSEARCH flag | ||
553 | * | 673 | * |
554 | * We will call this function to change the current boot flags. | 674 | * We will call this function to change the current autoboot flag. |
555 | * We expect a precise syntax: | 675 | * We expect a precise syntax: |
556 | * \"n n\" (n == 0 or 1) to toggle respectively AutoBoot and AutoSearch | 676 | * \"n\" (n == 0 or 1) to toggle AutoBoot Off or On |
557 | * | ||
558 | * As of now there is no incentive on my side to provide more "knobs" to that | ||
559 | * interface, since modifying the rest of the data is pretty meaningless when | ||
560 | * the machine is running and for the expected use of that facility, such as | ||
561 | * PALO setting up the boot disk when installing a Linux distribution... | ||
562 | */ | 677 | */ |
563 | static ssize_t | 678 | static ssize_t |
564 | pdcs_info_write(struct subsystem *entry, const char *buf, size_t count) | 679 | pdcs_auto_write(struct subsystem *entry, const char *buf, size_t count, int knob) |
565 | { | 680 | { |
566 | struct pdcspath_entry *pathentry; | 681 | struct pdcspath_entry *pathentry; |
567 | unsigned char flags; | 682 | unsigned char flags; |
@@ -582,7 +697,9 @@ pdcs_info_write(struct subsystem *entry, const char *buf, size_t count) | |||
582 | pathentry = &pdcspath_entry_primary; | 697 | pathentry = &pdcspath_entry_primary; |
583 | 698 | ||
584 | /* Be nice to the existing flag record */ | 699 | /* Be nice to the existing flag record */ |
700 | read_lock(&pathentry->rw_lock); | ||
585 | flags = pathentry->devpath.flags; | 701 | flags = pathentry->devpath.flags; |
702 | read_unlock(&pathentry->rw_lock); | ||
586 | 703 | ||
587 | DPRINTK("%s: flags before: 0x%X\n", __func__, flags); | 704 | DPRINTK("%s: flags before: 0x%X\n", __func__, flags); |
588 | 705 | ||
@@ -595,50 +712,85 @@ pdcs_info_write(struct subsystem *entry, const char *buf, size_t count) | |||
595 | if ((c != 0) && (c != 1)) | 712 | if ((c != 0) && (c != 1)) |
596 | goto parse_error; | 713 | goto parse_error; |
597 | if (c == 0) | 714 | if (c == 0) |
598 | flags &= ~PF_AUTOBOOT; | 715 | flags &= ~knob; |
599 | else | 716 | else |
600 | flags |= PF_AUTOBOOT; | 717 | flags |= knob; |
601 | |||
602 | if (*temp++ != ' ') | ||
603 | goto parse_error; | ||
604 | |||
605 | c = *temp++ - '0'; | ||
606 | if ((c != 0) && (c != 1)) | ||
607 | goto parse_error; | ||
608 | if (c == 0) | ||
609 | flags &= ~PF_AUTOSEARCH; | ||
610 | else | ||
611 | flags |= PF_AUTOSEARCH; | ||
612 | 718 | ||
613 | DPRINTK("%s: flags after: 0x%X\n", __func__, flags); | 719 | DPRINTK("%s: flags after: 0x%X\n", __func__, flags); |
614 | 720 | ||
615 | /* So far so good, let's get in deep */ | 721 | /* So far so good, let's get in deep */ |
722 | write_lock(&pathentry->rw_lock); | ||
616 | 723 | ||
617 | /* Change the path entry flags first */ | 724 | /* Change the path entry flags first */ |
618 | pathentry->devpath.flags = flags; | 725 | pathentry->devpath.flags = flags; |
619 | 726 | ||
620 | /* Now, dive in. Write back to the hardware */ | 727 | /* Now, dive in. Write back to the hardware */ |
621 | WARN_ON(pdcspath_store(pathentry)); /* this warn should *NEVER* happen */ | 728 | pdcspath_store(pathentry); |
729 | write_unlock(&pathentry->rw_lock); | ||
622 | 730 | ||
623 | printk(KERN_INFO "PDC Stable Storage: changed flags to \"%s\"\n", buf); | 731 | printk(KERN_INFO PDCS_PREFIX ": changed \"%s\" to \"%s\"\n", |
732 | (knob & PF_AUTOBOOT) ? "autoboot" : "autosearch", | ||
733 | (flags & knob) ? "On" : "Off"); | ||
624 | 734 | ||
625 | return count; | 735 | return count; |
626 | 736 | ||
627 | parse_error: | 737 | parse_error: |
628 | printk(KERN_WARNING "%s: Parse error: expect \"n n\" (n == 0 or 1) for AB and AS\n", __func__); | 738 | printk(KERN_WARNING "%s: Parse error: expect \"n\" (n == 0 or 1)\n", __func__); |
629 | return -EINVAL; | 739 | return -EINVAL; |
630 | } | 740 | } |
631 | 741 | ||
632 | /* The last attribute (the 'root' one actually) with all remaining data. */ | 742 | /** |
633 | static PDCS_ATTR(info, 0600, pdcs_info_read, pdcs_info_write); | 743 | * pdcs_autoboot_write - This function handles autoboot flag modifying. |
744 | * @entry: An allocated and populated subsytem struct. We don't use it tho. | ||
745 | * @buf: The input buffer to read from. | ||
746 | * @count: The number of bytes to be read. | ||
747 | * | ||
748 | * We will call this function to change the current boot flags. | ||
749 | * We expect a precise syntax: | ||
750 | * \"n\" (n == 0 or 1) to toggle AutoSearch Off or On | ||
751 | */ | ||
752 | static inline ssize_t | ||
753 | pdcs_autoboot_write(struct subsystem *entry, const char *buf, size_t count) | ||
754 | { | ||
755 | return pdcs_auto_write(entry, buf, count, PF_AUTOBOOT); | ||
756 | } | ||
757 | |||
758 | /** | ||
759 | * pdcs_autosearch_write - This function handles autosearch flag modifying. | ||
760 | * @entry: An allocated and populated subsytem struct. We don't use it tho. | ||
761 | * @buf: The input buffer to read from. | ||
762 | * @count: The number of bytes to be read. | ||
763 | * | ||
764 | * We will call this function to change the current boot flags. | ||
765 | * We expect a precise syntax: | ||
766 | * \"n\" (n == 0 or 1) to toggle AutoSearch Off or On | ||
767 | */ | ||
768 | static inline ssize_t | ||
769 | pdcs_autosearch_write(struct subsystem *entry, const char *buf, size_t count) | ||
770 | { | ||
771 | return pdcs_auto_write(entry, buf, count, PF_AUTOSEARCH); | ||
772 | } | ||
773 | |||
774 | /* The remaining attributes. */ | ||
775 | static PDCS_ATTR(size, 0444, pdcs_size_read, NULL); | ||
776 | static PDCS_ATTR(autoboot, 0644, pdcs_autoboot_read, pdcs_autoboot_write); | ||
777 | static PDCS_ATTR(autosearch, 0644, pdcs_autosearch_read, pdcs_autosearch_write); | ||
778 | static PDCS_ATTR(timer, 0444, pdcs_timer_read, NULL); | ||
779 | static PDCS_ATTR(osid, 0400, pdcs_osid_read, NULL); | ||
780 | static PDCS_ATTR(fastsize, 0400, pdcs_fastsize_read, NULL); | ||
634 | 781 | ||
635 | static struct subsys_attribute *pdcs_subsys_attrs[] = { | 782 | static struct subsys_attribute *pdcs_subsys_attrs[] = { |
636 | &pdcs_attr_info, | 783 | &pdcs_attr_size, |
637 | NULL, /* maybe more in the future? */ | 784 | &pdcs_attr_autoboot, |
785 | &pdcs_attr_autosearch, | ||
786 | &pdcs_attr_timer, | ||
787 | &pdcs_attr_osid, | ||
788 | &pdcs_attr_fastsize, | ||
789 | NULL, | ||
638 | }; | 790 | }; |
639 | 791 | ||
640 | static decl_subsys(paths, &ktype_pdcspath, NULL); | 792 | static decl_subsys(paths, &ktype_pdcspath, NULL); |
641 | static decl_subsys(pdc, NULL, NULL); | 793 | static decl_subsys(stable, NULL, NULL); |
642 | 794 | ||
643 | /** | 795 | /** |
644 | * pdcs_register_pathentries - Prepares path entries kobjects for sysfs usage. | 796 | * pdcs_register_pathentries - Prepares path entries kobjects for sysfs usage. |
@@ -656,8 +808,16 @@ pdcs_register_pathentries(void) | |||
656 | struct pdcspath_entry *entry; | 808 | struct pdcspath_entry *entry; |
657 | int err; | 809 | int err; |
658 | 810 | ||
811 | /* Initialize the entries rw_lock before anything else */ | ||
812 | for (i = 0; (entry = pdcspath_entries[i]); i++) | ||
813 | rwlock_init(&entry->rw_lock); | ||
814 | |||
659 | for (i = 0; (entry = pdcspath_entries[i]); i++) { | 815 | for (i = 0; (entry = pdcspath_entries[i]); i++) { |
660 | if (pdcspath_fetch(entry) < 0) | 816 | write_lock(&entry->rw_lock); |
817 | err = pdcspath_fetch(entry); | ||
818 | write_unlock(&entry->rw_lock); | ||
819 | |||
820 | if (err < 0) | ||
661 | continue; | 821 | continue; |
662 | 822 | ||
663 | if ((err = kobject_set_name(&entry->kobj, "%s", entry->name))) | 823 | if ((err = kobject_set_name(&entry->kobj, "%s", entry->name))) |
@@ -667,13 +827,14 @@ pdcs_register_pathentries(void) | |||
667 | return err; | 827 | return err; |
668 | 828 | ||
669 | /* kobject is now registered */ | 829 | /* kobject is now registered */ |
830 | write_lock(&entry->rw_lock); | ||
670 | entry->ready = 2; | 831 | entry->ready = 2; |
671 | 832 | ||
672 | if (!entry->dev) | ||
673 | continue; | ||
674 | |||
675 | /* Add a nice symlink to the real device */ | 833 | /* Add a nice symlink to the real device */ |
676 | sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device"); | 834 | if (entry->dev) |
835 | sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device"); | ||
836 | |||
837 | write_unlock(&entry->rw_lock); | ||
677 | } | 838 | } |
678 | 839 | ||
679 | return 0; | 840 | return 0; |
@@ -688,14 +849,17 @@ pdcs_unregister_pathentries(void) | |||
688 | unsigned short i; | 849 | unsigned short i; |
689 | struct pdcspath_entry *entry; | 850 | struct pdcspath_entry *entry; |
690 | 851 | ||
691 | for (i = 0; (entry = pdcspath_entries[i]); i++) | 852 | for (i = 0; (entry = pdcspath_entries[i]); i++) { |
853 | read_lock(&entry->rw_lock); | ||
692 | if (entry->ready >= 2) | 854 | if (entry->ready >= 2) |
693 | kobject_unregister(&entry->kobj); | 855 | kobject_unregister(&entry->kobj); |
856 | read_unlock(&entry->rw_lock); | ||
857 | } | ||
694 | } | 858 | } |
695 | 859 | ||
696 | /* | 860 | /* |
697 | * For now we register the pdc subsystem with the firmware subsystem | 861 | * For now we register the stable subsystem with the firmware subsystem |
698 | * and the paths subsystem with the pdc subsystem | 862 | * and the paths subsystem with the stable subsystem |
699 | */ | 863 | */ |
700 | static int __init | 864 | static int __init |
701 | pdc_stable_init(void) | 865 | pdc_stable_init(void) |
@@ -707,19 +871,23 @@ pdc_stable_init(void) | |||
707 | if (pdc_stable_get_size(&pdcs_size) != PDC_OK) | 871 | if (pdc_stable_get_size(&pdcs_size) != PDC_OK) |
708 | return -ENODEV; | 872 | return -ENODEV; |
709 | 873 | ||
710 | printk(KERN_INFO "PDC Stable Storage facility v%s\n", PDCS_VERSION); | 874 | /* make sure we have enough data */ |
875 | if (pdcs_size < 96) | ||
876 | return -ENODATA; | ||
877 | |||
878 | printk(KERN_INFO PDCS_PREFIX " facility v%s\n", PDCS_VERSION); | ||
711 | 879 | ||
712 | /* For now we'll register the pdc subsys within this driver */ | 880 | /* For now we'll register the stable subsys within this driver */ |
713 | if ((rc = firmware_register(&pdc_subsys))) | 881 | if ((rc = firmware_register(&stable_subsys))) |
714 | goto fail_firmreg; | 882 | goto fail_firmreg; |
715 | 883 | ||
716 | /* Don't forget the info entry */ | 884 | /* Don't forget the root entries */ |
717 | for (i = 0; (attr = pdcs_subsys_attrs[i]) && !error; i++) | 885 | for (i = 0; (attr = pdcs_subsys_attrs[i]) && !error; i++) |
718 | if (attr->show) | 886 | if (attr->show) |
719 | error = subsys_create_file(&pdc_subsys, attr); | 887 | error = subsys_create_file(&stable_subsys, attr); |
720 | 888 | ||
721 | /* register the paths subsys as a subsystem of pdc subsys */ | 889 | /* register the paths subsys as a subsystem of stable subsys */ |
722 | kset_set_kset_s(&paths_subsys, pdc_subsys); | 890 | kset_set_kset_s(&paths_subsys, stable_subsys); |
723 | if ((rc= subsystem_register(&paths_subsys))) | 891 | if ((rc= subsystem_register(&paths_subsys))) |
724 | goto fail_subsysreg; | 892 | goto fail_subsysreg; |
725 | 893 | ||
@@ -734,10 +902,10 @@ fail_pdcsreg: | |||
734 | subsystem_unregister(&paths_subsys); | 902 | subsystem_unregister(&paths_subsys); |
735 | 903 | ||
736 | fail_subsysreg: | 904 | fail_subsysreg: |
737 | firmware_unregister(&pdc_subsys); | 905 | firmware_unregister(&stable_subsys); |
738 | 906 | ||
739 | fail_firmreg: | 907 | fail_firmreg: |
740 | printk(KERN_INFO "PDC Stable Storage bailing out\n"); | 908 | printk(KERN_INFO PDCS_PREFIX " bailing out\n"); |
741 | return rc; | 909 | return rc; |
742 | } | 910 | } |
743 | 911 | ||
@@ -747,7 +915,7 @@ pdc_stable_exit(void) | |||
747 | pdcs_unregister_pathentries(); | 915 | pdcs_unregister_pathentries(); |
748 | subsystem_unregister(&paths_subsys); | 916 | subsystem_unregister(&paths_subsys); |
749 | 917 | ||
750 | firmware_unregister(&pdc_subsys); | 918 | firmware_unregister(&stable_subsys); |
751 | } | 919 | } |
752 | 920 | ||
753 | 921 | ||
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index c85653f315aa..52f265e97729 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c | |||
@@ -2064,14 +2064,13 @@ sba_driver_callback(struct parisc_device *dev) | |||
2064 | printk(KERN_INFO "%s found %s at 0x%lx\n", | 2064 | printk(KERN_INFO "%s found %s at 0x%lx\n", |
2065 | MODULE_NAME, version, dev->hpa.start); | 2065 | MODULE_NAME, version, dev->hpa.start); |
2066 | 2066 | ||
2067 | sba_dev = kmalloc(sizeof(struct sba_device), GFP_KERNEL); | 2067 | sba_dev = kzalloc(sizeof(struct sba_device), GFP_KERNEL); |
2068 | if (!sba_dev) { | 2068 | if (!sba_dev) { |
2069 | printk(KERN_ERR MODULE_NAME " - couldn't alloc sba_device\n"); | 2069 | printk(KERN_ERR MODULE_NAME " - couldn't alloc sba_device\n"); |
2070 | return -ENOMEM; | 2070 | return -ENOMEM; |
2071 | } | 2071 | } |
2072 | 2072 | ||
2073 | parisc_set_drvdata(dev, sba_dev); | 2073 | parisc_set_drvdata(dev, sba_dev); |
2074 | memset(sba_dev, 0, sizeof(struct sba_device)); | ||
2075 | 2074 | ||
2076 | for(i=0; i<MAX_IOC; i++) | 2075 | for(i=0; i<MAX_IOC; i++) |
2077 | spin_lock_init(&(sba_dev->ioc[i].res_lock)); | 2076 | spin_lock_init(&(sba_dev->ioc[i].res_lock)); |
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c index d14888e149bb..ba971fecd0d8 100644 --- a/drivers/parisc/superio.c +++ b/drivers/parisc/superio.c | |||
@@ -89,6 +89,9 @@ static struct superio_device sio_dev; | |||
89 | #define DBG_INIT(x...) | 89 | #define DBG_INIT(x...) |
90 | #endif | 90 | #endif |
91 | 91 | ||
92 | #define SUPERIO "SuperIO" | ||
93 | #define PFX SUPERIO ": " | ||
94 | |||
92 | static irqreturn_t | 95 | static irqreturn_t |
93 | superio_interrupt(int parent_irq, void *devp, struct pt_regs *regs) | 96 | superio_interrupt(int parent_irq, void *devp, struct pt_regs *regs) |
94 | { | 97 | { |
@@ -117,7 +120,7 @@ superio_interrupt(int parent_irq, void *devp, struct pt_regs *regs) | |||
117 | local_irq = results & 0x0f; | 120 | local_irq = results & 0x0f; |
118 | 121 | ||
119 | if (local_irq == 2 || local_irq > 7) { | 122 | if (local_irq == 2 || local_irq > 7) { |
120 | printk(KERN_ERR "SuperIO: slave interrupted!\n"); | 123 | printk(KERN_ERR PFX "slave interrupted!\n"); |
121 | return IRQ_HANDLED; | 124 | return IRQ_HANDLED; |
122 | } | 125 | } |
123 | 126 | ||
@@ -128,7 +131,7 @@ superio_interrupt(int parent_irq, void *devp, struct pt_regs *regs) | |||
128 | outb(OCW3_ISR,IC_PIC1+0); | 131 | outb(OCW3_ISR,IC_PIC1+0); |
129 | results = inb(IC_PIC1+0); | 132 | results = inb(IC_PIC1+0); |
130 | if ((results & 0x80) == 0) { /* if ISR7 not set: spurious */ | 133 | if ((results & 0x80) == 0) { /* if ISR7 not set: spurious */ |
131 | printk(KERN_WARNING "SuperIO: spurious interrupt!\n"); | 134 | printk(KERN_WARNING PFX "spurious interrupt!\n"); |
132 | return IRQ_HANDLED; | 135 | return IRQ_HANDLED; |
133 | } | 136 | } |
134 | } | 137 | } |
@@ -163,27 +166,27 @@ superio_init(struct pci_dev *pcidev) | |||
163 | /* ...then properly fixup the USB to point at suckyio PIC */ | 166 | /* ...then properly fixup the USB to point at suckyio PIC */ |
164 | sio->usb_pdev->irq = superio_fixup_irq(sio->usb_pdev); | 167 | sio->usb_pdev->irq = superio_fixup_irq(sio->usb_pdev); |
165 | 168 | ||
166 | printk(KERN_INFO "SuperIO: Found NS87560 Legacy I/O device at %s (IRQ %i) \n", | 169 | printk(KERN_INFO PFX "Found NS87560 Legacy I/O device at %s (IRQ %i) \n", |
167 | pci_name(pdev), pdev->irq); | 170 | pci_name(pdev), pdev->irq); |
168 | 171 | ||
169 | pci_read_config_dword (pdev, SIO_SP1BAR, &sio->sp1_base); | 172 | pci_read_config_dword (pdev, SIO_SP1BAR, &sio->sp1_base); |
170 | sio->sp1_base &= ~1; | 173 | sio->sp1_base &= ~1; |
171 | printk (KERN_INFO "SuperIO: Serial port 1 at 0x%x\n", sio->sp1_base); | 174 | printk(KERN_INFO PFX "Serial port 1 at 0x%x\n", sio->sp1_base); |
172 | 175 | ||
173 | pci_read_config_dword (pdev, SIO_SP2BAR, &sio->sp2_base); | 176 | pci_read_config_dword (pdev, SIO_SP2BAR, &sio->sp2_base); |
174 | sio->sp2_base &= ~1; | 177 | sio->sp2_base &= ~1; |
175 | printk (KERN_INFO "SuperIO: Serial port 2 at 0x%x\n", sio->sp2_base); | 178 | printk(KERN_INFO PFX "Serial port 2 at 0x%x\n", sio->sp2_base); |
176 | 179 | ||
177 | pci_read_config_dword (pdev, SIO_PPBAR, &sio->pp_base); | 180 | pci_read_config_dword (pdev, SIO_PPBAR, &sio->pp_base); |
178 | sio->pp_base &= ~1; | 181 | sio->pp_base &= ~1; |
179 | printk (KERN_INFO "SuperIO: Parallel port at 0x%x\n", sio->pp_base); | 182 | printk(KERN_INFO PFX "Parallel port at 0x%x\n", sio->pp_base); |
180 | 183 | ||
181 | pci_read_config_dword (pdev, SIO_FDCBAR, &sio->fdc_base); | 184 | pci_read_config_dword (pdev, SIO_FDCBAR, &sio->fdc_base); |
182 | sio->fdc_base &= ~1; | 185 | sio->fdc_base &= ~1; |
183 | printk (KERN_INFO "SuperIO: Floppy controller at 0x%x\n", sio->fdc_base); | 186 | printk(KERN_INFO PFX "Floppy controller at 0x%x\n", sio->fdc_base); |
184 | pci_read_config_dword (pdev, SIO_ACPIBAR, &sio->acpi_base); | 187 | pci_read_config_dword (pdev, SIO_ACPIBAR, &sio->acpi_base); |
185 | sio->acpi_base &= ~1; | 188 | sio->acpi_base &= ~1; |
186 | printk (KERN_INFO "SuperIO: ACPI at 0x%x\n", sio->acpi_base); | 189 | printk(KERN_INFO PFX "ACPI at 0x%x\n", sio->acpi_base); |
187 | 190 | ||
188 | request_region (IC_PIC1, 0x1f, "pic1"); | 191 | request_region (IC_PIC1, 0x1f, "pic1"); |
189 | request_region (IC_PIC2, 0x1f, "pic2"); | 192 | request_region (IC_PIC2, 0x1f, "pic2"); |
@@ -263,14 +266,14 @@ superio_init(struct pci_dev *pcidev) | |||
263 | /* Setup USB power regulation */ | 266 | /* Setup USB power regulation */ |
264 | outb(1, sio->acpi_base + USB_REG_CR); | 267 | outb(1, sio->acpi_base + USB_REG_CR); |
265 | if (inb(sio->acpi_base + USB_REG_CR) & 1) | 268 | if (inb(sio->acpi_base + USB_REG_CR) & 1) |
266 | printk(KERN_INFO "SuperIO: USB regulator enabled\n"); | 269 | printk(KERN_INFO PFX "USB regulator enabled\n"); |
267 | else | 270 | else |
268 | printk(KERN_ERR "USB regulator not initialized!\n"); | 271 | printk(KERN_ERR PFX "USB regulator not initialized!\n"); |
269 | 272 | ||
270 | if (request_irq(pdev->irq, superio_interrupt, SA_INTERRUPT, | 273 | if (request_irq(pdev->irq, superio_interrupt, SA_INTERRUPT, |
271 | "SuperIO", (void *)sio)) { | 274 | SUPERIO, (void *)sio)) { |
272 | 275 | ||
273 | printk(KERN_ERR "SuperIO: could not get irq\n"); | 276 | printk(KERN_ERR PFX "could not get irq\n"); |
274 | BUG(); | 277 | BUG(); |
275 | return; | 278 | return; |
276 | } | 279 | } |
@@ -284,7 +287,7 @@ static void superio_disable_irq(unsigned int irq) | |||
284 | u8 r8; | 287 | u8 r8; |
285 | 288 | ||
286 | if ((irq < 1) || (irq == 2) || (irq > 7)) { | 289 | if ((irq < 1) || (irq == 2) || (irq > 7)) { |
287 | printk(KERN_ERR "SuperIO: Illegal irq number.\n"); | 290 | printk(KERN_ERR PFX "Illegal irq number.\n"); |
288 | BUG(); | 291 | BUG(); |
289 | return; | 292 | return; |
290 | } | 293 | } |
@@ -301,7 +304,7 @@ static void superio_enable_irq(unsigned int irq) | |||
301 | u8 r8; | 304 | u8 r8; |
302 | 305 | ||
303 | if ((irq < 1) || (irq == 2) || (irq > 7)) { | 306 | if ((irq < 1) || (irq == 2) || (irq > 7)) { |
304 | printk(KERN_ERR "SuperIO: Illegal irq number (%d).\n", irq); | 307 | printk(KERN_ERR PFX "Illegal irq number (%d).\n", irq); |
305 | BUG(); | 308 | BUG(); |
306 | return; | 309 | return; |
307 | } | 310 | } |
@@ -319,7 +322,7 @@ static unsigned int superio_startup_irq(unsigned int irq) | |||
319 | } | 322 | } |
320 | 323 | ||
321 | static struct hw_interrupt_type superio_interrupt_type = { | 324 | static struct hw_interrupt_type superio_interrupt_type = { |
322 | .typename = "SuperIO", | 325 | .typename = SUPERIO, |
323 | .startup = superio_startup_irq, | 326 | .startup = superio_startup_irq, |
324 | .shutdown = superio_disable_irq, | 327 | .shutdown = superio_disable_irq, |
325 | .enable = superio_enable_irq, | 328 | .enable = superio_enable_irq, |
@@ -413,7 +416,7 @@ static void __devinit superio_serial_init(void) | |||
413 | 416 | ||
414 | retval = early_serial_setup(&serial[0]); | 417 | retval = early_serial_setup(&serial[0]); |
415 | if (retval < 0) { | 418 | if (retval < 0) { |
416 | printk(KERN_WARNING "SuperIO: Register Serial #0 failed.\n"); | 419 | printk(KERN_WARNING PFX "Register Serial #0 failed.\n"); |
417 | return; | 420 | return; |
418 | } | 421 | } |
419 | 422 | ||
@@ -423,7 +426,7 @@ static void __devinit superio_serial_init(void) | |||
423 | retval = early_serial_setup(&serial[1]); | 426 | retval = early_serial_setup(&serial[1]); |
424 | 427 | ||
425 | if (retval < 0) | 428 | if (retval < 0) |
426 | printk(KERN_WARNING "SuperIO: Register Serial #1 failed.\n"); | 429 | printk(KERN_WARNING PFX "Register Serial #1 failed.\n"); |
427 | #endif /* CONFIG_SERIAL_8250 */ | 430 | #endif /* CONFIG_SERIAL_8250 */ |
428 | } | 431 | } |
429 | 432 | ||
@@ -437,7 +440,7 @@ static void __devinit superio_parport_init(void) | |||
437 | PARPORT_DMA_NONE /* dma */, | 440 | PARPORT_DMA_NONE /* dma */, |
438 | NULL /*struct pci_dev* */) ) | 441 | NULL /*struct pci_dev* */) ) |
439 | 442 | ||
440 | printk(KERN_WARNING "SuperIO: Probing parallel port failed.\n"); | 443 | printk(KERN_WARNING PFX "Probing parallel port failed.\n"); |
441 | #endif /* CONFIG_PARPORT_PC */ | 444 | #endif /* CONFIG_PARPORT_PC */ |
442 | } | 445 | } |
443 | 446 | ||
@@ -499,7 +502,7 @@ static struct pci_device_id superio_tbl[] = { | |||
499 | }; | 502 | }; |
500 | 503 | ||
501 | static struct pci_driver superio_driver = { | 504 | static struct pci_driver superio_driver = { |
502 | .name = "SuperIO", | 505 | .name = SUPERIO, |
503 | .id_table = superio_tbl, | 506 | .id_table = superio_tbl, |
504 | .probe = superio_probe, | 507 | .probe = superio_probe, |
505 | }; | 508 | }; |
diff --git a/drivers/parisc/wax.c b/drivers/parisc/wax.c index 17dce2adf7fe..813c2c24ab1e 100644 --- a/drivers/parisc/wax.c +++ b/drivers/parisc/wax.c | |||
@@ -76,7 +76,7 @@ wax_init_chip(struct parisc_device *dev) | |||
76 | struct gsc_irq gsc_irq; | 76 | struct gsc_irq gsc_irq; |
77 | int ret; | 77 | int ret; |
78 | 78 | ||
79 | wax = kmalloc(sizeof(*wax), GFP_KERNEL); | 79 | wax = kzalloc(sizeof(*wax), GFP_KERNEL); |
80 | if (!wax) | 80 | if (!wax) |
81 | return -ENOMEM; | 81 | return -ENOMEM; |
82 | 82 | ||
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig index f605dea57224..f63c387976cf 100644 --- a/drivers/parport/Kconfig +++ b/drivers/parport/Kconfig | |||
@@ -90,6 +90,15 @@ config PARPORT_ARC | |||
90 | depends on ARM && PARPORT | 90 | depends on ARM && PARPORT |
91 | select PARPORT_NOT_PC | 91 | select PARPORT_NOT_PC |
92 | 92 | ||
93 | config PARPORT_IP32 | ||
94 | tristate "SGI IP32 builtin port (EXPERIMENTAL)" | ||
95 | depends on SGI_IP32 && PARPORT && EXPERIMENTAL | ||
96 | select PARPORT_NOT_PC | ||
97 | help | ||
98 | Say Y here if you need support for the parallel port on | ||
99 | SGI O2 machines. This code is also available as a module (say M), | ||
100 | called parport_ip32. If in doubt, saying N is the safe plan. | ||
101 | |||
93 | config PARPORT_AMIGA | 102 | config PARPORT_AMIGA |
94 | tristate "Amiga builtin port" | 103 | tristate "Amiga builtin port" |
95 | depends on AMIGA && PARPORT | 104 | depends on AMIGA && PARPORT |
diff --git a/drivers/parport/Makefile b/drivers/parport/Makefile index 5372212bb9d9..a19de35f8de2 100644 --- a/drivers/parport/Makefile +++ b/drivers/parport/Makefile | |||
@@ -17,3 +17,4 @@ obj-$(CONFIG_PARPORT_MFC3) += parport_mfc3.o | |||
17 | obj-$(CONFIG_PARPORT_ATARI) += parport_atari.o | 17 | obj-$(CONFIG_PARPORT_ATARI) += parport_atari.o |
18 | obj-$(CONFIG_PARPORT_SUNBPP) += parport_sunbpp.o | 18 | obj-$(CONFIG_PARPORT_SUNBPP) += parport_sunbpp.o |
19 | obj-$(CONFIG_PARPORT_GSC) += parport_gsc.o | 19 | obj-$(CONFIG_PARPORT_GSC) += parport_gsc.o |
20 | obj-$(CONFIG_PARPORT_IP32) += parport_ip32.o | ||
diff --git a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c index 5b887ba5aaf9..690b239ad3a7 100644 --- a/drivers/parport/ieee1284.c +++ b/drivers/parport/ieee1284.c | |||
@@ -61,10 +61,10 @@ static void timeout_waiting_on_port (unsigned long cookie) | |||
61 | * set to zero, it returns immediately. | 61 | * set to zero, it returns immediately. |
62 | * | 62 | * |
63 | * If an interrupt occurs before the timeout period elapses, this | 63 | * If an interrupt occurs before the timeout period elapses, this |
64 | * function returns one immediately. If it times out, it returns | 64 | * function returns zero immediately. If it times out, it returns |
65 | * a value greater than zero. An error code less than zero | 65 | * one. An error code less than zero indicates an error (most |
66 | * indicates an error (most likely a pending signal), and the | 66 | * likely a pending signal), and the calling code should finish |
67 | * calling code should finish what it's doing as soon as it can. | 67 | * what it's doing as soon as it can. |
68 | */ | 68 | */ |
69 | 69 | ||
70 | int parport_wait_event (struct parport *port, signed long timeout) | 70 | int parport_wait_event (struct parport *port, signed long timeout) |
@@ -110,7 +110,7 @@ int parport_wait_event (struct parport *port, signed long timeout) | |||
110 | * | 110 | * |
111 | * If the status lines take on the desired values before the | 111 | * If the status lines take on the desired values before the |
112 | * timeout period elapses, parport_poll_peripheral() returns zero | 112 | * timeout period elapses, parport_poll_peripheral() returns zero |
113 | * immediately. A zero return value greater than zero indicates | 113 | * immediately. A return value greater than zero indicates |
114 | * a timeout. An error code (less than zero) indicates an error, | 114 | * a timeout. An error code (less than zero) indicates an error, |
115 | * most likely a signal that arrived, and the caller should | 115 | * most likely a signal that arrived, and the caller should |
116 | * finish what it is doing as soon as possible. | 116 | * finish what it is doing as soon as possible. |
diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c index fde29a75f888..1de52d9febf9 100644 --- a/drivers/parport/parport_gsc.c +++ b/drivers/parport/parport_gsc.c | |||
@@ -249,7 +249,7 @@ struct parport *__devinit parport_gsc_probe_port (unsigned long base, | |||
249 | struct parport tmp; | 249 | struct parport tmp; |
250 | struct parport *p = &tmp; | 250 | struct parport *p = &tmp; |
251 | 251 | ||
252 | priv = kmalloc (sizeof (struct parport_gsc_private), GFP_KERNEL); | 252 | priv = kzalloc (sizeof (struct parport_gsc_private), GFP_KERNEL); |
253 | if (!priv) { | 253 | if (!priv) { |
254 | printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base); | 254 | printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base); |
255 | return NULL; | 255 | return NULL; |
diff --git a/drivers/parport/parport_ip32.c b/drivers/parport/parport_ip32.c new file mode 100644 index 000000000000..46e06e596d73 --- /dev/null +++ b/drivers/parport/parport_ip32.c | |||
@@ -0,0 +1,2253 @@ | |||
1 | /* Low-level parallel port routines for built-in port on SGI IP32 | ||
2 | * | ||
3 | * Author: Arnaud Giersch <arnaud.giersch@free.fr> | ||
4 | * | ||
5 | * Based on parport_pc.c by | ||
6 | * Phil Blundell, Tim Waugh, Jose Renau, David Campbell, | ||
7 | * Andrea Arcangeli, et al. | ||
8 | * | ||
9 | * Thanks to Ilya A. Volynets-Evenbakh for his help. | ||
10 | * | ||
11 | * Copyright (C) 2005, 2006 Arnaud Giersch. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify it | ||
14 | * under the terms of the GNU General Public License as published by the Free | ||
15 | * Software Foundation; either version 2 of the License, or (at your option) | ||
16 | * any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
19 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
20 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
21 | * more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License along | ||
24 | * with this program; if not, write to the Free Software Foundation, Inc., 59 | ||
25 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
26 | */ | ||
27 | |||
28 | /* Current status: | ||
29 | * | ||
30 | * Basic SPP and PS2 modes are supported. | ||
31 | * Support for parallel port IRQ is present. | ||
32 | * Hardware SPP (a.k.a. compatibility), EPP, and ECP modes are | ||
33 | * supported. | ||
34 | * SPP/ECP FIFO can be driven in PIO or DMA mode. PIO mode can work with | ||
35 | * or without interrupt support. | ||
36 | * | ||
37 | * Hardware ECP mode is not fully implemented (ecp_read_data and | ||
38 | * ecp_write_addr are actually missing). | ||
39 | * | ||
40 | * To do: | ||
41 | * | ||
42 | * Fully implement ECP mode. | ||
43 | * EPP and ECP mode need to be tested. I currently do not own any | ||
44 | * peripheral supporting these extended mode, and cannot test them. | ||
45 | * If DMA mode works well, decide if support for PIO FIFO modes should be | ||
46 | * dropped. | ||
47 | * Use the io{read,write} family functions when they become available in | ||
48 | * the linux-mips.org tree. Note: the MIPS specific functions readsb() | ||
49 | * and writesb() are to be translated by ioread8_rep() and iowrite8_rep() | ||
50 | * respectively. | ||
51 | */ | ||
52 | |||
53 | /* The built-in parallel port on the SGI 02 workstation (a.k.a. IP32) is an | ||
54 | * IEEE 1284 parallel port driven by a Texas Instrument TL16PIR552PH chip[1]. | ||
55 | * This chip supports SPP, bidirectional, EPP and ECP modes. It has a 16 byte | ||
56 | * FIFO buffer and supports DMA transfers. | ||
57 | * | ||
58 | * [1] http://focus.ti.com/docs/prod/folders/print/tl16pir552.html | ||
59 | * | ||
60 | * Theoretically, we could simply use the parport_pc module. It is however | ||
61 | * not so simple. The parport_pc code assumes that the parallel port | ||
62 | * registers are port-mapped. On the O2, they are memory-mapped. | ||
63 | * Furthermore, each register is replicated on 256 consecutive addresses (as | ||
64 | * it is for the built-in serial ports on the same chip). | ||
65 | */ | ||
66 | |||
67 | /*--- Some configuration defines ---------------------------------------*/ | ||
68 | |||
69 | /* DEBUG_PARPORT_IP32 | ||
70 | * 0 disable debug | ||
71 | * 1 standard level: pr_debug1 is enabled | ||
72 | * 2 parport_ip32_dump_state is enabled | ||
73 | * >=3 verbose level: pr_debug is enabled | ||
74 | */ | ||
75 | #if !defined(DEBUG_PARPORT_IP32) | ||
76 | # define DEBUG_PARPORT_IP32 0 /* 0 (disabled) for production */ | ||
77 | #endif | ||
78 | |||
79 | /*----------------------------------------------------------------------*/ | ||
80 | |||
81 | /* Setup DEBUG macros. This is done before any includes, just in case we | ||
82 | * activate pr_debug() with DEBUG_PARPORT_IP32 >= 3. | ||
83 | */ | ||
84 | #if DEBUG_PARPORT_IP32 == 1 | ||
85 | # warning DEBUG_PARPORT_IP32 == 1 | ||
86 | #elif DEBUG_PARPORT_IP32 == 2 | ||
87 | # warning DEBUG_PARPORT_IP32 == 2 | ||
88 | #elif DEBUG_PARPORT_IP32 >= 3 | ||
89 | # warning DEBUG_PARPORT_IP32 >= 3 | ||
90 | # if !defined(DEBUG) | ||
91 | # define DEBUG /* enable pr_debug() in kernel.h */ | ||
92 | # endif | ||
93 | #endif | ||
94 | |||
95 | #include <linux/completion.h> | ||
96 | #include <linux/delay.h> | ||
97 | #include <linux/dma-mapping.h> | ||
98 | #include <linux/err.h> | ||
99 | #include <linux/init.h> | ||
100 | #include <linux/interrupt.h> | ||
101 | #include <linux/jiffies.h> | ||
102 | #include <linux/kernel.h> | ||
103 | #include <linux/module.h> | ||
104 | #include <linux/parport.h> | ||
105 | #include <linux/sched.h> | ||
106 | #include <linux/spinlock.h> | ||
107 | #include <linux/stddef.h> | ||
108 | #include <linux/types.h> | ||
109 | #include <asm/io.h> | ||
110 | #include <asm/ip32/ip32_ints.h> | ||
111 | #include <asm/ip32/mace.h> | ||
112 | |||
113 | /*--- Global variables -------------------------------------------------*/ | ||
114 | |||
115 | /* Verbose probing on by default for debugging. */ | ||
116 | #if DEBUG_PARPORT_IP32 >= 1 | ||
117 | # define DEFAULT_VERBOSE_PROBING 1 | ||
118 | #else | ||
119 | # define DEFAULT_VERBOSE_PROBING 0 | ||
120 | #endif | ||
121 | |||
122 | /* Default prefix for printk */ | ||
123 | #define PPIP32 "parport_ip32: " | ||
124 | |||
125 | /* | ||
126 | * These are the module parameters: | ||
127 | * @features: bit mask of features to enable/disable | ||
128 | * (all enabled by default) | ||
129 | * @verbose_probing: log chit-chat during initialization | ||
130 | */ | ||
131 | #define PARPORT_IP32_ENABLE_IRQ (1U << 0) | ||
132 | #define PARPORT_IP32_ENABLE_DMA (1U << 1) | ||
133 | #define PARPORT_IP32_ENABLE_SPP (1U << 2) | ||
134 | #define PARPORT_IP32_ENABLE_EPP (1U << 3) | ||
135 | #define PARPORT_IP32_ENABLE_ECP (1U << 4) | ||
136 | static unsigned int features = ~0U; | ||
137 | static int verbose_probing = DEFAULT_VERBOSE_PROBING; | ||
138 | |||
139 | /* We do not support more than one port. */ | ||
140 | static struct parport *this_port = NULL; | ||
141 | |||
142 | /* Timing constants for FIFO modes. */ | ||
143 | #define FIFO_NFAULT_TIMEOUT 100 /* milliseconds */ | ||
144 | #define FIFO_POLLING_INTERVAL 50 /* microseconds */ | ||
145 | |||
146 | /*--- I/O register definitions -----------------------------------------*/ | ||
147 | |||
148 | /** | ||
149 | * struct parport_ip32_regs - virtual addresses of parallel port registers | ||
150 | * @data: Data Register | ||
151 | * @dsr: Device Status Register | ||
152 | * @dcr: Device Control Register | ||
153 | * @eppAddr: EPP Address Register | ||
154 | * @eppData0: EPP Data Register 0 | ||
155 | * @eppData1: EPP Data Register 1 | ||
156 | * @eppData2: EPP Data Register 2 | ||
157 | * @eppData3: EPP Data Register 3 | ||
158 | * @ecpAFifo: ECP Address FIFO | ||
159 | * @fifo: General FIFO register. The same address is used for: | ||
160 | * - cFifo, the Parallel Port DATA FIFO | ||
161 | * - ecpDFifo, the ECP Data FIFO | ||
162 | * - tFifo, the ECP Test FIFO | ||
163 | * @cnfgA: Configuration Register A | ||
164 | * @cnfgB: Configuration Register B | ||
165 | * @ecr: Extended Control Register | ||
166 | */ | ||
167 | struct parport_ip32_regs { | ||
168 | void __iomem *data; | ||
169 | void __iomem *dsr; | ||
170 | void __iomem *dcr; | ||
171 | void __iomem *eppAddr; | ||
172 | void __iomem *eppData0; | ||
173 | void __iomem *eppData1; | ||
174 | void __iomem *eppData2; | ||
175 | void __iomem *eppData3; | ||
176 | void __iomem *ecpAFifo; | ||
177 | void __iomem *fifo; | ||
178 | void __iomem *cnfgA; | ||
179 | void __iomem *cnfgB; | ||
180 | void __iomem *ecr; | ||
181 | }; | ||
182 | |||
183 | /* Device Status Register */ | ||
184 | #define DSR_nBUSY (1U << 7) /* PARPORT_STATUS_BUSY */ | ||
185 | #define DSR_nACK (1U << 6) /* PARPORT_STATUS_ACK */ | ||
186 | #define DSR_PERROR (1U << 5) /* PARPORT_STATUS_PAPEROUT */ | ||
187 | #define DSR_SELECT (1U << 4) /* PARPORT_STATUS_SELECT */ | ||
188 | #define DSR_nFAULT (1U << 3) /* PARPORT_STATUS_ERROR */ | ||
189 | #define DSR_nPRINT (1U << 2) /* specific to TL16PIR552 */ | ||
190 | /* #define DSR_reserved (1U << 1) */ | ||
191 | #define DSR_TIMEOUT (1U << 0) /* EPP timeout */ | ||
192 | |||
193 | /* Device Control Register */ | ||
194 | /* #define DCR_reserved (1U << 7) | (1U << 6) */ | ||
195 | #define DCR_DIR (1U << 5) /* direction */ | ||
196 | #define DCR_IRQ (1U << 4) /* interrupt on nAck */ | ||
197 | #define DCR_SELECT (1U << 3) /* PARPORT_CONTROL_SELECT */ | ||
198 | #define DCR_nINIT (1U << 2) /* PARPORT_CONTROL_INIT */ | ||
199 | #define DCR_AUTOFD (1U << 1) /* PARPORT_CONTROL_AUTOFD */ | ||
200 | #define DCR_STROBE (1U << 0) /* PARPORT_CONTROL_STROBE */ | ||
201 | |||
202 | /* ECP Configuration Register A */ | ||
203 | #define CNFGA_IRQ (1U << 7) | ||
204 | #define CNFGA_ID_MASK ((1U << 6) | (1U << 5) | (1U << 4)) | ||
205 | #define CNFGA_ID_SHIFT 4 | ||
206 | #define CNFGA_ID_16 (00U << CNFGA_ID_SHIFT) | ||
207 | #define CNFGA_ID_8 (01U << CNFGA_ID_SHIFT) | ||
208 | #define CNFGA_ID_32 (02U << CNFGA_ID_SHIFT) | ||
209 | /* #define CNFGA_reserved (1U << 3) */ | ||
210 | #define CNFGA_nBYTEINTRANS (1U << 2) | ||
211 | #define CNFGA_PWORDLEFT ((1U << 1) | (1U << 0)) | ||
212 | |||
213 | /* ECP Configuration Register B */ | ||
214 | #define CNFGB_COMPRESS (1U << 7) | ||
215 | #define CNFGB_INTRVAL (1U << 6) | ||
216 | #define CNFGB_IRQ_MASK ((1U << 5) | (1U << 4) | (1U << 3)) | ||
217 | #define CNFGB_IRQ_SHIFT 3 | ||
218 | #define CNFGB_DMA_MASK ((1U << 2) | (1U << 1) | (1U << 0)) | ||
219 | #define CNFGB_DMA_SHIFT 0 | ||
220 | |||
221 | /* Extended Control Register */ | ||
222 | #define ECR_MODE_MASK ((1U << 7) | (1U << 6) | (1U << 5)) | ||
223 | #define ECR_MODE_SHIFT 5 | ||
224 | #define ECR_MODE_SPP (00U << ECR_MODE_SHIFT) | ||
225 | #define ECR_MODE_PS2 (01U << ECR_MODE_SHIFT) | ||
226 | #define ECR_MODE_PPF (02U << ECR_MODE_SHIFT) | ||
227 | #define ECR_MODE_ECP (03U << ECR_MODE_SHIFT) | ||
228 | #define ECR_MODE_EPP (04U << ECR_MODE_SHIFT) | ||
229 | /* #define ECR_MODE_reserved (05U << ECR_MODE_SHIFT) */ | ||
230 | #define ECR_MODE_TST (06U << ECR_MODE_SHIFT) | ||
231 | #define ECR_MODE_CFG (07U << ECR_MODE_SHIFT) | ||
232 | #define ECR_nERRINTR (1U << 4) | ||
233 | #define ECR_DMAEN (1U << 3) | ||
234 | #define ECR_SERVINTR (1U << 2) | ||
235 | #define ECR_F_FULL (1U << 1) | ||
236 | #define ECR_F_EMPTY (1U << 0) | ||
237 | |||
238 | /*--- Private data -----------------------------------------------------*/ | ||
239 | |||
240 | /** | ||
241 | * enum parport_ip32_irq_mode - operation mode of interrupt handler | ||
242 | * @PARPORT_IP32_IRQ_FWD: forward interrupt to the upper parport layer | ||
243 | * @PARPORT_IP32_IRQ_HERE: interrupt is handled locally | ||
244 | */ | ||
245 | enum parport_ip32_irq_mode { PARPORT_IP32_IRQ_FWD, PARPORT_IP32_IRQ_HERE }; | ||
246 | |||
247 | /** | ||
248 | * struct parport_ip32_private - private stuff for &struct parport | ||
249 | * @regs: register addresses | ||
250 | * @dcr_cache: cached contents of DCR | ||
251 | * @dcr_writable: bit mask of writable DCR bits | ||
252 | * @pword: number of bytes per PWord | ||
253 | * @fifo_depth: number of PWords that FIFO will hold | ||
254 | * @readIntrThreshold: minimum number of PWords we can read | ||
255 | * if we get an interrupt | ||
256 | * @writeIntrThreshold: minimum number of PWords we can write | ||
257 | * if we get an interrupt | ||
258 | * @irq_mode: operation mode of interrupt handler for this port | ||
259 | * @irq_complete: mutex used to wait for an interrupt to occur | ||
260 | */ | ||
261 | struct parport_ip32_private { | ||
262 | struct parport_ip32_regs regs; | ||
263 | unsigned int dcr_cache; | ||
264 | unsigned int dcr_writable; | ||
265 | unsigned int pword; | ||
266 | unsigned int fifo_depth; | ||
267 | unsigned int readIntrThreshold; | ||
268 | unsigned int writeIntrThreshold; | ||
269 | enum parport_ip32_irq_mode irq_mode; | ||
270 | struct completion irq_complete; | ||
271 | }; | ||
272 | |||
273 | /*--- Debug code -------------------------------------------------------*/ | ||
274 | |||
275 | /* | ||
276 | * pr_debug1 - print debug messages | ||
277 | * | ||
278 | * This is like pr_debug(), but is defined for %DEBUG_PARPORT_IP32 >= 1 | ||
279 | */ | ||
280 | #if DEBUG_PARPORT_IP32 >= 1 | ||
281 | # define pr_debug1(...) printk(KERN_DEBUG __VA_ARGS__) | ||
282 | #else /* DEBUG_PARPORT_IP32 < 1 */ | ||
283 | # define pr_debug1(...) do { } while (0) | ||
284 | #endif | ||
285 | |||
286 | /* | ||
287 | * pr_trace, pr_trace1 - trace function calls | ||
288 | * @p: pointer to &struct parport | ||
289 | * @fmt: printk format string | ||
290 | * @...: parameters for format string | ||
291 | * | ||
292 | * Macros used to trace function calls. The given string is formatted after | ||
293 | * function name. pr_trace() uses pr_debug(), and pr_trace1() uses | ||
294 | * pr_debug1(). __pr_trace() is the low-level macro and is not to be used | ||
295 | * directly. | ||
296 | */ | ||
297 | #define __pr_trace(pr, p, fmt, ...) \ | ||
298 | pr("%s: %s" fmt "\n", \ | ||
299 | ({ const struct parport *__p = (p); \ | ||
300 | __p ? __p->name : "parport_ip32"; }), \ | ||
301 | __func__ , ##__VA_ARGS__) | ||
302 | #define pr_trace(p, fmt, ...) __pr_trace(pr_debug, p, fmt , ##__VA_ARGS__) | ||
303 | #define pr_trace1(p, fmt, ...) __pr_trace(pr_debug1, p, fmt , ##__VA_ARGS__) | ||
304 | |||
305 | /* | ||
306 | * __pr_probe, pr_probe - print message if @verbose_probing is true | ||
307 | * @p: pointer to &struct parport | ||
308 | * @fmt: printk format string | ||
309 | * @...: parameters for format string | ||
310 | * | ||
311 | * For new lines, use pr_probe(). Use __pr_probe() for continued lines. | ||
312 | */ | ||
313 | #define __pr_probe(...) \ | ||
314 | do { if (verbose_probing) printk(__VA_ARGS__); } while (0) | ||
315 | #define pr_probe(p, fmt, ...) \ | ||
316 | __pr_probe(KERN_INFO PPIP32 "0x%lx: " fmt, (p)->base , ##__VA_ARGS__) | ||
317 | |||
318 | /* | ||
319 | * parport_ip32_dump_state - print register status of parport | ||
320 | * @p: pointer to &struct parport | ||
321 | * @str: string to add in message | ||
322 | * @show_ecp_config: shall we dump ECP configuration registers too? | ||
323 | * | ||
324 | * This function is only here for debugging purpose, and should be used with | ||
325 | * care. Reading the parallel port registers may have undesired side effects. | ||
326 | * Especially if @show_ecp_config is true, the parallel port is resetted. | ||
327 | * This function is only defined if %DEBUG_PARPORT_IP32 >= 2. | ||
328 | */ | ||
329 | #if DEBUG_PARPORT_IP32 >= 2 | ||
330 | static void parport_ip32_dump_state(struct parport *p, char *str, | ||
331 | unsigned int show_ecp_config) | ||
332 | { | ||
333 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
334 | unsigned int i; | ||
335 | |||
336 | printk(KERN_DEBUG PPIP32 "%s: state (%s):\n", p->name, str); | ||
337 | { | ||
338 | static const char ecr_modes[8][4] = {"SPP", "PS2", "PPF", | ||
339 | "ECP", "EPP", "???", | ||
340 | "TST", "CFG"}; | ||
341 | unsigned int ecr = readb(priv->regs.ecr); | ||
342 | printk(KERN_DEBUG PPIP32 " ecr=0x%02x", ecr); | ||
343 | printk(" %s", | ||
344 | ecr_modes[(ecr & ECR_MODE_MASK) >> ECR_MODE_SHIFT]); | ||
345 | if (ecr & ECR_nERRINTR) | ||
346 | printk(",nErrIntrEn"); | ||
347 | if (ecr & ECR_DMAEN) | ||
348 | printk(",dmaEn"); | ||
349 | if (ecr & ECR_SERVINTR) | ||
350 | printk(",serviceIntr"); | ||
351 | if (ecr & ECR_F_FULL) | ||
352 | printk(",f_full"); | ||
353 | if (ecr & ECR_F_EMPTY) | ||
354 | printk(",f_empty"); | ||
355 | printk("\n"); | ||
356 | } | ||
357 | if (show_ecp_config) { | ||
358 | unsigned int oecr, cnfgA, cnfgB; | ||
359 | oecr = readb(priv->regs.ecr); | ||
360 | writeb(ECR_MODE_PS2, priv->regs.ecr); | ||
361 | writeb(ECR_MODE_CFG, priv->regs.ecr); | ||
362 | cnfgA = readb(priv->regs.cnfgA); | ||
363 | cnfgB = readb(priv->regs.cnfgB); | ||
364 | writeb(ECR_MODE_PS2, priv->regs.ecr); | ||
365 | writeb(oecr, priv->regs.ecr); | ||
366 | printk(KERN_DEBUG PPIP32 " cnfgA=0x%02x", cnfgA); | ||
367 | printk(" ISA-%s", (cnfgA & CNFGA_IRQ) ? "Level" : "Pulses"); | ||
368 | switch (cnfgA & CNFGA_ID_MASK) { | ||
369 | case CNFGA_ID_8: | ||
370 | printk(",8 bits"); | ||
371 | break; | ||
372 | case CNFGA_ID_16: | ||
373 | printk(",16 bits"); | ||
374 | break; | ||
375 | case CNFGA_ID_32: | ||
376 | printk(",32 bits"); | ||
377 | break; | ||
378 | default: | ||
379 | printk(",unknown ID"); | ||
380 | break; | ||
381 | } | ||
382 | if (!(cnfgA & CNFGA_nBYTEINTRANS)) | ||
383 | printk(",ByteInTrans"); | ||
384 | if ((cnfgA & CNFGA_ID_MASK) != CNFGA_ID_8) | ||
385 | printk(",%d byte%s left", cnfgA & CNFGA_PWORDLEFT, | ||
386 | ((cnfgA & CNFGA_PWORDLEFT) > 1) ? "s" : ""); | ||
387 | printk("\n"); | ||
388 | printk(KERN_DEBUG PPIP32 " cnfgB=0x%02x", cnfgB); | ||
389 | printk(" irq=%u,dma=%u", | ||
390 | (cnfgB & CNFGB_IRQ_MASK) >> CNFGB_IRQ_SHIFT, | ||
391 | (cnfgB & CNFGB_DMA_MASK) >> CNFGB_DMA_SHIFT); | ||
392 | printk(",intrValue=%d", !!(cnfgB & CNFGB_INTRVAL)); | ||
393 | if (cnfgB & CNFGB_COMPRESS) | ||
394 | printk(",compress"); | ||
395 | printk("\n"); | ||
396 | } | ||
397 | for (i = 0; i < 2; i++) { | ||
398 | unsigned int dcr = i ? priv->dcr_cache : readb(priv->regs.dcr); | ||
399 | printk(KERN_DEBUG PPIP32 " dcr(%s)=0x%02x", | ||
400 | i ? "soft" : "hard", dcr); | ||
401 | printk(" %s", (dcr & DCR_DIR) ? "rev" : "fwd"); | ||
402 | if (dcr & DCR_IRQ) | ||
403 | printk(",ackIntEn"); | ||
404 | if (!(dcr & DCR_SELECT)) | ||
405 | printk(",nSelectIn"); | ||
406 | if (dcr & DCR_nINIT) | ||
407 | printk(",nInit"); | ||
408 | if (!(dcr & DCR_AUTOFD)) | ||
409 | printk(",nAutoFD"); | ||
410 | if (!(dcr & DCR_STROBE)) | ||
411 | printk(",nStrobe"); | ||
412 | printk("\n"); | ||
413 | } | ||
414 | #define sep (f++ ? ',' : ' ') | ||
415 | { | ||
416 | unsigned int f = 0; | ||
417 | unsigned int dsr = readb(priv->regs.dsr); | ||
418 | printk(KERN_DEBUG PPIP32 " dsr=0x%02x", dsr); | ||
419 | if (!(dsr & DSR_nBUSY)) | ||
420 | printk("%cBusy", sep); | ||
421 | if (dsr & DSR_nACK) | ||
422 | printk("%cnAck", sep); | ||
423 | if (dsr & DSR_PERROR) | ||
424 | printk("%cPError", sep); | ||
425 | if (dsr & DSR_SELECT) | ||
426 | printk("%cSelect", sep); | ||
427 | if (dsr & DSR_nFAULT) | ||
428 | printk("%cnFault", sep); | ||
429 | if (!(dsr & DSR_nPRINT)) | ||
430 | printk("%c(Print)", sep); | ||
431 | if (dsr & DSR_TIMEOUT) | ||
432 | printk("%cTimeout", sep); | ||
433 | printk("\n"); | ||
434 | } | ||
435 | #undef sep | ||
436 | } | ||
437 | #else /* DEBUG_PARPORT_IP32 < 2 */ | ||
438 | #define parport_ip32_dump_state(...) do { } while (0) | ||
439 | #endif | ||
440 | |||
441 | /* | ||
442 | * CHECK_EXTRA_BITS - track and log extra bits | ||
443 | * @p: pointer to &struct parport | ||
444 | * @b: byte to inspect | ||
445 | * @m: bit mask of authorized bits | ||
446 | * | ||
447 | * This is used to track and log extra bits that should not be there in | ||
448 | * parport_ip32_write_control() and parport_ip32_frob_control(). It is only | ||
449 | * defined if %DEBUG_PARPORT_IP32 >= 1. | ||
450 | */ | ||
451 | #if DEBUG_PARPORT_IP32 >= 1 | ||
452 | #define CHECK_EXTRA_BITS(p, b, m) \ | ||
453 | do { \ | ||
454 | unsigned int __b = (b), __m = (m); \ | ||
455 | if (__b & ~__m) \ | ||
456 | pr_debug1(PPIP32 "%s: extra bits in %s(%s): " \ | ||
457 | "0x%02x/0x%02x\n", \ | ||
458 | (p)->name, __func__, #b, __b, __m); \ | ||
459 | } while (0) | ||
460 | #else /* DEBUG_PARPORT_IP32 < 1 */ | ||
461 | #define CHECK_EXTRA_BITS(...) do { } while (0) | ||
462 | #endif | ||
463 | |||
464 | /*--- IP32 parallel port DMA operations --------------------------------*/ | ||
465 | |||
466 | /** | ||
467 | * struct parport_ip32_dma_data - private data needed for DMA operation | ||
468 | * @dir: DMA direction (from or to device) | ||
469 | * @buf: buffer physical address | ||
470 | * @len: buffer length | ||
471 | * @next: address of next bytes to DMA transfer | ||
472 | * @left: number of bytes remaining | ||
473 | * @ctx: next context to write (0: context_a; 1: context_b) | ||
474 | * @irq_on: are the DMA IRQs currently enabled? | ||
475 | * @lock: spinlock to protect access to the structure | ||
476 | */ | ||
477 | struct parport_ip32_dma_data { | ||
478 | enum dma_data_direction dir; | ||
479 | dma_addr_t buf; | ||
480 | dma_addr_t next; | ||
481 | size_t len; | ||
482 | size_t left; | ||
483 | unsigned int ctx; | ||
484 | unsigned int irq_on; | ||
485 | spinlock_t lock; | ||
486 | }; | ||
487 | static struct parport_ip32_dma_data parport_ip32_dma; | ||
488 | |||
489 | /** | ||
490 | * parport_ip32_dma_setup_context - setup next DMA context | ||
491 | * @limit: maximum data size for the context | ||
492 | * | ||
493 | * The alignment constraints must be verified in caller function, and the | ||
494 | * parameter @limit must be set accordingly. | ||
495 | */ | ||
496 | static void parport_ip32_dma_setup_context(unsigned int limit) | ||
497 | { | ||
498 | unsigned long flags; | ||
499 | |||
500 | spin_lock_irqsave(&parport_ip32_dma.lock, flags); | ||
501 | if (parport_ip32_dma.left > 0) { | ||
502 | /* Note: ctxreg is "volatile" here only because | ||
503 | * mace->perif.ctrl.parport.context_a and context_b are | ||
504 | * "volatile". */ | ||
505 | volatile u64 __iomem *ctxreg = (parport_ip32_dma.ctx == 0) ? | ||
506 | &mace->perif.ctrl.parport.context_a : | ||
507 | &mace->perif.ctrl.parport.context_b; | ||
508 | u64 count; | ||
509 | u64 ctxval; | ||
510 | if (parport_ip32_dma.left <= limit) { | ||
511 | count = parport_ip32_dma.left; | ||
512 | ctxval = MACEPAR_CONTEXT_LASTFLAG; | ||
513 | } else { | ||
514 | count = limit; | ||
515 | ctxval = 0; | ||
516 | } | ||
517 | |||
518 | pr_trace(NULL, | ||
519 | "(%u): 0x%04x:0x%04x, %u -> %u%s", | ||
520 | limit, | ||
521 | (unsigned int)parport_ip32_dma.buf, | ||
522 | (unsigned int)parport_ip32_dma.next, | ||
523 | (unsigned int)count, | ||
524 | parport_ip32_dma.ctx, ctxval ? "*" : ""); | ||
525 | |||
526 | ctxval |= parport_ip32_dma.next & | ||
527 | MACEPAR_CONTEXT_BASEADDR_MASK; | ||
528 | ctxval |= ((count - 1) << MACEPAR_CONTEXT_DATALEN_SHIFT) & | ||
529 | MACEPAR_CONTEXT_DATALEN_MASK; | ||
530 | writeq(ctxval, ctxreg); | ||
531 | parport_ip32_dma.next += count; | ||
532 | parport_ip32_dma.left -= count; | ||
533 | parport_ip32_dma.ctx ^= 1U; | ||
534 | } | ||
535 | /* If there is nothing more to send, disable IRQs to avoid to | ||
536 | * face an IRQ storm which can lock the machine. Disable them | ||
537 | * only once. */ | ||
538 | if (parport_ip32_dma.left == 0 && parport_ip32_dma.irq_on) { | ||
539 | pr_debug(PPIP32 "IRQ off (ctx)\n"); | ||
540 | disable_irq_nosync(MACEISA_PAR_CTXA_IRQ); | ||
541 | disable_irq_nosync(MACEISA_PAR_CTXB_IRQ); | ||
542 | parport_ip32_dma.irq_on = 0; | ||
543 | } | ||
544 | spin_unlock_irqrestore(&parport_ip32_dma.lock, flags); | ||
545 | } | ||
546 | |||
547 | /** | ||
548 | * parport_ip32_dma_interrupt - DMA interrupt handler | ||
549 | * @irq: interrupt number | ||
550 | * @dev_id: unused | ||
551 | * @regs: pointer to &struct pt_regs | ||
552 | */ | ||
553 | static irqreturn_t parport_ip32_dma_interrupt(int irq, void *dev_id, | ||
554 | struct pt_regs *regs) | ||
555 | { | ||
556 | if (parport_ip32_dma.left) | ||
557 | pr_trace(NULL, "(%d): ctx=%d", irq, parport_ip32_dma.ctx); | ||
558 | parport_ip32_dma_setup_context(MACEPAR_CONTEXT_DATA_BOUND); | ||
559 | return IRQ_HANDLED; | ||
560 | } | ||
561 | |||
562 | #if DEBUG_PARPORT_IP32 | ||
563 | static irqreturn_t parport_ip32_merr_interrupt(int irq, void *dev_id, | ||
564 | struct pt_regs *regs) | ||
565 | { | ||
566 | pr_trace1(NULL, "(%d)", irq); | ||
567 | return IRQ_HANDLED; | ||
568 | } | ||
569 | #endif | ||
570 | |||
571 | /** | ||
572 | * parport_ip32_dma_start - begins a DMA transfer | ||
573 | * @dir: DMA direction: DMA_TO_DEVICE or DMA_FROM_DEVICE | ||
574 | * @addr: pointer to data buffer | ||
575 | * @count: buffer size | ||
576 | * | ||
577 | * Calls to parport_ip32_dma_start() and parport_ip32_dma_stop() must be | ||
578 | * correctly balanced. | ||
579 | */ | ||
580 | static int parport_ip32_dma_start(enum dma_data_direction dir, | ||
581 | void *addr, size_t count) | ||
582 | { | ||
583 | unsigned int limit; | ||
584 | u64 ctrl; | ||
585 | |||
586 | pr_trace(NULL, "(%d, %lu)", dir, (unsigned long)count); | ||
587 | |||
588 | /* FIXME - add support for DMA_FROM_DEVICE. In this case, buffer must | ||
589 | * be 64 bytes aligned. */ | ||
590 | BUG_ON(dir != DMA_TO_DEVICE); | ||
591 | |||
592 | /* Reset DMA controller */ | ||
593 | ctrl = MACEPAR_CTLSTAT_RESET; | ||
594 | writeq(ctrl, &mace->perif.ctrl.parport.cntlstat); | ||
595 | |||
596 | /* DMA IRQs should normally be enabled */ | ||
597 | if (!parport_ip32_dma.irq_on) { | ||
598 | WARN_ON(1); | ||
599 | enable_irq(MACEISA_PAR_CTXA_IRQ); | ||
600 | enable_irq(MACEISA_PAR_CTXB_IRQ); | ||
601 | parport_ip32_dma.irq_on = 1; | ||
602 | } | ||
603 | |||
604 | /* Prepare DMA pointers */ | ||
605 | parport_ip32_dma.dir = dir; | ||
606 | parport_ip32_dma.buf = dma_map_single(NULL, addr, count, dir); | ||
607 | parport_ip32_dma.len = count; | ||
608 | parport_ip32_dma.next = parport_ip32_dma.buf; | ||
609 | parport_ip32_dma.left = parport_ip32_dma.len; | ||
610 | parport_ip32_dma.ctx = 0; | ||
611 | |||
612 | /* Setup DMA direction and first two contexts */ | ||
613 | ctrl = (dir == DMA_TO_DEVICE) ? 0 : MACEPAR_CTLSTAT_DIRECTION; | ||
614 | writeq(ctrl, &mace->perif.ctrl.parport.cntlstat); | ||
615 | /* Single transfer should not cross a 4K page boundary */ | ||
616 | limit = MACEPAR_CONTEXT_DATA_BOUND - | ||
617 | (parport_ip32_dma.next & (MACEPAR_CONTEXT_DATA_BOUND - 1)); | ||
618 | parport_ip32_dma_setup_context(limit); | ||
619 | parport_ip32_dma_setup_context(MACEPAR_CONTEXT_DATA_BOUND); | ||
620 | |||
621 | /* Real start of DMA transfer */ | ||
622 | ctrl |= MACEPAR_CTLSTAT_ENABLE; | ||
623 | writeq(ctrl, &mace->perif.ctrl.parport.cntlstat); | ||
624 | |||
625 | return 0; | ||
626 | } | ||
627 | |||
628 | /** | ||
629 | * parport_ip32_dma_stop - ends a running DMA transfer | ||
630 | * | ||
631 | * Calls to parport_ip32_dma_start() and parport_ip32_dma_stop() must be | ||
632 | * correctly balanced. | ||
633 | */ | ||
634 | static void parport_ip32_dma_stop(void) | ||
635 | { | ||
636 | u64 ctx_a; | ||
637 | u64 ctx_b; | ||
638 | u64 ctrl; | ||
639 | u64 diag; | ||
640 | size_t res[2]; /* {[0] = res_a, [1] = res_b} */ | ||
641 | |||
642 | pr_trace(NULL, "()"); | ||
643 | |||
644 | /* Disable IRQs */ | ||
645 | spin_lock_irq(&parport_ip32_dma.lock); | ||
646 | if (parport_ip32_dma.irq_on) { | ||
647 | pr_debug(PPIP32 "IRQ off (stop)\n"); | ||
648 | disable_irq_nosync(MACEISA_PAR_CTXA_IRQ); | ||
649 | disable_irq_nosync(MACEISA_PAR_CTXB_IRQ); | ||
650 | parport_ip32_dma.irq_on = 0; | ||
651 | } | ||
652 | spin_unlock_irq(&parport_ip32_dma.lock); | ||
653 | /* Force IRQ synchronization, even if the IRQs were disabled | ||
654 | * elsewhere. */ | ||
655 | synchronize_irq(MACEISA_PAR_CTXA_IRQ); | ||
656 | synchronize_irq(MACEISA_PAR_CTXB_IRQ); | ||
657 | |||
658 | /* Stop DMA transfer */ | ||
659 | ctrl = readq(&mace->perif.ctrl.parport.cntlstat); | ||
660 | ctrl &= ~MACEPAR_CTLSTAT_ENABLE; | ||
661 | writeq(ctrl, &mace->perif.ctrl.parport.cntlstat); | ||
662 | |||
663 | /* Adjust residue (parport_ip32_dma.left) */ | ||
664 | ctx_a = readq(&mace->perif.ctrl.parport.context_a); | ||
665 | ctx_b = readq(&mace->perif.ctrl.parport.context_b); | ||
666 | ctrl = readq(&mace->perif.ctrl.parport.cntlstat); | ||
667 | diag = readq(&mace->perif.ctrl.parport.diagnostic); | ||
668 | res[0] = (ctrl & MACEPAR_CTLSTAT_CTXA_VALID) ? | ||
669 | 1 + ((ctx_a & MACEPAR_CONTEXT_DATALEN_MASK) >> | ||
670 | MACEPAR_CONTEXT_DATALEN_SHIFT) : | ||
671 | 0; | ||
672 | res[1] = (ctrl & MACEPAR_CTLSTAT_CTXB_VALID) ? | ||
673 | 1 + ((ctx_b & MACEPAR_CONTEXT_DATALEN_MASK) >> | ||
674 | MACEPAR_CONTEXT_DATALEN_SHIFT) : | ||
675 | 0; | ||
676 | if (diag & MACEPAR_DIAG_DMACTIVE) | ||
677 | res[(diag & MACEPAR_DIAG_CTXINUSE) != 0] = | ||
678 | 1 + ((diag & MACEPAR_DIAG_CTRMASK) >> | ||
679 | MACEPAR_DIAG_CTRSHIFT); | ||
680 | parport_ip32_dma.left += res[0] + res[1]; | ||
681 | |||
682 | /* Reset DMA controller, and re-enable IRQs */ | ||
683 | ctrl = MACEPAR_CTLSTAT_RESET; | ||
684 | writeq(ctrl, &mace->perif.ctrl.parport.cntlstat); | ||
685 | pr_debug(PPIP32 "IRQ on (stop)\n"); | ||
686 | enable_irq(MACEISA_PAR_CTXA_IRQ); | ||
687 | enable_irq(MACEISA_PAR_CTXB_IRQ); | ||
688 | parport_ip32_dma.irq_on = 1; | ||
689 | |||
690 | dma_unmap_single(NULL, parport_ip32_dma.buf, parport_ip32_dma.len, | ||
691 | parport_ip32_dma.dir); | ||
692 | } | ||
693 | |||
694 | /** | ||
695 | * parport_ip32_dma_get_residue - get residue from last DMA transfer | ||
696 | * | ||
697 | * Returns the number of bytes remaining from last DMA transfer. | ||
698 | */ | ||
699 | static inline size_t parport_ip32_dma_get_residue(void) | ||
700 | { | ||
701 | return parport_ip32_dma.left; | ||
702 | } | ||
703 | |||
704 | /** | ||
705 | * parport_ip32_dma_register - initialize DMA engine | ||
706 | * | ||
707 | * Returns zero for success. | ||
708 | */ | ||
709 | static int parport_ip32_dma_register(void) | ||
710 | { | ||
711 | int err; | ||
712 | |||
713 | spin_lock_init(&parport_ip32_dma.lock); | ||
714 | parport_ip32_dma.irq_on = 1; | ||
715 | |||
716 | /* Reset DMA controller */ | ||
717 | writeq(MACEPAR_CTLSTAT_RESET, &mace->perif.ctrl.parport.cntlstat); | ||
718 | |||
719 | /* Request IRQs */ | ||
720 | err = request_irq(MACEISA_PAR_CTXA_IRQ, parport_ip32_dma_interrupt, | ||
721 | 0, "parport_ip32", NULL); | ||
722 | if (err) | ||
723 | goto fail_a; | ||
724 | err = request_irq(MACEISA_PAR_CTXB_IRQ, parport_ip32_dma_interrupt, | ||
725 | 0, "parport_ip32", NULL); | ||
726 | if (err) | ||
727 | goto fail_b; | ||
728 | #if DEBUG_PARPORT_IP32 | ||
729 | /* FIXME - what is this IRQ for? */ | ||
730 | err = request_irq(MACEISA_PAR_MERR_IRQ, parport_ip32_merr_interrupt, | ||
731 | 0, "parport_ip32", NULL); | ||
732 | if (err) | ||
733 | goto fail_merr; | ||
734 | #endif | ||
735 | return 0; | ||
736 | |||
737 | #if DEBUG_PARPORT_IP32 | ||
738 | fail_merr: | ||
739 | free_irq(MACEISA_PAR_CTXB_IRQ, NULL); | ||
740 | #endif | ||
741 | fail_b: | ||
742 | free_irq(MACEISA_PAR_CTXA_IRQ, NULL); | ||
743 | fail_a: | ||
744 | return err; | ||
745 | } | ||
746 | |||
747 | /** | ||
748 | * parport_ip32_dma_unregister - release and free resources for DMA engine | ||
749 | */ | ||
750 | static void parport_ip32_dma_unregister(void) | ||
751 | { | ||
752 | #if DEBUG_PARPORT_IP32 | ||
753 | free_irq(MACEISA_PAR_MERR_IRQ, NULL); | ||
754 | #endif | ||
755 | free_irq(MACEISA_PAR_CTXB_IRQ, NULL); | ||
756 | free_irq(MACEISA_PAR_CTXA_IRQ, NULL); | ||
757 | } | ||
758 | |||
759 | /*--- Interrupt handlers and associates --------------------------------*/ | ||
760 | |||
761 | /** | ||
762 | * parport_ip32_wakeup - wakes up code waiting for an interrupt | ||
763 | * @p: pointer to &struct parport | ||
764 | */ | ||
765 | static inline void parport_ip32_wakeup(struct parport *p) | ||
766 | { | ||
767 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
768 | complete(&priv->irq_complete); | ||
769 | } | ||
770 | |||
771 | /** | ||
772 | * parport_ip32_interrupt - interrupt handler | ||
773 | * @irq: interrupt number | ||
774 | * @dev_id: pointer to &struct parport | ||
775 | * @regs: pointer to &struct pt_regs | ||
776 | * | ||
777 | * Caught interrupts are forwarded to the upper parport layer if IRQ_mode is | ||
778 | * %PARPORT_IP32_IRQ_FWD. | ||
779 | */ | ||
780 | static irqreturn_t parport_ip32_interrupt(int irq, void *dev_id, | ||
781 | struct pt_regs *regs) | ||
782 | { | ||
783 | struct parport * const p = dev_id; | ||
784 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
785 | enum parport_ip32_irq_mode irq_mode = priv->irq_mode; | ||
786 | switch (irq_mode) { | ||
787 | case PARPORT_IP32_IRQ_FWD: | ||
788 | parport_generic_irq(irq, p, regs); | ||
789 | break; | ||
790 | case PARPORT_IP32_IRQ_HERE: | ||
791 | parport_ip32_wakeup(p); | ||
792 | break; | ||
793 | } | ||
794 | return IRQ_HANDLED; | ||
795 | } | ||
796 | |||
797 | /*--- Some utility function to manipulate ECR register -----------------*/ | ||
798 | |||
799 | /** | ||
800 | * parport_ip32_read_econtrol - read contents of the ECR register | ||
801 | * @p: pointer to &struct parport | ||
802 | */ | ||
803 | static inline unsigned int parport_ip32_read_econtrol(struct parport *p) | ||
804 | { | ||
805 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
806 | return readb(priv->regs.ecr); | ||
807 | } | ||
808 | |||
809 | /** | ||
810 | * parport_ip32_write_econtrol - write new contents to the ECR register | ||
811 | * @p: pointer to &struct parport | ||
812 | * @c: new value to write | ||
813 | */ | ||
814 | static inline void parport_ip32_write_econtrol(struct parport *p, | ||
815 | unsigned int c) | ||
816 | { | ||
817 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
818 | writeb(c, priv->regs.ecr); | ||
819 | } | ||
820 | |||
821 | /** | ||
822 | * parport_ip32_frob_econtrol - change bits from the ECR register | ||
823 | * @p: pointer to &struct parport | ||
824 | * @mask: bit mask of bits to change | ||
825 | * @val: new value for changed bits | ||
826 | * | ||
827 | * Read from the ECR, mask out the bits in @mask, exclusive-or with the bits | ||
828 | * in @val, and write the result to the ECR. | ||
829 | */ | ||
830 | static inline void parport_ip32_frob_econtrol(struct parport *p, | ||
831 | unsigned int mask, | ||
832 | unsigned int val) | ||
833 | { | ||
834 | unsigned int c; | ||
835 | c = (parport_ip32_read_econtrol(p) & ~mask) ^ val; | ||
836 | parport_ip32_write_econtrol(p, c); | ||
837 | } | ||
838 | |||
839 | /** | ||
840 | * parport_ip32_set_mode - change mode of ECP port | ||
841 | * @p: pointer to &struct parport | ||
842 | * @mode: new mode to write in ECR | ||
843 | * | ||
844 | * ECR is reset in a sane state (interrupts and DMA disabled), and placed in | ||
845 | * mode @mode. Go through PS2 mode if needed. | ||
846 | */ | ||
847 | static void parport_ip32_set_mode(struct parport *p, unsigned int mode) | ||
848 | { | ||
849 | unsigned int omode; | ||
850 | |||
851 | mode &= ECR_MODE_MASK; | ||
852 | omode = parport_ip32_read_econtrol(p) & ECR_MODE_MASK; | ||
853 | |||
854 | if (!(mode == ECR_MODE_SPP || mode == ECR_MODE_PS2 | ||
855 | || omode == ECR_MODE_SPP || omode == ECR_MODE_PS2)) { | ||
856 | /* We have to go through PS2 mode */ | ||
857 | unsigned int ecr = ECR_MODE_PS2 | ECR_nERRINTR | ECR_SERVINTR; | ||
858 | parport_ip32_write_econtrol(p, ecr); | ||
859 | } | ||
860 | parport_ip32_write_econtrol(p, mode | ECR_nERRINTR | ECR_SERVINTR); | ||
861 | } | ||
862 | |||
863 | /*--- Basic functions needed for parport -------------------------------*/ | ||
864 | |||
865 | /** | ||
866 | * parport_ip32_read_data - return current contents of the DATA register | ||
867 | * @p: pointer to &struct parport | ||
868 | */ | ||
869 | static inline unsigned char parport_ip32_read_data(struct parport *p) | ||
870 | { | ||
871 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
872 | return readb(priv->regs.data); | ||
873 | } | ||
874 | |||
875 | /** | ||
876 | * parport_ip32_write_data - set new contents for the DATA register | ||
877 | * @p: pointer to &struct parport | ||
878 | * @d: new value to write | ||
879 | */ | ||
880 | static inline void parport_ip32_write_data(struct parport *p, unsigned char d) | ||
881 | { | ||
882 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
883 | writeb(d, priv->regs.data); | ||
884 | } | ||
885 | |||
886 | /** | ||
887 | * parport_ip32_read_status - return current contents of the DSR register | ||
888 | * @p: pointer to &struct parport | ||
889 | */ | ||
890 | static inline unsigned char parport_ip32_read_status(struct parport *p) | ||
891 | { | ||
892 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
893 | return readb(priv->regs.dsr); | ||
894 | } | ||
895 | |||
896 | /** | ||
897 | * __parport_ip32_read_control - return cached contents of the DCR register | ||
898 | * @p: pointer to &struct parport | ||
899 | */ | ||
900 | static inline unsigned int __parport_ip32_read_control(struct parport *p) | ||
901 | { | ||
902 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
903 | return priv->dcr_cache; /* use soft copy */ | ||
904 | } | ||
905 | |||
906 | /** | ||
907 | * __parport_ip32_write_control - set new contents for the DCR register | ||
908 | * @p: pointer to &struct parport | ||
909 | * @c: new value to write | ||
910 | */ | ||
911 | static inline void __parport_ip32_write_control(struct parport *p, | ||
912 | unsigned int c) | ||
913 | { | ||
914 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
915 | CHECK_EXTRA_BITS(p, c, priv->dcr_writable); | ||
916 | c &= priv->dcr_writable; /* only writable bits */ | ||
917 | writeb(c, priv->regs.dcr); | ||
918 | priv->dcr_cache = c; /* update soft copy */ | ||
919 | } | ||
920 | |||
921 | /** | ||
922 | * __parport_ip32_frob_control - change bits from the DCR register | ||
923 | * @p: pointer to &struct parport | ||
924 | * @mask: bit mask of bits to change | ||
925 | * @val: new value for changed bits | ||
926 | * | ||
927 | * This is equivalent to read from the DCR, mask out the bits in @mask, | ||
928 | * exclusive-or with the bits in @val, and write the result to the DCR. | ||
929 | * Actually, the cached contents of the DCR is used. | ||
930 | */ | ||
931 | static inline void __parport_ip32_frob_control(struct parport *p, | ||
932 | unsigned int mask, | ||
933 | unsigned int val) | ||
934 | { | ||
935 | unsigned int c; | ||
936 | c = (__parport_ip32_read_control(p) & ~mask) ^ val; | ||
937 | __parport_ip32_write_control(p, c); | ||
938 | } | ||
939 | |||
940 | /** | ||
941 | * parport_ip32_read_control - return cached contents of the DCR register | ||
942 | * @p: pointer to &struct parport | ||
943 | * | ||
944 | * The return value is masked so as to only return the value of %DCR_STROBE, | ||
945 | * %DCR_AUTOFD, %DCR_nINIT, and %DCR_SELECT. | ||
946 | */ | ||
947 | static inline unsigned char parport_ip32_read_control(struct parport *p) | ||
948 | { | ||
949 | const unsigned int rm = | ||
950 | DCR_STROBE | DCR_AUTOFD | DCR_nINIT | DCR_SELECT; | ||
951 | return __parport_ip32_read_control(p) & rm; | ||
952 | } | ||
953 | |||
954 | /** | ||
955 | * parport_ip32_write_control - set new contents for the DCR register | ||
956 | * @p: pointer to &struct parport | ||
957 | * @c: new value to write | ||
958 | * | ||
959 | * The value is masked so as to only change the value of %DCR_STROBE, | ||
960 | * %DCR_AUTOFD, %DCR_nINIT, and %DCR_SELECT. | ||
961 | */ | ||
962 | static inline void parport_ip32_write_control(struct parport *p, | ||
963 | unsigned char c) | ||
964 | { | ||
965 | const unsigned int wm = | ||
966 | DCR_STROBE | DCR_AUTOFD | DCR_nINIT | DCR_SELECT; | ||
967 | CHECK_EXTRA_BITS(p, c, wm); | ||
968 | __parport_ip32_frob_control(p, wm, c & wm); | ||
969 | } | ||
970 | |||
971 | /** | ||
972 | * parport_ip32_frob_control - change bits from the DCR register | ||
973 | * @p: pointer to &struct parport | ||
974 | * @mask: bit mask of bits to change | ||
975 | * @val: new value for changed bits | ||
976 | * | ||
977 | * This differs from __parport_ip32_frob_control() in that it only allows to | ||
978 | * change the value of %DCR_STROBE, %DCR_AUTOFD, %DCR_nINIT, and %DCR_SELECT. | ||
979 | */ | ||
980 | static inline unsigned char parport_ip32_frob_control(struct parport *p, | ||
981 | unsigned char mask, | ||
982 | unsigned char val) | ||
983 | { | ||
984 | const unsigned int wm = | ||
985 | DCR_STROBE | DCR_AUTOFD | DCR_nINIT | DCR_SELECT; | ||
986 | CHECK_EXTRA_BITS(p, mask, wm); | ||
987 | CHECK_EXTRA_BITS(p, val, wm); | ||
988 | __parport_ip32_frob_control(p, mask & wm, val & wm); | ||
989 | return parport_ip32_read_control(p); | ||
990 | } | ||
991 | |||
992 | /** | ||
993 | * parport_ip32_disable_irq - disable interrupts on the rising edge of nACK | ||
994 | * @p: pointer to &struct parport | ||
995 | */ | ||
996 | static inline void parport_ip32_disable_irq(struct parport *p) | ||
997 | { | ||
998 | __parport_ip32_frob_control(p, DCR_IRQ, 0); | ||
999 | } | ||
1000 | |||
1001 | /** | ||
1002 | * parport_ip32_enable_irq - enable interrupts on the rising edge of nACK | ||
1003 | * @p: pointer to &struct parport | ||
1004 | */ | ||
1005 | static inline void parport_ip32_enable_irq(struct parport *p) | ||
1006 | { | ||
1007 | __parport_ip32_frob_control(p, DCR_IRQ, DCR_IRQ); | ||
1008 | } | ||
1009 | |||
1010 | /** | ||
1011 | * parport_ip32_data_forward - enable host-to-peripheral communications | ||
1012 | * @p: pointer to &struct parport | ||
1013 | * | ||
1014 | * Enable the data line drivers, for 8-bit host-to-peripheral communications. | ||
1015 | */ | ||
1016 | static inline void parport_ip32_data_forward(struct parport *p) | ||
1017 | { | ||
1018 | __parport_ip32_frob_control(p, DCR_DIR, 0); | ||
1019 | } | ||
1020 | |||
1021 | /** | ||
1022 | * parport_ip32_data_reverse - enable peripheral-to-host communications | ||
1023 | * @p: pointer to &struct parport | ||
1024 | * | ||
1025 | * Place the data bus in a high impedance state, if @p->modes has the | ||
1026 | * PARPORT_MODE_TRISTATE bit set. | ||
1027 | */ | ||
1028 | static inline void parport_ip32_data_reverse(struct parport *p) | ||
1029 | { | ||
1030 | __parport_ip32_frob_control(p, DCR_DIR, DCR_DIR); | ||
1031 | } | ||
1032 | |||
1033 | /** | ||
1034 | * parport_ip32_init_state - for core parport code | ||
1035 | * @dev: pointer to &struct pardevice | ||
1036 | * @s: pointer to &struct parport_state to initialize | ||
1037 | */ | ||
1038 | static void parport_ip32_init_state(struct pardevice *dev, | ||
1039 | struct parport_state *s) | ||
1040 | { | ||
1041 | s->u.ip32.dcr = DCR_SELECT | DCR_nINIT; | ||
1042 | s->u.ip32.ecr = ECR_MODE_PS2 | ECR_nERRINTR | ECR_SERVINTR; | ||
1043 | } | ||
1044 | |||
1045 | /** | ||
1046 | * parport_ip32_save_state - for core parport code | ||
1047 | * @p: pointer to &struct parport | ||
1048 | * @s: pointer to &struct parport_state to save state to | ||
1049 | */ | ||
1050 | static void parport_ip32_save_state(struct parport *p, | ||
1051 | struct parport_state *s) | ||
1052 | { | ||
1053 | s->u.ip32.dcr = __parport_ip32_read_control(p); | ||
1054 | s->u.ip32.ecr = parport_ip32_read_econtrol(p); | ||
1055 | } | ||
1056 | |||
1057 | /** | ||
1058 | * parport_ip32_restore_state - for core parport code | ||
1059 | * @p: pointer to &struct parport | ||
1060 | * @s: pointer to &struct parport_state to restore state from | ||
1061 | */ | ||
1062 | static void parport_ip32_restore_state(struct parport *p, | ||
1063 | struct parport_state *s) | ||
1064 | { | ||
1065 | parport_ip32_set_mode(p, s->u.ip32.ecr & ECR_MODE_MASK); | ||
1066 | parport_ip32_write_econtrol(p, s->u.ip32.ecr); | ||
1067 | __parport_ip32_write_control(p, s->u.ip32.dcr); | ||
1068 | } | ||
1069 | |||
1070 | /*--- EPP mode functions -----------------------------------------------*/ | ||
1071 | |||
1072 | /** | ||
1073 | * parport_ip32_clear_epp_timeout - clear Timeout bit in EPP mode | ||
1074 | * @p: pointer to &struct parport | ||
1075 | * | ||
1076 | * Returns 1 if the Timeout bit is clear, and 0 otherwise. | ||
1077 | */ | ||
1078 | static unsigned int parport_ip32_clear_epp_timeout(struct parport *p) | ||
1079 | { | ||
1080 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
1081 | unsigned int cleared; | ||
1082 | |||
1083 | if (!(parport_ip32_read_status(p) & DSR_TIMEOUT)) | ||
1084 | cleared = 1; | ||
1085 | else { | ||
1086 | unsigned int r; | ||
1087 | /* To clear timeout some chips require double read */ | ||
1088 | parport_ip32_read_status(p); | ||
1089 | r = parport_ip32_read_status(p); | ||
1090 | /* Some reset by writing 1 */ | ||
1091 | writeb(r | DSR_TIMEOUT, priv->regs.dsr); | ||
1092 | /* Others by writing 0 */ | ||
1093 | writeb(r & ~DSR_TIMEOUT, priv->regs.dsr); | ||
1094 | |||
1095 | r = parport_ip32_read_status(p); | ||
1096 | cleared = !(r & DSR_TIMEOUT); | ||
1097 | } | ||
1098 | |||
1099 | pr_trace(p, "(): %s", cleared ? "cleared" : "failed"); | ||
1100 | return cleared; | ||
1101 | } | ||
1102 | |||
1103 | /** | ||
1104 | * parport_ip32_epp_read - generic EPP read function | ||
1105 | * @eppreg: I/O register to read from | ||
1106 | * @p: pointer to &struct parport | ||
1107 | * @buf: buffer to store read data | ||
1108 | * @len: length of buffer @buf | ||
1109 | * @flags: may be PARPORT_EPP_FAST | ||
1110 | */ | ||
1111 | static size_t parport_ip32_epp_read(void __iomem *eppreg, | ||
1112 | struct parport *p, void *buf, | ||
1113 | size_t len, int flags) | ||
1114 | { | ||
1115 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
1116 | size_t got; | ||
1117 | parport_ip32_set_mode(p, ECR_MODE_EPP); | ||
1118 | parport_ip32_data_reverse(p); | ||
1119 | parport_ip32_write_control(p, DCR_nINIT); | ||
1120 | if ((flags & PARPORT_EPP_FAST) && (len > 1)) { | ||
1121 | readsb(eppreg, buf, len); | ||
1122 | if (readb(priv->regs.dsr) & DSR_TIMEOUT) { | ||
1123 | parport_ip32_clear_epp_timeout(p); | ||
1124 | return -EIO; | ||
1125 | } | ||
1126 | got = len; | ||
1127 | } else { | ||
1128 | u8 *bufp = buf; | ||
1129 | for (got = 0; got < len; got++) { | ||
1130 | *bufp++ = readb(eppreg); | ||
1131 | if (readb(priv->regs.dsr) & DSR_TIMEOUT) { | ||
1132 | parport_ip32_clear_epp_timeout(p); | ||
1133 | break; | ||
1134 | } | ||
1135 | } | ||
1136 | } | ||
1137 | parport_ip32_data_forward(p); | ||
1138 | parport_ip32_set_mode(p, ECR_MODE_PS2); | ||
1139 | return got; | ||
1140 | } | ||
1141 | |||
1142 | /** | ||
1143 | * parport_ip32_epp_write - generic EPP write function | ||
1144 | * @eppreg: I/O register to write to | ||
1145 | * @p: pointer to &struct parport | ||
1146 | * @buf: buffer of data to write | ||
1147 | * @len: length of buffer @buf | ||
1148 | * @flags: may be PARPORT_EPP_FAST | ||
1149 | */ | ||
1150 | static size_t parport_ip32_epp_write(void __iomem *eppreg, | ||
1151 | struct parport *p, const void *buf, | ||
1152 | size_t len, int flags) | ||
1153 | { | ||
1154 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
1155 | size_t written; | ||
1156 | parport_ip32_set_mode(p, ECR_MODE_EPP); | ||
1157 | parport_ip32_data_forward(p); | ||
1158 | parport_ip32_write_control(p, DCR_nINIT); | ||
1159 | if ((flags & PARPORT_EPP_FAST) && (len > 1)) { | ||
1160 | writesb(eppreg, buf, len); | ||
1161 | if (readb(priv->regs.dsr) & DSR_TIMEOUT) { | ||
1162 | parport_ip32_clear_epp_timeout(p); | ||
1163 | return -EIO; | ||
1164 | } | ||
1165 | written = len; | ||
1166 | } else { | ||
1167 | const u8 *bufp = buf; | ||
1168 | for (written = 0; written < len; written++) { | ||
1169 | writeb(*bufp++, eppreg); | ||
1170 | if (readb(priv->regs.dsr) & DSR_TIMEOUT) { | ||
1171 | parport_ip32_clear_epp_timeout(p); | ||
1172 | break; | ||
1173 | } | ||
1174 | } | ||
1175 | } | ||
1176 | parport_ip32_set_mode(p, ECR_MODE_PS2); | ||
1177 | return written; | ||
1178 | } | ||
1179 | |||
1180 | /** | ||
1181 | * parport_ip32_epp_read_data - read a block of data in EPP mode | ||
1182 | * @p: pointer to &struct parport | ||
1183 | * @buf: buffer to store read data | ||
1184 | * @len: length of buffer @buf | ||
1185 | * @flags: may be PARPORT_EPP_FAST | ||
1186 | */ | ||
1187 | static size_t parport_ip32_epp_read_data(struct parport *p, void *buf, | ||
1188 | size_t len, int flags) | ||
1189 | { | ||
1190 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
1191 | return parport_ip32_epp_read(priv->regs.eppData0, p, buf, len, flags); | ||
1192 | } | ||
1193 | |||
1194 | /** | ||
1195 | * parport_ip32_epp_write_data - write a block of data in EPP mode | ||
1196 | * @p: pointer to &struct parport | ||
1197 | * @buf: buffer of data to write | ||
1198 | * @len: length of buffer @buf | ||
1199 | * @flags: may be PARPORT_EPP_FAST | ||
1200 | */ | ||
1201 | static size_t parport_ip32_epp_write_data(struct parport *p, const void *buf, | ||
1202 | size_t len, int flags) | ||
1203 | { | ||
1204 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
1205 | return parport_ip32_epp_write(priv->regs.eppData0, p, buf, len, flags); | ||
1206 | } | ||
1207 | |||
1208 | /** | ||
1209 | * parport_ip32_epp_read_addr - read a block of addresses in EPP mode | ||
1210 | * @p: pointer to &struct parport | ||
1211 | * @buf: buffer to store read data | ||
1212 | * @len: length of buffer @buf | ||
1213 | * @flags: may be PARPORT_EPP_FAST | ||
1214 | */ | ||
1215 | static size_t parport_ip32_epp_read_addr(struct parport *p, void *buf, | ||
1216 | size_t len, int flags) | ||
1217 | { | ||
1218 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
1219 | return parport_ip32_epp_read(priv->regs.eppAddr, p, buf, len, flags); | ||
1220 | } | ||
1221 | |||
1222 | /** | ||
1223 | * parport_ip32_epp_write_addr - write a block of addresses in EPP mode | ||
1224 | * @p: pointer to &struct parport | ||
1225 | * @buf: buffer of data to write | ||
1226 | * @len: length of buffer @buf | ||
1227 | * @flags: may be PARPORT_EPP_FAST | ||
1228 | */ | ||
1229 | static size_t parport_ip32_epp_write_addr(struct parport *p, const void *buf, | ||
1230 | size_t len, int flags) | ||
1231 | { | ||
1232 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
1233 | return parport_ip32_epp_write(priv->regs.eppAddr, p, buf, len, flags); | ||
1234 | } | ||
1235 | |||
1236 | /*--- ECP mode functions (FIFO) ----------------------------------------*/ | ||
1237 | |||
1238 | /** | ||
1239 | * parport_ip32_fifo_wait_break - check if the waiting function should return | ||
1240 | * @p: pointer to &struct parport | ||
1241 | * @expire: timeout expiring date, in jiffies | ||
1242 | * | ||
1243 | * parport_ip32_fifo_wait_break() checks if the waiting function should return | ||
1244 | * immediately or not. The break conditions are: | ||
1245 | * - expired timeout; | ||
1246 | * - a pending signal; | ||
1247 | * - nFault asserted low. | ||
1248 | * This function also calls cond_resched(). | ||
1249 | */ | ||
1250 | static unsigned int parport_ip32_fifo_wait_break(struct parport *p, | ||
1251 | unsigned long expire) | ||
1252 | { | ||
1253 | cond_resched(); | ||
1254 | if (time_after(jiffies, expire)) { | ||
1255 | pr_debug1(PPIP32 "%s: FIFO write timed out\n", p->name); | ||
1256 | return 1; | ||
1257 | } | ||
1258 | if (signal_pending(current)) { | ||
1259 | pr_debug1(PPIP32 "%s: Signal pending\n", p->name); | ||
1260 | return 1; | ||
1261 | } | ||
1262 | if (!(parport_ip32_read_status(p) & DSR_nFAULT)) { | ||
1263 | pr_debug1(PPIP32 "%s: nFault asserted low\n", p->name); | ||
1264 | return 1; | ||
1265 | } | ||
1266 | return 0; | ||
1267 | } | ||
1268 | |||
1269 | /** | ||
1270 | * parport_ip32_fwp_wait_polling - wait for FIFO to empty (polling) | ||
1271 | * @p: pointer to &struct parport | ||
1272 | * | ||
1273 | * Returns the number of bytes that can safely be written in the FIFO. A | ||
1274 | * return value of zero means that the calling function should terminate as | ||
1275 | * fast as possible. | ||
1276 | */ | ||
1277 | static unsigned int parport_ip32_fwp_wait_polling(struct parport *p) | ||
1278 | { | ||
1279 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
1280 | struct parport * const physport = p->physport; | ||
1281 | unsigned long expire; | ||
1282 | unsigned int count; | ||
1283 | unsigned int ecr; | ||
1284 | |||
1285 | expire = jiffies + physport->cad->timeout; | ||
1286 | count = 0; | ||
1287 | while (1) { | ||
1288 | if (parport_ip32_fifo_wait_break(p, expire)) | ||
1289 | break; | ||
1290 | |||
1291 | /* Check FIFO state. We do nothing when the FIFO is nor full, | ||
1292 | * nor empty. It appears that the FIFO full bit is not always | ||
1293 | * reliable, the FIFO state is sometimes wrongly reported, and | ||
1294 | * the chip gets confused if we give it another byte. */ | ||
1295 | ecr = parport_ip32_read_econtrol(p); | ||
1296 | if (ecr & ECR_F_EMPTY) { | ||
1297 | /* FIFO is empty, fill it up */ | ||
1298 | count = priv->fifo_depth; | ||
1299 | break; | ||
1300 | } | ||
1301 | |||
1302 | /* Wait a moment... */ | ||
1303 | udelay(FIFO_POLLING_INTERVAL); | ||
1304 | } /* while (1) */ | ||
1305 | |||
1306 | return count; | ||
1307 | } | ||
1308 | |||
1309 | /** | ||
1310 | * parport_ip32_fwp_wait_interrupt - wait for FIFO to empty (interrupt-driven) | ||
1311 | * @p: pointer to &struct parport | ||
1312 | * | ||
1313 | * Returns the number of bytes that can safely be written in the FIFO. A | ||
1314 | * return value of zero means that the calling function should terminate as | ||
1315 | * fast as possible. | ||
1316 | */ | ||
1317 | static unsigned int parport_ip32_fwp_wait_interrupt(struct parport *p) | ||
1318 | { | ||
1319 | static unsigned int lost_interrupt = 0; | ||
1320 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
1321 | struct parport * const physport = p->physport; | ||
1322 | unsigned long nfault_timeout; | ||
1323 | unsigned long expire; | ||
1324 | unsigned int count; | ||
1325 | unsigned int ecr; | ||
1326 | |||
1327 | nfault_timeout = min((unsigned long)physport->cad->timeout, | ||
1328 | msecs_to_jiffies(FIFO_NFAULT_TIMEOUT)); | ||
1329 | expire = jiffies + physport->cad->timeout; | ||
1330 | count = 0; | ||
1331 | while (1) { | ||
1332 | if (parport_ip32_fifo_wait_break(p, expire)) | ||
1333 | break; | ||
1334 | |||
1335 | /* Initialize mutex used to take interrupts into account */ | ||
1336 | INIT_COMPLETION(priv->irq_complete); | ||
1337 | |||
1338 | /* Enable serviceIntr */ | ||
1339 | parport_ip32_frob_econtrol(p, ECR_SERVINTR, 0); | ||
1340 | |||
1341 | /* Enabling serviceIntr while the FIFO is empty does not | ||
1342 | * always generate an interrupt, so check for emptiness | ||
1343 | * now. */ | ||
1344 | ecr = parport_ip32_read_econtrol(p); | ||
1345 | if (!(ecr & ECR_F_EMPTY)) { | ||
1346 | /* FIFO is not empty: wait for an interrupt or a | ||
1347 | * timeout to occur */ | ||
1348 | wait_for_completion_interruptible_timeout( | ||
1349 | &priv->irq_complete, nfault_timeout); | ||
1350 | ecr = parport_ip32_read_econtrol(p); | ||
1351 | if ((ecr & ECR_F_EMPTY) && !(ecr & ECR_SERVINTR) | ||
1352 | && !lost_interrupt) { | ||
1353 | printk(KERN_WARNING PPIP32 | ||
1354 | "%s: lost interrupt in %s\n", | ||
1355 | p->name, __func__); | ||
1356 | lost_interrupt = 1; | ||
1357 | } | ||
1358 | } | ||
1359 | |||
1360 | /* Disable serviceIntr */ | ||
1361 | parport_ip32_frob_econtrol(p, ECR_SERVINTR, ECR_SERVINTR); | ||
1362 | |||
1363 | /* Check FIFO state */ | ||
1364 | if (ecr & ECR_F_EMPTY) { | ||
1365 | /* FIFO is empty, fill it up */ | ||
1366 | count = priv->fifo_depth; | ||
1367 | break; | ||
1368 | } else if (ecr & ECR_SERVINTR) { | ||
1369 | /* FIFO is not empty, but we know that can safely push | ||
1370 | * writeIntrThreshold bytes into it */ | ||
1371 | count = priv->writeIntrThreshold; | ||
1372 | break; | ||
1373 | } | ||
1374 | /* FIFO is not empty, and we did not get any interrupt. | ||
1375 | * Either it's time to check for nFault, or a signal is | ||
1376 | * pending. This is verified in | ||
1377 | * parport_ip32_fifo_wait_break(), so we continue the loop. */ | ||
1378 | } /* while (1) */ | ||
1379 | |||
1380 | return count; | ||
1381 | } | ||
1382 | |||
1383 | /** | ||
1384 | * parport_ip32_fifo_write_block_pio - write a block of data (PIO mode) | ||
1385 | * @p: pointer to &struct parport | ||
1386 | * @buf: buffer of data to write | ||
1387 | * @len: length of buffer @buf | ||
1388 | * | ||
1389 | * Uses PIO to write the contents of the buffer @buf into the parallel port | ||
1390 | * FIFO. Returns the number of bytes that were actually written. It can work | ||
1391 | * with or without the help of interrupts. The parallel port must be | ||
1392 | * correctly initialized before calling parport_ip32_fifo_write_block_pio(). | ||
1393 | */ | ||
1394 | static size_t parport_ip32_fifo_write_block_pio(struct parport *p, | ||
1395 | const void *buf, size_t len) | ||
1396 | { | ||
1397 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
1398 | const u8 *bufp = buf; | ||
1399 | size_t left = len; | ||
1400 | |||
1401 | priv->irq_mode = PARPORT_IP32_IRQ_HERE; | ||
1402 | |||
1403 | while (left > 0) { | ||
1404 | unsigned int count; | ||
1405 | |||
1406 | count = (p->irq == PARPORT_IRQ_NONE) ? | ||
1407 | parport_ip32_fwp_wait_polling(p) : | ||
1408 | parport_ip32_fwp_wait_interrupt(p); | ||
1409 | if (count == 0) | ||
1410 | break; /* Transmission should be stopped */ | ||
1411 | if (count > left) | ||
1412 | count = left; | ||
1413 | if (count == 1) { | ||
1414 | writeb(*bufp, priv->regs.fifo); | ||
1415 | bufp++, left--; | ||
1416 | } else { | ||
1417 | writesb(priv->regs.fifo, bufp, count); | ||
1418 | bufp += count, left -= count; | ||
1419 | } | ||
1420 | } | ||
1421 | |||
1422 | priv->irq_mode = PARPORT_IP32_IRQ_FWD; | ||
1423 | |||
1424 | return len - left; | ||
1425 | } | ||
1426 | |||
1427 | /** | ||
1428 | * parport_ip32_fifo_write_block_dma - write a block of data (DMA mode) | ||
1429 | * @p: pointer to &struct parport | ||
1430 | * @buf: buffer of data to write | ||
1431 | * @len: length of buffer @buf | ||
1432 | * | ||
1433 | * Uses DMA to write the contents of the buffer @buf into the parallel port | ||
1434 | * FIFO. Returns the number of bytes that were actually written. The | ||
1435 | * parallel port must be correctly initialized before calling | ||
1436 | * parport_ip32_fifo_write_block_dma(). | ||
1437 | */ | ||
1438 | static size_t parport_ip32_fifo_write_block_dma(struct parport *p, | ||
1439 | const void *buf, size_t len) | ||
1440 | { | ||
1441 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
1442 | struct parport * const physport = p->physport; | ||
1443 | unsigned long nfault_timeout; | ||
1444 | unsigned long expire; | ||
1445 | size_t written; | ||
1446 | unsigned int ecr; | ||
1447 | |||
1448 | priv->irq_mode = PARPORT_IP32_IRQ_HERE; | ||
1449 | |||
1450 | parport_ip32_dma_start(DMA_TO_DEVICE, (void *)buf, len); | ||
1451 | INIT_COMPLETION(priv->irq_complete); | ||
1452 | parport_ip32_frob_econtrol(p, ECR_DMAEN | ECR_SERVINTR, ECR_DMAEN); | ||
1453 | |||
1454 | nfault_timeout = min((unsigned long)physport->cad->timeout, | ||
1455 | msecs_to_jiffies(FIFO_NFAULT_TIMEOUT)); | ||
1456 | expire = jiffies + physport->cad->timeout; | ||
1457 | while (1) { | ||
1458 | if (parport_ip32_fifo_wait_break(p, expire)) | ||
1459 | break; | ||
1460 | wait_for_completion_interruptible_timeout(&priv->irq_complete, | ||
1461 | nfault_timeout); | ||
1462 | ecr = parport_ip32_read_econtrol(p); | ||
1463 | if (ecr & ECR_SERVINTR) | ||
1464 | break; /* DMA transfer just finished */ | ||
1465 | } | ||
1466 | parport_ip32_dma_stop(); | ||
1467 | written = len - parport_ip32_dma_get_residue(); | ||
1468 | |||
1469 | priv->irq_mode = PARPORT_IP32_IRQ_FWD; | ||
1470 | |||
1471 | return written; | ||
1472 | } | ||
1473 | |||
1474 | /** | ||
1475 | * parport_ip32_fifo_write_block - write a block of data | ||
1476 | * @p: pointer to &struct parport | ||
1477 | * @buf: buffer of data to write | ||
1478 | * @len: length of buffer @buf | ||
1479 | * | ||
1480 | * Uses PIO or DMA to write the contents of the buffer @buf into the parallel | ||
1481 | * p FIFO. Returns the number of bytes that were actually written. | ||
1482 | */ | ||
1483 | static size_t parport_ip32_fifo_write_block(struct parport *p, | ||
1484 | const void *buf, size_t len) | ||
1485 | { | ||
1486 | size_t written = 0; | ||
1487 | if (len) | ||
1488 | /* FIXME - Maybe some threshold value should be set for @len | ||
1489 | * under which we revert to PIO mode? */ | ||
1490 | written = (p->modes & PARPORT_MODE_DMA) ? | ||
1491 | parport_ip32_fifo_write_block_dma(p, buf, len) : | ||
1492 | parport_ip32_fifo_write_block_pio(p, buf, len); | ||
1493 | return written; | ||
1494 | } | ||
1495 | |||
1496 | /** | ||
1497 | * parport_ip32_drain_fifo - wait for FIFO to empty | ||
1498 | * @p: pointer to &struct parport | ||
1499 | * @timeout: timeout, in jiffies | ||
1500 | * | ||
1501 | * This function waits for FIFO to empty. It returns 1 when FIFO is empty, or | ||
1502 | * 0 if the timeout @timeout is reached before, or if a signal is pending. | ||
1503 | */ | ||
1504 | static unsigned int parport_ip32_drain_fifo(struct parport *p, | ||
1505 | unsigned long timeout) | ||
1506 | { | ||
1507 | unsigned long expire = jiffies + timeout; | ||
1508 | unsigned int polling_interval; | ||
1509 | unsigned int counter; | ||
1510 | |||
1511 | /* Busy wait for approx. 200us */ | ||
1512 | for (counter = 0; counter < 40; counter++) { | ||
1513 | if (parport_ip32_read_econtrol(p) & ECR_F_EMPTY) | ||
1514 | break; | ||
1515 | if (time_after(jiffies, expire)) | ||
1516 | break; | ||
1517 | if (signal_pending(current)) | ||
1518 | break; | ||
1519 | udelay(5); | ||
1520 | } | ||
1521 | /* Poll slowly. Polling interval starts with 1 millisecond, and is | ||
1522 | * increased exponentially until 128. */ | ||
1523 | polling_interval = 1; /* msecs */ | ||
1524 | while (!(parport_ip32_read_econtrol(p) & ECR_F_EMPTY)) { | ||
1525 | if (time_after_eq(jiffies, expire)) | ||
1526 | break; | ||
1527 | msleep_interruptible(polling_interval); | ||
1528 | if (signal_pending(current)) | ||
1529 | break; | ||
1530 | if (polling_interval < 128) | ||
1531 | polling_interval *= 2; | ||
1532 | } | ||
1533 | |||
1534 | return !!(parport_ip32_read_econtrol(p) & ECR_F_EMPTY); | ||
1535 | } | ||
1536 | |||
1537 | /** | ||
1538 | * parport_ip32_get_fifo_residue - reset FIFO | ||
1539 | * @p: pointer to &struct parport | ||
1540 | * @mode: current operation mode (ECR_MODE_PPF or ECR_MODE_ECP) | ||
1541 | * | ||
1542 | * This function resets FIFO, and returns the number of bytes remaining in it. | ||
1543 | */ | ||
1544 | static unsigned int parport_ip32_get_fifo_residue(struct parport *p, | ||
1545 | unsigned int mode) | ||
1546 | { | ||
1547 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
1548 | unsigned int residue; | ||
1549 | unsigned int cnfga; | ||
1550 | |||
1551 | /* FIXME - We are missing one byte if the printer is off-line. I | ||
1552 | * don't know how to detect this. It looks that the full bit is not | ||
1553 | * always reliable. For the moment, the problem is avoided in most | ||
1554 | * cases by testing for BUSY in parport_ip32_compat_write_data(). | ||
1555 | */ | ||
1556 | if (parport_ip32_read_econtrol(p) & ECR_F_EMPTY) | ||
1557 | residue = 0; | ||
1558 | else { | ||
1559 | pr_debug1(PPIP32 "%s: FIFO is stuck\n", p->name); | ||
1560 | |||
1561 | /* Stop all transfers. | ||
1562 | * | ||
1563 | * Microsoft's document instructs to drive DCR_STROBE to 0, | ||
1564 | * but it doesn't work (at least in Compatibility mode, not | ||
1565 | * tested in ECP mode). Switching directly to Test mode (as | ||
1566 | * in parport_pc) is not an option: it does confuse the port, | ||
1567 | * ECP service interrupts are no more working after that. A | ||
1568 | * hard reset is then needed to revert to a sane state. | ||
1569 | * | ||
1570 | * Let's hope that the FIFO is really stuck and that the | ||
1571 | * peripheral doesn't wake up now. | ||
1572 | */ | ||
1573 | parport_ip32_frob_control(p, DCR_STROBE, 0); | ||
1574 | |||
1575 | /* Fill up FIFO */ | ||
1576 | for (residue = priv->fifo_depth; residue > 0; residue--) { | ||
1577 | if (parport_ip32_read_econtrol(p) & ECR_F_FULL) | ||
1578 | break; | ||
1579 | writeb(0x00, priv->regs.fifo); | ||
1580 | } | ||
1581 | } | ||
1582 | if (residue) | ||
1583 | pr_debug1(PPIP32 "%s: %d PWord%s left in FIFO\n", | ||
1584 | p->name, residue, | ||
1585 | (residue == 1) ? " was" : "s were"); | ||
1586 | |||
1587 | /* Now reset the FIFO */ | ||
1588 | parport_ip32_set_mode(p, ECR_MODE_PS2); | ||
1589 | |||
1590 | /* Host recovery for ECP mode */ | ||
1591 | if (mode == ECR_MODE_ECP) { | ||
1592 | parport_ip32_data_reverse(p); | ||
1593 | parport_ip32_frob_control(p, DCR_nINIT, 0); | ||
1594 | if (parport_wait_peripheral(p, DSR_PERROR, 0)) | ||
1595 | pr_debug1(PPIP32 "%s: PEerror timeout 1 in %s\n", | ||
1596 | p->name, __func__); | ||
1597 | parport_ip32_frob_control(p, DCR_STROBE, DCR_STROBE); | ||
1598 | parport_ip32_frob_control(p, DCR_nINIT, DCR_nINIT); | ||
1599 | if (parport_wait_peripheral(p, DSR_PERROR, DSR_PERROR)) | ||
1600 | pr_debug1(PPIP32 "%s: PEerror timeout 2 in %s\n", | ||
1601 | p->name, __func__); | ||
1602 | } | ||
1603 | |||
1604 | /* Adjust residue if needed */ | ||
1605 | parport_ip32_set_mode(p, ECR_MODE_CFG); | ||
1606 | cnfga = readb(priv->regs.cnfgA); | ||
1607 | if (!(cnfga & CNFGA_nBYTEINTRANS)) { | ||
1608 | pr_debug1(PPIP32 "%s: cnfgA contains 0x%02x\n", | ||
1609 | p->name, cnfga); | ||
1610 | pr_debug1(PPIP32 "%s: Accounting for extra byte\n", | ||
1611 | p->name); | ||
1612 | residue++; | ||
1613 | } | ||
1614 | |||
1615 | /* Don't care about partial PWords since we do not support | ||
1616 | * PWord != 1 byte. */ | ||
1617 | |||
1618 | /* Back to forward PS2 mode. */ | ||
1619 | parport_ip32_set_mode(p, ECR_MODE_PS2); | ||
1620 | parport_ip32_data_forward(p); | ||
1621 | |||
1622 | return residue; | ||
1623 | } | ||
1624 | |||
1625 | /** | ||
1626 | * parport_ip32_compat_write_data - write a block of data in SPP mode | ||
1627 | * @p: pointer to &struct parport | ||
1628 | * @buf: buffer of data to write | ||
1629 | * @len: length of buffer @buf | ||
1630 | * @flags: ignored | ||
1631 | */ | ||
1632 | static size_t parport_ip32_compat_write_data(struct parport *p, | ||
1633 | const void *buf, size_t len, | ||
1634 | int flags) | ||
1635 | { | ||
1636 | static unsigned int ready_before = 1; | ||
1637 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
1638 | struct parport * const physport = p->physport; | ||
1639 | size_t written = 0; | ||
1640 | |||
1641 | /* Special case: a timeout of zero means we cannot call schedule(). | ||
1642 | * Also if O_NONBLOCK is set then use the default implementation. */ | ||
1643 | if (physport->cad->timeout <= PARPORT_INACTIVITY_O_NONBLOCK) | ||
1644 | return parport_ieee1284_write_compat(p, buf, len, flags); | ||
1645 | |||
1646 | /* Reset FIFO, go in forward mode, and disable ackIntEn */ | ||
1647 | parport_ip32_set_mode(p, ECR_MODE_PS2); | ||
1648 | parport_ip32_write_control(p, DCR_SELECT | DCR_nINIT); | ||
1649 | parport_ip32_data_forward(p); | ||
1650 | parport_ip32_disable_irq(p); | ||
1651 | parport_ip32_set_mode(p, ECR_MODE_PPF); | ||
1652 | physport->ieee1284.phase = IEEE1284_PH_FWD_DATA; | ||
1653 | |||
1654 | /* Wait for peripheral to become ready */ | ||
1655 | if (parport_wait_peripheral(p, DSR_nBUSY | DSR_nFAULT, | ||
1656 | DSR_nBUSY | DSR_nFAULT)) { | ||
1657 | /* Avoid to flood the logs */ | ||
1658 | if (ready_before) | ||
1659 | printk(KERN_INFO PPIP32 "%s: not ready in %s\n", | ||
1660 | p->name, __func__); | ||
1661 | ready_before = 0; | ||
1662 | goto stop; | ||
1663 | } | ||
1664 | ready_before = 1; | ||
1665 | |||
1666 | written = parport_ip32_fifo_write_block(p, buf, len); | ||
1667 | |||
1668 | /* Wait FIFO to empty. Timeout is proportional to FIFO_depth. */ | ||
1669 | parport_ip32_drain_fifo(p, physport->cad->timeout * priv->fifo_depth); | ||
1670 | |||
1671 | /* Check for a potential residue */ | ||
1672 | written -= parport_ip32_get_fifo_residue(p, ECR_MODE_PPF); | ||
1673 | |||
1674 | /* Then, wait for BUSY to get low. */ | ||
1675 | if (parport_wait_peripheral(p, DSR_nBUSY, DSR_nBUSY)) | ||
1676 | printk(KERN_DEBUG PPIP32 "%s: BUSY timeout in %s\n", | ||
1677 | p->name, __func__); | ||
1678 | |||
1679 | stop: | ||
1680 | /* Reset FIFO */ | ||
1681 | parport_ip32_set_mode(p, ECR_MODE_PS2); | ||
1682 | physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE; | ||
1683 | |||
1684 | return written; | ||
1685 | } | ||
1686 | |||
1687 | /* | ||
1688 | * FIXME - Insert here parport_ip32_ecp_read_data(). | ||
1689 | */ | ||
1690 | |||
1691 | /** | ||
1692 | * parport_ip32_ecp_write_data - write a block of data in ECP mode | ||
1693 | * @p: pointer to &struct parport | ||
1694 | * @buf: buffer of data to write | ||
1695 | * @len: length of buffer @buf | ||
1696 | * @flags: ignored | ||
1697 | */ | ||
1698 | static size_t parport_ip32_ecp_write_data(struct parport *p, | ||
1699 | const void *buf, size_t len, | ||
1700 | int flags) | ||
1701 | { | ||
1702 | static unsigned int ready_before = 1; | ||
1703 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
1704 | struct parport * const physport = p->physport; | ||
1705 | size_t written = 0; | ||
1706 | |||
1707 | /* Special case: a timeout of zero means we cannot call schedule(). | ||
1708 | * Also if O_NONBLOCK is set then use the default implementation. */ | ||
1709 | if (physport->cad->timeout <= PARPORT_INACTIVITY_O_NONBLOCK) | ||
1710 | return parport_ieee1284_ecp_write_data(p, buf, len, flags); | ||
1711 | |||
1712 | /* Negotiate to forward mode if necessary. */ | ||
1713 | if (physport->ieee1284.phase != IEEE1284_PH_FWD_IDLE) { | ||
1714 | /* Event 47: Set nInit high. */ | ||
1715 | parport_ip32_frob_control(p, DCR_nINIT | DCR_AUTOFD, | ||
1716 | DCR_nINIT | DCR_AUTOFD); | ||
1717 | |||
1718 | /* Event 49: PError goes high. */ | ||
1719 | if (parport_wait_peripheral(p, DSR_PERROR, DSR_PERROR)) { | ||
1720 | printk(KERN_DEBUG PPIP32 "%s: PError timeout in %s", | ||
1721 | p->name, __func__); | ||
1722 | physport->ieee1284.phase = IEEE1284_PH_ECP_DIR_UNKNOWN; | ||
1723 | return 0; | ||
1724 | } | ||
1725 | } | ||
1726 | |||
1727 | /* Reset FIFO, go in forward mode, and disable ackIntEn */ | ||
1728 | parport_ip32_set_mode(p, ECR_MODE_PS2); | ||
1729 | parport_ip32_write_control(p, DCR_SELECT | DCR_nINIT); | ||
1730 | parport_ip32_data_forward(p); | ||
1731 | parport_ip32_disable_irq(p); | ||
1732 | parport_ip32_set_mode(p, ECR_MODE_ECP); | ||
1733 | physport->ieee1284.phase = IEEE1284_PH_FWD_DATA; | ||
1734 | |||
1735 | /* Wait for peripheral to become ready */ | ||
1736 | if (parport_wait_peripheral(p, DSR_nBUSY | DSR_nFAULT, | ||
1737 | DSR_nBUSY | DSR_nFAULT)) { | ||
1738 | /* Avoid to flood the logs */ | ||
1739 | if (ready_before) | ||
1740 | printk(KERN_INFO PPIP32 "%s: not ready in %s\n", | ||
1741 | p->name, __func__); | ||
1742 | ready_before = 0; | ||
1743 | goto stop; | ||
1744 | } | ||
1745 | ready_before = 1; | ||
1746 | |||
1747 | written = parport_ip32_fifo_write_block(p, buf, len); | ||
1748 | |||
1749 | /* Wait FIFO to empty. Timeout is proportional to FIFO_depth. */ | ||
1750 | parport_ip32_drain_fifo(p, physport->cad->timeout * priv->fifo_depth); | ||
1751 | |||
1752 | /* Check for a potential residue */ | ||
1753 | written -= parport_ip32_get_fifo_residue(p, ECR_MODE_ECP); | ||
1754 | |||
1755 | /* Then, wait for BUSY to get low. */ | ||
1756 | if (parport_wait_peripheral(p, DSR_nBUSY, DSR_nBUSY)) | ||
1757 | printk(KERN_DEBUG PPIP32 "%s: BUSY timeout in %s\n", | ||
1758 | p->name, __func__); | ||
1759 | |||
1760 | stop: | ||
1761 | /* Reset FIFO */ | ||
1762 | parport_ip32_set_mode(p, ECR_MODE_PS2); | ||
1763 | physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE; | ||
1764 | |||
1765 | return written; | ||
1766 | } | ||
1767 | |||
1768 | /* | ||
1769 | * FIXME - Insert here parport_ip32_ecp_write_addr(). | ||
1770 | */ | ||
1771 | |||
1772 | /*--- Default parport operations ---------------------------------------*/ | ||
1773 | |||
1774 | static __initdata struct parport_operations parport_ip32_ops = { | ||
1775 | .write_data = parport_ip32_write_data, | ||
1776 | .read_data = parport_ip32_read_data, | ||
1777 | |||
1778 | .write_control = parport_ip32_write_control, | ||
1779 | .read_control = parport_ip32_read_control, | ||
1780 | .frob_control = parport_ip32_frob_control, | ||
1781 | |||
1782 | .read_status = parport_ip32_read_status, | ||
1783 | |||
1784 | .enable_irq = parport_ip32_enable_irq, | ||
1785 | .disable_irq = parport_ip32_disable_irq, | ||
1786 | |||
1787 | .data_forward = parport_ip32_data_forward, | ||
1788 | .data_reverse = parport_ip32_data_reverse, | ||
1789 | |||
1790 | .init_state = parport_ip32_init_state, | ||
1791 | .save_state = parport_ip32_save_state, | ||
1792 | .restore_state = parport_ip32_restore_state, | ||
1793 | |||
1794 | .epp_write_data = parport_ieee1284_epp_write_data, | ||
1795 | .epp_read_data = parport_ieee1284_epp_read_data, | ||
1796 | .epp_write_addr = parport_ieee1284_epp_write_addr, | ||
1797 | .epp_read_addr = parport_ieee1284_epp_read_addr, | ||
1798 | |||
1799 | .ecp_write_data = parport_ieee1284_ecp_write_data, | ||
1800 | .ecp_read_data = parport_ieee1284_ecp_read_data, | ||
1801 | .ecp_write_addr = parport_ieee1284_ecp_write_addr, | ||
1802 | |||
1803 | .compat_write_data = parport_ieee1284_write_compat, | ||
1804 | .nibble_read_data = parport_ieee1284_read_nibble, | ||
1805 | .byte_read_data = parport_ieee1284_read_byte, | ||
1806 | |||
1807 | .owner = THIS_MODULE, | ||
1808 | }; | ||
1809 | |||
1810 | /*--- Device detection -------------------------------------------------*/ | ||
1811 | |||
1812 | /** | ||
1813 | * parport_ip32_ecp_supported - check for an ECP port | ||
1814 | * @p: pointer to the &parport structure | ||
1815 | * | ||
1816 | * Returns 1 if an ECP port is found, and 0 otherwise. This function actually | ||
1817 | * checks if an Extended Control Register seems to be present. On successful | ||
1818 | * return, the port is placed in SPP mode. | ||
1819 | */ | ||
1820 | static __init unsigned int parport_ip32_ecp_supported(struct parport *p) | ||
1821 | { | ||
1822 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
1823 | unsigned int ecr; | ||
1824 | |||
1825 | ecr = ECR_MODE_PS2 | ECR_nERRINTR | ECR_SERVINTR; | ||
1826 | writeb(ecr, priv->regs.ecr); | ||
1827 | if (readb(priv->regs.ecr) != (ecr | ECR_F_EMPTY)) | ||
1828 | goto fail; | ||
1829 | |||
1830 | pr_probe(p, "Found working ECR register\n"); | ||
1831 | parport_ip32_set_mode(p, ECR_MODE_SPP); | ||
1832 | parport_ip32_write_control(p, DCR_SELECT | DCR_nINIT); | ||
1833 | return 1; | ||
1834 | |||
1835 | fail: | ||
1836 | pr_probe(p, "ECR register not found\n"); | ||
1837 | return 0; | ||
1838 | } | ||
1839 | |||
1840 | /** | ||
1841 | * parport_ip32_fifo_supported - check for FIFO parameters | ||
1842 | * @p: pointer to the &parport structure | ||
1843 | * | ||
1844 | * Check for FIFO parameters of an Extended Capabilities Port. Returns 1 on | ||
1845 | * success, and 0 otherwise. Adjust FIFO parameters in the parport structure. | ||
1846 | * On return, the port is placed in SPP mode. | ||
1847 | */ | ||
1848 | static __init unsigned int parport_ip32_fifo_supported(struct parport *p) | ||
1849 | { | ||
1850 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
1851 | unsigned int configa, configb; | ||
1852 | unsigned int pword; | ||
1853 | unsigned int i; | ||
1854 | |||
1855 | /* Configuration mode */ | ||
1856 | parport_ip32_set_mode(p, ECR_MODE_CFG); | ||
1857 | configa = readb(priv->regs.cnfgA); | ||
1858 | configb = readb(priv->regs.cnfgB); | ||
1859 | |||
1860 | /* Find out PWord size */ | ||
1861 | switch (configa & CNFGA_ID_MASK) { | ||
1862 | case CNFGA_ID_8: | ||
1863 | pword = 1; | ||
1864 | break; | ||
1865 | case CNFGA_ID_16: | ||
1866 | pword = 2; | ||
1867 | break; | ||
1868 | case CNFGA_ID_32: | ||
1869 | pword = 4; | ||
1870 | break; | ||
1871 | default: | ||
1872 | pr_probe(p, "Unknown implementation ID: 0x%0x\n", | ||
1873 | (configa & CNFGA_ID_MASK) >> CNFGA_ID_SHIFT); | ||
1874 | goto fail; | ||
1875 | break; | ||
1876 | } | ||
1877 | if (pword != 1) { | ||
1878 | pr_probe(p, "Unsupported PWord size: %u\n", pword); | ||
1879 | goto fail; | ||
1880 | } | ||
1881 | priv->pword = pword; | ||
1882 | pr_probe(p, "PWord is %u bits\n", 8 * priv->pword); | ||
1883 | |||
1884 | /* Check for compression support */ | ||
1885 | writeb(configb | CNFGB_COMPRESS, priv->regs.cnfgB); | ||
1886 | if (readb(priv->regs.cnfgB) & CNFGB_COMPRESS) | ||
1887 | pr_probe(p, "Hardware compression detected (unsupported)\n"); | ||
1888 | writeb(configb & ~CNFGB_COMPRESS, priv->regs.cnfgB); | ||
1889 | |||
1890 | /* Reset FIFO and go in test mode (no interrupt, no DMA) */ | ||
1891 | parport_ip32_set_mode(p, ECR_MODE_TST); | ||
1892 | |||
1893 | /* FIFO must be empty now */ | ||
1894 | if (!(readb(priv->regs.ecr) & ECR_F_EMPTY)) { | ||
1895 | pr_probe(p, "FIFO not reset\n"); | ||
1896 | goto fail; | ||
1897 | } | ||
1898 | |||
1899 | /* Find out FIFO depth. */ | ||
1900 | priv->fifo_depth = 0; | ||
1901 | for (i = 0; i < 1024; i++) { | ||
1902 | if (readb(priv->regs.ecr) & ECR_F_FULL) { | ||
1903 | /* FIFO full */ | ||
1904 | priv->fifo_depth = i; | ||
1905 | break; | ||
1906 | } | ||
1907 | writeb((u8)i, priv->regs.fifo); | ||
1908 | } | ||
1909 | if (i >= 1024) { | ||
1910 | pr_probe(p, "Can't fill FIFO\n"); | ||
1911 | goto fail; | ||
1912 | } | ||
1913 | if (!priv->fifo_depth) { | ||
1914 | pr_probe(p, "Can't get FIFO depth\n"); | ||
1915 | goto fail; | ||
1916 | } | ||
1917 | pr_probe(p, "FIFO is %u PWords deep\n", priv->fifo_depth); | ||
1918 | |||
1919 | /* Enable interrupts */ | ||
1920 | parport_ip32_frob_econtrol(p, ECR_SERVINTR, 0); | ||
1921 | |||
1922 | /* Find out writeIntrThreshold: number of PWords we know we can write | ||
1923 | * if we get an interrupt. */ | ||
1924 | priv->writeIntrThreshold = 0; | ||
1925 | for (i = 0; i < priv->fifo_depth; i++) { | ||
1926 | if (readb(priv->regs.fifo) != (u8)i) { | ||
1927 | pr_probe(p, "Invalid data in FIFO\n"); | ||
1928 | goto fail; | ||
1929 | } | ||
1930 | if (!priv->writeIntrThreshold | ||
1931 | && readb(priv->regs.ecr) & ECR_SERVINTR) | ||
1932 | /* writeIntrThreshold reached */ | ||
1933 | priv->writeIntrThreshold = i + 1; | ||
1934 | if (i + 1 < priv->fifo_depth | ||
1935 | && readb(priv->regs.ecr) & ECR_F_EMPTY) { | ||
1936 | /* FIFO empty before the last byte? */ | ||
1937 | pr_probe(p, "Data lost in FIFO\n"); | ||
1938 | goto fail; | ||
1939 | } | ||
1940 | } | ||
1941 | if (!priv->writeIntrThreshold) { | ||
1942 | pr_probe(p, "Can't get writeIntrThreshold\n"); | ||
1943 | goto fail; | ||
1944 | } | ||
1945 | pr_probe(p, "writeIntrThreshold is %u\n", priv->writeIntrThreshold); | ||
1946 | |||
1947 | /* FIFO must be empty now */ | ||
1948 | if (!(readb(priv->regs.ecr) & ECR_F_EMPTY)) { | ||
1949 | pr_probe(p, "Can't empty FIFO\n"); | ||
1950 | goto fail; | ||
1951 | } | ||
1952 | |||
1953 | /* Reset FIFO */ | ||
1954 | parport_ip32_set_mode(p, ECR_MODE_PS2); | ||
1955 | /* Set reverse direction (must be in PS2 mode) */ | ||
1956 | parport_ip32_data_reverse(p); | ||
1957 | /* Test FIFO, no interrupt, no DMA */ | ||
1958 | parport_ip32_set_mode(p, ECR_MODE_TST); | ||
1959 | /* Enable interrupts */ | ||
1960 | parport_ip32_frob_econtrol(p, ECR_SERVINTR, 0); | ||
1961 | |||
1962 | /* Find out readIntrThreshold: number of PWords we can read if we get | ||
1963 | * an interrupt. */ | ||
1964 | priv->readIntrThreshold = 0; | ||
1965 | for (i = 0; i < priv->fifo_depth; i++) { | ||
1966 | writeb(0xaa, priv->regs.fifo); | ||
1967 | if (readb(priv->regs.ecr) & ECR_SERVINTR) { | ||
1968 | /* readIntrThreshold reached */ | ||
1969 | priv->readIntrThreshold = i + 1; | ||
1970 | break; | ||
1971 | } | ||
1972 | } | ||
1973 | if (!priv->readIntrThreshold) { | ||
1974 | pr_probe(p, "Can't get readIntrThreshold\n"); | ||
1975 | goto fail; | ||
1976 | } | ||
1977 | pr_probe(p, "readIntrThreshold is %u\n", priv->readIntrThreshold); | ||
1978 | |||
1979 | /* Reset ECR */ | ||
1980 | parport_ip32_set_mode(p, ECR_MODE_PS2); | ||
1981 | parport_ip32_data_forward(p); | ||
1982 | parport_ip32_set_mode(p, ECR_MODE_SPP); | ||
1983 | return 1; | ||
1984 | |||
1985 | fail: | ||
1986 | priv->fifo_depth = 0; | ||
1987 | parport_ip32_set_mode(p, ECR_MODE_SPP); | ||
1988 | return 0; | ||
1989 | } | ||
1990 | |||
1991 | /*--- Initialization code ----------------------------------------------*/ | ||
1992 | |||
1993 | /** | ||
1994 | * parport_ip32_make_isa_registers - compute (ISA) register addresses | ||
1995 | * @regs: pointer to &struct parport_ip32_regs to fill | ||
1996 | * @base: base address of standard and EPP registers | ||
1997 | * @base_hi: base address of ECP registers | ||
1998 | * @regshift: how much to shift register offset by | ||
1999 | * | ||
2000 | * Compute register addresses, according to the ISA standard. The addresses | ||
2001 | * of the standard and EPP registers are computed from address @base. The | ||
2002 | * addresses of the ECP registers are computed from address @base_hi. | ||
2003 | */ | ||
2004 | static void __init | ||
2005 | parport_ip32_make_isa_registers(struct parport_ip32_regs *regs, | ||
2006 | void __iomem *base, void __iomem *base_hi, | ||
2007 | unsigned int regshift) | ||
2008 | { | ||
2009 | #define r_base(offset) ((u8 __iomem *)base + ((offset) << regshift)) | ||
2010 | #define r_base_hi(offset) ((u8 __iomem *)base_hi + ((offset) << regshift)) | ||
2011 | *regs = (struct parport_ip32_regs){ | ||
2012 | .data = r_base(0), | ||
2013 | .dsr = r_base(1), | ||
2014 | .dcr = r_base(2), | ||
2015 | .eppAddr = r_base(3), | ||
2016 | .eppData0 = r_base(4), | ||
2017 | .eppData1 = r_base(5), | ||
2018 | .eppData2 = r_base(6), | ||
2019 | .eppData3 = r_base(7), | ||
2020 | .ecpAFifo = r_base(0), | ||
2021 | .fifo = r_base_hi(0), | ||
2022 | .cnfgA = r_base_hi(0), | ||
2023 | .cnfgB = r_base_hi(1), | ||
2024 | .ecr = r_base_hi(2) | ||
2025 | }; | ||
2026 | #undef r_base_hi | ||
2027 | #undef r_base | ||
2028 | } | ||
2029 | |||
2030 | /** | ||
2031 | * parport_ip32_probe_port - probe and register IP32 built-in parallel port | ||
2032 | * | ||
2033 | * Returns the new allocated &parport structure. On error, an error code is | ||
2034 | * encoded in return value with the ERR_PTR function. | ||
2035 | */ | ||
2036 | static __init struct parport *parport_ip32_probe_port(void) | ||
2037 | { | ||
2038 | struct parport_ip32_regs regs; | ||
2039 | struct parport_ip32_private *priv = NULL; | ||
2040 | struct parport_operations *ops = NULL; | ||
2041 | struct parport *p = NULL; | ||
2042 | int err; | ||
2043 | |||
2044 | parport_ip32_make_isa_registers(®s, &mace->isa.parallel, | ||
2045 | &mace->isa.ecp1284, 8 /* regshift */); | ||
2046 | |||
2047 | ops = kmalloc(sizeof(struct parport_operations), GFP_KERNEL); | ||
2048 | priv = kmalloc(sizeof(struct parport_ip32_private), GFP_KERNEL); | ||
2049 | p = parport_register_port(0, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, ops); | ||
2050 | if (ops == NULL || priv == NULL || p == NULL) { | ||
2051 | err = -ENOMEM; | ||
2052 | goto fail; | ||
2053 | } | ||
2054 | p->base = MACE_BASE + offsetof(struct sgi_mace, isa.parallel); | ||
2055 | p->base_hi = MACE_BASE + offsetof(struct sgi_mace, isa.ecp1284); | ||
2056 | p->private_data = priv; | ||
2057 | |||
2058 | *ops = parport_ip32_ops; | ||
2059 | *priv = (struct parport_ip32_private){ | ||
2060 | .regs = regs, | ||
2061 | .dcr_writable = DCR_DIR | DCR_SELECT | DCR_nINIT | | ||
2062 | DCR_AUTOFD | DCR_STROBE, | ||
2063 | .irq_mode = PARPORT_IP32_IRQ_FWD, | ||
2064 | }; | ||
2065 | init_completion(&priv->irq_complete); | ||
2066 | |||
2067 | /* Probe port. */ | ||
2068 | if (!parport_ip32_ecp_supported(p)) { | ||
2069 | err = -ENODEV; | ||
2070 | goto fail; | ||
2071 | } | ||
2072 | parport_ip32_dump_state(p, "begin init", 0); | ||
2073 | |||
2074 | /* We found what looks like a working ECR register. Simply assume | ||
2075 | * that all modes are correctly supported. Enable basic modes. */ | ||
2076 | p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT; | ||
2077 | p->modes |= PARPORT_MODE_TRISTATE; | ||
2078 | |||
2079 | if (!parport_ip32_fifo_supported(p)) { | ||
2080 | printk(KERN_WARNING PPIP32 | ||
2081 | "%s: error: FIFO disabled\n", p->name); | ||
2082 | /* Disable hardware modes depending on a working FIFO. */ | ||
2083 | features &= ~PARPORT_IP32_ENABLE_SPP; | ||
2084 | features &= ~PARPORT_IP32_ENABLE_ECP; | ||
2085 | /* DMA is not needed if FIFO is not supported. */ | ||
2086 | features &= ~PARPORT_IP32_ENABLE_DMA; | ||
2087 | } | ||
2088 | |||
2089 | /* Request IRQ */ | ||
2090 | if (features & PARPORT_IP32_ENABLE_IRQ) { | ||
2091 | int irq = MACEISA_PARALLEL_IRQ; | ||
2092 | if (request_irq(irq, parport_ip32_interrupt, 0, p->name, p)) { | ||
2093 | printk(KERN_WARNING PPIP32 | ||
2094 | "%s: error: IRQ disabled\n", p->name); | ||
2095 | /* DMA cannot work without interrupts. */ | ||
2096 | features &= ~PARPORT_IP32_ENABLE_DMA; | ||
2097 | } else { | ||
2098 | pr_probe(p, "Interrupt support enabled\n"); | ||
2099 | p->irq = irq; | ||
2100 | priv->dcr_writable |= DCR_IRQ; | ||
2101 | } | ||
2102 | } | ||
2103 | |||
2104 | /* Allocate DMA resources */ | ||
2105 | if (features & PARPORT_IP32_ENABLE_DMA) { | ||
2106 | if (parport_ip32_dma_register()) | ||
2107 | printk(KERN_WARNING PPIP32 | ||
2108 | "%s: error: DMA disabled\n", p->name); | ||
2109 | else { | ||
2110 | pr_probe(p, "DMA support enabled\n"); | ||
2111 | p->dma = 0; /* arbitrary value != PARPORT_DMA_NONE */ | ||
2112 | p->modes |= PARPORT_MODE_DMA; | ||
2113 | } | ||
2114 | } | ||
2115 | |||
2116 | if (features & PARPORT_IP32_ENABLE_SPP) { | ||
2117 | /* Enable compatibility FIFO mode */ | ||
2118 | p->ops->compat_write_data = parport_ip32_compat_write_data; | ||
2119 | p->modes |= PARPORT_MODE_COMPAT; | ||
2120 | pr_probe(p, "Hardware support for SPP mode enabled\n"); | ||
2121 | } | ||
2122 | if (features & PARPORT_IP32_ENABLE_EPP) { | ||
2123 | /* Set up access functions to use EPP hardware. */ | ||
2124 | p->ops->epp_read_data = parport_ip32_epp_read_data; | ||
2125 | p->ops->epp_write_data = parport_ip32_epp_write_data; | ||
2126 | p->ops->epp_read_addr = parport_ip32_epp_read_addr; | ||
2127 | p->ops->epp_write_addr = parport_ip32_epp_write_addr; | ||
2128 | p->modes |= PARPORT_MODE_EPP; | ||
2129 | pr_probe(p, "Hardware support for EPP mode enabled\n"); | ||
2130 | } | ||
2131 | if (features & PARPORT_IP32_ENABLE_ECP) { | ||
2132 | /* Enable ECP FIFO mode */ | ||
2133 | p->ops->ecp_write_data = parport_ip32_ecp_write_data; | ||
2134 | /* FIXME - not implemented */ | ||
2135 | /* p->ops->ecp_read_data = parport_ip32_ecp_read_data; */ | ||
2136 | /* p->ops->ecp_write_addr = parport_ip32_ecp_write_addr; */ | ||
2137 | p->modes |= PARPORT_MODE_ECP; | ||
2138 | pr_probe(p, "Hardware support for ECP mode enabled\n"); | ||
2139 | } | ||
2140 | |||
2141 | /* Initialize the port with sensible values */ | ||
2142 | parport_ip32_set_mode(p, ECR_MODE_PS2); | ||
2143 | parport_ip32_write_control(p, DCR_SELECT | DCR_nINIT); | ||
2144 | parport_ip32_data_forward(p); | ||
2145 | parport_ip32_disable_irq(p); | ||
2146 | parport_ip32_write_data(p, 0x00); | ||
2147 | parport_ip32_dump_state(p, "end init", 0); | ||
2148 | |||
2149 | /* Print out what we found */ | ||
2150 | printk(KERN_INFO "%s: SGI IP32 at 0x%lx (0x%lx)", | ||
2151 | p->name, p->base, p->base_hi); | ||
2152 | if (p->irq != PARPORT_IRQ_NONE) | ||
2153 | printk(", irq %d", p->irq); | ||
2154 | printk(" ["); | ||
2155 | #define printmode(x) if (p->modes & PARPORT_MODE_##x) \ | ||
2156 | printk("%s%s", f++ ? "," : "", #x) | ||
2157 | { | ||
2158 | unsigned int f = 0; | ||
2159 | printmode(PCSPP); | ||
2160 | printmode(TRISTATE); | ||
2161 | printmode(COMPAT); | ||
2162 | printmode(EPP); | ||
2163 | printmode(ECP); | ||
2164 | printmode(DMA); | ||
2165 | } | ||
2166 | #undef printmode | ||
2167 | printk("]\n"); | ||
2168 | |||
2169 | parport_announce_port(p); | ||
2170 | return p; | ||
2171 | |||
2172 | fail: | ||
2173 | if (p) | ||
2174 | parport_put_port(p); | ||
2175 | kfree(priv); | ||
2176 | kfree(ops); | ||
2177 | return ERR_PTR(err); | ||
2178 | } | ||
2179 | |||
2180 | /** | ||
2181 | * parport_ip32_unregister_port - unregister a parallel port | ||
2182 | * @p: pointer to the &struct parport | ||
2183 | * | ||
2184 | * Unregisters a parallel port and free previously allocated resources | ||
2185 | * (memory, IRQ, ...). | ||
2186 | */ | ||
2187 | static __exit void parport_ip32_unregister_port(struct parport *p) | ||
2188 | { | ||
2189 | struct parport_ip32_private * const priv = p->physport->private_data; | ||
2190 | struct parport_operations *ops = p->ops; | ||
2191 | |||
2192 | parport_remove_port(p); | ||
2193 | if (p->modes & PARPORT_MODE_DMA) | ||
2194 | parport_ip32_dma_unregister(); | ||
2195 | if (p->irq != PARPORT_IRQ_NONE) | ||
2196 | free_irq(p->irq, p); | ||
2197 | parport_put_port(p); | ||
2198 | kfree(priv); | ||
2199 | kfree(ops); | ||
2200 | } | ||
2201 | |||
2202 | /** | ||
2203 | * parport_ip32_init - module initialization function | ||
2204 | */ | ||
2205 | static int __init parport_ip32_init(void) | ||
2206 | { | ||
2207 | pr_info(PPIP32 "SGI IP32 built-in parallel port driver v0.6\n"); | ||
2208 | pr_debug1(PPIP32 "Compiled on %s, %s\n", __DATE__, __TIME__); | ||
2209 | this_port = parport_ip32_probe_port(); | ||
2210 | return IS_ERR(this_port) ? PTR_ERR(this_port) : 0; | ||
2211 | } | ||
2212 | |||
2213 | /** | ||
2214 | * parport_ip32_exit - module termination function | ||
2215 | */ | ||
2216 | static void __exit parport_ip32_exit(void) | ||
2217 | { | ||
2218 | parport_ip32_unregister_port(this_port); | ||
2219 | } | ||
2220 | |||
2221 | /*--- Module stuff -----------------------------------------------------*/ | ||
2222 | |||
2223 | MODULE_AUTHOR("Arnaud Giersch <arnaud.giersch@free.fr>"); | ||
2224 | MODULE_DESCRIPTION("SGI IP32 built-in parallel port driver"); | ||
2225 | MODULE_LICENSE("GPL"); | ||
2226 | MODULE_VERSION("0.6"); /* update in parport_ip32_init() too */ | ||
2227 | |||
2228 | module_init(parport_ip32_init); | ||
2229 | module_exit(parport_ip32_exit); | ||
2230 | |||
2231 | module_param(verbose_probing, bool, S_IRUGO); | ||
2232 | MODULE_PARM_DESC(verbose_probing, "Log chit-chat during initialization"); | ||
2233 | |||
2234 | module_param(features, uint, S_IRUGO); | ||
2235 | MODULE_PARM_DESC(features, | ||
2236 | "Bit mask of features to enable" | ||
2237 | ", bit 0: IRQ support" | ||
2238 | ", bit 1: DMA support" | ||
2239 | ", bit 2: hardware SPP mode" | ||
2240 | ", bit 3: hardware EPP mode" | ||
2241 | ", bit 4: hardware ECP mode"); | ||
2242 | |||
2243 | /*--- Inform (X)Emacs about preferred coding style ---------------------*/ | ||
2244 | /* | ||
2245 | * Local Variables: | ||
2246 | * mode: c | ||
2247 | * c-file-style: "linux" | ||
2248 | * indent-tabs-mode: t | ||
2249 | * tab-width: 8 | ||
2250 | * fill-column: 78 | ||
2251 | * ispell-local-dictionary: "american" | ||
2252 | * End: | ||
2253 | */ | ||
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c index 76dd077e3184..166de3507780 100644 --- a/drivers/parport/parport_serial.c +++ b/drivers/parport/parport_serial.c | |||
@@ -329,9 +329,9 @@ static int __devinit parport_register (struct pci_dev *dev, | |||
329 | 329 | ||
330 | if (priv->num_par == ARRAY_SIZE (priv->port)) { | 330 | if (priv->num_par == ARRAY_SIZE (priv->port)) { |
331 | printk (KERN_WARNING | 331 | printk (KERN_WARNING |
332 | "parport_serial: %s: only %u parallel ports " | 332 | "parport_serial: %s: only %zu parallel ports " |
333 | "supported (%d reported)\n", pci_name (dev), | 333 | "supported (%d reported)\n", pci_name (dev), |
334 | ARRAY_SIZE (priv->port), card->numports); | 334 | ARRAY_SIZE(priv->port), card->numports); |
335 | break; | 335 | break; |
336 | } | 336 | } |
337 | 337 | ||
diff --git a/drivers/parport/probe.c b/drivers/parport/probe.c index b62aee8de3cb..ea83b70e0de2 100644 --- a/drivers/parport/probe.c +++ b/drivers/parport/probe.c | |||
@@ -199,7 +199,7 @@ static ssize_t parport_read_device_id (struct parport *port, char *buffer, | |||
199 | 199 | ||
200 | if (port->physport->ieee1284.phase != IEEE1284_PH_HBUSY_DAVAIL) { | 200 | if (port->physport->ieee1284.phase != IEEE1284_PH_HBUSY_DAVAIL) { |
201 | if (belen != len) { | 201 | if (belen != len) { |
202 | printk (KERN_DEBUG "%s: Device ID was %d bytes" | 202 | printk (KERN_DEBUG "%s: Device ID was %zd bytes" |
203 | " while device told it would be %d" | 203 | " while device told it would be %d" |
204 | " bytes\n", | 204 | " bytes\n", |
205 | port->name, len, belen); | 205 | port->name, len, belen); |
@@ -214,7 +214,7 @@ static ssize_t parport_read_device_id (struct parport *port, char *buffer, | |||
214 | if (buffer[len-1] == ';') { | 214 | if (buffer[len-1] == ';') { |
215 | printk (KERN_DEBUG "%s: Device ID reading stopped" | 215 | printk (KERN_DEBUG "%s: Device ID reading stopped" |
216 | " before device told data not available. " | 216 | " before device told data not available. " |
217 | "Current idlen %d of %d, len bytes %02X %02X\n", | 217 | "Current idlen %u of %u, len bytes %02X %02X\n", |
218 | port->name, current_idlen, numidlens, | 218 | port->name, current_idlen, numidlens, |
219 | length[0], length[1]); | 219 | length[0], length[1]); |
220 | goto done; | 220 | goto done; |
diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig index 6f50cc9323d9..6912399d0937 100644 --- a/drivers/s390/block/Kconfig +++ b/drivers/s390/block/Kconfig | |||
@@ -55,13 +55,21 @@ config DASD_DIAG | |||
55 | Disks under VM. If you are not running under VM or unsure what it is, | 55 | Disks under VM. If you are not running under VM or unsure what it is, |
56 | say "N". | 56 | say "N". |
57 | 57 | ||
58 | config DASD_EER | ||
59 | tristate "Extended error reporting (EER)" | ||
60 | depends on DASD | ||
61 | help | ||
62 | This driver provides a character device interface to the | ||
63 | DASD extended error reporting. This is only needed if you want to | ||
64 | use applications written for the EER facility. | ||
65 | |||
58 | config DASD_CMB | 66 | config DASD_CMB |
59 | tristate "Compatibility interface for DASD channel measurement blocks" | 67 | tristate "Compatibility interface for DASD channel measurement blocks" |
60 | depends on DASD | 68 | depends on DASD |
61 | help | 69 | help |
62 | This driver provides an additional interface to the channel measurement | 70 | This driver provides an additional interface to the channel |
63 | facility, which is normally accessed though sysfs, with a set of | 71 | measurement facility, which is normally accessed though sysfs, with |
64 | ioctl functions specific to the dasd driver. | 72 | a set of ioctl functions specific to the dasd driver. |
65 | This is only needed if you want to use applications written for | 73 | This is only needed if you want to use applications written for |
66 | linux-2.4 dasd channel measurement facility interface. | 74 | linux-2.4 dasd channel measurement facility interface. |
67 | 75 | ||
diff --git a/drivers/s390/block/Makefile b/drivers/s390/block/Makefile index 58c6780134f7..0c0d871e8f51 100644 --- a/drivers/s390/block/Makefile +++ b/drivers/s390/block/Makefile | |||
@@ -5,6 +5,7 @@ | |||
5 | dasd_eckd_mod-objs := dasd_eckd.o dasd_3990_erp.o dasd_9343_erp.o | 5 | dasd_eckd_mod-objs := dasd_eckd.o dasd_3990_erp.o dasd_9343_erp.o |
6 | dasd_fba_mod-objs := dasd_fba.o dasd_3370_erp.o dasd_9336_erp.o | 6 | dasd_fba_mod-objs := dasd_fba.o dasd_3370_erp.o dasd_9336_erp.o |
7 | dasd_diag_mod-objs := dasd_diag.o | 7 | dasd_diag_mod-objs := dasd_diag.o |
8 | dasd_eer_mod-objs := dasd_eer.o | ||
8 | dasd_mod-objs := dasd.o dasd_ioctl.o dasd_proc.o dasd_devmap.o \ | 9 | dasd_mod-objs := dasd.o dasd_ioctl.o dasd_proc.o dasd_devmap.o \ |
9 | dasd_genhd.o dasd_erp.o | 10 | dasd_genhd.o dasd_erp.o |
10 | 11 | ||
@@ -13,5 +14,6 @@ obj-$(CONFIG_DASD_DIAG) += dasd_diag_mod.o | |||
13 | obj-$(CONFIG_DASD_ECKD) += dasd_eckd_mod.o | 14 | obj-$(CONFIG_DASD_ECKD) += dasd_eckd_mod.o |
14 | obj-$(CONFIG_DASD_FBA) += dasd_fba_mod.o | 15 | obj-$(CONFIG_DASD_FBA) += dasd_fba_mod.o |
15 | obj-$(CONFIG_DASD_CMB) += dasd_cmb.o | 16 | obj-$(CONFIG_DASD_CMB) += dasd_cmb.o |
17 | obj-$(CONFIG_DASD_EER) += dasd_eer.o | ||
16 | obj-$(CONFIG_BLK_DEV_XPRAM) += xpram.o | 18 | obj-$(CONFIG_BLK_DEV_XPRAM) += xpram.o |
17 | obj-$(CONFIG_DCSSBLK) += dcssblk.o | 19 | obj-$(CONFIG_DCSSBLK) += dcssblk.o |
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index abdf1ee633e7..08c88fcd8963 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/buffer_head.h> | 19 | #include <linux/buffer_head.h> |
20 | #include <linux/hdreg.h> | 20 | #include <linux/hdreg.h> |
21 | #include <linux/notifier.h> | ||
21 | 22 | ||
22 | #include <asm/ccwdev.h> | 23 | #include <asm/ccwdev.h> |
23 | #include <asm/ebcdic.h> | 24 | #include <asm/ebcdic.h> |
@@ -57,6 +58,7 @@ static void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *); | |||
57 | static void dasd_flush_ccw_queue(struct dasd_device *, int); | 58 | static void dasd_flush_ccw_queue(struct dasd_device *, int); |
58 | static void dasd_tasklet(struct dasd_device *); | 59 | static void dasd_tasklet(struct dasd_device *); |
59 | static void do_kick_device(void *data); | 60 | static void do_kick_device(void *data); |
61 | static void dasd_disable_eer(struct dasd_device *device); | ||
60 | 62 | ||
61 | /* | 63 | /* |
62 | * SECTION: Operations on the device structure. | 64 | * SECTION: Operations on the device structure. |
@@ -151,6 +153,8 @@ dasd_state_new_to_known(struct dasd_device *device) | |||
151 | static inline void | 153 | static inline void |
152 | dasd_state_known_to_new(struct dasd_device * device) | 154 | dasd_state_known_to_new(struct dasd_device * device) |
153 | { | 155 | { |
156 | /* disable extended error reporting for this device */ | ||
157 | dasd_disable_eer(device); | ||
154 | /* Forget the discipline information. */ | 158 | /* Forget the discipline information. */ |
155 | device->discipline = NULL; | 159 | device->discipline = NULL; |
156 | device->state = DASD_STATE_NEW; | 160 | device->state = DASD_STATE_NEW; |
@@ -867,6 +871,9 @@ dasd_handle_state_change_pending(struct dasd_device *device) | |||
867 | struct dasd_ccw_req *cqr; | 871 | struct dasd_ccw_req *cqr; |
868 | struct list_head *l, *n; | 872 | struct list_head *l, *n; |
869 | 873 | ||
874 | /* first of all call extended error reporting */ | ||
875 | dasd_write_eer_trigger(DASD_EER_STATECHANGE, device, NULL); | ||
876 | |||
870 | device->stopped &= ~DASD_STOPPED_PENDING; | 877 | device->stopped &= ~DASD_STOPPED_PENDING; |
871 | 878 | ||
872 | /* restart all 'running' IO on queue */ | 879 | /* restart all 'running' IO on queue */ |
@@ -1086,6 +1093,19 @@ restart: | |||
1086 | } | 1093 | } |
1087 | goto restart; | 1094 | goto restart; |
1088 | } | 1095 | } |
1096 | |||
1097 | /* first of all call extended error reporting */ | ||
1098 | if (device->eer && cqr->status == DASD_CQR_FAILED) { | ||
1099 | dasd_write_eer_trigger(DASD_EER_FATALERROR, | ||
1100 | device, cqr); | ||
1101 | |||
1102 | /* restart request */ | ||
1103 | cqr->status = DASD_CQR_QUEUED; | ||
1104 | cqr->retries = 255; | ||
1105 | device->stopped |= DASD_STOPPED_QUIESCE; | ||
1106 | goto restart; | ||
1107 | } | ||
1108 | |||
1089 | /* Process finished ERP request. */ | 1109 | /* Process finished ERP request. */ |
1090 | if (cqr->refers) { | 1110 | if (cqr->refers) { |
1091 | __dasd_process_erp(device, cqr); | 1111 | __dasd_process_erp(device, cqr); |
@@ -1223,7 +1243,8 @@ __dasd_start_head(struct dasd_device * device) | |||
1223 | cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list); | 1243 | cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list); |
1224 | /* check FAILFAST */ | 1244 | /* check FAILFAST */ |
1225 | if (device->stopped & ~DASD_STOPPED_PENDING && | 1245 | if (device->stopped & ~DASD_STOPPED_PENDING && |
1226 | test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags)) { | 1246 | test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) && |
1247 | (!device->eer)) { | ||
1227 | cqr->status = DASD_CQR_FAILED; | 1248 | cqr->status = DASD_CQR_FAILED; |
1228 | dasd_schedule_bh(device); | 1249 | dasd_schedule_bh(device); |
1229 | } | 1250 | } |
@@ -1965,6 +1986,9 @@ dasd_generic_notify(struct ccw_device *cdev, int event) | |||
1965 | switch (event) { | 1986 | switch (event) { |
1966 | case CIO_GONE: | 1987 | case CIO_GONE: |
1967 | case CIO_NO_PATH: | 1988 | case CIO_NO_PATH: |
1989 | /* first of all call extended error reporting */ | ||
1990 | dasd_write_eer_trigger(DASD_EER_NOPATH, device, NULL); | ||
1991 | |||
1968 | if (device->state < DASD_STATE_BASIC) | 1992 | if (device->state < DASD_STATE_BASIC) |
1969 | break; | 1993 | break; |
1970 | /* Device is active. We want to keep it. */ | 1994 | /* Device is active. We want to keep it. */ |
@@ -2022,6 +2046,51 @@ dasd_generic_auto_online (struct ccw_driver *dasd_discipline_driver) | |||
2022 | put_driver(drv); | 2046 | put_driver(drv); |
2023 | } | 2047 | } |
2024 | 2048 | ||
2049 | /* | ||
2050 | * notifications for extended error reports | ||
2051 | */ | ||
2052 | static struct notifier_block *dasd_eer_chain; | ||
2053 | |||
2054 | int | ||
2055 | dasd_register_eer_notifier(struct notifier_block *nb) | ||
2056 | { | ||
2057 | return notifier_chain_register(&dasd_eer_chain, nb); | ||
2058 | } | ||
2059 | |||
2060 | int | ||
2061 | dasd_unregister_eer_notifier(struct notifier_block *nb) | ||
2062 | { | ||
2063 | return notifier_chain_unregister(&dasd_eer_chain, nb); | ||
2064 | } | ||
2065 | |||
2066 | /* | ||
2067 | * Notify the registered error reporting module of a problem | ||
2068 | */ | ||
2069 | void | ||
2070 | dasd_write_eer_trigger(unsigned int id, struct dasd_device *device, | ||
2071 | struct dasd_ccw_req *cqr) | ||
2072 | { | ||
2073 | if (device->eer) { | ||
2074 | struct dasd_eer_trigger temp; | ||
2075 | temp.id = id; | ||
2076 | temp.device = device; | ||
2077 | temp.cqr = cqr; | ||
2078 | notifier_call_chain(&dasd_eer_chain, DASD_EER_TRIGGER, | ||
2079 | (void *)&temp); | ||
2080 | } | ||
2081 | } | ||
2082 | |||
2083 | /* | ||
2084 | * Tell the registered error reporting module to disable error reporting for | ||
2085 | * a given device and to cleanup any private data structures on that device. | ||
2086 | */ | ||
2087 | static void | ||
2088 | dasd_disable_eer(struct dasd_device *device) | ||
2089 | { | ||
2090 | notifier_call_chain(&dasd_eer_chain, DASD_EER_DISABLE, (void *)device); | ||
2091 | } | ||
2092 | |||
2093 | |||
2025 | static int __init | 2094 | static int __init |
2026 | dasd_init(void) | 2095 | dasd_init(void) |
2027 | { | 2096 | { |
@@ -2103,6 +2172,11 @@ EXPORT_SYMBOL_GPL(dasd_generic_set_online); | |||
2103 | EXPORT_SYMBOL_GPL(dasd_generic_set_offline); | 2172 | EXPORT_SYMBOL_GPL(dasd_generic_set_offline); |
2104 | EXPORT_SYMBOL_GPL(dasd_generic_auto_online); | 2173 | EXPORT_SYMBOL_GPL(dasd_generic_auto_online); |
2105 | 2174 | ||
2175 | EXPORT_SYMBOL(dasd_register_eer_notifier); | ||
2176 | EXPORT_SYMBOL(dasd_unregister_eer_notifier); | ||
2177 | EXPORT_SYMBOL(dasd_write_eer_trigger); | ||
2178 | |||
2179 | |||
2106 | /* | 2180 | /* |
2107 | * Overrides for Emacs so that we follow Linus's tabbing style. | 2181 | * Overrides for Emacs so that we follow Linus's tabbing style. |
2108 | * Emacs will notice this stuff at the end of the file and automatically | 2182 | * Emacs will notice this stuff at the end of the file and automatically |
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index 4ee0f934e325..c811380b9079 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c | |||
@@ -1108,6 +1108,9 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense) | |||
1108 | case 0x0B: | 1108 | case 0x0B: |
1109 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 1109 | DEV_MESSAGE(KERN_WARNING, device, "%s", |
1110 | "FORMAT F - Volume is suspended duplex"); | 1110 | "FORMAT F - Volume is suspended duplex"); |
1111 | /* call extended error reporting (EER) */ | ||
1112 | dasd_write_eer_trigger(DASD_EER_PPRCSUSPEND, device, | ||
1113 | erp->refers); | ||
1111 | break; | 1114 | break; |
1112 | case 0x0C: | 1115 | case 0x0C: |
1113 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 1116 | DEV_MESSAGE(KERN_WARNING, device, "%s", |
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index bc3823d35223..e15dd7978050 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h | |||
@@ -29,6 +29,7 @@ | |||
29 | #define DASD_ECKD_CCW_PSF 0x27 | 29 | #define DASD_ECKD_CCW_PSF 0x27 |
30 | #define DASD_ECKD_CCW_RSSD 0x3e | 30 | #define DASD_ECKD_CCW_RSSD 0x3e |
31 | #define DASD_ECKD_CCW_LOCATE_RECORD 0x47 | 31 | #define DASD_ECKD_CCW_LOCATE_RECORD 0x47 |
32 | #define DASD_ECKD_CCW_SNSS 0x54 | ||
32 | #define DASD_ECKD_CCW_DEFINE_EXTENT 0x63 | 33 | #define DASD_ECKD_CCW_DEFINE_EXTENT 0x63 |
33 | #define DASD_ECKD_CCW_WRITE_MT 0x85 | 34 | #define DASD_ECKD_CCW_WRITE_MT 0x85 |
34 | #define DASD_ECKD_CCW_READ_MT 0x86 | 35 | #define DASD_ECKD_CCW_READ_MT 0x86 |
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c new file mode 100644 index 000000000000..f70cd7716b24 --- /dev/null +++ b/drivers/s390/block/dasd_eer.c | |||
@@ -0,0 +1,1090 @@ | |||
1 | /* | ||
2 | * character device driver for extended error reporting | ||
3 | * | ||
4 | * | ||
5 | * Copyright (C) 2005 IBM Corporation | ||
6 | * extended error reporting for DASD ECKD devices | ||
7 | * Author(s): Stefan Weinhuber <wein@de.ibm.com> | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include <linux/init.h> | ||
12 | #include <linux/fs.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/miscdevice.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/moduleparam.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/workqueue.h> | ||
19 | #include <linux/poll.h> | ||
20 | #include <linux/notifier.h> | ||
21 | |||
22 | #include <asm/uaccess.h> | ||
23 | #include <asm/semaphore.h> | ||
24 | #include <asm/atomic.h> | ||
25 | #include <asm/ebcdic.h> | ||
26 | |||
27 | #include "dasd_int.h" | ||
28 | #include "dasd_eckd.h" | ||
29 | |||
30 | |||
31 | MODULE_LICENSE("GPL"); | ||
32 | |||
33 | MODULE_AUTHOR("Stefan Weinhuber <wein@de.ibm.com>"); | ||
34 | MODULE_DESCRIPTION("DASD extended error reporting module"); | ||
35 | |||
36 | |||
37 | #ifdef PRINTK_HEADER | ||
38 | #undef PRINTK_HEADER | ||
39 | #endif /* PRINTK_HEADER */ | ||
40 | #define PRINTK_HEADER "dasd(eer):" | ||
41 | |||
42 | |||
43 | |||
44 | |||
45 | |||
46 | /*****************************************************************************/ | ||
47 | /* the internal buffer */ | ||
48 | /*****************************************************************************/ | ||
49 | |||
50 | /* | ||
51 | * The internal buffer is meant to store obaque blobs of data, so it doesn't | ||
52 | * know of higher level concepts like triggers. | ||
53 | * It consists of a number of pages that are used as a ringbuffer. Each data | ||
54 | * blob is stored in a simple record that consists of an integer, which | ||
55 | * contains the size of the following data, and the data bytes themselfes. | ||
56 | * | ||
57 | * To allow for multiple independent readers we create one internal buffer | ||
58 | * each time the device is opened and destroy the buffer when the file is | ||
59 | * closed again. | ||
60 | * | ||
61 | * One record can be written to a buffer by using the functions | ||
62 | * - dasd_eer_start_record (one time per record to write the size to the buffer | ||
63 | * and reserve the space for the data) | ||
64 | * - dasd_eer_write_buffer (one or more times per record to write the data) | ||
65 | * The data can be written in several steps but you will have to compute | ||
66 | * the total size up front for the invocation of dasd_eer_start_record. | ||
67 | * If the ringbuffer is full, dasd_eer_start_record will remove the required | ||
68 | * number of old records. | ||
69 | * | ||
70 | * A record is typically read in two steps, first read the integer that | ||
71 | * specifies the size of the following data, then read the data. | ||
72 | * Both can be done by | ||
73 | * - dasd_eer_read_buffer | ||
74 | * | ||
75 | * For all mentioned functions you need to get the bufferlock first and keep it | ||
76 | * until a complete record is written or read. | ||
77 | */ | ||
78 | |||
79 | |||
80 | /* | ||
81 | * Alle information necessary to keep track of an internal buffer is kept in | ||
82 | * a struct eerbuffer. The buffer specific to a file pointer is strored in | ||
83 | * the private_data field of that file. To be able to write data to all | ||
84 | * existing buffers, each buffer is also added to the bufferlist. | ||
85 | * If the user doesn't want to read a complete record in one go, we have to | ||
86 | * keep track of the rest of the record. residual stores the number of bytes | ||
87 | * that are still to deliver. If the rest of the record is invalidated between | ||
88 | * two reads then residual will be set to -1 so that the next read will fail. | ||
89 | * All entries in the eerbuffer structure are protected with the bufferlock. | ||
90 | * To avoid races between writing to a buffer on the one side and creating | ||
91 | * and destroying buffers on the other side, the bufferlock must also be used | ||
92 | * to protect the bufferlist. | ||
93 | */ | ||
94 | |||
95 | struct eerbuffer { | ||
96 | struct list_head list; | ||
97 | char **buffer; | ||
98 | int buffersize; | ||
99 | int buffer_page_count; | ||
100 | int head; | ||
101 | int tail; | ||
102 | int residual; | ||
103 | }; | ||
104 | |||
105 | LIST_HEAD(bufferlist); | ||
106 | |||
107 | static spinlock_t bufferlock = SPIN_LOCK_UNLOCKED; | ||
108 | |||
109 | DECLARE_WAIT_QUEUE_HEAD(dasd_eer_read_wait_queue); | ||
110 | |||
111 | /* | ||
112 | * How many free bytes are available on the buffer. | ||
113 | * needs to be called with bufferlock held | ||
114 | */ | ||
115 | static int | ||
116 | dasd_eer_get_free_bytes(struct eerbuffer *eerb) | ||
117 | { | ||
118 | if (eerb->head < eerb->tail) { | ||
119 | return eerb->tail - eerb->head - 1; | ||
120 | } else | ||
121 | return eerb->buffersize - eerb->head + eerb->tail -1; | ||
122 | } | ||
123 | |||
124 | /* | ||
125 | * How many bytes of buffer space are used. | ||
126 | * needs to be called with bufferlock held | ||
127 | */ | ||
128 | static int | ||
129 | dasd_eer_get_filled_bytes(struct eerbuffer *eerb) | ||
130 | { | ||
131 | |||
132 | if (eerb->head >= eerb->tail) { | ||
133 | return eerb->head - eerb->tail; | ||
134 | } else | ||
135 | return eerb->buffersize - eerb->tail + eerb->head; | ||
136 | } | ||
137 | |||
138 | /* | ||
139 | * The dasd_eer_write_buffer function just copies count bytes of data | ||
140 | * to the buffer. Make sure to call dasd_eer_start_record first, to | ||
141 | * make sure that enough free space is available. | ||
142 | * needs to be called with bufferlock held | ||
143 | */ | ||
144 | static void | ||
145 | dasd_eer_write_buffer(struct eerbuffer *eerb, int count, char *data) | ||
146 | { | ||
147 | |||
148 | unsigned long headindex,localhead; | ||
149 | unsigned long rest, len; | ||
150 | char *nextdata; | ||
151 | |||
152 | nextdata = data; | ||
153 | rest = count; | ||
154 | while (rest > 0) { | ||
155 | headindex = eerb->head / PAGE_SIZE; | ||
156 | localhead = eerb->head % PAGE_SIZE; | ||
157 | len = min(rest, (PAGE_SIZE - localhead)); | ||
158 | memcpy(eerb->buffer[headindex]+localhead, nextdata, len); | ||
159 | nextdata += len; | ||
160 | rest -= len; | ||
161 | eerb->head += len; | ||
162 | if ( eerb->head == eerb->buffersize ) | ||
163 | eerb->head = 0; /* wrap around */ | ||
164 | if (eerb->head > eerb->buffersize) { | ||
165 | MESSAGE(KERN_ERR, "%s", "runaway buffer head."); | ||
166 | BUG(); | ||
167 | } | ||
168 | } | ||
169 | } | ||
170 | |||
171 | /* | ||
172 | * needs to be called with bufferlock held | ||
173 | */ | ||
174 | static int | ||
175 | dasd_eer_read_buffer(struct eerbuffer *eerb, int count, char *data) | ||
176 | { | ||
177 | |||
178 | unsigned long tailindex,localtail; | ||
179 | unsigned long rest, len, finalcount; | ||
180 | char *nextdata; | ||
181 | |||
182 | finalcount = min(count, dasd_eer_get_filled_bytes(eerb)); | ||
183 | nextdata = data; | ||
184 | rest = finalcount; | ||
185 | while (rest > 0) { | ||
186 | tailindex = eerb->tail / PAGE_SIZE; | ||
187 | localtail = eerb->tail % PAGE_SIZE; | ||
188 | len = min(rest, (PAGE_SIZE - localtail)); | ||
189 | memcpy(nextdata, eerb->buffer[tailindex]+localtail, len); | ||
190 | nextdata += len; | ||
191 | rest -= len; | ||
192 | eerb->tail += len; | ||
193 | if ( eerb->tail == eerb->buffersize ) | ||
194 | eerb->tail = 0; /* wrap around */ | ||
195 | if (eerb->tail > eerb->buffersize) { | ||
196 | MESSAGE(KERN_ERR, "%s", "runaway buffer tail."); | ||
197 | BUG(); | ||
198 | } | ||
199 | } | ||
200 | return finalcount; | ||
201 | } | ||
202 | |||
203 | /* | ||
204 | * Whenever you want to write a blob of data to the internal buffer you | ||
205 | * have to start by using this function first. It will write the number | ||
206 | * of bytes that will be written to the buffer. If necessary it will remove | ||
207 | * old records to make room for the new one. | ||
208 | * needs to be called with bufferlock held | ||
209 | */ | ||
210 | static int | ||
211 | dasd_eer_start_record(struct eerbuffer *eerb, int count) | ||
212 | { | ||
213 | int tailcount; | ||
214 | if (count + sizeof(count) > eerb->buffersize) | ||
215 | return -ENOMEM; | ||
216 | while (dasd_eer_get_free_bytes(eerb) < count + sizeof(count)) { | ||
217 | if (eerb->residual > 0) { | ||
218 | eerb->tail += eerb->residual; | ||
219 | if (eerb->tail >= eerb->buffersize) | ||
220 | eerb->tail -= eerb->buffersize; | ||
221 | eerb->residual = -1; | ||
222 | } | ||
223 | dasd_eer_read_buffer(eerb, sizeof(tailcount), | ||
224 | (char*)(&tailcount)); | ||
225 | eerb->tail += tailcount; | ||
226 | if (eerb->tail >= eerb->buffersize) | ||
227 | eerb->tail -= eerb->buffersize; | ||
228 | } | ||
229 | dasd_eer_write_buffer(eerb, sizeof(count), (char*)(&count)); | ||
230 | |||
231 | return 0; | ||
232 | }; | ||
233 | |||
234 | /* | ||
235 | * release pages that are not used anymore | ||
236 | */ | ||
237 | static void | ||
238 | dasd_eer_free_buffer_pages(char **buf, int no_pages) | ||
239 | { | ||
240 | int i; | ||
241 | |||
242 | for (i = 0; i < no_pages; ++i) { | ||
243 | free_page((unsigned long)buf[i]); | ||
244 | } | ||
245 | } | ||
246 | |||
247 | /* | ||
248 | * allocate a new set of memory pages | ||
249 | */ | ||
250 | static int | ||
251 | dasd_eer_allocate_buffer_pages(char **buf, int no_pages) | ||
252 | { | ||
253 | int i; | ||
254 | |||
255 | for (i = 0; i < no_pages; ++i) { | ||
256 | buf[i] = (char *) get_zeroed_page(GFP_KERNEL); | ||
257 | if (!buf[i]) { | ||
258 | dasd_eer_free_buffer_pages(buf, i); | ||
259 | return -ENOMEM; | ||
260 | } | ||
261 | } | ||
262 | return 0; | ||
263 | } | ||
264 | |||
265 | /* | ||
266 | * empty the buffer by resetting head and tail | ||
267 | * In case there is a half read data blob in the buffer, we set residual | ||
268 | * to -1 to indicate that the remainder of the blob is lost. | ||
269 | */ | ||
270 | static void | ||
271 | dasd_eer_purge_buffer(struct eerbuffer *eerb) | ||
272 | { | ||
273 | unsigned long flags; | ||
274 | |||
275 | spin_lock_irqsave(&bufferlock, flags); | ||
276 | if (eerb->residual > 0) | ||
277 | eerb->residual = -1; | ||
278 | eerb->tail=0; | ||
279 | eerb->head=0; | ||
280 | spin_unlock_irqrestore(&bufferlock, flags); | ||
281 | } | ||
282 | |||
283 | /* | ||
284 | * set the size of the buffer, newsize is the new number of pages to be used | ||
285 | * we don't try to copy any data back an forth, so any resize will also purge | ||
286 | * the buffer | ||
287 | */ | ||
288 | static int | ||
289 | dasd_eer_resize_buffer(struct eerbuffer *eerb, int newsize) | ||
290 | { | ||
291 | int i, oldcount, reuse; | ||
292 | char **new; | ||
293 | char **old; | ||
294 | unsigned long flags; | ||
295 | |||
296 | if (newsize < 1) | ||
297 | return -EINVAL; | ||
298 | if (eerb->buffer_page_count == newsize) { | ||
299 | /* documented behaviour is that any successfull invocation | ||
300 | * will purge all records */ | ||
301 | dasd_eer_purge_buffer(eerb); | ||
302 | return 0; | ||
303 | } | ||
304 | new = kmalloc(newsize*sizeof(char*), GFP_KERNEL); | ||
305 | if (!new) | ||
306 | return -ENOMEM; | ||
307 | |||
308 | reuse=min(eerb->buffer_page_count, newsize); | ||
309 | for (i = 0; i < reuse; ++i) { | ||
310 | new[i] = eerb->buffer[i]; | ||
311 | } | ||
312 | if (eerb->buffer_page_count < newsize) { | ||
313 | if (dasd_eer_allocate_buffer_pages( | ||
314 | &new[eerb->buffer_page_count], | ||
315 | newsize - eerb->buffer_page_count)) { | ||
316 | kfree(new); | ||
317 | return -ENOMEM; | ||
318 | } | ||
319 | } | ||
320 | |||
321 | spin_lock_irqsave(&bufferlock, flags); | ||
322 | old = eerb->buffer; | ||
323 | eerb->buffer = new; | ||
324 | if (eerb->residual > 0) | ||
325 | eerb->residual = -1; | ||
326 | eerb->tail = 0; | ||
327 | eerb->head = 0; | ||
328 | oldcount = eerb->buffer_page_count; | ||
329 | eerb->buffer_page_count = newsize; | ||
330 | spin_unlock_irqrestore(&bufferlock, flags); | ||
331 | |||
332 | if (oldcount > newsize) { | ||
333 | for (i = newsize; i < oldcount; ++i) { | ||
334 | free_page((unsigned long)old[i]); | ||
335 | } | ||
336 | } | ||
337 | kfree(old); | ||
338 | |||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | |||
343 | /*****************************************************************************/ | ||
344 | /* The extended error reporting functionality */ | ||
345 | /*****************************************************************************/ | ||
346 | |||
347 | /* | ||
348 | * When a DASD device driver wants to report an error, it calls the | ||
349 | * function dasd_eer_write_trigger (via a notifier mechanism) and gives the | ||
350 | * respective trigger ID as parameter. | ||
351 | * Currently there are four kinds of triggers: | ||
352 | * | ||
353 | * DASD_EER_FATALERROR: all kinds of unrecoverable I/O problems | ||
354 | * DASD_EER_PPRCSUSPEND: PPRC was suspended | ||
355 | * DASD_EER_NOPATH: There is no path to the device left. | ||
356 | * DASD_EER_STATECHANGE: The state of the device has changed. | ||
357 | * | ||
358 | * For the first three triggers all required information can be supplied by | ||
359 | * the caller. For these triggers a record is written by the function | ||
360 | * dasd_eer_write_standard_trigger. | ||
361 | * | ||
362 | * When dasd_eer_write_trigger is called to write a DASD_EER_STATECHANGE | ||
363 | * trigger, we have to gather the necessary sense data first. We cannot queue | ||
364 | * the necessary SNSS (sense subsystem status) request immediatly, since we | ||
365 | * are likely to run in a deadlock situation. Instead, we schedule a | ||
366 | * work_struct that calls the function dasd_eer_sense_subsystem_status to | ||
367 | * create and start an SNSS request asynchronously. | ||
368 | * | ||
369 | * To avoid memory allocations at runtime, the necessary memory is allocated | ||
370 | * when the extended error reporting is enabled for a device (by | ||
371 | * dasd_eer_probe). There is one private eer data structure for each eer | ||
372 | * enabled DASD device. It contains memory for the work_struct, one SNSS cqr | ||
373 | * and a flags field that is used to coordinate the use of the cqr. The call | ||
374 | * to write a state change trigger can come in at any time, so we have one flag | ||
375 | * CQR_IN_USE that protects the cqr itself. When this flag indicates that the | ||
376 | * cqr is currently in use, dasd_eer_sense_subsystem_status cannot start a | ||
377 | * second request but sets the SNSS_REQUESTED flag instead. | ||
378 | * | ||
379 | * When the request is finished, the callback function dasd_eer_SNSS_cb | ||
380 | * is called. This function will invoke the function | ||
381 | * dasd_eer_write_SNSS_trigger to finally write the trigger. It will also | ||
382 | * check the SNSS_REQUESTED flag and if it is set it will call | ||
383 | * dasd_eer_sense_subsystem_status again. | ||
384 | * | ||
385 | * To avoid race conditions during the handling of the lock, the flags must | ||
386 | * be protected by the snsslock. | ||
387 | */ | ||
388 | |||
389 | struct dasd_eer_private { | ||
390 | struct dasd_ccw_req *cqr; | ||
391 | unsigned long flags; | ||
392 | struct work_struct worker; | ||
393 | }; | ||
394 | |||
395 | static void dasd_eer_destroy(struct dasd_device *device, | ||
396 | struct dasd_eer_private *eer); | ||
397 | static int | ||
398 | dasd_eer_write_trigger(struct dasd_eer_trigger *trigger); | ||
399 | static void dasd_eer_sense_subsystem_status(void *data); | ||
400 | static int dasd_eer_notify(struct notifier_block *self, | ||
401 | unsigned long action, void *data); | ||
402 | |||
403 | struct workqueue_struct *dasd_eer_workqueue; | ||
404 | |||
405 | #define SNSS_DATA_SIZE 44 | ||
406 | static spinlock_t snsslock = SPIN_LOCK_UNLOCKED; | ||
407 | |||
408 | #define DASD_EER_BUSID_SIZE 10 | ||
409 | struct dasd_eer_header { | ||
410 | __u32 total_size; | ||
411 | __u32 trigger; | ||
412 | __u64 tv_sec; | ||
413 | __u64 tv_usec; | ||
414 | char busid[DASD_EER_BUSID_SIZE]; | ||
415 | } __attribute__ ((packed)); | ||
416 | |||
417 | static struct notifier_block dasd_eer_nb = { | ||
418 | .notifier_call = dasd_eer_notify, | ||
419 | }; | ||
420 | |||
421 | /* | ||
422 | * flags for use with dasd_eer_private | ||
423 | */ | ||
424 | #define CQR_IN_USE 0 | ||
425 | #define SNSS_REQUESTED 1 | ||
426 | |||
427 | /* | ||
428 | * This function checks if extended error reporting is available for a given | ||
429 | * dasd_device. If yes, then it creates and returns a struct dasd_eer, | ||
430 | * otherwise it returns an -EPERM error pointer. | ||
431 | */ | ||
432 | struct dasd_eer_private * | ||
433 | dasd_eer_probe(struct dasd_device *device) | ||
434 | { | ||
435 | struct dasd_eer_private *private; | ||
436 | |||
437 | if (!(device && device->discipline | ||
438 | && !strcmp(device->discipline->name, "ECKD"))) { | ||
439 | return ERR_PTR(-EPERM); | ||
440 | } | ||
441 | /* allocate the private data structure */ | ||
442 | private = (struct dasd_eer_private *)kmalloc( | ||
443 | sizeof(struct dasd_eer_private), GFP_KERNEL); | ||
444 | if (!private) { | ||
445 | return ERR_PTR(-ENOMEM); | ||
446 | } | ||
447 | INIT_WORK(&private->worker, dasd_eer_sense_subsystem_status, | ||
448 | (void *)device); | ||
449 | private->cqr = dasd_kmalloc_request("ECKD", | ||
450 | 1 /* SNSS */ , | ||
451 | SNSS_DATA_SIZE , | ||
452 | device); | ||
453 | if (!private->cqr) { | ||
454 | kfree(private); | ||
455 | return ERR_PTR(-ENOMEM); | ||
456 | } | ||
457 | private->flags = 0; | ||
458 | return private; | ||
459 | }; | ||
460 | |||
461 | /* | ||
462 | * If our private SNSS request is queued, remove it from the | ||
463 | * dasd ccw queue so we can free the requests memory. | ||
464 | */ | ||
465 | static void | ||
466 | dasd_eer_dequeue_SNSS_request(struct dasd_device *device, | ||
467 | struct dasd_eer_private *eer) | ||
468 | { | ||
469 | struct list_head *lst, *nxt; | ||
470 | struct dasd_ccw_req *cqr, *erpcqr; | ||
471 | dasd_erp_fn_t erp_fn; | ||
472 | |||
473 | spin_lock_irq(get_ccwdev_lock(device->cdev)); | ||
474 | list_for_each_safe(lst, nxt, &device->ccw_queue) { | ||
475 | cqr = list_entry(lst, struct dasd_ccw_req, list); | ||
476 | /* we are looking for two kinds or requests */ | ||
477 | /* first kind: our SNSS request: */ | ||
478 | if (cqr == eer->cqr) { | ||
479 | if (cqr->status == DASD_CQR_IN_IO) | ||
480 | device->discipline->term_IO(cqr); | ||
481 | list_del(&cqr->list); | ||
482 | break; | ||
483 | } | ||
484 | /* second kind: ERP requests for our SNSS request */ | ||
485 | if (cqr->refers) { | ||
486 | /* If this erp request chain ends in our cqr, then */ | ||
487 | /* cal the erp_postaction to clean it up */ | ||
488 | erpcqr = cqr; | ||
489 | while (erpcqr->refers) { | ||
490 | erpcqr = erpcqr->refers; | ||
491 | } | ||
492 | if (erpcqr == eer->cqr) { | ||
493 | erp_fn = device->discipline->erp_postaction( | ||
494 | cqr); | ||
495 | erp_fn(cqr); | ||
496 | } | ||
497 | continue; | ||
498 | } | ||
499 | } | ||
500 | spin_unlock_irq(get_ccwdev_lock(device->cdev)); | ||
501 | } | ||
502 | |||
503 | /* | ||
504 | * This function dismantles a struct dasd_eer that was created by | ||
505 | * dasd_eer_probe. Since we want to free our private data structure, | ||
506 | * we must make sure that the memory is not in use anymore. | ||
507 | * We have to flush the work queue and remove a possible SNSS request | ||
508 | * from the dasd queue. | ||
509 | */ | ||
510 | static void | ||
511 | dasd_eer_destroy(struct dasd_device *device, struct dasd_eer_private *eer) | ||
512 | { | ||
513 | flush_workqueue(dasd_eer_workqueue); | ||
514 | dasd_eer_dequeue_SNSS_request(device, eer); | ||
515 | dasd_kfree_request(eer->cqr, device); | ||
516 | kfree(eer); | ||
517 | }; | ||
518 | |||
519 | /* | ||
520 | * enable the extended error reporting for a particular device | ||
521 | */ | ||
522 | static int | ||
523 | dasd_eer_enable_on_device(struct dasd_device *device) | ||
524 | { | ||
525 | void *eer; | ||
526 | if (!device) | ||
527 | return -ENODEV; | ||
528 | if (device->eer) | ||
529 | return 0; | ||
530 | if (!try_module_get(THIS_MODULE)) { | ||
531 | return -EINVAL; | ||
532 | } | ||
533 | eer = (void *)dasd_eer_probe(device); | ||
534 | if (IS_ERR(eer)) { | ||
535 | module_put(THIS_MODULE); | ||
536 | return PTR_ERR(eer); | ||
537 | } | ||
538 | device->eer = eer; | ||
539 | return 0; | ||
540 | } | ||
541 | |||
542 | /* | ||
543 | * enable the extended error reporting for a particular device | ||
544 | */ | ||
545 | static int | ||
546 | dasd_eer_disable_on_device(struct dasd_device *device) | ||
547 | { | ||
548 | struct dasd_eer_private *eer = device->eer; | ||
549 | |||
550 | if (!device) | ||
551 | return -ENODEV; | ||
552 | if (!device->eer) | ||
553 | return 0; | ||
554 | device->eer = NULL; | ||
555 | dasd_eer_destroy(device,eer); | ||
556 | module_put(THIS_MODULE); | ||
557 | |||
558 | return 0; | ||
559 | } | ||
560 | |||
561 | /* | ||
562 | * Set extended error reporting (eer) | ||
563 | * Note: This will be registered as a DASD ioctl, to be called on DASD devices. | ||
564 | */ | ||
565 | static int | ||
566 | dasd_ioctl_set_eer(struct block_device *bdev, int no, long args) | ||
567 | { | ||
568 | struct dasd_device *device; | ||
569 | int intval; | ||
570 | |||
571 | if (!capable(CAP_SYS_ADMIN)) | ||
572 | return -EACCES; | ||
573 | if (bdev != bdev->bd_contains) | ||
574 | /* Error-reporting is not allowed for partitions */ | ||
575 | return -EINVAL; | ||
576 | if (get_user(intval, (int __user *) args)) | ||
577 | return -EFAULT; | ||
578 | device = bdev->bd_disk->private_data; | ||
579 | if (device == NULL) | ||
580 | return -ENODEV; | ||
581 | |||
582 | intval = (intval != 0); | ||
583 | DEV_MESSAGE (KERN_DEBUG, device, | ||
584 | "set eer on device to %d", intval); | ||
585 | if (intval) | ||
586 | return dasd_eer_enable_on_device(device); | ||
587 | else | ||
588 | return dasd_eer_disable_on_device(device); | ||
589 | } | ||
590 | |||
591 | /* | ||
592 | * Get value of extended error reporting. | ||
593 | * Note: This will be registered as a DASD ioctl, to be called on DASD devices. | ||
594 | */ | ||
595 | static int | ||
596 | dasd_ioctl_get_eer(struct block_device *bdev, int no, long args) | ||
597 | { | ||
598 | struct dasd_device *device; | ||
599 | |||
600 | device = bdev->bd_disk->private_data; | ||
601 | if (device == NULL) | ||
602 | return -ENODEV; | ||
603 | return put_user((device->eer != NULL), (int __user *) args); | ||
604 | } | ||
605 | |||
606 | /* | ||
607 | * The following function can be used for those triggers that have | ||
608 | * all necessary data available when the function is called. | ||
609 | * If the parameter cqr is not NULL, the chain of requests will be searched | ||
610 | * for valid sense data, and all valid sense data sets will be added to | ||
611 | * the triggers data. | ||
612 | */ | ||
613 | static int | ||
614 | dasd_eer_write_standard_trigger(int trigger, struct dasd_device *device, | ||
615 | struct dasd_ccw_req *cqr) | ||
616 | { | ||
617 | struct dasd_ccw_req *temp_cqr; | ||
618 | int data_size; | ||
619 | struct timeval tv; | ||
620 | struct dasd_eer_header header; | ||
621 | unsigned long flags; | ||
622 | struct eerbuffer *eerb; | ||
623 | |||
624 | /* go through cqr chain and count the valid sense data sets */ | ||
625 | temp_cqr = cqr; | ||
626 | data_size = 0; | ||
627 | while (temp_cqr) { | ||
628 | if (temp_cqr->irb.esw.esw0.erw.cons) | ||
629 | data_size += 32; | ||
630 | temp_cqr = temp_cqr->refers; | ||
631 | } | ||
632 | |||
633 | header.total_size = sizeof(header) + data_size + 4; /* "EOR" */ | ||
634 | header.trigger = trigger; | ||
635 | do_gettimeofday(&tv); | ||
636 | header.tv_sec = tv.tv_sec; | ||
637 | header.tv_usec = tv.tv_usec; | ||
638 | strncpy(header.busid, device->cdev->dev.bus_id, DASD_EER_BUSID_SIZE); | ||
639 | |||
640 | spin_lock_irqsave(&bufferlock, flags); | ||
641 | list_for_each_entry(eerb, &bufferlist, list) { | ||
642 | dasd_eer_start_record(eerb, header.total_size); | ||
643 | dasd_eer_write_buffer(eerb, sizeof(header), (char*)(&header)); | ||
644 | temp_cqr = cqr; | ||
645 | while (temp_cqr) { | ||
646 | if (temp_cqr->irb.esw.esw0.erw.cons) | ||
647 | dasd_eer_write_buffer(eerb, 32, cqr->irb.ecw); | ||
648 | temp_cqr = temp_cqr->refers; | ||
649 | } | ||
650 | dasd_eer_write_buffer(eerb, 4,"EOR"); | ||
651 | } | ||
652 | spin_unlock_irqrestore(&bufferlock, flags); | ||
653 | |||
654 | wake_up_interruptible(&dasd_eer_read_wait_queue); | ||
655 | |||
656 | return 0; | ||
657 | } | ||
658 | |||
659 | /* | ||
660 | * This function writes a DASD_EER_STATECHANGE trigger. | ||
661 | */ | ||
662 | static void | ||
663 | dasd_eer_write_SNSS_trigger(struct dasd_device *device, | ||
664 | struct dasd_ccw_req *cqr) | ||
665 | { | ||
666 | int data_size; | ||
667 | int snss_rc; | ||
668 | struct timeval tv; | ||
669 | struct dasd_eer_header header; | ||
670 | unsigned long flags; | ||
671 | struct eerbuffer *eerb; | ||
672 | |||
673 | snss_rc = (cqr->status == DASD_CQR_FAILED) ? -EIO : 0; | ||
674 | if (snss_rc) | ||
675 | data_size = 0; | ||
676 | else | ||
677 | data_size = SNSS_DATA_SIZE; | ||
678 | |||
679 | header.total_size = sizeof(header) + data_size + 4; /* "EOR" */ | ||
680 | header.trigger = DASD_EER_STATECHANGE; | ||
681 | do_gettimeofday(&tv); | ||
682 | header.tv_sec = tv.tv_sec; | ||
683 | header.tv_usec = tv.tv_usec; | ||
684 | strncpy(header.busid, device->cdev->dev.bus_id, DASD_EER_BUSID_SIZE); | ||
685 | |||
686 | spin_lock_irqsave(&bufferlock, flags); | ||
687 | list_for_each_entry(eerb, &bufferlist, list) { | ||
688 | dasd_eer_start_record(eerb, header.total_size); | ||
689 | dasd_eer_write_buffer(eerb, sizeof(header),(char*)(&header)); | ||
690 | if (!snss_rc) | ||
691 | dasd_eer_write_buffer(eerb, SNSS_DATA_SIZE, cqr->data); | ||
692 | dasd_eer_write_buffer(eerb, 4,"EOR"); | ||
693 | } | ||
694 | spin_unlock_irqrestore(&bufferlock, flags); | ||
695 | |||
696 | wake_up_interruptible(&dasd_eer_read_wait_queue); | ||
697 | } | ||
698 | |||
699 | /* | ||
700 | * callback function for use with SNSS request | ||
701 | */ | ||
702 | static void | ||
703 | dasd_eer_SNSS_cb(struct dasd_ccw_req *cqr, void *data) | ||
704 | { | ||
705 | struct dasd_device *device; | ||
706 | struct dasd_eer_private *private; | ||
707 | unsigned long irqflags; | ||
708 | |||
709 | device = (struct dasd_device *)data; | ||
710 | private = (struct dasd_eer_private *)device->eer; | ||
711 | dasd_eer_write_SNSS_trigger(device, cqr); | ||
712 | spin_lock_irqsave(&snsslock, irqflags); | ||
713 | if(!test_and_clear_bit(SNSS_REQUESTED, &private->flags)) { | ||
714 | clear_bit(CQR_IN_USE, &private->flags); | ||
715 | spin_unlock_irqrestore(&snsslock, irqflags); | ||
716 | return; | ||
717 | }; | ||
718 | clear_bit(CQR_IN_USE, &private->flags); | ||
719 | spin_unlock_irqrestore(&snsslock, irqflags); | ||
720 | dasd_eer_sense_subsystem_status(device); | ||
721 | return; | ||
722 | } | ||
723 | |||
724 | /* | ||
725 | * clean a used cqr before using it again | ||
726 | */ | ||
727 | static void | ||
728 | dasd_eer_clean_SNSS_request(struct dasd_ccw_req *cqr) | ||
729 | { | ||
730 | struct ccw1 *cpaddr = cqr->cpaddr; | ||
731 | void *data = cqr->data; | ||
732 | |||
733 | memset(cqr, 0, sizeof(struct dasd_ccw_req)); | ||
734 | memset(cpaddr, 0, sizeof(struct ccw1)); | ||
735 | memset(data, 0, SNSS_DATA_SIZE); | ||
736 | cqr->cpaddr = cpaddr; | ||
737 | cqr->data = data; | ||
738 | strncpy((char *) &cqr->magic, "ECKD", 4); | ||
739 | ASCEBC((char *) &cqr->magic, 4); | ||
740 | set_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); | ||
741 | } | ||
742 | |||
743 | /* | ||
744 | * build and start an SNSS request | ||
745 | * This function is called from a work queue so we have to | ||
746 | * pass the dasd_device pointer as a void pointer. | ||
747 | */ | ||
748 | static void | ||
749 | dasd_eer_sense_subsystem_status(void *data) | ||
750 | { | ||
751 | struct dasd_device *device; | ||
752 | struct dasd_eer_private *private; | ||
753 | struct dasd_ccw_req *cqr; | ||
754 | struct ccw1 *ccw; | ||
755 | unsigned long irqflags; | ||
756 | |||
757 | device = (struct dasd_device *)data; | ||
758 | private = (struct dasd_eer_private *)device->eer; | ||
759 | if (!private) /* device not eer enabled any more */ | ||
760 | return; | ||
761 | cqr = private->cqr; | ||
762 | spin_lock_irqsave(&snsslock, irqflags); | ||
763 | if(test_and_set_bit(CQR_IN_USE, &private->flags)) { | ||
764 | set_bit(SNSS_REQUESTED, &private->flags); | ||
765 | spin_unlock_irqrestore(&snsslock, irqflags); | ||
766 | return; | ||
767 | }; | ||
768 | spin_unlock_irqrestore(&snsslock, irqflags); | ||
769 | dasd_eer_clean_SNSS_request(cqr); | ||
770 | cqr->device = device; | ||
771 | cqr->retries = 255; | ||
772 | cqr->expires = 10 * HZ; | ||
773 | |||
774 | ccw = cqr->cpaddr; | ||
775 | ccw->cmd_code = DASD_ECKD_CCW_SNSS; | ||
776 | ccw->count = SNSS_DATA_SIZE; | ||
777 | ccw->flags = 0; | ||
778 | ccw->cda = (__u32)(addr_t)cqr->data; | ||
779 | |||
780 | cqr->buildclk = get_clock(); | ||
781 | cqr->status = DASD_CQR_FILLED; | ||
782 | cqr->callback = dasd_eer_SNSS_cb; | ||
783 | cqr->callback_data = (void *)device; | ||
784 | dasd_add_request_head(cqr); | ||
785 | |||
786 | return; | ||
787 | } | ||
788 | |||
789 | /* | ||
790 | * This function is called for all triggers. It calls the appropriate | ||
791 | * function that writes the actual trigger records. | ||
792 | */ | ||
793 | static int | ||
794 | dasd_eer_write_trigger(struct dasd_eer_trigger *trigger) | ||
795 | { | ||
796 | int rc; | ||
797 | struct dasd_eer_private *private = trigger->device->eer; | ||
798 | |||
799 | switch (trigger->id) { | ||
800 | case DASD_EER_FATALERROR: | ||
801 | case DASD_EER_PPRCSUSPEND: | ||
802 | rc = dasd_eer_write_standard_trigger( | ||
803 | trigger->id, trigger->device, trigger->cqr); | ||
804 | break; | ||
805 | case DASD_EER_NOPATH: | ||
806 | rc = dasd_eer_write_standard_trigger( | ||
807 | trigger->id, trigger->device, NULL); | ||
808 | break; | ||
809 | case DASD_EER_STATECHANGE: | ||
810 | if (queue_work(dasd_eer_workqueue, &private->worker)) { | ||
811 | rc=0; | ||
812 | } else { | ||
813 | /* If the work_struct was already queued, it can't | ||
814 | * be queued again. But this is OK since we don't | ||
815 | * need to have it queued twice. | ||
816 | */ | ||
817 | rc = -EBUSY; | ||
818 | } | ||
819 | break; | ||
820 | default: /* unknown trigger, so we write it without any sense data */ | ||
821 | rc = dasd_eer_write_standard_trigger( | ||
822 | trigger->id, trigger->device, NULL); | ||
823 | break; | ||
824 | } | ||
825 | return rc; | ||
826 | } | ||
827 | |||
828 | /* | ||
829 | * This function is registered with the dasd device driver and gets called | ||
830 | * for all dasd eer notifications. | ||
831 | */ | ||
832 | static int dasd_eer_notify(struct notifier_block *self, | ||
833 | unsigned long action, void *data) | ||
834 | { | ||
835 | switch (action) { | ||
836 | case DASD_EER_DISABLE: | ||
837 | dasd_eer_disable_on_device((struct dasd_device *)data); | ||
838 | break; | ||
839 | case DASD_EER_TRIGGER: | ||
840 | dasd_eer_write_trigger((struct dasd_eer_trigger *)data); | ||
841 | break; | ||
842 | } | ||
843 | return NOTIFY_OK; | ||
844 | } | ||
845 | |||
846 | |||
847 | /*****************************************************************************/ | ||
848 | /* the device operations */ | ||
849 | /*****************************************************************************/ | ||
850 | |||
851 | /* | ||
852 | * On the one side we need a lock to access our internal buffer, on the | ||
853 | * other side a copy_to_user can sleep. So we need to copy the data we have | ||
854 | * to transfer in a readbuffer, which is protected by the readbuffer_mutex. | ||
855 | */ | ||
856 | static char readbuffer[PAGE_SIZE]; | ||
857 | DECLARE_MUTEX(readbuffer_mutex); | ||
858 | |||
859 | |||
860 | static int | ||
861 | dasd_eer_open(struct inode *inp, struct file *filp) | ||
862 | { | ||
863 | struct eerbuffer *eerb; | ||
864 | unsigned long flags; | ||
865 | |||
866 | eerb = kmalloc(sizeof(struct eerbuffer), GFP_KERNEL); | ||
867 | eerb->head = 0; | ||
868 | eerb->tail = 0; | ||
869 | eerb->residual = 0; | ||
870 | eerb->buffer_page_count = 1; | ||
871 | eerb->buffersize = eerb->buffer_page_count * PAGE_SIZE; | ||
872 | eerb->buffer = kmalloc(eerb->buffer_page_count*sizeof(char*), | ||
873 | GFP_KERNEL); | ||
874 | if (!eerb->buffer) | ||
875 | return -ENOMEM; | ||
876 | if (dasd_eer_allocate_buffer_pages(eerb->buffer, | ||
877 | eerb->buffer_page_count)) { | ||
878 | kfree(eerb->buffer); | ||
879 | return -ENOMEM; | ||
880 | } | ||
881 | filp->private_data = eerb; | ||
882 | spin_lock_irqsave(&bufferlock, flags); | ||
883 | list_add(&eerb->list, &bufferlist); | ||
884 | spin_unlock_irqrestore(&bufferlock, flags); | ||
885 | |||
886 | return nonseekable_open(inp,filp); | ||
887 | } | ||
888 | |||
889 | static int | ||
890 | dasd_eer_close(struct inode *inp, struct file *filp) | ||
891 | { | ||
892 | struct eerbuffer *eerb; | ||
893 | unsigned long flags; | ||
894 | |||
895 | eerb = (struct eerbuffer *)filp->private_data; | ||
896 | spin_lock_irqsave(&bufferlock, flags); | ||
897 | list_del(&eerb->list); | ||
898 | spin_unlock_irqrestore(&bufferlock, flags); | ||
899 | dasd_eer_free_buffer_pages(eerb->buffer, eerb->buffer_page_count); | ||
900 | kfree(eerb->buffer); | ||
901 | kfree(eerb); | ||
902 | |||
903 | return 0; | ||
904 | } | ||
905 | |||
906 | static long | ||
907 | dasd_eer_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | ||
908 | { | ||
909 | int intval; | ||
910 | struct eerbuffer *eerb; | ||
911 | |||
912 | eerb = (struct eerbuffer *)filp->private_data; | ||
913 | switch (cmd) { | ||
914 | case DASD_EER_PURGE: | ||
915 | dasd_eer_purge_buffer(eerb); | ||
916 | return 0; | ||
917 | case DASD_EER_SETBUFSIZE: | ||
918 | if (get_user(intval, (int __user *)arg)) | ||
919 | return -EFAULT; | ||
920 | return dasd_eer_resize_buffer(eerb, intval); | ||
921 | default: | ||
922 | return -ENOIOCTLCMD; | ||
923 | } | ||
924 | } | ||
925 | |||
926 | static ssize_t | ||
927 | dasd_eer_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) | ||
928 | { | ||
929 | int tc,rc; | ||
930 | int tailcount,effective_count; | ||
931 | unsigned long flags; | ||
932 | struct eerbuffer *eerb; | ||
933 | |||
934 | eerb = (struct eerbuffer *)filp->private_data; | ||
935 | if(down_interruptible(&readbuffer_mutex)) | ||
936 | return -ERESTARTSYS; | ||
937 | |||
938 | spin_lock_irqsave(&bufferlock, flags); | ||
939 | |||
940 | if (eerb->residual < 0) { /* the remainder of this record */ | ||
941 | /* has been deleted */ | ||
942 | eerb->residual = 0; | ||
943 | spin_unlock_irqrestore(&bufferlock, flags); | ||
944 | up(&readbuffer_mutex); | ||
945 | return -EIO; | ||
946 | } else if (eerb->residual > 0) { | ||
947 | /* OK we still have a second half of a record to deliver */ | ||
948 | effective_count = min(eerb->residual, (int)count); | ||
949 | eerb->residual -= effective_count; | ||
950 | } else { | ||
951 | tc = 0; | ||
952 | while (!tc) { | ||
953 | tc = dasd_eer_read_buffer(eerb, | ||
954 | sizeof(tailcount), (char*)(&tailcount)); | ||
955 | if (!tc) { | ||
956 | /* no data available */ | ||
957 | spin_unlock_irqrestore(&bufferlock, flags); | ||
958 | up(&readbuffer_mutex); | ||
959 | if (filp->f_flags & O_NONBLOCK) | ||
960 | return -EAGAIN; | ||
961 | rc = wait_event_interruptible( | ||
962 | dasd_eer_read_wait_queue, | ||
963 | eerb->head != eerb->tail); | ||
964 | if (rc) { | ||
965 | return rc; | ||
966 | } | ||
967 | if(down_interruptible(&readbuffer_mutex)) | ||
968 | return -ERESTARTSYS; | ||
969 | spin_lock_irqsave(&bufferlock, flags); | ||
970 | } | ||
971 | } | ||
972 | WARN_ON(tc != sizeof(tailcount)); | ||
973 | effective_count = min(tailcount,(int)count); | ||
974 | eerb->residual = tailcount - effective_count; | ||
975 | } | ||
976 | |||
977 | tc = dasd_eer_read_buffer(eerb, effective_count, readbuffer); | ||
978 | WARN_ON(tc != effective_count); | ||
979 | |||
980 | spin_unlock_irqrestore(&bufferlock, flags); | ||
981 | |||
982 | if (copy_to_user(buf, readbuffer, effective_count)) { | ||
983 | up(&readbuffer_mutex); | ||
984 | return -EFAULT; | ||
985 | } | ||
986 | |||
987 | up(&readbuffer_mutex); | ||
988 | return effective_count; | ||
989 | } | ||
990 | |||
991 | static unsigned int | ||
992 | dasd_eer_poll (struct file *filp, poll_table *ptable) | ||
993 | { | ||
994 | unsigned int mask; | ||
995 | unsigned long flags; | ||
996 | struct eerbuffer *eerb; | ||
997 | |||
998 | eerb = (struct eerbuffer *)filp->private_data; | ||
999 | poll_wait(filp, &dasd_eer_read_wait_queue, ptable); | ||
1000 | spin_lock_irqsave(&bufferlock, flags); | ||
1001 | if (eerb->head != eerb->tail) | ||
1002 | mask = POLLIN | POLLRDNORM ; | ||
1003 | else | ||
1004 | mask = 0; | ||
1005 | spin_unlock_irqrestore(&bufferlock, flags); | ||
1006 | return mask; | ||
1007 | } | ||
1008 | |||
1009 | static struct file_operations dasd_eer_fops = { | ||
1010 | .open = &dasd_eer_open, | ||
1011 | .release = &dasd_eer_close, | ||
1012 | .unlocked_ioctl = &dasd_eer_ioctl, | ||
1013 | .compat_ioctl = &dasd_eer_ioctl, | ||
1014 | .read = &dasd_eer_read, | ||
1015 | .poll = &dasd_eer_poll, | ||
1016 | .owner = THIS_MODULE, | ||
1017 | }; | ||
1018 | |||
1019 | static struct miscdevice dasd_eer_dev = { | ||
1020 | .minor = MISC_DYNAMIC_MINOR, | ||
1021 | .name = "dasd_eer", | ||
1022 | .fops = &dasd_eer_fops, | ||
1023 | }; | ||
1024 | |||
1025 | |||
1026 | /*****************************************************************************/ | ||
1027 | /* Init and exit */ | ||
1028 | /*****************************************************************************/ | ||
1029 | |||
1030 | static int | ||
1031 | __init dasd_eer_init(void) | ||
1032 | { | ||
1033 | int rc; | ||
1034 | |||
1035 | dasd_eer_workqueue = create_singlethread_workqueue("dasd_eer"); | ||
1036 | if (!dasd_eer_workqueue) { | ||
1037 | MESSAGE(KERN_ERR , "%s", "dasd_eer_init could not " | ||
1038 | "create workqueue \n"); | ||
1039 | rc = -ENOMEM; | ||
1040 | goto out; | ||
1041 | } | ||
1042 | |||
1043 | rc = dasd_register_eer_notifier(&dasd_eer_nb); | ||
1044 | if (rc) { | ||
1045 | MESSAGE(KERN_ERR, "%s", "dasd_eer_init could not " | ||
1046 | "register error reporting"); | ||
1047 | goto queue; | ||
1048 | } | ||
1049 | |||
1050 | dasd_ioctl_no_register(THIS_MODULE, BIODASDEERSET, dasd_ioctl_set_eer); | ||
1051 | dasd_ioctl_no_register(THIS_MODULE, BIODASDEERGET, dasd_ioctl_get_eer); | ||
1052 | |||
1053 | /* we don't need our own character device, | ||
1054 | * so we just register as misc device */ | ||
1055 | rc = misc_register(&dasd_eer_dev); | ||
1056 | if (rc) { | ||
1057 | MESSAGE(KERN_ERR, "%s", "dasd_eer_init could not " | ||
1058 | "register misc device"); | ||
1059 | goto unregister; | ||
1060 | } | ||
1061 | |||
1062 | return 0; | ||
1063 | |||
1064 | unregister: | ||
1065 | dasd_unregister_eer_notifier(&dasd_eer_nb); | ||
1066 | dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERSET, | ||
1067 | dasd_ioctl_set_eer); | ||
1068 | dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERGET, | ||
1069 | dasd_ioctl_get_eer); | ||
1070 | queue: | ||
1071 | destroy_workqueue(dasd_eer_workqueue); | ||
1072 | out: | ||
1073 | return rc; | ||
1074 | |||
1075 | } | ||
1076 | module_init(dasd_eer_init); | ||
1077 | |||
1078 | static void | ||
1079 | __exit dasd_eer_exit(void) | ||
1080 | { | ||
1081 | dasd_unregister_eer_notifier(&dasd_eer_nb); | ||
1082 | dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERSET, | ||
1083 | dasd_ioctl_set_eer); | ||
1084 | dasd_ioctl_no_unregister(THIS_MODULE, BIODASDEERGET, | ||
1085 | dasd_ioctl_get_eer); | ||
1086 | destroy_workqueue(dasd_eer_workqueue); | ||
1087 | |||
1088 | WARN_ON(misc_deregister(&dasd_eer_dev) != 0); | ||
1089 | } | ||
1090 | module_exit(dasd_eer_exit); | ||
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index c20af9874500..d1b08fa13fd2 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h | |||
@@ -275,6 +275,34 @@ struct dasd_discipline { | |||
275 | 275 | ||
276 | extern struct dasd_discipline *dasd_diag_discipline_pointer; | 276 | extern struct dasd_discipline *dasd_diag_discipline_pointer; |
277 | 277 | ||
278 | |||
279 | /* | ||
280 | * Notification numbers for extended error reporting notifications: | ||
281 | * The DASD_EER_DISABLE notification is sent before a dasd_device (and it's | ||
282 | * eer pointer) is freed. The error reporting module needs to do all necessary | ||
283 | * cleanup steps. | ||
284 | * The DASD_EER_TRIGGER notification sends the actual error reports (triggers). | ||
285 | */ | ||
286 | #define DASD_EER_DISABLE 0 | ||
287 | #define DASD_EER_TRIGGER 1 | ||
288 | |||
289 | /* Trigger IDs for extended error reporting DASD_EER_TRIGGER notification */ | ||
290 | #define DASD_EER_FATALERROR 1 | ||
291 | #define DASD_EER_NOPATH 2 | ||
292 | #define DASD_EER_STATECHANGE 3 | ||
293 | #define DASD_EER_PPRCSUSPEND 4 | ||
294 | |||
295 | /* | ||
296 | * The dasd_eer_trigger structure contains all data that we need to send | ||
297 | * along with an DASD_EER_TRIGGER notification. | ||
298 | */ | ||
299 | struct dasd_eer_trigger { | ||
300 | unsigned int id; | ||
301 | struct dasd_device *device; | ||
302 | struct dasd_ccw_req *cqr; | ||
303 | }; | ||
304 | |||
305 | |||
278 | struct dasd_device { | 306 | struct dasd_device { |
279 | /* Block device stuff. */ | 307 | /* Block device stuff. */ |
280 | struct gendisk *gdp; | 308 | struct gendisk *gdp; |
@@ -288,6 +316,9 @@ struct dasd_device { | |||
288 | unsigned long flags; /* per device flags */ | 316 | unsigned long flags; /* per device flags */ |
289 | unsigned short features; /* copy of devmap-features (read-only!) */ | 317 | unsigned short features; /* copy of devmap-features (read-only!) */ |
290 | 318 | ||
319 | /* extended error reporting stuff (eer) */ | ||
320 | void *eer; | ||
321 | |||
291 | /* Device discipline stuff. */ | 322 | /* Device discipline stuff. */ |
292 | struct dasd_discipline *discipline; | 323 | struct dasd_discipline *discipline; |
293 | char *private; | 324 | char *private; |
@@ -488,6 +519,12 @@ int dasd_generic_set_online(struct ccw_device *, struct dasd_discipline *); | |||
488 | int dasd_generic_set_offline (struct ccw_device *cdev); | 519 | int dasd_generic_set_offline (struct ccw_device *cdev); |
489 | int dasd_generic_notify(struct ccw_device *, int); | 520 | int dasd_generic_notify(struct ccw_device *, int); |
490 | void dasd_generic_auto_online (struct ccw_driver *); | 521 | void dasd_generic_auto_online (struct ccw_driver *); |
522 | int dasd_register_eer_notifier(struct notifier_block *); | ||
523 | int dasd_unregister_eer_notifier(struct notifier_block *); | ||
524 | void dasd_write_eer_trigger(unsigned int , struct dasd_device *, | ||
525 | struct dasd_ccw_req *); | ||
526 | |||
527 | |||
491 | 528 | ||
492 | /* externals in dasd_devmap.c */ | 529 | /* externals in dasd_devmap.c */ |
493 | extern int dasd_max_devindex; | 530 | extern int dasd_max_devindex; |
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h index 44e4b4bb1c5a..3e75095f35d0 100644 --- a/drivers/s390/cio/chsc.h +++ b/drivers/s390/cio/chsc.h | |||
@@ -68,6 +68,6 @@ extern void *chsc_get_chp_desc(struct subchannel*, int); | |||
68 | 68 | ||
69 | extern int chsc_enable_facility(int); | 69 | extern int chsc_enable_facility(int); |
70 | 70 | ||
71 | #define to_channelpath(dev) container_of(dev, struct channel_path, dev) | 71 | #define to_channelpath(device) container_of(device, struct channel_path, dev) |
72 | 72 | ||
73 | #endif | 73 | #endif |
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 38d6d00fb0fc..014cc8d54a9f 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c | |||
@@ -38,10 +38,10 @@ | |||
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/completion.h> | 39 | #include <linux/completion.h> |
40 | #include <linux/blkdev.h> | 40 | #include <linux/blkdev.h> |
41 | #include <linux/delay.h> | ||
41 | #include <scsi/scsi_host.h> | 42 | #include <scsi/scsi_host.h> |
42 | #include <scsi/scsi_device.h> | 43 | #include <scsi/scsi_device.h> |
43 | #include <asm/semaphore.h> | 44 | #include <asm/semaphore.h> |
44 | #include <asm/delay.h> | ||
45 | 45 | ||
46 | #include "aacraid.h" | 46 | #include "aacraid.h" |
47 | 47 | ||
diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c index 311a4122bd70..93edaa8696cf 100644 --- a/drivers/scsi/mac53c94.c +++ b/drivers/scsi/mac53c94.c | |||
@@ -537,9 +537,9 @@ static int mac53c94_remove(struct macio_dev *mdev) | |||
537 | free_irq(fp->intr, fp); | 537 | free_irq(fp->intr, fp); |
538 | 538 | ||
539 | if (fp->regs) | 539 | if (fp->regs) |
540 | iounmap((void *) fp->regs); | 540 | iounmap(fp->regs); |
541 | if (fp->dma) | 541 | if (fp->dma) |
542 | iounmap((void *) fp->dma); | 542 | iounmap(fp->dma); |
543 | kfree(fp->dma_cmd_space); | 543 | kfree(fp->dma_cmd_space); |
544 | 544 | ||
545 | scsi_host_put(host); | 545 | scsi_host_put(host); |
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 245ca99a641e..c551bb84dbfb 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c | |||
@@ -1245,7 +1245,7 @@ static int __init init_scsi(void) | |||
1245 | if (error) | 1245 | if (error) |
1246 | goto cleanup_sysctl; | 1246 | goto cleanup_sysctl; |
1247 | 1247 | ||
1248 | for (i = 0; i < NR_CPUS; i++) | 1248 | for_each_cpu(i) |
1249 | INIT_LIST_HEAD(&per_cpu(scsi_done_q, i)); | 1249 | INIT_LIST_HEAD(&per_cpu(scsi_done_q, i)); |
1250 | 1250 | ||
1251 | devfs_mk_dir("scsi"); | 1251 | devfs_mk_dir("scsi"); |
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 59a1c9d9d3bd..723f7acbeb12 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c | |||
@@ -463,7 +463,7 @@ static inline struct list_head *skb_to_lh(struct sk_buff *skb) | |||
463 | } | 463 | } |
464 | 464 | ||
465 | static void* | 465 | static void* |
466 | mempool_zone_alloc_skb(unsigned int gfp_mask, void *pool_data) | 466 | mempool_zone_alloc_skb(gfp_t gfp_mask, void *pool_data) |
467 | { | 467 | { |
468 | struct mempool_zone *zone = pool_data; | 468 | struct mempool_zone *zone = pool_data; |
469 | 469 | ||
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 7d0700091f3d..2a547538d444 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c | |||
@@ -1679,7 +1679,7 @@ static int | |||
1679 | sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, int tablesize) | 1679 | sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, int tablesize) |
1680 | { | 1680 | { |
1681 | int sg_bufflen = tablesize * sizeof(struct scatterlist); | 1681 | int sg_bufflen = tablesize * sizeof(struct scatterlist); |
1682 | unsigned int gfp_flags = GFP_ATOMIC | __GFP_NOWARN; | 1682 | gfp_t gfp_flags = GFP_ATOMIC | __GFP_NOWARN; |
1683 | 1683 | ||
1684 | /* | 1684 | /* |
1685 | * TODO: test without low_dma, we should not need it since | 1685 | * TODO: test without low_dma, we should not need it since |
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c index 7aef7518b0d1..8c5c276c5577 100644 --- a/drivers/serial/21285.c +++ b/drivers/serial/21285.c | |||
@@ -362,7 +362,7 @@ static struct uart_ops serial21285_ops = { | |||
362 | 362 | ||
363 | static struct uart_port serial21285_port = { | 363 | static struct uart_port serial21285_port = { |
364 | .mapbase = 0x42000160, | 364 | .mapbase = 0x42000160, |
365 | .iotype = SERIAL_IO_MEM, | 365 | .iotype = UPIO_MEM, |
366 | .irq = NO_IRQ, | 366 | .irq = NO_IRQ, |
367 | .fifosize = 16, | 367 | .fifosize = 16, |
368 | .ops = &serial21285_ops, | 368 | .ops = &serial21285_ops, |
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index 8cbf0fc5a225..7f0f35a05dca 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c | |||
@@ -332,7 +332,7 @@ static _INLINE_ void receive_chars(struct m68k_serial *info, struct pt_regs *reg | |||
332 | * Make sure that we do not overflow the buffer | 332 | * Make sure that we do not overflow the buffer |
333 | */ | 333 | */ |
334 | if (tty_request_buffer_room(tty, 1) == 0) { | 334 | if (tty_request_buffer_room(tty, 1) == 0) { |
335 | schedule_work(&tty->flip.work); | 335 | tty_schedule_flip(tty); |
336 | return; | 336 | return; |
337 | } | 337 | } |
338 | 338 | ||
@@ -353,7 +353,7 @@ static _INLINE_ void receive_chars(struct m68k_serial *info, struct pt_regs *reg | |||
353 | } while((rx = uart->urx.w) & URX_DATA_READY); | 353 | } while((rx = uart->urx.w) & URX_DATA_READY); |
354 | #endif | 354 | #endif |
355 | 355 | ||
356 | schedule_work(&tty->flip.work); | 356 | tty_schedule_flip(tty); |
357 | 357 | ||
358 | clear_and_exit: | 358 | clear_and_exit: |
359 | return; | 359 | return; |
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c index 60f5a5dc17f1..9843ae3d420e 100644 --- a/drivers/serial/68360serial.c +++ b/drivers/serial/68360serial.c | |||
@@ -509,7 +509,7 @@ static _INLINE_ void receive_chars(ser_info_t *info) | |||
509 | 509 | ||
510 | info->rx_cur = (QUICC_BD *)bdp; | 510 | info->rx_cur = (QUICC_BD *)bdp; |
511 | 511 | ||
512 | schedule_work(&tty->flip.work); | 512 | tty_schedule_flip(tty); |
513 | } | 513 | } |
514 | 514 | ||
515 | static _INLINE_ void receive_break(ser_info_t *info) | 515 | static _INLINE_ void receive_break(ser_info_t *info) |
@@ -521,7 +521,7 @@ static _INLINE_ void receive_break(ser_info_t *info) | |||
521 | * the break. If not, we exit now, losing the break. FIXME | 521 | * the break. If not, we exit now, losing the break. FIXME |
522 | */ | 522 | */ |
523 | tty_insert_flip_char(tty, 0, TTY_BREAK); | 523 | tty_insert_flip_char(tty, 0, TTY_BREAK); |
524 | schedule_work(&tty->flip.work); | 524 | tty_schedule_flip(tty); |
525 | } | 525 | } |
526 | 526 | ||
527 | static _INLINE_ void transmit_chars(ser_info_t *info) | 527 | static _INLINE_ void transmit_chars(ser_info_t *info) |
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 179c1f065e60..b1fc97d5f643 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -2229,6 +2229,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) | |||
2229 | * and restore the IER | 2229 | * and restore the IER |
2230 | */ | 2230 | */ |
2231 | wait_for_xmitr(up, BOTH_EMPTY); | 2231 | wait_for_xmitr(up, BOTH_EMPTY); |
2232 | up->ier |= UART_IER_THRI; | ||
2232 | serial_out(up, UART_IER, ier | UART_IER_THRI); | 2233 | serial_out(up, UART_IER, ier | UART_IER_THRI); |
2233 | } | 2234 | } |
2234 | 2235 | ||
diff --git a/drivers/serial/8250_au1x00.c b/drivers/serial/8250_au1x00.c index 06ae8fbcc947..8d8d7a70d03e 100644 --- a/drivers/serial/8250_au1x00.c +++ b/drivers/serial/8250_au1x00.c | |||
@@ -56,7 +56,6 @@ static struct plat_serial8250_port au1x00_data[] = { | |||
56 | #elif defined(CONFIG_SOC_AU1550) | 56 | #elif defined(CONFIG_SOC_AU1550) |
57 | PORT(UART0_ADDR, AU1550_UART0_INT), | 57 | PORT(UART0_ADDR, AU1550_UART0_INT), |
58 | PORT(UART1_ADDR, AU1550_UART1_INT), | 58 | PORT(UART1_ADDR, AU1550_UART1_INT), |
59 | PORT(UART2_ADDR, AU1550_UART2_INT), | ||
60 | PORT(UART3_ADDR, AU1550_UART3_INT), | 59 | PORT(UART3_ADDR, AU1550_UART3_INT), |
61 | #elif defined(CONFIG_SOC_AU1200) | 60 | #elif defined(CONFIG_SOC_AU1200) |
62 | PORT(UART0_ADDR, AU1200_UART0_INT), | 61 | PORT(UART0_ADDR, AU1200_UART0_INT), |
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index 2a912153321e..94886c000d2a 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c | |||
@@ -439,6 +439,20 @@ static int pci_siig_init(struct pci_dev *dev) | |||
439 | return -ENODEV; | 439 | return -ENODEV; |
440 | } | 440 | } |
441 | 441 | ||
442 | static int pci_siig_setup(struct serial_private *priv, | ||
443 | struct pciserial_board *board, | ||
444 | struct uart_port *port, int idx) | ||
445 | { | ||
446 | unsigned int bar = FL_GET_BASE(board->flags) + idx, offset = 0; | ||
447 | |||
448 | if (idx > 3) { | ||
449 | bar = 4; | ||
450 | offset = (idx - 4) * 8; | ||
451 | } | ||
452 | |||
453 | return setup_port(priv, port, bar, offset, 0); | ||
454 | } | ||
455 | |||
442 | /* | 456 | /* |
443 | * Timedia has an explosion of boards, and to avoid the PCI table from | 457 | * Timedia has an explosion of boards, and to avoid the PCI table from |
444 | * growing *huge*, we use this function to collapse some 70 entries | 458 | * growing *huge*, we use this function to collapse some 70 entries |
@@ -748,7 +762,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = { | |||
748 | .subvendor = PCI_ANY_ID, | 762 | .subvendor = PCI_ANY_ID, |
749 | .subdevice = PCI_ANY_ID, | 763 | .subdevice = PCI_ANY_ID, |
750 | .init = pci_siig_init, | 764 | .init = pci_siig_init, |
751 | .setup = pci_default_setup, | 765 | .setup = pci_siig_setup, |
752 | }, | 766 | }, |
753 | /* | 767 | /* |
754 | * Titan cards | 768 | * Titan cards |
@@ -1868,6 +1882,10 @@ static struct pci_device_id serial_pci_tbl[] = { | |||
1868 | PCI_SUBVENDOR_ID_CONNECT_TECH, | 1882 | PCI_SUBVENDOR_ID_CONNECT_TECH, |
1869 | PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_4, 0, 0, | 1883 | PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_4, 0, 0, |
1870 | pbn_b0_4_1843200 }, | 1884 | pbn_b0_4_1843200 }, |
1885 | { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954, | ||
1886 | PCI_VENDOR_ID_AFAVLAB, | ||
1887 | PCI_SUBDEVICE_ID_AFAVLAB_P061, 0, 0, | ||
1888 | pbn_b0_4_1152000 }, | ||
1871 | { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152, | 1889 | { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152, |
1872 | PCI_SUBVENDOR_ID_CONNECT_TECH, | 1890 | PCI_SUBVENDOR_ID_CONNECT_TECH, |
1873 | PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_232, 0, 0, | 1891 | PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_232, 0, 0, |
@@ -2141,6 +2159,15 @@ static struct pci_device_id serial_pci_tbl[] = { | |||
2141 | { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850, | 2159 | { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850, |
2142 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 2160 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
2143 | pbn_b0_bt_4_921600 }, | 2161 | pbn_b0_bt_4_921600 }, |
2162 | { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_550, | ||
2163 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, | ||
2164 | pbn_b0_bt_8_921600 }, | ||
2165 | { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_650, | ||
2166 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, | ||
2167 | pbn_b0_bt_8_921600 }, | ||
2168 | { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_850, | ||
2169 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, | ||
2170 | pbn_b0_bt_8_921600 }, | ||
2144 | 2171 | ||
2145 | /* | 2172 | /* |
2146 | * Computone devices submitted by Doug McNash dmcnash@computone.com | 2173 | * Computone devices submitted by Doug McNash dmcnash@computone.com |
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 0d38f0f2ae29..0f4361c8466b 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -98,6 +98,7 @@ config SERIAL_8250_NR_UARTS | |||
98 | config SERIAL_8250_RUNTIME_UARTS | 98 | config SERIAL_8250_RUNTIME_UARTS |
99 | int "Number of 8250/16550 serial ports to register at runtime" | 99 | int "Number of 8250/16550 serial ports to register at runtime" |
100 | depends on SERIAL_8250 | 100 | depends on SERIAL_8250 |
101 | range 0 SERIAL_8250_NR_UARTS | ||
101 | default "4" | 102 | default "4" |
102 | help | 103 | help |
103 | Set this to the maximum number of serial ports you want | 104 | Set this to the maximum number of serial ports you want |
@@ -892,20 +893,20 @@ config SERIAL_VR41XX_CONSOLE | |||
892 | a console on a serial port, say Y. Otherwise, say N. | 893 | a console on a serial port, say Y. Otherwise, say N. |
893 | 894 | ||
894 | config SERIAL_JSM | 895 | config SERIAL_JSM |
895 | tristate "Digi International NEO PCI Support" | 896 | tristate "Digi International NEO PCI Support" |
896 | depends on PCI && BROKEN | 897 | depends on PCI |
897 | select SERIAL_CORE | 898 | select SERIAL_CORE |
898 | help | 899 | help |
899 | This is a driver for Digi International's Neo series | 900 | This is a driver for Digi International's Neo series |
900 | of cards which provide multiple serial ports. You would need | 901 | of cards which provide multiple serial ports. You would need |
901 | something like this to connect more than two modems to your Linux | 902 | something like this to connect more than two modems to your Linux |
902 | box, for instance in order to become a dial-in server. This driver | 903 | box, for instance in order to become a dial-in server. This driver |
903 | supports PCI boards only. | 904 | supports PCI boards only. |
904 | If you have a card like this, say Y here and read the file | 905 | If you have a card like this, say Y here and read the file |
905 | <file:Documentation/jsm.txt>. | 906 | <file:Documentation/jsm.txt>. |
906 | 907 | ||
907 | To compile this driver as a module, choose M here: the | 908 | To compile this driver as a module, choose M here: the |
908 | module will be called jsm. | 909 | module will be called jsm. |
909 | 910 | ||
910 | config SERIAL_SGI_IOC4 | 911 | config SERIAL_SGI_IOC4 |
911 | tristate "SGI IOC4 controller serial support" | 912 | tristate "SGI IOC4 controller serial support" |
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index 429de2723a1c..321a3b3a5728 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c | |||
@@ -561,7 +561,7 @@ static struct uart_amba_port amba_ports[UART_NR] = { | |||
561 | .port = { | 561 | .port = { |
562 | .membase = (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE), | 562 | .membase = (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE), |
563 | .mapbase = INTEGRATOR_UART0_BASE, | 563 | .mapbase = INTEGRATOR_UART0_BASE, |
564 | .iotype = SERIAL_IO_MEM, | 564 | .iotype = UPIO_MEM, |
565 | .irq = IRQ_UARTINT0, | 565 | .irq = IRQ_UARTINT0, |
566 | .uartclk = 14745600, | 566 | .uartclk = 14745600, |
567 | .fifosize = 16, | 567 | .fifosize = 16, |
@@ -576,7 +576,7 @@ static struct uart_amba_port amba_ports[UART_NR] = { | |||
576 | .port = { | 576 | .port = { |
577 | .membase = (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE), | 577 | .membase = (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE), |
578 | .mapbase = INTEGRATOR_UART1_BASE, | 578 | .mapbase = INTEGRATOR_UART1_BASE, |
579 | .iotype = SERIAL_IO_MEM, | 579 | .iotype = UPIO_MEM, |
580 | .irq = IRQ_UARTINT1, | 580 | .irq = IRQ_UARTINT1, |
581 | .uartclk = 14745600, | 581 | .uartclk = 14745600, |
582 | .fifosize = 16, | 582 | .fifosize = 16, |
diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c index ceb5d7f37bbd..344022fe53ef 100644 --- a/drivers/serial/au1x00_uart.c +++ b/drivers/serial/au1x00_uart.c | |||
@@ -892,7 +892,7 @@ serial8250_request_std_resource(struct uart_8250_port *up, struct resource **res | |||
892 | int ret = 0; | 892 | int ret = 0; |
893 | 893 | ||
894 | switch (up->port.iotype) { | 894 | switch (up->port.iotype) { |
895 | case SERIAL_IO_MEM: | 895 | case UPIO_MEM: |
896 | if (up->port.mapbase) { | 896 | if (up->port.mapbase) { |
897 | *res = request_mem_region(up->port.mapbase, size, "serial"); | 897 | *res = request_mem_region(up->port.mapbase, size, "serial"); |
898 | if (!*res) | 898 | if (!*res) |
@@ -900,8 +900,8 @@ serial8250_request_std_resource(struct uart_8250_port *up, struct resource **res | |||
900 | } | 900 | } |
901 | break; | 901 | break; |
902 | 902 | ||
903 | case SERIAL_IO_HUB6: | 903 | case UPIO_HUB6: |
904 | case SERIAL_IO_PORT: | 904 | case UPIO_PORT: |
905 | *res = request_region(up->port.iobase, size, "serial"); | 905 | *res = request_region(up->port.iobase, size, "serial"); |
906 | if (!*res) | 906 | if (!*res) |
907 | ret = -EBUSY; | 907 | ret = -EBUSY; |
@@ -919,7 +919,7 @@ static void serial8250_release_port(struct uart_port *port) | |||
919 | size <<= up->port.regshift; | 919 | size <<= up->port.regshift; |
920 | 920 | ||
921 | switch (up->port.iotype) { | 921 | switch (up->port.iotype) { |
922 | case SERIAL_IO_MEM: | 922 | case UPIO_MEM: |
923 | if (up->port.mapbase) { | 923 | if (up->port.mapbase) { |
924 | /* | 924 | /* |
925 | * Unmap the area. | 925 | * Unmap the area. |
@@ -935,8 +935,8 @@ static void serial8250_release_port(struct uart_port *port) | |||
935 | } | 935 | } |
936 | break; | 936 | break; |
937 | 937 | ||
938 | case SERIAL_IO_HUB6: | 938 | case UPIO_HUB6: |
939 | case SERIAL_IO_PORT: | 939 | case UPIO_PORT: |
940 | start = up->port.iobase; | 940 | start = up->port.iobase; |
941 | 941 | ||
942 | if (size) | 942 | if (size) |
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 16af5626c243..b7bf4c698a47 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c | |||
@@ -252,12 +252,9 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs) | |||
252 | /* If we have not enough room in tty flip buffer, then we try | 252 | /* If we have not enough room in tty flip buffer, then we try |
253 | * later, which will be the next rx-interrupt or a timeout | 253 | * later, which will be the next rx-interrupt or a timeout |
254 | */ | 254 | */ |
255 | if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) { | 255 | if(tty_buffer_request_room(tty, i) < i) { |
256 | tty->flip.work.func((void *)tty); | 256 | printk(KERN_WARNING "No room in flip buffer\n"); |
257 | if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) { | 257 | return; |
258 | printk(KERN_WARNING "TTY_DONT_FLIP set\n"); | ||
259 | return; | ||
260 | } | ||
261 | } | 258 | } |
262 | 259 | ||
263 | /* get pointer */ | 260 | /* get pointer */ |
@@ -276,9 +273,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs) | |||
276 | continue; | 273 | continue; |
277 | 274 | ||
278 | error_return: | 275 | error_return: |
279 | *tty->flip.char_buf_ptr++ = ch; | 276 | tty_insert_flip_char(tty, ch, flg); |
280 | *tty->flip.flag_buf_ptr++ = flg; | ||
281 | tty->flip.count++; | ||
282 | 277 | ||
283 | } /* End while (i--) */ | 278 | } /* End while (i--) */ |
284 | 279 | ||
@@ -908,7 +903,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { | |||
908 | .port = { | 903 | .port = { |
909 | .irq = SMC1_IRQ, | 904 | .irq = SMC1_IRQ, |
910 | .ops = &cpm_uart_pops, | 905 | .ops = &cpm_uart_pops, |
911 | .iotype = SERIAL_IO_MEM, | 906 | .iotype = UPIO_MEM, |
912 | .lock = SPIN_LOCK_UNLOCKED, | 907 | .lock = SPIN_LOCK_UNLOCKED, |
913 | }, | 908 | }, |
914 | .flags = FLAG_SMC, | 909 | .flags = FLAG_SMC, |
@@ -922,7 +917,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { | |||
922 | .port = { | 917 | .port = { |
923 | .irq = SMC2_IRQ, | 918 | .irq = SMC2_IRQ, |
924 | .ops = &cpm_uart_pops, | 919 | .ops = &cpm_uart_pops, |
925 | .iotype = SERIAL_IO_MEM, | 920 | .iotype = UPIO_MEM, |
926 | .lock = SPIN_LOCK_UNLOCKED, | 921 | .lock = SPIN_LOCK_UNLOCKED, |
927 | }, | 922 | }, |
928 | .flags = FLAG_SMC, | 923 | .flags = FLAG_SMC, |
@@ -939,7 +934,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { | |||
939 | .port = { | 934 | .port = { |
940 | .irq = SCC1_IRQ, | 935 | .irq = SCC1_IRQ, |
941 | .ops = &cpm_uart_pops, | 936 | .ops = &cpm_uart_pops, |
942 | .iotype = SERIAL_IO_MEM, | 937 | .iotype = UPIO_MEM, |
943 | .lock = SPIN_LOCK_UNLOCKED, | 938 | .lock = SPIN_LOCK_UNLOCKED, |
944 | }, | 939 | }, |
945 | .tx_nrfifos = TX_NUM_FIFO, | 940 | .tx_nrfifos = TX_NUM_FIFO, |
@@ -953,7 +948,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { | |||
953 | .port = { | 948 | .port = { |
954 | .irq = SCC2_IRQ, | 949 | .irq = SCC2_IRQ, |
955 | .ops = &cpm_uart_pops, | 950 | .ops = &cpm_uart_pops, |
956 | .iotype = SERIAL_IO_MEM, | 951 | .iotype = UPIO_MEM, |
957 | .lock = SPIN_LOCK_UNLOCKED, | 952 | .lock = SPIN_LOCK_UNLOCKED, |
958 | }, | 953 | }, |
959 | .tx_nrfifos = TX_NUM_FIFO, | 954 | .tx_nrfifos = TX_NUM_FIFO, |
@@ -967,7 +962,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { | |||
967 | .port = { | 962 | .port = { |
968 | .irq = SCC3_IRQ, | 963 | .irq = SCC3_IRQ, |
969 | .ops = &cpm_uart_pops, | 964 | .ops = &cpm_uart_pops, |
970 | .iotype = SERIAL_IO_MEM, | 965 | .iotype = UPIO_MEM, |
971 | .lock = SPIN_LOCK_UNLOCKED, | 966 | .lock = SPIN_LOCK_UNLOCKED, |
972 | }, | 967 | }, |
973 | .tx_nrfifos = TX_NUM_FIFO, | 968 | .tx_nrfifos = TX_NUM_FIFO, |
@@ -981,7 +976,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { | |||
981 | .port = { | 976 | .port = { |
982 | .irq = SCC4_IRQ, | 977 | .irq = SCC4_IRQ, |
983 | .ops = &cpm_uart_pops, | 978 | .ops = &cpm_uart_pops, |
984 | .iotype = SERIAL_IO_MEM, | 979 | .iotype = UPIO_MEM, |
985 | .lock = SPIN_LOCK_UNLOCKED, | 980 | .lock = SPIN_LOCK_UNLOCKED, |
986 | }, | 981 | }, |
987 | .tx_nrfifos = TX_NUM_FIFO, | 982 | .tx_nrfifos = TX_NUM_FIFO, |
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c index a64ba26a94e8..ba5541de673b 100644 --- a/drivers/serial/dz.c +++ b/drivers/serial/dz.c | |||
@@ -262,6 +262,7 @@ static inline void dz_receive_chars(struct dz_port *dport) | |||
262 | } | 262 | } |
263 | tty_insert_flip_char(tty, ch, flag); | 263 | tty_insert_flip_char(tty, ch, flag); |
264 | ignore_char: | 264 | ignore_char: |
265 | ; | ||
265 | } while (status & DZ_DVAL); | 266 | } while (status & DZ_DVAL); |
266 | 267 | ||
267 | if (tty) | 268 | if (tty) |
@@ -650,7 +651,7 @@ static void __init dz_init_ports(void) | |||
650 | for (i = 0, dport = dz_ports; i < DZ_NB_PORT; i++, dport++) { | 651 | for (i = 0, dport = dz_ports; i < DZ_NB_PORT; i++, dport++) { |
651 | spin_lock_init(&dport->port.lock); | 652 | spin_lock_init(&dport->port.lock); |
652 | dport->port.membase = (char *) base; | 653 | dport->port.membase = (char *) base; |
653 | dport->port.iotype = SERIAL_IO_PORT; | 654 | dport->port.iotype = UPIO_PORT; |
654 | dport->port.irq = dec_interrupt[DEC_IRQ_DZ11]; | 655 | dport->port.irq = dec_interrupt[DEC_IRQ_DZ11]; |
655 | dport->port.line = i; | 656 | dport->port.line = i; |
656 | dport->port.fifosize = 1; | 657 | dport->port.fifosize = 1; |
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 858048efe1ed..4d53fb5ca87b 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c | |||
@@ -668,7 +668,7 @@ static struct imx_port imx_ports[] = { | |||
668 | .rtsirq = UART1_MINT_RTS, | 668 | .rtsirq = UART1_MINT_RTS, |
669 | .port = { | 669 | .port = { |
670 | .type = PORT_IMX, | 670 | .type = PORT_IMX, |
671 | .iotype = SERIAL_IO_MEM, | 671 | .iotype = UPIO_MEM, |
672 | .membase = (void *)IMX_UART1_BASE, | 672 | .membase = (void *)IMX_UART1_BASE, |
673 | .mapbase = IMX_UART1_BASE, /* FIXME */ | 673 | .mapbase = IMX_UART1_BASE, /* FIXME */ |
674 | .irq = UART1_MINT_RX, | 674 | .irq = UART1_MINT_RX, |
@@ -684,7 +684,7 @@ static struct imx_port imx_ports[] = { | |||
684 | .rtsirq = UART2_MINT_RTS, | 684 | .rtsirq = UART2_MINT_RTS, |
685 | .port = { | 685 | .port = { |
686 | .type = PORT_IMX, | 686 | .type = PORT_IMX, |
687 | .iotype = SERIAL_IO_MEM, | 687 | .iotype = UPIO_MEM, |
688 | .membase = (void *)IMX_UART2_BASE, | 688 | .membase = (void *)IMX_UART2_BASE, |
689 | .mapbase = IMX_UART2_BASE, /* FIXME */ | 689 | .mapbase = IMX_UART2_BASE, /* FIXME */ |
690 | .irq = UART2_MINT_RX, | 690 | .irq = UART2_MINT_RX, |
diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c index 66f117d15065..419dd3cd7862 100644 --- a/drivers/serial/ip22zilog.c +++ b/drivers/serial/ip22zilog.c | |||
@@ -215,7 +215,7 @@ static void __load_zsregs(struct zilog_channel *channel, unsigned char *regs) | |||
215 | /* Lower and upper byte of baud rate generator divisor. */ | 215 | /* Lower and upper byte of baud rate generator divisor. */ |
216 | write_zsreg(channel, R12, regs[R12]); | 216 | write_zsreg(channel, R12, regs[R12]); |
217 | write_zsreg(channel, R13, regs[R13]); | 217 | write_zsreg(channel, R13, regs[R13]); |
218 | 218 | ||
219 | /* Now rewrite R14, with BRENAB (if set). */ | 219 | /* Now rewrite R14, with BRENAB (if set). */ |
220 | write_zsreg(channel, R14, regs[R14]); | 220 | write_zsreg(channel, R14, regs[R14]); |
221 | 221 | ||
@@ -571,7 +571,7 @@ static void ip22zilog_set_mctrl(struct uart_port *port, unsigned int mctrl) | |||
571 | else | 571 | else |
572 | clear_bits |= DTR; | 572 | clear_bits |= DTR; |
573 | 573 | ||
574 | /* NOTE: Not subject to 'transmitter active' rule. */ | 574 | /* NOTE: Not subject to 'transmitter active' rule. */ |
575 | up->curregs[R5] |= set_bits; | 575 | up->curregs[R5] |= set_bits; |
576 | up->curregs[R5] &= ~clear_bits; | 576 | up->curregs[R5] &= ~clear_bits; |
577 | write_zsreg(channel, R5, up->curregs[R5]); | 577 | write_zsreg(channel, R5, up->curregs[R5]); |
@@ -654,7 +654,7 @@ static void ip22zilog_enable_ms(struct uart_port *port) | |||
654 | if (new_reg != up->curregs[R15]) { | 654 | if (new_reg != up->curregs[R15]) { |
655 | up->curregs[R15] = new_reg; | 655 | up->curregs[R15] = new_reg; |
656 | 656 | ||
657 | /* NOTE: Not subject to 'transmitter active' rule. */ | 657 | /* NOTE: Not subject to 'transmitter active' rule. */ |
658 | write_zsreg(channel, R15, up->curregs[R15]); | 658 | write_zsreg(channel, R15, up->curregs[R15]); |
659 | } | 659 | } |
660 | } | 660 | } |
@@ -680,7 +680,7 @@ static void ip22zilog_break_ctl(struct uart_port *port, int break_state) | |||
680 | if (new_reg != up->curregs[R5]) { | 680 | if (new_reg != up->curregs[R5]) { |
681 | up->curregs[R5] = new_reg; | 681 | up->curregs[R5] = new_reg; |
682 | 682 | ||
683 | /* NOTE: Not subject to 'transmitter active' rule. */ | 683 | /* NOTE: Not subject to 'transmitter active' rule. */ |
684 | write_zsreg(channel, R5, up->curregs[R5]); | 684 | write_zsreg(channel, R5, up->curregs[R5]); |
685 | } | 685 | } |
686 | 686 | ||
diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h index 18753193f59b..dfc1e86d3aa1 100644 --- a/drivers/serial/jsm/jsm.h +++ b/drivers/serial/jsm/jsm.h | |||
@@ -380,7 +380,6 @@ struct neo_uart_struct { | |||
380 | extern struct uart_driver jsm_uart_driver; | 380 | extern struct uart_driver jsm_uart_driver; |
381 | extern struct board_ops jsm_neo_ops; | 381 | extern struct board_ops jsm_neo_ops; |
382 | extern int jsm_debug; | 382 | extern int jsm_debug; |
383 | extern int jsm_rawreadok; | ||
384 | 383 | ||
385 | /************************************************************************* | 384 | /************************************************************************* |
386 | * | 385 | * |
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c index 7e56c7824194..b1b66e71d281 100644 --- a/drivers/serial/jsm/jsm_driver.c +++ b/drivers/serial/jsm/jsm_driver.c | |||
@@ -49,11 +49,8 @@ struct uart_driver jsm_uart_driver = { | |||
49 | }; | 49 | }; |
50 | 50 | ||
51 | int jsm_debug; | 51 | int jsm_debug; |
52 | int jsm_rawreadok; | ||
53 | module_param(jsm_debug, int, 0); | 52 | module_param(jsm_debug, int, 0); |
54 | module_param(jsm_rawreadok, int, 0); | ||
55 | MODULE_PARM_DESC(jsm_debug, "Driver debugging level"); | 53 | MODULE_PARM_DESC(jsm_debug, "Driver debugging level"); |
56 | MODULE_PARM_DESC(jsm_rawreadok, "Bypass flip buffers on input"); | ||
57 | 54 | ||
58 | static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) | 55 | static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) |
59 | { | 56 | { |
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c index 6fa0d62d6f68..4d48b625cd3d 100644 --- a/drivers/serial/jsm/jsm_tty.c +++ b/drivers/serial/jsm/jsm_tty.c | |||
@@ -20,8 +20,10 @@ | |||
20 | * | 20 | * |
21 | * Contact Information: | 21 | * Contact Information: |
22 | * Scott H Kilau <Scott_Kilau@digi.com> | 22 | * Scott H Kilau <Scott_Kilau@digi.com> |
23 | * Wendy Xiong <wendyx@us.ltcfwd.linux.ibm.com> | 23 | * Ananda Venkatarman <mansarov@us.ibm.com> |
24 | * | 24 | * Modifications: |
25 | * 01/19/06: changed jsm_input routine to use the dynamically allocated | ||
26 | * tty_buffer changes. Contributors: Scott Kilau and Ananda V. | ||
25 | ***********************************************************************/ | 27 | ***********************************************************************/ |
26 | #include <linux/tty.h> | 28 | #include <linux/tty.h> |
27 | #include <linux/tty_flip.h> | 29 | #include <linux/tty_flip.h> |
@@ -497,16 +499,15 @@ void jsm_input(struct jsm_channel *ch) | |||
497 | { | 499 | { |
498 | struct jsm_board *bd; | 500 | struct jsm_board *bd; |
499 | struct tty_struct *tp; | 501 | struct tty_struct *tp; |
502 | struct tty_ldisc *ld; | ||
500 | u32 rmask; | 503 | u32 rmask; |
501 | u16 head; | 504 | u16 head; |
502 | u16 tail; | 505 | u16 tail; |
503 | int data_len; | 506 | int data_len; |
504 | unsigned long lock_flags; | 507 | unsigned long lock_flags; |
505 | int flip_len; | 508 | int flip_len = 0; |
506 | int len = 0; | 509 | int len = 0; |
507 | int n = 0; | 510 | int n = 0; |
508 | char *buf = NULL; | ||
509 | char *buf2 = NULL; | ||
510 | int s = 0; | 511 | int s = 0; |
511 | int i = 0; | 512 | int i = 0; |
512 | 513 | ||
@@ -574,56 +575,50 @@ void jsm_input(struct jsm_channel *ch) | |||
574 | 575 | ||
575 | /* | 576 | /* |
576 | * If the rxbuf is empty and we are not throttled, put as much | 577 | * If the rxbuf is empty and we are not throttled, put as much |
577 | * as we can directly into the linux TTY flip buffer. | 578 | * as we can directly into the linux TTY buffer. |
578 | * The jsm_rawreadok case takes advantage of carnal knowledge that | ||
579 | * the char_buf and the flag_buf are next to each other and | ||
580 | * are each of (2 * TTY_FLIPBUF_SIZE) size. | ||
581 | * | 579 | * |
582 | * NOTE: if(!tty->real_raw), the call to ldisc.receive_buf | ||
583 | *actually still uses the flag buffer, so you can't | ||
584 | *use it for input data | ||
585 | */ | 580 | */ |
586 | if (jsm_rawreadok) { | 581 | flip_len = TTY_FLIPBUF_SIZE; |
587 | if (tp->real_raw) | ||
588 | flip_len = MYFLIPLEN; | ||
589 | else | ||
590 | flip_len = 2 * TTY_FLIPBUF_SIZE; | ||
591 | } else | ||
592 | flip_len = TTY_FLIPBUF_SIZE - tp->flip.count; | ||
593 | 582 | ||
594 | len = min(data_len, flip_len); | 583 | len = min(data_len, flip_len); |
595 | len = min(len, (N_TTY_BUF_SIZE - 1) - tp->read_cnt); | 584 | len = min(len, (N_TTY_BUF_SIZE - 1) - tp->read_cnt); |
585 | ld = tty_ldisc_ref(tp); | ||
596 | 586 | ||
597 | if (len <= 0) { | 587 | /* |
598 | spin_unlock_irqrestore(&ch->ch_lock, lock_flags); | 588 | * If the DONT_FLIP flag is on, don't flush our buffer, and act |
599 | jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "jsm_input 1\n"); | 589 | * like the ld doesn't have any space to put the data right now. |
600 | return; | 590 | */ |
601 | } | 591 | if (test_bit(TTY_DONT_FLIP, &tp->flags)) |
592 | len = 0; | ||
602 | 593 | ||
603 | /* | 594 | /* |
604 | * If we're bypassing flip buffers on rx, we can blast it | 595 | * If we were unable to get a reference to the ld, |
605 | * right into the beginning of the buffer. | 596 | * don't flush our buffer, and act like the ld doesn't |
597 | * have any space to put the data right now. | ||
606 | */ | 598 | */ |
607 | if (jsm_rawreadok) { | 599 | if (!ld) { |
608 | if (tp->real_raw) { | 600 | len = 0; |
609 | if (ch->ch_flags & CH_FLIPBUF_IN_USE) { | ||
610 | jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, | ||
611 | "JSM - FLIPBUF in use. delaying input\n"); | ||
612 | spin_unlock_irqrestore(&ch->ch_lock, lock_flags); | ||
613 | return; | ||
614 | } | ||
615 | ch->ch_flags |= CH_FLIPBUF_IN_USE; | ||
616 | buf = ch->ch_bd->flipbuf; | ||
617 | buf2 = NULL; | ||
618 | } else { | ||
619 | buf = tp->flip.char_buf; | ||
620 | buf2 = tp->flip.flag_buf; | ||
621 | } | ||
622 | } else { | 601 | } else { |
623 | buf = tp->flip.char_buf_ptr; | 602 | /* |
624 | buf2 = tp->flip.flag_buf_ptr; | 603 | * If ld doesn't have a pointer to a receive_buf function, |
604 | * flush the data, then act like the ld doesn't have any | ||
605 | * space to put the data right now. | ||
606 | */ | ||
607 | if (!ld->receive_buf) { | ||
608 | ch->ch_r_head = ch->ch_r_tail; | ||
609 | len = 0; | ||
610 | } | ||
625 | } | 611 | } |
626 | 612 | ||
613 | if (len <= 0) { | ||
614 | spin_unlock_irqrestore(&ch->ch_lock, lock_flags); | ||
615 | jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "jsm_input 1\n"); | ||
616 | if (ld) | ||
617 | tty_ldisc_deref(ld); | ||
618 | return; | ||
619 | } | ||
620 | |||
621 | len = tty_buffer_request_room(tp, len); | ||
627 | n = len; | 622 | n = len; |
628 | 623 | ||
629 | /* | 624 | /* |
@@ -638,121 +633,47 @@ void jsm_input(struct jsm_channel *ch) | |||
638 | if (s <= 0) | 633 | if (s <= 0) |
639 | break; | 634 | break; |
640 | 635 | ||
641 | memcpy(buf, ch->ch_rqueue + tail, s); | 636 | /* |
642 | 637 | * If conditions are such that ld needs to see all | |
643 | /* buf2 is only set when port isn't raw */ | 638 | * UART errors, we will have to walk each character |
644 | if (buf2) | 639 | * and error byte and send them to the buffer one at |
645 | memcpy(buf2, ch->ch_equeue + tail, s); | 640 | * a time. |
646 | 641 | */ | |
647 | tail += s; | ||
648 | buf += s; | ||
649 | if (buf2) | ||
650 | buf2 += s; | ||
651 | n -= s; | ||
652 | /* Flip queue if needed */ | ||
653 | tail &= rmask; | ||
654 | } | ||
655 | 642 | ||
656 | /* | ||
657 | * In high performance mode, we don't have to update | ||
658 | * flag_buf or any of the counts or pointers into flip buf. | ||
659 | */ | ||
660 | if (!jsm_rawreadok) { | ||
661 | if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) { | 643 | if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) { |
662 | for (i = 0; i < len; i++) { | 644 | for (i = 0; i < s; i++) { |
663 | /* | 645 | /* |
664 | * Give the Linux ld the flags in the | 646 | * Give the Linux ld the flags in the |
665 | * format it likes. | 647 | * format it likes. |
666 | */ | 648 | */ |
667 | if (tp->flip.flag_buf_ptr[i] & UART_LSR_BI) | 649 | if (*(ch->ch_equeue +tail +i) & UART_LSR_BI) |
668 | tp->flip.flag_buf_ptr[i] = TTY_BREAK; | 650 | tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_BREAK); |
669 | else if (tp->flip.flag_buf_ptr[i] & UART_LSR_PE) | 651 | else if (*(ch->ch_equeue +tail +i) & UART_LSR_PE) |
670 | tp->flip.flag_buf_ptr[i] = TTY_PARITY; | 652 | tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_PARITY); |
671 | else if (tp->flip.flag_buf_ptr[i] & UART_LSR_FE) | 653 | else if (*(ch->ch_equeue +tail +i) & UART_LSR_FE) |
672 | tp->flip.flag_buf_ptr[i] = TTY_FRAME; | 654 | tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_FRAME); |
673 | else | 655 | else |
674 | tp->flip.flag_buf_ptr[i] = TTY_NORMAL; | 656 | tty_insert_flip_char(tp, *(ch->ch_rqueue +tail +i), TTY_NORMAL); |
675 | } | 657 | } |
676 | } else { | 658 | } else { |
677 | memset(tp->flip.flag_buf_ptr, 0, len); | 659 | tty_insert_flip_string(tp, ch->ch_rqueue + tail, s) ; |
678 | } | 660 | } |
679 | 661 | tail += s; | |
680 | tp->flip.char_buf_ptr += len; | 662 | n -= s; |
681 | tp->flip.flag_buf_ptr += len; | 663 | /* Flip queue if needed */ |
682 | tp->flip.count += len; | 664 | tail &= rmask; |
683 | } | ||
684 | else if (!tp->real_raw) { | ||
685 | if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) { | ||
686 | for (i = 0; i < len; i++) { | ||
687 | /* | ||
688 | * Give the Linux ld the flags in the | ||
689 | * format it likes. | ||
690 | */ | ||
691 | if (tp->flip.flag_buf_ptr[i] & UART_LSR_BI) | ||
692 | tp->flip.flag_buf_ptr[i] = TTY_BREAK; | ||
693 | else if (tp->flip.flag_buf_ptr[i] & UART_LSR_PE) | ||
694 | tp->flip.flag_buf_ptr[i] = TTY_PARITY; | ||
695 | else if (tp->flip.flag_buf_ptr[i] & UART_LSR_FE) | ||
696 | tp->flip.flag_buf_ptr[i] = TTY_FRAME; | ||
697 | else | ||
698 | tp->flip.flag_buf_ptr[i] = TTY_NORMAL; | ||
699 | } | ||
700 | } else | ||
701 | memset(tp->flip.flag_buf, 0, len); | ||
702 | } | 665 | } |
703 | 666 | ||
704 | /* | 667 | ch->ch_r_tail = tail & rmask; |
705 | * If we're doing raw reads, jam it right into the | 668 | ch->ch_e_tail = tail & rmask; |
706 | * line disc bypassing the flip buffers. | 669 | jsm_check_queue_flow_control(ch); |
707 | */ | 670 | spin_unlock_irqrestore(&ch->ch_lock, lock_flags); |
708 | if (jsm_rawreadok) { | ||
709 | if (tp->real_raw) { | ||
710 | ch->ch_r_tail = tail & rmask; | ||
711 | ch->ch_e_tail = tail & rmask; | ||
712 | |||
713 | jsm_check_queue_flow_control(ch); | ||
714 | |||
715 | /* !!! WE *MUST* LET GO OF ALL LOCKS BEFORE CALLING RECEIVE BUF !!! */ | ||
716 | 671 | ||
717 | spin_unlock_irqrestore(&ch->ch_lock, lock_flags); | 672 | /* Tell the tty layer its okay to "eat" the data now */ |
673 | tty_flip_buffer_push(tp); | ||
718 | 674 | ||
719 | jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, | 675 | if (ld) |
720 | "jsm_input. %d real_raw len:%d calling receive_buf for board %d\n", | 676 | tty_ldisc_deref(ld); |
721 | __LINE__, len, ch->ch_bd->boardnum); | ||
722 | tp->ldisc.receive_buf(tp, ch->ch_bd->flipbuf, NULL, len); | ||
723 | |||
724 | /* Allow use of channel flip buffer again */ | ||
725 | spin_lock_irqsave(&ch->ch_lock, lock_flags); | ||
726 | ch->ch_flags &= ~CH_FLIPBUF_IN_USE; | ||
727 | spin_unlock_irqrestore(&ch->ch_lock, lock_flags); | ||
728 | |||
729 | } else { | ||
730 | ch->ch_r_tail = tail & rmask; | ||
731 | ch->ch_e_tail = tail & rmask; | ||
732 | |||
733 | jsm_check_queue_flow_control(ch); | ||
734 | |||
735 | /* !!! WE *MUST* LET GO OF ALL LOCKS BEFORE CALLING RECEIVE BUF !!! */ | ||
736 | spin_unlock_irqrestore(&ch->ch_lock, lock_flags); | ||
737 | |||
738 | jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, | ||
739 | "jsm_input. %d not real_raw len:%d calling receive_buf for board %d\n", | ||
740 | __LINE__, len, ch->ch_bd->boardnum); | ||
741 | |||
742 | tp->ldisc.receive_buf(tp, tp->flip.char_buf, tp->flip.flag_buf, len); | ||
743 | } | ||
744 | } else { | ||
745 | ch->ch_r_tail = tail & rmask; | ||
746 | ch->ch_e_tail = tail & rmask; | ||
747 | |||
748 | jsm_check_queue_flow_control(ch); | ||
749 | |||
750 | spin_unlock_irqrestore(&ch->ch_lock, lock_flags); | ||
751 | |||
752 | jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, | ||
753 | "jsm_input. %d not jsm_read raw okay scheduling flip\n", __LINE__); | ||
754 | tty_schedule_flip(tp); | ||
755 | } | ||
756 | 677 | ||
757 | jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n"); | 678 | jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n"); |
758 | } | 679 | } |
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c index b48066a64a7d..242a04104393 100644 --- a/drivers/serial/m32r_sio.c +++ b/drivers/serial/m32r_sio.c | |||
@@ -80,7 +80,7 @@ | |||
80 | #include <asm/serial.h> | 80 | #include <asm/serial.h> |
81 | 81 | ||
82 | /* Standard COM flags */ | 82 | /* Standard COM flags */ |
83 | #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) | 83 | #define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST) |
84 | 84 | ||
85 | /* | 85 | /* |
86 | * SERIAL_PORT_DFNS tells us about built-in ports that have no | 86 | * SERIAL_PORT_DFNS tells us about built-in ports that have no |
diff --git a/drivers/serial/m32r_sio.h b/drivers/serial/m32r_sio.h index 07d0dd80aa3d..7c3ec24f7e50 100644 --- a/drivers/serial/m32r_sio.h +++ b/drivers/serial/m32r_sio.h | |||
@@ -37,7 +37,7 @@ struct old_serial_port { | |||
37 | unsigned int irq; | 37 | unsigned int irq; |
38 | unsigned int flags; | 38 | unsigned int flags; |
39 | unsigned char io_type; | 39 | unsigned char io_type; |
40 | unsigned char *iomem_base; | 40 | unsigned char __iomem *iomem_base; |
41 | unsigned short iomem_reg_shift; | 41 | unsigned short iomem_reg_shift; |
42 | }; | 42 | }; |
43 | 43 | ||
diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c index d957a3a9edf1..8cbbb954df2c 100644 --- a/drivers/serial/mcfserial.c +++ b/drivers/serial/mcfserial.c | |||
@@ -57,20 +57,16 @@ struct timer_list mcfrs_timer_struct; | |||
57 | * keep going. Perhaps one day the cflag settings for the | 57 | * keep going. Perhaps one day the cflag settings for the |
58 | * console can be used instead. | 58 | * console can be used instead. |
59 | */ | 59 | */ |
60 | #if defined(CONFIG_ARNEWSH) || defined(CONFIG_FREESCALE) || \ | ||
61 | defined(CONFIG_senTec) || defined(CONFIG_SNEHA) | ||
62 | #define CONSOLE_BAUD_RATE 19200 | ||
63 | #define DEFAULT_CBAUD B19200 | ||
64 | #endif | ||
65 | |||
66 | #if defined(CONFIG_HW_FEITH) | 60 | #if defined(CONFIG_HW_FEITH) |
67 | #define CONSOLE_BAUD_RATE 38400 | 61 | #define CONSOLE_BAUD_RATE 38400 |
68 | #define DEFAULT_CBAUD B38400 | 62 | #define DEFAULT_CBAUD B38400 |
69 | #endif | 63 | #elif defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB) |
70 | |||
71 | #if defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB) | ||
72 | #define CONSOLE_BAUD_RATE 115200 | 64 | #define CONSOLE_BAUD_RATE 115200 |
73 | #define DEFAULT_CBAUD B115200 | 65 | #define DEFAULT_CBAUD B115200 |
66 | #elif defined(CONFIG_ARNEWSH) || defined(CONFIG_FREESCALE) || \ | ||
67 | defined(CONFIG_senTec) || defined(CONFIG_SNEHA) | ||
68 | #define CONSOLE_BAUD_RATE 19200 | ||
69 | #define DEFAULT_CBAUD B19200 | ||
74 | #endif | 70 | #endif |
75 | 71 | ||
76 | #ifndef CONSOLE_BAUD_RATE | 72 | #ifndef CONSOLE_BAUD_RATE |
@@ -350,8 +346,7 @@ static inline void receive_chars(struct mcf_serial *info) | |||
350 | } | 346 | } |
351 | tty_insert_flip_char(tty, ch, flag); | 347 | tty_insert_flip_char(tty, ch, flag); |
352 | } | 348 | } |
353 | 349 | tty_schedule_flip(tty); | |
354 | schedule_work(&tty->flip.work); | ||
355 | return; | 350 | return; |
356 | } | 351 | } |
357 | 352 | ||
diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c index 4e49168c3176..868eaf4a1a68 100644 --- a/drivers/serial/mux.c +++ b/drivers/serial/mux.c | |||
@@ -462,7 +462,7 @@ static int __init mux_probe(struct parisc_device *dev) | |||
462 | port->mapbase = dev->hpa.start + MUX_OFFSET + | 462 | port->mapbase = dev->hpa.start + MUX_OFFSET + |
463 | (i * MUX_LINE_OFFSET); | 463 | (i * MUX_LINE_OFFSET); |
464 | port->membase = ioremap(port->mapbase, MUX_LINE_OFFSET); | 464 | port->membase = ioremap(port->mapbase, MUX_LINE_OFFSET); |
465 | port->iotype = SERIAL_IO_MEM; | 465 | port->iotype = UPIO_MEM; |
466 | port->type = PORT_MUX; | 466 | port->type = PORT_MUX; |
467 | port->irq = NO_IRQ; | 467 | port->irq = NO_IRQ; |
468 | port->uartclk = 0; | 468 | port->uartclk = 0; |
diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index 4e03a87f3fb4..9b7ed58cb53b 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c | |||
@@ -1492,7 +1492,7 @@ no_dma: | |||
1492 | /* | 1492 | /* |
1493 | * Init remaining bits of "port" structure | 1493 | * Init remaining bits of "port" structure |
1494 | */ | 1494 | */ |
1495 | uap->port.iotype = SERIAL_IO_MEM; | 1495 | uap->port.iotype = UPIO_MEM; |
1496 | uap->port.irq = np->intrs[0].line; | 1496 | uap->port.irq = np->intrs[0].line; |
1497 | uap->port.uartclk = ZS_CLOCK; | 1497 | uap->port.uartclk = ZS_CLOCK; |
1498 | uap->port.fifosize = 1; | 1498 | uap->port.fifosize = 1; |
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index 0a2dd6c5b95f..7410e093a6b9 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c | |||
@@ -161,7 +161,11 @@ s3c24xx_serial_dbg(const char *fmt, ...) | |||
161 | 161 | ||
162 | /* we can support 3 uarts, but not always use them */ | 162 | /* we can support 3 uarts, but not always use them */ |
163 | 163 | ||
164 | #ifdef CONFIG_CPU_S3C2400 | ||
165 | #define NR_PORTS (2) | ||
166 | #else | ||
164 | #define NR_PORTS (3) | 167 | #define NR_PORTS (3) |
168 | #endif | ||
165 | 169 | ||
166 | /* port irq numbers */ | 170 | /* port irq numbers */ |
167 | 171 | ||
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c index ff7b60b4de37..2c00b8625852 100644 --- a/drivers/serial/sa1100.c +++ b/drivers/serial/sa1100.c | |||
@@ -628,7 +628,7 @@ static void __init sa1100_init_ports(void) | |||
628 | sa1100_ports[i].port.ops = &sa1100_pops; | 628 | sa1100_ports[i].port.ops = &sa1100_pops; |
629 | sa1100_ports[i].port.fifosize = 8; | 629 | sa1100_ports[i].port.fifosize = 8; |
630 | sa1100_ports[i].port.line = i; | 630 | sa1100_ports[i].port.line = i; |
631 | sa1100_ports[i].port.iotype = SERIAL_IO_MEM; | 631 | sa1100_ports[i].port.iotype = UPIO_MEM; |
632 | init_timer(&sa1100_ports[i].timer); | 632 | init_timer(&sa1100_ports[i].timer); |
633 | sa1100_ports[i].timer.function = sa1100_timeout; | 633 | sa1100_ports[i].timer.function = sa1100_timeout; |
634 | sa1100_ports[i].timer.data = (unsigned long)&sa1100_ports[i]; | 634 | sa1100_ports[i].timer.data = (unsigned long)&sa1100_ports[i]; |
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 0717abfdae06..95fb4939c675 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c | |||
@@ -2237,7 +2237,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port) | |||
2237 | * If this port is a console, then the spinlock is already | 2237 | * If this port is a console, then the spinlock is already |
2238 | * initialised. | 2238 | * initialised. |
2239 | */ | 2239 | */ |
2240 | if (!uart_console(port)) | 2240 | if (!(uart_console(port) && (port->cons->flags & CON_ENABLED))) |
2241 | spin_lock_init(&port->lock); | 2241 | spin_lock_init(&port->lock); |
2242 | 2242 | ||
2243 | uart_configure_port(drv, state, port); | 2243 | uart_configure_port(drv, state, port); |
diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c index d0490f67f597..04186eaae227 100644 --- a/drivers/serial/serial_lh7a40x.c +++ b/drivers/serial/serial_lh7a40x.c | |||
@@ -501,7 +501,7 @@ static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = { | |||
501 | .port = { | 501 | .port = { |
502 | .membase = (void*) io_p2v (UART1_PHYS), | 502 | .membase = (void*) io_p2v (UART1_PHYS), |
503 | .mapbase = UART1_PHYS, | 503 | .mapbase = UART1_PHYS, |
504 | .iotype = SERIAL_IO_MEM, | 504 | .iotype = UPIO_MEM, |
505 | .irq = IRQ_UART1INTR, | 505 | .irq = IRQ_UART1INTR, |
506 | .uartclk = 14745600/2, | 506 | .uartclk = 14745600/2, |
507 | .fifosize = 16, | 507 | .fifosize = 16, |
@@ -514,7 +514,7 @@ static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = { | |||
514 | .port = { | 514 | .port = { |
515 | .membase = (void*) io_p2v (UART2_PHYS), | 515 | .membase = (void*) io_p2v (UART2_PHYS), |
516 | .mapbase = UART2_PHYS, | 516 | .mapbase = UART2_PHYS, |
517 | .iotype = SERIAL_IO_MEM, | 517 | .iotype = UPIO_MEM, |
518 | .irq = IRQ_UART2INTR, | 518 | .irq = IRQ_UART2INTR, |
519 | .uartclk = 14745600/2, | 519 | .uartclk = 14745600/2, |
520 | .fifosize = 16, | 520 | .fifosize = 16, |
@@ -527,7 +527,7 @@ static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = { | |||
527 | .port = { | 527 | .port = { |
528 | .membase = (void*) io_p2v (UART3_PHYS), | 528 | .membase = (void*) io_p2v (UART3_PHYS), |
529 | .mapbase = UART3_PHYS, | 529 | .mapbase = UART3_PHYS, |
530 | .iotype = SERIAL_IO_MEM, | 530 | .iotype = UPIO_MEM, |
531 | .irq = IRQ_UART3INTR, | 531 | .irq = IRQ_UART3INTR, |
532 | .uartclk = 14745600/2, | 532 | .uartclk = 14745600/2, |
533 | .fifosize = 16, | 533 | .fifosize = 16, |
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 80737c131ce7..44f6bf79bbe1 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c | |||
@@ -1468,10 +1468,10 @@ static struct sci_port sci_ports[] = { | |||
1468 | .port = { | 1468 | .port = { |
1469 | .membase = (void *)0xff923000, | 1469 | .membase = (void *)0xff923000, |
1470 | .mapbase = 0xff923000, | 1470 | .mapbase = 0xff923000, |
1471 | .iotype = SERIAL_IO_MEM, | 1471 | .iotype = UPIO_MEM, |
1472 | .irq = 61, | 1472 | .irq = 61, |
1473 | .ops = &sci_uart_ops, | 1473 | .ops = &sci_uart_ops, |
1474 | .flags = ASYNC_BOOT_AUTOCONF, | 1474 | .flags = UPF_BOOT_AUTOCONF, |
1475 | .line = 0, | 1475 | .line = 0, |
1476 | }, | 1476 | }, |
1477 | .type = PORT_SCIF, | 1477 | .type = PORT_SCIF, |
@@ -1482,10 +1482,10 @@ static struct sci_port sci_ports[] = { | |||
1482 | .port = { | 1482 | .port = { |
1483 | .membase = (void *)0xff924000, | 1483 | .membase = (void *)0xff924000, |
1484 | .mapbase = 0xff924000, | 1484 | .mapbase = 0xff924000, |
1485 | .iotype = SERIAL_IO_MEM, | 1485 | .iotype = UPIO_MEM, |
1486 | .irq = 62, | 1486 | .irq = 62, |
1487 | .ops = &sci_uart_ops, | 1487 | .ops = &sci_uart_ops, |
1488 | .flags = ASYNC_BOOT_AUTOCONF, | 1488 | .flags = UPF_BOOT_AUTOCONF, |
1489 | .line = 1, | 1489 | .line = 1, |
1490 | }, | 1490 | }, |
1491 | .type = PORT_SCIF, | 1491 | .type = PORT_SCIF, |
@@ -1496,10 +1496,10 @@ static struct sci_port sci_ports[] = { | |||
1496 | .port = { | 1496 | .port = { |
1497 | .membase = (void *)0xff925000, | 1497 | .membase = (void *)0xff925000, |
1498 | .mapbase = 0xff925000, | 1498 | .mapbase = 0xff925000, |
1499 | .iotype = SERIAL_IO_MEM, | 1499 | .iotype = UPIO_MEM, |
1500 | .irq = 63, | 1500 | .irq = 63, |
1501 | .ops = &sci_uart_ops, | 1501 | .ops = &sci_uart_ops, |
1502 | .flags = ASYNC_BOOT_AUTOCONF, | 1502 | .flags = UPF_BOOT_AUTOCONF, |
1503 | .line = 2, | 1503 | .line = 2, |
1504 | }, | 1504 | }, |
1505 | .type = PORT_SCIF, | 1505 | .type = PORT_SCIF, |
@@ -1511,10 +1511,10 @@ static struct sci_port sci_ports[] = { | |||
1511 | .port = { | 1511 | .port = { |
1512 | .membase = (void *)0xffe00000, | 1512 | .membase = (void *)0xffe00000, |
1513 | .mapbase = 0xffe00000, | 1513 | .mapbase = 0xffe00000, |
1514 | .iotype = SERIAL_IO_MEM, | 1514 | .iotype = UPIO_MEM, |
1515 | .irq = 43, | 1515 | .irq = 43, |
1516 | .ops = &sci_uart_ops, | 1516 | .ops = &sci_uart_ops, |
1517 | .flags = ASYNC_BOOT_AUTOCONF, | 1517 | .flags = UPF_BOOT_AUTOCONF, |
1518 | .line = 0, | 1518 | .line = 0, |
1519 | }, | 1519 | }, |
1520 | .type = PORT_SCIF, | 1520 | .type = PORT_SCIF, |
@@ -1525,10 +1525,10 @@ static struct sci_port sci_ports[] = { | |||
1525 | .port = { | 1525 | .port = { |
1526 | .membase = (void *)0xffe10000, | 1526 | .membase = (void *)0xffe10000, |
1527 | .mapbase = 0xffe10000, | 1527 | .mapbase = 0xffe10000, |
1528 | .iotype = SERIAL_IO_MEM, | 1528 | .iotype = UPIO_MEM, |
1529 | .irq = 79, | 1529 | .irq = 79, |
1530 | .ops = &sci_uart_ops, | 1530 | .ops = &sci_uart_ops, |
1531 | .flags = ASYNC_BOOT_AUTOCONF, | 1531 | .flags = UPF_BOOT_AUTOCONF, |
1532 | .line = 1, | 1532 | .line = 1, |
1533 | }, | 1533 | }, |
1534 | .type = PORT_SCIF, | 1534 | .type = PORT_SCIF, |
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 8bcaebcc0ad7..85664228a0b6 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c | |||
@@ -1036,7 +1036,7 @@ static void __init sab_attach_callback(struct linux_ebus_device *edev, void *arg | |||
1036 | up->port.irq = edev->irqs[0]; | 1036 | up->port.irq = edev->irqs[0]; |
1037 | up->port.fifosize = SAB82532_XMIT_FIFO_SIZE; | 1037 | up->port.fifosize = SAB82532_XMIT_FIFO_SIZE; |
1038 | up->port.mapbase = (unsigned long)up->regs; | 1038 | up->port.mapbase = (unsigned long)up->regs; |
1039 | up->port.iotype = SERIAL_IO_MEM; | 1039 | up->port.iotype = UPIO_MEM; |
1040 | 1040 | ||
1041 | writeb(SAB82532_IPC_IC_ACT_LOW, &up->regs->w.ipc); | 1041 | writeb(SAB82532_IPC_IC_ACT_LOW, &up->regs->w.ipc); |
1042 | 1042 | ||
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index bc67442c6b4c..308704566948 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c | |||
@@ -109,11 +109,11 @@ static _INLINE_ unsigned int serial_in(struct uart_sunsu_port *up, int offset) | |||
109 | offset <<= up->port.regshift; | 109 | offset <<= up->port.regshift; |
110 | 110 | ||
111 | switch (up->port.iotype) { | 111 | switch (up->port.iotype) { |
112 | case SERIAL_IO_HUB6: | 112 | case UPIO_HUB6: |
113 | outb(up->port.hub6 - 1 + offset, up->port.iobase); | 113 | outb(up->port.hub6 - 1 + offset, up->port.iobase); |
114 | return inb(up->port.iobase + 1); | 114 | return inb(up->port.iobase + 1); |
115 | 115 | ||
116 | case SERIAL_IO_MEM: | 116 | case UPIO_MEM: |
117 | return readb(up->port.membase + offset); | 117 | return readb(up->port.membase + offset); |
118 | 118 | ||
119 | default: | 119 | default: |
@@ -139,12 +139,12 @@ serial_out(struct uart_sunsu_port *up, int offset, int value) | |||
139 | offset <<= up->port.regshift; | 139 | offset <<= up->port.regshift; |
140 | 140 | ||
141 | switch (up->port.iotype) { | 141 | switch (up->port.iotype) { |
142 | case SERIAL_IO_HUB6: | 142 | case UPIO_HUB6: |
143 | outb(up->port.hub6 - 1 + offset, up->port.iobase); | 143 | outb(up->port.hub6 - 1 + offset, up->port.iobase); |
144 | outb(value, up->port.iobase + 1); | 144 | outb(value, up->port.iobase + 1); |
145 | break; | 145 | break; |
146 | 146 | ||
147 | case SERIAL_IO_MEM: | 147 | case UPIO_MEM: |
148 | writeb(value, up->port.membase + offset); | 148 | writeb(value, up->port.membase + offset); |
149 | break; | 149 | break; |
150 | 150 | ||
@@ -1052,7 +1052,7 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up) | |||
1052 | return; | 1052 | return; |
1053 | 1053 | ||
1054 | up->type_probed = PORT_UNKNOWN; | 1054 | up->type_probed = PORT_UNKNOWN; |
1055 | up->port.iotype = SERIAL_IO_MEM; | 1055 | up->port.iotype = UPIO_MEM; |
1056 | 1056 | ||
1057 | /* | 1057 | /* |
1058 | * First we look for Ebus-bases su's | 1058 | * First we look for Ebus-bases su's |
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index 3c72484adea7..5cc4d4c2935c 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c | |||
@@ -1487,7 +1487,7 @@ static void __init sunzilog_prepare(void) | |||
1487 | up[(chip * 2) + 1].port.membase = (void __iomem *)&rp->channelB; | 1487 | up[(chip * 2) + 1].port.membase = (void __iomem *)&rp->channelB; |
1488 | 1488 | ||
1489 | /* Channel A */ | 1489 | /* Channel A */ |
1490 | up[(chip * 2) + 0].port.iotype = SERIAL_IO_MEM; | 1490 | up[(chip * 2) + 0].port.iotype = UPIO_MEM; |
1491 | up[(chip * 2) + 0].port.irq = zilog_irq; | 1491 | up[(chip * 2) + 0].port.irq = zilog_irq; |
1492 | up[(chip * 2) + 0].port.uartclk = ZS_CLOCK; | 1492 | up[(chip * 2) + 0].port.uartclk = ZS_CLOCK; |
1493 | up[(chip * 2) + 0].port.fifosize = 1; | 1493 | up[(chip * 2) + 0].port.fifosize = 1; |
@@ -1498,7 +1498,7 @@ static void __init sunzilog_prepare(void) | |||
1498 | up[(chip * 2) + 0].flags |= SUNZILOG_FLAG_IS_CHANNEL_A; | 1498 | up[(chip * 2) + 0].flags |= SUNZILOG_FLAG_IS_CHANNEL_A; |
1499 | 1499 | ||
1500 | /* Channel B */ | 1500 | /* Channel B */ |
1501 | up[(chip * 2) + 1].port.iotype = SERIAL_IO_MEM; | 1501 | up[(chip * 2) + 1].port.iotype = UPIO_MEM; |
1502 | up[(chip * 2) + 1].port.irq = zilog_irq; | 1502 | up[(chip * 2) + 1].port.irq = zilog_irq; |
1503 | up[(chip * 2) + 1].port.uartclk = ZS_CLOCK; | 1503 | up[(chip * 2) + 1].port.uartclk = ZS_CLOCK; |
1504 | up[(chip * 2) + 1].port.fifosize = 1; | 1504 | up[(chip * 2) + 1].port.fifosize = 1; |
diff --git a/drivers/serial/v850e_uart.c b/drivers/serial/v850e_uart.c index 9378895a8d56..df705fda4243 100644 --- a/drivers/serial/v850e_uart.c +++ b/drivers/serial/v850e_uart.c | |||
@@ -496,7 +496,7 @@ static int __init v850e_uart_init (void) | |||
496 | 496 | ||
497 | port->ops = &v850e_uart_ops; | 497 | port->ops = &v850e_uart_ops; |
498 | port->line = chan; | 498 | port->line = chan; |
499 | port->iotype = SERIAL_IO_MEM; | 499 | port->iotype = UPIO_MEM; |
500 | port->flags = UPF_BOOT_AUTOCONF; | 500 | port->flags = UPF_BOOT_AUTOCONF; |
501 | 501 | ||
502 | /* We actually use multiple IRQs, but the serial | 502 | /* We actually use multiple IRQs, but the serial |
diff --git a/drivers/sn/ioc3.c b/drivers/sn/ioc3.c index c70ae81b5d98..12357e1fa558 100644 --- a/drivers/sn/ioc3.c +++ b/drivers/sn/ioc3.c | |||
@@ -38,10 +38,10 @@ static inline unsigned mcr_pack(unsigned pulse, unsigned sample) | |||
38 | 38 | ||
39 | static int nic_wait(struct ioc3_driver_data *idd) | 39 | static int nic_wait(struct ioc3_driver_data *idd) |
40 | { | 40 | { |
41 | volatile unsigned mcr; | 41 | unsigned mcr; |
42 | 42 | ||
43 | do { | 43 | do { |
44 | mcr = (volatile unsigned)idd->vma->mcr; | 44 | mcr = readl(&idd->vma->mcr); |
45 | } while (!(mcr & 2)); | 45 | } while (!(mcr & 2)); |
46 | 46 | ||
47 | return mcr & 1; | 47 | return mcr & 1; |
@@ -53,7 +53,7 @@ static int nic_reset(struct ioc3_driver_data *idd) | |||
53 | unsigned long flags; | 53 | unsigned long flags; |
54 | 54 | ||
55 | local_irq_save(flags); | 55 | local_irq_save(flags); |
56 | idd->vma->mcr = mcr_pack(500, 65); | 56 | writel(mcr_pack(500, 65), &idd->vma->mcr); |
57 | presence = nic_wait(idd); | 57 | presence = nic_wait(idd); |
58 | local_irq_restore(flags); | 58 | local_irq_restore(flags); |
59 | 59 | ||
@@ -68,7 +68,7 @@ static inline int nic_read_bit(struct ioc3_driver_data *idd) | |||
68 | unsigned long flags; | 68 | unsigned long flags; |
69 | 69 | ||
70 | local_irq_save(flags); | 70 | local_irq_save(flags); |
71 | idd->vma->mcr = mcr_pack(6, 13); | 71 | writel(mcr_pack(6, 13), &idd->vma->mcr); |
72 | result = nic_wait(idd); | 72 | result = nic_wait(idd); |
73 | local_irq_restore(flags); | 73 | local_irq_restore(flags); |
74 | 74 | ||
@@ -80,9 +80,9 @@ static inline int nic_read_bit(struct ioc3_driver_data *idd) | |||
80 | static inline void nic_write_bit(struct ioc3_driver_data *idd, int bit) | 80 | static inline void nic_write_bit(struct ioc3_driver_data *idd, int bit) |
81 | { | 81 | { |
82 | if (bit) | 82 | if (bit) |
83 | idd->vma->mcr = mcr_pack(6, 110); | 83 | writel(mcr_pack(6, 110), &idd->vma->mcr); |
84 | else | 84 | else |
85 | idd->vma->mcr = mcr_pack(80, 30); | 85 | writel(mcr_pack(80, 30), &idd->vma->mcr); |
86 | 86 | ||
87 | nic_wait(idd); | 87 | nic_wait(idd); |
88 | } | 88 | } |
@@ -337,7 +337,7 @@ static void probe_nic(struct ioc3_driver_data *idd) | |||
337 | int save = 0, loops = 3; | 337 | int save = 0, loops = 3; |
338 | unsigned long first, addr; | 338 | unsigned long first, addr; |
339 | 339 | ||
340 | idd->vma->gpcr_s = GPCR_MLAN_EN; | 340 | writel(GPCR_MLAN_EN, &idd->vma->gpcr_s); |
341 | 341 | ||
342 | while(loops>0) { | 342 | while(loops>0) { |
343 | idd->nic_part[0] = 0; | 343 | idd->nic_part[0] = 0; |
@@ -408,7 +408,7 @@ static irqreturn_t ioc3_intr_io(int irq, void *arg, struct pt_regs *regs) | |||
408 | 408 | ||
409 | read_lock_irqsave(&ioc3_submodules_lock, flags); | 409 | read_lock_irqsave(&ioc3_submodules_lock, flags); |
410 | 410 | ||
411 | if(idd->dual_irq && idd->vma->eisr) { | 411 | if(idd->dual_irq && readb(&idd->vma->eisr)) { |
412 | /* send Ethernet IRQ to the driver */ | 412 | /* send Ethernet IRQ to the driver */ |
413 | if(ioc3_ethernet && idd->active[ioc3_ethernet->id] && | 413 | if(ioc3_ethernet && idd->active[ioc3_ethernet->id] && |
414 | ioc3_ethernet->intr) { | 414 | ioc3_ethernet->intr) { |
@@ -682,7 +682,7 @@ static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) | |||
682 | idd->id = ioc3_counter++; | 682 | idd->id = ioc3_counter++; |
683 | up_write(&ioc3_devices_rwsem); | 683 | up_write(&ioc3_devices_rwsem); |
684 | 684 | ||
685 | idd->gpdr_shadow = idd->vma->gpdr; | 685 | idd->gpdr_shadow = readl(&idd->vma->gpdr); |
686 | 686 | ||
687 | /* Read IOC3 NIC contents */ | 687 | /* Read IOC3 NIC contents */ |
688 | probe_nic(idd); | 688 | probe_nic(idd); |
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index b77dbd63e596..7a75faeb0526 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig | |||
@@ -75,16 +75,6 @@ config SPI_BUTTERFLY | |||
75 | inexpensive battery powered microcontroller evaluation board. | 75 | inexpensive battery powered microcontroller evaluation board. |
76 | This same cable can be used to flash new firmware. | 76 | This same cable can be used to flash new firmware. |
77 | 77 | ||
78 | config SPI_BUTTERFLY | ||
79 | tristate "Parallel port adapter for AVR Butterfly (DEVELOPMENT)" | ||
80 | depends on SPI_MASTER && PARPORT && EXPERIMENTAL | ||
81 | select SPI_BITBANG | ||
82 | help | ||
83 | This uses a custom parallel port cable to connect to an AVR | ||
84 | Butterfly <http://www.atmel.com/products/avr/butterfly>, an | ||
85 | inexpensive battery powered microcontroller evaluation board. | ||
86 | This same cable can be used to flash new firmware. | ||
87 | |||
88 | # | 78 | # |
89 | # Add new SPI master controllers in alphabetical order above this line | 79 | # Add new SPI master controllers in alphabetical order above this line |
90 | # | 80 | # |
diff --git a/drivers/spi/spi_butterfly.c b/drivers/spi/spi_butterfly.c index 79a3c59615ab..ff9e5faa4dc9 100644 --- a/drivers/spi/spi_butterfly.c +++ b/drivers/spi/spi_butterfly.c | |||
@@ -163,21 +163,20 @@ static void butterfly_chipselect(struct spi_device *spi, int value) | |||
163 | struct butterfly *pp = spidev_to_pp(spi); | 163 | struct butterfly *pp = spidev_to_pp(spi); |
164 | 164 | ||
165 | /* set default clock polarity */ | 165 | /* set default clock polarity */ |
166 | if (value) | 166 | if (value != BITBANG_CS_INACTIVE) |
167 | setsck(spi, spi->mode & SPI_CPOL); | 167 | setsck(spi, spi->mode & SPI_CPOL); |
168 | 168 | ||
169 | /* no chipselect on this USI link config */ | 169 | /* no chipselect on this USI link config */ |
170 | if (is_usidev(spi)) | 170 | if (is_usidev(spi)) |
171 | return; | 171 | return; |
172 | 172 | ||
173 | /* here, value == "activate or not" */ | 173 | /* here, value == "activate or not"; |
174 | 174 | * most PARPORT_CONTROL_* bits are negated, so we must | |
175 | /* most PARPORT_CONTROL_* bits are negated */ | 175 | * morph it to value == "bit value to write in control register" |
176 | */ | ||
176 | if (spi_cs_bit == PARPORT_CONTROL_INIT) | 177 | if (spi_cs_bit == PARPORT_CONTROL_INIT) |
177 | value = !value; | 178 | value = !value; |
178 | 179 | ||
179 | /* here, value == "bit value to write in control register" */ | ||
180 | |||
181 | parport_frob_control(pp->port, spi_cs_bit, value ? spi_cs_bit : 0); | 180 | parport_frob_control(pp->port, spi_cs_bit, value ? spi_cs_bit : 0); |
182 | } | 181 | } |
183 | 182 | ||
@@ -202,7 +201,9 @@ butterfly_txrx_word_mode0(struct spi_device *spi, | |||
202 | 201 | ||
203 | /* override default partitioning with cmdlinepart */ | 202 | /* override default partitioning with cmdlinepart */ |
204 | static struct mtd_partition partitions[] = { { | 203 | static struct mtd_partition partitions[] = { { |
205 | /* JFFS2 wants partitions of 4*N blocks for this device ... */ | 204 | /* JFFS2 wants partitions of 4*N blocks for this device, |
205 | * so sectors 0 and 1 can't be partitions by themselves. | ||
206 | */ | ||
206 | 207 | ||
207 | /* sector 0 = 8 pages * 264 bytes/page (1 block) | 208 | /* sector 0 = 8 pages * 264 bytes/page (1 block) |
208 | * sector 1 = 248 pages * 264 bytes/page | 209 | * sector 1 = 248 pages * 264 bytes/page |
@@ -316,8 +317,9 @@ static void butterfly_attach(struct parport *p) | |||
316 | if (status < 0) | 317 | if (status < 0) |
317 | goto clean2; | 318 | goto clean2; |
318 | 319 | ||
319 | /* Bus 1 lets us talk to at45db041b (firmware disables AVR) | 320 | /* Bus 1 lets us talk to at45db041b (firmware disables AVR SPI), AVR |
320 | * or AVR (firmware resets at45, acts as spi slave) | 321 | * (firmware resets at45, acts as spi slave) or neither (we ignore |
322 | * both, AVR uses AT45). Here we expect firmware for the first option. | ||
321 | */ | 323 | */ |
322 | pp->info[0].max_speed_hz = 15 * 1000 * 1000; | 324 | pp->info[0].max_speed_hz = 15 * 1000 * 1000; |
323 | strcpy(pp->info[0].modalias, "mtd_dataflash"); | 325 | strcpy(pp->info[0].modalias, "mtd_dataflash"); |
@@ -330,7 +332,9 @@ static void butterfly_attach(struct parport *p) | |||
330 | pp->dataflash->dev.bus_id); | 332 | pp->dataflash->dev.bus_id); |
331 | 333 | ||
332 | #ifdef HAVE_USI | 334 | #ifdef HAVE_USI |
333 | /* even more custom AVR firmware */ | 335 | /* Bus 2 is only for talking to the AVR, and it can work no |
336 | * matter who masters bus 1; needs appropriate AVR firmware. | ||
337 | */ | ||
334 | pp->info[1].max_speed_hz = 10 /* ?? */ * 1000 * 1000; | 338 | pp->info[1].max_speed_hz = 10 /* ?? */ * 1000 * 1000; |
335 | strcpy(pp->info[1].modalias, "butterfly"); | 339 | strcpy(pp->info[1].modalias, "butterfly"); |
336 | // pp->info[1].platform_data = ... TBD ... ; | 340 | // pp->info[1].platform_data = ... TBD ... ; |
@@ -378,13 +382,8 @@ static void butterfly_detach(struct parport *p) | |||
378 | pp = butterfly; | 382 | pp = butterfly; |
379 | butterfly = NULL; | 383 | butterfly = NULL; |
380 | 384 | ||
381 | #ifdef HAVE_USI | 385 | /* stop() unregisters child devices too */ |
382 | spi_unregister_device(pp->butterfly); | 386 | pdev = to_platform_device(pp->bitbang.master->cdev.dev); |
383 | pp->butterfly = NULL; | ||
384 | #endif | ||
385 | spi_unregister_device(pp->dataflash); | ||
386 | pp->dataflash = NULL; | ||
387 | |||
388 | status = spi_bitbang_stop(&pp->bitbang); | 387 | status = spi_bitbang_stop(&pp->bitbang); |
389 | 388 | ||
390 | /* turn off VCC */ | 389 | /* turn off VCC */ |
@@ -394,8 +393,6 @@ static void butterfly_detach(struct parport *p) | |||
394 | parport_release(pp->pd); | 393 | parport_release(pp->pd); |
395 | parport_unregister_device(pp->pd); | 394 | parport_unregister_device(pp->pd); |
396 | 395 | ||
397 | pdev = to_platform_device(pp->bitbang.master->cdev.dev); | ||
398 | |||
399 | (void) spi_master_put(pp->bitbang.master); | 396 | (void) spi_master_put(pp->bitbang.master); |
400 | 397 | ||
401 | platform_device_unregister(pdev); | 398 | platform_device_unregister(pdev); |
@@ -420,4 +417,5 @@ static void __exit butterfly_exit(void) | |||
420 | } | 417 | } |
421 | module_exit(butterfly_exit); | 418 | module_exit(butterfly_exit); |
422 | 419 | ||
420 | MODULE_DESCRIPTION("Parport Adapter driver for AVR Butterfly"); | ||
423 | MODULE_LICENSE("GPL"); | 421 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/tc/tc.c b/drivers/tc/tc.c index a0e5af638e0e..4a51e56f85b6 100644 --- a/drivers/tc/tc.c +++ b/drivers/tc/tc.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
18 | 18 | ||
19 | #include <asm/addrspace.h> | 19 | #include <asm/addrspace.h> |
20 | #include <asm/bug.h> | ||
21 | #include <asm/errno.h> | 20 | #include <asm/errno.h> |
22 | #include <asm/io.h> | 21 | #include <asm/io.h> |
23 | #include <asm/paccess.h> | 22 | #include <asm/paccess.h> |
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c index f6704688ee8c..5578a9dd04e8 100644 --- a/drivers/telephony/ixj.c +++ b/drivers/telephony/ixj.c | |||
@@ -3558,10 +3558,16 @@ static void ixj_write_frame(IXJ *j) | |||
3558 | } | 3558 | } |
3559 | /* Add word 0 to G.729 frames for the 8021. Right now we don't do VAD/CNG */ | 3559 | /* Add word 0 to G.729 frames for the 8021. Right now we don't do VAD/CNG */ |
3560 | if (j->play_codec == G729 && (cnt == 0 || cnt == 10 || cnt == 20)) { | 3560 | if (j->play_codec == G729 && (cnt == 0 || cnt == 10 || cnt == 20)) { |
3561 | if(j->write_buffer_rp + cnt == 0 && j->write_buffer_rp + cnt + 1 == 0 && j->write_buffer_rp + cnt + 2 == 0 && | 3561 | if (j->write_buffer_rp[cnt] == 0 && |
3562 | j->write_buffer_rp + cnt + 3 == 0 && j->write_buffer_rp + cnt + 4 == 0 && j->write_buffer_rp + cnt + 5 == 0 && | 3562 | j->write_buffer_rp[cnt + 1] == 0 && |
3563 | j->write_buffer_rp + cnt + 6 == 0 && j->write_buffer_rp + cnt + 7 == 0 && j->write_buffer_rp + cnt + 8 == 0 && | 3563 | j->write_buffer_rp[cnt + 2] == 0 && |
3564 | j->write_buffer_rp + cnt + 9 == 0) { | 3564 | j->write_buffer_rp[cnt + 3] == 0 && |
3565 | j->write_buffer_rp[cnt + 4] == 0 && | ||
3566 | j->write_buffer_rp[cnt + 5] == 0 && | ||
3567 | j->write_buffer_rp[cnt + 6] == 0 && | ||
3568 | j->write_buffer_rp[cnt + 7] == 0 && | ||
3569 | j->write_buffer_rp[cnt + 8] == 0 && | ||
3570 | j->write_buffer_rp[cnt + 9] == 0) { | ||
3565 | /* someone is trying to write silence lets make this a type 0 frame. */ | 3571 | /* someone is trying to write silence lets make this a type 0 frame. */ |
3566 | outb_p(0x00, j->DSPbase + 0x0C); | 3572 | outb_p(0x00, j->DSPbase + 0x0C); |
3567 | outb_p(0x00, j->DSPbase + 0x0D); | 3573 | outb_p(0x00, j->DSPbase + 0x0D); |
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 076462c8ba2a..dce9d987f0fc 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -378,7 +378,7 @@ const struct usb_device_id *usb_match_id(struct usb_interface *interface, | |||
378 | 378 | ||
379 | return NULL; | 379 | return NULL; |
380 | } | 380 | } |
381 | EXPORT_SYMBOL_GPL(usb_match_id); | 381 | EXPORT_SYMBOL(usb_match_id); |
382 | 382 | ||
383 | int usb_device_match(struct device *dev, struct device_driver *drv) | 383 | int usb_device_match(struct device *dev, struct device_driver *drv) |
384 | { | 384 | { |
@@ -446,7 +446,7 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner) | |||
446 | 446 | ||
447 | return retval; | 447 | return retval; |
448 | } | 448 | } |
449 | EXPORT_SYMBOL_GPL(usb_register_driver); | 449 | EXPORT_SYMBOL(usb_register_driver); |
450 | 450 | ||
451 | /** | 451 | /** |
452 | * usb_deregister - unregister a USB driver | 452 | * usb_deregister - unregister a USB driver |
@@ -469,4 +469,4 @@ void usb_deregister(struct usb_driver *driver) | |||
469 | 469 | ||
470 | usbfs_update_special(); | 470 | usbfs_update_special(); |
471 | } | 471 | } |
472 | EXPORT_SYMBOL_GPL(usb_deregister); | 472 | EXPORT_SYMBOL(usb_deregister); |
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 9d5015e99372..bd39bbd88d41 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/ctype.h> | 13 | #include <linux/ctype.h> |
14 | #include <linux/err.h> | 14 | #include <linux/err.h> |
15 | #include <linux/fb.h> | 15 | #include <linux/fb.h> |
16 | #include <asm/bug.h> | ||
17 | 16 | ||
18 | static ssize_t backlight_show_power(struct class_device *cdev, char *buf) | 17 | static ssize_t backlight_show_power(struct class_device *cdev, char *buf) |
19 | { | 18 | { |
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index 68c690605aa7..9e32485ee7bb 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/ctype.h> | 13 | #include <linux/ctype.h> |
14 | #include <linux/err.h> | 14 | #include <linux/err.h> |
15 | #include <linux/fb.h> | 15 | #include <linux/fb.h> |
16 | #include <asm/bug.h> | ||
17 | 16 | ||
18 | static ssize_t lcd_show_power(struct class_device *cdev, char *buf) | 17 | static ssize_t lcd_show_power(struct class_device *cdev, char *buf) |
19 | { | 18 | { |
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c index a7bcd17112c0..0339f5640a78 100644 --- a/drivers/video/console/sticore.c +++ b/drivers/video/console/sticore.c | |||
@@ -30,10 +30,11 @@ | |||
30 | 30 | ||
31 | #define STI_DRIVERVERSION "Version 0.9a" | 31 | #define STI_DRIVERVERSION "Version 0.9a" |
32 | 32 | ||
33 | struct sti_struct *default_sti; | 33 | struct sti_struct *default_sti __read_mostly; |
34 | 34 | ||
35 | static int num_sti_roms; /* # of STI ROMS found */ | 35 | /* number of STI ROMS found and their ptrs to each struct */ |
36 | static struct sti_struct *sti_roms[MAX_STI_ROMS]; /* ptr to each sti_struct */ | 36 | static int num_sti_roms __read_mostly; |
37 | static struct sti_struct *sti_roms[MAX_STI_ROMS] __read_mostly; | ||
37 | 38 | ||
38 | 39 | ||
39 | /* The colour indices used by STI are | 40 | /* The colour indices used by STI are |
@@ -266,7 +267,7 @@ sti_rom_copy(unsigned long base, unsigned long count, void *dest) | |||
266 | 267 | ||
267 | 268 | ||
268 | 269 | ||
269 | static char default_sti_path[21]; | 270 | static char default_sti_path[21] __read_mostly; |
270 | 271 | ||
271 | #ifndef MODULE | 272 | #ifndef MODULE |
272 | static int __init sti_setup(char *str) | 273 | static int __init sti_setup(char *str) |
@@ -414,10 +415,10 @@ sti_init_glob_cfg(struct sti_struct *sti, | |||
414 | if (!sti->sti_mem_request) | 415 | if (!sti->sti_mem_request) |
415 | sti->sti_mem_request = 256; /* STI default */ | 416 | sti->sti_mem_request = 256; /* STI default */ |
416 | 417 | ||
417 | glob_cfg = kmalloc(sizeof(*sti->glob_cfg), GFP_KERNEL); | 418 | glob_cfg = kzalloc(sizeof(*sti->glob_cfg), GFP_KERNEL); |
418 | glob_cfg_ext = kmalloc(sizeof(*glob_cfg_ext), GFP_KERNEL); | 419 | glob_cfg_ext = kzalloc(sizeof(*glob_cfg_ext), GFP_KERNEL); |
419 | save_addr = kmalloc(save_addr_size, GFP_KERNEL); | 420 | save_addr = kzalloc(save_addr_size, GFP_KERNEL); |
420 | sti_mem_addr = kmalloc(sti->sti_mem_request, GFP_KERNEL); | 421 | sti_mem_addr = kzalloc(sti->sti_mem_request, GFP_KERNEL); |
421 | 422 | ||
422 | if (!(glob_cfg && glob_cfg_ext && save_addr && sti_mem_addr)) { | 423 | if (!(glob_cfg && glob_cfg_ext && save_addr && sti_mem_addr)) { |
423 | kfree(glob_cfg); | 424 | kfree(glob_cfg); |
@@ -427,11 +428,6 @@ sti_init_glob_cfg(struct sti_struct *sti, | |||
427 | return -ENOMEM; | 428 | return -ENOMEM; |
428 | } | 429 | } |
429 | 430 | ||
430 | memset(glob_cfg, 0, sizeof(*glob_cfg)); | ||
431 | memset(glob_cfg_ext, 0, sizeof(*glob_cfg_ext)); | ||
432 | memset(save_addr, 0, save_addr_size); | ||
433 | memset(sti_mem_addr, 0, sti->sti_mem_request); | ||
434 | |||
435 | glob_cfg->ext_ptr = STI_PTR(glob_cfg_ext); | 431 | glob_cfg->ext_ptr = STI_PTR(glob_cfg_ext); |
436 | glob_cfg->save_addr = STI_PTR(save_addr); | 432 | glob_cfg->save_addr = STI_PTR(save_addr); |
437 | for (i=0; i<8; i++) { | 433 | for (i=0; i<8; i++) { |
@@ -502,9 +498,9 @@ sti_init_glob_cfg(struct sti_struct *sti, | |||
502 | 498 | ||
503 | #ifdef CONFIG_FB | 499 | #ifdef CONFIG_FB |
504 | struct sti_cooked_font * __init | 500 | struct sti_cooked_font * __init |
505 | sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name ) | 501 | sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) |
506 | { | 502 | { |
507 | struct font_desc *fbfont; | 503 | const struct font_desc *fbfont; |
508 | unsigned int size, bpc; | 504 | unsigned int size, bpc; |
509 | void *dest; | 505 | void *dest; |
510 | struct sti_rom_font *nf; | 506 | struct sti_rom_font *nf; |
@@ -525,10 +521,9 @@ sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name ) | |||
525 | size = bpc * 256; | 521 | size = bpc * 256; |
526 | size += sizeof(struct sti_rom_font); | 522 | size += sizeof(struct sti_rom_font); |
527 | 523 | ||
528 | nf = kmalloc(size, GFP_KERNEL); | 524 | nf = kzalloc(size, GFP_KERNEL); |
529 | if (!nf) | 525 | if (!nf) |
530 | return NULL; | 526 | return NULL; |
531 | memset(nf, 0, size); | ||
532 | 527 | ||
533 | nf->first_char = 0; | 528 | nf->first_char = 0; |
534 | nf->last_char = 255; | 529 | nf->last_char = 255; |
@@ -544,7 +539,7 @@ sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name ) | |||
544 | dest += sizeof(struct sti_rom_font); | 539 | dest += sizeof(struct sti_rom_font); |
545 | memcpy(dest, fbfont->data, bpc*256); | 540 | memcpy(dest, fbfont->data, bpc*256); |
546 | 541 | ||
547 | cooked_font = kmalloc(sizeof(*cooked_font), GFP_KERNEL); | 542 | cooked_font = kzalloc(sizeof(*cooked_font), GFP_KERNEL); |
548 | if (!cooked_font) { | 543 | if (!cooked_font) { |
549 | kfree(nf); | 544 | kfree(nf); |
550 | return NULL; | 545 | return NULL; |
@@ -559,7 +554,7 @@ sti_select_fbfont( struct sti_cooked_rom *cooked_rom, char *fbfont_name ) | |||
559 | } | 554 | } |
560 | #else | 555 | #else |
561 | struct sti_cooked_font * __init | 556 | struct sti_cooked_font * __init |
562 | sti_select_fbfont(struct sti_cooked_rom *cooked_rom, char *fbfont_name) | 557 | sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) |
563 | { | 558 | { |
564 | return NULL; | 559 | return NULL; |
565 | } | 560 | } |
@@ -617,7 +612,7 @@ sti_cook_fonts(struct sti_cooked_rom *cooked_rom, | |||
617 | struct sti_rom_font *raw_font, *font_start; | 612 | struct sti_rom_font *raw_font, *font_start; |
618 | struct sti_cooked_font *cooked_font; | 613 | struct sti_cooked_font *cooked_font; |
619 | 614 | ||
620 | cooked_font = kmalloc(sizeof(*cooked_font), GFP_KERNEL); | 615 | cooked_font = kzalloc(sizeof(*cooked_font), GFP_KERNEL); |
621 | if (!cooked_font) | 616 | if (!cooked_font) |
622 | return 0; | 617 | return 0; |
623 | 618 | ||
@@ -631,7 +626,7 @@ sti_cook_fonts(struct sti_cooked_rom *cooked_rom, | |||
631 | while (raw_font->next_font) { | 626 | while (raw_font->next_font) { |
632 | raw_font = ((void *)font_start) + (raw_font->next_font); | 627 | raw_font = ((void *)font_start) + (raw_font->next_font); |
633 | 628 | ||
634 | cooked_font->next_font = kmalloc(sizeof(*cooked_font), GFP_KERNEL); | 629 | cooked_font->next_font = kzalloc(sizeof(*cooked_font), GFP_KERNEL); |
635 | if (!cooked_font->next_font) | 630 | if (!cooked_font->next_font) |
636 | return 1; | 631 | return 1; |
637 | 632 | ||
@@ -668,10 +663,9 @@ sti_bmode_font_raw(struct sti_cooked_font *f) | |||
668 | unsigned char *n, *p, *q; | 663 | unsigned char *n, *p, *q; |
669 | int size = f->raw->bytes_per_char*256+sizeof(struct sti_rom_font); | 664 | int size = f->raw->bytes_per_char*256+sizeof(struct sti_rom_font); |
670 | 665 | ||
671 | n = kmalloc (4*size, GFP_KERNEL); | 666 | n = kzalloc (4*size, GFP_KERNEL); |
672 | if (!n) | 667 | if (!n) |
673 | return NULL; | 668 | return NULL; |
674 | memset (n, 0, 4*size); | ||
675 | p = n + 3; | 669 | p = n + 3; |
676 | q = (unsigned char *)f->raw; | 670 | q = (unsigned char *)f->raw; |
677 | while (size--) { | 671 | while (size--) { |
@@ -816,13 +810,12 @@ sti_try_rom_generic(unsigned long address, unsigned long hpa, struct pci_dev *pd | |||
816 | return NULL; | 810 | return NULL; |
817 | } | 811 | } |
818 | 812 | ||
819 | sti = kmalloc(sizeof(*sti), GFP_KERNEL); | 813 | sti = kzalloc(sizeof(*sti), GFP_KERNEL); |
820 | if (!sti) { | 814 | if (!sti) { |
821 | printk(KERN_ERR "Not enough memory !\n"); | 815 | printk(KERN_ERR "Not enough memory !\n"); |
822 | return NULL; | 816 | return NULL; |
823 | } | 817 | } |
824 | 818 | ||
825 | memset(sti, 0, sizeof(*sti)); | ||
826 | spin_lock_init(&sti->lock); | 819 | spin_lock_init(&sti->lock); |
827 | 820 | ||
828 | test_rom: | 821 | test_rom: |
@@ -1035,7 +1028,7 @@ static struct parisc_driver pa_sti_driver = { | |||
1035 | * sti_init_roms() - detects all STI ROMs and stores them in sti_roms[] | 1028 | * sti_init_roms() - detects all STI ROMs and stores them in sti_roms[] |
1036 | */ | 1029 | */ |
1037 | 1030 | ||
1038 | static int sticore_initialized; | 1031 | static int sticore_initialized __read_mostly; |
1039 | 1032 | ||
1040 | static void __init sti_init_roms(void) | 1033 | static void __init sti_init_roms(void) |
1041 | { | 1034 | { |
diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c index f3927b6cda9d..f5361cd8ccce 100644 --- a/drivers/video/pmag-ba-fb.c +++ b/drivers/video/pmag-ba-fb.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/types.h> | 31 | #include <linux/types.h> |
32 | 32 | ||
33 | #include <asm/bug.h> | ||
34 | #include <asm/io.h> | 33 | #include <asm/io.h> |
35 | #include <asm/system.h> | 34 | #include <asm/system.h> |
36 | 35 | ||
diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c index 25148de5fe67..eeeac924b500 100644 --- a/drivers/video/pmagb-b-fb.c +++ b/drivers/video/pmagb-b-fb.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/types.h> | 28 | #include <linux/types.h> |
29 | 29 | ||
30 | #include <asm/bug.h> | ||
31 | #include <asm/io.h> | 30 | #include <asm/io.h> |
32 | #include <asm/system.h> | 31 | #include <asm/system.h> |
33 | 32 | ||