Browse Source

Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6: (235 commits)
  Staging: IIO: add selection of IIO_SW_RING to LIS3L02DQ as needed
  Staging: IIO: Add tsl2560-2 support to tsl2563 driver.
  Staging: IIO: Remove tsl2561 driver. Support merged with tsl2563.
  Staging: wlags49_h2: fix up signal levels
  + drivers-staging-wlags49_h2-remove-cvs-metadata.patch added to -mm tree
  Staging: samsung-laptop: add TODO file
  Staging: samsung-laptop: remove old kernel code
  Staging: add Samsung Laptop driver
  staging: batman-adv meshing protocol
  Staging: rtl8192u: depends on USB
  Staging: rtl8192u: remove dead code
  Staging: rtl8192u: remove bad whitespaces
  Staging: rtl8192u: make it compile
  Staging: Added Realtek rtl8192u driver to staging
  Staging: dream: add gpio and pmem support
  Staging: dream: add TODO file
  Staging: android: delete android drivers
  Staging: et131x: clean up the avail fields in the rx registers
  Staging: et131x: Clean up number fields
  Staging: et131x: kill RX_DMA_MAX_PKT_TIME
  ...
Linus Torvalds 15 years ago
parent
commit
0e2f7b8376
100 changed files with 7755 additions and 6587 deletions
  1. 12 4
      drivers/staging/Kconfig
  2. 8 4
      drivers/staging/Makefile
  3. 3 3
      drivers/staging/altpciechdma/altpciechdma.c
  4. 0 96
      drivers/staging/android/Kconfig
  5. 0 6
      drivers/staging/android/Makefile
  6. 0 10
      drivers/staging/android/TODO
  7. 0 3767
      drivers/staging/android/binder.c
  8. 0 330
      drivers/staging/android/binder.h
  9. 0 607
      drivers/staging/android/logger.c
  10. 0 48
      drivers/staging/android/logger.h
  11. 0 173
      drivers/staging/android/lowmemorykiller.c
  12. 0 410
      drivers/staging/android/ram_console.c
  13. 0 166
      drivers/staging/android/timed_gpio.c
  14. 0 33
      drivers/staging/android/timed_gpio.h
  15. 0 121
      drivers/staging/android/timed_output.c
  16. 0 37
      drivers/staging/android/timed_output.h
  17. 0 12
      drivers/staging/b3dfg/b3dfg.c
  18. 37 0
      drivers/staging/batman-adv/CHANGELOG
  19. 25 0
      drivers/staging/batman-adv/Kconfig
  20. 22 0
      drivers/staging/batman-adv/Makefile
  21. 125 0
      drivers/staging/batman-adv/README
  22. 51 0
      drivers/staging/batman-adv/TODO
  23. 232 0
      drivers/staging/batman-adv/aggregation.c
  24. 37 0
      drivers/staging/batman-adv/aggregation.h
  25. 177 0
      drivers/staging/batman-adv/bitarray.c
  26. 45 0
      drivers/staging/batman-adv/bitarray.h
  27. 75 0
      drivers/staging/batman-adv/compat.h
  28. 337 0
      drivers/staging/batman-adv/device.c
  29. 36 0
      drivers/staging/batman-adv/device.h
  30. 451 0
      drivers/staging/batman-adv/hard-interface.c
  31. 36 0
      drivers/staging/batman-adv/hard-interface.h
  32. 313 0
      drivers/staging/batman-adv/hash.c
  33. 99 0
      drivers/staging/batman-adv/hash.h
  34. 179 0
      drivers/staging/batman-adv/log.c
  35. 32 0
      drivers/staging/batman-adv/log.h
  36. 286 0
      drivers/staging/batman-adv/main.c
  37. 151 0
      drivers/staging/batman-adv/main.h
  38. 96 0
      drivers/staging/batman-adv/packet.h
  39. 950 0
      drivers/staging/batman-adv/proc.c
  40. 49 0
      drivers/staging/batman-adv/proc.h
  41. 52 0
      drivers/staging/batman-adv/ring_buffer.c
  42. 23 0
      drivers/staging/batman-adv/ring_buffer.h
  43. 1010 0
      drivers/staging/batman-adv/routing.c
  44. 34 0
      drivers/staging/batman-adv/routing.h
  45. 473 0
      drivers/staging/batman-adv/send.c
  46. 36 0
      drivers/staging/batman-adv/send.h
  47. 349 0
      drivers/staging/batman-adv/soft-interface.c
  48. 33 0
      drivers/staging/batman-adv/soft-interface.h
  49. 454 0
      drivers/staging/batman-adv/translation-table.c
  50. 42 0
      drivers/staging/batman-adv/translation-table.h
  51. 124 0
      drivers/staging/batman-adv/types.h
  52. 564 0
      drivers/staging/batman-adv/vis.c
  53. 63 0
      drivers/staging/batman-adv/vis.h
  54. 0 8
      drivers/staging/comedi/comedi.h
  55. 14 135
      drivers/staging/comedi/comedi_compat32.c
  56. 1 15
      drivers/staging/comedi/comedi_compat32.h
  57. 0 15
      drivers/staging/comedi/comedi_fops.c
  58. 34 26
      drivers/staging/comedi/comedidev.h
  59. 1 1
      drivers/staging/comedi/drivers.c
  60. 2 1
      drivers/staging/comedi/drivers/8253.h
  61. 10 13
      drivers/staging/comedi/drivers/8255.c
  62. 4 5
      drivers/staging/comedi/drivers/acl7225b.c
  63. 1 2
      drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
  64. 3 3
      drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
  65. 1 1
      drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
  66. 1 1
      drivers/staging/comedi/drivers/addi-data/addi_common.h
  67. 1 1
      drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
  68. 1 1
      drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
  69. 1 1
      drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
  70. 1 1
      drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
  71. 2 2
      drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
  72. 1 1
      drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
  73. 3 4
      drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
  74. 1 1
      drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
  75. 1 1
      drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
  76. 1 1
      drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
  77. 33 20
      drivers/staging/comedi/drivers/adl_pci6208.c
  78. 9 10
      drivers/staging/comedi/drivers/adl_pci7296.c
  79. 15 17
      drivers/staging/comedi/drivers/adl_pci7432.c
  80. 19 18
      drivers/staging/comedi/drivers/adl_pci8164.c
  81. 1 1
      drivers/staging/comedi/drivers/adl_pci9118.c
  82. 2 2
      drivers/staging/comedi/drivers/adv_pci1710.c
  83. 8 10
      drivers/staging/comedi/drivers/amplc_pc263.c
  84. 3 3
      drivers/staging/comedi/drivers/cb_das16_cs.c
  85. 1 1
      drivers/staging/comedi/drivers/cb_pcidda.c
  86. 2 2
      drivers/staging/comedi/drivers/cb_pcidio.c
  87. 1 4
      drivers/staging/comedi/drivers/comedi_fc.c
  88. 1 1
      drivers/staging/comedi/drivers/dmm32at.c
  89. 1 1
      drivers/staging/comedi/drivers/dt2814.c
  90. 2 2
      drivers/staging/comedi/drivers/dt282x.c
  91. 64 62
      drivers/staging/comedi/drivers/gsc_hpdi.c
  92. 182 163
      drivers/staging/comedi/drivers/icp_multi.c
  93. 43 40
      drivers/staging/comedi/drivers/ii_pci20kc.c
  94. 12 9
      drivers/staging/comedi/drivers/ke_counter.c
  95. 1 1
      drivers/staging/comedi/drivers/me4000.c
  96. 121 110
      drivers/staging/comedi/drivers/mite.c
  97. 0 7
      drivers/staging/comedi/drivers/mite.h
  98. 11 14
      drivers/staging/comedi/drivers/multiq3.c
  99. 14 19
      drivers/staging/comedi/drivers/ni_6527.c
  100. 3 3
      drivers/staging/comedi/drivers/ni_at_ao.c

+ 12 - 4
drivers/staging/Kconfig

@@ -65,8 +65,6 @@ source "drivers/staging/rt2860/Kconfig"
 
 source "drivers/staging/rt2870/Kconfig"
 
-source "drivers/staging/rt3090/Kconfig"
-
 source "drivers/staging/comedi/Kconfig"
 
 source "drivers/staging/asus_oled/Kconfig"
@@ -79,14 +77,14 @@ source "drivers/staging/rtl8187se/Kconfig"
 
 source "drivers/staging/rtl8192su/Kconfig"
 
+source "drivers/staging/rtl8192u/Kconfig"
+
 source "drivers/staging/rtl8192e/Kconfig"
 
 source "drivers/staging/mimio/Kconfig"
 
 source "drivers/staging/frontier/Kconfig"
 
-source "drivers/staging/android/Kconfig"
-
 source "drivers/staging/dream/Kconfig"
 
 source "drivers/staging/dst/Kconfig"
@@ -127,6 +125,16 @@ source "drivers/staging/sep/Kconfig"
 
 source "drivers/staging/iio/Kconfig"
 
+source "drivers/staging/ramzswap/Kconfig"
+
+source "drivers/staging/wlags49_h2/Kconfig"
+
+source "drivers/staging/wlags49_h25/Kconfig"
+
+source "drivers/staging/batman-adv/Kconfig"
+
+source "drivers/staging/samsung-laptop/Kconfig"
+
 source "drivers/staging/strip/Kconfig"
 
 source "drivers/staging/arlan/Kconfig"

+ 8 - 4
drivers/staging/Makefile

@@ -15,18 +15,17 @@ obj-$(CONFIG_POCH)		+= poch/
 obj-$(CONFIG_OTUS)		+= otus/
 obj-$(CONFIG_RT2860)		+= rt2860/
 obj-$(CONFIG_RT2870)		+= rt2870/
-obj-$(CONFIG_RT3090)		+= rt3090/
 obj-$(CONFIG_COMEDI)		+= comedi/
 obj-$(CONFIG_ASUS_OLED)		+= asus_oled/
 obj-$(CONFIG_PANEL)		+= panel/
 obj-$(CONFIG_ALTERA_PCIE_CHDMA)	+= altpciechdma/
-obj-$(CONFIG_RTL8187SE)		+= rtl8187se/
+obj-$(CONFIG_R8187SE)		+= rtl8187se/
 obj-$(CONFIG_RTL8192SU)		+= rtl8192su/
+obj-$(CONFIG_RTL8192U)		+= rtl8192u/
 obj-$(CONFIG_RTL8192E)		+= rtl8192e/
 obj-$(CONFIG_INPUT_MIMIO)	+= mimio/
 obj-$(CONFIG_TRANZPORT)		+= frontier/
-obj-$(CONFIG_ANDROID)		+= android/
-obj-$(CONFIG_ANDROID)		+= dream/
+obj-$(CONFIG_DREAM)		+= dream/
 obj-$(CONFIG_DST)		+= dst/
 obj-$(CONFIG_POHMELFS)		+= pohmelfs/
 obj-$(CONFIG_B3DFG)		+= b3dfg/
@@ -44,6 +43,11 @@ obj-$(CONFIG_VME_BUS)		+= vme/
 obj-$(CONFIG_RAR_REGISTER)	+= rar/
 obj-$(CONFIG_DX_SEP)		+= sep/
 obj-$(CONFIG_IIO)		+= iio/
+obj-$(CONFIG_RAMZSWAP)		+= ramzswap/
+obj-$(CONFIG_WLAGS49_H2)	+= wlags49_h2/
+obj-$(CONFIG_WLAGS49_H25)	+= wlags49_h25/
+obj-$(CONFIG_BATMAN_ADV)	+= batman-adv/
+obj-$(CONFIG_SAMSUNG_LAPTOP)	+= samsung-laptop/
 obj-$(CONFIG_STRIP)		+= strip/
 obj-$(CONFIG_ARLAN)		+= arlan/
 obj-$(CONFIG_WAVELAN)		+= wavelan/

+ 3 - 3
drivers/staging/altpciechdma/altpciechdma.c

@@ -212,7 +212,7 @@ struct ape_dev {
 	int msi_enabled;
 	/* whether this driver could obtain the regions */
 	int got_regions;
-	/* irq line succesfully requested by this driver, -1 otherwise */
+	/* irq line successfully requested by this driver, -1 otherwise */
 	int irq_line;
 	/* board revision */
 	u8 revision;
@@ -336,7 +336,7 @@ static int __devinit map_bars(struct ape_dev *ape, struct pci_dev *dev)
 		printk(KERN_DEBUG "BAR[%d] mapped at 0x%p with length %lu(/%lu).\n", i,
 		ape->bar[i], bar_min_len[i], bar_length);
 	}
-	/* succesfully mapped all required BAR regions */
+	/* successfully mapped all required BAR regions */
 	rc = 0;
 	goto success;
 fail:
@@ -911,7 +911,7 @@ static int __devinit probe(struct pci_dev *dev, const struct pci_device_id *id)
 	/* perform DMA engines loop back test */
 	rc = dma_test(ape, dev);
 	(void)rc;
-	/* succesfully took the device */
+	/* successfully took the device */
 	rc = 0;
 	printk(KERN_DEBUG "probe() successful.\n");
 	goto end;

+ 0 - 96
drivers/staging/android/Kconfig

@@ -1,96 +0,0 @@
-menu "Android"
-
-config ANDROID
-	bool "Android Drivers"
-	depends on BROKEN
-	default N
-	---help---
-	  Enable support for various drivers needed on the Android platform
-
-if ANDROID
-
-config ANDROID_BINDER_IPC
-	bool "Android Binder IPC Driver"
-	default n
-
-config ANDROID_LOGGER
-	tristate "Android log driver"
-	default n
-
-config ANDROID_RAM_CONSOLE
-	bool "Android RAM buffer console"
-	default n
-
-config ANDROID_RAM_CONSOLE_ENABLE_VERBOSE
-	bool "Enable verbose console messages on Android RAM console"
-	default y
-	depends on ANDROID_RAM_CONSOLE
-
-menuconfig ANDROID_RAM_CONSOLE_ERROR_CORRECTION
-	bool "Android RAM Console Enable error correction"
-	default n
-	depends on ANDROID_RAM_CONSOLE
-	depends on !ANDROID_RAM_CONSOLE_EARLY_INIT
-	select REED_SOLOMON
-	select REED_SOLOMON_ENC8
-	select REED_SOLOMON_DEC8
-
-if ANDROID_RAM_CONSOLE_ERROR_CORRECTION
-
-config ANDROID_RAM_CONSOLE_ERROR_CORRECTION_DATA_SIZE
-	int "Android RAM Console Data data size"
-	default 128
-	help
-	  Must be a power of 2.
-
-config ANDROID_RAM_CONSOLE_ERROR_CORRECTION_ECC_SIZE
-	int "Android RAM Console ECC size"
-	default 16
-
-config ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE
-	int "Android RAM Console Symbol size"
-	default 8
-
-config ANDROID_RAM_CONSOLE_ERROR_CORRECTION_POLYNOMIAL
-	hex "Android RAM Console Polynomial"
-	default 0x19 if (ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE = 4)
-	default 0x29 if (ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE = 5)
-	default 0x61 if (ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE = 6)
-	default 0x89 if (ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE = 7)
-	default 0x11d if (ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE = 8)
-
-endif # ANDROID_RAM_CONSOLE_ERROR_CORRECTION
-
-config ANDROID_RAM_CONSOLE_EARLY_INIT
-	bool "Start Android RAM console early"
-	default n
-	depends on ANDROID_RAM_CONSOLE
-
-config ANDROID_RAM_CONSOLE_EARLY_ADDR
-	hex "Android RAM console virtual address"
-	default 0
-	depends on ANDROID_RAM_CONSOLE_EARLY_INIT
-
-config ANDROID_RAM_CONSOLE_EARLY_SIZE
-	hex "Android RAM console buffer size"
-	default 0
-	depends on ANDROID_RAM_CONSOLE_EARLY_INIT
-
-config ANDROID_TIMED_OUTPUT
-	bool "Timed output class driver"
-	default y
-
-config ANDROID_TIMED_GPIO
-	tristate "Android timed gpio driver"
-	depends on GENERIC_GPIO && ANDROID_TIMED_OUTPUT
-	default n
-
-config ANDROID_LOW_MEMORY_KILLER
-	bool "Android Low Memory Killer"
-	default N
-	---help---
-	  Register processes to be killed when memory is low
-
-endif # if ANDROID
-
-endmenu

+ 0 - 6
drivers/staging/android/Makefile

@@ -1,6 +0,0 @@
-obj-$(CONFIG_ANDROID_BINDER_IPC)	+= binder.o
-obj-$(CONFIG_ANDROID_LOGGER)		+= logger.o
-obj-$(CONFIG_ANDROID_RAM_CONSOLE)	+= ram_console.o
-obj-$(CONFIG_ANDROID_TIMED_OUTPUT)	+= timed_output.o
-obj-$(CONFIG_ANDROID_TIMED_GPIO)	+= timed_gpio.o
-obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER)	+= lowmemorykiller.o

+ 0 - 10
drivers/staging/android/TODO

@@ -1,10 +0,0 @@
-TODO:
-	- checkpatch.pl cleanups
-	- sparse fixes
-	- rename files to be not so "generic"
-	- make sure things build as modules properly
-	- add proper arch dependancies as needed
-	- audit userspace interfaces to make sure they are sane
-
-Please send patches to Greg Kroah-Hartman <greg@kroah.com> and Cc:
-Brian Swetland <swetland@google.com>

+ 0 - 3767
drivers/staging/android/binder.c

@@ -1,3767 +0,0 @@
-/* binder.c
- *
- * Android IPC Subsystem
- *
- * Copyright (C) 2007-2008 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <asm/cacheflush.h>
-#include <linux/fdtable.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/list.h>
-#include <linux/miscdevice.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/nsproxy.h>
-#include <linux/poll.h>
-#include <linux/proc_fs.h>
-#include <linux/rbtree.h>
-#include <linux/sched.h>
-#include <linux/uaccess.h>
-#include <linux/vmalloc.h>
-
-#include "binder.h"
-
-static DEFINE_MUTEX(binder_lock);
-static DEFINE_MUTEX(binder_deferred_lock);
-
-static HLIST_HEAD(binder_procs);
-static HLIST_HEAD(binder_deferred_list);
-static HLIST_HEAD(binder_dead_nodes);
-
-static struct proc_dir_entry *binder_proc_dir_entry_root;
-static struct proc_dir_entry *binder_proc_dir_entry_proc;
-static struct binder_node *binder_context_mgr_node;
-static uid_t binder_context_mgr_uid = -1;
-static int binder_last_id;
-
-static int binder_read_proc_proc(char *page, char **start, off_t off,
-				 int count, int *eof, void *data);
-
-/* This is only defined in include/asm-arm/sizes.h */
-#ifndef SZ_1K
-#define SZ_1K                               0x400
-#endif
-
-#ifndef SZ_4M
-#define SZ_4M                               0x400000
-#endif
-
-#define FORBIDDEN_MMAP_FLAGS                (VM_WRITE)
-
-#define BINDER_SMALL_BUF_SIZE (PAGE_SIZE * 64)
-
-enum {
-	BINDER_DEBUG_USER_ERROR             = 1U << 0,
-	BINDER_DEBUG_FAILED_TRANSACTION     = 1U << 1,
-	BINDER_DEBUG_DEAD_TRANSACTION       = 1U << 2,
-	BINDER_DEBUG_OPEN_CLOSE             = 1U << 3,
-	BINDER_DEBUG_DEAD_BINDER            = 1U << 4,
-	BINDER_DEBUG_DEATH_NOTIFICATION     = 1U << 5,
-	BINDER_DEBUG_READ_WRITE             = 1U << 6,
-	BINDER_DEBUG_USER_REFS              = 1U << 7,
-	BINDER_DEBUG_THREADS                = 1U << 8,
-	BINDER_DEBUG_TRANSACTION            = 1U << 9,
-	BINDER_DEBUG_TRANSACTION_COMPLETE   = 1U << 10,
-	BINDER_DEBUG_FREE_BUFFER            = 1U << 11,
-	BINDER_DEBUG_INTERNAL_REFS          = 1U << 12,
-	BINDER_DEBUG_BUFFER_ALLOC           = 1U << 13,
-	BINDER_DEBUG_PRIORITY_CAP           = 1U << 14,
-	BINDER_DEBUG_BUFFER_ALLOC_ASYNC     = 1U << 15,
-};
-static uint32_t binder_debug_mask = BINDER_DEBUG_USER_ERROR |
-	BINDER_DEBUG_FAILED_TRANSACTION | BINDER_DEBUG_DEAD_TRANSACTION;
-module_param_named(debug_mask, binder_debug_mask, uint, S_IWUSR | S_IRUGO);
-
-static int binder_debug_no_lock;
-module_param_named(proc_no_lock, binder_debug_no_lock, bool, S_IWUSR | S_IRUGO);
-
-static DECLARE_WAIT_QUEUE_HEAD(binder_user_error_wait);
-static int binder_stop_on_user_error;
-
-static int binder_set_stop_on_user_error(const char *val,
-					 struct kernel_param *kp)
-{
-	int ret;
-	ret = param_set_int(val, kp);
-	if (binder_stop_on_user_error < 2)
-		wake_up(&binder_user_error_wait);
-	return ret;
-}
-module_param_call(stop_on_user_error, binder_set_stop_on_user_error,
-	param_get_int, &binder_stop_on_user_error, S_IWUSR | S_IRUGO);
-
-#define binder_debug(mask, x...) \
-	do { \
-		if (binder_debug_mask & mask) \
-			printk(KERN_INFO x); \
-	} while (0)
-
-#define binder_user_error(x...) \
-	do { \
-		if (binder_debug_mask & BINDER_DEBUG_USER_ERROR) \
-			printk(KERN_INFO x); \
-		if (binder_stop_on_user_error) \
-			binder_stop_on_user_error = 2; \
-	} while (0)
-
-enum binder_stat_types {
-	BINDER_STAT_PROC,
-	BINDER_STAT_THREAD,
-	BINDER_STAT_NODE,
-	BINDER_STAT_REF,
-	BINDER_STAT_DEATH,
-	BINDER_STAT_TRANSACTION,
-	BINDER_STAT_TRANSACTION_COMPLETE,
-	BINDER_STAT_COUNT
-};
-
-struct binder_stats {
-	int br[_IOC_NR(BR_FAILED_REPLY) + 1];
-	int bc[_IOC_NR(BC_DEAD_BINDER_DONE) + 1];
-	int obj_created[BINDER_STAT_COUNT];
-	int obj_deleted[BINDER_STAT_COUNT];
-};
-
-static struct binder_stats binder_stats;
-
-static inline void binder_stats_deleted(enum binder_stat_types type)
-{
-	binder_stats.obj_deleted[type]++;
-}
-
-static inline void binder_stats_created(enum binder_stat_types type)
-{
-	binder_stats.obj_created[type]++;
-}
-
-struct binder_transaction_log_entry {
-	int debug_id;
-	int call_type;
-	int from_proc;
-	int from_thread;
-	int target_handle;
-	int to_proc;
-	int to_thread;
-	int to_node;
-	int data_size;
-	int offsets_size;
-};
-struct binder_transaction_log {
-	int next;
-	int full;
-	struct binder_transaction_log_entry entry[32];
-};
-static struct binder_transaction_log binder_transaction_log;
-static struct binder_transaction_log binder_transaction_log_failed;
-
-static struct binder_transaction_log_entry *binder_transaction_log_add(
-	struct binder_transaction_log *log)
-{
-	struct binder_transaction_log_entry *e;
-	e = &log->entry[log->next];
-	memset(e, 0, sizeof(*e));
-	log->next++;
-	if (log->next == ARRAY_SIZE(log->entry)) {
-		log->next = 0;
-		log->full = 1;
-	}
-	return e;
-}
-
-struct binder_work {
-	struct list_head entry;
-	enum {
-		BINDER_WORK_TRANSACTION = 1,
-		BINDER_WORK_TRANSACTION_COMPLETE,
-		BINDER_WORK_NODE,
-		BINDER_WORK_DEAD_BINDER,
-		BINDER_WORK_DEAD_BINDER_AND_CLEAR,
-		BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
-	} type;
-};
-
-struct binder_node {
-	int debug_id;
-	struct binder_work work;
-	union {
-		struct rb_node rb_node;
-		struct hlist_node dead_node;
-	};
-	struct binder_proc *proc;
-	struct hlist_head refs;
-	int internal_strong_refs;
-	int local_weak_refs;
-	int local_strong_refs;
-	void __user *ptr;
-	void __user *cookie;
-	unsigned has_strong_ref:1;
-	unsigned pending_strong_ref:1;
-	unsigned has_weak_ref:1;
-	unsigned pending_weak_ref:1;
-	unsigned has_async_transaction:1;
-	unsigned accept_fds:1;
-	unsigned min_priority:8;
-	struct list_head async_todo;
-};
-
-struct binder_ref_death {
-	struct binder_work work;
-	void __user *cookie;
-};
-
-struct binder_ref {
-	/* Lookups needed: */
-	/*   node + proc => ref (transaction) */
-	/*   desc + proc => ref (transaction, inc/dec ref) */
-	/*   node => refs + procs (proc exit) */
-	int debug_id;
-	struct rb_node rb_node_desc;
-	struct rb_node rb_node_node;
-	struct hlist_node node_entry;
-	struct binder_proc *proc;
-	struct binder_node *node;
-	uint32_t desc;
-	int strong;
-	int weak;
-	struct binder_ref_death *death;
-};
-
-struct binder_buffer {
-	struct list_head entry; /* free and allocated entries by addesss */
-	struct rb_node rb_node; /* free entry by size or allocated entry */
-				/* by address */
-	unsigned free:1;
-	unsigned allow_user_free:1;
-	unsigned async_transaction:1;
-	unsigned debug_id:29;
-
-	struct binder_transaction *transaction;
-
-	struct binder_node *target_node;
-	size_t data_size;
-	size_t offsets_size;
-	uint8_t data[0];
-};
-
-enum binder_deferred_state {
-	BINDER_DEFERRED_PUT_FILES    = 0x01,
-	BINDER_DEFERRED_FLUSH        = 0x02,
-	BINDER_DEFERRED_RELEASE      = 0x04,
-};
-
-struct binder_proc {
-	struct hlist_node proc_node;
-	struct rb_root threads;
-	struct rb_root nodes;
-	struct rb_root refs_by_desc;
-	struct rb_root refs_by_node;
-	int pid;
-	struct vm_area_struct *vma;
-	struct task_struct *tsk;
-	struct files_struct *files;
-	struct hlist_node deferred_work_node;
-	int deferred_work;
-	void *buffer;
-	ptrdiff_t user_buffer_offset;
-
-	struct list_head buffers;
-	struct rb_root free_buffers;
-	struct rb_root allocated_buffers;
-	size_t free_async_space;
-
-	struct page **pages;
-	size_t buffer_size;
-	uint32_t buffer_free;
-	struct list_head todo;
-	wait_queue_head_t wait;
-	struct binder_stats stats;
-	struct list_head delivered_death;
-	int max_threads;
-	int requested_threads;
-	int requested_threads_started;
-	int ready_threads;
-	long default_priority;
-};
-
-enum {
-	BINDER_LOOPER_STATE_REGISTERED  = 0x01,
-	BINDER_LOOPER_STATE_ENTERED     = 0x02,
-	BINDER_LOOPER_STATE_EXITED      = 0x04,
-	BINDER_LOOPER_STATE_INVALID     = 0x08,
-	BINDER_LOOPER_STATE_WAITING     = 0x10,
-	BINDER_LOOPER_STATE_NEED_RETURN = 0x20
-};
-
-struct binder_thread {
-	struct binder_proc *proc;
-	struct rb_node rb_node;
-	int pid;
-	int looper;
-	struct binder_transaction *transaction_stack;
-	struct list_head todo;
-	uint32_t return_error; /* Write failed, return error code in read buf */
-	uint32_t return_error2; /* Write failed, return error code in read */
-		/* buffer. Used when sending a reply to a dead process that */
-		/* we are also waiting on */
-	wait_queue_head_t wait;
-	struct binder_stats stats;
-};
-
-struct binder_transaction {
-	int debug_id;
-	struct binder_work work;
-	struct binder_thread *from;
-	struct binder_transaction *from_parent;
-	struct binder_proc *to_proc;
-	struct binder_thread *to_thread;
-	struct binder_transaction *to_parent;
-	unsigned need_reply:1;
-	/* unsigned is_dead:1; */	/* not used at the moment */
-
-	struct binder_buffer *buffer;
-	unsigned int	code;
-	unsigned int	flags;
-	long	priority;
-	long	saved_priority;
-	uid_t	sender_euid;
-};
-
-static void
-binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer);
-
-/*
- * copied from get_unused_fd_flags
- */
-int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
-{
-	struct files_struct *files = proc->files;
-	int fd, error;
-	struct fdtable *fdt;
-	unsigned long rlim_cur;
-	unsigned long irqs;
-
-	if (files == NULL)
-		return -ESRCH;
-
-	error = -EMFILE;
-	spin_lock(&files->file_lock);
-
-repeat:
-	fdt = files_fdtable(files);
-	fd = find_next_zero_bit(fdt->open_fds->fds_bits, fdt->max_fds,
-				files->next_fd);
-
-	/*
-	 * N.B. For clone tasks sharing a files structure, this test
-	 * will limit the total number of files that can be opened.
-	 */
-	rlim_cur = 0;
-	if (lock_task_sighand(proc->tsk, &irqs)) {
-		rlim_cur = proc->tsk->signal->rlim[RLIMIT_NOFILE].rlim_cur;
-		unlock_task_sighand(proc->tsk, &irqs);
-	}
-	if (fd >= rlim_cur)
-		goto out;
-
-	/* Do we need to expand the fd array or fd set?  */
-	error = expand_files(files, fd);
-	if (error < 0)
-		goto out;
-
-	if (error) {
-		/*
-		 * If we needed to expand the fs array we
-		 * might have blocked - try again.
-		 */
-		error = -EMFILE;
-		goto repeat;
-	}
-
-	FD_SET(fd, fdt->open_fds);
-	if (flags & O_CLOEXEC)
-		FD_SET(fd, fdt->close_on_exec);
-	else
-		FD_CLR(fd, fdt->close_on_exec);
-	files->next_fd = fd + 1;
-#if 1
-	/* Sanity check */
-	if (fdt->fd[fd] != NULL) {
-		printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd);
-		fdt->fd[fd] = NULL;
-	}
-#endif
-	error = fd;
-
-out:
-	spin_unlock(&files->file_lock);
-	return error;
-}
-
-/*
- * copied from fd_install
- */
-static void task_fd_install(
-	struct binder_proc *proc, unsigned int fd, struct file *file)
-{
-	struct files_struct *files = proc->files;
-	struct fdtable *fdt;
-
-	if (files == NULL)
-		return;
-
-	spin_lock(&files->file_lock);
-	fdt = files_fdtable(files);
-	BUG_ON(fdt->fd[fd] != NULL);
-	rcu_assign_pointer(fdt->fd[fd], file);
-	spin_unlock(&files->file_lock);
-}
-
-/*
- * copied from __put_unused_fd in open.c
- */
-static void __put_unused_fd(struct files_struct *files, unsigned int fd)
-{
-	struct fdtable *fdt = files_fdtable(files);
-	__FD_CLR(fd, fdt->open_fds);
-	if (fd < files->next_fd)
-		files->next_fd = fd;
-}
-
-/*
- * copied from sys_close
- */
-static long task_close_fd(struct binder_proc *proc, unsigned int fd)
-{
-	struct file *filp;
-	struct files_struct *files = proc->files;
-	struct fdtable *fdt;
-	int retval;
-
-	if (files == NULL)
-		return -ESRCH;
-
-	spin_lock(&files->file_lock);
-	fdt = files_fdtable(files);
-	if (fd >= fdt->max_fds)
-		goto out_unlock;
-	filp = fdt->fd[fd];
-	if (!filp)
-		goto out_unlock;
-	rcu_assign_pointer(fdt->fd[fd], NULL);
-	FD_CLR(fd, fdt->close_on_exec);
-	__put_unused_fd(files, fd);
-	spin_unlock(&files->file_lock);
-	retval = filp_close(filp, files);
-
-	/* can't restart close syscall because file table entry was cleared */
-	if (unlikely(retval == -ERESTARTSYS ||
-		     retval == -ERESTARTNOINTR ||
-		     retval == -ERESTARTNOHAND ||
-		     retval == -ERESTART_RESTARTBLOCK))
-		retval = -EINTR;
-
-	return retval;
-
-out_unlock:
-	spin_unlock(&files->file_lock);
-	return -EBADF;
-}
-
-static void binder_set_nice(long nice)
-{
-	long min_nice;
-	if (can_nice(current, nice)) {
-		set_user_nice(current, nice);
-		return;
-	}
-	min_nice = 20 - current->signal->rlim[RLIMIT_NICE].rlim_cur;
-	binder_debug(BINDER_DEBUG_PRIORITY_CAP,
-		     "binder: %d: nice value %ld not allowed use "
-		     "%ld instead\n", current->pid, nice, min_nice);
-	set_user_nice(current, min_nice);
-	if (min_nice < 20)
-		return;
-	binder_user_error("binder: %d RLIMIT_NICE not set\n", current->pid);
-}
-
-static size_t binder_buffer_size(struct binder_proc *proc,
-				 struct binder_buffer *buffer)
-{
-	if (list_is_last(&buffer->entry, &proc->buffers))
-		return proc->buffer + proc->buffer_size - (void *)buffer->data;
-	else
-		return (size_t)list_entry(buffer->entry.next,
-			struct binder_buffer, entry) - (size_t)buffer->data;
-}
-
-static void binder_insert_free_buffer(struct binder_proc *proc,
-				      struct binder_buffer *new_buffer)
-{
-	struct rb_node **p = &proc->free_buffers.rb_node;
-	struct rb_node *parent = NULL;
-	struct binder_buffer *buffer;
-	size_t buffer_size;
-	size_t new_buffer_size;
-
-	BUG_ON(!new_buffer->free);
-
-	new_buffer_size = binder_buffer_size(proc, new_buffer);
-
-	binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-		     "binder: %d: add free buffer, size %zd, "
-		     "at %p\n", proc->pid, new_buffer_size, new_buffer);
-
-	while (*p) {
-		parent = *p;
-		buffer = rb_entry(parent, struct binder_buffer, rb_node);
-		BUG_ON(!buffer->free);
-
-		buffer_size = binder_buffer_size(proc, buffer);
-
-		if (new_buffer_size < buffer_size)
-			p = &parent->rb_left;
-		else
-			p = &parent->rb_right;
-	}
-	rb_link_node(&new_buffer->rb_node, parent, p);
-	rb_insert_color(&new_buffer->rb_node, &proc->free_buffers);
-}
-
-static void binder_insert_allocated_buffer(struct binder_proc *proc,
-					   struct binder_buffer *new_buffer)
-{
-	struct rb_node **p = &proc->allocated_buffers.rb_node;
-	struct rb_node *parent = NULL;
-	struct binder_buffer *buffer;
-
-	BUG_ON(new_buffer->free);
-
-	while (*p) {
-		parent = *p;
-		buffer = rb_entry(parent, struct binder_buffer, rb_node);
-		BUG_ON(buffer->free);
-
-		if (new_buffer < buffer)
-			p = &parent->rb_left;
-		else if (new_buffer > buffer)
-			p = &parent->rb_right;
-		else
-			BUG();
-	}
-	rb_link_node(&new_buffer->rb_node, parent, p);
-	rb_insert_color(&new_buffer->rb_node, &proc->allocated_buffers);
-}
-
-static struct binder_buffer *binder_buffer_lookup(struct binder_proc *proc,
-						  void __user *user_ptr)
-{
-	struct rb_node *n = proc->allocated_buffers.rb_node;
-	struct binder_buffer *buffer;
-	struct binder_buffer *kern_ptr;
-
-	kern_ptr = user_ptr - proc->user_buffer_offset
-		- offsetof(struct binder_buffer, data);
-
-	while (n) {
-		buffer = rb_entry(n, struct binder_buffer, rb_node);
-		BUG_ON(buffer->free);
-
-		if (kern_ptr < buffer)
-			n = n->rb_left;
-		else if (kern_ptr > buffer)
-			n = n->rb_right;
-		else
-			return buffer;
-	}
-	return NULL;
-}
-
-static int binder_update_page_range(struct binder_proc *proc, int allocate,
-				    void *start, void *end,
-				    struct vm_area_struct *vma)
-{
-	void *page_addr;
-	unsigned long user_page_addr;
-	struct vm_struct tmp_area;
-	struct page **page;
-	struct mm_struct *mm;
-
-	binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-		     "binder: %d: %s pages %p-%p\n", proc->pid,
-		     allocate ? "allocate" : "free", start, end);
-
-	if (end <= start)
-		return 0;
-
-	if (vma)
-		mm = NULL;
-	else
-		mm = get_task_mm(proc->tsk);
-
-	if (mm) {
-		down_write(&mm->mmap_sem);
-		vma = proc->vma;
-	}
-
-	if (allocate == 0)
-		goto free_range;
-
-	if (vma == NULL) {
-		printk(KERN_ERR "binder: %d: binder_alloc_buf failed to "
-		       "map pages in userspace, no vma\n", proc->pid);
-		goto err_no_vma;
-	}
-
-	for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) {
-		int ret;
-		struct page **page_array_ptr;
-		page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];
-
-		BUG_ON(*page);
-		*page = alloc_page(GFP_KERNEL | __GFP_ZERO);
-		if (*page == NULL) {
-			printk(KERN_ERR "binder: %d: binder_alloc_buf failed "
-			       "for page at %p\n", proc->pid, page_addr);
-			goto err_alloc_page_failed;
-		}
-		tmp_area.addr = page_addr;
-		tmp_area.size = PAGE_SIZE + PAGE_SIZE /* guard page? */;
-		page_array_ptr = page;
-		ret = map_vm_area(&tmp_area, PAGE_KERNEL, &page_array_ptr);
-		if (ret) {
-			printk(KERN_ERR "binder: %d: binder_alloc_buf failed "
-			       "to map page at %p in kernel\n",
-			       proc->pid, page_addr);
-			goto err_map_kernel_failed;
-		}
-		user_page_addr =
-			(uintptr_t)page_addr + proc->user_buffer_offset;
-		ret = vm_insert_page(vma, user_page_addr, page[0]);
-		if (ret) {
-			printk(KERN_ERR "binder: %d: binder_alloc_buf failed "
-			       "to map page at %lx in userspace\n",
-			       proc->pid, user_page_addr);
-			goto err_vm_insert_page_failed;
-		}
-		/* vm_insert_page does not seem to increment the refcount */
-	}
-	if (mm) {
-		up_write(&mm->mmap_sem);
-		mmput(mm);
-	}
-	return 0;
-
-free_range:
-	for (page_addr = end - PAGE_SIZE; page_addr >= start;
-	     page_addr -= PAGE_SIZE) {
-		page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];
-		if (vma)
-			zap_page_range(vma, (uintptr_t)page_addr +
-				proc->user_buffer_offset, PAGE_SIZE, NULL);
-err_vm_insert_page_failed:
-		unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE);
-err_map_kernel_failed:
-		__free_page(*page);
-		*page = NULL;
-err_alloc_page_failed:
-		;
-	}
-err_no_vma:
-	if (mm) {
-		up_write(&mm->mmap_sem);
-		mmput(mm);
-	}
-	return -ENOMEM;
-}
-
-static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc,
-					      size_t data_size,
-					      size_t offsets_size, int is_async)
-{
-	struct rb_node *n = proc->free_buffers.rb_node;
-	struct binder_buffer *buffer;
-	size_t buffer_size;
-	struct rb_node *best_fit = NULL;
-	void *has_page_addr;
-	void *end_page_addr;
-	size_t size;
-
-	if (proc->vma == NULL) {
-		printk(KERN_ERR "binder: %d: binder_alloc_buf, no vma\n",
-		       proc->pid);
-		return NULL;
-	}
-
-	size = ALIGN(data_size, sizeof(void *)) +
-		ALIGN(offsets_size, sizeof(void *));
-
-	if (size < data_size || size < offsets_size) {
-		binder_user_error("binder: %d: got transaction with invalid "
-			"size %zd-%zd\n", proc->pid, data_size, offsets_size);
-		return NULL;
-	}
-
-	if (is_async &&
-	    proc->free_async_space < size + sizeof(struct binder_buffer)) {
-		binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-			     "binder: %d: binder_alloc_buf size %zd"
-			     "failed, no async space left\n", proc->pid, size);
-		return NULL;
-	}
-
-	while (n) {
-		buffer = rb_entry(n, struct binder_buffer, rb_node);
-		BUG_ON(!buffer->free);
-		buffer_size = binder_buffer_size(proc, buffer);
-
-		if (size < buffer_size) {
-			best_fit = n;
-			n = n->rb_left;
-		} else if (size > buffer_size)
-			n = n->rb_right;
-		else {
-			best_fit = n;
-			break;
-		}
-	}
-	if (best_fit == NULL) {
-		printk(KERN_ERR "binder: %d: binder_alloc_buf size %zd failed, "
-		       "no address space\n", proc->pid, size);
-		return NULL;
-	}
-	if (n == NULL) {
-		buffer = rb_entry(best_fit, struct binder_buffer, rb_node);
-		buffer_size = binder_buffer_size(proc, buffer);
-	}
-
-	binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-		     "binder: %d: binder_alloc_buf size %zd got buff"
-		     "er %p size %zd\n", proc->pid, size, buffer, buffer_size);
-
-	has_page_addr =
-		(void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK);
-	if (n == NULL) {
-		if (size + sizeof(struct binder_buffer) + 4 >= buffer_size)
-			buffer_size = size; /* no room for other buffers */
-		else
-			buffer_size = size + sizeof(struct binder_buffer);
-	}
-	end_page_addr =
-		(void *)PAGE_ALIGN((uintptr_t)buffer->data + buffer_size);
-	if (end_page_addr > has_page_addr)
-		end_page_addr = has_page_addr;
-	if (binder_update_page_range(proc, 1,
-	    (void *)PAGE_ALIGN((uintptr_t)buffer->data), end_page_addr, NULL))
-		return NULL;
-
-	rb_erase(best_fit, &proc->free_buffers);
-	buffer->free = 0;
-	binder_insert_allocated_buffer(proc, buffer);
-	if (buffer_size != size) {
-		struct binder_buffer *new_buffer = (void *)buffer->data + size;
-		list_add(&new_buffer->entry, &buffer->entry);
-		new_buffer->free = 1;
-		binder_insert_free_buffer(proc, new_buffer);
-	}
-	binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-		     "binder: %d: binder_alloc_buf size %zd got "
-		     "%p\n", proc->pid, size, buffer);
-	buffer->data_size = data_size;
-	buffer->offsets_size = offsets_size;
-	buffer->async_transaction = is_async;
-	if (is_async) {
-		proc->free_async_space -= size + sizeof(struct binder_buffer);
-		binder_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC,
-			     "binder: %d: binder_alloc_buf size %zd "
-			     "async free %zd\n", proc->pid, size,
-			     proc->free_async_space);
-	}
-
-	return buffer;
-}
-
-static void *buffer_start_page(struct binder_buffer *buffer)
-{
-	return (void *)((uintptr_t)buffer & PAGE_MASK);
-}
-
-static void *buffer_end_page(struct binder_buffer *buffer)
-{
-	return (void *)(((uintptr_t)(buffer + 1) - 1) & PAGE_MASK);
-}
-
-static void binder_delete_free_buffer(struct binder_proc *proc,
-				      struct binder_buffer *buffer)
-{
-	struct binder_buffer *prev, *next = NULL;
-	int free_page_end = 1;
-	int free_page_start = 1;
-
-	BUG_ON(proc->buffers.next == &buffer->entry);
-	prev = list_entry(buffer->entry.prev, struct binder_buffer, entry);
-	BUG_ON(!prev->free);
-	if (buffer_end_page(prev) == buffer_start_page(buffer)) {
-		free_page_start = 0;
-		if (buffer_end_page(prev) == buffer_end_page(buffer))
-			free_page_end = 0;
-		binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-			     "binder: %d: merge free, buffer %p "
-			     "share page with %p\n", proc->pid, buffer, prev);
-	}
-
-	if (!list_is_last(&buffer->entry, &proc->buffers)) {
-		next = list_entry(buffer->entry.next,
-				  struct binder_buffer, entry);
-		if (buffer_start_page(next) == buffer_end_page(buffer)) {
-			free_page_end = 0;
-			if (buffer_start_page(next) ==
-			    buffer_start_page(buffer))
-				free_page_start = 0;
-			binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-				     "binder: %d: merge free, buffer"
-				     " %p share page with %p\n", proc->pid,
-				     buffer, prev);
-		}
-	}
-	list_del(&buffer->entry);
-	if (free_page_start || free_page_end) {
-		binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-			     "binder: %d: merge free, buffer %p do "
-			     "not share page%s%s with with %p or %p\n",
-			     proc->pid, buffer, free_page_start ? "" : " end",
-			     free_page_end ? "" : " start", prev, next);
-		binder_update_page_range(proc, 0, free_page_start ?
-			buffer_start_page(buffer) : buffer_end_page(buffer),
-			(free_page_end ? buffer_end_page(buffer) :
-			buffer_start_page(buffer)) + PAGE_SIZE, NULL);
-	}
-}
-
-static void binder_free_buf(struct binder_proc *proc,
-			    struct binder_buffer *buffer)
-{
-	size_t size, buffer_size;
-
-	buffer_size = binder_buffer_size(proc, buffer);
-
-	size = ALIGN(buffer->data_size, sizeof(void *)) +
-		ALIGN(buffer->offsets_size, sizeof(void *));
-
-	binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-		     "binder: %d: binder_free_buf %p size %zd buffer"
-		     "_size %zd\n", proc->pid, buffer, size, buffer_size);
-
-	BUG_ON(buffer->free);
-	BUG_ON(size > buffer_size);
-	BUG_ON(buffer->transaction != NULL);
-	BUG_ON((void *)buffer < proc->buffer);
-	BUG_ON((void *)buffer > proc->buffer + proc->buffer_size);
-
-	if (buffer->async_transaction) {
-		proc->free_async_space += size + sizeof(struct binder_buffer);
-
-		binder_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC,
-			     "binder: %d: binder_free_buf size %zd "
-			     "async free %zd\n", proc->pid, size,
-			     proc->free_async_space);
-	}
-
-	binder_update_page_range(proc, 0,
-		(void *)PAGE_ALIGN((uintptr_t)buffer->data),
-		(void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK),
-		NULL);
-	rb_erase(&buffer->rb_node, &proc->allocated_buffers);
-	buffer->free = 1;
-	if (!list_is_last(&buffer->entry, &proc->buffers)) {
-		struct binder_buffer *next = list_entry(buffer->entry.next,
-						struct binder_buffer, entry);
-		if (next->free) {
-			rb_erase(&next->rb_node, &proc->free_buffers);
-			binder_delete_free_buffer(proc, next);
-		}
-	}
-	if (proc->buffers.next != &buffer->entry) {
-		struct binder_buffer *prev = list_entry(buffer->entry.prev,
-						struct binder_buffer, entry);
-		if (prev->free) {
-			binder_delete_free_buffer(proc, buffer);
-			rb_erase(&prev->rb_node, &proc->free_buffers);
-			buffer = prev;
-		}
-	}
-	binder_insert_free_buffer(proc, buffer);
-}
-
-static struct binder_node *binder_get_node(struct binder_proc *proc,
-					   void __user *ptr)
-{
-	struct rb_node *n = proc->nodes.rb_node;
-	struct binder_node *node;
-
-	while (n) {
-		node = rb_entry(n, struct binder_node, rb_node);
-
-		if (ptr < node->ptr)
-			n = n->rb_left;
-		else if (ptr > node->ptr)
-			n = n->rb_right;
-		else
-			return node;
-	}
-	return NULL;
-}
-
-static struct binder_node *binder_new_node(struct binder_proc *proc,
-					   void __user *ptr,
-					   void __user *cookie)
-{
-	struct rb_node **p = &proc->nodes.rb_node;
-	struct rb_node *parent = NULL;
-	struct binder_node *node;
-
-	while (*p) {
-		parent = *p;
-		node = rb_entry(parent, struct binder_node, rb_node);
-
-		if (ptr < node->ptr)
-			p = &(*p)->rb_left;
-		else if (ptr > node->ptr)
-			p = &(*p)->rb_right;
-		else
-			return NULL;
-	}
-
-	node = kzalloc(sizeof(*node), GFP_KERNEL);
-	if (node == NULL)
-		return NULL;
-	binder_stats_created(BINDER_STAT_NODE);
-	rb_link_node(&node->rb_node, parent, p);
-	rb_insert_color(&node->rb_node, &proc->nodes);
-	node->debug_id = ++binder_last_id;
-	node->proc = proc;
-	node->ptr = ptr;
-	node->cookie = cookie;
-	node->work.type = BINDER_WORK_NODE;
-	INIT_LIST_HEAD(&node->work.entry);
-	INIT_LIST_HEAD(&node->async_todo);
-	binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-		     "binder: %d:%d node %d u%p c%p created\n",
-		     proc->pid, current->pid, node->debug_id,
-		     node->ptr, node->cookie);
-	return node;
-}
-
-static int binder_inc_node(struct binder_node *node, int strong, int internal,
-			   struct list_head *target_list)
-{
-	if (strong) {
-		if (internal) {
-			if (target_list == NULL &&
-			    node->internal_strong_refs == 0 &&
-			    !(node == binder_context_mgr_node &&
-			    node->has_strong_ref)) {
-				printk(KERN_ERR "binder: invalid inc strong "
-					"node for %d\n", node->debug_id);
-				return -EINVAL;
-			}
-			node->internal_strong_refs++;
-		} else
-			node->local_strong_refs++;
-		if (!node->has_strong_ref && target_list) {
-			list_del_init(&node->work.entry);
-			list_add_tail(&node->work.entry, target_list);
-		}
-	} else {
-		if (!internal)
-			node->local_weak_refs++;
-		if (!node->has_weak_ref && list_empty(&node->work.entry)) {
-			if (target_list == NULL) {
-				printk(KERN_ERR "binder: invalid inc weak node "
-					"for %d\n", node->debug_id);
-				return -EINVAL;
-			}
-			list_add_tail(&node->work.entry, target_list);
-		}
-	}
-	return 0;
-}
-
-static int binder_dec_node(struct binder_node *node, int strong, int internal)
-{
-	if (strong) {
-		if (internal)
-			node->internal_strong_refs--;
-		else
-			node->local_strong_refs--;
-		if (node->local_strong_refs || node->internal_strong_refs)
-			return 0;
-	} else {
-		if (!internal)
-			node->local_weak_refs--;
-		if (node->local_weak_refs || !hlist_empty(&node->refs))
-			return 0;
-	}
-	if (node->proc && (node->has_strong_ref || node->has_weak_ref)) {
-		if (list_empty(&node->work.entry)) {
-			list_add_tail(&node->work.entry, &node->proc->todo);
-			wake_up_interruptible(&node->proc->wait);
-		}
-	} else {
-		if (hlist_empty(&node->refs) && !node->local_strong_refs &&
-		    !node->local_weak_refs) {
-			list_del_init(&node->work.entry);
-			if (node->proc) {
-				rb_erase(&node->rb_node, &node->proc->nodes);
-				binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-					     "binder: refless node %d deleted\n",
-					     node->debug_id);
-			} else {
-				hlist_del(&node->dead_node);
-				binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-					     "binder: dead node %d deleted\n",
-					     node->debug_id);
-			}
-			kfree(node);
-			binder_stats_deleted(BINDER_STAT_NODE);
-		}
-	}
-
-	return 0;
-}
-
-
-static struct binder_ref *binder_get_ref(struct binder_proc *proc,
-					 uint32_t desc)
-{
-	struct rb_node *n = proc->refs_by_desc.rb_node;
-	struct binder_ref *ref;
-
-	while (n) {
-		ref = rb_entry(n, struct binder_ref, rb_node_desc);
-
-		if (desc < ref->desc)
-			n = n->rb_left;
-		else if (desc > ref->desc)
-			n = n->rb_right;
-		else
-			return ref;
-	}
-	return NULL;
-}
-
-static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc,
-						  struct binder_node *node)
-{
-	struct rb_node *n;
-	struct rb_node **p = &proc->refs_by_node.rb_node;
-	struct rb_node *parent = NULL;
-	struct binder_ref *ref, *new_ref;
-
-	while (*p) {
-		parent = *p;
-		ref = rb_entry(parent, struct binder_ref, rb_node_node);
-
-		if (node < ref->node)
-			p = &(*p)->rb_left;
-		else if (node > ref->node)
-			p = &(*p)->rb_right;
-		else
-			return ref;
-	}
-	new_ref = kzalloc(sizeof(*ref), GFP_KERNEL);
-	if (new_ref == NULL)
-		return NULL;
-	binder_stats_created(BINDER_STAT_REF);
-	new_ref->debug_id = ++binder_last_id;
-	new_ref->proc = proc;
-	new_ref->node = node;
-	rb_link_node(&new_ref->rb_node_node, parent, p);
-	rb_insert_color(&new_ref->rb_node_node, &proc->refs_by_node);
-
-	new_ref->desc = (node == binder_context_mgr_node) ? 0 : 1;
-	for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) {
-		ref = rb_entry(n, struct binder_ref, rb_node_desc);
-		if (ref->desc > new_ref->desc)
-			break;
-		new_ref->desc = ref->desc + 1;
-	}
-
-	p = &proc->refs_by_desc.rb_node;
-	while (*p) {
-		parent = *p;
-		ref = rb_entry(parent, struct binder_ref, rb_node_desc);
-
-		if (new_ref->desc < ref->desc)
-			p = &(*p)->rb_left;
-		else if (new_ref->desc > ref->desc)
-			p = &(*p)->rb_right;
-		else
-			BUG();
-	}
-	rb_link_node(&new_ref->rb_node_desc, parent, p);
-	rb_insert_color(&new_ref->rb_node_desc, &proc->refs_by_desc);
-	if (node) {
-		hlist_add_head(&new_ref->node_entry, &node->refs);
-
-		binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-			     "binder: %d new ref %d desc %d for "
-			     "node %d\n", proc->pid, new_ref->debug_id,
-			     new_ref->desc, node->debug_id);
-	} else {
-		binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-			     "binder: %d new ref %d desc %d for "
-			     "dead node\n", proc->pid, new_ref->debug_id,
-			      new_ref->desc);
-	}
-	return new_ref;
-}
-
-static void binder_delete_ref(struct binder_ref *ref)
-{
-	binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-		     "binder: %d delete ref %d desc %d for "
-		     "node %d\n", ref->proc->pid, ref->debug_id,
-		     ref->desc, ref->node->debug_id);
-
-	rb_erase(&ref->rb_node_desc, &ref->proc->refs_by_desc);
-	rb_erase(&ref->rb_node_node, &ref->proc->refs_by_node);
-	if (ref->strong)
-		binder_dec_node(ref->node, 1, 1);
-	hlist_del(&ref->node_entry);
-	binder_dec_node(ref->node, 0, 1);
-	if (ref->death) {
-		binder_debug(BINDER_DEBUG_DEAD_BINDER,
-			     "binder: %d delete ref %d desc %d "
-			     "has death notification\n", ref->proc->pid,
-			     ref->debug_id, ref->desc);
-		list_del(&ref->death->work.entry);
-		kfree(ref->death);
-		binder_stats_deleted(BINDER_STAT_DEATH);
-	}
-	kfree(ref);
-	binder_stats_deleted(BINDER_STAT_REF);
-}
-
-static int binder_inc_ref(struct binder_ref *ref, int strong,
-			  struct list_head *target_list)
-{
-	int ret;
-	if (strong) {
-		if (ref->strong == 0) {
-			ret = binder_inc_node(ref->node, 1, 1, target_list);
-			if (ret)
-				return ret;
-		}
-		ref->strong++;
-	} else {
-		if (ref->weak == 0) {
-			ret = binder_inc_node(ref->node, 0, 1, target_list);
-			if (ret)
-				return ret;
-		}
-		ref->weak++;
-	}
-	return 0;
-}
-
-
-static int binder_dec_ref(struct binder_ref *ref, int strong)
-{
-	if (strong) {
-		if (ref->strong == 0) {
-			binder_user_error("binder: %d invalid dec strong, "
-					  "ref %d desc %d s %d w %d\n",
-					  ref->proc->pid, ref->debug_id,
-					  ref->desc, ref->strong, ref->weak);
-			return -EINVAL;
-		}
-		ref->strong--;
-		if (ref->strong == 0) {
-			int ret;
-			ret = binder_dec_node(ref->node, strong, 1);
-			if (ret)
-				return ret;
-		}
-	} else {
-		if (ref->weak == 0) {
-			binder_user_error("binder: %d invalid dec weak, "
-					  "ref %d desc %d s %d w %d\n",
-					  ref->proc->pid, ref->debug_id,
-					  ref->desc, ref->strong, ref->weak);
-			return -EINVAL;
-		}
-		ref->weak--;
-	}
-	if (ref->strong == 0 && ref->weak == 0)
-		binder_delete_ref(ref);
-	return 0;
-}
-
-static void binder_pop_transaction(struct binder_thread *target_thread,
-				   struct binder_transaction *t)
-{
-	if (target_thread) {
-		BUG_ON(target_thread->transaction_stack != t);
-		BUG_ON(target_thread->transaction_stack->from != target_thread);
-		target_thread->transaction_stack =
-			target_thread->transaction_stack->from_parent;
-		t->from = NULL;
-	}
-	t->need_reply = 0;
-	if (t->buffer)
-		t->buffer->transaction = NULL;
-	kfree(t);
-	binder_stats_deleted(BINDER_STAT_TRANSACTION);
-}
-
-static void binder_send_failed_reply(struct binder_transaction *t,
-				     uint32_t error_code)
-{
-	struct binder_thread *target_thread;
-	BUG_ON(t->flags & TF_ONE_WAY);
-	while (1) {
-		target_thread = t->from;
-		if (target_thread) {
-			if (target_thread->return_error != BR_OK &&
-			   target_thread->return_error2 == BR_OK) {
-				target_thread->return_error2 =
-					target_thread->return_error;
-				target_thread->return_error = BR_OK;
-			}
-			if (target_thread->return_error == BR_OK) {
-				binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
-					     "binder: send failed reply for "
-					     "transaction %d to %d:%d\n",
-					      t->debug_id, target_thread->proc->pid,
-					      target_thread->pid);
-
-				binder_pop_transaction(target_thread, t);
-				target_thread->return_error = error_code;
-				wake_up_interruptible(&target_thread->wait);
-			} else {
-				printk(KERN_ERR "binder: reply failed, target "
-					"thread, %d:%d, has error code %d "
-					"already\n", target_thread->proc->pid,
-					target_thread->pid,
-					target_thread->return_error);
-			}
-			return;
-		} else {
-			struct binder_transaction *next = t->from_parent;
-
-			binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
-				     "binder: send failed reply "
-				     "for transaction %d, target dead\n",
-				     t->debug_id);
-
-			binder_pop_transaction(target_thread, t);
-			if (next == NULL) {
-				binder_debug(BINDER_DEBUG_DEAD_BINDER,
-					     "binder: reply failed,"
-					     " no target thread at root\n");
-				return;
-			}
-			t = next;
-			binder_debug(BINDER_DEBUG_DEAD_BINDER,
-				     "binder: reply failed, no target "
-				     "thread -- retry %d\n", t->debug_id);
-		}
-	}
-}
-
-static void binder_transaction_buffer_release(struct binder_proc *proc,
-					      struct binder_buffer *buffer,
-					      size_t *failed_at)
-{
-	size_t *offp, *off_end;
-	int debug_id = buffer->debug_id;
-
-	binder_debug(BINDER_DEBUG_TRANSACTION,
-		     "binder: %d buffer release %d, size %zd-%zd, failed at %p\n",
-		     proc->pid, buffer->debug_id,
-		     buffer->data_size, buffer->offsets_size, failed_at);
-
-	if (buffer->target_node)
-		binder_dec_node(buffer->target_node, 1, 0);
-
-	offp = (size_t *)(buffer->data + ALIGN(buffer->data_size, sizeof(void *)));
-	if (failed_at)
-		off_end = failed_at;
-	else
-		off_end = (void *)offp + buffer->offsets_size;
-	for (; offp < off_end; offp++) {
-		struct flat_binder_object *fp;
-		if (*offp > buffer->data_size - sizeof(*fp) ||
-		    buffer->data_size < sizeof(*fp) ||
-		    !IS_ALIGNED(*offp, sizeof(void *))) {
-			printk(KERN_ERR "binder: transaction release %d bad"
-					"offset %zd, size %zd\n", debug_id,
-					*offp, buffer->data_size);
-			continue;
-		}
-		fp = (struct flat_binder_object *)(buffer->data + *offp);
-		switch (fp->type) {
-		case BINDER_TYPE_BINDER:
-		case BINDER_TYPE_WEAK_BINDER: {
-			struct binder_node *node = binder_get_node(proc, fp->binder);
-			if (node == NULL) {
-				printk(KERN_ERR "binder: transaction release %d"
-				       " bad node %p\n", debug_id, fp->binder);
-				break;
-			}
-			binder_debug(BINDER_DEBUG_TRANSACTION,
-				     "        node %d u%p\n",
-				     node->debug_id, node->ptr);
-			binder_dec_node(node, fp->type == BINDER_TYPE_BINDER, 0);
-		} break;
-		case BINDER_TYPE_HANDLE:
-		case BINDER_TYPE_WEAK_HANDLE: {
-			struct binder_ref *ref = binder_get_ref(proc, fp->handle);
-			if (ref == NULL) {
-				printk(KERN_ERR "binder: transaction release %d"
-				       " bad handle %ld\n", debug_id,
-				       fp->handle);
-				break;
-			}
-			binder_debug(BINDER_DEBUG_TRANSACTION,
-				     "        ref %d desc %d (node %d)\n",
-				     ref->debug_id, ref->desc, ref->node->debug_id);
-			binder_dec_ref(ref, fp->type == BINDER_TYPE_HANDLE);
-		} break;
-
-		case BINDER_TYPE_FD:
-			binder_debug(BINDER_DEBUG_TRANSACTION,
-				     "        fd %ld\n", fp->handle);
-			if (failed_at)
-				task_close_fd(proc, fp->handle);
-			break;
-
-		default:
-			printk(KERN_ERR "binder: transaction release %d bad "
-			       "object type %lx\n", debug_id, fp->type);
-			break;
-		}
-	}
-}
-
-static void binder_transaction(struct binder_proc *proc,
-			       struct binder_thread *thread,
-			       struct binder_transaction_data *tr, int reply)
-{
-	struct binder_transaction *t;
-	struct binder_work *tcomplete;
-	size_t *offp, *off_end;
-	struct binder_proc *target_proc;
-	struct binder_thread *target_thread = NULL;
-	struct binder_node *target_node = NULL;
-	struct list_head *target_list;
-	wait_queue_head_t *target_wait;
-	struct binder_transaction *in_reply_to = NULL;
-	struct binder_transaction_log_entry *e;
-	uint32_t return_error;
-
-	e = binder_transaction_log_add(&binder_transaction_log);
-	e->call_type = reply ? 2 : !!(tr->flags & TF_ONE_WAY);
-	e->from_proc = proc->pid;
-	e->from_thread = thread->pid;
-	e->target_handle = tr->target.handle;
-	e->data_size = tr->data_size;
-	e->offsets_size = tr->offsets_size;
-
-	if (reply) {
-		in_reply_to = thread->transaction_stack;
-		if (in_reply_to == NULL) {
-			binder_user_error("binder: %d:%d got reply transaction "
-					  "with no transaction stack\n",
-					  proc->pid, thread->pid);
-			return_error = BR_FAILED_REPLY;
-			goto err_empty_call_stack;
-		}
-		binder_set_nice(in_reply_to->saved_priority);
-		if (in_reply_to->to_thread != thread) {
-			binder_user_error("binder: %d:%d got reply transaction "
-				"with bad transaction stack,"
-				" transaction %d has target %d:%d\n",
-				proc->pid, thread->pid, in_reply_to->debug_id,
-				in_reply_to->to_proc ?
-				in_reply_to->to_proc->pid : 0,
-				in_reply_to->to_thread ?
-				in_reply_to->to_thread->pid : 0);
-			return_error = BR_FAILED_REPLY;
-			in_reply_to = NULL;
-			goto err_bad_call_stack;
-		}
-		thread->transaction_stack = in_reply_to->to_parent;
-		target_thread = in_reply_to->from;
-		if (target_thread == NULL) {
-			return_error = BR_DEAD_REPLY;
-			goto err_dead_binder;
-		}
-		if (target_thread->transaction_stack != in_reply_to) {
-			binder_user_error("binder: %d:%d got reply transaction "
-				"with bad target transaction stack %d, "
-				"expected %d\n",
-				proc->pid, thread->pid,
-				target_thread->transaction_stack ?
-				target_thread->transaction_stack->debug_id : 0,
-				in_reply_to->debug_id);
-			return_error = BR_FAILED_REPLY;
-			in_reply_to = NULL;
-			target_thread = NULL;
-			goto err_dead_binder;
-		}
-		target_proc = target_thread->proc;
-	} else {
-		if (tr->target.handle) {
-			struct binder_ref *ref;
-			ref = binder_get_ref(proc, tr->target.handle);
-			if (ref == NULL) {
-				binder_user_error("binder: %d:%d got "
-					"transaction to invalid handle\n",
-					proc->pid, thread->pid);
-				return_error = BR_FAILED_REPLY;
-				goto err_invalid_target_handle;
-			}
-			target_node = ref->node;
-		} else {
-			target_node = binder_context_mgr_node;
-			if (target_node == NULL) {
-				return_error = BR_DEAD_REPLY;
-				goto err_no_context_mgr_node;
-			}
-		}
-		e->to_node = target_node->debug_id;
-		target_proc = target_node->proc;
-		if (target_proc == NULL) {
-			return_error = BR_DEAD_REPLY;
-			goto err_dead_binder;
-		}
-		if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) {
-			struct binder_transaction *tmp;
-			tmp = thread->transaction_stack;
-			if (tmp->to_thread != thread) {
-				binder_user_error("binder: %d:%d got new "
-					"transaction with bad transaction stack"
-					", transaction %d has target %d:%d\n",
-					proc->pid, thread->pid, tmp->debug_id,
-					tmp->to_proc ? tmp->to_proc->pid : 0,
-					tmp->to_thread ?
-					tmp->to_thread->pid : 0);
-				return_error = BR_FAILED_REPLY;
-				goto err_bad_call_stack;
-			}
-			while (tmp) {
-				if (tmp->from && tmp->from->proc == target_proc)
-					target_thread = tmp->from;
-				tmp = tmp->from_parent;
-			}
-		}
-	}
-	if (target_thread) {
-		e->to_thread = target_thread->pid;
-		target_list = &target_thread->todo;
-		target_wait = &target_thread->wait;
-	} else {
-		target_list = &target_proc->todo;
-		target_wait = &target_proc->wait;
-	}
-	e->to_proc = target_proc->pid;
-
-	/* TODO: reuse incoming transaction for reply */
-	t = kzalloc(sizeof(*t), GFP_KERNEL);
-	if (t == NULL) {
-		return_error = BR_FAILED_REPLY;
-		goto err_alloc_t_failed;
-	}
-	binder_stats_created(BINDER_STAT_TRANSACTION);
-
-	tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);
-	if (tcomplete == NULL) {
-		return_error = BR_FAILED_REPLY;
-		goto err_alloc_tcomplete_failed;
-	}
-	binder_stats_created(BINDER_STAT_TRANSACTION_COMPLETE);
-
-	t->debug_id = ++binder_last_id;
-	e->debug_id = t->debug_id;
-
-	if (reply)
-		binder_debug(BINDER_DEBUG_TRANSACTION,
-			     "binder: %d:%d BC_REPLY %d -> %d:%d, "
-			     "data %p-%p size %zd-%zd\n",
-			     proc->pid, thread->pid, t->debug_id,
-			     target_proc->pid, target_thread->pid,
-			     tr->data.ptr.buffer, tr->data.ptr.offsets,
-			     tr->data_size, tr->offsets_size);
-	else
-		binder_debug(BINDER_DEBUG_TRANSACTION,
-			     "binder: %d:%d BC_TRANSACTION %d -> "
-			     "%d - node %d, data %p-%p size %zd-%zd\n",
-			     proc->pid, thread->pid, t->debug_id,
-			     target_proc->pid, target_node->debug_id,
-			     tr->data.ptr.buffer, tr->data.ptr.offsets,
-			     tr->data_size, tr->offsets_size);
-
-	if (!reply && !(tr->flags & TF_ONE_WAY))
-		t->from = thread;
-	else
-		t->from = NULL;
-	t->sender_euid = proc->tsk->cred->euid;
-	t->to_proc = target_proc;
-	t->to_thread = target_thread;
-	t->code = tr->code;
-	t->flags = tr->flags;
-	t->priority = task_nice(current);
-	t->buffer = binder_alloc_buf(target_proc, tr->data_size,
-		tr->offsets_size, !reply && (t->flags & TF_ONE_WAY));
-	if (t->buffer == NULL) {
-		return_error = BR_FAILED_REPLY;
-		goto err_binder_alloc_buf_failed;
-	}
-	t->buffer->allow_user_free = 0;
-	t->buffer->debug_id = t->debug_id;
-	t->buffer->transaction = t;
-	t->buffer->target_node = target_node;
-	if (target_node)
-		binder_inc_node(target_node, 1, 0, NULL);
-
-	offp = (size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *)));
-
-	if (copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) {
-		binder_user_error("binder: %d:%d got transaction with invalid "
-			"data ptr\n", proc->pid, thread->pid);
-		return_error = BR_FAILED_REPLY;
-		goto err_copy_data_failed;
-	}
-	if (copy_from_user(offp, tr->data.ptr.offsets, tr->offsets_size)) {
-		binder_user_error("binder: %d:%d got transaction with invalid "
-			"offsets ptr\n", proc->pid, thread->pid);
-		return_error = BR_FAILED_REPLY;
-		goto err_copy_data_failed;
-	}
-	if (!IS_ALIGNED(tr->offsets_size, sizeof(size_t))) {
-		binder_user_error("binder: %d:%d got transaction with "
-			"invalid offsets size, %zd\n",
-			proc->pid, thread->pid, tr->offsets_size);
-		return_error = BR_FAILED_REPLY;
-		goto err_bad_offset;
-	}
-	off_end = (void *)offp + tr->offsets_size;
-	for (; offp < off_end; offp++) {
-		struct flat_binder_object *fp;
-		if (*offp > t->buffer->data_size - sizeof(*fp) ||
-		    t->buffer->data_size < sizeof(*fp) ||
-		    !IS_ALIGNED(*offp, sizeof(void *))) {
-			binder_user_error("binder: %d:%d got transaction with "
-				"invalid offset, %zd\n",
-				proc->pid, thread->pid, *offp);
-			return_error = BR_FAILED_REPLY;
-			goto err_bad_offset;
-		}
-		fp = (struct flat_binder_object *)(t->buffer->data + *offp);
-		switch (fp->type) {
-		case BINDER_TYPE_BINDER:
-		case BINDER_TYPE_WEAK_BINDER: {
-			struct binder_ref *ref;
-			struct binder_node *node = binder_get_node(proc, fp->binder);
-			if (node == NULL) {
-				node = binder_new_node(proc, fp->binder, fp->cookie);
-				if (node == NULL) {
-					return_error = BR_FAILED_REPLY;
-					goto err_binder_new_node_failed;
-				}
-				node->min_priority = fp->flags & FLAT_BINDER_FLAG_PRIORITY_MASK;
-				node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);
-			}
-			if (fp->cookie != node->cookie) {
-				binder_user_error("binder: %d:%d sending u%p "
-					"node %d, cookie mismatch %p != %p\n",
-					proc->pid, thread->pid,
-					fp->binder, node->debug_id,
-					fp->cookie, node->cookie);
-				goto err_binder_get_ref_for_node_failed;
-			}
-			ref = binder_get_ref_for_node(target_proc, node);
-			if (ref == NULL) {
-				return_error = BR_FAILED_REPLY;
-				goto err_binder_get_ref_for_node_failed;
-			}
-			if (fp->type == BINDER_TYPE_BINDER)
-				fp->type = BINDER_TYPE_HANDLE;
-			else
-				fp->type = BINDER_TYPE_WEAK_HANDLE;
-			fp->handle = ref->desc;
-			binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE,
-				       &thread->todo);
-
-			binder_debug(BINDER_DEBUG_TRANSACTION,
-				     "        node %d u%p -> ref %d desc %d\n",
-				     node->debug_id, node->ptr, ref->debug_id,
-				     ref->desc);
-		} break;
-		case BINDER_TYPE_HANDLE:
-		case BINDER_TYPE_WEAK_HANDLE: {
-			struct binder_ref *ref = binder_get_ref(proc, fp->handle);
-			if (ref == NULL) {
-				binder_user_error("binder: %d:%d got "
-					"transaction with invalid "
-					"handle, %ld\n", proc->pid,
-					thread->pid, fp->handle);
-				return_error = BR_FAILED_REPLY;
-				goto err_binder_get_ref_failed;
-			}
-			if (ref->node->proc == target_proc) {
-				if (fp->type == BINDER_TYPE_HANDLE)
-					fp->type = BINDER_TYPE_BINDER;
-				else
-					fp->type = BINDER_TYPE_WEAK_BINDER;
-				fp->binder = ref->node->ptr;
-				fp->cookie = ref->node->cookie;
-				binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL);
-				binder_debug(BINDER_DEBUG_TRANSACTION,
-					     "        ref %d desc %d -> node %d u%p\n",
-					     ref->debug_id, ref->desc, ref->node->debug_id,
-					     ref->node->ptr);
-			} else {
-				struct binder_ref *new_ref;
-				new_ref = binder_get_ref_for_node(target_proc, ref->node);
-				if (new_ref == NULL) {
-					return_error = BR_FAILED_REPLY;
-					goto err_binder_get_ref_for_node_failed;
-				}
-				fp->handle = new_ref->desc;
-				binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL);
-				binder_debug(BINDER_DEBUG_TRANSACTION,
-					     "        ref %d desc %d -> ref %d desc %d (node %d)\n",
-					     ref->debug_id, ref->desc, new_ref->debug_id,
-					     new_ref->desc, ref->node->debug_id);
-			}
-		} break;
-
-		case BINDER_TYPE_FD: {
-			int target_fd;
-			struct file *file;
-
-			if (reply) {
-				if (!(in_reply_to->flags & TF_ACCEPT_FDS)) {
-					binder_user_error("binder: %d:%d got reply with fd, %ld, but target does not allow fds\n",
-						proc->pid, thread->pid, fp->handle);
-					return_error = BR_FAILED_REPLY;
-					goto err_fd_not_allowed;
-				}
-			} else if (!target_node->accept_fds) {
-				binder_user_error("binder: %d:%d got transaction with fd, %ld, but target does not allow fds\n",
-					proc->pid, thread->pid, fp->handle);
-				return_error = BR_FAILED_REPLY;
-				goto err_fd_not_allowed;
-			}
-
-			file = fget(fp->handle);
-			if (file == NULL) {
-				binder_user_error("binder: %d:%d got transaction with invalid fd, %ld\n",
-					proc->pid, thread->pid, fp->handle);
-				return_error = BR_FAILED_REPLY;
-				goto err_fget_failed;
-			}
-			target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC);
-			if (target_fd < 0) {
-				fput(file);
-				return_error = BR_FAILED_REPLY;
-				goto err_get_unused_fd_failed;
-			}
-			task_fd_install(target_proc, target_fd, file);
-			binder_debug(BINDER_DEBUG_TRANSACTION,
-				     "        fd %ld -> %d\n", fp->handle, target_fd);
-			/* TODO: fput? */
-			fp->handle = target_fd;
-		} break;
-
-		default:
-			binder_user_error("binder: %d:%d got transactio"
-				"n with invalid object type, %lx\n",
-				proc->pid, thread->pid, fp->type);
-			return_error = BR_FAILED_REPLY;
-			goto err_bad_object_type;
-		}
-	}
-	if (reply) {
-		BUG_ON(t->buffer->async_transaction != 0);
-		binder_pop_transaction(target_thread, in_reply_to);
-	} else if (!(t->flags & TF_ONE_WAY)) {
-		BUG_ON(t->buffer->async_transaction != 0);
-		t->need_reply = 1;
-		t->from_parent = thread->transaction_stack;
-		thread->transaction_stack = t;
-	} else {
-		BUG_ON(target_node == NULL);
-		BUG_ON(t->buffer->async_transaction != 1);
-		if (target_node->has_async_transaction) {
-			target_list = &target_node->async_todo;
-			target_wait = NULL;
-		} else
-			target_node->has_async_transaction = 1;
-	}
-	t->work.type = BINDER_WORK_TRANSACTION;
-	list_add_tail(&t->work.entry, target_list);
-	tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
-	list_add_tail(&tcomplete->entry, &thread->todo);
-	if (target_wait)
-		wake_up_interruptible(target_wait);
-	return;
-
-err_get_unused_fd_failed:
-err_fget_failed:
-err_fd_not_allowed:
-err_binder_get_ref_for_node_failed:
-err_binder_get_ref_failed:
-err_binder_new_node_failed:
-err_bad_object_type:
-err_bad_offset:
-err_copy_data_failed:
-	binder_transaction_buffer_release(target_proc, t->buffer, offp);
-	t->buffer->transaction = NULL;
-	binder_free_buf(target_proc, t->buffer);
-err_binder_alloc_buf_failed:
-	kfree(tcomplete);
-	binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
-err_alloc_tcomplete_failed:
-	kfree(t);
-	binder_stats_deleted(BINDER_STAT_TRANSACTION);
-err_alloc_t_failed:
-err_bad_call_stack:
-err_empty_call_stack:
-err_dead_binder:
-err_invalid_target_handle:
-err_no_context_mgr_node:
-	binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
-		     "binder: %d:%d transaction failed %d, size %zd-%zd\n",
-		     proc->pid, thread->pid, return_error,
-		     tr->data_size, tr->offsets_size);
-
-	{
-		struct binder_transaction_log_entry *fe;
-		fe = binder_transaction_log_add(&binder_transaction_log_failed);
-		*fe = *e;
-	}
-
-	BUG_ON(thread->return_error != BR_OK);
-	if (in_reply_to) {
-		thread->return_error = BR_TRANSACTION_COMPLETE;
-		binder_send_failed_reply(in_reply_to, return_error);
-	} else
-		thread->return_error = return_error;
-}
-
-int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
-			void __user *buffer, int size, signed long *consumed)
-{
-	uint32_t cmd;
-	void __user *ptr = buffer + *consumed;
-	void __user *end = buffer + size;
-
-	while (ptr < end && thread->return_error == BR_OK) {
-		if (get_user(cmd, (uint32_t __user *)ptr))
-			return -EFAULT;
-		ptr += sizeof(uint32_t);
-		if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.bc)) {
-			binder_stats.bc[_IOC_NR(cmd)]++;
-			proc->stats.bc[_IOC_NR(cmd)]++;
-			thread->stats.bc[_IOC_NR(cmd)]++;
-		}
-		switch (cmd) {
-		case BC_INCREFS:
-		case BC_ACQUIRE:
-		case BC_RELEASE:
-		case BC_DECREFS: {
-			uint32_t target;
-			struct binder_ref *ref;
-			const char *debug_string;
-
-			if (get_user(target, (uint32_t __user *)ptr))
-				return -EFAULT;
-			ptr += sizeof(uint32_t);
-			if (target == 0 && binder_context_mgr_node &&
-			    (cmd == BC_INCREFS || cmd == BC_ACQUIRE)) {
-				ref = binder_get_ref_for_node(proc,
-					       binder_context_mgr_node);
-				if (ref->desc != target) {
-					binder_user_error("binder: %d:"
-						"%d tried to acquire "
-						"reference to desc 0, "
-						"got %d instead\n",
-						proc->pid, thread->pid,
-						ref->desc);
-				}
-			} else
-				ref = binder_get_ref(proc, target);
-			if (ref == NULL) {
-				binder_user_error("binder: %d:%d refcou"
-					"nt change on invalid ref %d\n",
-					proc->pid, thread->pid, target);
-				break;
-			}
-			switch (cmd) {
-			case BC_INCREFS:
-				debug_string = "IncRefs";
-				binder_inc_ref(ref, 0, NULL);
-				break;
-			case BC_ACQUIRE:
-				debug_string = "Acquire";
-				binder_inc_ref(ref, 1, NULL);
-				break;
-			case BC_RELEASE:
-				debug_string = "Release";
-				binder_dec_ref(ref, 1);
-				break;
-			case BC_DECREFS:
-			default:
-				debug_string = "DecRefs";
-				binder_dec_ref(ref, 0);
-				break;
-			}
-			binder_debug(BINDER_DEBUG_USER_REFS,
-				     "binder: %d:%d %s ref %d desc %d s %d w %d for node %d\n",
-				     proc->pid, thread->pid, debug_string, ref->debug_id,
-				     ref->desc, ref->strong, ref->weak, ref->node->debug_id);
-			break;
-		}
-		case BC_INCREFS_DONE:
-		case BC_ACQUIRE_DONE: {
-			void __user *node_ptr;
-			void *cookie;
-			struct binder_node *node;
-
-			if (get_user(node_ptr, (void * __user *)ptr))
-				return -EFAULT;
-			ptr += sizeof(void *);
-			if (get_user(cookie, (void * __user *)ptr))
-				return -EFAULT;
-			ptr += sizeof(void *);
-			node = binder_get_node(proc, node_ptr);
-			if (node == NULL) {
-				binder_user_error("binder: %d:%d "
-					"%s u%p no match\n",
-					proc->pid, thread->pid,
-					cmd == BC_INCREFS_DONE ?
-					"BC_INCREFS_DONE" :
-					"BC_ACQUIRE_DONE",
-					node_ptr);
-				break;
-			}
-			if (cookie != node->cookie) {
-				binder_user_error("binder: %d:%d %s u%p node %d"
-					" cookie mismatch %p != %p\n",
-					proc->pid, thread->pid,
-					cmd == BC_INCREFS_DONE ?
-					"BC_INCREFS_DONE" : "BC_ACQUIRE_DONE",
-					node_ptr, node->debug_id,
-					cookie, node->cookie);
-				break;
-			}
-			if (cmd == BC_ACQUIRE_DONE) {
-				if (node->pending_strong_ref == 0) {
-					binder_user_error("binder: %d:%d "
-						"BC_ACQUIRE_DONE node %d has "
-						"no pending acquire request\n",
-						proc->pid, thread->pid,
-						node->debug_id);
-					break;
-				}
-				node->pending_strong_ref = 0;
-			} else {
-				if (node->pending_weak_ref == 0) {
-					binder_user_error("binder: %d:%d "
-						"BC_INCREFS_DONE node %d has "
-						"no pending increfs request\n",
-						proc->pid, thread->pid,
-						node->debug_id);
-					break;
-				}
-				node->pending_weak_ref = 0;
-			}
-			binder_dec_node(node, cmd == BC_ACQUIRE_DONE, 0);
-			binder_debug(BINDER_DEBUG_USER_REFS,
-				     "binder: %d:%d %s node %d ls %d lw %d\n",
-				     proc->pid, thread->pid,
-				     cmd == BC_INCREFS_DONE ? "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE",
-				     node->debug_id, node->local_strong_refs, node->local_weak_refs);
-			break;
-		}
-		case BC_ATTEMPT_ACQUIRE:
-			printk(KERN_ERR "binder: BC_ATTEMPT_ACQUIRE not supported\n");
-			return -EINVAL;
-		case BC_ACQUIRE_RESULT:
-			printk(KERN_ERR "binder: BC_ACQUIRE_RESULT not supported\n");
-			return -EINVAL;
-
-		case BC_FREE_BUFFER: {
-			void __user *data_ptr;
-			struct binder_buffer *buffer;
-
-			if (get_user(data_ptr, (void * __user *)ptr))
-				return -EFAULT;
-			ptr += sizeof(void *);
-
-			buffer = binder_buffer_lookup(proc, data_ptr);
-			if (buffer == NULL) {
-				binder_user_error("binder: %d:%d "
-					"BC_FREE_BUFFER u%p no match\n",
-					proc->pid, thread->pid, data_ptr);
-				break;
-			}
-			if (!buffer->allow_user_free) {
-				binder_user_error("binder: %d:%d "
-					"BC_FREE_BUFFER u%p matched "
-					"unreturned buffer\n",
-					proc->pid, thread->pid, data_ptr);
-				break;
-			}
-			binder_debug(BINDER_DEBUG_FREE_BUFFER,
-				     "binder: %d:%d BC_FREE_BUFFER u%p found buffer %d for %s transaction\n",
-				     proc->pid, thread->pid, data_ptr, buffer->debug_id,
-				     buffer->transaction ? "active" : "finished");
-
-			if (buffer->transaction) {
-				buffer->transaction->buffer = NULL;
-				buffer->transaction = NULL;
-			}
-			if (buffer->async_transaction && buffer->target_node) {
-				BUG_ON(!buffer->target_node->has_async_transaction);
-				if (list_empty(&buffer->target_node->async_todo))
-					buffer->target_node->has_async_transaction = 0;
-				else
-					list_move_tail(buffer->target_node->async_todo.next, &thread->todo);
-			}
-			binder_transaction_buffer_release(proc, buffer, NULL);
-			binder_free_buf(proc, buffer);
-			break;
-		}
-
-		case BC_TRANSACTION:
-		case BC_REPLY: {
-			struct binder_transaction_data tr;
-
-			if (copy_from_user(&tr, ptr, sizeof(tr)))
-				return -EFAULT;
-			ptr += sizeof(tr);
-			binder_transaction(proc, thread, &tr, cmd == BC_REPLY);
-			break;
-		}
-
-		case BC_REGISTER_LOOPER:
-			binder_debug(BINDER_DEBUG_THREADS,
-				     "binder: %d:%d BC_REGISTER_LOOPER\n",
-				     proc->pid, thread->pid);
-			if (thread->looper & BINDER_LOOPER_STATE_ENTERED) {
-				thread->looper |= BINDER_LOOPER_STATE_INVALID;
-				binder_user_error("binder: %d:%d ERROR:"
-					" BC_REGISTER_LOOPER called "
-					"after BC_ENTER_LOOPER\n",
-					proc->pid, thread->pid);
-			} else if (proc->requested_threads == 0) {
-				thread->looper |= BINDER_LOOPER_STATE_INVALID;
-				binder_user_error("binder: %d:%d ERROR:"
-					" BC_REGISTER_LOOPER called "
-					"without request\n",
-					proc->pid, thread->pid);
-			} else {
-				proc->requested_threads--;
-				proc->requested_threads_started++;
-			}
-			thread->looper |= BINDER_LOOPER_STATE_REGISTERED;
-			break;
-		case BC_ENTER_LOOPER:
-			binder_debug(BINDER_DEBUG_THREADS,
-				     "binder: %d:%d BC_ENTER_LOOPER\n",
-				     proc->pid, thread->pid);
-			if (thread->looper & BINDER_LOOPER_STATE_REGISTERED) {
-				thread->looper |= BINDER_LOOPER_STATE_INVALID;
-				binder_user_error("binder: %d:%d ERROR:"
-					" BC_ENTER_LOOPER called after "
-					"BC_REGISTER_LOOPER\n",
-					proc->pid, thread->pid);
-			}
-			thread->looper |= BINDER_LOOPER_STATE_ENTERED;
-			break;
-		case BC_EXIT_LOOPER:
-			binder_debug(BINDER_DEBUG_THREADS,
-				     "binder: %d:%d BC_EXIT_LOOPER\n",
-				     proc->pid, thread->pid);
-			thread->looper |= BINDER_LOOPER_STATE_EXITED;
-			break;
-
-		case BC_REQUEST_DEATH_NOTIFICATION:
-		case BC_CLEAR_DEATH_NOTIFICATION: {
-			uint32_t target;
-			void __user *cookie;
-			struct binder_ref *ref;
-			struct binder_ref_death *death;
-
-			if (get_user(target, (uint32_t __user *)ptr))
-				return -EFAULT;
-			ptr += sizeof(uint32_t);
-			if (get_user(cookie, (void __user * __user *)ptr))
-				return -EFAULT;
-			ptr += sizeof(void *);
-			ref = binder_get_ref(proc, target);
-			if (ref == NULL) {
-				binder_user_error("binder: %d:%d %s "
-					"invalid ref %d\n",
-					proc->pid, thread->pid,
-					cmd == BC_REQUEST_DEATH_NOTIFICATION ?
-					"BC_REQUEST_DEATH_NOTIFICATION" :
-					"BC_CLEAR_DEATH_NOTIFICATION",
-					target);
-				break;
-			}
-
-			binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
-				     "binder: %d:%d %s %p ref %d desc %d s %d w %d for node %d\n",
-				     proc->pid, thread->pid,
-				     cmd == BC_REQUEST_DEATH_NOTIFICATION ?
-				     "BC_REQUEST_DEATH_NOTIFICATION" :
-				     "BC_CLEAR_DEATH_NOTIFICATION",
-				     cookie, ref->debug_id, ref->desc,
-				     ref->strong, ref->weak, ref->node->debug_id);
-
-			if (cmd == BC_REQUEST_DEATH_NOTIFICATION) {
-				if (ref->death) {
-					binder_user_error("binder: %d:%"
-						"d BC_REQUEST_DEATH_NOTI"
-						"FICATION death notific"
-						"ation already set\n",
-						proc->pid, thread->pid);
-					break;
-				}
-				death = kzalloc(sizeof(*death), GFP_KERNEL);
-				if (death == NULL) {
-					thread->return_error = BR_ERROR;
-					binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
-						     "binder: %d:%d "
-						     "BC_REQUEST_DEATH_NOTIFICATION failed\n",
-						     proc->pid, thread->pid);
-					break;
-				}
-				binder_stats_created(BINDER_STAT_DEATH);
-				INIT_LIST_HEAD(&death->work.entry);
-				death->cookie = cookie;
-				ref->death = death;
-				if (ref->node->proc == NULL) {
-					ref->death->work.type = BINDER_WORK_DEAD_BINDER;
-					if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) {
-						list_add_tail(&ref->death->work.entry, &thread->todo);
-					} else {
-						list_add_tail(&ref->death->work.entry, &proc->todo);
-						wake_up_interruptible(&proc->wait);
-					}
-				}
-			} else {
-				if (ref->death == NULL) {
-					binder_user_error("binder: %d:%"
-						"d BC_CLEAR_DEATH_NOTIFI"
-						"CATION death notificat"
-						"ion not active\n",
-						proc->pid, thread->pid);
-					break;
-				}
-				death = ref->death;
-				if (death->cookie != cookie) {
-					binder_user_error("binder: %d:%"
-						"d BC_CLEAR_DEATH_NOTIFI"
-						"CATION death notificat"
-						"ion cookie mismatch "
-						"%p != %p\n",
-						proc->pid, thread->pid,
-						death->cookie, cookie);
-					break;
-				}
-				ref->death = NULL;
-				if (list_empty(&death->work.entry)) {
-					death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION;
-					if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) {
-						list_add_tail(&death->work.entry, &thread->todo);
-					} else {
-						list_add_tail(&death->work.entry, &proc->todo);
-						wake_up_interruptible(&proc->wait);
-					}
-				} else {
-					BUG_ON(death->work.type != BINDER_WORK_DEAD_BINDER);
-					death->work.type = BINDER_WORK_DEAD_BINDER_AND_CLEAR;
-				}
-			}
-		} break;
-		case BC_DEAD_BINDER_DONE: {
-			struct binder_work *w;
-			void __user *cookie;
-			struct binder_ref_death *death = NULL;
-			if (get_user(cookie, (void __user * __user *)ptr))
-				return -EFAULT;
-
-			ptr += sizeof(void *);
-			list_for_each_entry(w, &proc->delivered_death, entry) {
-				struct binder_ref_death *tmp_death = container_of(w, struct binder_ref_death, work);
-				if (tmp_death->cookie == cookie) {
-					death = tmp_death;
-					break;
-				}
-			}
-			binder_debug(BINDER_DEBUG_DEAD_BINDER,
-				     "binder: %d:%d BC_DEAD_BINDER_DONE %p found %p\n",
-				     proc->pid, thread->pid, cookie, death);
-			if (death == NULL) {
-				binder_user_error("binder: %d:%d BC_DEAD"
-					"_BINDER_DONE %p not found\n",
-					proc->pid, thread->pid, cookie);
-				break;
-			}
-
-			list_del_init(&death->work.entry);
-			if (death->work.type == BINDER_WORK_DEAD_BINDER_AND_CLEAR) {
-				death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION;
-				if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) {
-					list_add_tail(&death->work.entry, &thread->todo);
-				} else {
-					list_add_tail(&death->work.entry, &proc->todo);
-					wake_up_interruptible(&proc->wait);
-				}
-			}
-		} break;
-
-		default:
-			printk(KERN_ERR "binder: %d:%d unknown command %d\n",
-			       proc->pid, thread->pid, cmd);
-			return -EINVAL;
-		}
-		*consumed = ptr - buffer;
-	}
-	return 0;
-}
-
-void binder_stat_br(struct binder_proc *proc, struct binder_thread *thread,
-		    uint32_t cmd)
-{
-	if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.br)) {
-		binder_stats.br[_IOC_NR(cmd)]++;
-		proc->stats.br[_IOC_NR(cmd)]++;
-		thread->stats.br[_IOC_NR(cmd)]++;
-	}
-}
-
-static int binder_has_proc_work(struct binder_proc *proc,
-				struct binder_thread *thread)
-{
-	return !list_empty(&proc->todo) ||
-		(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN);
-}
-
-static int binder_has_thread_work(struct binder_thread *thread)
-{
-	return !list_empty(&thread->todo) || thread->return_error != BR_OK ||
-		(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN);
-}
-
-static int binder_thread_read(struct binder_proc *proc,
-			      struct binder_thread *thread,
-			      void  __user *buffer, int size,
-			      signed long *consumed, int non_block)
-{
-	void __user *ptr = buffer + *consumed;
-	void __user *end = buffer + size;
-
-	int ret = 0;
-	int wait_for_proc_work;
-
-	if (*consumed == 0) {
-		if (put_user(BR_NOOP, (uint32_t __user *)ptr))
-			return -EFAULT;
-		ptr += sizeof(uint32_t);
-	}
-
-retry:
-	wait_for_proc_work = thread->transaction_stack == NULL &&
-				list_empty(&thread->todo);
-
-	if (thread->return_error != BR_OK && ptr < end) {
-		if (thread->return_error2 != BR_OK) {
-			if (put_user(thread->return_error2, (uint32_t __user *)ptr))
-				return -EFAULT;
-			ptr += sizeof(uint32_t);
-			if (ptr == end)
-				goto done;
-			thread->return_error2 = BR_OK;
-		}
-		if (put_user(thread->return_error, (uint32_t __user *)ptr))
-			return -EFAULT;
-		ptr += sizeof(uint32_t);
-		thread->return_error = BR_OK;
-		goto done;
-	}
-
-
-	thread->looper |= BINDER_LOOPER_STATE_WAITING;
-	if (wait_for_proc_work)
-		proc->ready_threads++;
-	mutex_unlock(&binder_lock);
-	if (wait_for_proc_work) {
-		if (!(thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
-					BINDER_LOOPER_STATE_ENTERED))) {
-			binder_user_error("binder: %d:%d ERROR: Thread waiting "
-				"for process work before calling BC_REGISTER_"
-				"LOOPER or BC_ENTER_LOOPER (state %x)\n",
-				proc->pid, thread->pid, thread->looper);
-			wait_event_interruptible(binder_user_error_wait,
-						 binder_stop_on_user_error < 2);
-		}
-		binder_set_nice(proc->default_priority);
-		if (non_block) {
-			if (!binder_has_proc_work(proc, thread))
-				ret = -EAGAIN;
-		} else
-			ret = wait_event_interruptible_exclusive(proc->wait, binder_has_proc_work(proc, thread));
-	} else {
-		if (non_block) {
-			if (!binder_has_thread_work(thread))
-				ret = -EAGAIN;
-		} else
-			ret = wait_event_interruptible(thread->wait, binder_has_thread_work(thread));
-	}
-	mutex_lock(&binder_lock);
-	if (wait_for_proc_work)
-		proc->ready_threads--;
-	thread->looper &= ~BINDER_LOOPER_STATE_WAITING;
-
-	if (ret)
-		return ret;
-
-	while (1) {
-		uint32_t cmd;
-		struct binder_transaction_data tr;
-		struct binder_work *w;
-		struct binder_transaction *t = NULL;
-
-		if (!list_empty(&thread->todo))
-			w = list_first_entry(&thread->todo, struct binder_work, entry);
-		else if (!list_empty(&proc->todo) && wait_for_proc_work)
-			w = list_first_entry(&proc->todo, struct binder_work, entry);
-		else {
-			if (ptr - buffer == 4 && !(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN)) /* no data added */
-				goto retry;
-			break;
-		}
-
-		if (end - ptr < sizeof(tr) + 4)
-			break;
-
-		switch (w->type) {
-		case BINDER_WORK_TRANSACTION: {
-			t = container_of(w, struct binder_transaction, work);
-		} break;
-		case BINDER_WORK_TRANSACTION_COMPLETE: {
-			cmd = BR_TRANSACTION_COMPLETE;
-			if (put_user(cmd, (uint32_t __user *)ptr))
-				return -EFAULT;
-			ptr += sizeof(uint32_t);
-
-			binder_stat_br(proc, thread, cmd);
-			binder_debug(BINDER_DEBUG_TRANSACTION_COMPLETE,
-				     "binder: %d:%d BR_TRANSACTION_COMPLETE\n",
-				     proc->pid, thread->pid);
-
-			list_del(&w->entry);
-			kfree(w);
-			binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
-		} break;
-		case BINDER_WORK_NODE: {
-			struct binder_node *node = container_of(w, struct binder_node, work);
-			uint32_t cmd = BR_NOOP;
-			const char *cmd_name;
-			int strong = node->internal_strong_refs || node->local_strong_refs;
-			int weak = !hlist_empty(&node->refs) || node->local_weak_refs || strong;
-			if (weak && !node->has_weak_ref) {
-				cmd = BR_INCREFS;
-				cmd_name = "BR_INCREFS";
-				node->has_weak_ref = 1;
-				node->pending_weak_ref = 1;
-				node->local_weak_refs++;
-			} else if (strong && !node->has_strong_ref) {
-				cmd = BR_ACQUIRE;
-				cmd_name = "BR_ACQUIRE";
-				node->has_strong_ref = 1;
-				node->pending_strong_ref = 1;
-				node->local_strong_refs++;
-			} else if (!strong && node->has_strong_ref) {
-				cmd = BR_RELEASE;
-				cmd_name = "BR_RELEASE";
-				node->has_strong_ref = 0;
-			} else if (!weak && node->has_weak_ref) {
-				cmd = BR_DECREFS;
-				cmd_name = "BR_DECREFS";
-				node->has_weak_ref = 0;
-			}
-			if (cmd != BR_NOOP) {
-				if (put_user(cmd, (uint32_t __user *)ptr))
-					return -EFAULT;
-				ptr += sizeof(uint32_t);
-				if (put_user(node->ptr, (void * __user *)ptr))
-					return -EFAULT;
-				ptr += sizeof(void *);
-				if (put_user(node->cookie, (void * __user *)ptr))
-					return -EFAULT;
-				ptr += sizeof(void *);
-
-				binder_stat_br(proc, thread, cmd);
-				binder_debug(BINDER_DEBUG_USER_REFS,
-					     "binder: %d:%d %s %d u%p c%p\n",
-					     proc->pid, thread->pid, cmd_name, node->debug_id, node->ptr, node->cookie);
-			} else {
-				list_del_init(&w->entry);
-				if (!weak && !strong) {
-					binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-						     "binder: %d:%d node %d u%p c%p deleted\n",
-						     proc->pid, thread->pid, node->debug_id,
-						     node->ptr, node->cookie);
-					rb_erase(&node->rb_node, &proc->nodes);
-					kfree(node);
-					binder_stats_deleted(BINDER_STAT_NODE);
-				} else {
-					binder_debug(BINDER_DEBUG_INTERNAL_REFS,
-						     "binder: %d:%d node %d u%p c%p state unchanged\n",
-						     proc->pid, thread->pid, node->debug_id, node->ptr,
-						     node->cookie);
-				}
-			}
-		} break;
-		case BINDER_WORK_DEAD_BINDER:
-		case BINDER_WORK_DEAD_BINDER_AND_CLEAR:
-		case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: {
-			struct binder_ref_death *death;
-			uint32_t cmd;
-
-			death = container_of(w, struct binder_ref_death, work);
-			if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION)
-				cmd = BR_CLEAR_DEATH_NOTIFICATION_DONE;
-			else
-				cmd = BR_DEAD_BINDER;
-			if (put_user(cmd, (uint32_t __user *)ptr))
-				return -EFAULT;
-			ptr += sizeof(uint32_t);
-			if (put_user(death->cookie, (void * __user *)ptr))
-				return -EFAULT;
-			ptr += sizeof(void *);
-			binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
-				     "binder: %d:%d %s %p\n",
-				      proc->pid, thread->pid,
-				      cmd == BR_DEAD_BINDER ?
-				      "BR_DEAD_BINDER" :
-				      "BR_CLEAR_DEATH_NOTIFICATION_DONE",
-				      death->cookie);
-
-			if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) {
-				list_del(&w->entry);
-				kfree(death);
-				binder_stats_deleted(BINDER_STAT_DEATH);
-			} else
-				list_move(&w->entry, &proc->delivered_death);
-			if (cmd == BR_DEAD_BINDER)
-				goto done; /* DEAD_BINDER notifications can cause transactions */
-		} break;
-		}
-
-		if (!t)
-			continue;
-
-		BUG_ON(t->buffer == NULL);
-		if (t->buffer->target_node) {
-			struct binder_node *target_node = t->buffer->target_node;
-			tr.target.ptr = target_node->ptr;
-			tr.cookie =  target_node->cookie;
-			t->saved_priority = task_nice(current);
-			if (t->priority < target_node->min_priority &&
-			    !(t->flags & TF_ONE_WAY))
-				binder_set_nice(t->priority);
-			else if (!(t->flags & TF_ONE_WAY) ||
-				 t->saved_priority > target_node->min_priority)
-				binder_set_nice(target_node->min_priority);
-			cmd = BR_TRANSACTION;
-		} else {
-			tr.target.ptr = NULL;
-			tr.cookie = NULL;
-			cmd = BR_REPLY;
-		}
-		tr.code = t->code;
-		tr.flags = t->flags;
-		tr.sender_euid = t->sender_euid;
-
-		if (t->from) {
-			struct task_struct *sender = t->from->proc->tsk;
-			tr.sender_pid = task_tgid_nr_ns(sender,
-							current->nsproxy->pid_ns);
-		} else {
-			tr.sender_pid = 0;
-		}
-
-		tr.data_size = t->buffer->data_size;
-		tr.offsets_size = t->buffer->offsets_size;
-		tr.data.ptr.buffer = (void *)t->buffer->data +
-					proc->user_buffer_offset;
-		tr.data.ptr.offsets = tr.data.ptr.buffer +
-					ALIGN(t->buffer->data_size,
-					    sizeof(void *));
-
-		if (put_user(cmd, (uint32_t __user *)ptr))
-			return -EFAULT;
-		ptr += sizeof(uint32_t);
-		if (copy_to_user(ptr, &tr, sizeof(tr)))
-			return -EFAULT;
-		ptr += sizeof(tr);
-
-		binder_stat_br(proc, thread, cmd);
-		binder_debug(BINDER_DEBUG_TRANSACTION,
-			     "binder: %d:%d %s %d %d:%d, cmd %d"
-			     "size %zd-%zd ptr %p-%p\n",
-			     proc->pid, thread->pid,
-			     (cmd == BR_TRANSACTION) ? "BR_TRANSACTION" :
-			     "BR_REPLY",
-			     t->debug_id, t->from ? t->from->proc->pid : 0,
-			     t->from ? t->from->pid : 0, cmd,
-			     t->buffer->data_size, t->buffer->offsets_size,
-			     tr.data.ptr.buffer, tr.data.ptr.offsets);
-
-		list_del(&t->work.entry);
-		t->buffer->allow_user_free = 1;
-		if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY)) {
-			t->to_parent = thread->transaction_stack;
-			t->to_thread = thread;
-			thread->transaction_stack = t;
-		} else {
-			t->buffer->transaction = NULL;
-			kfree(t);
-			binder_stats_deleted(BINDER_STAT_TRANSACTION);
-		}
-		break;
-	}
-
-done:
-
-	*consumed = ptr - buffer;
-	if (proc->requested_threads + proc->ready_threads == 0 &&
-	    proc->requested_threads_started < proc->max_threads &&
-	    (thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
-	     BINDER_LOOPER_STATE_ENTERED)) /* the user-space code fails to */
-	     /*spawn a new thread if we leave this out */) {
-		proc->requested_threads++;
-		binder_debug(BINDER_DEBUG_THREADS,
-			     "binder: %d:%d BR_SPAWN_LOOPER\n",
-			     proc->pid, thread->pid);
-		if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer))
-			return -EFAULT;
-	}
-	return 0;
-}
-
-static void binder_release_work(struct list_head *list)
-{
-	struct binder_work *w;
-	while (!list_empty(list)) {
-		w = list_first_entry(list, struct binder_work, entry);
-		list_del_init(&w->entry);
-		switch (w->type) {
-		case BINDER_WORK_TRANSACTION: {
-			struct binder_transaction *t;
-
-			t = container_of(w, struct binder_transaction, work);
-			if (t->buffer->target_node && !(t->flags & TF_ONE_WAY))
-				binder_send_failed_reply(t, BR_DEAD_REPLY);
-		} break;
-		case BINDER_WORK_TRANSACTION_COMPLETE: {
-			kfree(w);
-			binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
-		} break;
-		default:
-			break;
-		}
-	}
-
-}
-
-static struct binder_thread *binder_get_thread(struct binder_proc *proc)
-{
-	struct binder_thread *thread = NULL;
-	struct rb_node *parent = NULL;
-	struct rb_node **p = &proc->threads.rb_node;
-
-	while (*p) {
-		parent = *p;
-		thread = rb_entry(parent, struct binder_thread, rb_node);
-
-		if (current->pid < thread->pid)
-			p = &(*p)->rb_left;
-		else if (current->pid > thread->pid)
-			p = &(*p)->rb_right;
-		else
-			break;
-	}
-	if (*p == NULL) {
-		thread = kzalloc(sizeof(*thread), GFP_KERNEL);
-		if (thread == NULL)
-			return NULL;
-		binder_stats_created(BINDER_STAT_THREAD);
-		thread->proc = proc;
-		thread->pid = current->pid;
-		init_waitqueue_head(&thread->wait);
-		INIT_LIST_HEAD(&thread->todo);
-		rb_link_node(&thread->rb_node, parent, p);
-		rb_insert_color(&thread->rb_node, &proc->threads);
-		thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN;
-		thread->return_error = BR_OK;
-		thread->return_error2 = BR_OK;
-	}
-	return thread;
-}
-
-static int binder_free_thread(struct binder_proc *proc,
-			      struct binder_thread *thread)
-{
-	struct binder_transaction *t;
-	struct binder_transaction *send_reply = NULL;
-	int active_transactions = 0;
-
-	rb_erase(&thread->rb_node, &proc->threads);
-	t = thread->transaction_stack;
-	if (t && t->to_thread == thread)
-		send_reply = t;
-	while (t) {
-		active_transactions++;
-		binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
-			     "binder: release %d:%d transaction %d "
-			     "%s, still active\n", proc->pid, thread->pid,
-			     t->debug_id,
-			     (t->to_thread == thread) ? "in" : "out");
-
-		if (t->to_thread == thread) {
-			t->to_proc = NULL;
-			t->to_thread = NULL;
-			if (t->buffer) {
-				t->buffer->transaction = NULL;
-				t->buffer = NULL;
-			}
-			t = t->to_parent;
-		} else if (t->from == thread) {
-			t->from = NULL;
-			t = t->from_parent;
-		} else
-			BUG();
-	}
-	if (send_reply)
-		binder_send_failed_reply(send_reply, BR_DEAD_REPLY);
-	binder_release_work(&thread->todo);
-	kfree(thread);
-	binder_stats_deleted(BINDER_STAT_THREAD);
-	return active_transactions;
-}
-
-static unsigned int binder_poll(struct file *filp,
-				struct poll_table_struct *wait)
-{
-	struct binder_proc *proc = filp->private_data;
-	struct binder_thread *thread = NULL;
-	int wait_for_proc_work;
-
-	mutex_lock(&binder_lock);
-	thread = binder_get_thread(proc);
-
-	wait_for_proc_work = thread->transaction_stack == NULL &&
-		list_empty(&thread->todo) && thread->return_error == BR_OK;
-	mutex_unlock(&binder_lock);
-
-	if (wait_for_proc_work) {
-		if (binder_has_proc_work(proc, thread))
-			return POLLIN;
-		poll_wait(filp, &proc->wait, wait);
-		if (binder_has_proc_work(proc, thread))
-			return POLLIN;
-	} else {
-		if (binder_has_thread_work(thread))
-			return POLLIN;
-		poll_wait(filp, &thread->wait, wait);
-		if (binder_has_thread_work(thread))
-			return POLLIN;
-	}
-	return 0;
-}
-
-static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-	int ret;
-	struct binder_proc *proc = filp->private_data;
-	struct binder_thread *thread;
-	unsigned int size = _IOC_SIZE(cmd);
-	void __user *ubuf = (void __user *)arg;
-
-	/*printk(KERN_INFO "binder_ioctl: %d:%d %x %lx\n", proc->pid, current->pid, cmd, arg);*/
-
-	ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
-	if (ret)
-		return ret;
-
-	mutex_lock(&binder_lock);
-	thread = binder_get_thread(proc);
-	if (thread == NULL) {
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	switch (cmd) {
-	case BINDER_WRITE_READ: {
-		struct binder_write_read bwr;
-		if (size != sizeof(struct binder_write_read)) {
-			ret = -EINVAL;
-			goto err;
-		}
-		if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {
-			ret = -EFAULT;
-			goto err;
-		}
-		binder_debug(BINDER_DEBUG_READ_WRITE,
-			     "binder: %d:%d write %ld at %08lx, read %ld at %08lx\n",
-			     proc->pid, thread->pid, bwr.write_size, bwr.write_buffer,
-			     bwr.read_size, bwr.read_buffer);
-
-		if (bwr.write_size > 0) {
-			ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed);
-			if (ret < 0) {
-				bwr.read_consumed = 0;
-				if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
-					ret = -EFAULT;
-				goto err;
-			}
-		}
-		if (bwr.read_size > 0) {
-			ret = binder_thread_read(proc, thread, (void __user *)bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK);
-			if (!list_empty(&proc->todo))
-				wake_up_interruptible(&proc->wait);
-			if (ret < 0) {
-				if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
-					ret = -EFAULT;
-				goto err;
-			}
-		}
-		binder_debug(BINDER_DEBUG_READ_WRITE,
-			     "binder: %d:%d wrote %ld of %ld, read return %ld of %ld\n",
-			     proc->pid, thread->pid, bwr.write_consumed, bwr.write_size,
-			     bwr.read_consumed, bwr.read_size);
-		if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
-			ret = -EFAULT;
-			goto err;
-		}
-		break;
-	}
-	case BINDER_SET_MAX_THREADS:
-		if (copy_from_user(&proc->max_threads, ubuf, sizeof(proc->max_threads))) {
-			ret = -EINVAL;
-			goto err;
-		}
-		break;
-	case BINDER_SET_CONTEXT_MGR:
-		if (binder_context_mgr_node != NULL) {
-			printk(KERN_ERR "binder: BINDER_SET_CONTEXT_MGR already set\n");
-			ret = -EBUSY;
-			goto err;
-		}
-		if (binder_context_mgr_uid != -1) {
-			if (binder_context_mgr_uid != current->cred->euid) {
-				printk(KERN_ERR "binder: BINDER_SET_"
-				       "CONTEXT_MGR bad uid %d != %d\n",
-				       current->cred->euid,
-				       binder_context_mgr_uid);
-				ret = -EPERM;
-				goto err;
-			}
-		} else
-			binder_context_mgr_uid = current->cred->euid;
-		binder_context_mgr_node = binder_new_node(proc, NULL, NULL);
-		if (binder_context_mgr_node == NULL) {
-			ret = -ENOMEM;
-			goto err;
-		}
-		binder_context_mgr_node->local_weak_refs++;
-		binder_context_mgr_node->local_strong_refs++;
-		binder_context_mgr_node->has_strong_ref = 1;
-		binder_context_mgr_node->has_weak_ref = 1;
-		break;
-	case BINDER_THREAD_EXIT:
-		binder_debug(BINDER_DEBUG_THREADS, "binder: %d:%d exit\n",
-			     proc->pid, thread->pid);
-		binder_free_thread(proc, thread);
-		thread = NULL;
-		break;
-	case BINDER_VERSION:
-		if (size != sizeof(struct binder_version)) {
-			ret = -EINVAL;
-			goto err;
-		}
-		if (put_user(BINDER_CURRENT_PROTOCOL_VERSION, &((struct binder_version *)ubuf)->protocol_version)) {
-			ret = -EINVAL;
-			goto err;
-		}
-		break;
-	default:
-		ret = -EINVAL;
-		goto err;
-	}
-	ret = 0;
-err:
-	if (thread)
-		thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN;
-	mutex_unlock(&binder_lock);
-	wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
-	if (ret && ret != -ERESTARTSYS)
-		printk(KERN_INFO "binder: %d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
-	return ret;
-}
-
-static void binder_vma_open(struct vm_area_struct *vma)
-{
-	struct binder_proc *proc = vma->vm_private_data;
-	binder_debug(BINDER_DEBUG_OPEN_CLOSE,
-		     "binder: %d open vm area %lx-%lx (%ld K) vma %lx pagep %lx\n",
-		     proc->pid, vma->vm_start, vma->vm_end,
-		     (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
-		     (unsigned long)pgprot_val(vma->vm_page_prot));
-	dump_stack();
-}
-
-static void binder_vma_close(struct vm_area_struct *vma)
-{
-	struct binder_proc *proc = vma->vm_private_data;
-	binder_debug(BINDER_DEBUG_OPEN_CLOSE,
-		     "binder: %d close vm area %lx-%lx (%ld K) vma %lx pagep %lx\n",
-		     proc->pid, vma->vm_start, vma->vm_end,
-		     (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
-		     (unsigned long)pgprot_val(vma->vm_page_prot));
-	proc->vma = NULL;
-	binder_defer_work(proc, BINDER_DEFERRED_PUT_FILES);
-}
-
-static struct vm_operations_struct binder_vm_ops = {
-	.open = binder_vma_open,
-	.close = binder_vma_close,
-};
-
-static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-	int ret;
-	struct vm_struct *area;
-	struct binder_proc *proc = filp->private_data;
-	const char *failure_string;
-	struct binder_buffer *buffer;
-
-	if ((vma->vm_end - vma->vm_start) > SZ_4M)
-		vma->vm_end = vma->vm_start + SZ_4M;
-
-	binder_debug(BINDER_DEBUG_OPEN_CLOSE,
-		     "binder_mmap: %d %lx-%lx (%ld K) vma %lx pagep %lx\n",
-		     proc->pid, vma->vm_start, vma->vm_end,
-		     (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
-		     (unsigned long)pgprot_val(vma->vm_page_prot));
-
-	if (vma->vm_flags & FORBIDDEN_MMAP_FLAGS) {
-		ret = -EPERM;
-		failure_string = "bad vm_flags";
-		goto err_bad_arg;
-	}
-	vma->vm_flags = (vma->vm_flags | VM_DONTCOPY) & ~VM_MAYWRITE;
-
-	if (proc->buffer) {
-		ret = -EBUSY;
-		failure_string = "already mapped";
-		goto err_already_mapped;
-	}
-
-	area = get_vm_area(vma->vm_end - vma->vm_start, VM_IOREMAP);
-	if (area == NULL) {
-		ret = -ENOMEM;
-		failure_string = "get_vm_area";
-		goto err_get_vm_area_failed;
-	}
-	proc->buffer = area->addr;
-	proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer;
-
-#ifdef CONFIG_CPU_CACHE_VIPT
-	if (cache_is_vipt_aliasing()) {
-		while (CACHE_COLOUR((vma->vm_start ^ (uint32_t)proc->buffer))) {
-			printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p bad alignment\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer);
-			vma->vm_start += PAGE_SIZE;
-		}
-	}
-#endif
-	proc->pages = kzalloc(sizeof(proc->pages[0]) * ((vma->vm_end - vma->vm_start) / PAGE_SIZE), GFP_KERNEL);
-	if (proc->pages == NULL) {
-		ret = -ENOMEM;
-		failure_string = "alloc page array";
-		goto err_alloc_pages_failed;
-	}
-	proc->buffer_size = vma->vm_end - vma->vm_start;
-
-	vma->vm_ops = &binder_vm_ops;
-	vma->vm_private_data = proc;
-
-	if (binder_update_page_range(proc, 1, proc->buffer, proc->buffer + PAGE_SIZE, vma)) {
-		ret = -ENOMEM;
-		failure_string = "alloc small buf";
-		goto err_alloc_small_buf_failed;
-	}
-	buffer = proc->buffer;
-	INIT_LIST_HEAD(&proc->buffers);
-	list_add(&buffer->entry, &proc->buffers);
-	buffer->free = 1;
-	binder_insert_free_buffer(proc, buffer);
-	proc->free_async_space = proc->buffer_size / 2;
-	barrier();
-	proc->files = get_files_struct(current);
-	proc->vma = vma;
-
-	/*printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p\n",
-		 proc->pid, vma->vm_start, vma->vm_end, proc->buffer);*/
-	return 0;
-
-err_alloc_small_buf_failed:
-	kfree(proc->pages);
-	proc->pages = NULL;
-err_alloc_pages_failed:
-	vfree(proc->buffer);
-	proc->buffer = NULL;
-err_get_vm_area_failed:
-err_already_mapped:
-err_bad_arg:
-	printk(KERN_ERR "binder_mmap: %d %lx-%lx %s failed %d\n",
-	       proc->pid, vma->vm_start, vma->vm_end, failure_string, ret);
-	return ret;
-}
-
-static int binder_open(struct inode *nodp, struct file *filp)
-{
-	struct binder_proc *proc;
-
-	binder_debug(BINDER_DEBUG_OPEN_CLOSE, "binder_open: %d:%d\n",
-		     current->group_leader->pid, current->pid);
-
-	proc = kzalloc(sizeof(*proc), GFP_KERNEL);
-	if (proc == NULL)
-		return -ENOMEM;
-	get_task_struct(current);
-	proc->tsk = current;
-	INIT_LIST_HEAD(&proc->todo);
-	init_waitqueue_head(&proc->wait);
-	proc->default_priority = task_nice(current);
-	mutex_lock(&binder_lock);
-	binder_stats_created(BINDER_STAT_PROC);
-	hlist_add_head(&proc->proc_node, &binder_procs);
-	proc->pid = current->group_leader->pid;
-	INIT_LIST_HEAD(&proc->delivered_death);
-	filp->private_data = proc;
-	mutex_unlock(&binder_lock);
-
-	if (binder_proc_dir_entry_proc) {
-		char strbuf[11];
-		snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
-		remove_proc_entry(strbuf, binder_proc_dir_entry_proc);
-		create_proc_read_entry(strbuf, S_IRUGO,
-				       binder_proc_dir_entry_proc,
-				       binder_read_proc_proc, proc);
-	}
-
-	return 0;
-}
-
-static int binder_flush(struct file *filp, fl_owner_t id)
-{
-	struct binder_proc *proc = filp->private_data;
-
-	binder_defer_work(proc, BINDER_DEFERRED_FLUSH);
-
-	return 0;
-}
-
-static void binder_deferred_flush(struct binder_proc *proc)
-{
-	struct rb_node *n;
-	int wake_count = 0;
-	for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) {
-		struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node);
-		thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN;
-		if (thread->looper & BINDER_LOOPER_STATE_WAITING) {
-			wake_up_interruptible(&thread->wait);
-			wake_count++;
-		}
-	}
-	wake_up_interruptible_all(&proc->wait);
-
-	binder_debug(BINDER_DEBUG_OPEN_CLOSE,
-		     "binder_flush: %d woke %d threads\n", proc->pid,
-		     wake_count);
-}
-
-static int binder_release(struct inode *nodp, struct file *filp)
-{
-	struct binder_proc *proc = filp->private_data;
-	if (binder_proc_dir_entry_proc) {
-		char strbuf[11];
-		snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
-		remove_proc_entry(strbuf, binder_proc_dir_entry_proc);
-	}
-
-	binder_defer_work(proc, BINDER_DEFERRED_RELEASE);
-
-	return 0;
-}
-
-static void binder_deferred_release(struct binder_proc *proc)
-{
-	struct hlist_node *pos;
-	struct binder_transaction *t;
-	struct rb_node *n;
-	int threads, nodes, incoming_refs, outgoing_refs, buffers, active_transactions, page_count;
-
-	BUG_ON(proc->vma);
-	BUG_ON(proc->files);
-
-	hlist_del(&proc->proc_node);
-	if (binder_context_mgr_node && binder_context_mgr_node->proc == proc) {
-		binder_debug(BINDER_DEBUG_DEAD_BINDER,
-			     "binder_release: %d context_mgr_node gone\n",
-			     proc->pid);
-		binder_context_mgr_node = NULL;
-	}
-
-	threads = 0;
-	active_transactions = 0;
-	while ((n = rb_first(&proc->threads))) {
-		struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node);
-		threads++;
-		active_transactions += binder_free_thread(proc, thread);
-	}
-	nodes = 0;
-	incoming_refs = 0;
-	while ((n = rb_first(&proc->nodes))) {
-		struct binder_node *node = rb_entry(n, struct binder_node, rb_node);
-
-		nodes++;
-		rb_erase(&node->rb_node, &proc->nodes);
-		list_del_init(&node->work.entry);
-		if (hlist_empty(&node->refs)) {
-			kfree(node);
-			binder_stats_deleted(BINDER_STAT_NODE);
-		} else {
-			struct binder_ref *ref;
-			int death = 0;
-
-			node->proc = NULL;
-			node->local_strong_refs = 0;
-			node->local_weak_refs = 0;
-			hlist_add_head(&node->dead_node, &binder_dead_nodes);
-
-			hlist_for_each_entry(ref, pos, &node->refs, node_entry) {
-				incoming_refs++;
-				if (ref->death) {
-					death++;
-					if (list_empty(&ref->death->work.entry)) {
-						ref->death->work.type = BINDER_WORK_DEAD_BINDER;
-						list_add_tail(&ref->death->work.entry, &ref->proc->todo);
-						wake_up_interruptible(&ref->proc->wait);
-					} else
-						BUG();
-				}
-			}
-			binder_debug(BINDER_DEBUG_DEAD_BINDER,
-				     "binder: node %d now dead, "
-				     "refs %d, death %d\n", node->debug_id,
-				     incoming_refs, death);
-		}
-	}
-	outgoing_refs = 0;
-	while ((n = rb_first(&proc->refs_by_desc))) {
-		struct binder_ref *ref = rb_entry(n, struct binder_ref,
-						  rb_node_desc);
-		outgoing_refs++;
-		binder_delete_ref(ref);
-	}
-	binder_release_work(&proc->todo);
-	buffers = 0;
-
-	while ((n = rb_first(&proc->allocated_buffers))) {
-		struct binder_buffer *buffer = rb_entry(n, struct binder_buffer,
-							rb_node);
-		t = buffer->transaction;
-		if (t) {
-			t->buffer = NULL;
-			buffer->transaction = NULL;
-			printk(KERN_ERR "binder: release proc %d, "
-			       "transaction %d, not freed\n",
-			       proc->pid, t->debug_id);
-			/*BUG();*/
-		}
-		binder_free_buf(proc, buffer);
-		buffers++;
-	}
-
-	binder_stats_deleted(BINDER_STAT_PROC);
-
-	page_count = 0;
-	if (proc->pages) {
-		int i;
-		for (i = 0; i < proc->buffer_size / PAGE_SIZE; i++) {
-			if (proc->pages[i]) {
-				binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
-					     "binder_release: %d: "
-					     "page %d at %p not freed\n",
-					     proc->pid, i,
-					     proc->buffer + i * PAGE_SIZE);
-				__free_page(proc->pages[i]);
-				page_count++;
-			}
-		}
-		kfree(proc->pages);
-		vfree(proc->buffer);
-	}
-
-	put_task_struct(proc->tsk);
-
-	binder_debug(BINDER_DEBUG_OPEN_CLOSE,
-		     "binder_release: %d threads %d, nodes %d (ref %d), "
-		     "refs %d, active transactions %d, buffers %d, "
-		     "pages %d\n",
-		     proc->pid, threads, nodes, incoming_refs, outgoing_refs,
-		     active_transactions, buffers, page_count);
-
-	kfree(proc);
-}
-
-static void binder_deferred_func(struct work_struct *work)
-{
-	struct binder_proc *proc;
-	struct files_struct *files;
-
-	int defer;
-	do {
-		mutex_lock(&binder_lock);
-		mutex_lock(&binder_deferred_lock);
-		if (!hlist_empty(&binder_deferred_list)) {
-			proc = hlist_entry(binder_deferred_list.first,
-					struct binder_proc, deferred_work_node);
-			hlist_del_init(&proc->deferred_work_node);
-			defer = proc->deferred_work;
-			proc->deferred_work = 0;
-		} else {
-			proc = NULL;
-			defer = 0;
-		}
-		mutex_unlock(&binder_deferred_lock);
-
-		files = NULL;
-		if (defer & BINDER_DEFERRED_PUT_FILES) {
-			files = proc->files;
-			if (files)
-				proc->files = NULL;
-		}
-
-		if (defer & BINDER_DEFERRED_FLUSH)
-			binder_deferred_flush(proc);
-
-		if (defer & BINDER_DEFERRED_RELEASE)
-			binder_deferred_release(proc); /* frees proc */
-
-		mutex_unlock(&binder_lock);
-		if (files)
-			put_files_struct(files);
-	} while (proc);
-}
-static DECLARE_WORK(binder_deferred_work, binder_deferred_func);
-
-static void
-binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer)
-{
-	mutex_lock(&binder_deferred_lock);
-	proc->deferred_work |= defer;
-	if (hlist_unhashed(&proc->deferred_work_node)) {
-		hlist_add_head(&proc->deferred_work_node,
-				&binder_deferred_list);
-		schedule_work(&binder_deferred_work);
-	}
-	mutex_unlock(&binder_deferred_lock);
-}
-
-static char *print_binder_transaction(char *buf, char *end, const char *prefix,
-				      struct binder_transaction *t)
-{
-	buf += snprintf(buf, end - buf,
-			"%s %d: %p from %d:%d to %d:%d code %x "
-			"flags %x pri %ld r%d",
-			prefix, t->debug_id, t,
-			t->from ? t->from->proc->pid : 0,
-			t->from ? t->from->pid : 0,
-			t->to_proc ? t->to_proc->pid : 0,
-			t->to_thread ? t->to_thread->pid : 0,
-			t->code, t->flags, t->priority, t->need_reply);
-	if (buf >= end)
-		return buf;
-	if (t->buffer == NULL) {
-		buf += snprintf(buf, end - buf, " buffer free\n");
-		return buf;
-	}
-	if (t->buffer->target_node) {
-		buf += snprintf(buf, end - buf, " node %d",
-				t->buffer->target_node->debug_id);
-		if (buf >= end)
-			return buf;
-	}
-	buf += snprintf(buf, end - buf, " size %zd:%zd data %p\n",
-			t->buffer->data_size, t->buffer->offsets_size,
-			t->buffer->data);
-	return buf;
-}
-
-static char *print_binder_buffer(char *buf, char *end, const char *prefix,
-				 struct binder_buffer *buffer)
-{
-	buf += snprintf(buf, end - buf, "%s %d: %p size %zd:%zd %s\n",
-			prefix, buffer->debug_id, buffer->data,
-			buffer->data_size, buffer->offsets_size,
-			buffer->transaction ? "active" : "delivered");
-	return buf;
-}
-
-static char *print_binder_work(char *buf, char *end, const char *prefix,
-			       const char *transaction_prefix,
-			       struct binder_work *w)
-{
-	struct binder_node *node;
-	struct binder_transaction *t;
-
-	switch (w->type) {
-	case BINDER_WORK_TRANSACTION:
-		t = container_of(w, struct binder_transaction, work);
-		buf = print_binder_transaction(buf, end, transaction_prefix, t);
-		break;
-	case BINDER_WORK_TRANSACTION_COMPLETE:
-		buf += snprintf(buf, end - buf,
-				"%stransaction complete\n", prefix);
-		break;
-	case BINDER_WORK_NODE:
-		node = container_of(w, struct binder_node, work);
-		buf += snprintf(buf, end - buf, "%snode work %d: u%p c%p\n",
-				prefix, node->debug_id, node->ptr,
-				node->cookie);
-		break;
-	case BINDER_WORK_DEAD_BINDER:
-		buf += snprintf(buf, end - buf, "%shas dead binder\n", prefix);
-		break;
-	case BINDER_WORK_DEAD_BINDER_AND_CLEAR:
-		buf += snprintf(buf, end - buf,
-				"%shas cleared dead binder\n", prefix);
-		break;
-	case BINDER_WORK_CLEAR_DEATH_NOTIFICATION:
-		buf += snprintf(buf, end - buf,
-				"%shas cleared death notification\n", prefix);
-		break;
-	default:
-		buf += snprintf(buf, end - buf, "%sunknown work: type %d\n",
-				prefix, w->type);
-		break;
-	}
-	return buf;
-}
-
-static char *print_binder_thread(char *buf, char *end,
-				 struct binder_thread *thread,
-				 int print_always)
-{
-	struct binder_transaction *t;
-	struct binder_work *w;
-	char *start_buf = buf;
-	char *header_buf;
-
-	buf += snprintf(buf, end - buf, "  thread %d: l %02x\n",
-			thread->pid, thread->looper);
-	header_buf = buf;
-	t = thread->transaction_stack;
-	while (t) {
-		if (buf >= end)
-			break;
-		if (t->from == thread) {
-			buf = print_binder_transaction(buf, end,
-						"    outgoing transaction", t);
-			t = t->from_parent;
-		} else if (t->to_thread == thread) {
-			buf = print_binder_transaction(buf, end,
-						"    incoming transaction", t);
-			t = t->to_parent;
-		} else {
-			buf = print_binder_transaction(buf, end,
-						"    bad transaction", t);
-			t = NULL;
-		}
-	}
-	list_for_each_entry(w, &thread->todo, entry) {
-		if (buf >= end)
-			break;
-		buf = print_binder_work(buf, end, "    ",
-					"    pending transaction", w);
-	}
-	if (!print_always && buf == header_buf)
-		buf = start_buf;
-	return buf;
-}
-
-static char *print_binder_node(char *buf, char *end, struct binder_node *node)
-{
-	struct binder_ref *ref;
-	struct hlist_node *pos;
-	struct binder_work *w;
-	int count;
-
-	count = 0;
-	hlist_for_each_entry(ref, pos, &node->refs, node_entry)
-		count++;
-
-	buf += snprintf(buf, end - buf,
-			"  node %d: u%p c%p hs %d hw %d ls %d lw %d "
-			"is %d iw %d",
-			node->debug_id, node->ptr, node->cookie,
-			node->has_strong_ref, node->has_weak_ref,
-			node->local_strong_refs, node->local_weak_refs,
-			node->internal_strong_refs, count);
-	if (buf >= end)
-		return buf;
-	if (count) {
-		buf += snprintf(buf, end - buf, " proc");
-		if (buf >= end)
-			return buf;
-		hlist_for_each_entry(ref, pos, &node->refs, node_entry) {
-			buf += snprintf(buf, end - buf, " %d", ref->proc->pid);
-			if (buf >= end)
-				return buf;
-		}
-	}
-	buf += snprintf(buf, end - buf, "\n");
-	list_for_each_entry(w, &node->async_todo, entry) {
-		if (buf >= end)
-			break;
-		buf = print_binder_work(buf, end, "    ",
-					"    pending async transaction", w);
-	}
-	return buf;
-}
-
-static char *print_binder_ref(char *buf, char *end, struct binder_ref *ref)
-{
-	buf += snprintf(buf, end - buf,
-			"  ref %d: desc %d %snode %d s %d w %d d %p\n",
-			ref->debug_id, ref->desc,
-			ref->node->proc ? "" : "dead ", ref->node->debug_id,
-			ref->strong, ref->weak, ref->death);
-	return buf;
-}
-
-static char *print_binder_proc(char *buf, char *end,
-			       struct binder_proc *proc, int print_all)
-{
-	struct binder_work *w;
-	struct rb_node *n;
-	char *start_buf = buf;
-	char *header_buf;
-
-	buf += snprintf(buf, end - buf, "proc %d\n", proc->pid);
-	header_buf = buf;
-
-	for (n = rb_first(&proc->threads);
-	     n != NULL && buf < end;
-	     n = rb_next(n))
-		buf = print_binder_thread(buf, end,
-					  rb_entry(n, struct binder_thread,
-						   rb_node), print_all);
-	for (n = rb_first(&proc->nodes);
-	     n != NULL && buf < end;
-	     n = rb_next(n)) {
-		struct binder_node *node = rb_entry(n, struct binder_node,
-						    rb_node);
-		if (print_all || node->has_async_transaction)
-			buf = print_binder_node(buf, end, node);
-	}
-	if (print_all) {
-		for (n = rb_first(&proc->refs_by_desc);
-		     n != NULL && buf < end;
-		     n = rb_next(n))
-			buf = print_binder_ref(buf, end,
-					       rb_entry(n, struct binder_ref,
-							rb_node_desc));
-	}
-	for (n = rb_first(&proc->allocated_buffers);
-	     n != NULL && buf < end;
-	     n = rb_next(n))
-		buf = print_binder_buffer(buf, end, "  buffer",
-					  rb_entry(n, struct binder_buffer,
-						   rb_node));
-	list_for_each_entry(w, &proc->todo, entry) {
-		if (buf >= end)
-			break;
-		buf = print_binder_work(buf, end, "  ",
-					"  pending transaction", w);
-	}
-	list_for_each_entry(w, &proc->delivered_death, entry) {
-		if (buf >= end)
-			break;
-		buf += snprintf(buf, end - buf,
-				"  has delivered dead binder\n");
-		break;
-	}
-	if (!print_all && buf == header_buf)
-		buf = start_buf;
-	return buf;
-}
-
-static const char *binder_return_strings[] = {
-	"BR_ERROR",
-	"BR_OK",
-	"BR_TRANSACTION",
-	"BR_REPLY",
-	"BR_ACQUIRE_RESULT",
-	"BR_DEAD_REPLY",
-	"BR_TRANSACTION_COMPLETE",
-	"BR_INCREFS",
-	"BR_ACQUIRE",
-	"BR_RELEASE",
-	"BR_DECREFS",
-	"BR_ATTEMPT_ACQUIRE",
-	"BR_NOOP",
-	"BR_SPAWN_LOOPER",
-	"BR_FINISHED",
-	"BR_DEAD_BINDER",
-	"BR_CLEAR_DEATH_NOTIFICATION_DONE",
-	"BR_FAILED_REPLY"
-};
-
-static const char *binder_command_strings[] = {
-	"BC_TRANSACTION",
-	"BC_REPLY",
-	"BC_ACQUIRE_RESULT",
-	"BC_FREE_BUFFER",
-	"BC_INCREFS",
-	"BC_ACQUIRE",
-	"BC_RELEASE",
-	"BC_DECREFS",
-	"BC_INCREFS_DONE",
-	"BC_ACQUIRE_DONE",
-	"BC_ATTEMPT_ACQUIRE",
-	"BC_REGISTER_LOOPER",
-	"BC_ENTER_LOOPER",
-	"BC_EXIT_LOOPER",
-	"BC_REQUEST_DEATH_NOTIFICATION",
-	"BC_CLEAR_DEATH_NOTIFICATION",
-	"BC_DEAD_BINDER_DONE"
-};
-
-static const char *binder_objstat_strings[] = {
-	"proc",
-	"thread",
-	"node",
-	"ref",
-	"death",
-	"transaction",
-	"transaction_complete"
-};
-
-static char *print_binder_stats(char *buf, char *end, const char *prefix,
-				struct binder_stats *stats)
-{
-	int i;
-
-	BUILD_BUG_ON(ARRAY_SIZE(stats->bc) !=
-			ARRAY_SIZE(binder_command_strings));
-	for (i = 0; i < ARRAY_SIZE(stats->bc); i++) {
-		if (stats->bc[i])
-			buf += snprintf(buf, end - buf, "%s%s: %d\n", prefix,
-					binder_command_strings[i],
-					stats->bc[i]);
-		if (buf >= end)
-			return buf;
-	}
-
-	BUILD_BUG_ON(ARRAY_SIZE(stats->br) !=
-			ARRAY_SIZE(binder_return_strings));
-	for (i = 0; i < ARRAY_SIZE(stats->br); i++) {
-		if (stats->br[i])
-			buf += snprintf(buf, end - buf, "%s%s: %d\n", prefix,
-					binder_return_strings[i], stats->br[i]);
-		if (buf >= end)
-			return buf;
-	}
-
-	BUILD_BUG_ON(ARRAY_SIZE(stats->obj_created) !=
-			ARRAY_SIZE(binder_objstat_strings));
-	BUILD_BUG_ON(ARRAY_SIZE(stats->obj_created) !=
-			ARRAY_SIZE(stats->obj_deleted));
-	for (i = 0; i < ARRAY_SIZE(stats->obj_created); i++) {
-		if (stats->obj_created[i] || stats->obj_deleted[i])
-			buf += snprintf(buf, end - buf,
-					"%s%s: active %d total %d\n", prefix,
-					binder_objstat_strings[i],
-					stats->obj_created[i] -
-						stats->obj_deleted[i],
-					stats->obj_created[i]);
-		if (buf >= end)
-			return buf;
-	}
-	return buf;
-}
-
-static char *print_binder_proc_stats(char *buf, char *end,
-				     struct binder_proc *proc)
-{
-	struct binder_work *w;
-	struct rb_node *n;
-	int count, strong, weak;
-
-	buf += snprintf(buf, end - buf, "proc %d\n", proc->pid);
-	if (buf >= end)
-		return buf;
-	count = 0;
-	for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n))
-		count++;
-	buf += snprintf(buf, end - buf, "  threads: %d\n", count);
-	if (buf >= end)
-		return buf;
-	buf += snprintf(buf, end - buf, "  requested threads: %d+%d/%d\n"
-			"  ready threads %d\n"
-			"  free async space %zd\n", proc->requested_threads,
-			proc->requested_threads_started, proc->max_threads,
-			proc->ready_threads, proc->free_async_space);
-	if (buf >= end)
-		return buf;
-	count = 0;
-	for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n))
-		count++;
-	buf += snprintf(buf, end - buf, "  nodes: %d\n", count);
-	if (buf >= end)
-		return buf;
-	count = 0;
-	strong = 0;
-	weak = 0;
-	for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) {
-		struct binder_ref *ref = rb_entry(n, struct binder_ref,
-						  rb_node_desc);
-		count++;
-		strong += ref->strong;
-		weak += ref->weak;
-	}
-	buf += snprintf(buf, end - buf, "  refs: %d s %d w %d\n",
-			count, strong, weak);
-	if (buf >= end)
-		return buf;
-
-	count = 0;
-	for (n = rb_first(&proc->allocated_buffers); n != NULL; n = rb_next(n))
-		count++;
-	buf += snprintf(buf, end - buf, "  buffers: %d\n", count);
-	if (buf >= end)
-		return buf;
-
-	count = 0;
-	list_for_each_entry(w, &proc->todo, entry) {
-		switch (w->type) {
-		case BINDER_WORK_TRANSACTION:
-			count++;
-			break;
-		default:
-			break;
-		}
-	}
-	buf += snprintf(buf, end - buf, "  pending transactions: %d\n", count);
-	if (buf >= end)
-		return buf;
-
-	buf = print_binder_stats(buf, end, "  ", &proc->stats);
-
-	return buf;
-}
-
-
-static int binder_read_proc_state(char *page, char **start, off_t off,
-				  int count, int *eof, void *data)
-{
-	struct binder_proc *proc;
-	struct hlist_node *pos;
-	struct binder_node *node;
-	int len = 0;
-	char *buf = page;
-	char *end = page + PAGE_SIZE;
-	int do_lock = !binder_debug_no_lock;
-
-	if (off)
-		return 0;
-
-	if (do_lock)
-		mutex_lock(&binder_lock);
-
-	buf += snprintf(buf, end - buf, "binder state:\n");
-
-	if (!hlist_empty(&binder_dead_nodes))
-		buf += snprintf(buf, end - buf, "dead nodes:\n");
-	hlist_for_each_entry(node, pos, &binder_dead_nodes, dead_node) {
-		if (buf >= end)
-			break;
-		buf = print_binder_node(buf, end, node);
-	}
-
-	hlist_for_each_entry(proc, pos, &binder_procs, proc_node) {
-		if (buf >= end)
-			break;
-		buf = print_binder_proc(buf, end, proc, 1);
-	}
-	if (do_lock)
-		mutex_unlock(&binder_lock);
-	if (buf > page + PAGE_SIZE)
-		buf = page + PAGE_SIZE;
-
-	*start = page + off;
-
-	len = buf - page;
-	if (len > off)
-		len -= off;
-	else
-		len = 0;
-
-	return len < count ? len  : count;
-}
-
-static int binder_read_proc_stats(char *page, char **start, off_t off,
-				  int count, int *eof, void *data)
-{
-	struct binder_proc *proc;
-	struct hlist_node *pos;
-	int len = 0;
-	char *p = page;
-	int do_lock = !binder_debug_no_lock;
-
-	if (off)
-		return 0;
-
-	if (do_lock)
-		mutex_lock(&binder_lock);
-
-	p += snprintf(p, PAGE_SIZE, "binder stats:\n");
-
-	p = print_binder_stats(p, page + PAGE_SIZE, "", &binder_stats);
-
-	hlist_for_each_entry(proc, pos, &binder_procs, proc_node) {
-		if (p >= page + PAGE_SIZE)
-			break;
-		p = print_binder_proc_stats(p, page + PAGE_SIZE, proc);
-	}
-	if (do_lock)
-		mutex_unlock(&binder_lock);
-	if (p > page + PAGE_SIZE)
-		p = page + PAGE_SIZE;
-
-	*start = page + off;
-
-	len = p - page;
-	if (len > off)
-		len -= off;
-	else
-		len = 0;
-
-	return len < count ? len  : count;
-}
-
-static int binder_read_proc_transactions(char *page, char **start, off_t off,
-					 int count, int *eof, void *data)
-{
-	struct binder_proc *proc;
-	struct hlist_node *pos;
-	int len = 0;
-	char *buf = page;
-	char *end = page + PAGE_SIZE;
-	int do_lock = !binder_debug_no_lock;
-
-	if (off)
-		return 0;
-
-	if (do_lock)
-		mutex_lock(&binder_lock);
-
-	buf += snprintf(buf, end - buf, "binder transactions:\n");
-	hlist_for_each_entry(proc, pos, &binder_procs, proc_node) {
-		if (buf >= end)
-			break;
-		buf = print_binder_proc(buf, end, proc, 0);
-	}
-	if (do_lock)
-		mutex_unlock(&binder_lock);
-	if (buf > page + PAGE_SIZE)
-		buf = page + PAGE_SIZE;
-
-	*start = page + off;
-
-	len = buf - page;
-	if (len > off)
-		len -= off;
-	else
-		len = 0;
-
-	return len < count ? len  : count;
-}
-
-static int binder_read_proc_proc(char *page, char **start, off_t off,
-				 int count, int *eof, void *data)
-{
-	struct binder_proc *proc = data;
-	int len = 0;
-	char *p = page;
-	int do_lock = !binder_debug_no_lock;
-
-	if (off)
-		return 0;
-
-	if (do_lock)
-		mutex_lock(&binder_lock);
-	p += snprintf(p, PAGE_SIZE, "binder proc state:\n");
-	p = print_binder_proc(p, page + PAGE_SIZE, proc, 1);
-	if (do_lock)
-		mutex_unlock(&binder_lock);
-
-	if (p > page + PAGE_SIZE)
-		p = page + PAGE_SIZE;
-	*start = page + off;
-
-	len = p - page;
-	if (len > off)
-		len -= off;
-	else
-		len = 0;
-
-	return len < count ? len  : count;
-}
-
-static char *print_binder_transaction_log_entry(char *buf, char *end,
-					struct binder_transaction_log_entry *e)
-{
-	buf += snprintf(buf, end - buf,
-			"%d: %s from %d:%d to %d:%d node %d handle %d "
-			"size %d:%d\n",
-			e->debug_id, (e->call_type == 2) ? "reply" :
-			((e->call_type == 1) ? "async" : "call "), e->from_proc,
-			e->from_thread, e->to_proc, e->to_thread, e->to_node,
-			e->target_handle, e->data_size, e->offsets_size);
-	return buf;
-}
-
-static int binder_read_proc_transaction_log(
-	char *page, char **start, off_t off, int count, int *eof, void *data)
-{
-	struct binder_transaction_log *log = data;
-	int len = 0;
-	int i;
-	char *buf = page;
-	char *end = page + PAGE_SIZE;
-
-	if (off)
-		return 0;
-
-	if (log->full) {
-		for (i = log->next; i < ARRAY_SIZE(log->entry); i++) {
-			if (buf >= end)
-				break;
-			buf = print_binder_transaction_log_entry(buf, end,
-								&log->entry[i]);
-		}
-	}
-	for (i = 0; i < log->next; i++) {
-		if (buf >= end)
-			break;
-		buf = print_binder_transaction_log_entry(buf, end,
-							 &log->entry[i]);
-	}
-
-	*start = page + off;
-
-	len = buf - page;
-	if (len > off)
-		len -= off;
-	else
-		len = 0;
-
-	return len < count ? len  : count;
-}
-
-static const struct file_operations binder_fops = {
-	.owner = THIS_MODULE,
-	.poll = binder_poll,
-	.unlocked_ioctl = binder_ioctl,
-	.mmap = binder_mmap,
-	.open = binder_open,
-	.flush = binder_flush,
-	.release = binder_release,
-};
-
-static struct miscdevice binder_miscdev = {
-	.minor = MISC_DYNAMIC_MINOR,
-	.name = "binder",
-	.fops = &binder_fops
-};
-
-static int __init binder_init(void)
-{
-	int ret;
-
-	binder_proc_dir_entry_root = proc_mkdir("binder", NULL);
-	if (binder_proc_dir_entry_root)
-		binder_proc_dir_entry_proc = proc_mkdir("proc",
-						binder_proc_dir_entry_root);
-	ret = misc_register(&binder_miscdev);
-	if (binder_proc_dir_entry_root) {
-		create_proc_read_entry("state",
-				       S_IRUGO,
-				       binder_proc_dir_entry_root,
-				       binder_read_proc_state,
-				       NULL);
-		create_proc_read_entry("stats",
-				       S_IRUGO,
-				       binder_proc_dir_entry_root,
-				       binder_read_proc_stats,
-				       NULL);
-		create_proc_read_entry("transactions",
-				       S_IRUGO,
-				       binder_proc_dir_entry_root,
-				       binder_read_proc_transactions,
-				       NULL);
-		create_proc_read_entry("transaction_log",
-				       S_IRUGO,
-				       binder_proc_dir_entry_root,
-				       binder_read_proc_transaction_log,
-				       &binder_transaction_log);
-		create_proc_read_entry("failed_transaction_log",
-				       S_IRUGO,
-				       binder_proc_dir_entry_root,
-				       binder_read_proc_transaction_log,
-				       &binder_transaction_log_failed);
-	}
-	return ret;
-}
-
-device_initcall(binder_init);
-
-MODULE_LICENSE("GPL v2");

+ 0 - 330
drivers/staging/android/binder.h

@@ -1,330 +0,0 @@
-/*
- * Copyright (C) 2008 Google, Inc.
- *
- * Based on, but no longer compatible with, the original
- * OpenBinder.org binder driver interface, which is:
- *
- * Copyright (c) 2005 Palmsource, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _LINUX_BINDER_H
-#define _LINUX_BINDER_H
-
-#include <linux/ioctl.h>
-
-#define B_PACK_CHARS(c1, c2, c3, c4) \
-	((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4))
-#define B_TYPE_LARGE 0x85
-
-enum {
-	BINDER_TYPE_BINDER	= B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE),
-	BINDER_TYPE_WEAK_BINDER	= B_PACK_CHARS('w', 'b', '*', B_TYPE_LARGE),
-	BINDER_TYPE_HANDLE	= B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE),
-	BINDER_TYPE_WEAK_HANDLE	= B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE),
-	BINDER_TYPE_FD		= B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE),
-};
-
-enum {
-	FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff,
-	FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100,
-};
-
-/*
- * This is the flattened representation of a Binder object for transfer
- * between processes.  The 'offsets' supplied as part of a binder transaction
- * contains offsets into the data where these structures occur.  The Binder
- * driver takes care of re-writing the structure type and data as it moves
- * between processes.
- */
-struct flat_binder_object {
-	/* 8 bytes for large_flat_header. */
-	unsigned long		type;
-	unsigned long		flags;
-
-	/* 8 bytes of data. */
-	union {
-		void		*binder;	/* local object */
-		signed long	handle;		/* remote object */
-	};
-
-	/* extra data associated with local object */
-	void			*cookie;
-};
-
-/*
- * On 64-bit platforms where user code may run in 32-bits the driver must
- * translate the buffer (and local binder) addresses apropriately.
- */
-
-struct binder_write_read {
-	signed long	write_size;	/* bytes to write */
-	signed long	write_consumed;	/* bytes consumed by driver */
-	unsigned long	write_buffer;
-	signed long	read_size;	/* bytes to read */
-	signed long	read_consumed;	/* bytes consumed by driver */
-	unsigned long	read_buffer;
-};
-
-/* Use with BINDER_VERSION, driver fills in fields. */
-struct binder_version {
-	/* driver protocol version -- increment with incompatible change */
-	signed long	protocol_version;
-};
-
-/* This is the current protocol version. */
-#define BINDER_CURRENT_PROTOCOL_VERSION 7
-
-#define BINDER_WRITE_READ   		_IOWR('b', 1, struct binder_write_read)
-#define	BINDER_SET_IDLE_TIMEOUT		_IOW('b', 3, int64_t)
-#define	BINDER_SET_MAX_THREADS		_IOW('b', 5, size_t)
-#define	BINDER_SET_IDLE_PRIORITY	_IOW('b', 6, int)
-#define	BINDER_SET_CONTEXT_MGR		_IOW('b', 7, int)
-#define	BINDER_THREAD_EXIT		_IOW('b', 8, int)
-#define BINDER_VERSION			_IOWR('b', 9, struct binder_version)
-
-/*
- * NOTE: Two special error codes you should check for when calling
- * in to the driver are:
- *
- * EINTR -- The operation has been interupted.  This should be
- * handled by retrying the ioctl() until a different error code
- * is returned.
- *
- * ECONNREFUSED -- The driver is no longer accepting operations
- * from your process.  That is, the process is being destroyed.
- * You should handle this by exiting from your process.  Note
- * that once this error code is returned, all further calls to
- * the driver from any thread will return this same code.
- */
-
-enum transaction_flags {
-	TF_ONE_WAY	= 0x01,	/* this is a one-way call: async, no return */
-	TF_ROOT_OBJECT	= 0x04,	/* contents are the component's root object */
-	TF_STATUS_CODE	= 0x08,	/* contents are a 32-bit status code */
-	TF_ACCEPT_FDS	= 0x10,	/* allow replies with file descriptors */
-};
-
-struct binder_transaction_data {
-	/* The first two are only used for bcTRANSACTION and brTRANSACTION,
-	 * identifying the target and contents of the transaction.
-	 */
-	union {
-		size_t	handle;	/* target descriptor of command transaction */
-		void	*ptr;	/* target descriptor of return transaction */
-	} target;
-	void		*cookie;	/* target object cookie */
-	unsigned int	code;		/* transaction command */
-
-	/* General information about the transaction. */
-	unsigned int	flags;
-	pid_t		sender_pid;
-	uid_t		sender_euid;
-	size_t		data_size;	/* number of bytes of data */
-	size_t		offsets_size;	/* number of bytes of offsets */
-
-	/* If this transaction is inline, the data immediately
-	 * follows here; otherwise, it ends with a pointer to
-	 * the data buffer.
-	 */
-	union {
-		struct {
-			/* transaction data */
-			const void	*buffer;
-			/* offsets from buffer to flat_binder_object structs */
-			const void	*offsets;
-		} ptr;
-		uint8_t	buf[8];
-	} data;
-};
-
-struct binder_ptr_cookie {
-	void *ptr;
-	void *cookie;
-};
-
-struct binder_pri_desc {
-	int priority;
-	int desc;
-};
-
-struct binder_pri_ptr_cookie {
-	int priority;
-	void *ptr;
-	void *cookie;
-};
-
-enum BinderDriverReturnProtocol {
-	BR_ERROR = _IOR('r', 0, int),
-	/*
-	 * int: error code
-	 */
-
-	BR_OK = _IO('r', 1),
-	/* No parameters! */
-
-	BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data),
-	BR_REPLY = _IOR('r', 3, struct binder_transaction_data),
-	/*
-	 * binder_transaction_data: the received command.
-	 */
-
-	BR_ACQUIRE_RESULT = _IOR('r', 4, int),
-	/*
-	 * not currently supported
-	 * int: 0 if the last bcATTEMPT_ACQUIRE was not successful.
-	 * Else the remote object has acquired a primary reference.
-	 */
-
-	BR_DEAD_REPLY = _IO('r', 5),
-	/*
-	 * The target of the last transaction (either a bcTRANSACTION or
-	 * a bcATTEMPT_ACQUIRE) is no longer with us.  No parameters.
-	 */
-
-	BR_TRANSACTION_COMPLETE = _IO('r', 6),
-	/*
-	 * No parameters... always refers to the last transaction requested
-	 * (including replies).  Note that this will be sent even for
-	 * asynchronous transactions.
-	 */
-
-	BR_INCREFS = _IOR('r', 7, struct binder_ptr_cookie),
-	BR_ACQUIRE = _IOR('r', 8, struct binder_ptr_cookie),
-	BR_RELEASE = _IOR('r', 9, struct binder_ptr_cookie),
-	BR_DECREFS = _IOR('r', 10, struct binder_ptr_cookie),
-	/*
-	 * void *:	ptr to binder
-	 * void *: cookie for binder
-	 */
-
-	BR_ATTEMPT_ACQUIRE = _IOR('r', 11, struct binder_pri_ptr_cookie),
-	/*
-	 * not currently supported
-	 * int:	priority
-	 * void *: ptr to binder
-	 * void *: cookie for binder
-	 */
-
-	BR_NOOP = _IO('r', 12),
-	/*
-	 * No parameters.  Do nothing and examine the next command.  It exists
-	 * primarily so that we can replace it with a BR_SPAWN_LOOPER command.
-	 */
-
-	BR_SPAWN_LOOPER = _IO('r', 13),
-	/*
-	 * No parameters.  The driver has determined that a process has no
-	 * threads waiting to service incomming transactions.  When a process
-	 * receives this command, it must spawn a new service thread and
-	 * register it via bcENTER_LOOPER.
-	 */
-
-	BR_FINISHED = _IO('r', 14),
-	/*
-	 * not currently supported
-	 * stop threadpool thread
-	 */
-
-	BR_DEAD_BINDER = _IOR('r', 15, void *),
-	/*
-	 * void *: cookie
-	 */
-	BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, void *),
-	/*
-	 * void *: cookie
-	 */
-
-	BR_FAILED_REPLY = _IO('r', 17),
-	/*
-	 * The the last transaction (either a bcTRANSACTION or
-	 * a bcATTEMPT_ACQUIRE) failed (e.g. out of memory).  No parameters.
-	 */
-};
-
-enum BinderDriverCommandProtocol {
-	BC_TRANSACTION = _IOW('c', 0, struct binder_transaction_data),
-	BC_REPLY = _IOW('c', 1, struct binder_transaction_data),
-	/*
-	 * binder_transaction_data: the sent command.
-	 */
-
-	BC_ACQUIRE_RESULT = _IOW('c', 2, int),
-	/*
-	 * not currently supported
-	 * int:  0 if the last BR_ATTEMPT_ACQUIRE was not successful.
-	 * Else you have acquired a primary reference on the object.
-	 */
-
-	BC_FREE_BUFFER = _IOW('c', 3, int),
-	/*
-	 * void *: ptr to transaction data received on a read
-	 */
-
-	BC_INCREFS = _IOW('c', 4, int),
-	BC_ACQUIRE = _IOW('c', 5, int),
-	BC_RELEASE = _IOW('c', 6, int),
-	BC_DECREFS = _IOW('c', 7, int),
-	/*
-	 * int:	descriptor
-	 */
-
-	BC_INCREFS_DONE = _IOW('c', 8, struct binder_ptr_cookie),
-	BC_ACQUIRE_DONE = _IOW('c', 9, struct binder_ptr_cookie),
-	/*
-	 * void *: ptr to binder
-	 * void *: cookie for binder
-	 */
-
-	BC_ATTEMPT_ACQUIRE = _IOW('c', 10, struct binder_pri_desc),
-	/*
-	 * not currently supported
-	 * int: priority
-	 * int: descriptor
-	 */
-
-	BC_REGISTER_LOOPER = _IO('c', 11),
-	/*
-	 * No parameters.
-	 * Register a spawned looper thread with the device.
-	 */
-
-	BC_ENTER_LOOPER = _IO('c', 12),
-	BC_EXIT_LOOPER = _IO('c', 13),
-	/*
-	 * No parameters.
-	 * These two commands are sent as an application-level thread
-	 * enters and exits the binder loop, respectively.  They are
-	 * used so the binder can have an accurate count of the number
-	 * of looping threads it has available.
-	 */
-
-	BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct binder_ptr_cookie),
-	/*
-	 * void *: ptr to binder
-	 * void *: cookie
-	 */
-
-	BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_ptr_cookie),
-	/*
-	 * void *: ptr to binder
-	 * void *: cookie
-	 */
-
-	BC_DEAD_BINDER_DONE = _IOW('c', 16, void *),
-	/*
-	 * void *: cookie
-	 */
-};
-
-#endif /* _LINUX_BINDER_H */
-

+ 0 - 607
drivers/staging/android/logger.c

@@ -1,607 +0,0 @@
-/*
- * drivers/misc/logger.c
- *
- * A Logging Subsystem
- *
- * Copyright (C) 2007-2008 Google, Inc.
- *
- * Robert Love <rlove@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
-#include <linux/uaccess.h>
-#include <linux/poll.h>
-#include <linux/time.h>
-#include "logger.h"
-
-#include <asm/ioctls.h>
-
-/*
- * struct logger_log - represents a specific log, such as 'main' or 'radio'
- *
- * This structure lives from module insertion until module removal, so it does
- * not need additional reference counting. The structure is protected by the
- * mutex 'mutex'.
- */
-struct logger_log {
-	unsigned char 		*buffer;/* the ring buffer itself */
-	struct miscdevice	misc;	/* misc device representing the log */
-	wait_queue_head_t	wq;	/* wait queue for readers */
-	struct list_head	readers; /* this log's readers */
-	struct mutex		mutex;	/* mutex protecting buffer */
-	size_t			w_off;	/* current write head offset */
-	size_t			head;	/* new readers start here */
-	size_t			size;	/* size of the log */
-};
-
-/*
- * struct logger_reader - a logging device open for reading
- *
- * This object lives from open to release, so we don't need additional
- * reference counting. The structure is protected by log->mutex.
- */
-struct logger_reader {
-	struct logger_log	*log;	/* associated log */
-	struct list_head	list;	/* entry in logger_log's list */
-	size_t			r_off;	/* current read head offset */
-};
-
-/* logger_offset - returns index 'n' into the log via (optimized) modulus */
-#define logger_offset(n)	((n) & (log->size - 1))
-
-/*
- * file_get_log - Given a file structure, return the associated log
- *
- * This isn't aesthetic. We have several goals:
- *
- * 	1) Need to quickly obtain the associated log during an I/O operation
- * 	2) Readers need to maintain state (logger_reader)
- * 	3) Writers need to be very fast (open() should be a near no-op)
- *
- * In the reader case, we can trivially go file->logger_reader->logger_log.
- * For a writer, we don't want to maintain a logger_reader, so we just go
- * file->logger_log. Thus what file->private_data points at depends on whether
- * or not the file was opened for reading. This function hides that dirtiness.
- */
-static inline struct logger_log *file_get_log(struct file *file)
-{
-	if (file->f_mode & FMODE_READ) {
-		struct logger_reader *reader = file->private_data;
-		return reader->log;
-	} else
-		return file->private_data;
-}
-
-/*
- * get_entry_len - Grabs the length of the payload of the next entry starting
- * from 'off'.
- *
- * Caller needs to hold log->mutex.
- */
-static __u32 get_entry_len(struct logger_log *log, size_t off)
-{
-	__u16 val;
-
-	switch (log->size - off) {
-	case 1:
-		memcpy(&val, log->buffer + off, 1);
-		memcpy(((char *) &val) + 1, log->buffer, 1);
-		break;
-	default:
-		memcpy(&val, log->buffer + off, 2);
-	}
-
-	return sizeof(struct logger_entry) + val;
-}
-
-/*
- * do_read_log_to_user - reads exactly 'count' bytes from 'log' into the
- * user-space buffer 'buf'. Returns 'count' on success.
- *
- * Caller must hold log->mutex.
- */
-static ssize_t do_read_log_to_user(struct logger_log *log,
-				   struct logger_reader *reader,
-				   char __user *buf,
-				   size_t count)
-{
-	size_t len;
-
-	/*
-	 * We read from the log in two disjoint operations. First, we read from
-	 * the current read head offset up to 'count' bytes or to the end of
-	 * the log, whichever comes first.
-	 */
-	len = min(count, log->size - reader->r_off);
-	if (copy_to_user(buf, log->buffer + reader->r_off, len))
-		return -EFAULT;
-
-	/*
-	 * Second, we read any remaining bytes, starting back at the head of
-	 * the log.
-	 */
-	if (count != len)
-		if (copy_to_user(buf + len, log->buffer, count - len))
-			return -EFAULT;
-
-	reader->r_off = logger_offset(reader->r_off + count);
-
-	return count;
-}
-
-/*
- * logger_read - our log's read() method
- *
- * Behavior:
- *
- * 	- O_NONBLOCK works
- * 	- If there are no log entries to read, blocks until log is written to
- * 	- Atomically reads exactly one log entry
- *
- * Optimal read size is LOGGER_ENTRY_MAX_LEN. Will set errno to EINVAL if read
- * buffer is insufficient to hold next entry.
- */
-static ssize_t logger_read(struct file *file, char __user *buf,
-			   size_t count, loff_t *pos)
-{
-	struct logger_reader *reader = file->private_data;
-	struct logger_log *log = reader->log;
-	ssize_t ret;
-	DEFINE_WAIT(wait);
-
-start:
-	while (1) {
-		prepare_to_wait(&log->wq, &wait, TASK_INTERRUPTIBLE);
-
-		mutex_lock(&log->mutex);
-		ret = (log->w_off == reader->r_off);
-		mutex_unlock(&log->mutex);
-		if (!ret)
-			break;
-
-		if (file->f_flags & O_NONBLOCK) {
-			ret = -EAGAIN;
-			break;
-		}
-
-		if (signal_pending(current)) {
-			ret = -EINTR;
-			break;
-		}
-
-		schedule();
-	}
-
-	finish_wait(&log->wq, &wait);
-	if (ret)
-		return ret;
-
-	mutex_lock(&log->mutex);
-
-	/* is there still something to read or did we race? */
-	if (unlikely(log->w_off == reader->r_off)) {
-		mutex_unlock(&log->mutex);
-		goto start;
-	}
-
-	/* get the size of the next entry */
-	ret = get_entry_len(log, reader->r_off);
-	if (count < ret) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	/* get exactly one entry from the log */
-	ret = do_read_log_to_user(log, reader, buf, ret);
-
-out:
-	mutex_unlock(&log->mutex);
-
-	return ret;
-}
-
-/*
- * get_next_entry - return the offset of the first valid entry at least 'len'
- * bytes after 'off'.
- *
- * Caller must hold log->mutex.
- */
-static size_t get_next_entry(struct logger_log *log, size_t off, size_t len)
-{
-	size_t count = 0;
-
-	do {
-		size_t nr = get_entry_len(log, off);
-		off = logger_offset(off + nr);
-		count += nr;
-	} while (count < len);
-
-	return off;
-}
-
-/*
- * clock_interval - is a < c < b in mod-space? Put another way, does the line
- * from a to b cross c?
- */
-static inline int clock_interval(size_t a, size_t b, size_t c)
-{
-	if (b < a) {
-		if (a < c || b >= c)
-			return 1;
-	} else {
-		if (a < c && b >= c)
-			return 1;
-	}
-
-	return 0;
-}
-
-/*
- * fix_up_readers - walk the list of all readers and "fix up" any who were
- * lapped by the writer; also do the same for the default "start head".
- * We do this by "pulling forward" the readers and start head to the first
- * entry after the new write head.
- *
- * The caller needs to hold log->mutex.
- */
-static void fix_up_readers(struct logger_log *log, size_t len)
-{
-	size_t old = log->w_off;
-	size_t new = logger_offset(old + len);
-	struct logger_reader *reader;
-
-	if (clock_interval(old, new, log->head))
-		log->head = get_next_entry(log, log->head, len);
-
-	list_for_each_entry(reader, &log->readers, list)
-		if (clock_interval(old, new, reader->r_off))
-			reader->r_off = get_next_entry(log, reader->r_off, len);
-}
-
-/*
- * do_write_log - writes 'len' bytes from 'buf' to 'log'
- *
- * The caller needs to hold log->mutex.
- */
-static void do_write_log(struct logger_log *log, const void *buf, size_t count)
-{
-	size_t len;
-
-	len = min(count, log->size - log->w_off);
-	memcpy(log->buffer + log->w_off, buf, len);
-
-	if (count != len)
-		memcpy(log->buffer, buf + len, count - len);
-
-	log->w_off = logger_offset(log->w_off + count);
-
-}
-
-/*
- * do_write_log_user - writes 'len' bytes from the user-space buffer 'buf' to
- * the log 'log'
- *
- * The caller needs to hold log->mutex.
- *
- * Returns 'count' on success, negative error code on failure.
- */
-static ssize_t do_write_log_from_user(struct logger_log *log,
-				      const void __user *buf, size_t count)
-{
-	size_t len;
-
-	len = min(count, log->size - log->w_off);
-	if (len && copy_from_user(log->buffer + log->w_off, buf, len))
-		return -EFAULT;
-
-	if (count != len)
-		if (copy_from_user(log->buffer, buf + len, count - len))
-			return -EFAULT;
-
-	log->w_off = logger_offset(log->w_off + count);
-
-	return count;
-}
-
-/*
- * logger_aio_write - our write method, implementing support for write(),
- * writev(), and aio_write(). Writes are our fast path, and we try to optimize
- * them above all else.
- */
-ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov,
-			 unsigned long nr_segs, loff_t ppos)
-{
-	struct logger_log *log = file_get_log(iocb->ki_filp);
-	size_t orig = log->w_off;
-	struct logger_entry header;
-	struct timespec now;
-	ssize_t ret = 0;
-
-	now = current_kernel_time();
-
-	header.pid = current->tgid;
-	header.tid = current->pid;
-	header.sec = now.tv_sec;
-	header.nsec = now.tv_nsec;
-	header.len = min_t(size_t, iocb->ki_left, LOGGER_ENTRY_MAX_PAYLOAD);
-
-	/* null writes succeed, return zero */
-	if (unlikely(!header.len))
-		return 0;
-
-	mutex_lock(&log->mutex);
-
-	/*
-	 * Fix up any readers, pulling them forward to the first readable
-	 * entry after (what will be) the new write offset. We do this now
-	 * because if we partially fail, we can end up with clobbered log
-	 * entries that encroach on readable buffer.
-	 */
-	fix_up_readers(log, sizeof(struct logger_entry) + header.len);
-
-	do_write_log(log, &header, sizeof(struct logger_entry));
-
-	while (nr_segs-- > 0) {
-		size_t len;
-		ssize_t nr;
-
-		/* figure out how much of this vector we can keep */
-		len = min_t(size_t, iov->iov_len, header.len - ret);
-
-		/* write out this segment's payload */
-		nr = do_write_log_from_user(log, iov->iov_base, len);
-		if (unlikely(nr < 0)) {
-			log->w_off = orig;
-			mutex_unlock(&log->mutex);
-			return nr;
-		}
-
-		iov++;
-		ret += nr;
-	}
-
-	mutex_unlock(&log->mutex);
-
-	/* wake up any blocked readers */
-	wake_up_interruptible(&log->wq);
-
-	return ret;
-}
-
-static struct logger_log *get_log_from_minor(int);
-
-/*
- * logger_open - the log's open() file operation
- *
- * Note how near a no-op this is in the write-only case. Keep it that way!
- */
-static int logger_open(struct inode *inode, struct file *file)
-{
-	struct logger_log *log;
-	int ret;
-
-	ret = nonseekable_open(inode, file);
-	if (ret)
-		return ret;
-
-	log = get_log_from_minor(MINOR(inode->i_rdev));
-	if (!log)
-		return -ENODEV;
-
-	if (file->f_mode & FMODE_READ) {
-		struct logger_reader *reader;
-
-		reader = kmalloc(sizeof(struct logger_reader), GFP_KERNEL);
-		if (!reader)
-			return -ENOMEM;
-
-		reader->log = log;
-		INIT_LIST_HEAD(&reader->list);
-
-		mutex_lock(&log->mutex);
-		reader->r_off = log->head;
-		list_add_tail(&reader->list, &log->readers);
-		mutex_unlock(&log->mutex);
-
-		file->private_data = reader;
-	} else
-		file->private_data = log;
-
-	return 0;
-}
-
-/*
- * logger_release - the log's release file operation
- *
- * Note this is a total no-op in the write-only case. Keep it that way!
- */
-static int logger_release(struct inode *ignored, struct file *file)
-{
-	if (file->f_mode & FMODE_READ) {
-		struct logger_reader *reader = file->private_data;
-		list_del(&reader->list);
-		kfree(reader);
-	}
-
-	return 0;
-}
-
-/*
- * logger_poll - the log's poll file operation, for poll/select/epoll
- *
- * Note we always return POLLOUT, because you can always write() to the log.
- * Note also that, strictly speaking, a return value of POLLIN does not
- * guarantee that the log is readable without blocking, as there is a small
- * chance that the writer can lap the reader in the interim between poll()
- * returning and the read() request.
- */
-static unsigned int logger_poll(struct file *file, poll_table *wait)
-{
-	struct logger_reader *reader;
-	struct logger_log *log;
-	unsigned int ret = POLLOUT | POLLWRNORM;
-
-	if (!(file->f_mode & FMODE_READ))
-		return ret;
-
-	reader = file->private_data;
-	log = reader->log;
-
-	poll_wait(file, &log->wq, wait);
-
-	mutex_lock(&log->mutex);
-	if (log->w_off != reader->r_off)
-		ret |= POLLIN | POLLRDNORM;
-	mutex_unlock(&log->mutex);
-
-	return ret;
-}
-
-static long logger_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct logger_log *log = file_get_log(file);
-	struct logger_reader *reader;
-	long ret = -ENOTTY;
-
-	mutex_lock(&log->mutex);
-
-	switch (cmd) {
-	case LOGGER_GET_LOG_BUF_SIZE:
-		ret = log->size;
-		break;
-	case LOGGER_GET_LOG_LEN:
-		if (!(file->f_mode & FMODE_READ)) {
-			ret = -EBADF;
-			break;
-		}
-		reader = file->private_data;
-		if (log->w_off >= reader->r_off)
-			ret = log->w_off - reader->r_off;
-		else
-			ret = (log->size - reader->r_off) + log->w_off;
-		break;
-	case LOGGER_GET_NEXT_ENTRY_LEN:
-		if (!(file->f_mode & FMODE_READ)) {
-			ret = -EBADF;
-			break;
-		}
-		reader = file->private_data;
-		if (log->w_off != reader->r_off)
-			ret = get_entry_len(log, reader->r_off);
-		else
-			ret = 0;
-		break;
-	case LOGGER_FLUSH_LOG:
-		if (!(file->f_mode & FMODE_WRITE)) {
-			ret = -EBADF;
-			break;
-		}
-		list_for_each_entry(reader, &log->readers, list)
-			reader->r_off = log->w_off;
-		log->head = log->w_off;
-		ret = 0;
-		break;
-	}
-
-	mutex_unlock(&log->mutex);
-
-	return ret;
-}
-
-static const struct file_operations logger_fops = {
-	.owner = THIS_MODULE,
-	.read = logger_read,
-	.aio_write = logger_aio_write,
-	.poll = logger_poll,
-	.unlocked_ioctl = logger_ioctl,
-	.compat_ioctl = logger_ioctl,
-	.open = logger_open,
-	.release = logger_release,
-};
-
-/*
- * Defines a log structure with name 'NAME' and a size of 'SIZE' bytes, which
- * must be a power of two, greater than LOGGER_ENTRY_MAX_LEN, and less than
- * LONG_MAX minus LOGGER_ENTRY_MAX_LEN.
- */
-#define DEFINE_LOGGER_DEVICE(VAR, NAME, SIZE) \
-static unsigned char _buf_ ## VAR[SIZE]; \
-static struct logger_log VAR = { \
-	.buffer = _buf_ ## VAR, \
-	.misc = { \
-		.minor = MISC_DYNAMIC_MINOR, \
-		.name = NAME, \
-		.fops = &logger_fops, \
-		.parent = NULL, \
-	}, \
-	.wq = __WAIT_QUEUE_HEAD_INITIALIZER(VAR .wq), \
-	.readers = LIST_HEAD_INIT(VAR .readers), \
-	.mutex = __MUTEX_INITIALIZER(VAR .mutex), \
-	.w_off = 0, \
-	.head = 0, \
-	.size = SIZE, \
-};
-
-DEFINE_LOGGER_DEVICE(log_main, LOGGER_LOG_MAIN, 64*1024)
-DEFINE_LOGGER_DEVICE(log_events, LOGGER_LOG_EVENTS, 256*1024)
-DEFINE_LOGGER_DEVICE(log_radio, LOGGER_LOG_RADIO, 64*1024)
-
-static struct logger_log *get_log_from_minor(int minor)
-{
-	if (log_main.misc.minor == minor)
-		return &log_main;
-	if (log_events.misc.minor == minor)
-		return &log_events;
-	if (log_radio.misc.minor == minor)
-		return &log_radio;
-	return NULL;
-}
-
-static int __init init_log(struct logger_log *log)
-{
-	int ret;
-
-	ret = misc_register(&log->misc);
-	if (unlikely(ret)) {
-		printk(KERN_ERR "logger: failed to register misc "
-		       "device for log '%s'!\n", log->misc.name);
-		return ret;
-	}
-
-	printk(KERN_INFO "logger: created %luK log '%s'\n",
-	       (unsigned long) log->size >> 10, log->misc.name);
-
-	return 0;
-}
-
-static int __init logger_init(void)
-{
-	int ret;
-
-	ret = init_log(&log_main);
-	if (unlikely(ret))
-		goto out;
-
-	ret = init_log(&log_events);
-	if (unlikely(ret))
-		goto out;
-
-	ret = init_log(&log_radio);
-	if (unlikely(ret))
-		goto out;
-
-out:
-	return ret;
-}
-device_initcall(logger_init);

+ 0 - 48
drivers/staging/android/logger.h

@@ -1,48 +0,0 @@
-/* include/linux/logger.h
- *
- * Copyright (C) 2007-2008 Google, Inc.
- * Author: Robert Love <rlove@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _LINUX_LOGGER_H
-#define _LINUX_LOGGER_H
-
-#include <linux/types.h>
-#include <linux/ioctl.h>
-
-struct logger_entry {
-	__u16		len;	/* length of the payload */
-	__u16		__pad;	/* no matter what, we get 2 bytes of padding */
-	__s32		pid;	/* generating process's pid */
-	__s32		tid;	/* generating process's tid */
-	__s32		sec;	/* seconds since Epoch */
-	__s32		nsec;	/* nanoseconds */
-	char		msg[0];	/* the entry's payload */
-};
-
-#define LOGGER_LOG_RADIO	"log_radio"	/* radio-related messages */
-#define LOGGER_LOG_EVENTS	"log_events"	/* system/hardware events */
-#define LOGGER_LOG_MAIN		"log_main"	/* everything else */
-
-#define LOGGER_ENTRY_MAX_LEN		(4*1024)
-#define LOGGER_ENTRY_MAX_PAYLOAD	\
-	(LOGGER_ENTRY_MAX_LEN - sizeof(struct logger_entry))
-
-#define __LOGGERIO	0xAE
-
-#define LOGGER_GET_LOG_BUF_SIZE		_IO(__LOGGERIO, 1) /* size of log */
-#define LOGGER_GET_LOG_LEN		_IO(__LOGGERIO, 2) /* used log len */
-#define LOGGER_GET_NEXT_ENTRY_LEN	_IO(__LOGGERIO, 3) /* next entry len */
-#define LOGGER_FLUSH_LOG		_IO(__LOGGERIO, 4) /* flush log */
-
-#endif /* _LINUX_LOGGER_H */

+ 0 - 173
drivers/staging/android/lowmemorykiller.c

@@ -1,173 +0,0 @@
-/* drivers/misc/lowmemorykiller.c
- *
- * The lowmemorykiller driver lets user-space specify a set of memory thresholds
- * where processes with a range of oom_adj values will get killed. Specify the
- * minimum oom_adj values in /sys/module/lowmemorykiller/parameters/adj and the
- * number of free pages in /sys/module/lowmemorykiller/parameters/minfree. Both
- * files take a comma separated list of numbers in ascending order.
- *
- * For example, write "0,8" to /sys/module/lowmemorykiller/parameters/adj and
- * "1024,4096" to /sys/module/lowmemorykiller/parameters/minfree to kill processes
- * with a oom_adj value of 8 or higher when the free memory drops below 4096 pages
- * and kill processes with a oom_adj value of 0 or higher when the free memory
- * drops below 1024 pages.
- *
- * The driver considers memory used for caches to be free, but if a large
- * percentage of the cached memory is locked this can be very inaccurate
- * and processes may not get killed until the normal oom killer is triggered.
- *
- * Copyright (C) 2007-2008 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/oom.h>
-#include <linux/sched.h>
-
-static uint32_t lowmem_debug_level = 2;
-static int lowmem_adj[6] = {
-	0,
-	1,
-	6,
-	12,
-};
-static int lowmem_adj_size = 4;
-static size_t lowmem_minfree[6] = {
-	3 * 512,	/* 6MB */
-	2 * 1024,	/* 8MB */
-	4 * 1024,	/* 16MB */
-	16 * 1024,	/* 64MB */
-};
-static int lowmem_minfree_size = 4;
-
-#define lowmem_print(level, x...)			\
-	do {						\
-		if (lowmem_debug_level >= (level))	\
-			printk(x);			\
-	} while (0)
-
-static int lowmem_shrink(int nr_to_scan, gfp_t gfp_mask)
-{
-	struct task_struct *p;
-	struct task_struct *selected = NULL;
-	int rem = 0;
-	int tasksize;
-	int i;
-	int min_adj = OOM_ADJUST_MAX + 1;
-	int selected_tasksize = 0;
-	int selected_oom_adj;
-	int array_size = ARRAY_SIZE(lowmem_adj);
-	int other_free = global_page_state(NR_FREE_PAGES);
-	int other_file = global_page_state(NR_FILE_PAGES);
-
-	if (lowmem_adj_size < array_size)
-		array_size = lowmem_adj_size;
-	if (lowmem_minfree_size < array_size)
-		array_size = lowmem_minfree_size;
-	for (i = 0; i < array_size; i++) {
-		if (other_free < lowmem_minfree[i] &&
-		    other_file < lowmem_minfree[i]) {
-			min_adj = lowmem_adj[i];
-			break;
-		}
-	}
-	if (nr_to_scan > 0)
-		lowmem_print(3, "lowmem_shrink %d, %x, ofree %d %d, ma %d\n",
-			     nr_to_scan, gfp_mask, other_free, other_file,
-			     min_adj);
-	rem = global_page_state(NR_ACTIVE_ANON) +
-		global_page_state(NR_ACTIVE_FILE) +
-		global_page_state(NR_INACTIVE_ANON) +
-		global_page_state(NR_INACTIVE_FILE);
-	if (nr_to_scan <= 0 || min_adj == OOM_ADJUST_MAX + 1) {
-		lowmem_print(5, "lowmem_shrink %d, %x, return %d\n",
-			     nr_to_scan, gfp_mask, rem);
-		return rem;
-	}
-	selected_oom_adj = min_adj;
-
-	read_lock(&tasklist_lock);
-	for_each_process(p) {
-		struct mm_struct *mm;
-		int oom_adj;
-
-		task_lock(p);
-		mm = p->mm;
-		if (!mm) {
-			task_unlock(p);
-			continue;
-		}
-		oom_adj = mm->oom_adj;
-		if (oom_adj < min_adj) {
-			task_unlock(p);
-			continue;
-		}
-		tasksize = get_mm_rss(mm);
-		task_unlock(p);
-		if (tasksize <= 0)
-			continue;
-		if (selected) {
-			if (oom_adj < selected_oom_adj)
-				continue;
-			if (oom_adj == selected_oom_adj &&
-			    tasksize <= selected_tasksize)
-				continue;
-		}
-		selected = p;
-		selected_tasksize = tasksize;
-		selected_oom_adj = oom_adj;
-		lowmem_print(2, "select %d (%s), adj %d, size %d, to kill\n",
-			     p->pid, p->comm, oom_adj, tasksize);
-	}
-	if (selected) {
-		lowmem_print(1, "send sigkill to %d (%s), adj %d, size %d\n",
-			     selected->pid, selected->comm,
-			     selected_oom_adj, selected_tasksize);
-		force_sig(SIGKILL, selected);
-		rem -= selected_tasksize;
-	}
-	lowmem_print(4, "lowmem_shrink %d, %x, return %d\n",
-		     nr_to_scan, gfp_mask, rem);
-	read_unlock(&tasklist_lock);
-	return rem;
-}
-
-static struct shrinker lowmem_shrinker = {
-	.shrink = lowmem_shrink,
-	.seeks = DEFAULT_SEEKS * 16
-};
-
-static int __init lowmem_init(void)
-{
-	register_shrinker(&lowmem_shrinker);
-	return 0;
-}
-
-static void __exit lowmem_exit(void)
-{
-	unregister_shrinker(&lowmem_shrinker);
-}
-
-module_param_named(cost, lowmem_shrinker.seeks, int, S_IRUGO | S_IWUSR);
-module_param_array_named(adj, lowmem_adj, int, &lowmem_adj_size,
-			 S_IRUGO | S_IWUSR);
-module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size,
-			 S_IRUGO | S_IWUSR);
-module_param_named(debug_level, lowmem_debug_level, uint, S_IRUGO | S_IWUSR);
-
-module_init(lowmem_init);
-module_exit(lowmem_exit);
-
-MODULE_LICENSE("GPL");
-

+ 0 - 410
drivers/staging/android/ram_console.c

@@ -1,410 +0,0 @@
-/* drivers/android/ram_console.c
- *
- * Copyright (C) 2007-2008 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/console.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/proc_fs.h>
-#include <linux/string.h>
-#include <linux/uaccess.h>
-#include <linux/io.h>
-
-#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
-#include <linux/rslib.h>
-#endif
-
-struct ram_console_buffer {
-	uint32_t    sig;
-	uint32_t    start;
-	uint32_t    size;
-	uint8_t     data[0];
-};
-
-#define RAM_CONSOLE_SIG (0x43474244) /* DBGC */
-
-#ifdef CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT
-static char __initdata
-	ram_console_old_log_init_buffer[CONFIG_ANDROID_RAM_CONSOLE_EARLY_SIZE];
-#endif
-static char *ram_console_old_log;
-static size_t ram_console_old_log_size;
-
-static struct ram_console_buffer *ram_console_buffer;
-static size_t ram_console_buffer_size;
-#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
-static char *ram_console_par_buffer;
-static struct rs_control *ram_console_rs_decoder;
-static int ram_console_corrected_bytes;
-static int ram_console_bad_blocks;
-#define ECC_BLOCK_SIZE CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_DATA_SIZE
-#define ECC_SIZE CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_ECC_SIZE
-#define ECC_SYMSIZE CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE
-#define ECC_POLY CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_POLYNOMIAL
-#endif
-
-#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
-static void ram_console_encode_rs8(uint8_t *data, size_t len, uint8_t *ecc)
-{
-	int i;
-	uint16_t par[ECC_SIZE];
-	/* Initialize the parity buffer */
-	memset(par, 0, sizeof(par));
-	encode_rs8(ram_console_rs_decoder, data, len, par, 0);
-	for (i = 0; i < ECC_SIZE; i++)
-		ecc[i] = par[i];
-}
-
-static int ram_console_decode_rs8(void *data, size_t len, uint8_t *ecc)
-{
-	int i;
-	uint16_t par[ECC_SIZE];
-	for (i = 0; i < ECC_SIZE; i++)
-		par[i] = ecc[i];
-	return decode_rs8(ram_console_rs_decoder, data, par, len,
-				NULL, 0, NULL, 0, NULL);
-}
-#endif
-
-static void ram_console_update(const char *s, unsigned int count)
-{
-	struct ram_console_buffer *buffer = ram_console_buffer;
-#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
-	uint8_t *buffer_end = buffer->data + ram_console_buffer_size;
-	uint8_t *block;
-	uint8_t *par;
-	int size = ECC_BLOCK_SIZE;
-#endif
-	memcpy(buffer->data + buffer->start, s, count);
-#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
-	block = buffer->data + (buffer->start & ~(ECC_BLOCK_SIZE - 1));
-	par = ram_console_par_buffer +
-	      (buffer->start / ECC_BLOCK_SIZE) * ECC_SIZE;
-	do {
-		if (block + ECC_BLOCK_SIZE > buffer_end)
-			size = buffer_end - block;
-		ram_console_encode_rs8(block, size, par);
-		block += ECC_BLOCK_SIZE;
-		par += ECC_SIZE;
-	} while (block < buffer->data + buffer->start + count);
-#endif
-}
-
-static void ram_console_update_header(void)
-{
-#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
-	struct ram_console_buffer *buffer = ram_console_buffer;
-	uint8_t *par;
-	par = ram_console_par_buffer +
-	      DIV_ROUND_UP(ram_console_buffer_size, ECC_BLOCK_SIZE) * ECC_SIZE;
-	ram_console_encode_rs8((uint8_t *)buffer, sizeof(*buffer), par);
-#endif
-}
-
-static void
-ram_console_write(struct console *console, const char *s, unsigned int count)
-{
-	int rem;
-	struct ram_console_buffer *buffer = ram_console_buffer;
-
-	if (count > ram_console_buffer_size) {
-		s += count - ram_console_buffer_size;
-		count = ram_console_buffer_size;
-	}
-	rem = ram_console_buffer_size - buffer->start;
-	if (rem < count) {
-		ram_console_update(s, rem);
-		s += rem;
-		count -= rem;
-		buffer->start = 0;
-		buffer->size = ram_console_buffer_size;
-	}
-	ram_console_update(s, count);
-
-	buffer->start += count;
-	if (buffer->size < ram_console_buffer_size)
-		buffer->size += count;
-	ram_console_update_header();
-}
-
-static struct console ram_console = {
-	.name	= "ram",
-	.write	= ram_console_write,
-	.flags	= CON_PRINTBUFFER | CON_ENABLED,
-	.index	= -1,
-};
-
-static void __init
-ram_console_save_old(struct ram_console_buffer *buffer, char *dest)
-{
-	size_t old_log_size = buffer->size;
-#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
-	uint8_t *block;
-	uint8_t *par;
-	char strbuf[80];
-	int strbuf_len;
-
-	block = buffer->data;
-	par = ram_console_par_buffer;
-	while (block < buffer->data + buffer->size) {
-		int numerr;
-		int size = ECC_BLOCK_SIZE;
-		if (block + size > buffer->data + ram_console_buffer_size)
-			size = buffer->data + ram_console_buffer_size - block;
-		numerr = ram_console_decode_rs8(block, size, par);
-		if (numerr > 0) {
-#if 0
-			printk(KERN_INFO "ram_console: error in block %p, %d\n",
-			       block, numerr);
-#endif
-			ram_console_corrected_bytes += numerr;
-		} else if (numerr < 0) {
-#if 0
-			printk(KERN_INFO "ram_console: uncorrectable error in "
-			       "block %p\n", block);
-#endif
-			ram_console_bad_blocks++;
-		}
-		block += ECC_BLOCK_SIZE;
-		par += ECC_SIZE;
-	}
-	if (ram_console_corrected_bytes || ram_console_bad_blocks)
-		strbuf_len = snprintf(strbuf, sizeof(strbuf),
-			"\n%d Corrected bytes, %d unrecoverable blocks\n",
-			ram_console_corrected_bytes, ram_console_bad_blocks);
-	else
-		strbuf_len = snprintf(strbuf, sizeof(strbuf),
-				      "\nNo errors detected\n");
-	if (strbuf_len >= sizeof(strbuf))
-		strbuf_len = sizeof(strbuf) - 1;
-	old_log_size += strbuf_len;
-#endif
-
-	if (dest == NULL) {
-		dest = kmalloc(old_log_size, GFP_KERNEL);
-		if (dest == NULL) {
-			printk(KERN_ERR
-			       "ram_console: failed to allocate buffer\n");
-			return;
-		}
-	}
-
-	ram_console_old_log = dest;
-	ram_console_old_log_size = old_log_size;
-	memcpy(ram_console_old_log,
-	       &buffer->data[buffer->start], buffer->size - buffer->start);
-	memcpy(ram_console_old_log + buffer->size - buffer->start,
-	       &buffer->data[0], buffer->start);
-#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
-	memcpy(ram_console_old_log + old_log_size - strbuf_len,
-	       strbuf, strbuf_len);
-#endif
-}
-
-static int __init ram_console_init(struct ram_console_buffer *buffer,
-				   size_t buffer_size, char *old_buf)
-{
-#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
-	int numerr;
-	uint8_t *par;
-#endif
-	ram_console_buffer = buffer;
-	ram_console_buffer_size =
-		buffer_size - sizeof(struct ram_console_buffer);
-
-	if (ram_console_buffer_size > buffer_size) {
-		pr_err("ram_console: buffer %p, invalid size %zu, "
-		       "datasize %zu\n", buffer, buffer_size,
-		       ram_console_buffer_size);
-		return 0;
-	}
-
-#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
-	ram_console_buffer_size -= (DIV_ROUND_UP(ram_console_buffer_size,
-						ECC_BLOCK_SIZE) + 1) * ECC_SIZE;
-
-	if (ram_console_buffer_size > buffer_size) {
-		pr_err("ram_console: buffer %p, invalid size %zu, "
-		       "non-ecc datasize %zu\n",
-		       buffer, buffer_size, ram_console_buffer_size);
-		return 0;
-	}
-
-	ram_console_par_buffer = buffer->data + ram_console_buffer_size;
-
-
-	/* first consecutive root is 0
-	 * primitive element to generate roots = 1
-	 */
-	ram_console_rs_decoder = init_rs(ECC_SYMSIZE, ECC_POLY, 0, 1, ECC_SIZE);
-	if (ram_console_rs_decoder == NULL) {
-		printk(KERN_INFO "ram_console: init_rs failed\n");
-		return 0;
-	}
-
-	ram_console_corrected_bytes = 0;
-	ram_console_bad_blocks = 0;
-
-	par = ram_console_par_buffer +
-	      DIV_ROUND_UP(ram_console_buffer_size, ECC_BLOCK_SIZE) * ECC_SIZE;
-
-	numerr = ram_console_decode_rs8(buffer, sizeof(*buffer), par);
-	if (numerr > 0) {
-		printk(KERN_INFO "ram_console: error in header, %d\n", numerr);
-		ram_console_corrected_bytes += numerr;
-	} else if (numerr < 0) {
-		printk(KERN_INFO
-		       "ram_console: uncorrectable error in header\n");
-		ram_console_bad_blocks++;
-	}
-#endif
-
-	if (buffer->sig == RAM_CONSOLE_SIG) {
-		if (buffer->size > ram_console_buffer_size
-		    || buffer->start > buffer->size)
-			printk(KERN_INFO "ram_console: found existing invalid "
-			       "buffer, size %d, start %d\n",
-			       buffer->size, buffer->start);
-		else {
-			printk(KERN_INFO "ram_console: found existing buffer, "
-			       "size %d, start %d\n",
-			       buffer->size, buffer->start);
-			ram_console_save_old(buffer, old_buf);
-		}
-	} else {
-		printk(KERN_INFO "ram_console: no valid data in buffer "
-		       "(sig = 0x%08x)\n", buffer->sig);
-	}
-
-	buffer->sig = RAM_CONSOLE_SIG;
-	buffer->start = 0;
-	buffer->size = 0;
-
-	register_console(&ram_console);
-#ifdef CONFIG_ANDROID_RAM_CONSOLE_ENABLE_VERBOSE
-	console_verbose();
-#endif
-	return 0;
-}
-
-#ifdef CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT
-static int __init ram_console_early_init(void)
-{
-	return ram_console_init((struct ram_console_buffer *)
-		CONFIG_ANDROID_RAM_CONSOLE_EARLY_ADDR,
-		CONFIG_ANDROID_RAM_CONSOLE_EARLY_SIZE,
-		ram_console_old_log_init_buffer);
-}
-#else
-static int ram_console_driver_probe(struct platform_device *pdev)
-{
-	struct resource *res = pdev->resource;
-	size_t start;
-	size_t buffer_size;
-	void *buffer;
-
-	if (res == NULL || pdev->num_resources != 1 ||
-	    !(res->flags & IORESOURCE_MEM)) {
-		printk(KERN_ERR "ram_console: invalid resource, %p %d flags "
-		       "%lx\n", res, pdev->num_resources, res ? res->flags : 0);
-		return -ENXIO;
-	}
-	buffer_size = res->end - res->start + 1;
-	start = res->start;
-	printk(KERN_INFO "ram_console: got buffer at %zx, size %zx\n",
-	       start, buffer_size);
-	buffer = ioremap(res->start, buffer_size);
-	if (buffer == NULL) {
-		printk(KERN_ERR "ram_console: failed to map memory\n");
-		return -ENOMEM;
-	}
-
-	return ram_console_init(buffer, buffer_size, NULL/* allocate */);
-}
-
-static struct platform_driver ram_console_driver = {
-	.probe = ram_console_driver_probe,
-	.driver		= {
-		.name	= "ram_console",
-	},
-};
-
-static int __init ram_console_module_init(void)
-{
-	int err;
-	err = platform_driver_register(&ram_console_driver);
-	return err;
-}
-#endif
-
-static ssize_t ram_console_read_old(struct file *file, char __user *buf,
-				    size_t len, loff_t *offset)
-{
-	loff_t pos = *offset;
-	ssize_t count;
-
-	if (pos >= ram_console_old_log_size)
-		return 0;
-
-	count = min(len, (size_t)(ram_console_old_log_size - pos));
-	if (copy_to_user(buf, ram_console_old_log + pos, count))
-		return -EFAULT;
-
-	*offset += count;
-	return count;
-}
-
-static const struct file_operations ram_console_file_ops = {
-	.owner = THIS_MODULE,
-	.read = ram_console_read_old,
-};
-
-static int __init ram_console_late_init(void)
-{
-	struct proc_dir_entry *entry;
-
-	if (ram_console_old_log == NULL)
-		return 0;
-#ifdef CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT
-	ram_console_old_log = kmalloc(ram_console_old_log_size, GFP_KERNEL);
-	if (ram_console_old_log == NULL) {
-		printk(KERN_ERR
-		       "ram_console: failed to allocate buffer for old log\n");
-		ram_console_old_log_size = 0;
-		return 0;
-	}
-	memcpy(ram_console_old_log,
-	       ram_console_old_log_init_buffer, ram_console_old_log_size);
-#endif
-	entry = create_proc_entry("last_kmsg", S_IFREG | S_IRUGO, NULL);
-	if (!entry) {
-		printk(KERN_ERR "ram_console: failed to create proc entry\n");
-		kfree(ram_console_old_log);
-		ram_console_old_log = NULL;
-		return 0;
-	}
-
-	entry->proc_fops = &ram_console_file_ops;
-	entry->size = ram_console_old_log_size;
-	return 0;
-}
-
-#ifdef CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT
-console_initcall(ram_console_early_init);
-#else
-module_init(ram_console_module_init);
-#endif
-late_initcall(ram_console_late_init);
-

+ 0 - 166
drivers/staging/android/timed_gpio.c

@@ -1,166 +0,0 @@
-/* drivers/misc/timed_gpio.c
- *
- * Copyright (C) 2008 Google, Inc.
- * Author: Mike Lockwood <lockwood@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/hrtimer.h>
-#include <linux/err.h>
-#include <linux/gpio.h>
-
-#include "timed_output.h"
-#include "timed_gpio.h"
-
-
-struct timed_gpio_data {
-	struct timed_output_dev dev;
-	struct hrtimer timer;
-	spinlock_t lock;
-	unsigned 	gpio;
-	int 		max_timeout;
-	u8 		active_low;
-};
-
-static enum hrtimer_restart gpio_timer_func(struct hrtimer *timer)
-{
-	struct timed_gpio_data *data =
-		container_of(timer, struct timed_gpio_data, timer);
-
-	gpio_direction_output(data->gpio, data->active_low ? 1 : 0);
-	return HRTIMER_NORESTART;
-}
-
-static int gpio_get_time(struct timed_output_dev *dev)
-{
-	struct timed_gpio_data	*data =
-		container_of(dev, struct timed_gpio_data, dev);
-
-	if (hrtimer_active(&data->timer)) {
-		ktime_t r = hrtimer_get_remaining(&data->timer);
-		struct timeval t = ktime_to_timeval(r);
-		return t.tv_sec * 1000 + t.tv_usec / 1000;
-	} else
-		return 0;
-}
-
-static void gpio_enable(struct timed_output_dev *dev, int value)
-{
-	struct timed_gpio_data	*data =
-		container_of(dev, struct timed_gpio_data, dev);
-	unsigned long	flags;
-
-	spin_lock_irqsave(&data->lock, flags);
-
-	/* cancel previous timer and set GPIO according to value */
-	hrtimer_cancel(&data->timer);
-	gpio_direction_output(data->gpio, data->active_low ? !value : !!value);
-
-	if (value > 0) {
-		if (value > data->max_timeout)
-			value = data->max_timeout;
-
-		hrtimer_start(&data->timer,
-			ktime_set(value / 1000, (value % 1000) * 1000000),
-			HRTIMER_MODE_REL);
-	}
-
-	spin_unlock_irqrestore(&data->lock, flags);
-}
-
-static int timed_gpio_probe(struct platform_device *pdev)
-{
-	struct timed_gpio_platform_data *pdata = pdev->dev.platform_data;
-	struct timed_gpio *cur_gpio;
-	struct timed_gpio_data *gpio_data, *gpio_dat;
-	int i, j, ret = 0;
-
-	if (!pdata)
-		return -EBUSY;
-
-	gpio_data = kzalloc(sizeof(struct timed_gpio_data) * pdata->num_gpios,
-			GFP_KERNEL);
-	if (!gpio_data)
-		return -ENOMEM;
-
-	for (i = 0; i < pdata->num_gpios; i++) {
-		cur_gpio = &pdata->gpios[i];
-		gpio_dat = &gpio_data[i];
-
-		hrtimer_init(&gpio_dat->timer, CLOCK_MONOTONIC,
-				HRTIMER_MODE_REL);
-		gpio_dat->timer.function = gpio_timer_func;
-		spin_lock_init(&gpio_dat->lock);
-
-		gpio_dat->dev.name = cur_gpio->name;
-		gpio_dat->dev.get_time = gpio_get_time;
-		gpio_dat->dev.enable = gpio_enable;
-		ret = timed_output_dev_register(&gpio_dat->dev);
-		if (ret < 0) {
-			for (j = 0; j < i; j++)
-				timed_output_dev_unregister(&gpio_data[i].dev);
-			kfree(gpio_data);
-			return ret;
-		}
-
-		gpio_dat->gpio = cur_gpio->gpio;
-		gpio_dat->max_timeout = cur_gpio->max_timeout;
-		gpio_dat->active_low = cur_gpio->active_low;
-		gpio_direction_output(gpio_dat->gpio, gpio_dat->active_low);
-	}
-
-	platform_set_drvdata(pdev, gpio_data);
-
-	return 0;
-}
-
-static int timed_gpio_remove(struct platform_device *pdev)
-{
-	struct timed_gpio_platform_data *pdata = pdev->dev.platform_data;
-	struct timed_gpio_data *gpio_data = platform_get_drvdata(pdev);
-	int i;
-
-	for (i = 0; i < pdata->num_gpios; i++)
-		timed_output_dev_unregister(&gpio_data[i].dev);
-
-	kfree(gpio_data);
-
-	return 0;
-}
-
-static struct platform_driver timed_gpio_driver = {
-	.probe		= timed_gpio_probe,
-	.remove		= timed_gpio_remove,
-	.driver		= {
-		.name		= TIMED_GPIO_NAME,
-		.owner		= THIS_MODULE,
-	},
-};
-
-static int __init timed_gpio_init(void)
-{
-	return platform_driver_register(&timed_gpio_driver);
-}
-
-static void __exit timed_gpio_exit(void)
-{
-	platform_driver_unregister(&timed_gpio_driver);
-}
-
-module_init(timed_gpio_init);
-module_exit(timed_gpio_exit);
-
-MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
-MODULE_DESCRIPTION("timed gpio driver");
-MODULE_LICENSE("GPL");

+ 0 - 33
drivers/staging/android/timed_gpio.h

@@ -1,33 +0,0 @@
-/* include/linux/timed_gpio.h
- *
- * Copyright (C) 2008 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
-*/
-
-#ifndef _LINUX_TIMED_GPIO_H
-#define _LINUX_TIMED_GPIO_H
-
-#define TIMED_GPIO_NAME "timed-gpio"
-
-struct timed_gpio {
-	const char *name;
-	unsigned 	gpio;
-	int		max_timeout;
-	u8 		active_low;
-};
-
-struct timed_gpio_platform_data {
-	int 		num_gpios;
-	struct timed_gpio *gpios;
-};
-
-#endif

+ 0 - 121
drivers/staging/android/timed_output.c

@@ -1,121 +0,0 @@
-/* drivers/misc/timed_output.c
- *
- * Copyright (C) 2009 Google, Inc.
- * Author: Mike Lockwood <lockwood@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/device.h>
-#include <linux/fs.h>
-#include <linux/err.h>
-
-#include "timed_output.h"
-
-static struct class *timed_output_class;
-static atomic_t device_count;
-
-static ssize_t enable_show(struct device *dev, struct device_attribute *attr,
-		char *buf)
-{
-	struct timed_output_dev *tdev = dev_get_drvdata(dev);
-	int remaining = tdev->get_time(tdev);
-
-	return sprintf(buf, "%d\n", remaining);
-}
-
-static ssize_t enable_store(
-		struct device *dev, struct device_attribute *attr,
-		const char *buf, size_t size)
-{
-	struct timed_output_dev *tdev = dev_get_drvdata(dev);
-	int value;
-
-	sscanf(buf, "%d", &value);
-	tdev->enable(tdev, value);
-
-	return size;
-}
-
-static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, enable_show, enable_store);
-
-static int create_timed_output_class(void)
-{
-	if (!timed_output_class) {
-		timed_output_class = class_create(THIS_MODULE, "timed_output");
-		if (IS_ERR(timed_output_class))
-			return PTR_ERR(timed_output_class);
-		atomic_set(&device_count, 0);
-	}
-
-	return 0;
-}
-
-int timed_output_dev_register(struct timed_output_dev *tdev)
-{
-	int ret;
-
-	if (!tdev || !tdev->name || !tdev->enable || !tdev->get_time)
-		return -EINVAL;
-
-	ret = create_timed_output_class();
-	if (ret < 0)
-		return ret;
-
-	tdev->index = atomic_inc_return(&device_count);
-	tdev->dev = device_create(timed_output_class, NULL,
-		MKDEV(0, tdev->index), NULL, tdev->name);
-	if (IS_ERR(tdev->dev))
-		return PTR_ERR(tdev->dev);
-
-	ret = device_create_file(tdev->dev, &dev_attr_enable);
-	if (ret < 0)
-		goto err_create_file;
-
-	dev_set_drvdata(tdev->dev, tdev);
-	tdev->state = 0;
-	return 0;
-
-err_create_file:
-	device_destroy(timed_output_class, MKDEV(0, tdev->index));
-	printk(KERN_ERR "timed_output: Failed to register driver %s\n",
-			tdev->name);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(timed_output_dev_register);
-
-void timed_output_dev_unregister(struct timed_output_dev *tdev)
-{
-	device_remove_file(tdev->dev, &dev_attr_enable);
-	device_destroy(timed_output_class, MKDEV(0, tdev->index));
-	dev_set_drvdata(tdev->dev, NULL);
-}
-EXPORT_SYMBOL_GPL(timed_output_dev_unregister);
-
-static int __init timed_output_init(void)
-{
-	return create_timed_output_class();
-}
-
-static void __exit timed_output_exit(void)
-{
-	class_destroy(timed_output_class);
-}
-
-module_init(timed_output_init);
-module_exit(timed_output_exit);
-
-MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
-MODULE_DESCRIPTION("timed output class driver");
-MODULE_LICENSE("GPL");

+ 0 - 37
drivers/staging/android/timed_output.h

@@ -1,37 +0,0 @@
-/* include/linux/timed_output.h
- *
- * Copyright (C) 2008 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
-*/
-
-#ifndef _LINUX_TIMED_OUTPUT_H
-#define _LINUX_TIMED_OUTPUT_H
-
-struct timed_output_dev {
-	const char	*name;
-
-	/* enable the output and set the timer */
-	void	(*enable)(struct timed_output_dev *sdev, int timeout);
-
-	/* returns the current number of milliseconds remaining on the timer */
-	int		(*get_time)(struct timed_output_dev *sdev);
-
-	/* private data */
-	struct device	*dev;
-	int		index;
-	int		state;
-};
-
-extern int timed_output_dev_register(struct timed_output_dev *dev);
-extern void timed_output_dev_unregister(struct timed_output_dev *dev);
-
-#endif

+ 0 - 12
drivers/staging/b3dfg/b3dfg.c

@@ -468,7 +468,6 @@ static int get_wand_status(struct b3dfg_dev *fgdev, int __user *arg)
 
 static int enable_transmission(struct b3dfg_dev *fgdev)
 {
-	u16 command;
 	unsigned long flags;
 	struct device *dev = &fgdev->pdev->dev;
 
@@ -480,17 +479,6 @@ static int enable_transmission(struct b3dfg_dev *fgdev)
 		return -EINVAL;
 	}
 
-	/*
-	 * Check we're a bus master.
-	 * TODO: I think we can remove this having added the pci_set_master call
-	 */
-	pci_read_config_word(fgdev->pdev, PCI_COMMAND, &command);
-	if (!(command & PCI_COMMAND_MASTER)) {
-		dev_err(dev, "not a bus master, force-enabling\n");
-		pci_write_config_word(fgdev->pdev, PCI_COMMAND,
-			command | PCI_COMMAND_MASTER);
-	}
-
 	spin_lock_irqsave(&fgdev->buffer_lock, flags);
 
 	/* Handle racing enable_transmission calls. */

+ 37 - 0
drivers/staging/batman-adv/CHANGELOG

@@ -0,0 +1,37 @@
+batman-adv 0.2:
+
+* support latest kernels (2.6.20 - 2.6.31)
+* temporary routing loops / TTL code bug / ghost entries in originator table fixed
+* internal packet queue for packet aggregation & transmission retry (ARQ)
+  for payload broadcasts added
+* interface detection converted to event based handling to avoid timers
+* major linux coding style adjustments applied
+* all kernel version compatibility functions has been moved to compat.h
+* use random ethernet address generator from the kernel
+* /sys/module/batman_adv/version to export kernel module version
+* vis: secondary interface export for dot draw format + JSON output format added
+* many bugs (alignment issues, race conditions, deadlocks, etc) squashed
+
+ -- Sat, 07 Nov 2009 15:44:31 +0100
+
+batman-adv 0.1:
+
+* support latest kernels (2.6.20 - 2.6.28)
+* LOTS of cleanup: locking, stack usage, memory leaks
+* Change Ethertype from 0x0842 to 0x4305
+  unregistered at IEEE, if you want to sponsor an official Ethertype ($2500)
+  please contact us
+
+ -- Sun, 28 Dec 2008 00:44:31 +0100
+
+batman-adv 0.1-beta:
+
+* layer 2 meshing based on BATMAN TQ algorithm in kernelland
+* operates on any ethernet like interface
+* supports IPv4, IPv6, DHCP, etc
+* is controlled via /proc/net/batman-adv/
+* bridging via brctl is supported
+* interface watchdog (interfaces can be (de)activated dynamically)
+* offers integrated vis server which meshes/syncs with other vis servers in range
+
+ -- Mon, 05 May 2008 14:10:04 +0200

+ 25 - 0
drivers/staging/batman-adv/Kconfig

@@ -0,0 +1,25 @@
+#
+# B.A.T.M.A.N meshing protocol
+#
+
+config BATMAN_ADV
+	tristate "B.A.T.M.A.N. Advanced Meshing Protocol"
+        default n
+	---help---
+
+        B.A.T.M.A.N. (better approach to mobile ad-hoc networking) is
+        a routing protocol for multi-hop ad-hoc mesh networks. The
+        networks may be wired or wireless. See
+        http://www.open-mesh.org/ for more information and user space
+        tools.
+
+config BATMAN_DEBUG
+	bool "B.A.T.M.A.N. debugging"
+	depends on BATMAN != n
+	help
+
+	  This is an option for use by developers; most people should
+	  say N here. This enables compilation of support for
+	  outputting debugging information to the kernel log. The
+	  output is controlled via the module parameter debug.
+

+ 22 - 0
drivers/staging/batman-adv/Makefile

@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+#
+# Marek Lindner, Simon Wunderlich
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of version 2 of the GNU General Public
+# License as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA
+#
+
+obj-m += batman-adv.o
+batman-adv-objs := main.o proc.o send.o routing.o soft-interface.o device.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o log.o

+ 125 - 0
drivers/staging/batman-adv/README

@@ -0,0 +1,125 @@
+[state: 07-11-2009]
+
+BATMAN-ADV
+----------
+
+Batman-advanced is a new approach to wireless networking which does no longer
+operate on the IP basis. Unlike B.A.T.M.A.N, which exchanges information
+using UDP packets and sets routing tables, batman-advanced operates on ISO/OSI
+Layer 2 only and uses and routes (or better: bridges) Ethernet Frames. It
+emulates a virtual network switch of all nodes participating. Therefore all
+nodes appear to be link local, thus all higher operating protocols won't be
+affected by any changes within the network. You can run almost any protocol
+above B.A.T.M.A.N. Advanced, prominent examples are: IPv4, IPv6, DHCP, IPX.
+
+This is batman-advanced implemented as Linux kernel driver. It does not depend
+on any network (other) driver, and can be used on wifi as well as ethernet,
+vpn, etc ... (anything with ethernet-style layer 2).
+It compiles against and should work with Linux 2.6.20 - 2.6.31. Supporting older
+versions is not planned, but it's probably easy to backport it. If you work on a
+backport, feel free to contact us.  :-)
+
+COMPILE
+-------
+To compile against your currently installed kernel, just type:
+
+# make
+
+if you want to compile against some other kernel, use:
+
+# make KERNELPATH=/path/to/kernel
+
+USAGE
+-----
+
+insmod the batman-adv.ko in your kernel:
+
+# insmod batman-adv.ko
+
+the module is now waiting for activation. You must add some interfaces
+on which batman can operate. Each interface must be added separately:
+
+# echo wlan0 > /proc/net/batman-adv/interfaces
+
+( # echo wlan1 > /proc/net/batman-adv/interfaces )
+( # echo eth0 > /proc/net/batman-adv/interfaces )
+( ... )
+
+Now batman starts broadcasting on this interface.
+You can now view the table of originators (mesh participants) with:
+
+# cat /proc/net/batman-adv/originators
+
+The module will create a new interface "bat0", which can be used as a
+regular interface:
+
+# ifconfig bat0 inet 192.168.0.1 up
+# ping 192.168.0.2
+...
+
+If you want topology visualization, your meshnode must be configured
+as VIS-server:
+
+# echo "server" > /proc/net/batman-adv/vis
+
+Each node is either configured as "server" or as "client" (default:
+"client"). Clients send their topology data to the server next to them,
+and server synchronize with other servers. If there is no server
+configured (default) within the mesh, no topology information will be
+transmitted. With these "synchronizing servers", there can be 1 or
+more vis servers sharing the same (or at least very similar) data.
+
+When configured as server, you can get a topology snapshot of your mesh:
+
+# cat /proc/net/batman-adv/vis
+
+This output format is a graphviz formatted text file which can be
+processed with graphviz-tools like dot.
+The labels are similar/compatible to the ETX metric, 1.0 means perfect
+connection (100%), 2.0 means 50%, 3.0 means 33% and so on.
+
+Alternatively, a JSON output format is available. The format can be set
+using by writing either "dot_draw" or "json" into the vis_format file.
+"dot_draw" is selected by default.
+
+echo "json" > /proc/net/batman-adv/vis_format
+
+In very mobile scenarios, you might want to adjust the originator
+interval to a lower value. This will make the mesh more responsive to
+topology changes, but will also increase the overhead. Please make sure
+that all nodes in your mesh use the same interval. The default value
+is 1000 ms (1 second).
+
+# echo 1000 > /proc/net/batman-adv/orig_interval
+
+To deactivate batman, do:
+
+# echo "" > /proc/net/batman-adv/interfaces
+
+BATCTL
+------
+
+B.A.T.M.A.N.  advanced  operates on layer 2 and thus all hosts partici-
+pating in the virtual switch are completely transparent for all  proto-
+cols above layer 2. Therefore the common diagnosis tools do not work as
+expected. To overcome these problems batctl was created. At the  moment
+the  batctl contains ping, traceroute, tcpdump and interfaces to the
+kernel module settings.
+
+For more information, please see the manpage (man batctl).
+
+batctl is available on http://www.open-mesh.net/
+
+CONTACT
+-------
+
+Please send us comments, experiences, questions, anything :)
+
+IRC:             #batman on irc.freenode.org
+Mailing-list:    b.a.t.m.a.n@open-mesh.net
+(subscription at https://list.open-mesh.net/mm/listinfo/b.a.t.m.a.n )
+
+You can also contact the Authors:
+
+Marek Lindner <lindner_marek@yahoo.de>
+Simon Wunderlich <siwu@hrz.tu-chemnitz.de>

+ 51 - 0
drivers/staging/batman-adv/TODO

@@ -0,0 +1,51 @@
+=> proc interface
+* implement new interface to add/delete interfaces and setting options
+* /proc/sys/net/batman-adv/ as main folder
+* in interfaces/ list every available interface of the host
+* each interfaces/$iface/ contains the following files:
+-> enable (def: 0) [add/remove this interface to batman-adv]
+-> ogm_interval (def: 1000) [ogm interval of that interface]
+-> context (def: bat0) [later we want to support multiple mesh instances via
+-> bat0/bat1/bat2/..]
+-> status (read-only) [outputs the interface status from batman's
+-> perspective]
+* in mesh/batX/ list every available mesh subnet
+-> vis_server (def: 0) [enable/disable vis server for that mesh]
+-> vis_data (read-only) [outputs the vis data in a raw format]
+-> aggregate_ogm (def: 1) [enable/disable ogm aggregation for that mesh]
+-> originators (read-only) [outputs the originator table]
+-> transtable_global (read-only) [outputs the global translation table]
+-> transtable_local (read-only) [outputs the local translation table]
+
+=> vis "raw" data output
+* the raw format shall replace dot draw / json to offer a neutral that can
+* be converted
+* the format (comma seperated entries):
+-> "mac" -> mac address of an originator (each line begins with it)
+-> "TQ mac value" -> src mac's link quality towards mac address
+-> "HNA mac" -> HNA announced by source mac
+-> "PRIMARY" -> this is a primary interface
+-> "SEC mac" -> secondary mac address of source (requires preceeding
+-> PRIMARY)
+
+=> logging
+* the log level LOG_TYPE_CRIT, LOG_TYPE_WARN & LOG_TYPE_NOTICE will be
+* unified to use printk
+* LOG_TYPE_BATMAN & LOG_TYPE_ROUTES will also use printk but only after the
+* internal debug level has been raised
+* the internal debug level can be modified using a module parameter (debug)
+* or at run time via /sys/module/batman-adv/parameters/debug
+* make use of printk %pM support instead of converting mac addresses
+* manually
+
+=> strip out all backward compatibility support to older kernels
+   (only found in compat.h)
+
+=> fix checkpatch.pl errors
+
+Please send all patches to:
+	Marek Lindner <lindner_marek@yahoo.de>
+	Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
+	Andrew Lunn <andrew@lunn.ch>
+	b.a.t.m.a.n@lists.open-mesh.net
+	Greg Kroah-Hartman <gregkh@suse.de>

+ 232 - 0
drivers/staging/batman-adv/aggregation.c

@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#include "main.h"
+#include "aggregation.h"
+#include "send.h"
+#include "routing.h"
+
+/* calculate the size of the hna information for a given packet */
+static int hna_len(struct batman_packet *batman_packet)
+{
+	return batman_packet->num_hna * ETH_ALEN;
+}
+
+/* return true if new_packet can be aggregated with forw_packet */
+static bool can_aggregate_with(struct batman_packet *new_batman_packet,
+			       int packet_len,
+			       unsigned long send_time,
+			       bool directlink,
+			       struct batman_if *if_incoming,
+			       struct forw_packet *forw_packet)
+{
+	struct batman_packet *batman_packet =
+		(struct batman_packet *)forw_packet->packet_buff;
+	int aggregated_bytes = forw_packet->packet_len + packet_len;
+
+	/**
+	 * we can aggregate the current packet to this aggregated packet
+	 * if:
+	 *
+	 * - the send time is within our MAX_AGGREGATION_MS time
+	 * - the resulting packet wont be bigger than
+	 *   MAX_AGGREGATION_BYTES
+	 */
+
+	if (time_before(send_time, forw_packet->send_time) &&
+	    (aggregated_bytes <= MAX_AGGREGATION_BYTES)) {
+
+		/**
+		 * check aggregation compatibility
+		 * -> direct link packets are broadcasted on
+		 *    their interface only
+		 * -> aggregate packet if the current packet is
+		 *    a "global" packet as well as the base
+		 *    packet
+		 */
+
+		/* packets without direct link flag and high TTL
+		 * are flooded through the net  */
+		if ((!directlink) &&
+		    (!(batman_packet->flags & DIRECTLINK)) &&
+		    (batman_packet->ttl != 1) &&
+
+		    /* own packets originating non-primary
+		     * interfaces leave only that interface */
+		    ((!forw_packet->own) ||
+		     (forw_packet->if_incoming->if_num == 0)))
+			return true;
+
+		/* if the incoming packet is sent via this one
+		 * interface only - we still can aggregate */
+		if ((directlink) &&
+		    (new_batman_packet->ttl == 1) &&
+		    (forw_packet->if_incoming == if_incoming))
+			return true;
+
+	}
+
+	return false;
+}
+
+/* create a new aggregated packet and add this packet to it */
+static void new_aggregated_packet(unsigned char *packet_buff,
+			   int packet_len,
+			   unsigned long send_time,
+			   bool direct_link,
+			   struct batman_if *if_incoming,
+			   int own_packet)
+{
+	struct forw_packet *forw_packet_aggr;
+
+	forw_packet_aggr = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC);
+	if (!forw_packet_aggr)
+		return;
+
+	forw_packet_aggr->packet_buff = kmalloc(MAX_AGGREGATION_BYTES,
+						GFP_ATOMIC);
+	if (!forw_packet_aggr->packet_buff) {
+		kfree(forw_packet_aggr);
+		return;
+	}
+
+	INIT_HLIST_NODE(&forw_packet_aggr->list);
+
+	forw_packet_aggr->packet_len = packet_len;
+	memcpy(forw_packet_aggr->packet_buff,
+	       packet_buff,
+	       forw_packet_aggr->packet_len);
+
+	forw_packet_aggr->own = own_packet;
+	forw_packet_aggr->if_incoming = if_incoming;
+	forw_packet_aggr->num_packets = 0;
+	forw_packet_aggr->direct_link_flags = 0;
+	forw_packet_aggr->send_time = send_time;
+
+	/* save packet direct link flag status */
+	if (direct_link)
+		forw_packet_aggr->direct_link_flags |= 1;
+
+	/* add new packet to packet list */
+	spin_lock(&forw_bat_list_lock);
+	hlist_add_head(&forw_packet_aggr->list, &forw_bat_list);
+	spin_unlock(&forw_bat_list_lock);
+
+	/* start timer for this packet */
+	INIT_DELAYED_WORK(&forw_packet_aggr->delayed_work,
+			  send_outstanding_bat_packet);
+	queue_delayed_work(bat_event_workqueue,
+			   &forw_packet_aggr->delayed_work,
+			   send_time - jiffies);
+}
+
+/* aggregate a new packet into the existing aggregation */
+static void aggregate(struct forw_packet *forw_packet_aggr,
+		      unsigned char *packet_buff,
+		      int packet_len,
+		      bool direct_link)
+{
+	memcpy((forw_packet_aggr->packet_buff + forw_packet_aggr->packet_len),
+	       packet_buff, packet_len);
+	forw_packet_aggr->packet_len += packet_len;
+	forw_packet_aggr->num_packets++;
+
+	/* save packet direct link flag status */
+	if (direct_link)
+		forw_packet_aggr->direct_link_flags |=
+			(1 << forw_packet_aggr->num_packets);
+}
+
+void add_bat_packet_to_list(unsigned char *packet_buff, int packet_len,
+			    struct batman_if *if_incoming, char own_packet,
+			    unsigned long send_time)
+{
+	/**
+	 * _aggr -> pointer to the packet we want to aggregate with
+	 * _pos -> pointer to the position in the queue
+	 */
+	struct forw_packet *forw_packet_aggr = NULL, *forw_packet_pos = NULL;
+	struct hlist_node *tmp_node;
+	struct batman_packet *batman_packet =
+		(struct batman_packet *)packet_buff;
+	bool direct_link = batman_packet->flags & DIRECTLINK ? 1 : 0;
+
+	/* find position for the packet in the forward queue */
+	spin_lock(&forw_bat_list_lock);
+	/* own packets are not to be aggregated */
+	if ((atomic_read(&aggregation_enabled)) && (!own_packet)) {
+		hlist_for_each_entry(forw_packet_pos, tmp_node, &forw_bat_list,
+				     list) {
+			if (can_aggregate_with(batman_packet,
+					       packet_len,
+					       send_time,
+					       direct_link,
+					       if_incoming,
+					       forw_packet_pos)) {
+				forw_packet_aggr = forw_packet_pos;
+				break;
+			}
+		}
+	}
+
+	/* nothing to aggregate with - either aggregation disabled or no
+	 * suitable aggregation packet found */
+	if (forw_packet_aggr == NULL) {
+		/* the following section can run without the lock */
+		spin_unlock(&forw_bat_list_lock);
+		new_aggregated_packet(packet_buff, packet_len,
+				      send_time, direct_link,
+				      if_incoming, own_packet);
+	} else {
+		aggregate(forw_packet_aggr,
+			  packet_buff, packet_len,
+			  direct_link);
+		spin_unlock(&forw_bat_list_lock);
+	}
+}
+
+/* unpack the aggregated packets and process them one by one */
+void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff,
+			     int packet_len, struct batman_if *if_incoming)
+{
+	struct batman_packet *batman_packet;
+	int buff_pos = 0;
+	unsigned char *hna_buff;
+
+	batman_packet = (struct batman_packet *)packet_buff;
+
+	while (aggregated_packet(buff_pos, packet_len,
+				 batman_packet->num_hna)) {
+
+		/* network to host order for our 16bit seqno, and the
+		   orig_interval. */
+		batman_packet->seqno = ntohs(batman_packet->seqno);
+
+		hna_buff = packet_buff + buff_pos + BAT_PACKET_LEN;
+		receive_bat_packet(ethhdr, batman_packet,
+				   hna_buff, hna_len(batman_packet),
+				   if_incoming);
+
+		buff_pos += BAT_PACKET_LEN + hna_len(batman_packet);
+		batman_packet = (struct batman_packet *)
+			(packet_buff + buff_pos);
+	}
+}

+ 37 - 0
drivers/staging/batman-adv/aggregation.h

@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#include "main.h"
+
+/* is there another aggregated packet here? */
+static inline int aggregated_packet(int buff_pos, int packet_len, int num_hna)
+{
+	int next_buff_pos = buff_pos + BAT_PACKET_LEN + (num_hna * ETH_ALEN);
+
+	return (next_buff_pos <= packet_len) &&
+		(next_buff_pos <= MAX_AGGREGATION_BYTES);
+}
+
+void add_bat_packet_to_list(unsigned char *packet_buff, int packet_len,
+			    struct batman_if *if_outgoing, char own_packet,
+			    unsigned long send_time);
+void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff,
+			     int packet_len, struct batman_if *if_incoming);

+ 177 - 0
drivers/staging/batman-adv/bitarray.c

@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2006-2009 B.A.T.M.A.N. contributors:
+ *
+ * Simon Wunderlich, Marek Lindner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#include "main.h"
+#include "bitarray.h"
+#include "log.h"
+
+/* returns true if the corresponding bit in the given seq_bits indicates true
+ * and curr_seqno is within range of last_seqno */
+uint8_t get_bit_status(TYPE_OF_WORD *seq_bits, uint16_t last_seqno,
+		       uint16_t curr_seqno)
+{
+	int16_t diff, word_offset, word_num;
+
+	diff = last_seqno - curr_seqno;
+	if (diff < 0 || diff >= TQ_LOCAL_WINDOW_SIZE) {
+		return 0;
+	} else {
+		/* which word */
+		word_num = (last_seqno - curr_seqno) / WORD_BIT_SIZE;
+		/* which position in the selected word */
+		word_offset = (last_seqno - curr_seqno) % WORD_BIT_SIZE;
+
+		if (seq_bits[word_num] & 1 << word_offset)
+			return 1;
+		else
+			return 0;
+	}
+}
+
+/* turn corresponding bit on, so we can remember that we got the packet */
+void bit_mark(TYPE_OF_WORD *seq_bits, int32_t n)
+{
+	int32_t word_offset, word_num;
+
+	/* if too old, just drop it */
+	if (n < 0 || n >= TQ_LOCAL_WINDOW_SIZE)
+		return;
+
+	/* which word */
+	word_num = n / WORD_BIT_SIZE;
+	/* which position in the selected word */
+	word_offset = n % WORD_BIT_SIZE;
+
+	seq_bits[word_num] |= 1 << word_offset;	/* turn the position on */
+}
+
+/* shift the packet array by n places. */
+void bit_shift(TYPE_OF_WORD *seq_bits, int32_t n)
+{
+	int32_t word_offset, word_num;
+	int32_t i;
+
+	if (n <= 0)
+		return;
+
+	word_offset = n % WORD_BIT_SIZE;/* shift how much inside each word */
+	word_num = n / WORD_BIT_SIZE;	/* shift over how much (full) words */
+
+	for (i = NUM_WORDS - 1; i > word_num; i--) {
+		/* going from old to new, so we don't overwrite the data we copy
+		 * from.
+		 *
+		 * left is high, right is low: FEDC BA98 7654 3210
+		 *	                                  ^^ ^^
+		 *                             vvvv
+		 * ^^^^ = from, vvvvv =to, we'd have word_num==1 and
+		 * word_offset==WORD_BIT_SIZE/2 ????? in this example.
+		 * (=24 bits)
+		 *
+		 * our desired output would be: 9876 5432 1000 0000
+		 * */
+
+		seq_bits[i] =
+			(seq_bits[i - word_num] << word_offset) +
+			/* take the lower port from the left half, shift it left
+			 * to its final position */
+			(seq_bits[i - word_num - 1] >>
+			 (WORD_BIT_SIZE-word_offset));
+		/* and the upper part of the right half and shift it left to
+		 * it's position */
+		/* for our example that would be: word[0] = 9800 + 0076 =
+		 * 9876 */
+	}
+	/* now for our last word, i==word_num, we only have the it's "left"
+	 * half. that's the 1000 word in our example.*/
+
+	seq_bits[i] = (seq_bits[i - word_num] << word_offset);
+
+	/* pad the rest with 0, if there is anything */
+	i--;
+
+	for (; i >= 0; i--)
+		seq_bits[i] = 0;
+}
+
+
+/* receive and process one packet, returns 1 if received seq_num is considered
+ * new, 0 if old  */
+char bit_get_packet(TYPE_OF_WORD *seq_bits, int16_t seq_num_diff,
+		    int8_t set_mark)
+{
+	int i;
+
+	/* we already got a sequence number higher than this one, so we just
+	 * mark it. this should wrap around the integer just fine */
+	if ((seq_num_diff < 0) && (seq_num_diff >= -TQ_LOCAL_WINDOW_SIZE)) {
+		if (set_mark)
+			bit_mark(seq_bits, -seq_num_diff);
+		return 0;
+	}
+
+	/* it seems we missed a lot of packets or the other host restarted */
+	if ((seq_num_diff > TQ_LOCAL_WINDOW_SIZE) ||
+	    (seq_num_diff < -TQ_LOCAL_WINDOW_SIZE)) {
+
+		if (seq_num_diff > TQ_LOCAL_WINDOW_SIZE)
+			debug_log(LOG_TYPE_BATMAN,
+				  "We missed a lot of packets (%i) !\n",
+				  seq_num_diff-1);
+
+		if (-seq_num_diff > TQ_LOCAL_WINDOW_SIZE)
+			debug_log(LOG_TYPE_BATMAN,
+				  "Other host probably restarted !\n");
+
+		for (i = 0; i < NUM_WORDS; i++)
+			seq_bits[i] = 0;
+
+		if (set_mark)
+			seq_bits[0] = 1;  /* we only have the latest packet */
+	} else {
+		bit_shift(seq_bits, seq_num_diff);
+
+		if (set_mark)
+			bit_mark(seq_bits, 0);
+	}
+
+	return 1;
+}
+
+/* count the hamming weight, how many good packets did we receive? just count
+ * the 1's. The inner loop uses the Kernighan algorithm, see
+ * http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan
+ */
+int bit_packet_count(TYPE_OF_WORD *seq_bits)
+{
+	int i, hamming = 0;
+	TYPE_OF_WORD word;
+
+	for (i = 0; i < NUM_WORDS; i++) {
+		word = seq_bits[i];
+
+		while (word) {
+			word &= word-1;
+			hamming++;
+		}
+	}
+	return hamming;
+}

+ 45 - 0
drivers/staging/batman-adv/bitarray.h

@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2006-2009 B.A.T.M.A.N. contributors:
+ *
+ * Simon Wunderlich, Marek Lindner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+
+/* you should choose something big, if you don't want to waste cpu */
+#define TYPE_OF_WORD unsigned long
+#define WORD_BIT_SIZE (sizeof(TYPE_OF_WORD) * 8)
+
+/* returns true if the corresponding bit in the given seq_bits indicates true
+ * and curr_seqno is within range of last_seqno */
+uint8_t get_bit_status(TYPE_OF_WORD *seq_bits, uint16_t last_seqno,
+					   uint16_t curr_seqno);
+
+/* turn corresponding bit on, so we can remember that we got the packet */
+void bit_mark(TYPE_OF_WORD *seq_bits, int32_t n);
+
+/* shift the packet array by n places. */
+void bit_shift(TYPE_OF_WORD *seq_bits, int32_t n);
+
+
+/* receive and process one packet, returns 1 if received seq_num is considered
+ * new, 0 if old  */
+char bit_get_packet(TYPE_OF_WORD *seq_bits, int16_t seq_num_diff,
+					int8_t set_mark);
+
+/* count the hamming weight, how many good packets did we receive? */
+int  bit_packet_count(TYPE_OF_WORD *seq_bits);

+ 75 - 0
drivers/staging/batman-adv/compat.h

@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ *
+ * This file contains macros for maintaining compatibility with older versions
+ * of the Linux kernel.
+ */
+
+#include <linux/version.h>	/* LINUX_VERSION_CODE */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
+
+#define skb_set_network_header(_skb, _offset) \
+	do { (_skb)->nh.raw = (_skb)->data + (_offset); } while (0)
+
+#define skb_reset_mac_header(_skb) \
+	do { (_skb)->mac.raw = (_skb)->data; } while (0)
+
+#define list_first_entry(ptr, type, member) \
+	list_entry((ptr)->next, type, member)
+
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) */
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
+
+#define device_create(_cls, _parent, _devt, _device, _fmt) \
+	class_device_create(_cls, _parent, _devt, _device, _fmt)
+
+#define device_destroy(_cls, _device) \
+	class_device_destroy(_cls, _device)
+
+#else
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
+
+#define device_create(_cls, _parent, _devt, _device, _fmt) \
+	device_create_drvdata(_cls, _parent, _devt, _device, _fmt)
+
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) */
+
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
+
+#define cancel_delayed_work_sync(wq) cancel_rearming_delayed_work(wq)
+
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
+#define strict_strtoul(cp, base, res) \
+	({ \
+	int ret = 0; \
+	char *endp; \
+	*res = simple_strtoul(cp, &endp, base); \
+	if (cp == endp) \
+		ret = -EINVAL; \
+	ret; \
+})
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) */

+ 337 - 0
drivers/staging/batman-adv/device.c

@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#include "main.h"
+#include "device.h"
+#include "log.h"
+#include "send.h"
+#include "types.h"
+#include "hash.h"
+
+#include "compat.h"
+
+static struct class *batman_class;
+
+static int Major;	/* Major number assigned to our device driver */
+
+static const struct file_operations fops = {
+	.open = bat_device_open,
+	.release = bat_device_release,
+	.read = bat_device_read,
+	.write = bat_device_write,
+	.poll = bat_device_poll,
+};
+
+static struct device_client *device_client_hash[256];
+
+void bat_device_init(void)
+{
+	int i;
+
+	for (i = 0; i < 256; i++)
+		device_client_hash[i] = NULL;
+}
+
+int bat_device_setup(void)
+{
+	int tmp_major;
+
+	if (Major)
+		return 1;
+
+	/* register our device - kernel assigns a free major number */
+	tmp_major = register_chrdev(0, DRIVER_DEVICE, &fops);
+	if (tmp_major < 0) {
+		debug_log(LOG_TYPE_WARN, "Registering the character device failed with %d\n",
+			  tmp_major);
+		return 0;
+	}
+
+	batman_class = class_create(THIS_MODULE, "batman-adv");
+
+	if (IS_ERR(batman_class)) {
+		debug_log(LOG_TYPE_WARN, "Could not register class 'batman-adv' \n");
+		return 0;
+	}
+
+	device_create(batman_class, NULL, MKDEV(tmp_major, 0), NULL,
+		      "batman-adv");
+
+	Major = tmp_major;
+	return 1;
+}
+
+void bat_device_destroy(void)
+{
+	if (!Major)
+		return;
+
+	device_destroy(batman_class, MKDEV(Major, 0));
+	class_destroy(batman_class);
+
+	/* Unregister the device */
+	unregister_chrdev(Major, DRIVER_DEVICE);
+
+	Major = 0;
+}
+
+int bat_device_open(struct inode *inode, struct file *file)
+{
+	unsigned int i;
+	struct device_client *device_client;
+
+	device_client = kmalloc(sizeof(struct device_client), GFP_KERNEL);
+
+	if (!device_client)
+		return -ENOMEM;
+
+	for (i = 0; i < 256; i++) {
+		if (!device_client_hash[i]) {
+			device_client_hash[i] = device_client;
+			break;
+		}
+	}
+
+	if (device_client_hash[i] != device_client) {
+		debug_log(LOG_TYPE_WARN, "Error - can't add another packet client: maximum number of clients reached \n");
+		kfree(device_client);
+		return -EXFULL;
+	}
+
+	INIT_LIST_HEAD(&device_client->queue_list);
+	device_client->queue_len = 0;
+	device_client->index = i;
+	device_client->lock = __SPIN_LOCK_UNLOCKED(device_client->lock);
+	init_waitqueue_head(&device_client->queue_wait);
+
+	file->private_data = device_client;
+
+	inc_module_count();
+	return 0;
+}
+
+int bat_device_release(struct inode *inode, struct file *file)
+{
+	struct device_client *device_client =
+		(struct device_client *)file->private_data;
+	struct device_packet *device_packet;
+	struct list_head *list_pos, *list_pos_tmp;
+
+	spin_lock(&device_client->lock);
+
+	/* for all packets in the queue ... */
+	list_for_each_safe(list_pos, list_pos_tmp, &device_client->queue_list) {
+		device_packet = list_entry(list_pos,
+					   struct device_packet, list);
+
+		list_del(list_pos);
+		kfree(device_packet);
+	}
+
+	device_client_hash[device_client->index] = NULL;
+	spin_unlock(&device_client->lock);
+
+	kfree(device_client);
+	dec_module_count();
+
+	return 0;
+}
+
+ssize_t bat_device_read(struct file *file, char __user *buf, size_t count,
+			loff_t *ppos)
+{
+	struct device_client *device_client =
+		(struct device_client *)file->private_data;
+	struct device_packet *device_packet;
+	int error;
+
+	if ((file->f_flags & O_NONBLOCK) && (device_client->queue_len == 0))
+		return -EAGAIN;
+
+	if ((!buf) || (count < sizeof(struct icmp_packet)))
+		return -EINVAL;
+
+	if (!access_ok(VERIFY_WRITE, buf, count))
+		return -EFAULT;
+
+	error = wait_event_interruptible(device_client->queue_wait,
+					 device_client->queue_len);
+
+	if (error)
+		return error;
+
+	spin_lock(&device_client->lock);
+
+	device_packet = list_first_entry(&device_client->queue_list,
+					 struct device_packet, list);
+	list_del(&device_packet->list);
+	device_client->queue_len--;
+
+	spin_unlock(&device_client->lock);
+
+	error = __copy_to_user(buf, &device_packet->icmp_packet,
+			       sizeof(struct icmp_packet));
+
+	kfree(device_packet);
+
+	if (error)
+		return error;
+
+	return sizeof(struct icmp_packet);
+}
+
+ssize_t bat_device_write(struct file *file, const char __user *buff,
+			 size_t len, loff_t *off)
+{
+	struct device_client *device_client =
+		(struct device_client *)file->private_data;
+	struct icmp_packet icmp_packet;
+	struct orig_node *orig_node;
+	struct batman_if *batman_if;
+
+	if (len < sizeof(struct icmp_packet)) {
+		debug_log(LOG_TYPE_NOTICE, "Error - can't send packet from char device: invalid packet size\n");
+		return -EINVAL;
+	}
+
+	if (!access_ok(VERIFY_READ, buff, sizeof(struct icmp_packet)))
+		return -EFAULT;
+
+	if (__copy_from_user(&icmp_packet, buff, sizeof(icmp_packet)))
+		return -EFAULT;
+
+	if (icmp_packet.packet_type != BAT_ICMP) {
+		debug_log(LOG_TYPE_NOTICE, "Error - can't send packet from char device: got bogus packet type (expected: BAT_ICMP)\n");
+		return -EINVAL;
+	}
+
+	if (icmp_packet.msg_type != ECHO_REQUEST) {
+		debug_log(LOG_TYPE_NOTICE, "Error - can't send packet from char device: got bogus message type (expected: ECHO_REQUEST)\n");
+		return -EINVAL;
+	}
+
+	icmp_packet.uid = device_client->index;
+
+	if (icmp_packet.version != COMPAT_VERSION) {
+		icmp_packet.msg_type = PARAMETER_PROBLEM;
+		icmp_packet.ttl = COMPAT_VERSION;
+		bat_device_add_packet(device_client, &icmp_packet);
+		goto out;
+	}
+
+	if (atomic_read(&module_state) != MODULE_ACTIVE)
+		goto dst_unreach;
+
+	spin_lock(&orig_hash_lock);
+	orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet.dst));
+
+	if (!orig_node)
+		goto unlock;
+
+	if (!orig_node->router)
+		goto unlock;
+
+	batman_if = orig_node->batman_if;
+
+	if (!batman_if)
+		goto unlock;
+
+	memcpy(icmp_packet.orig,
+	       batman_if->net_dev->dev_addr,
+	       ETH_ALEN);
+
+	send_raw_packet((unsigned char *)&icmp_packet,
+			sizeof(struct icmp_packet),
+			batman_if, orig_node->router->addr);
+
+	spin_unlock(&orig_hash_lock);
+	goto out;
+
+unlock:
+	spin_unlock(&orig_hash_lock);
+dst_unreach:
+	icmp_packet.msg_type = DESTINATION_UNREACHABLE;
+	bat_device_add_packet(device_client, &icmp_packet);
+out:
+	return len;
+}
+
+unsigned int bat_device_poll(struct file *file, poll_table *wait)
+{
+	struct device_client *device_client =
+		(struct device_client *)file->private_data;
+
+	poll_wait(file, &device_client->queue_wait, wait);
+
+	if (device_client->queue_len > 0)
+		return POLLIN | POLLRDNORM;
+
+	return 0;
+}
+
+void bat_device_add_packet(struct device_client *device_client,
+			   struct icmp_packet *icmp_packet)
+{
+	struct device_packet *device_packet;
+
+	device_packet = kmalloc(sizeof(struct device_packet), GFP_KERNEL);
+
+	if (!device_packet)
+		return;
+
+	INIT_LIST_HEAD(&device_packet->list);
+	memcpy(&device_packet->icmp_packet, icmp_packet,
+	       sizeof(struct icmp_packet));
+
+	spin_lock(&device_client->lock);
+
+	/* while waiting for the lock the device_client could have been
+	 * deleted */
+	if (!device_client_hash[icmp_packet->uid]) {
+		spin_unlock(&device_client->lock);
+		kfree(device_packet);
+		return;
+	}
+
+	list_add_tail(&device_packet->list, &device_client->queue_list);
+	device_client->queue_len++;
+
+	if (device_client->queue_len > 100) {
+		device_packet = list_first_entry(&device_client->queue_list,
+						 struct device_packet, list);
+
+		list_del(&device_packet->list);
+		kfree(device_packet);
+		device_client->queue_len--;
+	}
+
+	spin_unlock(&device_client->lock);
+
+	wake_up(&device_client->queue_wait);
+}
+
+void bat_device_receive_packet(struct icmp_packet *icmp_packet)
+{
+	struct device_client *hash = device_client_hash[icmp_packet->uid];
+
+	if (hash)
+		bat_device_add_packet(hash, icmp_packet);
+}

+ 36 - 0
drivers/staging/batman-adv/device.h

@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#include "types.h"
+
+void bat_device_init(void);
+int bat_device_setup(void);
+void bat_device_destroy(void);
+int bat_device_open(struct inode *inode, struct file *file);
+int bat_device_release(struct inode *inode, struct file *file);
+ssize_t bat_device_read(struct file *file, char __user *buf, size_t count,
+			loff_t *ppos);
+ssize_t bat_device_write(struct file *file, const char __user *buff,
+			 size_t len, loff_t *off);
+unsigned int bat_device_poll(struct file *file, poll_table *wait);
+void bat_device_add_packet(struct device_client *device_client,
+			   struct icmp_packet *icmp_packet);
+void bat_device_receive_packet(struct icmp_packet *icmp_packet);

+ 451 - 0
drivers/staging/batman-adv/hard-interface.c

@@ -0,0 +1,451 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#include "main.h"
+#include "hard-interface.h"
+#include "log.h"
+#include "soft-interface.h"
+#include "send.h"
+#include "translation-table.h"
+#include "routing.h"
+#include "hash.h"
+#include "compat.h"
+
+#define MIN(x, y) ((x) < (y) ? (x) : (y))
+
+static char avail_ifs;
+static char active_ifs;
+
+static void hardif_free_interface(struct rcu_head *rcu);
+
+static struct batman_if *get_batman_if_by_name(char *name)
+{
+	struct batman_if *batman_if;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(batman_if, &if_list, list) {
+		if (strncmp(batman_if->dev, name, IFNAMSIZ) == 0)
+			goto out;
+	}
+
+	batman_if = NULL;
+
+out:
+	rcu_read_unlock();
+	return batman_if;
+}
+
+int hardif_min_mtu(void)
+{
+	struct batman_if *batman_if;
+	/* allow big frames if all devices are capable to do so
+	 * (have MTU > 1500 + BAT_HEADER_LEN) */
+	int min_mtu = ETH_DATA_LEN;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(batman_if, &if_list, list) {
+		if ((batman_if->if_active == IF_ACTIVE) ||
+		    (batman_if->if_active == IF_TO_BE_ACTIVATED))
+			min_mtu = MIN(batman_if->net_dev->mtu - BAT_HEADER_LEN,
+				      min_mtu);
+	}
+	rcu_read_unlock();
+
+	return min_mtu;
+}
+
+static void check_known_mac_addr(uint8_t *addr)
+{
+	struct batman_if *batman_if;
+	char mac_string[ETH_STR_LEN];
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(batman_if, &if_list, list) {
+		if ((batman_if->if_active != IF_ACTIVE) &&
+		    (batman_if->if_active != IF_TO_BE_ACTIVATED))
+			continue;
+
+		if (!compare_orig(batman_if->net_dev->dev_addr, addr))
+			continue;
+
+		addr_to_string(mac_string, addr);
+		debug_log(LOG_TYPE_WARN, "The newly added mac address (%s) already exists on: %s\n",
+		          mac_string, batman_if->dev);
+		debug_log(LOG_TYPE_WARN, "It is strongly recommended to keep mac addresses unique to avoid problems!\n");
+	}
+	rcu_read_unlock();
+}
+
+/* adjusts the MTU if a new interface with a smaller MTU appeared. */
+void update_min_mtu(void)
+{
+	int min_mtu;
+
+	min_mtu = hardif_min_mtu();
+	if (soft_device->mtu != min_mtu)
+		soft_device->mtu = min_mtu;
+}
+
+/* checks if the interface is up. (returns 1 if it is) */
+static int hardif_is_interface_up(char *dev)
+{
+	struct net_device *net_dev;
+
+	/**
+	 * if we already have an interface in our interface list and
+	 * the current interface is not the primary interface and
+	 * the primary interface is not up and
+	 * the primary interface has never been up - don't activate any
+	 * secondary interface !
+	 */
+
+	rcu_read_lock();
+	if ((!list_empty(&if_list)) &&
+	    strncmp(((struct batman_if *)if_list.next)->dev, dev, IFNAMSIZ) &&
+	    !(((struct batman_if *)if_list.next)->if_active == IF_ACTIVE) &&
+	    !(((struct batman_if *)if_list.next)->if_active == IF_TO_BE_ACTIVATED) &&
+	    (!main_if_was_up())) {
+		rcu_read_unlock();
+		goto end;
+	}
+	rcu_read_unlock();
+
+#ifdef __NET_NET_NAMESPACE_H
+	net_dev = dev_get_by_name(&init_net, dev);
+#else
+	net_dev = dev_get_by_name(dev);
+#endif
+	if (!net_dev)
+		goto end;
+
+	if (!(net_dev->flags & IFF_UP))
+		goto failure;
+
+	dev_put(net_dev);
+	return 1;
+
+failure:
+	dev_put(net_dev);
+end:
+	return 0;
+}
+
+/* deactivates the interface. */
+void hardif_deactivate_interface(struct batman_if *batman_if)
+{
+	if (batman_if->if_active != IF_ACTIVE)
+		return;
+
+	if (batman_if->raw_sock)
+		sock_release(batman_if->raw_sock);
+
+	/**
+	 * batman_if->net_dev has been acquired by dev_get_by_name() in
+	 * proc_interfaces_write() and has to be unreferenced.
+	 */
+
+	if (batman_if->net_dev)
+		dev_put(batman_if->net_dev);
+
+	batman_if->raw_sock = NULL;
+	batman_if->net_dev = NULL;
+
+	batman_if->if_active = IF_INACTIVE;
+	active_ifs--;
+
+	debug_log(LOG_TYPE_NOTICE, "Interface deactivated: %s\n",
+	          batman_if->dev);
+}
+
+/* (re)activate given interface. */
+static void hardif_activate_interface(struct batman_if *batman_if)
+{
+	struct sockaddr_ll bind_addr;
+	int retval;
+
+	if (batman_if->if_active != IF_INACTIVE)
+		return;
+
+#ifdef __NET_NET_NAMESPACE_H
+	batman_if->net_dev = dev_get_by_name(&init_net, batman_if->dev);
+#else
+	batman_if->net_dev = dev_get_by_name(batman_if->dev);
+#endif
+	if (!batman_if->net_dev)
+		goto dev_err;
+
+	retval = sock_create_kern(PF_PACKET, SOCK_RAW,
+				  __constant_htons(ETH_P_BATMAN),
+				  &batman_if->raw_sock);
+
+	if (retval < 0) {
+		debug_log(LOG_TYPE_WARN, "Can't create raw socket: %i\n",
+			  retval);
+		goto sock_err;
+	}
+
+	bind_addr.sll_family = AF_PACKET;
+	bind_addr.sll_ifindex = batman_if->net_dev->ifindex;
+	bind_addr.sll_protocol = 0;	/* is set by the kernel */
+
+	retval = kernel_bind(batman_if->raw_sock,
+			     (struct sockaddr *)&bind_addr, sizeof(bind_addr));
+
+	if (retval < 0) {
+		debug_log(LOG_TYPE_WARN, "Can't create bind raw socket: %i\n",
+			  retval);
+		goto bind_err;
+	}
+
+	check_known_mac_addr(batman_if->net_dev->dev_addr);
+
+	batman_if->raw_sock->sk->sk_user_data =
+		batman_if->raw_sock->sk->sk_data_ready;
+	batman_if->raw_sock->sk->sk_data_ready = batman_data_ready;
+
+	addr_to_string(batman_if->addr_str, batman_if->net_dev->dev_addr);
+
+	memcpy(((struct batman_packet *)(batman_if->packet_buff))->orig,
+	       batman_if->net_dev->dev_addr, ETH_ALEN);
+	memcpy(((struct batman_packet *)(batman_if->packet_buff))->prev_sender,
+	       batman_if->net_dev->dev_addr, ETH_ALEN);
+
+	batman_if->if_active = IF_TO_BE_ACTIVATED;
+	active_ifs++;
+
+	/* save the mac address if it is our primary interface */
+	if (batman_if->if_num == 0)
+		set_main_if_addr(batman_if->net_dev->dev_addr);
+
+	debug_log(LOG_TYPE_NOTICE, "Interface activated: %s\n",
+	          batman_if->dev);
+
+	return;
+
+bind_err:
+	sock_release(batman_if->raw_sock);
+sock_err:
+	dev_put(batman_if->net_dev);
+dev_err:
+	batman_if->raw_sock = NULL;
+	batman_if->net_dev = NULL;
+}
+
+static void hardif_free_interface(struct rcu_head *rcu)
+{
+	struct batman_if *batman_if = container_of(rcu, struct batman_if, rcu);
+
+	kfree(batman_if->packet_buff);
+	kfree(batman_if->dev);
+	kfree(batman_if);
+}
+
+/**
+ * called by
+ *  - echo '' > /proc/.../interfaces
+ *  - modprobe -r batman-adv-core
+ */
+/* removes and frees all interfaces */
+void hardif_remove_interfaces(void)
+{
+	struct batman_if *batman_if = NULL;
+
+	avail_ifs = 0;
+
+	/* no lock needed - we don't delete somewhere else */
+	list_for_each_entry(batman_if, &if_list, list) {
+
+		list_del_rcu(&batman_if->list);
+
+		/* first deactivate interface */
+		if (batman_if->if_active != IF_INACTIVE)
+			hardif_deactivate_interface(batman_if);
+
+		call_rcu(&batman_if->rcu, hardif_free_interface);
+	}
+}
+
+static int resize_orig(struct orig_node *orig_node, int if_num)
+{
+	void *data_ptr;
+
+	data_ptr = kmalloc((if_num + 1) * sizeof(TYPE_OF_WORD) * NUM_WORDS,
+			   GFP_ATOMIC);
+	if (!data_ptr) {
+		debug_log(LOG_TYPE_WARN, "Can't resize orig: out of memory\n");
+		return -1;
+	}
+
+	memcpy(data_ptr, orig_node->bcast_own,
+	       if_num * sizeof(TYPE_OF_WORD) * NUM_WORDS);
+	kfree(orig_node->bcast_own);
+	orig_node->bcast_own = data_ptr;
+
+	data_ptr = kmalloc((if_num + 1) * sizeof(uint8_t), GFP_ATOMIC);
+	if (!data_ptr) {
+		debug_log(LOG_TYPE_WARN, "Can't resize orig: out of memory\n");
+		return -1;
+	}
+
+	memcpy(data_ptr, orig_node->bcast_own_sum, if_num * sizeof(uint8_t));
+	kfree(orig_node->bcast_own_sum);
+	orig_node->bcast_own_sum = data_ptr;
+
+	return 0;
+}
+
+
+/* adds an interface the interface list and activate it, if possible */
+int hardif_add_interface(char *dev, int if_num)
+{
+	struct batman_if *batman_if;
+	struct batman_packet *batman_packet;
+	struct orig_node *orig_node;
+	struct hash_it_t *hashit = NULL;
+
+	batman_if = kmalloc(sizeof(struct batman_if), GFP_KERNEL);
+
+	if (!batman_if) {
+		debug_log(LOG_TYPE_WARN, "Can't add interface (%s): out of memory\n", dev);
+		return -1;
+	}
+
+	batman_if->raw_sock = NULL;
+	batman_if->net_dev = NULL;
+
+	if ((if_num == 0) && (num_hna > 0))
+		batman_if->packet_len = BAT_PACKET_LEN + num_hna * ETH_ALEN;
+	else
+		batman_if->packet_len = BAT_PACKET_LEN;
+
+	batman_if->packet_buff = kmalloc(batman_if->packet_len, GFP_KERNEL);
+
+	if (!batman_if->packet_buff) {
+		debug_log(LOG_TYPE_WARN, "Can't add interface packet (%s): out of memory\n", dev);
+		goto out;
+	}
+
+	batman_if->if_num = if_num;
+	batman_if->dev = dev;
+	batman_if->if_active = IF_INACTIVE;
+	INIT_RCU_HEAD(&batman_if->rcu);
+
+	debug_log(LOG_TYPE_NOTICE, "Adding interface: %s\n", dev);
+	avail_ifs++;
+
+	INIT_LIST_HEAD(&batman_if->list);
+
+	batman_packet = (struct batman_packet *)(batman_if->packet_buff);
+	batman_packet->packet_type = BAT_PACKET;
+	batman_packet->version = COMPAT_VERSION;
+	batman_packet->flags = 0x00;
+	batman_packet->ttl = (batman_if->if_num > 0 ? 2 : TTL);
+	batman_packet->flags = 0;
+	batman_packet->tq = TQ_MAX_VALUE;
+	batman_packet->num_hna = 0;
+
+	if (batman_if->packet_len != BAT_PACKET_LEN) {
+		unsigned char *hna_buff;
+		int hna_len;
+
+		hna_buff = batman_if->packet_buff + BAT_PACKET_LEN;
+		hna_len = batman_if->packet_len - BAT_PACKET_LEN;
+		batman_packet->num_hna = hna_local_fill_buffer(hna_buff,
+							       hna_len);
+	}
+
+	atomic_set(&batman_if->seqno, 1);
+
+	/* resize all orig nodes because orig_node->bcast_own(_sum) depend on
+	 * if_num */
+	spin_lock(&orig_hash_lock);
+
+	while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
+		orig_node = hashit->bucket->data;
+		if (resize_orig(orig_node, if_num) == -1) {
+			spin_unlock(&orig_hash_lock);
+			goto out;
+		}
+	}
+
+	spin_unlock(&orig_hash_lock);
+
+	if (!hardif_is_interface_up(batman_if->dev))
+		debug_log(LOG_TYPE_WARN, "Not using interface %s (retrying later): interface not active\n", batman_if->dev);
+	else
+		hardif_activate_interface(batman_if);
+
+	list_add_tail_rcu(&batman_if->list, &if_list);
+
+	/* begin sending originator messages on that interface */
+	schedule_own_packet(batman_if);
+	return 1;
+
+out:
+	if (batman_if->packet_buff)
+		kfree(batman_if->packet_buff);
+	kfree(batman_if);
+	kfree(dev);
+	return -1;
+}
+
+char hardif_get_active_if_num(void)
+{
+	return active_ifs;
+}
+
+static int hard_if_event(struct notifier_block *this,
+                            unsigned long event, void *ptr)
+{
+	struct net_device *dev = (struct net_device *)ptr;
+	struct batman_if *batman_if = get_batman_if_by_name(dev->name);
+
+	if (!batman_if)
+		goto out;
+
+	switch (event) {
+	case NETDEV_GOING_DOWN:
+	case NETDEV_DOWN:
+	case NETDEV_UNREGISTER:
+		hardif_deactivate_interface(batman_if);
+		break;
+	case NETDEV_UP:
+		hardif_activate_interface(batman_if);
+		if ((atomic_read(&module_state) == MODULE_INACTIVE) &&
+		    (hardif_get_active_if_num() > 0)) {
+			activate_module();
+		}
+		break;
+	/* NETDEV_CHANGEADDR - mac address change - what are we doing here ? */
+	default:
+		/* debug_log(LOG_TYPE_CRIT, "hard_if_event: %s %i\n", dev->name, event); */
+		break;
+	};
+
+	update_min_mtu();
+
+out:
+	return NOTIFY_DONE;
+}
+
+struct notifier_block hard_if_notifier = {
+        .notifier_call = hard_if_event,
+};

+ 36 - 0
drivers/staging/batman-adv/hard-interface.h

@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#define IF_INACTIVE 0
+#define IF_ACTIVE 1
+/* #define IF_TO_BE_DEACTIVATED 2 - not needed anymore */
+#define IF_TO_BE_ACTIVATED 3
+
+extern struct notifier_block hard_if_notifier;
+
+void hardif_remove_interfaces(void);
+int hardif_add_interface(char *dev, int if_num);
+void hardif_deactivate_interface(struct batman_if *batman_if);
+char hardif_get_active_if_num(void);
+void hardif_check_interfaces_status(void);
+void hardif_check_interfaces_status_wq(struct work_struct *work);
+int hardif_min_mtu(void);
+void update_min_mtu(void);

+ 313 - 0
drivers/staging/batman-adv/hash.c

@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2006-2009 B.A.T.M.A.N. contributors:
+ *
+ * Simon Wunderlich, Marek Lindner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#include "main.h"
+#include "hash.h"
+
+/* clears the hash */
+void hash_init(struct hashtable_t *hash)
+{
+	int i;
+
+	hash->elements = 0;
+
+	for (i = 0 ; i < hash->size; i++)
+		hash->table[i] = NULL;
+}
+
+/* remove the hash structure. if hashdata_free_cb != NULL, this function will be
+ * called to remove the elements inside of the hash.  if you don't remove the
+ * elements, memory might be leaked. */
+void hash_delete(struct hashtable_t *hash, hashdata_free_cb free_cb)
+{
+	struct element_t *bucket, *last_bucket;
+	int i;
+
+	for (i = 0; i < hash->size; i++) {
+		bucket = hash->table[i];
+
+		while (bucket != NULL) {
+			if (free_cb != NULL)
+				free_cb(bucket->data);
+
+			last_bucket = bucket;
+			bucket = bucket->next;
+			kfree(last_bucket);
+		}
+	}
+
+	hash_destroy(hash);
+}
+
+/* free only the hashtable and the hash itself. */
+void hash_destroy(struct hashtable_t *hash)
+{
+	kfree(hash->table);
+	kfree(hash);
+}
+
+/* iterate though the hash. first element is selected with iter_in NULL.  use
+ * the returned iterator to access the elements until hash_it_t returns NULL. */
+struct hash_it_t *hash_iterate(struct hashtable_t *hash,
+			       struct hash_it_t *iter_in)
+{
+	struct hash_it_t *iter;
+
+	if (!hash)
+		return NULL;
+
+	if (iter_in == NULL) {
+		iter = kmalloc(sizeof(struct hash_it_t), GFP_ATOMIC);
+		iter->index = -1;
+		iter->bucket = NULL;
+		iter->prev_bucket = NULL;
+	} else {
+		iter = iter_in;
+	}
+
+	/* sanity checks first (if our bucket got deleted in the last
+	 * iteration): */
+	if (iter->bucket != NULL) {
+		if (iter->first_bucket != NULL) {
+			/* we're on the first element and it got removed after
+			 * the last iteration. */
+			if ((*iter->first_bucket) != iter->bucket) {
+				/* there are still other elements in the list */
+				if ((*iter->first_bucket) != NULL) {
+					iter->prev_bucket = NULL;
+					iter->bucket = (*iter->first_bucket);
+					iter->first_bucket =
+						&hash->table[iter->index];
+					return iter;
+				} else {
+					iter->bucket = NULL;
+				}
+			}
+		} else if (iter->prev_bucket != NULL) {
+			/*
+			* we're not on the first element, and the bucket got
+			* removed after the last iteration.  the last bucket's
+			* next pointer is not pointing to our actual bucket
+			* anymore.  select the next.
+			*/
+			if (iter->prev_bucket->next != iter->bucket)
+				iter->bucket = iter->prev_bucket;
+		}
+	}
+
+	/* now as we are sane, select the next one if there is some */
+	if (iter->bucket != NULL) {
+		if (iter->bucket->next != NULL) {
+			iter->prev_bucket = iter->bucket;
+			iter->bucket = iter->bucket->next;
+			iter->first_bucket = NULL;
+			return iter;
+		}
+	}
+
+	/* if not returned yet, we've reached the last one on the index and have
+	 * to search forward */
+	iter->index++;
+	/* go through the entries of the hash table */
+	while (iter->index < hash->size) {
+		if ((hash->table[iter->index]) != NULL) {
+			iter->prev_bucket = NULL;
+			iter->bucket = hash->table[iter->index];
+			iter->first_bucket = &hash->table[iter->index];
+			return iter;
+		} else {
+			iter->index++;
+		}
+	}
+
+	/* nothing to iterate over anymore */
+	kfree(iter);
+	return NULL;
+}
+
+/* allocates and clears the hash */
+struct hashtable_t *hash_new(int size, hashdata_compare_cb compare,
+			     hashdata_choose_cb choose)
+{
+	struct hashtable_t *hash;
+
+	hash = kmalloc(sizeof(struct hashtable_t) , GFP_ATOMIC);
+
+	if (hash == NULL)
+		return NULL;
+
+	hash->size = size;
+	hash->table = kmalloc(sizeof(struct element_t *) * size, GFP_ATOMIC);
+
+	if (hash->table == NULL) {
+		kfree(hash);
+		return NULL;
+	}
+
+	hash_init(hash);
+
+	hash->compare = compare;
+	hash->choose = choose;
+
+	return hash;
+}
+
+/* adds data to the hashtable. returns 0 on success, -1 on error */
+int hash_add(struct hashtable_t *hash, void *data)
+{
+	int index;
+	struct element_t *bucket, *prev_bucket = NULL;
+
+	if (!hash)
+		return -1;
+
+	index = hash->choose(data, hash->size);
+	bucket = hash->table[index];
+
+	while (bucket != NULL) {
+		if (hash->compare(bucket->data, data))
+			return -1;
+
+		prev_bucket = bucket;
+		bucket = bucket->next;
+	}
+
+	/* found the tail of the list, add new element */
+	bucket = kmalloc(sizeof(struct element_t), GFP_ATOMIC);
+
+	if (bucket == NULL)
+		return -1;
+
+	bucket->data = data;
+	bucket->next = NULL;
+
+	/* and link it */
+	if (prev_bucket == NULL)
+		hash->table[index] = bucket;
+	else
+		prev_bucket->next = bucket;
+
+	hash->elements++;
+	return 0;
+}
+
+/* finds data, based on the key in keydata. returns the found data on success,
+ * or NULL on error */
+void *hash_find(struct hashtable_t *hash, void *keydata)
+{
+	int index;
+	struct element_t *bucket;
+
+	if (!hash)
+		return NULL;
+
+	index = hash->choose(keydata , hash->size);
+	bucket = hash->table[index];
+
+	while (bucket != NULL) {
+		if (hash->compare(bucket->data, keydata))
+			return bucket->data;
+
+		bucket = bucket->next;
+	}
+
+	return NULL;
+}
+
+/* remove bucket (this might be used in hash_iterate() if you already found the
+ * bucket you want to delete and don't need the overhead to find it again with
+ * hash_remove(). But usually, you don't want to use this function, as it
+ * fiddles with hash-internals. */
+void *hash_remove_bucket(struct hashtable_t *hash, struct hash_it_t *hash_it_t)
+{
+	void *data_save;
+
+	data_save = hash_it_t->bucket->data;
+
+	if (hash_it_t->prev_bucket != NULL)
+		hash_it_t->prev_bucket->next = hash_it_t->bucket->next;
+	else if (hash_it_t->first_bucket != NULL)
+		(*hash_it_t->first_bucket) = hash_it_t->bucket->next;
+
+	kfree(hash_it_t->bucket);
+	hash->elements--;
+
+	return data_save;
+}
+
+/* removes data from hash, if found. returns pointer do data on success, so you
+ * can remove the used structure yourself, or NULL on error .  data could be the
+ * structure you use with just the key filled, we just need the key for
+ * comparing. */
+void *hash_remove(struct hashtable_t *hash, void *data)
+{
+	struct hash_it_t hash_it_t;
+
+	hash_it_t.index = hash->choose(data, hash->size);
+	hash_it_t.bucket = hash->table[hash_it_t.index];
+	hash_it_t.prev_bucket = NULL;
+
+	while (hash_it_t.bucket != NULL) {
+		if (hash->compare(hash_it_t.bucket->data, data)) {
+			hash_it_t.first_bucket =
+				(hash_it_t.bucket ==
+				 hash->table[hash_it_t.index] ?
+				 &hash->table[hash_it_t.index] : NULL);
+			return hash_remove_bucket(hash, &hash_it_t);
+		}
+
+		hash_it_t.prev_bucket = hash_it_t.bucket;
+		hash_it_t.bucket = hash_it_t.bucket->next;
+	}
+
+	return NULL;
+}
+
+/* resize the hash, returns the pointer to the new hash or NULL on
+ * error. removes the old hash on success. */
+struct hashtable_t *hash_resize(struct hashtable_t *hash, int size)
+{
+	struct hashtable_t *new_hash;
+	struct element_t *bucket;
+	int i;
+
+	/* initialize a new hash with the new size */
+	new_hash = hash_new(size, hash->compare, hash->choose);
+
+	if (new_hash == NULL)
+		return NULL;
+
+	/* copy the elements */
+	for (i = 0; i < hash->size; i++) {
+		bucket = hash->table[i];
+
+		while (bucket != NULL) {
+			hash_add(new_hash, bucket->data);
+			bucket = bucket->next;
+		}
+	}
+
+	/* remove hash and eventual overflow buckets but not the content
+	 * itself. */
+	hash_delete(hash, NULL);
+
+	return new_hash;
+}

+ 99 - 0
drivers/staging/batman-adv/hash.h

@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2006-2009 B.A.T.M.A.N. contributors:
+ *
+ * Simon Wunderlich, Marek Lindner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#ifndef _BATMAN_HASH_H
+#define _BATMAN_HASH_H
+
+typedef int (*hashdata_compare_cb)(void *, void *);
+typedef int (*hashdata_choose_cb)(void *, int);
+typedef void (*hashdata_free_cb)(void *);
+
+struct element_t {
+	void *data;		/* pointer to the data */
+	struct element_t *next;	/* overflow bucket pointer */
+};
+
+struct hash_it_t {
+	int index;
+	struct element_t *bucket;
+	struct element_t *prev_bucket;
+	struct element_t **first_bucket;
+};
+
+struct hashtable_t {
+	struct element_t **table;   /* the hashtable itself, with the buckets */
+	int elements;		    /* number of elements registered */
+	int size;		    /* size of hashtable */
+	hashdata_compare_cb compare;/* callback to a compare function.  should
+				     * compare 2 element datas for their keys,
+				     * return 0 if same and not 0 if not
+				     * same */
+	hashdata_choose_cb choose;  /* the hashfunction, should return an index
+				     * based on the key in the data of the first
+				     * argument and the size the second */
+};
+
+/* clears the hash */
+void hash_init(struct hashtable_t *hash);
+
+/* allocates and clears the hash */
+struct hashtable_t *hash_new(int size, hashdata_compare_cb compare,
+			     hashdata_choose_cb choose);
+
+/* remove bucket (this might be used in hash_iterate() if you already found the
+ * bucket you want to delete and don't need the overhead to find it again with
+ * hash_remove().  But usually, you don't want to use this function, as it
+ * fiddles with hash-internals. */
+void *hash_remove_bucket(struct hashtable_t *hash, struct hash_it_t *hash_it_t);
+
+/* remove the hash structure. if hashdata_free_cb != NULL, this function will be
+ * called to remove the elements inside of the hash.  if you don't remove the
+ * elements, memory might be leaked. */
+void hash_delete(struct hashtable_t *hash, hashdata_free_cb free_cb);
+
+/* free only the hashtable and the hash itself. */
+void hash_destroy(struct hashtable_t *hash);
+
+/* adds data to the hashtable. returns 0 on success, -1 on error */
+int hash_add(struct hashtable_t *hash, void *data);
+
+/* removes data from hash, if found. returns pointer do data on success, so you
+ * can remove the used structure yourself, or NULL on error .  data could be the
+ * structure you use with just the key filled, we just need the key for
+ * comparing. */
+void *hash_remove(struct hashtable_t *hash, void *data);
+
+/* finds data, based on the key in keydata. returns the found data on success,
+ * or NULL on error */
+void *hash_find(struct hashtable_t *hash, void *keydata);
+
+/* resize the hash, returns the pointer to the new hash or NULL on
+ * error. removes the old hash on success */
+struct hashtable_t *hash_resize(struct hashtable_t *hash, int size);
+
+/* iterate though the hash. first element is selected with iter_in NULL.  use
+ * the returned iterator to access the elements until hash_it_t returns NULL. */
+struct hash_it_t *hash_iterate(struct hashtable_t *hash,
+			       struct hash_it_t *iter_in);
+
+/* print the hash table for debugging */
+void hash_debug(struct hashtable_t *hash);
+#endif

+ 179 - 0
drivers/staging/batman-adv/log.c

@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#include "main.h"
+#include "log.h"
+
+#define LOG_BUF_MASK (log_buf_len-1)
+#define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK])
+
+static char log_buf[LOG_BUF_LEN];
+static int log_buf_len = LOG_BUF_LEN;
+static unsigned long log_start;
+static unsigned long log_end;
+uint8_t log_level;
+
+static DEFINE_SPINLOCK(logbuf_lock);
+
+const struct file_operations proc_log_operations = {
+	.open           = log_open,
+	.release        = log_release,
+	.read           = log_read,
+	.write          = log_write,
+	.poll           = log_poll,
+};
+
+static DECLARE_WAIT_QUEUE_HEAD(log_wait);
+
+static void emit_log_char(char c)
+{
+	LOG_BUF(log_end) = c;
+	log_end++;
+
+	if (log_end - log_start > log_buf_len)
+		log_start = log_end - log_buf_len;
+}
+
+static int fdebug_log(char *fmt, ...)
+{
+	int printed_len;
+	char *p;
+	va_list args;
+	static char debug_log_buf[256];
+	unsigned long flags;
+
+	spin_lock_irqsave(&logbuf_lock, flags);
+	va_start(args, fmt);
+	printed_len = vscnprintf(debug_log_buf, sizeof(debug_log_buf), fmt,
+				 args);
+	va_end(args);
+
+	for (p = debug_log_buf; *p != 0; p++)
+		emit_log_char(*p);
+
+	spin_unlock_irqrestore(&logbuf_lock, flags);
+
+	wake_up(&log_wait);
+
+	return 0;
+}
+
+int debug_log(int type, char *fmt, ...)
+{
+	va_list args;
+	int retval = 0;
+	char tmp_log_buf[256];
+
+	/* only critical information get into the official kernel log */
+	if (type == LOG_TYPE_CRIT) {
+		va_start(args, fmt);
+		vscnprintf(tmp_log_buf, sizeof(tmp_log_buf), fmt, args);
+		printk(KERN_ERR "batman-adv: %s", tmp_log_buf);
+		va_end(args);
+	}
+
+	if ((type == LOG_TYPE_CRIT) || (log_level & type)) {
+		va_start(args, fmt);
+		vscnprintf(tmp_log_buf, sizeof(tmp_log_buf), fmt, args);
+		fdebug_log("[%10u] %s", (jiffies / HZ), tmp_log_buf);
+		va_end(args);
+	}
+
+	return retval;
+}
+
+int log_open(struct inode *inode, struct file *file)
+{
+	inc_module_count();
+	return 0;
+}
+
+int log_release(struct inode *inode, struct file *file)
+{
+	dec_module_count();
+	return 0;
+}
+
+ssize_t log_read(struct file *file, char __user *buf, size_t count,
+		 loff_t *ppos)
+{
+	int error, i = 0;
+	char c;
+	unsigned long flags;
+
+	if ((file->f_flags & O_NONBLOCK) && !(log_end - log_start))
+		return -EAGAIN;
+
+	if ((!buf) || (count < 0))
+		return -EINVAL;
+
+	if (count == 0)
+		return 0;
+
+	if (!access_ok(VERIFY_WRITE, buf, count))
+		return -EFAULT;
+
+	error = wait_event_interruptible(log_wait, (log_start - log_end));
+
+	if (error)
+		return error;
+
+	spin_lock_irqsave(&logbuf_lock, flags);
+
+	while ((!error) && (log_start != log_end) && (i < count)) {
+		c = LOG_BUF(log_start);
+
+		log_start++;
+
+		spin_unlock_irqrestore(&logbuf_lock, flags);
+
+		error = __put_user(c, buf);
+
+		spin_lock_irqsave(&logbuf_lock, flags);
+
+		buf++;
+		i++;
+
+	}
+
+	spin_unlock_irqrestore(&logbuf_lock, flags);
+
+	if (!error)
+		return i;
+
+	return error;
+}
+
+ssize_t log_write(struct file *file, const char __user *buf, size_t count,
+		  loff_t *ppos)
+{
+	return count;
+}
+
+unsigned int log_poll(struct file *file, poll_table *wait)
+{
+	poll_wait(file, &log_wait, wait);
+
+	if (log_end - log_start)
+		return POLLIN | POLLRDNORM;
+
+	return 0;
+}

+ 32 - 0
drivers/staging/batman-adv/log.h

@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+extern const struct file_operations proc_log_operations;
+extern uint8_t log_level;
+
+int debug_log(int type, char *fmt, ...);
+int log_open(struct inode *inode, struct file *file);
+int log_release(struct inode *inode, struct file *file);
+ssize_t log_read(struct file *file, char __user *buf, size_t count,
+		 loff_t *ppos);
+ssize_t log_write(struct file *file, const char __user *buf, size_t count,
+		  loff_t *ppos);
+unsigned int log_poll(struct file *file, poll_table *wait);

+ 286 - 0
drivers/staging/batman-adv/main.c

@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#include "main.h"
+#include "proc.h"
+#include "log.h"
+#include "routing.h"
+#include "send.h"
+#include "soft-interface.h"
+#include "device.h"
+#include "translation-table.h"
+#include "hard-interface.h"
+#include "types.h"
+#include "vis.h"
+#include "hash.h"
+#include "compat.h"
+
+struct list_head if_list;
+struct hlist_head forw_bat_list;
+struct hlist_head forw_bcast_list;
+struct hashtable_t *orig_hash;
+
+DEFINE_SPINLOCK(orig_hash_lock);
+DEFINE_SPINLOCK(forw_bat_list_lock);
+DEFINE_SPINLOCK(forw_bcast_list_lock);
+
+atomic_t originator_interval;
+atomic_t vis_interval;
+atomic_t aggregation_enabled;
+int16_t num_hna;
+int16_t num_ifs;
+
+struct net_device *soft_device;
+
+static struct task_struct *kthread_task;
+
+unsigned char broadcastAddr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+atomic_t module_state;
+
+struct workqueue_struct *bat_event_workqueue;
+
+int init_module(void)
+{
+	int retval;
+
+	INIT_LIST_HEAD(&if_list);
+	INIT_HLIST_HEAD(&forw_bat_list);
+	INIT_HLIST_HEAD(&forw_bcast_list);
+
+	atomic_set(&module_state, MODULE_INACTIVE);
+
+	atomic_set(&originator_interval, 1000);
+	atomic_set(&vis_interval, 1000);/* TODO: raise this later, this is only
+					 * for debugging now. */
+	atomic_set(&aggregation_enabled, 1);
+
+	/* the name should not be longer than 10 chars - see
+	 * http://lwn.net/Articles/23634/ */
+	bat_event_workqueue = create_singlethread_workqueue("bat_events");
+
+	if (!bat_event_workqueue)
+		return -ENOMEM;
+
+	retval = setup_procfs();
+	if (retval < 0)
+		return retval;
+
+	bat_device_init();
+
+	/* initialize layer 2 interface */
+	soft_device = alloc_netdev(sizeof(struct bat_priv) , "bat%d",
+				   interface_setup);
+
+	if (!soft_device) {
+		debug_log(LOG_TYPE_CRIT, "Unable to allocate the batman interface\n");
+		goto end;
+	}
+
+	retval = register_netdev(soft_device);
+
+	if (retval < 0) {
+		debug_log(LOG_TYPE_CRIT, "Unable to register the batman interface: %i\n", retval);
+		goto free_soft_device;
+	}
+
+	register_netdevice_notifier(&hard_if_notifier);
+
+	debug_log(LOG_TYPE_CRIT, "B.A.T.M.A.N. advanced %s%s (compatibility version %i) loaded \n",
+	          SOURCE_VERSION, REVISION_VERSION_STR, COMPAT_VERSION);
+
+	return 0;
+
+free_soft_device:
+	free_netdev(soft_device);
+	soft_device = NULL;
+end:
+	return -ENOMEM;
+}
+
+void cleanup_module(void)
+{
+	shutdown_module();
+
+	if (soft_device) {
+		unregister_netdev(soft_device);
+		soft_device = NULL;
+	}
+
+	unregister_netdevice_notifier(&hard_if_notifier);
+	cleanup_procfs();
+
+	destroy_workqueue(bat_event_workqueue);
+	bat_event_workqueue = NULL;
+}
+
+/* activates the module, creates bat device, starts timer ... */
+void activate_module(void)
+{
+	if (originator_init() < 1)
+		goto err;
+
+	if (hna_local_init() < 1)
+		goto err;
+
+	if (hna_global_init() < 1)
+		goto err;
+
+	hna_local_add(soft_device->dev_addr);
+
+	if (bat_device_setup() < 1)
+		goto end;
+
+	if (vis_init() < 1)
+		goto err;
+
+	/* (re)start kernel thread for packet processing */
+	if (!kthread_task) {
+		kthread_task = kthread_run(packet_recv_thread, NULL, "batman-adv");
+
+		if (IS_ERR(kthread_task)) {
+			debug_log(LOG_TYPE_CRIT, "Unable to start packet receive thread\n");
+			kthread_task = NULL;
+		}
+	}
+
+	update_min_mtu();
+	atomic_set(&module_state, MODULE_ACTIVE);
+	goto end;
+
+err:
+	debug_log(LOG_TYPE_CRIT, "Unable to allocate memory for mesh information structures: out of mem ?\n");
+	shutdown_module();
+end:
+	return;
+}
+
+/* shuts down the whole module.*/
+void shutdown_module(void)
+{
+	atomic_set(&module_state, MODULE_DEACTIVATING);
+
+	purge_outstanding_packets();
+	flush_workqueue(bat_event_workqueue);
+
+	vis_quit();
+
+	/* deactivate kernel thread for packet processing (if running) */
+	if (kthread_task) {
+		atomic_set(&exit_cond, 1);
+		wake_up_interruptible(&thread_wait);
+		kthread_stop(kthread_task);
+
+		kthread_task = NULL;
+	}
+
+	originator_free();
+
+	hna_local_free();
+	hna_global_free();
+
+	synchronize_net();
+	bat_device_destroy();
+
+	hardif_remove_interfaces();
+	synchronize_rcu();
+	atomic_set(&module_state, MODULE_INACTIVE);
+}
+
+void inc_module_count(void)
+{
+	try_module_get(THIS_MODULE);
+}
+
+void dec_module_count(void)
+{
+	module_put(THIS_MODULE);
+}
+
+int addr_to_string(char *buff, uint8_t *addr)
+{
+	return sprintf(buff, "%02x:%02x:%02x:%02x:%02x:%02x",
+		       addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+}
+
+/* returns 1 if they are the same originator */
+
+int compare_orig(void *data1, void *data2)
+{
+	return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
+}
+
+/* hashfunction to choose an entry in a hash table of given size */
+/* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */
+int choose_orig(void *data, int32_t size)
+{
+	unsigned char *key = data;
+	uint32_t hash = 0;
+	size_t i;
+
+	for (i = 0; i < 6; i++) {
+		hash += key[i];
+		hash += (hash << 10);
+		hash ^= (hash >> 6);
+	}
+
+	hash += (hash << 3);
+	hash ^= (hash >> 11);
+	hash += (hash << 15);
+
+	return hash % size;
+}
+
+int is_my_mac(uint8_t *addr)
+{
+	struct batman_if *batman_if;
+	rcu_read_lock();
+	list_for_each_entry_rcu(batman_if, &if_list, list) {
+		if ((batman_if->net_dev) &&
+		    (compare_orig(batman_if->net_dev->dev_addr, addr))) {
+			rcu_read_unlock();
+			return 1;
+		}
+	}
+	rcu_read_unlock();
+	return 0;
+
+}
+
+int is_bcast(uint8_t *addr)
+{
+	return (addr[0] == (uint8_t)0xff) && (addr[1] == (uint8_t)0xff);
+}
+
+int is_mcast(uint8_t *addr)
+{
+	return *addr & 0x01;
+}
+
+MODULE_LICENSE("GPL");
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_SUPPORTED_DEVICE(DRIVER_DEVICE);
+#ifdef REVISION_VERSION
+MODULE_VERSION(SOURCE_VERSION "-" REVISION_VERSION);
+#else
+MODULE_VERSION(SOURCE_VERSION);
+#endif

+ 151 - 0
drivers/staging/batman-adv/main.h

@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+/* Kernel Programming */
+#define LINUX
+
+#define DRIVER_AUTHOR "Marek Lindner <lindner_marek@yahoo.de>, Simon Wunderlich <siwu@hrz.tu-chemnitz.de>"
+#define DRIVER_DESC   "B.A.T.M.A.N. advanced"
+#define DRIVER_DEVICE "batman-adv"
+
+#define SOURCE_VERSION "0.2.1-beta"
+
+
+/* B.A.T.M.A.N. parameters */
+
+#define TQ_MAX_VALUE 255
+#define JITTER 20
+#define TTL 50		          /* Time To Live of broadcast messages */
+#define MAX_ADDR 16	          /* number of interfaces which can be added to
+				   * batman. */
+
+#define PURGE_TIMEOUT 200000      /* purge originators after time in ms if no
+				   * valid packet comes in -> TODO: check
+				   * influence on TQ_LOCAL_WINDOW_SIZE */
+#define LOCAL_HNA_TIMEOUT 3600000
+
+#define TQ_LOCAL_WINDOW_SIZE 64   /* sliding packet range of received originator
+				   * messages in squence numbers (should be a
+				   * multiple of our word size) */
+#define TQ_GLOBAL_WINDOW_SIZE 5
+#define TQ_LOCAL_BIDRECT_SEND_MINIMUM 1
+#define TQ_LOCAL_BIDRECT_RECV_MINIMUM 1
+#define TQ_TOTAL_BIDRECT_LIMIT 1
+
+#define TQ_HOP_PENALTY 10
+
+#define NUM_WORDS (TQ_LOCAL_WINDOW_SIZE / WORD_BIT_SIZE)
+
+#define PACKBUFF_SIZE 2000
+#define LOG_BUF_LEN 8192	  /* has to be a power of 2 */
+#define ETH_STR_LEN 20
+
+#define MAX_AGGREGATION_BYTES 512 /* should not be bigger than 512 bytes or
+				   * change the size of
+				   * forw_packet->direct_link_flags */
+#define MAX_AGGREGATION_MS 100
+
+#define MODULE_INACTIVE 0
+#define MODULE_ACTIVE 1
+#define MODULE_DEACTIVATING 2
+
+
+/*
+ * Logging
+ */
+
+#define LOG_TYPE_CRIT 0		/* highest priority for fatal errors such as
+				 * blocked sockets / failed packet delivery /
+				 * programming errors */
+#define LOG_TYPE_WARN 1		/* warnings for small errors like wrong user
+				 * input / damaged packets / etc */
+#define LOG_TYPE_NOTICE 2	/* notice information for new interfaces /
+				 * changed settings / new originators / etc */
+#define LOG_TYPE_BATMAN 4	/* all messages related to routing / flooding /
+				 * broadcasting / etc */
+#define LOG_TYPE_ROUTES 8	/* route or hna added / changed / deleted */
+#define LOG_TYPE_CRIT_NAME	"critical"
+#define LOG_TYPE_WARN_NAME	"warnings"
+#define LOG_TYPE_NOTICE_NAME	"notices"
+#define LOG_TYPE_BATMAN_NAME	"batman"
+#define LOG_TYPE_ROUTES_NAME	"routes"
+
+/*
+ *  Vis
+ */
+
+/* #define VIS_SUBCLUSTERS_DISABLED */
+
+/*
+ * Kernel headers
+ */
+
+#include <linux/mutex.h>	/* mutex */
+#include <linux/module.h>	/* needed by all modules */
+#include <linux/netdevice.h>	/* netdevice */
+#include <linux/if_ether.h>	/* ethernet header */
+#include <linux/poll.h>		/* poll_table */
+#include <linux/kthread.h>	/* kernel threads */
+#include <linux/pkt_sched.h>	/* schedule types */
+#include <linux/workqueue.h>	/* workqueue */
+#include <net/sock.h>		/* struct sock */
+#include <linux/jiffies.h>
+#include "types.h"
+
+#ifndef REVISION_VERSION
+#define REVISION_VERSION_STR ""
+#else
+#define REVISION_VERSION_STR " "REVISION_VERSION
+#endif
+
+extern struct list_head if_list;
+extern struct hlist_head forw_bat_list;
+extern struct hlist_head forw_bcast_list;
+extern struct hashtable_t *orig_hash;
+
+extern spinlock_t orig_hash_lock;
+extern spinlock_t forw_bat_list_lock;
+extern spinlock_t forw_bcast_list_lock;
+
+extern atomic_t originator_interval;
+extern atomic_t vis_interval;
+extern atomic_t aggregation_enabled;
+extern int16_t num_hna;
+extern int16_t num_ifs;
+
+extern struct net_device *soft_device;
+
+extern unsigned char broadcastAddr[];
+extern atomic_t module_state;
+extern struct workqueue_struct *bat_event_workqueue;
+
+void activate_module(void);
+void shutdown_module(void);
+void inc_module_count(void);
+void dec_module_count(void);
+int addr_to_string(char *buff, uint8_t *addr);
+int compare_orig(void *data1, void *data2);
+int choose_orig(void *data, int32_t size);
+int is_my_mac(uint8_t *addr);
+int is_bcast(uint8_t *addr);
+int is_mcast(uint8_t *addr);
+
+

+ 96 - 0
drivers/staging/batman-adv/packet.h

@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#define ETH_P_BATMAN  0x4305	/* unofficial/not registered Ethertype */
+
+#define BAT_PACKET    0x01
+#define BAT_ICMP      0x02
+#define BAT_UNICAST   0x03
+#define BAT_BCAST     0x04
+#define BAT_VIS       0x05
+
+/* this file is included by batctl which needs these defines */
+#define COMPAT_VERSION 8
+#define DIRECTLINK 0x40
+#define VIS_SERVER 0x20
+
+/* ICMP message types */
+#define ECHO_REPLY 0
+#define DESTINATION_UNREACHABLE 3
+#define ECHO_REQUEST 8
+#define TTL_EXCEEDED 11
+#define PARAMETER_PROBLEM 12
+
+/* vis defines */
+#define VIS_TYPE_SERVER_SYNC		0
+#define VIS_TYPE_CLIENT_UPDATE		1
+
+struct batman_packet {
+	uint8_t  packet_type;
+	uint8_t  version;  /* batman version field */
+	uint8_t  flags;    /* 0x40: DIRECTLINK flag, 0x20 VIS_SERVER flag... */
+	uint8_t  tq;
+	uint16_t seqno;
+	uint8_t  orig[6];
+	uint8_t  prev_sender[6];
+	uint8_t  ttl;
+	uint8_t  num_hna;
+} __attribute__((packed));
+
+#define BAT_PACKET_LEN sizeof(struct batman_packet)
+
+struct icmp_packet {
+	uint8_t  packet_type;
+	uint8_t  version;  /* batman version field */
+	uint8_t  msg_type; /* see ICMP message types above */
+	uint8_t  ttl;
+	uint8_t  dst[6];
+	uint8_t  orig[6];
+	uint16_t seqno;
+	uint8_t  uid;
+} __attribute__((packed));
+
+struct unicast_packet {
+	uint8_t  packet_type;
+	uint8_t  version;  /* batman version field */
+	uint8_t  dest[6];
+	uint8_t  ttl;
+} __attribute__((packed));
+
+struct bcast_packet {
+	uint8_t  packet_type;
+	uint8_t  version;  /* batman version field */
+	uint8_t  orig[6];
+	uint16_t seqno;
+} __attribute__((packed));
+
+struct vis_packet {
+	uint8_t  packet_type;
+	uint8_t  version;        /* batman version field */
+	uint8_t  vis_type;	 /* which type of vis-participant sent this? */
+	uint8_t  seqno;		 /* sequence number */
+	uint8_t  entries;	 /* number of entries behind this struct */
+	uint8_t  ttl;		 /* TTL */
+	uint8_t  vis_orig[6];	 /* originator that informs about its
+				  * neighbours */
+	uint8_t  target_orig[6]; /* who should receive this packet */
+	uint8_t  sender_orig[6]; /* who sent or rebroadcasted this packet */
+} __attribute__((packed));

+ 950 - 0
drivers/staging/batman-adv/proc.c

@@ -0,0 +1,950 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#include "main.h"
+#include "proc.h"
+#include "log.h"
+#include "routing.h"
+#include "translation-table.h"
+#include "hard-interface.h"
+#include "types.h"
+#include "hash.h"
+#include "vis.h"
+#include "compat.h"
+
+static uint8_t vis_format = DOT_DRAW;
+
+static struct proc_dir_entry *proc_batman_dir, *proc_interface_file;
+static struct proc_dir_entry *proc_orig_interval_file, *proc_originators_file;
+static struct proc_dir_entry *proc_log_file, *proc_log_level_file;
+static struct proc_dir_entry *proc_transt_local_file;
+static struct proc_dir_entry *proc_transt_global_file;
+static struct proc_dir_entry *proc_vis_file, *proc_vis_format_file;
+static struct proc_dir_entry *proc_aggr_file;
+
+static int proc_interfaces_read(struct seq_file *seq, void *offset)
+{
+	struct batman_if *batman_if;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(batman_if, &if_list, list) {
+		seq_printf(seq, "[%8s] %s %s \n",
+			   (batman_if->if_active == IF_ACTIVE ?
+			    "active" : "inactive"),
+			   batman_if->dev,
+			   (batman_if->if_active == IF_ACTIVE ?
+			    batman_if->addr_str : " "));
+	}
+	rcu_read_unlock();
+
+	return 0;
+}
+
+static int proc_interfaces_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, proc_interfaces_read, NULL);
+}
+
+static ssize_t proc_interfaces_write(struct file *instance,
+				     const char __user *userbuffer,
+				     size_t count, loff_t *data)
+{
+	char *if_string, *colon_ptr = NULL, *cr_ptr = NULL;
+	int not_copied = 0, if_num = 0;
+	struct batman_if *batman_if = NULL;
+
+	if_string = kmalloc(count, GFP_KERNEL);
+
+	if (!if_string)
+		return -ENOMEM;
+
+	if (count > IFNAMSIZ - 1) {
+		debug_log(LOG_TYPE_WARN,
+			  "Can't add interface: device name is too long\n");
+		goto end;
+	}
+
+	not_copied = copy_from_user(if_string, userbuffer, count);
+	if_string[count - not_copied - 1] = 0;
+
+	colon_ptr = strchr(if_string, ':');
+	if (colon_ptr)
+		*colon_ptr = 0;
+
+	if (!colon_ptr) {
+		cr_ptr = strchr(if_string, '\n');
+		if (cr_ptr)
+			*cr_ptr = 0;
+	}
+
+	if (strlen(if_string) == 0) {
+		shutdown_module();
+		num_ifs = 0;
+		goto end;
+	}
+
+	/* add interface */
+	rcu_read_lock();
+	list_for_each_entry_rcu(batman_if, &if_list, list) {
+		if (strncmp(batman_if->dev, if_string, count) == 0) {
+			debug_log(LOG_TYPE_WARN, "Given interface is already active: %s\n", if_string);
+			rcu_read_unlock();
+			goto end;
+
+		}
+
+		if_num++;
+	}
+	rcu_read_unlock();
+
+	hardif_add_interface(if_string, if_num);
+
+	if ((atomic_read(&module_state) == MODULE_INACTIVE) &&
+	    (hardif_get_active_if_num() > 0))
+		activate_module();
+
+	rcu_read_lock();
+	if (list_empty(&if_list)) {
+		rcu_read_unlock();
+		goto end;
+	}
+	rcu_read_unlock();
+
+	num_ifs = if_num + 1;
+	return count;
+
+end:
+	kfree(if_string);
+	return count;
+}
+
+static int proc_orig_interval_read(struct seq_file *seq, void *offset)
+{
+	seq_printf(seq, "%i\n", atomic_read(&originator_interval));
+
+	return 0;
+}
+
+static ssize_t proc_orig_interval_write(struct file *file,
+					const char __user *buffer,
+					size_t count, loff_t *ppos)
+{
+	char *interval_string;
+	int not_copied = 0;
+	unsigned long originator_interval_tmp;
+	int retval;
+
+	interval_string = kmalloc(count, GFP_KERNEL);
+
+	if (!interval_string)
+		return -ENOMEM;
+
+	not_copied = copy_from_user(interval_string, buffer, count);
+	interval_string[count - not_copied - 1] = 0;
+
+	retval = strict_strtoul(interval_string, 10, &originator_interval_tmp);
+	if (retval) {
+		debug_log(LOG_TYPE_WARN, "New originator interval invalid\n");
+		goto end;
+	}
+
+	if (originator_interval_tmp <= JITTER * 2) {
+		debug_log(LOG_TYPE_WARN,
+			  "New originator interval too small: %i (min: %i)\n",
+			  originator_interval_tmp, JITTER * 2);
+		goto end;
+	}
+
+	debug_log(LOG_TYPE_NOTICE,
+		  "Changing originator interval from: %i to: %i\n",
+		  atomic_read(&originator_interval), originator_interval_tmp);
+
+	atomic_set(&originator_interval, originator_interval_tmp);
+
+end:
+	kfree(interval_string);
+	return count;
+}
+
+static int proc_orig_interval_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, proc_orig_interval_read, NULL);
+}
+
+static int proc_originators_read(struct seq_file *seq, void *offset)
+{
+	struct hash_it_t *hashit = NULL;
+	struct orig_node *orig_node;
+	struct neigh_node *neigh_node;
+	int batman_count = 0;
+	char orig_str[ETH_STR_LEN], router_str[ETH_STR_LEN];
+
+	rcu_read_lock();
+	if (list_empty(&if_list)) {
+		rcu_read_unlock();
+		seq_printf(seq, "BATMAN disabled - please specify interfaces to enable it \n");
+		goto end;
+	}
+
+	if (((struct batman_if *)if_list.next)->if_active != IF_ACTIVE) {
+		rcu_read_unlock();
+		seq_printf(seq, "BATMAN disabled - primary interface not active \n");
+		goto end;
+	}
+
+	seq_printf(seq,
+		   "  %-14s (%s/%i) %17s [%10s]: %20s ... [B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s] \n",
+		   "Originator", "#", TQ_MAX_VALUE, "Nexthop", "outgoingIF",
+		   "Potential nexthops", SOURCE_VERSION, REVISION_VERSION_STR,
+		   ((struct batman_if *)if_list.next)->dev,
+		   ((struct batman_if *)if_list.next)->addr_str);
+
+	rcu_read_unlock();
+	spin_lock(&orig_hash_lock);
+
+	while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
+
+		orig_node = hashit->bucket->data;
+
+		if (!orig_node->router)
+			continue;
+
+		if (orig_node->router->tq_avg == 0)
+			continue;
+
+		batman_count++;
+
+		addr_to_string(orig_str, orig_node->orig);
+		addr_to_string(router_str, orig_node->router->addr);
+
+		seq_printf(seq, "%-17s  (%3i) %17s [%10s]:",
+			   orig_str, orig_node->router->tq_avg,
+			   router_str, orig_node->router->if_incoming->dev);
+
+		list_for_each_entry(neigh_node, &orig_node->neigh_list, list) {
+			addr_to_string(orig_str, neigh_node->addr);
+			seq_printf(seq, " %17s (%3i)",
+				   orig_str, neigh_node->tq_avg);
+		}
+
+		seq_printf(seq, "\n");
+
+	}
+
+	spin_unlock(&orig_hash_lock);
+
+	if (batman_count == 0)
+		seq_printf(seq, "No batman nodes in range ... \n");
+
+end:
+	return 0;
+}
+
+static int proc_originators_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, proc_originators_read, NULL);
+}
+
+static int proc_log_level_read(struct seq_file *seq, void *offset)
+{
+
+	seq_printf(seq, "[x] %s (%d)\n", LOG_TYPE_CRIT_NAME, LOG_TYPE_CRIT);
+	seq_printf(seq, "[%c] %s (%d)\n",
+		   (LOG_TYPE_WARN & log_level) ? 'x' : ' ',
+		   LOG_TYPE_WARN_NAME, LOG_TYPE_WARN);
+	seq_printf(seq, "[%c] %s (%d)\n",
+		   (LOG_TYPE_NOTICE & log_level) ? 'x' : ' ',
+		   LOG_TYPE_NOTICE_NAME, LOG_TYPE_NOTICE);
+	seq_printf(seq, "[%c] %s (%d)\n",
+		   (LOG_TYPE_BATMAN & log_level) ? 'x' : ' ',
+		   LOG_TYPE_BATMAN_NAME, LOG_TYPE_BATMAN);
+	seq_printf(seq, "[%c] %s (%d)\n",
+		   (LOG_TYPE_ROUTES & log_level) ? 'x' : ' ',
+		   LOG_TYPE_ROUTES_NAME, LOG_TYPE_ROUTES);
+	return 0;
+}
+
+static int proc_log_level_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, proc_log_level_read, NULL);
+}
+
+static ssize_t proc_log_level_write(struct file *instance,
+				    const char __user *userbuffer,
+				    size_t count, loff_t *data)
+{
+	char *log_level_string, *tokptr, *cp;
+	int finished, not_copied = 0;
+	unsigned long log_level_tmp = 0;
+
+	log_level_string = kmalloc(count, GFP_KERNEL);
+
+	if (!log_level_string)
+		return -ENOMEM;
+
+	not_copied = copy_from_user(log_level_string, userbuffer, count);
+	log_level_string[count - not_copied - 1] = 0;
+
+	if (strict_strtoul(log_level_string, 10, &log_level_tmp) < 0) {
+		/* was not a number, doing textual parsing */
+		log_level_tmp = 0;
+		tokptr = log_level_string;
+
+		for (cp = log_level_string, finished = 0; !finished; cp++) {
+			switch (*cp) {
+			case 0:
+				finished = 1;
+			case ' ':
+			case '\n':
+			case '\t':
+				*cp = 0;
+				/* compare */
+				if (strcmp(tokptr, LOG_TYPE_WARN_NAME) == 0)
+					log_level_tmp |= LOG_TYPE_WARN;
+				if (strcmp(tokptr, LOG_TYPE_NOTICE_NAME) == 0)
+					log_level_tmp |= LOG_TYPE_NOTICE;
+				if (strcmp(tokptr, LOG_TYPE_BATMAN_NAME) == 0)
+					log_level_tmp |= LOG_TYPE_BATMAN;
+				if (strcmp(tokptr, LOG_TYPE_ROUTES_NAME) == 0)
+					log_level_tmp |= LOG_TYPE_ROUTES;
+				tokptr = cp + 1;
+				break;
+			default:
+				;
+			}
+		}
+	}
+
+	debug_log(LOG_TYPE_CRIT, "Changing log_level from: %i to: %i\n",
+		  log_level, log_level_tmp);
+	log_level = log_level_tmp;
+
+	kfree(log_level_string);
+	return count;
+}
+
+static int proc_transt_local_read(struct seq_file *seq, void *offset)
+{
+	char *buf;
+
+	buf = kmalloc(4096, GFP_KERNEL);
+	if (!buf)
+		return 0;
+
+	rcu_read_lock();
+	if (list_empty(&if_list)) {
+		rcu_read_unlock();
+		seq_printf(seq, "BATMAN disabled - please specify interfaces to enable it \n");
+		goto end;
+	}
+
+	rcu_read_unlock();
+
+	seq_printf(seq, "Locally retrieved addresses (from %s) announced via HNA:\n", soft_device->name);
+
+	hna_local_fill_buffer_text(buf, 4096);
+	seq_printf(seq, "%s", buf);
+
+end:
+	kfree(buf);
+	return 0;
+}
+
+static int proc_transt_local_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, proc_transt_local_read, NULL);
+}
+
+static int proc_transt_global_read(struct seq_file *seq, void *offset)
+{
+	char *buf;
+
+	buf = kmalloc(4096, GFP_KERNEL);
+	if (!buf)
+		return 0;
+
+	rcu_read_lock();
+	if (list_empty(&if_list)) {
+		rcu_read_unlock();
+		seq_printf(seq, "BATMAN disabled - please specify interfaces to enable it \n");
+		goto end;
+	}
+	rcu_read_unlock();
+
+
+	seq_printf(seq, "Globally announced HNAs received via the mesh (translation table):\n");
+
+	hna_global_fill_buffer_text(buf, 4096);
+	seq_printf(seq, "%s", buf);
+
+end:
+	kfree(buf);
+	return 0;
+}
+
+static int proc_transt_global_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, proc_transt_global_read, NULL);
+}
+
+/* insert interface to the list of interfaces of one originator */
+
+static void proc_vis_insert_interface(const uint8_t *interface,
+				      struct vis_if_list **if_entry,
+				      bool primary)
+{
+	/* Did we get an empty list? (then insert imediately) */
+	if(*if_entry == NULL) {
+		*if_entry = kmalloc(sizeof(struct vis_if_list), GFP_KERNEL);
+		if (*if_entry == NULL)
+			return;
+
+		(*if_entry)->primary = primary;
+		(*if_entry)->next = NULL;
+		memcpy((*if_entry)->addr, interface, ETH_ALEN);
+	} else {
+		struct vis_if_list *head_if_entry = *if_entry;
+		/* Do we already have this interface in our list? */
+		while (!compare_orig((*if_entry)->addr, (void *)interface)) {
+
+			/* Or did we reach the end (then append the interface) */
+			if ((*if_entry)->next == NULL) {
+				(*if_entry)->next = kmalloc(sizeof(struct vis_if_list), GFP_KERNEL);
+				if ((*if_entry)->next == NULL)
+					return;
+
+				memcpy((*if_entry)->next->addr, interface, ETH_ALEN);
+				(*if_entry)->next->primary = primary;
+				(*if_entry)->next->next = NULL;
+				break;
+			}
+			*if_entry = (*if_entry)->next;
+		}
+		/* Rewind the list to its head */
+		*if_entry = head_if_entry;
+	}
+}
+/* read an entry  */
+
+static void proc_vis_read_entry(struct seq_file *seq,
+				struct vis_info_entry *entry,
+				struct vis_if_list **if_entry,
+				uint8_t *vis_orig,
+				uint8_t current_format,
+				uint8_t first_line)
+{
+	char from[40];
+	char to[40];
+	int int_part, frac_part;
+
+	addr_to_string(to, entry->dest);
+	if (entry->quality == 0) {
+#ifndef VIS_SUBCLUSTERS_DISABLED
+		proc_vis_insert_interface(vis_orig, if_entry, true);
+#endif /* VIS_SUBCLUSTERS_DISABLED */
+		addr_to_string(from, vis_orig);
+		if (current_format == DOT_DRAW) {
+			seq_printf(seq, "\t\"%s\" -> \"%s\" [label=\"HNA\"]\n",
+				   from, to);
+		} else {
+			seq_printf(seq,
+				   "%s\t{ router : \"%s\", gateway   : \"%s\", label : \"HNA\" }",
+				   (first_line ? "" : ",\n"), from, to);
+		}
+	} else {
+#ifndef VIS_SUBCLUSTERS_DISABLED
+		proc_vis_insert_interface(entry->src, if_entry, compare_orig(entry->src, vis_orig));
+#endif /* VIS_SUBCLUSTERS_DISABLED */
+		addr_to_string(from, entry->src);
+
+		/* kernel has no printf-support for %f? it'd be better to return
+		 * this in float. */
+
+		int_part = TQ_MAX_VALUE / entry->quality;
+		frac_part = 1000 * TQ_MAX_VALUE / entry->quality - int_part * 1000;
+
+		if (current_format == DOT_DRAW) {
+			seq_printf(seq,
+				   "\t\"%s\" -> \"%s\" [label=\"%d.%d\"]\n",
+				   from, to, int_part, frac_part);
+		} else {
+			seq_printf(seq,
+				   "%s\t{ router : \"%s\", neighbour : \"%s\", label : %d.%d }",
+				   (first_line ? "" : ",\n"), from, to, int_part, frac_part);
+		}
+	}
+}
+
+
+static int proc_vis_read(struct seq_file *seq, void *offset)
+{
+	struct hash_it_t *hashit = NULL;
+	struct vis_info *info;
+	struct vis_info_entry *entries;
+	struct vis_if_list *if_entries = NULL;
+	int i;
+	uint8_t current_format, first_line = 1;
+#ifndef VIS_SUBCLUSTERS_DISABLED
+	char tmp_addr_str[ETH_STR_LEN];
+	struct vis_if_list *tmp_if_next;
+#endif /* VIS_SUBCLUSTERS_DISABLED */
+
+	current_format = vis_format;
+
+	rcu_read_lock();
+	if (list_empty(&if_list) || (!is_vis_server())) {
+		rcu_read_unlock();
+		if (current_format == DOT_DRAW)
+			seq_printf(seq, "digraph {\n}\n");
+		goto end;
+	}
+
+	rcu_read_unlock();
+
+	if (current_format == DOT_DRAW)
+		seq_printf(seq, "digraph {\n");
+
+	spin_lock(&vis_hash_lock);
+	while (NULL != (hashit = hash_iterate(vis_hash, hashit))) {
+		info = hashit->bucket->data;
+		entries = (struct vis_info_entry *)
+			((char *)info + sizeof(struct vis_info));
+
+		for (i = 0; i < info->packet.entries; i++) {
+			proc_vis_read_entry(seq, &entries[i], &if_entries,
+					    info->packet.vis_orig,
+					    current_format, first_line);
+			if (first_line)
+				first_line = 0;
+		}
+
+#ifndef VIS_SUBCLUSTERS_DISABLED
+		/* Generate subgraphs from the collected items */
+		if (current_format == DOT_DRAW) {
+
+			addr_to_string(tmp_addr_str, info->packet.vis_orig);
+			seq_printf(seq, "\tsubgraph \"cluster_%s\" {\n", tmp_addr_str);
+			while (if_entries != NULL) {
+
+				addr_to_string(tmp_addr_str, if_entries->addr);
+				if (if_entries->primary)
+					seq_printf(seq, "\t\t\"%s\" [peripheries=2]\n", tmp_addr_str);
+				else
+					seq_printf(seq, "\t\t\"%s\"\n", tmp_addr_str);
+
+				/* ... and empty the list while doing this */
+				tmp_if_next = if_entries->next;
+				kfree(if_entries);
+				if_entries = tmp_if_next;
+			}
+			seq_printf(seq, "\t}\n");
+		}
+#endif /* VIS_SUBCLUSTERS_DISABLED */
+	}
+	spin_unlock(&vis_hash_lock);
+
+	if (current_format == DOT_DRAW)
+		seq_printf(seq, "}\n");
+	else
+		seq_printf(seq, "\n");
+end:
+	return 0;
+}
+
+/* setting the mode of the vis server by the user */
+static ssize_t proc_vis_write(struct file *file, const char __user * buffer,
+			      size_t count, loff_t *ppos)
+{
+	char *vis_mode_string;
+	int not_copied = 0;
+
+	vis_mode_string = kmalloc(count, GFP_KERNEL);
+
+	if (!vis_mode_string)
+		return -ENOMEM;
+
+	not_copied = copy_from_user(vis_mode_string, buffer, count);
+	vis_mode_string[count - not_copied - 1] = 0;
+
+	if (strcmp(vis_mode_string, "client") == 0) {
+		debug_log(LOG_TYPE_NOTICE, "Setting VIS mode to client\n");
+		vis_set_mode(VIS_TYPE_CLIENT_UPDATE);
+	} else if (strcmp(vis_mode_string, "server") == 0) {
+		debug_log(LOG_TYPE_NOTICE, "Setting VIS mode to server\n");
+		vis_set_mode(VIS_TYPE_SERVER_SYNC);
+	} else
+		debug_log(LOG_TYPE_WARN, "Unknown VIS mode: %s\n",
+			  vis_mode_string);
+
+	kfree(vis_mode_string);
+	return count;
+}
+
+static int proc_vis_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, proc_vis_read, NULL);
+}
+
+static int proc_vis_format_read(struct seq_file *seq, void *offset)
+{
+	uint8_t current_format = vis_format;
+
+	seq_printf(seq, "[%c] %s\n",
+		   (current_format == DOT_DRAW) ? 'x' : ' ',
+		   VIS_FORMAT_DD_NAME);
+	seq_printf(seq, "[%c] %s\n",
+		   (current_format == JSON) ? 'x' : ' ',
+		   VIS_FORMAT_JSON_NAME);
+	return 0;
+}
+
+static int proc_vis_format_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, proc_vis_format_read, NULL);
+}
+
+static ssize_t proc_vis_format_write(struct file *file,
+				     const char __user *buffer,
+				     size_t count, loff_t *ppos)
+{
+	char *vis_format_string;
+	int not_copied = 0;
+
+	vis_format_string = kmalloc(count, GFP_KERNEL);
+
+	if (!vis_format_string)
+		return -ENOMEM;
+
+	not_copied = copy_from_user(vis_format_string, buffer, count);
+	vis_format_string[count - not_copied - 1] = 0;
+
+	if (strcmp(vis_format_string, VIS_FORMAT_DD_NAME) == 0) {
+		debug_log(LOG_TYPE_NOTICE, "Setting VIS output format to: %s\n",
+			  VIS_FORMAT_DD_NAME);
+		vis_format = DOT_DRAW;
+	} else if (strcmp(vis_format_string, VIS_FORMAT_JSON_NAME) == 0) {
+		debug_log(LOG_TYPE_NOTICE, "Setting VIS output format to: %s\n",
+			  VIS_FORMAT_JSON_NAME);
+		vis_format = JSON;
+	} else
+		debug_log(LOG_TYPE_WARN, "Unknown VIS output format: %s\n",
+			  vis_format_string);
+
+	kfree(vis_format_string);
+	return count;
+}
+
+static int proc_aggr_read(struct seq_file *seq, void *offset)
+{
+	seq_printf(seq, "%i\n", atomic_read(&aggregation_enabled));
+
+	return 0;
+}
+
+static ssize_t proc_aggr_write(struct file *file, const char __user *buffer,
+			       size_t count, loff_t *ppos)
+{
+	char *aggr_string;
+	int not_copied = 0;
+	unsigned long aggregation_enabled_tmp;
+
+	aggr_string = kmalloc(count, GFP_KERNEL);
+
+	if (!aggr_string)
+		return -ENOMEM;
+
+	not_copied = copy_from_user(aggr_string, buffer, count);
+	aggr_string[count - not_copied - 1] = 0;
+
+	strict_strtoul(aggr_string, 10, &aggregation_enabled_tmp);
+
+	if ((aggregation_enabled_tmp != 0) && (aggregation_enabled_tmp != 1)) {
+		debug_log(LOG_TYPE_WARN, "Aggregation can only be enabled (1) or disabled (0), given value: %li\n", aggregation_enabled_tmp);
+		goto end;
+	}
+
+	debug_log(LOG_TYPE_NOTICE, "Changing aggregation from: %s (%i) to: %s (%li)\n",
+		  (atomic_read(&aggregation_enabled) == 1 ?
+		   "enabled" : "disabled"),
+		  atomic_read(&aggregation_enabled),
+		  (aggregation_enabled_tmp == 1 ? "enabled" : "disabled"),
+		  aggregation_enabled_tmp);
+
+	atomic_set(&aggregation_enabled, (unsigned)aggregation_enabled_tmp);
+end:
+	kfree(aggr_string);
+	return count;
+}
+
+static int proc_aggr_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, proc_aggr_read, NULL);
+}
+
+/* satisfying different prototypes ... */
+static ssize_t proc_dummy_write(struct file *file, const char __user *buffer,
+				size_t count, loff_t *ppos)
+{
+	return count;
+}
+
+static const struct file_operations proc_aggr_fops = {
+	.owner		= THIS_MODULE,
+	.open		= proc_aggr_open,
+	.read		= seq_read,
+	.write		= proc_aggr_write,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static const struct file_operations proc_vis_format_fops = {
+	.owner		= THIS_MODULE,
+	.open		= proc_vis_format_open,
+	.read		= seq_read,
+	.write		= proc_vis_format_write,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static const struct file_operations proc_vis_fops = {
+	.owner		= THIS_MODULE,
+	.open		= proc_vis_open,
+	.read		= seq_read,
+	.write		= proc_vis_write,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static const struct file_operations proc_originators_fops = {
+	.owner		= THIS_MODULE,
+	.open		= proc_originators_open,
+	.read		= seq_read,
+	.write		= proc_dummy_write,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static const struct file_operations proc_transt_local_fops = {
+	.owner		= THIS_MODULE,
+	.open		= proc_transt_local_open,
+	.read		= seq_read,
+	.write		= proc_dummy_write,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static const struct file_operations proc_transt_global_fops = {
+	.owner		= THIS_MODULE,
+	.open		= proc_transt_global_open,
+	.read		= seq_read,
+	.write		= proc_dummy_write,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static const struct file_operations proc_log_level_fops = {
+	.owner		= THIS_MODULE,
+	.open		= proc_log_level_open,
+	.read		= seq_read,
+	.write		= proc_log_level_write,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static const struct file_operations proc_interfaces_fops = {
+	.owner		= THIS_MODULE,
+	.open		= proc_interfaces_open,
+	.read		= seq_read,
+	.write		= proc_interfaces_write,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static const struct file_operations proc_orig_interval_fops = {
+	.owner		= THIS_MODULE,
+	.open		= proc_orig_interval_open,
+	.read		= seq_read,
+	.write		= proc_orig_interval_write,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+void cleanup_procfs(void)
+{
+	if (proc_transt_global_file)
+		remove_proc_entry(PROC_FILE_TRANST_GLOBAL, proc_batman_dir);
+
+	if (proc_transt_local_file)
+		remove_proc_entry(PROC_FILE_TRANST_LOCAL, proc_batman_dir);
+
+	if (proc_log_file)
+		remove_proc_entry(PROC_FILE_LOG, proc_batman_dir);
+
+	if (proc_log_level_file)
+		remove_proc_entry(PROC_FILE_LOG_LEVEL, proc_batman_dir);
+
+	if (proc_originators_file)
+		remove_proc_entry(PROC_FILE_ORIGINATORS, proc_batman_dir);
+
+	if (proc_orig_interval_file)
+		remove_proc_entry(PROC_FILE_ORIG_INTERVAL, proc_batman_dir);
+
+	if (proc_interface_file)
+		remove_proc_entry(PROC_FILE_INTERFACES, proc_batman_dir);
+
+	if (proc_vis_file)
+		remove_proc_entry(PROC_FILE_VIS, proc_batman_dir);
+
+	if (proc_vis_format_file)
+		remove_proc_entry(PROC_FILE_VIS_FORMAT, proc_batman_dir);
+
+	if (proc_aggr_file)
+		remove_proc_entry(PROC_FILE_AGGR, proc_batman_dir);
+
+	if (proc_batman_dir)
+#ifdef __NET_NET_NAMESPACE_H
+		remove_proc_entry(PROC_ROOT_DIR, init_net.proc_net);
+#else
+		remove_proc_entry(PROC_ROOT_DIR, proc_net);
+#endif
+}
+
+int setup_procfs(void)
+{
+#ifdef __NET_NET_NAMESPACE_H
+	proc_batman_dir = proc_mkdir(PROC_ROOT_DIR, init_net.proc_net);
+#else
+	proc_batman_dir = proc_mkdir(PROC_ROOT_DIR, proc_net);
+#endif
+
+	if (!proc_batman_dir) {
+		printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s' folder failed\n", PROC_ROOT_DIR);
+		return -EFAULT;
+	}
+
+	proc_interface_file = create_proc_entry(PROC_FILE_INTERFACES,
+						S_IWUSR | S_IRUGO,
+						proc_batman_dir);
+	if (proc_interface_file) {
+		proc_interface_file->proc_fops = &proc_interfaces_fops;
+	} else {
+		printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_INTERFACES);
+		cleanup_procfs();
+		return -EFAULT;
+	}
+
+	proc_orig_interval_file = create_proc_entry(PROC_FILE_ORIG_INTERVAL,
+						    S_IWUSR | S_IRUGO,
+						    proc_batman_dir);
+	if (proc_orig_interval_file) {
+		proc_orig_interval_file->proc_fops = &proc_orig_interval_fops;
+	} else {
+		printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_ORIG_INTERVAL);
+		cleanup_procfs();
+		return -EFAULT;
+	}
+
+	proc_log_level_file = create_proc_entry(PROC_FILE_LOG_LEVEL,
+						S_IWUSR | S_IRUGO,
+						proc_batman_dir);
+	if (proc_log_level_file) {
+		proc_log_level_file->proc_fops = &proc_log_level_fops;
+	} else {
+		printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_LOG_LEVEL);
+		cleanup_procfs();
+		return -EFAULT;
+	}
+
+	proc_originators_file = create_proc_entry(PROC_FILE_ORIGINATORS,
+						  S_IRUGO, proc_batman_dir);
+	if (proc_originators_file) {
+		proc_originators_file->proc_fops = &proc_originators_fops;
+	} else {
+		printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_ORIGINATORS);
+		cleanup_procfs();
+		return -EFAULT;
+	}
+
+	proc_log_file = create_proc_entry(PROC_FILE_LOG,
+					  S_IRUGO, proc_batman_dir);
+	if (proc_log_file) {
+		proc_log_file->proc_fops = &proc_log_operations;
+	} else {
+		printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_FILE_LOG, PROC_FILE_GATEWAYS);
+		cleanup_procfs();
+		return -EFAULT;
+	}
+
+	proc_transt_local_file = create_proc_entry(PROC_FILE_TRANST_LOCAL,
+						   S_IRUGO, proc_batman_dir);
+	if (proc_transt_local_file) {
+		proc_transt_local_file->proc_fops = &proc_transt_local_fops;
+	} else {
+		printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_TRANST_LOCAL);
+		cleanup_procfs();
+		return -EFAULT;
+	}
+
+	proc_transt_global_file = create_proc_entry(PROC_FILE_TRANST_GLOBAL,
+						    S_IRUGO, proc_batman_dir);
+	if (proc_transt_global_file) {
+		proc_transt_global_file->proc_fops = &proc_transt_global_fops;
+	} else {
+		printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_TRANST_GLOBAL);
+		cleanup_procfs();
+		return -EFAULT;
+	}
+
+	proc_vis_file = create_proc_entry(PROC_FILE_VIS, S_IWUSR | S_IRUGO,
+					  proc_batman_dir);
+	if (proc_vis_file) {
+		proc_vis_file->proc_fops = &proc_vis_fops;
+	} else {
+		printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS);
+		cleanup_procfs();
+		return -EFAULT;
+	}
+
+	proc_vis_format_file = create_proc_entry(PROC_FILE_VIS_FORMAT,
+						 S_IWUSR | S_IRUGO,
+						 proc_batman_dir);
+	if (proc_vis_format_file) {
+		proc_vis_format_file->proc_fops = &proc_vis_format_fops;
+	} else {
+		printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS_FORMAT);
+		cleanup_procfs();
+		return -EFAULT;
+	}
+
+	proc_aggr_file = create_proc_entry(PROC_FILE_AGGR, S_IWUSR | S_IRUGO,
+					   proc_batman_dir);
+	if (proc_aggr_file) {
+		proc_aggr_file->proc_fops = &proc_aggr_fops;
+	} else {
+		printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_AGGR);
+		cleanup_procfs();
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+

+ 49 - 0
drivers/staging/batman-adv/proc.h

@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#define PROC_ROOT_DIR "batman-adv"
+#define PROC_FILE_INTERFACES "interfaces"
+#define PROC_FILE_ORIG_INTERVAL "orig_interval"
+#define PROC_FILE_ORIGINATORS "originators"
+#define PROC_FILE_GATEWAYS "gateways"
+#define PROC_FILE_LOG "log"
+#define PROC_FILE_LOG_LEVEL "log_level"
+#define PROC_FILE_TRANST_LOCAL "transtable_local"
+#define PROC_FILE_TRANST_GLOBAL "transtable_global"
+#define PROC_FILE_VIS "vis"
+#define PROC_FILE_VIS_FORMAT "vis_format"
+#define PROC_FILE_AGGR "aggregate_ogm"
+
+void cleanup_procfs(void);
+int setup_procfs(void);
+
+/* While scanning for vis-entries of a particular vis-originator
+ * this list collects its interfaces to create a subgraph/cluster
+ * out of them later
+ */
+struct vis_if_list {
+	uint8_t addr[ETH_ALEN];
+	bool primary;
+	struct vis_if_list *next;
+};

+ 52 - 0
drivers/staging/batman-adv/ring_buffer.c

@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#include "main.h"
+#include "ring_buffer.h"
+
+void ring_buffer_set(uint8_t lq_recv[], uint8_t *lq_index, uint8_t value)
+{
+	lq_recv[*lq_index] = value;
+	*lq_index = (*lq_index + 1) % TQ_GLOBAL_WINDOW_SIZE;
+}
+
+uint8_t ring_buffer_avg(uint8_t lq_recv[])
+{
+	uint8_t *ptr;
+	uint16_t count = 0, i = 0, sum = 0;
+
+	ptr = lq_recv;
+
+	while (i < TQ_GLOBAL_WINDOW_SIZE) {
+		if (*ptr != 0) {
+			count++;
+			sum += *ptr;
+		}
+
+		i++;
+		ptr++;
+	}
+
+	if (count == 0)
+		return 0;
+
+	return (uint8_t)(sum / count);
+}

+ 23 - 0
drivers/staging/batman-adv/ring_buffer.h

@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+void ring_buffer_set(uint8_t lq_recv[], uint8_t *lq_index, uint8_t value);
+uint8_t ring_buffer_avg(uint8_t lq_recv[]);

+ 1010 - 0
drivers/staging/batman-adv/routing.c

@@ -0,0 +1,1010 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+
+
+
+
+#include "main.h"
+#include "routing.h"
+#include "log.h"
+#include "send.h"
+#include "soft-interface.h"
+#include "hard-interface.h"
+#include "device.h"
+#include "translation-table.h"
+#include "types.h"
+#include "hash.h"
+#include "ring_buffer.h"
+#include "vis.h"
+#include "aggregation.h"
+#include "compat.h"
+
+
+
+DECLARE_WAIT_QUEUE_HEAD(thread_wait);
+static DECLARE_DELAYED_WORK(purge_orig_wq, purge_orig);
+
+static atomic_t data_ready_cond;
+atomic_t exit_cond;
+
+static void start_purge_timer(void)
+{
+	queue_delayed_work(bat_event_workqueue, &purge_orig_wq, 1 * HZ);
+}
+
+int originator_init(void)
+{
+	if (orig_hash)
+		return 1;
+
+	spin_lock(&orig_hash_lock);
+	orig_hash = hash_new(128, compare_orig, choose_orig);
+
+	if (!orig_hash)
+		goto err;
+
+	spin_unlock(&orig_hash_lock);
+	start_purge_timer();
+	return 1;
+
+err:
+	spin_unlock(&orig_hash_lock);
+	return 0;
+}
+
+void originator_free(void)
+{
+	if (!orig_hash)
+		return;
+
+	cancel_delayed_work_sync(&purge_orig_wq);
+
+	spin_lock(&orig_hash_lock);
+	hash_delete(orig_hash, free_orig_node);
+	orig_hash = NULL;
+	spin_unlock(&orig_hash_lock);
+}
+
+static struct neigh_node *create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, uint8_t *neigh, struct batman_if *if_incoming)
+{
+	struct neigh_node *neigh_node;
+
+	debug_log(LOG_TYPE_BATMAN, "Creating new last-hop neighbour of originator\n");
+
+	neigh_node = kmalloc(sizeof(struct neigh_node), GFP_ATOMIC);
+	memset(neigh_node, 0, sizeof(struct neigh_node));
+	INIT_LIST_HEAD(&neigh_node->list);
+
+	memcpy(neigh_node->addr, neigh, ETH_ALEN);
+	neigh_node->orig_node = orig_neigh_node;
+	neigh_node->if_incoming = if_incoming;
+
+	list_add_tail(&neigh_node->list, &orig_node->neigh_list);
+	return neigh_node;
+}
+
+void free_orig_node(void *data)
+{
+	struct list_head *list_pos, *list_pos_tmp;
+	struct neigh_node *neigh_node;
+	struct orig_node *orig_node = (struct orig_node *)data;
+
+	/* for all neighbours towards this originator ... */
+	list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) {
+		neigh_node = list_entry(list_pos, struct neigh_node, list);
+
+		list_del(list_pos);
+		kfree(neigh_node);
+	}
+
+	hna_global_del_orig(orig_node, "originator timed out");
+
+	kfree(orig_node->bcast_own);
+	kfree(orig_node->bcast_own_sum);
+	kfree(orig_node);
+}
+
+/* this function finds or creates an originator entry for the given address if it does not exits */
+static struct orig_node *get_orig_node(uint8_t *addr)
+{
+	struct orig_node *orig_node;
+	struct hashtable_t *swaphash;
+	char orig_str[ETH_STR_LEN];
+
+	orig_node = ((struct orig_node *)hash_find(orig_hash, addr));
+
+	if (orig_node != NULL)
+		return orig_node;
+
+	addr_to_string(orig_str, addr);
+	debug_log(LOG_TYPE_BATMAN, "Creating new originator: %s \n", orig_str);
+
+	orig_node = kmalloc(sizeof(struct orig_node), GFP_ATOMIC);
+	memset(orig_node, 0, sizeof(struct orig_node));
+	INIT_LIST_HEAD(&orig_node->neigh_list);
+
+	memcpy(orig_node->orig, addr, ETH_ALEN);
+	orig_node->router = NULL;
+	orig_node->batman_if = NULL;
+	orig_node->hna_buff = NULL;
+
+	orig_node->bcast_own = kmalloc(num_ifs * sizeof(TYPE_OF_WORD) * NUM_WORDS, GFP_ATOMIC);
+	memset(orig_node->bcast_own, 0, num_ifs * sizeof(TYPE_OF_WORD) * NUM_WORDS);
+
+	orig_node->bcast_own_sum = kmalloc(num_ifs * sizeof(uint8_t), GFP_ATOMIC);
+	memset(orig_node->bcast_own_sum, 0, num_ifs * sizeof(uint8_t));
+
+	hash_add(orig_hash, orig_node);
+
+	if (orig_hash->elements * 4 > orig_hash->size) {
+		swaphash = hash_resize(orig_hash, orig_hash->size * 2);
+
+		if (swaphash == NULL)
+			debug_log(LOG_TYPE_CRIT, "Couldn't resize orig hash table \n");
+		else
+			orig_hash = swaphash;
+	}
+
+	return orig_node;
+}
+
+void slide_own_bcast_window(struct batman_if *batman_if)
+{
+	struct hash_it_t *hashit = NULL;
+	struct orig_node *orig_node;
+
+	spin_lock(&orig_hash_lock);
+
+	while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
+		orig_node = hashit->bucket->data;
+
+		bit_get_packet((TYPE_OF_WORD *)&(orig_node->bcast_own[batman_if->if_num * NUM_WORDS]), 1, 0);
+		orig_node->bcast_own_sum[batman_if->if_num] = bit_packet_count((TYPE_OF_WORD *)&(orig_node->bcast_own[batman_if->if_num * NUM_WORDS]));
+	}
+
+	spin_unlock(&orig_hash_lock);
+}
+
+static void update_routes(struct orig_node *orig_node, struct neigh_node *neigh_node, unsigned char *hna_buff, int hna_buff_len)
+{
+	char orig_str[ETH_STR_LEN], neigh_str[ETH_STR_LEN], router_str[ETH_STR_LEN];
+
+	if (orig_node == NULL)
+		return;
+
+	if (orig_node->router != neigh_node) {
+		addr_to_string(orig_str, orig_node->orig);
+
+		/* route deleted */
+		if ((orig_node->router != NULL) && (neigh_node == NULL)) {
+
+			debug_log(LOG_TYPE_ROUTES, "Deleting route towards: %s\n", orig_str);
+			hna_global_del_orig(orig_node, "originator timed out");
+
+		/* route added */
+		} else if ((orig_node->router == NULL) && (neigh_node != NULL)) {
+
+			addr_to_string(neigh_str, neigh_node->addr);
+			debug_log(LOG_TYPE_ROUTES, "Adding route towards: %s (via %s)\n", orig_str, neigh_str);
+			hna_global_add_orig(orig_node, hna_buff, hna_buff_len);
+
+		/* route changed */
+		} else {
+
+			addr_to_string(neigh_str, neigh_node->addr);
+			addr_to_string(router_str, orig_node->router->addr);
+			debug_log(LOG_TYPE_ROUTES, "Changing route towards: %s (now via %s - was via %s)\n", orig_str, neigh_str, router_str);
+
+		}
+
+		if (neigh_node != NULL)
+			orig_node->batman_if = neigh_node->if_incoming;
+		else
+			orig_node->batman_if = NULL;
+
+		orig_node->router = neigh_node;
+
+	/* may be just HNA changed */
+	} else {
+
+		if ((hna_buff_len != orig_node->hna_buff_len) || ((hna_buff_len > 0) && (orig_node->hna_buff_len > 0) && (memcmp(orig_node->hna_buff, hna_buff, hna_buff_len) != 0))) {
+
+			if (orig_node->hna_buff_len > 0)
+				hna_global_del_orig(orig_node, "originator changed hna");
+
+			if ((hna_buff_len > 0) && (hna_buff != NULL))
+				hna_global_add_orig(orig_node, hna_buff, hna_buff_len);
+
+		}
+
+	}
+}
+
+static int isBidirectionalNeigh(struct orig_node *orig_node, struct orig_node *orig_neigh_node, struct batman_packet *batman_packet, struct batman_if *if_incoming)
+{
+	struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
+	char orig_str[ETH_STR_LEN], neigh_str[ETH_STR_LEN];
+	unsigned char total_count;
+
+	addr_to_string(orig_str, orig_node->orig);
+	addr_to_string(neigh_str, orig_neigh_node->orig);
+
+	if (orig_node == orig_neigh_node) {
+		list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {
+
+			if (compare_orig(tmp_neigh_node->addr, orig_neigh_node->orig) && (tmp_neigh_node->if_incoming == if_incoming))
+				neigh_node = tmp_neigh_node;
+		}
+
+		if (neigh_node == NULL)
+			neigh_node = create_neighbor(orig_node, orig_neigh_node, orig_neigh_node->orig, if_incoming);
+
+		neigh_node->last_valid = jiffies;
+	} else {
+		/* find packet count of corresponding one hop neighbor */
+		list_for_each_entry(tmp_neigh_node, &orig_neigh_node->neigh_list, list) {
+
+			if (compare_orig(tmp_neigh_node->addr, orig_neigh_node->orig) && (tmp_neigh_node->if_incoming == if_incoming))
+				neigh_node = tmp_neigh_node;
+		}
+
+		if (neigh_node == NULL)
+			neigh_node = create_neighbor(orig_neigh_node, orig_neigh_node, orig_neigh_node->orig, if_incoming);
+	}
+
+	orig_node->last_valid = jiffies;
+
+	/* pay attention to not get a value bigger than 100 % */
+	total_count = (orig_neigh_node->bcast_own_sum[if_incoming->if_num] > neigh_node->real_packet_count ? neigh_node->real_packet_count : orig_neigh_node->bcast_own_sum[if_incoming->if_num]);
+
+	/* if we have too few packets (too less data) we set tq_own to zero */
+	/* if we receive too few packets it is not considered bidirectional */
+	if ((total_count < TQ_LOCAL_BIDRECT_SEND_MINIMUM) || (neigh_node->real_packet_count < TQ_LOCAL_BIDRECT_RECV_MINIMUM))
+		orig_neigh_node->tq_own = 0;
+	else
+		/* neigh_node->real_packet_count is never zero as we only purge old information when getting new information */
+		orig_neigh_node->tq_own = (TQ_MAX_VALUE * total_count) / neigh_node->real_packet_count;
+
+	/*
+	 * 1 - ((1-x) ** 3), normalized to TQ_MAX_VALUE
+	 * this does affect the nearly-symmetric links only a little,
+	 * but punishes asymmetric links more.
+	 * this will give a value between 0 and TQ_MAX_VALUE
+	 */
+	orig_neigh_node->tq_asym_penalty = TQ_MAX_VALUE - (TQ_MAX_VALUE *
+			(TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count) *
+			(TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count) *
+			(TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count)) /
+			(TQ_LOCAL_WINDOW_SIZE * TQ_LOCAL_WINDOW_SIZE * TQ_LOCAL_WINDOW_SIZE);
+
+	batman_packet->tq = ((batman_packet->tq * orig_neigh_node->tq_own * orig_neigh_node->tq_asym_penalty) / (TQ_MAX_VALUE *  TQ_MAX_VALUE));
+
+	debug_log(LOG_TYPE_BATMAN, "bidirectional: orig = %-15s neigh = %-15s => own_bcast = %2i, real recv = %2i, local tq: %3i, asym_penalty: %3i, total tq: %3i \n",
+		  orig_str, neigh_str, total_count, neigh_node->real_packet_count, orig_neigh_node->tq_own, orig_neigh_node->tq_asym_penalty, batman_packet->tq);
+
+	/* if link has the minimum required transmission quality consider it bidirectional */
+	if (batman_packet->tq >= TQ_TOTAL_BIDRECT_LIMIT)
+		return 1;
+
+	return 0;
+}
+
+static void update_orig(struct orig_node *orig_node, struct ethhdr *ethhdr, struct batman_packet *batman_packet, struct batman_if *if_incoming, unsigned char *hna_buff, int hna_buff_len, char is_duplicate)
+{
+	struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
+	int tmp_hna_buff_len;
+
+	debug_log(LOG_TYPE_BATMAN, "update_originator(): Searching and updating originator entry of received packet \n");
+
+	list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {
+		if (compare_orig(tmp_neigh_node->addr, ethhdr->h_source) && (tmp_neigh_node->if_incoming == if_incoming)) {
+			neigh_node = tmp_neigh_node;
+			continue;
+		}
+
+		if (is_duplicate)
+			continue;
+
+		ring_buffer_set(tmp_neigh_node->tq_recv, &tmp_neigh_node->tq_index, 0);
+		tmp_neigh_node->tq_avg = ring_buffer_avg(tmp_neigh_node->tq_recv);
+	}
+
+	if (neigh_node == NULL)
+		neigh_node = create_neighbor(orig_node, get_orig_node(ethhdr->h_source), ethhdr->h_source, if_incoming);
+	else
+		debug_log(LOG_TYPE_BATMAN, "Updating existing last-hop neighbour of originator\n");
+
+	orig_node->flags = batman_packet->flags;
+	neigh_node->last_valid = jiffies;
+
+	ring_buffer_set(neigh_node->tq_recv, &neigh_node->tq_index, batman_packet->tq);
+	neigh_node->tq_avg = ring_buffer_avg(neigh_node->tq_recv);
+
+	if (!is_duplicate) {
+		orig_node->last_ttl = batman_packet->ttl;
+		neigh_node->last_ttl = batman_packet->ttl;
+	}
+
+	tmp_hna_buff_len = (hna_buff_len > batman_packet->num_hna * ETH_ALEN ? batman_packet->num_hna * ETH_ALEN : hna_buff_len);
+
+	/* if this neighbor already is our next hop there is nothing to change */
+	if (orig_node->router == neigh_node)
+		goto update_hna;
+
+	/* if this neighbor does not offer a better TQ we won't consider it */
+	if ((orig_node->router) &&
+	    (orig_node->router->tq_avg > neigh_node->tq_avg))
+		goto update_hna;
+
+	/* if the TQ is the same and the link not more symetric we won't consider it either */
+	if ((orig_node->router) &&
+	     ((neigh_node->tq_avg == orig_node->router->tq_avg) &&
+	     (orig_node->router->orig_node->bcast_own_sum[if_incoming->if_num] >=
+	      neigh_node->orig_node->bcast_own_sum[if_incoming->if_num])))
+		goto update_hna;
+
+	update_routes(orig_node, neigh_node, hna_buff, tmp_hna_buff_len);
+	return;
+
+update_hna:
+	update_routes(orig_node, orig_node->router, hna_buff, tmp_hna_buff_len);
+	return;
+}
+
+static char count_real_packets(struct ethhdr *ethhdr, struct batman_packet *batman_packet, struct batman_if *if_incoming)
+{
+	struct orig_node *orig_node;
+	struct neigh_node *tmp_neigh_node;
+	char is_duplicate = 0;
+
+
+	orig_node = get_orig_node(batman_packet->orig);
+	if (orig_node == NULL)
+		return 0;
+
+
+	list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {
+
+		if (!is_duplicate)
+			is_duplicate = get_bit_status(tmp_neigh_node->real_bits, orig_node->last_real_seqno, batman_packet->seqno);
+
+		if (compare_orig(tmp_neigh_node->addr, ethhdr->h_source) && (tmp_neigh_node->if_incoming == if_incoming))
+			bit_get_packet(tmp_neigh_node->real_bits, batman_packet->seqno - orig_node->last_real_seqno, 1);
+		else
+			bit_get_packet(tmp_neigh_node->real_bits, batman_packet->seqno - orig_node->last_real_seqno, 0);
+
+		tmp_neigh_node->real_packet_count = bit_packet_count(tmp_neigh_node->real_bits);
+	}
+
+	if (!is_duplicate) {
+		debug_log(LOG_TYPE_BATMAN, "updating last_seqno: old %d, new %d \n", orig_node->last_real_seqno, batman_packet->seqno);
+		orig_node->last_real_seqno = batman_packet->seqno;
+	}
+
+	return is_duplicate;
+}
+
+void receive_bat_packet(struct ethhdr *ethhdr, struct batman_packet *batman_packet, unsigned char *hna_buff, int hna_buff_len, struct batman_if *if_incoming)
+{
+	struct batman_if *batman_if;
+	struct orig_node *orig_neigh_node, *orig_node;
+	char orig_str[ETH_STR_LEN], prev_sender_str[ETH_STR_LEN], neigh_str[ETH_STR_LEN];
+	char has_directlink_flag;
+	char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0, is_broadcast = 0, is_bidirectional, is_single_hop_neigh, is_duplicate;
+	unsigned short if_incoming_seqno;
+
+	/* Silently drop when the batman packet is actually not a correct packet.
+	 *
+	 * This might happen if a packet is padded (e.g. Ethernet has a
+	 * minimum frame length of 64 byte) and the aggregation interprets
+	 * it as an additional length.
+	 *
+	 * TODO: A more sane solution would be to have a bit in the batman_packet
+	 * to detect whether the packet is the last packet in an aggregation.
+	 * Here we expect that the padding is always zero (or not 0x01)
+	 */
+	if (batman_packet->packet_type != BAT_PACKET)
+		return;
+
+	/* could be changed by schedule_own_packet() */
+	if_incoming_seqno = atomic_read(&if_incoming->seqno);
+
+	addr_to_string(orig_str, batman_packet->orig);
+	addr_to_string(prev_sender_str, batman_packet->prev_sender);
+	addr_to_string(neigh_str, ethhdr->h_source);
+
+	has_directlink_flag = (batman_packet->flags & DIRECTLINK ? 1 : 0);
+
+	is_single_hop_neigh = (compare_orig(ethhdr->h_source, batman_packet->orig) ? 1 : 0);
+
+	debug_log(LOG_TYPE_BATMAN, "Received BATMAN packet via NB: %s, IF: %s [%s] (from OG: %s, via prev OG: %s, seqno %d, tq %d, TTL %d, V %d, IDF %d) \n", neigh_str, if_incoming->dev, if_incoming->addr_str, orig_str, prev_sender_str, batman_packet->seqno, batman_packet->tq, batman_packet->ttl, batman_packet->version, has_directlink_flag);
+
+	list_for_each_entry_rcu(batman_if, &if_list, list) {
+		if (batman_if->if_active != IF_ACTIVE)
+			continue;
+
+		if (compare_orig(ethhdr->h_source, batman_if->net_dev->dev_addr))
+			is_my_addr = 1;
+
+		if (compare_orig(batman_packet->orig, batman_if->net_dev->dev_addr))
+			is_my_orig = 1;
+
+		if (compare_orig(batman_packet->prev_sender, batman_if->net_dev->dev_addr))
+			is_my_oldorig = 1;
+
+		if (compare_orig(ethhdr->h_source, broadcastAddr))
+			is_broadcast = 1;
+	}
+
+	if (batman_packet->version != COMPAT_VERSION) {
+		debug_log(LOG_TYPE_BATMAN, "Drop packet: incompatible batman version (%i) \n", batman_packet->version);
+		return;
+	}
+
+	if (is_my_addr) {
+		debug_log(LOG_TYPE_BATMAN, "Drop packet: received my own broadcast (sender: %s) \n", neigh_str);
+		return;
+	}
+
+	if (is_broadcast) {
+		debug_log(LOG_TYPE_BATMAN, "Drop packet: ignoring all packets with broadcast source addr (sender: %s) \n", neigh_str);
+		return;
+	}
+
+	if (is_my_orig) {
+		orig_neigh_node = get_orig_node(ethhdr->h_source);
+
+		/* neighbour has to indicate direct link and it has to come via the corresponding interface */
+		/* if received seqno equals last send seqno save new seqno for bidirectional check */
+		if (has_directlink_flag && compare_orig(if_incoming->net_dev->dev_addr, batman_packet->orig) &&
+				  (batman_packet->seqno - if_incoming_seqno + 2 == 0)) {
+			bit_mark((TYPE_OF_WORD *)&(orig_neigh_node->bcast_own[if_incoming->if_num * NUM_WORDS]), 0);
+			orig_neigh_node->bcast_own_sum[if_incoming->if_num] = bit_packet_count((TYPE_OF_WORD *)&(orig_neigh_node->bcast_own[if_incoming->if_num * NUM_WORDS]));
+		}
+
+		debug_log(LOG_TYPE_BATMAN, "Drop packet: originator packet from myself (via neighbour) \n");
+		return;
+	}
+
+	if (batman_packet->tq == 0) {
+		count_real_packets(ethhdr, batman_packet, if_incoming);
+
+		debug_log(LOG_TYPE_BATMAN, "Drop packet: originator packet with tq equal 0 \n");
+		return;
+	}
+
+	if (is_my_oldorig) {
+		debug_log(LOG_TYPE_BATMAN, "Drop packet: ignoring all rebroadcast echos (sender: %s) \n", neigh_str);
+		return;
+	}
+
+	is_duplicate = count_real_packets(ethhdr, batman_packet, if_incoming);
+
+	orig_node = get_orig_node(batman_packet->orig);
+	if (orig_node == NULL)
+		return;
+
+	/* avoid temporary routing loops */
+	if ((orig_node->router) && (orig_node->router->orig_node->router) &&
+	    (compare_orig(orig_node->router->addr, batman_packet->prev_sender)) &&
+	    !(compare_orig(batman_packet->orig, batman_packet->prev_sender)) &&
+	    (compare_orig(orig_node->router->addr, orig_node->router->orig_node->router->addr))) {
+		debug_log(LOG_TYPE_BATMAN, "Drop packet: ignoring all rebroadcast packets that may make me loop (sender: %s) \n", neigh_str);
+		return;
+	}
+
+	/* if sender is a direct neighbor the sender mac equals originator mac */
+	orig_neigh_node = (is_single_hop_neigh ? orig_node : get_orig_node(ethhdr->h_source));
+	if (orig_neigh_node == NULL)
+		return;
+
+	/* drop packet if sender is not a direct neighbor and if we don't route towards it */
+	if (!is_single_hop_neigh && (orig_neigh_node->router == NULL)) {
+		debug_log(LOG_TYPE_BATMAN, "Drop packet: OGM via unknown neighbor! \n");
+		return;
+	}
+
+	is_bidirectional = isBidirectionalNeigh(orig_node, orig_neigh_node, batman_packet, if_incoming);
+
+	/* update ranking if it is not a duplicate or has the same seqno and similar ttl as the non-duplicate */
+	if (is_bidirectional && (!is_duplicate ||
+		((orig_node->last_real_seqno == batman_packet->seqno) &&
+			(orig_node->last_ttl - 3 <= batman_packet->ttl))))
+		update_orig(orig_node, ethhdr, batman_packet, if_incoming, hna_buff, hna_buff_len, is_duplicate);
+
+	/* is single hop (direct) neighbour */
+	if (is_single_hop_neigh) {
+
+		/* mark direct link on incoming interface */
+		schedule_forward_packet(orig_node, ethhdr, batman_packet, 1, hna_buff_len, if_incoming);
+
+		debug_log(LOG_TYPE_BATMAN, "Forwarding packet: rebroadcast neighbour packet with direct link flag \n");
+		return;
+	}
+
+	/* multihop originator */
+	if (!is_bidirectional) {
+		debug_log(LOG_TYPE_BATMAN, "Drop packet: not received via bidirectional link\n");
+		return;
+	}
+
+	if (is_duplicate) {
+		debug_log(LOG_TYPE_BATMAN, "Drop packet: duplicate packet received\n");
+		return;
+	}
+
+	debug_log(LOG_TYPE_BATMAN, "Forwarding packet: rebroadcast originator packet \n");
+	schedule_forward_packet(orig_node, ethhdr, batman_packet, 0, hna_buff_len, if_incoming);
+}
+
+void purge_orig(struct work_struct *work)
+{
+	struct list_head *list_pos, *list_pos_tmp;
+	struct hash_it_t *hashit = NULL;
+	struct orig_node *orig_node;
+	struct neigh_node *neigh_node, *best_neigh_node;
+	char orig_str[ETH_STR_LEN], neigh_str[ETH_STR_LEN], neigh_purged;
+
+	spin_lock(&orig_hash_lock);
+
+	/* for all origins... */
+	while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
+
+		orig_node = hashit->bucket->data;
+		addr_to_string(orig_str, orig_node->orig);
+
+		if (time_after(jiffies, orig_node->last_valid + ((2 * PURGE_TIMEOUT * HZ) / 1000))) {
+
+			debug_log(LOG_TYPE_BATMAN, "Originator timeout: originator %s, last_valid %u \n", orig_str, (orig_node->last_valid / HZ));
+
+			hash_remove_bucket(orig_hash, hashit);
+			free_orig_node(orig_node);
+
+		} else {
+
+			best_neigh_node = NULL;
+			neigh_purged = 0;
+
+			/* for all neighbours towards this originator ... */
+			list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) {
+				neigh_node = list_entry(list_pos, struct neigh_node, list);
+
+				if (time_after(jiffies, neigh_node->last_valid + ((PURGE_TIMEOUT * HZ) / 1000))) {
+
+					addr_to_string(neigh_str, neigh_node->addr);
+					debug_log(LOG_TYPE_BATMAN, "Neighbour timeout: originator %s, neighbour: %s, last_valid %u \n", orig_str, neigh_str, (neigh_node->last_valid / HZ));
+
+					neigh_purged = 1;
+					list_del(list_pos);
+					kfree(neigh_node);
+
+				} else {
+
+					if ((best_neigh_node == NULL) || (neigh_node->tq_avg > best_neigh_node->tq_avg))
+						best_neigh_node = neigh_node;
+
+				}
+
+			}
+
+			if (neigh_purged)
+				update_routes(orig_node, best_neigh_node, orig_node->hna_buff, orig_node->hna_buff_len);
+
+		}
+
+	}
+
+	spin_unlock(&orig_hash_lock);
+
+	start_purge_timer();
+}
+
+static int receive_raw_packet(struct socket *raw_sock, unsigned char *packet_buff, int packet_buff_len)
+{
+	struct kvec iov;
+	struct msghdr msg;
+
+	iov.iov_base = packet_buff;
+	iov.iov_len = packet_buff_len;
+
+	msg.msg_flags = MSG_DONTWAIT;	/* non-blocking */
+	msg.msg_name = NULL;
+	msg.msg_namelen = 0;
+	msg.msg_control = NULL;
+
+	return kernel_recvmsg(raw_sock, &msg, &iov, 1, packet_buff_len, MSG_DONTWAIT);
+}
+
+int packet_recv_thread(void *data)
+{
+	struct batman_if *batman_if;
+	struct ethhdr *ethhdr;
+	struct batman_packet *batman_packet;
+	struct unicast_packet *unicast_packet;
+	struct bcast_packet *bcast_packet;
+	struct icmp_packet *icmp_packet;
+	struct vis_packet *vis_packet;
+	struct orig_node *orig_node;
+	unsigned char *packet_buff, src_str[ETH_STR_LEN], dst_str[ETH_STR_LEN];
+	int vis_info_len;
+	int result;
+
+	atomic_set(&data_ready_cond, 0);
+	atomic_set(&exit_cond, 0);
+	packet_buff = kmalloc(PACKBUFF_SIZE, GFP_KERNEL);
+	if (!packet_buff) {
+		debug_log(LOG_TYPE_CRIT, "Could allocate memory for the packet buffer. :(\n");
+		return -1;
+	}
+
+	while ((!kthread_should_stop()) && (!atomic_read(&exit_cond))) {
+
+		wait_event_interruptible(thread_wait, (atomic_read(&data_ready_cond) || atomic_read(&exit_cond)));
+
+		atomic_set(&data_ready_cond, 0);
+
+		if (kthread_should_stop() || atomic_read(&exit_cond))
+			break;
+
+		/* we only want to safely traverse the list, hard-interfaces
+		 * won't be deleted anyway as long as this thread runs. */
+
+		rcu_read_lock();
+		list_for_each_entry_rcu(batman_if, &if_list, list) {
+			rcu_read_unlock();
+
+			result = -1;
+
+			while (1) {
+				if (batman_if->if_active != IF_ACTIVE) {
+					if (batman_if->if_active != IF_TO_BE_ACTIVATED)
+						debug_log(LOG_TYPE_NOTICE,
+						          "Could not read from deactivated interface %s!\n",
+						          batman_if->dev);
+
+					if (batman_if->raw_sock)
+						receive_raw_packet(batman_if->raw_sock, packet_buff, PACKBUFF_SIZE);
+					result = 0;
+					break;
+				}
+
+				result = receive_raw_packet(batman_if->raw_sock, packet_buff, PACKBUFF_SIZE);
+				if (result <= 0)
+					break;
+
+				if (result < sizeof(struct ethhdr) + 2)
+					continue;
+
+				ethhdr = (struct ethhdr *)packet_buff;
+				batman_packet = (struct batman_packet *)(packet_buff + sizeof(struct ethhdr));
+
+				if (batman_packet->version != COMPAT_VERSION) {
+					debug_log(LOG_TYPE_BATMAN, "Drop packet: incompatible batman version (%i) \n", batman_packet->version);
+					continue;
+				}
+
+				switch (batman_packet->packet_type) {
+				/* batman originator packet */
+				case BAT_PACKET:
+					/* packet with broadcast indication but unicast recipient */
+					if (!is_bcast(ethhdr->h_dest))
+						continue;
+
+					/* packet with broadcast sender address */
+					if (is_bcast(ethhdr->h_source))
+						continue;
+
+					/* drop packet if it has not at least one batman packet as payload */
+					if (result < sizeof(struct ethhdr) + sizeof(struct batman_packet))
+						continue;
+
+					spin_lock(&orig_hash_lock);
+					receive_aggr_bat_packet(ethhdr,
+					                        packet_buff + sizeof(struct ethhdr),
+					                        result - sizeof(struct ethhdr),
+					                        batman_if);
+					spin_unlock(&orig_hash_lock);
+
+					break;
+
+				/* batman icmp packet */
+				case BAT_ICMP:
+					/* packet with unicast indication but broadcast recipient */
+					if (is_bcast(ethhdr->h_dest))
+						continue;
+
+					/* packet with broadcast sender address */
+					if (is_bcast(ethhdr->h_source))
+						continue;
+
+					/* not for me */
+					if (!is_my_mac(ethhdr->h_dest))
+						continue;
+
+					/* drop packet if it has not necessary minimum size */
+					if (result < sizeof(struct ethhdr) + sizeof(struct icmp_packet))
+						continue;
+
+					icmp_packet = (struct icmp_packet *)(packet_buff + sizeof(struct ethhdr));
+
+					/* packet for me */
+					if (is_my_mac(icmp_packet->dst)) {
+
+						/* add data to device queue */
+						if (icmp_packet->msg_type != ECHO_REQUEST) {
+							bat_device_receive_packet(icmp_packet);
+							continue;
+						}
+
+						/* answer echo request (ping) */
+						/* get routing information */
+						spin_lock(&orig_hash_lock);
+						orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet->orig));
+
+						if ((orig_node != NULL) && (orig_node->batman_if != NULL) && (orig_node->router != NULL)) {
+
+							memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
+							memcpy(icmp_packet->orig, ethhdr->h_dest, ETH_ALEN);
+							icmp_packet->msg_type = ECHO_REPLY;
+							icmp_packet->ttl = TTL;
+
+							send_raw_packet(packet_buff + sizeof(struct ethhdr),
+							                result - sizeof(struct ethhdr),
+							                orig_node->batman_if,
+							                orig_node->router->addr);
+
+						}
+
+						spin_unlock(&orig_hash_lock);
+						continue;
+
+					}
+
+					/* TTL exceeded */
+					if (icmp_packet->ttl < 2) {
+
+						addr_to_string(src_str, icmp_packet->orig);
+						addr_to_string(dst_str, icmp_packet->dst);
+
+						debug_log(LOG_TYPE_NOTICE, "Error - can't send packet from %s to %s: ttl exceeded\n", src_str, dst_str);
+
+						/* send TTL exceeded if packet is an echo request (traceroute) */
+						if (icmp_packet->msg_type != ECHO_REQUEST)
+							continue;
+
+						/* get routing information */
+						spin_lock(&orig_hash_lock);
+						orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet->orig));
+
+						if ((orig_node != NULL) && (orig_node->batman_if != NULL) && (orig_node->router != NULL)) {
+
+							memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
+							memcpy(icmp_packet->orig, ethhdr->h_dest, ETH_ALEN);
+							icmp_packet->msg_type = TTL_EXCEEDED;
+							icmp_packet->ttl = TTL;
+
+							send_raw_packet(packet_buff + sizeof(struct ethhdr),
+							                result - sizeof(struct ethhdr),
+							                orig_node->batman_if,
+							                orig_node->router->addr);
+
+						}
+
+						spin_unlock(&orig_hash_lock);
+						continue;
+
+					}
+
+					/* get routing information */
+					spin_lock(&orig_hash_lock);
+					orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet->dst));
+
+					if ((orig_node != NULL) && (orig_node->batman_if != NULL) && (orig_node->router != NULL)) {
+
+						/* decrement ttl */
+						icmp_packet->ttl--;
+
+						/* route it */
+						send_raw_packet(packet_buff + sizeof(struct ethhdr),
+						                result - sizeof(struct ethhdr),
+						                orig_node->batman_if,
+						                orig_node->router->addr);
+					}
+
+					spin_unlock(&orig_hash_lock);
+					break;
+
+				/* unicast packet */
+				case BAT_UNICAST:
+					/* packet with unicast indication but broadcast recipient */
+					if (is_bcast(ethhdr->h_dest))
+						continue;
+
+					/* packet with broadcast sender address */
+					if (is_bcast(ethhdr->h_source))
+						continue;
+
+					/* not for me */
+					if (!is_my_mac(ethhdr->h_dest))
+						continue;
+
+					/* drop packet if it has not necessary minimum size */
+					if (result < sizeof(struct ethhdr) + sizeof(struct unicast_packet))
+						continue;
+
+					unicast_packet = (struct unicast_packet *)(packet_buff + sizeof(struct ethhdr));
+
+					/* packet for me */
+					if (is_my_mac(unicast_packet->dest)) {
+
+						interface_rx(soft_device, packet_buff + sizeof(struct ethhdr) + sizeof(struct unicast_packet), result - sizeof(struct ethhdr) - sizeof(struct unicast_packet));
+						continue;
+
+					}
+
+					/* TTL exceeded */
+					if (unicast_packet->ttl < 2) {
+						addr_to_string(src_str, ((struct ethhdr *)(unicast_packet + 1))->h_source);
+						addr_to_string(dst_str, unicast_packet->dest);
+
+						debug_log(LOG_TYPE_NOTICE, "Error - can't send packet from %s to %s: ttl exceeded\n", src_str, dst_str);
+						continue;
+					}
+
+					/* get routing information */
+					spin_lock(&orig_hash_lock);
+					orig_node = ((struct orig_node *)hash_find(orig_hash, unicast_packet->dest));
+
+					if ((orig_node != NULL) && (orig_node->batman_if != NULL) && (orig_node->router != NULL)) {
+						/* decrement ttl */
+						unicast_packet->ttl--;
+
+						/* route it */
+						send_raw_packet(packet_buff + sizeof(struct ethhdr),
+						                result - sizeof(struct ethhdr),
+						                orig_node->batman_if,
+						                orig_node->router->addr);
+					}
+
+					spin_unlock(&orig_hash_lock);
+					break;
+
+				/* broadcast packet */
+				case BAT_BCAST:
+					/* packet with broadcast indication but unicast recipient */
+					if (!is_bcast(ethhdr->h_dest))
+						continue;
+
+					/* packet with broadcast sender address */
+					if (is_bcast(ethhdr->h_source))
+						continue;
+
+					/* drop packet if it has not necessary minimum size */
+					if (result < sizeof(struct ethhdr) + sizeof(struct bcast_packet))
+						continue;
+
+					/* ignore broadcasts sent by myself */
+					if (is_my_mac(ethhdr->h_source))
+						continue;
+
+					bcast_packet = (struct bcast_packet *)(packet_buff + sizeof(struct ethhdr));
+
+					/* ignore broadcasts originated by myself */
+					if (is_my_mac(bcast_packet->orig))
+						continue;
+
+					spin_lock(&orig_hash_lock);
+					orig_node = ((struct orig_node *)hash_find(orig_hash, bcast_packet->orig));
+
+					if (orig_node == NULL) {
+						spin_unlock(&orig_hash_lock);
+						continue;
+					}
+
+					/* check flood history */
+					if (get_bit_status(orig_node->bcast_bits, orig_node->last_bcast_seqno, ntohs(bcast_packet->seqno))) {
+						spin_unlock(&orig_hash_lock);
+						continue;
+					}
+
+					/* mark broadcast in flood history */
+					if (bit_get_packet(orig_node->bcast_bits, ntohs(bcast_packet->seqno) - orig_node->last_bcast_seqno, 1))
+						orig_node->last_bcast_seqno = ntohs(bcast_packet->seqno);
+
+					spin_unlock(&orig_hash_lock);
+
+					/* broadcast for me */
+					interface_rx(soft_device, packet_buff + sizeof(struct ethhdr) + sizeof(struct bcast_packet), result - sizeof(struct ethhdr) - sizeof(struct bcast_packet));
+
+					/* rebroadcast packet */
+					add_bcast_packet_to_list(packet_buff + sizeof(struct ethhdr),
+									result - sizeof(struct ethhdr));
+
+					break;
+
+				/* vis packet */
+				case BAT_VIS:
+					/* drop if too short. */
+					if (result < sizeof(struct ethhdr) + sizeof(struct vis_packet))
+						continue;
+
+					/* not for me */
+					if (!is_my_mac(ethhdr->h_dest))
+						continue;
+
+					vis_packet = (struct vis_packet *)(packet_buff + sizeof(struct ethhdr));
+					vis_info_len = result  - sizeof(struct ethhdr) - sizeof(struct vis_packet);
+
+					/* ignore own packets */
+					if (is_my_mac(vis_packet->vis_orig))
+						continue;
+
+					if (is_my_mac(vis_packet->sender_orig))
+						continue;
+
+					switch (vis_packet->vis_type) {
+					case VIS_TYPE_SERVER_SYNC:
+						receive_server_sync_packet(vis_packet, vis_info_len);
+						break;
+
+					case VIS_TYPE_CLIENT_UPDATE:
+						receive_client_update_packet(vis_packet, vis_info_len);
+						break;
+
+					default:	/* ignore unknown packet */
+						break;
+					}
+
+					break;
+				}
+
+			}
+
+			if ((result < 0) && (result != -EAGAIN))
+				debug_log(LOG_TYPE_CRIT, "Could not receive packet from interface %s: %i\n", batman_if->dev, result);
+
+			/* lock for the next iteration */
+			rcu_read_lock();
+		}
+		rcu_read_unlock();
+
+	}
+	kfree(packet_buff);
+
+	/* do not exit until kthread_stop() is actually called, otherwise it will wait for us
+	 * forever. */
+	while (!kthread_should_stop())
+		schedule();
+
+	return 0;
+}
+
+void batman_data_ready(struct sock *sk, int len)
+{
+	void (*data_ready)(struct sock *, int) = sk->sk_user_data;
+
+	data_ready(sk, len);
+
+	atomic_set(&data_ready_cond, 1);
+	wake_up_interruptible(&thread_wait);
+}
+

+ 34 - 0
drivers/staging/batman-adv/routing.h

@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#include "types.h"
+
+extern wait_queue_head_t thread_wait;
+extern atomic_t exit_cond;
+
+int originator_init(void);
+void free_orig_node(void *data);
+void originator_free(void);
+void slide_own_bcast_window(struct batman_if *batman_if);
+void batman_data_ready(struct sock *sk, int len);
+void purge_orig(struct work_struct *work);
+int packet_recv_thread(void *data);
+void receive_bat_packet(struct ethhdr *ethhdr, struct batman_packet *batman_packet, unsigned char *hna_buff, int hna_buff_len, struct batman_if *if_incoming);

+ 473 - 0
drivers/staging/batman-adv/send.c

@@ -0,0 +1,473 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#include "main.h"
+#include "send.h"
+#include "log.h"
+#include "routing.h"
+#include "translation-table.h"
+#include "hard-interface.h"
+#include "types.h"
+#include "vis.h"
+#include "aggregation.h"
+
+#include "compat.h"
+
+/* apply hop penalty for a normal link */
+static uint8_t hop_penalty(const uint8_t tq)
+{
+	return (tq * (TQ_MAX_VALUE - TQ_HOP_PENALTY)) / (TQ_MAX_VALUE);
+}
+
+/* when do we schedule our own packet to be sent */
+static unsigned long own_send_time(void)
+{
+	return jiffies +
+		(((atomic_read(&originator_interval) - JITTER +
+		   (random32() % 2*JITTER)) * HZ) / 1000);
+}
+
+/* when do we schedule a forwarded packet to be sent */
+static unsigned long forward_send_time(void)
+{
+	unsigned long send_time = jiffies; /* Starting now plus... */
+
+	if (atomic_read(&aggregation_enabled))
+		send_time += (((MAX_AGGREGATION_MS - (JITTER/2) +
+				(random32() % JITTER)) * HZ) / 1000);
+	else
+		send_time += (((random32() % (JITTER/2)) * HZ) / 1000);
+
+	return send_time;
+}
+
+/* sends a raw packet. */
+void send_raw_packet(unsigned char *pack_buff, int pack_buff_len,
+		     struct batman_if *batman_if, uint8_t *dst_addr)
+{
+	struct ethhdr *ethhdr;
+	struct sk_buff *skb;
+	int retval;
+	char *data;
+
+	if (batman_if->if_active != IF_ACTIVE)
+		return;
+
+	if (!(batman_if->net_dev->flags & IFF_UP)) {
+		debug_log(LOG_TYPE_WARN,
+		         "Interface %s is not up - can't send packet via that interface (IF_TO_BE_DEACTIVATED was here) !\n",
+		          batman_if->dev);
+		return;
+	}
+
+	skb = dev_alloc_skb(pack_buff_len + sizeof(struct ethhdr));
+	if (!skb)
+		return;
+	data = skb_put(skb, pack_buff_len + sizeof(struct ethhdr));
+
+	memcpy(data + sizeof(struct ethhdr), pack_buff, pack_buff_len);
+
+	ethhdr = (struct ethhdr *) data;
+	memcpy(ethhdr->h_source, batman_if->net_dev->dev_addr, ETH_ALEN);
+	memcpy(ethhdr->h_dest, dst_addr, ETH_ALEN);
+	ethhdr->h_proto = __constant_htons(ETH_P_BATMAN);
+
+	skb_reset_mac_header(skb);
+	skb_set_network_header(skb, ETH_HLEN);
+	skb->priority = TC_PRIO_CONTROL;
+	skb->protocol = __constant_htons(ETH_P_BATMAN);
+	skb->dev = batman_if->net_dev;
+
+	/* dev_queue_xmit() returns a negative result on error.	 However on
+	 * congestion and traffic shaping, it drops and returns NET_XMIT_DROP
+	 * (which is > 0). This will not be treated as an error. */
+	retval = dev_queue_xmit(skb);
+	if (retval < 0)
+		debug_log(LOG_TYPE_CRIT,
+		          "Can't write to raw socket (IF_TO_BE_DEACTIVATED was here): %i\n",
+		          retval);
+}
+
+/* Send a packet to a given interface */
+static void send_packet_to_if(struct forw_packet *forw_packet,
+			      struct batman_if *batman_if)
+{
+	char *fwd_str;
+	uint8_t packet_num;
+	int16_t buff_pos;
+	struct batman_packet *batman_packet;
+	char orig_str[ETH_STR_LEN];
+
+	if (batman_if->if_active != IF_ACTIVE)
+		return;
+
+	packet_num = buff_pos = 0;
+	batman_packet = (struct batman_packet *)
+		(forw_packet->packet_buff);
+
+	/* adjust all flags and log packets */
+	while (aggregated_packet(buff_pos,
+				 forw_packet->packet_len,
+				 batman_packet->num_hna)) {
+
+		/* we might have aggregated direct link packets with an
+		 * ordinary base packet */
+		if ((forw_packet->direct_link_flags & (1 << packet_num)) &&
+		    (forw_packet->if_incoming == batman_if))
+			batman_packet->flags |= DIRECTLINK;
+		else
+			batman_packet->flags &= ~DIRECTLINK;
+
+		addr_to_string(orig_str, batman_packet->orig);
+		fwd_str = (packet_num > 0 ? "Forwarding" : (forw_packet->own ?
+							    "Sending own" :
+							    "Forwarding"));
+		debug_log(LOG_TYPE_BATMAN,
+			  "%s %spacket (originator %s, seqno %d, TQ %d, TTL %d, IDF %s) on interface %s [%s]\n",
+			  fwd_str,
+			  (packet_num > 0 ? "aggregated " : ""),
+			  orig_str, ntohs(batman_packet->seqno),
+			  batman_packet->tq, batman_packet->ttl,
+			  (batman_packet->flags & DIRECTLINK ?
+			   "on" : "off"),
+			  batman_if->dev, batman_if->addr_str);
+
+		buff_pos += sizeof(struct batman_packet) +
+			(batman_packet->num_hna * ETH_ALEN);
+		packet_num++;
+		batman_packet = (struct batman_packet *)
+			(forw_packet->packet_buff + buff_pos);
+	}
+
+	send_raw_packet(forw_packet->packet_buff,
+			forw_packet->packet_len,
+			batman_if, broadcastAddr);
+}
+
+/* send a batman packet */
+static void send_packet(struct forw_packet *forw_packet)
+{
+	struct batman_if *batman_if;
+	struct batman_packet *batman_packet =
+		(struct batman_packet *)(forw_packet->packet_buff);
+	char orig_str[ETH_STR_LEN];
+	unsigned char directlink = (batman_packet->flags & DIRECTLINK ? 1 : 0);
+
+	if (!forw_packet->if_incoming) {
+		debug_log(LOG_TYPE_CRIT,
+			  "Error - can't forward packet: incoming iface not specified\n");
+		return;
+	}
+
+	if (forw_packet->if_incoming->if_active != IF_ACTIVE)
+		return;
+
+	addr_to_string(orig_str, batman_packet->orig);
+
+	/* multihomed peer assumed */
+	/* non-primary OGMs are only broadcasted on their interface */
+	if ((directlink && (batman_packet->ttl == 1)) ||
+	    (forw_packet->own && (forw_packet->if_incoming->if_num > 0))) {
+
+		/* FIXME: what about aggregated packets ? */
+		debug_log(LOG_TYPE_BATMAN,
+			  "%s packet (originator %s, seqno %d, TTL %d) on interface %s [%s]\n",
+			  (forw_packet->own ? "Sending own" : "Forwarding"),
+			  orig_str, ntohs(batman_packet->seqno),
+			  batman_packet->ttl, forw_packet->if_incoming->dev,
+			  forw_packet->if_incoming->addr_str);
+
+		send_raw_packet(forw_packet->packet_buff,
+				forw_packet->packet_len,
+				forw_packet->if_incoming,
+				broadcastAddr);
+		return;
+	}
+
+	/* broadcast on every interface */
+	rcu_read_lock();
+	list_for_each_entry_rcu(batman_if, &if_list, list)
+		send_packet_to_if(forw_packet, batman_if);
+	rcu_read_unlock();
+}
+
+static void rebuild_batman_packet(struct batman_if *batman_if)
+{
+	int new_len;
+	unsigned char *new_buff;
+	struct batman_packet *batman_packet;
+
+	new_len = sizeof(struct batman_packet) + (num_hna * ETH_ALEN);
+	new_buff = kmalloc(new_len, GFP_ATOMIC);
+
+	/* keep old buffer if kmalloc should fail */
+	if (new_buff) {
+		memcpy(new_buff, batman_if->packet_buff,
+		       sizeof(struct batman_packet));
+		batman_packet = (struct batman_packet *)new_buff;
+
+		batman_packet->num_hna = hna_local_fill_buffer(
+			new_buff + sizeof(struct batman_packet),
+			new_len - sizeof(struct batman_packet));
+
+		kfree(batman_if->packet_buff);
+		batman_if->packet_buff = new_buff;
+		batman_if->packet_len = new_len;
+	}
+}
+
+void schedule_own_packet(struct batman_if *batman_if)
+{
+	unsigned long send_time;
+	struct batman_packet *batman_packet;
+
+	/**
+	 * the interface gets activated here to avoid race conditions between
+	 * the moment of activating the interface in
+	 * hardif_activate_interface() where the originator mac is set and
+	 * outdated packets (especially uninitialized mac addresses) in the
+	 * packet queue
+	 */
+	if (batman_if->if_active == IF_TO_BE_ACTIVATED)
+		batman_if->if_active = IF_ACTIVE;
+
+	/* if local hna has changed and interface is a primary interface */
+	if ((atomic_read(&hna_local_changed)) && (batman_if->if_num == 0))
+		rebuild_batman_packet(batman_if);
+
+	/**
+	 * NOTE: packet_buff might just have been re-allocated in
+	 * rebuild_batman_packet()
+	 */
+	batman_packet = (struct batman_packet *)batman_if->packet_buff;
+
+	/* change sequence number to network order */
+	batman_packet->seqno = htons((uint16_t)atomic_read(&batman_if->seqno));
+
+	if (is_vis_server())
+		batman_packet->flags = VIS_SERVER;
+	else
+		batman_packet->flags = 0;
+
+	/* could be read by receive_bat_packet() */
+	atomic_inc(&batman_if->seqno);
+
+	slide_own_bcast_window(batman_if);
+	send_time = own_send_time();
+	add_bat_packet_to_list(batman_if->packet_buff,
+			       batman_if->packet_len, batman_if, 1, send_time);
+}
+
+void schedule_forward_packet(struct orig_node *orig_node,
+			     struct ethhdr *ethhdr,
+			     struct batman_packet *batman_packet,
+			     uint8_t directlink, int hna_buff_len,
+			     struct batman_if *if_incoming)
+{
+	unsigned char in_tq, in_ttl, tq_avg = 0;
+	unsigned long send_time;
+
+	if (batman_packet->ttl <= 1) {
+		debug_log(LOG_TYPE_BATMAN, "ttl exceeded \n");
+		return;
+	}
+
+	in_tq = batman_packet->tq;
+	in_ttl = batman_packet->ttl;
+
+	batman_packet->ttl--;
+	memcpy(batman_packet->prev_sender, ethhdr->h_source, ETH_ALEN);
+
+	/* rebroadcast tq of our best ranking neighbor to ensure the rebroadcast
+	 * of our best tq value */
+	if ((orig_node->router) && (orig_node->router->tq_avg != 0)) {
+
+		/* rebroadcast ogm of best ranking neighbor as is */
+		if (!compare_orig(orig_node->router->addr, ethhdr->h_source)) {
+			batman_packet->tq = orig_node->router->tq_avg;
+
+			if (orig_node->router->last_ttl)
+				batman_packet->ttl = orig_node->router->last_ttl - 1;
+		}
+
+		tq_avg = orig_node->router->tq_avg;
+	}
+
+	/* apply hop penalty */
+	batman_packet->tq = hop_penalty(batman_packet->tq);
+
+	debug_log(LOG_TYPE_BATMAN, "Forwarding packet: tq_orig: %i, tq_avg: %i, tq_forw: %i, ttl_orig: %i, ttl_forw: %i \n",
+		  in_tq, tq_avg, batman_packet->tq, in_ttl - 1,
+		  batman_packet->ttl);
+
+	batman_packet->seqno = htons(batman_packet->seqno);
+
+	if (directlink)
+		batman_packet->flags |= DIRECTLINK;
+	else
+		batman_packet->flags &= ~DIRECTLINK;
+
+	send_time = forward_send_time();
+	add_bat_packet_to_list((unsigned char *)batman_packet,
+			       sizeof(struct batman_packet) + hna_buff_len,
+			       if_incoming, 0, send_time);
+}
+
+static void forw_packet_free(struct forw_packet *forw_packet)
+{
+	kfree(forw_packet->packet_buff);
+	kfree(forw_packet);
+}
+
+static void _add_bcast_packet_to_list(struct forw_packet *forw_packet,
+				      unsigned long send_time)
+{
+	INIT_HLIST_NODE(&forw_packet->list);
+
+	/* add new packet to packet list */
+	spin_lock(&forw_bcast_list_lock);
+	hlist_add_head(&forw_packet->list, &forw_bcast_list);
+	spin_unlock(&forw_bcast_list_lock);
+
+	/* start timer for this packet */
+	INIT_DELAYED_WORK(&forw_packet->delayed_work,
+			  send_outstanding_bcast_packet);
+	queue_delayed_work(bat_event_workqueue, &forw_packet->delayed_work,
+			   send_time);
+}
+
+void add_bcast_packet_to_list(unsigned char *packet_buff, int packet_len)
+{
+	struct forw_packet *forw_packet;
+
+	forw_packet = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC);
+	if (!forw_packet)
+		return;
+
+	forw_packet->packet_buff = kmalloc(packet_len, GFP_ATOMIC);
+	if (!forw_packet->packet_buff)
+		return;
+
+	forw_packet->packet_len = packet_len;
+	memcpy(forw_packet->packet_buff, packet_buff, forw_packet->packet_len);
+
+	/* how often did we send the bcast packet ? */
+	forw_packet->num_packets = 0;
+
+	_add_bcast_packet_to_list(forw_packet, 1);
+}
+
+void send_outstanding_bcast_packet(struct work_struct *work)
+{
+	struct batman_if *batman_if;
+	struct delayed_work *delayed_work =
+		container_of(work, struct delayed_work, work);
+	struct forw_packet *forw_packet =
+		container_of(delayed_work, struct forw_packet, delayed_work);
+
+	spin_lock(&forw_bcast_list_lock);
+	hlist_del(&forw_packet->list);
+	spin_unlock(&forw_bcast_list_lock);
+
+	/* rebroadcast packet */
+	rcu_read_lock();
+	list_for_each_entry_rcu(batman_if, &if_list, list) {
+		send_raw_packet(forw_packet->packet_buff,
+				forw_packet->packet_len,
+				batman_if, broadcastAddr);
+	}
+	rcu_read_unlock();
+
+	forw_packet->num_packets++;
+
+	/* if we still have some more bcasts to send and we are not shutting
+	 * down */
+	if ((forw_packet->num_packets < 3) &&
+	    (atomic_read(&module_state) != MODULE_DEACTIVATING))
+		_add_bcast_packet_to_list(forw_packet, ((5 * HZ) / 1000));
+	else
+		forw_packet_free(forw_packet);
+}
+
+void send_outstanding_bat_packet(struct work_struct *work)
+{
+	struct delayed_work *delayed_work =
+		container_of(work, struct delayed_work, work);
+	struct forw_packet *forw_packet =
+		container_of(delayed_work, struct forw_packet, delayed_work);
+
+	spin_lock(&forw_bat_list_lock);
+	hlist_del(&forw_packet->list);
+	spin_unlock(&forw_bat_list_lock);
+
+	send_packet(forw_packet);
+
+	/**
+	 * we have to have at least one packet in the queue
+	 * to determine the queues wake up time unless we are
+	 * shutting down
+	 */
+	if ((forw_packet->own) &&
+	    (atomic_read(&module_state) != MODULE_DEACTIVATING))
+		schedule_own_packet(forw_packet->if_incoming);
+
+	forw_packet_free(forw_packet);
+}
+
+void purge_outstanding_packets(void)
+{
+	struct forw_packet *forw_packet;
+	struct hlist_node *tmp_node, *safe_tmp_node;
+
+	debug_log(LOG_TYPE_BATMAN, "purge_outstanding_packets()\n");
+
+	/* free bcast list */
+	spin_lock(&forw_bcast_list_lock);
+	hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node,
+				  &forw_bcast_list, list) {
+
+		spin_unlock(&forw_bcast_list_lock);
+
+		/**
+		 * send_outstanding_bcast_packet() will lock the list to
+		 * delete the item from the list
+		 */
+		cancel_delayed_work_sync(&forw_packet->delayed_work);
+		spin_lock(&forw_bcast_list_lock);
+	}
+	spin_unlock(&forw_bcast_list_lock);
+
+	/* free batman packet list */
+	spin_lock(&forw_bat_list_lock);
+	hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node,
+				  &forw_bat_list, list) {
+
+		spin_unlock(&forw_bat_list_lock);
+
+		/**
+		 * send_outstanding_bat_packet() will lock the list to
+		 * delete the item from the list
+		 */
+		cancel_delayed_work_sync(&forw_packet->delayed_work);
+		spin_lock(&forw_bat_list_lock);
+	}
+	spin_unlock(&forw_bat_list_lock);
+}

+ 36 - 0
drivers/staging/batman-adv/send.h

@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#include "types.h"
+
+void send_own_packet_work(struct work_struct *work);
+void send_raw_packet(unsigned char *pack_buff, int pack_buff_len,
+		     struct batman_if *batman_if, uint8_t *dst_addr);
+void schedule_own_packet(struct batman_if *batman_if);
+void schedule_forward_packet(struct orig_node *orig_node,
+			     struct ethhdr *ethhdr,
+			     struct batman_packet *batman_packet,
+			     uint8_t directlink, int hna_buff_len,
+			     struct batman_if *if_outgoing);
+void add_bcast_packet_to_list(unsigned char *packet_buff, int packet_len);
+void send_outstanding_bcast_packet(struct work_struct *work);
+void send_outstanding_bat_packet(struct work_struct *work);
+void purge_outstanding_packets(void);

+ 349 - 0
drivers/staging/batman-adv/soft-interface.c

@@ -0,0 +1,349 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#include "main.h"
+#include "soft-interface.h"
+#include "hard-interface.h"
+#include "send.h"
+#include "translation-table.h"
+#include "log.h"
+#include "types.h"
+#include "hash.h"
+#include <linux/ethtool.h>
+#include <linux/etherdevice.h>
+#include "compat.h"
+
+static uint16_t bcast_seqno = 1; /* give own bcast messages seq numbers to avoid
+				  * broadcast storms */
+static int32_t skb_packets;
+static int32_t skb_bad_packets;
+static int32_t lock_dropped;
+
+unsigned char mainIfAddr[ETH_ALEN];
+static unsigned char mainIfAddr_default[ETH_ALEN];
+static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd);
+static void bat_get_drvinfo(struct net_device *dev,
+			    struct ethtool_drvinfo *info);
+static u32 bat_get_msglevel(struct net_device *dev);
+static void bat_set_msglevel(struct net_device *dev, u32 value);
+static u32 bat_get_link(struct net_device *dev);
+static u32 bat_get_rx_csum(struct net_device *dev);
+static int bat_set_rx_csum(struct net_device *dev, u32 data);
+
+static const struct ethtool_ops bat_ethtool_ops = {
+	.get_settings = bat_get_settings,
+	.get_drvinfo = bat_get_drvinfo,
+	.get_msglevel = bat_get_msglevel,
+	.set_msglevel = bat_set_msglevel,
+	.get_link = bat_get_link,
+	.get_rx_csum = bat_get_rx_csum,
+	.set_rx_csum = bat_set_rx_csum
+};
+
+void set_main_if_addr(uint8_t *addr)
+{
+	memcpy(mainIfAddr, addr, ETH_ALEN);
+}
+
+int main_if_was_up(void)
+{
+	return (memcmp(mainIfAddr, mainIfAddr_default, ETH_ALEN) != 0 ? 1 : 0);
+}
+
+static int my_skb_push(struct sk_buff *skb, unsigned int len)
+{
+	int result = 0;
+
+	skb_packets++;
+	if (skb->data - len < skb->head) {
+		skb_bad_packets++;
+		result = pskb_expand_head(skb, len, 0, GFP_ATOMIC);
+
+		if (result < 0)
+			return result;
+	}
+
+	skb_push(skb, len);
+	return 0;
+}
+
+#ifdef HAVE_NET_DEVICE_OPS
+static const struct net_device_ops bat_netdev_ops = {
+	.ndo_open = interface_open,
+	.ndo_stop = interface_release,
+	.ndo_get_stats = interface_stats,
+	.ndo_set_mac_address = interface_set_mac_addr,
+	.ndo_change_mtu = interface_change_mtu,
+	.ndo_start_xmit = interface_tx,
+	.ndo_validate_addr = eth_validate_addr
+};
+#endif
+
+void interface_setup(struct net_device *dev)
+{
+	struct bat_priv *priv = netdev_priv(dev);
+	char dev_addr[ETH_ALEN];
+
+	ether_setup(dev);
+
+#ifdef HAVE_NET_DEVICE_OPS
+	dev->netdev_ops = &bat_netdev_ops;
+#else
+	dev->open = interface_open;
+	dev->stop = interface_release;
+	dev->get_stats = interface_stats;
+	dev->set_mac_address = interface_set_mac_addr;
+	dev->change_mtu = interface_change_mtu;
+	dev->hard_start_xmit = interface_tx;
+#endif
+	dev->destructor = free_netdev;
+
+	dev->mtu = hardif_min_mtu();
+	dev->hard_header_len = BAT_HEADER_LEN; /* reserve more space in the
+						* skbuff for our header */
+
+	/* generate random address */
+	random_ether_addr(dev_addr);
+	memcpy(dev->dev_addr, dev_addr, sizeof(dev->dev_addr));
+
+	SET_ETHTOOL_OPS(dev, &bat_ethtool_ops);
+
+	memset(priv, 0, sizeof(struct bat_priv));
+}
+
+int interface_open(struct net_device *dev)
+{
+	netif_start_queue(dev);
+	return 0;
+}
+
+int interface_release(struct net_device *dev)
+{
+	netif_stop_queue(dev);
+	return 0;
+}
+
+struct net_device_stats *interface_stats(struct net_device *dev)
+{
+	struct bat_priv *priv = netdev_priv(dev);
+	return &priv->stats;
+}
+
+int interface_set_mac_addr(struct net_device *dev, void *addr)
+{
+	return -EBUSY;
+}
+
+int interface_change_mtu(struct net_device *dev, int new_mtu)
+{
+	/* check ranges */
+	if ((new_mtu < 68) || (new_mtu > hardif_min_mtu()))
+		return -EINVAL;
+
+	dev->mtu = new_mtu;
+
+	return 0;
+}
+
+int interface_tx(struct sk_buff *skb, struct net_device *dev)
+{
+	struct unicast_packet *unicast_packet;
+	struct bcast_packet *bcast_packet;
+	struct orig_node *orig_node;
+	struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
+	struct bat_priv *priv = netdev_priv(dev);
+	int data_len = skb->len;
+
+	if (atomic_read(&module_state) != MODULE_ACTIVE)
+		goto dropped;
+
+	dev->trans_start = jiffies;
+	/* TODO: check this for locks */
+	hna_local_add(ethhdr->h_source);
+
+	/* ethernet packet should be broadcasted */
+	if (is_bcast(ethhdr->h_dest) || is_mcast(ethhdr->h_dest)) {
+
+		if (my_skb_push(skb, sizeof(struct bcast_packet)) < 0)
+			goto dropped;
+
+		bcast_packet = (struct bcast_packet *)skb->data;
+
+		bcast_packet->version = COMPAT_VERSION;
+
+		/* batman packet type: broadcast */
+		bcast_packet->packet_type = BAT_BCAST;
+
+		/* hw address of first interface is the orig mac because only
+		 * this mac is known throughout the mesh */
+		memcpy(bcast_packet->orig, mainIfAddr, ETH_ALEN);
+		/* set broadcast sequence number */
+		bcast_packet->seqno = htons(bcast_seqno);
+
+		bcast_seqno++;
+
+		/* broadcast packet */
+		add_bcast_packet_to_list(skb->data, skb->len);
+
+	/* unicast packet */
+	} else {
+
+		/* simply spin_lock()ing can deadlock when the lock is already
+		 * hold. */
+		/* TODO: defer the work in a working queue instead of
+		 * dropping */
+		if (!spin_trylock(&orig_hash_lock)) {
+			lock_dropped++;
+			debug_log(LOG_TYPE_NOTICE, "%d packets dropped because lock was hold\n", lock_dropped);
+			goto dropped;
+		}
+
+		/* get routing information */
+		orig_node = ((struct orig_node *)hash_find(orig_hash,
+							   ethhdr->h_dest));
+
+		/* check for hna host */
+		if (!orig_node)
+			orig_node = transtable_search(ethhdr->h_dest);
+
+		if ((orig_node) &&
+		    (orig_node->batman_if) &&
+		    (orig_node->router)) {
+			if (my_skb_push(skb, sizeof(struct unicast_packet)) < 0)
+				goto unlock;
+
+			unicast_packet = (struct unicast_packet *)skb->data;
+
+			unicast_packet->version = COMPAT_VERSION;
+			/* batman packet type: unicast */
+			unicast_packet->packet_type = BAT_UNICAST;
+			/* set unicast ttl */
+			unicast_packet->ttl = TTL;
+			/* copy the destination for faster routing */
+			memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
+
+			/* net_dev won't be available when not active */
+			if (orig_node->batman_if->if_active != IF_ACTIVE)
+				goto unlock;
+
+			send_raw_packet(skb->data, skb->len,
+					orig_node->batman_if,
+					orig_node->router->addr);
+		} else {
+			goto unlock;
+		}
+
+		spin_unlock(&orig_hash_lock);
+	}
+
+	priv->stats.tx_packets++;
+	priv->stats.tx_bytes += data_len;
+	goto end;
+
+unlock:
+	spin_unlock(&orig_hash_lock);
+dropped:
+	priv->stats.tx_dropped++;
+end:
+	kfree_skb(skb);
+	return 0;
+}
+
+void interface_rx(struct net_device *dev, void *packet, int packet_len)
+{
+	struct sk_buff *skb;
+	struct bat_priv *priv = netdev_priv(dev);
+
+	skb = dev_alloc_skb(packet_len);
+
+	if (!skb) {
+		priv->stats.rx_dropped++;
+		goto out;
+	}
+
+	memcpy(skb_put(skb, packet_len), packet, packet_len);
+
+	/* Write metadata, and then pass to the receive level */
+	skb->dev = dev;
+	skb->protocol = eth_type_trans(skb, dev);
+	skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+	priv->stats.rx_packets++;
+	priv->stats.rx_bytes += packet_len;
+
+	dev->last_rx = jiffies;
+
+	netif_rx(skb);
+
+out:
+	return;
+}
+
+/* ethtool */
+static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	cmd->supported = 0;
+	cmd->advertising = 0;
+	cmd->speed = SPEED_10;
+	cmd->duplex = DUPLEX_FULL;
+	cmd->port = PORT_TP;
+	cmd->phy_address = 0;
+	cmd->transceiver = XCVR_INTERNAL;
+	cmd->autoneg = AUTONEG_DISABLE;
+	cmd->maxtxpkt = 0;
+	cmd->maxrxpkt = 0;
+
+	return 0;
+}
+
+static void bat_get_drvinfo(struct net_device *dev,
+			    struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, "B.A.T.M.A.N. advanced");
+	strcpy(info->version, SOURCE_VERSION);
+	strcpy(info->fw_version, "N/A");
+	strcpy(info->bus_info, "batman");
+}
+
+static u32 bat_get_msglevel(struct net_device *dev)
+{
+	return -EOPNOTSUPP;
+}
+
+static void bat_set_msglevel(struct net_device *dev, u32 value)
+{
+	return;
+}
+
+static u32 bat_get_link(struct net_device *dev)
+{
+	return 1;
+}
+
+static u32 bat_get_rx_csum(struct net_device *dev)
+{
+	return 0;
+}
+
+static int bat_set_rx_csum(struct net_device *dev, u32 data)
+{
+	return -EOPNOTSUPP;
+}

+ 33 - 0
drivers/staging/batman-adv/soft-interface.h

@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+void set_main_if_addr(uint8_t *addr);
+int main_if_was_up(void);
+void interface_setup(struct net_device *dev);
+int interface_open(struct net_device *dev);
+int interface_release(struct net_device *dev);
+struct net_device_stats *interface_stats(struct net_device *dev);
+int interface_set_mac_addr(struct net_device *dev, void *addr);
+int interface_change_mtu(struct net_device *dev, int new_mtu);
+int interface_tx(struct sk_buff *skb, struct net_device *dev);
+void interface_rx(struct net_device *dev, void *packet, int packet_len);
+
+extern unsigned char mainIfAddr[];

+ 454 - 0
drivers/staging/batman-adv/translation-table.c

@@ -0,0 +1,454 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#include "main.h"
+#include "translation-table.h"
+#include "log.h"
+#include "soft-interface.h"
+#include "types.h"
+#include "hash.h"
+#include "compat.h"
+
+struct hashtable_t *hna_local_hash;
+static struct hashtable_t *hna_global_hash;
+atomic_t hna_local_changed;
+
+DEFINE_SPINLOCK(hna_local_hash_lock);
+static DEFINE_SPINLOCK(hna_global_hash_lock);
+
+static DECLARE_DELAYED_WORK(hna_local_purge_wq, hna_local_purge);
+
+static void hna_local_start_timer(void)
+{
+	queue_delayed_work(bat_event_workqueue, &hna_local_purge_wq, 10 * HZ);
+}
+
+int hna_local_init(void)
+{
+	if (hna_local_hash)
+		return 1;
+
+	hna_local_hash = hash_new(128, compare_orig, choose_orig);
+
+	if (!hna_local_hash)
+		return 0;
+
+	atomic_set(&hna_local_changed, 0);
+	hna_local_start_timer();
+
+	return 1;
+}
+
+void hna_local_add(uint8_t *addr)
+{
+	struct hna_local_entry *hna_local_entry;
+	struct hna_global_entry *hna_global_entry;
+	struct hashtable_t *swaphash;
+	char hna_str[ETH_STR_LEN];
+	unsigned long flags;
+
+	spin_lock_irqsave(&hna_local_hash_lock, flags);
+	hna_local_entry =
+		((struct hna_local_entry *)hash_find(hna_local_hash, addr));
+	spin_unlock_irqrestore(&hna_local_hash_lock, flags);
+
+	if (hna_local_entry != NULL) {
+		hna_local_entry->last_seen = jiffies;
+		return;
+	}
+
+	addr_to_string(hna_str, addr);
+
+	/* only announce as many hosts as possible in the batman-packet and
+	   space in batman_packet->num_hna That also should give a limit to
+	   MAC-flooding. */
+	if ((num_hna + 1 > (ETH_DATA_LEN - BAT_PACKET_LEN) / ETH_ALEN) ||
+	    (num_hna + 1 > 255)) {
+		debug_log(LOG_TYPE_ROUTES, "Can't add new local hna entry (%s): number of local hna entries exceeds packet size \n", hna_str);
+		return;
+	}
+
+	debug_log(LOG_TYPE_ROUTES, "Creating new local hna entry: %s \n",
+		  hna_str);
+
+	hna_local_entry = kmalloc(sizeof(struct hna_local_entry), GFP_ATOMIC);
+	if (!hna_local_entry)
+		return;
+
+	memcpy(hna_local_entry->addr, addr, ETH_ALEN);
+	hna_local_entry->last_seen = jiffies;
+
+	/* the batman interface mac address should never be purged */
+	if (compare_orig(addr, soft_device->dev_addr))
+		hna_local_entry->never_purge = 1;
+	else
+		hna_local_entry->never_purge = 0;
+
+	spin_lock_irqsave(&hna_local_hash_lock, flags);
+
+	hash_add(hna_local_hash, hna_local_entry);
+	num_hna++;
+	atomic_set(&hna_local_changed, 1);
+
+	if (hna_local_hash->elements * 4 > hna_local_hash->size) {
+		swaphash = hash_resize(hna_local_hash,
+				       hna_local_hash->size * 2);
+
+		if (swaphash == NULL)
+			debug_log(LOG_TYPE_CRIT, "Couldn't resize local hna hash table \n");
+		else
+			hna_local_hash = swaphash;
+	}
+
+	spin_unlock_irqrestore(&hna_local_hash_lock, flags);
+
+	/* remove address from global hash if present */
+	spin_lock_irqsave(&hna_global_hash_lock, flags);
+
+	hna_global_entry =
+		((struct hna_global_entry *)hash_find(hna_global_hash, addr));
+
+	if (hna_global_entry != NULL)
+		_hna_global_del_orig(hna_global_entry, "local hna received");
+
+	spin_unlock_irqrestore(&hna_global_hash_lock, flags);
+}
+
+int hna_local_fill_buffer(unsigned char *buff, int buff_len)
+{
+	struct hna_local_entry *hna_local_entry;
+	struct hash_it_t *hashit = NULL;
+	int i = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hna_local_hash_lock, flags);
+
+	while (NULL != (hashit = hash_iterate(hna_local_hash, hashit))) {
+
+		if (buff_len < (i + 1) * ETH_ALEN)
+			break;
+
+		hna_local_entry = hashit->bucket->data;
+		memcpy(buff + (i * ETH_ALEN), hna_local_entry->addr, ETH_ALEN);
+
+		i++;
+	}
+
+	/* if we did not get all new local hnas see you next time  ;-) */
+	if (i == num_hna)
+		atomic_set(&hna_local_changed, 0);
+
+	spin_unlock_irqrestore(&hna_local_hash_lock, flags);
+
+	return i;
+}
+
+int hna_local_fill_buffer_text(unsigned char *buff, int buff_len)
+{
+	struct hna_local_entry *hna_local_entry;
+	struct hash_it_t *hashit = NULL;
+	int bytes_written = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hna_local_hash_lock, flags);
+
+	while (NULL != (hashit = hash_iterate(hna_local_hash, hashit))) {
+
+		if (buff_len < bytes_written + ETH_STR_LEN + 4)
+			break;
+
+		hna_local_entry = hashit->bucket->data;
+
+		bytes_written += snprintf(buff + bytes_written, ETH_STR_LEN + 4,
+					  " * %02x:%02x:%02x:%02x:%02x:%02x\n",
+					  hna_local_entry->addr[0],
+					  hna_local_entry->addr[1],
+					  hna_local_entry->addr[2],
+					  hna_local_entry->addr[3],
+					  hna_local_entry->addr[4],
+					  hna_local_entry->addr[5]);
+	}
+
+	spin_unlock_irqrestore(&hna_local_hash_lock, flags);
+
+	return bytes_written;
+}
+
+static void _hna_local_del(void *data)
+{
+	kfree(data);
+	num_hna--;
+	atomic_set(&hna_local_changed, 1);
+}
+
+static void hna_local_del(struct hna_local_entry *hna_local_entry,
+			  char *message)
+{
+	char hna_str[ETH_STR_LEN];
+
+	addr_to_string(hna_str, hna_local_entry->addr);
+	debug_log(LOG_TYPE_ROUTES, "Deleting local hna entry (%s): %s \n",
+		  hna_str, message);
+
+	hash_remove(hna_local_hash, hna_local_entry->addr);
+	_hna_local_del(hna_local_entry);
+}
+
+void hna_local_purge(struct work_struct *work)
+{
+	struct hna_local_entry *hna_local_entry;
+	struct hash_it_t *hashit = NULL;
+	unsigned long flags;
+	unsigned long timeout;
+
+	spin_lock_irqsave(&hna_local_hash_lock, flags);
+
+	while (NULL != (hashit = hash_iterate(hna_local_hash, hashit))) {
+		hna_local_entry = hashit->bucket->data;
+
+		timeout = hna_local_entry->last_seen +
+			((LOCAL_HNA_TIMEOUT / 1000) * HZ);
+		if ((!hna_local_entry->never_purge) &&
+		    time_after(jiffies, timeout))
+			hna_local_del(hna_local_entry, "address timed out");
+	}
+
+	spin_unlock_irqrestore(&hna_local_hash_lock, flags);
+	hna_local_start_timer();
+}
+
+void hna_local_free(void)
+{
+	if (!hna_local_hash)
+		return;
+
+	cancel_delayed_work_sync(&hna_local_purge_wq);
+	hash_delete(hna_local_hash, _hna_local_del);
+	hna_local_hash = NULL;
+}
+
+int hna_global_init(void)
+{
+	if (hna_global_hash)
+		return 1;
+
+	hna_global_hash = hash_new(128, compare_orig, choose_orig);
+
+	if (!hna_global_hash)
+		return 0;
+
+	return 1;
+}
+
+void hna_global_add_orig(struct orig_node *orig_node,
+			 unsigned char *hna_buff, int hna_buff_len)
+{
+	struct hna_global_entry *hna_global_entry;
+	struct hna_local_entry *hna_local_entry;
+	struct hashtable_t *swaphash;
+	char hna_str[ETH_STR_LEN], orig_str[ETH_STR_LEN];
+	int hna_buff_count = 0;
+	unsigned long flags;
+	unsigned char *hna_ptr;
+
+	addr_to_string(orig_str, orig_node->orig);
+
+	while ((hna_buff_count + 1) * ETH_ALEN <= hna_buff_len) {
+		spin_lock_irqsave(&hna_global_hash_lock, flags);
+
+		hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN);
+		hna_global_entry = (struct hna_global_entry *)
+			hash_find(hna_global_hash, hna_ptr);
+
+		if (hna_global_entry == NULL) {
+			spin_unlock_irqrestore(&hna_global_hash_lock, flags);
+
+			hna_global_entry =
+				kmalloc(sizeof(struct hna_global_entry),
+					GFP_ATOMIC);
+
+			if (!hna_global_entry)
+				break;
+
+			memcpy(hna_global_entry->addr, hna_ptr, ETH_ALEN);
+
+			addr_to_string(hna_str, hna_global_entry->addr);
+			debug_log(LOG_TYPE_ROUTES, "Creating new global hna entry: %s (via %s)\n", hna_str, orig_str);
+
+			spin_lock_irqsave(&hna_global_hash_lock, flags);
+			hash_add(hna_global_hash, hna_global_entry);
+
+		}
+
+		hna_global_entry->orig_node = orig_node;
+		spin_unlock_irqrestore(&hna_global_hash_lock, flags);
+
+		/* remove address from local hash if present */
+		spin_lock_irqsave(&hna_local_hash_lock, flags);
+
+		hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN);
+		hna_local_entry = (struct hna_local_entry *)
+			hash_find(hna_local_hash, hna_ptr);
+
+		if (hna_local_entry != NULL)
+			hna_local_del(hna_local_entry, "global hna received");
+
+		spin_unlock_irqrestore(&hna_local_hash_lock, flags);
+
+		hna_buff_count++;
+	}
+
+	orig_node->hna_buff_len = hna_buff_len;
+
+	if (orig_node->hna_buff_len > 0) {
+		orig_node->hna_buff = kmalloc(orig_node->hna_buff_len,
+					      GFP_ATOMIC);
+		memcpy(orig_node->hna_buff, hna_buff, orig_node->hna_buff_len);
+	} else {
+		orig_node->hna_buff = NULL;
+	}
+
+	spin_lock_irqsave(&hna_global_hash_lock, flags);
+
+	if (hna_global_hash->elements * 4 > hna_global_hash->size) {
+		swaphash = hash_resize(hna_global_hash,
+				       hna_global_hash->size * 2);
+
+		if (swaphash == NULL)
+			debug_log(LOG_TYPE_CRIT, "Couldn't resize global hna hash table \n");
+		else
+			hna_global_hash = swaphash;
+	}
+
+	spin_unlock_irqrestore(&hna_global_hash_lock, flags);
+}
+
+int hna_global_fill_buffer_text(unsigned char *buff, int buff_len)
+{
+	struct hna_global_entry *hna_global_entry;
+	struct hash_it_t *hashit = NULL;
+	int bytes_written = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hna_global_hash_lock, flags);
+
+	while (NULL != (hashit = hash_iterate(hna_global_hash, hashit))) {
+		if (buff_len < bytes_written + (2 * ETH_STR_LEN) + 10)
+			break;
+
+		hna_global_entry = hashit->bucket->data;
+
+		bytes_written += snprintf(buff + bytes_written,
+					  (2 * ETH_STR_LEN) + 10,
+					  " * %02x:%02x:%02x:%02x:%02x:%02x via %02x:%02x:%02x:%02x:%02x:%02x \n",
+					  hna_global_entry->addr[0],
+					  hna_global_entry->addr[1],
+					  hna_global_entry->addr[2],
+					  hna_global_entry->addr[3],
+					  hna_global_entry->addr[4],
+					  hna_global_entry->addr[5],
+					  hna_global_entry->orig_node->orig[0],
+					  hna_global_entry->orig_node->orig[1],
+					  hna_global_entry->orig_node->orig[2],
+					  hna_global_entry->orig_node->orig[3],
+					  hna_global_entry->orig_node->orig[4],
+					  hna_global_entry->orig_node->orig[5]);
+	}
+
+	spin_unlock_irqrestore(&hna_global_hash_lock, flags);
+
+	return bytes_written;
+}
+
+void _hna_global_del_orig(struct hna_global_entry *hna_global_entry,
+			  char *message)
+{
+	char hna_str[ETH_STR_LEN], orig_str[ETH_STR_LEN];
+
+	addr_to_string(orig_str, hna_global_entry->orig_node->orig);
+	addr_to_string(hna_str, hna_global_entry->addr);
+
+	debug_log(LOG_TYPE_ROUTES, "Deleting global hna entry %s (via %s): %s \n", hna_str, orig_str, message);
+
+	hash_remove(hna_global_hash, hna_global_entry->addr);
+	kfree(hna_global_entry);
+}
+
+void hna_global_del_orig(struct orig_node *orig_node, char *message)
+{
+	struct hna_global_entry *hna_global_entry;
+	int hna_buff_count = 0;
+	unsigned long flags;
+	unsigned char *hna_ptr;
+
+	if (orig_node->hna_buff_len == 0)
+		return;
+
+	spin_lock_irqsave(&hna_global_hash_lock, flags);
+
+	while ((hna_buff_count + 1) * ETH_ALEN <= orig_node->hna_buff_len) {
+		hna_ptr = orig_node->hna_buff + (hna_buff_count * ETH_ALEN);
+		hna_global_entry = (struct hna_global_entry *)
+			hash_find(hna_global_hash, hna_ptr);
+
+		if ((hna_global_entry != NULL) &&
+		    (hna_global_entry->orig_node == orig_node))
+			_hna_global_del_orig(hna_global_entry, message);
+
+		hna_buff_count++;
+	}
+
+	spin_unlock_irqrestore(&hna_global_hash_lock, flags);
+
+	orig_node->hna_buff_len = 0;
+	kfree(orig_node->hna_buff);
+	orig_node->hna_buff = NULL;
+}
+
+static void hna_global_del(void *data)
+{
+	kfree(data);
+}
+
+void hna_global_free(void)
+{
+	if (!hna_global_hash)
+		return;
+
+	hash_delete(hna_global_hash, hna_global_del);
+	hna_global_hash = NULL;
+}
+
+struct orig_node *transtable_search(uint8_t *addr)
+{
+	struct hna_global_entry *hna_global_entry;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hna_global_hash_lock, flags);
+	hna_global_entry = (struct hna_global_entry *)
+		hash_find(hna_global_hash, addr);
+	spin_unlock_irqrestore(&hna_global_hash_lock, flags);
+
+	if (hna_global_entry == NULL)
+		return NULL;
+
+	return hna_global_entry->orig_node;
+}

+ 42 - 0
drivers/staging/batman-adv/translation-table.h

@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#include "types.h"
+
+int hna_local_init(void);
+void hna_local_add(uint8_t *addr);
+int hna_local_fill_buffer(unsigned char *buff, int buff_len);
+int hna_local_fill_buffer_text(unsigned char *buff, int buff_len);
+void hna_local_purge(struct work_struct *work);
+void hna_local_free(void);
+int hna_global_init(void);
+void hna_global_add_orig(struct orig_node *orig_node, unsigned char *hna_buff,
+			 int hna_buff_len);
+int hna_global_fill_buffer_text(unsigned char *buff, int buff_len);
+void _hna_global_del_orig(struct hna_global_entry *hna_global_entry,
+			  char *orig_str);
+void hna_global_del_orig(struct orig_node *orig_node, char *message);
+void hna_global_free(void);
+struct orig_node *transtable_search(uint8_t *addr);
+
+extern spinlock_t hna_local_hash_lock;
+extern struct hashtable_t *hna_local_hash;
+extern atomic_t hna_local_changed;

+ 124 - 0
drivers/staging/batman-adv/types.h

@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+
+
+
+
+#ifndef TYPES_H
+#define TYPES_H
+
+#include "packet.h"
+#include "bitarray.h"
+
+#define BAT_HEADER_LEN (sizeof(struct ethhdr) + ((sizeof(struct unicast_packet) > sizeof(struct bcast_packet) ? sizeof(struct unicast_packet) : sizeof(struct bcast_packet))))
+
+
+struct batman_if {
+	struct list_head list;
+	int16_t if_num;
+	char *dev;
+	char if_active;
+	char addr_str[ETH_STR_LEN];
+	struct net_device *net_dev;
+	struct socket *raw_sock;
+	atomic_t seqno;
+	unsigned char *packet_buff;
+	int packet_len;
+	struct rcu_head rcu;
+
+};
+
+struct orig_node {               /* structure for orig_list maintaining nodes of mesh */
+	uint8_t orig[ETH_ALEN];
+	struct neigh_node *router;
+	struct batman_if *batman_if;
+	TYPE_OF_WORD *bcast_own;
+	uint8_t *bcast_own_sum;
+	uint8_t tq_own;
+	int tq_asym_penalty;
+	unsigned long last_valid;        /* when last packet from this node was received */
+/*	uint8_t  gwflags;      * flags related to gateway functions: gateway class */
+	uint8_t  flags;    		/* for now only VIS_SERVER flag. */
+	unsigned char *hna_buff;
+	int16_t  hna_buff_len;
+	uint16_t last_real_seqno;   /* last and best known squence number */
+	uint8_t last_ttl;         /* ttl of last received packet */
+	TYPE_OF_WORD bcast_bits[NUM_WORDS];
+	uint16_t last_bcast_seqno;  /* last broadcast sequence number received by this host */
+	struct list_head neigh_list;
+};
+
+struct neigh_node {
+	struct list_head list;
+	uint8_t addr[ETH_ALEN];
+	uint8_t real_packet_count;
+	uint8_t tq_recv[TQ_GLOBAL_WINDOW_SIZE];
+	uint8_t tq_index;
+	uint8_t tq_avg;
+	uint8_t last_ttl;
+	unsigned long last_valid;            /* when last packet via this neighbour was received */
+	TYPE_OF_WORD real_bits[NUM_WORDS];
+	struct orig_node *orig_node;
+	struct batman_if *if_incoming;
+};
+
+struct bat_priv {
+	struct net_device_stats stats;
+};
+
+struct device_client {
+	struct list_head queue_list;
+	unsigned int queue_len;
+	unsigned char index;
+	spinlock_t lock;
+	wait_queue_head_t queue_wait;
+};
+
+struct device_packet {
+	struct list_head list;
+	struct icmp_packet icmp_packet;
+};
+
+struct hna_local_entry {
+	uint8_t addr[ETH_ALEN];
+	unsigned long last_seen;
+	char never_purge;
+};
+
+struct hna_global_entry {
+	uint8_t addr[ETH_ALEN];
+	struct orig_node *orig_node;
+};
+
+struct forw_packet {               /* structure for forw_list maintaining packets to be send/forwarded */
+	struct hlist_node list;
+	unsigned long send_time;
+	uint8_t own;
+	unsigned char *packet_buff;
+	uint16_t packet_len;
+	uint32_t direct_link_flags;
+	uint8_t num_packets;
+	struct delayed_work delayed_work;
+	struct batman_if *if_incoming;
+};
+
+#endif

+ 564 - 0
drivers/staging/batman-adv/vis.c

@@ -0,0 +1,564 @@
+/*
+ * Copyright (C) 2008-2009 B.A.T.M.A.N. contributors:
+ *
+ * Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#include "main.h"
+#include "send.h"
+#include "translation-table.h"
+#include "vis.h"
+#include "log.h"
+#include "soft-interface.h"
+#include "hard-interface.h"
+#include "hash.h"
+#include "compat.h"
+
+struct hashtable_t *vis_hash;
+DEFINE_SPINLOCK(vis_hash_lock);
+static struct vis_info *my_vis_info;
+static struct list_head send_list;	/* always locked with vis_hash_lock */
+
+static void start_vis_timer(void);
+
+/* free the info */
+static void free_info(void *data)
+{
+	struct vis_info *info = data;
+	struct recvlist_node *entry, *tmp;
+
+	list_del_init(&info->send_list);
+	list_for_each_entry_safe(entry, tmp, &info->recv_list, list) {
+		list_del(&entry->list);
+		kfree(entry);
+	}
+	kfree(info);
+}
+
+/* set the mode of the visualization to client or server */
+void vis_set_mode(int mode)
+{
+	spin_lock(&vis_hash_lock);
+
+	if (my_vis_info != NULL)
+		my_vis_info->packet.vis_type = mode;
+
+	spin_unlock(&vis_hash_lock);
+}
+
+/* is_vis_server(), locked outside */
+static int is_vis_server_locked(void)
+{
+	if (my_vis_info != NULL)
+		if (my_vis_info->packet.vis_type == VIS_TYPE_SERVER_SYNC)
+			return 1;
+
+	return 0;
+}
+
+/* get the current set mode */
+int is_vis_server(void)
+{
+	int ret = 0;
+
+	spin_lock(&vis_hash_lock);
+	ret = is_vis_server_locked();
+	spin_unlock(&vis_hash_lock);
+
+	return ret;
+}
+
+/* Compare two vis packets, used by the hashing algorithm */
+static int vis_info_cmp(void *data1, void *data2)
+{
+	struct vis_info *d1, *d2;
+	d1 = data1;
+	d2 = data2;
+	return compare_orig(d1->packet.vis_orig, d2->packet.vis_orig);
+}
+
+/* hash function to choose an entry in a hash table of given size */
+/* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */
+static int vis_info_choose(void *data, int size)
+{
+	struct vis_info *vis_info = data;
+	unsigned char *key;
+	uint32_t hash = 0;
+	size_t i;
+
+	key = vis_info->packet.vis_orig;
+	for (i = 0; i < ETH_ALEN; i++) {
+		hash += key[i];
+		hash += (hash << 10);
+		hash ^= (hash >> 6);
+	}
+
+	hash += (hash << 3);
+	hash ^= (hash >> 11);
+	hash += (hash << 15);
+
+	return hash % size;
+}
+
+/* tries to add one entry to the receive list. */
+static void recv_list_add(struct list_head *recv_list, char *mac)
+{
+	struct recvlist_node *entry;
+	entry = kmalloc(sizeof(struct recvlist_node), GFP_ATOMIC);
+	if (!entry)
+		return;
+
+	memcpy(entry->mac, mac, ETH_ALEN);
+	list_add_tail(&entry->list, recv_list);
+}
+
+/* returns 1 if this mac is in the recv_list */
+static int recv_list_is_in(struct list_head *recv_list, char *mac)
+{
+	struct recvlist_node *entry;
+
+	list_for_each_entry(entry, recv_list, list) {
+		if (memcmp(entry->mac, mac, ETH_ALEN) == 0)
+			return 1;
+	}
+
+	return 0;
+}
+
+/* try to add the packet to the vis_hash. return NULL if invalid (e.g. too old,
+ * broken.. ).  vis hash must be locked outside.  is_new is set when the packet
+ * is newer than old entries in the hash. */
+static struct vis_info *add_packet(struct vis_packet *vis_packet,
+				   int vis_info_len, int *is_new)
+{
+	struct vis_info *info, *old_info;
+	struct vis_info search_elem;
+
+	*is_new = 0;
+	/* sanity check */
+	if (vis_hash == NULL)
+		return NULL;
+
+	/* see if the packet is already in vis_hash */
+	memcpy(search_elem.packet.vis_orig, vis_packet->vis_orig, ETH_ALEN);
+	old_info = hash_find(vis_hash, &search_elem);
+
+	if (old_info != NULL) {
+		if (vis_packet->seqno - old_info->packet.seqno <= 0) {
+			if (old_info->packet.seqno == vis_packet->seqno) {
+				recv_list_add(&old_info->recv_list,
+					      vis_packet->sender_orig);
+				return old_info;
+			} else {
+				/* newer packet is already in hash. */
+				return NULL;
+			}
+		}
+		/* remove old entry */
+		hash_remove(vis_hash, old_info);
+		free_info(old_info);
+	}
+
+	info = kmalloc(sizeof(struct vis_info) + vis_info_len, GFP_ATOMIC);
+	if (info == NULL)
+		return NULL;
+
+	INIT_LIST_HEAD(&info->send_list);
+	INIT_LIST_HEAD(&info->recv_list);
+	info->first_seen = jiffies;
+	memcpy(&info->packet, vis_packet,
+	       sizeof(struct vis_packet) + vis_info_len);
+
+	/* initialize and add new packet. */
+	*is_new = 1;
+
+	/* repair if entries is longer than packet. */
+	if (info->packet.entries * sizeof(struct vis_info_entry) > vis_info_len)
+		info->packet.entries = vis_info_len / sizeof(struct vis_info_entry);
+
+	recv_list_add(&info->recv_list, info->packet.sender_orig);
+
+	/* try to add it */
+	if (hash_add(vis_hash, info) < 0) {
+		/* did not work (for some reason) */
+		free_info(info);
+		info = NULL;
+	}
+
+	return info;
+}
+
+/* handle the server sync packet, forward if needed. */
+void receive_server_sync_packet(struct vis_packet *vis_packet, int vis_info_len)
+{
+	struct vis_info *info;
+	int is_new;
+
+	spin_lock(&vis_hash_lock);
+	info = add_packet(vis_packet, vis_info_len, &is_new);
+	if (info == NULL)
+		goto end;
+
+	/* only if we are server ourselves and packet is newer than the one in
+	 * hash.*/
+	if (is_vis_server_locked() && is_new) {
+		memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN);
+		if (list_empty(&info->send_list))
+			list_add_tail(&info->send_list, &send_list);
+	}
+end:
+	spin_unlock(&vis_hash_lock);
+}
+
+/* handle an incoming client update packet and schedule forward if needed. */
+void receive_client_update_packet(struct vis_packet *vis_packet,
+				  int vis_info_len)
+{
+	struct vis_info *info;
+	int is_new;
+
+	/* clients shall not broadcast. */
+	if (is_bcast(vis_packet->target_orig))
+		return;
+
+	spin_lock(&vis_hash_lock);
+	info = add_packet(vis_packet, vis_info_len, &is_new);
+	if (info == NULL)
+		goto end;
+	/* note that outdated packets will be dropped at this point. */
+
+
+	/* send only if we're the target server or ... */
+	if (is_vis_server_locked() &&
+	    is_my_mac(info->packet.target_orig) &&
+	    is_new) {
+		info->packet.vis_type = VIS_TYPE_SERVER_SYNC;	/* upgrade! */
+		memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN);
+		if (list_empty(&info->send_list))
+			list_add_tail(&info->send_list, &send_list);
+
+		/* ... we're not the recipient (and thus need to forward). */
+	} else if (!is_my_mac(info->packet.target_orig)) {
+		if (list_empty(&info->send_list))
+			list_add_tail(&info->send_list, &send_list);
+	}
+end:
+	spin_unlock(&vis_hash_lock);
+}
+
+/* Walk the originators and find the VIS server with the best tq. Set the packet
+ * address to its address and return the best_tq.
+ *
+ * Must be called with the originator hash locked */
+static int find_best_vis_server(struct vis_info *info)
+{
+	struct hash_it_t *hashit = NULL;
+	struct orig_node *orig_node;
+	int best_tq = -1;
+
+	while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
+		orig_node = hashit->bucket->data;
+		if ((orig_node != NULL) &&
+		    (orig_node->router != NULL) &&
+		    (orig_node->flags & VIS_SERVER) &&
+		    (orig_node->router->tq_avg > best_tq)) {
+			best_tq = orig_node->router->tq_avg;
+			memcpy(info->packet.target_orig, orig_node->orig,
+			       ETH_ALEN);
+		}
+	}
+	return best_tq;
+}
+
+/* Return true if the vis packet is full. */
+static bool vis_packet_full(struct vis_info *info)
+{
+	if (info->packet.entries + 1 >
+	    (1000 - sizeof(struct vis_info)) / sizeof(struct vis_info_entry))
+		return true;
+	return false;
+}
+
+/* generates a packet of own vis data,
+ * returns 0 on success, -1 if no packet could be generated */
+static int generate_vis_packet(void)
+{
+	struct hash_it_t *hashit = NULL;
+	struct orig_node *orig_node;
+	struct vis_info *info = (struct vis_info *)my_vis_info;
+	struct vis_info_entry *entry, *entry_array;
+	struct hna_local_entry *hna_local_entry;
+	int best_tq = -1;
+	unsigned long flags;
+
+	info->first_seen = jiffies;
+
+	spin_lock(&orig_hash_lock);
+	memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN);
+	info->packet.ttl = TTL;
+	info->packet.seqno++;
+	info->packet.entries = 0;
+
+	if (!is_vis_server_locked()) {
+		best_tq = find_best_vis_server(info);
+		if (best_tq < 0) {
+			spin_unlock(&orig_hash_lock);
+			return -1;
+		}
+	}
+	hashit = NULL;
+
+	entry_array = (struct vis_info_entry *)
+		((char *)info + sizeof(struct vis_info));
+
+	while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
+		orig_node = hashit->bucket->data;
+		if (orig_node->router != NULL
+			&& compare_orig(orig_node->router->addr, orig_node->orig)
+			&& orig_node->batman_if
+			&& (orig_node->batman_if->if_active == IF_ACTIVE)
+		    && orig_node->router->tq_avg > 0) {
+
+			/* fill one entry into buffer. */
+			entry = &entry_array[info->packet.entries];
+			memcpy(entry->src, orig_node->batman_if->net_dev->dev_addr, ETH_ALEN);
+			memcpy(entry->dest, orig_node->orig, ETH_ALEN);
+			entry->quality = orig_node->router->tq_avg;
+			info->packet.entries++;
+
+			if (vis_packet_full(info)) {
+				spin_unlock(&orig_hash_lock);
+				return 0;
+			}
+		}
+	}
+
+	spin_unlock(&orig_hash_lock);
+
+	hashit = NULL;
+	spin_lock_irqsave(&hna_local_hash_lock, flags);
+	while (NULL != (hashit = hash_iterate(hna_local_hash, hashit))) {
+		hna_local_entry = hashit->bucket->data;
+		entry = &entry_array[info->packet.entries];
+		memset(entry->src, 0, ETH_ALEN);
+		memcpy(entry->dest, hna_local_entry->addr, ETH_ALEN);
+		entry->quality = 0; /* 0 means HNA */
+		info->packet.entries++;
+
+		if (vis_packet_full(info)) {
+			spin_unlock_irqrestore(&hna_local_hash_lock, flags);
+			return 0;
+		}
+	}
+	spin_unlock_irqrestore(&hna_local_hash_lock, flags);
+	return 0;
+}
+
+static void purge_vis_packets(void)
+{
+	struct hash_it_t *hashit = NULL;
+	struct vis_info *info;
+
+	while (NULL != (hashit = hash_iterate(vis_hash, hashit))) {
+		info = hashit->bucket->data;
+		if (info == my_vis_info)	/* never purge own data. */
+			continue;
+		if (time_after(jiffies,
+			       info->first_seen + (VIS_TIMEOUT/1000)*HZ)) {
+			hash_remove_bucket(vis_hash, hashit);
+			free_info(info);
+		}
+	}
+}
+
+static void broadcast_vis_packet(struct vis_info *info, int packet_length)
+{
+	struct hash_it_t *hashit = NULL;
+	struct orig_node *orig_node;
+
+	spin_lock(&orig_hash_lock);
+
+	/* send to all routers in range. */
+	while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
+		orig_node = hashit->bucket->data;
+
+		/* if it's a vis server and reachable, send it. */
+		if (orig_node &&
+		    (orig_node->flags & VIS_SERVER) &&
+		    orig_node->batman_if &&
+		    orig_node->router) {
+
+			/* don't send it if we already received the packet from
+			 * this node. */
+			if (recv_list_is_in(&info->recv_list, orig_node->orig))
+				continue;
+
+			memcpy(info->packet.target_orig,
+			       orig_node->orig, ETH_ALEN);
+
+			send_raw_packet((unsigned char *) &info->packet,
+					packet_length,
+					orig_node->batman_if,
+					orig_node->router->addr);
+		}
+	}
+	memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN);
+	spin_unlock(&orig_hash_lock);
+}
+
+static void unicast_vis_packet(struct vis_info *info, int packet_length)
+{
+	struct orig_node *orig_node;
+
+	spin_lock(&orig_hash_lock);
+	orig_node = ((struct orig_node *)
+		     hash_find(orig_hash, info->packet.target_orig));
+
+	if ((orig_node != NULL) &&
+	    (orig_node->batman_if != NULL) &&
+	    (orig_node->router != NULL)) {
+		send_raw_packet((unsigned char *) &info->packet, packet_length,
+				orig_node->batman_if,
+				orig_node->router->addr);
+	}
+	spin_unlock(&orig_hash_lock);
+}
+
+/* only send one vis packet. called from send_vis_packets() */
+static void send_vis_packet(struct vis_info *info)
+{
+	int packet_length;
+
+	if (info->packet.ttl < 2) {
+		debug_log(LOG_TYPE_NOTICE,
+			  "Error - can't send vis packet: ttl exceeded\n");
+		return;
+	}
+
+	memcpy(info->packet.sender_orig, mainIfAddr, ETH_ALEN);
+	info->packet.ttl--;
+
+	packet_length = sizeof(struct vis_packet) +
+		info->packet.entries * sizeof(struct vis_info_entry);
+
+	if (is_bcast(info->packet.target_orig))
+		broadcast_vis_packet(info, packet_length);
+	else
+		unicast_vis_packet(info, packet_length);
+	info->packet.ttl++; /* restore TTL */
+}
+
+/* called from timer; send (and maybe generate) vis packet. */
+static void send_vis_packets(struct work_struct *work)
+{
+	struct vis_info *info, *temp;
+
+	spin_lock(&vis_hash_lock);
+	purge_vis_packets();
+
+	if (generate_vis_packet() == 0)
+		/* schedule if generation was successful */
+		list_add_tail(&my_vis_info->send_list, &send_list);
+
+	list_for_each_entry_safe(info, temp, &send_list, send_list) {
+		list_del_init(&info->send_list);
+		send_vis_packet(info);
+	}
+	spin_unlock(&vis_hash_lock);
+	start_vis_timer();
+}
+static DECLARE_DELAYED_WORK(vis_timer_wq, send_vis_packets);
+
+/* init the vis server. this may only be called when if_list is already
+ * initialized (e.g. bat0 is initialized, interfaces have been added) */
+int vis_init(void)
+{
+	if (vis_hash)
+		return 1;
+
+	spin_lock(&vis_hash_lock);
+
+	vis_hash = hash_new(256, vis_info_cmp, vis_info_choose);
+	if (!vis_hash) {
+		debug_log(LOG_TYPE_CRIT, "Can't initialize vis_hash\n");
+		goto err;
+	}
+
+	my_vis_info = kmalloc(1000, GFP_ATOMIC);
+	if (!my_vis_info) {
+		debug_log(LOG_TYPE_CRIT, "Can't initialize vis packet\n");
+		goto err;
+	}
+
+	/* prefill the vis info */
+	my_vis_info->first_seen = jiffies - atomic_read(&vis_interval);
+	INIT_LIST_HEAD(&my_vis_info->recv_list);
+	INIT_LIST_HEAD(&my_vis_info->send_list);
+	my_vis_info->packet.version = COMPAT_VERSION;
+	my_vis_info->packet.packet_type = BAT_VIS;
+	my_vis_info->packet.vis_type = VIS_TYPE_CLIENT_UPDATE;
+	my_vis_info->packet.ttl = TTL;
+	my_vis_info->packet.seqno = 0;
+	my_vis_info->packet.entries = 0;
+
+	INIT_LIST_HEAD(&send_list);
+
+	memcpy(my_vis_info->packet.vis_orig, mainIfAddr, ETH_ALEN);
+	memcpy(my_vis_info->packet.sender_orig, mainIfAddr, ETH_ALEN);
+
+	if (hash_add(vis_hash, my_vis_info) < 0) {
+		debug_log(LOG_TYPE_CRIT,
+			  "Can't add own vis packet into hash\n");
+		free_info(my_vis_info);	/* not in hash, need to remove it
+					 * manually. */
+		goto err;
+	}
+
+	spin_unlock(&vis_hash_lock);
+	start_vis_timer();
+	return 1;
+
+err:
+	spin_unlock(&vis_hash_lock);
+	vis_quit();
+	return 0;
+}
+
+/* shutdown vis-server */
+void vis_quit(void)
+{
+	if (!vis_hash)
+		return;
+
+	cancel_delayed_work_sync(&vis_timer_wq);
+
+	spin_lock(&vis_hash_lock);
+	/* properly remove, kill timers ... */
+	hash_delete(vis_hash, free_info);
+	vis_hash = NULL;
+	my_vis_info = NULL;
+	spin_unlock(&vis_hash_lock);
+}
+
+/* schedule packets for (re)transmission */
+static void start_vis_timer(void)
+{
+	queue_delayed_work(bat_event_workqueue, &vis_timer_wq,
+			   (atomic_read(&vis_interval)/1000) * HZ);
+}
+

+ 63 - 0
drivers/staging/batman-adv/vis.h

@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2008-2009 B.A.T.M.A.N. contributors:
+ *
+ * Simon Wunderlich, Marek Lindner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+#define VIS_TIMEOUT		200000
+#define VIS_FORMAT_DD_NAME	"dot_draw"
+#define VIS_FORMAT_JSON_NAME	"json"
+
+struct vis_info {
+	unsigned long       first_seen;
+	struct list_head    recv_list;
+			    /* list of server-neighbors we received a vis-packet
+			     * from.  we should not reply to them. */
+	struct list_head send_list;
+	/* this packet might be part of the vis send queue. */
+	struct vis_packet packet;
+	/* vis_info may follow here*/
+} __attribute__((packed));
+
+struct vis_info_entry {
+	uint8_t  src[ETH_ALEN];
+	uint8_t  dest[ETH_ALEN];
+	uint8_t  quality;	/* quality = 0 means HNA */
+} __attribute__((packed));
+
+struct recvlist_node {
+	struct list_head list;
+	uint8_t mac[ETH_ALEN];
+};
+
+enum vis_formats {
+	DOT_DRAW,
+	JSON,
+};
+
+extern struct hashtable_t *vis_hash;
+extern spinlock_t vis_hash_lock;
+
+void vis_set_mode(int mode);
+int is_vis_server(void);
+void receive_server_sync_packet(struct vis_packet *vis_packet,
+				int vis_info_len);
+void receive_client_update_packet(struct vis_packet *vis_packet,
+				  int vis_info_len);
+int vis_init(void);
+void vis_quit(void);

+ 0 - 8
drivers/staging/comedi/comedi.h

@@ -24,10 +24,6 @@
 #ifndef _COMEDI_H
 #define _COMEDI_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #define COMEDI_MAJORVERSION	0
 #define COMEDI_MINORVERSION	7
 #define COMEDI_MICROVERSION	76
@@ -871,8 +867,4 @@ INSN_CONFIG_ARM */
 		AMPLC_DIO_GAT_RESERVED7
 	};
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* _COMEDI_H */

+ 14 - 135
drivers/staging/comedi/comedi_compat32.c

@@ -27,16 +27,12 @@
 #define __NO_VERSION__
 #include "comedi.h"
 #include <linux/smp_lock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "comedi_compat32.h"
 
 #ifdef CONFIG_COMPAT
 
-#ifndef HAVE_COMPAT_IOCTL
-#include <linux/ioctl32.h>	/* for (un)register_ioctl32_conversion */
-#endif
-
 #define COMEDI32_CHANINFO _IOR(CIO, 3, struct comedi32_chaninfo_struct)
 #define COMEDI32_RANGEINFO _IOR(CIO, 8, struct comedi32_rangeinfo_struct)
 /* N.B. COMEDI32_CMD and COMEDI_CMD ought to use _IOWR, not _IOR.
@@ -101,22 +97,9 @@ static int translated_ioctl(struct file *file, unsigned int cmd,
 	if (!file->f_op)
 		return -ENOTTY;
 
-#ifdef HAVE_UNLOCKED_IOCTL
-	if (file->f_op->unlocked_ioctl) {
-		int rc = (int)(*file->f_op->unlocked_ioctl) (file, cmd, arg);
-		if (rc == -ENOIOCTLCMD)
-			rc = -ENOTTY;
-		return rc;
-	}
-#endif
-	if (file->f_op->ioctl) {
-		int rc;
-		lock_kernel();
-		rc = (*file->f_op->ioctl) (file->f_dentry->d_inode,
-					   file, cmd, arg);
-		unlock_kernel();
-		return rc;
-	}
+	if (file->f_op->unlocked_ioctl)
+		return file->f_op->unlocked_ioctl(file, cmd, arg);
+
 	return -ENOTTY;
 }
 
@@ -186,8 +169,8 @@ static int compat_rangeinfo(struct file *file, unsigned long arg)
 }
 
 /* Copy 32-bit cmd structure to native cmd structure. */
-static int get_compat_cmd(struct comedi_cmd __user * cmd,
-			  struct comedi32_cmd_struct __user * cmd32)
+static int get_compat_cmd(struct comedi_cmd __user *cmd,
+			  struct comedi32_cmd_struct __user *cmd32)
 {
 	int err;
 	union {
@@ -237,8 +220,8 @@ static int get_compat_cmd(struct comedi_cmd __user * cmd,
 }
 
 /* Copy native cmd structure to 32-bit cmd structure. */
-static int put_compat_cmd(struct comedi32_cmd_struct __user * cmd32,
-			  struct comedi_cmd __user * cmd)
+static int put_compat_cmd(struct comedi32_cmd_struct __user *cmd32,
+			  struct comedi_cmd __user *cmd)
 {
 	int err;
 	unsigned int temp;
@@ -328,8 +311,8 @@ static int compat_cmdtest(struct file *file, unsigned long arg)
 }
 
 /* Copy 32-bit insn structure to native insn structure. */
-static int get_compat_insn(struct comedi_insn __user * insn,
-			   struct comedi32_insn_struct __user * insn32)
+static int get_compat_insn(struct comedi_insn __user *insn,
+			   struct comedi32_insn_struct __user *insn32)
 {
 	int err;
 	union {
@@ -372,9 +355,9 @@ static int compat_insnlist(struct file *file, unsigned long arg)
 	insnlist32 = compat_ptr(arg);
 
 	/* Get 32-bit insnlist structure.  */
-	if (!access_ok(VERIFY_READ, insnlist32, sizeof(*insnlist32))) {
+	if (!access_ok(VERIFY_READ, insnlist32, sizeof(*insnlist32)))
 		return -EFAULT;
-	}
+
 	err = 0;
 	err |= __get_user(n_insns, &insnlist32->n_insns);
 	err |= __get_user(uptr, &insnlist32->insns);
@@ -387,9 +370,9 @@ static int compat_insnlist(struct file *file, unsigned long arg)
 					     insn[n_insns]));
 
 	/* Set native insnlist structure. */
-	if (!access_ok(VERIFY_WRITE, &s->insnlist, sizeof(s->insnlist))) {
+	if (!access_ok(VERIFY_WRITE, &s->insnlist, sizeof(s->insnlist)))
 		return -EFAULT;
-	}
+
 	err |= __put_user(n_insns, &s->insnlist.n_insns);
 	err |= __put_user(&s->insn[0], &s->insnlist.insns);
 	if (err)
@@ -472,8 +455,6 @@ static inline int raw_ioctl(struct file *file, unsigned int cmd,
 	return rc;
 }
 
-#ifdef HAVE_COMPAT_IOCTL	/* defined in <linux/fs.h> 2.6.11 onwards */
-
 /* compat_ioctl file operation. */
 /* Returns -ENOIOCTLCMD for unrecognised ioctl codes. */
 long comedi_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
@@ -481,106 +462,4 @@ long comedi_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	return raw_ioctl(file, cmd, arg);
 }
 
-#else /* HAVE_COMPAT_IOCTL */
-
-/*
- * Brain-dead ioctl compatibility for 2.6.10 and earlier.
- *
- * It's brain-dead because cmd numbers need to be unique system-wide!
- * The comedi driver could end up attempting to execute ioctls for non-Comedi
- * devices because it registered the system-wide cmd code first.  Similarly,
- * another driver could end up attempting to execute ioctls for a Comedi
- * device because it registered the cmd code first.  Chaos ensues.
- */
-
-/* Handler for all 32-bit ioctl codes registered by this driver. */
-static int mapped_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg,
-			struct file *file)
-{
-	int rc;
-
-	/* Make sure we are dealing with a Comedi device. */
-	if (imajor(file->f_dentry->d_inode) != COMEDI_MAJOR)
-		return -ENOTTY;
-
-	rc = raw_ioctl(file, cmd, arg);
-	/* Do not return -ENOIOCTLCMD. */
-	if (rc == -ENOIOCTLCMD)
-		rc = -ENOTTY;
-
-	return rc;
-}
-
-struct ioctl32_map {
-	unsigned int cmd;
-	int (*handler) (unsigned int, unsigned int, unsigned long,
-			struct file *);
-	int registered;
-};
-
-static struct ioctl32_map comedi_ioctl32_map[] = {
-	{COMEDI_DEVCONFIG, mapped_ioctl, 0},
-	{COMEDI_DEVINFO, mapped_ioctl, 0},
-	{COMEDI_SUBDINFO, mapped_ioctl, 0},
-	{COMEDI_BUFCONFIG, mapped_ioctl, 0},
-	{COMEDI_BUFINFO, mapped_ioctl, 0},
-	{COMEDI_LOCK, mapped_ioctl, 0},
-	{COMEDI_UNLOCK, mapped_ioctl, 0},
-	{COMEDI_CANCEL, mapped_ioctl, 0},
-	{COMEDI_POLL, mapped_ioctl, 0},
-	{COMEDI32_CHANINFO, mapped_ioctl, 0},
-	{COMEDI32_RANGEINFO, mapped_ioctl, 0},
-	{COMEDI32_CMD, mapped_ioctl, 0},
-	{COMEDI32_CMDTEST, mapped_ioctl, 0},
-	{COMEDI32_INSNLIST, mapped_ioctl, 0},
-	{COMEDI32_INSN, mapped_ioctl, 0},
-};
-
-#define NUM_IOCTL32_MAPS ARRAY_SIZE(comedi_ioctl32_map)
-
-/* Register system-wide 32-bit ioctl handlers. */
-void comedi_register_ioctl32(void)
-{
-	int n, rc;
-
-	for (n = 0; n < NUM_IOCTL32_MAPS; n++) {
-		rc = register_ioctl32_conversion(comedi_ioctl32_map[n].cmd,
-						 comedi_ioctl32_map[n].handler);
-		if (rc) {
-			printk(KERN_WARNING
-			       "comedi: failed to register 32-bit "
-			       "compatible ioctl handler for 0x%X - "
-			       "expect bad things to happen!\n",
-			       comedi_ioctl32_map[n].cmd);
-		}
-		comedi_ioctl32_map[n].registered = !rc;
-	}
-}
-
-/* Unregister system-wide 32-bit ioctl translations. */
-void comedi_unregister_ioctl32(void)
-{
-	int n, rc;
-
-	for (n = 0; n < NUM_IOCTL32_MAPS; n++) {
-		if (comedi_ioctl32_map[n].registered) {
-			rc = unregister_ioctl32_conversion(comedi_ioctl32_map
-							   [n].cmd,
-							   comedi_ioctl32_map
-							   [n].handler);
-			if (rc) {
-				printk(KERN_ERR
-				       "comedi: failed to unregister 32-bit "
-				       "compatible ioctl handler for 0x%X - "
-				       "expect kernel Oops!\n",
-				       comedi_ioctl32_map[n].cmd);
-			} else {
-				comedi_ioctl32_map[n].registered = 0;
-			}
-		}
-	}
-}
-
-#endif /* HAVE_COMPAT_IOCTL */
-
 #endif /* CONFIG_COMPAT */

+ 1 - 15
drivers/staging/comedi/comedi_compat32.h

@@ -28,30 +28,16 @@
 #define _COMEDI_COMPAT32_H
 
 #include <linux/compat.h>
-#include <linux/fs.h>		/* For HAVE_COMPAT_IOCTL and HAVE_UNLOCKED_IOCTL */
+#include <linux/fs.h>
 
 #ifdef CONFIG_COMPAT
 
-#ifdef HAVE_COMPAT_IOCTL
-
 extern long comedi_compat_ioctl(struct file *file, unsigned int cmd,
 				unsigned long arg);
-#define comedi_register_ioctl32() do {} while (0)
-#define comedi_unregister_ioctl32() do {} while (0)
-
-#else /* HAVE_COMPAT_IOCTL */
-
-#define comedi_compat_ioctl 0	/* NULL */
-extern void comedi_register_ioctl32(void);
-extern void comedi_unregister_ioctl32(void);
-
-#endif /* HAVE_COMPAT_IOCTL */
 
 #else /* CONFIG_COMPAT */
 
 #define comedi_compat_ioctl 0	/* NULL */
-#define comedi_register_ioctl32() do {} while (0)
-#define comedi_unregister_ioctl32() do {} while (0)
 
 #endif /* CONFIG_COMPAT */
 

+ 0 - 15
drivers/staging/comedi/comedi_fops.c

@@ -110,13 +110,8 @@ static struct device_attribute dev_attr_read_buffer_kb;
 static struct device_attribute dev_attr_max_write_buffer_kb;
 static struct device_attribute dev_attr_write_buffer_kb;
 
-#ifdef HAVE_UNLOCKED_IOCTL
 static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
 				  unsigned long arg)
-#else
-static int comedi_ioctl(struct inode *inode, struct file *file,
-			unsigned int cmd, unsigned long arg)
-#endif
 {
 	const unsigned minor = iminor(file->f_dentry->d_inode);
 	struct comedi_device_file_info *dev_file_info =
@@ -1867,14 +1862,8 @@ static int comedi_fasync(int fd, struct file *file, int on)
 
 const struct file_operations comedi_fops = {
 	.owner = THIS_MODULE,
-#ifdef HAVE_UNLOCKED_IOCTL
 	.unlocked_ioctl = comedi_unlocked_ioctl,
-#else
-	.ioctl = comedi_ioctl,
-#endif
-#ifdef HAVE_COMPAT_IOCTL
 	.compat_ioctl = comedi_compat_ioctl,
-#endif
 	.open = comedi_open,
 	.release = comedi_close,
 	.read = comedi_read,
@@ -1959,8 +1948,6 @@ static int __init comedi_init(void)
 		}
 	}
 
-	comedi_register_ioctl32();
-
 	return 0;
 }
 
@@ -1977,8 +1964,6 @@ static void __exit comedi_cleanup(void)
 	unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS);
 
 	comedi_proc_cleanup();
-
-	comedi_unregister_ioctl32();
 }
 
 module_init(comedi_init);

+ 34 - 26
drivers/staging/comedi/comedidev.h

@@ -49,7 +49,8 @@
 } while (0)
 
 #define COMEDI_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
-#define COMEDI_VERSION_CODE COMEDI_VERSION(COMEDI_MAJORVERSION, COMEDI_MINORVERSION, COMEDI_MICROVERSION)
+#define COMEDI_VERSION_CODE COMEDI_VERSION(COMEDI_MAJORVERSION, \
+	COMEDI_MINORVERSION, COMEDI_MICROVERSION)
 #define COMEDI_RELEASE VERSION
 
 #define COMEDI_INITCLEANUP_NOMODULE(x)					\
@@ -58,12 +59,12 @@
 	static void __exit x ## _cleanup_module(void)			\
 		{comedi_driver_unregister(&(x)); } 			\
 	module_init(x ## _init_module);					\
-	module_exit(x ## _cleanup_module);					\
+	module_exit(x ## _cleanup_module);
 
 #define COMEDI_MODULE_MACROS						\
 	MODULE_AUTHOR("Comedi http://www.comedi.org");		\
 	MODULE_DESCRIPTION("Comedi low-level driver");			\
-	MODULE_LICENSE("GPL");						\
+	MODULE_LICENSE("GPL");
 
 #define COMEDI_INITCLEANUP(x)						\
 	COMEDI_MODULE_MACROS		\
@@ -75,7 +76,8 @@
 	{ \
 		return comedi_pci_auto_config(dev, comedi_driver.driver_name); \
 	} \
-	static void __devexit comedi_driver ## _pci_remove(struct pci_dev *dev) \
+	static void __devexit comedi_driver ## _pci_remove(\
+		struct pci_dev *dev) \
 	{ \
 		comedi_pci_auto_unconfig(dev); \
 	} \
@@ -91,7 +93,8 @@
 		retval = comedi_driver_register(&comedi_driver); \
 		if (retval < 0) \
 			return retval; \
-		comedi_driver ## _pci_driver.name = (char *)comedi_driver.driver_name; \
+			comedi_driver ## _pci_driver.name = \
+				(char *)comedi_driver.driver_name; \
 		return pci_register_driver(&comedi_driver ## _pci_driver); \
 	} \
 	static void __exit comedi_driver ## _cleanup_module(void) \
@@ -170,14 +173,15 @@ struct comedi_subdevice {
 			   struct comedi_cmd *);
 	int (*poll) (struct comedi_device *, struct comedi_subdevice *);
 	int (*cancel) (struct comedi_device *, struct comedi_subdevice *);
-	/* int (*do_lock)(struct comedi_device *,struct comedi_subdevice *); */
-	/* int (*do_unlock)(struct comedi_device *,struct comedi_subdevice *); */
+	/* int (*do_lock)(struct comedi_device *, struct comedi_subdevice *); */
+	/* int (*do_unlock)(struct comedi_device *, \
+			struct comedi_subdevice *); */
 
 	/* called when the buffer changes */
-	int (*buf_change) (struct comedi_device * dev,
-			   struct comedi_subdevice * s, unsigned long new_size);
+	int (*buf_change) (struct comedi_device *dev,
+			   struct comedi_subdevice *s, unsigned long new_size);
 
-	void (*munge) (struct comedi_device * dev, struct comedi_subdevice * s,
+	void (*munge) (struct comedi_device *dev, struct comedi_subdevice *s,
 		       void *data, unsigned int num_bytes,
 		       unsigned int start_chan_index);
 	enum dma_data_direction async_dma_dir;
@@ -198,16 +202,22 @@ struct comedi_async {
 
 	void *prealloc_buf;	/* pre-allocated buffer */
 	unsigned int prealloc_bufsz;	/* buffer size, in bytes */
-	struct comedi_buf_page *buf_page_list;	/* virtual and dma address of each page */
+	/* virtual and dma address of each page */
+	struct comedi_buf_page *buf_page_list;
 	unsigned n_buf_pages;	/* num elements in buf_page_list */
 
 	unsigned int max_bufsize;	/* maximum buffer size, bytes */
-	unsigned int mmap_count;	/* current number of mmaps of prealloc_buf */
-
-	unsigned int buf_write_count;	/* byte count for writer (write completed) */
-	unsigned int buf_write_alloc_count;	/* byte count for writer (allocated for writing) */
-	unsigned int buf_read_count;	/* byte count for reader (read completed) */
-	unsigned int buf_read_alloc_count;	/* byte count for reader (allocated for reading) */
+	/* current number of mmaps of prealloc_buf */
+	unsigned int mmap_count;
+
+	/* byte count for writer (write completed) */
+	unsigned int buf_write_count;
+	/* byte count for writer (allocated for writing) */
+	unsigned int buf_write_alloc_count;
+	/* byte count for reader (read completed) */
+	unsigned int buf_read_count;
+	/* byte count for reader (allocated for reading) */
+	unsigned int buf_read_alloc_count;
 
 	unsigned int buf_write_ptr;	/* buffer marker for writer */
 	unsigned int buf_read_ptr;	/* buffer marker for reader */
@@ -233,7 +243,7 @@ struct comedi_async {
 	int (*cb_func) (unsigned int flags, void *);
 	void *cb_arg;
 
-	int (*inttrig) (struct comedi_device * dev, struct comedi_subdevice * s,
+	int (*inttrig) (struct comedi_device *dev, struct comedi_subdevice *s,
 			unsigned int x);
 };
 
@@ -283,8 +293,8 @@ struct comedi_device {
 
 	struct fasync_struct *async_queue;
 
-	void (*open) (struct comedi_device * dev);
-	void (*close) (struct comedi_device * dev);
+	void (*open) (struct comedi_device *dev);
+	void (*close) (struct comedi_device *dev);
 };
 
 struct comedi_device_file_info {
@@ -318,9 +328,8 @@ static const unsigned COMEDI_SUBDEVICE_MINOR_OFFSET = 1;
 
 struct comedi_device_file_info *comedi_get_device_file_info(unsigned minor);
 
-static inline struct comedi_subdevice *comedi_get_read_subdevice(const struct
-								 comedi_device_file_info
-								 *info)
+static inline struct comedi_subdevice *comedi_get_read_subdevice(
+	const struct comedi_device_file_info *info)
 {
 	if (info->read_subdevice)
 		return info->read_subdevice;
@@ -329,9 +338,8 @@ static inline struct comedi_subdevice *comedi_get_read_subdevice(const struct
 	return info->device->read_subdev;
 }
 
-static inline struct comedi_subdevice *comedi_get_write_subdevice(const struct
-								  comedi_device_file_info
-								  *info)
+static inline struct comedi_subdevice *comedi_get_write_subdevice(
+	const struct comedi_device_file_info *info)
 {
 	if (info->write_subdevice)
 		return info->write_subdevice;

+ 1 - 1
drivers/staging/comedi/drivers.c

@@ -387,7 +387,7 @@ static int insn_rw_emulate_bits(struct comedi_device *dev,
 	return 1;
 }
 
-static inline unsigned long uvirt_to_kva(pgd_t * pgd, unsigned long adr)
+static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
 {
 	unsigned long ret = 0UL;
 	pmd_t *pmd;

+ 2 - 1
drivers/staging/comedi/drivers/8253.h

@@ -206,7 +206,8 @@ static inline void i8253_cascade_ns_to_timer_2div(int i8253_osc_base,
 	}
 
 	*nanosec = div1 * div2 * i8253_osc_base;
-	*d1 = div1 & 0xffff;	/*  masking is done since counter maps zero to 0x10000 */
+	/*  masking is done since counter maps zero to 0x10000 */
+	*d1 = div1 & 0xffff;
 	*d2 = div2 & 0xffff;
 	return;
 }

+ 10 - 13
drivers/staging/comedi/drivers/8255.c

@@ -132,6 +132,7 @@ void subdev_8255_interrupt(struct comedi_device *dev,
 
 	comedi_event(dev, s);
 }
+EXPORT_SYMBOL(subdev_8255_interrupt);
 
 static int subdev_8255_cb(int dir, int port, int data, unsigned long arg)
 {
@@ -179,15 +180,14 @@ static int subdev_8255_insn_config(struct comedi_device *dev,
 	unsigned int bits;
 
 	mask = 1 << CR_CHAN(insn->chanspec);
-	if (mask & 0x0000ff) {
+	if (mask & 0x0000ff)
 		bits = 0x0000ff;
-	} else if (mask & 0x00ff00) {
+	else if (mask & 0x00ff00)
 		bits = 0x00ff00;
-	} else if (mask & 0x0f0000) {
+	else if (mask & 0x0f0000)
 		bits = 0x0f0000;
-	} else {
+	else
 		bits = 0xf00000;
-	}
 
 	switch (data[0]) {
 	case INSN_CONFIG_DIO_INPUT:
@@ -333,11 +333,10 @@ int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s,
 		return -ENOMEM;
 
 	CALLBACK_ARG = arg;
-	if (cb == NULL) {
+	if (cb == NULL)
 		CALLBACK_FUNC = subdev_8255_cb;
-	} else {
+	else
 		CALLBACK_FUNC = cb;
-	}
 	s->insn_bits = subdev_8255_insn;
 	s->insn_config = subdev_8255_insn_config;
 
@@ -347,6 +346,7 @@ int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s,
 
 	return 0;
 }
+EXPORT_SYMBOL(subdev_8255_init);
 
 int subdev_8255_init_irq(struct comedi_device *dev, struct comedi_subdevice *s,
 			 int (*cb) (int, int, int, unsigned long),
@@ -366,6 +366,7 @@ int subdev_8255_init_irq(struct comedi_device *dev, struct comedi_subdevice *s,
 
 	return 0;
 }
+EXPORT_SYMBOL(subdev_8255_init_irq);
 
 void subdev_8255_cleanup(struct comedi_device *dev, struct comedi_subdevice *s)
 {
@@ -378,6 +379,7 @@ void subdev_8255_cleanup(struct comedi_device *dev, struct comedi_subdevice *s)
 		kfree(s->private);
 	}
 }
+EXPORT_SYMBOL(subdev_8255_cleanup);
 
 /*
 
@@ -448,8 +450,3 @@ static int dev_8255_detach(struct comedi_device *dev)
 
 	return 0;
 }
-
-EXPORT_SYMBOL(subdev_8255_init);
-EXPORT_SYMBOL(subdev_8255_init_irq);
-EXPORT_SYMBOL(subdev_8255_cleanup);
-EXPORT_SYMBOL(subdev_8255_interrupt);

+ 4 - 5
drivers/staging/comedi/drivers/acl7225b.c

@@ -94,10 +94,11 @@ static int acl7225b_attach(struct comedi_device *dev,
 
 	iobase = it->options[0];
 	iorange = this_board->io_range;
-	printk("comedi%d: acl7225b: board=%s 0x%04x ", dev->minor,
+	printk(KERN_INFO "comedi%d: acl7225b: board=%s 0x%04x\n", dev->minor,
 	       this_board->name, iobase);
 	if (!request_region(iobase, iorange, "acl7225b")) {
-		printk("I/O port conflict\n");
+		printk(KERN_ERR "comedi%d: request_region failed - I/O port conflict\n",
+			dev->minor);
 		return -EIO;
 	}
 	dev->board_name = this_board->name;
@@ -137,14 +138,12 @@ static int acl7225b_attach(struct comedi_device *dev,
 	s->range_table = &range_digital;
 	s->private = (void *)ACL7225_DI_LO;
 
-	printk("\n");
-
 	return 0;
 }
 
 static int acl7225b_detach(struct comedi_device *dev)
 {
-	printk("comedi%d: acl7225b: remove\n", dev->minor);
+	printk(KERN_INFO "comedi%d: acl7225b: remove\n", dev->minor);
 
 	if (dev->iobase)
 		release_region(dev->iobase, this_board->io_range);

+ 1 - 2
drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c

@@ -1386,8 +1386,7 @@ int i_APCI1710_ReadChronoValue(struct comedi_device *dev,
 				/* Test the timout parameter */
 		 /*****************************/
 
-				if ((ui_TimeOut >= 0)
-					&& (ui_TimeOut <= 65535UL)) {
+				if (ui_TimeOut <= 65535UL) {
 
 					for (;;) {
 			  /*******************/

+ 3 - 3
drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c

@@ -3807,7 +3807,7 @@ int i_APCI1710_EnableFrequencyMeasurement(struct comedi_device *dev,
 			s_ModuleInfo[b_ModulNbr].
 			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
 	      /********************************************/
-			/* Test if frequency mesurement initialised */
+			/* Test if frequency measurement initialised */
 	      /********************************************/
 
 			if (devpriv->
@@ -3953,7 +3953,7 @@ int i_APCI1710_DisableFrequencyMeasurement(struct comedi_device *dev, unsigned c
 			s_ModuleInfo[b_ModulNbr].
 			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
 	      /********************************************/
-			/* Test if frequency mesurement initialised */
+			/* Test if frequency measurement initialised */
 	      /********************************************/
 
 			if (devpriv->
@@ -5166,7 +5166,7 @@ int i_APCI1710_ReadFrequencyMeasurement(struct comedi_device *dev,
 			s_ModuleInfo[b_ModulNbr].
 			s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) {
 	      /********************************************/
-			/* Test if frequency mesurement initialised */
+			/* Test if frequency measurement initialised */
 	      /********************************************/
 
 			if (devpriv->

+ 1 - 1
drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c

@@ -1808,7 +1808,7 @@ int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device
 									2) {
 									if (dw_Status & 4) {
 				/************************/
-										/* Tor counter owerflow */
+										/* Tor counter overflow */
 				/************************/
 
 										*pb_TorCounterStatus

+ 1 - 1
drivers/staging/comedi/drivers/addi-data/addi_common.h

@@ -82,7 +82,7 @@ struct addi_board {
 
 	int i_NbrDiChannel;	/*  Number of DI channels */
 	int i_NbrDoChannel;	/*  Number of DO channels */
-	int i_DoMaxdata;	/*  data to set all chanels high */
+	int i_DoMaxdata;	/*  data to set all channels high */
 
 	int i_NbrTTLChannel;	/*  Number of TTL channels */
 	const struct comedi_lrange *pr_TTLRangelist;	/* rangelist for TTL */

+ 1 - 1
drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c

@@ -150,7 +150,7 @@ int i_APCI1032_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdev
 	unsigned int ui_TmpValue = 0;
 	unsigned int ui_Channel;
 	ui_Channel = CR_CHAN(insn->chanspec);
-	if (ui_Channel >= 0 && ui_Channel <= 31) {
+	if (ui_Channel <= 31) {
 		ui_TmpValue = (unsigned int) inl(devpriv->iobase + APCI1032_DIGITAL_IP);
 /*
 * since only 1 channel reqd to bring it to last bit it is rotated 8

+ 1 - 1
drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c

@@ -968,7 +968,7 @@ int i_APCI1500_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_sub
 
 	switch (data[0]) {
 	case 0:
-		if (ui_Channel >= 0 && ui_Channel <= 15) {
+		if (ui_Channel <= 15) {
 			ui_TmpValue =
 				(unsigned int) inw(devpriv->i_IobaseAddon +
 				APCI1500_DIGITAL_IP);

+ 1 - 1
drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c

@@ -79,7 +79,7 @@ int i_APCI1516_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdev
 	unsigned int ui_TmpValue = 0;
 	unsigned int ui_Channel;
 	ui_Channel = CR_CHAN(insn->chanspec);
-	if (ui_Channel >= 0 && ui_Channel <= 7) {
+	if (ui_Channel <= 7) {
 		ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI1516_DIGITAL_IP);
 		/*   since only 1 channel reqd  to bring it to last bit it is rotated */
 		/*   8 +(chan - 1) times then ANDed with 1 for last bit. */

+ 1 - 1
drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c

@@ -154,7 +154,7 @@ int i_APCI1564_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdev
 	unsigned int ui_Channel;
 
 	ui_Channel = CR_CHAN(insn->chanspec);
-	if (ui_Channel >= 0 && ui_Channel <= 31) {
+	if (ui_Channel <= 31) {
 		ui_TmpValue =
 			(unsigned int) inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP);
 /*

+ 2 - 2
drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c

@@ -117,7 +117,7 @@ int i_APCI2016_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subde
 	unsigned int ui_NoOfChannel;
 	unsigned int ui_Temp, ui_Temp1;
 	ui_NoOfChannel = CR_CHAN(insn->chanspec);
-	if ((ui_NoOfChannel < 0) || (ui_NoOfChannel > 15)) {
+	if (ui_NoOfChannel > 15) {
 		comedi_error(dev,
 			"Invalid Channel Numbers !!!, Channel Numbers must be between 0 and 15\n");
 		return -EINVAL;
@@ -272,7 +272,7 @@ int i_APCI2016_BitsDigitalOutput(struct comedi_device *dev, struct comedi_subdev
 	unsigned int ui_Temp;
 	unsigned int ui_NoOfChannel;
 	ui_NoOfChannel = CR_CHAN(insn->chanspec);
-	if ((ui_NoOfChannel < 0) || (ui_NoOfChannel > 15)) {
+	if (ui_NoOfChannel > 15) {
 		comedi_error(dev,
 			"Invalid Channel Numbers !!!, Channel Numbers must be between 0 and 15\n");
 		return -EINVAL;

+ 1 - 1
drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c

@@ -79,7 +79,7 @@ int i_APCI2200_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdev
 	unsigned int ui_TmpValue = 0;
 	unsigned int ui_Channel;
 	ui_Channel = CR_CHAN(insn->chanspec);
-	if (ui_Channel >= 0 && ui_Channel <= 7) {
+	if (ui_Channel <= 7) {
 		ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI2200_DIGITAL_IP);
 		*data = (ui_TmpValue >> ui_Channel) & 0x1;
 	}			/* if(ui_Channel >= 0 && ui_Channel <=7) */

+ 3 - 4
drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c

@@ -1468,7 +1468,7 @@ void v_APCI3120_Interrupt(int irq, void *d)
 	int_amcc = inl(devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);	/*  get AMCC int register */
 
 	if ((!int_daq) && (!(int_amcc & ANY_S593X_INT))) {
-		comedi_error(dev, "IRQ from unknow source");
+		comedi_error(dev, "IRQ from unknown source");
 		return;
 	}
 
@@ -2350,7 +2350,7 @@ int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev,
 	ui_Chan = CR_CHAN(insn->chanspec);	/*  channel specified */
 
 	/* this_board->i_hwdrv_InsnReadDigitalInput(dev,ui_Chan,data); */
-	if (ui_Chan >= 0 && ui_Chan <= 3) {
+	if (ui_Chan <= 3) {
 		ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI3120_RD_STATUS);
 
 /*
@@ -2539,8 +2539,7 @@ int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev,
 			"Not a valid Data !!! ,Data should be 1 or 0\n");
 		return -EINVAL;
 	}
-	if ((ui_NoOfChannel > (this_board->i_NbrDoChannel - 1))
-		|| (ui_NoOfChannel < 0)) {
+	if (ui_NoOfChannel > this_board->i_NbrDoChannel - 1) {
 		comedi_error(dev,
 			"This board doesn't have specified channel !!! \n");
 		return -EINVAL;

+ 1 - 1
drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c

@@ -461,7 +461,7 @@ int i_APCI3200_GetChannelCalibrationValue(struct comedi_device *dev,
 	if (s_BoardInfos[dev->minor].i_ConnectionType == 1) {
 		/* if diff */
 
-		if ((ui_Channel_num >= 0) && (ui_Channel_num <= 1))
+		if (ui_Channel_num <= 1)
 			i_DiffChannel = ui_Channel_num, i_Module = 0;
 		else if ((ui_Channel_num >= 2) && (ui_Channel_num <= 3))
 			i_DiffChannel = ui_Channel_num - 2, i_Module = 1;

+ 1 - 1
drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c

@@ -724,7 +724,7 @@ void v_APCI3501_Interrupt(int irq, void *d)
 		APCI3501_TCW_IRQ) & 0x1;
 
 	if ((!ui_Timer_AOWatchdog)) {
-		comedi_error(dev, "IRQ from unknow source");
+		comedi_error(dev, "IRQ from unknown source");
 		return;
 	}
 

+ 1 - 1
drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c

@@ -148,7 +148,7 @@ int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device *dev,
 			/* Test the convert time value */
 	      /*******************************/
 
-			if ((dw_ReloadValue >= 0) && (dw_ReloadValue <= 65535)) {
+			if (dw_ReloadValue <= 65535) {
 				dw_TestReloadValue = dw_ReloadValue;
 
 				if (b_TimeBase == 1) {

+ 33 - 20
drivers/staging/comedi/drivers/adl_pci6208.c

@@ -133,9 +133,11 @@ static int pci6208_ao_winsn(struct comedi_device *dev,
 static int pci6208_ao_rinsn(struct comedi_device *dev,
 			    struct comedi_subdevice *s,
 			    struct comedi_insn *insn, unsigned int *data);
-/* static int pci6208_dio_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, */
+/* static int pci6208_dio_insn_bits (struct comedi_device *dev,
+ * 					struct comedi_subdevice *s, */
 /* struct comedi_insn *insn,unsigned int *data); */
-/* static int pci6208_dio_insn_config(struct comedi_device *dev,struct comedi_subdevice *s, */
+/* static int pci6208_dio_insn_config(struct comedi_device *dev,
+ * 					struct comedi_subdevice *s, */
 /* struct comedi_insn *insn,unsigned int *data); */
 
 /*
@@ -151,7 +153,7 @@ static int pci6208_attach(struct comedi_device *dev,
 	int retval;
 	unsigned long io_base;
 
-	printk("comedi%d: pci6208: ", dev->minor);
+	printk(KERN_INFO "comedi%d: pci6208: ", dev->minor);
 
 	retval = alloc_private(dev, sizeof(struct pci6208_private));
 	if (retval < 0)
@@ -195,7 +197,7 @@ static int pci6208_attach(struct comedi_device *dev,
 	/* s->insn_bits = pci6208_dio_insn_bits; */
 	/* s->insn_config = pci6208_dio_insn_config; */
 
-	printk("attached\n");
+	printk(KERN_INFO "attached\n");
 
 	return 1;
 }
@@ -210,12 +212,11 @@ static int pci6208_attach(struct comedi_device *dev,
  */
 static int pci6208_detach(struct comedi_device *dev)
 {
-	printk("comedi%d: pci6208: remove\n", dev->minor);
+	printk(KERN_INFO "comedi%d: pci6208: remove\n", dev->minor);
 
 	if (devpriv && devpriv->pci_dev) {
-		if (dev->iobase) {
+		if (dev->iobase)
 			comedi_pci_disable(devpriv->pci_dev);
-		}
 		pci_dev_put(devpriv->pci_dev);
 	}
 
@@ -266,7 +267,8 @@ static int pci6208_ao_rinsn(struct comedi_device *dev,
  * useful to applications if you implement the insn_bits interface.
  * This allows packed reading/writing of the DIO channels.  The
  * comedi core can convert between insn_bits and insn_read/write */
-/* static int pci6208_dio_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, */
+/* static int pci6208_dio_insn_bits(struct comedi_device *dev,
+ * 					struct comedi_subdevice *s, */
 /* struct comedi_insn *insn,unsigned int *data) */
 /* { */
 /* if(insn->n!=2)return -EINVAL; */
@@ -290,7 +292,8 @@ static int pci6208_ao_rinsn(struct comedi_device *dev,
 /* return 2; */
 /* } */
 
-/* static int pci6208_dio_insn_config(struct comedi_device *dev,struct comedi_subdevice *s, */
+/* static int pci6208_dio_insn_config(struct comedi_device *dev,
+ * 					struct comedi_subdevice *s, */
 /* struct comedi_insn *insn,unsigned int *data) */
 /* { */
 /* int chan=CR_CHAN(insn->chanspec); */
@@ -320,10 +323,16 @@ static int pci6208_find_device(struct comedi_device *dev, int bus, int slot)
 	     pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) {
 		if (pci_dev->vendor == PCI_VENDOR_ID_ADLINK) {
 			for (i = 0; i < ARRAY_SIZE(pci6208_boards); i++) {
-				if (pci6208_boards[i].dev_id == pci_dev->device) {
-					/*  was a particular bus/slot requested? */
+				if (pci6208_boards[i].dev_id ==
+					pci_dev->device) {
+					/*
+					 * was a particular bus/slot requested?
+					*/
 					if ((bus != 0) || (slot != 0)) {
-						/*  are we on the wrong bus/slot? */
+						/*
+						 * are we on the
+						 * wrong bus/slot?
+						*/
 						if (pci_dev->bus->number
 						    != bus ||
 						    PCI_SLOT(pci_dev->devfn)
@@ -338,8 +347,9 @@ static int pci6208_find_device(struct comedi_device *dev, int bus, int slot)
 		}
 	}
 
-	printk("comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
-	       dev->minor, bus, slot);
+	printk(KERN_ERR "comedi%d: no supported board found! "
+			"(req. bus/slot : %d/%d)\n",
+			dev->minor, bus, slot);
 	return -EIO;
 
 found:
@@ -368,17 +378,20 @@ pci6208_pci_setup(struct pci_dev *pci_dev, unsigned long *io_base_ptr,
 
 	/*  Enable PCI device and request regions */
 	if (comedi_pci_enable(pci_dev, PCI6208_DRIVER_NAME) < 0) {
-		printk
-		    ("comedi%d: Failed to enable PCI device and request regions\n",
-		     dev_minor);
+		printk(KERN_ERR "comedi%d: Failed to enable PCI device "
+			"and request regions\n",
+			dev_minor);
 		return -EIO;
 	}
-	/*  Read local configuration register base address [PCI_BASE_ADDRESS #1]. */
+	/* Read local configuration register
+	 * base address [PCI_BASE_ADDRESS #1].
+	 */
 	lcr_io_base = pci_resource_start(pci_dev, 1);
 	lcr_io_range = pci_resource_len(pci_dev, 1);
 
-	printk("comedi%d: local config registers at address 0x%4lx [0x%4lx]\n",
-	       dev_minor, lcr_io_base, lcr_io_range);
+	printk(KERN_INFO "comedi%d: local config registers at address"
+			" 0x%4lx [0x%4lx]\n",
+			dev_minor, lcr_io_base, lcr_io_range);
 
 	/*  Read PCI6208 register base address [PCI_BASE_ADDRESS #2]. */
 	io_base = pci_resource_start(pci_dev, 2);

+ 9 - 10
drivers/staging/comedi/drivers/adl_pci7296.c

@@ -82,8 +82,7 @@ static int adl_pci7296_attach(struct comedi_device *dev,
 	int bus, slot;
 	int ret;
 
-	printk("comedi: attempt to attach...\n");
-	printk("comedi%d: adl_pci7432\n", dev->minor);
+	printk(KERN_INFO "comedi%d: attach adl_pci7432\n", dev->minor);
 
 	dev->board_name = "pci7432";
 	bus = it->options[0];
@@ -110,14 +109,14 @@ static int adl_pci7296_attach(struct comedi_device *dev,
 			}
 			devpriv->pci_dev = pcidev;
 			if (comedi_pci_enable(pcidev, "adl_pci7296") < 0) {
-				printk
-				    ("comedi%d: Failed to enable PCI device and request regions\n",
+				printk(KERN_ERR "comedi%d: Failed to enable PCI device and request regions\n",
 				     dev->minor);
 				return -EIO;
 			}
 
 			dev->iobase = pci_resource_start(pcidev, 2);
-			printk("comedi: base addr %4lx\n", dev->iobase);
+			printk(KERN_INFO "comedi: base addr %4lx\n",
+				dev->iobase);
 
 			/*  four 8255 digital io subdevices */
 			s = dev->subdevices + 0;
@@ -145,25 +144,25 @@ static int adl_pci7296_attach(struct comedi_device *dev,
 			if (ret < 0)
 				return ret;
 
-			printk("attached\n");
+			printk(KERN_DEBUG "comedi%d: adl_pci7432 attached\n",
+				dev->minor);
 
 			return 1;
 		}
 	}
 
-	printk("comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
+	printk(KERN_ERR "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
 	       dev->minor, bus, slot);
 	return -EIO;
 }
 
 static int adl_pci7296_detach(struct comedi_device *dev)
 {
-	printk("comedi%d: pci7432: remove\n", dev->minor);
+	printk(KERN_INFO "comedi%d: pci7432: remove\n", dev->minor);
 
 	if (devpriv && devpriv->pci_dev) {
-		if (dev->iobase) {
+		if (dev->iobase)
 			comedi_pci_disable(devpriv->pci_dev);
-		}
 		pci_dev_put(devpriv->pci_dev);
 	}
 	/*  detach four 8255 digital io subdevices */

+ 15 - 17
drivers/staging/comedi/drivers/adl_pci7432.c

@@ -90,8 +90,7 @@ static int adl_pci7432_attach(struct comedi_device *dev,
 	struct comedi_subdevice *s;
 	int bus, slot;
 
-	printk("comedi: attempt to attach...\n");
-	printk("comedi%d: adl_pci7432\n", dev->minor);
+	printk(KERN_INFO "comedi%d: attach adl_pci7432\n", dev->minor);
 
 	dev->board_name = "pci7432";
 	bus = it->options[0];
@@ -118,13 +117,13 @@ static int adl_pci7432_attach(struct comedi_device *dev,
 			}
 			devpriv->pci_dev = pcidev;
 			if (comedi_pci_enable(pcidev, "adl_pci7432") < 0) {
-				printk
-				    ("comedi%d: Failed to enable PCI device and request regions\n",
+				printk(KERN_ERR "comedi%d: Failed to enable PCI device and request regions\n",
 				     dev->minor);
 				return -EIO;
 			}
 			dev->iobase = pci_resource_start(pcidev, 2);
-			printk("comedi: base addr %4lx\n", dev->iobase);
+			printk(KERN_INFO "comedi: base addr %4lx\n",
+				dev->iobase);
 
 			s = dev->subdevices + 0;
 			s->type = COMEDI_SUBD_DI;
@@ -148,25 +147,24 @@ static int adl_pci7432_attach(struct comedi_device *dev,
 			s->range_table = &range_digital;
 			s->insn_bits = adl_pci7432_do_insn_bits;
 
-			printk("comedi: attached\n");
-
+			printk(KERN_DEBUG "comedi%d: adl_pci7432 attached\n",
+				dev->minor);
 			return 1;
 		}
 	}
 
-	printk("comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
+	printk(KERN_ERR "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
 	       dev->minor, bus, slot);
 	return -EIO;
 }
 
 static int adl_pci7432_detach(struct comedi_device *dev)
 {
-	printk("comedi%d: pci7432: remove\n", dev->minor);
+	printk(KERN_INFO "comedi%d: pci7432: remove\n", dev->minor);
 
 	if (devpriv && devpriv->pci_dev) {
-		if (dev->iobase) {
+		if (dev->iobase)
 			comedi_pci_disable(devpriv->pci_dev);
-		}
 		pci_dev_put(devpriv->pci_dev);
 	}
 
@@ -178,8 +176,8 @@ static int adl_pci7432_do_insn_bits(struct comedi_device *dev,
 				    struct comedi_insn *insn,
 				    unsigned int *data)
 {
-	printk("comedi: pci7432_do_insn_bits called\n");
-	printk("comedi: data0: %8x data1: %8x\n", data[0], data[1]);
+	printk(KERN_DEBUG "comedi: pci7432_do_insn_bits called\n");
+	printk(KERN_DEBUG "comedi: data0: %8x data1: %8x\n", data[0], data[1]);
 
 	if (insn->n != 2)
 		return -EINVAL;
@@ -188,7 +186,7 @@ static int adl_pci7432_do_insn_bits(struct comedi_device *dev,
 		s->state &= ~data[0];
 		s->state |= (data[0] & data[1]);
 
-		printk("comedi: out: %8x on iobase %4lx\n", s->state,
+		printk(KERN_DEBUG "comedi: out: %8x on iobase %4lx\n", s->state,
 		       dev->iobase + PCI7432_DO);
 		outl(s->state & 0xffffffff, dev->iobase + PCI7432_DO);
 	}
@@ -200,14 +198,14 @@ static int adl_pci7432_di_insn_bits(struct comedi_device *dev,
 				    struct comedi_insn *insn,
 				    unsigned int *data)
 {
-	printk("comedi: pci7432_di_insn_bits called\n");
-	printk("comedi: data0: %8x data1: %8x\n", data[0], data[1]);
+	printk(KERN_DEBUG "comedi: pci7432_di_insn_bits called\n");
+	printk(KERN_DEBUG "comedi: data0: %8x data1: %8x\n", data[0], data[1]);
 
 	if (insn->n != 2)
 		return -EINVAL;
 
 	data[1] = inl(dev->iobase + PCI7432_DI) & 0xffffffff;
-	printk("comedi: data1 %8x\n", data[1]);
+	printk(KERN_DEBUG "comedi: data1 %8x\n", data[1]);
 
 	return 2;
 }

+ 19 - 18
drivers/staging/comedi/drivers/adl_pci8164.c

@@ -35,6 +35,7 @@ Configuration Options:
 */
 
 #include "../comedidev.h"
+#include <linux/kernel.h>
 #include <linux/delay.h>
 #include "comedi_fc.h"
 #include "comedi_pci.h"
@@ -128,8 +129,8 @@ static int adl_pci8164_attach(struct comedi_device *dev,
 	struct comedi_subdevice *s;
 	int bus, slot;
 
-	printk("comedi: attempt to attach...\n");
-	printk("comedi%d: adl_pci8164\n", dev->minor);
+	printk(KERN_INFO "comedi: attempt to attach...\n");
+	printk(KERN_INFO "comedi%d: adl_pci8164\n", dev->minor);
 
 	dev->board_name = "pci8164";
 	bus = it->options[0];
@@ -150,19 +151,18 @@ static int adl_pci8164_attach(struct comedi_device *dev,
 			if (bus || slot) {
 				/* requested particular bus/slot */
 				if (pcidev->bus->number != bus
-				    || PCI_SLOT(pcidev->devfn) != slot) {
+					|| PCI_SLOT(pcidev->devfn) != slot)
 					continue;
-				}
 			}
 			devpriv->pci_dev = pcidev;
 			if (comedi_pci_enable(pcidev, "adl_pci8164") < 0) {
-				printk
-				    ("comedi%d: Failed to enable PCI device and request regions\n",
-				     dev->minor);
+				printk(KERN_ERR "comedi%d: Failed to enable "
+				"PCI device and request regions\n", dev->minor);
 				return -EIO;
 			}
 			dev->iobase = pci_resource_start(pcidev, 2);
-			printk("comedi: base addr %4lx\n", dev->iobase);
+			printk(KERN_DEBUG "comedi: base addr %4lx\n",
+				   dev->iobase);
 
 			s = dev->subdevices + 0;
 			s->type = COMEDI_SUBD_PROC;
@@ -204,25 +204,24 @@ static int adl_pci8164_attach(struct comedi_device *dev,
 			s->insn_read = adl_pci8164_insn_read_buf1;
 			s->insn_write = adl_pci8164_insn_write_buf1;
 
-			printk("comedi: attached\n");
+			printk(KERN_INFO "comedi: attached\n");
 
 			return 1;
 		}
 	}
 
-	printk("comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
-	       dev->minor, bus, slot);
+	printk(KERN_ERR "comedi%d: no supported board found!"
+		   "(req. bus/slot : %d/%d)\n", dev->minor, bus, slot);
 	return -EIO;
 }
 
 static int adl_pci8164_detach(struct comedi_device *dev)
 {
-	printk("comedi%d: pci8164: remove\n", dev->minor);
+	printk(KERN_INFO "comedi%d: pci8164: remove\n", dev->minor);
 
 	if (devpriv && devpriv->pci_dev) {
-		if (dev->iobase) {
+		if (dev->iobase)
 			comedi_pci_disable(devpriv->pci_dev);
-		}
 		pci_dev_put(devpriv->pci_dev);
 	}
 
@@ -267,8 +266,9 @@ static void adl_pci8164_insn_read(struct comedi_device *dev,
 	}
 
 	data[0] = inw(dev->iobase + axis_reg + offset);
-	printk("comedi: pci8164 %s read -> %04X:%04X on axis %s\n", action,
-	       data[0], data[1], axisname);
+	printk(KERN_DEBUG "comedi: pci8164 %s read -> "
+						  "%04X:%04X on axis %s\n",
+				action, data[0], data[1], axisname);
 }
 
 static int adl_pci8164_insn_read_msts(struct comedi_device *dev,
@@ -347,8 +347,9 @@ static void adl_pci8164_insn_out(struct comedi_device *dev,
 
 	outw(data[0], dev->iobase + axis_reg + offset);
 
-	printk("comedi: pci8164 %s write -> %04X:%04X on axis %s\n", action,
-	       data[0], data[1], axisname);
+	printk(KERN_DEBUG "comedi: pci8164 %s write -> "
+						"%04X:%04X on axis %s\n",
+				action, data[0], data[1], axisname);
 
 }
 

+ 1 - 1
drivers/staging/comedi/drivers/adl_pci9118.c

@@ -780,7 +780,7 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev,
 			      struct comedi_cmd *cmd)
 {
 	int err = 0;
-	int tmp, divisor1, divisor2;
+	int tmp, divisor1 = 0, divisor2 = 0;
 
 	/* step 1: make sure trigger sources are trivially valid */
 

+ 2 - 2
drivers/staging/comedi/drivers/adv_pci1710.c

@@ -830,7 +830,7 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d)
 static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device *dev,
 				     struct comedi_subdevice *s)
 {
-	unsigned int divisor1, divisor2;
+	unsigned int divisor1 = 0, divisor2 = 0;
 	unsigned int seglen;
 
 	DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_docmd_and_mode(%d,...)\n",
@@ -934,7 +934,7 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev,
 			      struct comedi_cmd *cmd)
 {
 	int err = 0;
-	int tmp, divisor1, divisor2;
+	int tmp, divisor1 = 0, divisor2 = 0;
 
 	DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...)\n");
 #ifdef PCI171X_EXTDEBUG

+ 8 - 10
drivers/staging/comedi/drivers/amplc_pc263.c

@@ -117,7 +117,8 @@ MODULE_DEVICE_TABLE(pci, pc263_pci_table);
 
 /* this structure is for data unique to this hardware driver.  If
    several hardware drivers keep similar information in this structure,
-   feel free to suggest moving the variable to the struct comedi_device struct.  */
+   feel free to suggest moving the variable to the struct comedi_device struct.
+*/
 #ifdef CONFIG_COMEDI_PCI
 struct pc263_private {
 	/* PCI device. */
@@ -281,7 +282,8 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 		ret = comedi_pci_enable(pci_dev, PC263_DRIVER_NAME);
 		if (ret < 0) {
 			printk(KERN_ERR
-			       "comedi%d: error! cannot enable PCI device and request regions!\n",
+			       "comedi%d: error! cannot enable PCI device and "
+				"request regions!\n",
 			       dev->minor);
 			return ret;
 		}
@@ -290,9 +292,8 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 #endif
 	{
 		ret = pc263_request_region(dev->minor, iobase, PC263_IO_SIZE);
-		if (ret < 0) {
+		if (ret < 0)
 			return ret;
-		}
 	}
 	dev->iobase = iobase;
 
@@ -350,21 +351,18 @@ static int pc263_detach(struct comedi_device *dev)
 	       PC263_DRIVER_NAME);
 
 #ifdef CONFIG_COMEDI_PCI
-	if (devpriv)
+	if (devpriv) {
 #endif
-	{
 #ifdef CONFIG_COMEDI_PCI
 		if (devpriv->pci_dev) {
-			if (dev->iobase) {
+			if (dev->iobase)
 				comedi_pci_disable(devpriv->pci_dev);
-			}
 			pci_dev_put(devpriv->pci_dev);
 		} else
 #endif
 		{
-			if (dev->iobase) {
+			if (dev->iobase)
 				release_region(dev->iobase, PC263_IO_SIZE);
-			}
 		}
 	}
 	if (dev->board_name) {

+ 3 - 3
drivers/staging/comedi/drivers/cb_das16_cs.c

@@ -372,7 +372,7 @@ static int das16cs_ai_cmdtest(struct comedi_device *dev,
 
 	/* step 2: make sure trigger sources are unique and mutually compatible */
 
-	/* note that mutual compatiblity is not an issue here */
+	/* note that mutual compatibility is not an issue here */
 	if (cmd->scan_begin_src != TRIG_TIMER &&
 	    cmd->scan_begin_src != TRIG_EXT)
 		err++;
@@ -452,7 +452,7 @@ static int das16cs_ai_cmdtest(struct comedi_device *dev,
 	/* step 4: fix up any arguments */
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
-		unsigned int div1, div2;
+		unsigned int div1 = 0, div2 = 0;
 
 		tmp = cmd->scan_begin_arg;
 		i8253_cascade_ns_to_timer(100, &div1, &div2,
@@ -462,7 +462,7 @@ static int das16cs_ai_cmdtest(struct comedi_device *dev,
 			err++;
 	}
 	if (cmd->convert_src == TRIG_TIMER) {
-		unsigned int div1, div2;
+		unsigned int div1 = 0, div2 = 0;
 
 		tmp = cmd->convert_arg;
 		i8253_cascade_ns_to_timer(100, &div1, &div2,

+ 1 - 1
drivers/staging/comedi/drivers/cb_pcidda.c

@@ -497,7 +497,7 @@ static int cb_pcidda_ai_cmdtest(struct comedi_device *dev,
 
 	/* step 2: make sure trigger sources are unique and mutually compatible */
 
-	/* note that mutual compatiblity is not an issue here */
+	/* note that mutual compatibility is not an issue here */
 	if (cmd->scan_begin_src != TRIG_TIMER
 	    && cmd->scan_begin_src != TRIG_EXT)
 		err++;

+ 2 - 2
drivers/staging/comedi/drivers/cb_pcidio.c

@@ -109,12 +109,12 @@ MODULE_DEVICE_TABLE(pci, pcidio_pci_table);
    several hardware drivers keep similar information in this structure,
    feel free to suggest moving the variable to the struct comedi_device struct.  */
 struct pcidio_private {
-	int data;		/*  curently unused */
+	int data;		/*  currently unused */
 
 	/* would be useful for a PCI device */
 	struct pci_dev *pci_dev;
 
-	/* used for DO readback, curently unused */
+	/* used for DO readback, currently unused */
 	unsigned int do_readback[4];	/* up to 4 unsigned int suffice to hold 96 bits for PCI-DIO96 */
 
 	unsigned long dio_reg_base;	/*  address of port A of the first 8255 chip on board */

+ 1 - 4
drivers/staging/comedi/drivers/comedi_fc.c

@@ -53,7 +53,7 @@ unsigned int cfc_write_array_to_buffer(struct comedi_subdevice *subd,
 
 	retval = comedi_buf_write_alloc(async, num_bytes);
 	if (retval != num_bytes) {
-		printk("comedi: buffer overrun\n");
+		printk(KERN_WARNING "comedi: buffer overrun\n");
 		async->events |= COMEDI_CB_OVERFLOW;
 		return 0;
 	}
@@ -65,7 +65,6 @@ unsigned int cfc_write_array_to_buffer(struct comedi_subdevice *subd,
 
 	return num_bytes;
 }
-
 EXPORT_SYMBOL(cfc_write_array_to_buffer);
 
 unsigned int cfc_read_array_from_buffer(struct comedi_subdevice *subd,
@@ -84,7 +83,6 @@ unsigned int cfc_read_array_from_buffer(struct comedi_subdevice *subd,
 
 	return num_bytes;
 }
-
 EXPORT_SYMBOL(cfc_read_array_from_buffer);
 
 unsigned int cfc_handle_events(struct comedi_device *dev,
@@ -102,7 +100,6 @@ unsigned int cfc_handle_events(struct comedi_device *dev,
 
 	return events;
 }
-
 EXPORT_SYMBOL(cfc_handle_events);
 
 MODULE_AUTHOR("Frank Mori Hess <fmhess@users.sourceforge.net>");

+ 1 - 1
drivers/staging/comedi/drivers/dmm32at.c

@@ -629,7 +629,7 @@ static int dmm32at_ai_cmdtest(struct comedi_device *dev,
 
 	/* step 2: make sure trigger sources are unique and mutually compatible */
 
-	/* note that mutual compatiblity is not an issue here */
+	/* note that mutual compatibility is not an issue here */
 	if (cmd->scan_begin_src != TRIG_TIMER &&
 	    cmd->scan_begin_src != TRIG_EXT)
 		err++;

+ 1 - 1
drivers/staging/comedi/drivers/dt2814.c

@@ -175,7 +175,7 @@ static int dt2814_ai_cmdtest(struct comedi_device *dev,
 
 	/* step 2: make sure trigger sources are unique and mutually compatible */
 
-	/* note that mutual compatiblity is not an issue here */
+	/* note that mutual compatibility is not an issue here */
 	if (cmd->stop_src != TRIG_TIMER && cmd->stop_src != TRIG_EXT)
 		err++;
 

+ 2 - 2
drivers/staging/comedi/drivers/dt282x.c

@@ -777,7 +777,7 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev,
 
 	/* step 2: make sure trigger sources are unique and mutually compatible */
 
-	/* note that mutual compatiblity is not an issue here */
+	/* note that mutual compatibility is not an issue here */
 	if (cmd->scan_begin_src != TRIG_FOLLOW &&
 	    cmd->scan_begin_src != TRIG_EXT)
 		err++;
@@ -1050,7 +1050,7 @@ static int dt282x_ao_cmdtest(struct comedi_device *dev,
 
 	/* step 2: make sure trigger sources are unique and mutually compatible */
 
-	/* note that mutual compatiblity is not an issue here */
+	/* note that mutual compatibility is not an issue here */
 	if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
 		err++;
 

+ 64 - 62
drivers/staging/comedi/drivers/gsc_hpdi.c

@@ -55,7 +55,7 @@ support could be added to this driver.
 
 static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it);
 static int hpdi_detach(struct comedi_device *dev);
-void abort_dma(struct comedi_device *dev, unsigned int channel);
+static void abort_dma(struct comedi_device *dev, unsigned int channel);
 static int hpdi_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
 static int hpdi_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 			 struct comedi_cmd *cmd);
@@ -110,7 +110,8 @@ enum hpdi_registers {
 int command_channel_valid(unsigned int channel)
 {
 	if (channel == 0 || channel > 6) {
-		printk("gsc_hpdi: bug! invalid cable command channel\n");
+		printk(KERN_WARNING
+		       "gsc_hpdi: bug! invalid cable command channel\n");
 		return 0;
 	}
 	return 1;
@@ -142,7 +143,8 @@ enum board_control_bits {
 	RX_FIFO_RESET_BIT = 0x4,
 	TX_ENABLE_BIT = 0x10,
 	RX_ENABLE_BIT = 0x20,
-	DEMAND_DMA_DIRECTION_TX_BIT = 0x40,	/* for channel 0, channel 1 can only transmit (when present) */
+	DEMAND_DMA_DIRECTION_TX_BIT = 0x40,
+		/* for ch 0, ch 1 can only transmit (when present) */
 	LINE_VALID_ON_STATUS_VALID_BIT = 0x80,
 	START_TX_BIT = 0x10,
 	CABLE_THROTTLE_ENABLE_BIT = 0x20,
@@ -420,9 +422,11 @@ static void init_plx9080(struct comedi_device *dev)
 	bits |= PLX_DMA_EN_READYIN_BIT;
 	/*  enable dma chaining */
 	bits |= PLX_EN_CHAIN_BIT;
-	/*  enable interrupt on dma done (probably don't need this, since chain never finishes) */
+	/*  enable interrupt on dma done
+	 *  (probably don't need this, since chain never finishes) */
 	bits |= PLX_EN_DMA_DONE_INTR_BIT;
-	/*  don't increment local address during transfers (we are transferring from a fixed fifo register) */
+	/*  don't increment local address during transfers
+	 *  (we are transferring from a fixed fifo register) */
 	bits |= PLX_LOCAL_ADDR_CONST_BIT;
 	/*  route dma interrupt to pci bus */
 	bits |= PLX_DMA_INTR_PCI_BIT;
@@ -560,7 +564,7 @@ static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	int i;
 	int retval;
 
-	printk("comedi%d: gsc_hpdi\n", dev->minor);
+	printk(KERN_WARNING "comedi%d: gsc_hpdi\n", dev->minor);
 
 	if (alloc_private(dev, sizeof(struct hpdi_private)) < 0)
 		return -ENOMEM;
@@ -588,11 +592,12 @@ static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 		} while (pcidev != NULL);
 	}
 	if (dev->board_ptr == NULL) {
-		printk("gsc_hpdi: no hpdi card found\n");
+		printk(KERN_WARNING "gsc_hpdi: no hpdi card found\n");
 		return -EIO;
 	}
 
-	printk("gsc_hpdi: found %s on bus %i, slot %i\n", board(dev)->name,
+	printk(KERN_WARNING
+	       "gsc_hpdi: found %s on bus %i, slot %i\n", board(dev)->name,
 	       pcidev->bus->number, PCI_SLOT(pcidev->devfn));
 
 	if (comedi_pci_enable(pcidev, driver_hpdi.driver_name)) {
@@ -618,7 +623,7 @@ static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	    ioremap(priv(dev)->hpdi_phys_iobase,
 		    pci_resource_len(pcidev, HPDI_BADDRINDEX));
 	if (!priv(dev)->plx9080_iobase || !priv(dev)->hpdi_iobase) {
-		printk(" failed to remap io memory\n");
+		printk(KERN_WARNING " failed to remap io memory\n");
 		return -ENOMEM;
 	}
 
@@ -630,12 +635,13 @@ static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	/*  get irq */
 	if (request_irq(pcidev->irq, handle_interrupt, IRQF_SHARED,
 			driver_hpdi.driver_name, dev)) {
-		printk(" unable to allocate irq %u\n", pcidev->irq);
+		printk(KERN_WARNING
+		       " unable to allocate irq %u\n", pcidev->irq);
 		return -EINVAL;
 	}
 	dev->irq = pcidev->irq;
 
-	printk(" irq %u\n", dev->irq);
+	printk(KERN_WARNING " irq %u\n", dev->irq);
 
 	/*  alocate pci dma buffers */
 	for (i = 0; i < NUM_DMA_BUFFERS; i++) {
@@ -653,7 +659,8 @@ static int hpdi_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 						   &priv(dev)->
 						   dma_desc_phys_addr);
 	if (priv(dev)->dma_desc_phys_addr & 0xf) {
-		printk(" dma descriptors not quad-word aligned (bug)\n");
+		printk(KERN_WARNING
+		       " dma descriptors not quad-word aligned (bug)\n");
 		return -EIO;
 	}
 
@@ -672,42 +679,39 @@ static int hpdi_detach(struct comedi_device *dev)
 {
 	unsigned int i;
 
-	printk("comedi%d: gsc_hpdi: remove\n", dev->minor);
+	printk(KERN_WARNING "comedi%d: gsc_hpdi: remove\n", dev->minor);
 
 	if (dev->irq)
 		free_irq(dev->irq, dev);
-	if (priv(dev)) {
-		if (priv(dev)->hw_dev) {
-			if (priv(dev)->plx9080_iobase) {
-				disable_plx_interrupts(dev);
-				iounmap((void *)priv(dev)->plx9080_iobase);
-			}
-			if (priv(dev)->hpdi_iobase)
-				iounmap((void *)priv(dev)->hpdi_iobase);
-			/*  free pci dma buffers */
-			for (i = 0; i < NUM_DMA_BUFFERS; i++) {
-				if (priv(dev)->dio_buffer[i])
-					pci_free_consistent(priv(dev)->hw_dev,
-							    DMA_BUFFER_SIZE,
-							    priv(dev)->
-							    dio_buffer[i],
-							    priv
-							    (dev)->dio_buffer_phys_addr
-							    [i]);
-			}
-			/*  free dma descriptors */
-			if (priv(dev)->dma_desc)
+	if ((priv(dev)) && (priv(dev)->hw_dev)) {
+		if (priv(dev)->plx9080_iobase) {
+			disable_plx_interrupts(dev);
+			iounmap((void *)priv(dev)->plx9080_iobase);
+		}
+		if (priv(dev)->hpdi_iobase)
+			iounmap((void *)priv(dev)->hpdi_iobase);
+		/*  free pci dma buffers */
+		for (i = 0; i < NUM_DMA_BUFFERS; i++) {
+			if (priv(dev)->dio_buffer[i])
 				pci_free_consistent(priv(dev)->hw_dev,
-						    sizeof(struct plx_dma_desc)
-						    * NUM_DMA_DESCRIPTORS,
-						    priv(dev)->dma_desc,
+						    DMA_BUFFER_SIZE,
 						    priv(dev)->
-						    dma_desc_phys_addr);
-			if (priv(dev)->hpdi_phys_iobase) {
-				comedi_pci_disable(priv(dev)->hw_dev);
-			}
-			pci_dev_put(priv(dev)->hw_dev);
+						    dio_buffer[i],
+						    priv
+						    (dev)->dio_buffer_phys_addr
+						    [i]);
 		}
+		/*  free dma descriptors */
+		if (priv(dev)->dma_desc)
+			pci_free_consistent(priv(dev)->hw_dev,
+					    sizeof(struct plx_dma_desc)
+					    * NUM_DMA_DESCRIPTORS,
+					    priv(dev)->dma_desc,
+					    priv(dev)->
+					    dma_desc_phys_addr);
+		if (priv(dev)->hpdi_phys_iobase)
+			comedi_pci_disable(priv(dev)->hw_dev);
+		pci_dev_put(priv(dev)->hw_dev);
 	}
 	return 0;
 }
@@ -810,15 +814,16 @@ static int di_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 	if (err)
 		return 4;
 
-	if (cmd->chanlist) {
-		for (i = 1; i < cmd->chanlist_len; i++) {
-			if (CR_CHAN(cmd->chanlist[i]) != i) {
-				/*  XXX could support 8 channels or 16 channels */
-				comedi_error(dev,
-					     "chanlist must be channels 0 to 31 in order");
-				err++;
-				break;
-			}
+	if (!cmd->chanlist)
+		return 0;
+
+	for (i = 1; i < cmd->chanlist_len; i++) {
+		if (CR_CHAN(cmd->chanlist[i]) != i) {
+			/*  XXX could support 8 or 16 channels */
+			comedi_error(dev,
+				     "chanlist must be ch 0 to 31 in order");
+			err++;
+			break;
 		}
 	}
 
@@ -831,9 +836,9 @@ static int di_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 static int hpdi_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 			 struct comedi_cmd *cmd)
 {
-	if (priv(dev)->dio_config_output) {
+	if (priv(dev)->dio_config_output)
 		return -EINVAL;
-	} else
+	else
 		return di_cmd_test(dev, s, cmd);
 }
 
@@ -899,9 +904,9 @@ static int di_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 static int hpdi_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	if (priv(dev)->dio_config_output) {
+	if (priv(dev)->dio_config_output)
 		return -EINVAL;
-	} else
+	else
 		return di_cmd(dev, s);
 }
 
@@ -963,14 +968,12 @@ static irqreturn_t handle_interrupt(int irq, void *d)
 	uint8_t dma0_status, dma1_status;
 	unsigned long flags;
 
-	if (!dev->attached) {
+	if (!dev->attached)
 		return IRQ_NONE;
-	}
 
 	plx_status = readl(priv(dev)->plx9080_iobase + PLX_INTRCS_REG);
-	if ((plx_status & (ICS_DMA0_A | ICS_DMA1_A | ICS_LIA)) == 0) {
+	if ((plx_status & (ICS_DMA0_A | ICS_DMA1_A | ICS_LIA)) == 0)
 		return IRQ_NONE;
-	}
 
 	hpdi_intr_status = readl(priv(dev)->hpdi_iobase + INTERRUPT_STATUS_REG);
 	hpdi_board_status = readl(priv(dev)->hpdi_iobase + BOARD_STATUS_REG);
@@ -990,9 +993,8 @@ static irqreturn_t handle_interrupt(int irq, void *d)
 		       priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG);
 
 		DEBUG_PRINT("dma0 status 0x%x\n", dma0_status);
-		if (dma0_status & PLX_DMA_EN_BIT) {
+		if (dma0_status & PLX_DMA_EN_BIT)
 			drain_dma_buffers(dev, 0);
-		}
 		DEBUG_PRINT(" cleared dma ch0 interrupt\n");
 	}
 	spin_unlock_irqrestore(&dev->spinlock, flags);
@@ -1042,7 +1044,7 @@ static irqreturn_t handle_interrupt(int irq, void *d)
 	return IRQ_HANDLED;
 }
 
-void abort_dma(struct comedi_device *dev, unsigned int channel)
+static void abort_dma(struct comedi_device *dev, unsigned int channel)
 {
 	unsigned long flags;
 

+ 182 - 163
drivers/staging/comedi/drivers/icp_multi.c

@@ -46,7 +46,7 @@ There are 4 x 12-bit Analogue Outputs.  Ranges : 5V, 10V, +/-5V, +/-10V
 
 Options:
  [0] - PCI bus number - if bus number and slot number are 0,
-                        then driver search for first unused card
+			then driver search for first unused card
  [1] - PCI slot number
 */
 
@@ -133,7 +133,7 @@ static int icp_multi_detach(struct comedi_device *dev);
 	Data & Structure declarations
 ==============================================================================
 */
-static unsigned short pci_list_builded = 0;	/*>0 list of card is known */
+static unsigned short pci_list_builded;	/*>0 list of card is known */
 
 struct boardtype {
 	const char *name;	/*  driver name */
@@ -176,13 +176,13 @@ static const struct boardtype boardtypes[] = {
 #define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype))
 
 static struct comedi_driver driver_icp_multi = {
-driver_name:"icp_multi",
-module:THIS_MODULE,
-attach:icp_multi_attach,
-detach:icp_multi_detach,
-num_names:n_boardtypes,
-board_name:&boardtypes[0].name,
-offset:sizeof(struct boardtype),
+driver_name: "icp_multi",
+module : THIS_MODULE,
+attach : icp_multi_attach,
+detach : icp_multi_detach,
+num_names : n_boardtypes,
+board_name : &boardtypes[0].name,
+offset : sizeof(struct boardtype),
 };
 
 COMEDI_INITCLEANUP(driver_icp_multi);
@@ -234,18 +234,18 @@ static int icp_multi_reset(struct comedi_device *dev);
 /*
 ==============================================================================
 
-	Name:	icp_multi_insn_read_ai
+Name:	icp_multi_insn_read_ai
 
-	Description:
-		This function reads a single analogue input.
+Description:
+	This function reads a single analogue input.
 
-	Parameters:
-		struct comedi_device *dev	Pointer to current device structure
-		struct comedi_subdevice *s	Pointer to current subdevice structure
-		struct comedi_insn *insn	Pointer to current comedi instruction
-		unsigned int *data		Pointer to analogue input data
+Parameters:
+	struct comedi_device *dev	Pointer to current device structure
+	struct comedi_subdevice *s	Pointer to current subdevice structure
+	struct comedi_insn *insn	Pointer to current comedi instruction
+	unsigned int *data		Pointer to analogue input data
 
-	Returns:int			Nmuber of instructions executed
+Returns:int			Nmuber of instructions executed
 
 ==============================================================================
 */
@@ -256,7 +256,7 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev,
 	int n, timeout;
 
 #ifdef ICP_MULTI_EXTDEBUG
-	printk("icp multi EDBG: BGN: icp_multi_insn_read_ai(...)\n");
+	printk(KERN_DEBUG "icp multi EDBG: BGN: icp_multi_insn_read_ai(...)\n");
 #endif
 	/*  Disable A/D conversion ready interrupt */
 	devpriv->IntEnable &= ~ADC_READY;
@@ -266,11 +266,11 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev,
 	devpriv->IntStatus |= ADC_READY;
 	writew(devpriv->IntStatus, devpriv->io_addr + ICP_MULTI_INT_STAT);
 
-	/*  Set up appropriate channel, mode and range data, for specified channel */
+	/*  Set up appropriate channel, mode and range data, for specified ch */
 	setup_channel_list(dev, s, &insn->chanspec, 1);
 
 #ifdef ICP_MULTI_EXTDEBUG
-	printk("icp_multi A ST=%4x IO=%p\n",
+	printk(KERN_DEBUG "icp_multi A ST=%4x IO=%p\n",
 	       readw(devpriv->io_addr + ICP_MULTI_ADC_CSR),
 	       devpriv->io_addr + ICP_MULTI_ADC_CSR);
 #endif
@@ -283,14 +283,14 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev,
 		devpriv->AdcCmdStatus &= ~ADC_ST;
 
 #ifdef ICP_MULTI_EXTDEBUG
-		printk("icp multi B n=%d ST=%4x\n", n,
+		printk(KERN_DEBUG "icp multi B n=%d ST=%4x\n", n,
 		       readw(devpriv->io_addr + ICP_MULTI_ADC_CSR));
 #endif
 
 		udelay(1);
 
 #ifdef ICP_MULTI_EXTDEBUG
-		printk("icp multi C n=%d ST=%4x\n", n,
+		printk(KERN_DEBUG "icp multi C n=%d ST=%4x\n", n,
 		       readw(devpriv->io_addr + ICP_MULTI_ADC_CSR));
 #endif
 
@@ -303,7 +303,8 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev,
 
 #ifdef ICP_MULTI_EXTDEBUG
 			if (!(timeout % 10))
-				printk("icp multi D n=%d tm=%d ST=%4x\n", n,
+				printk(KERN_DEBUG
+				       "icp multi D n=%d tm=%d ST=%4x\n", n,
 				       timeout,
 				       readw(devpriv->io_addr +
 					     ICP_MULTI_ADC_CSR));
@@ -328,9 +329,9 @@ static int icp_multi_insn_read_ai(struct comedi_device *dev,
 		data[n] = 0;
 
 #ifdef ICP_MULTI_EXTDEBUG
-		printk
-		    ("icp multi EDBG: END: icp_multi_insn_read_ai(...) n=%d\n",
-		     n);
+		printk(KERN_DEBUG
+		      "icp multi EDBG: END: icp_multi_insn_read_ai(...) n=%d\n",
+		      n);
 #endif
 		return -ETIME;
 
@@ -348,7 +349,8 @@ conv_finish:
 	writew(devpriv->IntStatus, devpriv->io_addr + ICP_MULTI_INT_STAT);
 
 #ifdef ICP_MULTI_EXTDEBUG
-	printk("icp multi EDBG: END: icp_multi_insn_read_ai(...) n=%d\n", n);
+	printk(KERN_DEBUG
+	       "icp multi EDBG: END: icp_multi_insn_read_ai(...) n=%d\n", n);
 #endif
 	return n;
 }
@@ -356,18 +358,18 @@ conv_finish:
 /*
 ==============================================================================
 
-	Name:	icp_multi_insn_write_ao
+Name:	icp_multi_insn_write_ao
 
-	Description:
-		This function writes a single analogue output.
+Description:
+	This function writes a single analogue output.
 
-	Parameters:
-		struct comedi_device *dev	Pointer to current device structure
-		struct comedi_subdevice *s	Pointer to current subdevice structure
-		struct comedi_insn *insn	Pointer to current comedi instruction
-		unsigned int *data		Pointer to analogue output data
+Parameters:
+	struct comedi_device *dev	Pointer to current device structure
+	struct comedi_subdevice *s	Pointer to current subdevice structure
+	struct comedi_insn *insn	Pointer to current comedi instruction
+	unsigned int *data		Pointer to analogue output data
 
-	Returns:int			Nmuber of instructions executed
+Returns:int			Nmuber of instructions executed
 
 ==============================================================================
 */
@@ -378,7 +380,8 @@ static int icp_multi_insn_write_ao(struct comedi_device *dev,
 	int n, chan, range, timeout;
 
 #ifdef ICP_MULTI_EXTDEBUG
-	printk("icp multi EDBG: BGN: icp_multi_insn_write_ao(...)\n");
+	printk(KERN_DEBUG
+	       "icp multi EDBG: BGN: icp_multi_insn_write_ao(...)\n");
 #endif
 	/*  Disable D/A conversion ready interrupt */
 	devpriv->IntEnable &= ~DAC_READY;
@@ -404,7 +407,8 @@ static int icp_multi_insn_write_ao(struct comedi_device *dev,
 	writew(devpriv->DacCmdStatus, devpriv->io_addr + ICP_MULTI_DAC_CSR);
 
 	for (n = 0; n < insn->n; n++) {
-		/*  Wait for analogue output data register to be ready for new data, or get fed up waiting */
+		/*  Wait for analogue output data register to be
+		 *  ready for new data, or get fed up waiting */
 		timeout = 100;
 		while (timeout--) {
 			if (!(readw(devpriv->io_addr +
@@ -413,7 +417,8 @@ static int icp_multi_insn_write_ao(struct comedi_device *dev,
 
 #ifdef ICP_MULTI_EXTDEBUG
 			if (!(timeout % 10))
-				printk("icp multi A n=%d tm=%d ST=%4x\n", n,
+				printk(KERN_DEBUG
+				       "icp multi A n=%d tm=%d ST=%4x\n", n,
 				       timeout,
 				       readw(devpriv->io_addr +
 					     ICP_MULTI_DAC_CSR));
@@ -438,8 +443,8 @@ static int icp_multi_insn_write_ao(struct comedi_device *dev,
 		devpriv->ao_data[chan] = 0;
 
 #ifdef ICP_MULTI_EXTDEBUG
-		printk
-		    ("icp multi EDBG: END: icp_multi_insn_write_ao(...) n=%d\n",
+		printk(KERN_DEBUG
+		     "icp multi EDBG: END: icp_multi_insn_write_ao(...) n=%d\n",
 		     n);
 #endif
 		return -ETIME;
@@ -459,7 +464,8 @@ dac_ready:
 	}
 
 #ifdef ICP_MULTI_EXTDEBUG
-	printk("icp multi EDBG: END: icp_multi_insn_write_ao(...) n=%d\n", n);
+	printk(KERN_DEBUG
+	       "icp multi EDBG: END: icp_multi_insn_write_ao(...) n=%d\n", n);
 #endif
 	return n;
 }
@@ -467,18 +473,18 @@ dac_ready:
 /*
 ==============================================================================
 
-	Name:	icp_multi_insn_read_ao
+Name:	icp_multi_insn_read_ao
 
-	Description:
-		This function reads a single analogue output.
+Description:
+	This function reads a single analogue output.
 
-	Parameters:
-		struct comedi_device *dev	Pointer to current device structure
-		struct comedi_subdevice *s	Pointer to current subdevice structure
-		struct comedi_insn *insn	Pointer to current comedi instruction
-		unsigned int *data		Pointer to analogue output data
+Parameters:
+	struct comedi_device *dev	Pointer to current device structure
+	struct comedi_subdevice *s	Pointer to current subdevice structure
+	struct comedi_insn *insn	Pointer to current comedi instruction
+	unsigned int *data		Pointer to analogue output data
 
-	Returns:int			Nmuber of instructions executed
+Returns:int			Nmuber of instructions executed
 
 ==============================================================================
 */
@@ -501,18 +507,18 @@ static int icp_multi_insn_read_ao(struct comedi_device *dev,
 /*
 ==============================================================================
 
-	Name:	icp_multi_insn_bits_di
+Name:	icp_multi_insn_bits_di
 
-	Description:
-		This function reads the digital inputs.
+Description:
+	This function reads the digital inputs.
 
-	Parameters:
-		struct comedi_device *dev	Pointer to current device structure
-		struct comedi_subdevice *s	Pointer to current subdevice structure
-		struct comedi_insn *insn	Pointer to current comedi instruction
-		unsigned int *data		Pointer to analogue output data
+Parameters:
+	struct comedi_device *dev	Pointer to current device structure
+	struct comedi_subdevice *s	Pointer to current subdevice structure
+	struct comedi_insn *insn	Pointer to current comedi instruction
+	unsigned int *data		Pointer to analogue output data
 
-	Returns:int			Nmuber of instructions executed
+Returns:int			Nmuber of instructions executed
 
 ==============================================================================
 */
@@ -528,18 +534,18 @@ static int icp_multi_insn_bits_di(struct comedi_device *dev,
 /*
 ==============================================================================
 
-	Name:	icp_multi_insn_bits_do
+Name:	icp_multi_insn_bits_do
 
-	Description:
-		This function writes the appropriate digital outputs.
+Description:
+	This function writes the appropriate digital outputs.
 
-	Parameters:
-		struct comedi_device *dev	Pointer to current device structure
-		struct comedi_subdevice *s	Pointer to current subdevice structure
-		struct comedi_insn *insn	Pointer to current comedi instruction
-		unsigned int *data		Pointer to analogue output data
+Parameters:
+	struct comedi_device *dev	Pointer to current device structure
+	struct comedi_subdevice *s	Pointer to current subdevice structure
+	struct comedi_insn *insn	Pointer to current comedi instruction
+	unsigned int *data		Pointer to analogue output data
 
-	Returns:int			Nmuber of instructions executed
+Returns:int			Nmuber of instructions executed
 
 ==============================================================================
 */
@@ -548,14 +554,14 @@ static int icp_multi_insn_bits_do(struct comedi_device *dev,
 				  struct comedi_insn *insn, unsigned int *data)
 {
 #ifdef ICP_MULTI_EXTDEBUG
-	printk("icp multi EDBG: BGN: icp_multi_insn_bits_do(...)\n");
+	printk(KERN_DEBUG "icp multi EDBG: BGN: icp_multi_insn_bits_do(...)\n");
 #endif
 
 	if (data[0]) {
 		s->state &= ~data[0];
 		s->state |= (data[0] & data[1]);
 
-		printk("Digital outputs = %4x \n", s->state);
+		printk(KERN_DEBUG "Digital outputs = %4x \n", s->state);
 
 		writew(s->state, devpriv->io_addr + ICP_MULTI_DO);
 	}
@@ -563,7 +569,7 @@ static int icp_multi_insn_bits_do(struct comedi_device *dev,
 	data[1] = readw(devpriv->io_addr + ICP_MULTI_DI);
 
 #ifdef ICP_MULTI_EXTDEBUG
-	printk("icp multi EDBG: END: icp_multi_insn_bits_do(...)\n");
+	printk(KERN_DEBUG "icp multi EDBG: END: icp_multi_insn_bits_do(...)\n");
 #endif
 	return 2;
 }
@@ -571,18 +577,18 @@ static int icp_multi_insn_bits_do(struct comedi_device *dev,
 /*
 ==============================================================================
 
-	Name:	icp_multi_insn_read_ctr
+Name:	icp_multi_insn_read_ctr
 
-	Description:
-		This function reads the specified counter.
+Description:
+	This function reads the specified counter.
 
-	Parameters:
-		struct comedi_device *dev	Pointer to current device structure
-		struct comedi_subdevice *s	Pointer to current subdevice structure
-		struct comedi_insn *insn	Pointer to current comedi instruction
-		unsigned int *data		Pointer to counter data
+Parameters:
+	struct comedi_device *dev	Pointer to current device structure
+	struct comedi_subdevice *s	Pointer to current subdevice structure
+	struct comedi_insn *insn	Pointer to current comedi instruction
+	unsigned int *data		Pointer to counter data
 
-	Returns:int			Nmuber of instructions executed
+Returns:int			Nmuber of instructions executed
 
 ==============================================================================
 */
@@ -596,18 +602,18 @@ static int icp_multi_insn_read_ctr(struct comedi_device *dev,
 /*
 ==============================================================================
 
-	Name:	icp_multi_insn_write_ctr
+Name:	icp_multi_insn_write_ctr
 
-	Description:
-		This function write to the specified counter.
+Description:
+	This function write to the specified counter.
 
-	Parameters:
-		struct comedi_device *dev	Pointer to current device structure
-		struct comedi_subdevice *s	Pointer to current subdevice structure
-		struct comedi_insn *insn	Pointer to current comedi instruction
-		unsigned int *data		Pointer to counter data
+Parameters:
+	struct comedi_device *dev	Pointer to current device structure
+	struct comedi_subdevice *s	Pointer to current subdevice structure
+	struct comedi_insn *insn	Pointer to current comedi instruction
+	unsigned int *data		Pointer to counter data
 
-	Returns:int			Nmuber of instructions executed
+Returns:int			Nmuber of instructions executed
 
 ==============================================================================
 */
@@ -622,15 +628,15 @@ static int icp_multi_insn_write_ctr(struct comedi_device *dev,
 /*
 ==============================================================================
 
-	Name:	interrupt_service_icp_multi
+Name:	interrupt_service_icp_multi
 
-	Description:
-		This function is the interrupt service routine for all
-		interrupts generated by the icp multi board.
+Description:
+	This function is the interrupt service routine for all
+	interrupts generated by the icp multi board.
 
-	Parameters:
-		int irq
-		void *d			Pointer to current device
+Parameters:
+	int irq
+	void *d			Pointer to current device
 
 ==============================================================================
 */
@@ -640,7 +646,8 @@ static irqreturn_t interrupt_service_icp_multi(int irq, void *d)
 	int int_no;
 
 #ifdef ICP_MULTI_EXTDEBUG
-	printk("icp multi EDBG: BGN: interrupt_service_icp_multi(%d,...)\n",
+	printk(KERN_DEBUG
+	       "icp multi EDBG: BGN: interrupt_service_icp_multi(%d,...)\n",
 	       irq);
 #endif
 
@@ -651,7 +658,8 @@ static irqreturn_t interrupt_service_icp_multi(int irq, void *d)
 		return IRQ_NONE;
 
 #ifdef ICP_MULTI_EXTDEBUG
-	printk("icp multi EDBG: interrupt_service_icp_multi() ST: %4x\n",
+	printk(KERN_DEBUG
+	       "icp multi EDBG: interrupt_service_icp_multi() ST: %4x\n",
 	       readw(devpriv->io_addr + ICP_MULTI_INT_STAT));
 #endif
 
@@ -679,7 +687,8 @@ static irqreturn_t interrupt_service_icp_multi(int irq, void *d)
 	}
 
 #ifdef ICP_MULTI_EXTDEBUG
-	printk("icp multi EDBG: END: interrupt_service_icp_multi(...)\n");
+	printk(KERN_DEBUG
+	       "icp multi EDBG: END: interrupt_service_icp_multi(...)\n");
 #endif
 	return IRQ_HANDLED;
 }
@@ -688,20 +697,20 @@ static irqreturn_t interrupt_service_icp_multi(int irq, void *d)
 /*
 ==============================================================================
 
-	Name:	check_channel_list
+Name:	check_channel_list
 
-	Description:
-		This function checks if the channel list, provided by user
-		is built correctly
+Description:
+	This function checks if the channel list, provided by user
+	is built correctly
 
-	Parameters:
-		struct comedi_device *dev	Pointer to current sevice structure
-		struct comedi_subdevice *s	Pointer to current subdevice structure
-		unsigned int *chanlist	Pointer to packed channel list
-		unsigned int n_chan	Number of channels to scan
+Parameters:
+	struct comedi_device *dev	Pointer to current sevice structure
+	struct comedi_subdevice *s	Pointer to current subdevice structure
+	unsigned int *chanlist	Pointer to packed channel list
+	unsigned int n_chan	Number of channels to scan
 
-	Returns:int 0 = failure
-		    1 = success
+Returns:int 0 = failure
+	    1 = success
 
 ==============================================================================
 */
@@ -712,7 +721,8 @@ static int check_channel_list(struct comedi_device *dev,
 	unsigned int i;
 
 #ifdef ICP_MULTI_EXTDEBUG
-	printk("icp multi EDBG:  check_channel_list(...,%d)\n", n_chan);
+	printk(KERN_DEBUG
+	       "icp multi EDBG:  check_channel_list(...,%d)\n", n_chan);
 #endif
 	/*  Check that we at least have one channel to check */
 	if (n_chan < 1) {
@@ -725,7 +735,7 @@ static int check_channel_list(struct comedi_device *dev,
 		if (CR_AREF(chanlist[i]) == AREF_DIFF) {
 			if (CR_CHAN(chanlist[i]) > this_board->n_aichand) {
 				comedi_error(dev,
-					     "Incorrect differential ai channel number");
+					     "Incorrect differential ai ch-nr");
 				return 0;
 			}
 		} else {
@@ -743,20 +753,20 @@ static int check_channel_list(struct comedi_device *dev,
 /*
 ==============================================================================
 
-	Name:	setup_channel_list
+Name:	setup_channel_list
 
-	Description:
-		This function sets the appropriate channel selection,
-		differential input mode and range bits in the ADC Command/
-		Status register.
+Description:
+	This function sets the appropriate channel selection,
+	differential input mode and range bits in the ADC Command/
+	Status register.
 
-	Parameters:
-		struct comedi_device *dev	Pointer to current sevice structure
-		struct comedi_subdevice *s	Pointer to current subdevice structure
-		unsigned int *chanlist	Pointer to packed channel list
-		unsigned int n_chan	Number of channels to scan
+Parameters:
+	struct comedi_device *dev	Pointer to current sevice structure
+	struct comedi_subdevice *s	Pointer to current subdevice structure
+	unsigned int *chanlist	Pointer to packed channel list
+	unsigned int n_chan	Number of channels to scan
 
-	Returns:Void
+Returns:Void
 
 ==============================================================================
 */
@@ -768,7 +778,8 @@ static void setup_channel_list(struct comedi_device *dev,
 	unsigned int diff;
 
 #ifdef ICP_MULTI_EXTDEBUG
-	printk("icp multi EDBG:  setup_channel_list(...,%d)\n", n_chan);
+	printk(KERN_DEBUG
+	       "icp multi EDBG:  setup_channel_list(...,%d)\n", n_chan);
 #endif
 	devpriv->act_chanlist_len = n_chan;
 	devpriv->act_chanlist_pos = 0;
@@ -786,7 +797,8 @@ static void setup_channel_list(struct comedi_device *dev,
 			chanprog &= 0x000f;
 		}
 
-		/*  Clear channel, range and input mode bits in A/D command/status register */
+		/*  Clear channel, range and input mode bits
+		 *  in A/D command/status register */
 		devpriv->AdcCmdStatus &= 0xf00f;
 
 		/*  Set channel number and differential mode status bit */
@@ -808,7 +820,8 @@ static void setup_channel_list(struct comedi_device *dev,
 		       devpriv->io_addr + ICP_MULTI_ADC_CSR);
 
 #ifdef ICP_MULTI_EXTDEBUG
-		printk("GS: %2d. [%4x]=%4x %4x\n", i, chanprog, range,
+		printk(KERN_DEBUG
+		       "GS: %2d. [%4x]=%4x %4x\n", i, chanprog, range,
 		       devpriv->act_chanlist[i]);
 #endif
 	}
@@ -818,15 +831,15 @@ static void setup_channel_list(struct comedi_device *dev,
 /*
 ==============================================================================
 
-	Name:	icp_multi_reset
+Name:	icp_multi_reset
 
-	Description:
-		This function resets the icp multi device to a 'safe' state
+Description:
+	This function resets the icp multi device to a 'safe' state
 
-	Parameters:
-		struct comedi_device *dev	Pointer to current sevice structure
+Parameters:
+	struct comedi_device *dev	Pointer to current sevice structure
 
-	Returns:int	0 = success
+Returns:int	0 = success
 
 ==============================================================================
 */
@@ -835,7 +848,8 @@ static int icp_multi_reset(struct comedi_device *dev)
 	unsigned int i;
 
 #ifdef ICP_MULTI_EXTDEBUG
-	printk("icp_multi EDBG: BGN: icp_multi_reset(...)\n");
+	printk(KERN_DEBUG
+	       "icp_multi EDBG: BGN: icp_multi_reset(...)\n");
 #endif
 	/*  Clear INT enables and requests */
 	writew(0, devpriv->io_addr + ICP_MULTI_INT_EN);
@@ -866,7 +880,8 @@ static int icp_multi_reset(struct comedi_device *dev)
 	writew(0, devpriv->io_addr + ICP_MULTI_DO);
 
 #ifdef ICP_MULTI_EXTDEBUG
-	printk("icp multi EDBG: END: icp_multi_reset(...)\n");
+	printk(KERN_DEBUG
+	       "icp multi EDBG: END: icp_multi_reset(...)\n");
 #endif
 	return 0;
 }
@@ -874,17 +889,17 @@ static int icp_multi_reset(struct comedi_device *dev)
 /*
 ==============================================================================
 
-	Name:	icp_multi_attach
+Name:	icp_multi_attach
 
-	Description:
-		This function sets up all the appropriate data for the current
-		device.
+Description:
+	This function sets up all the appropriate data for the current
+	device.
 
-	Parameters:
-		struct comedi_device *dev	Pointer to current device structure
-		struct comedi_devconfig *it	Pointer to current device configuration
+Parameters:
+	struct comedi_device *dev	Pointer to current device structure
+	struct comedi_devconfig *it	Pointer to current device configuration
 
-	Returns:int	0 = success
+Returns:int	0 = success
 
 ==============================================================================
 */
@@ -898,7 +913,8 @@ static int icp_multi_attach(struct comedi_device *dev,
 	resource_size_t io_addr[5], iobase;
 	unsigned char pci_bus, pci_slot, pci_func;
 
-	printk("icp_multi EDBG: BGN: icp_multi_attach(...)\n");
+	printk(KERN_WARNING
+	       "icp_multi EDBG: BGN: icp_multi_attach(...)\n");
 
 	/*  Alocate private data storage space */
 	ret = alloc_private(dev, sizeof(struct icp_multi_private));
@@ -916,7 +932,8 @@ static int icp_multi_attach(struct comedi_device *dev,
 		    );
 	}
 
-	printk("Anne's comedi%d: icp_multi: board=%s", dev->minor,
+	printk(KERN_WARNING
+	       "Anne's comedi%d: icp_multi: board=%s", dev->minor,
 	       this_board->name);
 
 	card = select_and_alloc_pci_card(PCI_VENDOR_ID_ICP,
@@ -930,24 +947,26 @@ static int icp_multi_attach(struct comedi_device *dev,
 
 	if ((pci_card_data(card, &pci_bus, &pci_slot, &pci_func, &io_addr[0],
 			   &irq)) < 0) {
-		printk(" - Can't get configuration data!\n");
+		printk(KERN_WARNING " - Can't get configuration data!\n");
 		return -EIO;
 	}
 
 	iobase = io_addr[2];
 	devpriv->phys_iobase = iobase;
 
-	printk(", b:s:f=%d:%d:%d, io=0x%8llx \n", pci_bus, pci_slot, pci_func,
+	printk(KERN_WARNING
+	       ", b:s:f=%d:%d:%d, io=0x%8llx \n", pci_bus, pci_slot, pci_func,
 	       (unsigned long long)iobase);
 
 	devpriv->io_addr = ioremap(iobase, ICP_MULTI_SIZE);
 
 	if (devpriv->io_addr == NULL) {
-		printk("ioremap failed.\n");
+		printk(KERN_WARNING "ioremap failed.\n");
 		return -ENOMEM;
 	}
 #ifdef ICP_MULTI_EXTDEBUG
-	printk("0x%08llx mapped to %p, ", (unsigned long long)iobase,
+	printk(KERN_DEBUG
+	       "0x%08llx mapped to %p, ", (unsigned long long)iobase,
 	       devpriv->io_addr);
 #endif
 
@@ -975,20 +994,20 @@ static int icp_multi_attach(struct comedi_device *dev,
 		if (irq) {
 			if (request_irq(irq, interrupt_service_icp_multi,
 					IRQF_SHARED, "Inova Icp Multi", dev)) {
-				printk
-				    (", unable to allocate IRQ %u, DISABLING IT",
+				printk(KERN_WARNING
+				    "unable to allocate IRQ %u, DISABLING IT",
 				     irq);
 				irq = 0;	/* Can't use IRQ */
 			} else
-				printk(", irq=%u", irq);
+				printk(KERN_WARNING ", irq=%u", irq);
 		} else
-			printk(", IRQ disabled");
+			printk(KERN_WARNING ", IRQ disabled");
 	} else
 		irq = 0;
 
 	dev->irq = irq;
 
-	printk(".\n");
+	printk(KERN_WARNING ".\n");
 
 	subdev = 0;
 
@@ -1063,7 +1082,7 @@ static int icp_multi_attach(struct comedi_device *dev,
 	devpriv->valid = 1;
 
 #ifdef ICP_MULTI_EXTDEBUG
-	printk("icp multi EDBG: END: icp_multi_attach(...)\n");
+	printk(KERN_DEBUG "icp multi EDBG: END: icp_multi_attach(...)\n");
 #endif
 
 	return 0;
@@ -1072,16 +1091,16 @@ static int icp_multi_attach(struct comedi_device *dev,
 /*
 ==============================================================================
 
-	Name:	icp_multi_detach
+Name:	icp_multi_detach
 
-	Description:
-		This function releases all the resources used by the current
-		device.
+Description:
+	This function releases all the resources used by the current
+	device.
 
-	Parameters:
-		struct comedi_device *dev	Pointer to current device structure
+Parameters:
+	struct comedi_device *dev	Pointer to current device structure
 
-	Returns:int	0 = success
+Returns:int	0 = success
 
 ==============================================================================
 */

+ 43 - 40
drivers/staging/comedi/drivers/ii_pci20kc.c

@@ -23,7 +23,8 @@
  *	no extern trigger implemented
  *
  *	NOT WORKING (but soon) only 4 on-board differential channels supported
- *	NOT WORKING (but soon) only ONE di-port and ONE do-port supported instead of 4 digital ports
+ *	NOT WORKING (but soon) only ONE di-port and ONE do-port supported
+ *			       instead of 4 digital ports
  *	di-port == Port 0
  *	do-port == Port 1
  *
@@ -63,17 +64,17 @@ Options:
 
 options for PCI-20006M:
   first:   Analog output channel 0 range configuration
-             0  bipolar 10  (-10V -- +10V)
-             1  unipolar 10  (0V -- +10V)
-             2  bipolar 5  (-5V -- 5V)
+	     0  bipolar 10  (-10V -- +10V)
+	     1  unipolar 10  (0V -- +10V)
+	     2  bipolar 5  (-5V -- 5V)
   second:  Analog output channel 1 range configuration
 
 options for PCI-20341M:
   first:   Analog input gain configuration
-             0  1
-             1  10
-             2  100
-             3  200
+	     0  1
+	     1  10
+	     2  100
+	     3  200
 */
 
 /* XXX needs to use ioremap() for compatibility with 2.4 kernels.  Should also
@@ -95,12 +96,12 @@ options for PCI-20341M:
 #define PCI20000_DIO_3			0xc1
 #define PCI20000_DIO_CONTROL_01		0x83	/* port 0, 1 control */
 #define PCI20000_DIO_CONTROL_23		0xc3	/* port 2, 3 control */
-#define PCI20000_DIO_BUFFER		0x82	/* buffer direction and enable */
+#define PCI20000_DIO_BUFFER		0x82	/* buffer direction & enable */
 #define PCI20000_DIO_EOC		0xef	/* even port, control output */
 #define PCI20000_DIO_OOC		0xfd	/* odd port, control output */
 #define PCI20000_DIO_EIC		0x90	/* even port, control input */
 #define PCI20000_DIO_OIC		0x82	/* odd port, control input */
-#define DIO_CAND			0x12	/* and bit 1, bit 4 of control */
+#define DIO_CAND			0x12	/* and bit 1 & 4 of control */
 #define DIO_BE				0x01	/* buffer: port enable */
 #define DIO_BO				0x04	/* buffer: output */
 #define DIO_BI				0x05	/* buffer: input */
@@ -137,7 +138,8 @@ union pci20xxx_subdev_private {
 	void *iobase;
 	struct {
 		void *iobase;
-		const struct comedi_lrange *ao_range_list[2];	/* range of channels of ao module */
+		const struct comedi_lrange *ao_range_list[2];
+					/* range of channels of ao module */
 		unsigned int last_data[2];
 	} pci20006;
 	struct {
@@ -224,14 +226,13 @@ static int pci20xxx_attach(struct comedi_device *dev,
 
 	/* Check PCI-20001 C-2A Carrier Board ID */
 	if ((readb(devpriv->ioaddr) & PCI20000_ID) != PCI20000_ID) {
-		printk("comedi%d: ii_pci20kc", dev->minor);
-		printk
-		    (" PCI-20001 C-2A Carrier Board at base=0x%p not found !\n",
-		     devpriv->ioaddr);
+		printk(KERN_WARNING "comedi%d: ii_pci20kc PCI-20001"
+		       " C-2A Carrier Board at base=0x%p not found !\n",
+		       dev->minor, devpriv->ioaddr);
 		return -EINVAL;
 	}
-	printk("comedi%d:\n", dev->minor);
-	printk("ii_pci20kc: PCI-20001 C-2A at base=0x%p\n", devpriv->ioaddr);
+	printk(KERN_INFO "comedi%d: ii_pci20kc: PCI-20001 C-2A at base=0x%p\n",
+	       dev->minor, devpriv->ioaddr);
 
 	for (i = 0; i < PCI20000_MODULES; i++) {
 		s = dev->subdevices + i;
@@ -244,21 +245,23 @@ static int pci20xxx_attach(struct comedi_device *dev,
 			    devpriv->ioaddr + (i + 1) * PCI20000_OFFSET;
 			pci20006_init(dev, s, it->options[2 * i + 2],
 				      it->options[2 * i + 3]);
-			printk("comedi%d: ii_pci20kc", dev->minor);
-			printk(" PCI-20006 module in slot %d \n", i + 1);
+			printk(KERN_INFO "comedi%d: "
+			       "ii_pci20kc PCI-20006 module in slot %d \n",
+			       dev->minor, i + 1);
 			break;
 		case PCI20341_ID:
 			sdp->pci20341.iobase =
 			    devpriv->ioaddr + (i + 1) * PCI20000_OFFSET;
 			pci20341_init(dev, s, it->options[2 * i + 2],
 				      it->options[2 * i + 3]);
-			printk("comedi%d: ii_pci20kc", dev->minor);
-			printk(" PCI-20341 module in slot %d \n", i + 1);
+			printk(KERN_INFO "comedi%d: "
+			       "ii_pci20kc PCI-20341 module in slot %d \n",
+			       dev->minor, i + 1);
 			break;
 		default:
-			printk
-			    ("ii_pci20kc: unknown module code 0x%02x in slot %d: module disabled\n",
-			     id, i);
+			printk(KERN_WARNING "ii_pci20kc: unknown module "
+			       "code 0x%02x in slot %d: module disabled\n",
+			       id, i); /* XXX this looks like a bug! i + 1 ?? */
 			/* fall through */
 		case PCI20xxx_EMPTY_ID:
 			s->type = COMEDI_SUBD_UNUSED;
@@ -274,7 +277,7 @@ static int pci20xxx_attach(struct comedi_device *dev,
 
 static int pci20xxx_detach(struct comedi_device *dev)
 {
-	printk("comedi%d: pci20xxx: remove\n", dev->minor);
+	printk(KERN_INFO "comedi%d: pci20xxx: remove\n", dev->minor);
 
 	return 0;
 }
@@ -339,7 +342,8 @@ static int pci20006_insn_write(struct comedi_device *dev,
 	unsigned int boarddata;
 
 	sdp->pci20006.last_data[CR_CHAN(insn->chanspec)] = data[0];
-	boarddata = (((unsigned int)data[0] + 0x8000) & 0xffff);	/* comedi-data -> board-data */
+	boarddata = (((unsigned int)data[0] + 0x8000) & 0xffff);
+						/* comedi-data -> board-data */
 	lo = (boarddata & 0xff);
 	hi = ((boarddata >> 8) & 0xff);
 
@@ -355,7 +359,8 @@ static int pci20006_insn_write(struct comedi_device *dev,
 		writeb(0x00, sdp->iobase + PCI20006_STROBE1);
 		break;
 	default:
-		printk(" comedi%d: pci20xxx: ao channel Error!\n", dev->minor);
+		printk(KERN_WARNING
+		       " comedi%d: pci20xxx: ao channel Error!\n", dev->minor);
 		return -EINVAL;
 	}
 
@@ -373,8 +378,7 @@ static const int pci20341_settling_time[] = { 0x58, 0x58, 0x93, 0x99 };
 
 static const struct comedi_lrange range_bipolar0_5 = { 1, {BIP_RANGE(0.5)} };
 static const struct comedi_lrange range_bipolar0_05 = { 1, {BIP_RANGE(0.05)} };
-static const struct comedi_lrange range_bipolar0_025 =
-    { 1, {BIP_RANGE(0.025)} };
+static const struct comedi_lrange range_bipolar0_025 = { 1, {BIP_RANGE(0.025)} };
 
 static const struct comedi_lrange *const pci20341_ranges[] = {
 	&range_bipolar5,
@@ -447,9 +451,10 @@ static int pci20341_insn_read(struct comedi_device *dev,
 			eoc = readb(sdp->iobase + PCI20341_STATUS_REG);
 		}
 		if (j >= 100) {
-			printk
-			    ("comedi%d:  pci20xxx: AI interrupt channel %i polling exit !\n",
-			     dev->minor, i);
+			printk(KERN_WARNING
+			       "comedi%d:  pci20xxx: "
+			       "AI interrupt channel %i polling exit !\n",
+			       dev->minor, i);
 			return -EINVAL;
 		}
 		lo = readb(sdp->iobase + PCI20341_LDATA);
@@ -502,20 +507,18 @@ static int pci20xxx_dio_insn_config(struct comedi_device *dev,
 	int mask, bits;
 
 	mask = 1 << CR_CHAN(insn->chanspec);
-	if (mask & 0x000000ff) {
+	if (mask & 0x000000ff)
 		bits = 0x000000ff;
-	} else if (mask & 0x0000ff00) {
+	else if (mask & 0x0000ff00)
 		bits = 0x0000ff00;
-	} else if (mask & 0x00ff0000) {
+	else if (mask & 0x00ff0000)
 		bits = 0x00ff0000;
-	} else {
+	else
 		bits = 0xff000000;
-	}
-	if (data[0]) {
+	if (data[0])
 		s->io_bits |= bits;
-	} else {
+	else
 		s->io_bits &= ~bits;
-	}
 	pci20xxx_dio_config(dev, s);
 
 	return 1;

+ 12 - 9
drivers/staging/comedi/drivers/ke_counter.c

@@ -192,12 +192,14 @@ static int cnt_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 			}
 		}
 	}
-	printk("comedi%d: no supported board found! (req. bus/slot: %d/%d)\n",
+	printk(KERN_WARNING
+	       "comedi%d: no supported board found! (req. bus/slot: %d/%d)\n",
 	       dev->minor, it->options[0], it->options[1]);
 	return -EIO;
 
 found:
-	printk("comedi%d: found %s at PCI bus %d, slot %d\n", dev->minor,
+	printk(KERN_INFO
+	       "comedi%d: found %s at PCI bus %d, slot %d\n", dev->minor,
 	       board->name, pci_device->bus->number,
 	       PCI_SLOT(pci_device->devfn));
 	devpriv->pcidev = pci_device;
@@ -206,9 +208,9 @@ found:
 	/* enable PCI device and request regions */
 	error = comedi_pci_enable(pci_device, CNT_DRIVER_NAME);
 	if (error < 0) {
-		printk
-		    ("comedi%d: failed to enable PCI device and request regions!\n",
-		     dev->minor);
+		printk(KERN_WARNING "comedi%d: "
+		       "failed to enable PCI device and request regions!\n",
+		       dev->minor);
 		return error;
 	}
 
@@ -239,7 +241,8 @@ found:
 	outb(0, dev->iobase + 0x20);
 	outb(0, dev->iobase + 0x40);
 
-	printk("comedi%d: " CNT_DRIVER_NAME " attached.\n", dev->minor);
+	printk(KERN_INFO "comedi%d: " CNT_DRIVER_NAME " attached.\n",
+	       dev->minor);
 	return 0;
 }
 
@@ -248,11 +251,11 @@ found:
 static int cnt_detach(struct comedi_device *dev)
 {
 	if (devpriv && devpriv->pcidev) {
-		if (dev->iobase) {
+		if (dev->iobase)
 			comedi_pci_disable(devpriv->pcidev);
-		}
 		pci_dev_put(devpriv->pcidev);
 	}
-	printk("comedi%d: " CNT_DRIVER_NAME " remove\n", dev->minor);
+	printk(KERN_INFO "comedi%d: " CNT_DRIVER_NAME " remove\n",
+	       dev->minor);
 	return 0;
 }

+ 1 - 1
drivers/staging/comedi/drivers/me4000.c

@@ -840,7 +840,7 @@ static int xilinx_download(struct comedi_device *dev)
 		       "comedi%d: me4000: xilinx_download(): DONE flag is not set\n",
 		       dev->minor);
 		printk(KERN_ERR
-		       "comedi%d: me4000: xilinx_download(): Download not succesful\n",
+		       "comedi%d: me4000: xilinx_download(): Download not successful\n",
 		       dev->minor);
 		return -EIO;
 	}

+ 121 - 110
drivers/staging/comedi/drivers/mite.c

@@ -64,6 +64,7 @@
 MODULE_LICENSE("GPL");
 
 struct mite_struct *mite_devices;
+EXPORT_SYMBOL(mite_devices);
 
 #define TOP_OF_PAGE(x) ((x)|(~(PAGE_MASK)))
 
@@ -80,7 +81,7 @@ void mite_init(void)
 
 			mite = kzalloc(sizeof(*mite), GFP_KERNEL);
 			if (!mite) {
-				printk("mite: allocation failed\n");
+				printk(KERN_ERR "mite: allocation failed\n");
 				pci_dev_put(pcidev);
 				return;
 			}
@@ -99,14 +100,14 @@ void mite_init(void)
 
 static void dump_chip_signature(u32 csigr_bits)
 {
-	printk
-	    ("mite: version = %i, type = %i, mite mode = %i, interface mode = %i\n",
-	     mite_csigr_version(csigr_bits), mite_csigr_type(csigr_bits),
-	     mite_csigr_mmode(csigr_bits), mite_csigr_imode(csigr_bits));
-	printk
-	    ("mite: num channels = %i, write post fifo depth = %i, wins = %i, iowins = %i\n",
-	     mite_csigr_dmac(csigr_bits), mite_csigr_wpdep(csigr_bits),
-	     mite_csigr_wins(csigr_bits), mite_csigr_iowins(csigr_bits));
+	printk(KERN_INFO "mite: version = %i, type = %i, mite mode = %i,"
+	       "interface mode = %i\n",
+	       mite_csigr_version(csigr_bits), mite_csigr_type(csigr_bits),
+	       mite_csigr_mmode(csigr_bits), mite_csigr_imode(csigr_bits));
+	printk(KERN_INFO "mite: num channels = %i, write post fifo depth = %i,"
+	       "wins = %i, iowins = %i\n",
+	       mite_csigr_dmac(csigr_bits), mite_csigr_wpdep(csigr_bits),
+	       mite_csigr_wins(csigr_bits), mite_csigr_iowins(csigr_bits));
 }
 
 unsigned mite_fifo_size(struct mite_struct *mite, unsigned channel)
@@ -126,7 +127,7 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1)
 	unsigned unknown_dma_burst_bits;
 
 	if (comedi_pci_enable(mite->pcidev, "mite")) {
-		printk("error enabling mite and requesting io regions\n");
+		printk(KERN_ERR "error enabling mite and requesting io regions\n");
 		return -EIO;
 	}
 	pci_set_master(mite->pcidev);
@@ -135,27 +136,30 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1)
 	mite->mite_phys_addr = addr;
 	mite->mite_io_addr = ioremap(addr, PCI_MITE_SIZE);
 	if (!mite->mite_io_addr) {
-		printk("failed to remap mite io memory address\n");
+		printk(KERN_ERR "Failed to remap mite io memory address\n");
 		return -ENOMEM;
 	}
-	printk("MITE:0x%08llx mapped to %p ",
+	printk(KERN_INFO "MITE:0x%08llx mapped to %p ",
 	       (unsigned long long)mite->mite_phys_addr, mite->mite_io_addr);
 
 	addr = pci_resource_start(mite->pcidev, 1);
 	mite->daq_phys_addr = addr;
 	length = pci_resource_len(mite->pcidev, 1);
-	/*  In case of a 660x board, DAQ size is 8k instead of 4k (see as shown by lspci output) */
+	/*
+	 * In case of a 660x board, DAQ size is 8k instead of 4k
+	 * (see as shown by lspci output)
+	 */
 	mite->daq_io_addr = ioremap(mite->daq_phys_addr, length);
 	if (!mite->daq_io_addr) {
-		printk("failed to remap daq io memory address\n");
+		printk(KERN_ERR "Failed to remap daq io memory address\n");
 		return -ENOMEM;
 	}
-	printk("DAQ:0x%08llx mapped to %p\n",
+	printk(KERN_INFO "DAQ:0x%08llx mapped to %p\n",
 	       (unsigned long long)mite->daq_phys_addr, mite->daq_io_addr);
 
 	if (use_iodwbsr_1) {
 		writel(0, mite->mite_io_addr + MITE_IODWBSR);
-		printk("mite: using I/O Window Base Size register 1\n");
+		printk(KERN_INFO "mite: using I/O Window Base Size register 1\n");
 		writel(mite->daq_phys_addr | WENAB |
 		       MITE_IODWBSR_1_WSIZE_bits(length),
 		       mite->mite_io_addr + MITE_IODWBSR_1);
@@ -164,11 +168,12 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1)
 		writel(mite->daq_phys_addr | WENAB,
 		       mite->mite_io_addr + MITE_IODWBSR);
 	}
-	/* make sure dma bursts work.  I got this from running a bus analyzer
-	   on a pxi-6281 and a pxi-6713.  6713 powered up with register value
-	   of 0x61f and bursts worked.  6281 powered up with register value of
-	   0x1f and bursts didn't work.  The NI windows driver reads the register,
-	   then does a bitwise-or of 0x600 with it and writes it back.
+	/*
+	 * make sure dma bursts work. I got this from running a bus analyzer
+	 * on a pxi-6281 and a pxi-6713. 6713 powered up with register value
+	 * of 0x61f and bursts worked. 6281 powered up with register value of
+	 * 0x1f and bursts didn't work. The NI windows driver reads the
+	 * register, then does a bitwise-or of 0x600 with it and writes it back.
 	 */
 	unknown_dma_burst_bits =
 	    readl(mite->mite_io_addr + MITE_UNKNOWN_DMA_BURST_REG);
@@ -179,9 +184,9 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1)
 	csigr_bits = readl(mite->mite_io_addr + MITE_CSIGR);
 	mite->num_channels = mite_csigr_dmac(csigr_bits);
 	if (mite->num_channels > MAX_MITE_DMA_CHANNELS) {
-		printk
-		    ("mite: bug? chip claims to have %i dma channels.  Setting to %i.\n",
-		     mite->num_channels, MAX_MITE_DMA_CHANNELS);
+		printk(KERN_WARNING "mite: bug? chip claims to have %i dma "
+		       "channels. Setting to %i.\n",
+		       mite->num_channels, MAX_MITE_DMA_CHANNELS);
 		mite->num_channels = MAX_MITE_DMA_CHANNELS;
 	}
 	dump_chip_signature(csigr_bits);
@@ -194,16 +199,18 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1)
 		       mite->mite_io_addr + MITE_CHCR(i));
 	}
 	mite->fifo_size = mite_fifo_size(mite, 0);
-	printk("mite: fifo size is %i.\n", mite->fifo_size);
+	printk(KERN_INFO "mite: fifo size is %i.\n", mite->fifo_size);
 	mite->used = 1;
 
 	return 0;
 }
+EXPORT_SYMBOL(mite_setup2);
 
 int mite_setup(struct mite_struct *mite)
 {
 	return mite_setup2(mite, 0);
 }
+EXPORT_SYMBOL(mite_setup);
 
 void mite_cleanup(void)
 {
@@ -238,22 +245,23 @@ void mite_unsetup(struct mite_struct *mite)
 
 	mite->used = 0;
 }
+EXPORT_SYMBOL(mite_unsetup);
 
 void mite_list_devices(void)
 {
 	struct mite_struct *mite, *next;
 
-	printk("Available NI device IDs:");
+	printk(KERN_INFO "Available NI device IDs:");
 	if (mite_devices)
 		for (mite = mite_devices; mite; mite = next) {
 			next = mite->next;
-			printk(" 0x%04x", mite_device_id(mite));
+			printk(KERN_INFO " 0x%04x", mite_device_id(mite));
 			if (mite->used)
-				printk("(used)");
+				printk(KERN_INFO "(used)");
 		}
-	printk("\n");
-
+	printk(KERN_INFO "\n");
 }
+EXPORT_SYMBOL(mite_list_devices);
 
 struct mite_channel *mite_request_channel_in_range(struct mite_struct *mite,
 						   struct
@@ -265,7 +273,9 @@ struct mite_channel *mite_request_channel_in_range(struct mite_struct *mite,
 	unsigned long flags;
 	struct mite_channel *channel = NULL;
 
-	/*  spin lock so mite_release_channel can be called safely from interrupts */
+	/* spin lock so mite_release_channel can be called safely
+	 * from interrupts
+	 */
 	spin_lock_irqsave(&mite->lock, flags);
 	for (i = min_channel; i <= max_channel; ++i) {
 		if (mite->channel_allocated[i] == 0) {
@@ -278,6 +288,7 @@ struct mite_channel *mite_request_channel_in_range(struct mite_struct *mite,
 	spin_unlock_irqrestore(&mite->lock, flags);
 	return channel;
 }
+EXPORT_SYMBOL(mite_request_channel_in_range);
 
 void mite_release_channel(struct mite_channel *mite_chan)
 {
@@ -289,8 +300,10 @@ void mite_release_channel(struct mite_channel *mite_chan)
 	if (mite->channel_allocated[mite_chan->channel]) {
 		mite_dma_disarm(mite_chan);
 		mite_dma_reset(mite_chan);
-/* disable all channel's interrupts (do it after disarm/reset so
-MITE_CHCR reg isn't changed while dma is still active!) */
+	/*
+	 * disable all channel's interrupts (do it after disarm/reset so
+	 * MITE_CHCR reg isn't changed while dma is still active!)
+	 */
 		writel(CHCR_CLR_DMA_IE | CHCR_CLR_LINKP_IE |
 		       CHCR_CLR_SAR_IE | CHCR_CLR_DONE_IE |
 		       CHCR_CLR_MRDY_IE | CHCR_CLR_DRDY_IE |
@@ -302,6 +315,7 @@ MITE_CHCR reg isn't changed while dma is still active!) */
 	}
 	spin_unlock_irqrestore(&mite->lock, flags);
 }
+EXPORT_SYMBOL(mite_release_channel);
 
 void mite_dma_arm(struct mite_channel *mite_chan)
 {
@@ -310,8 +324,10 @@ void mite_dma_arm(struct mite_channel *mite_chan)
 	unsigned long flags;
 
 	MDPRINTK("mite_dma_arm ch%i\n", channel);
-	/* memory barrier is intended to insure any twiddling with the buffer
-	   is done before writing to the mite to arm dma transfer */
+	/*
+	 * memory barrier is intended to insure any twiddling with the buffer
+	 * is done before writing to the mite to arm dma transfer
+	 */
 	smp_mb();
 	/* arm */
 	chor = CHOR_START;
@@ -322,6 +338,7 @@ void mite_dma_arm(struct mite_channel *mite_chan)
 	spin_unlock_irqrestore(&mite->lock, flags);
 /*       mite_dma_tcr(mite, channel); */
 }
+EXPORT_SYMBOL(mite_dma_arm);
 
 /**************************************/
 
@@ -354,7 +371,7 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring,
 			       n_links * sizeof(struct mite_dma_descriptor),
 			       &ring->descriptors_dma_addr, GFP_KERNEL);
 	if (!ring->descriptors) {
-		printk("mite: ring buffer allocation failed\n");
+		printk(KERN_ERR "mite: ring buffer allocation failed\n");
 		return -ENOMEM;
 	}
 	ring->n_links = n_links;
@@ -370,11 +387,14 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring,
 	}
 	ring->descriptors[n_links - 1].next =
 	    cpu_to_le32(ring->descriptors_dma_addr);
-	/* barrier is meant to insure that all the writes to the dma descriptors
-	   have completed before the dma controller is commanded to read them */
+	/*
+	 * barrier is meant to insure that all the writes to the dma descriptors
+	 * have completed before the dma controller is commanded to read them
+	 */
 	smp_wmb();
 	return 0;
 }
+EXPORT_SYMBOL(mite_buf_change);
 
 void mite_prep_dma(struct mite_channel *mite_chan,
 		   unsigned int num_device_bits, unsigned int num_memory_bits)
@@ -395,16 +415,19 @@ void mite_prep_dma(struct mite_channel *mite_chan,
 	 * Link Complete Interrupt: interrupt every time a link
 	 * in MITE_RING is completed. This can generate a lot of
 	 * extra interrupts, but right now we update the values
-	 * of buf_int_ptr and buf_int_count at each interrupt.  A
+	 * of buf_int_ptr and buf_int_count at each interrupt. A
 	 * better method is to poll the MITE before each user
 	 * "read()" to calculate the number of bytes available.
 	 */
 	chcr |= CHCR_SET_LC_IE;
 	if (num_memory_bits == 32 && num_device_bits == 16) {
-		/* Doing a combined 32 and 16 bit byteswap gets the 16 bit samples into the fifo in the right order.
-		   Tested doing 32 bit memory to 16 bit device transfers to the analog out of a pxi-6281,
-		   which has mite version = 1, type = 4.  This also works for dma reads from the counters
-		   on e-series boards.  */
+		/*
+		 * Doing a combined 32 and 16 bit byteswap gets the 16 bit
+		 * samples into the fifo in the right order. Tested doing 32 bit
+		 * memory to 16 bit device transfers to the analog out of a
+		 * pxi-6281, which has mite version = 1, type = 4. This also
+		 * works for dma reads from the counters on e-series boards.
+		 */
 		chcr |= CHCR_BYTE_SWAP_DEVICE | CHCR_BYTE_SWAP_MEMORY;
 	}
 	if (mite_chan->dir == COMEDI_INPUT)
@@ -425,7 +448,8 @@ void mite_prep_dma(struct mite_channel *mite_chan,
 		mcr |= CR_PSIZE32;
 		break;
 	default:
-		printk("mite: bug! invalid mem bit width for dma transfer\n");
+		printk(KERN_WARNING "mite: bug! invalid mem bit width for dma "
+		       "transfer\n");
 		break;
 	}
 	writel(mcr, mite->mite_io_addr + MITE_MCR(mite_chan->channel));
@@ -444,7 +468,8 @@ void mite_prep_dma(struct mite_channel *mite_chan,
 		dcr |= CR_PSIZE32;
 		break;
 	default:
-		printk("mite: bug! invalid dev bit width for dma transfer\n");
+		printk(KERN_WARNING "mite: bug! invalid dev bit width for dma "
+		       "transfer\n");
 		break;
 	}
 	writel(dcr, mite->mite_io_addr + MITE_DCR(mite_chan->channel));
@@ -462,6 +487,7 @@ void mite_prep_dma(struct mite_channel *mite_chan,
 
 	MDPRINTK("exit mite_prep_dma\n");
 }
+EXPORT_SYMBOL(mite_prep_dma);
 
 u32 mite_device_bytes_transferred(struct mite_channel *mite_chan)
 {
@@ -469,48 +495,53 @@ u32 mite_device_bytes_transferred(struct mite_channel *mite_chan)
 	return readl(mite->mite_io_addr + MITE_DAR(mite_chan->channel));
 }
 
-u32 mite_bytes_in_transit(struct mite_channel * mite_chan)
+u32 mite_bytes_in_transit(struct mite_channel *mite_chan)
 {
 	struct mite_struct *mite = mite_chan->mite;
 	return readl(mite->mite_io_addr +
 		     MITE_FCR(mite_chan->channel)) & 0x000000FF;
 }
+EXPORT_SYMBOL(mite_bytes_in_transit);
 
-/*  returns lower bound for number of bytes transferred from device to memory */
-u32 mite_bytes_written_to_memory_lb(struct mite_channel * mite_chan)
+/* returns lower bound for number of bytes transferred from device to memory */
+u32 mite_bytes_written_to_memory_lb(struct mite_channel *mite_chan)
 {
 	u32 device_byte_count;
 
 	device_byte_count = mite_device_bytes_transferred(mite_chan);
 	return device_byte_count - mite_bytes_in_transit(mite_chan);
 }
+EXPORT_SYMBOL(mite_bytes_written_to_memory_lb);
 
-/*  returns upper bound for number of bytes transferred from device to memory */
-u32 mite_bytes_written_to_memory_ub(struct mite_channel * mite_chan)
+/* returns upper bound for number of bytes transferred from device to memory */
+u32 mite_bytes_written_to_memory_ub(struct mite_channel *mite_chan)
 {
 	u32 in_transit_count;
 
 	in_transit_count = mite_bytes_in_transit(mite_chan);
 	return mite_device_bytes_transferred(mite_chan) - in_transit_count;
 }
+EXPORT_SYMBOL(mite_bytes_written_to_memory_ub);
 
-/*  returns lower bound for number of bytes read from memory for transfer to device */
-u32 mite_bytes_read_from_memory_lb(struct mite_channel * mite_chan)
+/* returns lower bound for number of bytes read from memory to device */
+u32 mite_bytes_read_from_memory_lb(struct mite_channel *mite_chan)
 {
 	u32 device_byte_count;
 
 	device_byte_count = mite_device_bytes_transferred(mite_chan);
 	return device_byte_count + mite_bytes_in_transit(mite_chan);
 }
+EXPORT_SYMBOL(mite_bytes_read_from_memory_lb);
 
-/*  returns upper bound for number of bytes read from memory for transfer to device */
-u32 mite_bytes_read_from_memory_ub(struct mite_channel * mite_chan)
+/* returns upper bound for number of bytes read from memory to device */
+u32 mite_bytes_read_from_memory_ub(struct mite_channel *mite_chan)
 {
 	u32 in_transit_count;
 
 	in_transit_count = mite_bytes_in_transit(mite_chan);
 	return mite_device_bytes_transferred(mite_chan) + in_transit_count;
 }
+EXPORT_SYMBOL(mite_bytes_read_from_memory_ub);
 
 unsigned mite_dma_tcr(struct mite_channel *mite_chan)
 {
@@ -525,6 +556,7 @@ unsigned mite_dma_tcr(struct mite_channel *mite_chan)
 
 	return tcr;
 }
+EXPORT_SYMBOL(mite_dma_tcr);
 
 void mite_dma_disarm(struct mite_channel *mite_chan)
 {
@@ -535,6 +567,7 @@ void mite_dma_disarm(struct mite_channel *mite_chan)
 	chor = CHOR_ABORT;
 	writel(chor, mite->mite_io_addr + MITE_CHOR(mite_chan->channel));
 }
+EXPORT_SYMBOL(mite_dma_disarm);
 
 int mite_sync_input_dma(struct mite_channel *mite_chan,
 			struct comedi_async *async)
@@ -544,7 +577,7 @@ int mite_sync_input_dma(struct mite_channel *mite_chan,
 	const unsigned bytes_per_scan = cfc_bytes_per_scan(async->subdevice);
 
 	old_alloc_count = async->buf_write_alloc_count;
-	/*  write alloc as much as we can */
+	/* write alloc as much as we can */
 	comedi_buf_write_alloc(async, async->prealloc_bufsz);
 
 	nbytes = mite_bytes_written_to_memory_lb(mite_chan);
@@ -571,6 +604,7 @@ int mite_sync_input_dma(struct mite_channel *mite_chan,
 	async->events |= COMEDI_CB_BLOCK;
 	return 0;
 }
+EXPORT_SYMBOL(mite_sync_input_dma);
 
 int mite_sync_output_dma(struct mite_channel *mite_chan,
 			 struct comedi_async *async)
@@ -593,7 +627,7 @@ int mite_sync_output_dma(struct mite_channel *mite_chan,
 	    (int)(nbytes_ub - stop_count) > 0)
 		nbytes_ub = stop_count;
 	if ((int)(nbytes_ub - old_alloc_count) > 0) {
-		printk("mite: DMA underrun\n");
+		printk(KERN_ERR "mite: DMA underrun\n");
 		async->events |= COMEDI_CB_OVERFLOW;
 		return -1;
 	}
@@ -607,6 +641,7 @@ int mite_sync_output_dma(struct mite_channel *mite_chan,
 	}
 	return 0;
 }
+EXPORT_SYMBOL(mite_sync_output_dma);
 
 unsigned mite_get_status(struct mite_channel *mite_chan)
 {
@@ -625,6 +660,7 @@ unsigned mite_get_status(struct mite_channel *mite_chan)
 	spin_unlock_irqrestore(&mite->lock, flags);
 	return status;
 }
+EXPORT_SYMBOL(mite_get_status);
 
 int mite_done(struct mite_channel *mite_chan)
 {
@@ -638,6 +674,7 @@ int mite_done(struct mite_channel *mite_chan)
 	spin_unlock_irqrestore(&mite->lock, flags);
 	return done;
 }
+EXPORT_SYMBOL(mite_done);
 
 #ifdef DEBUG_MITE
 
@@ -719,46 +756,51 @@ void mite_dump_regs(struct mite_channel *mite_chan)
 	unsigned long addr = 0;
 	unsigned long temp = 0;
 
-	printk("mite_dump_regs ch%i\n", mite_chan->channel);
-	printk("mite address is  =0x%08lx\n", mite_io_addr);
+	printk(KERN_DEBUG "mite_dump_regs ch%i\n", mite_chan->channel);
+	printk(KERN_DEBUG "mite address is  =0x%08lx\n", mite_io_addr);
 
 	addr = mite_io_addr + MITE_CHOR(channel);
-	printk("mite status[CHOR]at 0x%08lx =0x%08lx\n", addr, temp =
-	       readl(addr));
+	printk(KERN_DEBUG "mite status[CHOR]at 0x%08lx =0x%08lx\n", addr,
+	       temp = readl(addr));
 	mite_decode(mite_CHOR_strings, temp);
 	addr = mite_io_addr + MITE_CHCR(channel);
-	printk("mite status[CHCR]at 0x%08lx =0x%08lx\n", addr, temp =
-	       readl(addr));
+	printk(KERN_DEBUG "mite status[CHCR]at 0x%08lx =0x%08lx\n", addr,
+	       temp = readl(addr));
 	mite_decode(mite_CHCR_strings, temp);
 	addr = mite_io_addr + MITE_TCR(channel);
-	printk("mite status[TCR] at 0x%08lx =0x%08x\n", addr, readl(addr));
-	addr = mite_io_addr + MITE_MCR(channel);
-	printk("mite status[MCR] at 0x%08lx =0x%08lx\n", addr, temp =
+	printk(KERN_DEBUG "mite status[TCR] at 0x%08lx =0x%08x\n", addr,
 	       readl(addr));
+	addr = mite_io_addr + MITE_MCR(channel);
+	printk(KERN_DEBUG "mite status[MCR] at 0x%08lx =0x%08lx\n", addr,
+	       temp = readl(addr));
 	mite_decode(mite_MCR_strings, temp);
 
 	addr = mite_io_addr + MITE_MAR(channel);
-	printk("mite status[MAR] at 0x%08lx =0x%08x\n", addr, readl(addr));
-	addr = mite_io_addr + MITE_DCR(channel);
-	printk("mite status[DCR] at 0x%08lx =0x%08lx\n", addr, temp =
+	printk(KERN_DEBUG "mite status[MAR] at 0x%08lx =0x%08x\n", addr,
 	       readl(addr));
+	addr = mite_io_addr + MITE_DCR(channel);
+	printk(KERN_DEBUG "mite status[DCR] at 0x%08lx =0x%08lx\n", addr,
+	       temp = readl(addr));
 	mite_decode(mite_DCR_strings, temp);
 	addr = mite_io_addr + MITE_DAR(channel);
-	printk("mite status[DAR] at 0x%08lx =0x%08x\n", addr, readl(addr));
-	addr = mite_io_addr + MITE_LKCR(channel);
-	printk("mite status[LKCR]at 0x%08lx =0x%08lx\n", addr, temp =
+	printk(KERN_DEBUG "mite status[DAR] at 0x%08lx =0x%08x\n", addr,
 	       readl(addr));
+	addr = mite_io_addr + MITE_LKCR(channel);
+	printk(KERN_DEBUG "mite status[LKCR]at 0x%08lx =0x%08lx\n", addr,
+	       temp = readl(addr));
 	mite_decode(mite_LKCR_strings, temp);
 	addr = mite_io_addr + MITE_LKAR(channel);
-	printk("mite status[LKAR]at 0x%08lx =0x%08x\n", addr, readl(addr));
-
-	addr = mite_io_addr + MITE_CHSR(channel);
-	printk("mite status[CHSR]at 0x%08lx =0x%08lx\n", addr, temp =
+	printk(KERN_DEBUG "mite status[LKAR]at 0x%08lx =0x%08x\n", addr,
 	       readl(addr));
+	addr = mite_io_addr + MITE_CHSR(channel);
+	printk(KERN_DEBUG "mite status[CHSR]at 0x%08lx =0x%08lx\n", addr,
+	       temp = readl(addr));
 	mite_decode(mite_CHSR_strings, temp);
 	addr = mite_io_addr + MITE_FCR(channel);
-	printk("mite status[FCR] at 0x%08lx =0x%08x\n\n", addr, readl(addr));
+	printk(KERN_DEBUG "mite status[FCR] at 0x%08lx =0x%08x\n\n", addr,
+	       readl(addr));
 }
+EXPORT_SYMBOL(mite_dump_regs);
 
 static void mite_decode(char **bit_str, unsigned int bits)
 {
@@ -766,10 +808,11 @@ static void mite_decode(char **bit_str, unsigned int bits)
 
 	for (i = 31; i >= 0; i--) {
 		if (bits & (1 << i))
-			printk(" %s", bit_str[i]);
+			printk(KERN_DEBUG " %s", bit_str[i]);
 	}
-	printk("\n");
+	printk(KERN_DEBUG "\n");
 }
+EXPORT_SYMBOL(mite_decode);
 #endif
 
 #ifdef MODULE
@@ -785,36 +828,4 @@ void __exit cleanup_module(void)
 {
 	mite_cleanup();
 }
-
-EXPORT_SYMBOL(mite_dma_tcr);
-EXPORT_SYMBOL(mite_dma_arm);
-EXPORT_SYMBOL(mite_dma_disarm);
-EXPORT_SYMBOL(mite_sync_input_dma);
-EXPORT_SYMBOL(mite_sync_output_dma);
-EXPORT_SYMBOL(mite_setup);
-EXPORT_SYMBOL(mite_setup2);
-EXPORT_SYMBOL(mite_unsetup);
-#if 0
-EXPORT_SYMBOL(mite_kvmem_segment_load);
-EXPORT_SYMBOL(mite_ll_from_kvmem);
-EXPORT_SYMBOL(mite_setregs);
-#endif
-EXPORT_SYMBOL(mite_devices);
-EXPORT_SYMBOL(mite_list_devices);
-EXPORT_SYMBOL(mite_request_channel_in_range);
-EXPORT_SYMBOL(mite_release_channel);
-EXPORT_SYMBOL(mite_prep_dma);
-EXPORT_SYMBOL(mite_buf_change);
-EXPORT_SYMBOL(mite_bytes_written_to_memory_lb);
-EXPORT_SYMBOL(mite_bytes_written_to_memory_ub);
-EXPORT_SYMBOL(mite_bytes_read_from_memory_lb);
-EXPORT_SYMBOL(mite_bytes_read_from_memory_ub);
-EXPORT_SYMBOL(mite_bytes_in_transit);
-EXPORT_SYMBOL(mite_get_status);
-EXPORT_SYMBOL(mite_done);
-#ifdef DEBUG_MITE
-EXPORT_SYMBOL(mite_decode);
-EXPORT_SYMBOL(mite_dump_regs);
-#endif
-
 #endif

+ 0 - 7
drivers/staging/comedi/drivers/mite.h

@@ -163,13 +163,6 @@ u32 mite_bytes_in_transit(struct mite_channel *mite_chan);
 unsigned mite_get_status(struct mite_channel *mite_chan);
 int mite_done(struct mite_channel *mite_chan);
 
-#if 0
-unsigned long mite_ll_from_kvmem(struct mite_struct *mite,
-				 struct comedi_async *async, int len);
-void mite_setregs(struct mite_struct *mite, unsigned long ll_start, int chan,
-		  int dir);
-#endif
-
 void mite_prep_dma(struct mite_channel *mite_chan,
 		   unsigned int num_device_bits, unsigned int num_memory_bits);
 int mite_buf_change(struct mite_dma_descriptor_ring *ring,

+ 11 - 14
drivers/staging/comedi/drivers/multiq3.c

@@ -144,9 +144,8 @@ static int multiq3_ao_insn_read(struct comedi_device *dev,
 	int i;
 	int chan = CR_CHAN(insn->chanspec);
 
-	for (i = 0; i < insn->n; i++) {
+	for (i = 0; i < insn->n; i++)
 		data[i] = devpriv->ao_readback[chan];
-	}
 
 	return i;
 }
@@ -253,20 +252,20 @@ static int multiq3_attach(struct comedi_device *dev,
 	struct comedi_subdevice *s;
 
 	iobase = it->options[0];
-	printk("comedi%d: multiq3: 0x%04lx ", dev->minor, iobase);
+	printk(KERN_INFO "comedi%d: multiq3: 0x%04lx ", dev->minor, iobase);
 	if (!request_region(iobase, MULTIQ3_SIZE, "multiq3")) {
-		printk("comedi%d: I/O port conflict\n", dev->minor);
+		printk(KERN_ERR "comedi%d: I/O port conflict\n", dev->minor);
 		return -EIO;
 	}
 
 	dev->iobase = iobase;
 
 	irq = it->options[1];
-	if (irq) {
-		printk("comedi%d: irq = %u ignored\n", dev->minor, irq);
-	} else {
-		printk("comedi%d: no irq\n", dev->minor);
-	}
+	if (irq)
+		printk(KERN_WARNING "comedi%d: irq = %u ignored\n",
+			dev->minor, irq);
+	else
+		printk(KERN_WARNING "comedi%d: no irq\n", dev->minor);
 	dev->board_name = "multiq3";
 	result = alloc_subdevices(dev, 5);
 	if (result < 0)
@@ -330,14 +329,12 @@ static int multiq3_attach(struct comedi_device *dev,
 
 static int multiq3_detach(struct comedi_device *dev)
 {
-	printk("comedi%d: multiq3: remove\n", dev->minor);
+	printk(KERN_INFO "comedi%d: multiq3: remove\n", dev->minor);
 
-	if (dev->iobase) {
+	if (dev->iobase)
 		release_region(dev->iobase, MULTIQ3_SIZE);
-	}
-	if (dev->irq) {
+	if (dev->irq)
 		free_irq(dev->irq, dev);
-	}
 
 	return 0;
 }

+ 14 - 19
drivers/staging/comedi/drivers/ni_6527.c

@@ -273,7 +273,8 @@ static int ni6527_intr_cmdtest(struct comedi_device *dev,
 	if (err)
 		return 1;
 
-	/* step 2: make sure trigger sources are unique and mutually compatible */
+	/* step 2: make sure trigger sources are unique and */
+	/*         are mutually compatible */
 
 	if (err)
 		return 2;
@@ -377,7 +378,7 @@ static int ni6527_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	struct comedi_subdevice *s;
 	int ret;
 
-	printk("comedi%d: ni6527:", dev->minor);
+	printk(KERN_INFO "comedi%d: ni6527\n", dev->minor);
 
 	ret = alloc_private(dev, sizeof(struct ni6527_private));
 	if (ret < 0)
@@ -389,14 +390,13 @@ static int ni6527_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 	ret = mite_setup(devpriv->mite);
 	if (ret < 0) {
-		printk("error setting up mite\n");
+		printk(KERN_ERR "comedi: error setting up mite\n");
 		return ret;
 	}
 
 	dev->board_name = this_board->name;
-	printk(" %s", dev->board_name);
-
-	printk(" ID=0x%02x", readb(devpriv->mite->daq_io_addr + ID_Register));
+	printk(KERN_INFO "comedi board: %s, ID=0x%02x\n", dev->board_name,
+		readb(devpriv->mite->daq_io_addr + ID_Register));
 
 	ret = alloc_subdevices(dev, 3);
 	if (ret < 0)
@@ -415,7 +415,7 @@ static int ni6527_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	s->type = COMEDI_SUBD_DO;
 	s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
 	s->n_chan = 24;
-	s->range_table = &range_unknown;	/* FIXME: actually conductance */
+	s->range_table = &range_unknown;  /* FIXME: actually conductance */
 	s->maxdata = 1;
 	s->insn_bits = ni6527_do_insn_bits;
 
@@ -442,30 +442,25 @@ static int ni6527_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 	ret = request_irq(mite_irq(devpriv->mite), ni6527_interrupt,
 			  IRQF_SHARED, "ni6527", dev);
-	if (ret < 0) {
-		printk(" irq not available");
-	} else
+	if (ret < 0)
+		printk(KERN_WARNING "comedi i6527 irq not available\n");
+	else
 		dev->irq = mite_irq(devpriv->mite);
 
-	printk("\n");
-
 	return 0;
 }
 
 static int ni6527_detach(struct comedi_device *dev)
 {
-	if (devpriv && devpriv->mite && devpriv->mite->daq_io_addr) {
+	if (devpriv && devpriv->mite && devpriv->mite->daq_io_addr)
 		writeb(0x00,
 		       devpriv->mite->daq_io_addr + Master_Interrupt_Control);
-	}
 
-	if (dev->irq) {
+	if (dev->irq)
 		free_irq(dev->irq, dev);
-	}
 
-	if (devpriv && devpriv->mite) {
+	if (devpriv && devpriv->mite)
 		mite_unsetup(devpriv->mite);
-	}
 
 	return 0;
 }
@@ -491,7 +486,7 @@ static int ni6527_find_device(struct comedi_device *dev, int bus, int slot)
 			}
 		}
 	}
-	printk("no device found\n");
+	printk(KERN_ERR "comedi 6527: no device found\n");
 	mite_list_devices();
 	return -EIO;
 }

+ 3 - 3
drivers/staging/comedi/drivers/ni_at_ao.c

@@ -32,7 +32,8 @@ Configuration options:
   [0] - I/O port base address
   [1] - IRQ (unused)
   [2] - DMA (unused)
-  [3] - analog output range, set by jumpers on hardware (0 for -10 to 10V bipolar, 1 for 0V to 10V unipolar)
+  [3] - analog output range, set by jumpers on hardware (0 for -10 to 10V
+	bipolar, 1 for 0V to 10V unipolar)
 
 */
 /*
@@ -431,9 +432,8 @@ static int atao_calib_insn_read(struct comedi_device *dev,
 				struct comedi_insn *insn, unsigned int *data)
 {
 	int i;
-	for (i = 0; i < insn->n; i++) {
+	for (i = 0; i < insn->n; i++)
 		data[i] = 0;	/* XXX */
-	}
 	return insn->n;
 }
 

Some files were not shown because too many files changed in this diff