diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-20 14:16:20 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-20 14:16:20 -0400 |
commit | 4a52246302f01596f0edf7b4a3e6425e23479192 (patch) | |
tree | f384d86722d3ccfc875e3e5e8d8726e993a922ee /drivers | |
parent | 9f9d2760da8c7f94fae119fac3e13d5a1702f8f0 (diff) | |
parent | adc80ae60eae24a43a357bf5b30fb496f34aa605 (diff) |
Merge tag 'driver-core-3.3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core
Pull driver core patches for 3.4-rc1 from Greg KH:
"Here's the big driver core merge for 3.4-rc1.
Lots of various things here, sysfs fixes/tweaks (with the nlink
breakage reverted), dynamic debugging updates, w1 drivers, hyperv
driver updates, and a variety of other bits and pieces, full
information in the shortlog."
* tag 'driver-core-3.3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (78 commits)
Tools: hv: Support enumeration from all the pools
Tools: hv: Fully support the new KVP verbs in the user level daemon
Drivers: hv: Support the newly introduced KVP messages in the driver
Drivers: hv: Add new message types to enhance KVP
regulator: Support driver probe deferral
Revert "sysfs: Kill nlink counting."
uevent: send events in correct order according to seqnum (v3)
driver core: minor comment formatting cleanups
driver core: move the deferred probe pointer into the private area
drivercore: Add driver probe deferral mechanism
DS2781 Maxim Stand-Alone Fuel Gauge battery and w1 slave drivers
w1_bq27000: Only one thread can access the bq27000 at a time.
w1_bq27000 - remove w1_bq27000_write
w1_bq27000: remove unnecessary NULL test.
sysfs: Fix memory leak in sysfs_sd_setsecdata().
intel_idle: Revert change of auto_demotion_disable_flags for Nehalem
w1: Fix w1_bq27000
driver-core: documentation: fix up Greg's email address
powernow-k6: Really enable auto-loading
powernow-k7: Fix CPU family number
...
Diffstat (limited to 'drivers')
65 files changed, 2138 insertions, 679 deletions
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 8ae05ce18500..2801b418d7bb 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c | |||
@@ -474,6 +474,7 @@ static __ref int acpi_processor_start(struct acpi_processor *pr) | |||
474 | 474 | ||
475 | #ifdef CONFIG_CPU_FREQ | 475 | #ifdef CONFIG_CPU_FREQ |
476 | acpi_processor_ppc_has_changed(pr, 0); | 476 | acpi_processor_ppc_has_changed(pr, 0); |
477 | acpi_processor_load_module(pr); | ||
477 | #endif | 478 | #endif |
478 | acpi_processor_get_throttling_info(pr); | 479 | acpi_processor_get_throttling_info(pr); |
479 | acpi_processor_get_limit_info(pr); | 480 | acpi_processor_get_limit_info(pr); |
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 85b32376dad7..0af48a8554cd 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c | |||
@@ -240,6 +240,28 @@ void acpi_processor_ppc_exit(void) | |||
240 | acpi_processor_ppc_status &= ~PPC_REGISTERED; | 240 | acpi_processor_ppc_status &= ~PPC_REGISTERED; |
241 | } | 241 | } |
242 | 242 | ||
243 | /* | ||
244 | * Do a quick check if the systems looks like it should use ACPI | ||
245 | * cpufreq. We look at a _PCT method being available, but don't | ||
246 | * do a whole lot of sanity checks. | ||
247 | */ | ||
248 | void acpi_processor_load_module(struct acpi_processor *pr) | ||
249 | { | ||
250 | static int requested; | ||
251 | acpi_status status = 0; | ||
252 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
253 | |||
254 | if (!arch_has_acpi_pdc() || requested) | ||
255 | return; | ||
256 | status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer); | ||
257 | if (!ACPI_FAILURE(status)) { | ||
258 | printk(KERN_INFO PREFIX "Requesting acpi_cpufreq\n"); | ||
259 | request_module_nowait("acpi_cpufreq"); | ||
260 | requested = 1; | ||
261 | } | ||
262 | kfree(buffer.pointer); | ||
263 | } | ||
264 | |||
243 | static int acpi_processor_get_performance_control(struct acpi_processor *pr) | 265 | static int acpi_processor_get_performance_control(struct acpi_processor *pr) |
244 | { | 266 | { |
245 | int result = 0; | 267 | int result = 0; |
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index 7be9f79018e9..9aa618acfe97 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig | |||
@@ -176,6 +176,9 @@ config GENERIC_CPU_DEVICES | |||
176 | bool | 176 | bool |
177 | default n | 177 | default n |
178 | 178 | ||
179 | config SOC_BUS | ||
180 | bool | ||
181 | |||
179 | source "drivers/base/regmap/Kconfig" | 182 | source "drivers/base/regmap/Kconfig" |
180 | 183 | ||
181 | config DMA_SHARED_BUFFER | 184 | config DMA_SHARED_BUFFER |
diff --git a/drivers/base/Makefile b/drivers/base/Makefile index 610f9997a403..b6d1b9c4200c 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile | |||
@@ -19,6 +19,7 @@ obj-$(CONFIG_MODULES) += module.o | |||
19 | endif | 19 | endif |
20 | obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o | 20 | obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o |
21 | obj-$(CONFIG_REGMAP) += regmap/ | 21 | obj-$(CONFIG_REGMAP) += regmap/ |
22 | obj-$(CONFIG_SOC_BUS) += soc.o | ||
22 | 23 | ||
23 | ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG | 24 | ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG |
24 | 25 | ||
diff --git a/drivers/base/base.h b/drivers/base/base.h index b858dfd9a37c..6ee17bb391a9 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h | |||
@@ -59,6 +59,10 @@ struct driver_private { | |||
59 | * @knode_parent - node in sibling list | 59 | * @knode_parent - node in sibling list |
60 | * @knode_driver - node in driver list | 60 | * @knode_driver - node in driver list |
61 | * @knode_bus - node in bus list | 61 | * @knode_bus - node in bus list |
62 | * @deferred_probe - entry in deferred_probe_list which is used to retry the | ||
63 | * binding of drivers which were unable to get all the resources needed by | ||
64 | * the device; typically because it depends on another driver getting | ||
65 | * probed first. | ||
62 | * @driver_data - private pointer for driver specific info. Will turn into a | 66 | * @driver_data - private pointer for driver specific info. Will turn into a |
63 | * list soon. | 67 | * list soon. |
64 | * @device - pointer back to the struct class that this structure is | 68 | * @device - pointer back to the struct class that this structure is |
@@ -71,6 +75,7 @@ struct device_private { | |||
71 | struct klist_node knode_parent; | 75 | struct klist_node knode_parent; |
72 | struct klist_node knode_driver; | 76 | struct klist_node knode_driver; |
73 | struct klist_node knode_bus; | 77 | struct klist_node knode_bus; |
78 | struct list_head deferred_probe; | ||
74 | void *driver_data; | 79 | void *driver_data; |
75 | struct device *device; | 80 | struct device *device; |
76 | }; | 81 | }; |
@@ -105,6 +110,7 @@ extern void bus_remove_driver(struct device_driver *drv); | |||
105 | 110 | ||
106 | extern void driver_detach(struct device_driver *drv); | 111 | extern void driver_detach(struct device_driver *drv); |
107 | extern int driver_probe_device(struct device_driver *drv, struct device *dev); | 112 | extern int driver_probe_device(struct device_driver *drv, struct device *dev); |
113 | extern void driver_deferred_probe_del(struct device *dev); | ||
108 | static inline int driver_match_device(struct device_driver *drv, | 114 | static inline int driver_match_device(struct device_driver *drv, |
109 | struct device *dev) | 115 | struct device *dev) |
110 | { | 116 | { |
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 40fb12288ce2..26a06b801b5b 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
@@ -1194,13 +1194,15 @@ EXPORT_SYMBOL_GPL(subsys_interface_register); | |||
1194 | 1194 | ||
1195 | void subsys_interface_unregister(struct subsys_interface *sif) | 1195 | void subsys_interface_unregister(struct subsys_interface *sif) |
1196 | { | 1196 | { |
1197 | struct bus_type *subsys = sif->subsys; | 1197 | struct bus_type *subsys; |
1198 | struct subsys_dev_iter iter; | 1198 | struct subsys_dev_iter iter; |
1199 | struct device *dev; | 1199 | struct device *dev; |
1200 | 1200 | ||
1201 | if (!sif) | 1201 | if (!sif || !sif->subsys) |
1202 | return; | 1202 | return; |
1203 | 1203 | ||
1204 | subsys = sif->subsys; | ||
1205 | |||
1204 | mutex_lock(&subsys->p->mutex); | 1206 | mutex_lock(&subsys->p->mutex); |
1205 | list_del_init(&sif->node); | 1207 | list_del_init(&sif->node); |
1206 | if (sif->remove_dev) { | 1208 | if (sif->remove_dev) { |
diff --git a/drivers/base/core.c b/drivers/base/core.c index 74dda4f697f9..7050a75dde38 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -921,6 +921,7 @@ int device_private_init(struct device *dev) | |||
921 | dev->p->device = dev; | 921 | dev->p->device = dev; |
922 | klist_init(&dev->p->klist_children, klist_children_get, | 922 | klist_init(&dev->p->klist_children, klist_children_get, |
923 | klist_children_put); | 923 | klist_children_put); |
924 | INIT_LIST_HEAD(&dev->p->deferred_probe); | ||
924 | return 0; | 925 | return 0; |
925 | } | 926 | } |
926 | 927 | ||
@@ -1188,6 +1189,7 @@ void device_del(struct device *dev) | |||
1188 | device_remove_file(dev, &uevent_attr); | 1189 | device_remove_file(dev, &uevent_attr); |
1189 | device_remove_attrs(dev); | 1190 | device_remove_attrs(dev); |
1190 | bus_remove_device(dev); | 1191 | bus_remove_device(dev); |
1192 | driver_deferred_probe_del(dev); | ||
1191 | 1193 | ||
1192 | /* | 1194 | /* |
1193 | * Some platform devices are driven without driver attached | 1195 | * Some platform devices are driven without driver attached |
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 4dabf5077c48..adf937bf4091 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/device.h> | 11 | #include <linux/device.h> |
12 | #include <linux/node.h> | 12 | #include <linux/node.h> |
13 | #include <linux/gfp.h> | 13 | #include <linux/gfp.h> |
14 | #include <linux/slab.h> | ||
14 | #include <linux/percpu.h> | 15 | #include <linux/percpu.h> |
15 | 16 | ||
16 | #include "base.h" | 17 | #include "base.h" |
@@ -244,6 +245,9 @@ int __cpuinit register_cpu(struct cpu *cpu, int num) | |||
244 | cpu->dev.id = num; | 245 | cpu->dev.id = num; |
245 | cpu->dev.bus = &cpu_subsys; | 246 | cpu->dev.bus = &cpu_subsys; |
246 | cpu->dev.release = cpu_device_release; | 247 | cpu->dev.release = cpu_device_release; |
248 | #ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE | ||
249 | cpu->dev.bus->uevent = arch_cpu_uevent; | ||
250 | #endif | ||
247 | error = device_register(&cpu->dev); | 251 | error = device_register(&cpu->dev); |
248 | if (!error && cpu->hotpluggable) | 252 | if (!error && cpu->hotpluggable) |
249 | register_cpu_control(cpu); | 253 | register_cpu_control(cpu); |
@@ -268,6 +272,10 @@ struct device *get_cpu_device(unsigned cpu) | |||
268 | } | 272 | } |
269 | EXPORT_SYMBOL_GPL(get_cpu_device); | 273 | EXPORT_SYMBOL_GPL(get_cpu_device); |
270 | 274 | ||
275 | #ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE | ||
276 | static DEVICE_ATTR(modalias, 0444, arch_print_cpu_modalias, NULL); | ||
277 | #endif | ||
278 | |||
271 | static struct attribute *cpu_root_attrs[] = { | 279 | static struct attribute *cpu_root_attrs[] = { |
272 | #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE | 280 | #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE |
273 | &dev_attr_probe.attr, | 281 | &dev_attr_probe.attr, |
@@ -278,6 +286,9 @@ static struct attribute *cpu_root_attrs[] = { | |||
278 | &cpu_attrs[2].attr.attr, | 286 | &cpu_attrs[2].attr.attr, |
279 | &dev_attr_kernel_max.attr, | 287 | &dev_attr_kernel_max.attr, |
280 | &dev_attr_offline.attr, | 288 | &dev_attr_offline.attr, |
289 | #ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE | ||
290 | &dev_attr_modalias.attr, | ||
291 | #endif | ||
281 | NULL | 292 | NULL |
282 | }; | 293 | }; |
283 | 294 | ||
diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 142e3d600f14..1b1cbb571d38 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c | |||
@@ -28,6 +28,141 @@ | |||
28 | #include "base.h" | 28 | #include "base.h" |
29 | #include "power/power.h" | 29 | #include "power/power.h" |
30 | 30 | ||
31 | /* | ||
32 | * Deferred Probe infrastructure. | ||
33 | * | ||
34 | * Sometimes driver probe order matters, but the kernel doesn't always have | ||
35 | * dependency information which means some drivers will get probed before a | ||
36 | * resource it depends on is available. For example, an SDHCI driver may | ||
37 | * first need a GPIO line from an i2c GPIO controller before it can be | ||
38 | * initialized. If a required resource is not available yet, a driver can | ||
39 | * request probing to be deferred by returning -EPROBE_DEFER from its probe hook | ||
40 | * | ||
41 | * Deferred probe maintains two lists of devices, a pending list and an active | ||
42 | * list. A driver returning -EPROBE_DEFER causes the device to be added to the | ||
43 | * pending list. A successful driver probe will trigger moving all devices | ||
44 | * from the pending to the active list so that the workqueue will eventually | ||
45 | * retry them. | ||
46 | * | ||
47 | * The deferred_probe_mutex must be held any time the deferred_probe_*_list | ||
48 | * of the (struct device*)->p->deferred_probe pointers are manipulated | ||
49 | */ | ||
50 | static DEFINE_MUTEX(deferred_probe_mutex); | ||
51 | static LIST_HEAD(deferred_probe_pending_list); | ||
52 | static LIST_HEAD(deferred_probe_active_list); | ||
53 | static struct workqueue_struct *deferred_wq; | ||
54 | |||
55 | /** | ||
56 | * deferred_probe_work_func() - Retry probing devices in the active list. | ||
57 | */ | ||
58 | static void deferred_probe_work_func(struct work_struct *work) | ||
59 | { | ||
60 | struct device *dev; | ||
61 | struct device_private *private; | ||
62 | /* | ||
63 | * This block processes every device in the deferred 'active' list. | ||
64 | * Each device is removed from the active list and passed to | ||
65 | * bus_probe_device() to re-attempt the probe. The loop continues | ||
66 | * until every device in the active list is removed and retried. | ||
67 | * | ||
68 | * Note: Once the device is removed from the list and the mutex is | ||
69 | * released, it is possible for the device get freed by another thread | ||
70 | * and cause a illegal pointer dereference. This code uses | ||
71 | * get/put_device() to ensure the device structure cannot disappear | ||
72 | * from under our feet. | ||
73 | */ | ||
74 | mutex_lock(&deferred_probe_mutex); | ||
75 | while (!list_empty(&deferred_probe_active_list)) { | ||
76 | private = list_first_entry(&deferred_probe_active_list, | ||
77 | typeof(*dev->p), deferred_probe); | ||
78 | dev = private->device; | ||
79 | list_del_init(&private->deferred_probe); | ||
80 | |||
81 | get_device(dev); | ||
82 | |||
83 | /* | ||
84 | * Drop the mutex while probing each device; the probe path may | ||
85 | * manipulate the deferred list | ||
86 | */ | ||
87 | mutex_unlock(&deferred_probe_mutex); | ||
88 | dev_dbg(dev, "Retrying from deferred list\n"); | ||
89 | bus_probe_device(dev); | ||
90 | mutex_lock(&deferred_probe_mutex); | ||
91 | |||
92 | put_device(dev); | ||
93 | } | ||
94 | mutex_unlock(&deferred_probe_mutex); | ||
95 | } | ||
96 | static DECLARE_WORK(deferred_probe_work, deferred_probe_work_func); | ||
97 | |||
98 | static void driver_deferred_probe_add(struct device *dev) | ||
99 | { | ||
100 | mutex_lock(&deferred_probe_mutex); | ||
101 | if (list_empty(&dev->p->deferred_probe)) { | ||
102 | dev_dbg(dev, "Added to deferred list\n"); | ||
103 | list_add(&dev->p->deferred_probe, &deferred_probe_pending_list); | ||
104 | } | ||
105 | mutex_unlock(&deferred_probe_mutex); | ||
106 | } | ||
107 | |||
108 | void driver_deferred_probe_del(struct device *dev) | ||
109 | { | ||
110 | mutex_lock(&deferred_probe_mutex); | ||
111 | if (!list_empty(&dev->p->deferred_probe)) { | ||
112 | dev_dbg(dev, "Removed from deferred list\n"); | ||
113 | list_del_init(&dev->p->deferred_probe); | ||
114 | } | ||
115 | mutex_unlock(&deferred_probe_mutex); | ||
116 | } | ||
117 | |||
118 | static bool driver_deferred_probe_enable = false; | ||
119 | /** | ||
120 | * driver_deferred_probe_trigger() - Kick off re-probing deferred devices | ||
121 | * | ||
122 | * This functions moves all devices from the pending list to the active | ||
123 | * list and schedules the deferred probe workqueue to process them. It | ||
124 | * should be called anytime a driver is successfully bound to a device. | ||
125 | */ | ||
126 | static void driver_deferred_probe_trigger(void) | ||
127 | { | ||
128 | if (!driver_deferred_probe_enable) | ||
129 | return; | ||
130 | |||
131 | /* | ||
132 | * A successful probe means that all the devices in the pending list | ||
133 | * should be triggered to be reprobed. Move all the deferred devices | ||
134 | * into the active list so they can be retried by the workqueue | ||
135 | */ | ||
136 | mutex_lock(&deferred_probe_mutex); | ||
137 | list_splice_tail_init(&deferred_probe_pending_list, | ||
138 | &deferred_probe_active_list); | ||
139 | mutex_unlock(&deferred_probe_mutex); | ||
140 | |||
141 | /* | ||
142 | * Kick the re-probe thread. It may already be scheduled, but it is | ||
143 | * safe to kick it again. | ||
144 | */ | ||
145 | queue_work(deferred_wq, &deferred_probe_work); | ||
146 | } | ||
147 | |||
148 | /** | ||
149 | * deferred_probe_initcall() - Enable probing of deferred devices | ||
150 | * | ||
151 | * We don't want to get in the way when the bulk of drivers are getting probed. | ||
152 | * Instead, this initcall makes sure that deferred probing is delayed until | ||
153 | * late_initcall time. | ||
154 | */ | ||
155 | static int deferred_probe_initcall(void) | ||
156 | { | ||
157 | deferred_wq = create_singlethread_workqueue("deferwq"); | ||
158 | if (WARN_ON(!deferred_wq)) | ||
159 | return -ENOMEM; | ||
160 | |||
161 | driver_deferred_probe_enable = true; | ||
162 | driver_deferred_probe_trigger(); | ||
163 | return 0; | ||
164 | } | ||
165 | late_initcall(deferred_probe_initcall); | ||
31 | 166 | ||
32 | static void driver_bound(struct device *dev) | 167 | static void driver_bound(struct device *dev) |
33 | { | 168 | { |
@@ -42,6 +177,13 @@ static void driver_bound(struct device *dev) | |||
42 | 177 | ||
43 | klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices); | 178 | klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices); |
44 | 179 | ||
180 | /* | ||
181 | * Make sure the device is no longer in one of the deferred lists and | ||
182 | * kick off retrying all pending devices | ||
183 | */ | ||
184 | driver_deferred_probe_del(dev); | ||
185 | driver_deferred_probe_trigger(); | ||
186 | |||
45 | if (dev->bus) | 187 | if (dev->bus) |
46 | blocking_notifier_call_chain(&dev->bus->p->bus_notifier, | 188 | blocking_notifier_call_chain(&dev->bus->p->bus_notifier, |
47 | BUS_NOTIFY_BOUND_DRIVER, dev); | 189 | BUS_NOTIFY_BOUND_DRIVER, dev); |
@@ -142,7 +284,11 @@ probe_failed: | |||
142 | driver_sysfs_remove(dev); | 284 | driver_sysfs_remove(dev); |
143 | dev->driver = NULL; | 285 | dev->driver = NULL; |
144 | 286 | ||
145 | if (ret != -ENODEV && ret != -ENXIO) { | 287 | if (ret == -EPROBE_DEFER) { |
288 | /* Driver requested deferred probing */ | ||
289 | dev_info(dev, "Driver %s requests probe deferral\n", drv->name); | ||
290 | driver_deferred_probe_add(dev); | ||
291 | } else if (ret != -ENODEV && ret != -ENXIO) { | ||
146 | /* driver matched but the probe failed */ | 292 | /* driver matched but the probe failed */ |
147 | printk(KERN_WARNING | 293 | printk(KERN_WARNING |
148 | "%s: probe of %s failed with error %d\n", | 294 | "%s: probe of %s failed with error %d\n", |
diff --git a/drivers/base/driver.c b/drivers/base/driver.c index b631f7c59453..60e4f77ca662 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c | |||
@@ -153,34 +153,6 @@ int driver_add_kobj(struct device_driver *drv, struct kobject *kobj, | |||
153 | } | 153 | } |
154 | EXPORT_SYMBOL_GPL(driver_add_kobj); | 154 | EXPORT_SYMBOL_GPL(driver_add_kobj); |
155 | 155 | ||
156 | /** | ||
157 | * get_driver - increment driver reference count. | ||
158 | * @drv: driver. | ||
159 | */ | ||
160 | struct device_driver *get_driver(struct device_driver *drv) | ||
161 | { | ||
162 | if (drv) { | ||
163 | struct driver_private *priv; | ||
164 | struct kobject *kobj; | ||
165 | |||
166 | kobj = kobject_get(&drv->p->kobj); | ||
167 | priv = to_driver(kobj); | ||
168 | return priv->driver; | ||
169 | } | ||
170 | return NULL; | ||
171 | } | ||
172 | EXPORT_SYMBOL_GPL(get_driver); | ||
173 | |||
174 | /** | ||
175 | * put_driver - decrement driver's refcount. | ||
176 | * @drv: driver. | ||
177 | */ | ||
178 | void put_driver(struct device_driver *drv) | ||
179 | { | ||
180 | kobject_put(&drv->p->kobj); | ||
181 | } | ||
182 | EXPORT_SYMBOL_GPL(put_driver); | ||
183 | |||
184 | static int driver_add_groups(struct device_driver *drv, | 156 | static int driver_add_groups(struct device_driver *drv, |
185 | const struct attribute_group **groups) | 157 | const struct attribute_group **groups) |
186 | { | 158 | { |
@@ -234,7 +206,6 @@ int driver_register(struct device_driver *drv) | |||
234 | 206 | ||
235 | other = driver_find(drv->name, drv->bus); | 207 | other = driver_find(drv->name, drv->bus); |
236 | if (other) { | 208 | if (other) { |
237 | put_driver(other); | ||
238 | printk(KERN_ERR "Error: Driver '%s' is already registered, " | 209 | printk(KERN_ERR "Error: Driver '%s' is already registered, " |
239 | "aborting...\n", drv->name); | 210 | "aborting...\n", drv->name); |
240 | return -EBUSY; | 211 | return -EBUSY; |
@@ -275,7 +246,9 @@ EXPORT_SYMBOL_GPL(driver_unregister); | |||
275 | * Call kset_find_obj() to iterate over list of drivers on | 246 | * Call kset_find_obj() to iterate over list of drivers on |
276 | * a bus to find driver by name. Return driver if found. | 247 | * a bus to find driver by name. Return driver if found. |
277 | * | 248 | * |
278 | * Note that kset_find_obj increments driver's reference count. | 249 | * This routine provides no locking to prevent the driver it returns |
250 | * from being unregistered or unloaded while the caller is using it. | ||
251 | * The caller is responsible for preventing this. | ||
279 | */ | 252 | */ |
280 | struct device_driver *driver_find(const char *name, struct bus_type *bus) | 253 | struct device_driver *driver_find(const char *name, struct bus_type *bus) |
281 | { | 254 | { |
@@ -283,6 +256,8 @@ struct device_driver *driver_find(const char *name, struct bus_type *bus) | |||
283 | struct driver_private *priv; | 256 | struct driver_private *priv; |
284 | 257 | ||
285 | if (k) { | 258 | if (k) { |
259 | /* Drop reference added by kset_find_obj() */ | ||
260 | kobject_put(k); | ||
286 | priv = to_driver(k); | 261 | priv = to_driver(k); |
287 | return priv->driver; | 262 | return priv->driver; |
288 | } | 263 | } |
diff --git a/drivers/base/soc.c b/drivers/base/soc.c new file mode 100644 index 000000000000..05f150382da8 --- /dev/null +++ b/drivers/base/soc.c | |||
@@ -0,0 +1,183 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2011 | ||
3 | * | ||
4 | * Author: Lee Jones <lee.jones@linaro.org> for ST-Ericsson. | ||
5 | * License terms: GNU General Public License (GPL), version 2 | ||
6 | */ | ||
7 | |||
8 | #include <linux/sysfs.h> | ||
9 | #include <linux/module.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/stat.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/idr.h> | ||
14 | #include <linux/spinlock.h> | ||
15 | #include <linux/sys_soc.h> | ||
16 | #include <linux/err.h> | ||
17 | |||
18 | static DEFINE_IDR(soc_ida); | ||
19 | static DEFINE_SPINLOCK(soc_lock); | ||
20 | |||
21 | static ssize_t soc_info_get(struct device *dev, | ||
22 | struct device_attribute *attr, | ||
23 | char *buf); | ||
24 | |||
25 | struct soc_device { | ||
26 | struct device dev; | ||
27 | struct soc_device_attribute *attr; | ||
28 | int soc_dev_num; | ||
29 | }; | ||
30 | |||
31 | static struct bus_type soc_bus_type = { | ||
32 | .name = "soc", | ||
33 | }; | ||
34 | |||
35 | static DEVICE_ATTR(machine, S_IRUGO, soc_info_get, NULL); | ||
36 | static DEVICE_ATTR(family, S_IRUGO, soc_info_get, NULL); | ||
37 | static DEVICE_ATTR(soc_id, S_IRUGO, soc_info_get, NULL); | ||
38 | static DEVICE_ATTR(revision, S_IRUGO, soc_info_get, NULL); | ||
39 | |||
40 | struct device *soc_device_to_device(struct soc_device *soc_dev) | ||
41 | { | ||
42 | return &soc_dev->dev; | ||
43 | } | ||
44 | |||
45 | static mode_t soc_attribute_mode(struct kobject *kobj, | ||
46 | struct attribute *attr, | ||
47 | int index) | ||
48 | { | ||
49 | struct device *dev = container_of(kobj, struct device, kobj); | ||
50 | struct soc_device *soc_dev = container_of(dev, struct soc_device, dev); | ||
51 | |||
52 | if ((attr == &dev_attr_machine.attr) | ||
53 | && (soc_dev->attr->machine != NULL)) | ||
54 | return attr->mode; | ||
55 | if ((attr == &dev_attr_family.attr) | ||
56 | && (soc_dev->attr->family != NULL)) | ||
57 | return attr->mode; | ||
58 | if ((attr == &dev_attr_revision.attr) | ||
59 | && (soc_dev->attr->revision != NULL)) | ||
60 | return attr->mode; | ||
61 | if ((attr == &dev_attr_soc_id.attr) | ||
62 | && (soc_dev->attr->soc_id != NULL)) | ||
63 | return attr->mode; | ||
64 | |||
65 | /* Unknown or unfilled attribute. */ | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static ssize_t soc_info_get(struct device *dev, | ||
70 | struct device_attribute *attr, | ||
71 | char *buf) | ||
72 | { | ||
73 | struct soc_device *soc_dev = container_of(dev, struct soc_device, dev); | ||
74 | |||
75 | if (attr == &dev_attr_machine) | ||
76 | return sprintf(buf, "%s\n", soc_dev->attr->machine); | ||
77 | if (attr == &dev_attr_family) | ||
78 | return sprintf(buf, "%s\n", soc_dev->attr->family); | ||
79 | if (attr == &dev_attr_revision) | ||
80 | return sprintf(buf, "%s\n", soc_dev->attr->revision); | ||
81 | if (attr == &dev_attr_soc_id) | ||
82 | return sprintf(buf, "%s\n", soc_dev->attr->soc_id); | ||
83 | |||
84 | return -EINVAL; | ||
85 | |||
86 | } | ||
87 | |||
88 | static struct attribute *soc_attr[] = { | ||
89 | &dev_attr_machine.attr, | ||
90 | &dev_attr_family.attr, | ||
91 | &dev_attr_soc_id.attr, | ||
92 | &dev_attr_revision.attr, | ||
93 | NULL, | ||
94 | }; | ||
95 | |||
96 | static const struct attribute_group soc_attr_group = { | ||
97 | .attrs = soc_attr, | ||
98 | .is_visible = soc_attribute_mode, | ||
99 | }; | ||
100 | |||
101 | static const struct attribute_group *soc_attr_groups[] = { | ||
102 | &soc_attr_group, | ||
103 | NULL, | ||
104 | }; | ||
105 | |||
106 | static void soc_release(struct device *dev) | ||
107 | { | ||
108 | struct soc_device *soc_dev = container_of(dev, struct soc_device, dev); | ||
109 | |||
110 | kfree(soc_dev); | ||
111 | } | ||
112 | |||
113 | struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr) | ||
114 | { | ||
115 | struct soc_device *soc_dev; | ||
116 | int ret; | ||
117 | |||
118 | soc_dev = kzalloc(sizeof(*soc_dev), GFP_KERNEL); | ||
119 | if (!soc_dev) { | ||
120 | ret = -ENOMEM; | ||
121 | goto out1; | ||
122 | } | ||
123 | |||
124 | /* Fetch a unique (reclaimable) SOC ID. */ | ||
125 | do { | ||
126 | if (!ida_pre_get(&soc_ida, GFP_KERNEL)) { | ||
127 | ret = -ENOMEM; | ||
128 | goto out2; | ||
129 | } | ||
130 | |||
131 | spin_lock(&soc_lock); | ||
132 | ret = ida_get_new(&soc_ida, &soc_dev->soc_dev_num); | ||
133 | spin_unlock(&soc_lock); | ||
134 | |||
135 | } while (ret == -EAGAIN); | ||
136 | |||
137 | if (ret) | ||
138 | goto out2; | ||
139 | |||
140 | soc_dev->attr = soc_dev_attr; | ||
141 | soc_dev->dev.bus = &soc_bus_type; | ||
142 | soc_dev->dev.groups = soc_attr_groups; | ||
143 | soc_dev->dev.release = soc_release; | ||
144 | |||
145 | dev_set_name(&soc_dev->dev, "soc%d", soc_dev->soc_dev_num); | ||
146 | |||
147 | ret = device_register(&soc_dev->dev); | ||
148 | if (ret) | ||
149 | goto out3; | ||
150 | |||
151 | return soc_dev; | ||
152 | |||
153 | out3: | ||
154 | ida_remove(&soc_ida, soc_dev->soc_dev_num); | ||
155 | out2: | ||
156 | kfree(soc_dev); | ||
157 | out1: | ||
158 | return ERR_PTR(ret); | ||
159 | } | ||
160 | |||
161 | /* Ensure soc_dev->attr is freed prior to calling soc_device_unregister. */ | ||
162 | void soc_device_unregister(struct soc_device *soc_dev) | ||
163 | { | ||
164 | ida_remove(&soc_ida, soc_dev->soc_dev_num); | ||
165 | |||
166 | device_unregister(&soc_dev->dev); | ||
167 | } | ||
168 | |||
169 | static int __init soc_bus_register(void) | ||
170 | { | ||
171 | spin_lock_init(&soc_lock); | ||
172 | |||
173 | return bus_register(&soc_bus_type); | ||
174 | } | ||
175 | core_initcall(soc_bus_register); | ||
176 | |||
177 | static void __exit soc_bus_unregister(void) | ||
178 | { | ||
179 | ida_destroy(&soc_ida); | ||
180 | |||
181 | bus_unregister(&soc_bus_type); | ||
182 | } | ||
183 | module_exit(soc_bus_unregister); | ||
diff --git a/drivers/cpufreq/cpufreq-nforce2.c b/drivers/cpufreq/cpufreq-nforce2.c index 7bac808804f3..13d311ee08b3 100644 --- a/drivers/cpufreq/cpufreq-nforce2.c +++ b/drivers/cpufreq/cpufreq-nforce2.c | |||
@@ -385,6 +385,14 @@ static struct cpufreq_driver nforce2_driver = { | |||
385 | .owner = THIS_MODULE, | 385 | .owner = THIS_MODULE, |
386 | }; | 386 | }; |
387 | 387 | ||
388 | #ifdef MODULE | ||
389 | static DEFINE_PCI_DEVICE_TABLE(nforce2_ids) = { | ||
390 | { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2 }, | ||
391 | {} | ||
392 | }; | ||
393 | MODULE_DEVICE_TABLE(pci, nforce2_ids); | ||
394 | #endif | ||
395 | |||
388 | /** | 396 | /** |
389 | * nforce2_detect_chipset - detect the Southbridge which contains FSB PLL logic | 397 | * nforce2_detect_chipset - detect the Southbridge which contains FSB PLL logic |
390 | * | 398 | * |
diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c index 4bd6815d317b..3fffbe6025cd 100644 --- a/drivers/cpufreq/e_powersaver.c +++ b/drivers/cpufreq/e_powersaver.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | 18 | ||
19 | #include <asm/cpu_device_id.h> | ||
19 | #include <asm/msr.h> | 20 | #include <asm/msr.h> |
20 | #include <asm/tsc.h> | 21 | #include <asm/tsc.h> |
21 | 22 | ||
@@ -437,18 +438,19 @@ static struct cpufreq_driver eps_driver = { | |||
437 | .attr = eps_attr, | 438 | .attr = eps_attr, |
438 | }; | 439 | }; |
439 | 440 | ||
441 | |||
442 | /* This driver will work only on Centaur C7 processors with | ||
443 | * Enhanced SpeedStep/PowerSaver registers */ | ||
444 | static const struct x86_cpu_id eps_cpu_id[] = { | ||
445 | { X86_VENDOR_CENTAUR, 6, X86_MODEL_ANY, X86_FEATURE_EST }, | ||
446 | {} | ||
447 | }; | ||
448 | MODULE_DEVICE_TABLE(x86cpu, eps_cpu_id); | ||
449 | |||
440 | static int __init eps_init(void) | 450 | static int __init eps_init(void) |
441 | { | 451 | { |
442 | struct cpuinfo_x86 *c = &cpu_data(0); | 452 | if (!x86_match_cpu(eps_cpu_id) || boot_cpu_data.x86_model < 10) |
443 | |||
444 | /* This driver will work only on Centaur C7 processors with | ||
445 | * Enhanced SpeedStep/PowerSaver registers */ | ||
446 | if (c->x86_vendor != X86_VENDOR_CENTAUR | ||
447 | || c->x86 != 6 || c->x86_model < 10) | ||
448 | return -ENODEV; | ||
449 | if (!cpu_has(c, X86_FEATURE_EST)) | ||
450 | return -ENODEV; | 453 | return -ENODEV; |
451 | |||
452 | if (cpufreq_register_driver(&eps_driver)) | 454 | if (cpufreq_register_driver(&eps_driver)) |
453 | return -EINVAL; | 455 | return -EINVAL; |
454 | return 0; | 456 | return 0; |
diff --git a/drivers/cpufreq/elanfreq.c b/drivers/cpufreq/elanfreq.c index c587db472a75..960671fd3d7e 100644 --- a/drivers/cpufreq/elanfreq.c +++ b/drivers/cpufreq/elanfreq.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/cpufreq.h> | 24 | #include <linux/cpufreq.h> |
25 | 25 | ||
26 | #include <asm/cpu_device_id.h> | ||
26 | #include <asm/msr.h> | 27 | #include <asm/msr.h> |
27 | #include <linux/timex.h> | 28 | #include <linux/timex.h> |
28 | #include <linux/io.h> | 29 | #include <linux/io.h> |
@@ -277,17 +278,16 @@ static struct cpufreq_driver elanfreq_driver = { | |||
277 | .attr = elanfreq_attr, | 278 | .attr = elanfreq_attr, |
278 | }; | 279 | }; |
279 | 280 | ||
281 | static const struct x86_cpu_id elan_id[] = { | ||
282 | { X86_VENDOR_AMD, 4, 10, }, | ||
283 | {} | ||
284 | }; | ||
285 | MODULE_DEVICE_TABLE(x86cpu, elan_id); | ||
280 | 286 | ||
281 | static int __init elanfreq_init(void) | 287 | static int __init elanfreq_init(void) |
282 | { | 288 | { |
283 | struct cpuinfo_x86 *c = &cpu_data(0); | 289 | if (!x86_match_cpu(elan_id)) |
284 | |||
285 | /* Test if we have the right hardware */ | ||
286 | if ((c->x86_vendor != X86_VENDOR_AMD) || | ||
287 | (c->x86 != 4) || (c->x86_model != 10)) { | ||
288 | printk(KERN_INFO "elanfreq: error: no Elan processor found!\n"); | ||
289 | return -ENODEV; | 290 | return -ENODEV; |
290 | } | ||
291 | return cpufreq_register_driver(&elanfreq_driver); | 291 | return cpufreq_register_driver(&elanfreq_driver); |
292 | } | 292 | } |
293 | 293 | ||
diff --git a/drivers/cpufreq/gx-suspmod.c b/drivers/cpufreq/gx-suspmod.c index ffe1f2c92ed3..456bee058fe6 100644 --- a/drivers/cpufreq/gx-suspmod.c +++ b/drivers/cpufreq/gx-suspmod.c | |||
@@ -82,6 +82,7 @@ | |||
82 | #include <linux/errno.h> | 82 | #include <linux/errno.h> |
83 | #include <linux/slab.h> | 83 | #include <linux/slab.h> |
84 | 84 | ||
85 | #include <asm/cpu_device_id.h> | ||
85 | #include <asm/processor-cyrix.h> | 86 | #include <asm/processor-cyrix.h> |
86 | 87 | ||
87 | /* PCI config registers, all at F0 */ | 88 | /* PCI config registers, all at F0 */ |
@@ -171,6 +172,7 @@ static struct pci_device_id gx_chipset_tbl[] __initdata = { | |||
171 | { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5510), }, | 172 | { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5510), }, |
172 | { 0, }, | 173 | { 0, }, |
173 | }; | 174 | }; |
175 | MODULE_DEVICE_TABLE(pci, gx_chipset_tbl); | ||
174 | 176 | ||
175 | static void gx_write_byte(int reg, int value) | 177 | static void gx_write_byte(int reg, int value) |
176 | { | 178 | { |
@@ -185,13 +187,6 @@ static __init struct pci_dev *gx_detect_chipset(void) | |||
185 | { | 187 | { |
186 | struct pci_dev *gx_pci = NULL; | 188 | struct pci_dev *gx_pci = NULL; |
187 | 189 | ||
188 | /* check if CPU is a MediaGX or a Geode. */ | ||
189 | if ((boot_cpu_data.x86_vendor != X86_VENDOR_NSC) && | ||
190 | (boot_cpu_data.x86_vendor != X86_VENDOR_CYRIX)) { | ||
191 | pr_debug("error: no MediaGX/Geode processor found!\n"); | ||
192 | return NULL; | ||
193 | } | ||
194 | |||
195 | /* detect which companion chip is used */ | 190 | /* detect which companion chip is used */ |
196 | for_each_pci_dev(gx_pci) { | 191 | for_each_pci_dev(gx_pci) { |
197 | if ((pci_match_id(gx_chipset_tbl, gx_pci)) != NULL) | 192 | if ((pci_match_id(gx_chipset_tbl, gx_pci)) != NULL) |
diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c index f47d26e2a135..53ddbc760af7 100644 --- a/drivers/cpufreq/longhaul.c +++ b/drivers/cpufreq/longhaul.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/acpi.h> | 35 | #include <linux/acpi.h> |
36 | 36 | ||
37 | #include <asm/msr.h> | 37 | #include <asm/msr.h> |
38 | #include <asm/cpu_device_id.h> | ||
38 | #include <acpi/processor.h> | 39 | #include <acpi/processor.h> |
39 | 40 | ||
40 | #include "longhaul.h" | 41 | #include "longhaul.h" |
@@ -951,12 +952,17 @@ static struct cpufreq_driver longhaul_driver = { | |||
951 | .attr = longhaul_attr, | 952 | .attr = longhaul_attr, |
952 | }; | 953 | }; |
953 | 954 | ||
955 | static const struct x86_cpu_id longhaul_id[] = { | ||
956 | { X86_VENDOR_CENTAUR, 6 }, | ||
957 | {} | ||
958 | }; | ||
959 | MODULE_DEVICE_TABLE(x86cpu, longhaul_id); | ||
954 | 960 | ||
955 | static int __init longhaul_init(void) | 961 | static int __init longhaul_init(void) |
956 | { | 962 | { |
957 | struct cpuinfo_x86 *c = &cpu_data(0); | 963 | struct cpuinfo_x86 *c = &cpu_data(0); |
958 | 964 | ||
959 | if (c->x86_vendor != X86_VENDOR_CENTAUR || c->x86 != 6) | 965 | if (!x86_match_cpu(longhaul_id)) |
960 | return -ENODEV; | 966 | return -ENODEV; |
961 | 967 | ||
962 | #ifdef CONFIG_SMP | 968 | #ifdef CONFIG_SMP |
diff --git a/drivers/cpufreq/longrun.c b/drivers/cpufreq/longrun.c index 34ea359b370e..8bc9f5fbbaeb 100644 --- a/drivers/cpufreq/longrun.c +++ b/drivers/cpufreq/longrun.c | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #include <asm/msr.h> | 15 | #include <asm/msr.h> |
16 | #include <asm/processor.h> | 16 | #include <asm/processor.h> |
17 | #include <asm/cpu_device_id.h> | ||
17 | 18 | ||
18 | static struct cpufreq_driver longrun_driver; | 19 | static struct cpufreq_driver longrun_driver; |
19 | 20 | ||
@@ -288,6 +289,12 @@ static struct cpufreq_driver longrun_driver = { | |||
288 | .owner = THIS_MODULE, | 289 | .owner = THIS_MODULE, |
289 | }; | 290 | }; |
290 | 291 | ||
292 | static const struct x86_cpu_id longrun_ids[] = { | ||
293 | { X86_VENDOR_TRANSMETA, X86_FAMILY_ANY, X86_MODEL_ANY, | ||
294 | X86_FEATURE_LONGRUN }, | ||
295 | {} | ||
296 | }; | ||
297 | MODULE_DEVICE_TABLE(x86cpu, longrun_ids); | ||
291 | 298 | ||
292 | /** | 299 | /** |
293 | * longrun_init - initializes the Transmeta Crusoe LongRun CPUFreq driver | 300 | * longrun_init - initializes the Transmeta Crusoe LongRun CPUFreq driver |
@@ -296,12 +303,8 @@ static struct cpufreq_driver longrun_driver = { | |||
296 | */ | 303 | */ |
297 | static int __init longrun_init(void) | 304 | static int __init longrun_init(void) |
298 | { | 305 | { |
299 | struct cpuinfo_x86 *c = &cpu_data(0); | 306 | if (!x86_match_cpu(longrun_ids)) |
300 | |||
301 | if (c->x86_vendor != X86_VENDOR_TRANSMETA || | ||
302 | !cpu_has(c, X86_FEATURE_LONGRUN)) | ||
303 | return -ENODEV; | 307 | return -ENODEV; |
304 | |||
305 | return cpufreq_register_driver(&longrun_driver); | 308 | return cpufreq_register_driver(&longrun_driver); |
306 | } | 309 | } |
307 | 310 | ||
diff --git a/drivers/cpufreq/p4-clockmod.c b/drivers/cpufreq/p4-clockmod.c index 6be3e0760c26..827629c9aad7 100644 --- a/drivers/cpufreq/p4-clockmod.c +++ b/drivers/cpufreq/p4-clockmod.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <asm/processor.h> | 31 | #include <asm/processor.h> |
32 | #include <asm/msr.h> | 32 | #include <asm/msr.h> |
33 | #include <asm/timer.h> | 33 | #include <asm/timer.h> |
34 | #include <asm/cpu_device_id.h> | ||
34 | 35 | ||
35 | #include "speedstep-lib.h" | 36 | #include "speedstep-lib.h" |
36 | 37 | ||
@@ -289,21 +290,25 @@ static struct cpufreq_driver p4clockmod_driver = { | |||
289 | .attr = p4clockmod_attr, | 290 | .attr = p4clockmod_attr, |
290 | }; | 291 | }; |
291 | 292 | ||
293 | static const struct x86_cpu_id cpufreq_p4_id[] = { | ||
294 | { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_ACC }, | ||
295 | {} | ||
296 | }; | ||
297 | |||
298 | /* | ||
299 | * Intentionally no MODULE_DEVICE_TABLE here: this driver should not | ||
300 | * be auto loaded. Please don't add one. | ||
301 | */ | ||
292 | 302 | ||
293 | static int __init cpufreq_p4_init(void) | 303 | static int __init cpufreq_p4_init(void) |
294 | { | 304 | { |
295 | struct cpuinfo_x86 *c = &cpu_data(0); | ||
296 | int ret; | 305 | int ret; |
297 | 306 | ||
298 | /* | 307 | /* |
299 | * THERM_CONTROL is architectural for IA32 now, so | 308 | * THERM_CONTROL is architectural for IA32 now, so |
300 | * we can rely on the capability checks | 309 | * we can rely on the capability checks |
301 | */ | 310 | */ |
302 | if (c->x86_vendor != X86_VENDOR_INTEL) | 311 | if (!x86_match_cpu(cpufreq_p4_id) || !boot_cpu_has(X86_FEATURE_ACPI)) |
303 | return -ENODEV; | ||
304 | |||
305 | if (!test_cpu_cap(c, X86_FEATURE_ACPI) || | ||
306 | !test_cpu_cap(c, X86_FEATURE_ACC)) | ||
307 | return -ENODEV; | 312 | return -ENODEV; |
308 | 313 | ||
309 | ret = cpufreq_register_driver(&p4clockmod_driver); | 314 | ret = cpufreq_register_driver(&p4clockmod_driver); |
diff --git a/drivers/cpufreq/powernow-k6.c b/drivers/cpufreq/powernow-k6.c index b3379d6a5c57..af23e0b9ec92 100644 --- a/drivers/cpufreq/powernow-k6.c +++ b/drivers/cpufreq/powernow-k6.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/timex.h> | 16 | #include <linux/timex.h> |
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | 18 | ||
19 | #include <asm/cpu_device_id.h> | ||
19 | #include <asm/msr.h> | 20 | #include <asm/msr.h> |
20 | 21 | ||
21 | #define POWERNOW_IOPORT 0xfff0 /* it doesn't matter where, as long | 22 | #define POWERNOW_IOPORT 0xfff0 /* it doesn't matter where, as long |
@@ -210,6 +211,12 @@ static struct cpufreq_driver powernow_k6_driver = { | |||
210 | .attr = powernow_k6_attr, | 211 | .attr = powernow_k6_attr, |
211 | }; | 212 | }; |
212 | 213 | ||
214 | static const struct x86_cpu_id powernow_k6_ids[] = { | ||
215 | { X86_VENDOR_AMD, 5, 12 }, | ||
216 | { X86_VENDOR_AMD, 5, 13 }, | ||
217 | {} | ||
218 | }; | ||
219 | MODULE_DEVICE_TABLE(x86cpu, powernow_k6_ids); | ||
213 | 220 | ||
214 | /** | 221 | /** |
215 | * powernow_k6_init - initializes the k6 PowerNow! CPUFreq driver | 222 | * powernow_k6_init - initializes the k6 PowerNow! CPUFreq driver |
@@ -220,10 +227,7 @@ static struct cpufreq_driver powernow_k6_driver = { | |||
220 | */ | 227 | */ |
221 | static int __init powernow_k6_init(void) | 228 | static int __init powernow_k6_init(void) |
222 | { | 229 | { |
223 | struct cpuinfo_x86 *c = &cpu_data(0); | 230 | if (!x86_match_cpu(powernow_k6_ids)) |
224 | |||
225 | if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 5) || | ||
226 | ((c->x86_model != 12) && (c->x86_model != 13))) | ||
227 | return -ENODEV; | 231 | return -ENODEV; |
228 | 232 | ||
229 | if (!request_region(POWERNOW_IOPORT, 16, "PowerNow!")) { | 233 | if (!request_region(POWERNOW_IOPORT, 16, "PowerNow!")) { |
diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c index d71d9f372359..cf7e1ee005a2 100644 --- a/drivers/cpufreq/powernow-k7.c +++ b/drivers/cpufreq/powernow-k7.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <asm/timer.h> /* Needed for recalibrate_cpu_khz() */ | 28 | #include <asm/timer.h> /* Needed for recalibrate_cpu_khz() */ |
29 | #include <asm/msr.h> | 29 | #include <asm/msr.h> |
30 | #include <asm/system.h> | 30 | #include <asm/system.h> |
31 | #include <asm/cpu_device_id.h> | ||
31 | 32 | ||
32 | #ifdef CONFIG_X86_POWERNOW_K7_ACPI | 33 | #ifdef CONFIG_X86_POWERNOW_K7_ACPI |
33 | #include <linux/acpi.h> | 34 | #include <linux/acpi.h> |
@@ -110,18 +111,19 @@ static int check_fsb(unsigned int fsbspeed) | |||
110 | return delta < 5; | 111 | return delta < 5; |
111 | } | 112 | } |
112 | 113 | ||
114 | static const struct x86_cpu_id powernow_k7_cpuids[] = { | ||
115 | { X86_VENDOR_AMD, 6, }, | ||
116 | {} | ||
117 | }; | ||
118 | MODULE_DEVICE_TABLE(x86cpu, powernow_k7_cpuids); | ||
119 | |||
113 | static int check_powernow(void) | 120 | static int check_powernow(void) |
114 | { | 121 | { |
115 | struct cpuinfo_x86 *c = &cpu_data(0); | 122 | struct cpuinfo_x86 *c = &cpu_data(0); |
116 | unsigned int maxei, eax, ebx, ecx, edx; | 123 | unsigned int maxei, eax, ebx, ecx, edx; |
117 | 124 | ||
118 | if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 6)) { | 125 | if (!x86_match_cpu(powernow_k7_cpuids)) |
119 | #ifdef MODULE | ||
120 | printk(KERN_INFO PFX "This module only works with " | ||
121 | "AMD K7 CPUs\n"); | ||
122 | #endif | ||
123 | return 0; | 126 | return 0; |
124 | } | ||
125 | 127 | ||
126 | /* Get maximum capabilities */ | 128 | /* Get maximum capabilities */ |
127 | maxei = cpuid_eax(0x80000000); | 129 | maxei = cpuid_eax(0x80000000); |
diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index 8f9b2ceeec85..c0e816468e30 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/delay.h> | 40 | #include <linux/delay.h> |
41 | 41 | ||
42 | #include <asm/msr.h> | 42 | #include <asm/msr.h> |
43 | #include <asm/cpu_device_id.h> | ||
43 | 44 | ||
44 | #include <linux/acpi.h> | 45 | #include <linux/acpi.h> |
45 | #include <linux/mutex.h> | 46 | #include <linux/mutex.h> |
@@ -520,6 +521,15 @@ static int core_voltage_post_transition(struct powernow_k8_data *data, | |||
520 | return 0; | 521 | return 0; |
521 | } | 522 | } |
522 | 523 | ||
524 | static const struct x86_cpu_id powernow_k8_ids[] = { | ||
525 | /* IO based frequency switching */ | ||
526 | { X86_VENDOR_AMD, 0xf }, | ||
527 | /* MSR based frequency switching supported */ | ||
528 | X86_FEATURE_MATCH(X86_FEATURE_HW_PSTATE), | ||
529 | {} | ||
530 | }; | ||
531 | MODULE_DEVICE_TABLE(x86cpu, powernow_k8_ids); | ||
532 | |||
523 | static void check_supported_cpu(void *_rc) | 533 | static void check_supported_cpu(void *_rc) |
524 | { | 534 | { |
525 | u32 eax, ebx, ecx, edx; | 535 | u32 eax, ebx, ecx, edx; |
@@ -527,13 +537,7 @@ static void check_supported_cpu(void *_rc) | |||
527 | 537 | ||
528 | *rc = -ENODEV; | 538 | *rc = -ENODEV; |
529 | 539 | ||
530 | if (__this_cpu_read(cpu_info.x86_vendor) != X86_VENDOR_AMD) | ||
531 | return; | ||
532 | |||
533 | eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE); | 540 | eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE); |
534 | if (((eax & CPUID_XFAM) != CPUID_XFAM_K8) && | ||
535 | ((eax & CPUID_XFAM) < CPUID_XFAM_10H)) | ||
536 | return; | ||
537 | 541 | ||
538 | if ((eax & CPUID_XFAM) == CPUID_XFAM_K8) { | 542 | if ((eax & CPUID_XFAM) == CPUID_XFAM_K8) { |
539 | if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) || | 543 | if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) || |
@@ -1553,6 +1557,9 @@ static int __cpuinit powernowk8_init(void) | |||
1553 | unsigned int i, supported_cpus = 0, cpu; | 1557 | unsigned int i, supported_cpus = 0, cpu; |
1554 | int rv; | 1558 | int rv; |
1555 | 1559 | ||
1560 | if (!x86_match_cpu(powernow_k8_ids)) | ||
1561 | return -ENODEV; | ||
1562 | |||
1556 | for_each_online_cpu(i) { | 1563 | for_each_online_cpu(i) { |
1557 | int rc; | 1564 | int rc; |
1558 | smp_call_function_single(i, check_supported_cpu, &rc, 1); | 1565 | smp_call_function_single(i, check_supported_cpu, &rc, 1); |
diff --git a/drivers/cpufreq/sc520_freq.c b/drivers/cpufreq/sc520_freq.c index 1e205e6b1727..e42e073cd9b8 100644 --- a/drivers/cpufreq/sc520_freq.c +++ b/drivers/cpufreq/sc520_freq.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/timex.h> | 22 | #include <linux/timex.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | 24 | ||
25 | #include <asm/cpu_device_id.h> | ||
25 | #include <asm/msr.h> | 26 | #include <asm/msr.h> |
26 | 27 | ||
27 | #define MMCR_BASE 0xfffef000 /* The default base address */ | 28 | #define MMCR_BASE 0xfffef000 /* The default base address */ |
@@ -150,18 +151,19 @@ static struct cpufreq_driver sc520_freq_driver = { | |||
150 | .attr = sc520_freq_attr, | 151 | .attr = sc520_freq_attr, |
151 | }; | 152 | }; |
152 | 153 | ||
154 | static const struct x86_cpu_id sc520_ids[] = { | ||
155 | { X86_VENDOR_AMD, 4, 9 }, | ||
156 | {} | ||
157 | }; | ||
158 | MODULE_DEVICE_TABLE(x86cpu, sc520_ids); | ||
153 | 159 | ||
154 | static int __init sc520_freq_init(void) | 160 | static int __init sc520_freq_init(void) |
155 | { | 161 | { |
156 | struct cpuinfo_x86 *c = &cpu_data(0); | ||
157 | int err; | 162 | int err; |
158 | 163 | ||
159 | /* Test if we have the right hardware */ | 164 | if (!x86_match_cpu(sc520_ids)) |
160 | if (c->x86_vendor != X86_VENDOR_AMD || | ||
161 | c->x86 != 4 || c->x86_model != 9) { | ||
162 | pr_debug("no Elan SC520 processor found!\n"); | ||
163 | return -ENODEV; | 165 | return -ENODEV; |
164 | } | 166 | |
165 | cpuctl = ioremap((unsigned long)(MMCR_BASE + OFFS_CPUCTL), 1); | 167 | cpuctl = ioremap((unsigned long)(MMCR_BASE + OFFS_CPUCTL), 1); |
166 | if (!cpuctl) { | 168 | if (!cpuctl) { |
167 | printk(KERN_ERR "sc520_freq: error: failed to remap memory\n"); | 169 | printk(KERN_ERR "sc520_freq: error: failed to remap memory\n"); |
diff --git a/drivers/cpufreq/speedstep-centrino.c b/drivers/cpufreq/speedstep-centrino.c index 6ea3455def21..3a953d519f46 100644 --- a/drivers/cpufreq/speedstep-centrino.c +++ b/drivers/cpufreq/speedstep-centrino.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <asm/msr.h> | 25 | #include <asm/msr.h> |
26 | #include <asm/processor.h> | 26 | #include <asm/processor.h> |
27 | #include <asm/cpufeature.h> | 27 | #include <asm/cpufeature.h> |
28 | #include <asm/cpu_device_id.h> | ||
28 | 29 | ||
29 | #define PFX "speedstep-centrino: " | 30 | #define PFX "speedstep-centrino: " |
30 | #define MAINTAINER "cpufreq@vger.kernel.org" | 31 | #define MAINTAINER "cpufreq@vger.kernel.org" |
@@ -595,6 +596,24 @@ static struct cpufreq_driver centrino_driver = { | |||
595 | .owner = THIS_MODULE, | 596 | .owner = THIS_MODULE, |
596 | }; | 597 | }; |
597 | 598 | ||
599 | /* | ||
600 | * This doesn't replace the detailed checks above because | ||
601 | * the generic CPU IDs don't have a way to match for steppings | ||
602 | * or ASCII model IDs. | ||
603 | */ | ||
604 | static const struct x86_cpu_id centrino_ids[] = { | ||
605 | { X86_VENDOR_INTEL, 6, 9, X86_FEATURE_EST }, | ||
606 | { X86_VENDOR_INTEL, 6, 13, X86_FEATURE_EST }, | ||
607 | { X86_VENDOR_INTEL, 6, 13, X86_FEATURE_EST }, | ||
608 | { X86_VENDOR_INTEL, 6, 13, X86_FEATURE_EST }, | ||
609 | { X86_VENDOR_INTEL, 15, 3, X86_FEATURE_EST }, | ||
610 | { X86_VENDOR_INTEL, 15, 4, X86_FEATURE_EST }, | ||
611 | {} | ||
612 | }; | ||
613 | #if 0 | ||
614 | /* Autoload or not? Do not for now. */ | ||
615 | MODULE_DEVICE_TABLE(x86cpu, centrino_ids); | ||
616 | #endif | ||
598 | 617 | ||
599 | /** | 618 | /** |
600 | * centrino_init - initializes the Enhanced SpeedStep CPUFreq driver | 619 | * centrino_init - initializes the Enhanced SpeedStep CPUFreq driver |
@@ -612,11 +631,8 @@ static struct cpufreq_driver centrino_driver = { | |||
612 | */ | 631 | */ |
613 | static int __init centrino_init(void) | 632 | static int __init centrino_init(void) |
614 | { | 633 | { |
615 | struct cpuinfo_x86 *cpu = &cpu_data(0); | 634 | if (!x86_match_cpu(centrino_ids)) |
616 | |||
617 | if (!cpu_has(cpu, X86_FEATURE_EST)) | ||
618 | return -ENODEV; | 635 | return -ENODEV; |
619 | |||
620 | return cpufreq_register_driver(¢rino_driver); | 636 | return cpufreq_register_driver(¢rino_driver); |
621 | } | 637 | } |
622 | 638 | ||
diff --git a/drivers/cpufreq/speedstep-ich.c b/drivers/cpufreq/speedstep-ich.c index a748ce782fee..7432b3a72cd4 100644 --- a/drivers/cpufreq/speedstep-ich.c +++ b/drivers/cpufreq/speedstep-ich.c | |||
@@ -25,6 +25,8 @@ | |||
25 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
26 | #include <linux/sched.h> | 26 | #include <linux/sched.h> |
27 | 27 | ||
28 | #include <asm/cpu_device_id.h> | ||
29 | |||
28 | #include "speedstep-lib.h" | 30 | #include "speedstep-lib.h" |
29 | 31 | ||
30 | 32 | ||
@@ -388,6 +390,16 @@ static struct cpufreq_driver speedstep_driver = { | |||
388 | .attr = speedstep_attr, | 390 | .attr = speedstep_attr, |
389 | }; | 391 | }; |
390 | 392 | ||
393 | static const struct x86_cpu_id ss_smi_ids[] = { | ||
394 | { X86_VENDOR_INTEL, 6, 0xb, }, | ||
395 | { X86_VENDOR_INTEL, 6, 0x8, }, | ||
396 | { X86_VENDOR_INTEL, 15, 2 }, | ||
397 | {} | ||
398 | }; | ||
399 | #if 0 | ||
400 | /* Autoload or not? Do not for now. */ | ||
401 | MODULE_DEVICE_TABLE(x86cpu, ss_smi_ids); | ||
402 | #endif | ||
391 | 403 | ||
392 | /** | 404 | /** |
393 | * speedstep_init - initializes the SpeedStep CPUFreq driver | 405 | * speedstep_init - initializes the SpeedStep CPUFreq driver |
@@ -398,6 +410,9 @@ static struct cpufreq_driver speedstep_driver = { | |||
398 | */ | 410 | */ |
399 | static int __init speedstep_init(void) | 411 | static int __init speedstep_init(void) |
400 | { | 412 | { |
413 | if (!x86_match_cpu(ss_smi_ids)) | ||
414 | return -ENODEV; | ||
415 | |||
401 | /* detect processor */ | 416 | /* detect processor */ |
402 | speedstep_processor = speedstep_detect_processor(); | 417 | speedstep_processor = speedstep_detect_processor(); |
403 | if (!speedstep_processor) { | 418 | if (!speedstep_processor) { |
diff --git a/drivers/cpufreq/speedstep-lib.c b/drivers/cpufreq/speedstep-lib.c index 8af2d2fd9d51..7047821a7f8a 100644 --- a/drivers/cpufreq/speedstep-lib.c +++ b/drivers/cpufreq/speedstep-lib.c | |||
@@ -249,6 +249,7 @@ EXPORT_SYMBOL_GPL(speedstep_get_frequency); | |||
249 | * DETECT SPEEDSTEP-CAPABLE PROCESSOR * | 249 | * DETECT SPEEDSTEP-CAPABLE PROCESSOR * |
250 | *********************************************************************/ | 250 | *********************************************************************/ |
251 | 251 | ||
252 | /* Keep in sync with the x86_cpu_id tables in the different modules */ | ||
252 | unsigned int speedstep_detect_processor(void) | 253 | unsigned int speedstep_detect_processor(void) |
253 | { | 254 | { |
254 | struct cpuinfo_x86 *c = &cpu_data(0); | 255 | struct cpuinfo_x86 *c = &cpu_data(0); |
diff --git a/drivers/cpufreq/speedstep-smi.c b/drivers/cpufreq/speedstep-smi.c index c76ead3490bf..6a457fcaaad5 100644 --- a/drivers/cpufreq/speedstep-smi.c +++ b/drivers/cpufreq/speedstep-smi.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
22 | #include <asm/ist.h> | 22 | #include <asm/ist.h> |
23 | #include <asm/cpu_device_id.h> | ||
23 | 24 | ||
24 | #include "speedstep-lib.h" | 25 | #include "speedstep-lib.h" |
25 | 26 | ||
@@ -379,6 +380,17 @@ static struct cpufreq_driver speedstep_driver = { | |||
379 | .attr = speedstep_attr, | 380 | .attr = speedstep_attr, |
380 | }; | 381 | }; |
381 | 382 | ||
383 | static const struct x86_cpu_id ss_smi_ids[] = { | ||
384 | { X86_VENDOR_INTEL, 6, 0xb, }, | ||
385 | { X86_VENDOR_INTEL, 6, 0x8, }, | ||
386 | { X86_VENDOR_INTEL, 15, 2 }, | ||
387 | {} | ||
388 | }; | ||
389 | #if 0 | ||
390 | /* Not auto loaded currently */ | ||
391 | MODULE_DEVICE_TABLE(x86cpu, ss_smi_ids); | ||
392 | #endif | ||
393 | |||
382 | /** | 394 | /** |
383 | * speedstep_init - initializes the SpeedStep CPUFreq driver | 395 | * speedstep_init - initializes the SpeedStep CPUFreq driver |
384 | * | 396 | * |
@@ -388,6 +400,9 @@ static struct cpufreq_driver speedstep_driver = { | |||
388 | */ | 400 | */ |
389 | static int __init speedstep_init(void) | 401 | static int __init speedstep_init(void) |
390 | { | 402 | { |
403 | if (!x86_match_cpu(ss_smi_ids)) | ||
404 | return -ENODEV; | ||
405 | |||
391 | speedstep_processor = speedstep_detect_processor(); | 406 | speedstep_processor = speedstep_detect_processor(); |
392 | 407 | ||
393 | switch (speedstep_processor) { | 408 | switch (speedstep_processor) { |
diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c index 29b9469f8378..37b2e9406af6 100644 --- a/drivers/crypto/padlock-aes.c +++ b/drivers/crypto/padlock-aes.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/percpu.h> | 19 | #include <linux/percpu.h> |
20 | #include <linux/smp.h> | 20 | #include <linux/smp.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <asm/cpu_device_id.h> | ||
22 | #include <asm/byteorder.h> | 23 | #include <asm/byteorder.h> |
23 | #include <asm/processor.h> | 24 | #include <asm/processor.h> |
24 | #include <asm/i387.h> | 25 | #include <asm/i387.h> |
@@ -503,12 +504,18 @@ static struct crypto_alg cbc_aes_alg = { | |||
503 | } | 504 | } |
504 | }; | 505 | }; |
505 | 506 | ||
507 | static struct x86_cpu_id padlock_cpu_id[] = { | ||
508 | X86_FEATURE_MATCH(X86_FEATURE_XCRYPT), | ||
509 | {} | ||
510 | }; | ||
511 | MODULE_DEVICE_TABLE(x86cpu, padlock_cpu_id); | ||
512 | |||
506 | static int __init padlock_init(void) | 513 | static int __init padlock_init(void) |
507 | { | 514 | { |
508 | int ret; | 515 | int ret; |
509 | struct cpuinfo_x86 *c = &cpu_data(0); | 516 | struct cpuinfo_x86 *c = &cpu_data(0); |
510 | 517 | ||
511 | if (!cpu_has_xcrypt) | 518 | if (!x86_match_cpu(padlock_cpu_id)) |
512 | return -ENODEV; | 519 | return -ENODEV; |
513 | 520 | ||
514 | if (!cpu_has_xcrypt_enabled) { | 521 | if (!cpu_has_xcrypt_enabled) { |
diff --git a/drivers/crypto/padlock-sha.c b/drivers/crypto/padlock-sha.c index 06bdb4b2c6a6..9266c0e25492 100644 --- a/drivers/crypto/padlock-sha.c +++ b/drivers/crypto/padlock-sha.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | #include <linux/scatterlist.h> | 24 | #include <linux/scatterlist.h> |
25 | #include <asm/cpu_device_id.h> | ||
25 | #include <asm/i387.h> | 26 | #include <asm/i387.h> |
26 | 27 | ||
27 | struct padlock_sha_desc { | 28 | struct padlock_sha_desc { |
@@ -526,6 +527,12 @@ static struct shash_alg sha256_alg_nano = { | |||
526 | } | 527 | } |
527 | }; | 528 | }; |
528 | 529 | ||
530 | static struct x86_cpu_id padlock_sha_ids[] = { | ||
531 | X86_FEATURE_MATCH(X86_FEATURE_PHE), | ||
532 | {} | ||
533 | }; | ||
534 | MODULE_DEVICE_TABLE(x86cpu, padlock_sha_ids); | ||
535 | |||
529 | static int __init padlock_init(void) | 536 | static int __init padlock_init(void) |
530 | { | 537 | { |
531 | int rc = -ENODEV; | 538 | int rc = -ENODEV; |
@@ -533,15 +540,8 @@ static int __init padlock_init(void) | |||
533 | struct shash_alg *sha1; | 540 | struct shash_alg *sha1; |
534 | struct shash_alg *sha256; | 541 | struct shash_alg *sha256; |
535 | 542 | ||
536 | if (!cpu_has_phe) { | 543 | if (!x86_match_cpu(padlock_sha_ids) || !cpu_has_phe_enabled) |
537 | printk(KERN_NOTICE PFX "VIA PadLock Hash Engine not detected.\n"); | ||
538 | return -ENODEV; | ||
539 | } | ||
540 | |||
541 | if (!cpu_has_phe_enabled) { | ||
542 | printk(KERN_NOTICE PFX "VIA PadLock detected, but not enabled. Hmm, strange...\n"); | ||
543 | return -ENODEV; | 544 | return -ENODEV; |
544 | } | ||
545 | 545 | ||
546 | /* Register the newly added algorithm module if on * | 546 | /* Register the newly added algorithm module if on * |
547 | * VIA Nano processor, or else just do as before */ | 547 | * VIA Nano processor, or else just do as before */ |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index af08ce7207d9..bce53fa0e166 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -1619,11 +1619,7 @@ static ssize_t store_new_id(struct device_driver *drv, const char *buf, | |||
1619 | list_add_tail(&dynid->list, &hdrv->dyn_list); | 1619 | list_add_tail(&dynid->list, &hdrv->dyn_list); |
1620 | spin_unlock(&hdrv->dyn_lock); | 1620 | spin_unlock(&hdrv->dyn_lock); |
1621 | 1621 | ||
1622 | ret = 0; | 1622 | ret = driver_attach(&hdrv->driver); |
1623 | if (get_driver(&hdrv->driver)) { | ||
1624 | ret = driver_attach(&hdrv->driver); | ||
1625 | put_driver(&hdrv->driver); | ||
1626 | } | ||
1627 | 1623 | ||
1628 | return ret ? : count; | 1624 | return ret ? : count; |
1629 | } | 1625 | } |
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 36484db36baf..9ffbfc575a0c 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c | |||
@@ -37,81 +37,6 @@ struct vmbus_channel_message_table_entry { | |||
37 | void (*message_handler)(struct vmbus_channel_message_header *msg); | 37 | void (*message_handler)(struct vmbus_channel_message_header *msg); |
38 | }; | 38 | }; |
39 | 39 | ||
40 | #define MAX_MSG_TYPES 4 | ||
41 | #define MAX_NUM_DEVICE_CLASSES_SUPPORTED 8 | ||
42 | |||
43 | static const uuid_le | ||
44 | supported_device_classes[MAX_NUM_DEVICE_CLASSES_SUPPORTED] = { | ||
45 | /* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */ | ||
46 | /* Storage - SCSI */ | ||
47 | { | ||
48 | .b = { | ||
49 | 0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, | ||
50 | 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f | ||
51 | } | ||
52 | }, | ||
53 | |||
54 | /* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */ | ||
55 | /* Network */ | ||
56 | { | ||
57 | .b = { | ||
58 | 0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, | ||
59 | 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E | ||
60 | } | ||
61 | }, | ||
62 | |||
63 | /* {CFA8B69E-5B4A-4cc0-B98B-8BA1A1F3F95A} */ | ||
64 | /* Input */ | ||
65 | { | ||
66 | .b = { | ||
67 | 0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c, | ||
68 | 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A | ||
69 | } | ||
70 | }, | ||
71 | |||
72 | /* {32412632-86cb-44a2-9b5c-50d1417354f5} */ | ||
73 | /* IDE */ | ||
74 | { | ||
75 | .b = { | ||
76 | 0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, | ||
77 | 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5 | ||
78 | } | ||
79 | }, | ||
80 | /* 0E0B6031-5213-4934-818B-38D90CED39DB */ | ||
81 | /* Shutdown */ | ||
82 | { | ||
83 | .b = { | ||
84 | 0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49, | ||
85 | 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB | ||
86 | } | ||
87 | }, | ||
88 | /* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */ | ||
89 | /* TimeSync */ | ||
90 | { | ||
91 | .b = { | ||
92 | 0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49, | ||
93 | 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf | ||
94 | } | ||
95 | }, | ||
96 | /* {57164f39-9115-4e78-ab55-382f3bd5422d} */ | ||
97 | /* Heartbeat */ | ||
98 | { | ||
99 | .b = { | ||
100 | 0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, | ||
101 | 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d | ||
102 | } | ||
103 | }, | ||
104 | /* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */ | ||
105 | /* KVP */ | ||
106 | { | ||
107 | .b = { | ||
108 | 0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d, | ||
109 | 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6 | ||
110 | } | ||
111 | }, | ||
112 | |||
113 | }; | ||
114 | |||
115 | 40 | ||
116 | /** | 41 | /** |
117 | * vmbus_prep_negotiate_resp() - Create default response for Hyper-V Negotiate message | 42 | * vmbus_prep_negotiate_resp() - Create default response for Hyper-V Negotiate message |
@@ -321,20 +246,8 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr) | |||
321 | struct vmbus_channel *newchannel; | 246 | struct vmbus_channel *newchannel; |
322 | uuid_le *guidtype; | 247 | uuid_le *guidtype; |
323 | uuid_le *guidinstance; | 248 | uuid_le *guidinstance; |
324 | int i; | ||
325 | int fsupported = 0; | ||
326 | 249 | ||
327 | offer = (struct vmbus_channel_offer_channel *)hdr; | 250 | offer = (struct vmbus_channel_offer_channel *)hdr; |
328 | for (i = 0; i < MAX_NUM_DEVICE_CLASSES_SUPPORTED; i++) { | ||
329 | if (!uuid_le_cmp(offer->offer.if_type, | ||
330 | supported_device_classes[i])) { | ||
331 | fsupported = 1; | ||
332 | break; | ||
333 | } | ||
334 | } | ||
335 | |||
336 | if (!fsupported) | ||
337 | return; | ||
338 | 251 | ||
339 | guidtype = &offer->offer.if_type; | 252 | guidtype = &offer->offer.if_type; |
340 | guidinstance = &offer->offer.if_instance; | 253 | guidinstance = &offer->offer.if_instance; |
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 12aa97f31f93..15956bd48b48 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c | |||
@@ -155,9 +155,9 @@ int hv_init(void) | |||
155 | union hv_x64_msr_hypercall_contents hypercall_msr; | 155 | union hv_x64_msr_hypercall_contents hypercall_msr; |
156 | void *virtaddr = NULL; | 156 | void *virtaddr = NULL; |
157 | 157 | ||
158 | memset(hv_context.synic_event_page, 0, sizeof(void *) * MAX_NUM_CPUS); | 158 | memset(hv_context.synic_event_page, 0, sizeof(void *) * NR_CPUS); |
159 | memset(hv_context.synic_message_page, 0, | 159 | memset(hv_context.synic_message_page, 0, |
160 | sizeof(void *) * MAX_NUM_CPUS); | 160 | sizeof(void *) * NR_CPUS); |
161 | 161 | ||
162 | if (!query_hypervisor_presence()) | 162 | if (!query_hypervisor_presence()) |
163 | goto cleanup; | 163 | goto cleanup; |
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c index 0e8343f585bb..6186025209ce 100644 --- a/drivers/hv/hv_kvp.c +++ b/drivers/hv/hv_kvp.c | |||
@@ -28,8 +28,6 @@ | |||
28 | #include <linux/workqueue.h> | 28 | #include <linux/workqueue.h> |
29 | #include <linux/hyperv.h> | 29 | #include <linux/hyperv.h> |
30 | 30 | ||
31 | #include "hv_kvp.h" | ||
32 | |||
33 | 31 | ||
34 | 32 | ||
35 | /* | 33 | /* |
@@ -44,9 +42,10 @@ | |||
44 | static struct { | 42 | static struct { |
45 | bool active; /* transaction status - active or not */ | 43 | bool active; /* transaction status - active or not */ |
46 | int recv_len; /* number of bytes received. */ | 44 | int recv_len; /* number of bytes received. */ |
47 | int index; /* current index */ | 45 | struct hv_kvp_msg *kvp_msg; /* current message */ |
48 | struct vmbus_channel *recv_channel; /* chn we got the request */ | 46 | struct vmbus_channel *recv_channel; /* chn we got the request */ |
49 | u64 recv_req_id; /* request ID. */ | 47 | u64 recv_req_id; /* request ID. */ |
48 | void *kvp_context; /* for the channel callback */ | ||
50 | } kvp_transaction; | 49 | } kvp_transaction; |
51 | 50 | ||
52 | static void kvp_send_key(struct work_struct *dummy); | 51 | static void kvp_send_key(struct work_struct *dummy); |
@@ -73,15 +72,20 @@ kvp_register(void) | |||
73 | { | 72 | { |
74 | 73 | ||
75 | struct cn_msg *msg; | 74 | struct cn_msg *msg; |
75 | struct hv_kvp_msg *kvp_msg; | ||
76 | char *version; | ||
76 | 77 | ||
77 | msg = kzalloc(sizeof(*msg) + strlen(HV_DRV_VERSION) + 1 , GFP_ATOMIC); | 78 | msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg), GFP_ATOMIC); |
78 | 79 | ||
79 | if (msg) { | 80 | if (msg) { |
81 | kvp_msg = (struct hv_kvp_msg *)msg->data; | ||
82 | version = kvp_msg->body.kvp_register.version; | ||
80 | msg->id.idx = CN_KVP_IDX; | 83 | msg->id.idx = CN_KVP_IDX; |
81 | msg->id.val = CN_KVP_VAL; | 84 | msg->id.val = CN_KVP_VAL; |
82 | msg->seq = KVP_REGISTER; | 85 | |
83 | strcpy(msg->data, HV_DRV_VERSION); | 86 | kvp_msg->kvp_hdr.operation = KVP_OP_REGISTER; |
84 | msg->len = strlen(HV_DRV_VERSION) + 1; | 87 | strcpy(version, HV_DRV_VERSION); |
88 | msg->len = sizeof(struct hv_kvp_msg); | ||
85 | cn_netlink_send(msg, 0, GFP_ATOMIC); | 89 | cn_netlink_send(msg, 0, GFP_ATOMIC); |
86 | kfree(msg); | 90 | kfree(msg); |
87 | } | 91 | } |
@@ -103,23 +107,28 @@ kvp_work_func(struct work_struct *dummy) | |||
103 | static void | 107 | static void |
104 | kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) | 108 | kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) |
105 | { | 109 | { |
106 | struct hv_ku_msg *message; | 110 | struct hv_kvp_msg *message; |
111 | struct hv_kvp_msg_enumerate *data; | ||
107 | 112 | ||
108 | message = (struct hv_ku_msg *)msg->data; | 113 | message = (struct hv_kvp_msg *)msg->data; |
109 | if (msg->seq == KVP_REGISTER) { | 114 | switch (message->kvp_hdr.operation) { |
115 | case KVP_OP_REGISTER: | ||
110 | pr_info("KVP: user-mode registering done.\n"); | 116 | pr_info("KVP: user-mode registering done.\n"); |
111 | kvp_register(); | 117 | kvp_register(); |
112 | } | 118 | kvp_transaction.active = false; |
119 | hv_kvp_onchannelcallback(kvp_transaction.kvp_context); | ||
120 | break; | ||
113 | 121 | ||
114 | if (msg->seq == KVP_USER_SET) { | 122 | default: |
123 | data = &message->body.kvp_enum_data; | ||
115 | /* | 124 | /* |
116 | * Complete the transaction by forwarding the key value | 125 | * Complete the transaction by forwarding the key value |
117 | * to the host. But first, cancel the timeout. | 126 | * to the host. But first, cancel the timeout. |
118 | */ | 127 | */ |
119 | if (cancel_delayed_work_sync(&kvp_work)) | 128 | if (cancel_delayed_work_sync(&kvp_work)) |
120 | kvp_respond_to_host(message->kvp_key, | 129 | kvp_respond_to_host(data->data.key, |
121 | message->kvp_value, | 130 | data->data.value, |
122 | !strlen(message->kvp_key)); | 131 | !strlen(data->data.key)); |
123 | } | 132 | } |
124 | } | 133 | } |
125 | 134 | ||
@@ -127,19 +136,105 @@ static void | |||
127 | kvp_send_key(struct work_struct *dummy) | 136 | kvp_send_key(struct work_struct *dummy) |
128 | { | 137 | { |
129 | struct cn_msg *msg; | 138 | struct cn_msg *msg; |
130 | int index = kvp_transaction.index; | 139 | struct hv_kvp_msg *message; |
140 | struct hv_kvp_msg *in_msg; | ||
141 | __u8 operation = kvp_transaction.kvp_msg->kvp_hdr.operation; | ||
142 | __u8 pool = kvp_transaction.kvp_msg->kvp_hdr.pool; | ||
143 | __u32 val32; | ||
144 | __u64 val64; | ||
131 | 145 | ||
132 | msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC); | 146 | msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC); |
147 | if (!msg) | ||
148 | return; | ||
133 | 149 | ||
134 | if (msg) { | 150 | msg->id.idx = CN_KVP_IDX; |
135 | msg->id.idx = CN_KVP_IDX; | 151 | msg->id.val = CN_KVP_VAL; |
136 | msg->id.val = CN_KVP_VAL; | 152 | |
137 | msg->seq = KVP_KERNEL_GET; | 153 | message = (struct hv_kvp_msg *)msg->data; |
138 | ((struct hv_ku_msg *)msg->data)->kvp_index = index; | 154 | message->kvp_hdr.operation = operation; |
139 | msg->len = sizeof(struct hv_ku_msg); | 155 | message->kvp_hdr.pool = pool; |
140 | cn_netlink_send(msg, 0, GFP_ATOMIC); | 156 | in_msg = kvp_transaction.kvp_msg; |
141 | kfree(msg); | 157 | |
158 | /* | ||
159 | * The key/value strings sent from the host are encoded in | ||
160 | * in utf16; convert it to utf8 strings. | ||
161 | * The host assures us that the utf16 strings will not exceed | ||
162 | * the max lengths specified. We will however, reserve room | ||
163 | * for the string terminating character - in the utf16s_utf8s() | ||
164 | * function we limit the size of the buffer where the converted | ||
165 | * string is placed to HV_KVP_EXCHANGE_MAX_*_SIZE -1 to gaurantee | ||
166 | * that the strings can be properly terminated! | ||
167 | */ | ||
168 | |||
169 | switch (message->kvp_hdr.operation) { | ||
170 | case KVP_OP_SET: | ||
171 | switch (in_msg->body.kvp_set.data.value_type) { | ||
172 | case REG_SZ: | ||
173 | /* | ||
174 | * The value is a string - utf16 encoding. | ||
175 | */ | ||
176 | message->body.kvp_set.data.value_size = | ||
177 | utf16s_to_utf8s( | ||
178 | (wchar_t *)in_msg->body.kvp_set.data.value, | ||
179 | in_msg->body.kvp_set.data.value_size, | ||
180 | UTF16_LITTLE_ENDIAN, | ||
181 | message->body.kvp_set.data.value, | ||
182 | HV_KVP_EXCHANGE_MAX_VALUE_SIZE - 1) + 1; | ||
183 | break; | ||
184 | |||
185 | case REG_U32: | ||
186 | /* | ||
187 | * The value is a 32 bit scalar. | ||
188 | * We save this as a utf8 string. | ||
189 | */ | ||
190 | val32 = in_msg->body.kvp_set.data.value_u32; | ||
191 | message->body.kvp_set.data.value_size = | ||
192 | sprintf(message->body.kvp_set.data.value, | ||
193 | "%d", val32) + 1; | ||
194 | break; | ||
195 | |||
196 | case REG_U64: | ||
197 | /* | ||
198 | * The value is a 64 bit scalar. | ||
199 | * We save this as a utf8 string. | ||
200 | */ | ||
201 | val64 = in_msg->body.kvp_set.data.value_u64; | ||
202 | message->body.kvp_set.data.value_size = | ||
203 | sprintf(message->body.kvp_set.data.value, | ||
204 | "%llu", val64) + 1; | ||
205 | break; | ||
206 | |||
207 | } | ||
208 | case KVP_OP_GET: | ||
209 | message->body.kvp_set.data.key_size = | ||
210 | utf16s_to_utf8s( | ||
211 | (wchar_t *)in_msg->body.kvp_set.data.key, | ||
212 | in_msg->body.kvp_set.data.key_size, | ||
213 | UTF16_LITTLE_ENDIAN, | ||
214 | message->body.kvp_set.data.key, | ||
215 | HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1; | ||
216 | break; | ||
217 | |||
218 | case KVP_OP_DELETE: | ||
219 | message->body.kvp_delete.key_size = | ||
220 | utf16s_to_utf8s( | ||
221 | (wchar_t *)in_msg->body.kvp_delete.key, | ||
222 | in_msg->body.kvp_delete.key_size, | ||
223 | UTF16_LITTLE_ENDIAN, | ||
224 | message->body.kvp_delete.key, | ||
225 | HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1; | ||
226 | break; | ||
227 | |||
228 | case KVP_OP_ENUMERATE: | ||
229 | message->body.kvp_enum_data.index = | ||
230 | in_msg->body.kvp_enum_data.index; | ||
231 | break; | ||
142 | } | 232 | } |
233 | |||
234 | msg->len = sizeof(struct hv_kvp_msg); | ||
235 | cn_netlink_send(msg, 0, GFP_ATOMIC); | ||
236 | kfree(msg); | ||
237 | |||
143 | return; | 238 | return; |
144 | } | 239 | } |
145 | 240 | ||
@@ -151,10 +246,11 @@ static void | |||
151 | kvp_respond_to_host(char *key, char *value, int error) | 246 | kvp_respond_to_host(char *key, char *value, int error) |
152 | { | 247 | { |
153 | struct hv_kvp_msg *kvp_msg; | 248 | struct hv_kvp_msg *kvp_msg; |
154 | struct hv_kvp_msg_enumerate *kvp_data; | 249 | struct hv_kvp_exchg_msg_value *kvp_data; |
155 | char *key_name; | 250 | char *key_name; |
156 | struct icmsg_hdr *icmsghdrp; | 251 | struct icmsg_hdr *icmsghdrp; |
157 | int keylen, valuelen; | 252 | int keylen = 0; |
253 | int valuelen = 0; | ||
158 | u32 buf_len; | 254 | u32 buf_len; |
159 | struct vmbus_channel *channel; | 255 | struct vmbus_channel *channel; |
160 | u64 req_id; | 256 | u64 req_id; |
@@ -181,6 +277,9 @@ kvp_respond_to_host(char *key, char *value, int error) | |||
181 | 277 | ||
182 | kvp_transaction.active = false; | 278 | kvp_transaction.active = false; |
183 | 279 | ||
280 | icmsghdrp = (struct icmsg_hdr *) | ||
281 | &recv_buffer[sizeof(struct vmbuspipe_hdr)]; | ||
282 | |||
184 | if (channel->onchannel_callback == NULL) | 283 | if (channel->onchannel_callback == NULL) |
185 | /* | 284 | /* |
186 | * We have raced with util driver being unloaded; | 285 | * We have raced with util driver being unloaded; |
@@ -188,41 +287,67 @@ kvp_respond_to_host(char *key, char *value, int error) | |||
188 | */ | 287 | */ |
189 | return; | 288 | return; |
190 | 289 | ||
191 | icmsghdrp = (struct icmsg_hdr *) | ||
192 | &recv_buffer[sizeof(struct vmbuspipe_hdr)]; | ||
193 | kvp_msg = (struct hv_kvp_msg *) | ||
194 | &recv_buffer[sizeof(struct vmbuspipe_hdr) + | ||
195 | sizeof(struct icmsg_hdr)]; | ||
196 | kvp_data = &kvp_msg->kvp_data; | ||
197 | key_name = key; | ||
198 | 290 | ||
199 | /* | 291 | /* |
200 | * If the error parameter is set, terminate the host's enumeration. | 292 | * If the error parameter is set, terminate the host's enumeration |
293 | * on this pool. | ||
201 | */ | 294 | */ |
202 | if (error) { | 295 | if (error) { |
203 | /* | 296 | /* |
204 | * We don't support this index or the we have timedout; | 297 | * Something failed or the we have timedout; |
205 | * terminate the host-side iteration by returning an error. | 298 | * terminate the current host-side iteration. |
206 | */ | 299 | */ |
207 | icmsghdrp->status = HV_E_FAIL; | 300 | icmsghdrp->status = HV_S_CONT; |
208 | goto response_done; | 301 | goto response_done; |
209 | } | 302 | } |
210 | 303 | ||
304 | icmsghdrp->status = HV_S_OK; | ||
305 | |||
306 | kvp_msg = (struct hv_kvp_msg *) | ||
307 | &recv_buffer[sizeof(struct vmbuspipe_hdr) + | ||
308 | sizeof(struct icmsg_hdr)]; | ||
309 | |||
310 | switch (kvp_transaction.kvp_msg->kvp_hdr.operation) { | ||
311 | case KVP_OP_GET: | ||
312 | kvp_data = &kvp_msg->body.kvp_get.data; | ||
313 | goto copy_value; | ||
314 | |||
315 | case KVP_OP_SET: | ||
316 | case KVP_OP_DELETE: | ||
317 | goto response_done; | ||
318 | |||
319 | default: | ||
320 | break; | ||
321 | } | ||
322 | |||
323 | kvp_data = &kvp_msg->body.kvp_enum_data.data; | ||
324 | key_name = key; | ||
325 | |||
211 | /* | 326 | /* |
212 | * The windows host expects the key/value pair to be encoded | 327 | * The windows host expects the key/value pair to be encoded |
213 | * in utf16. | 328 | * in utf16. Ensure that the key/value size reported to the host |
329 | * will be less than or equal to the MAX size (including the | ||
330 | * terminating character). | ||
214 | */ | 331 | */ |
215 | keylen = utf8s_to_utf16s(key_name, strlen(key_name), UTF16_HOST_ENDIAN, | 332 | keylen = utf8s_to_utf16s(key_name, strlen(key_name), UTF16_HOST_ENDIAN, |
216 | (wchar_t *) kvp_data->data.key, | 333 | (wchar_t *) kvp_data->key, |
217 | HV_KVP_EXCHANGE_MAX_KEY_SIZE / 2); | 334 | (HV_KVP_EXCHANGE_MAX_KEY_SIZE / 2) - 2); |
218 | kvp_data->data.key_size = 2*(keylen + 1); /* utf16 encoding */ | 335 | kvp_data->key_size = 2*(keylen + 1); /* utf16 encoding */ |
336 | |||
337 | copy_value: | ||
219 | valuelen = utf8s_to_utf16s(value, strlen(value), UTF16_HOST_ENDIAN, | 338 | valuelen = utf8s_to_utf16s(value, strlen(value), UTF16_HOST_ENDIAN, |
220 | (wchar_t *) kvp_data->data.value, | 339 | (wchar_t *) kvp_data->value, |
221 | HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2); | 340 | (HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2) - 2); |
222 | kvp_data->data.value_size = 2*(valuelen + 1); /* utf16 encoding */ | 341 | kvp_data->value_size = 2*(valuelen + 1); /* utf16 encoding */ |
223 | 342 | ||
224 | kvp_data->data.value_type = REG_SZ; /* all our values are strings */ | 343 | /* |
225 | icmsghdrp->status = HV_S_OK; | 344 | * If the utf8s to utf16s conversion failed; notify host |
345 | * of the error. | ||
346 | */ | ||
347 | if ((keylen < 0) || (valuelen < 0)) | ||
348 | icmsghdrp->status = HV_E_FAIL; | ||
349 | |||
350 | kvp_data->value_type = REG_SZ; /* all our values are strings */ | ||
226 | 351 | ||
227 | response_done: | 352 | response_done: |
228 | icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; | 353 | icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; |
@@ -249,11 +374,18 @@ void hv_kvp_onchannelcallback(void *context) | |||
249 | u64 requestid; | 374 | u64 requestid; |
250 | 375 | ||
251 | struct hv_kvp_msg *kvp_msg; | 376 | struct hv_kvp_msg *kvp_msg; |
252 | struct hv_kvp_msg_enumerate *kvp_data; | ||
253 | 377 | ||
254 | struct icmsg_hdr *icmsghdrp; | 378 | struct icmsg_hdr *icmsghdrp; |
255 | struct icmsg_negotiate *negop = NULL; | 379 | struct icmsg_negotiate *negop = NULL; |
256 | 380 | ||
381 | if (kvp_transaction.active) { | ||
382 | /* | ||
383 | * We will defer processing this callback once | ||
384 | * the current transaction is complete. | ||
385 | */ | ||
386 | kvp_transaction.kvp_context = context; | ||
387 | return; | ||
388 | } | ||
257 | 389 | ||
258 | vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE, &recvlen, &requestid); | 390 | vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE, &recvlen, &requestid); |
259 | 391 | ||
@@ -268,29 +400,16 @@ void hv_kvp_onchannelcallback(void *context) | |||
268 | sizeof(struct vmbuspipe_hdr) + | 400 | sizeof(struct vmbuspipe_hdr) + |
269 | sizeof(struct icmsg_hdr)]; | 401 | sizeof(struct icmsg_hdr)]; |
270 | 402 | ||
271 | kvp_data = &kvp_msg->kvp_data; | ||
272 | |||
273 | /* | ||
274 | * We only support the "get" operation on | ||
275 | * "KVP_POOL_AUTO" pool. | ||
276 | */ | ||
277 | |||
278 | if ((kvp_msg->kvp_hdr.pool != KVP_POOL_AUTO) || | ||
279 | (kvp_msg->kvp_hdr.operation != | ||
280 | KVP_OP_ENUMERATE)) { | ||
281 | icmsghdrp->status = HV_E_FAIL; | ||
282 | goto callback_done; | ||
283 | } | ||
284 | |||
285 | /* | 403 | /* |
286 | * Stash away this global state for completing the | 404 | * Stash away this global state for completing the |
287 | * transaction; note transactions are serialized. | 405 | * transaction; note transactions are serialized. |
288 | */ | 406 | */ |
407 | |||
289 | kvp_transaction.recv_len = recvlen; | 408 | kvp_transaction.recv_len = recvlen; |
290 | kvp_transaction.recv_channel = channel; | 409 | kvp_transaction.recv_channel = channel; |
291 | kvp_transaction.recv_req_id = requestid; | 410 | kvp_transaction.recv_req_id = requestid; |
292 | kvp_transaction.active = true; | 411 | kvp_transaction.active = true; |
293 | kvp_transaction.index = kvp_data->index; | 412 | kvp_transaction.kvp_msg = kvp_msg; |
294 | 413 | ||
295 | /* | 414 | /* |
296 | * Get the information from the | 415 | * Get the information from the |
@@ -308,8 +427,6 @@ void hv_kvp_onchannelcallback(void *context) | |||
308 | 427 | ||
309 | } | 428 | } |
310 | 429 | ||
311 | callback_done: | ||
312 | |||
313 | icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | 430 | icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION |
314 | | ICMSGHDRFLAG_RESPONSE; | 431 | | ICMSGHDRFLAG_RESPONSE; |
315 | 432 | ||
@@ -330,6 +447,14 @@ hv_kvp_init(struct hv_util_service *srv) | |||
330 | return err; | 447 | return err; |
331 | recv_buffer = srv->recv_buffer; | 448 | recv_buffer = srv->recv_buffer; |
332 | 449 | ||
450 | /* | ||
451 | * When this driver loads, the user level daemon that | ||
452 | * processes the host requests may not yet be running. | ||
453 | * Defer processing channel callbacks until the daemon | ||
454 | * has registered. | ||
455 | */ | ||
456 | kvp_transaction.active = true; | ||
457 | |||
333 | return 0; | 458 | return 0; |
334 | } | 459 | } |
335 | 460 | ||
diff --git a/drivers/hv/hv_kvp.h b/drivers/hv/hv_kvp.h deleted file mode 100644 index 9b765d7df838..000000000000 --- a/drivers/hv/hv_kvp.h +++ /dev/null | |||
@@ -1,184 +0,0 @@ | |||
1 | /* | ||
2 | * An implementation of HyperV key value pair (KVP) functionality for Linux. | ||
3 | * | ||
4 | * | ||
5 | * Copyright (C) 2010, Novell, Inc. | ||
6 | * Author : K. Y. Srinivasan <ksrinivasan@novell.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License version 2 as published | ||
10 | * by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
15 | * NON INFRINGEMENT. See the GNU General Public License for more | ||
16 | * details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * | ||
22 | */ | ||
23 | #ifndef _KVP_H | ||
24 | #define _KVP_H_ | ||
25 | |||
26 | /* | ||
27 | * Maximum value size - used for both key names and value data, and includes | ||
28 | * any applicable NULL terminators. | ||
29 | * | ||
30 | * Note: This limit is somewhat arbitrary, but falls easily within what is | ||
31 | * supported for all native guests (back to Win 2000) and what is reasonable | ||
32 | * for the IC KVP exchange functionality. Note that Windows Me/98/95 are | ||
33 | * limited to 255 character key names. | ||
34 | * | ||
35 | * MSDN recommends not storing data values larger than 2048 bytes in the | ||
36 | * registry. | ||
37 | * | ||
38 | * Note: This value is used in defining the KVP exchange message - this value | ||
39 | * cannot be modified without affecting the message size and compatibility. | ||
40 | */ | ||
41 | |||
42 | /* | ||
43 | * bytes, including any null terminators | ||
44 | */ | ||
45 | #define HV_KVP_EXCHANGE_MAX_VALUE_SIZE (2048) | ||
46 | |||
47 | |||
48 | /* | ||
49 | * Maximum key size - the registry limit for the length of an entry name | ||
50 | * is 256 characters, including the null terminator | ||
51 | */ | ||
52 | |||
53 | #define HV_KVP_EXCHANGE_MAX_KEY_SIZE (512) | ||
54 | |||
55 | /* | ||
56 | * In Linux, we implement the KVP functionality in two components: | ||
57 | * 1) The kernel component which is packaged as part of the hv_utils driver | ||
58 | * is responsible for communicating with the host and responsible for | ||
59 | * implementing the host/guest protocol. 2) A user level daemon that is | ||
60 | * responsible for data gathering. | ||
61 | * | ||
62 | * Host/Guest Protocol: The host iterates over an index and expects the guest | ||
63 | * to assign a key name to the index and also return the value corresponding to | ||
64 | * the key. The host will have atmost one KVP transaction outstanding at any | ||
65 | * given point in time. The host side iteration stops when the guest returns | ||
66 | * an error. Microsoft has specified the following mapping of key names to | ||
67 | * host specified index: | ||
68 | * | ||
69 | * Index Key Name | ||
70 | * 0 FullyQualifiedDomainName | ||
71 | * 1 IntegrationServicesVersion | ||
72 | * 2 NetworkAddressIPv4 | ||
73 | * 3 NetworkAddressIPv6 | ||
74 | * 4 OSBuildNumber | ||
75 | * 5 OSName | ||
76 | * 6 OSMajorVersion | ||
77 | * 7 OSMinorVersion | ||
78 | * 8 OSVersion | ||
79 | * 9 ProcessorArchitecture | ||
80 | * | ||
81 | * The Windows host expects the Key Name and Key Value to be encoded in utf16. | ||
82 | * | ||
83 | * Guest Kernel/KVP Daemon Protocol: As noted earlier, we implement all of the | ||
84 | * data gathering functionality in a user mode daemon. The user level daemon | ||
85 | * is also responsible for binding the key name to the index as well. The | ||
86 | * kernel and user-level daemon communicate using a connector channel. | ||
87 | * | ||
88 | * The user mode component first registers with the | ||
89 | * the kernel component. Subsequently, the kernel component requests, data | ||
90 | * for the specified keys. In response to this message the user mode component | ||
91 | * fills in the value corresponding to the specified key. We overload the | ||
92 | * sequence field in the cn_msg header to define our KVP message types. | ||
93 | * | ||
94 | * | ||
95 | * The kernel component simply acts as a conduit for communication between the | ||
96 | * Windows host and the user-level daemon. The kernel component passes up the | ||
97 | * index received from the Host to the user-level daemon. If the index is | ||
98 | * valid (supported), the corresponding key as well as its | ||
99 | * value (both are strings) is returned. If the index is invalid | ||
100 | * (not supported), a NULL key string is returned. | ||
101 | */ | ||
102 | |||
103 | /* | ||
104 | * | ||
105 | * The following definitions are shared with the user-mode component; do not | ||
106 | * change any of this without making the corresponding changes in | ||
107 | * the KVP user-mode component. | ||
108 | */ | ||
109 | |||
110 | #define CN_KVP_VAL 0x1 /* This supports queries from the kernel */ | ||
111 | #define CN_KVP_USER_VAL 0x2 /* This supports queries from the user */ | ||
112 | |||
113 | enum hv_ku_op { | ||
114 | KVP_REGISTER = 0, /* Register the user mode component */ | ||
115 | KVP_KERNEL_GET, /* Kernel is requesting the value */ | ||
116 | KVP_KERNEL_SET, /* Kernel is providing the value */ | ||
117 | KVP_USER_GET, /* User is requesting the value */ | ||
118 | KVP_USER_SET /* User is providing the value */ | ||
119 | }; | ||
120 | |||
121 | struct hv_ku_msg { | ||
122 | __u32 kvp_index; /* Key index */ | ||
123 | __u8 kvp_key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; /* Key name */ | ||
124 | __u8 kvp_value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; /* Key value */ | ||
125 | }; | ||
126 | |||
127 | |||
128 | |||
129 | |||
130 | #ifdef __KERNEL__ | ||
131 | |||
132 | /* | ||
133 | * Registry value types. | ||
134 | */ | ||
135 | |||
136 | #define REG_SZ 1 | ||
137 | |||
138 | enum hv_kvp_exchg_op { | ||
139 | KVP_OP_GET = 0, | ||
140 | KVP_OP_SET, | ||
141 | KVP_OP_DELETE, | ||
142 | KVP_OP_ENUMERATE, | ||
143 | KVP_OP_COUNT /* Number of operations, must be last. */ | ||
144 | }; | ||
145 | |||
146 | enum hv_kvp_exchg_pool { | ||
147 | KVP_POOL_EXTERNAL = 0, | ||
148 | KVP_POOL_GUEST, | ||
149 | KVP_POOL_AUTO, | ||
150 | KVP_POOL_AUTO_EXTERNAL, | ||
151 | KVP_POOL_AUTO_INTERNAL, | ||
152 | KVP_POOL_COUNT /* Number of pools, must be last. */ | ||
153 | }; | ||
154 | |||
155 | struct hv_kvp_hdr { | ||
156 | u8 operation; | ||
157 | u8 pool; | ||
158 | }; | ||
159 | |||
160 | struct hv_kvp_exchg_msg_value { | ||
161 | u32 value_type; | ||
162 | u32 key_size; | ||
163 | u32 value_size; | ||
164 | u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; | ||
165 | u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; | ||
166 | }; | ||
167 | |||
168 | struct hv_kvp_msg_enumerate { | ||
169 | u32 index; | ||
170 | struct hv_kvp_exchg_msg_value data; | ||
171 | }; | ||
172 | |||
173 | struct hv_kvp_msg { | ||
174 | struct hv_kvp_hdr kvp_hdr; | ||
175 | struct hv_kvp_msg_enumerate kvp_data; | ||
176 | }; | ||
177 | |||
178 | int hv_kvp_init(struct hv_util_service *); | ||
179 | void hv_kvp_deinit(void); | ||
180 | void hv_kvp_onchannelcallback(void *); | ||
181 | |||
182 | #endif /* __KERNEL__ */ | ||
183 | #endif /* _KVP_H */ | ||
184 | |||
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c index 55d58f21e6d4..dbb8b8eec210 100644 --- a/drivers/hv/hv_util.c +++ b/drivers/hv/hv_util.c | |||
@@ -28,9 +28,6 @@ | |||
28 | #include <linux/reboot.h> | 28 | #include <linux/reboot.h> |
29 | #include <linux/hyperv.h> | 29 | #include <linux/hyperv.h> |
30 | 30 | ||
31 | #include "hv_kvp.h" | ||
32 | |||
33 | |||
34 | static void shutdown_onchannelcallback(void *context); | 31 | static void shutdown_onchannelcallback(void *context); |
35 | static struct hv_util_service util_shutdown = { | 32 | static struct hv_util_service util_shutdown = { |
36 | .util_cb = shutdown_onchannelcallback, | 33 | .util_cb = shutdown_onchannelcallback, |
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 6d7d286d5440..699f0d8e59ed 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h | |||
@@ -457,7 +457,6 @@ static const uuid_le VMBUS_SERVICE_ID = { | |||
457 | }, | 457 | }, |
458 | }; | 458 | }; |
459 | 459 | ||
460 | #define MAX_NUM_CPUS 32 | ||
461 | 460 | ||
462 | 461 | ||
463 | struct hv_input_signal_event_buffer { | 462 | struct hv_input_signal_event_buffer { |
@@ -483,8 +482,8 @@ struct hv_context { | |||
483 | /* 8-bytes aligned of the buffer above */ | 482 | /* 8-bytes aligned of the buffer above */ |
484 | struct hv_input_signal_event *signal_event_param; | 483 | struct hv_input_signal_event *signal_event_param; |
485 | 484 | ||
486 | void *synic_message_page[MAX_NUM_CPUS]; | 485 | void *synic_message_page[NR_CPUS]; |
487 | void *synic_event_page[MAX_NUM_CPUS]; | 486 | void *synic_event_page[NR_CPUS]; |
488 | }; | 487 | }; |
489 | 488 | ||
490 | extern struct hv_context hv_context; | 489 | extern struct hv_context hv_context; |
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index a6c6ec36615e..249ac460e3d9 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/moduleparam.h> | 39 | #include <linux/moduleparam.h> |
40 | #include <asm/msr.h> | 40 | #include <asm/msr.h> |
41 | #include <asm/processor.h> | 41 | #include <asm/processor.h> |
42 | #include <asm/cpu_device_id.h> | ||
42 | 43 | ||
43 | #define DRVNAME "coretemp" | 44 | #define DRVNAME "coretemp" |
44 | 45 | ||
@@ -759,13 +760,23 @@ static struct notifier_block coretemp_cpu_notifier __refdata = { | |||
759 | .notifier_call = coretemp_cpu_callback, | 760 | .notifier_call = coretemp_cpu_callback, |
760 | }; | 761 | }; |
761 | 762 | ||
763 | static const struct x86_cpu_id coretemp_ids[] = { | ||
764 | { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_DTS }, | ||
765 | {} | ||
766 | }; | ||
767 | MODULE_DEVICE_TABLE(x86cpu, coretemp_ids); | ||
768 | |||
762 | static int __init coretemp_init(void) | 769 | static int __init coretemp_init(void) |
763 | { | 770 | { |
764 | int i, err = -ENODEV; | 771 | int i, err = -ENODEV; |
765 | 772 | ||
766 | /* quick check if we run Intel */ | 773 | /* |
767 | if (cpu_data(0).x86_vendor != X86_VENDOR_INTEL) | 774 | * CPUID.06H.EAX[0] indicates whether the CPU has thermal |
768 | goto exit; | 775 | * sensors. We check this bit only, all the early CPUs |
776 | * without thermal sensors will be filtered out. | ||
777 | */ | ||
778 | if (!x86_match_cpu(coretemp_ids)) | ||
779 | return -ENODEV; | ||
769 | 780 | ||
770 | err = platform_driver_register(&coretemp_driver); | 781 | err = platform_driver_register(&coretemp_driver); |
771 | if (err) | 782 | if (err) |
diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c index 8eac67d769fa..8689664ef03c 100644 --- a/drivers/hwmon/via-cputemp.c +++ b/drivers/hwmon/via-cputemp.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/cpu.h> | 37 | #include <linux/cpu.h> |
38 | #include <asm/msr.h> | 38 | #include <asm/msr.h> |
39 | #include <asm/processor.h> | 39 | #include <asm/processor.h> |
40 | #include <asm/cpu_device_id.h> | ||
40 | 41 | ||
41 | #define DRVNAME "via_cputemp" | 42 | #define DRVNAME "via_cputemp" |
42 | 43 | ||
@@ -308,15 +309,20 @@ static struct notifier_block via_cputemp_cpu_notifier __refdata = { | |||
308 | .notifier_call = via_cputemp_cpu_callback, | 309 | .notifier_call = via_cputemp_cpu_callback, |
309 | }; | 310 | }; |
310 | 311 | ||
312 | static const struct x86_cpu_id cputemp_ids[] = { | ||
313 | { X86_VENDOR_CENTAUR, 6, 0xa, }, /* C7 A */ | ||
314 | { X86_VENDOR_CENTAUR, 6, 0xd, }, /* C7 D */ | ||
315 | { X86_VENDOR_CENTAUR, 6, 0xf, }, /* Nano */ | ||
316 | {} | ||
317 | }; | ||
318 | MODULE_DEVICE_TABLE(x86cpu, cputemp_ids); | ||
319 | |||
311 | static int __init via_cputemp_init(void) | 320 | static int __init via_cputemp_init(void) |
312 | { | 321 | { |
313 | int i, err; | 322 | int i, err; |
314 | 323 | ||
315 | if (cpu_data(0).x86_vendor != X86_VENDOR_CENTAUR) { | 324 | if (!x86_match_cpu(cputemp_ids)) |
316 | printk(KERN_DEBUG DRVNAME ": Not a VIA CPU\n"); | 325 | return -ENODEV; |
317 | err = -ENODEV; | ||
318 | goto exit; | ||
319 | } | ||
320 | 326 | ||
321 | err = platform_driver_register(&via_cputemp_driver); | 327 | err = platform_driver_register(&via_cputemp_driver); |
322 | if (err) | 328 | if (err) |
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 54ab97bae042..1c15e9b33575 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c | |||
@@ -62,6 +62,7 @@ | |||
62 | #include <linux/notifier.h> | 62 | #include <linux/notifier.h> |
63 | #include <linux/cpu.h> | 63 | #include <linux/cpu.h> |
64 | #include <linux/module.h> | 64 | #include <linux/module.h> |
65 | #include <asm/cpu_device_id.h> | ||
65 | #include <asm/mwait.h> | 66 | #include <asm/mwait.h> |
66 | #include <asm/msr.h> | 67 | #include <asm/msr.h> |
67 | 68 | ||
@@ -81,6 +82,17 @@ static unsigned int mwait_substates; | |||
81 | /* Reliable LAPIC Timer States, bit 1 for C1 etc. */ | 82 | /* Reliable LAPIC Timer States, bit 1 for C1 etc. */ |
82 | static unsigned int lapic_timer_reliable_states = (1 << 1); /* Default to only C1 */ | 83 | static unsigned int lapic_timer_reliable_states = (1 << 1); /* Default to only C1 */ |
83 | 84 | ||
85 | struct idle_cpu { | ||
86 | struct cpuidle_state *state_table; | ||
87 | |||
88 | /* | ||
89 | * Hardware C-state auto-demotion may not always be optimal. | ||
90 | * Indicate which enable bits to clear here. | ||
91 | */ | ||
92 | unsigned long auto_demotion_disable_flags; | ||
93 | }; | ||
94 | |||
95 | static const struct idle_cpu *icpu; | ||
84 | static struct cpuidle_device __percpu *intel_idle_cpuidle_devices; | 96 | static struct cpuidle_device __percpu *intel_idle_cpuidle_devices; |
85 | static int intel_idle(struct cpuidle_device *dev, | 97 | static int intel_idle(struct cpuidle_device *dev, |
86 | struct cpuidle_driver *drv, int index); | 98 | struct cpuidle_driver *drv, int index); |
@@ -88,12 +100,6 @@ static int intel_idle(struct cpuidle_device *dev, | |||
88 | static struct cpuidle_state *cpuidle_state_table; | 100 | static struct cpuidle_state *cpuidle_state_table; |
89 | 101 | ||
90 | /* | 102 | /* |
91 | * Hardware C-state auto-demotion may not always be optimal. | ||
92 | * Indicate which enable bits to clear here. | ||
93 | */ | ||
94 | static unsigned long long auto_demotion_disable_flags; | ||
95 | |||
96 | /* | ||
97 | * Set this flag for states where the HW flushes the TLB for us | 103 | * Set this flag for states where the HW flushes the TLB for us |
98 | * and so we don't need cross-calls to keep it consistent. | 104 | * and so we don't need cross-calls to keep it consistent. |
99 | * If this flag is set, SW flushes the TLB, so even if the | 105 | * If this flag is set, SW flushes the TLB, so even if the |
@@ -319,27 +325,68 @@ static void auto_demotion_disable(void *dummy) | |||
319 | unsigned long long msr_bits; | 325 | unsigned long long msr_bits; |
320 | 326 | ||
321 | rdmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits); | 327 | rdmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits); |
322 | msr_bits &= ~auto_demotion_disable_flags; | 328 | msr_bits &= ~(icpu->auto_demotion_disable_flags); |
323 | wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits); | 329 | wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits); |
324 | } | 330 | } |
325 | 331 | ||
332 | static const struct idle_cpu idle_cpu_nehalem = { | ||
333 | .state_table = nehalem_cstates, | ||
334 | .auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE, | ||
335 | }; | ||
336 | |||
337 | static const struct idle_cpu idle_cpu_atom = { | ||
338 | .state_table = atom_cstates, | ||
339 | }; | ||
340 | |||
341 | static const struct idle_cpu idle_cpu_lincroft = { | ||
342 | .state_table = atom_cstates, | ||
343 | .auto_demotion_disable_flags = ATM_LNC_C6_AUTO_DEMOTE, | ||
344 | }; | ||
345 | |||
346 | static const struct idle_cpu idle_cpu_snb = { | ||
347 | .state_table = snb_cstates, | ||
348 | }; | ||
349 | |||
350 | #define ICPU(model, cpu) \ | ||
351 | { X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&cpu } | ||
352 | |||
353 | static const struct x86_cpu_id intel_idle_ids[] = { | ||
354 | ICPU(0x1a, idle_cpu_nehalem), | ||
355 | ICPU(0x1e, idle_cpu_nehalem), | ||
356 | ICPU(0x1f, idle_cpu_nehalem), | ||
357 | ICPU(0x25, idle_cpu_nehalem), | ||
358 | ICPU(0x2c, idle_cpu_nehalem), | ||
359 | ICPU(0x2e, idle_cpu_nehalem), | ||
360 | ICPU(0x1c, idle_cpu_atom), | ||
361 | ICPU(0x26, idle_cpu_lincroft), | ||
362 | ICPU(0x2f, idle_cpu_nehalem), | ||
363 | ICPU(0x2a, idle_cpu_snb), | ||
364 | ICPU(0x2d, idle_cpu_snb), | ||
365 | {} | ||
366 | }; | ||
367 | MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids); | ||
368 | |||
326 | /* | 369 | /* |
327 | * intel_idle_probe() | 370 | * intel_idle_probe() |
328 | */ | 371 | */ |
329 | static int intel_idle_probe(void) | 372 | static int intel_idle_probe(void) |
330 | { | 373 | { |
331 | unsigned int eax, ebx, ecx; | 374 | unsigned int eax, ebx, ecx; |
375 | const struct x86_cpu_id *id; | ||
332 | 376 | ||
333 | if (max_cstate == 0) { | 377 | if (max_cstate == 0) { |
334 | pr_debug(PREFIX "disabled\n"); | 378 | pr_debug(PREFIX "disabled\n"); |
335 | return -EPERM; | 379 | return -EPERM; |
336 | } | 380 | } |
337 | 381 | ||
338 | if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) | 382 | id = x86_match_cpu(intel_idle_ids); |
339 | return -ENODEV; | 383 | if (!id) { |
340 | 384 | if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && | |
341 | if (!boot_cpu_has(X86_FEATURE_MWAIT)) | 385 | boot_cpu_data.x86 == 6) |
386 | pr_debug(PREFIX "does not run on family %d model %d\n", | ||
387 | boot_cpu_data.x86, boot_cpu_data.x86_model); | ||
342 | return -ENODEV; | 388 | return -ENODEV; |
389 | } | ||
343 | 390 | ||
344 | if (boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF) | 391 | if (boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF) |
345 | return -ENODEV; | 392 | return -ENODEV; |
@@ -353,43 +400,8 @@ static int intel_idle_probe(void) | |||
353 | 400 | ||
354 | pr_debug(PREFIX "MWAIT substates: 0x%x\n", mwait_substates); | 401 | pr_debug(PREFIX "MWAIT substates: 0x%x\n", mwait_substates); |
355 | 402 | ||
356 | 403 | icpu = (const struct idle_cpu *)id->driver_data; | |
357 | if (boot_cpu_data.x86 != 6) /* family 6 */ | 404 | cpuidle_state_table = icpu->state_table; |
358 | return -ENODEV; | ||
359 | |||
360 | switch (boot_cpu_data.x86_model) { | ||
361 | |||
362 | case 0x1A: /* Core i7, Xeon 5500 series */ | ||
363 | case 0x1E: /* Core i7 and i5 Processor - Lynnfield Jasper Forest */ | ||
364 | case 0x1F: /* Core i7 and i5 Processor - Nehalem */ | ||
365 | case 0x2E: /* Nehalem-EX Xeon */ | ||
366 | case 0x2F: /* Westmere-EX Xeon */ | ||
367 | case 0x25: /* Westmere */ | ||
368 | case 0x2C: /* Westmere */ | ||
369 | cpuidle_state_table = nehalem_cstates; | ||
370 | auto_demotion_disable_flags = | ||
371 | (NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE); | ||
372 | break; | ||
373 | |||
374 | case 0x1C: /* 28 - Atom Processor */ | ||
375 | cpuidle_state_table = atom_cstates; | ||
376 | break; | ||
377 | |||
378 | case 0x26: /* 38 - Lincroft Atom Processor */ | ||
379 | cpuidle_state_table = atom_cstates; | ||
380 | auto_demotion_disable_flags = ATM_LNC_C6_AUTO_DEMOTE; | ||
381 | break; | ||
382 | |||
383 | case 0x2A: /* SNB */ | ||
384 | case 0x2D: /* SNB Xeon */ | ||
385 | cpuidle_state_table = snb_cstates; | ||
386 | break; | ||
387 | |||
388 | default: | ||
389 | pr_debug(PREFIX "does not run on family %d model %d\n", | ||
390 | boot_cpu_data.x86, boot_cpu_data.x86_model); | ||
391 | return -ENODEV; | ||
392 | } | ||
393 | 405 | ||
394 | if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */ | 406 | if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */ |
395 | lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE; | 407 | lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE; |
@@ -470,7 +482,7 @@ static int intel_idle_cpuidle_driver_init(void) | |||
470 | drv->state_count += 1; | 482 | drv->state_count += 1; |
471 | } | 483 | } |
472 | 484 | ||
473 | if (auto_demotion_disable_flags) | 485 | if (icpu->auto_demotion_disable_flags) |
474 | on_each_cpu(auto_demotion_disable, NULL, 1); | 486 | on_each_cpu(auto_demotion_disable, NULL, 1); |
475 | 487 | ||
476 | return 0; | 488 | return 0; |
@@ -522,7 +534,7 @@ int intel_idle_cpu_init(int cpu) | |||
522 | return -EIO; | 534 | return -EIO; |
523 | } | 535 | } |
524 | 536 | ||
525 | if (auto_demotion_disable_flags) | 537 | if (icpu->auto_demotion_disable_flags) |
526 | smp_call_function_single(cpu, auto_demotion_disable, NULL, 1); | 538 | smp_call_function_single(cpu, auto_demotion_disable, NULL, 1); |
527 | 539 | ||
528 | return 0; | 540 | return 0; |
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index c351aa421f8f..da739d9d1905 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c | |||
@@ -449,7 +449,6 @@ static ssize_t gameport_rebind_driver(struct device *dev, struct device_attribut | |||
449 | } else if ((drv = driver_find(buf, &gameport_bus)) != NULL) { | 449 | } else if ((drv = driver_find(buf, &gameport_bus)) != NULL) { |
450 | gameport_disconnect_port(gameport); | 450 | gameport_disconnect_port(gameport); |
451 | error = gameport_bind_driver(gameport, to_gameport_driver(drv)); | 451 | error = gameport_bind_driver(gameport, to_gameport_driver(drv)); |
452 | put_driver(drv); | ||
453 | } else { | 452 | } else { |
454 | error = -EINVAL; | 453 | error = -EINVAL; |
455 | } | 454 | } |
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index ba70058e2be3..d0f7533dbf88 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c | |||
@@ -441,7 +441,6 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute * | |||
441 | } else if ((drv = driver_find(buf, &serio_bus)) != NULL) { | 441 | } else if ((drv = driver_find(buf, &serio_bus)) != NULL) { |
442 | serio_disconnect_port(serio); | 442 | serio_disconnect_port(serio); |
443 | error = serio_bind_driver(serio, to_serio_driver(drv)); | 443 | error = serio_bind_driver(serio, to_serio_driver(drv)); |
444 | put_driver(drv); | ||
445 | serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT); | 444 | serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT); |
446 | } else { | 445 | } else { |
447 | error = -EINVAL; | 446 | error = -EINVAL; |
diff --git a/drivers/media/video/cx18/cx18-alsa-main.c b/drivers/media/video/cx18/cx18-alsa-main.c index a1e6c2a32478..e118361c2e7b 100644 --- a/drivers/media/video/cx18/cx18-alsa-main.c +++ b/drivers/media/video/cx18/cx18-alsa-main.c | |||
@@ -285,7 +285,6 @@ static void __exit cx18_alsa_exit(void) | |||
285 | 285 | ||
286 | drv = driver_find("cx18", &pci_bus_type); | 286 | drv = driver_find("cx18", &pci_bus_type); |
287 | ret = driver_for_each_device(drv, NULL, NULL, cx18_alsa_exit_callback); | 287 | ret = driver_for_each_device(drv, NULL, NULL, cx18_alsa_exit_callback); |
288 | put_driver(drv); | ||
289 | 288 | ||
290 | cx18_ext_init = NULL; | 289 | cx18_ext_init = NULL; |
291 | printk(KERN_INFO "cx18-alsa: module unload complete\n"); | 290 | printk(KERN_INFO "cx18-alsa: module unload complete\n"); |
diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c index d0fbfcf7133d..e5e7fa9e737b 100644 --- a/drivers/media/video/ivtv/ivtvfb.c +++ b/drivers/media/video/ivtv/ivtvfb.c | |||
@@ -1293,7 +1293,6 @@ static int __init ivtvfb_init(void) | |||
1293 | 1293 | ||
1294 | drv = driver_find("ivtv", &pci_bus_type); | 1294 | drv = driver_find("ivtv", &pci_bus_type); |
1295 | err = driver_for_each_device(drv, NULL, ®istered, ivtvfb_callback_init); | 1295 | err = driver_for_each_device(drv, NULL, ®istered, ivtvfb_callback_init); |
1296 | put_driver(drv); | ||
1297 | if (!registered) { | 1296 | if (!registered) { |
1298 | printk(KERN_ERR "ivtvfb: no cards found\n"); | 1297 | printk(KERN_ERR "ivtvfb: no cards found\n"); |
1299 | return -ENODEV; | 1298 | return -ENODEV; |
@@ -1310,7 +1309,6 @@ static void ivtvfb_cleanup(void) | |||
1310 | 1309 | ||
1311 | drv = driver_find("ivtv", &pci_bus_type); | 1310 | drv = driver_find("ivtv", &pci_bus_type); |
1312 | err = driver_for_each_device(drv, NULL, NULL, ivtvfb_callback_cleanup); | 1311 | err = driver_for_each_device(drv, NULL, NULL, ivtvfb_callback_cleanup); |
1313 | put_driver(drv); | ||
1314 | } | 1312 | } |
1315 | 1313 | ||
1316 | module_init(ivtvfb_init); | 1314 | module_init(ivtvfb_init); |
diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.c b/drivers/media/video/s5p-fimc/fimc-mdevice.c index 8ea4ee116e46..63eccb55728f 100644 --- a/drivers/media/video/s5p-fimc/fimc-mdevice.c +++ b/drivers/media/video/s5p-fimc/fimc-mdevice.c | |||
@@ -344,16 +344,13 @@ static int fimc_md_register_platform_entities(struct fimc_md *fmd) | |||
344 | return -ENODEV; | 344 | return -ENODEV; |
345 | ret = driver_for_each_device(driver, NULL, fmd, | 345 | ret = driver_for_each_device(driver, NULL, fmd, |
346 | fimc_register_callback); | 346 | fimc_register_callback); |
347 | put_driver(driver); | ||
348 | if (ret) | 347 | if (ret) |
349 | return ret; | 348 | return ret; |
350 | 349 | ||
351 | driver = driver_find(CSIS_DRIVER_NAME, &platform_bus_type); | 350 | driver = driver_find(CSIS_DRIVER_NAME, &platform_bus_type); |
352 | if (driver) { | 351 | if (driver) |
353 | ret = driver_for_each_device(driver, NULL, fmd, | 352 | ret = driver_for_each_device(driver, NULL, fmd, |
354 | csis_register_callback); | 353 | csis_register_callback); |
355 | put_driver(driver); | ||
356 | } | ||
357 | return ret; | 354 | return ret; |
358 | } | 355 | } |
359 | 356 | ||
diff --git a/drivers/media/video/s5p-tv/mixer_video.c b/drivers/media/video/s5p-tv/mixer_video.c index 7884baeff76a..f7ca5cc143c6 100644 --- a/drivers/media/video/s5p-tv/mixer_video.c +++ b/drivers/media/video/s5p-tv/mixer_video.c | |||
@@ -58,7 +58,6 @@ static struct v4l2_subdev *find_and_register_subdev( | |||
58 | } | 58 | } |
59 | 59 | ||
60 | done: | 60 | done: |
61 | put_driver(drv); | ||
62 | return sd; | 61 | return sd; |
63 | } | 62 | } |
64 | 63 | ||
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index f320f466f03b..e8c42d6a7d1c 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c | |||
@@ -915,9 +915,7 @@ static int phy_probe(struct device *dev) | |||
915 | 915 | ||
916 | phydev = to_phy_device(dev); | 916 | phydev = to_phy_device(dev); |
917 | 917 | ||
918 | /* Make sure the driver is held. | 918 | drv = phydev->dev.driver; |
919 | * XXX -- Is this correct? */ | ||
920 | drv = get_driver(phydev->dev.driver); | ||
921 | phydrv = to_phy_driver(drv); | 919 | phydrv = to_phy_driver(drv); |
922 | phydev->drv = phydrv; | 920 | phydev->drv = phydrv; |
923 | 921 | ||
@@ -957,8 +955,6 @@ static int phy_remove(struct device *dev) | |||
957 | 955 | ||
958 | if (phydev->drv->remove) | 956 | if (phydev->drv->remove) |
959 | phydev->drv->remove(phydev); | 957 | phydev->drv->remove(phydev); |
960 | |||
961 | put_driver(dev->driver); | ||
962 | phydev->drv = NULL; | 958 | phydev->drv = NULL; |
963 | 959 | ||
964 | return 0; | 960 | return 0; |
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 3623d65f8b86..8d9616b821ca 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -72,9 +72,7 @@ int pci_add_dynid(struct pci_driver *drv, | |||
72 | list_add_tail(&dynid->node, &drv->dynids.list); | 72 | list_add_tail(&dynid->node, &drv->dynids.list); |
73 | spin_unlock(&drv->dynids.lock); | 73 | spin_unlock(&drv->dynids.lock); |
74 | 74 | ||
75 | get_driver(&drv->driver); | ||
76 | retval = driver_attach(&drv->driver); | 75 | retval = driver_attach(&drv->driver); |
77 | put_driver(&drv->driver); | ||
78 | 76 | ||
79 | return retval; | 77 | return retval; |
80 | } | 78 | } |
@@ -190,43 +188,34 @@ store_remove_id(struct device_driver *driver, const char *buf, size_t count) | |||
190 | static DRIVER_ATTR(remove_id, S_IWUSR, NULL, store_remove_id); | 188 | static DRIVER_ATTR(remove_id, S_IWUSR, NULL, store_remove_id); |
191 | 189 | ||
192 | static int | 190 | static int |
193 | pci_create_newid_file(struct pci_driver *drv) | 191 | pci_create_newid_files(struct pci_driver *drv) |
194 | { | 192 | { |
195 | int error = 0; | 193 | int error = 0; |
196 | if (drv->probe != NULL) | ||
197 | error = driver_create_file(&drv->driver, &driver_attr_new_id); | ||
198 | return error; | ||
199 | } | ||
200 | |||
201 | static void pci_remove_newid_file(struct pci_driver *drv) | ||
202 | { | ||
203 | driver_remove_file(&drv->driver, &driver_attr_new_id); | ||
204 | } | ||
205 | 194 | ||
206 | static int | 195 | if (drv->probe != NULL) { |
207 | pci_create_removeid_file(struct pci_driver *drv) | 196 | error = driver_create_file(&drv->driver, &driver_attr_new_id); |
208 | { | 197 | if (error == 0) { |
209 | int error = 0; | 198 | error = driver_create_file(&drv->driver, |
210 | if (drv->probe != NULL) | 199 | &driver_attr_remove_id); |
211 | error = driver_create_file(&drv->driver,&driver_attr_remove_id); | 200 | if (error) |
201 | driver_remove_file(&drv->driver, | ||
202 | &driver_attr_new_id); | ||
203 | } | ||
204 | } | ||
212 | return error; | 205 | return error; |
213 | } | 206 | } |
214 | 207 | ||
215 | static void pci_remove_removeid_file(struct pci_driver *drv) | 208 | static void pci_remove_newid_files(struct pci_driver *drv) |
216 | { | 209 | { |
217 | driver_remove_file(&drv->driver, &driver_attr_remove_id); | 210 | driver_remove_file(&drv->driver, &driver_attr_remove_id); |
211 | driver_remove_file(&drv->driver, &driver_attr_new_id); | ||
218 | } | 212 | } |
219 | #else /* !CONFIG_HOTPLUG */ | 213 | #else /* !CONFIG_HOTPLUG */ |
220 | static inline int pci_create_newid_file(struct pci_driver *drv) | 214 | static inline int pci_create_newid_files(struct pci_driver *drv) |
221 | { | 215 | { |
222 | return 0; | 216 | return 0; |
223 | } | 217 | } |
224 | static inline void pci_remove_newid_file(struct pci_driver *drv) {} | 218 | static inline void pci_remove_newid_files(struct pci_driver *drv) {} |
225 | static inline int pci_create_removeid_file(struct pci_driver *drv) | ||
226 | { | ||
227 | return 0; | ||
228 | } | ||
229 | static inline void pci_remove_removeid_file(struct pci_driver *drv) {} | ||
230 | #endif | 219 | #endif |
231 | 220 | ||
232 | /** | 221 | /** |
@@ -1138,18 +1127,12 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner, | |||
1138 | if (error) | 1127 | if (error) |
1139 | goto out; | 1128 | goto out; |
1140 | 1129 | ||
1141 | error = pci_create_newid_file(drv); | 1130 | error = pci_create_newid_files(drv); |
1142 | if (error) | 1131 | if (error) |
1143 | goto out_newid; | 1132 | goto out_newid; |
1144 | |||
1145 | error = pci_create_removeid_file(drv); | ||
1146 | if (error) | ||
1147 | goto out_removeid; | ||
1148 | out: | 1133 | out: |
1149 | return error; | 1134 | return error; |
1150 | 1135 | ||
1151 | out_removeid: | ||
1152 | pci_remove_newid_file(drv); | ||
1153 | out_newid: | 1136 | out_newid: |
1154 | driver_unregister(&drv->driver); | 1137 | driver_unregister(&drv->driver); |
1155 | goto out; | 1138 | goto out; |
@@ -1168,8 +1151,7 @@ out_newid: | |||
1168 | void | 1151 | void |
1169 | pci_unregister_driver(struct pci_driver *drv) | 1152 | pci_unregister_driver(struct pci_driver *drv) |
1170 | { | 1153 | { |
1171 | pci_remove_removeid_file(drv); | 1154 | pci_remove_newid_files(drv); |
1172 | pci_remove_newid_file(drv); | ||
1173 | driver_unregister(&drv->driver); | 1155 | driver_unregister(&drv->driver); |
1174 | pci_free_dynids(drv); | 1156 | pci_free_dynids(drv); |
1175 | } | 1157 | } |
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c index 1620088a0e7e..401090110922 100644 --- a/drivers/pci/xen-pcifront.c +++ b/drivers/pci/xen-pcifront.c | |||
@@ -593,7 +593,7 @@ static pci_ers_result_t pcifront_common_process(int cmd, | |||
593 | } | 593 | } |
594 | pdrv = pcidev->driver; | 594 | pdrv = pcidev->driver; |
595 | 595 | ||
596 | if (get_driver(&pdrv->driver)) { | 596 | if (pdrv) { |
597 | if (pdrv->err_handler && pdrv->err_handler->error_detected) { | 597 | if (pdrv->err_handler && pdrv->err_handler->error_detected) { |
598 | dev_dbg(&pcidev->dev, | 598 | dev_dbg(&pcidev->dev, |
599 | "trying to call AER service\n"); | 599 | "trying to call AER service\n"); |
@@ -623,7 +623,6 @@ static pci_ers_result_t pcifront_common_process(int cmd, | |||
623 | } | 623 | } |
624 | } | 624 | } |
625 | } | 625 | } |
626 | put_driver(&pdrv->driver); | ||
627 | } | 626 | } |
628 | if (!flag) | 627 | if (!flag) |
629 | result = PCI_ERS_RESULT_NONE; | 628 | result = PCI_ERS_RESULT_NONE; |
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 1932029de48d..079629bff957 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -127,10 +127,7 @@ pcmcia_store_new_id(struct device_driver *driver, const char *buf, size_t count) | |||
127 | list_add_tail(&dynid->node, &pdrv->dynids.list); | 127 | list_add_tail(&dynid->node, &pdrv->dynids.list); |
128 | mutex_unlock(&pdrv->dynids.lock); | 128 | mutex_unlock(&pdrv->dynids.lock); |
129 | 129 | ||
130 | if (get_driver(&pdrv->drv)) { | 130 | retval = driver_attach(&pdrv->drv); |
131 | retval = driver_attach(&pdrv->drv); | ||
132 | put_driver(&pdrv->drv); | ||
133 | } | ||
134 | 131 | ||
135 | if (retval) | 132 | if (retval) |
136 | return retval; | 133 | return retval; |
@@ -160,6 +157,11 @@ pcmcia_create_newid_file(struct pcmcia_driver *drv) | |||
160 | return error; | 157 | return error; |
161 | } | 158 | } |
162 | 159 | ||
160 | static void | ||
161 | pcmcia_remove_newid_file(struct pcmcia_driver *drv) | ||
162 | { | ||
163 | driver_remove_file(&drv->drv, &driver_attr_new_id); | ||
164 | } | ||
163 | 165 | ||
164 | /** | 166 | /** |
165 | * pcmcia_register_driver - register a PCMCIA driver with the bus core | 167 | * pcmcia_register_driver - register a PCMCIA driver with the bus core |
@@ -204,6 +206,7 @@ EXPORT_SYMBOL(pcmcia_register_driver); | |||
204 | void pcmcia_unregister_driver(struct pcmcia_driver *driver) | 206 | void pcmcia_unregister_driver(struct pcmcia_driver *driver) |
205 | { | 207 | { |
206 | pr_debug("unregistering driver %s\n", driver->name); | 208 | pr_debug("unregistering driver %s\n", driver->name); |
209 | pcmcia_remove_newid_file(driver); | ||
207 | driver_unregister(&driver->drv); | 210 | driver_unregister(&driver->drv); |
208 | pcmcia_free_dynids(driver); | 211 | pcmcia_free_dynids(driver); |
209 | } | 212 | } |
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 3a8daf858742..459f66437fe9 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig | |||
@@ -76,6 +76,20 @@ config BATTERY_DS2780 | |||
76 | help | 76 | help |
77 | Say Y here to enable support for batteries with ds2780 chip. | 77 | Say Y here to enable support for batteries with ds2780 chip. |
78 | 78 | ||
79 | config BATTERY_DS2781 | ||
80 | tristate "2781 battery driver" | ||
81 | depends on HAS_IOMEM | ||
82 | select W1 | ||
83 | select W1_SLAVE_DS2781 | ||
84 | help | ||
85 | If you enable this you will have the DS2781 battery driver support. | ||
86 | |||
87 | The battery monitor chip is used in many batteries/devices | ||
88 | as the one who is responsible for charging/discharging/monitoring | ||
89 | Li+ batteries. | ||
90 | |||
91 | If you are unsure, say N. | ||
92 | |||
79 | config BATTERY_DS2782 | 93 | config BATTERY_DS2782 |
80 | tristate "DS2782/DS2786 standalone gas-gauge" | 94 | tristate "DS2782/DS2786 standalone gas-gauge" |
81 | depends on I2C | 95 | depends on I2C |
diff --git a/drivers/power/Makefile b/drivers/power/Makefile index e429008eaf10..c590fa533406 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile | |||
@@ -16,6 +16,7 @@ obj-$(CONFIG_TEST_POWER) += test_power.o | |||
16 | 16 | ||
17 | obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o | 17 | obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o |
18 | obj-$(CONFIG_BATTERY_DS2780) += ds2780_battery.o | 18 | obj-$(CONFIG_BATTERY_DS2780) += ds2780_battery.o |
19 | obj-$(CONFIG_BATTERY_DS2781) += ds2781_battery.o | ||
19 | obj-$(CONFIG_BATTERY_DS2782) += ds2782_battery.o | 20 | obj-$(CONFIG_BATTERY_DS2782) += ds2782_battery.o |
20 | obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o | 21 | obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o |
21 | obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o | 22 | obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o |
diff --git a/drivers/power/ds2781_battery.c b/drivers/power/ds2781_battery.c new file mode 100644 index 000000000000..ca0d653d0a7a --- /dev/null +++ b/drivers/power/ds2781_battery.c | |||
@@ -0,0 +1,874 @@ | |||
1 | /* | ||
2 | * 1-wire client/driver for the Maxim/Dallas DS2781 Stand-Alone Fuel Gauge IC | ||
3 | * | ||
4 | * Author: Renata Sayakhova <renata@oktetlabs.ru> | ||
5 | * | ||
6 | * Based on ds2780_battery drivers | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/param.h> | ||
17 | #include <linux/pm.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/power_supply.h> | ||
20 | #include <linux/idr.h> | ||
21 | |||
22 | #include "../w1/w1.h" | ||
23 | #include "../w1/slaves/w1_ds2781.h" | ||
24 | |||
25 | /* Current unit measurement in uA for a 1 milli-ohm sense resistor */ | ||
26 | #define DS2781_CURRENT_UNITS 1563 | ||
27 | /* Charge unit measurement in uAh for a 1 milli-ohm sense resistor */ | ||
28 | #define DS2781_CHARGE_UNITS 6250 | ||
29 | /* Number of bytes in user EEPROM space */ | ||
30 | #define DS2781_USER_EEPROM_SIZE (DS2781_EEPROM_BLOCK0_END - \ | ||
31 | DS2781_EEPROM_BLOCK0_START + 1) | ||
32 | /* Number of bytes in parameter EEPROM space */ | ||
33 | #define DS2781_PARAM_EEPROM_SIZE (DS2781_EEPROM_BLOCK1_END - \ | ||
34 | DS2781_EEPROM_BLOCK1_START + 1) | ||
35 | |||
36 | struct ds2781_device_info { | ||
37 | struct device *dev; | ||
38 | struct power_supply bat; | ||
39 | struct device *w1_dev; | ||
40 | struct task_struct *mutex_holder; | ||
41 | }; | ||
42 | |||
43 | enum current_types { | ||
44 | CURRENT_NOW, | ||
45 | CURRENT_AVG, | ||
46 | }; | ||
47 | |||
48 | static const char model[] = "DS2781"; | ||
49 | static const char manufacturer[] = "Maxim/Dallas"; | ||
50 | |||
51 | static inline struct ds2781_device_info * | ||
52 | to_ds2781_device_info(struct power_supply *psy) | ||
53 | { | ||
54 | return container_of(psy, struct ds2781_device_info, bat); | ||
55 | } | ||
56 | |||
57 | static inline struct power_supply *to_power_supply(struct device *dev) | ||
58 | { | ||
59 | return dev_get_drvdata(dev); | ||
60 | } | ||
61 | |||
62 | static inline int ds2781_battery_io(struct ds2781_device_info *dev_info, | ||
63 | char *buf, int addr, size_t count, int io) | ||
64 | { | ||
65 | if (dev_info->mutex_holder == current) | ||
66 | return w1_ds2781_io_nolock(dev_info->w1_dev, buf, addr, | ||
67 | count, io); | ||
68 | else | ||
69 | return w1_ds2781_io(dev_info->w1_dev, buf, addr, count, io); | ||
70 | } | ||
71 | |||
72 | int w1_ds2781_read(struct ds2781_device_info *dev_info, char *buf, | ||
73 | int addr, size_t count) | ||
74 | { | ||
75 | return ds2781_battery_io(dev_info, buf, addr, count, 0); | ||
76 | } | ||
77 | |||
78 | static inline int ds2781_read8(struct ds2781_device_info *dev_info, u8 *val, | ||
79 | int addr) | ||
80 | { | ||
81 | return ds2781_battery_io(dev_info, val, addr, sizeof(u8), 0); | ||
82 | } | ||
83 | |||
84 | static int ds2781_read16(struct ds2781_device_info *dev_info, s16 *val, | ||
85 | int addr) | ||
86 | { | ||
87 | int ret; | ||
88 | u8 raw[2]; | ||
89 | |||
90 | ret = ds2781_battery_io(dev_info, raw, addr, sizeof(raw), 0); | ||
91 | if (ret < 0) | ||
92 | return ret; | ||
93 | |||
94 | *val = (raw[0] << 8) | raw[1]; | ||
95 | |||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | static inline int ds2781_read_block(struct ds2781_device_info *dev_info, | ||
100 | u8 *val, int addr, size_t count) | ||
101 | { | ||
102 | return ds2781_battery_io(dev_info, val, addr, count, 0); | ||
103 | } | ||
104 | |||
105 | static inline int ds2781_write(struct ds2781_device_info *dev_info, u8 *val, | ||
106 | int addr, size_t count) | ||
107 | { | ||
108 | return ds2781_battery_io(dev_info, val, addr, count, 1); | ||
109 | } | ||
110 | |||
111 | static inline int ds2781_store_eeprom(struct device *dev, int addr) | ||
112 | { | ||
113 | return w1_ds2781_eeprom_cmd(dev, addr, W1_DS2781_COPY_DATA); | ||
114 | } | ||
115 | |||
116 | static inline int ds2781_recall_eeprom(struct device *dev, int addr) | ||
117 | { | ||
118 | return w1_ds2781_eeprom_cmd(dev, addr, W1_DS2781_RECALL_DATA); | ||
119 | } | ||
120 | |||
121 | static int ds2781_save_eeprom(struct ds2781_device_info *dev_info, int reg) | ||
122 | { | ||
123 | int ret; | ||
124 | |||
125 | ret = ds2781_store_eeprom(dev_info->w1_dev, reg); | ||
126 | if (ret < 0) | ||
127 | return ret; | ||
128 | |||
129 | ret = ds2781_recall_eeprom(dev_info->w1_dev, reg); | ||
130 | if (ret < 0) | ||
131 | return ret; | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | /* Set sense resistor value in mhos */ | ||
137 | static int ds2781_set_sense_register(struct ds2781_device_info *dev_info, | ||
138 | u8 conductance) | ||
139 | { | ||
140 | int ret; | ||
141 | |||
142 | ret = ds2781_write(dev_info, &conductance, | ||
143 | DS2781_RSNSP, sizeof(u8)); | ||
144 | if (ret < 0) | ||
145 | return ret; | ||
146 | |||
147 | return ds2781_save_eeprom(dev_info, DS2781_RSNSP); | ||
148 | } | ||
149 | |||
150 | /* Get RSGAIN value from 0 to 1.999 in steps of 0.001 */ | ||
151 | static int ds2781_get_rsgain_register(struct ds2781_device_info *dev_info, | ||
152 | u16 *rsgain) | ||
153 | { | ||
154 | return ds2781_read16(dev_info, rsgain, DS2781_RSGAIN_MSB); | ||
155 | } | ||
156 | |||
157 | /* Set RSGAIN value from 0 to 1.999 in steps of 0.001 */ | ||
158 | static int ds2781_set_rsgain_register(struct ds2781_device_info *dev_info, | ||
159 | u16 rsgain) | ||
160 | { | ||
161 | int ret; | ||
162 | u8 raw[] = {rsgain >> 8, rsgain & 0xFF}; | ||
163 | |||
164 | ret = ds2781_write(dev_info, raw, | ||
165 | DS2781_RSGAIN_MSB, sizeof(raw)); | ||
166 | if (ret < 0) | ||
167 | return ret; | ||
168 | |||
169 | return ds2781_save_eeprom(dev_info, DS2781_RSGAIN_MSB); | ||
170 | } | ||
171 | |||
172 | static int ds2781_get_voltage(struct ds2781_device_info *dev_info, | ||
173 | int *voltage_uV) | ||
174 | { | ||
175 | int ret; | ||
176 | char val[2]; | ||
177 | int voltage_raw; | ||
178 | |||
179 | ret = w1_ds2781_read(dev_info, val, DS2781_VOLT_MSB, 2 * sizeof(u8)); | ||
180 | if (ret < 0) | ||
181 | return ret; | ||
182 | /* | ||
183 | * The voltage value is located in 10 bits across the voltage MSB | ||
184 | * and LSB registers in two's compliment form | ||
185 | * Sign bit of the voltage value is in bit 7 of the voltage MSB register | ||
186 | * Bits 9 - 3 of the voltage value are in bits 6 - 0 of the | ||
187 | * voltage MSB register | ||
188 | * Bits 2 - 0 of the voltage value are in bits 7 - 5 of the | ||
189 | * voltage LSB register | ||
190 | */ | ||
191 | voltage_raw = (val[0] << 3) | | ||
192 | (val[1] >> 5); | ||
193 | |||
194 | /* DS2781 reports voltage in units of 9.76mV, but the battery class | ||
195 | * reports in units of uV, so convert by multiplying by 9760. */ | ||
196 | *voltage_uV = voltage_raw * 9760; | ||
197 | |||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | static int ds2781_get_temperature(struct ds2781_device_info *dev_info, | ||
202 | int *temp) | ||
203 | { | ||
204 | int ret; | ||
205 | char val[2]; | ||
206 | int temp_raw; | ||
207 | |||
208 | ret = w1_ds2781_read(dev_info, val, DS2781_TEMP_MSB, 2 * sizeof(u8)); | ||
209 | if (ret < 0) | ||
210 | return ret; | ||
211 | /* | ||
212 | * The temperature value is located in 10 bits across the temperature | ||
213 | * MSB and LSB registers in two's compliment form | ||
214 | * Sign bit of the temperature value is in bit 7 of the temperature | ||
215 | * MSB register | ||
216 | * Bits 9 - 3 of the temperature value are in bits 6 - 0 of the | ||
217 | * temperature MSB register | ||
218 | * Bits 2 - 0 of the temperature value are in bits 7 - 5 of the | ||
219 | * temperature LSB register | ||
220 | */ | ||
221 | temp_raw = ((val[0]) << 3) | | ||
222 | (val[1] >> 5); | ||
223 | *temp = temp_raw + (temp_raw / 4); | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | static int ds2781_get_current(struct ds2781_device_info *dev_info, | ||
229 | enum current_types type, int *current_uA) | ||
230 | { | ||
231 | int ret, sense_res; | ||
232 | s16 current_raw; | ||
233 | u8 sense_res_raw, reg_msb; | ||
234 | |||
235 | /* | ||
236 | * The units of measurement for current are dependent on the value of | ||
237 | * the sense resistor. | ||
238 | */ | ||
239 | ret = ds2781_read8(dev_info, &sense_res_raw, DS2781_RSNSP); | ||
240 | if (ret < 0) | ||
241 | return ret; | ||
242 | |||
243 | if (sense_res_raw == 0) { | ||
244 | dev_err(dev_info->dev, "sense resistor value is 0\n"); | ||
245 | return -EINVAL; | ||
246 | } | ||
247 | sense_res = 1000 / sense_res_raw; | ||
248 | |||
249 | if (type == CURRENT_NOW) | ||
250 | reg_msb = DS2781_CURRENT_MSB; | ||
251 | else if (type == CURRENT_AVG) | ||
252 | reg_msb = DS2781_IAVG_MSB; | ||
253 | else | ||
254 | return -EINVAL; | ||
255 | |||
256 | /* | ||
257 | * The current value is located in 16 bits across the current MSB | ||
258 | * and LSB registers in two's compliment form | ||
259 | * Sign bit of the current value is in bit 7 of the current MSB register | ||
260 | * Bits 14 - 8 of the current value are in bits 6 - 0 of the current | ||
261 | * MSB register | ||
262 | * Bits 7 - 0 of the current value are in bits 7 - 0 of the current | ||
263 | * LSB register | ||
264 | */ | ||
265 | ret = ds2781_read16(dev_info, ¤t_raw, reg_msb); | ||
266 | if (ret < 0) | ||
267 | return ret; | ||
268 | |||
269 | *current_uA = current_raw * (DS2781_CURRENT_UNITS / sense_res); | ||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static int ds2781_get_accumulated_current(struct ds2781_device_info *dev_info, | ||
274 | int *accumulated_current) | ||
275 | { | ||
276 | int ret, sense_res; | ||
277 | s16 current_raw; | ||
278 | u8 sense_res_raw; | ||
279 | |||
280 | /* | ||
281 | * The units of measurement for accumulated current are dependent on | ||
282 | * the value of the sense resistor. | ||
283 | */ | ||
284 | ret = ds2781_read8(dev_info, &sense_res_raw, DS2781_RSNSP); | ||
285 | if (ret < 0) | ||
286 | return ret; | ||
287 | |||
288 | if (sense_res_raw == 0) { | ||
289 | dev_err(dev_info->dev, "sense resistor value is 0\n"); | ||
290 | return -EINVAL; | ||
291 | } | ||
292 | sense_res = 1000 / sense_res_raw; | ||
293 | |||
294 | /* | ||
295 | * The ACR value is located in 16 bits across the ACR MSB and | ||
296 | * LSB registers | ||
297 | * Bits 15 - 8 of the ACR value are in bits 7 - 0 of the ACR | ||
298 | * MSB register | ||
299 | * Bits 7 - 0 of the ACR value are in bits 7 - 0 of the ACR | ||
300 | * LSB register | ||
301 | */ | ||
302 | ret = ds2781_read16(dev_info, ¤t_raw, DS2781_ACR_MSB); | ||
303 | if (ret < 0) | ||
304 | return ret; | ||
305 | |||
306 | *accumulated_current = current_raw * (DS2781_CHARGE_UNITS / sense_res); | ||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | static int ds2781_get_capacity(struct ds2781_device_info *dev_info, | ||
311 | int *capacity) | ||
312 | { | ||
313 | int ret; | ||
314 | u8 raw; | ||
315 | |||
316 | ret = ds2781_read8(dev_info, &raw, DS2781_RARC); | ||
317 | if (ret < 0) | ||
318 | return ret; | ||
319 | |||
320 | *capacity = raw; | ||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | static int ds2781_get_status(struct ds2781_device_info *dev_info, int *status) | ||
325 | { | ||
326 | int ret, current_uA, capacity; | ||
327 | |||
328 | ret = ds2781_get_current(dev_info, CURRENT_NOW, ¤t_uA); | ||
329 | if (ret < 0) | ||
330 | return ret; | ||
331 | |||
332 | ret = ds2781_get_capacity(dev_info, &capacity); | ||
333 | if (ret < 0) | ||
334 | return ret; | ||
335 | |||
336 | if (power_supply_am_i_supplied(&dev_info->bat)) { | ||
337 | if (capacity == 100) | ||
338 | *status = POWER_SUPPLY_STATUS_FULL; | ||
339 | else if (current_uA > 50000) | ||
340 | *status = POWER_SUPPLY_STATUS_CHARGING; | ||
341 | else | ||
342 | *status = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
343 | } else { | ||
344 | *status = POWER_SUPPLY_STATUS_DISCHARGING; | ||
345 | } | ||
346 | return 0; | ||
347 | } | ||
348 | |||
349 | static int ds2781_get_charge_now(struct ds2781_device_info *dev_info, | ||
350 | int *charge_now) | ||
351 | { | ||
352 | int ret; | ||
353 | u16 charge_raw; | ||
354 | |||
355 | /* | ||
356 | * The RAAC value is located in 16 bits across the RAAC MSB and | ||
357 | * LSB registers | ||
358 | * Bits 15 - 8 of the RAAC value are in bits 7 - 0 of the RAAC | ||
359 | * MSB register | ||
360 | * Bits 7 - 0 of the RAAC value are in bits 7 - 0 of the RAAC | ||
361 | * LSB register | ||
362 | */ | ||
363 | ret = ds2781_read16(dev_info, &charge_raw, DS2781_RAAC_MSB); | ||
364 | if (ret < 0) | ||
365 | return ret; | ||
366 | |||
367 | *charge_now = charge_raw * 1600; | ||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static int ds2781_get_control_register(struct ds2781_device_info *dev_info, | ||
372 | u8 *control_reg) | ||
373 | { | ||
374 | return ds2781_read8(dev_info, control_reg, DS2781_CONTROL); | ||
375 | } | ||
376 | |||
377 | static int ds2781_set_control_register(struct ds2781_device_info *dev_info, | ||
378 | u8 control_reg) | ||
379 | { | ||
380 | int ret; | ||
381 | |||
382 | ret = ds2781_write(dev_info, &control_reg, | ||
383 | DS2781_CONTROL, sizeof(u8)); | ||
384 | if (ret < 0) | ||
385 | return ret; | ||
386 | |||
387 | return ds2781_save_eeprom(dev_info, DS2781_CONTROL); | ||
388 | } | ||
389 | |||
390 | static int ds2781_battery_get_property(struct power_supply *psy, | ||
391 | enum power_supply_property psp, | ||
392 | union power_supply_propval *val) | ||
393 | { | ||
394 | int ret = 0; | ||
395 | struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); | ||
396 | |||
397 | switch (psp) { | ||
398 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
399 | ret = ds2781_get_voltage(dev_info, &val->intval); | ||
400 | break; | ||
401 | |||
402 | case POWER_SUPPLY_PROP_TEMP: | ||
403 | ret = ds2781_get_temperature(dev_info, &val->intval); | ||
404 | break; | ||
405 | |||
406 | case POWER_SUPPLY_PROP_MODEL_NAME: | ||
407 | val->strval = model; | ||
408 | break; | ||
409 | |||
410 | case POWER_SUPPLY_PROP_MANUFACTURER: | ||
411 | val->strval = manufacturer; | ||
412 | break; | ||
413 | |||
414 | case POWER_SUPPLY_PROP_CURRENT_NOW: | ||
415 | ret = ds2781_get_current(dev_info, CURRENT_NOW, &val->intval); | ||
416 | break; | ||
417 | |||
418 | case POWER_SUPPLY_PROP_CURRENT_AVG: | ||
419 | ret = ds2781_get_current(dev_info, CURRENT_AVG, &val->intval); | ||
420 | break; | ||
421 | |||
422 | case POWER_SUPPLY_PROP_STATUS: | ||
423 | ret = ds2781_get_status(dev_info, &val->intval); | ||
424 | break; | ||
425 | |||
426 | case POWER_SUPPLY_PROP_CAPACITY: | ||
427 | ret = ds2781_get_capacity(dev_info, &val->intval); | ||
428 | break; | ||
429 | |||
430 | case POWER_SUPPLY_PROP_CHARGE_COUNTER: | ||
431 | ret = ds2781_get_accumulated_current(dev_info, &val->intval); | ||
432 | break; | ||
433 | |||
434 | case POWER_SUPPLY_PROP_CHARGE_NOW: | ||
435 | ret = ds2781_get_charge_now(dev_info, &val->intval); | ||
436 | break; | ||
437 | |||
438 | default: | ||
439 | ret = -EINVAL; | ||
440 | } | ||
441 | |||
442 | return ret; | ||
443 | } | ||
444 | |||
445 | static enum power_supply_property ds2781_battery_props[] = { | ||
446 | POWER_SUPPLY_PROP_STATUS, | ||
447 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
448 | POWER_SUPPLY_PROP_TEMP, | ||
449 | POWER_SUPPLY_PROP_MODEL_NAME, | ||
450 | POWER_SUPPLY_PROP_MANUFACTURER, | ||
451 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
452 | POWER_SUPPLY_PROP_CURRENT_AVG, | ||
453 | POWER_SUPPLY_PROP_CAPACITY, | ||
454 | POWER_SUPPLY_PROP_CHARGE_COUNTER, | ||
455 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
456 | }; | ||
457 | |||
458 | static ssize_t ds2781_get_pmod_enabled(struct device *dev, | ||
459 | struct device_attribute *attr, | ||
460 | char *buf) | ||
461 | { | ||
462 | int ret; | ||
463 | u8 control_reg; | ||
464 | struct power_supply *psy = to_power_supply(dev); | ||
465 | struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); | ||
466 | |||
467 | /* Get power mode */ | ||
468 | ret = ds2781_get_control_register(dev_info, &control_reg); | ||
469 | if (ret < 0) | ||
470 | return ret; | ||
471 | |||
472 | return sprintf(buf, "%d\n", | ||
473 | !!(control_reg & DS2781_CONTROL_PMOD)); | ||
474 | } | ||
475 | |||
476 | static ssize_t ds2781_set_pmod_enabled(struct device *dev, | ||
477 | struct device_attribute *attr, | ||
478 | const char *buf, | ||
479 | size_t count) | ||
480 | { | ||
481 | int ret; | ||
482 | u8 control_reg, new_setting; | ||
483 | struct power_supply *psy = to_power_supply(dev); | ||
484 | struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); | ||
485 | |||
486 | /* Set power mode */ | ||
487 | ret = ds2781_get_control_register(dev_info, &control_reg); | ||
488 | if (ret < 0) | ||
489 | return ret; | ||
490 | |||
491 | ret = kstrtou8(buf, 0, &new_setting); | ||
492 | if (ret < 0) | ||
493 | return ret; | ||
494 | |||
495 | if ((new_setting != 0) && (new_setting != 1)) { | ||
496 | dev_err(dev_info->dev, "Invalid pmod setting (0 or 1)\n"); | ||
497 | return -EINVAL; | ||
498 | } | ||
499 | |||
500 | if (new_setting) | ||
501 | control_reg |= DS2781_CONTROL_PMOD; | ||
502 | else | ||
503 | control_reg &= ~DS2781_CONTROL_PMOD; | ||
504 | |||
505 | ret = ds2781_set_control_register(dev_info, control_reg); | ||
506 | if (ret < 0) | ||
507 | return ret; | ||
508 | |||
509 | return count; | ||
510 | } | ||
511 | |||
512 | static ssize_t ds2781_get_sense_resistor_value(struct device *dev, | ||
513 | struct device_attribute *attr, | ||
514 | char *buf) | ||
515 | { | ||
516 | int ret; | ||
517 | u8 sense_resistor; | ||
518 | struct power_supply *psy = to_power_supply(dev); | ||
519 | struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); | ||
520 | |||
521 | ret = ds2781_read8(dev_info, &sense_resistor, DS2781_RSNSP); | ||
522 | if (ret < 0) | ||
523 | return ret; | ||
524 | |||
525 | ret = sprintf(buf, "%d\n", sense_resistor); | ||
526 | return ret; | ||
527 | } | ||
528 | |||
529 | static ssize_t ds2781_set_sense_resistor_value(struct device *dev, | ||
530 | struct device_attribute *attr, | ||
531 | const char *buf, | ||
532 | size_t count) | ||
533 | { | ||
534 | int ret; | ||
535 | u8 new_setting; | ||
536 | struct power_supply *psy = to_power_supply(dev); | ||
537 | struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); | ||
538 | |||
539 | ret = kstrtou8(buf, 0, &new_setting); | ||
540 | if (ret < 0) | ||
541 | return ret; | ||
542 | |||
543 | ret = ds2781_set_sense_register(dev_info, new_setting); | ||
544 | if (ret < 0) | ||
545 | return ret; | ||
546 | |||
547 | return count; | ||
548 | } | ||
549 | |||
550 | static ssize_t ds2781_get_rsgain_setting(struct device *dev, | ||
551 | struct device_attribute *attr, | ||
552 | char *buf) | ||
553 | { | ||
554 | int ret; | ||
555 | u16 rsgain; | ||
556 | struct power_supply *psy = to_power_supply(dev); | ||
557 | struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); | ||
558 | |||
559 | ret = ds2781_get_rsgain_register(dev_info, &rsgain); | ||
560 | if (ret < 0) | ||
561 | return ret; | ||
562 | |||
563 | return sprintf(buf, "%d\n", rsgain); | ||
564 | } | ||
565 | |||
566 | static ssize_t ds2781_set_rsgain_setting(struct device *dev, | ||
567 | struct device_attribute *attr, | ||
568 | const char *buf, | ||
569 | size_t count) | ||
570 | { | ||
571 | int ret; | ||
572 | u16 new_setting; | ||
573 | struct power_supply *psy = to_power_supply(dev); | ||
574 | struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); | ||
575 | |||
576 | ret = kstrtou16(buf, 0, &new_setting); | ||
577 | if (ret < 0) | ||
578 | return ret; | ||
579 | |||
580 | /* Gain can only be from 0 to 1.999 in steps of .001 */ | ||
581 | if (new_setting > 1999) { | ||
582 | dev_err(dev_info->dev, "Invalid rsgain setting (0 - 1999)\n"); | ||
583 | return -EINVAL; | ||
584 | } | ||
585 | |||
586 | ret = ds2781_set_rsgain_register(dev_info, new_setting); | ||
587 | if (ret < 0) | ||
588 | return ret; | ||
589 | |||
590 | return count; | ||
591 | } | ||
592 | |||
593 | static ssize_t ds2781_get_pio_pin(struct device *dev, | ||
594 | struct device_attribute *attr, | ||
595 | char *buf) | ||
596 | { | ||
597 | int ret; | ||
598 | u8 sfr; | ||
599 | struct power_supply *psy = to_power_supply(dev); | ||
600 | struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); | ||
601 | |||
602 | ret = ds2781_read8(dev_info, &sfr, DS2781_SFR); | ||
603 | if (ret < 0) | ||
604 | return ret; | ||
605 | |||
606 | ret = sprintf(buf, "%d\n", sfr & DS2781_SFR_PIOSC); | ||
607 | return ret; | ||
608 | } | ||
609 | |||
610 | static ssize_t ds2781_set_pio_pin(struct device *dev, | ||
611 | struct device_attribute *attr, | ||
612 | const char *buf, | ||
613 | size_t count) | ||
614 | { | ||
615 | int ret; | ||
616 | u8 new_setting; | ||
617 | struct power_supply *psy = to_power_supply(dev); | ||
618 | struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); | ||
619 | |||
620 | ret = kstrtou8(buf, 0, &new_setting); | ||
621 | if (ret < 0) | ||
622 | return ret; | ||
623 | |||
624 | if ((new_setting != 0) && (new_setting != 1)) { | ||
625 | dev_err(dev_info->dev, "Invalid pio_pin setting (0 or 1)\n"); | ||
626 | return -EINVAL; | ||
627 | } | ||
628 | |||
629 | ret = ds2781_write(dev_info, &new_setting, | ||
630 | DS2781_SFR, sizeof(u8)); | ||
631 | if (ret < 0) | ||
632 | return ret; | ||
633 | |||
634 | return count; | ||
635 | } | ||
636 | |||
637 | static ssize_t ds2781_read_param_eeprom_bin(struct file *filp, | ||
638 | struct kobject *kobj, | ||
639 | struct bin_attribute *bin_attr, | ||
640 | char *buf, loff_t off, size_t count) | ||
641 | { | ||
642 | struct device *dev = container_of(kobj, struct device, kobj); | ||
643 | struct power_supply *psy = to_power_supply(dev); | ||
644 | struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); | ||
645 | |||
646 | count = min_t(loff_t, count, | ||
647 | DS2781_EEPROM_BLOCK1_END - | ||
648 | DS2781_EEPROM_BLOCK1_START + 1 - off); | ||
649 | |||
650 | return ds2781_read_block(dev_info, buf, | ||
651 | DS2781_EEPROM_BLOCK1_START + off, count); | ||
652 | } | ||
653 | |||
654 | static ssize_t ds2781_write_param_eeprom_bin(struct file *filp, | ||
655 | struct kobject *kobj, | ||
656 | struct bin_attribute *bin_attr, | ||
657 | char *buf, loff_t off, size_t count) | ||
658 | { | ||
659 | struct device *dev = container_of(kobj, struct device, kobj); | ||
660 | struct power_supply *psy = to_power_supply(dev); | ||
661 | struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); | ||
662 | int ret; | ||
663 | |||
664 | count = min_t(loff_t, count, | ||
665 | DS2781_EEPROM_BLOCK1_END - | ||
666 | DS2781_EEPROM_BLOCK1_START + 1 - off); | ||
667 | |||
668 | ret = ds2781_write(dev_info, buf, | ||
669 | DS2781_EEPROM_BLOCK1_START + off, count); | ||
670 | if (ret < 0) | ||
671 | return ret; | ||
672 | |||
673 | ret = ds2781_save_eeprom(dev_info, DS2781_EEPROM_BLOCK1_START); | ||
674 | if (ret < 0) | ||
675 | return ret; | ||
676 | |||
677 | return count; | ||
678 | } | ||
679 | |||
680 | static struct bin_attribute ds2781_param_eeprom_bin_attr = { | ||
681 | .attr = { | ||
682 | .name = "param_eeprom", | ||
683 | .mode = S_IRUGO | S_IWUSR, | ||
684 | }, | ||
685 | .size = DS2781_EEPROM_BLOCK1_END - DS2781_EEPROM_BLOCK1_START + 1, | ||
686 | .read = ds2781_read_param_eeprom_bin, | ||
687 | .write = ds2781_write_param_eeprom_bin, | ||
688 | }; | ||
689 | |||
690 | static ssize_t ds2781_read_user_eeprom_bin(struct file *filp, | ||
691 | struct kobject *kobj, | ||
692 | struct bin_attribute *bin_attr, | ||
693 | char *buf, loff_t off, size_t count) | ||
694 | { | ||
695 | struct device *dev = container_of(kobj, struct device, kobj); | ||
696 | struct power_supply *psy = to_power_supply(dev); | ||
697 | struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); | ||
698 | |||
699 | count = min_t(loff_t, count, | ||
700 | DS2781_EEPROM_BLOCK0_END - | ||
701 | DS2781_EEPROM_BLOCK0_START + 1 - off); | ||
702 | |||
703 | return ds2781_read_block(dev_info, buf, | ||
704 | DS2781_EEPROM_BLOCK0_START + off, count); | ||
705 | |||
706 | } | ||
707 | |||
708 | static ssize_t ds2781_write_user_eeprom_bin(struct file *filp, | ||
709 | struct kobject *kobj, | ||
710 | struct bin_attribute *bin_attr, | ||
711 | char *buf, loff_t off, size_t count) | ||
712 | { | ||
713 | struct device *dev = container_of(kobj, struct device, kobj); | ||
714 | struct power_supply *psy = to_power_supply(dev); | ||
715 | struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); | ||
716 | int ret; | ||
717 | |||
718 | count = min_t(loff_t, count, | ||
719 | DS2781_EEPROM_BLOCK0_END - | ||
720 | DS2781_EEPROM_BLOCK0_START + 1 - off); | ||
721 | |||
722 | ret = ds2781_write(dev_info, buf, | ||
723 | DS2781_EEPROM_BLOCK0_START + off, count); | ||
724 | if (ret < 0) | ||
725 | return ret; | ||
726 | |||
727 | ret = ds2781_save_eeprom(dev_info, DS2781_EEPROM_BLOCK0_START); | ||
728 | if (ret < 0) | ||
729 | return ret; | ||
730 | |||
731 | return count; | ||
732 | } | ||
733 | |||
734 | static struct bin_attribute ds2781_user_eeprom_bin_attr = { | ||
735 | .attr = { | ||
736 | .name = "user_eeprom", | ||
737 | .mode = S_IRUGO | S_IWUSR, | ||
738 | }, | ||
739 | .size = DS2781_EEPROM_BLOCK0_END - DS2781_EEPROM_BLOCK0_START + 1, | ||
740 | .read = ds2781_read_user_eeprom_bin, | ||
741 | .write = ds2781_write_user_eeprom_bin, | ||
742 | }; | ||
743 | |||
744 | static DEVICE_ATTR(pmod_enabled, S_IRUGO | S_IWUSR, ds2781_get_pmod_enabled, | ||
745 | ds2781_set_pmod_enabled); | ||
746 | static DEVICE_ATTR(sense_resistor_value, S_IRUGO | S_IWUSR, | ||
747 | ds2781_get_sense_resistor_value, ds2781_set_sense_resistor_value); | ||
748 | static DEVICE_ATTR(rsgain_setting, S_IRUGO | S_IWUSR, ds2781_get_rsgain_setting, | ||
749 | ds2781_set_rsgain_setting); | ||
750 | static DEVICE_ATTR(pio_pin, S_IRUGO | S_IWUSR, ds2781_get_pio_pin, | ||
751 | ds2781_set_pio_pin); | ||
752 | |||
753 | |||
754 | static struct attribute *ds2781_attributes[] = { | ||
755 | &dev_attr_pmod_enabled.attr, | ||
756 | &dev_attr_sense_resistor_value.attr, | ||
757 | &dev_attr_rsgain_setting.attr, | ||
758 | &dev_attr_pio_pin.attr, | ||
759 | NULL | ||
760 | }; | ||
761 | |||
762 | static const struct attribute_group ds2781_attr_group = { | ||
763 | .attrs = ds2781_attributes, | ||
764 | }; | ||
765 | |||
766 | static int __devinit ds2781_battery_probe(struct platform_device *pdev) | ||
767 | { | ||
768 | int ret = 0; | ||
769 | struct ds2781_device_info *dev_info; | ||
770 | |||
771 | dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL); | ||
772 | if (!dev_info) { | ||
773 | ret = -ENOMEM; | ||
774 | goto fail; | ||
775 | } | ||
776 | |||
777 | platform_set_drvdata(pdev, dev_info); | ||
778 | |||
779 | dev_info->dev = &pdev->dev; | ||
780 | dev_info->w1_dev = pdev->dev.parent; | ||
781 | dev_info->bat.name = dev_name(&pdev->dev); | ||
782 | dev_info->bat.type = POWER_SUPPLY_TYPE_BATTERY; | ||
783 | dev_info->bat.properties = ds2781_battery_props; | ||
784 | dev_info->bat.num_properties = ARRAY_SIZE(ds2781_battery_props); | ||
785 | dev_info->bat.get_property = ds2781_battery_get_property; | ||
786 | dev_info->mutex_holder = current; | ||
787 | |||
788 | ret = power_supply_register(&pdev->dev, &dev_info->bat); | ||
789 | if (ret) { | ||
790 | dev_err(dev_info->dev, "failed to register battery\n"); | ||
791 | goto fail_free_info; | ||
792 | } | ||
793 | |||
794 | ret = sysfs_create_group(&dev_info->bat.dev->kobj, &ds2781_attr_group); | ||
795 | if (ret) { | ||
796 | dev_err(dev_info->dev, "failed to create sysfs group\n"); | ||
797 | goto fail_unregister; | ||
798 | } | ||
799 | |||
800 | ret = sysfs_create_bin_file(&dev_info->bat.dev->kobj, | ||
801 | &ds2781_param_eeprom_bin_attr); | ||
802 | if (ret) { | ||
803 | dev_err(dev_info->dev, | ||
804 | "failed to create param eeprom bin file"); | ||
805 | goto fail_remove_group; | ||
806 | } | ||
807 | |||
808 | ret = sysfs_create_bin_file(&dev_info->bat.dev->kobj, | ||
809 | &ds2781_user_eeprom_bin_attr); | ||
810 | if (ret) { | ||
811 | dev_err(dev_info->dev, | ||
812 | "failed to create user eeprom bin file"); | ||
813 | goto fail_remove_bin_file; | ||
814 | } | ||
815 | |||
816 | dev_info->mutex_holder = NULL; | ||
817 | |||
818 | return 0; | ||
819 | |||
820 | fail_remove_bin_file: | ||
821 | sysfs_remove_bin_file(&dev_info->bat.dev->kobj, | ||
822 | &ds2781_param_eeprom_bin_attr); | ||
823 | fail_remove_group: | ||
824 | sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2781_attr_group); | ||
825 | fail_unregister: | ||
826 | power_supply_unregister(&dev_info->bat); | ||
827 | fail_free_info: | ||
828 | kfree(dev_info); | ||
829 | fail: | ||
830 | return ret; | ||
831 | } | ||
832 | |||
833 | static int __devexit ds2781_battery_remove(struct platform_device *pdev) | ||
834 | { | ||
835 | struct ds2781_device_info *dev_info = platform_get_drvdata(pdev); | ||
836 | |||
837 | dev_info->mutex_holder = current; | ||
838 | |||
839 | /* remove attributes */ | ||
840 | sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2781_attr_group); | ||
841 | |||
842 | power_supply_unregister(&dev_info->bat); | ||
843 | |||
844 | kfree(dev_info); | ||
845 | return 0; | ||
846 | } | ||
847 | |||
848 | static struct platform_driver ds2781_battery_driver = { | ||
849 | .driver = { | ||
850 | .name = "ds2781-battery", | ||
851 | }, | ||
852 | .probe = ds2781_battery_probe, | ||
853 | .remove = __devexit_p(ds2781_battery_remove), | ||
854 | }; | ||
855 | |||
856 | static int __init ds2781_battery_init(void) | ||
857 | { | ||
858 | return platform_driver_register(&ds2781_battery_driver); | ||
859 | } | ||
860 | |||
861 | static void __exit ds2781_battery_exit(void) | ||
862 | { | ||
863 | platform_driver_unregister(&ds2781_battery_driver); | ||
864 | } | ||
865 | |||
866 | module_init(ds2781_battery_init); | ||
867 | module_exit(ds2781_battery_exit); | ||
868 | |||
869 | |||
870 | MODULE_LICENSE("GPL"); | ||
871 | MODULE_AUTHOR("Renata Sayakhova <renata@oktetlabs.ru>"); | ||
872 | MODULE_DESCRIPTION("Maxim/Dallas DS2781 Stand-Alone Fuel Gauage IC driver"); | ||
873 | MODULE_ALIAS("platform:ds2781-battery"); | ||
874 | |||
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index e9a83f84adaf..fcde037b3461 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c | |||
@@ -1210,7 +1210,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id, | |||
1210 | { | 1210 | { |
1211 | struct regulator_dev *rdev; | 1211 | struct regulator_dev *rdev; |
1212 | struct regulator_map *map; | 1212 | struct regulator_map *map; |
1213 | struct regulator *regulator = ERR_PTR(-ENODEV); | 1213 | struct regulator *regulator = ERR_PTR(-EPROBE_DEFER); |
1214 | const char *devname = NULL; | 1214 | const char *devname = NULL; |
1215 | int ret; | 1215 | int ret; |
1216 | 1216 | ||
@@ -2834,7 +2834,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, | |||
2834 | 2834 | ||
2835 | if (!r) { | 2835 | if (!r) { |
2836 | dev_err(dev, "Failed to find supply %s\n", supply); | 2836 | dev_err(dev, "Failed to find supply %s\n", supply); |
2837 | ret = -ENODEV; | 2837 | ret = -EPROBE_DEFER; |
2838 | goto scrub; | 2838 | goto scrub; |
2839 | } | 2839 | } |
2840 | 2840 | ||
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 4f1989d27b1f..5f1dc6fb5708 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c | |||
@@ -580,7 +580,6 @@ void ccwgroup_driver_unregister(struct ccwgroup_driver *cdriver) | |||
580 | struct device *dev; | 580 | struct device *dev; |
581 | 581 | ||
582 | /* We don't want ccwgroup devices to live longer than their driver. */ | 582 | /* We don't want ccwgroup devices to live longer than their driver. */ |
583 | get_driver(&cdriver->driver); | ||
584 | while ((dev = driver_find_device(&cdriver->driver, NULL, NULL, | 583 | while ((dev = driver_find_device(&cdriver->driver, NULL, NULL, |
585 | __ccwgroup_match_all))) { | 584 | __ccwgroup_match_all))) { |
586 | struct ccwgroup_device *gdev = to_ccwgroupdev(dev); | 585 | struct ccwgroup_device *gdev = to_ccwgroupdev(dev); |
@@ -592,7 +591,6 @@ void ccwgroup_driver_unregister(struct ccwgroup_driver *cdriver) | |||
592 | mutex_unlock(&gdev->reg_mutex); | 591 | mutex_unlock(&gdev->reg_mutex); |
593 | put_device(dev); | 592 | put_device(dev); |
594 | } | 593 | } |
595 | put_driver(&cdriver->driver); | ||
596 | driver_unregister(&cdriver->driver); | 594 | driver_unregister(&cdriver->driver); |
597 | } | 595 | } |
598 | EXPORT_SYMBOL(ccwgroup_driver_unregister); | 596 | EXPORT_SYMBOL(ccwgroup_driver_unregister); |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 47269858ecb6..02d015259461 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -1676,15 +1676,9 @@ struct ccw_device *get_ccwdev_by_busid(struct ccw_driver *cdrv, | |||
1676 | const char *bus_id) | 1676 | const char *bus_id) |
1677 | { | 1677 | { |
1678 | struct device *dev; | 1678 | struct device *dev; |
1679 | struct device_driver *drv; | ||
1680 | 1679 | ||
1681 | drv = get_driver(&cdrv->driver); | 1680 | dev = driver_find_device(&cdrv->driver, NULL, (void *)bus_id, |
1682 | if (!drv) | ||
1683 | return NULL; | ||
1684 | |||
1685 | dev = driver_find_device(drv, NULL, (void *)bus_id, | ||
1686 | __ccwdev_check_busid); | 1681 | __ccwdev_check_busid); |
1687 | put_driver(drv); | ||
1688 | 1682 | ||
1689 | return dev ? to_ccwdev(dev) : NULL; | 1683 | return dev ? to_ccwdev(dev) : NULL; |
1690 | } | 1684 | } |
diff --git a/drivers/s390/net/smsgiucv_app.c b/drivers/s390/net/smsgiucv_app.c index 4d2ea4000422..32515a201bbc 100644 --- a/drivers/s390/net/smsgiucv_app.c +++ b/drivers/s390/net/smsgiucv_app.c | |||
@@ -168,7 +168,7 @@ static int __init smsgiucv_app_init(void) | |||
168 | rc = dev_set_name(smsg_app_dev, KMSG_COMPONENT); | 168 | rc = dev_set_name(smsg_app_dev, KMSG_COMPONENT); |
169 | if (rc) { | 169 | if (rc) { |
170 | kfree(smsg_app_dev); | 170 | kfree(smsg_app_dev); |
171 | goto fail_put_driver; | 171 | goto fail; |
172 | } | 172 | } |
173 | smsg_app_dev->bus = &iucv_bus; | 173 | smsg_app_dev->bus = &iucv_bus; |
174 | smsg_app_dev->parent = iucv_root; | 174 | smsg_app_dev->parent = iucv_root; |
@@ -177,7 +177,7 @@ static int __init smsgiucv_app_init(void) | |||
177 | rc = device_register(smsg_app_dev); | 177 | rc = device_register(smsg_app_dev); |
178 | if (rc) { | 178 | if (rc) { |
179 | put_device(smsg_app_dev); | 179 | put_device(smsg_app_dev); |
180 | goto fail_put_driver; | 180 | goto fail; |
181 | } | 181 | } |
182 | 182 | ||
183 | /* convert sender to uppercase characters */ | 183 | /* convert sender to uppercase characters */ |
@@ -191,12 +191,11 @@ static int __init smsgiucv_app_init(void) | |||
191 | rc = smsg_register_callback(SMSG_PREFIX, smsg_app_callback); | 191 | rc = smsg_register_callback(SMSG_PREFIX, smsg_app_callback); |
192 | if (rc) { | 192 | if (rc) { |
193 | device_unregister(smsg_app_dev); | 193 | device_unregister(smsg_app_dev); |
194 | goto fail_put_driver; | 194 | goto fail; |
195 | } | 195 | } |
196 | 196 | ||
197 | rc = 0; | 197 | rc = 0; |
198 | fail_put_driver: | 198 | fail: |
199 | put_driver(smsgiucv_drv); | ||
200 | return rc; | 199 | return rc; |
201 | } | 200 | } |
202 | module_init(smsgiucv_app_init); | 201 | module_init(smsgiucv_app_init); |
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index bb6317fb925c..ff109ae94767 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c | |||
@@ -140,19 +140,6 @@ static void ssb_device_put(struct ssb_device *dev) | |||
140 | put_device(dev->dev); | 140 | put_device(dev->dev); |
141 | } | 141 | } |
142 | 142 | ||
143 | static inline struct ssb_driver *ssb_driver_get(struct ssb_driver *drv) | ||
144 | { | ||
145 | if (drv) | ||
146 | get_driver(&drv->drv); | ||
147 | return drv; | ||
148 | } | ||
149 | |||
150 | static inline void ssb_driver_put(struct ssb_driver *drv) | ||
151 | { | ||
152 | if (drv) | ||
153 | put_driver(&drv->drv); | ||
154 | } | ||
155 | |||
156 | static int ssb_device_resume(struct device *dev) | 143 | static int ssb_device_resume(struct device *dev) |
157 | { | 144 | { |
158 | struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); | 145 | struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); |
@@ -250,11 +237,9 @@ int ssb_devices_freeze(struct ssb_bus *bus, struct ssb_freeze_context *ctx) | |||
250 | ssb_device_put(sdev); | 237 | ssb_device_put(sdev); |
251 | continue; | 238 | continue; |
252 | } | 239 | } |
253 | sdrv = ssb_driver_get(drv_to_ssb_drv(sdev->dev->driver)); | 240 | sdrv = drv_to_ssb_drv(sdev->dev->driver); |
254 | if (!sdrv || SSB_WARN_ON(!sdrv->remove)) { | 241 | if (SSB_WARN_ON(!sdrv->remove)) |
255 | ssb_device_put(sdev); | ||
256 | continue; | 242 | continue; |
257 | } | ||
258 | sdrv->remove(sdev); | 243 | sdrv->remove(sdev); |
259 | ctx->device_frozen[i] = 1; | 244 | ctx->device_frozen[i] = 1; |
260 | } | 245 | } |
@@ -293,7 +278,6 @@ int ssb_devices_thaw(struct ssb_freeze_context *ctx) | |||
293 | dev_name(sdev->dev)); | 278 | dev_name(sdev->dev)); |
294 | result = err; | 279 | result = err; |
295 | } | 280 | } |
296 | ssb_driver_put(sdrv); | ||
297 | ssb_device_put(sdev); | 281 | ssb_device_put(sdev); |
298 | } | 282 | } |
299 | 283 | ||
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index d40ff9568813..4fee024ecc9b 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -71,10 +71,7 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids, | |||
71 | list_add_tail(&dynid->node, &dynids->list); | 71 | list_add_tail(&dynid->node, &dynids->list); |
72 | spin_unlock(&dynids->lock); | 72 | spin_unlock(&dynids->lock); |
73 | 73 | ||
74 | if (get_driver(driver)) { | 74 | retval = driver_attach(driver); |
75 | retval = driver_attach(driver); | ||
76 | put_driver(driver); | ||
77 | } | ||
78 | 75 | ||
79 | if (retval) | 76 | if (retval) |
80 | return retval; | 77 | return retval; |
@@ -132,43 +129,39 @@ store_remove_id(struct device_driver *driver, const char *buf, size_t count) | |||
132 | } | 129 | } |
133 | static DRIVER_ATTR(remove_id, S_IWUSR, NULL, store_remove_id); | 130 | static DRIVER_ATTR(remove_id, S_IWUSR, NULL, store_remove_id); |
134 | 131 | ||
135 | static int usb_create_newid_file(struct usb_driver *usb_drv) | 132 | static int usb_create_newid_files(struct usb_driver *usb_drv) |
136 | { | 133 | { |
137 | int error = 0; | 134 | int error = 0; |
138 | 135 | ||
139 | if (usb_drv->no_dynamic_id) | 136 | if (usb_drv->no_dynamic_id) |
140 | goto exit; | 137 | goto exit; |
141 | 138 | ||
142 | if (usb_drv->probe != NULL) | 139 | if (usb_drv->probe != NULL) { |
143 | error = driver_create_file(&usb_drv->drvwrap.driver, | 140 | error = driver_create_file(&usb_drv->drvwrap.driver, |
144 | &driver_attr_new_id); | 141 | &driver_attr_new_id); |
142 | if (error == 0) { | ||
143 | error = driver_create_file(&usb_drv->drvwrap.driver, | ||
144 | &driver_attr_remove_id); | ||
145 | if (error) | ||
146 | driver_remove_file(&usb_drv->drvwrap.driver, | ||
147 | &driver_attr_new_id); | ||
148 | } | ||
149 | } | ||
145 | exit: | 150 | exit: |
146 | return error; | 151 | return error; |
147 | } | 152 | } |
148 | 153 | ||
149 | static void usb_remove_newid_file(struct usb_driver *usb_drv) | 154 | static void usb_remove_newid_files(struct usb_driver *usb_drv) |
150 | { | 155 | { |
151 | if (usb_drv->no_dynamic_id) | 156 | if (usb_drv->no_dynamic_id) |
152 | return; | 157 | return; |
153 | 158 | ||
154 | if (usb_drv->probe != NULL) | 159 | if (usb_drv->probe != NULL) { |
155 | driver_remove_file(&usb_drv->drvwrap.driver, | 160 | driver_remove_file(&usb_drv->drvwrap.driver, |
156 | &driver_attr_new_id); | ||
157 | } | ||
158 | |||
159 | static int | ||
160 | usb_create_removeid_file(struct usb_driver *drv) | ||
161 | { | ||
162 | int error = 0; | ||
163 | if (drv->probe != NULL) | ||
164 | error = driver_create_file(&drv->drvwrap.driver, | ||
165 | &driver_attr_remove_id); | 161 | &driver_attr_remove_id); |
166 | return error; | 162 | driver_remove_file(&usb_drv->drvwrap.driver, |
167 | } | 163 | &driver_attr_new_id); |
168 | 164 | } | |
169 | static void usb_remove_removeid_file(struct usb_driver *drv) | ||
170 | { | ||
171 | driver_remove_file(&drv->drvwrap.driver, &driver_attr_remove_id); | ||
172 | } | 165 | } |
173 | 166 | ||
174 | static void usb_free_dynids(struct usb_driver *usb_drv) | 167 | static void usb_free_dynids(struct usb_driver *usb_drv) |
@@ -183,22 +176,12 @@ static void usb_free_dynids(struct usb_driver *usb_drv) | |||
183 | spin_unlock(&usb_drv->dynids.lock); | 176 | spin_unlock(&usb_drv->dynids.lock); |
184 | } | 177 | } |
185 | #else | 178 | #else |
186 | static inline int usb_create_newid_file(struct usb_driver *usb_drv) | 179 | static inline int usb_create_newid_files(struct usb_driver *usb_drv) |
187 | { | 180 | { |
188 | return 0; | 181 | return 0; |
189 | } | 182 | } |
190 | 183 | ||
191 | static void usb_remove_newid_file(struct usb_driver *usb_drv) | 184 | static void usb_remove_newid_files(struct usb_driver *usb_drv) |
192 | { | ||
193 | } | ||
194 | |||
195 | static int | ||
196 | usb_create_removeid_file(struct usb_driver *drv) | ||
197 | { | ||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | static void usb_remove_removeid_file(struct usb_driver *drv) | ||
202 | { | 185 | { |
203 | } | 186 | } |
204 | 187 | ||
@@ -875,22 +858,16 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner, | |||
875 | 858 | ||
876 | usbfs_update_special(); | 859 | usbfs_update_special(); |
877 | 860 | ||
878 | retval = usb_create_newid_file(new_driver); | 861 | retval = usb_create_newid_files(new_driver); |
879 | if (retval) | 862 | if (retval) |
880 | goto out_newid; | 863 | goto out_newid; |
881 | 864 | ||
882 | retval = usb_create_removeid_file(new_driver); | ||
883 | if (retval) | ||
884 | goto out_removeid; | ||
885 | |||
886 | pr_info("%s: registered new interface driver %s\n", | 865 | pr_info("%s: registered new interface driver %s\n", |
887 | usbcore_name, new_driver->name); | 866 | usbcore_name, new_driver->name); |
888 | 867 | ||
889 | out: | 868 | out: |
890 | return retval; | 869 | return retval; |
891 | 870 | ||
892 | out_removeid: | ||
893 | usb_remove_newid_file(new_driver); | ||
894 | out_newid: | 871 | out_newid: |
895 | driver_unregister(&new_driver->drvwrap.driver); | 872 | driver_unregister(&new_driver->drvwrap.driver); |
896 | 873 | ||
@@ -917,10 +894,9 @@ void usb_deregister(struct usb_driver *driver) | |||
917 | pr_info("%s: deregistering interface driver %s\n", | 894 | pr_info("%s: deregistering interface driver %s\n", |
918 | usbcore_name, driver->name); | 895 | usbcore_name, driver->name); |
919 | 896 | ||
920 | usb_remove_removeid_file(driver); | 897 | usb_remove_newid_files(driver); |
921 | usb_remove_newid_file(driver); | ||
922 | usb_free_dynids(driver); | ||
923 | driver_unregister(&driver->drvwrap.driver); | 898 | driver_unregister(&driver->drvwrap.driver); |
899 | usb_free_dynids(driver); | ||
924 | 900 | ||
925 | usbfs_update_special(); | 901 | usbfs_update_special(); |
926 | } | 902 | } |
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 64e1f7c67b08..c68e4270457a 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c | |||
@@ -171,14 +171,4 @@ MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); | |||
171 | MODULE_LICENSE("Dual BSD/GPL"); | 171 | MODULE_LICENSE("Dual BSD/GPL"); |
172 | MODULE_DESCRIPTION("DesignWare USB3 PCI Glue Layer"); | 172 | MODULE_DESCRIPTION("DesignWare USB3 PCI Glue Layer"); |
173 | 173 | ||
174 | static int __devinit dwc3_pci_init(void) | 174 | module_pci_driver(dwc3_pci_driver); |
175 | { | ||
176 | return pci_register_driver(&dwc3_pci_driver); | ||
177 | } | ||
178 | module_init(dwc3_pci_init); | ||
179 | |||
180 | static void __exit dwc3_pci_exit(void) | ||
181 | { | ||
182 | pci_unregister_driver(&dwc3_pci_driver); | ||
183 | } | ||
184 | module_exit(dwc3_pci_exit); | ||
diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c index fcbe742188a5..df600d14974d 100644 --- a/drivers/w1/masters/w1-gpio.c +++ b/drivers/w1/masters/w1-gpio.c | |||
@@ -13,12 +13,11 @@ | |||
13 | #include <linux/platform_device.h> | 13 | #include <linux/platform_device.h> |
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/w1-gpio.h> | 15 | #include <linux/w1-gpio.h> |
16 | #include <linux/gpio.h> | ||
16 | 17 | ||
17 | #include "../w1.h" | 18 | #include "../w1.h" |
18 | #include "../w1_int.h" | 19 | #include "../w1_int.h" |
19 | 20 | ||
20 | #include <asm/gpio.h> | ||
21 | |||
22 | static void w1_gpio_write_bit_dir(void *data, u8 bit) | 21 | static void w1_gpio_write_bit_dir(void *data, u8 bit) |
23 | { | 22 | { |
24 | struct w1_gpio_platform_data *pdata = data; | 23 | struct w1_gpio_platform_data *pdata = data; |
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig index d0cb01b42012..eb9e376d6244 100644 --- a/drivers/w1/slaves/Kconfig +++ b/drivers/w1/slaves/Kconfig | |||
@@ -81,6 +81,19 @@ config W1_SLAVE_DS2780 | |||
81 | 81 | ||
82 | If you are unsure, say N. | 82 | If you are unsure, say N. |
83 | 83 | ||
84 | config W1_SLAVE_DS2781 | ||
85 | tristate "Dallas 2781 battery monitor chip" | ||
86 | depends on W1 | ||
87 | help | ||
88 | If you enable this you will have the DS2781 battery monitor | ||
89 | chip support. | ||
90 | |||
91 | The battery monitor chip is used in many batteries/devices | ||
92 | as the one who is responsible for charging/discharging/monitoring | ||
93 | Li+ batteries. | ||
94 | |||
95 | If you are unsure, say N. | ||
96 | |||
84 | config W1_SLAVE_BQ27000 | 97 | config W1_SLAVE_BQ27000 |
85 | tristate "BQ27000 slave support" | 98 | tristate "BQ27000 slave support" |
86 | depends on W1 | 99 | depends on W1 |
diff --git a/drivers/w1/slaves/Makefile b/drivers/w1/slaves/Makefile index 1f31e9fb0b25..c4f1859fb520 100644 --- a/drivers/w1/slaves/Makefile +++ b/drivers/w1/slaves/Makefile | |||
@@ -10,4 +10,5 @@ obj-$(CONFIG_W1_SLAVE_DS2431) += w1_ds2431.o | |||
10 | obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o | 10 | obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o |
11 | obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o | 11 | obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o |
12 | obj-$(CONFIG_W1_SLAVE_DS2780) += w1_ds2780.o | 12 | obj-$(CONFIG_W1_SLAVE_DS2780) += w1_ds2780.o |
13 | obj-$(CONFIG_W1_SLAVE_DS2781) += w1_ds2781.o | ||
13 | obj-$(CONFIG_W1_SLAVE_BQ27000) += w1_bq27000.o | 14 | obj-$(CONFIG_W1_SLAVE_BQ27000) += w1_bq27000.o |
diff --git a/drivers/w1/slaves/w1_bq27000.c b/drivers/w1/slaves/w1_bq27000.c index 8f4c91f6c680..52ad812fa1e7 100644 --- a/drivers/w1/slaves/w1_bq27000.c +++ b/drivers/w1/slaves/w1_bq27000.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/types.h> | 15 | #include <linux/types.h> |
16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
17 | #include <linux/mutex.h> | 17 | #include <linux/mutex.h> |
18 | #include <linux/power/bq27x00_battery.h> | ||
18 | 19 | ||
19 | #include "../w1.h" | 20 | #include "../w1.h" |
20 | #include "../w1_int.h" | 21 | #include "../w1_int.h" |
@@ -25,46 +26,37 @@ | |||
25 | 26 | ||
26 | static int F_ID; | 27 | static int F_ID; |
27 | 28 | ||
28 | void w1_bq27000_write(struct device *dev, u8 buf, u8 reg) | 29 | static int w1_bq27000_read(struct device *dev, unsigned int reg) |
29 | { | ||
30 | struct w1_slave *sl = container_of(dev, struct w1_slave, dev); | ||
31 | |||
32 | if (!dev) { | ||
33 | pr_info("Could not obtain slave dev ptr\n"); | ||
34 | return; | ||
35 | } | ||
36 | |||
37 | w1_write_8(sl->master, HDQ_CMD_WRITE | reg); | ||
38 | w1_write_8(sl->master, buf); | ||
39 | } | ||
40 | EXPORT_SYMBOL(w1_bq27000_write); | ||
41 | |||
42 | int w1_bq27000_read(struct device *dev, u8 reg) | ||
43 | { | 30 | { |
44 | u8 val; | 31 | u8 val; |
45 | struct w1_slave *sl = container_of(dev, struct w1_slave, dev); | 32 | struct w1_slave *sl = container_of(dev->parent, struct w1_slave, dev); |
46 | |||
47 | if (!dev) | ||
48 | return 0; | ||
49 | 33 | ||
34 | mutex_lock(&sl->master->mutex); | ||
50 | w1_write_8(sl->master, HDQ_CMD_READ | reg); | 35 | w1_write_8(sl->master, HDQ_CMD_READ | reg); |
51 | val = w1_read_8(sl->master); | 36 | val = w1_read_8(sl->master); |
37 | mutex_unlock(&sl->master->mutex); | ||
52 | 38 | ||
53 | return val; | 39 | return val; |
54 | } | 40 | } |
55 | EXPORT_SYMBOL(w1_bq27000_read); | 41 | |
42 | static struct bq27000_platform_data bq27000_battery_info = { | ||
43 | .read = w1_bq27000_read, | ||
44 | .name = "bq27000-battery", | ||
45 | }; | ||
56 | 46 | ||
57 | static int w1_bq27000_add_slave(struct w1_slave *sl) | 47 | static int w1_bq27000_add_slave(struct w1_slave *sl) |
58 | { | 48 | { |
59 | int ret; | 49 | int ret; |
60 | int id = 1; | ||
61 | struct platform_device *pdev; | 50 | struct platform_device *pdev; |
62 | 51 | ||
63 | pdev = platform_device_alloc("bq27000-battery", id); | 52 | pdev = platform_device_alloc("bq27000-battery", -1); |
64 | if (!pdev) { | 53 | if (!pdev) { |
65 | ret = -ENOMEM; | 54 | ret = -ENOMEM; |
66 | return ret; | 55 | return ret; |
67 | } | 56 | } |
57 | ret = platform_device_add_data(pdev, | ||
58 | &bq27000_battery_info, | ||
59 | sizeof(bq27000_battery_info)); | ||
68 | pdev->dev.parent = &sl->dev; | 60 | pdev->dev.parent = &sl->dev; |
69 | 61 | ||
70 | ret = platform_device_add(pdev); | 62 | ret = platform_device_add(pdev); |
diff --git a/drivers/w1/slaves/w1_ds2781.c b/drivers/w1/slaves/w1_ds2781.c new file mode 100644 index 000000000000..0d0c7985293f --- /dev/null +++ b/drivers/w1/slaves/w1_ds2781.c | |||
@@ -0,0 +1,201 @@ | |||
1 | /* | ||
2 | * 1-Wire implementation for the ds2781 chip | ||
3 | * | ||
4 | * Author: Renata Sayakhova <renata@oktetlabs.ru> | ||
5 | * | ||
6 | * Based on w1-ds2780 driver | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/types.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/mutex.h> | ||
20 | #include <linux/idr.h> | ||
21 | |||
22 | #include "../w1.h" | ||
23 | #include "../w1_int.h" | ||
24 | #include "../w1_family.h" | ||
25 | #include "w1_ds2781.h" | ||
26 | |||
27 | static int w1_ds2781_do_io(struct device *dev, char *buf, int addr, | ||
28 | size_t count, int io) | ||
29 | { | ||
30 | struct w1_slave *sl = container_of(dev, struct w1_slave, dev); | ||
31 | |||
32 | if (addr > DS2781_DATA_SIZE || addr < 0) | ||
33 | return 0; | ||
34 | |||
35 | count = min_t(int, count, DS2781_DATA_SIZE - addr); | ||
36 | |||
37 | if (w1_reset_select_slave(sl) == 0) { | ||
38 | if (io) { | ||
39 | w1_write_8(sl->master, W1_DS2781_WRITE_DATA); | ||
40 | w1_write_8(sl->master, addr); | ||
41 | w1_write_block(sl->master, buf, count); | ||
42 | } else { | ||
43 | w1_write_8(sl->master, W1_DS2781_READ_DATA); | ||
44 | w1_write_8(sl->master, addr); | ||
45 | count = w1_read_block(sl->master, buf, count); | ||
46 | } | ||
47 | } | ||
48 | |||
49 | return count; | ||
50 | } | ||
51 | |||
52 | int w1_ds2781_io(struct device *dev, char *buf, int addr, size_t count, | ||
53 | int io) | ||
54 | { | ||
55 | struct w1_slave *sl = container_of(dev, struct w1_slave, dev); | ||
56 | int ret; | ||
57 | |||
58 | if (!dev) | ||
59 | return -ENODEV; | ||
60 | |||
61 | mutex_lock(&sl->master->mutex); | ||
62 | |||
63 | ret = w1_ds2781_do_io(dev, buf, addr, count, io); | ||
64 | |||
65 | mutex_unlock(&sl->master->mutex); | ||
66 | |||
67 | return ret; | ||
68 | } | ||
69 | EXPORT_SYMBOL(w1_ds2781_io); | ||
70 | |||
71 | int w1_ds2781_io_nolock(struct device *dev, char *buf, int addr, size_t count, | ||
72 | int io) | ||
73 | { | ||
74 | int ret; | ||
75 | |||
76 | if (!dev) | ||
77 | return -ENODEV; | ||
78 | |||
79 | ret = w1_ds2781_do_io(dev, buf, addr, count, io); | ||
80 | |||
81 | return ret; | ||
82 | } | ||
83 | EXPORT_SYMBOL(w1_ds2781_io_nolock); | ||
84 | |||
85 | int w1_ds2781_eeprom_cmd(struct device *dev, int addr, int cmd) | ||
86 | { | ||
87 | struct w1_slave *sl = container_of(dev, struct w1_slave, dev); | ||
88 | |||
89 | if (!dev) | ||
90 | return -EINVAL; | ||
91 | |||
92 | mutex_lock(&sl->master->mutex); | ||
93 | |||
94 | if (w1_reset_select_slave(sl) == 0) { | ||
95 | w1_write_8(sl->master, cmd); | ||
96 | w1_write_8(sl->master, addr); | ||
97 | } | ||
98 | |||
99 | mutex_unlock(&sl->master->mutex); | ||
100 | return 0; | ||
101 | } | ||
102 | EXPORT_SYMBOL(w1_ds2781_eeprom_cmd); | ||
103 | |||
104 | static ssize_t w1_ds2781_read_bin(struct file *filp, | ||
105 | struct kobject *kobj, | ||
106 | struct bin_attribute *bin_attr, | ||
107 | char *buf, loff_t off, size_t count) | ||
108 | { | ||
109 | struct device *dev = container_of(kobj, struct device, kobj); | ||
110 | return w1_ds2781_io(dev, buf, off, count, 0); | ||
111 | } | ||
112 | |||
113 | static struct bin_attribute w1_ds2781_bin_attr = { | ||
114 | .attr = { | ||
115 | .name = "w1_slave", | ||
116 | .mode = S_IRUGO, | ||
117 | }, | ||
118 | .size = DS2781_DATA_SIZE, | ||
119 | .read = w1_ds2781_read_bin, | ||
120 | }; | ||
121 | |||
122 | static DEFINE_IDA(bat_ida); | ||
123 | |||
124 | static int w1_ds2781_add_slave(struct w1_slave *sl) | ||
125 | { | ||
126 | int ret; | ||
127 | int id; | ||
128 | struct platform_device *pdev; | ||
129 | |||
130 | id = ida_simple_get(&bat_ida, 0, 0, GFP_KERNEL); | ||
131 | if (id < 0) { | ||
132 | ret = id; | ||
133 | goto noid; | ||
134 | } | ||
135 | |||
136 | pdev = platform_device_alloc("ds2781-battery", id); | ||
137 | if (!pdev) { | ||
138 | ret = -ENOMEM; | ||
139 | goto pdev_alloc_failed; | ||
140 | } | ||
141 | pdev->dev.parent = &sl->dev; | ||
142 | |||
143 | ret = platform_device_add(pdev); | ||
144 | if (ret) | ||
145 | goto pdev_add_failed; | ||
146 | |||
147 | ret = sysfs_create_bin_file(&sl->dev.kobj, &w1_ds2781_bin_attr); | ||
148 | if (ret) | ||
149 | goto bin_attr_failed; | ||
150 | |||
151 | dev_set_drvdata(&sl->dev, pdev); | ||
152 | |||
153 | return 0; | ||
154 | |||
155 | bin_attr_failed: | ||
156 | pdev_add_failed: | ||
157 | platform_device_unregister(pdev); | ||
158 | pdev_alloc_failed: | ||
159 | ida_simple_remove(&bat_ida, id); | ||
160 | noid: | ||
161 | return ret; | ||
162 | } | ||
163 | |||
164 | static void w1_ds2781_remove_slave(struct w1_slave *sl) | ||
165 | { | ||
166 | struct platform_device *pdev = dev_get_drvdata(&sl->dev); | ||
167 | int id = pdev->id; | ||
168 | |||
169 | platform_device_unregister(pdev); | ||
170 | ida_simple_remove(&bat_ida, id); | ||
171 | sysfs_remove_bin_file(&sl->dev.kobj, &w1_ds2781_bin_attr); | ||
172 | } | ||
173 | |||
174 | static struct w1_family_ops w1_ds2781_fops = { | ||
175 | .add_slave = w1_ds2781_add_slave, | ||
176 | .remove_slave = w1_ds2781_remove_slave, | ||
177 | }; | ||
178 | |||
179 | static struct w1_family w1_ds2781_family = { | ||
180 | .fid = W1_FAMILY_DS2781, | ||
181 | .fops = &w1_ds2781_fops, | ||
182 | }; | ||
183 | |||
184 | static int __init w1_ds2781_init(void) | ||
185 | { | ||
186 | ida_init(&bat_ida); | ||
187 | return w1_register_family(&w1_ds2781_family); | ||
188 | } | ||
189 | |||
190 | static void __exit w1_ds2781_exit(void) | ||
191 | { | ||
192 | w1_unregister_family(&w1_ds2781_family); | ||
193 | ida_destroy(&bat_ida); | ||
194 | } | ||
195 | |||
196 | module_init(w1_ds2781_init); | ||
197 | module_exit(w1_ds2781_exit); | ||
198 | |||
199 | MODULE_LICENSE("GPL"); | ||
200 | MODULE_AUTHOR("Renata Sayakhova <renata@oktetlabs.ru>"); | ||
201 | MODULE_DESCRIPTION("1-wire Driver for Maxim/Dallas DS2781 Stand-Alone Fuel Gauge IC"); | ||
diff --git a/drivers/w1/slaves/w1_ds2781.h b/drivers/w1/slaves/w1_ds2781.h new file mode 100644 index 000000000000..82bc66497b43 --- /dev/null +++ b/drivers/w1/slaves/w1_ds2781.h | |||
@@ -0,0 +1,136 @@ | |||
1 | /* | ||
2 | * 1-Wire implementation for the ds2780 chip | ||
3 | * | ||
4 | * Author: Renata Sayakhova <renata@oktetlabs.ru> | ||
5 | * | ||
6 | * Based on w1-ds2760 driver | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #ifndef _W1_DS2781_H | ||
15 | #define _W1_DS2781_H | ||
16 | |||
17 | /* Function commands */ | ||
18 | #define W1_DS2781_READ_DATA 0x69 | ||
19 | #define W1_DS2781_WRITE_DATA 0x6C | ||
20 | #define W1_DS2781_COPY_DATA 0x48 | ||
21 | #define W1_DS2781_RECALL_DATA 0xB8 | ||
22 | #define W1_DS2781_LOCK 0x6A | ||
23 | |||
24 | /* Register map */ | ||
25 | /* Register 0x00 Reserved */ | ||
26 | #define DS2781_STATUS 0x01 | ||
27 | #define DS2781_RAAC_MSB 0x02 | ||
28 | #define DS2781_RAAC_LSB 0x03 | ||
29 | #define DS2781_RSAC_MSB 0x04 | ||
30 | #define DS2781_RSAC_LSB 0x05 | ||
31 | #define DS2781_RARC 0x06 | ||
32 | #define DS2781_RSRC 0x07 | ||
33 | #define DS2781_IAVG_MSB 0x08 | ||
34 | #define DS2781_IAVG_LSB 0x09 | ||
35 | #define DS2781_TEMP_MSB 0x0A | ||
36 | #define DS2781_TEMP_LSB 0x0B | ||
37 | #define DS2781_VOLT_MSB 0x0C | ||
38 | #define DS2781_VOLT_LSB 0x0D | ||
39 | #define DS2781_CURRENT_MSB 0x0E | ||
40 | #define DS2781_CURRENT_LSB 0x0F | ||
41 | #define DS2781_ACR_MSB 0x10 | ||
42 | #define DS2781_ACR_LSB 0x11 | ||
43 | #define DS2781_ACRL_MSB 0x12 | ||
44 | #define DS2781_ACRL_LSB 0x13 | ||
45 | #define DS2781_AS 0x14 | ||
46 | #define DS2781_SFR 0x15 | ||
47 | #define DS2781_FULL_MSB 0x16 | ||
48 | #define DS2781_FULL_LSB 0x17 | ||
49 | #define DS2781_AE_MSB 0x18 | ||
50 | #define DS2781_AE_LSB 0x19 | ||
51 | #define DS2781_SE_MSB 0x1A | ||
52 | #define DS2781_SE_LSB 0x1B | ||
53 | /* Register 0x1C - 0x1E Reserved */ | ||
54 | #define DS2781_EEPROM 0x1F | ||
55 | #define DS2781_EEPROM_BLOCK0_START 0x20 | ||
56 | /* Register 0x20 - 0x2F User EEPROM */ | ||
57 | #define DS2781_EEPROM_BLOCK0_END 0x2F | ||
58 | /* Register 0x30 - 0x5F Reserved */ | ||
59 | #define DS2781_EEPROM_BLOCK1_START 0x60 | ||
60 | #define DS2781_CONTROL 0x60 | ||
61 | #define DS2781_AB 0x61 | ||
62 | #define DS2781_AC_MSB 0x62 | ||
63 | #define DS2781_AC_LSB 0x63 | ||
64 | #define DS2781_VCHG 0x64 | ||
65 | #define DS2781_IMIN 0x65 | ||
66 | #define DS2781_VAE 0x66 | ||
67 | #define DS2781_IAE 0x67 | ||
68 | #define DS2781_AE_40 0x68 | ||
69 | #define DS2781_RSNSP 0x69 | ||
70 | #define DS2781_FULL_40_MSB 0x6A | ||
71 | #define DS2781_FULL_40_LSB 0x6B | ||
72 | #define DS2781_FULL_4_SLOPE 0x6C | ||
73 | #define DS2781_FULL_3_SLOPE 0x6D | ||
74 | #define DS2781_FULL_2_SLOPE 0x6E | ||
75 | #define DS2781_FULL_1_SLOPE 0x6F | ||
76 | #define DS2781_AE_4_SLOPE 0x70 | ||
77 | #define DS2781_AE_3_SLOPE 0x71 | ||
78 | #define DS2781_AE_2_SLOPE 0x72 | ||
79 | #define DS2781_AE_1_SLOPE 0x73 | ||
80 | #define DS2781_SE_4_SLOPE 0x74 | ||
81 | #define DS2781_SE_3_SLOPE 0x75 | ||
82 | #define DS2781_SE_2_SLOPE 0x76 | ||
83 | #define DS2781_SE_1_SLOPE 0x77 | ||
84 | #define DS2781_RSGAIN_MSB 0x78 | ||
85 | #define DS2781_RSGAIN_LSB 0x79 | ||
86 | #define DS2781_RSTC 0x7A | ||
87 | #define DS2781_COB 0x7B | ||
88 | #define DS2781_TBP34 0x7C | ||
89 | #define DS2781_TBP23 0x7D | ||
90 | #define DS2781_TBP12 0x7E | ||
91 | #define DS2781_EEPROM_BLOCK1_END 0x7F | ||
92 | /* Register 0x7D - 0xFF Reserved */ | ||
93 | |||
94 | #define DS2781_FSGAIN_MSB 0xB0 | ||
95 | #define DS2781_FSGAIN_LSB 0xB1 | ||
96 | |||
97 | /* Number of valid register addresses */ | ||
98 | #define DS2781_DATA_SIZE 0xB2 | ||
99 | |||
100 | /* Status register bits */ | ||
101 | #define DS2781_STATUS_CHGTF (1 << 7) | ||
102 | #define DS2781_STATUS_AEF (1 << 6) | ||
103 | #define DS2781_STATUS_SEF (1 << 5) | ||
104 | #define DS2781_STATUS_LEARNF (1 << 4) | ||
105 | /* Bit 3 Reserved */ | ||
106 | #define DS2781_STATUS_UVF (1 << 2) | ||
107 | #define DS2781_STATUS_PORF (1 << 1) | ||
108 | /* Bit 0 Reserved */ | ||
109 | |||
110 | /* Control register bits */ | ||
111 | /* Bit 7 Reserved */ | ||
112 | #define DS2781_CONTROL_NBEN (1 << 7) | ||
113 | #define DS2781_CONTROL_UVEN (1 << 6) | ||
114 | #define DS2781_CONTROL_PMOD (1 << 5) | ||
115 | #define DS2781_CONTROL_RNAOP (1 << 4) | ||
116 | #define DS1781_CONTROL_UVTH (1 << 3) | ||
117 | /* Bit 0 - 2 Reserved */ | ||
118 | |||
119 | /* Special feature register bits */ | ||
120 | /* Bit 1 - 7 Reserved */ | ||
121 | #define DS2781_SFR_PIOSC (1 << 0) | ||
122 | |||
123 | /* EEPROM register bits */ | ||
124 | #define DS2781_EEPROM_EEC (1 << 7) | ||
125 | #define DS2781_EEPROM_LOCK (1 << 6) | ||
126 | /* Bit 2 - 6 Reserved */ | ||
127 | #define DS2781_EEPROM_BL1 (1 << 1) | ||
128 | #define DS2781_EEPROM_BL0 (1 << 0) | ||
129 | |||
130 | extern int w1_ds2781_io(struct device *dev, char *buf, int addr, size_t count, | ||
131 | int io); | ||
132 | extern int w1_ds2781_io_nolock(struct device *dev, char *buf, int addr, | ||
133 | size_t count, int io); | ||
134 | extern int w1_ds2781_eeprom_cmd(struct device *dev, int addr, int cmd); | ||
135 | |||
136 | #endif /* !_W1_DS2781_H */ | ||
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h index 490cda2281bc..874aeb05011b 100644 --- a/drivers/w1/w1_family.h +++ b/drivers/w1/w1_family.h | |||
@@ -38,6 +38,7 @@ | |||
38 | #define W1_EEPROM_DS2431 0x2D | 38 | #define W1_EEPROM_DS2431 0x2D |
39 | #define W1_FAMILY_DS2760 0x30 | 39 | #define W1_FAMILY_DS2760 0x30 |
40 | #define W1_FAMILY_DS2780 0x32 | 40 | #define W1_FAMILY_DS2780 0x32 |
41 | #define W1_FAMILY_DS2781 0x3D | ||
41 | #define W1_THERM_DS28EA00 0x42 | 42 | #define W1_THERM_DS28EA00 0x42 |
42 | 43 | ||
43 | #define MAXNAMELEN 32 | 44 | #define MAXNAMELEN 32 |