aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/Kconfig21
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/asus-laptop.c1165
-rw-r--r--drivers/misc/hdpuftrs/hdpu_cpustate.c2
-rw-r--r--drivers/misc/hdpuftrs/hdpu_nexus.c2
-rw-r--r--drivers/misc/ibmasm/ibmasmfs.c10
-rw-r--r--drivers/misc/ioc4.c6
-rw-r--r--drivers/misc/lkdtm.c4
-rw-r--r--drivers/misc/tifm_7xx1.c404
-rw-r--r--drivers/misc/tifm_core.c65
10 files changed, 1460 insertions, 220 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index d7e8969fc319..80b199fa0aa9 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -42,7 +42,7 @@ config SGI_IOC4
42 42
43config TIFM_CORE 43config TIFM_CORE
44 tristate "TI Flash Media interface support (EXPERIMENTAL)" 44 tristate "TI Flash Media interface support (EXPERIMENTAL)"
45 depends on EXPERIMENTAL 45 depends on EXPERIMENTAL && PCI
46 help 46 help
47 If you want support for Texas Instruments(R) Flash Media adapters 47 If you want support for Texas Instruments(R) Flash Media adapters
48 you should select this option and then also choose an appropriate 48 you should select this option and then also choose an appropriate
@@ -69,6 +69,25 @@ config TIFM_7XX1
69 To compile this driver as a module, choose M here: the module will 69 To compile this driver as a module, choose M here: the module will
70 be called tifm_7xx1. 70 be called tifm_7xx1.
71 71
72config ASUS_LAPTOP
73 tristate "Asus Laptop Extras (EXPERIMENTAL)"
74 depends on X86
75 depends on ACPI
76 depends on EXPERIMENTAL && !ACPI_ASUS
77 depends on LEDS_CLASS
78 depends on BACKLIGHT_CLASS_DEVICE
79 ---help---
80 This is the new Linux driver for Asus laptops. It may also support some
81 MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate
82 standard ACPI events that go through /proc/acpi/events. It also adds
83 support for video output switching, LCD backlight control, Bluetooth and
84 Wlan control, and most importantly, allows you to blink those fancy LEDs.
85
86 For more information and a userspace daemon for handling the extra
87 buttons see <http://acpi4asus.sf.net/>.
88
89 If you have an ACPI-compatible ASUS laptop, say Y or M here.
90
72config MSI_LAPTOP 91config MSI_LAPTOP
73 tristate "MSI Laptop Extras" 92 tristate "MSI Laptop Extras"
74 depends on X86 93 depends on X86
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index f86f9dcfcfe5..7793ccd79049 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -6,6 +6,7 @@ obj- := misc.o # Dummy rule to force built-in.o to be made
6obj-$(CONFIG_IBM_ASM) += ibmasm/ 6obj-$(CONFIG_IBM_ASM) += ibmasm/
7obj-$(CONFIG_HDPU_FEATURES) += hdpuftrs/ 7obj-$(CONFIG_HDPU_FEATURES) += hdpuftrs/
8obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o 8obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o
9obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o
9obj-$(CONFIG_LKDTM) += lkdtm.o 10obj-$(CONFIG_LKDTM) += lkdtm.o
10obj-$(CONFIG_TIFM_CORE) += tifm_core.o 11obj-$(CONFIG_TIFM_CORE) += tifm_core.o
11obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o 12obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o
diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c
new file mode 100644
index 000000000000..861c39935f99
--- /dev/null
+++ b/drivers/misc/asus-laptop.c
@@ -0,0 +1,1165 @@
1/*
2 * asus-laptop.c - Asus Laptop Support
3 *
4 *
5 * Copyright (C) 2002-2005 Julien Lerouge, 2003-2006 Karol Kozimor
6 * Copyright (C) 2006 Corentin Chary
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 as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 *
23 * The development page for this driver is located at
24 * http://sourceforge.net/projects/acpi4asus/
25 *
26 * Credits:
27 * Pontus Fuchs - Helper functions, cleanup
28 * Johann Wiesner - Small compile fixes
29 * John Belmonte - ACPI code for Toshiba laptop was a good starting point.
30 * Eric Burghard - LED display support for W1N
31 * Josh Green - Light Sens support
32 * Thomas Tuttle - His first patch for led support was very helpfull
33 *
34 */
35
36#include <linux/autoconf.h>
37#include <linux/kernel.h>
38#include <linux/module.h>
39#include <linux/init.h>
40#include <linux/types.h>
41#include <linux/err.h>
42#include <linux/proc_fs.h>
43#include <linux/backlight.h>
44#include <linux/fb.h>
45#include <linux/leds.h>
46#include <linux/platform_device.h>
47#include <acpi/acpi_drivers.h>
48#include <acpi/acpi_bus.h>
49#include <asm/uaccess.h>
50
51#define ASUS_LAPTOP_VERSION "0.40"
52
53#define ASUS_HOTK_NAME "Asus Laptop Support"
54#define ASUS_HOTK_CLASS "hotkey"
55#define ASUS_HOTK_DEVICE_NAME "Hotkey"
56#define ASUS_HOTK_HID "ATK0100"
57#define ASUS_HOTK_FILE "asus-laptop"
58#define ASUS_HOTK_PREFIX "\\_SB.ATKD."
59
60/*
61 * Some events we use, same for all Asus
62 */
63#define ATKD_BR_UP 0x10
64#define ATKD_BR_DOWN 0x20
65#define ATKD_LCD_ON 0x33
66#define ATKD_LCD_OFF 0x34
67
68/*
69 * Known bits returned by \_SB.ATKD.HWRS
70 */
71#define WL_HWRS 0x80
72#define BT_HWRS 0x100
73
74/*
75 * Flags for hotk status
76 * WL_ON and BT_ON are also used for wireless_status()
77 */
78#define WL_ON 0x01 //internal Wifi
79#define BT_ON 0x02 //internal Bluetooth
80#define MLED_ON 0x04 //mail LED
81#define TLED_ON 0x08 //touchpad LED
82#define RLED_ON 0x10 //Record LED
83#define PLED_ON 0x20 //Phone LED
84#define LCD_ON 0x40 //LCD backlight
85
86#define ASUS_LOG ASUS_HOTK_FILE ": "
87#define ASUS_ERR KERN_ERR ASUS_LOG
88#define ASUS_WARNING KERN_WARNING ASUS_LOG
89#define ASUS_NOTICE KERN_NOTICE ASUS_LOG
90#define ASUS_INFO KERN_INFO ASUS_LOG
91#define ASUS_DEBUG KERN_DEBUG ASUS_LOG
92
93MODULE_AUTHOR("Julien Lerouge, Karol Kozimor, Corentin Chary");
94MODULE_DESCRIPTION(ASUS_HOTK_NAME);
95MODULE_LICENSE("GPL");
96
97#define ASUS_HANDLE(object, paths...) \
98 static acpi_handle object##_handle = NULL; \
99 static char *object##_paths[] = { paths }
100
101/* LED */
102ASUS_HANDLE(mled_set, ASUS_HOTK_PREFIX "MLED");
103ASUS_HANDLE(tled_set, ASUS_HOTK_PREFIX "TLED");
104ASUS_HANDLE(rled_set, ASUS_HOTK_PREFIX "RLED"); /* W1JC */
105ASUS_HANDLE(pled_set, ASUS_HOTK_PREFIX "PLED"); /* A7J */
106
107/* LEDD */
108ASUS_HANDLE(ledd_set, ASUS_HOTK_PREFIX "SLCM");
109
110/* Bluetooth and WLAN
111 * WLED and BLED are not handled like other XLED, because in some dsdt
112 * they also control the WLAN/Bluetooth device.
113 */
114ASUS_HANDLE(wl_switch, ASUS_HOTK_PREFIX "WLED");
115ASUS_HANDLE(bt_switch, ASUS_HOTK_PREFIX "BLED");
116ASUS_HANDLE(wireless_status, ASUS_HOTK_PREFIX "RSTS"); /* All new models */
117
118/* Brightness */
119ASUS_HANDLE(brightness_set, ASUS_HOTK_PREFIX "SPLV");
120ASUS_HANDLE(brightness_get, ASUS_HOTK_PREFIX "GPLV");
121
122/* Backlight */
123ASUS_HANDLE(lcd_switch, "\\_SB.PCI0.SBRG.EC0._Q10", /* All new models */
124 "\\_SB.PCI0.ISA.EC0._Q10", /* A1x */
125 "\\_SB.PCI0.PX40.ECD0._Q10", /* L3C */
126 "\\_SB.PCI0.PX40.EC0.Q10", /* M1A */
127 "\\_SB.PCI0.LPCB.EC0._Q10", /* P30 */
128 "\\_SB.PCI0.PX40.Q10", /* S1x */
129 "\\Q10"); /* A2x, L2D, L3D, M2E */
130
131/* Display */
132ASUS_HANDLE(display_set, ASUS_HOTK_PREFIX "SDSP");
133ASUS_HANDLE(display_get, "\\_SB.PCI0.P0P1.VGA.GETD", /* A6B, A6K A6R A7D F3JM L4R M6R A3G
134 M6A M6V VX-1 V6J V6V W3Z */
135 "\\_SB.PCI0.P0P2.VGA.GETD", /* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V
136 S5A M5A z33A W1Jc W2V */
137 "\\_SB.PCI0.P0P3.VGA.GETD", /* A6V A6Q */
138 "\\_SB.PCI0.P0PA.VGA.GETD", /* A6T, A6M */
139 "\\_SB.PCI0.PCI1.VGAC.NMAP", /* L3C */
140 "\\_SB.PCI0.VGA.GETD", /* Z96F */
141 "\\ACTD", /* A2D */
142 "\\ADVG", /* A4G Z71A W1N W5A W5F M2N M3N M5N M6N S1N S5N */
143 "\\DNXT", /* P30 */
144 "\\INFB", /* A2H D1 L2D L3D L3H L2E L5D L5C M1A M2E L4L W3V */
145 "\\SSTE"); /* A3F A6F A3N A3L M6N W3N W6A */
146
147ASUS_HANDLE(ls_switch, ASUS_HOTK_PREFIX "ALSC"); /* Z71A Z71V */
148ASUS_HANDLE(ls_level, ASUS_HOTK_PREFIX "ALSL"); /* Z71A Z71V */
149
150/*
151 * This is the main structure, we can use it to store anything interesting
152 * about the hotk device
153 */
154struct asus_hotk {
155 char *name; //laptop name
156 struct acpi_device *device; //the device we are in
157 acpi_handle handle; //the handle of the hotk device
158 char status; //status of the hotk, for LEDs, ...
159 u32 ledd_status; //status of the LED display
160 u8 light_level; //light sensor level
161 u8 light_switch; //light sensor switch value
162 u16 event_count[128]; //count for each event TODO make this better
163};
164
165/*
166 * This header is made available to allow proper configuration given model,
167 * revision number , ... this info cannot go in struct asus_hotk because it is
168 * available before the hotk
169 */
170static struct acpi_table_header *asus_info;
171
172/* The actual device the driver binds to */
173static struct asus_hotk *hotk;
174
175/*
176 * The hotkey driver declaration
177 */
178static int asus_hotk_add(struct acpi_device *device);
179static int asus_hotk_remove(struct acpi_device *device, int type);
180static struct acpi_driver asus_hotk_driver = {
181 .name = ASUS_HOTK_NAME,
182 .class = ASUS_HOTK_CLASS,
183 .ids = ASUS_HOTK_HID,
184 .ops = {
185 .add = asus_hotk_add,
186 .remove = asus_hotk_remove,
187 },
188};
189
190/* The backlight device /sys/class/backlight */
191static struct backlight_device *asus_backlight_device;
192
193/*
194 * The backlight class declaration
195 */
196static int read_brightness(struct backlight_device *bd);
197static int update_bl_status(struct backlight_device *bd);
198static struct backlight_properties asusbl_data = {
199 .owner = THIS_MODULE,
200 .get_brightness = read_brightness,
201 .update_status = update_bl_status,
202 .max_brightness = 15,
203};
204
205/* These functions actually update the LED's, and are called from a
206 * workqueue. By doing this as separate work rather than when the LED
207 * subsystem asks, we avoid messing with the Asus ACPI stuff during a
208 * potentially bad time, such as a timer interrupt. */
209static struct workqueue_struct *led_workqueue;
210
211#define ASUS_LED(object, ledname) \
212 static void object##_led_set(struct led_classdev *led_cdev, \
213 enum led_brightness value); \
214 static void object##_led_update(struct work_struct *ignored); \
215 static int object##_led_wk; \
216 DECLARE_WORK(object##_led_work, object##_led_update); \
217 static struct led_classdev object##_led = { \
218 .name = "asus:" ledname, \
219 .brightness_set = object##_led_set, \
220 }
221
222ASUS_LED(mled, "mail");
223ASUS_LED(tled, "touchpad");
224ASUS_LED(rled, "record");
225ASUS_LED(pled, "phone");
226
227/*
228 * This function evaluates an ACPI method, given an int as parameter, the
229 * method is searched within the scope of the handle, can be NULL. The output
230 * of the method is written is output, which can also be NULL
231 *
232 * returns 1 if write is successful, 0 else.
233 */
234static int write_acpi_int(acpi_handle handle, const char *method, int val,
235 struct acpi_buffer *output)
236{
237 struct acpi_object_list params; //list of input parameters (an int here)
238 union acpi_object in_obj; //the only param we use
239 acpi_status status;
240
241 params.count = 1;
242 params.pointer = &in_obj;
243 in_obj.type = ACPI_TYPE_INTEGER;
244 in_obj.integer.value = val;
245
246 status = acpi_evaluate_object(handle, (char *)method, &params, output);
247 return (status == AE_OK);
248}
249
250static int read_acpi_int(acpi_handle handle, const char *method, int *val,
251 struct acpi_object_list *params)
252{
253 struct acpi_buffer output;
254 union acpi_object out_obj;
255 acpi_status status;
256
257 output.length = sizeof(out_obj);
258 output.pointer = &out_obj;
259
260 status = acpi_evaluate_object(handle, (char *)method, params, &output);
261 *val = out_obj.integer.value;
262 return (status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER);
263}
264
265static int read_wireless_status(int mask)
266{
267 int status;
268
269 if (!wireless_status_handle)
270 return (hotk->status & mask) ? 1 : 0;
271
272 if (read_acpi_int(wireless_status_handle, NULL, &status, NULL)) {
273 return (status & mask) ? 1 : 0;
274 } else
275 printk(ASUS_WARNING "Error reading Wireless status\n");
276
277 return (hotk->status & mask) ? 1 : 0;
278}
279
280/* Generic LED functions */
281static int read_status(int mask)
282{
283 /* There is a special method for both wireless devices */
284 if (mask == BT_ON || mask == WL_ON)
285 return read_wireless_status(mask);
286
287 return (hotk->status & mask) ? 1 : 0;
288}
289
290static void write_status(acpi_handle handle, int out, int mask, int invert)
291{
292 hotk->status = (out) ? (hotk->status | mask) : (hotk->status & ~mask);
293
294 if (invert) /* invert target value */
295 out = !out & 0x1;
296
297 if (handle && !write_acpi_int(handle, NULL, out, NULL))
298 printk(ASUS_WARNING " write failed\n");
299}
300
301/* /sys/class/led handlers */
302#define ASUS_LED_HANDLER(object, mask, invert) \
303 static void object##_led_set(struct led_classdev *led_cdev, \
304 enum led_brightness value) \
305 { \
306 object##_led_wk = value; \
307 queue_work(led_workqueue, &object##_led_work); \
308 } \
309 static void object##_led_update(struct work_struct *ignored) \
310 { \
311 int value = object##_led_wk; \
312 write_status(object##_set_handle, value, (mask), (invert)); \
313 }
314
315ASUS_LED_HANDLER(mled, MLED_ON, 1);
316ASUS_LED_HANDLER(pled, PLED_ON, 0);
317ASUS_LED_HANDLER(rled, RLED_ON, 0);
318ASUS_LED_HANDLER(tled, TLED_ON, 0);
319
320static int get_lcd_state(void)
321{
322 return read_status(LCD_ON);
323}
324
325static int set_lcd_state(int value)
326{
327 int lcd = 0;
328 acpi_status status = 0;
329
330 lcd = value ? 1 : 0;
331
332 if (lcd == get_lcd_state())
333 return 0;
334
335 if (lcd_switch_handle) {
336 status = acpi_evaluate_object(lcd_switch_handle,
337 NULL, NULL, NULL);
338
339 if (ACPI_FAILURE(status))
340 printk(ASUS_WARNING "Error switching LCD\n");
341 }
342
343 write_status(NULL, lcd, LCD_ON, 0);
344 return 0;
345}
346
347static void lcd_blank(int blank)
348{
349 struct backlight_device *bd = asus_backlight_device;
350
351 if (bd) {
352 down(&bd->sem);
353 if (likely(bd->props)) {
354 bd->props->power = blank;
355 if (likely(bd->props->update_status))
356 bd->props->update_status(bd);
357 }
358 up(&bd->sem);
359 }
360}
361
362static int read_brightness(struct backlight_device *bd)
363{
364 int value;
365
366 if (!read_acpi_int(brightness_get_handle, NULL, &value, NULL))
367 printk(ASUS_WARNING "Error reading brightness\n");
368
369 return value;
370}
371
372static int set_brightness(struct backlight_device *bd, int value)
373{
374 int ret = 0;
375
376 value = (0 < value) ? ((15 < value) ? 15 : value) : 0;
377 /* 0 <= value <= 15 */
378
379 if (!write_acpi_int(brightness_set_handle, NULL, value, NULL)) {
380 printk(ASUS_WARNING "Error changing brightness\n");
381 ret = -EIO;
382 }
383
384 return ret;
385}
386
387static int update_bl_status(struct backlight_device *bd)
388{
389 int rv;
390 int value = bd->props->brightness;
391
392 rv = set_brightness(bd, value);
393 if (rv)
394 return rv;
395
396 value = (bd->props->power == FB_BLANK_UNBLANK) ? 1 : 0;
397 return set_lcd_state(value);
398}
399
400/*
401 * Platform device handlers
402 */
403
404/*
405 * We write our info in page, we begin at offset off and cannot write more
406 * than count bytes. We set eof to 1 if we handle those 2 values. We return the
407 * number of bytes written in page
408 */
409static ssize_t show_infos(struct device *dev,
410 struct device_attribute *attr, char *page)
411{
412 int len = 0;
413 int temp;
414 char buf[16]; //enough for all info
415 /*
416 * We use the easy way, we don't care of off and count, so we don't set eof
417 * to 1
418 */
419
420 len += sprintf(page, ASUS_HOTK_NAME " " ASUS_LAPTOP_VERSION "\n");
421 len += sprintf(page + len, "Model reference : %s\n", hotk->name);
422 /*
423 * The SFUN method probably allows the original driver to get the list
424 * of features supported by a given model. For now, 0x0100 or 0x0800
425 * bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card.
426 * The significance of others is yet to be found.
427 */
428 if (read_acpi_int(hotk->handle, "SFUN", &temp, NULL))
429 len +=
430 sprintf(page + len, "SFUN value : 0x%04x\n", temp);
431 /*
432 * Another value for userspace: the ASYM method returns 0x02 for
433 * battery low and 0x04 for battery critical, its readings tend to be
434 * more accurate than those provided by _BST.
435 * Note: since not all the laptops provide this method, errors are
436 * silently ignored.
437 */
438 if (read_acpi_int(hotk->handle, "ASYM", &temp, NULL))
439 len +=
440 sprintf(page + len, "ASYM value : 0x%04x\n", temp);
441 if (asus_info) {
442 snprintf(buf, 16, "%d", asus_info->length);
443 len += sprintf(page + len, "DSDT length : %s\n", buf);
444 snprintf(buf, 16, "%d", asus_info->checksum);
445 len += sprintf(page + len, "DSDT checksum : %s\n", buf);
446 snprintf(buf, 16, "%d", asus_info->revision);
447 len += sprintf(page + len, "DSDT revision : %s\n", buf);
448 snprintf(buf, 7, "%s", asus_info->oem_id);
449 len += sprintf(page + len, "OEM id : %s\n", buf);
450 snprintf(buf, 9, "%s", asus_info->oem_table_id);
451 len += sprintf(page + len, "OEM table id : %s\n", buf);
452 snprintf(buf, 16, "%x", asus_info->oem_revision);
453 len += sprintf(page + len, "OEM revision : 0x%s\n", buf);
454 snprintf(buf, 5, "%s", asus_info->asl_compiler_id);
455 len += sprintf(page + len, "ASL comp vendor id : %s\n", buf);
456 snprintf(buf, 16, "%x", asus_info->asl_compiler_revision);
457 len += sprintf(page + len, "ASL comp revision : 0x%s\n", buf);
458 }
459
460 return len;
461}
462
463static int parse_arg(const char *buf, unsigned long count, int *val)
464{
465 if (!count)
466 return 0;
467 if (count > 31)
468 return -EINVAL;
469 if (sscanf(buf, "%i", val) != 1)
470 return -EINVAL;
471 return count;
472}
473
474static ssize_t store_status(const char *buf, size_t count,
475 acpi_handle handle, int mask, int invert)
476{
477 int rv, value;
478 int out = 0;
479
480 rv = parse_arg(buf, count, &value);
481 if (rv > 0)
482 out = value ? 1 : 0;
483
484 write_status(handle, out, mask, invert);
485
486 return rv;
487}
488
489/*
490 * LEDD display
491 */
492static ssize_t show_ledd(struct device *dev,
493 struct device_attribute *attr, char *buf)
494{
495 return sprintf(buf, "0x%08x\n", hotk->ledd_status);
496}
497
498static ssize_t store_ledd(struct device *dev, struct device_attribute *attr,
499 const char *buf, size_t count)
500{
501 int rv, value;
502
503 rv = parse_arg(buf, count, &value);
504 if (rv > 0) {
505 if (!write_acpi_int(ledd_set_handle, NULL, value, NULL))
506 printk(ASUS_WARNING "LED display write failed\n");
507 else
508 hotk->ledd_status = (u32) value;
509 }
510 return rv;
511}
512
513/*
514 * WLAN
515 */
516static ssize_t show_wlan(struct device *dev,
517 struct device_attribute *attr, char *buf)
518{
519 return sprintf(buf, "%d\n", read_status(WL_ON));
520}
521
522static ssize_t store_wlan(struct device *dev, struct device_attribute *attr,
523 const char *buf, size_t count)
524{
525 return store_status(buf, count, wl_switch_handle, WL_ON, 0);
526}
527
528/*
529 * Bluetooth
530 */
531static ssize_t show_bluetooth(struct device *dev,
532 struct device_attribute *attr, char *buf)
533{
534 return sprintf(buf, "%d\n", read_status(BT_ON));
535}
536
537static ssize_t store_bluetooth(struct device *dev,
538 struct device_attribute *attr, const char *buf,
539 size_t count)
540{
541 return store_status(buf, count, bt_switch_handle, BT_ON, 0);
542}
543
544/*
545 * Display
546 */
547static void set_display(int value)
548{
549 /* no sanity check needed for now */
550 if (!write_acpi_int(display_set_handle, NULL, value, NULL))
551 printk(ASUS_WARNING "Error setting display\n");
552 return;
553}
554
555static int read_display(void)
556{
557 int value = 0;
558
559 /* In most of the case, we know how to set the display, but sometime
560 we can't read it */
561 if (display_get_handle) {
562 if (!read_acpi_int(display_get_handle, NULL, &value, NULL))
563 printk(ASUS_WARNING "Error reading display status\n");
564 }
565
566 value &= 0x0F; /* needed for some models, shouldn't hurt others */
567
568 return value;
569}
570
571/*
572 * Now, *this* one could be more user-friendly, but so far, no-one has
573 * complained. The significance of bits is the same as in store_disp()
574 */
575static ssize_t show_disp(struct device *dev,
576 struct device_attribute *attr, char *buf)
577{
578 return sprintf(buf, "%d\n", read_display());
579}
580
581/*
582 * Experimental support for display switching. As of now: 1 should activate
583 * the LCD output, 2 should do for CRT, 4 for TV-Out and 8 for DVI.
584 * Any combination (bitwise) of these will suffice. I never actually tested 4
585 * displays hooked up simultaneously, so be warned. See the acpi4asus README
586 * for more info.
587 */
588static ssize_t store_disp(struct device *dev, struct device_attribute *attr,
589 const char *buf, size_t count)
590{
591 int rv, value;
592
593 rv = parse_arg(buf, count, &value);
594 if (rv > 0)
595 set_display(value);
596 return rv;
597}
598
599/*
600 * Light Sens
601 */
602static void set_light_sens_switch(int value)
603{
604 if (!write_acpi_int(ls_switch_handle, NULL, value, NULL))
605 printk(ASUS_WARNING "Error setting light sensor switch\n");
606 hotk->light_switch = value;
607}
608
609static ssize_t show_lssw(struct device *dev,
610 struct device_attribute *attr, char *buf)
611{
612 return sprintf(buf, "%d\n", hotk->light_switch);
613}
614
615static ssize_t store_lssw(struct device *dev, struct device_attribute *attr,
616 const char *buf, size_t count)
617{
618 int rv, value;
619
620 rv = parse_arg(buf, count, &value);
621 if (rv > 0)
622 set_light_sens_switch(value ? 1 : 0);
623
624 return rv;
625}
626
627static void set_light_sens_level(int value)
628{
629 if (!write_acpi_int(ls_level_handle, NULL, value, NULL))
630 printk(ASUS_WARNING "Error setting light sensor level\n");
631 hotk->light_level = value;
632}
633
634static ssize_t show_lslvl(struct device *dev,
635 struct device_attribute *attr, char *buf)
636{
637 return sprintf(buf, "%d\n", hotk->light_level);
638}
639
640static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr,
641 const char *buf, size_t count)
642{
643 int rv, value;
644
645 rv = parse_arg(buf, count, &value);
646 if (rv > 0) {
647 value = (0 < value) ? ((15 < value) ? 15 : value) : 0;
648 /* 0 <= value <= 15 */
649 set_light_sens_level(value);
650 }
651
652 return rv;
653}
654
655static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
656{
657 /* TODO Find a better way to handle events count. */
658 if (!hotk)
659 return;
660
661 /*
662 * We need to tell the backlight device when the backlight power is
663 * switched
664 */
665 if (event == ATKD_LCD_ON) {
666 write_status(NULL, 1, LCD_ON, 0);
667 lcd_blank(FB_BLANK_UNBLANK);
668 } else if (event == ATKD_LCD_OFF) {
669 write_status(NULL, 0, LCD_ON, 0);
670 lcd_blank(FB_BLANK_POWERDOWN);
671 }
672
673 acpi_bus_generate_event(hotk->device, event,
674 hotk->event_count[event % 128]++);
675
676 return;
677}
678
679#define ASUS_CREATE_DEVICE_ATTR(_name) \
680 struct device_attribute dev_attr_##_name = { \
681 .attr = { \
682 .name = __stringify(_name), \
683 .mode = 0, \
684 .owner = THIS_MODULE }, \
685 .show = NULL, \
686 .store = NULL, \
687 }
688
689#define ASUS_SET_DEVICE_ATTR(_name, _mode, _show, _store) \
690 do { \
691 dev_attr_##_name.attr.mode = _mode; \
692 dev_attr_##_name.show = _show; \
693 dev_attr_##_name.store = _store; \
694 } while(0)
695
696static ASUS_CREATE_DEVICE_ATTR(infos);
697static ASUS_CREATE_DEVICE_ATTR(wlan);
698static ASUS_CREATE_DEVICE_ATTR(bluetooth);
699static ASUS_CREATE_DEVICE_ATTR(display);
700static ASUS_CREATE_DEVICE_ATTR(ledd);
701static ASUS_CREATE_DEVICE_ATTR(ls_switch);
702static ASUS_CREATE_DEVICE_ATTR(ls_level);
703
704static struct attribute *asuspf_attributes[] = {
705 &dev_attr_infos.attr,
706 &dev_attr_wlan.attr,
707 &dev_attr_bluetooth.attr,
708 &dev_attr_display.attr,
709 &dev_attr_ledd.attr,
710 &dev_attr_ls_switch.attr,
711 &dev_attr_ls_level.attr,
712 NULL
713};
714
715static struct attribute_group asuspf_attribute_group = {
716 .attrs = asuspf_attributes
717};
718
719static struct platform_driver asuspf_driver = {
720 .driver = {
721 .name = ASUS_HOTK_FILE,
722 .owner = THIS_MODULE,
723 }
724};
725
726static struct platform_device *asuspf_device;
727
728static void asus_hotk_add_fs(void)
729{
730 ASUS_SET_DEVICE_ATTR(infos, 0444, show_infos, NULL);
731
732 if (wl_switch_handle)
733 ASUS_SET_DEVICE_ATTR(wlan, 0644, show_wlan, store_wlan);
734
735 if (bt_switch_handle)
736 ASUS_SET_DEVICE_ATTR(bluetooth, 0644,
737 show_bluetooth, store_bluetooth);
738
739 if (display_set_handle && display_get_handle)
740 ASUS_SET_DEVICE_ATTR(display, 0644, show_disp, store_disp);
741 else if (display_set_handle)
742 ASUS_SET_DEVICE_ATTR(display, 0200, NULL, store_disp);
743
744 if (ledd_set_handle)
745 ASUS_SET_DEVICE_ATTR(ledd, 0644, show_ledd, store_ledd);
746
747 if (ls_switch_handle && ls_level_handle) {
748 ASUS_SET_DEVICE_ATTR(ls_level, 0644, show_lslvl, store_lslvl);
749 ASUS_SET_DEVICE_ATTR(ls_switch, 0644, show_lssw, store_lssw);
750 }
751}
752
753static int asus_handle_init(char *name, acpi_handle * handle,
754 char **paths, int num_paths)
755{
756 int i;
757 acpi_status status;
758
759 for (i = 0; i < num_paths; i++) {
760 status = acpi_get_handle(NULL, paths[i], handle);
761 if (ACPI_SUCCESS(status))
762 return 0;
763 }
764
765 *handle = NULL;
766 return -ENODEV;
767}
768
769#define ASUS_HANDLE_INIT(object) \
770 asus_handle_init(#object, &object##_handle, object##_paths, \
771 ARRAY_SIZE(object##_paths))
772
773/*
774 * This function is used to initialize the hotk with right values. In this
775 * method, we can make all the detection we want, and modify the hotk struct
776 */
777static int asus_hotk_get_info(void)
778{
779 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
780 union acpi_object *model = NULL;
781 int bsts_result, hwrs_result;
782 char *string = NULL;
783 acpi_status status;
784
785 /*
786 * Get DSDT headers early enough to allow for differentiating between
787 * models, but late enough to allow acpi_bus_register_driver() to fail
788 * before doing anything ACPI-specific. Should we encounter a machine,
789 * which needs special handling (i.e. its hotkey device has a different
790 * HID), this bit will be moved. A global variable asus_info contains
791 * the DSDT header.
792 */
793 status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus_info);
794 if (ACPI_FAILURE(status))
795 printk(ASUS_WARNING "Couldn't get the DSDT table header\n");
796
797 /* We have to write 0 on init this far for all ASUS models */
798 if (!write_acpi_int(hotk->handle, "INIT", 0, &buffer)) {
799 printk(ASUS_ERR "Hotkey initialization failed\n");
800 return -ENODEV;
801 }
802
803 /* This needs to be called for some laptops to init properly */
804 if (!read_acpi_int(hotk->handle, "BSTS", &bsts_result, NULL))
805 printk(ASUS_WARNING "Error calling BSTS\n");
806 else if (bsts_result)
807 printk(ASUS_NOTICE "BSTS called, 0x%02x returned\n",
808 bsts_result);
809
810 /*
811 * Try to match the object returned by INIT to the specific model.
812 * Handle every possible object (or the lack of thereof) the DSDT
813 * writers might throw at us. When in trouble, we pass NULL to
814 * asus_model_match() and try something completely different.
815 */
816 if (buffer.pointer) {
817 model = buffer.pointer;
818 switch (model->type) {
819 case ACPI_TYPE_STRING:
820 string = model->string.pointer;
821 break;
822 case ACPI_TYPE_BUFFER:
823 string = model->buffer.pointer;
824 break;
825 default:
826 string = "";
827 break;
828 }
829 }
830 hotk->name = kstrdup(string, GFP_KERNEL);
831 if (!hotk->name)
832 return -ENOMEM;
833
834 if (*string)
835 printk(ASUS_NOTICE " %s model detected\n", string);
836
837 ASUS_HANDLE_INIT(mled_set);
838 ASUS_HANDLE_INIT(tled_set);
839 ASUS_HANDLE_INIT(rled_set);
840 ASUS_HANDLE_INIT(pled_set);
841
842 ASUS_HANDLE_INIT(ledd_set);
843
844 /*
845 * The HWRS method return informations about the hardware.
846 * 0x80 bit is for WLAN, 0x100 for Bluetooth.
847 * The significance of others is yet to be found.
848 * If we don't find the method, we assume the device are present.
849 */
850 if (!read_acpi_int(hotk->handle, "HRWS", &hwrs_result, NULL))
851 hwrs_result = WL_HWRS | BT_HWRS;
852
853 if (hwrs_result & WL_HWRS)
854 ASUS_HANDLE_INIT(wl_switch);
855 if (hwrs_result & BT_HWRS)
856 ASUS_HANDLE_INIT(bt_switch);
857
858 ASUS_HANDLE_INIT(wireless_status);
859
860 ASUS_HANDLE_INIT(brightness_set);
861 ASUS_HANDLE_INIT(brightness_get);
862
863 ASUS_HANDLE_INIT(lcd_switch);
864
865 ASUS_HANDLE_INIT(display_set);
866 ASUS_HANDLE_INIT(display_get);
867
868 /* There is a lot of models with "ALSL", but a few get
869 a real light sens, so we need to check it. */
870 if (ASUS_HANDLE_INIT(ls_switch))
871 ASUS_HANDLE_INIT(ls_level);
872
873 kfree(model);
874
875 return AE_OK;
876}
877
878static int asus_hotk_check(void)
879{
880 int result = 0;
881
882 result = acpi_bus_get_status(hotk->device);
883 if (result)
884 return result;
885
886 if (hotk->device->status.present) {
887 result = asus_hotk_get_info();
888 } else {
889 printk(ASUS_ERR "Hotkey device not present, aborting\n");
890 return -EINVAL;
891 }
892
893 return result;
894}
895
896static int asus_hotk_found;
897
898static int asus_hotk_add(struct acpi_device *device)
899{
900 acpi_status status = AE_OK;
901 int result;
902
903 if (!device)
904 return -EINVAL;
905
906 printk(ASUS_NOTICE "Asus Laptop Support version %s\n",
907 ASUS_LAPTOP_VERSION);
908
909 hotk = kmalloc(sizeof(struct asus_hotk), GFP_KERNEL);
910 if (!hotk)
911 return -ENOMEM;
912 memset(hotk, 0, sizeof(struct asus_hotk));
913
914 hotk->handle = device->handle;
915 strcpy(acpi_device_name(device), ASUS_HOTK_DEVICE_NAME);
916 strcpy(acpi_device_class(device), ASUS_HOTK_CLASS);
917 acpi_driver_data(device) = hotk;
918 hotk->device = device;
919
920 result = asus_hotk_check();
921 if (result)
922 goto end;
923
924 asus_hotk_add_fs();
925
926 /*
927 * We install the handler, it will receive the hotk in parameter, so, we
928 * could add other data to the hotk struct
929 */
930 status = acpi_install_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY,
931 asus_hotk_notify, hotk);
932 if (ACPI_FAILURE(status))
933 printk(ASUS_ERR "Error installing notify handler\n");
934
935 asus_hotk_found = 1;
936
937 /* WLED and BLED are on by default */
938 write_status(bt_switch_handle, 1, BT_ON, 0);
939 write_status(wl_switch_handle, 1, WL_ON, 0);
940
941 /* LCD Backlight is on by default */
942 write_status(NULL, 1, LCD_ON, 0);
943
944 /* LED display is off by default */
945 hotk->ledd_status = 0xFFF;
946
947 /* Set initial values of light sensor and level */
948 hotk->light_switch = 1; /* Default to light sensor disabled */
949 hotk->light_level = 0; /* level 5 for sensor sensitivity */
950
951 if (ls_switch_handle)
952 set_light_sens_switch(hotk->light_switch);
953
954 if (ls_level_handle)
955 set_light_sens_level(hotk->light_level);
956
957 end:
958 if (result) {
959 kfree(hotk->name);
960 kfree(hotk);
961 }
962
963 return result;
964}
965
966static int asus_hotk_remove(struct acpi_device *device, int type)
967{
968 acpi_status status = 0;
969
970 if (!device || !acpi_driver_data(device))
971 return -EINVAL;
972
973 status = acpi_remove_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY,
974 asus_hotk_notify);
975 if (ACPI_FAILURE(status))
976 printk(ASUS_ERR "Error removing notify handler\n");
977
978 kfree(hotk->name);
979 kfree(hotk);
980
981 return 0;
982}
983
984static void asus_backlight_exit(void)
985{
986 if (asus_backlight_device)
987 backlight_device_unregister(asus_backlight_device);
988}
989
990#define ASUS_LED_UNREGISTER(object) \
991 if(object##_led.class_dev \
992 && !IS_ERR(object##_led.class_dev)) \
993 led_classdev_unregister(&object##_led)
994
995static void asus_led_exit(void)
996{
997 ASUS_LED_UNREGISTER(mled);
998 ASUS_LED_UNREGISTER(tled);
999 ASUS_LED_UNREGISTER(pled);
1000 ASUS_LED_UNREGISTER(rled);
1001
1002 destroy_workqueue(led_workqueue);
1003}
1004
1005static void __exit asus_laptop_exit(void)
1006{
1007 asus_backlight_exit();
1008 asus_led_exit();
1009
1010 acpi_bus_unregister_driver(&asus_hotk_driver);
1011 sysfs_remove_group(&asuspf_device->dev.kobj, &asuspf_attribute_group);
1012 platform_device_unregister(asuspf_device);
1013 platform_driver_unregister(&asuspf_driver);
1014}
1015
1016static int asus_backlight_init(struct device *dev)
1017{
1018 struct backlight_device *bd;
1019
1020 if (brightness_set_handle && lcd_switch_handle) {
1021 bd = backlight_device_register(ASUS_HOTK_FILE, dev,
1022 NULL, &asusbl_data);
1023 if (IS_ERR(bd)) {
1024 printk(ASUS_ERR
1025 "Could not register asus backlight device\n");
1026 asus_backlight_device = NULL;
1027 return PTR_ERR(bd);
1028 }
1029
1030 asus_backlight_device = bd;
1031
1032 down(&bd->sem);
1033 if (likely(bd->props)) {
1034 bd->props->brightness = read_brightness(NULL);
1035 bd->props->power = FB_BLANK_UNBLANK;
1036 if (likely(bd->props->update_status))
1037 bd->props->update_status(bd);
1038 }
1039 up(&bd->sem);
1040 }
1041 return 0;
1042}
1043
1044static int asus_led_register(acpi_handle handle,
1045 struct led_classdev *ldev, struct device *dev)
1046{
1047 if (!handle)
1048 return 0;
1049
1050 return led_classdev_register(dev, ldev);
1051}
1052
1053#define ASUS_LED_REGISTER(object, device) \
1054 asus_led_register(object##_set_handle, &object##_led, device)
1055
1056static int asus_led_init(struct device *dev)
1057{
1058 int rv;
1059
1060 rv = ASUS_LED_REGISTER(mled, dev);
1061 if (rv)
1062 return rv;
1063
1064 rv = ASUS_LED_REGISTER(tled, dev);
1065 if (rv)
1066 return rv;
1067
1068 rv = ASUS_LED_REGISTER(rled, dev);
1069 if (rv)
1070 return rv;
1071
1072 rv = ASUS_LED_REGISTER(pled, dev);
1073 if (rv)
1074 return rv;
1075
1076 led_workqueue = create_singlethread_workqueue("led_workqueue");
1077 if (!led_workqueue)
1078 return -ENOMEM;
1079
1080 return 0;
1081}
1082
1083static int __init asus_laptop_init(void)
1084{
1085 struct device *dev;
1086 int result;
1087
1088 if (acpi_disabled)
1089 return -ENODEV;
1090
1091 if (!acpi_specific_hotkey_enabled) {
1092 printk(ASUS_ERR "Using generic hotkey driver\n");
1093 return -ENODEV;
1094 }
1095
1096 result = acpi_bus_register_driver(&asus_hotk_driver);
1097 if (result < 0)
1098 return result;
1099
1100 /*
1101 * This is a bit of a kludge. We only want this module loaded
1102 * for ASUS systems, but there's currently no way to probe the
1103 * ACPI namespace for ASUS HIDs. So we just return failure if
1104 * we didn't find one, which will cause the module to be
1105 * unloaded.
1106 */
1107 if (!asus_hotk_found) {
1108 acpi_bus_unregister_driver(&asus_hotk_driver);
1109 return -ENODEV;
1110 }
1111
1112 dev = acpi_get_physical_device(hotk->device->handle);
1113
1114 result = asus_backlight_init(dev);
1115 if (result)
1116 goto fail_backlight;
1117
1118 result = asus_led_init(dev);
1119 if (result)
1120 goto fail_led;
1121
1122 /* Register platform stuff */
1123 result = platform_driver_register(&asuspf_driver);
1124 if (result)
1125 goto fail_platform_driver;
1126
1127 asuspf_device = platform_device_alloc(ASUS_HOTK_FILE, -1);
1128 if (!asuspf_device) {
1129 result = -ENOMEM;
1130 goto fail_platform_device1;
1131 }
1132
1133 result = platform_device_add(asuspf_device);
1134 if (result)
1135 goto fail_platform_device2;
1136
1137 result = sysfs_create_group(&asuspf_device->dev.kobj,
1138 &asuspf_attribute_group);
1139 if (result)
1140 goto fail_sysfs;
1141
1142 return 0;
1143
1144 fail_sysfs:
1145 platform_device_del(asuspf_device);
1146
1147 fail_platform_device2:
1148 platform_device_put(asuspf_device);
1149
1150 fail_platform_device1:
1151 platform_driver_unregister(&asuspf_driver);
1152
1153 fail_platform_driver:
1154 asus_led_exit();
1155
1156 fail_led:
1157 asus_backlight_exit();
1158
1159 fail_backlight:
1160
1161 return result;
1162}
1163
1164module_init(asus_laptop_init);
1165module_exit(asus_laptop_exit);
diff --git a/drivers/misc/hdpuftrs/hdpu_cpustate.c b/drivers/misc/hdpuftrs/hdpu_cpustate.c
index 11a801be71c8..ca86f113f36a 100644
--- a/drivers/misc/hdpuftrs/hdpu_cpustate.c
+++ b/drivers/misc/hdpuftrs/hdpu_cpustate.c
@@ -169,7 +169,7 @@ static struct platform_driver hdpu_cpustate_driver = {
169/* 169/*
170 * The various file operations we support. 170 * The various file operations we support.
171 */ 171 */
172static struct file_operations cpustate_fops = { 172static const struct file_operations cpustate_fops = {
173 owner:THIS_MODULE, 173 owner:THIS_MODULE,
174 open:cpustate_open, 174 open:cpustate_open,
175 release:cpustate_release, 175 release:cpustate_release,
diff --git a/drivers/misc/hdpuftrs/hdpu_nexus.c b/drivers/misc/hdpuftrs/hdpu_nexus.c
index ea9d5f233c83..6a51e99a8079 100644
--- a/drivers/misc/hdpuftrs/hdpu_nexus.c
+++ b/drivers/misc/hdpuftrs/hdpu_nexus.c
@@ -72,11 +72,9 @@ static int hdpu_nexus_probe(struct platform_device *pdev)
72 printk("Could not map slot id\n"); 72 printk("Could not map slot id\n");
73 hdpu_slot_id = create_proc_entry("sky_slot_id", 0666, &proc_root); 73 hdpu_slot_id = create_proc_entry("sky_slot_id", 0666, &proc_root);
74 hdpu_slot_id->read_proc = hdpu_slot_id_read; 74 hdpu_slot_id->read_proc = hdpu_slot_id_read;
75 hdpu_slot_id->nlink = 1;
76 75
77 hdpu_chassis_id = create_proc_entry("sky_chassis_id", 0666, &proc_root); 76 hdpu_chassis_id = create_proc_entry("sky_chassis_id", 0666, &proc_root);
78 hdpu_chassis_id->read_proc = hdpu_chassis_id_read; 77 hdpu_chassis_id->read_proc = hdpu_chassis_id_read;
79 hdpu_chassis_id->nlink = 1;
80 return 0; 78 return 0;
81} 79}
82 80
diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c
index b99dc507de2e..c436d3de8b8b 100644
--- a/drivers/misc/ibmasm/ibmasmfs.c
+++ b/drivers/misc/ibmasm/ibmasmfs.c
@@ -156,7 +156,7 @@ static struct inode *ibmasmfs_make_inode(struct super_block *sb, int mode)
156static struct dentry *ibmasmfs_create_file (struct super_block *sb, 156static struct dentry *ibmasmfs_create_file (struct super_block *sb,
157 struct dentry *parent, 157 struct dentry *parent,
158 const char *name, 158 const char *name,
159 struct file_operations *fops, 159 const struct file_operations *fops,
160 void *data, 160 void *data,
161 int mode) 161 int mode)
162{ 162{
@@ -581,28 +581,28 @@ static ssize_t remote_settings_file_write(struct file *file, const char __user *
581 return count; 581 return count;
582} 582}
583 583
584static struct file_operations command_fops = { 584static const struct file_operations command_fops = {
585 .open = command_file_open, 585 .open = command_file_open,
586 .release = command_file_close, 586 .release = command_file_close,
587 .read = command_file_read, 587 .read = command_file_read,
588 .write = command_file_write, 588 .write = command_file_write,
589}; 589};
590 590
591static struct file_operations event_fops = { 591static const struct file_operations event_fops = {
592 .open = event_file_open, 592 .open = event_file_open,
593 .release = event_file_close, 593 .release = event_file_close,
594 .read = event_file_read, 594 .read = event_file_read,
595 .write = event_file_write, 595 .write = event_file_write,
596}; 596};
597 597
598static struct file_operations r_heartbeat_fops = { 598static const struct file_operations r_heartbeat_fops = {
599 .open = r_heartbeat_file_open, 599 .open = r_heartbeat_file_open,
600 .release = r_heartbeat_file_close, 600 .release = r_heartbeat_file_close,
601 .read = r_heartbeat_file_read, 601 .read = r_heartbeat_file_read,
602 .write = r_heartbeat_file_write, 602 .write = r_heartbeat_file_write,
603}; 603};
604 604
605static struct file_operations remote_settings_fops = { 605static const struct file_operations remote_settings_fops = {
606 .open = remote_settings_file_open, 606 .open = remote_settings_file_open,
607 .release = remote_settings_file_close, 607 .release = remote_settings_file_close,
608 .read = remote_settings_file_read, 608 .read = remote_settings_file_read,
diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c
index b995a15b7526..6a5a05d1f392 100644
--- a/drivers/misc/ioc4.c
+++ b/drivers/misc/ioc4.c
@@ -309,7 +309,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
309 ret = -ENODEV; 309 ret = -ENODEV;
310 goto out_pci; 310 goto out_pci;
311 } 311 }
312 if (!request_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs), 312 if (!request_mem_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs),
313 "ioc4_misc")) { 313 "ioc4_misc")) {
314 printk(KERN_WARNING 314 printk(KERN_WARNING
315 "%s: Unable to request IOC4 misc region " 315 "%s: Unable to request IOC4 misc region "
@@ -379,7 +379,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
379 return 0; 379 return 0;
380 380
381out_misc_region: 381out_misc_region:
382 release_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs)); 382 release_mem_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs));
383out_pci: 383out_pci:
384 kfree(idd); 384 kfree(idd);
385out_idd: 385out_idd:
@@ -418,7 +418,7 @@ ioc4_remove(struct pci_dev *pdev)
418 "Device removal may be incomplete.\n", 418 "Device removal may be incomplete.\n",
419 __FUNCTION__, pci_name(idd->idd_pdev)); 419 __FUNCTION__, pci_name(idd->idd_pdev));
420 } 420 }
421 release_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs)); 421 release_mem_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs));
422 422
423 /* Disable IOC4 and relinquish */ 423 /* Disable IOC4 and relinquish */
424 pci_disable_device(pdev); 424 pci_disable_device(pdev);
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
index db9d7df75ae0..552b7957a92a 100644
--- a/drivers/misc/lkdtm.c
+++ b/drivers/misc/lkdtm.c
@@ -108,8 +108,8 @@ static struct jprobe lkdtm;
108static int lkdtm_parse_commandline(void); 108static int lkdtm_parse_commandline(void);
109static void lkdtm_handler(void); 109static void lkdtm_handler(void);
110 110
111static char* cpoint_name = INVALID; 111static char* cpoint_name;
112static char* cpoint_type = NONE; 112static char* cpoint_type;
113static int cpoint_count = DEFAULT_COUNT; 113static int cpoint_count = DEFAULT_COUNT;
114static int recur_count = REC_NUM_DEFAULT; 114static int recur_count = REC_NUM_DEFAULT;
115 115
diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c
index 2ab7add78f94..bc60e2fc3c2c 100644
--- a/drivers/misc/tifm_7xx1.c
+++ b/drivers/misc/tifm_7xx1.c
@@ -11,66 +11,25 @@
11 11
12#include <linux/tifm.h> 12#include <linux/tifm.h>
13#include <linux/dma-mapping.h> 13#include <linux/dma-mapping.h>
14#include <linux/freezer.h>
14 15
15#define DRIVER_NAME "tifm_7xx1" 16#define DRIVER_NAME "tifm_7xx1"
16#define DRIVER_VERSION "0.6" 17#define DRIVER_VERSION "0.7"
17 18
18static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock) 19static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock)
19{ 20{
20 int cnt;
21 unsigned long flags;
22
23 spin_lock_irqsave(&fm->lock, flags);
24 if (!fm->inhibit_new_cards) {
25 for (cnt = 0; cnt < fm->max_sockets; cnt++) {
26 if (fm->sockets[cnt] == sock) {
27 fm->remove_mask |= (1 << cnt);
28 queue_work(fm->wq, &fm->media_remover);
29 break;
30 }
31 }
32 }
33 spin_unlock_irqrestore(&fm->lock, flags);
34}
35
36static void tifm_7xx1_remove_media(struct work_struct *work)
37{
38 struct tifm_adapter *fm =
39 container_of(work, struct tifm_adapter, media_remover);
40 unsigned long flags; 21 unsigned long flags;
41 int cnt;
42 struct tifm_dev *sock;
43 22
44 if (!class_device_get(&fm->cdev))
45 return;
46 spin_lock_irqsave(&fm->lock, flags); 23 spin_lock_irqsave(&fm->lock, flags);
47 for (cnt = 0; cnt < fm->max_sockets; cnt++) { 24 fm->socket_change_set |= 1 << sock->socket_id;
48 if (fm->sockets[cnt] && (fm->remove_mask & (1 << cnt))) { 25 wake_up_all(&fm->change_set_notify);
49 printk(KERN_INFO DRIVER_NAME
50 ": demand removing card from socket %d\n", cnt);
51 sock = fm->sockets[cnt];
52 fm->sockets[cnt] = NULL;
53 fm->remove_mask &= ~(1 << cnt);
54
55 writel(0x0e00, sock->addr + SOCK_CONTROL);
56
57 writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt,
58 fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
59 writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt,
60 fm->addr + FM_SET_INTERRUPT_ENABLE);
61
62 spin_unlock_irqrestore(&fm->lock, flags);
63 device_unregister(&sock->dev);
64 spin_lock_irqsave(&fm->lock, flags);
65 }
66 }
67 spin_unlock_irqrestore(&fm->lock, flags); 26 spin_unlock_irqrestore(&fm->lock, flags);
68 class_device_put(&fm->cdev);
69} 27}
70 28
71static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id) 29static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id)
72{ 30{
73 struct tifm_adapter *fm = dev_id; 31 struct tifm_adapter *fm = dev_id;
32 struct tifm_dev *sock;
74 unsigned int irq_status; 33 unsigned int irq_status;
75 unsigned int sock_irq_status, cnt; 34 unsigned int sock_irq_status, cnt;
76 35
@@ -84,42 +43,32 @@ static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id)
84 if (irq_status & TIFM_IRQ_ENABLE) { 43 if (irq_status & TIFM_IRQ_ENABLE) {
85 writel(TIFM_IRQ_ENABLE, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); 44 writel(TIFM_IRQ_ENABLE, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
86 45
87 for (cnt = 0; cnt < fm->max_sockets; cnt++) { 46 for (cnt = 0; cnt < fm->num_sockets; cnt++) {
88 sock_irq_status = (irq_status >> cnt) & 47 sock = fm->sockets[cnt];
89 (TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK); 48 sock_irq_status = (irq_status >> cnt)
90 49 & (TIFM_IRQ_FIFOMASK(1)
91 if (fm->sockets[cnt]) { 50 | TIFM_IRQ_CARDMASK(1));
92 if (sock_irq_status &&
93 fm->sockets[cnt]->signal_irq)
94 sock_irq_status = fm->sockets[cnt]->
95 signal_irq(fm->sockets[cnt],
96 sock_irq_status);
97 51
98 if (irq_status & (1 << cnt)) 52 if (sock && sock_irq_status)
99 fm->remove_mask |= 1 << cnt; 53 sock->signal_irq(sock, sock_irq_status);
100 } else {
101 if (irq_status & (1 << cnt))
102 fm->insert_mask |= 1 << cnt;
103 }
104 } 54 }
55
56 fm->socket_change_set |= irq_status
57 & ((1 << fm->num_sockets) - 1);
105 } 58 }
106 writel(irq_status, fm->addr + FM_INTERRUPT_STATUS); 59 writel(irq_status, fm->addr + FM_INTERRUPT_STATUS);
107 60
108 if (!fm->inhibit_new_cards) { 61 if (!fm->socket_change_set)
109 if (!fm->remove_mask && !fm->insert_mask) { 62 writel(TIFM_IRQ_ENABLE, fm->addr + FM_SET_INTERRUPT_ENABLE);
110 writel(TIFM_IRQ_ENABLE, 63 else
111 fm->addr + FM_SET_INTERRUPT_ENABLE); 64 wake_up_all(&fm->change_set_notify);
112 } else {
113 queue_work(fm->wq, &fm->media_remover);
114 queue_work(fm->wq, &fm->media_inserter);
115 }
116 }
117 65
118 spin_unlock(&fm->lock); 66 spin_unlock(&fm->lock);
119 return IRQ_HANDLED; 67 return IRQ_HANDLED;
120} 68}
121 69
122static tifm_media_id tifm_7xx1_toggle_sock_power(char __iomem *sock_addr, int is_x2) 70static tifm_media_id tifm_7xx1_toggle_sock_power(char __iomem *sock_addr,
71 int is_x2)
123{ 72{
124 unsigned int s_state; 73 unsigned int s_state;
125 int cnt; 74 int cnt;
@@ -127,8 +76,8 @@ static tifm_media_id tifm_7xx1_toggle_sock_power(char __iomem *sock_addr, int is
127 writel(0x0e00, sock_addr + SOCK_CONTROL); 76 writel(0x0e00, sock_addr + SOCK_CONTROL);
128 77
129 for (cnt = 0; cnt < 100; cnt++) { 78 for (cnt = 0; cnt < 100; cnt++) {
130 if (!(TIFM_SOCK_STATE_POWERED & 79 if (!(TIFM_SOCK_STATE_POWERED
131 readl(sock_addr + SOCK_PRESENT_STATE))) 80 & readl(sock_addr + SOCK_PRESENT_STATE)))
132 break; 81 break;
133 msleep(10); 82 msleep(10);
134 } 83 }
@@ -151,8 +100,8 @@ static tifm_media_id tifm_7xx1_toggle_sock_power(char __iomem *sock_addr, int is
151 } 100 }
152 101
153 for (cnt = 0; cnt < 100; cnt++) { 102 for (cnt = 0; cnt < 100; cnt++) {
154 if ((TIFM_SOCK_STATE_POWERED & 103 if ((TIFM_SOCK_STATE_POWERED
155 readl(sock_addr + SOCK_PRESENT_STATE))) 104 & readl(sock_addr + SOCK_PRESENT_STATE)))
156 break; 105 break;
157 msleep(10); 106 msleep(10);
158 } 107 }
@@ -170,130 +119,209 @@ tifm_7xx1_sock_addr(char __iomem *base_addr, unsigned int sock_num)
170 return base_addr + ((sock_num + 1) << 10); 119 return base_addr + ((sock_num + 1) << 10);
171} 120}
172 121
173static void tifm_7xx1_insert_media(struct work_struct *work) 122static int tifm_7xx1_switch_media(void *data)
174{ 123{
175 struct tifm_adapter *fm = 124 struct tifm_adapter *fm = data;
176 container_of(work, struct tifm_adapter, media_inserter);
177 unsigned long flags; 125 unsigned long flags;
178 tifm_media_id media_id; 126 tifm_media_id media_id;
179 char *card_name = "xx"; 127 char *card_name = "xx";
180 int cnt, ok_to_register; 128 int cnt, rc;
181 unsigned int insert_mask; 129 struct tifm_dev *sock;
182 struct tifm_dev *new_sock = NULL; 130 unsigned int socket_change_set;
183 131
184 if (!class_device_get(&fm->cdev)) 132 while (1) {
185 return; 133 rc = wait_event_interruptible(fm->change_set_notify,
186 spin_lock_irqsave(&fm->lock, flags); 134 fm->socket_change_set);
187 insert_mask = fm->insert_mask; 135 if (rc == -ERESTARTSYS)
188 fm->insert_mask = 0; 136 try_to_freeze();
189 if (fm->inhibit_new_cards) { 137
138 spin_lock_irqsave(&fm->lock, flags);
139 socket_change_set = fm->socket_change_set;
140 fm->socket_change_set = 0;
141
142 dev_dbg(fm->dev, "checking media set %x\n",
143 socket_change_set);
144
145 if (kthread_should_stop())
146 socket_change_set = (1 << fm->num_sockets) - 1;
190 spin_unlock_irqrestore(&fm->lock, flags); 147 spin_unlock_irqrestore(&fm->lock, flags);
191 class_device_put(&fm->cdev);
192 return;
193 }
194 spin_unlock_irqrestore(&fm->lock, flags);
195 148
196 for (cnt = 0; cnt < fm->max_sockets; cnt++) { 149 if (!socket_change_set)
197 if (!(insert_mask & (1 << cnt)))
198 continue; 150 continue;
199 151
200 media_id = tifm_7xx1_toggle_sock_power(tifm_7xx1_sock_addr(fm->addr, cnt), 152 spin_lock_irqsave(&fm->lock, flags);
201 fm->max_sockets == 2); 153 for (cnt = 0; cnt < fm->num_sockets; cnt++) {
202 if (media_id) { 154 if (!(socket_change_set & (1 << cnt)))
203 ok_to_register = 0; 155 continue;
204 new_sock = tifm_alloc_device(fm, cnt); 156 sock = fm->sockets[cnt];
205 if (new_sock) { 157 if (sock) {
206 new_sock->addr = tifm_7xx1_sock_addr(fm->addr,
207 cnt);
208 new_sock->media_id = media_id;
209 switch (media_id) {
210 case 1:
211 card_name = "xd";
212 break;
213 case 2:
214 card_name = "ms";
215 break;
216 case 3:
217 card_name = "sd";
218 break;
219 default:
220 break;
221 }
222 snprintf(new_sock->dev.bus_id, BUS_ID_SIZE,
223 "tifm_%s%u:%u", card_name, fm->id, cnt);
224 printk(KERN_INFO DRIVER_NAME 158 printk(KERN_INFO DRIVER_NAME
225 ": %s card detected in socket %d\n", 159 ": demand removing card from socket %d\n",
226 card_name, cnt); 160 cnt);
161 fm->sockets[cnt] = NULL;
162 spin_unlock_irqrestore(&fm->lock, flags);
163 device_unregister(&sock->dev);
227 spin_lock_irqsave(&fm->lock, flags); 164 spin_lock_irqsave(&fm->lock, flags);
228 if (!fm->sockets[cnt]) { 165 writel(0x0e00,
229 fm->sockets[cnt] = new_sock; 166 tifm_7xx1_sock_addr(fm->addr, cnt)
230 ok_to_register = 1; 167 + SOCK_CONTROL);
168 }
169 if (kthread_should_stop())
170 continue;
171
172 spin_unlock_irqrestore(&fm->lock, flags);
173 media_id = tifm_7xx1_toggle_sock_power(
174 tifm_7xx1_sock_addr(fm->addr, cnt),
175 fm->num_sockets == 2);
176 if (media_id) {
177 sock = tifm_alloc_device(fm);
178 if (sock) {
179 sock->addr = tifm_7xx1_sock_addr(fm->addr,
180 cnt);
181 sock->media_id = media_id;
182 sock->socket_id = cnt;
183 switch (media_id) {
184 case 1:
185 card_name = "xd";
186 break;
187 case 2:
188 card_name = "ms";
189 break;
190 case 3:
191 card_name = "sd";
192 break;
193 default:
194 tifm_free_device(&sock->dev);
195 spin_lock_irqsave(&fm->lock, flags);
196 continue;
197 }
198 snprintf(sock->dev.bus_id, BUS_ID_SIZE,
199 "tifm_%s%u:%u", card_name,
200 fm->id, cnt);
201 printk(KERN_INFO DRIVER_NAME
202 ": %s card detected in socket %d\n",
203 card_name, cnt);
204 if (!device_register(&sock->dev)) {
205 spin_lock_irqsave(&fm->lock, flags);
206 if (!fm->sockets[cnt]) {
207 fm->sockets[cnt] = sock;
208 sock = NULL;
209 }
210 spin_unlock_irqrestore(&fm->lock, flags);
211 }
212 if (sock)
213 tifm_free_device(&sock->dev);
231 } 214 }
215 spin_lock_irqsave(&fm->lock, flags);
216 }
217 }
218
219 if (!kthread_should_stop()) {
220 writel(TIFM_IRQ_FIFOMASK(socket_change_set)
221 | TIFM_IRQ_CARDMASK(socket_change_set),
222 fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
223 writel(TIFM_IRQ_FIFOMASK(socket_change_set)
224 | TIFM_IRQ_CARDMASK(socket_change_set),
225 fm->addr + FM_SET_INTERRUPT_ENABLE);
226 writel(TIFM_IRQ_ENABLE,
227 fm->addr + FM_SET_INTERRUPT_ENABLE);
228 spin_unlock_irqrestore(&fm->lock, flags);
229 } else {
230 for (cnt = 0; cnt < fm->num_sockets; cnt++) {
231 if (fm->sockets[cnt])
232 fm->socket_change_set |= 1 << cnt;
233 }
234 if (!fm->socket_change_set) {
235 spin_unlock_irqrestore(&fm->lock, flags);
236 return 0;
237 } else {
232 spin_unlock_irqrestore(&fm->lock, flags); 238 spin_unlock_irqrestore(&fm->lock, flags);
233 if (!ok_to_register ||
234 device_register(&new_sock->dev)) {
235 spin_lock_irqsave(&fm->lock, flags);
236 fm->sockets[cnt] = NULL;
237 spin_unlock_irqrestore(&fm->lock,
238 flags);
239 tifm_free_device(&new_sock->dev);
240 }
241 } 239 }
242 } 240 }
243 writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt,
244 fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
245 writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt,
246 fm->addr + FM_SET_INTERRUPT_ENABLE);
247 } 241 }
248 242 return 0;
249 writel(TIFM_IRQ_ENABLE, fm->addr + FM_SET_INTERRUPT_ENABLE);
250 class_device_put(&fm->cdev);
251} 243}
252 244
245#ifdef CONFIG_PM
246
253static int tifm_7xx1_suspend(struct pci_dev *dev, pm_message_t state) 247static int tifm_7xx1_suspend(struct pci_dev *dev, pm_message_t state)
254{ 248{
255 struct tifm_adapter *fm = pci_get_drvdata(dev); 249 dev_dbg(&dev->dev, "suspending host\n");
256 unsigned long flags;
257 250
258 spin_lock_irqsave(&fm->lock, flags); 251 pci_save_state(dev);
259 fm->inhibit_new_cards = 1; 252 pci_enable_wake(dev, pci_choose_state(dev, state), 0);
260 fm->remove_mask = 0xf; 253 pci_disable_device(dev);
261 fm->insert_mask = 0; 254 pci_set_power_state(dev, pci_choose_state(dev, state));
262 writel(TIFM_IRQ_ENABLE, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
263 spin_unlock_irqrestore(&fm->lock, flags);
264 flush_workqueue(fm->wq);
265
266 tifm_7xx1_remove_media(&fm->media_remover);
267
268 pci_set_power_state(dev, PCI_D3hot);
269 pci_disable_device(dev);
270 pci_save_state(dev);
271 return 0; 255 return 0;
272} 256}
273 257
274static int tifm_7xx1_resume(struct pci_dev *dev) 258static int tifm_7xx1_resume(struct pci_dev *dev)
275{ 259{
276 struct tifm_adapter *fm = pci_get_drvdata(dev); 260 struct tifm_adapter *fm = pci_get_drvdata(dev);
261 int cnt, rc;
277 unsigned long flags; 262 unsigned long flags;
263 tifm_media_id new_ids[fm->num_sockets];
278 264
265 pci_set_power_state(dev, PCI_D0);
279 pci_restore_state(dev); 266 pci_restore_state(dev);
280 pci_enable_device(dev); 267 rc = pci_enable_device(dev);
281 pci_set_power_state(dev, PCI_D0); 268 if (rc)
282 pci_set_master(dev); 269 return rc;
270 pci_set_master(dev);
283 271
272 dev_dbg(&dev->dev, "resuming host\n");
273
274 for (cnt = 0; cnt < fm->num_sockets; cnt++)
275 new_ids[cnt] = tifm_7xx1_toggle_sock_power(
276 tifm_7xx1_sock_addr(fm->addr, cnt),
277 fm->num_sockets == 2);
284 spin_lock_irqsave(&fm->lock, flags); 278 spin_lock_irqsave(&fm->lock, flags);
285 fm->inhibit_new_cards = 0; 279 fm->socket_change_set = 0;
286 writel(TIFM_IRQ_SETALL, fm->addr + FM_INTERRUPT_STATUS); 280 for (cnt = 0; cnt < fm->num_sockets; cnt++) {
287 writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); 281 if (fm->sockets[cnt]) {
288 writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SETALLSOCK, 282 if (fm->sockets[cnt]->media_id == new_ids[cnt])
289 fm->addr + FM_SET_INTERRUPT_ENABLE); 283 fm->socket_change_set |= 1 << cnt;
290 fm->insert_mask = 0xf; 284
285 fm->sockets[cnt]->media_id = new_ids[cnt];
286 }
287 }
288
289 writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
290 fm->addr + FM_SET_INTERRUPT_ENABLE);
291 if (!fm->socket_change_set) {
292 spin_unlock_irqrestore(&fm->lock, flags);
293 return 0;
294 } else {
295 fm->socket_change_set = 0;
296 spin_unlock_irqrestore(&fm->lock, flags);
297 }
298
299 wait_event_timeout(fm->change_set_notify, fm->socket_change_set, HZ);
300
301 spin_lock_irqsave(&fm->lock, flags);
302 writel(TIFM_IRQ_FIFOMASK(fm->socket_change_set)
303 | TIFM_IRQ_CARDMASK(fm->socket_change_set),
304 fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
305 writel(TIFM_IRQ_FIFOMASK(fm->socket_change_set)
306 | TIFM_IRQ_CARDMASK(fm->socket_change_set),
307 fm->addr + FM_SET_INTERRUPT_ENABLE);
308 writel(TIFM_IRQ_ENABLE,
309 fm->addr + FM_SET_INTERRUPT_ENABLE);
310 fm->socket_change_set = 0;
311
291 spin_unlock_irqrestore(&fm->lock, flags); 312 spin_unlock_irqrestore(&fm->lock, flags);
292 return 0; 313 return 0;
293} 314}
294 315
316#else
317
318#define tifm_7xx1_suspend NULL
319#define tifm_7xx1_resume NULL
320
321#endif /* CONFIG_PM */
322
295static int tifm_7xx1_probe(struct pci_dev *dev, 323static int tifm_7xx1_probe(struct pci_dev *dev,
296 const struct pci_device_id *dev_id) 324 const struct pci_device_id *dev_id)
297{ 325{
298 struct tifm_adapter *fm; 326 struct tifm_adapter *fm;
299 int pci_dev_busy = 0; 327 int pci_dev_busy = 0;
@@ -324,36 +352,34 @@ static int tifm_7xx1_probe(struct pci_dev *dev,
324 } 352 }
325 353
326 fm->dev = &dev->dev; 354 fm->dev = &dev->dev;
327 fm->max_sockets = (dev->device == 0x803B) ? 2 : 4; 355 fm->num_sockets = (dev->device == PCI_DEVICE_ID_TI_XX21_XX11_FM)
328 fm->sockets = kzalloc(sizeof(struct tifm_dev*) * fm->max_sockets, 356 ? 4 : 2;
329 GFP_KERNEL); 357 fm->sockets = kzalloc(sizeof(struct tifm_dev*) * fm->num_sockets,
358 GFP_KERNEL);
330 if (!fm->sockets) 359 if (!fm->sockets)
331 goto err_out_free; 360 goto err_out_free;
332 361
333 INIT_WORK(&fm->media_inserter, tifm_7xx1_insert_media);
334 INIT_WORK(&fm->media_remover, tifm_7xx1_remove_media);
335 fm->eject = tifm_7xx1_eject; 362 fm->eject = tifm_7xx1_eject;
336 pci_set_drvdata(dev, fm); 363 pci_set_drvdata(dev, fm);
337 364
338 fm->addr = ioremap(pci_resource_start(dev, 0), 365 fm->addr = ioremap(pci_resource_start(dev, 0),
339 pci_resource_len(dev, 0)); 366 pci_resource_len(dev, 0));
340 if (!fm->addr) 367 if (!fm->addr)
341 goto err_out_free; 368 goto err_out_free;
342 369
343 rc = request_irq(dev->irq, tifm_7xx1_isr, SA_SHIRQ, DRIVER_NAME, fm); 370 rc = request_irq(dev->irq, tifm_7xx1_isr, IRQF_SHARED, DRIVER_NAME, fm);
344 if (rc) 371 if (rc)
345 goto err_out_unmap; 372 goto err_out_unmap;
346 373
347 rc = tifm_add_adapter(fm); 374 init_waitqueue_head(&fm->change_set_notify);
375 rc = tifm_add_adapter(fm, tifm_7xx1_switch_media);
348 if (rc) 376 if (rc)
349 goto err_out_irq; 377 goto err_out_irq;
350 378
351 writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); 379 writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
352 writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SETALLSOCK, 380 writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
353 fm->addr + FM_SET_INTERRUPT_ENABLE); 381 fm->addr + FM_SET_INTERRUPT_ENABLE);
354 382 wake_up_process(fm->media_switcher);
355 fm->insert_mask = 0xf;
356
357 return 0; 383 return 0;
358 384
359err_out_irq: 385err_out_irq:
@@ -377,19 +403,15 @@ static void tifm_7xx1_remove(struct pci_dev *dev)
377 struct tifm_adapter *fm = pci_get_drvdata(dev); 403 struct tifm_adapter *fm = pci_get_drvdata(dev);
378 unsigned long flags; 404 unsigned long flags;
379 405
406 writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
407 mmiowb();
408 free_irq(dev->irq, fm);
409
380 spin_lock_irqsave(&fm->lock, flags); 410 spin_lock_irqsave(&fm->lock, flags);
381 fm->inhibit_new_cards = 1; 411 fm->socket_change_set = (1 << fm->num_sockets) - 1;
382 fm->remove_mask = 0xf;
383 fm->insert_mask = 0;
384 writel(TIFM_IRQ_ENABLE, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
385 spin_unlock_irqrestore(&fm->lock, flags); 412 spin_unlock_irqrestore(&fm->lock, flags);
386 413
387 flush_workqueue(fm->wq); 414 kthread_stop(fm->media_switcher);
388
389 tifm_7xx1_remove_media(&fm->media_remover);
390
391 writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
392 free_irq(dev->irq, fm);
393 415
394 tifm_remove_adapter(fm); 416 tifm_remove_adapter(fm);
395 417
@@ -404,10 +426,12 @@ static void tifm_7xx1_remove(struct pci_dev *dev)
404} 426}
405 427
406static struct pci_device_id tifm_7xx1_pci_tbl [] = { 428static struct pci_device_id tifm_7xx1_pci_tbl [] = {
407 { PCI_VENDOR_ID_TI, 0x8033, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 429 { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX21_XX11_FM, PCI_ANY_ID,
408 0 }, /* xx21 - the one I have */ 430 PCI_ANY_ID, 0, 0, 0 }, /* xx21 - the one I have */
409 { PCI_VENDOR_ID_TI, 0x803B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 431 { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX12_FM, PCI_ANY_ID,
410 0 }, /* xx12 - should be also supported */ 432 PCI_ANY_ID, 0, 0, 0 },
433 { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX20_FM, PCI_ANY_ID,
434 PCI_ANY_ID, 0, 0, 0 },
411 { } 435 { }
412}; 436};
413 437
diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c
index d61df5c3ac36..6b10ebe9d936 100644
--- a/drivers/misc/tifm_core.c
+++ b/drivers/misc/tifm_core.c
@@ -14,7 +14,7 @@
14#include <linux/idr.h> 14#include <linux/idr.h>
15 15
16#define DRIVER_NAME "tifm_core" 16#define DRIVER_NAME "tifm_core"
17#define DRIVER_VERSION "0.6" 17#define DRIVER_VERSION "0.7"
18 18
19static DEFINE_IDR(tifm_adapter_idr); 19static DEFINE_IDR(tifm_adapter_idr);
20static DEFINE_SPINLOCK(tifm_adapter_lock); 20static DEFINE_SPINLOCK(tifm_adapter_lock);
@@ -60,10 +60,41 @@ static int tifm_uevent(struct device *dev, char **envp, int num_envp,
60 return 0; 60 return 0;
61} 61}
62 62
63#ifdef CONFIG_PM
64
65static int tifm_device_suspend(struct device *dev, pm_message_t state)
66{
67 struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev);
68 struct tifm_driver *drv = fm_dev->drv;
69
70 if (drv && drv->suspend)
71 return drv->suspend(fm_dev, state);
72 return 0;
73}
74
75static int tifm_device_resume(struct device *dev)
76{
77 struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev);
78 struct tifm_driver *drv = fm_dev->drv;
79
80 if (drv && drv->resume)
81 return drv->resume(fm_dev);
82 return 0;
83}
84
85#else
86
87#define tifm_device_suspend NULL
88#define tifm_device_resume NULL
89
90#endif /* CONFIG_PM */
91
63static struct bus_type tifm_bus_type = { 92static struct bus_type tifm_bus_type = {
64 .name = "tifm", 93 .name = "tifm",
65 .match = tifm_match, 94 .match = tifm_match,
66 .uevent = tifm_uevent, 95 .uevent = tifm_uevent,
96 .suspend = tifm_device_suspend,
97 .resume = tifm_device_resume
67}; 98};
68 99
69static void tifm_free(struct class_device *cdev) 100static void tifm_free(struct class_device *cdev)
@@ -71,8 +102,6 @@ static void tifm_free(struct class_device *cdev)
71 struct tifm_adapter *fm = container_of(cdev, struct tifm_adapter, cdev); 102 struct tifm_adapter *fm = container_of(cdev, struct tifm_adapter, cdev);
72 103
73 kfree(fm->sockets); 104 kfree(fm->sockets);
74 if (fm->wq)
75 destroy_workqueue(fm->wq);
76 kfree(fm); 105 kfree(fm);
77} 106}
78 107
@@ -101,7 +130,8 @@ void tifm_free_adapter(struct tifm_adapter *fm)
101} 130}
102EXPORT_SYMBOL(tifm_free_adapter); 131EXPORT_SYMBOL(tifm_free_adapter);
103 132
104int tifm_add_adapter(struct tifm_adapter *fm) 133int tifm_add_adapter(struct tifm_adapter *fm,
134 int (*mediathreadfn)(void *data))
105{ 135{
106 int rc; 136 int rc;
107 137
@@ -113,10 +143,10 @@ int tifm_add_adapter(struct tifm_adapter *fm)
113 spin_unlock(&tifm_adapter_lock); 143 spin_unlock(&tifm_adapter_lock);
114 if (!rc) { 144 if (!rc) {
115 snprintf(fm->cdev.class_id, BUS_ID_SIZE, "tifm%u", fm->id); 145 snprintf(fm->cdev.class_id, BUS_ID_SIZE, "tifm%u", fm->id);
116 strncpy(fm->wq_name, fm->cdev.class_id, KOBJ_NAME_LEN); 146 fm->media_switcher = kthread_create(mediathreadfn,
147 fm, "tifm/%u", fm->id);
117 148
118 fm->wq = create_singlethread_workqueue(fm->wq_name); 149 if (!IS_ERR(fm->media_switcher))
119 if (fm->wq)
120 return class_device_add(&fm->cdev); 150 return class_device_add(&fm->cdev);
121 151
122 spin_lock(&tifm_adapter_lock); 152 spin_lock(&tifm_adapter_lock);
@@ -141,27 +171,27 @@ EXPORT_SYMBOL(tifm_remove_adapter);
141void tifm_free_device(struct device *dev) 171void tifm_free_device(struct device *dev)
142{ 172{
143 struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev); 173 struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev);
144 if (fm_dev->wq)
145 destroy_workqueue(fm_dev->wq);
146 kfree(fm_dev); 174 kfree(fm_dev);
147} 175}
148EXPORT_SYMBOL(tifm_free_device); 176EXPORT_SYMBOL(tifm_free_device);
149 177
150struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm, unsigned int id) 178static void tifm_dummy_signal_irq(struct tifm_dev *sock,
179 unsigned int sock_irq_status)
180{
181 return;
182}
183
184struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm)
151{ 185{
152 struct tifm_dev *dev = kzalloc(sizeof(struct tifm_dev), GFP_KERNEL); 186 struct tifm_dev *dev = kzalloc(sizeof(struct tifm_dev), GFP_KERNEL);
153 187
154 if (dev) { 188 if (dev) {
155 spin_lock_init(&dev->lock); 189 spin_lock_init(&dev->lock);
156 snprintf(dev->wq_name, KOBJ_NAME_LEN, "tifm%u:%u", fm->id, id); 190
157 dev->wq = create_singlethread_workqueue(dev->wq_name);
158 if (!dev->wq) {
159 kfree(dev);
160 return NULL;
161 }
162 dev->dev.parent = fm->dev; 191 dev->dev.parent = fm->dev;
163 dev->dev.bus = &tifm_bus_type; 192 dev->dev.bus = &tifm_bus_type;
164 dev->dev.release = tifm_free_device; 193 dev->dev.release = tifm_free_device;
194 dev->signal_irq = tifm_dummy_signal_irq;
165 } 195 }
166 return dev; 196 return dev;
167} 197}
@@ -219,6 +249,7 @@ static int tifm_device_remove(struct device *dev)
219 struct tifm_driver *drv = fm_dev->drv; 249 struct tifm_driver *drv = fm_dev->drv;
220 250
221 if (drv) { 251 if (drv) {
252 fm_dev->signal_irq = tifm_dummy_signal_irq;
222 if (drv->remove) 253 if (drv->remove)
223 drv->remove(fm_dev); 254 drv->remove(fm_dev);
224 fm_dev->drv = NULL; 255 fm_dev->drv = NULL;
@@ -233,6 +264,8 @@ int tifm_register_driver(struct tifm_driver *drv)
233 drv->driver.bus = &tifm_bus_type; 264 drv->driver.bus = &tifm_bus_type;
234 drv->driver.probe = tifm_device_probe; 265 drv->driver.probe = tifm_device_probe;
235 drv->driver.remove = tifm_device_remove; 266 drv->driver.remove = tifm_device_remove;
267 drv->driver.suspend = tifm_device_suspend;
268 drv->driver.resume = tifm_device_resume;
236 269
237 return driver_register(&drv->driver); 270 return driver_register(&drv->driver);
238} 271}