diff options
347 files changed, 14739 insertions, 5970 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 63df2262d41a..fb8258ebc577 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt | |||
| @@ -205,20 +205,6 @@ Who: Len Brown <len.brown@intel.com> | |||
| 205 | 205 | ||
| 206 | --------------------------- | 206 | --------------------------- |
| 207 | 207 | ||
| 208 | What: Compaq touchscreen device emulation | ||
| 209 | When: Oct 2007 | ||
| 210 | Files: drivers/input/tsdev.c | ||
| 211 | Why: The code says it was obsolete when it was written in 2001. | ||
| 212 | tslib is a userspace library which does anything tsdev can do and | ||
| 213 | much more besides in userspace where this code belongs. There is no | ||
| 214 | longer any need for tsdev and applications should have converted to | ||
| 215 | use tslib by now. | ||
| 216 | The name "tsdev" is also extremely confusing and lots of people have | ||
| 217 | it loaded when they don't need/use it. | ||
| 218 | Who: Richard Purdie <rpurdie@rpsys.net> | ||
| 219 | |||
| 220 | --------------------------- | ||
| 221 | |||
| 222 | What: i2c-ixp2000, i2c-ixp4xx and scx200_i2c drivers | 208 | What: i2c-ixp2000, i2c-ixp4xx and scx200_i2c drivers |
| 223 | When: September 2007 | 209 | When: September 2007 |
| 224 | Why: Obsolete. The new i2c-gpio driver replaces all hardware-specific | 210 | Why: Obsolete. The new i2c-gpio driver replaces all hardware-specific |
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index c323778270ff..085e4a095eaa 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
| @@ -1083,6 +1083,13 @@ and is between 256 and 4096 characters. It is defined in the file | |||
| 1083 | [NFS] set the maximum lifetime for idmapper cache | 1083 | [NFS] set the maximum lifetime for idmapper cache |
| 1084 | entries. | 1084 | entries. |
| 1085 | 1085 | ||
| 1086 | nfs.enable_ino64= | ||
| 1087 | [NFS] enable 64-bit inode numbers. | ||
| 1088 | If zero, the NFS client will fake up a 32-bit inode | ||
| 1089 | number for the readdir() and stat() syscalls instead | ||
| 1090 | of returning the full 64-bit number. | ||
| 1091 | The default is to return 64-bit inode numbers. | ||
| 1092 | |||
| 1086 | nmi_watchdog= [KNL,BUGS=X86-32] Debugging features for SMP kernels | 1093 | nmi_watchdog= [KNL,BUGS=X86-32] Debugging features for SMP kernels |
| 1087 | 1094 | ||
| 1088 | no387 [BUGS=X86-32] Tells the kernel to use the 387 maths | 1095 | no387 [BUGS=X86-32] Tells the kernel to use the 387 maths |
| @@ -1883,9 +1890,6 @@ and is between 256 and 4096 characters. It is defined in the file | |||
| 1883 | Format: | 1890 | Format: |
| 1884 | <io>,<irq>,<dma>,<dma2>,<sb_io>,<sb_irq>,<sb_dma>,<mpu_io>,<mpu_irq> | 1891 | <io>,<irq>,<dma>,<dma2>,<sb_io>,<sb_irq>,<sb_dma>,<mpu_io>,<mpu_irq> |
| 1885 | 1892 | ||
| 1886 | tsdev.xres= [TS] Horizontal screen resolution. | ||
| 1887 | tsdev.yres= [TS] Vertical screen resolution. | ||
| 1888 | |||
| 1889 | turbografx.map[2|3]= [HW,JOY] | 1893 | turbografx.map[2|3]= [HW,JOY] |
| 1890 | TurboGraFX parallel port interface | 1894 | TurboGraFX parallel port interface |
| 1891 | Format: | 1895 | Format: |
diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt index 1da566630831..11340625e363 100644 --- a/Documentation/networking/bonding.txt +++ b/Documentation/networking/bonding.txt | |||
| @@ -281,6 +281,39 @@ downdelay | |||
| 281 | will be rounded down to the nearest multiple. The default | 281 | will be rounded down to the nearest multiple. The default |
| 282 | value is 0. | 282 | value is 0. |
| 283 | 283 | ||
| 284 | fail_over_mac | ||
| 285 | |||
| 286 | Specifies whether active-backup mode should set all slaves to | ||
| 287 | the same MAC address (the traditional behavior), or, when | ||
| 288 | enabled, change the bond's MAC address when changing the | ||
| 289 | active interface (i.e., fail over the MAC address itself). | ||
| 290 | |||
| 291 | Fail over MAC is useful for devices that cannot ever alter | ||
| 292 | their MAC address, or for devices that refuse incoming | ||
| 293 | broadcasts with their own source MAC (which interferes with | ||
| 294 | the ARP monitor). | ||
| 295 | |||
| 296 | The down side of fail over MAC is that every device on the | ||
| 297 | network must be updated via gratuitous ARP, vs. just updating | ||
| 298 | a switch or set of switches (which often takes place for any | ||
| 299 | traffic, not just ARP traffic, if the switch snoops incoming | ||
| 300 | traffic to update its tables) for the traditional method. If | ||
| 301 | the gratuitous ARP is lost, communication may be disrupted. | ||
| 302 | |||
| 303 | When fail over MAC is used in conjuction with the mii monitor, | ||
| 304 | devices which assert link up prior to being able to actually | ||
| 305 | transmit and receive are particularly susecptible to loss of | ||
| 306 | the gratuitous ARP, and an appropriate updelay setting may be | ||
| 307 | required. | ||
| 308 | |||
| 309 | A value of 0 disables fail over MAC, and is the default. A | ||
| 310 | value of 1 enables fail over MAC. This option is enabled | ||
| 311 | automatically if the first slave added cannot change its MAC | ||
| 312 | address. This option may be modified via sysfs only when no | ||
| 313 | slaves are present in the bond. | ||
| 314 | |||
| 315 | This option was added in bonding version 3.2.0. | ||
| 316 | |||
| 284 | lacp_rate | 317 | lacp_rate |
| 285 | 318 | ||
| 286 | Option specifying the rate in which we'll ask our link partner | 319 | Option specifying the rate in which we'll ask our link partner |
diff --git a/Documentation/networking/proc_net_tcp.txt b/Documentation/networking/proc_net_tcp.txt index 5e21f7cb6383..4a79209e77a7 100644 --- a/Documentation/networking/proc_net_tcp.txt +++ b/Documentation/networking/proc_net_tcp.txt | |||
| @@ -1,8 +1,9 @@ | |||
| 1 | This document describes the interfaces /proc/net/tcp and /proc/net/tcp6. | 1 | This document describes the interfaces /proc/net/tcp and /proc/net/tcp6. |
| 2 | Note that these interfaces are deprecated in favor of tcp_diag. | ||
| 2 | 3 | ||
| 3 | These /proc interfaces provide information about currently active TCP | 4 | These /proc interfaces provide information about currently active TCP |
| 4 | connections, and are implemented by tcp_get_info() in net/ipv4/tcp_ipv4.c and | 5 | connections, and are implemented by tcp4_seq_show() in net/ipv4/tcp_ipv4.c |
| 5 | tcp6_get_info() in net/ipv6/tcp_ipv6.c, respectively. | 6 | and tcp6_seq_show() in net/ipv6/tcp_ipv6.c, respectively. |
| 6 | 7 | ||
| 7 | It will first list all listening TCP sockets, and next list all established | 8 | It will first list all listening TCP sockets, and next list all established |
| 8 | TCP connections. A typical entry of /proc/net/tcp would look like this (split | 9 | TCP connections. A typical entry of /proc/net/tcp would look like this (split |
diff --git a/MAINTAINERS b/MAINTAINERS index 12cee3da2625..c7355e7f09ff 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -2404,6 +2404,15 @@ M: khali@linux-fr.org | |||
| 2404 | L: lm-sensors@lm-sensors.org | 2404 | L: lm-sensors@lm-sensors.org |
| 2405 | S: Maintained | 2405 | S: Maintained |
| 2406 | 2406 | ||
| 2407 | LOCKDEP AND LOCKSTAT | ||
| 2408 | P: Peter Zijlstra | ||
| 2409 | M: peterz@infradead.org | ||
| 2410 | P: Ingo Molnar | ||
| 2411 | M: mingo@redhat.com | ||
| 2412 | L: linux-kernel@vger.kernel.org | ||
| 2413 | T: git://git.kernel.org/pub/scm/linux/kernel/git/peterz/linux-2.6-lockdep.git | ||
| 2414 | S: Maintained | ||
| 2415 | |||
| 2407 | LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP/Vista Dynamic Disks) | 2416 | LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP/Vista Dynamic Disks) |
| 2408 | P: Richard Russon (FlatCap) | 2417 | P: Richard Russon (FlatCap) |
| 2409 | M: ldm@flatcap.org | 2418 | M: ldm@flatcap.org |
diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c index 2c47db494f7d..046e6d84bbfc 100644 --- a/arch/blackfin/mach-bf548/boards/ezkit.c +++ b/arch/blackfin/mach-bf548/boards/ezkit.c | |||
| @@ -88,7 +88,7 @@ static struct platform_device bf54x_lq043_device = { | |||
| 88 | #endif | 88 | #endif |
| 89 | 89 | ||
| 90 | #if defined(CONFIG_KEYBOARD_BFIN) || defined(CONFIG_KEYBOARD_BFIN_MODULE) | 90 | #if defined(CONFIG_KEYBOARD_BFIN) || defined(CONFIG_KEYBOARD_BFIN_MODULE) |
| 91 | static int bf548_keymap[] = { | 91 | static const unsigned int bf548_keymap[] = { |
| 92 | KEYVAL(0, 0, KEY_ENTER), | 92 | KEYVAL(0, 0, KEY_ENTER), |
| 93 | KEYVAL(0, 1, KEY_HELP), | 93 | KEYVAL(0, 1, KEY_HELP), |
| 94 | KEYVAL(0, 2, KEY_0), | 94 | KEYVAL(0, 2, KEY_0), |
| @@ -110,8 +110,8 @@ static int bf548_keymap[] = { | |||
| 110 | static struct bfin_kpad_platform_data bf54x_kpad_data = { | 110 | static struct bfin_kpad_platform_data bf54x_kpad_data = { |
| 111 | .rows = 4, | 111 | .rows = 4, |
| 112 | .cols = 4, | 112 | .cols = 4, |
| 113 | .keymap = bf548_keymap, | 113 | .keymap = bf548_keymap, |
| 114 | .keymapsize = ARRAY_SIZE(bf548_keymap), | 114 | .keymapsize = ARRAY_SIZE(bf548_keymap), |
| 115 | .repeat = 0, | 115 | .repeat = 0, |
| 116 | .debounce_time = 5000, /* ns (5ms) */ | 116 | .debounce_time = 5000, /* ns (5ms) */ |
| 117 | .coldrive_time = 1000, /* ns (1ms) */ | 117 | .coldrive_time = 1000, /* ns (1ms) */ |
diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c index fbbccb5e7511..880add120eb3 100644 --- a/arch/m68k/atari/atakeyb.c +++ b/arch/m68k/atari/atakeyb.c | |||
| @@ -1,6 +1,4 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * linux/arch/m68k/atari/atakeyb.c | ||
| 3 | * | ||
| 4 | * Atari Keyboard driver for 680x0 Linux | 2 | * Atari Keyboard driver for 680x0 Linux |
| 5 | * | 3 | * |
| 6 | * This file is subject to the terms and conditions of the GNU General Public | 4 | * This file is subject to the terms and conditions of the GNU General Public |
diff --git a/arch/mips/au1000/common/prom.c b/arch/mips/au1000/common/prom.c index a8637cdb5b4b..90d70695aa60 100644 --- a/arch/mips/au1000/common/prom.c +++ b/arch/mips/au1000/common/prom.c | |||
| @@ -33,7 +33,6 @@ | |||
| 33 | * with this program; if not, write to the Free Software Foundation, Inc., | 33 | * with this program; if not, write to the Free Software Foundation, Inc., |
| 34 | * 675 Mass Ave, Cambridge, MA 02139, USA. | 34 | * 675 Mass Ave, Cambridge, MA 02139, USA. |
| 35 | */ | 35 | */ |
| 36 | |||
| 37 | #include <linux/module.h> | 36 | #include <linux/module.h> |
| 38 | #include <linux/kernel.h> | 37 | #include <linux/kernel.h> |
| 39 | #include <linux/init.h> | 38 | #include <linux/init.h> |
| @@ -41,18 +40,16 @@ | |||
| 41 | 40 | ||
| 42 | #include <asm/bootinfo.h> | 41 | #include <asm/bootinfo.h> |
| 43 | 42 | ||
| 44 | /* #define DEBUG_CMDLINE */ | 43 | int prom_argc; |
| 45 | 44 | char **prom_argv; | |
| 46 | extern int prom_argc; | 45 | char **prom_envp; |
| 47 | extern char **prom_argv, **prom_envp; | ||
| 48 | |||
| 49 | 46 | ||
| 50 | char * __init_or_module prom_getcmdline(void) | 47 | char * __init_or_module prom_getcmdline(void) |
| 51 | { | 48 | { |
| 52 | return &(arcs_cmdline[0]); | 49 | return &(arcs_cmdline[0]); |
| 53 | } | 50 | } |
| 54 | 51 | ||
| 55 | void prom_init_cmdline(void) | 52 | void prom_init_cmdline(void) |
| 56 | { | 53 | { |
| 57 | char *cp; | 54 | char *cp; |
| 58 | int actr; | 55 | int actr; |
| @@ -61,7 +58,7 @@ void prom_init_cmdline(void) | |||
| 61 | 58 | ||
| 62 | cp = &(arcs_cmdline[0]); | 59 | cp = &(arcs_cmdline[0]); |
| 63 | while(actr < prom_argc) { | 60 | while(actr < prom_argc) { |
| 64 | strcpy(cp, prom_argv[actr]); | 61 | strcpy(cp, prom_argv[actr]); |
| 65 | cp += strlen(prom_argv[actr]); | 62 | cp += strlen(prom_argv[actr]); |
| 66 | *cp++ = ' '; | 63 | *cp++ = ' '; |
| 67 | actr++; | 64 | actr++; |
| @@ -70,10 +67,8 @@ void prom_init_cmdline(void) | |||
| 70 | --cp; | 67 | --cp; |
| 71 | if (prom_argc > 1) | 68 | if (prom_argc > 1) |
| 72 | *cp = '\0'; | 69 | *cp = '\0'; |
| 73 | |||
| 74 | } | 70 | } |
| 75 | 71 | ||
| 76 | |||
| 77 | char *prom_getenv(char *envname) | 72 | char *prom_getenv(char *envname) |
| 78 | { | 73 | { |
| 79 | /* | 74 | /* |
| @@ -95,21 +90,23 @@ char *prom_getenv(char *envname) | |||
| 95 | } | 90 | } |
| 96 | env++; | 91 | env++; |
| 97 | } | 92 | } |
| 93 | |||
| 98 | return NULL; | 94 | return NULL; |
| 99 | } | 95 | } |
| 100 | 96 | ||
| 101 | inline unsigned char str2hexnum(unsigned char c) | 97 | static inline unsigned char str2hexnum(unsigned char c) |
| 102 | { | 98 | { |
| 103 | if(c >= '0' && c <= '9') | 99 | if (c >= '0' && c <= '9') |
| 104 | return c - '0'; | 100 | return c - '0'; |
| 105 | if(c >= 'a' && c <= 'f') | 101 | if (c >= 'a' && c <= 'f') |
| 106 | return c - 'a' + 10; | 102 | return c - 'a' + 10; |
| 107 | if(c >= 'A' && c <= 'F') | 103 | if (c >= 'A' && c <= 'F') |
| 108 | return c - 'A' + 10; | 104 | return c - 'A' + 10; |
| 105 | |||
| 109 | return 0; /* foo */ | 106 | return 0; /* foo */ |
| 110 | } | 107 | } |
| 111 | 108 | ||
| 112 | inline void str2eaddr(unsigned char *ea, unsigned char *str) | 109 | static inline void str2eaddr(unsigned char *ea, unsigned char *str) |
| 113 | { | 110 | { |
| 114 | int i; | 111 | int i; |
| 115 | 112 | ||
| @@ -124,35 +121,29 @@ inline void str2eaddr(unsigned char *ea, unsigned char *str) | |||
| 124 | } | 121 | } |
| 125 | } | 122 | } |
| 126 | 123 | ||
| 127 | int get_ethernet_addr(char *ethernet_addr) | 124 | int prom_get_ethernet_addr(char *ethernet_addr) |
| 128 | { | 125 | { |
| 129 | char *ethaddr_str; | 126 | char *ethaddr_str; |
| 127 | char *argptr; | ||
| 130 | 128 | ||
| 131 | ethaddr_str = prom_getenv("ethaddr"); | 129 | /* Check the environment variables first */ |
| 130 | ethaddr_str = prom_getenv("ethaddr"); | ||
| 132 | if (!ethaddr_str) { | 131 | if (!ethaddr_str) { |
| 133 | printk("ethaddr not set in boot prom\n"); | 132 | /* Check command line */ |
| 134 | return -1; | 133 | argptr = prom_getcmdline(); |
| 135 | } | 134 | ethaddr_str = strstr(argptr, "ethaddr="); |
| 136 | str2eaddr(ethernet_addr, ethaddr_str); | 135 | if (!ethaddr_str) |
| 137 | 136 | return -1; | |
| 138 | #if 0 | ||
| 139 | { | ||
| 140 | int i; | ||
| 141 | 137 | ||
| 142 | printk("get_ethernet_addr: "); | 138 | ethaddr_str += strlen("ethaddr="); |
| 143 | for (i=0; i<5; i++) | ||
| 144 | printk("%02x:", (unsigned char)*(ethernet_addr+i)); | ||
| 145 | printk("%02x\n", *(ethernet_addr+i)); | ||
| 146 | } | 139 | } |
| 147 | #endif | 140 | |
| 141 | str2eaddr(ethernet_addr, ethaddr_str); | ||
| 148 | 142 | ||
| 149 | return 0; | 143 | return 0; |
| 150 | } | 144 | } |
| 145 | EXPORT_SYMBOL(prom_get_ethernet_addr); | ||
| 151 | 146 | ||
| 152 | void __init prom_free_prom_memory(void) | 147 | void __init prom_free_prom_memory(void) |
| 153 | { | 148 | { |
| 154 | } | 149 | } |
| 155 | |||
| 156 | EXPORT_SYMBOL(prom_getcmdline); | ||
| 157 | EXPORT_SYMBOL(get_ethernet_addr); | ||
| 158 | EXPORT_SYMBOL(str2eaddr); | ||
diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c index b212c0726125..a90d425d4651 100644 --- a/arch/mips/au1000/common/setup.c +++ b/arch/mips/au1000/common/setup.c | |||
| @@ -40,10 +40,11 @@ | |||
| 40 | #include <asm/mipsregs.h> | 40 | #include <asm/mipsregs.h> |
| 41 | #include <asm/reboot.h> | 41 | #include <asm/reboot.h> |
| 42 | #include <asm/pgtable.h> | 42 | #include <asm/pgtable.h> |
| 43 | #include <asm/mach-au1x00/au1000.h> | ||
| 44 | #include <asm/time.h> | 43 | #include <asm/time.h> |
| 45 | 44 | ||
| 46 | extern char * prom_getcmdline(void); | 45 | #include <au1000.h> |
| 46 | #include <prom.h> | ||
| 47 | |||
| 47 | extern void __init board_setup(void); | 48 | extern void __init board_setup(void); |
| 48 | extern void au1000_restart(char *); | 49 | extern void au1000_restart(char *); |
| 49 | extern void au1000_halt(void); | 50 | extern void au1000_halt(void); |
diff --git a/arch/mips/au1000/db1x00/init.c b/arch/mips/au1000/db1x00/init.c index 4d7bcfc8cf73..43298fd9459c 100644 --- a/arch/mips/au1000/db1x00/init.c +++ b/arch/mips/au1000/db1x00/init.c | |||
| @@ -31,15 +31,13 @@ | |||
| 31 | #include <linux/mm.h> | 31 | #include <linux/mm.h> |
| 32 | #include <linux/sched.h> | 32 | #include <linux/sched.h> |
| 33 | #include <linux/bootmem.h> | 33 | #include <linux/bootmem.h> |
| 34 | #include <asm/addrspace.h> | ||
| 35 | #include <asm/bootinfo.h> | ||
| 36 | #include <linux/string.h> | 34 | #include <linux/string.h> |
| 37 | #include <linux/kernel.h> | 35 | #include <linux/kernel.h> |
| 38 | 36 | ||
| 39 | int prom_argc; | 37 | #include <asm/addrspace.h> |
| 40 | char **prom_argv, **prom_envp; | 38 | #include <asm/bootinfo.h> |
| 41 | extern void __init prom_init_cmdline(void); | 39 | |
| 42 | extern char *prom_getenv(char *envname); | 40 | #include <prom.h> |
| 43 | 41 | ||
| 44 | const char *get_system_type(void) | 42 | const char *get_system_type(void) |
| 45 | { | 43 | { |
diff --git a/arch/mips/au1000/mtx-1/init.c b/arch/mips/au1000/mtx-1/init.c index 2aa7b2ed6a8c..cdeae3212a2d 100644 --- a/arch/mips/au1000/mtx-1/init.c +++ b/arch/mips/au1000/mtx-1/init.c | |||
| @@ -34,13 +34,11 @@ | |||
| 34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
| 35 | #include <linux/mm.h> | 35 | #include <linux/mm.h> |
| 36 | #include <linux/bootmem.h> | 36 | #include <linux/bootmem.h> |
| 37 | |||
| 37 | #include <asm/addrspace.h> | 38 | #include <asm/addrspace.h> |
| 38 | #include <asm/bootinfo.h> | 39 | #include <asm/bootinfo.h> |
| 39 | 40 | ||
| 40 | int prom_argc; | 41 | #include <prom.h> |
| 41 | char **prom_argv, **prom_envp; | ||
| 42 | extern void __init prom_init_cmdline(void); | ||
| 43 | extern char *prom_getenv(char *envname); | ||
| 44 | 42 | ||
| 45 | const char *get_system_type(void) | 43 | const char *get_system_type(void) |
| 46 | { | 44 | { |
diff --git a/arch/mips/au1000/pb1000/init.c b/arch/mips/au1000/pb1000/init.c index 4535f7208e18..ddccaf6997d0 100644 --- a/arch/mips/au1000/pb1000/init.c +++ b/arch/mips/au1000/pb1000/init.c | |||
| @@ -30,15 +30,13 @@ | |||
| 30 | #include <linux/mm.h> | 30 | #include <linux/mm.h> |
| 31 | #include <linux/sched.h> | 31 | #include <linux/sched.h> |
| 32 | #include <linux/bootmem.h> | 32 | #include <linux/bootmem.h> |
| 33 | #include <asm/addrspace.h> | ||
| 34 | #include <asm/bootinfo.h> | ||
| 35 | #include <linux/string.h> | 33 | #include <linux/string.h> |
| 36 | #include <linux/kernel.h> | 34 | #include <linux/kernel.h> |
| 37 | 35 | ||
| 38 | int prom_argc; | 36 | #include <asm/addrspace.h> |
| 39 | char **prom_argv, **prom_envp; | 37 | #include <asm/bootinfo.h> |
| 40 | extern void __init prom_init_cmdline(void); | 38 | |
| 41 | extern char *prom_getenv(char *envname); | 39 | #include <prom.h> |
| 42 | 40 | ||
| 43 | const char *get_system_type(void) | 41 | const char *get_system_type(void) |
| 44 | { | 42 | { |
diff --git a/arch/mips/au1000/pb1100/init.c b/arch/mips/au1000/pb1100/init.c index 7ba6852de7cd..c93fd39b4aba 100644 --- a/arch/mips/au1000/pb1100/init.c +++ b/arch/mips/au1000/pb1100/init.c | |||
| @@ -31,15 +31,13 @@ | |||
| 31 | #include <linux/mm.h> | 31 | #include <linux/mm.h> |
| 32 | #include <linux/sched.h> | 32 | #include <linux/sched.h> |
| 33 | #include <linux/bootmem.h> | 33 | #include <linux/bootmem.h> |
| 34 | #include <asm/addrspace.h> | ||
| 35 | #include <asm/bootinfo.h> | ||
| 36 | #include <linux/string.h> | 34 | #include <linux/string.h> |
| 37 | #include <linux/kernel.h> | 35 | #include <linux/kernel.h> |
| 38 | 36 | ||
| 39 | int prom_argc; | 37 | #include <asm/addrspace.h> |
| 40 | char **prom_argv, **prom_envp; | 38 | #include <asm/bootinfo.h> |
| 41 | extern void __init prom_init_cmdline(void); | 39 | |
| 42 | extern char *prom_getenv(char *envname); | 40 | #include <prom.h> |
| 43 | 41 | ||
| 44 | const char *get_system_type(void) | 42 | const char *get_system_type(void) |
| 45 | { | 43 | { |
diff --git a/arch/mips/au1000/pb1200/board_setup.c b/arch/mips/au1000/pb1200/board_setup.c index 2122515f79d7..5dbc9868f598 100644 --- a/arch/mips/au1000/pb1200/board_setup.c +++ b/arch/mips/au1000/pb1200/board_setup.c | |||
| @@ -41,8 +41,10 @@ | |||
| 41 | #include <asm/mipsregs.h> | 41 | #include <asm/mipsregs.h> |
| 42 | #include <asm/reboot.h> | 42 | #include <asm/reboot.h> |
| 43 | #include <asm/pgtable.h> | 43 | #include <asm/pgtable.h> |
| 44 | #include <asm/mach-au1x00/au1000.h> | 44 | |
| 45 | #include <asm/mach-au1x00/au1xxx_dbdma.h> | 45 | #include <au1000.h> |
| 46 | #include <au1xxx_dbdma.h> | ||
| 47 | #include <prom.h> | ||
| 46 | 48 | ||
| 47 | #ifdef CONFIG_MIPS_PB1200 | 49 | #ifdef CONFIG_MIPS_PB1200 |
| 48 | #include <asm/mach-pb1x00/pb1200.h> | 50 | #include <asm/mach-pb1x00/pb1200.h> |
diff --git a/arch/mips/au1000/pb1200/init.c b/arch/mips/au1000/pb1200/init.c index 5a70029d5388..c251570749ee 100644 --- a/arch/mips/au1000/pb1200/init.c +++ b/arch/mips/au1000/pb1200/init.c | |||
| @@ -31,15 +31,13 @@ | |||
| 31 | #include <linux/mm.h> | 31 | #include <linux/mm.h> |
| 32 | #include <linux/sched.h> | 32 | #include <linux/sched.h> |
| 33 | #include <linux/bootmem.h> | 33 | #include <linux/bootmem.h> |
| 34 | #include <asm/addrspace.h> | ||
| 35 | #include <asm/bootinfo.h> | ||
| 36 | #include <linux/string.h> | 34 | #include <linux/string.h> |
| 37 | #include <linux/kernel.h> | 35 | #include <linux/kernel.h> |
| 38 | 36 | ||
| 39 | int prom_argc; | 37 | #include <asm/addrspace.h> |
| 40 | char **prom_argv, **prom_envp; | 38 | #include <asm/bootinfo.h> |
| 41 | extern void __init prom_init_cmdline(void); | 39 | |
| 42 | extern char *prom_getenv(char *envname); | 40 | #include <prom.h> |
| 43 | 41 | ||
| 44 | const char *get_system_type(void) | 42 | const char *get_system_type(void) |
| 45 | { | 43 | { |
diff --git a/arch/mips/au1000/pb1500/init.c b/arch/mips/au1000/pb1500/init.c index e58a9d6c5021..507d4b204161 100644 --- a/arch/mips/au1000/pb1500/init.c +++ b/arch/mips/au1000/pb1500/init.c | |||
| @@ -31,15 +31,13 @@ | |||
| 31 | #include <linux/mm.h> | 31 | #include <linux/mm.h> |
| 32 | #include <linux/sched.h> | 32 | #include <linux/sched.h> |
| 33 | #include <linux/bootmem.h> | 33 | #include <linux/bootmem.h> |
| 34 | #include <asm/addrspace.h> | ||
| 35 | #include <asm/bootinfo.h> | ||
| 36 | #include <linux/string.h> | 34 | #include <linux/string.h> |
| 37 | #include <linux/kernel.h> | 35 | #include <linux/kernel.h> |
| 38 | 36 | ||
| 39 | int prom_argc; | 37 | #include <asm/addrspace.h> |
| 40 | char **prom_argv, **prom_envp; | 38 | #include <asm/bootinfo.h> |
| 41 | extern void __init prom_init_cmdline(void); | 39 | |
| 42 | extern char *prom_getenv(char *envname); | 40 | #include <prom.h> |
| 43 | 41 | ||
| 44 | const char *get_system_type(void) | 42 | const char *get_system_type(void) |
| 45 | { | 43 | { |
diff --git a/arch/mips/au1000/pb1550/init.c b/arch/mips/au1000/pb1550/init.c index fad53bf5aad1..b03eee601e36 100644 --- a/arch/mips/au1000/pb1550/init.c +++ b/arch/mips/au1000/pb1550/init.c | |||
| @@ -31,15 +31,13 @@ | |||
| 31 | #include <linux/mm.h> | 31 | #include <linux/mm.h> |
| 32 | #include <linux/sched.h> | 32 | #include <linux/sched.h> |
| 33 | #include <linux/bootmem.h> | 33 | #include <linux/bootmem.h> |
| 34 | #include <asm/addrspace.h> | ||
| 35 | #include <asm/bootinfo.h> | ||
| 36 | #include <linux/string.h> | 34 | #include <linux/string.h> |
| 37 | #include <linux/kernel.h> | 35 | #include <linux/kernel.h> |
| 38 | 36 | ||
| 39 | int prom_argc; | 37 | #include <asm/addrspace.h> |
| 40 | char **prom_argv, **prom_envp; | 38 | #include <asm/bootinfo.h> |
| 41 | extern void __init prom_init_cmdline(void); | 39 | |
| 42 | extern char *prom_getenv(char *envname); | 40 | #include <prom.h> |
| 43 | 41 | ||
| 44 | const char *get_system_type(void) | 42 | const char *get_system_type(void) |
| 45 | { | 43 | { |
diff --git a/arch/mips/au1000/xxs1500/init.c b/arch/mips/au1000/xxs1500/init.c index 9f839c36f69e..6532939f377a 100644 --- a/arch/mips/au1000/xxs1500/init.c +++ b/arch/mips/au1000/xxs1500/init.c | |||
| @@ -30,15 +30,13 @@ | |||
| 30 | #include <linux/mm.h> | 30 | #include <linux/mm.h> |
| 31 | #include <linux/sched.h> | 31 | #include <linux/sched.h> |
| 32 | #include <linux/bootmem.h> | 32 | #include <linux/bootmem.h> |
| 33 | #include <asm/addrspace.h> | ||
| 34 | #include <asm/bootinfo.h> | ||
| 35 | #include <linux/string.h> | 33 | #include <linux/string.h> |
| 36 | #include <linux/kernel.h> | 34 | #include <linux/kernel.h> |
| 37 | 35 | ||
| 38 | int prom_argc; | 36 | #include <asm/addrspace.h> |
| 39 | char **prom_argv, **prom_envp; | 37 | #include <asm/bootinfo.h> |
| 40 | extern void __init prom_init_cmdline(void); | 38 | |
| 41 | extern char *prom_getenv(char *envname); | 39 | #include <prom.h> |
| 42 | 40 | ||
| 43 | const char *get_system_type(void) | 41 | const char *get_system_type(void) |
| 44 | { | 42 | { |
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c index 1245b2f517bb..095988f13bf4 100644 --- a/arch/powerpc/platforms/cell/axon_msi.c +++ b/arch/powerpc/platforms/cell/axon_msi.c | |||
| @@ -77,12 +77,7 @@ static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val) | |||
| 77 | { | 77 | { |
| 78 | pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n); | 78 | pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n); |
| 79 | 79 | ||
| 80 | dcr_write(msic->dcr_host, msic->dcr_host.base + dcr_n, val); | 80 | dcr_write(msic->dcr_host, dcr_n, val); |
| 81 | } | ||
| 82 | |||
| 83 | static u32 msic_dcr_read(struct axon_msic *msic, unsigned int dcr_n) | ||
| 84 | { | ||
| 85 | return dcr_read(msic->dcr_host, msic->dcr_host.base + dcr_n); | ||
| 86 | } | 81 | } |
| 87 | 82 | ||
| 88 | static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc) | 83 | static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc) |
| @@ -91,7 +86,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc) | |||
| 91 | u32 write_offset, msi; | 86 | u32 write_offset, msi; |
| 92 | int idx; | 87 | int idx; |
| 93 | 88 | ||
| 94 | write_offset = msic_dcr_read(msic, MSIC_WRITE_OFFSET_REG); | 89 | write_offset = dcr_read(msic->dcr_host, MSIC_WRITE_OFFSET_REG); |
| 95 | pr_debug("axon_msi: original write_offset 0x%x\n", write_offset); | 90 | pr_debug("axon_msi: original write_offset 0x%x\n", write_offset); |
| 96 | 91 | ||
| 97 | /* write_offset doesn't wrap properly, so we have to mask it */ | 92 | /* write_offset doesn't wrap properly, so we have to mask it */ |
| @@ -306,7 +301,7 @@ static int axon_msi_notify_reboot(struct notifier_block *nb, | |||
| 306 | list_for_each_entry(msic, &axon_msic_list, list) { | 301 | list_for_each_entry(msic, &axon_msic_list, list) { |
| 307 | pr_debug("axon_msi: disabling %s\n", | 302 | pr_debug("axon_msi: disabling %s\n", |
| 308 | msic->irq_host->of_node->full_name); | 303 | msic->irq_host->of_node->full_name); |
| 309 | tmp = msic_dcr_read(msic, MSIC_CTRL_REG); | 304 | tmp = dcr_read(msic->dcr_host, MSIC_CTRL_REG); |
| 310 | tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE; | 305 | tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE; |
| 311 | msic_dcr_write(msic, MSIC_CTRL_REG, tmp); | 306 | msic_dcr_write(msic, MSIC_CTRL_REG, tmp); |
| 312 | } | 307 | } |
diff --git a/arch/powerpc/sysdev/dcr.c b/arch/powerpc/sysdev/dcr.c index ab11c0b29024..427027c7ea0f 100644 --- a/arch/powerpc/sysdev/dcr.c +++ b/arch/powerpc/sysdev/dcr.c | |||
| @@ -126,13 +126,13 @@ dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n, | |||
| 126 | } | 126 | } |
| 127 | EXPORT_SYMBOL_GPL(dcr_map); | 127 | EXPORT_SYMBOL_GPL(dcr_map); |
| 128 | 128 | ||
| 129 | void dcr_unmap(dcr_host_t host, unsigned int dcr_n, unsigned int dcr_c) | 129 | void dcr_unmap(dcr_host_t host, unsigned int dcr_c) |
| 130 | { | 130 | { |
| 131 | dcr_host_t h = host; | 131 | dcr_host_t h = host; |
| 132 | 132 | ||
| 133 | if (h.token == NULL) | 133 | if (h.token == NULL) |
| 134 | return; | 134 | return; |
| 135 | h.token += dcr_n * h.stride; | 135 | h.token += host.base * h.stride; |
| 136 | iounmap(h.token); | 136 | iounmap(h.token); |
| 137 | h.token = NULL; | 137 | h.token = NULL; |
| 138 | } | 138 | } |
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 893e65439e85..e47938899a92 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c | |||
| @@ -156,7 +156,7 @@ static inline u32 _mpic_read(enum mpic_reg_type type, | |||
| 156 | switch(type) { | 156 | switch(type) { |
| 157 | #ifdef CONFIG_PPC_DCR | 157 | #ifdef CONFIG_PPC_DCR |
| 158 | case mpic_access_dcr: | 158 | case mpic_access_dcr: |
| 159 | return dcr_read(rb->dhost, rb->dhost.base + reg); | 159 | return dcr_read(rb->dhost, reg); |
| 160 | #endif | 160 | #endif |
| 161 | case mpic_access_mmio_be: | 161 | case mpic_access_mmio_be: |
| 162 | return in_be32(rb->base + (reg >> 2)); | 162 | return in_be32(rb->base + (reg >> 2)); |
| @@ -173,7 +173,7 @@ static inline void _mpic_write(enum mpic_reg_type type, | |||
| 173 | switch(type) { | 173 | switch(type) { |
| 174 | #ifdef CONFIG_PPC_DCR | 174 | #ifdef CONFIG_PPC_DCR |
| 175 | case mpic_access_dcr: | 175 | case mpic_access_dcr: |
| 176 | return dcr_write(rb->dhost, rb->dhost.base + reg, value); | 176 | return dcr_write(rb->dhost, reg, value); |
| 177 | #endif | 177 | #endif |
| 178 | case mpic_access_mmio_be: | 178 | case mpic_access_mmio_be: |
| 179 | return out_be32(rb->base + (reg >> 2), value); | 179 | return out_be32(rb->base + (reg >> 2), value); |
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index f3bceb165321..139ca153d5cc 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
| @@ -68,9 +68,15 @@ STACK_SIZE = 1 << STACK_SHIFT | |||
| 68 | l %r1,BASED(.Ltrace_irq_off) | 68 | l %r1,BASED(.Ltrace_irq_off) |
| 69 | basr %r14,%r1 | 69 | basr %r14,%r1 |
| 70 | .endm | 70 | .endm |
| 71 | |||
| 72 | .macro LOCKDEP_SYS_EXIT | ||
| 73 | l %r1,BASED(.Llockdep_sys_exit) | ||
| 74 | basr %r14,%r1 | ||
| 75 | .endm | ||
| 71 | #else | 76 | #else |
| 72 | #define TRACE_IRQS_ON | 77 | #define TRACE_IRQS_ON |
| 73 | #define TRACE_IRQS_OFF | 78 | #define TRACE_IRQS_OFF |
| 79 | #define LOCKDEP_SYS_EXIT | ||
| 74 | #endif | 80 | #endif |
| 75 | 81 | ||
| 76 | /* | 82 | /* |
| @@ -260,6 +266,7 @@ sysc_return: | |||
| 260 | bno BASED(sysc_leave) | 266 | bno BASED(sysc_leave) |
| 261 | tm __TI_flags+3(%r9),_TIF_WORK_SVC | 267 | tm __TI_flags+3(%r9),_TIF_WORK_SVC |
| 262 | bnz BASED(sysc_work) # there is work to do (signals etc.) | 268 | bnz BASED(sysc_work) # there is work to do (signals etc.) |
| 269 | LOCKDEP_SYS_EXIT | ||
| 263 | sysc_leave: | 270 | sysc_leave: |
| 264 | RESTORE_ALL __LC_RETURN_PSW,1 | 271 | RESTORE_ALL __LC_RETURN_PSW,1 |
| 265 | 272 | ||
| @@ -283,6 +290,7 @@ sysc_work: | |||
| 283 | bo BASED(sysc_restart) | 290 | bo BASED(sysc_restart) |
| 284 | tm __TI_flags+3(%r9),_TIF_SINGLE_STEP | 291 | tm __TI_flags+3(%r9),_TIF_SINGLE_STEP |
| 285 | bo BASED(sysc_singlestep) | 292 | bo BASED(sysc_singlestep) |
| 293 | LOCKDEP_SYS_EXIT | ||
| 286 | b BASED(sysc_leave) | 294 | b BASED(sysc_leave) |
| 287 | 295 | ||
| 288 | # | 296 | # |
| @@ -572,6 +580,7 @@ io_return: | |||
| 572 | #endif | 580 | #endif |
| 573 | tm __TI_flags+3(%r9),_TIF_WORK_INT | 581 | tm __TI_flags+3(%r9),_TIF_WORK_INT |
| 574 | bnz BASED(io_work) # there is work to do (signals etc.) | 582 | bnz BASED(io_work) # there is work to do (signals etc.) |
| 583 | LOCKDEP_SYS_EXIT | ||
| 575 | io_leave: | 584 | io_leave: |
| 576 | RESTORE_ALL __LC_RETURN_PSW,0 | 585 | RESTORE_ALL __LC_RETURN_PSW,0 |
| 577 | io_done: | 586 | io_done: |
| @@ -618,6 +627,7 @@ io_work_loop: | |||
| 618 | bo BASED(io_reschedule) | 627 | bo BASED(io_reschedule) |
| 619 | tm __TI_flags+3(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK) | 628 | tm __TI_flags+3(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK) |
| 620 | bnz BASED(io_sigpending) | 629 | bnz BASED(io_sigpending) |
| 630 | LOCKDEP_SYS_EXIT | ||
| 621 | b BASED(io_leave) | 631 | b BASED(io_leave) |
| 622 | 632 | ||
| 623 | # | 633 | # |
| @@ -1040,6 +1050,8 @@ cleanup_io_leave_insn: | |||
| 1040 | .Ltrace_irq_on: .long trace_hardirqs_on | 1050 | .Ltrace_irq_on: .long trace_hardirqs_on |
| 1041 | .Ltrace_irq_off: | 1051 | .Ltrace_irq_off: |
| 1042 | .long trace_hardirqs_off | 1052 | .long trace_hardirqs_off |
| 1053 | .Llockdep_sys_exit: | ||
| 1054 | .long lockdep_sys_exit | ||
| 1043 | #endif | 1055 | #endif |
| 1044 | .Lcritical_start: | 1056 | .Lcritical_start: |
| 1045 | .long __critical_start + 0x80000000 | 1057 | .long __critical_start + 0x80000000 |
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 9c0d5cc8269d..05e26d1fdf40 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
| @@ -66,9 +66,14 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \ | |||
| 66 | .macro TRACE_IRQS_OFF | 66 | .macro TRACE_IRQS_OFF |
| 67 | brasl %r14,trace_hardirqs_off | 67 | brasl %r14,trace_hardirqs_off |
| 68 | .endm | 68 | .endm |
| 69 | |||
| 70 | .macro LOCKDEP_SYS_EXIT | ||
| 71 | brasl %r14,lockdep_sys_exit | ||
| 72 | .endm | ||
| 69 | #else | 73 | #else |
| 70 | #define TRACE_IRQS_ON | 74 | #define TRACE_IRQS_ON |
| 71 | #define TRACE_IRQS_OFF | 75 | #define TRACE_IRQS_OFF |
| 76 | #define LOCKDEP_SYS_EXIT | ||
| 72 | #endif | 77 | #endif |
| 73 | 78 | ||
| 74 | .macro STORE_TIMER lc_offset | 79 | .macro STORE_TIMER lc_offset |
| @@ -255,6 +260,7 @@ sysc_return: | |||
| 255 | jno sysc_leave | 260 | jno sysc_leave |
| 256 | tm __TI_flags+7(%r9),_TIF_WORK_SVC | 261 | tm __TI_flags+7(%r9),_TIF_WORK_SVC |
| 257 | jnz sysc_work # there is work to do (signals etc.) | 262 | jnz sysc_work # there is work to do (signals etc.) |
| 263 | LOCKDEP_SYS_EXIT | ||
| 258 | sysc_leave: | 264 | sysc_leave: |
| 259 | RESTORE_ALL __LC_RETURN_PSW,1 | 265 | RESTORE_ALL __LC_RETURN_PSW,1 |
| 260 | 266 | ||
| @@ -278,6 +284,7 @@ sysc_work: | |||
| 278 | jo sysc_restart | 284 | jo sysc_restart |
| 279 | tm __TI_flags+7(%r9),_TIF_SINGLE_STEP | 285 | tm __TI_flags+7(%r9),_TIF_SINGLE_STEP |
| 280 | jo sysc_singlestep | 286 | jo sysc_singlestep |
| 287 | LOCKDEP_SYS_EXIT | ||
| 281 | j sysc_leave | 288 | j sysc_leave |
| 282 | 289 | ||
| 283 | # | 290 | # |
| @@ -558,6 +565,7 @@ io_return: | |||
| 558 | #endif | 565 | #endif |
| 559 | tm __TI_flags+7(%r9),_TIF_WORK_INT | 566 | tm __TI_flags+7(%r9),_TIF_WORK_INT |
| 560 | jnz io_work # there is work to do (signals etc.) | 567 | jnz io_work # there is work to do (signals etc.) |
| 568 | LOCKDEP_SYS_EXIT | ||
| 561 | io_leave: | 569 | io_leave: |
| 562 | RESTORE_ALL __LC_RETURN_PSW,0 | 570 | RESTORE_ALL __LC_RETURN_PSW,0 |
| 563 | io_done: | 571 | io_done: |
| @@ -605,6 +613,7 @@ io_work_loop: | |||
| 605 | jo io_reschedule | 613 | jo io_reschedule |
| 606 | tm __TI_flags+7(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK) | 614 | tm __TI_flags+7(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK) |
| 607 | jnz io_sigpending | 615 | jnz io_sigpending |
| 616 | LOCKDEP_SYS_EXIT | ||
| 608 | j io_leave | 617 | j io_leave |
| 609 | 618 | ||
| 610 | # | 619 | # |
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 290b7bc82da3..8099fea0a72f 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S | |||
| @@ -251,6 +251,7 @@ check_userspace: | |||
| 251 | jb resume_kernel # not returning to v8086 or userspace | 251 | jb resume_kernel # not returning to v8086 or userspace |
| 252 | 252 | ||
| 253 | ENTRY(resume_userspace) | 253 | ENTRY(resume_userspace) |
| 254 | LOCKDEP_SYS_EXIT | ||
| 254 | DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt | 255 | DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt |
| 255 | # setting need_resched or sigpending | 256 | # setting need_resched or sigpending |
| 256 | # between sampling and the iret | 257 | # between sampling and the iret |
| @@ -338,6 +339,7 @@ sysenter_past_esp: | |||
| 338 | jae syscall_badsys | 339 | jae syscall_badsys |
| 339 | call *sys_call_table(,%eax,4) | 340 | call *sys_call_table(,%eax,4) |
| 340 | movl %eax,PT_EAX(%esp) | 341 | movl %eax,PT_EAX(%esp) |
| 342 | LOCKDEP_SYS_EXIT | ||
| 341 | DISABLE_INTERRUPTS(CLBR_ANY) | 343 | DISABLE_INTERRUPTS(CLBR_ANY) |
| 342 | TRACE_IRQS_OFF | 344 | TRACE_IRQS_OFF |
| 343 | movl TI_flags(%ebp), %ecx | 345 | movl TI_flags(%ebp), %ecx |
| @@ -377,6 +379,7 @@ syscall_call: | |||
| 377 | call *sys_call_table(,%eax,4) | 379 | call *sys_call_table(,%eax,4) |
| 378 | movl %eax,PT_EAX(%esp) # store the return value | 380 | movl %eax,PT_EAX(%esp) # store the return value |
| 379 | syscall_exit: | 381 | syscall_exit: |
| 382 | LOCKDEP_SYS_EXIT | ||
| 380 | DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt | 383 | DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt |
| 381 | # setting need_resched or sigpending | 384 | # setting need_resched or sigpending |
| 382 | # between sampling and the iret | 385 | # between sampling and the iret |
| @@ -467,6 +470,7 @@ work_pending: | |||
| 467 | jz work_notifysig | 470 | jz work_notifysig |
| 468 | work_resched: | 471 | work_resched: |
| 469 | call schedule | 472 | call schedule |
| 473 | LOCKDEP_SYS_EXIT | ||
| 470 | DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt | 474 | DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt |
| 471 | # setting need_resched or sigpending | 475 | # setting need_resched or sigpending |
| 472 | # between sampling and the iret | 476 | # between sampling and the iret |
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 1d232e5f5658..f1cacd4897f7 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
| @@ -244,6 +244,7 @@ ret_from_sys_call: | |||
| 244 | movl $_TIF_ALLWORK_MASK,%edi | 244 | movl $_TIF_ALLWORK_MASK,%edi |
| 245 | /* edi: flagmask */ | 245 | /* edi: flagmask */ |
| 246 | sysret_check: | 246 | sysret_check: |
| 247 | LOCKDEP_SYS_EXIT | ||
| 247 | GET_THREAD_INFO(%rcx) | 248 | GET_THREAD_INFO(%rcx) |
| 248 | cli | 249 | cli |
| 249 | TRACE_IRQS_OFF | 250 | TRACE_IRQS_OFF |
| @@ -333,6 +334,7 @@ int_ret_from_sys_call: | |||
| 333 | movl $_TIF_ALLWORK_MASK,%edi | 334 | movl $_TIF_ALLWORK_MASK,%edi |
| 334 | /* edi: mask to check */ | 335 | /* edi: mask to check */ |
| 335 | int_with_check: | 336 | int_with_check: |
| 337 | LOCKDEP_SYS_EXIT_IRQ | ||
| 336 | GET_THREAD_INFO(%rcx) | 338 | GET_THREAD_INFO(%rcx) |
| 337 | movl threadinfo_flags(%rcx),%edx | 339 | movl threadinfo_flags(%rcx),%edx |
| 338 | andl %edi,%edx | 340 | andl %edi,%edx |
| @@ -544,11 +546,13 @@ exit_intr: | |||
| 544 | retint_with_reschedule: | 546 | retint_with_reschedule: |
| 545 | movl $_TIF_WORK_MASK,%edi | 547 | movl $_TIF_WORK_MASK,%edi |
| 546 | retint_check: | 548 | retint_check: |
| 549 | LOCKDEP_SYS_EXIT_IRQ | ||
| 547 | movl threadinfo_flags(%rcx),%edx | 550 | movl threadinfo_flags(%rcx),%edx |
| 548 | andl %edi,%edx | 551 | andl %edi,%edx |
| 549 | CFI_REMEMBER_STATE | 552 | CFI_REMEMBER_STATE |
| 550 | jnz retint_careful | 553 | jnz retint_careful |
| 551 | retint_swapgs: | 554 | |
| 555 | retint_swapgs: /* return to user-space */ | ||
| 552 | /* | 556 | /* |
| 553 | * The iretq could re-enable interrupts: | 557 | * The iretq could re-enable interrupts: |
| 554 | */ | 558 | */ |
| @@ -557,7 +561,7 @@ retint_swapgs: | |||
| 557 | swapgs | 561 | swapgs |
| 558 | jmp restore_args | 562 | jmp restore_args |
| 559 | 563 | ||
| 560 | retint_restore_args: | 564 | retint_restore_args: /* return to kernel space */ |
| 561 | cli | 565 | cli |
| 562 | /* | 566 | /* |
| 563 | * The iretq could re-enable interrupts: | 567 | * The iretq could re-enable interrupts: |
| @@ -866,26 +870,21 @@ error_sti: | |||
| 866 | movq ORIG_RAX(%rsp),%rsi /* get error code */ | 870 | movq ORIG_RAX(%rsp),%rsi /* get error code */ |
| 867 | movq $-1,ORIG_RAX(%rsp) | 871 | movq $-1,ORIG_RAX(%rsp) |
| 868 | call *%rax | 872 | call *%rax |
| 869 | /* ebx: no swapgs flag (1: don't need swapgs, 0: need it) */ | 873 | /* ebx: no swapgs flag (1: don't need swapgs, 0: need it) */ |
| 870 | error_exit: | 874 | error_exit: |
| 871 | movl %ebx,%eax | 875 | movl %ebx,%eax |
| 872 | RESTORE_REST | 876 | RESTORE_REST |
| 873 | cli | 877 | cli |
| 874 | TRACE_IRQS_OFF | 878 | TRACE_IRQS_OFF |
| 875 | GET_THREAD_INFO(%rcx) | 879 | GET_THREAD_INFO(%rcx) |
| 876 | testl %eax,%eax | 880 | testl %eax,%eax |
| 877 | jne retint_kernel | 881 | jne retint_kernel |
| 882 | LOCKDEP_SYS_EXIT_IRQ | ||
| 878 | movl threadinfo_flags(%rcx),%edx | 883 | movl threadinfo_flags(%rcx),%edx |
| 879 | movl $_TIF_WORK_MASK,%edi | 884 | movl $_TIF_WORK_MASK,%edi |
| 880 | andl %edi,%edx | 885 | andl %edi,%edx |
| 881 | jnz retint_careful | 886 | jnz retint_careful |
| 882 | /* | 887 | jmp retint_swapgs |
| 883 | * The iret might restore flags: | ||
| 884 | */ | ||
| 885 | TRACE_IRQS_IRETQ | ||
| 886 | swapgs | ||
| 887 | RESTORE_ARGS 0,8,0 | ||
| 888 | jmp iret_label | ||
| 889 | CFI_ENDPROC | 888 | CFI_ENDPROC |
| 890 | 889 | ||
| 891 | error_kernelspace: | 890 | error_kernelspace: |
diff --git a/arch/x86/kernel/kprobes_32.c b/arch/x86/kernel/kprobes_32.c index c2d03e96ae9f..e7d0d3c2ef64 100644 --- a/arch/x86/kernel/kprobes_32.c +++ b/arch/x86/kernel/kprobes_32.c | |||
| @@ -557,6 +557,12 @@ static int __kprobes post_kprobe_handler(struct pt_regs *regs) | |||
| 557 | 557 | ||
| 558 | resume_execution(cur, regs, kcb); | 558 | resume_execution(cur, regs, kcb); |
| 559 | regs->eflags |= kcb->kprobe_saved_eflags; | 559 | regs->eflags |= kcb->kprobe_saved_eflags; |
| 560 | #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT | ||
| 561 | if (raw_irqs_disabled_flags(regs->eflags)) | ||
| 562 | trace_hardirqs_off(); | ||
| 563 | else | ||
| 564 | trace_hardirqs_on(); | ||
| 565 | #endif | ||
| 560 | 566 | ||
| 561 | /*Restore back the original saved kprobes variables and continue. */ | 567 | /*Restore back the original saved kprobes variables and continue. */ |
| 562 | if (kcb->kprobe_status == KPROBE_REENTER) { | 568 | if (kcb->kprobe_status == KPROBE_REENTER) { |
| @@ -694,6 +700,7 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | |||
| 694 | memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr, | 700 | memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr, |
| 695 | MIN_STACK_SIZE(addr)); | 701 | MIN_STACK_SIZE(addr)); |
| 696 | regs->eflags &= ~IF_MASK; | 702 | regs->eflags &= ~IF_MASK; |
| 703 | trace_hardirqs_off(); | ||
| 697 | regs->eip = (unsigned long)(jp->entry); | 704 | regs->eip = (unsigned long)(jp->entry); |
| 698 | return 1; | 705 | return 1; |
| 699 | } | 706 | } |
diff --git a/arch/x86/kernel/kprobes_64.c b/arch/x86/kernel/kprobes_64.c index 1df17a0ec0c9..62e28e52d784 100644 --- a/arch/x86/kernel/kprobes_64.c +++ b/arch/x86/kernel/kprobes_64.c | |||
| @@ -544,6 +544,12 @@ int __kprobes post_kprobe_handler(struct pt_regs *regs) | |||
| 544 | 544 | ||
| 545 | resume_execution(cur, regs, kcb); | 545 | resume_execution(cur, regs, kcb); |
| 546 | regs->eflags |= kcb->kprobe_saved_rflags; | 546 | regs->eflags |= kcb->kprobe_saved_rflags; |
| 547 | #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT | ||
| 548 | if (raw_irqs_disabled_flags(regs->eflags)) | ||
| 549 | trace_hardirqs_off(); | ||
| 550 | else | ||
| 551 | trace_hardirqs_on(); | ||
| 552 | #endif | ||
| 547 | 553 | ||
| 548 | /* Restore the original saved kprobes variables and continue. */ | 554 | /* Restore the original saved kprobes variables and continue. */ |
| 549 | if (kcb->kprobe_status == KPROBE_REENTER) { | 555 | if (kcb->kprobe_status == KPROBE_REENTER) { |
| @@ -684,6 +690,7 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | |||
| 684 | memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr, | 690 | memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr, |
| 685 | MIN_STACK_SIZE(addr)); | 691 | MIN_STACK_SIZE(addr)); |
| 686 | regs->eflags &= ~IF_MASK; | 692 | regs->eflags &= ~IF_MASK; |
| 693 | trace_hardirqs_off(); | ||
| 687 | regs->rip = (unsigned long)(jp->entry); | 694 | regs->rip = (unsigned long)(jp->entry); |
| 688 | return 1; | 695 | return 1; |
| 689 | } | 696 | } |
diff --git a/arch/x86/lib/thunk_64.S b/arch/x86/lib/thunk_64.S index 55e586d352d3..6ea73f3de567 100644 --- a/arch/x86/lib/thunk_64.S +++ b/arch/x86/lib/thunk_64.S | |||
| @@ -50,6 +50,10 @@ | |||
| 50 | thunk trace_hardirqs_on_thunk,trace_hardirqs_on | 50 | thunk trace_hardirqs_on_thunk,trace_hardirqs_on |
| 51 | thunk trace_hardirqs_off_thunk,trace_hardirqs_off | 51 | thunk trace_hardirqs_off_thunk,trace_hardirqs_off |
| 52 | #endif | 52 | #endif |
| 53 | |||
| 54 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
| 55 | thunk lockdep_sys_exit_thunk,lockdep_sys_exit | ||
| 56 | #endif | ||
| 53 | 57 | ||
| 54 | /* SAVE_ARGS below is used only for the .cfi directives it contains. */ | 58 | /* SAVE_ARGS below is used only for the .cfi directives it contains. */ |
| 55 | CFI_STARTPROC | 59 | CFI_STARTPROC |
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 4672066167e3..33f5eb038773 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig | |||
| @@ -272,6 +272,15 @@ config PATA_CS5535 | |||
| 272 | 272 | ||
| 273 | If unsure, say N. | 273 | If unsure, say N. |
| 274 | 274 | ||
| 275 | config PATA_CS5536 | ||
| 276 | tristate "CS5536 PATA support (Experimental)" | ||
| 277 | depends on PCI && X86 && !X86_64 && EXPERIMENTAL | ||
| 278 | help | ||
| 279 | This option enables support for the AMD CS5536 | ||
| 280 | companion chip used with the Geode LX processor family. | ||
| 281 | |||
| 282 | If unsure, say N. | ||
| 283 | |||
| 275 | config PATA_CYPRESS | 284 | config PATA_CYPRESS |
| 276 | tristate "Cypress CY82C693 PATA support (Very Experimental)" | 285 | tristate "Cypress CY82C693 PATA support (Very Experimental)" |
| 277 | depends on PCI && EXPERIMENTAL | 286 | depends on PCI && EXPERIMENTAL |
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index 2a63645003eb..6bdc307649e6 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile | |||
| @@ -28,6 +28,7 @@ obj-$(CONFIG_PATA_CMD64X) += pata_cmd64x.o | |||
| 28 | obj-$(CONFIG_PATA_CS5520) += pata_cs5520.o | 28 | obj-$(CONFIG_PATA_CS5520) += pata_cs5520.o |
| 29 | obj-$(CONFIG_PATA_CS5530) += pata_cs5530.o | 29 | obj-$(CONFIG_PATA_CS5530) += pata_cs5530.o |
| 30 | obj-$(CONFIG_PATA_CS5535) += pata_cs5535.o | 30 | obj-$(CONFIG_PATA_CS5535) += pata_cs5535.o |
| 31 | obj-$(CONFIG_PATA_CS5536) += pata_cs5536.o | ||
| 31 | obj-$(CONFIG_PATA_CYPRESS) += pata_cypress.o | 32 | obj-$(CONFIG_PATA_CYPRESS) += pata_cypress.o |
| 32 | obj-$(CONFIG_PATA_EFAR) += pata_efar.o | 33 | obj-$(CONFIG_PATA_EFAR) += pata_efar.o |
| 33 | obj-$(CONFIG_PATA_HPT366) += pata_hpt366.o | 34 | obj-$(CONFIG_PATA_HPT366) += pata_hpt366.o |
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 9ce4aa9c2f25..3c6f43e381f4 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c | |||
| @@ -130,6 +130,7 @@ enum { | |||
| 130 | ich8_sata_ahci = 9, | 130 | ich8_sata_ahci = 9, |
| 131 | piix_pata_mwdma = 10, /* PIIX3 MWDMA only */ | 131 | piix_pata_mwdma = 10, /* PIIX3 MWDMA only */ |
| 132 | tolapai_sata_ahci = 11, | 132 | tolapai_sata_ahci = 11, |
| 133 | ich9_2port_sata = 12, | ||
| 133 | 134 | ||
| 134 | /* constants for mapping table */ | 135 | /* constants for mapping table */ |
| 135 | P0 = 0, /* port 0 */ | 136 | P0 = 0, /* port 0 */ |
| @@ -238,19 +239,19 @@ static const struct pci_device_id piix_pci_tbl[] = { | |||
| 238 | /* SATA Controller 1 IDE (ICH8) */ | 239 | /* SATA Controller 1 IDE (ICH8) */ |
| 239 | { 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, | 240 | { 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, |
| 240 | /* SATA Controller 2 IDE (ICH8) */ | 241 | /* SATA Controller 2 IDE (ICH8) */ |
| 241 | { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, | 242 | { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata }, |
| 242 | /* Mobile SATA Controller IDE (ICH8M) */ | 243 | /* Mobile SATA Controller IDE (ICH8M) */ |
| 243 | { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, | 244 | { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, |
| 244 | /* SATA Controller IDE (ICH9) */ | 245 | /* SATA Controller IDE (ICH9) */ |
| 245 | { 0x8086, 0x2920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, | 246 | { 0x8086, 0x2920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, |
| 246 | /* SATA Controller IDE (ICH9) */ | 247 | /* SATA Controller IDE (ICH9) */ |
| 247 | { 0x8086, 0x2921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, | 248 | { 0x8086, 0x2921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata }, |
| 248 | /* SATA Controller IDE (ICH9) */ | 249 | /* SATA Controller IDE (ICH9) */ |
| 249 | { 0x8086, 0x2926, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, | 250 | { 0x8086, 0x2926, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata }, |
| 250 | /* SATA Controller IDE (ICH9M) */ | 251 | /* SATA Controller IDE (ICH9M) */ |
| 251 | { 0x8086, 0x2928, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, | 252 | { 0x8086, 0x2928, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata }, |
| 252 | /* SATA Controller IDE (ICH9M) */ | 253 | /* SATA Controller IDE (ICH9M) */ |
| 253 | { 0x8086, 0x292d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, | 254 | { 0x8086, 0x292d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata }, |
| 254 | /* SATA Controller IDE (ICH9M) */ | 255 | /* SATA Controller IDE (ICH9M) */ |
| 255 | { 0x8086, 0x292e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, | 256 | { 0x8086, 0x292e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, |
| 256 | /* SATA Controller IDE (Tolapai) */ | 257 | /* SATA Controller IDE (Tolapai) */ |
| @@ -448,6 +449,18 @@ static const struct piix_map_db tolapai_map_db = { | |||
| 448 | }, | 449 | }, |
| 449 | }; | 450 | }; |
| 450 | 451 | ||
| 452 | static const struct piix_map_db ich9_2port_map_db = { | ||
| 453 | .mask = 0x3, | ||
| 454 | .port_enable = 0x3, | ||
| 455 | .map = { | ||
| 456 | /* PM PS SM SS MAP */ | ||
| 457 | { P0, NA, P1, NA }, /* 00b */ | ||
| 458 | { RV, RV, RV, RV }, /* 01b */ | ||
| 459 | { RV, RV, RV, RV }, /* 10b */ | ||
| 460 | { RV, RV, RV, RV }, | ||
| 461 | }, | ||
| 462 | }; | ||
| 463 | |||
| 451 | static const struct piix_map_db *piix_map_db_table[] = { | 464 | static const struct piix_map_db *piix_map_db_table[] = { |
| 452 | [ich5_sata] = &ich5_map_db, | 465 | [ich5_sata] = &ich5_map_db, |
| 453 | [ich6_sata] = &ich6_map_db, | 466 | [ich6_sata] = &ich6_map_db, |
| @@ -455,6 +468,7 @@ static const struct piix_map_db *piix_map_db_table[] = { | |||
| 455 | [ich6m_sata_ahci] = &ich6m_map_db, | 468 | [ich6m_sata_ahci] = &ich6m_map_db, |
| 456 | [ich8_sata_ahci] = &ich8_map_db, | 469 | [ich8_sata_ahci] = &ich8_map_db, |
| 457 | [tolapai_sata_ahci] = &tolapai_map_db, | 470 | [tolapai_sata_ahci] = &tolapai_map_db, |
| 471 | [ich9_2port_sata] = &ich9_2port_map_db, | ||
| 458 | }; | 472 | }; |
| 459 | 473 | ||
| 460 | static struct ata_port_info piix_port_info[] = { | 474 | static struct ata_port_info piix_port_info[] = { |
| @@ -570,6 +584,17 @@ static struct ata_port_info piix_port_info[] = { | |||
| 570 | .udma_mask = ATA_UDMA6, | 584 | .udma_mask = ATA_UDMA6, |
| 571 | .port_ops = &piix_sata_ops, | 585 | .port_ops = &piix_sata_ops, |
| 572 | }, | 586 | }, |
| 587 | |||
| 588 | [ich9_2port_sata] = | ||
| 589 | { | ||
| 590 | .sht = &piix_sht, | ||
| 591 | .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR | | ||
| 592 | PIIX_FLAG_AHCI, | ||
| 593 | .pio_mask = 0x1f, /* pio0-4 */ | ||
| 594 | .mwdma_mask = 0x07, /* mwdma0-2 */ | ||
| 595 | .udma_mask = ATA_UDMA6, | ||
| 596 | .port_ops = &piix_sata_ops, | ||
| 597 | }, | ||
| 573 | }; | 598 | }; |
| 574 | 599 | ||
| 575 | static struct pci_bits piix_enable_bits[] = { | 600 | static struct pci_bits piix_enable_bits[] = { |
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index b05384a8c326..68699b3e7998 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
| @@ -3984,6 +3984,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { | |||
| 3984 | { "ST9120822AS", "3.CLF", ATA_HORKAGE_NONCQ, }, | 3984 | { "ST9120822AS", "3.CLF", ATA_HORKAGE_NONCQ, }, |
| 3985 | { "ST9160821AS", "3.CLF", ATA_HORKAGE_NONCQ, }, | 3985 | { "ST9160821AS", "3.CLF", ATA_HORKAGE_NONCQ, }, |
| 3986 | { "ST9160821AS", "3.ALD", ATA_HORKAGE_NONCQ, }, | 3986 | { "ST9160821AS", "3.ALD", ATA_HORKAGE_NONCQ, }, |
| 3987 | { "ST9160821AS", "3.CCD", ATA_HORKAGE_NONCQ, }, | ||
| 3987 | { "ST3160812AS", "3.ADJ", ATA_HORKAGE_NONCQ, }, | 3988 | { "ST3160812AS", "3.ADJ", ATA_HORKAGE_NONCQ, }, |
| 3988 | { "ST980813AS", "3.ADB", ATA_HORKAGE_NONCQ, }, | 3989 | { "ST980813AS", "3.ADB", ATA_HORKAGE_NONCQ, }, |
| 3989 | { "SAMSUNG HD401LJ", "ZZ100-15", ATA_HORKAGE_NONCQ, }, | 3990 | { "SAMSUNG HD401LJ", "ZZ100-15", ATA_HORKAGE_NONCQ, }, |
| @@ -4013,8 +4014,14 @@ int strn_pattern_cmp(const char *patt, const char *name, int wildchar) | |||
| 4013 | p = strchr(patt, wildchar); | 4014 | p = strchr(patt, wildchar); |
| 4014 | if (p && ((*(p + 1)) == 0)) | 4015 | if (p && ((*(p + 1)) == 0)) |
| 4015 | len = p - patt; | 4016 | len = p - patt; |
| 4016 | else | 4017 | else { |
| 4017 | len = strlen(name); | 4018 | len = strlen(name); |
| 4019 | if (!len) { | ||
| 4020 | if (!*patt) | ||
| 4021 | return 0; | ||
| 4022 | return -1; | ||
| 4023 | } | ||
| 4024 | } | ||
| 4018 | 4025 | ||
| 4019 | return strncmp(patt, name, len); | 4026 | return strncmp(patt, name, len); |
| 4020 | } | 4027 | } |
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index ea53e6a570b4..d63c81ed084f 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c | |||
| @@ -1363,6 +1363,7 @@ nothing_to_do: | |||
| 1363 | static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) | 1363 | static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) |
| 1364 | { | 1364 | { |
| 1365 | struct ata_port *ap = qc->ap; | 1365 | struct ata_port *ap = qc->ap; |
| 1366 | struct ata_eh_info *ehi = &qc->dev->link->eh_info; | ||
| 1366 | struct scsi_cmnd *cmd = qc->scsicmd; | 1367 | struct scsi_cmnd *cmd = qc->scsicmd; |
| 1367 | u8 *cdb = cmd->cmnd; | 1368 | u8 *cdb = cmd->cmnd; |
| 1368 | int need_sense = (qc->err_mask != 0); | 1369 | int need_sense = (qc->err_mask != 0); |
| @@ -1376,14 +1377,14 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) | |||
| 1376 | case ATA_CMD_SET_FEATURES: | 1377 | case ATA_CMD_SET_FEATURES: |
| 1377 | if ((qc->tf.feature == SETFEATURES_WC_ON) || | 1378 | if ((qc->tf.feature == SETFEATURES_WC_ON) || |
| 1378 | (qc->tf.feature == SETFEATURES_WC_OFF)) { | 1379 | (qc->tf.feature == SETFEATURES_WC_OFF)) { |
| 1379 | ap->link.eh_info.action |= ATA_EH_REVALIDATE; | 1380 | ehi->action |= ATA_EH_REVALIDATE; |
| 1380 | ata_port_schedule_eh(ap); | 1381 | ata_port_schedule_eh(ap); |
| 1381 | } | 1382 | } |
| 1382 | break; | 1383 | break; |
| 1383 | 1384 | ||
| 1384 | case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */ | 1385 | case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */ |
| 1385 | case ATA_CMD_SET_MULTI: /* multi_count changed */ | 1386 | case ATA_CMD_SET_MULTI: /* multi_count changed */ |
| 1386 | ap->link.eh_info.action |= ATA_EH_REVALIDATE; | 1387 | ehi->action |= ATA_EH_REVALIDATE; |
| 1387 | ata_port_schedule_eh(ap); | 1388 | ata_port_schedule_eh(ap); |
| 1388 | break; | 1389 | break; |
| 1389 | } | 1390 | } |
diff --git a/drivers/ata/pata_cs5536.c b/drivers/ata/pata_cs5536.c new file mode 100644 index 000000000000..53070f6b1fc4 --- /dev/null +++ b/drivers/ata/pata_cs5536.c | |||
| @@ -0,0 +1,344 @@ | |||
| 1 | /* | ||
| 2 | * pata_cs5536.c - CS5536 PATA for new ATA layer | ||
| 3 | * (C) 2007 Martin K. Petersen <mkp@mkp.net> | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License version 2 as | ||
| 7 | * published by the Free Software Foundation. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License | ||
| 15 | * along with this program; if not, write to the Free Software | ||
| 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 17 | * | ||
| 18 | * Documentation: | ||
| 19 | * Available from AMD web site. | ||
| 20 | * | ||
| 21 | * The IDE timing registers for the CS5536 live in the Geode Machine | ||
| 22 | * Specific Register file and not PCI config space. Most BIOSes | ||
| 23 | * virtualize the PCI registers so the chip looks like a standard IDE | ||
| 24 | * controller. Unfortunately not all implementations get this right. | ||
| 25 | * In particular some have problems with unaligned accesses to the | ||
| 26 | * virtualized PCI registers. This driver always does full dword | ||
| 27 | * writes to work around the issue. Also, in case of a bad BIOS this | ||
| 28 | * driver can be loaded with the "msr=1" parameter which forces using | ||
| 29 | * the Machine Specific Registers to configure the device. | ||
| 30 | */ | ||
| 31 | |||
| 32 | #include <linux/kernel.h> | ||
| 33 | #include <linux/module.h> | ||
| 34 | #include <linux/pci.h> | ||
| 35 | #include <linux/init.h> | ||
| 36 | #include <linux/blkdev.h> | ||
| 37 | #include <linux/delay.h> | ||
| 38 | #include <linux/libata.h> | ||
| 39 | #include <scsi/scsi_host.h> | ||
| 40 | #include <asm/msr.h> | ||
| 41 | |||
| 42 | #define DRV_NAME "pata_cs5536" | ||
| 43 | #define DRV_VERSION "0.0.5" | ||
| 44 | |||
| 45 | enum { | ||
| 46 | CFG = 0, | ||
| 47 | DTC = 1, | ||
| 48 | CAST = 2, | ||
| 49 | ETC = 3, | ||
| 50 | |||
| 51 | MSR_IDE_BASE = 0x51300000, | ||
| 52 | MSR_IDE_CFG = (MSR_IDE_BASE + 0x10), | ||
| 53 | MSR_IDE_DTC = (MSR_IDE_BASE + 0x12), | ||
| 54 | MSR_IDE_CAST = (MSR_IDE_BASE + 0x13), | ||
| 55 | MSR_IDE_ETC = (MSR_IDE_BASE + 0x14), | ||
| 56 | |||
| 57 | PCI_IDE_CFG = 0x40, | ||
| 58 | PCI_IDE_DTC = 0x48, | ||
| 59 | PCI_IDE_CAST = 0x4c, | ||
| 60 | PCI_IDE_ETC = 0x50, | ||
| 61 | |||
| 62 | IDE_CFG_CHANEN = 0x2, | ||
| 63 | IDE_CFG_CABLE = 0x10000, | ||
| 64 | |||
| 65 | IDE_D0_SHIFT = 24, | ||
| 66 | IDE_D1_SHIFT = 16, | ||
| 67 | IDE_DRV_MASK = 0xff, | ||
| 68 | |||
| 69 | IDE_CAST_D0_SHIFT = 6, | ||
| 70 | IDE_CAST_D1_SHIFT = 4, | ||
| 71 | IDE_CAST_DRV_MASK = 0x3, | ||
| 72 | IDE_CAST_CMD_MASK = 0xff, | ||
| 73 | IDE_CAST_CMD_SHIFT = 24, | ||
| 74 | |||
| 75 | IDE_ETC_NODMA = 0x03, | ||
| 76 | }; | ||
| 77 | |||
| 78 | static int use_msr; | ||
| 79 | |||
| 80 | static const u32 msr_reg[4] = { | ||
| 81 | MSR_IDE_CFG, MSR_IDE_DTC, MSR_IDE_CAST, MSR_IDE_ETC, | ||
| 82 | }; | ||
| 83 | |||
| 84 | static const u8 pci_reg[4] = { | ||
| 85 | PCI_IDE_CFG, PCI_IDE_DTC, PCI_IDE_CAST, PCI_IDE_ETC, | ||
| 86 | }; | ||
| 87 | |||
| 88 | static inline int cs5536_read(struct pci_dev *pdev, int reg, int *val) | ||
| 89 | { | ||
| 90 | if (unlikely(use_msr)) { | ||
| 91 | u32 dummy; | ||
| 92 | |||
| 93 | rdmsr(msr_reg[reg], *val, dummy); | ||
| 94 | return 0; | ||
| 95 | } | ||
| 96 | |||
| 97 | return pci_read_config_dword(pdev, pci_reg[reg], val); | ||
| 98 | } | ||
| 99 | |||
| 100 | static inline int cs5536_write(struct pci_dev *pdev, int reg, int val) | ||
| 101 | { | ||
| 102 | if (unlikely(use_msr)) { | ||
| 103 | wrmsr(msr_reg[reg], val, 0); | ||
| 104 | return 0; | ||
| 105 | } | ||
| 106 | |||
| 107 | return pci_write_config_dword(pdev, pci_reg[reg], val); | ||
| 108 | } | ||
| 109 | |||
| 110 | /** | ||
| 111 | * cs5536_cable_detect - detect cable type | ||
| 112 | * @ap: Port to detect on | ||
| 113 | * @deadline: deadline jiffies for the operation | ||
| 114 | * | ||
| 115 | * Perform cable detection for ATA66 capable cable. Return a libata | ||
| 116 | * cable type. | ||
| 117 | */ | ||
| 118 | |||
| 119 | static int cs5536_cable_detect(struct ata_port *ap) | ||
| 120 | { | ||
| 121 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | ||
| 122 | u32 cfg; | ||
| 123 | |||
| 124 | cs5536_read(pdev, CFG, &cfg); | ||
| 125 | |||
| 126 | if (cfg & (IDE_CFG_CABLE << ap->port_no)) | ||
| 127 | return ATA_CBL_PATA80; | ||
| 128 | else | ||
| 129 | return ATA_CBL_PATA40; | ||
| 130 | } | ||
| 131 | |||
| 132 | /** | ||
| 133 | * cs5536_set_piomode - PIO setup | ||
| 134 | * @ap: ATA interface | ||
| 135 | * @adev: device on the interface | ||
| 136 | */ | ||
| 137 | |||
| 138 | static void cs5536_set_piomode(struct ata_port *ap, struct ata_device *adev) | ||
| 139 | { | ||
| 140 | static const u8 drv_timings[5] = { | ||
| 141 | 0x98, 0x55, 0x32, 0x21, 0x20, | ||
| 142 | }; | ||
| 143 | |||
| 144 | static const u8 addr_timings[5] = { | ||
| 145 | 0x2, 0x1, 0x0, 0x0, 0x0, | ||
| 146 | }; | ||
| 147 | |||
| 148 | static const u8 cmd_timings[5] = { | ||
| 149 | 0x99, 0x92, 0x90, 0x22, 0x20, | ||
| 150 | }; | ||
| 151 | |||
| 152 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | ||
| 153 | struct ata_device *pair = ata_dev_pair(adev); | ||
| 154 | int mode = adev->pio_mode - XFER_PIO_0; | ||
| 155 | int cmdmode = mode; | ||
| 156 | int dshift = ap->port_no ? IDE_D1_SHIFT : IDE_D0_SHIFT; | ||
| 157 | int cshift = ap->port_no ? IDE_CAST_D1_SHIFT : IDE_CAST_D0_SHIFT; | ||
| 158 | u32 dtc, cast, etc; | ||
| 159 | |||
| 160 | if (pair) | ||
| 161 | cmdmode = min(mode, pair->pio_mode - XFER_PIO_0); | ||
| 162 | |||
| 163 | cs5536_read(pdev, DTC, &dtc); | ||
| 164 | cs5536_read(pdev, CAST, &cast); | ||
| 165 | cs5536_read(pdev, ETC, &etc); | ||
| 166 | |||
| 167 | dtc &= ~(IDE_DRV_MASK << dshift); | ||
| 168 | dtc |= drv_timings[mode] << dshift; | ||
| 169 | |||
| 170 | cast &= ~(IDE_CAST_DRV_MASK << cshift); | ||
| 171 | cast |= addr_timings[mode] << cshift; | ||
| 172 | |||
| 173 | cast &= ~(IDE_CAST_CMD_MASK << IDE_CAST_CMD_SHIFT); | ||
| 174 | cast |= cmd_timings[cmdmode] << IDE_CAST_CMD_SHIFT; | ||
| 175 | |||
| 176 | etc &= ~(IDE_DRV_MASK << dshift); | ||
| 177 | etc |= IDE_ETC_NODMA << dshift; | ||
| 178 | |||
| 179 | cs5536_write(pdev, DTC, dtc); | ||
| 180 | cs5536_write(pdev, CAST, cast); | ||
| 181 | cs5536_write(pdev, ETC, etc); | ||
| 182 | } | ||
| 183 | |||
| 184 | /** | ||
| 185 | * cs5536_set_dmamode - DMA timing setup | ||
| 186 | * @ap: ATA interface | ||
| 187 | * @adev: Device being configured | ||
| 188 | * | ||
| 189 | */ | ||
| 190 | |||
| 191 | static void cs5536_set_dmamode(struct ata_port *ap, struct ata_device *adev) | ||
| 192 | { | ||
| 193 | static const u8 udma_timings[6] = { | ||
| 194 | 0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6, | ||
| 195 | }; | ||
| 196 | |||
| 197 | static const u8 mwdma_timings[3] = { | ||
| 198 | 0x67, 0x21, 0x20, | ||
| 199 | }; | ||
| 200 | |||
| 201 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | ||
| 202 | u32 dtc, etc; | ||
| 203 | int mode = adev->dma_mode; | ||
| 204 | int dshift = ap->port_no ? IDE_D1_SHIFT : IDE_D0_SHIFT; | ||
| 205 | |||
| 206 | if (mode >= XFER_UDMA_0) { | ||
| 207 | cs5536_read(pdev, ETC, &etc); | ||
| 208 | |||
| 209 | etc &= ~(IDE_DRV_MASK << dshift); | ||
| 210 | etc |= udma_timings[mode - XFER_UDMA_0] << dshift; | ||
| 211 | |||
| 212 | cs5536_write(pdev, ETC, etc); | ||
| 213 | } else { /* MWDMA */ | ||
| 214 | cs5536_read(pdev, DTC, &dtc); | ||
| 215 | |||
| 216 | dtc &= ~(IDE_DRV_MASK << dshift); | ||
| 217 | dtc |= mwdma_timings[mode] << dshift; | ||
| 218 | |||
| 219 | cs5536_write(pdev, DTC, dtc); | ||
| 220 | } | ||
| 221 | } | ||
| 222 | |||
| 223 | static struct scsi_host_template cs5536_sht = { | ||
| 224 | .module = THIS_MODULE, | ||
| 225 | .name = DRV_NAME, | ||
| 226 | .ioctl = ata_scsi_ioctl, | ||
| 227 | .queuecommand = ata_scsi_queuecmd, | ||
| 228 | .can_queue = ATA_DEF_QUEUE, | ||
| 229 | .this_id = ATA_SHT_THIS_ID, | ||
| 230 | .sg_tablesize = LIBATA_MAX_PRD, | ||
| 231 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | ||
| 232 | .emulated = ATA_SHT_EMULATED, | ||
| 233 | .use_clustering = ATA_SHT_USE_CLUSTERING, | ||
| 234 | .proc_name = DRV_NAME, | ||
| 235 | .dma_boundary = ATA_DMA_BOUNDARY, | ||
| 236 | .slave_configure = ata_scsi_slave_config, | ||
| 237 | .slave_destroy = ata_scsi_slave_destroy, | ||
| 238 | .bios_param = ata_std_bios_param, | ||
| 239 | }; | ||
| 240 | |||
| 241 | static struct ata_port_operations cs5536_port_ops = { | ||
| 242 | .set_piomode = cs5536_set_piomode, | ||
| 243 | .set_dmamode = cs5536_set_dmamode, | ||
| 244 | .mode_filter = ata_pci_default_filter, | ||
| 245 | |||
| 246 | .tf_load = ata_tf_load, | ||
| 247 | .tf_read = ata_tf_read, | ||
| 248 | .check_status = ata_check_status, | ||
| 249 | .exec_command = ata_exec_command, | ||
| 250 | .dev_select = ata_std_dev_select, | ||
| 251 | |||
| 252 | .freeze = ata_bmdma_freeze, | ||
| 253 | .thaw = ata_bmdma_thaw, | ||
| 254 | .error_handler = ata_bmdma_error_handler, | ||
| 255 | .post_internal_cmd = ata_bmdma_post_internal_cmd, | ||
| 256 | .cable_detect = cs5536_cable_detect, | ||
| 257 | |||
| 258 | .bmdma_setup = ata_bmdma_setup, | ||
| 259 | .bmdma_start = ata_bmdma_start, | ||
| 260 | .bmdma_stop = ata_bmdma_stop, | ||
| 261 | .bmdma_status = ata_bmdma_status, | ||
| 262 | |||
| 263 | .qc_prep = ata_qc_prep, | ||
| 264 | .qc_issue = ata_qc_issue_prot, | ||
| 265 | |||
| 266 | .data_xfer = ata_data_xfer, | ||
| 267 | |||
| 268 | .irq_handler = ata_interrupt, | ||
| 269 | .irq_clear = ata_bmdma_irq_clear, | ||
| 270 | .irq_on = ata_irq_on, | ||
| 271 | |||
| 272 | .port_start = ata_port_start, | ||
| 273 | }; | ||
| 274 | |||
| 275 | /** | ||
| 276 | * cs5536_init_one | ||
| 277 | * @dev: PCI device | ||
| 278 | * @id: Entry in match table | ||
| 279 | * | ||
| 280 | */ | ||
| 281 | |||
| 282 | static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id) | ||
| 283 | { | ||
| 284 | static const struct ata_port_info info = { | ||
| 285 | .sht = &cs5536_sht, | ||
| 286 | .flags = ATA_FLAG_SLAVE_POSS, | ||
| 287 | .pio_mask = 0x1f, | ||
| 288 | .mwdma_mask = 0x07, | ||
| 289 | .udma_mask = ATA_UDMA5, | ||
| 290 | .port_ops = &cs5536_port_ops, | ||
| 291 | }; | ||
| 292 | |||
| 293 | const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info }; | ||
| 294 | u32 cfg; | ||
| 295 | |||
| 296 | if (use_msr) | ||
| 297 | printk(KERN_ERR DRV_NAME ": Using MSR regs instead of PCI\n"); | ||
| 298 | |||
| 299 | cs5536_read(dev, CFG, &cfg); | ||
| 300 | |||
| 301 | if ((cfg & IDE_CFG_CHANEN) == 0) { | ||
| 302 | printk(KERN_ERR DRV_NAME ": disabled by BIOS\n"); | ||
| 303 | return -ENODEV; | ||
| 304 | } | ||
| 305 | |||
| 306 | return ata_pci_init_one(dev, ppi); | ||
| 307 | } | ||
| 308 | |||
| 309 | static const struct pci_device_id cs5536[] = { | ||
| 310 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CS5536_IDE), }, | ||
| 311 | { }, | ||
| 312 | }; | ||
| 313 | |||
| 314 | static struct pci_driver cs5536_pci_driver = { | ||
| 315 | .name = DRV_NAME, | ||
| 316 | .id_table = cs5536, | ||
| 317 | .probe = cs5536_init_one, | ||
| 318 | .remove = ata_pci_remove_one, | ||
| 319 | #ifdef CONFIG_PM | ||
| 320 | .suspend = ata_pci_device_suspend, | ||
| 321 | .resume = ata_pci_device_resume, | ||
| 322 | #endif | ||
| 323 | }; | ||
| 324 | |||
| 325 | static int __init cs5536_init(void) | ||
| 326 | { | ||
| 327 | return pci_register_driver(&cs5536_pci_driver); | ||
| 328 | } | ||
| 329 | |||
| 330 | static void __exit cs5536_exit(void) | ||
| 331 | { | ||
| 332 | pci_unregister_driver(&cs5536_pci_driver); | ||
| 333 | } | ||
| 334 | |||
| 335 | MODULE_AUTHOR("Martin K. Petersen"); | ||
| 336 | MODULE_DESCRIPTION("low-level driver for the CS5536 IDE controller"); | ||
| 337 | MODULE_LICENSE("GPL"); | ||
| 338 | MODULE_DEVICE_TABLE(pci, cs5536); | ||
| 339 | MODULE_VERSION(DRV_VERSION); | ||
| 340 | module_param_named(msr, use_msr, int, 0644); | ||
| 341 | MODULE_PARM_DESC(msr, "Force using MSR to configure IDE function (Default: 0)"); | ||
| 342 | |||
| 343 | module_init(cs5536_init); | ||
| 344 | module_exit(cs5536_exit); | ||
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index 782ff4ada9d1..5db2013230b3 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c | |||
| @@ -353,6 +353,7 @@ static void pcmcia_remove_one(struct pcmcia_device *pdev) | |||
| 353 | 353 | ||
| 354 | static struct pcmcia_device_id pcmcia_devices[] = { | 354 | static struct pcmcia_device_id pcmcia_devices[] = { |
| 355 | PCMCIA_DEVICE_FUNC_ID(4), | 355 | PCMCIA_DEVICE_FUNC_ID(4), |
| 356 | PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000), /* Corsair */ | ||
| 356 | PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000), /* Hitachi */ | 357 | PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000), /* Hitachi */ |
| 357 | PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000), /* I-O Data CFA */ | 358 | PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000), /* I-O Data CFA */ |
| 358 | PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001), /* Mitsubishi CFA */ | 359 | PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001), /* Mitsubishi CFA */ |
| @@ -378,6 +379,7 @@ static struct pcmcia_device_id pcmcia_devices[] = { | |||
| 378 | PCMCIA_DEVICE_PROD_ID12("EXP ", "CD-ROM", 0x0a5c52fd, 0x66536591), | 379 | PCMCIA_DEVICE_PROD_ID12("EXP ", "CD-ROM", 0x0a5c52fd, 0x66536591), |
| 379 | PCMCIA_DEVICE_PROD_ID12("EXP ", "PnPIDE", 0x0a5c52fd, 0x0c694728), | 380 | PCMCIA_DEVICE_PROD_ID12("EXP ", "PnPIDE", 0x0a5c52fd, 0x0c694728), |
| 380 | PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e), | 381 | PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e), |
| 382 | PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420), | ||
| 381 | PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae), | 383 | PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae), |
| 382 | PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178), | 384 | PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178), |
| 383 | PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178), | 385 | PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178), |
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c index 2eb75cd74a96..4dc2e73298fd 100644 --- a/drivers/ata/pata_sil680.c +++ b/drivers/ata/pata_sil680.c | |||
| @@ -279,7 +279,7 @@ static struct ata_port_operations sil680_port_ops = { | |||
| 279 | * Returns the final clock settings. | 279 | * Returns the final clock settings. |
| 280 | */ | 280 | */ |
| 281 | 281 | ||
| 282 | static u8 sil680_init_chip(struct pci_dev *pdev) | 282 | static u8 sil680_init_chip(struct pci_dev *pdev, int *try_mmio) |
| 283 | { | 283 | { |
| 284 | u32 class_rev = 0; | 284 | u32 class_rev = 0; |
| 285 | u8 tmpbyte = 0; | 285 | u8 tmpbyte = 0; |
| @@ -297,6 +297,8 @@ static u8 sil680_init_chip(struct pci_dev *pdev) | |||
| 297 | dev_dbg(&pdev->dev, "sil680: BA5_EN = %d clock = %02X\n", | 297 | dev_dbg(&pdev->dev, "sil680: BA5_EN = %d clock = %02X\n", |
| 298 | tmpbyte & 1, tmpbyte & 0x30); | 298 | tmpbyte & 1, tmpbyte & 0x30); |
| 299 | 299 | ||
| 300 | *try_mmio = (tmpbyte & 1) || pci_resource_start(pdev, 5); | ||
| 301 | |||
| 300 | switch(tmpbyte & 0x30) { | 302 | switch(tmpbyte & 0x30) { |
| 301 | case 0x00: | 303 | case 0x00: |
| 302 | /* 133 clock attempt to force it on */ | 304 | /* 133 clock attempt to force it on */ |
| @@ -361,25 +363,76 @@ static int __devinit sil680_init_one(struct pci_dev *pdev, | |||
| 361 | }; | 363 | }; |
| 362 | const struct ata_port_info *ppi[] = { &info, NULL }; | 364 | const struct ata_port_info *ppi[] = { &info, NULL }; |
| 363 | static int printed_version; | 365 | static int printed_version; |
| 366 | struct ata_host *host; | ||
| 367 | void __iomem *mmio_base; | ||
| 368 | int rc, try_mmio; | ||
| 364 | 369 | ||
| 365 | if (!printed_version++) | 370 | if (!printed_version++) |
| 366 | dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); | 371 | dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); |
| 367 | 372 | ||
| 368 | switch(sil680_init_chip(pdev)) | 373 | switch (sil680_init_chip(pdev, &try_mmio)) { |
| 369 | { | ||
| 370 | case 0: | 374 | case 0: |
| 371 | ppi[0] = &info_slow; | 375 | ppi[0] = &info_slow; |
| 372 | break; | 376 | break; |
| 373 | case 0x30: | 377 | case 0x30: |
| 374 | return -ENODEV; | 378 | return -ENODEV; |
| 375 | } | 379 | } |
| 380 | |||
| 381 | if (!try_mmio) | ||
| 382 | goto use_ioports; | ||
| 383 | |||
| 384 | /* Try to acquire MMIO resources and fallback to PIO if | ||
| 385 | * that fails | ||
| 386 | */ | ||
| 387 | rc = pcim_enable_device(pdev); | ||
| 388 | if (rc) | ||
| 389 | return rc; | ||
| 390 | rc = pcim_iomap_regions(pdev, 1 << SIL680_MMIO_BAR, DRV_NAME); | ||
| 391 | if (rc) | ||
| 392 | goto use_ioports; | ||
| 393 | |||
| 394 | /* Allocate host and set it up */ | ||
| 395 | host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2); | ||
| 396 | if (!host) | ||
| 397 | return -ENOMEM; | ||
| 398 | host->iomap = pcim_iomap_table(pdev); | ||
| 399 | |||
| 400 | /* Setup DMA masks */ | ||
| 401 | rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); | ||
| 402 | if (rc) | ||
| 403 | return rc; | ||
| 404 | rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); | ||
| 405 | if (rc) | ||
| 406 | return rc; | ||
| 407 | pci_set_master(pdev); | ||
| 408 | |||
| 409 | /* Get MMIO base and initialize port addresses */ | ||
| 410 | mmio_base = host->iomap[SIL680_MMIO_BAR]; | ||
| 411 | host->ports[0]->ioaddr.bmdma_addr = mmio_base + 0x00; | ||
| 412 | host->ports[0]->ioaddr.cmd_addr = mmio_base + 0x80; | ||
| 413 | host->ports[0]->ioaddr.ctl_addr = mmio_base + 0x8a; | ||
| 414 | host->ports[0]->ioaddr.altstatus_addr = mmio_base + 0x8a; | ||
| 415 | ata_std_ports(&host->ports[0]->ioaddr); | ||
| 416 | host->ports[1]->ioaddr.bmdma_addr = mmio_base + 0x08; | ||
| 417 | host->ports[1]->ioaddr.cmd_addr = mmio_base + 0xc0; | ||
| 418 | host->ports[1]->ioaddr.ctl_addr = mmio_base + 0xca; | ||
| 419 | host->ports[1]->ioaddr.altstatus_addr = mmio_base + 0xca; | ||
| 420 | ata_std_ports(&host->ports[1]->ioaddr); | ||
| 421 | |||
| 422 | /* Register & activate */ | ||
| 423 | return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED, | ||
| 424 | &sil680_sht); | ||
| 425 | |||
| 426 | use_ioports: | ||
| 376 | return ata_pci_init_one(pdev, ppi); | 427 | return ata_pci_init_one(pdev, ppi); |
| 377 | } | 428 | } |
| 378 | 429 | ||
| 379 | #ifdef CONFIG_PM | 430 | #ifdef CONFIG_PM |
| 380 | static int sil680_reinit_one(struct pci_dev *pdev) | 431 | static int sil680_reinit_one(struct pci_dev *pdev) |
| 381 | { | 432 | { |
| 382 | sil680_init_chip(pdev); | 433 | int try_mmio; |
| 434 | |||
| 435 | sil680_init_chip(pdev, &try_mmio); | ||
| 383 | return ata_pci_device_resume(pdev); | 436 | return ata_pci_device_resume(pdev); |
| 384 | } | 437 | } |
| 385 | #endif | 438 | #endif |
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 40557fe2ffdf..240a8920d0bd 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c | |||
| @@ -169,6 +169,35 @@ enum { | |||
| 169 | NV_ADMA_PORT_REGISTER_MODE = (1 << 0), | 169 | NV_ADMA_PORT_REGISTER_MODE = (1 << 0), |
| 170 | NV_ADMA_ATAPI_SETUP_COMPLETE = (1 << 1), | 170 | NV_ADMA_ATAPI_SETUP_COMPLETE = (1 << 1), |
| 171 | 171 | ||
| 172 | /* MCP55 reg offset */ | ||
| 173 | NV_CTL_MCP55 = 0x400, | ||
| 174 | NV_INT_STATUS_MCP55 = 0x440, | ||
| 175 | NV_INT_ENABLE_MCP55 = 0x444, | ||
| 176 | NV_NCQ_REG_MCP55 = 0x448, | ||
| 177 | |||
| 178 | /* MCP55 */ | ||
| 179 | NV_INT_ALL_MCP55 = 0xffff, | ||
| 180 | NV_INT_PORT_SHIFT_MCP55 = 16, /* each port occupies 16 bits */ | ||
| 181 | NV_INT_MASK_MCP55 = NV_INT_ALL_MCP55 & 0xfffd, | ||
| 182 | |||
| 183 | /* SWNCQ ENABLE BITS*/ | ||
| 184 | NV_CTL_PRI_SWNCQ = 0x02, | ||
| 185 | NV_CTL_SEC_SWNCQ = 0x04, | ||
| 186 | |||
| 187 | /* SW NCQ status bits*/ | ||
| 188 | NV_SWNCQ_IRQ_DEV = (1 << 0), | ||
| 189 | NV_SWNCQ_IRQ_PM = (1 << 1), | ||
| 190 | NV_SWNCQ_IRQ_ADDED = (1 << 2), | ||
| 191 | NV_SWNCQ_IRQ_REMOVED = (1 << 3), | ||
| 192 | |||
| 193 | NV_SWNCQ_IRQ_BACKOUT = (1 << 4), | ||
| 194 | NV_SWNCQ_IRQ_SDBFIS = (1 << 5), | ||
| 195 | NV_SWNCQ_IRQ_DHREGFIS = (1 << 6), | ||
| 196 | NV_SWNCQ_IRQ_DMASETUP = (1 << 7), | ||
| 197 | |||
| 198 | NV_SWNCQ_IRQ_HOTPLUG = NV_SWNCQ_IRQ_ADDED | | ||
| 199 | NV_SWNCQ_IRQ_REMOVED, | ||
| 200 | |||
| 172 | }; | 201 | }; |
| 173 | 202 | ||
| 174 | /* ADMA Physical Region Descriptor - one SG segment */ | 203 | /* ADMA Physical Region Descriptor - one SG segment */ |
| @@ -226,6 +255,42 @@ struct nv_host_priv { | |||
| 226 | unsigned long type; | 255 | unsigned long type; |
| 227 | }; | 256 | }; |
| 228 | 257 | ||
| 258 | struct defer_queue { | ||
| 259 | u32 defer_bits; | ||
| 260 | unsigned int head; | ||
| 261 | unsigned int tail; | ||
| 262 | unsigned int tag[ATA_MAX_QUEUE]; | ||
| 263 | }; | ||
| 264 | |||
| 265 | enum ncq_saw_flag_list { | ||
| 266 | ncq_saw_d2h = (1U << 0), | ||
| 267 | ncq_saw_dmas = (1U << 1), | ||
| 268 | ncq_saw_sdb = (1U << 2), | ||
| 269 | ncq_saw_backout = (1U << 3), | ||
| 270 | }; | ||
| 271 | |||
| 272 | struct nv_swncq_port_priv { | ||
| 273 | struct ata_prd *prd; /* our SG list */ | ||
| 274 | dma_addr_t prd_dma; /* and its DMA mapping */ | ||
| 275 | void __iomem *sactive_block; | ||
| 276 | void __iomem *irq_block; | ||
| 277 | void __iomem *tag_block; | ||
| 278 | u32 qc_active; | ||
| 279 | |||
| 280 | unsigned int last_issue_tag; | ||
| 281 | |||
| 282 | /* fifo circular queue to store deferral command */ | ||
| 283 | struct defer_queue defer_queue; | ||
| 284 | |||
| 285 | /* for NCQ interrupt analysis */ | ||
| 286 | u32 dhfis_bits; | ||
| 287 | u32 dmafis_bits; | ||
| 288 | u32 sdbfis_bits; | ||
| 289 | |||
| 290 | unsigned int ncq_flags; | ||
| 291 | }; | ||
| 292 | |||
| 293 | |||
| 229 | #define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & ( 1 << (19 + (12 * (PORT))))) | 294 | #define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & ( 1 << (19 + (12 * (PORT))))) |
| 230 | 295 | ||
| 231 | static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); | 296 | static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); |
| @@ -263,13 +328,29 @@ static void nv_adma_host_stop(struct ata_host *host); | |||
| 263 | static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc); | 328 | static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc); |
| 264 | static void nv_adma_tf_read(struct ata_port *ap, struct ata_taskfile *tf); | 329 | static void nv_adma_tf_read(struct ata_port *ap, struct ata_taskfile *tf); |
| 265 | 330 | ||
| 331 | static void nv_mcp55_thaw(struct ata_port *ap); | ||
| 332 | static void nv_mcp55_freeze(struct ata_port *ap); | ||
| 333 | static void nv_swncq_error_handler(struct ata_port *ap); | ||
| 334 | static int nv_swncq_slave_config(struct scsi_device *sdev); | ||
| 335 | static int nv_swncq_port_start(struct ata_port *ap); | ||
| 336 | static void nv_swncq_qc_prep(struct ata_queued_cmd *qc); | ||
| 337 | static void nv_swncq_fill_sg(struct ata_queued_cmd *qc); | ||
| 338 | static unsigned int nv_swncq_qc_issue(struct ata_queued_cmd *qc); | ||
| 339 | static void nv_swncq_irq_clear(struct ata_port *ap, u16 fis); | ||
| 340 | static irqreturn_t nv_swncq_interrupt(int irq, void *dev_instance); | ||
| 341 | #ifdef CONFIG_PM | ||
| 342 | static int nv_swncq_port_suspend(struct ata_port *ap, pm_message_t mesg); | ||
| 343 | static int nv_swncq_port_resume(struct ata_port *ap); | ||
| 344 | #endif | ||
| 345 | |||
| 266 | enum nv_host_type | 346 | enum nv_host_type |
| 267 | { | 347 | { |
| 268 | GENERIC, | 348 | GENERIC, |
| 269 | NFORCE2, | 349 | NFORCE2, |
| 270 | NFORCE3 = NFORCE2, /* NF2 == NF3 as far as sata_nv is concerned */ | 350 | NFORCE3 = NFORCE2, /* NF2 == NF3 as far as sata_nv is concerned */ |
| 271 | CK804, | 351 | CK804, |
| 272 | ADMA | 352 | ADMA, |
| 353 | SWNCQ, | ||
| 273 | }; | 354 | }; |
| 274 | 355 | ||
| 275 | static const struct pci_device_id nv_pci_tbl[] = { | 356 | static const struct pci_device_id nv_pci_tbl[] = { |
| @@ -280,13 +361,13 @@ static const struct pci_device_id nv_pci_tbl[] = { | |||
| 280 | { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2), CK804 }, | 361 | { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2), CK804 }, |
| 281 | { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA), CK804 }, | 362 | { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA), CK804 }, |
| 282 | { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2), CK804 }, | 363 | { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2), CK804 }, |
| 283 | { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA), GENERIC }, | 364 | { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA), SWNCQ }, |
| 284 | { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2), GENERIC }, | 365 | { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2), SWNCQ }, |
| 285 | { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA), GENERIC }, | 366 | { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA), SWNCQ }, |
| 286 | { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2), GENERIC }, | 367 | { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2), SWNCQ }, |
| 287 | { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA), GENERIC }, | 368 | { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA), SWNCQ }, |
| 288 | { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2), GENERIC }, | 369 | { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2), SWNCQ }, |
| 289 | { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3), GENERIC }, | 370 | { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3), SWNCQ }, |
| 290 | 371 | ||
| 291 | { } /* terminate list */ | 372 | { } /* terminate list */ |
| 292 | }; | 373 | }; |
| @@ -339,6 +420,25 @@ static struct scsi_host_template nv_adma_sht = { | |||
| 339 | .bios_param = ata_std_bios_param, | 420 | .bios_param = ata_std_bios_param, |
| 340 | }; | 421 | }; |
| 341 | 422 | ||
| 423 | static struct scsi_host_template nv_swncq_sht = { | ||
| 424 | .module = THIS_MODULE, | ||
| 425 | .name = DRV_NAME, | ||
| 426 | .ioctl = ata_scsi_ioctl, | ||
| 427 | .queuecommand = ata_scsi_queuecmd, | ||
| 428 | .change_queue_depth = ata_scsi_change_queue_depth, | ||
| 429 | .can_queue = ATA_MAX_QUEUE, | ||
| 430 | .this_id = ATA_SHT_THIS_ID, | ||
| 431 | .sg_tablesize = LIBATA_MAX_PRD, | ||
| 432 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | ||
| 433 | .emulated = ATA_SHT_EMULATED, | ||
| 434 | .use_clustering = ATA_SHT_USE_CLUSTERING, | ||
| 435 | .proc_name = DRV_NAME, | ||
| 436 | .dma_boundary = ATA_DMA_BOUNDARY, | ||
| 437 | .slave_configure = nv_swncq_slave_config, | ||
| 438 | .slave_destroy = ata_scsi_slave_destroy, | ||
| 439 | .bios_param = ata_std_bios_param, | ||
| 440 | }; | ||
| 441 | |||
| 342 | static const struct ata_port_operations nv_generic_ops = { | 442 | static const struct ata_port_operations nv_generic_ops = { |
| 343 | .tf_load = ata_tf_load, | 443 | .tf_load = ata_tf_load, |
| 344 | .tf_read = ata_tf_read, | 444 | .tf_read = ata_tf_read, |
| @@ -444,6 +544,35 @@ static const struct ata_port_operations nv_adma_ops = { | |||
| 444 | .host_stop = nv_adma_host_stop, | 544 | .host_stop = nv_adma_host_stop, |
| 445 | }; | 545 | }; |
| 446 | 546 | ||
| 547 | static const struct ata_port_operations nv_swncq_ops = { | ||
| 548 | .tf_load = ata_tf_load, | ||
| 549 | .tf_read = ata_tf_read, | ||
| 550 | .exec_command = ata_exec_command, | ||
| 551 | .check_status = ata_check_status, | ||
| 552 | .dev_select = ata_std_dev_select, | ||
| 553 | .bmdma_setup = ata_bmdma_setup, | ||
| 554 | .bmdma_start = ata_bmdma_start, | ||
| 555 | .bmdma_stop = ata_bmdma_stop, | ||
| 556 | .bmdma_status = ata_bmdma_status, | ||
| 557 | .qc_defer = ata_std_qc_defer, | ||
| 558 | .qc_prep = nv_swncq_qc_prep, | ||
| 559 | .qc_issue = nv_swncq_qc_issue, | ||
| 560 | .freeze = nv_mcp55_freeze, | ||
| 561 | .thaw = nv_mcp55_thaw, | ||
| 562 | .error_handler = nv_swncq_error_handler, | ||
| 563 | .post_internal_cmd = ata_bmdma_post_internal_cmd, | ||
| 564 | .data_xfer = ata_data_xfer, | ||
| 565 | .irq_clear = ata_bmdma_irq_clear, | ||
| 566 | .irq_on = ata_irq_on, | ||
| 567 | .scr_read = nv_scr_read, | ||
| 568 | .scr_write = nv_scr_write, | ||
| 569 | #ifdef CONFIG_PM | ||
| 570 | .port_suspend = nv_swncq_port_suspend, | ||
| 571 | .port_resume = nv_swncq_port_resume, | ||
| 572 | #endif | ||
| 573 | .port_start = nv_swncq_port_start, | ||
| 574 | }; | ||
| 575 | |||
| 447 | static const struct ata_port_info nv_port_info[] = { | 576 | static const struct ata_port_info nv_port_info[] = { |
| 448 | /* generic */ | 577 | /* generic */ |
| 449 | { | 578 | { |
| @@ -490,6 +619,18 @@ static const struct ata_port_info nv_port_info[] = { | |||
| 490 | .port_ops = &nv_adma_ops, | 619 | .port_ops = &nv_adma_ops, |
| 491 | .irq_handler = nv_adma_interrupt, | 620 | .irq_handler = nv_adma_interrupt, |
| 492 | }, | 621 | }, |
| 622 | /* SWNCQ */ | ||
| 623 | { | ||
| 624 | .sht = &nv_swncq_sht, | ||
| 625 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | ||
| 626 | ATA_FLAG_NCQ, | ||
| 627 | .link_flags = ATA_LFLAG_HRST_TO_RESUME, | ||
| 628 | .pio_mask = NV_PIO_MASK, | ||
| 629 | .mwdma_mask = NV_MWDMA_MASK, | ||
| 630 | .udma_mask = NV_UDMA_MASK, | ||
| 631 | .port_ops = &nv_swncq_ops, | ||
| 632 | .irq_handler = nv_swncq_interrupt, | ||
| 633 | }, | ||
| 493 | }; | 634 | }; |
| 494 | 635 | ||
| 495 | MODULE_AUTHOR("NVIDIA"); | 636 | MODULE_AUTHOR("NVIDIA"); |
| @@ -499,6 +640,7 @@ MODULE_DEVICE_TABLE(pci, nv_pci_tbl); | |||
| 499 | MODULE_VERSION(DRV_VERSION); | 640 | MODULE_VERSION(DRV_VERSION); |
| 500 | 641 | ||
| 501 | static int adma_enabled = 1; | 642 | static int adma_enabled = 1; |
| 643 | static int swncq_enabled; | ||
| 502 | 644 | ||
| 503 | static void nv_adma_register_mode(struct ata_port *ap) | 645 | static void nv_adma_register_mode(struct ata_port *ap) |
| 504 | { | 646 | { |
| @@ -1452,6 +1594,34 @@ static void nv_ck804_thaw(struct ata_port *ap) | |||
| 1452 | writeb(mask, mmio_base + NV_INT_ENABLE_CK804); | 1594 | writeb(mask, mmio_base + NV_INT_ENABLE_CK804); |
| 1453 | } | 1595 | } |
| 1454 | 1596 | ||
| 1597 | static void nv_mcp55_freeze(struct ata_port *ap) | ||
| 1598 | { | ||
| 1599 | void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR]; | ||
| 1600 | int shift = ap->port_no * NV_INT_PORT_SHIFT_MCP55; | ||
| 1601 | u32 mask; | ||
| 1602 | |||
| 1603 | writel(NV_INT_ALL_MCP55 << shift, mmio_base + NV_INT_STATUS_MCP55); | ||
| 1604 | |||
| 1605 | mask = readl(mmio_base + NV_INT_ENABLE_MCP55); | ||
| 1606 | mask &= ~(NV_INT_ALL_MCP55 << shift); | ||
| 1607 | writel(mask, mmio_base + NV_INT_ENABLE_MCP55); | ||
| 1608 | ata_bmdma_freeze(ap); | ||
| 1609 | } | ||
| 1610 | |||
| 1611 | static void nv_mcp55_thaw(struct ata_port *ap) | ||
| 1612 | { | ||
| 1613 | void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR]; | ||
| 1614 | int shift = ap->port_no * NV_INT_PORT_SHIFT_MCP55; | ||
| 1615 | u32 mask; | ||
| 1616 | |||
| 1617 | writel(NV_INT_ALL_MCP55 << shift, mmio_base + NV_INT_STATUS_MCP55); | ||
| 1618 | |||
| 1619 | mask = readl(mmio_base + NV_INT_ENABLE_MCP55); | ||
| 1620 | mask |= (NV_INT_MASK_MCP55 << shift); | ||
| 1621 | writel(mask, mmio_base + NV_INT_ENABLE_MCP55); | ||
| 1622 | ata_bmdma_thaw(ap); | ||
| 1623 | } | ||
| 1624 | |||
| 1455 | static int nv_hardreset(struct ata_link *link, unsigned int *class, | 1625 | static int nv_hardreset(struct ata_link *link, unsigned int *class, |
| 1456 | unsigned long deadline) | 1626 | unsigned long deadline) |
| 1457 | { | 1627 | { |
| @@ -1525,6 +1695,663 @@ static void nv_adma_error_handler(struct ata_port *ap) | |||
| 1525 | nv_hardreset, ata_std_postreset); | 1695 | nv_hardreset, ata_std_postreset); |
| 1526 | } | 1696 | } |
| 1527 | 1697 | ||
| 1698 | static void nv_swncq_qc_to_dq(struct ata_port *ap, struct ata_queued_cmd *qc) | ||
| 1699 | { | ||
| 1700 | struct nv_swncq_port_priv *pp = ap->private_data; | ||
| 1701 | struct defer_queue *dq = &pp->defer_queue; | ||
| 1702 | |||
| 1703 | /* queue is full */ | ||
| 1704 | WARN_ON(dq->tail - dq->head == ATA_MAX_QUEUE); | ||
| 1705 | dq->defer_bits |= (1 << qc->tag); | ||
| 1706 | dq->tag[dq->tail++ & (ATA_MAX_QUEUE - 1)] = qc->tag; | ||
| 1707 | } | ||
| 1708 | |||
| 1709 | static struct ata_queued_cmd *nv_swncq_qc_from_dq(struct ata_port *ap) | ||
| 1710 | { | ||
| 1711 | struct nv_swncq_port_priv *pp = ap->private_data; | ||
| 1712 | struct defer_queue *dq = &pp->defer_queue; | ||
| 1713 | unsigned int tag; | ||
| 1714 | |||
| 1715 | if (dq->head == dq->tail) /* null queue */ | ||
| 1716 | return NULL; | ||
| 1717 | |||
| 1718 | tag = dq->tag[dq->head & (ATA_MAX_QUEUE - 1)]; | ||
| 1719 | dq->tag[dq->head++ & (ATA_MAX_QUEUE - 1)] = ATA_TAG_POISON; | ||
| 1720 | WARN_ON(!(dq->defer_bits & (1 << tag))); | ||
| 1721 | dq->defer_bits &= ~(1 << tag); | ||
| 1722 | |||
| 1723 | return ata_qc_from_tag(ap, tag); | ||
| 1724 | } | ||
| 1725 | |||
| 1726 | static void nv_swncq_fis_reinit(struct ata_port *ap) | ||
| 1727 | { | ||
| 1728 | struct nv_swncq_port_priv *pp = ap->private_data; | ||
| 1729 | |||
| 1730 | pp->dhfis_bits = 0; | ||
| 1731 | pp->dmafis_bits = 0; | ||
| 1732 | pp->sdbfis_bits = 0; | ||
| 1733 | pp->ncq_flags = 0; | ||
| 1734 | } | ||
| 1735 | |||
| 1736 | static void nv_swncq_pp_reinit(struct ata_port *ap) | ||
| 1737 | { | ||
| 1738 | struct nv_swncq_port_priv *pp = ap->private_data; | ||
| 1739 | struct defer_queue *dq = &pp->defer_queue; | ||
| 1740 | |||
| 1741 | dq->head = 0; | ||
| 1742 | dq->tail = 0; | ||
| 1743 | dq->defer_bits = 0; | ||
| 1744 | pp->qc_active = 0; | ||
| 1745 | pp->last_issue_tag = ATA_TAG_POISON; | ||
| 1746 | nv_swncq_fis_reinit(ap); | ||
| 1747 | } | ||
| 1748 | |||
| 1749 | static void nv_swncq_irq_clear(struct ata_port *ap, u16 fis) | ||
| 1750 | { | ||
| 1751 | struct nv_swncq_port_priv *pp = ap->private_data; | ||
| 1752 | |||
| 1753 | writew(fis, pp->irq_block); | ||
| 1754 | } | ||
| 1755 | |||
| 1756 | static void __ata_bmdma_stop(struct ata_port *ap) | ||
| 1757 | { | ||
| 1758 | struct ata_queued_cmd qc; | ||
| 1759 | |||
| 1760 | qc.ap = ap; | ||
| 1761 | ata_bmdma_stop(&qc); | ||
| 1762 | } | ||
| 1763 | |||
| 1764 | static void nv_swncq_ncq_stop(struct ata_port *ap) | ||
| 1765 | { | ||
| 1766 | struct nv_swncq_port_priv *pp = ap->private_data; | ||
| 1767 | unsigned int i; | ||
| 1768 | u32 sactive; | ||
| 1769 | u32 done_mask; | ||
| 1770 | |||
| 1771 | ata_port_printk(ap, KERN_ERR, | ||
| 1772 | "EH in SWNCQ mode,QC:qc_active 0x%X sactive 0x%X\n", | ||
| 1773 | ap->qc_active, ap->link.sactive); | ||
| 1774 | ata_port_printk(ap, KERN_ERR, | ||
| 1775 | "SWNCQ:qc_active 0x%X defer_bits 0x%X last_issue_tag 0x%x\n " | ||
| 1776 | "dhfis 0x%X dmafis 0x%X sdbfis 0x%X\n", | ||
| 1777 | pp->qc_active, pp->defer_queue.defer_bits, pp->last_issue_tag, | ||
| 1778 | pp->dhfis_bits, pp->dmafis_bits, pp->sdbfis_bits); | ||
| 1779 | |||
| 1780 | ata_port_printk(ap, KERN_ERR, "ATA_REG 0x%X ERR_REG 0x%X\n", | ||
| 1781 | ap->ops->check_status(ap), | ||
| 1782 | ioread8(ap->ioaddr.error_addr)); | ||
| 1783 | |||
| 1784 | sactive = readl(pp->sactive_block); | ||
| 1785 | done_mask = pp->qc_active ^ sactive; | ||
| 1786 | |||
| 1787 | ata_port_printk(ap, KERN_ERR, "tag : dhfis dmafis sdbfis sacitve\n"); | ||
| 1788 | for (i = 0; i < ATA_MAX_QUEUE; i++) { | ||
| 1789 | u8 err = 0; | ||
| 1790 | if (pp->qc_active & (1 << i)) | ||
| 1791 | err = 0; | ||
| 1792 | else if (done_mask & (1 << i)) | ||
| 1793 | err = 1; | ||
| 1794 | else | ||
| 1795 | continue; | ||
| 1796 | |||
| 1797 | ata_port_printk(ap, KERN_ERR, | ||
| 1798 | "tag 0x%x: %01x %01x %01x %01x %s\n", i, | ||
| 1799 | (pp->dhfis_bits >> i) & 0x1, | ||
| 1800 | (pp->dmafis_bits >> i) & 0x1, | ||
| 1801 | (pp->sdbfis_bits >> i) & 0x1, | ||
| 1802 | (sactive >> i) & 0x1, | ||
| 1803 | (err ? "error! tag doesn't exit" : " ")); | ||
| 1804 | } | ||
| 1805 | |||
| 1806 | nv_swncq_pp_reinit(ap); | ||
| 1807 | ap->ops->irq_clear(ap); | ||
| 1808 | __ata_bmdma_stop(ap); | ||
| 1809 | nv_swncq_irq_clear(ap, 0xffff); | ||
| 1810 | } | ||
| 1811 | |||
| 1812 | static void nv_swncq_error_handler(struct ata_port *ap) | ||
| 1813 | { | ||
| 1814 | struct ata_eh_context *ehc = &ap->link.eh_context; | ||
| 1815 | |||
| 1816 | if (ap->link.sactive) { | ||
| 1817 | nv_swncq_ncq_stop(ap); | ||
| 1818 | ehc->i.action |= ATA_EH_HARDRESET; | ||
| 1819 | } | ||
| 1820 | |||
| 1821 | ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, | ||
| 1822 | nv_hardreset, ata_std_postreset); | ||
| 1823 | } | ||
| 1824 | |||
| 1825 | #ifdef CONFIG_PM | ||
| 1826 | static int nv_swncq_port_suspend(struct ata_port *ap, pm_message_t mesg) | ||
| 1827 | { | ||
| 1828 | void __iomem *mmio = ap->host->iomap[NV_MMIO_BAR]; | ||
| 1829 | u32 tmp; | ||
| 1830 | |||
| 1831 | /* clear irq */ | ||
| 1832 | writel(~0, mmio + NV_INT_STATUS_MCP55); | ||
| 1833 | |||
| 1834 | /* disable irq */ | ||
| 1835 | writel(0, mmio + NV_INT_ENABLE_MCP55); | ||
| 1836 | |||
| 1837 | /* disable swncq */ | ||
| 1838 | tmp = readl(mmio + NV_CTL_MCP55); | ||
| 1839 | tmp &= ~(NV_CTL_PRI_SWNCQ | NV_CTL_SEC_SWNCQ); | ||
| 1840 | writel(tmp, mmio + NV_CTL_MCP55); | ||
| 1841 | |||
| 1842 | return 0; | ||
| 1843 | } | ||
| 1844 | |||
| 1845 | static int nv_swncq_port_resume(struct ata_port *ap) | ||
| 1846 | { | ||
| 1847 | void __iomem *mmio = ap->host->iomap[NV_MMIO_BAR]; | ||
| 1848 | u32 tmp; | ||
| 1849 | |||
| 1850 | /* clear irq */ | ||
| 1851 | writel(~0, mmio + NV_INT_STATUS_MCP55); | ||
| 1852 | |||
| 1853 | /* enable irq */ | ||
| 1854 | writel(0x00fd00fd, mmio + NV_INT_ENABLE_MCP55); | ||
| 1855 | |||
| 1856 | /* enable swncq */ | ||
| 1857 | tmp = readl(mmio + NV_CTL_MCP55); | ||
| 1858 | writel(tmp | NV_CTL_PRI_SWNCQ | NV_CTL_SEC_SWNCQ, mmio + NV_CTL_MCP55); | ||
| 1859 | |||
| 1860 | return 0; | ||
| 1861 | } | ||
| 1862 | #endif | ||
| 1863 | |||
| 1864 | static void nv_swncq_host_init(struct ata_host *host) | ||
| 1865 | { | ||
| 1866 | u32 tmp; | ||
| 1867 | void __iomem *mmio = host->iomap[NV_MMIO_BAR]; | ||
| 1868 | struct pci_dev *pdev = to_pci_dev(host->dev); | ||
| 1869 | u8 regval; | ||
| 1870 | |||
| 1871 | /* disable ECO 398 */ | ||
| 1872 | pci_read_config_byte(pdev, 0x7f, ®val); | ||
| 1873 | regval &= ~(1 << 7); | ||
| 1874 | pci_write_config_byte(pdev, 0x7f, regval); | ||
| 1875 | |||
| 1876 | /* enable swncq */ | ||
| 1877 | tmp = readl(mmio + NV_CTL_MCP55); | ||
| 1878 | VPRINTK("HOST_CTL:0x%X\n", tmp); | ||
| 1879 | writel(tmp | NV_CTL_PRI_SWNCQ | NV_CTL_SEC_SWNCQ, mmio + NV_CTL_MCP55); | ||
| 1880 | |||
| 1881 | /* enable irq intr */ | ||
| 1882 | tmp = readl(mmio + NV_INT_ENABLE_MCP55); | ||
| 1883 | VPRINTK("HOST_ENABLE:0x%X\n", tmp); | ||
| 1884 | writel(tmp | 0x00fd00fd, mmio + NV_INT_ENABLE_MCP55); | ||
| 1885 | |||
| 1886 | /* clear port irq */ | ||
| 1887 | writel(~0x0, mmio + NV_INT_STATUS_MCP55); | ||
| 1888 | } | ||
| 1889 | |||
| 1890 | static int nv_swncq_slave_config(struct scsi_device *sdev) | ||
| 1891 | { | ||
| 1892 | struct ata_port *ap = ata_shost_to_port(sdev->host); | ||
| 1893 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | ||
| 1894 | struct ata_device *dev; | ||
| 1895 | int rc; | ||
| 1896 | u8 rev; | ||
| 1897 | u8 check_maxtor = 0; | ||
| 1898 | unsigned char model_num[ATA_ID_PROD_LEN + 1]; | ||
| 1899 | |||
| 1900 | rc = ata_scsi_slave_config(sdev); | ||
| 1901 | if (sdev->id >= ATA_MAX_DEVICES || sdev->channel || sdev->lun) | ||
| 1902 | /* Not a proper libata device, ignore */ | ||
| 1903 | return rc; | ||
| 1904 | |||
| 1905 | dev = &ap->link.device[sdev->id]; | ||
| 1906 | if (!(ap->flags & ATA_FLAG_NCQ) || dev->class == ATA_DEV_ATAPI) | ||
| 1907 | return rc; | ||
| 1908 | |||
| 1909 | /* if MCP51 and Maxtor, then disable ncq */ | ||
| 1910 | if (pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA || | ||
| 1911 | pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2) | ||
| 1912 | check_maxtor = 1; | ||
| 1913 | |||
| 1914 | /* if MCP55 and rev <= a2 and Maxtor, then disable ncq */ | ||
| 1915 | if (pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA || | ||
| 1916 | pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2) { | ||
| 1917 | pci_read_config_byte(pdev, 0x8, &rev); | ||
| 1918 | if (rev <= 0xa2) | ||
| 1919 | check_maxtor = 1; | ||
| 1920 | } | ||
| 1921 | |||
| 1922 | if (!check_maxtor) | ||
| 1923 | return rc; | ||
| 1924 | |||
| 1925 | ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num)); | ||
| 1926 | |||
| 1927 | if (strncmp(model_num, "Maxtor", 6) == 0) { | ||
| 1928 | ata_scsi_change_queue_depth(sdev, 1); | ||
| 1929 | ata_dev_printk(dev, KERN_NOTICE, | ||
| 1930 | "Disabling SWNCQ mode (depth %x)\n", sdev->queue_depth); | ||
| 1931 | } | ||
| 1932 | |||
| 1933 | return rc; | ||
| 1934 | } | ||
| 1935 | |||
| 1936 | static int nv_swncq_port_start(struct ata_port *ap) | ||
| 1937 | { | ||
| 1938 | struct device *dev = ap->host->dev; | ||
| 1939 | void __iomem *mmio = ap->host->iomap[NV_MMIO_BAR]; | ||
| 1940 | struct nv_swncq_port_priv *pp; | ||
| 1941 | int rc; | ||
| 1942 | |||
| 1943 | rc = ata_port_start(ap); | ||
| 1944 | if (rc) | ||
| 1945 | return rc; | ||
| 1946 | |||
| 1947 | pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL); | ||
| 1948 | if (!pp) | ||
| 1949 | return -ENOMEM; | ||
| 1950 | |||
| 1951 | pp->prd = dmam_alloc_coherent(dev, ATA_PRD_TBL_SZ * ATA_MAX_QUEUE, | ||
| 1952 | &pp->prd_dma, GFP_KERNEL); | ||
| 1953 | if (!pp->prd) | ||
| 1954 | return -ENOMEM; | ||
| 1955 | memset(pp->prd, 0, ATA_PRD_TBL_SZ * ATA_MAX_QUEUE); | ||
| 1956 | |||
| 1957 | ap->private_data = pp; | ||
| 1958 | pp->sactive_block = ap->ioaddr.scr_addr + 4 * SCR_ACTIVE; | ||
| 1959 | pp->irq_block = mmio + NV_INT_STATUS_MCP55 + ap->port_no * 2; | ||
| 1960 | pp->tag_block = mmio + NV_NCQ_REG_MCP55 + ap->port_no * 2; | ||
| 1961 | |||
| 1962 | return 0; | ||
| 1963 | } | ||
| 1964 | |||
| 1965 | static void nv_swncq_qc_prep(struct ata_queued_cmd *qc) | ||
| 1966 | { | ||
| 1967 | if (qc->tf.protocol != ATA_PROT_NCQ) { | ||
| 1968 | ata_qc_prep(qc); | ||
| 1969 | return; | ||
| 1970 | } | ||
| 1971 | |||
| 1972 | if (!(qc->flags & ATA_QCFLAG_DMAMAP)) | ||
| 1973 | return; | ||
| 1974 | |||
| 1975 | nv_swncq_fill_sg(qc); | ||
| 1976 | } | ||
| 1977 | |||
| 1978 | static void nv_swncq_fill_sg(struct ata_queued_cmd *qc) | ||
| 1979 | { | ||
| 1980 | struct ata_port *ap = qc->ap; | ||
| 1981 | struct scatterlist *sg; | ||
| 1982 | unsigned int idx; | ||
| 1983 | struct nv_swncq_port_priv *pp = ap->private_data; | ||
| 1984 | struct ata_prd *prd; | ||
| 1985 | |||
| 1986 | WARN_ON(qc->__sg == NULL); | ||
| 1987 | WARN_ON(qc->n_elem == 0 && qc->pad_len == 0); | ||
| 1988 | |||
| 1989 | prd = pp->prd + ATA_MAX_PRD * qc->tag; | ||
| 1990 | |||
| 1991 | idx = 0; | ||
| 1992 | ata_for_each_sg(sg, qc) { | ||
| 1993 | u32 addr, offset; | ||
| 1994 | u32 sg_len, len; | ||
| 1995 | |||
| 1996 | addr = (u32)sg_dma_address(sg); | ||
| 1997 | sg_len = sg_dma_len(sg); | ||
| 1998 | |||
| 1999 | while (sg_len) { | ||
| 2000 | offset = addr & 0xffff; | ||
| 2001 | len = sg_len; | ||
| 2002 | if ((offset + sg_len) > 0x10000) | ||
| 2003 | len = 0x10000 - offset; | ||
| 2004 | |||
| 2005 | prd[idx].addr = cpu_to_le32(addr); | ||
| 2006 | prd[idx].flags_len = cpu_to_le32(len & 0xffff); | ||
| 2007 | |||
| 2008 | idx++; | ||
| 2009 | sg_len -= len; | ||
| 2010 | addr += len; | ||
| 2011 | } | ||
| 2012 | } | ||
| 2013 | |||
| 2014 | if (idx) | ||
| 2015 | prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); | ||
| 2016 | } | ||
| 2017 | |||
| 2018 | static unsigned int nv_swncq_issue_atacmd(struct ata_port *ap, | ||
| 2019 | struct ata_queued_cmd *qc) | ||
| 2020 | { | ||
| 2021 | struct nv_swncq_port_priv *pp = ap->private_data; | ||
| 2022 | |||
| 2023 | if (qc == NULL) | ||
| 2024 | return 0; | ||
| 2025 | |||
| 2026 | DPRINTK("Enter\n"); | ||
| 2027 | |||
| 2028 | writel((1 << qc->tag), pp->sactive_block); | ||
| 2029 | pp->last_issue_tag = qc->tag; | ||
| 2030 | pp->dhfis_bits &= ~(1 << qc->tag); | ||
| 2031 | pp->dmafis_bits &= ~(1 << qc->tag); | ||
| 2032 | pp->qc_active |= (0x1 << qc->tag); | ||
| 2033 | |||
| 2034 | ap->ops->tf_load(ap, &qc->tf); /* load tf registers */ | ||
| 2035 | ap->ops->exec_command(ap, &qc->tf); | ||
| 2036 | |||
| 2037 | DPRINTK("Issued tag %u\n", qc->tag); | ||
| 2038 | |||
| 2039 | return 0; | ||
| 2040 | } | ||
| 2041 | |||
| 2042 | static unsigned int nv_swncq_qc_issue(struct ata_queued_cmd *qc) | ||
| 2043 | { | ||
| 2044 | struct ata_port *ap = qc->ap; | ||
| 2045 | struct nv_swncq_port_priv *pp = ap->private_data; | ||
| 2046 | |||
| 2047 | if (qc->tf.protocol != ATA_PROT_NCQ) | ||
| 2048 | return ata_qc_issue_prot(qc); | ||
| 2049 | |||
| 2050 | DPRINTK("Enter\n"); | ||
| 2051 | |||
| 2052 | if (!pp->qc_active) | ||
| 2053 | nv_swncq_issue_atacmd(ap, qc); | ||
| 2054 | else | ||
| 2055 | nv_swncq_qc_to_dq(ap, qc); /* add qc to defer queue */ | ||
| 2056 | |||
| 2057 | return 0; | ||
| 2058 | } | ||
| 2059 | |||
| 2060 | static void nv_swncq_hotplug(struct ata_port *ap, u32 fis) | ||
| 2061 | { | ||
| 2062 | u32 serror; | ||
| 2063 | struct ata_eh_info *ehi = &ap->link.eh_info; | ||
| 2064 | |||
| 2065 | ata_ehi_clear_desc(ehi); | ||
| 2066 | |||
| 2067 | /* AHCI needs SError cleared; otherwise, it might lock up */ | ||
| 2068 | sata_scr_read(&ap->link, SCR_ERROR, &serror); | ||
| 2069 | sata_scr_write(&ap->link, SCR_ERROR, serror); | ||
| 2070 | |||
| 2071 | /* analyze @irq_stat */ | ||
| 2072 | if (fis & NV_SWNCQ_IRQ_ADDED) | ||
| 2073 | ata_ehi_push_desc(ehi, "hot plug"); | ||
| 2074 | else if (fis & NV_SWNCQ_IRQ_REMOVED) | ||
| 2075 | ata_ehi_push_desc(ehi, "hot unplug"); | ||
| 2076 | |||
| 2077 | ata_ehi_hotplugged(ehi); | ||
| 2078 | |||
| 2079 | /* okay, let's hand over to EH */ | ||
| 2080 | ehi->serror |= serror; | ||
| 2081 | |||
| 2082 | ata_port_freeze(ap); | ||
| 2083 | } | ||
| 2084 | |||
| 2085 | static int nv_swncq_sdbfis(struct ata_port *ap) | ||
| 2086 | { | ||
| 2087 | struct ata_queued_cmd *qc; | ||
| 2088 | struct nv_swncq_port_priv *pp = ap->private_data; | ||
| 2089 | struct ata_eh_info *ehi = &ap->link.eh_info; | ||
| 2090 | u32 sactive; | ||
| 2091 | int nr_done = 0; | ||
| 2092 | u32 done_mask; | ||
| 2093 | int i; | ||
| 2094 | u8 host_stat; | ||
| 2095 | u8 lack_dhfis = 0; | ||
| 2096 | |||
| 2097 | host_stat = ap->ops->bmdma_status(ap); | ||
| 2098 | if (unlikely(host_stat & ATA_DMA_ERR)) { | ||
| 2099 | /* error when transfering data to/from memory */ | ||
| 2100 | ata_ehi_clear_desc(ehi); | ||
| 2101 | ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat); | ||
| 2102 | ehi->err_mask |= AC_ERR_HOST_BUS; | ||
| 2103 | ehi->action |= ATA_EH_SOFTRESET; | ||
| 2104 | return -EINVAL; | ||
| 2105 | } | ||
| 2106 | |||
| 2107 | ap->ops->irq_clear(ap); | ||
| 2108 | __ata_bmdma_stop(ap); | ||
| 2109 | |||
| 2110 | sactive = readl(pp->sactive_block); | ||
| 2111 | done_mask = pp->qc_active ^ sactive; | ||
| 2112 | |||
| 2113 | if (unlikely(done_mask & sactive)) { | ||
| 2114 | ata_ehi_clear_desc(ehi); | ||
| 2115 | ata_ehi_push_desc(ehi, "illegal SWNCQ:qc_active transition" | ||
| 2116 | "(%08x->%08x)", pp->qc_active, sactive); | ||
| 2117 | ehi->err_mask |= AC_ERR_HSM; | ||
| 2118 | ehi->action |= ATA_EH_HARDRESET; | ||
| 2119 | return -EINVAL; | ||
| 2120 | } | ||
| 2121 | for (i = 0; i < ATA_MAX_QUEUE; i++) { | ||
| 2122 | if (!(done_mask & (1 << i))) | ||
| 2123 | continue; | ||
| 2124 | |||
| 2125 | qc = ata_qc_from_tag(ap, i); | ||
| 2126 | if (qc) { | ||
| 2127 | ata_qc_complete(qc); | ||
| 2128 | pp->qc_active &= ~(1 << i); | ||
| 2129 | pp->dhfis_bits &= ~(1 << i); | ||
| 2130 | pp->dmafis_bits &= ~(1 << i); | ||
| 2131 | pp->sdbfis_bits |= (1 << i); | ||
| 2132 | nr_done++; | ||
| 2133 | } | ||
| 2134 | } | ||
| 2135 | |||
| 2136 | if (!ap->qc_active) { | ||
| 2137 | DPRINTK("over\n"); | ||
| 2138 | nv_swncq_pp_reinit(ap); | ||
| 2139 | return nr_done; | ||
| 2140 | } | ||
| 2141 | |||
| 2142 | if (pp->qc_active & pp->dhfis_bits) | ||
| 2143 | return nr_done; | ||
| 2144 | |||
| 2145 | if ((pp->ncq_flags & ncq_saw_backout) || | ||
| 2146 | (pp->qc_active ^ pp->dhfis_bits)) | ||
| 2147 | /* if the controller cann't get a device to host register FIS, | ||
| 2148 | * The driver needs to reissue the new command. | ||
| 2149 | */ | ||
| 2150 | lack_dhfis = 1; | ||
| 2151 | |||
| 2152 | DPRINTK("id 0x%x QC: qc_active 0x%x," | ||
| 2153 | "SWNCQ:qc_active 0x%X defer_bits %X " | ||
| 2154 | "dhfis 0x%X dmafis 0x%X last_issue_tag %x\n", | ||
| 2155 | ap->print_id, ap->qc_active, pp->qc_active, | ||
| 2156 | pp->defer_queue.defer_bits, pp->dhfis_bits, | ||
| 2157 | pp->dmafis_bits, pp->last_issue_tag); | ||
| 2158 | |||
| 2159 | nv_swncq_fis_reinit(ap); | ||
| 2160 | |||
| 2161 | if (lack_dhfis) { | ||
| 2162 | qc = ata_qc_from_tag(ap, pp->last_issue_tag); | ||
| 2163 | nv_swncq_issue_atacmd(ap, qc); | ||
| 2164 | return nr_done; | ||
| 2165 | } | ||
| 2166 | |||
| 2167 | if (pp->defer_queue.defer_bits) { | ||
| 2168 | /* send deferral queue command */ | ||
| 2169 | qc = nv_swncq_qc_from_dq(ap); | ||
| 2170 | WARN_ON(qc == NULL); | ||
| 2171 | nv_swncq_issue_atacmd(ap, qc); | ||
| 2172 | } | ||
| 2173 | |||
| 2174 | return nr_done; | ||
| 2175 | } | ||
| 2176 | |||
| 2177 | static inline u32 nv_swncq_tag(struct ata_port *ap) | ||
| 2178 | { | ||
| 2179 | struct nv_swncq_port_priv *pp = ap->private_data; | ||
| 2180 | u32 tag; | ||
| 2181 | |||
| 2182 | tag = readb(pp->tag_block) >> 2; | ||
| 2183 | return (tag & 0x1f); | ||
| 2184 | } | ||
| 2185 | |||
| 2186 | static int nv_swncq_dmafis(struct ata_port *ap) | ||
| 2187 | { | ||
| 2188 | struct ata_queued_cmd *qc; | ||
| 2189 | unsigned int rw; | ||
| 2190 | u8 dmactl; | ||
| 2191 | u32 tag; | ||
| 2192 | struct nv_swncq_port_priv *pp = ap->private_data; | ||
| 2193 | |||
| 2194 | __ata_bmdma_stop(ap); | ||
| 2195 | tag = nv_swncq_tag(ap); | ||
| 2196 | |||
| 2197 | DPRINTK("dma setup tag 0x%x\n", tag); | ||
| 2198 | qc = ata_qc_from_tag(ap, tag); | ||
| 2199 | |||
| 2200 | if (unlikely(!qc)) | ||
| 2201 | return 0; | ||
| 2202 | |||
| 2203 | rw = qc->tf.flags & ATA_TFLAG_WRITE; | ||
| 2204 | |||
| 2205 | /* load PRD table addr. */ | ||
| 2206 | iowrite32(pp->prd_dma + ATA_PRD_TBL_SZ * qc->tag, | ||
| 2207 | ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS); | ||
| 2208 | |||
| 2209 | /* specify data direction, triple-check start bit is clear */ | ||
| 2210 | dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD); | ||
| 2211 | dmactl &= ~ATA_DMA_WR; | ||
| 2212 | if (!rw) | ||
| 2213 | dmactl |= ATA_DMA_WR; | ||
| 2214 | |||
| 2215 | iowrite8(dmactl | ATA_DMA_START, ap->ioaddr.bmdma_addr + ATA_DMA_CMD); | ||
| 2216 | |||
| 2217 | return 1; | ||
| 2218 | } | ||
| 2219 | |||
| 2220 | static void nv_swncq_host_interrupt(struct ata_port *ap, u16 fis) | ||
| 2221 | { | ||
| 2222 | struct nv_swncq_port_priv *pp = ap->private_data; | ||
| 2223 | struct ata_queued_cmd *qc; | ||
| 2224 | struct ata_eh_info *ehi = &ap->link.eh_info; | ||
| 2225 | u32 serror; | ||
| 2226 | u8 ata_stat; | ||
| 2227 | int rc = 0; | ||
| 2228 | |||
| 2229 | ata_stat = ap->ops->check_status(ap); | ||
| 2230 | nv_swncq_irq_clear(ap, fis); | ||
| 2231 | if (!fis) | ||
| 2232 | return; | ||
| 2233 | |||
| 2234 | if (ap->pflags & ATA_PFLAG_FROZEN) | ||
| 2235 | return; | ||
| 2236 | |||
| 2237 | if (fis & NV_SWNCQ_IRQ_HOTPLUG) { | ||
| 2238 | nv_swncq_hotplug(ap, fis); | ||
| 2239 | return; | ||
| 2240 | } | ||
| 2241 | |||
| 2242 | if (!pp->qc_active) | ||
| 2243 | return; | ||
| 2244 | |||
| 2245 | if (ap->ops->scr_read(ap, SCR_ERROR, &serror)) | ||
| 2246 | return; | ||
| 2247 | ap->ops->scr_write(ap, SCR_ERROR, serror); | ||
| 2248 | |||
| 2249 | if (ata_stat & ATA_ERR) { | ||
| 2250 | ata_ehi_clear_desc(ehi); | ||
| 2251 | ata_ehi_push_desc(ehi, "Ata error. fis:0x%X", fis); | ||
| 2252 | ehi->err_mask |= AC_ERR_DEV; | ||
| 2253 | ehi->serror |= serror; | ||
| 2254 | ehi->action |= ATA_EH_SOFTRESET; | ||
| 2255 | ata_port_freeze(ap); | ||
| 2256 | return; | ||
| 2257 | } | ||
| 2258 | |||
| 2259 | if (fis & NV_SWNCQ_IRQ_BACKOUT) { | ||
| 2260 | /* If the IRQ is backout, driver must issue | ||
| 2261 | * the new command again some time later. | ||
| 2262 | */ | ||
| 2263 | pp->ncq_flags |= ncq_saw_backout; | ||
| 2264 | } | ||
| 2265 | |||
| 2266 | if (fis & NV_SWNCQ_IRQ_SDBFIS) { | ||
| 2267 | pp->ncq_flags |= ncq_saw_sdb; | ||
| 2268 | DPRINTK("id 0x%x SWNCQ: qc_active 0x%X " | ||
| 2269 | "dhfis 0x%X dmafis 0x%X sactive 0x%X\n", | ||
| 2270 | ap->print_id, pp->qc_active, pp->dhfis_bits, | ||
| 2271 | pp->dmafis_bits, readl(pp->sactive_block)); | ||
| 2272 | rc = nv_swncq_sdbfis(ap); | ||
| 2273 | if (rc < 0) | ||
| 2274 | goto irq_error; | ||
| 2275 | } | ||
| 2276 | |||
| 2277 | if (fis & NV_SWNCQ_IRQ_DHREGFIS) { | ||
| 2278 | /* The interrupt indicates the new command | ||
| 2279 | * was transmitted correctly to the drive. | ||
| 2280 | */ | ||
| 2281 | pp->dhfis_bits |= (0x1 << pp->last_issue_tag); | ||
| 2282 | pp->ncq_flags |= ncq_saw_d2h; | ||
| 2283 | if (pp->ncq_flags & (ncq_saw_sdb | ncq_saw_backout)) { | ||
| 2284 | ata_ehi_push_desc(ehi, "illegal fis transaction"); | ||
| 2285 | ehi->err_mask |= AC_ERR_HSM; | ||
| 2286 | ehi->action |= ATA_EH_HARDRESET; | ||
| 2287 | goto irq_error; | ||
| 2288 | } | ||
| 2289 | |||
| 2290 | if (!(fis & NV_SWNCQ_IRQ_DMASETUP) && | ||
| 2291 | !(pp->ncq_flags & ncq_saw_dmas)) { | ||
| 2292 | ata_stat = ap->ops->check_status(ap); | ||
| 2293 | if (ata_stat & ATA_BUSY) | ||
| 2294 | goto irq_exit; | ||
| 2295 | |||
| 2296 | if (pp->defer_queue.defer_bits) { | ||
| 2297 | DPRINTK("send next command\n"); | ||
| 2298 | qc = nv_swncq_qc_from_dq(ap); | ||
| 2299 | nv_swncq_issue_atacmd(ap, qc); | ||
| 2300 | } | ||
| 2301 | } | ||
| 2302 | } | ||
| 2303 | |||
| 2304 | if (fis & NV_SWNCQ_IRQ_DMASETUP) { | ||
| 2305 | /* program the dma controller with appropriate PRD buffers | ||
| 2306 | * and start the DMA transfer for requested command. | ||
| 2307 | */ | ||
| 2308 | pp->dmafis_bits |= (0x1 << nv_swncq_tag(ap)); | ||
| 2309 | pp->ncq_flags |= ncq_saw_dmas; | ||
| 2310 | rc = nv_swncq_dmafis(ap); | ||
| 2311 | } | ||
| 2312 | |||
| 2313 | irq_exit: | ||
| 2314 | return; | ||
| 2315 | irq_error: | ||
| 2316 | ata_ehi_push_desc(ehi, "fis:0x%x", fis); | ||
| 2317 | ata_port_freeze(ap); | ||
| 2318 | return; | ||
| 2319 | } | ||
| 2320 | |||
| 2321 | static irqreturn_t nv_swncq_interrupt(int irq, void *dev_instance) | ||
| 2322 | { | ||
| 2323 | struct ata_host *host = dev_instance; | ||
| 2324 | unsigned int i; | ||
| 2325 | unsigned int handled = 0; | ||
| 2326 | unsigned long flags; | ||
| 2327 | u32 irq_stat; | ||
| 2328 | |||
| 2329 | spin_lock_irqsave(&host->lock, flags); | ||
| 2330 | |||
| 2331 | irq_stat = readl(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_MCP55); | ||
| 2332 | |||
| 2333 | for (i = 0; i < host->n_ports; i++) { | ||
| 2334 | struct ata_port *ap = host->ports[i]; | ||
| 2335 | |||
| 2336 | if (ap && !(ap->flags & ATA_FLAG_DISABLED)) { | ||
| 2337 | if (ap->link.sactive) { | ||
| 2338 | nv_swncq_host_interrupt(ap, (u16)irq_stat); | ||
| 2339 | handled = 1; | ||
| 2340 | } else { | ||
| 2341 | if (irq_stat) /* reserve Hotplug */ | ||
| 2342 | nv_swncq_irq_clear(ap, 0xfff0); | ||
| 2343 | |||
| 2344 | handled += nv_host_intr(ap, (u8)irq_stat); | ||
| 2345 | } | ||
| 2346 | } | ||
| 2347 | irq_stat >>= NV_INT_PORT_SHIFT_MCP55; | ||
| 2348 | } | ||
| 2349 | |||
| 2350 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 2351 | |||
| 2352 | return IRQ_RETVAL(handled); | ||
| 2353 | } | ||
| 2354 | |||
| 1528 | static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | 2355 | static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) |
| 1529 | { | 2356 | { |
| 1530 | static int printed_version = 0; | 2357 | static int printed_version = 0; |
| @@ -1551,7 +2378,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 1551 | return rc; | 2378 | return rc; |
| 1552 | 2379 | ||
| 1553 | /* determine type and allocate host */ | 2380 | /* determine type and allocate host */ |
| 1554 | if (type >= CK804 && adma_enabled) { | 2381 | if (type == CK804 && adma_enabled) { |
| 1555 | dev_printk(KERN_NOTICE, &pdev->dev, "Using ADMA mode\n"); | 2382 | dev_printk(KERN_NOTICE, &pdev->dev, "Using ADMA mode\n"); |
| 1556 | type = ADMA; | 2383 | type = ADMA; |
| 1557 | } | 2384 | } |
| @@ -1597,6 +2424,9 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 1597 | rc = nv_adma_host_init(host); | 2424 | rc = nv_adma_host_init(host); |
| 1598 | if (rc) | 2425 | if (rc) |
| 1599 | return rc; | 2426 | return rc; |
| 2427 | } else if (type == SWNCQ && swncq_enabled) { | ||
| 2428 | dev_printk(KERN_NOTICE, &pdev->dev, "Using SWNCQ mode\n"); | ||
| 2429 | nv_swncq_host_init(host); | ||
| 1600 | } | 2430 | } |
| 1601 | 2431 | ||
| 1602 | pci_set_master(pdev); | 2432 | pci_set_master(pdev); |
| @@ -1696,3 +2526,6 @@ module_init(nv_init); | |||
| 1696 | module_exit(nv_exit); | 2526 | module_exit(nv_exit); |
| 1697 | module_param_named(adma, adma_enabled, bool, 0444); | 2527 | module_param_named(adma, adma_enabled, bool, 0444); |
| 1698 | MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: true)"); | 2528 | MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: true)"); |
| 2529 | module_param_named(swncq, swncq_enabled, bool, 0444); | ||
| 2530 | MODULE_PARM_DESC(swncq, "Enable use of SWNCQ (Default: false)"); | ||
| 2531 | |||
diff --git a/drivers/char/ec3104_keyb.c b/drivers/char/ec3104_keyb.c deleted file mode 100644 index 020011495d91..000000000000 --- a/drivers/char/ec3104_keyb.c +++ /dev/null | |||
| @@ -1,457 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * linux/drivers/char/ec3104_keyb.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> | ||
| 5 | * | ||
| 6 | * based on linux/drivers/char/pc_keyb.c, which had the following comments: | ||
| 7 | * | ||
| 8 | * Separation of the PC low-level part by Geert Uytterhoeven, May 1997 | ||
| 9 | * See keyboard.c for the whole history. | ||
| 10 | * | ||
| 11 | * Major cleanup by Martin Mares, May 1997 | ||
| 12 | * | ||
| 13 | * Combined the keyboard and PS/2 mouse handling into one file, | ||
| 14 | * because they share the same hardware. | ||
| 15 | * Johan Myreen <jem@iki.fi> 1998-10-08. | ||
| 16 | * | ||
| 17 | * Code fixes to handle mouse ACKs properly. | ||
| 18 | * C. Scott Ananian <cananian@alumni.princeton.edu> 1999-01-29. | ||
| 19 | */ | ||
| 20 | /* EC3104 note: | ||
| 21 | * This code was written without any documentation about the EC3104 chip. While | ||
| 22 | * I hope I got most of the basic functionality right, the register names I use | ||
| 23 | * are most likely completely different from those in the chip documentation. | ||
| 24 | * | ||
| 25 | * If you have any further information about the EC3104, please tell me | ||
| 26 | * (prumpf@tux.org). | ||
| 27 | */ | ||
| 28 | |||
| 29 | |||
| 30 | #include <linux/spinlock.h> | ||
| 31 | #include <linux/sched.h> | ||
| 32 | #include <linux/interrupt.h> | ||
| 33 | #include <linux/tty.h> | ||
| 34 | #include <linux/mm.h> | ||
| 35 | #include <linux/signal.h> | ||
| 36 | #include <linux/init.h> | ||
| 37 | #include <linux/kbd_ll.h> | ||
| 38 | #include <linux/delay.h> | ||
| 39 | #include <linux/random.h> | ||
| 40 | #include <linux/poll.h> | ||
| 41 | #include <linux/miscdevice.h> | ||
| 42 | #include <linux/slab.h> | ||
| 43 | #include <linux/kbd_kern.h> | ||
| 44 | #include <linux/bitops.h> | ||
| 45 | |||
| 46 | #include <asm/keyboard.h> | ||
| 47 | #include <asm/uaccess.h> | ||
| 48 | #include <asm/irq.h> | ||
| 49 | #include <asm/system.h> | ||
| 50 | #include <asm/ec3104.h> | ||
| 51 | |||
| 52 | #include <asm/io.h> | ||
| 53 | |||
| 54 | /* Some configuration switches are present in the include file... */ | ||
| 55 | |||
| 56 | #include <linux/pc_keyb.h> | ||
| 57 | |||
| 58 | #define MSR_CTS 0x10 | ||
| 59 | #define MCR_RTS 0x02 | ||
| 60 | #define LSR_DR 0x01 | ||
| 61 | #define LSR_BOTH_EMPTY 0x60 | ||
| 62 | |||
| 63 | static struct e5_struct { | ||
| 64 | u8 packet[8]; | ||
| 65 | int pos; | ||
| 66 | int length; | ||
| 67 | |||
| 68 | u8 cached_mcr; | ||
| 69 | u8 last_msr; | ||
| 70 | } ec3104_keyb; | ||
| 71 | |||
| 72 | /* Simple translation table for the SysRq keys */ | ||
| 73 | |||
| 74 | |||
| 75 | #ifdef CONFIG_MAGIC_SYSRQ | ||
| 76 | unsigned char ec3104_kbd_sysrq_xlate[128] = | ||
| 77 | "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ | ||
| 78 | "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ | ||
| 79 | "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ | ||
| 80 | "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */ | ||
| 81 | "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */ | ||
| 82 | "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ | ||
| 83 | "\r\000/"; /* 0x60 - 0x6f */ | ||
| 84 | #endif | ||
| 85 | |||
| 86 | static void kbd_write_command_w(int data); | ||
| 87 | static void kbd_write_output_w(int data); | ||
| 88 | #ifdef CONFIG_PSMOUSE | ||
| 89 | static void aux_write_ack(int val); | ||
| 90 | static void __aux_write_ack(int val); | ||
| 91 | #endif | ||
| 92 | |||
| 93 | static DEFINE_SPINLOCK(kbd_controller_lock); | ||
| 94 | static unsigned char handle_kbd_event(void); | ||
| 95 | |||
| 96 | /* used only by send_data - set by keyboard_interrupt */ | ||
| 97 | static volatile unsigned char reply_expected; | ||
| 98 | static volatile unsigned char acknowledge; | ||
| 99 | static volatile unsigned char resend; | ||
| 100 | |||
| 101 | |||
| 102 | int ec3104_kbd_setkeycode(unsigned int scancode, unsigned int keycode) | ||
| 103 | { | ||
| 104 | return 0; | ||
| 105 | } | ||
| 106 | |||
| 107 | int ec3104_kbd_getkeycode(unsigned int scancode) | ||
| 108 | { | ||
| 109 | return 0; | ||
| 110 | } | ||
| 111 | |||
| 112 | |||
| 113 | /* yes, it probably would be faster to use an array. I don't care. */ | ||
| 114 | |||
| 115 | static inline unsigned char ec3104_scan2key(unsigned char scancode) | ||
| 116 | { | ||
| 117 | switch (scancode) { | ||
| 118 | case 1: /* '`' */ | ||
| 119 | return 41; | ||
| 120 | |||
| 121 | case 2 ... 27: | ||
| 122 | return scancode; | ||
| 123 | |||
| 124 | case 28: /* '\\' */ | ||
| 125 | return 43; | ||
| 126 | |||
| 127 | case 29 ... 39: | ||
| 128 | return scancode + 1; | ||
| 129 | |||
| 130 | case 40: /* '\r' */ | ||
| 131 | return 28; | ||
| 132 | |||
| 133 | case 41 ... 50: | ||
| 134 | return scancode + 3; | ||
| 135 | |||
| 136 | case 51: /* ' ' */ | ||
| 137 | return 57; | ||
| 138 | |||
| 139 | case 52: /* escape */ | ||
| 140 | return 1; | ||
| 141 | |||
| 142 | case 54: /* insert/delete (labelled delete) */ | ||
| 143 | /* this should arguably be 110, but I'd like to have ctrl-alt-del | ||
| 144 | * working with a standard keymap */ | ||
| 145 | return 111; | ||
| 146 | |||
| 147 | case 55: /* left */ | ||
| 148 | return 105; | ||
| 149 | case 56: /* home */ | ||
| 150 | return 102; | ||
| 151 | case 57: /* end */ | ||
| 152 | return 107; | ||
| 153 | case 58: /* up */ | ||
| 154 | return 103; | ||
| 155 | case 59: /* down */ | ||
| 156 | return 108; | ||
| 157 | case 60: /* pgup */ | ||
| 158 | return 104; | ||
| 159 | case 61: /* pgdown */ | ||
| 160 | return 109; | ||
| 161 | case 62: /* right */ | ||
| 162 | return 106; | ||
| 163 | |||
| 164 | case 79 ... 88: /* f1 - f10 */ | ||
| 165 | return scancode - 20; | ||
| 166 | |||
| 167 | case 89 ... 90: /* f11 - f12 */ | ||
| 168 | return scancode - 2; | ||
| 169 | |||
| 170 | case 91: /* left shift */ | ||
| 171 | return 42; | ||
| 172 | |||
| 173 | case 92: /* right shift */ | ||
| 174 | return 54; | ||
| 175 | |||
| 176 | case 93: /* left alt */ | ||
| 177 | return 56; | ||
| 178 | case 94: /* right alt */ | ||
| 179 | return 100; | ||
| 180 | case 95: /* left ctrl */ | ||
| 181 | return 29; | ||
| 182 | case 96: /* right ctrl */ | ||
| 183 | return 97; | ||
| 184 | |||
| 185 | case 97: /* caps lock */ | ||
| 186 | return 58; | ||
| 187 | case 102: /* left windows */ | ||
| 188 | return 125; | ||
| 189 | case 103: /* right windows */ | ||
| 190 | return 126; | ||
| 191 | |||
| 192 | case 106: /* Fn */ | ||
| 193 | /* this is wrong. */ | ||
| 194 | return 84; | ||
| 195 | |||
| 196 | default: | ||
| 197 | return 0; | ||
| 198 | } | ||
| 199 | } | ||
| 200 | |||
| 201 | int ec3104_kbd_translate(unsigned char scancode, unsigned char *keycode, | ||
| 202 | char raw_mode) | ||
| 203 | { | ||
| 204 | scancode &= 0x7f; | ||
| 205 | |||
| 206 | *keycode = ec3104_scan2key(scancode); | ||
| 207 | |||
| 208 | return 1; | ||
| 209 | } | ||
| 210 | |||
| 211 | char ec3104_kbd_unexpected_up(unsigned char keycode) | ||
| 212 | { | ||
| 213 | return 0200; | ||
| 214 | } | ||
| 215 | |||
| 216 | static inline void handle_keyboard_event(unsigned char scancode) | ||
| 217 | { | ||
| 218 | #ifdef CONFIG_VT | ||
| 219 | handle_scancode(scancode, !(scancode & 0x80)); | ||
| 220 | #endif | ||
| 221 | tasklet_schedule(&keyboard_tasklet); | ||
| 222 | } | ||
| 223 | |||
| 224 | void ec3104_kbd_leds(unsigned char leds) | ||
| 225 | { | ||
| 226 | } | ||
| 227 | |||
| 228 | static u8 e5_checksum(u8 *packet, int count) | ||
| 229 | { | ||
| 230 | int i; | ||
| 231 | u8 sum = 0; | ||
| 232 | |||
| 233 | for (i=0; i<count; i++) | ||
| 234 | sum ^= packet[i]; | ||
| 235 | |||
| 236 | if (sum & 0x80) | ||
| 237 | sum ^= 0xc0; | ||
| 238 | |||
| 239 | return sum; | ||
| 240 | } | ||
| 241 | |||
| 242 | static void e5_wait_for_cts(struct e5_struct *k) | ||
| 243 | { | ||
| 244 | u8 msr; | ||
| 245 | |||
| 246 | do { | ||
| 247 | msr = ctrl_inb(EC3104_SER4_MSR); | ||
| 248 | } while (!(msr & MSR_CTS)); | ||
| 249 | } | ||
| 250 | |||
| 251 | |||
| 252 | static void e5_send_byte(u8 byte, struct e5_struct *k) | ||
| 253 | { | ||
| 254 | u8 status; | ||
| 255 | |||
| 256 | do { | ||
| 257 | status = ctrl_inb(EC3104_SER4_LSR); | ||
| 258 | } while ((status & LSR_BOTH_EMPTY) != LSR_BOTH_EMPTY); | ||
| 259 | |||
| 260 | printk("<%02x>", byte); | ||
| 261 | |||
| 262 | ctrl_outb(byte, EC3104_SER4_DATA); | ||
| 263 | |||
| 264 | do { | ||
| 265 | status = ctrl_inb(EC3104_SER4_LSR); | ||
| 266 | } while ((status & LSR_BOTH_EMPTY) != LSR_BOTH_EMPTY); | ||
| 267 | |||
| 268 | } | ||
| 269 | |||
| 270 | static int e5_send_packet(u8 *packet, int count, struct e5_struct *k) | ||
| 271 | { | ||
| 272 | int i; | ||
| 273 | |||
| 274 | disable_irq(EC3104_IRQ_SER4); | ||
| 275 | |||
| 276 | if (k->cached_mcr & MCR_RTS) { | ||
| 277 | printk("e5_send_packet: too slow\n"); | ||
| 278 | enable_irq(EC3104_IRQ_SER4); | ||
| 279 | return -EAGAIN; | ||
| 280 | } | ||
| 281 | |||
| 282 | k->cached_mcr |= MCR_RTS; | ||
| 283 | ctrl_outb(k->cached_mcr, EC3104_SER4_MCR); | ||
| 284 | |||
| 285 | e5_wait_for_cts(k); | ||
| 286 | |||
| 287 | printk("p: "); | ||
| 288 | |||
| 289 | for(i=0; i<count; i++) | ||
| 290 | e5_send_byte(packet[i], k); | ||
| 291 | |||
| 292 | e5_send_byte(e5_checksum(packet, count), k); | ||
| 293 | |||
| 294 | printk("\n"); | ||
| 295 | |||
| 296 | udelay(1500); | ||
| 297 | |||
| 298 | k->cached_mcr &= ~MCR_RTS; | ||
| 299 | ctrl_outb(k->cached_mcr, EC3104_SER4_MCR); | ||
| 300 | |||
| 301 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
| 302 | |||
| 303 | |||
| 304 | |||
| 305 | enable_irq(EC3104_IRQ_SER4); | ||
| 306 | |||
| 307 | |||
| 308 | |||
| 309 | return 0; | ||
| 310 | } | ||
| 311 | |||
| 312 | /* | ||
| 313 | * E5 packets we know about: | ||
| 314 | * E5->host 0x80 0x05 <checksum> - resend packet | ||
| 315 | * host->E5 0x83 0x43 <contrast> - set LCD contrast | ||
| 316 | * host->E5 0x85 0x41 0x02 <brightness> 0x02 - set LCD backlight | ||
| 317 | * E5->host 0x87 <ps2 packet> 0x00 <checksum> - external PS2 | ||
| 318 | * E5->host 0x88 <scancode> <checksum> - key press | ||
| 319 | */ | ||
| 320 | |||
| 321 | static void e5_receive(struct e5_struct *k) | ||
| 322 | { | ||
| 323 | k->packet[k->pos++] = ctrl_inb(EC3104_SER4_DATA); | ||
| 324 | |||
| 325 | if (k->pos == 1) { | ||
| 326 | switch(k->packet[0]) { | ||
| 327 | case 0x80: | ||
| 328 | k->length = 3; | ||
| 329 | break; | ||
| 330 | |||
| 331 | case 0x87: /* PS2 ext */ | ||
| 332 | k->length = 6; | ||
| 333 | break; | ||
| 334 | |||
| 335 | case 0x88: /* keyboard */ | ||
| 336 | k->length = 3; | ||
| 337 | break; | ||
| 338 | |||
| 339 | default: | ||
| 340 | k->length = 1; | ||
| 341 | printk(KERN_WARNING "unknown E5 packet %02x\n", | ||
| 342 | k->packet[0]); | ||
| 343 | } | ||
| 344 | } | ||
| 345 | |||
| 346 | if (k->pos == k->length) { | ||
| 347 | int i; | ||
| 348 | |||
| 349 | if (e5_checksum(k->packet, k->length) != 0) | ||
| 350 | printk(KERN_WARNING "E5: wrong checksum\n"); | ||
| 351 | |||
| 352 | #if 0 | ||
| 353 | printk("E5 packet ["); | ||
| 354 | for(i=0; i<k->length; i++) { | ||
| 355 | printk("%02x ", k->packet[i]); | ||
| 356 | } | ||
| 357 | |||
| 358 | printk("(%02x)]\n", e5_checksum(k->packet, k->length-1)); | ||
| 359 | #endif | ||
| 360 | |||
| 361 | switch(k->packet[0]) { | ||
| 362 | case 0x80: | ||
| 363 | case 0x88: | ||
| 364 | handle_keyboard_event(k->packet[1]); | ||
| 365 | break; | ||
| 366 | } | ||
| 367 | |||
| 368 | k->pos = k->length = 0; | ||
| 369 | } | ||
| 370 | } | ||
| 371 | |||
| 372 | static void ec3104_keyb_interrupt(int irq, void *data) | ||
| 373 | { | ||
| 374 | struct e5_struct *k = &ec3104_keyb; | ||
| 375 | u8 msr, lsr; | ||
| 376 | |||
| 377 | msr = ctrl_inb(EC3104_SER4_MSR); | ||
| 378 | |||
| 379 | if ((msr & MSR_CTS) && !(k->last_msr & MSR_CTS)) { | ||
| 380 | if (k->cached_mcr & MCR_RTS) | ||
| 381 | printk("confused: RTS already high\n"); | ||
| 382 | /* CTS went high. Send RTS. */ | ||
| 383 | k->cached_mcr |= MCR_RTS; | ||
| 384 | |||
| 385 | ctrl_outb(k->cached_mcr, EC3104_SER4_MCR); | ||
| 386 | } else if ((!(msr & MSR_CTS)) && (k->last_msr & MSR_CTS)) { | ||
| 387 | /* CTS went low. */ | ||
| 388 | if (!(k->cached_mcr & MCR_RTS)) | ||
| 389 | printk("confused: RTS already low\n"); | ||
| 390 | |||
| 391 | k->cached_mcr &= ~MCR_RTS; | ||
| 392 | |||
| 393 | ctrl_outb(k->cached_mcr, EC3104_SER4_MCR); | ||
| 394 | } | ||
| 395 | |||
| 396 | k->last_msr = msr; | ||
| 397 | |||
| 398 | lsr = ctrl_inb(EC3104_SER4_LSR); | ||
| 399 | |||
| 400 | if (lsr & LSR_DR) | ||
| 401 | e5_receive(k); | ||
| 402 | } | ||
| 403 | |||
| 404 | static void ec3104_keyb_clear_state(void) | ||
| 405 | { | ||
| 406 | struct e5_struct *k = &ec3104_keyb; | ||
| 407 | u8 msr, lsr; | ||
| 408 | |||
| 409 | /* we want CTS to be low */ | ||
| 410 | k->last_msr = 0; | ||
| 411 | |||
| 412 | for (;;) { | ||
| 413 | msleep(100); | ||
| 414 | |||
| 415 | msr = ctrl_inb(EC3104_SER4_MSR); | ||
| 416 | |||
| 417 | lsr = ctrl_inb(EC3104_SER4_LSR); | ||
| 418 | |||
| 419 | if (lsr & LSR_DR) { | ||
| 420 | e5_receive(k); | ||
| 421 | continue; | ||
| 422 | } | ||
| 423 | |||
| 424 | if ((msr & MSR_CTS) && !(k->last_msr & MSR_CTS)) { | ||
| 425 | if (k->cached_mcr & MCR_RTS) | ||
| 426 | printk("confused: RTS already high\n"); | ||
| 427 | /* CTS went high. Send RTS. */ | ||
| 428 | k->cached_mcr |= MCR_RTS; | ||
| 429 | |||
| 430 | ctrl_outb(k->cached_mcr, EC3104_SER4_MCR); | ||
| 431 | } else if ((!(msr & MSR_CTS)) && (k->last_msr & MSR_CTS)) { | ||
| 432 | /* CTS went low. */ | ||
| 433 | if (!(k->cached_mcr & MCR_RTS)) | ||
| 434 | printk("confused: RTS already low\n"); | ||
| 435 | |||
| 436 | k->cached_mcr &= ~MCR_RTS; | ||
| 437 | |||
| 438 | ctrl_outb(k->cached_mcr, EC3104_SER4_MCR); | ||
| 439 | } else | ||
| 440 | break; | ||
| 441 | |||
| 442 | k->last_msr = msr; | ||
| 443 | |||
| 444 | continue; | ||
| 445 | } | ||
| 446 | } | ||
| 447 | |||
| 448 | void __init ec3104_kbd_init_hw(void) | ||
| 449 | { | ||
| 450 | ec3104_keyb.last_msr = ctrl_inb(EC3104_SER4_MSR); | ||
| 451 | ec3104_keyb.cached_mcr = ctrl_inb(EC3104_SER4_MCR); | ||
| 452 | |||
| 453 | ec3104_keyb_clear_state(); | ||
| 454 | |||
| 455 | /* Ok, finally allocate the IRQ, and off we go.. */ | ||
| 456 | request_irq(EC3104_IRQ_SER4, ec3104_keyb_interrupt, 0, "keyboard", NULL); | ||
| 457 | } | ||
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index e47f88170806..700a1657554f 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
| @@ -158,6 +158,7 @@ config SENSORS_K8TEMP | |||
| 158 | config SENSORS_AMS | 158 | config SENSORS_AMS |
| 159 | tristate "Apple Motion Sensor driver" | 159 | tristate "Apple Motion Sensor driver" |
| 160 | depends on PPC_PMAC && !PPC64 && INPUT && ((ADB_PMU && I2C = y) || (ADB_PMU && !I2C) || I2C) && EXPERIMENTAL | 160 | depends on PPC_PMAC && !PPC64 && INPUT && ((ADB_PMU && I2C = y) || (ADB_PMU && !I2C) || I2C) && EXPERIMENTAL |
| 161 | select INPUT_POLLDEV | ||
| 161 | help | 162 | help |
| 162 | Support for the motion sensor included in PowerBooks. Includes | 163 | Support for the motion sensor included in PowerBooks. Includes |
| 163 | implementations for PMU and I2C. | 164 | implementations for PMU and I2C. |
| @@ -701,6 +702,7 @@ config SENSORS_W83627EHF | |||
| 701 | config SENSORS_HDAPS | 702 | config SENSORS_HDAPS |
| 702 | tristate "IBM Hard Drive Active Protection System (hdaps)" | 703 | tristate "IBM Hard Drive Active Protection System (hdaps)" |
| 703 | depends on INPUT && X86 | 704 | depends on INPUT && X86 |
| 705 | select INPUT_POLLDEV | ||
| 704 | default n | 706 | default n |
| 705 | help | 707 | help |
| 706 | This driver provides support for the IBM Hard Drive Active Protection | 708 | This driver provides support for the IBM Hard Drive Active Protection |
| @@ -722,6 +724,7 @@ config SENSORS_APPLESMC | |||
| 722 | depends on INPUT && X86 | 724 | depends on INPUT && X86 |
| 723 | select NEW_LEDS | 725 | select NEW_LEDS |
| 724 | select LEDS_CLASS | 726 | select LEDS_CLASS |
| 727 | select INPUT_POLLDEV | ||
| 725 | default n | 728 | default n |
| 726 | help | 729 | help |
| 727 | This driver provides support for the Apple System Management | 730 | This driver provides support for the Apple System Management |
diff --git a/drivers/hwmon/ams/ams-input.c b/drivers/hwmon/ams/ams-input.c index ca7095d96ad0..7b81e0c2c2d9 100644 --- a/drivers/hwmon/ams/ams-input.c +++ b/drivers/hwmon/ams/ams-input.c | |||
| @@ -27,47 +27,32 @@ static unsigned int invert; | |||
| 27 | module_param(invert, bool, 0644); | 27 | module_param(invert, bool, 0644); |
| 28 | MODULE_PARM_DESC(invert, "Invert input data on X and Y axis"); | 28 | MODULE_PARM_DESC(invert, "Invert input data on X and Y axis"); |
| 29 | 29 | ||
| 30 | static int ams_input_kthread(void *data) | 30 | static void ams_idev_poll(struct input_polled_dev *dev) |
| 31 | { | 31 | { |
| 32 | struct input_dev *idev = dev->input; | ||
| 32 | s8 x, y, z; | 33 | s8 x, y, z; |
| 33 | 34 | ||
| 34 | while (!kthread_should_stop()) { | 35 | mutex_lock(&ams_info.lock); |
| 35 | mutex_lock(&ams_info.lock); | ||
| 36 | |||
| 37 | ams_sensors(&x, &y, &z); | ||
| 38 | |||
| 39 | x -= ams_info.xcalib; | ||
| 40 | y -= ams_info.ycalib; | ||
| 41 | z -= ams_info.zcalib; | ||
| 42 | |||
| 43 | input_report_abs(ams_info.idev, ABS_X, invert ? -x : x); | ||
| 44 | input_report_abs(ams_info.idev, ABS_Y, invert ? -y : y); | ||
| 45 | input_report_abs(ams_info.idev, ABS_Z, z); | ||
| 46 | 36 | ||
| 47 | input_sync(ams_info.idev); | 37 | ams_sensors(&x, &y, &z); |
| 48 | 38 | ||
| 49 | mutex_unlock(&ams_info.lock); | 39 | x -= ams_info.xcalib; |
| 40 | y -= ams_info.ycalib; | ||
| 41 | z -= ams_info.zcalib; | ||
| 50 | 42 | ||
| 51 | msleep(25); | 43 | input_report_abs(idev, ABS_X, invert ? -x : x); |
| 52 | } | 44 | input_report_abs(idev, ABS_Y, invert ? -y : y); |
| 45 | input_report_abs(idev, ABS_Z, z); | ||
| 53 | 46 | ||
| 54 | return 0; | 47 | input_sync(idev); |
| 55 | } | ||
| 56 | 48 | ||
| 57 | static int ams_input_open(struct input_dev *dev) | 49 | mutex_unlock(&ams_info.lock); |
| 58 | { | ||
| 59 | ams_info.kthread = kthread_run(ams_input_kthread, NULL, "kams"); | ||
| 60 | return IS_ERR(ams_info.kthread) ? PTR_ERR(ams_info.kthread) : 0; | ||
| 61 | } | ||
| 62 | |||
| 63 | static void ams_input_close(struct input_dev *dev) | ||
| 64 | { | ||
| 65 | kthread_stop(ams_info.kthread); | ||
| 66 | } | 50 | } |
| 67 | 51 | ||
| 68 | /* Call with ams_info.lock held! */ | 52 | /* Call with ams_info.lock held! */ |
| 69 | static void ams_input_enable(void) | 53 | static void ams_input_enable(void) |
| 70 | { | 54 | { |
| 55 | struct input_dev *input; | ||
| 71 | s8 x, y, z; | 56 | s8 x, y, z; |
| 72 | 57 | ||
| 73 | if (ams_info.idev) | 58 | if (ams_info.idev) |
| @@ -78,27 +63,29 @@ static void ams_input_enable(void) | |||
| 78 | ams_info.ycalib = y; | 63 | ams_info.ycalib = y; |
| 79 | ams_info.zcalib = z; | 64 | ams_info.zcalib = z; |
| 80 | 65 | ||
| 81 | ams_info.idev = input_allocate_device(); | 66 | ams_info.idev = input_allocate_polled_device(); |
| 82 | if (!ams_info.idev) | 67 | if (!ams_info.idev) |
| 83 | return; | 68 | return; |
| 84 | 69 | ||
| 85 | ams_info.idev->name = "Apple Motion Sensor"; | 70 | ams_info.idev->poll = ams_idev_poll; |
| 86 | ams_info.idev->id.bustype = ams_info.bustype; | 71 | ams_info.idev->poll_interval = 25; |
| 87 | ams_info.idev->id.vendor = 0; | 72 | |
| 88 | ams_info.idev->open = ams_input_open; | 73 | input = ams_info.idev->input; |
| 89 | ams_info.idev->close = ams_input_close; | 74 | input->name = "Apple Motion Sensor"; |
| 90 | ams_info.idev->dev.parent = &ams_info.of_dev->dev; | 75 | input->id.bustype = ams_info.bustype; |
| 76 | input->id.vendor = 0; | ||
| 77 | input->dev.parent = &ams_info.of_dev->dev; | ||
| 91 | 78 | ||
| 92 | input_set_abs_params(ams_info.idev, ABS_X, -50, 50, 3, 0); | 79 | input_set_abs_params(input, ABS_X, -50, 50, 3, 0); |
| 93 | input_set_abs_params(ams_info.idev, ABS_Y, -50, 50, 3, 0); | 80 | input_set_abs_params(input, ABS_Y, -50, 50, 3, 0); |
| 94 | input_set_abs_params(ams_info.idev, ABS_Z, -50, 50, 3, 0); | 81 | input_set_abs_params(input, ABS_Z, -50, 50, 3, 0); |
| 95 | 82 | ||
| 96 | set_bit(EV_ABS, ams_info.idev->evbit); | 83 | set_bit(EV_ABS, input->evbit); |
| 97 | set_bit(EV_KEY, ams_info.idev->evbit); | 84 | set_bit(EV_KEY, input->evbit); |
| 98 | set_bit(BTN_TOUCH, ams_info.idev->keybit); | 85 | set_bit(BTN_TOUCH, input->keybit); |
| 99 | 86 | ||
| 100 | if (input_register_device(ams_info.idev)) { | 87 | if (input_register_polled_device(ams_info.idev)) { |
| 101 | input_free_device(ams_info.idev); | 88 | input_free_polled_device(ams_info.idev); |
| 102 | ams_info.idev = NULL; | 89 | ams_info.idev = NULL; |
| 103 | return; | 90 | return; |
| 104 | } | 91 | } |
| @@ -108,7 +95,8 @@ static void ams_input_enable(void) | |||
| 108 | static void ams_input_disable(void) | 95 | static void ams_input_disable(void) |
| 109 | { | 96 | { |
| 110 | if (ams_info.idev) { | 97 | if (ams_info.idev) { |
| 111 | input_unregister_device(ams_info.idev); | 98 | input_unregister_polled_device(ams_info.idev); |
| 99 | input_free_polled_device(ams_info.idev); | ||
| 112 | ams_info.idev = NULL; | 100 | ams_info.idev = NULL; |
| 113 | } | 101 | } |
| 114 | } | 102 | } |
diff --git a/drivers/hwmon/ams/ams.h b/drivers/hwmon/ams/ams.h index 240730e6bcde..a6221e5dd984 100644 --- a/drivers/hwmon/ams/ams.h +++ b/drivers/hwmon/ams/ams.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | #include <linux/i2c.h> | 1 | #include <linux/i2c.h> |
| 2 | #include <linux/input.h> | 2 | #include <linux/input-polldev.h> |
| 3 | #include <linux/kthread.h> | 3 | #include <linux/kthread.h> |
| 4 | #include <linux/mutex.h> | 4 | #include <linux/mutex.h> |
| 5 | #include <linux/spinlock.h> | 5 | #include <linux/spinlock.h> |
| @@ -52,8 +52,7 @@ struct ams { | |||
| 52 | #endif | 52 | #endif |
| 53 | 53 | ||
| 54 | /* Joystick emulation */ | 54 | /* Joystick emulation */ |
| 55 | struct task_struct *kthread; | 55 | struct input_polled_dev *idev; |
| 56 | struct input_dev *idev; | ||
| 57 | __u16 bustype; | 56 | __u16 bustype; |
| 58 | 57 | ||
| 59 | /* calibrated null values */ | 58 | /* calibrated null values */ |
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index f37fd7ebf65a..4879125b4cdc 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c | |||
| @@ -28,7 +28,7 @@ | |||
| 28 | 28 | ||
| 29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
| 30 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
| 31 | #include <linux/input.h> | 31 | #include <linux/input-polldev.h> |
| 32 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
| 33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
| 34 | #include <linux/timer.h> | 34 | #include <linux/timer.h> |
| @@ -59,9 +59,9 @@ | |||
| 59 | 59 | ||
| 60 | #define LIGHT_SENSOR_LEFT_KEY "ALV0" /* r-o {alv (6 bytes) */ | 60 | #define LIGHT_SENSOR_LEFT_KEY "ALV0" /* r-o {alv (6 bytes) */ |
| 61 | #define LIGHT_SENSOR_RIGHT_KEY "ALV1" /* r-o {alv (6 bytes) */ | 61 | #define LIGHT_SENSOR_RIGHT_KEY "ALV1" /* r-o {alv (6 bytes) */ |
| 62 | #define BACKLIGHT_KEY "LKSB" /* w-o {lkb (2 bytes) */ | 62 | #define BACKLIGHT_KEY "LKSB" /* w-o {lkb (2 bytes) */ |
| 63 | 63 | ||
| 64 | #define CLAMSHELL_KEY "MSLD" /* r-o ui8 (unused) */ | 64 | #define CLAMSHELL_KEY "MSLD" /* r-o ui8 (unused) */ |
| 65 | 65 | ||
| 66 | #define MOTION_SENSOR_X_KEY "MO_X" /* r-o sp78 (2 bytes) */ | 66 | #define MOTION_SENSOR_X_KEY "MO_X" /* r-o sp78 (2 bytes) */ |
| 67 | #define MOTION_SENSOR_Y_KEY "MO_Y" /* r-o sp78 (2 bytes) */ | 67 | #define MOTION_SENSOR_Y_KEY "MO_Y" /* r-o sp78 (2 bytes) */ |
| @@ -103,7 +103,7 @@ static const char* fan_speed_keys[] = { | |||
| 103 | #define INIT_TIMEOUT_MSECS 5000 /* wait up to 5s for device init ... */ | 103 | #define INIT_TIMEOUT_MSECS 5000 /* wait up to 5s for device init ... */ |
| 104 | #define INIT_WAIT_MSECS 50 /* ... in 50ms increments */ | 104 | #define INIT_WAIT_MSECS 50 /* ... in 50ms increments */ |
| 105 | 105 | ||
| 106 | #define APPLESMC_POLL_PERIOD (HZ/20) /* poll for input every 1/20s */ | 106 | #define APPLESMC_POLL_INTERVAL 50 /* msecs */ |
| 107 | #define APPLESMC_INPUT_FUZZ 4 /* input event threshold */ | 107 | #define APPLESMC_INPUT_FUZZ 4 /* input event threshold */ |
| 108 | #define APPLESMC_INPUT_FLAT 4 | 108 | #define APPLESMC_INPUT_FLAT 4 |
| 109 | 109 | ||
| @@ -125,9 +125,8 @@ static const int debug; | |||
| 125 | static struct platform_device *pdev; | 125 | static struct platform_device *pdev; |
| 126 | static s16 rest_x; | 126 | static s16 rest_x; |
| 127 | static s16 rest_y; | 127 | static s16 rest_y; |
| 128 | static struct timer_list applesmc_timer; | ||
| 129 | static struct input_dev *applesmc_idev; | ||
| 130 | static struct device *hwmon_dev; | 128 | static struct device *hwmon_dev; |
| 129 | static struct input_polled_dev *applesmc_idev; | ||
| 131 | 130 | ||
| 132 | /* Indicates whether this computer has an accelerometer. */ | 131 | /* Indicates whether this computer has an accelerometer. */ |
| 133 | static unsigned int applesmc_accelerometer; | 132 | static unsigned int applesmc_accelerometer; |
| @@ -138,7 +137,7 @@ static unsigned int applesmc_light; | |||
| 138 | /* Indicates which temperature sensors set to use. */ | 137 | /* Indicates which temperature sensors set to use. */ |
| 139 | static unsigned int applesmc_temperature_set; | 138 | static unsigned int applesmc_temperature_set; |
| 140 | 139 | ||
| 141 | static struct mutex applesmc_lock; | 140 | static DEFINE_MUTEX(applesmc_lock); |
| 142 | 141 | ||
| 143 | /* | 142 | /* |
| 144 | * Last index written to key_at_index sysfs file, and value to use for all other | 143 | * Last index written to key_at_index sysfs file, and value to use for all other |
| @@ -455,27 +454,12 @@ static void applesmc_calibrate(void) | |||
| 455 | rest_x = -rest_x; | 454 | rest_x = -rest_x; |
| 456 | } | 455 | } |
| 457 | 456 | ||
| 458 | static int applesmc_idev_open(struct input_dev *dev) | 457 | static void applesmc_idev_poll(struct input_polled_dev *dev) |
| 459 | { | ||
| 460 | add_timer(&applesmc_timer); | ||
| 461 | |||
| 462 | return 0; | ||
| 463 | } | ||
| 464 | |||
| 465 | static void applesmc_idev_close(struct input_dev *dev) | ||
| 466 | { | ||
| 467 | del_timer_sync(&applesmc_timer); | ||
| 468 | } | ||
| 469 | |||
| 470 | static void applesmc_idev_poll(unsigned long unused) | ||
| 471 | { | 458 | { |
| 459 | struct input_dev *idev = dev->input; | ||
| 472 | s16 x, y; | 460 | s16 x, y; |
| 473 | 461 | ||
| 474 | /* Cannot sleep. Try nonblockingly. If we fail, try again later. */ | 462 | mutex_lock(&applesmc_lock); |
| 475 | if (!mutex_trylock(&applesmc_lock)) { | ||
| 476 | mod_timer(&applesmc_timer, jiffies + APPLESMC_POLL_PERIOD); | ||
| 477 | return; | ||
| 478 | } | ||
| 479 | 463 | ||
| 480 | if (applesmc_read_motion_sensor(SENSOR_X, &x)) | 464 | if (applesmc_read_motion_sensor(SENSOR_X, &x)) |
| 481 | goto out; | 465 | goto out; |
| @@ -483,13 +467,11 @@ static void applesmc_idev_poll(unsigned long unused) | |||
| 483 | goto out; | 467 | goto out; |
| 484 | 468 | ||
| 485 | x = -x; | 469 | x = -x; |
| 486 | input_report_abs(applesmc_idev, ABS_X, x - rest_x); | 470 | input_report_abs(idev, ABS_X, x - rest_x); |
| 487 | input_report_abs(applesmc_idev, ABS_Y, y - rest_y); | 471 | input_report_abs(idev, ABS_Y, y - rest_y); |
| 488 | input_sync(applesmc_idev); | 472 | input_sync(idev); |
| 489 | 473 | ||
| 490 | out: | 474 | out: |
| 491 | mod_timer(&applesmc_timer, jiffies + APPLESMC_POLL_PERIOD); | ||
| 492 | |||
| 493 | mutex_unlock(&applesmc_lock); | 475 | mutex_unlock(&applesmc_lock); |
| 494 | } | 476 | } |
| 495 | 477 | ||
| @@ -821,8 +803,7 @@ static ssize_t applesmc_key_at_index_read_show(struct device *dev, | |||
| 821 | 803 | ||
| 822 | if (!ret) { | 804 | if (!ret) { |
| 823 | return info[0]; | 805 | return info[0]; |
| 824 | } | 806 | } else { |
| 825 | else { | ||
| 826 | return ret; | 807 | return ret; |
| 827 | } | 808 | } |
| 828 | } | 809 | } |
| @@ -1093,6 +1074,7 @@ static int applesmc_dmi_match(const struct dmi_system_id *id) | |||
| 1093 | /* Create accelerometer ressources */ | 1074 | /* Create accelerometer ressources */ |
| 1094 | static int applesmc_create_accelerometer(void) | 1075 | static int applesmc_create_accelerometer(void) |
| 1095 | { | 1076 | { |
| 1077 | struct input_dev *idev; | ||
| 1096 | int ret; | 1078 | int ret; |
| 1097 | 1079 | ||
| 1098 | ret = sysfs_create_group(&pdev->dev.kobj, | 1080 | ret = sysfs_create_group(&pdev->dev.kobj, |
| @@ -1100,40 +1082,37 @@ static int applesmc_create_accelerometer(void) | |||
| 1100 | if (ret) | 1082 | if (ret) |
| 1101 | goto out; | 1083 | goto out; |
| 1102 | 1084 | ||
| 1103 | applesmc_idev = input_allocate_device(); | 1085 | applesmc_idev = input_allocate_polled_device(); |
| 1104 | if (!applesmc_idev) { | 1086 | if (!applesmc_idev) { |
| 1105 | ret = -ENOMEM; | 1087 | ret = -ENOMEM; |
| 1106 | goto out_sysfs; | 1088 | goto out_sysfs; |
| 1107 | } | 1089 | } |
| 1108 | 1090 | ||
| 1091 | applesmc_idev->poll = applesmc_idev_poll; | ||
| 1092 | applesmc_idev->poll_interval = APPLESMC_POLL_INTERVAL; | ||
| 1093 | |||
| 1109 | /* initial calibrate for the input device */ | 1094 | /* initial calibrate for the input device */ |
| 1110 | applesmc_calibrate(); | 1095 | applesmc_calibrate(); |
| 1111 | 1096 | ||
| 1112 | /* initialize the input class */ | 1097 | /* initialize the input device */ |
| 1113 | applesmc_idev->name = "applesmc"; | 1098 | idev = applesmc_idev->input; |
| 1114 | applesmc_idev->id.bustype = BUS_HOST; | 1099 | idev->name = "applesmc"; |
| 1115 | applesmc_idev->dev.parent = &pdev->dev; | 1100 | idev->id.bustype = BUS_HOST; |
| 1116 | applesmc_idev->evbit[0] = BIT(EV_ABS); | 1101 | idev->dev.parent = &pdev->dev; |
| 1117 | applesmc_idev->open = applesmc_idev_open; | 1102 | idev->evbit[0] = BIT(EV_ABS); |
| 1118 | applesmc_idev->close = applesmc_idev_close; | 1103 | input_set_abs_params(idev, ABS_X, |
| 1119 | input_set_abs_params(applesmc_idev, ABS_X, | ||
| 1120 | -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT); | 1104 | -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT); |
| 1121 | input_set_abs_params(applesmc_idev, ABS_Y, | 1105 | input_set_abs_params(idev, ABS_Y, |
| 1122 | -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT); | 1106 | -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT); |
| 1123 | 1107 | ||
| 1124 | ret = input_register_device(applesmc_idev); | 1108 | ret = input_register_polled_device(applesmc_idev); |
| 1125 | if (ret) | 1109 | if (ret) |
| 1126 | goto out_idev; | 1110 | goto out_idev; |
| 1127 | 1111 | ||
| 1128 | /* start up our timer for the input device */ | ||
| 1129 | init_timer(&applesmc_timer); | ||
| 1130 | applesmc_timer.function = applesmc_idev_poll; | ||
| 1131 | applesmc_timer.expires = jiffies + APPLESMC_POLL_PERIOD; | ||
| 1132 | |||
| 1133 | return 0; | 1112 | return 0; |
| 1134 | 1113 | ||
| 1135 | out_idev: | 1114 | out_idev: |
| 1136 | input_free_device(applesmc_idev); | 1115 | input_free_polled_device(applesmc_idev); |
| 1137 | 1116 | ||
| 1138 | out_sysfs: | 1117 | out_sysfs: |
| 1139 | sysfs_remove_group(&pdev->dev.kobj, &accelerometer_attributes_group); | 1118 | sysfs_remove_group(&pdev->dev.kobj, &accelerometer_attributes_group); |
| @@ -1146,8 +1125,8 @@ out: | |||
| 1146 | /* Release all ressources used by the accelerometer */ | 1125 | /* Release all ressources used by the accelerometer */ |
| 1147 | static void applesmc_release_accelerometer(void) | 1126 | static void applesmc_release_accelerometer(void) |
| 1148 | { | 1127 | { |
| 1149 | del_timer_sync(&applesmc_timer); | 1128 | input_unregister_polled_device(applesmc_idev); |
| 1150 | input_unregister_device(applesmc_idev); | 1129 | input_free_polled_device(applesmc_idev); |
| 1151 | sysfs_remove_group(&pdev->dev.kobj, &accelerometer_attributes_group); | 1130 | sysfs_remove_group(&pdev->dev.kobj, &accelerometer_attributes_group); |
| 1152 | } | 1131 | } |
| 1153 | 1132 | ||
| @@ -1184,8 +1163,6 @@ static int __init applesmc_init(void) | |||
| 1184 | int count; | 1163 | int count; |
| 1185 | int i; | 1164 | int i; |
| 1186 | 1165 | ||
| 1187 | mutex_init(&applesmc_lock); | ||
| 1188 | |||
| 1189 | if (!dmi_check_system(applesmc_whitelist)) { | 1166 | if (!dmi_check_system(applesmc_whitelist)) { |
| 1190 | printk(KERN_WARNING "applesmc: supported laptop not found!\n"); | 1167 | printk(KERN_WARNING "applesmc: supported laptop not found!\n"); |
| 1191 | ret = -ENODEV; | 1168 | ret = -ENODEV; |
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c index a7c6d407572b..8a7ae03aeee4 100644 --- a/drivers/hwmon/hdaps.c +++ b/drivers/hwmon/hdaps.c | |||
| @@ -28,7 +28,7 @@ | |||
| 28 | 28 | ||
| 29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
| 30 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
| 31 | #include <linux/input.h> | 31 | #include <linux/input-polldev.h> |
| 32 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
| 33 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
| 34 | #include <linux/module.h> | 34 | #include <linux/module.h> |
| @@ -61,13 +61,12 @@ | |||
| 61 | #define INIT_TIMEOUT_MSECS 4000 /* wait up to 4s for device init ... */ | 61 | #define INIT_TIMEOUT_MSECS 4000 /* wait up to 4s for device init ... */ |
| 62 | #define INIT_WAIT_MSECS 200 /* ... in 200ms increments */ | 62 | #define INIT_WAIT_MSECS 200 /* ... in 200ms increments */ |
| 63 | 63 | ||
| 64 | #define HDAPS_POLL_PERIOD (HZ/20) /* poll for input every 1/20s */ | 64 | #define HDAPS_POLL_INTERVAL 50 /* poll for input every 1/20s (50 ms)*/ |
| 65 | #define HDAPS_INPUT_FUZZ 4 /* input event threshold */ | 65 | #define HDAPS_INPUT_FUZZ 4 /* input event threshold */ |
| 66 | #define HDAPS_INPUT_FLAT 4 | 66 | #define HDAPS_INPUT_FLAT 4 |
| 67 | 67 | ||
| 68 | static struct timer_list hdaps_timer; | ||
| 69 | static struct platform_device *pdev; | 68 | static struct platform_device *pdev; |
| 70 | static struct input_dev *hdaps_idev; | 69 | static struct input_polled_dev *hdaps_idev; |
| 71 | static unsigned int hdaps_invert; | 70 | static unsigned int hdaps_invert; |
| 72 | static u8 km_activity; | 71 | static u8 km_activity; |
| 73 | static int rest_x; | 72 | static int rest_x; |
| @@ -323,24 +322,19 @@ static void hdaps_calibrate(void) | |||
| 323 | __hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &rest_x, &rest_y); | 322 | __hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &rest_x, &rest_y); |
| 324 | } | 323 | } |
| 325 | 324 | ||
| 326 | static void hdaps_mousedev_poll(unsigned long unused) | 325 | static void hdaps_mousedev_poll(struct input_polled_dev *dev) |
| 327 | { | 326 | { |
| 327 | struct input_dev *input_dev = dev->input; | ||
| 328 | int x, y; | 328 | int x, y; |
| 329 | 329 | ||
| 330 | /* Cannot sleep. Try nonblockingly. If we fail, try again later. */ | 330 | mutex_lock(&hdaps_mtx); |
| 331 | if (mutex_trylock(&hdaps_mtx)) { | ||
| 332 | mod_timer(&hdaps_timer,jiffies + HDAPS_POLL_PERIOD); | ||
| 333 | return; | ||
| 334 | } | ||
| 335 | 331 | ||
| 336 | if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y)) | 332 | if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y)) |
| 337 | goto out; | 333 | goto out; |
| 338 | 334 | ||
| 339 | input_report_abs(hdaps_idev, ABS_X, x - rest_x); | 335 | input_report_abs(input_dev, ABS_X, x - rest_x); |
| 340 | input_report_abs(hdaps_idev, ABS_Y, y - rest_y); | 336 | input_report_abs(input_dev, ABS_Y, y - rest_y); |
| 341 | input_sync(hdaps_idev); | 337 | input_sync(input_dev); |
| 342 | |||
| 343 | mod_timer(&hdaps_timer, jiffies + HDAPS_POLL_PERIOD); | ||
| 344 | 338 | ||
| 345 | out: | 339 | out: |
| 346 | mutex_unlock(&hdaps_mtx); | 340 | mutex_unlock(&hdaps_mtx); |
| @@ -536,6 +530,7 @@ static struct dmi_system_id __initdata hdaps_whitelist[] = { | |||
| 536 | 530 | ||
| 537 | static int __init hdaps_init(void) | 531 | static int __init hdaps_init(void) |
| 538 | { | 532 | { |
| 533 | struct input_dev *idev; | ||
| 539 | int ret; | 534 | int ret; |
| 540 | 535 | ||
| 541 | if (!dmi_check_system(hdaps_whitelist)) { | 536 | if (!dmi_check_system(hdaps_whitelist)) { |
| @@ -563,39 +558,37 @@ static int __init hdaps_init(void) | |||
| 563 | if (ret) | 558 | if (ret) |
| 564 | goto out_device; | 559 | goto out_device; |
| 565 | 560 | ||
| 566 | hdaps_idev = input_allocate_device(); | 561 | hdaps_idev = input_allocate_polled_device(); |
| 567 | if (!hdaps_idev) { | 562 | if (!hdaps_idev) { |
| 568 | ret = -ENOMEM; | 563 | ret = -ENOMEM; |
| 569 | goto out_group; | 564 | goto out_group; |
| 570 | } | 565 | } |
| 571 | 566 | ||
| 567 | hdaps_idev->poll = hdaps_mousedev_poll; | ||
| 568 | hdaps_idev->poll_interval = HDAPS_POLL_INTERVAL; | ||
| 569 | |||
| 572 | /* initial calibrate for the input device */ | 570 | /* initial calibrate for the input device */ |
| 573 | hdaps_calibrate(); | 571 | hdaps_calibrate(); |
| 574 | 572 | ||
| 575 | /* initialize the input class */ | 573 | /* initialize the input class */ |
| 576 | hdaps_idev->name = "hdaps"; | 574 | idev = hdaps_idev->input; |
| 577 | hdaps_idev->dev.parent = &pdev->dev; | 575 | idev->name = "hdaps"; |
| 578 | hdaps_idev->evbit[0] = BIT(EV_ABS); | 576 | idev->dev.parent = &pdev->dev; |
| 579 | input_set_abs_params(hdaps_idev, ABS_X, | 577 | idev->evbit[0] = BIT(EV_ABS); |
| 578 | input_set_abs_params(idev, ABS_X, | ||
| 580 | -256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT); | 579 | -256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT); |
| 581 | input_set_abs_params(hdaps_idev, ABS_Y, | 580 | input_set_abs_params(idev, ABS_Y, |
| 582 | -256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT); | 581 | -256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT); |
| 583 | 582 | ||
| 584 | ret = input_register_device(hdaps_idev); | 583 | ret = input_register_polled_device(hdaps_idev); |
| 585 | if (ret) | 584 | if (ret) |
| 586 | goto out_idev; | 585 | goto out_idev; |
| 587 | 586 | ||
| 588 | /* start up our timer for the input device */ | ||
| 589 | init_timer(&hdaps_timer); | ||
| 590 | hdaps_timer.function = hdaps_mousedev_poll; | ||
| 591 | hdaps_timer.expires = jiffies + HDAPS_POLL_PERIOD; | ||
| 592 | add_timer(&hdaps_timer); | ||
| 593 | |||
| 594 | printk(KERN_INFO "hdaps: driver successfully loaded.\n"); | 587 | printk(KERN_INFO "hdaps: driver successfully loaded.\n"); |
| 595 | return 0; | 588 | return 0; |
| 596 | 589 | ||
| 597 | out_idev: | 590 | out_idev: |
| 598 | input_free_device(hdaps_idev); | 591 | input_free_polled_device(hdaps_idev); |
| 599 | out_group: | 592 | out_group: |
| 600 | sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group); | 593 | sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group); |
| 601 | out_device: | 594 | out_device: |
| @@ -611,8 +604,8 @@ out: | |||
| 611 | 604 | ||
| 612 | static void __exit hdaps_exit(void) | 605 | static void __exit hdaps_exit(void) |
| 613 | { | 606 | { |
| 614 | del_timer_sync(&hdaps_timer); | 607 | input_unregister_polled_device(hdaps_idev); |
| 615 | input_unregister_device(hdaps_idev); | 608 | input_free_polled_device(hdaps_idev); |
| 616 | sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group); | 609 | sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group); |
| 617 | platform_device_unregister(pdev); | 610 | platform_device_unregister(pdev); |
| 618 | platform_driver_unregister(&hdaps_driver); | 611 | platform_driver_unregister(&hdaps_driver); |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index 6545fa798b12..1b3327ad6bc4 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h | |||
| @@ -349,6 +349,7 @@ struct ipoib_neigh { | |||
| 349 | struct sk_buff_head queue; | 349 | struct sk_buff_head queue; |
| 350 | 350 | ||
| 351 | struct neighbour *neighbour; | 351 | struct neighbour *neighbour; |
| 352 | struct net_device *dev; | ||
| 352 | 353 | ||
| 353 | struct list_head list; | 354 | struct list_head list; |
| 354 | }; | 355 | }; |
| @@ -365,7 +366,8 @@ static inline struct ipoib_neigh **to_ipoib_neigh(struct neighbour *neigh) | |||
| 365 | INFINIBAND_ALEN, sizeof(void *)); | 366 | INFINIBAND_ALEN, sizeof(void *)); |
| 366 | } | 367 | } |
| 367 | 368 | ||
| 368 | struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neigh); | 369 | struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neigh, |
| 370 | struct net_device *dev); | ||
| 369 | void ipoib_neigh_free(struct net_device *dev, struct ipoib_neigh *neigh); | 371 | void ipoib_neigh_free(struct net_device *dev, struct ipoib_neigh *neigh); |
| 370 | 372 | ||
| 371 | extern struct workqueue_struct *ipoib_workqueue; | 373 | extern struct workqueue_struct *ipoib_workqueue; |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index e072f3c32ce6..362610d870e4 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
| @@ -517,7 +517,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) | |||
| 517 | struct ipoib_path *path; | 517 | struct ipoib_path *path; |
| 518 | struct ipoib_neigh *neigh; | 518 | struct ipoib_neigh *neigh; |
| 519 | 519 | ||
| 520 | neigh = ipoib_neigh_alloc(skb->dst->neighbour); | 520 | neigh = ipoib_neigh_alloc(skb->dst->neighbour, skb->dev); |
| 521 | if (!neigh) { | 521 | if (!neigh) { |
| 522 | ++dev->stats.tx_dropped; | 522 | ++dev->stats.tx_dropped; |
| 523 | dev_kfree_skb_any(skb); | 523 | dev_kfree_skb_any(skb); |
| @@ -692,9 +692,10 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 692 | goto out; | 692 | goto out; |
| 693 | } | 693 | } |
| 694 | } else if (neigh->ah) { | 694 | } else if (neigh->ah) { |
| 695 | if (unlikely(memcmp(&neigh->dgid.raw, | 695 | if (unlikely((memcmp(&neigh->dgid.raw, |
| 696 | skb->dst->neighbour->ha + 4, | 696 | skb->dst->neighbour->ha + 4, |
| 697 | sizeof(union ib_gid)))) { | 697 | sizeof(union ib_gid))) || |
| 698 | (neigh->dev != dev))) { | ||
| 698 | spin_lock(&priv->lock); | 699 | spin_lock(&priv->lock); |
| 699 | /* | 700 | /* |
| 700 | * It's safe to call ipoib_put_ah() inside | 701 | * It's safe to call ipoib_put_ah() inside |
| @@ -817,6 +818,13 @@ static void ipoib_neigh_cleanup(struct neighbour *n) | |||
| 817 | unsigned long flags; | 818 | unsigned long flags; |
| 818 | struct ipoib_ah *ah = NULL; | 819 | struct ipoib_ah *ah = NULL; |
| 819 | 820 | ||
| 821 | neigh = *to_ipoib_neigh(n); | ||
| 822 | if (neigh) { | ||
| 823 | priv = netdev_priv(neigh->dev); | ||
| 824 | ipoib_dbg(priv, "neigh_destructor for bonding device: %s\n", | ||
| 825 | n->dev->name); | ||
| 826 | } else | ||
| 827 | return; | ||
| 820 | ipoib_dbg(priv, | 828 | ipoib_dbg(priv, |
| 821 | "neigh_cleanup for %06x " IPOIB_GID_FMT "\n", | 829 | "neigh_cleanup for %06x " IPOIB_GID_FMT "\n", |
| 822 | IPOIB_QPN(n->ha), | 830 | IPOIB_QPN(n->ha), |
| @@ -824,13 +832,10 @@ static void ipoib_neigh_cleanup(struct neighbour *n) | |||
| 824 | 832 | ||
| 825 | spin_lock_irqsave(&priv->lock, flags); | 833 | spin_lock_irqsave(&priv->lock, flags); |
| 826 | 834 | ||
| 827 | neigh = *to_ipoib_neigh(n); | 835 | if (neigh->ah) |
| 828 | if (neigh) { | 836 | ah = neigh->ah; |
| 829 | if (neigh->ah) | 837 | list_del(&neigh->list); |
| 830 | ah = neigh->ah; | 838 | ipoib_neigh_free(n->dev, neigh); |
| 831 | list_del(&neigh->list); | ||
| 832 | ipoib_neigh_free(n->dev, neigh); | ||
| 833 | } | ||
| 834 | 839 | ||
| 835 | spin_unlock_irqrestore(&priv->lock, flags); | 840 | spin_unlock_irqrestore(&priv->lock, flags); |
| 836 | 841 | ||
| @@ -838,7 +843,8 @@ static void ipoib_neigh_cleanup(struct neighbour *n) | |||
| 838 | ipoib_put_ah(ah); | 843 | ipoib_put_ah(ah); |
| 839 | } | 844 | } |
| 840 | 845 | ||
| 841 | struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour) | 846 | struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour, |
| 847 | struct net_device *dev) | ||
| 842 | { | 848 | { |
| 843 | struct ipoib_neigh *neigh; | 849 | struct ipoib_neigh *neigh; |
| 844 | 850 | ||
| @@ -847,6 +853,7 @@ struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour) | |||
| 847 | return NULL; | 853 | return NULL; |
| 848 | 854 | ||
| 849 | neigh->neighbour = neighbour; | 855 | neigh->neighbour = neighbour; |
| 856 | neigh->dev = dev; | ||
| 850 | *to_ipoib_neigh(neighbour) = neigh; | 857 | *to_ipoib_neigh(neighbour) = neigh; |
| 851 | skb_queue_head_init(&neigh->queue); | 858 | skb_queue_head_init(&neigh->queue); |
| 852 | ipoib_cm_set(neigh, NULL); | 859 | ipoib_cm_set(neigh, NULL); |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 827820ec66d1..9bcfc7ad6aa6 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c | |||
| @@ -705,7 +705,8 @@ out: | |||
| 705 | if (skb->dst && | 705 | if (skb->dst && |
| 706 | skb->dst->neighbour && | 706 | skb->dst->neighbour && |
| 707 | !*to_ipoib_neigh(skb->dst->neighbour)) { | 707 | !*to_ipoib_neigh(skb->dst->neighbour)) { |
| 708 | struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb->dst->neighbour); | 708 | struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb->dst->neighbour, |
| 709 | skb->dev); | ||
| 709 | 710 | ||
| 710 | if (neigh) { | 711 | if (neigh) { |
| 711 | kref_get(&mcast->ah->ref); | 712 | kref_get(&mcast->ah->ref); |
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 2d87357e2b2b..63512d906f02 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig | |||
| @@ -114,28 +114,6 @@ config INPUT_JOYDEV | |||
| 114 | To compile this driver as a module, choose M here: the | 114 | To compile this driver as a module, choose M here: the |
| 115 | module will be called joydev. | 115 | module will be called joydev. |
| 116 | 116 | ||
| 117 | config INPUT_TSDEV | ||
| 118 | tristate "Touchscreen interface" | ||
| 119 | ---help--- | ||
| 120 | Say Y here if you have an application that only can understand the | ||
| 121 | Compaq touchscreen protocol for absolute pointer data. This is | ||
| 122 | useful namely for embedded configurations. | ||
| 123 | |||
| 124 | If unsure, say N. | ||
| 125 | |||
| 126 | To compile this driver as a module, choose M here: the | ||
| 127 | module will be called tsdev. | ||
| 128 | |||
| 129 | config INPUT_TSDEV_SCREEN_X | ||
| 130 | int "Horizontal screen resolution" | ||
| 131 | depends on INPUT_TSDEV | ||
| 132 | default "240" | ||
| 133 | |||
| 134 | config INPUT_TSDEV_SCREEN_Y | ||
| 135 | int "Vertical screen resolution" | ||
| 136 | depends on INPUT_TSDEV | ||
| 137 | default "320" | ||
| 138 | |||
| 139 | config INPUT_EVDEV | 117 | config INPUT_EVDEV |
| 140 | tristate "Event interface" | 118 | tristate "Event interface" |
| 141 | help | 119 | help |
diff --git a/drivers/input/Makefile b/drivers/input/Makefile index 15eb752697b3..99af903bd3ce 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile | |||
| @@ -13,7 +13,6 @@ obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o | |||
| 13 | obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o | 13 | obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o |
| 14 | obj-$(CONFIG_INPUT_JOYDEV) += joydev.o | 14 | obj-$(CONFIG_INPUT_JOYDEV) += joydev.o |
| 15 | obj-$(CONFIG_INPUT_EVDEV) += evdev.o | 15 | obj-$(CONFIG_INPUT_EVDEV) += evdev.o |
| 16 | obj-$(CONFIG_INPUT_TSDEV) += tsdev.o | ||
| 17 | obj-$(CONFIG_INPUT_EVBUG) += evbug.o | 16 | obj-$(CONFIG_INPUT_EVBUG) += evbug.o |
| 18 | 17 | ||
| 19 | obj-$(CONFIG_INPUT_KEYBOARD) += keyboard/ | 18 | obj-$(CONFIG_INPUT_KEYBOARD) += keyboard/ |
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index f1c3d6cebd58..1d62c8b88e12 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
| @@ -30,6 +30,8 @@ struct evdev { | |||
| 30 | wait_queue_head_t wait; | 30 | wait_queue_head_t wait; |
| 31 | struct evdev_client *grab; | 31 | struct evdev_client *grab; |
| 32 | struct list_head client_list; | 32 | struct list_head client_list; |
| 33 | spinlock_t client_lock; /* protects client_list */ | ||
| 34 | struct mutex mutex; | ||
| 33 | struct device dev; | 35 | struct device dev; |
| 34 | }; | 36 | }; |
| 35 | 37 | ||
| @@ -37,39 +39,54 @@ struct evdev_client { | |||
| 37 | struct input_event buffer[EVDEV_BUFFER_SIZE]; | 39 | struct input_event buffer[EVDEV_BUFFER_SIZE]; |
| 38 | int head; | 40 | int head; |
| 39 | int tail; | 41 | int tail; |
| 42 | spinlock_t buffer_lock; /* protects access to buffer, head and tail */ | ||
| 40 | struct fasync_struct *fasync; | 43 | struct fasync_struct *fasync; |
| 41 | struct evdev *evdev; | 44 | struct evdev *evdev; |
| 42 | struct list_head node; | 45 | struct list_head node; |
| 43 | }; | 46 | }; |
| 44 | 47 | ||
| 45 | static struct evdev *evdev_table[EVDEV_MINORS]; | 48 | static struct evdev *evdev_table[EVDEV_MINORS]; |
| 49 | static DEFINE_MUTEX(evdev_table_mutex); | ||
| 46 | 50 | ||
| 47 | static void evdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) | 51 | static void evdev_pass_event(struct evdev_client *client, |
| 52 | struct input_event *event) | ||
| 53 | { | ||
| 54 | /* | ||
| 55 | * Interrupts are disabled, just acquire the lock | ||
| 56 | */ | ||
| 57 | spin_lock(&client->buffer_lock); | ||
| 58 | client->buffer[client->head++] = *event; | ||
| 59 | client->head &= EVDEV_BUFFER_SIZE - 1; | ||
| 60 | spin_unlock(&client->buffer_lock); | ||
| 61 | |||
| 62 | kill_fasync(&client->fasync, SIGIO, POLL_IN); | ||
| 63 | } | ||
| 64 | |||
| 65 | /* | ||
| 66 | * Pass incoming event to all connected clients. | ||
| 67 | */ | ||
| 68 | static void evdev_event(struct input_handle *handle, | ||
| 69 | unsigned int type, unsigned int code, int value) | ||
| 48 | { | 70 | { |
| 49 | struct evdev *evdev = handle->private; | 71 | struct evdev *evdev = handle->private; |
| 50 | struct evdev_client *client; | 72 | struct evdev_client *client; |
| 73 | struct input_event event; | ||
| 51 | 74 | ||
| 52 | if (evdev->grab) { | 75 | do_gettimeofday(&event.time); |
| 53 | client = evdev->grab; | 76 | event.type = type; |
| 77 | event.code = code; | ||
| 78 | event.value = value; | ||
| 54 | 79 | ||
| 55 | do_gettimeofday(&client->buffer[client->head].time); | 80 | rcu_read_lock(); |
| 56 | client->buffer[client->head].type = type; | ||
| 57 | client->buffer[client->head].code = code; | ||
| 58 | client->buffer[client->head].value = value; | ||
| 59 | client->head = (client->head + 1) & (EVDEV_BUFFER_SIZE - 1); | ||
| 60 | 81 | ||
| 61 | kill_fasync(&client->fasync, SIGIO, POLL_IN); | 82 | client = rcu_dereference(evdev->grab); |
| 62 | } else | 83 | if (client) |
| 63 | list_for_each_entry(client, &evdev->client_list, node) { | 84 | evdev_pass_event(client, &event); |
| 85 | else | ||
| 86 | list_for_each_entry_rcu(client, &evdev->client_list, node) | ||
| 87 | evdev_pass_event(client, &event); | ||
| 64 | 88 | ||
| 65 | do_gettimeofday(&client->buffer[client->head].time); | 89 | rcu_read_unlock(); |
| 66 | client->buffer[client->head].type = type; | ||
| 67 | client->buffer[client->head].code = code; | ||
| 68 | client->buffer[client->head].value = value; | ||
| 69 | client->head = (client->head + 1) & (EVDEV_BUFFER_SIZE - 1); | ||
| 70 | |||
| 71 | kill_fasync(&client->fasync, SIGIO, POLL_IN); | ||
| 72 | } | ||
| 73 | 90 | ||
| 74 | wake_up_interruptible(&evdev->wait); | 91 | wake_up_interruptible(&evdev->wait); |
| 75 | } | 92 | } |
| @@ -88,38 +105,140 @@ static int evdev_flush(struct file *file, fl_owner_t id) | |||
| 88 | { | 105 | { |
| 89 | struct evdev_client *client = file->private_data; | 106 | struct evdev_client *client = file->private_data; |
| 90 | struct evdev *evdev = client->evdev; | 107 | struct evdev *evdev = client->evdev; |
| 108 | int retval; | ||
| 109 | |||
| 110 | retval = mutex_lock_interruptible(&evdev->mutex); | ||
| 111 | if (retval) | ||
| 112 | return retval; | ||
| 91 | 113 | ||
| 92 | if (!evdev->exist) | 114 | if (!evdev->exist) |
| 93 | return -ENODEV; | 115 | retval = -ENODEV; |
| 116 | else | ||
| 117 | retval = input_flush_device(&evdev->handle, file); | ||
| 94 | 118 | ||
| 95 | return input_flush_device(&evdev->handle, file); | 119 | mutex_unlock(&evdev->mutex); |
| 120 | return retval; | ||
| 96 | } | 121 | } |
| 97 | 122 | ||
| 98 | static void evdev_free(struct device *dev) | 123 | static void evdev_free(struct device *dev) |
| 99 | { | 124 | { |
| 100 | struct evdev *evdev = container_of(dev, struct evdev, dev); | 125 | struct evdev *evdev = container_of(dev, struct evdev, dev); |
| 101 | 126 | ||
| 102 | evdev_table[evdev->minor] = NULL; | ||
| 103 | kfree(evdev); | 127 | kfree(evdev); |
| 104 | } | 128 | } |
| 105 | 129 | ||
| 130 | /* | ||
| 131 | * Grabs an event device (along with underlying input device). | ||
| 132 | * This function is called with evdev->mutex taken. | ||
| 133 | */ | ||
| 134 | static int evdev_grab(struct evdev *evdev, struct evdev_client *client) | ||
| 135 | { | ||
| 136 | int error; | ||
| 137 | |||
| 138 | if (evdev->grab) | ||
| 139 | return -EBUSY; | ||
| 140 | |||
| 141 | error = input_grab_device(&evdev->handle); | ||
| 142 | if (error) | ||
| 143 | return error; | ||
| 144 | |||
| 145 | rcu_assign_pointer(evdev->grab, client); | ||
| 146 | synchronize_rcu(); | ||
| 147 | |||
| 148 | return 0; | ||
| 149 | } | ||
| 150 | |||
| 151 | static int evdev_ungrab(struct evdev *evdev, struct evdev_client *client) | ||
| 152 | { | ||
| 153 | if (evdev->grab != client) | ||
| 154 | return -EINVAL; | ||
| 155 | |||
| 156 | rcu_assign_pointer(evdev->grab, NULL); | ||
| 157 | synchronize_rcu(); | ||
| 158 | input_release_device(&evdev->handle); | ||
| 159 | |||
| 160 | return 0; | ||
| 161 | } | ||
| 162 | |||
| 163 | static void evdev_attach_client(struct evdev *evdev, | ||
| 164 | struct evdev_client *client) | ||
| 165 | { | ||
| 166 | spin_lock(&evdev->client_lock); | ||
| 167 | list_add_tail_rcu(&client->node, &evdev->client_list); | ||
| 168 | spin_unlock(&evdev->client_lock); | ||
| 169 | synchronize_rcu(); | ||
| 170 | } | ||
| 171 | |||
| 172 | static void evdev_detach_client(struct evdev *evdev, | ||
| 173 | struct evdev_client *client) | ||
| 174 | { | ||
| 175 | spin_lock(&evdev->client_lock); | ||
| 176 | list_del_rcu(&client->node); | ||
| 177 | spin_unlock(&evdev->client_lock); | ||
| 178 | synchronize_rcu(); | ||
| 179 | } | ||
| 180 | |||
| 181 | static int evdev_open_device(struct evdev *evdev) | ||
| 182 | { | ||
| 183 | int retval; | ||
| 184 | |||
| 185 | retval = mutex_lock_interruptible(&evdev->mutex); | ||
| 186 | if (retval) | ||
| 187 | return retval; | ||
| 188 | |||
| 189 | if (!evdev->exist) | ||
| 190 | retval = -ENODEV; | ||
| 191 | else if (!evdev->open++) { | ||
| 192 | retval = input_open_device(&evdev->handle); | ||
| 193 | if (retval) | ||
| 194 | evdev->open--; | ||
| 195 | } | ||
| 196 | |||
| 197 | mutex_unlock(&evdev->mutex); | ||
| 198 | return retval; | ||
| 199 | } | ||
| 200 | |||
| 201 | static void evdev_close_device(struct evdev *evdev) | ||
| 202 | { | ||
| 203 | mutex_lock(&evdev->mutex); | ||
| 204 | |||
| 205 | if (evdev->exist && !--evdev->open) | ||
| 206 | input_close_device(&evdev->handle); | ||
| 207 | |||
| 208 | mutex_unlock(&evdev->mutex); | ||
| 209 | } | ||
| 210 | |||
| 211 | /* | ||
| 212 | * Wake up users waiting for IO so they can disconnect from | ||
| 213 | * dead device. | ||
| 214 | */ | ||
| 215 | static void evdev_hangup(struct evdev *evdev) | ||
| 216 | { | ||
| 217 | struct evdev_client *client; | ||
| 218 | |||
| 219 | spin_lock(&evdev->client_lock); | ||
| 220 | list_for_each_entry(client, &evdev->client_list, node) | ||
| 221 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); | ||
| 222 | spin_unlock(&evdev->client_lock); | ||
| 223 | |||
| 224 | wake_up_interruptible(&evdev->wait); | ||
| 225 | } | ||
| 226 | |||
| 106 | static int evdev_release(struct inode *inode, struct file *file) | 227 | static int evdev_release(struct inode *inode, struct file *file) |
| 107 | { | 228 | { |
| 108 | struct evdev_client *client = file->private_data; | 229 | struct evdev_client *client = file->private_data; |
| 109 | struct evdev *evdev = client->evdev; | 230 | struct evdev *evdev = client->evdev; |
| 110 | 231 | ||
| 111 | if (evdev->grab == client) { | 232 | mutex_lock(&evdev->mutex); |
| 112 | input_release_device(&evdev->handle); | 233 | if (evdev->grab == client) |
| 113 | evdev->grab = NULL; | 234 | evdev_ungrab(evdev, client); |
| 114 | } | 235 | mutex_unlock(&evdev->mutex); |
| 115 | 236 | ||
| 116 | evdev_fasync(-1, file, 0); | 237 | evdev_fasync(-1, file, 0); |
| 117 | list_del(&client->node); | 238 | evdev_detach_client(evdev, client); |
| 118 | kfree(client); | 239 | kfree(client); |
| 119 | 240 | ||
| 120 | if (!--evdev->open && evdev->exist) | 241 | evdev_close_device(evdev); |
| 121 | input_close_device(&evdev->handle); | ||
| 122 | |||
| 123 | put_device(&evdev->dev); | 242 | put_device(&evdev->dev); |
| 124 | 243 | ||
| 125 | return 0; | 244 | return 0; |
| @@ -127,41 +246,44 @@ static int evdev_release(struct inode *inode, struct file *file) | |||
| 127 | 246 | ||
| 128 | static int evdev_open(struct inode *inode, struct file *file) | 247 | static int evdev_open(struct inode *inode, struct file *file) |
| 129 | { | 248 | { |
| 130 | struct evdev_client *client; | ||
| 131 | struct evdev *evdev; | 249 | struct evdev *evdev; |
| 250 | struct evdev_client *client; | ||
| 132 | int i = iminor(inode) - EVDEV_MINOR_BASE; | 251 | int i = iminor(inode) - EVDEV_MINOR_BASE; |
| 133 | int error; | 252 | int error; |
| 134 | 253 | ||
| 135 | if (i >= EVDEV_MINORS) | 254 | if (i >= EVDEV_MINORS) |
| 136 | return -ENODEV; | 255 | return -ENODEV; |
| 137 | 256 | ||
| 257 | error = mutex_lock_interruptible(&evdev_table_mutex); | ||
| 258 | if (error) | ||
| 259 | return error; | ||
| 138 | evdev = evdev_table[i]; | 260 | evdev = evdev_table[i]; |
| 261 | if (evdev) | ||
| 262 | get_device(&evdev->dev); | ||
| 263 | mutex_unlock(&evdev_table_mutex); | ||
| 139 | 264 | ||
| 140 | if (!evdev || !evdev->exist) | 265 | if (!evdev) |
| 141 | return -ENODEV; | 266 | return -ENODEV; |
| 142 | 267 | ||
| 143 | get_device(&evdev->dev); | ||
| 144 | |||
| 145 | client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL); | 268 | client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL); |
| 146 | if (!client) { | 269 | if (!client) { |
| 147 | error = -ENOMEM; | 270 | error = -ENOMEM; |
| 148 | goto err_put_evdev; | 271 | goto err_put_evdev; |
| 149 | } | 272 | } |
| 150 | 273 | ||
| 274 | spin_lock_init(&client->buffer_lock); | ||
| 151 | client->evdev = evdev; | 275 | client->evdev = evdev; |
| 152 | list_add_tail(&client->node, &evdev->client_list); | 276 | evdev_attach_client(evdev, client); |
| 153 | 277 | ||
| 154 | if (!evdev->open++ && evdev->exist) { | 278 | error = evdev_open_device(evdev); |
| 155 | error = input_open_device(&evdev->handle); | 279 | if (error) |
| 156 | if (error) | 280 | goto err_free_client; |
| 157 | goto err_free_client; | ||
| 158 | } | ||
| 159 | 281 | ||
| 160 | file->private_data = client; | 282 | file->private_data = client; |
| 161 | return 0; | 283 | return 0; |
| 162 | 284 | ||
| 163 | err_free_client: | 285 | err_free_client: |
| 164 | list_del(&client->node); | 286 | evdev_detach_client(evdev, client); |
| 165 | kfree(client); | 287 | kfree(client); |
| 166 | err_put_evdev: | 288 | err_put_evdev: |
| 167 | put_device(&evdev->dev); | 289 | put_device(&evdev->dev); |
| @@ -197,12 +319,14 @@ static inline size_t evdev_event_size(void) | |||
| 197 | sizeof(struct input_event_compat) : sizeof(struct input_event); | 319 | sizeof(struct input_event_compat) : sizeof(struct input_event); |
| 198 | } | 320 | } |
| 199 | 321 | ||
| 200 | static int evdev_event_from_user(const char __user *buffer, struct input_event *event) | 322 | static int evdev_event_from_user(const char __user *buffer, |
| 323 | struct input_event *event) | ||
| 201 | { | 324 | { |
| 202 | if (COMPAT_TEST) { | 325 | if (COMPAT_TEST) { |
| 203 | struct input_event_compat compat_event; | 326 | struct input_event_compat compat_event; |
| 204 | 327 | ||
| 205 | if (copy_from_user(&compat_event, buffer, sizeof(struct input_event_compat))) | 328 | if (copy_from_user(&compat_event, buffer, |
| 329 | sizeof(struct input_event_compat))) | ||
| 206 | return -EFAULT; | 330 | return -EFAULT; |
| 207 | 331 | ||
| 208 | event->time.tv_sec = compat_event.time.tv_sec; | 332 | event->time.tv_sec = compat_event.time.tv_sec; |
| @@ -219,7 +343,8 @@ static int evdev_event_from_user(const char __user *buffer, struct input_event * | |||
| 219 | return 0; | 343 | return 0; |
| 220 | } | 344 | } |
| 221 | 345 | ||
| 222 | static int evdev_event_to_user(char __user *buffer, const struct input_event *event) | 346 | static int evdev_event_to_user(char __user *buffer, |
| 347 | const struct input_event *event) | ||
| 223 | { | 348 | { |
| 224 | if (COMPAT_TEST) { | 349 | if (COMPAT_TEST) { |
| 225 | struct input_event_compat compat_event; | 350 | struct input_event_compat compat_event; |
| @@ -230,7 +355,8 @@ static int evdev_event_to_user(char __user *buffer, const struct input_event *ev | |||
| 230 | compat_event.code = event->code; | 355 | compat_event.code = event->code; |
| 231 | compat_event.value = event->value; | 356 | compat_event.value = event->value; |
| 232 | 357 | ||
| 233 | if (copy_to_user(buffer, &compat_event, sizeof(struct input_event_compat))) | 358 | if (copy_to_user(buffer, &compat_event, |
| 359 | sizeof(struct input_event_compat))) | ||
| 234 | return -EFAULT; | 360 | return -EFAULT; |
| 235 | 361 | ||
| 236 | } else { | 362 | } else { |
| @@ -248,7 +374,8 @@ static inline size_t evdev_event_size(void) | |||
| 248 | return sizeof(struct input_event); | 374 | return sizeof(struct input_event); |
| 249 | } | 375 | } |
| 250 | 376 | ||
| 251 | static int evdev_event_from_user(const char __user *buffer, struct input_event *event) | 377 | static int evdev_event_from_user(const char __user *buffer, |
| 378 | struct input_event *event) | ||
| 252 | { | 379 | { |
| 253 | if (copy_from_user(event, buffer, sizeof(struct input_event))) | 380 | if (copy_from_user(event, buffer, sizeof(struct input_event))) |
| 254 | return -EFAULT; | 381 | return -EFAULT; |
| @@ -256,7 +383,8 @@ static int evdev_event_from_user(const char __user *buffer, struct input_event * | |||
| 256 | return 0; | 383 | return 0; |
| 257 | } | 384 | } |
| 258 | 385 | ||
| 259 | static int evdev_event_to_user(char __user *buffer, const struct input_event *event) | 386 | static int evdev_event_to_user(char __user *buffer, |
| 387 | const struct input_event *event) | ||
| 260 | { | 388 | { |
| 261 | if (copy_to_user(buffer, event, sizeof(struct input_event))) | 389 | if (copy_to_user(buffer, event, sizeof(struct input_event))) |
| 262 | return -EFAULT; | 390 | return -EFAULT; |
| @@ -266,37 +394,71 @@ static int evdev_event_to_user(char __user *buffer, const struct input_event *ev | |||
| 266 | 394 | ||
| 267 | #endif /* CONFIG_COMPAT */ | 395 | #endif /* CONFIG_COMPAT */ |
| 268 | 396 | ||
| 269 | static ssize_t evdev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | 397 | static ssize_t evdev_write(struct file *file, const char __user *buffer, |
| 398 | size_t count, loff_t *ppos) | ||
| 270 | { | 399 | { |
| 271 | struct evdev_client *client = file->private_data; | 400 | struct evdev_client *client = file->private_data; |
| 272 | struct evdev *evdev = client->evdev; | 401 | struct evdev *evdev = client->evdev; |
| 273 | struct input_event event; | 402 | struct input_event event; |
| 274 | int retval = 0; | 403 | int retval; |
| 275 | 404 | ||
| 276 | if (!evdev->exist) | 405 | retval = mutex_lock_interruptible(&evdev->mutex); |
| 277 | return -ENODEV; | 406 | if (retval) |
| 407 | return retval; | ||
| 408 | |||
| 409 | if (!evdev->exist) { | ||
| 410 | retval = -ENODEV; | ||
| 411 | goto out; | ||
| 412 | } | ||
| 278 | 413 | ||
| 279 | while (retval < count) { | 414 | while (retval < count) { |
| 280 | 415 | ||
| 281 | if (evdev_event_from_user(buffer + retval, &event)) | 416 | if (evdev_event_from_user(buffer + retval, &event)) { |
| 282 | return -EFAULT; | 417 | retval = -EFAULT; |
| 283 | input_inject_event(&evdev->handle, event.type, event.code, event.value); | 418 | goto out; |
| 419 | } | ||
| 420 | |||
| 421 | input_inject_event(&evdev->handle, | ||
| 422 | event.type, event.code, event.value); | ||
| 284 | retval += evdev_event_size(); | 423 | retval += evdev_event_size(); |
| 285 | } | 424 | } |
| 286 | 425 | ||
| 426 | out: | ||
| 427 | mutex_unlock(&evdev->mutex); | ||
| 287 | return retval; | 428 | return retval; |
| 288 | } | 429 | } |
| 289 | 430 | ||
| 290 | static ssize_t evdev_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) | 431 | static int evdev_fetch_next_event(struct evdev_client *client, |
| 432 | struct input_event *event) | ||
| 433 | { | ||
| 434 | int have_event; | ||
| 435 | |||
| 436 | spin_lock_irq(&client->buffer_lock); | ||
| 437 | |||
| 438 | have_event = client->head != client->tail; | ||
| 439 | if (have_event) { | ||
| 440 | *event = client->buffer[client->tail++]; | ||
| 441 | client->tail &= EVDEV_BUFFER_SIZE - 1; | ||
| 442 | } | ||
| 443 | |||
| 444 | spin_unlock_irq(&client->buffer_lock); | ||
| 445 | |||
| 446 | return have_event; | ||
| 447 | } | ||
| 448 | |||
| 449 | static ssize_t evdev_read(struct file *file, char __user *buffer, | ||
| 450 | size_t count, loff_t *ppos) | ||
| 291 | { | 451 | { |
| 292 | struct evdev_client *client = file->private_data; | 452 | struct evdev_client *client = file->private_data; |
| 293 | struct evdev *evdev = client->evdev; | 453 | struct evdev *evdev = client->evdev; |
| 454 | struct input_event event; | ||
| 294 | int retval; | 455 | int retval; |
| 295 | 456 | ||
| 296 | if (count < evdev_event_size()) | 457 | if (count < evdev_event_size()) |
| 297 | return -EINVAL; | 458 | return -EINVAL; |
| 298 | 459 | ||
| 299 | if (client->head == client->tail && evdev->exist && (file->f_flags & O_NONBLOCK)) | 460 | if (client->head == client->tail && evdev->exist && |
| 461 | (file->f_flags & O_NONBLOCK)) | ||
| 300 | return -EAGAIN; | 462 | return -EAGAIN; |
| 301 | 463 | ||
| 302 | retval = wait_event_interruptible(evdev->wait, | 464 | retval = wait_event_interruptible(evdev->wait, |
| @@ -307,14 +469,12 @@ static ssize_t evdev_read(struct file *file, char __user *buffer, size_t count, | |||
| 307 | if (!evdev->exist) | 469 | if (!evdev->exist) |
| 308 | return -ENODEV; | 470 | return -ENODEV; |
| 309 | 471 | ||
| 310 | while (client->head != client->tail && retval + evdev_event_size() <= count) { | 472 | while (retval + evdev_event_size() <= count && |
| 311 | 473 | evdev_fetch_next_event(client, &event)) { | |
| 312 | struct input_event *event = (struct input_event *) client->buffer + client->tail; | ||
| 313 | 474 | ||
| 314 | if (evdev_event_to_user(buffer + retval, event)) | 475 | if (evdev_event_to_user(buffer + retval, &event)) |
| 315 | return -EFAULT; | 476 | return -EFAULT; |
| 316 | 477 | ||
| 317 | client->tail = (client->tail + 1) & (EVDEV_BUFFER_SIZE - 1); | ||
| 318 | retval += evdev_event_size(); | 478 | retval += evdev_event_size(); |
| 319 | } | 479 | } |
| 320 | 480 | ||
| @@ -409,8 +569,8 @@ static int str_to_user(const char *str, unsigned int maxlen, void __user *p) | |||
| 409 | return copy_to_user(p, str, len) ? -EFAULT : len; | 569 | return copy_to_user(p, str, len) ? -EFAULT : len; |
| 410 | } | 570 | } |
| 411 | 571 | ||
| 412 | static long evdev_ioctl_handler(struct file *file, unsigned int cmd, | 572 | static long evdev_do_ioctl(struct file *file, unsigned int cmd, |
| 413 | void __user *p, int compat_mode) | 573 | void __user *p, int compat_mode) |
| 414 | { | 574 | { |
| 415 | struct evdev_client *client = file->private_data; | 575 | struct evdev_client *client = file->private_data; |
| 416 | struct evdev *evdev = client->evdev; | 576 | struct evdev *evdev = client->evdev; |
| @@ -421,215 +581,289 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd, | |||
| 421 | int i, t, u, v; | 581 | int i, t, u, v; |
| 422 | int error; | 582 | int error; |
| 423 | 583 | ||
| 424 | if (!evdev->exist) | ||
| 425 | return -ENODEV; | ||
| 426 | |||
| 427 | switch (cmd) { | 584 | switch (cmd) { |
| 428 | 585 | ||
| 429 | case EVIOCGVERSION: | 586 | case EVIOCGVERSION: |
| 430 | return put_user(EV_VERSION, ip); | 587 | return put_user(EV_VERSION, ip); |
| 431 | 588 | ||
| 432 | case EVIOCGID: | 589 | case EVIOCGID: |
| 433 | if (copy_to_user(p, &dev->id, sizeof(struct input_id))) | 590 | if (copy_to_user(p, &dev->id, sizeof(struct input_id))) |
| 434 | return -EFAULT; | 591 | return -EFAULT; |
| 435 | return 0; | 592 | return 0; |
| 436 | 593 | ||
| 437 | case EVIOCGREP: | 594 | case EVIOCGREP: |
| 438 | if (!test_bit(EV_REP, dev->evbit)) | 595 | if (!test_bit(EV_REP, dev->evbit)) |
| 439 | return -ENOSYS; | 596 | return -ENOSYS; |
| 440 | if (put_user(dev->rep[REP_DELAY], ip)) | 597 | if (put_user(dev->rep[REP_DELAY], ip)) |
| 441 | return -EFAULT; | 598 | return -EFAULT; |
| 442 | if (put_user(dev->rep[REP_PERIOD], ip + 1)) | 599 | if (put_user(dev->rep[REP_PERIOD], ip + 1)) |
| 443 | return -EFAULT; | 600 | return -EFAULT; |
| 444 | return 0; | 601 | return 0; |
| 445 | 602 | ||
| 446 | case EVIOCSREP: | 603 | case EVIOCSREP: |
| 447 | if (!test_bit(EV_REP, dev->evbit)) | 604 | if (!test_bit(EV_REP, dev->evbit)) |
| 448 | return -ENOSYS; | 605 | return -ENOSYS; |
| 449 | if (get_user(u, ip)) | 606 | if (get_user(u, ip)) |
| 450 | return -EFAULT; | 607 | return -EFAULT; |
| 451 | if (get_user(v, ip + 1)) | 608 | if (get_user(v, ip + 1)) |
| 452 | return -EFAULT; | 609 | return -EFAULT; |
| 453 | 610 | ||
| 454 | input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u); | 611 | input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u); |
| 455 | input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v); | 612 | input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v); |
| 456 | 613 | ||
| 457 | return 0; | 614 | return 0; |
| 458 | 615 | ||
| 459 | case EVIOCGKEYCODE: | 616 | case EVIOCGKEYCODE: |
| 460 | if (get_user(t, ip)) | 617 | if (get_user(t, ip)) |
| 461 | return -EFAULT; | 618 | return -EFAULT; |
| 462 | 619 | ||
| 463 | error = dev->getkeycode(dev, t, &v); | 620 | error = dev->getkeycode(dev, t, &v); |
| 464 | if (error) | 621 | if (error) |
| 465 | return error; | 622 | return error; |
| 466 | 623 | ||
| 467 | if (put_user(v, ip + 1)) | 624 | if (put_user(v, ip + 1)) |
| 468 | return -EFAULT; | 625 | return -EFAULT; |
| 469 | 626 | ||
| 470 | return 0; | 627 | return 0; |
| 471 | 628 | ||
| 472 | case EVIOCSKEYCODE: | 629 | case EVIOCSKEYCODE: |
| 473 | if (get_user(t, ip) || get_user(v, ip + 1)) | 630 | if (get_user(t, ip) || get_user(v, ip + 1)) |
| 474 | return -EFAULT; | 631 | return -EFAULT; |
| 475 | 632 | ||
| 476 | return dev->setkeycode(dev, t, v); | 633 | return dev->setkeycode(dev, t, v); |
| 477 | 634 | ||
| 478 | case EVIOCSFF: | 635 | case EVIOCSFF: |
| 479 | if (copy_from_user(&effect, p, sizeof(effect))) | 636 | if (copy_from_user(&effect, p, sizeof(effect))) |
| 480 | return -EFAULT; | 637 | return -EFAULT; |
| 481 | 638 | ||
| 482 | error = input_ff_upload(dev, &effect, file); | 639 | error = input_ff_upload(dev, &effect, file); |
| 483 | 640 | ||
| 484 | if (put_user(effect.id, &(((struct ff_effect __user *)p)->id))) | 641 | if (put_user(effect.id, &(((struct ff_effect __user *)p)->id))) |
| 485 | return -EFAULT; | 642 | return -EFAULT; |
| 486 | 643 | ||
| 487 | return error; | 644 | return error; |
| 488 | 645 | ||
| 489 | case EVIOCRMFF: | 646 | case EVIOCRMFF: |
| 490 | return input_ff_erase(dev, (int)(unsigned long) p, file); | 647 | return input_ff_erase(dev, (int)(unsigned long) p, file); |
| 491 | 648 | ||
| 492 | case EVIOCGEFFECTS: | 649 | case EVIOCGEFFECTS: |
| 493 | i = test_bit(EV_FF, dev->evbit) ? dev->ff->max_effects : 0; | 650 | i = test_bit(EV_FF, dev->evbit) ? |
| 494 | if (put_user(i, ip)) | 651 | dev->ff->max_effects : 0; |
| 495 | return -EFAULT; | 652 | if (put_user(i, ip)) |
| 496 | return 0; | 653 | return -EFAULT; |
| 497 | 654 | return 0; | |
| 498 | case EVIOCGRAB: | 655 | |
| 499 | if (p) { | 656 | case EVIOCGRAB: |
| 500 | if (evdev->grab) | 657 | if (p) |
| 501 | return -EBUSY; | 658 | return evdev_grab(evdev, client); |
| 502 | if (input_grab_device(&evdev->handle)) | 659 | else |
| 503 | return -EBUSY; | 660 | return evdev_ungrab(evdev, client); |
| 504 | evdev->grab = client; | ||
| 505 | return 0; | ||
| 506 | } else { | ||
| 507 | if (evdev->grab != client) | ||
| 508 | return -EINVAL; | ||
| 509 | input_release_device(&evdev->handle); | ||
| 510 | evdev->grab = NULL; | ||
| 511 | return 0; | ||
| 512 | } | ||
| 513 | 661 | ||
| 514 | default: | 662 | default: |
| 515 | 663 | ||
| 516 | if (_IOC_TYPE(cmd) != 'E') | 664 | if (_IOC_TYPE(cmd) != 'E') |
| 517 | return -EINVAL; | 665 | return -EINVAL; |
| 518 | 666 | ||
| 519 | if (_IOC_DIR(cmd) == _IOC_READ) { | 667 | if (_IOC_DIR(cmd) == _IOC_READ) { |
| 520 | 668 | ||
| 521 | if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { | 669 | if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0))) { |
| 522 | 670 | ||
| 523 | unsigned long *bits; | 671 | unsigned long *bits; |
| 524 | int len; | 672 | int len; |
| 525 | 673 | ||
| 526 | switch (_IOC_NR(cmd) & EV_MAX) { | 674 | switch (_IOC_NR(cmd) & EV_MAX) { |
| 527 | case 0: bits = dev->evbit; len = EV_MAX; break; | ||
| 528 | case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; | ||
| 529 | case EV_REL: bits = dev->relbit; len = REL_MAX; break; | ||
| 530 | case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; | ||
| 531 | case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break; | ||
| 532 | case EV_LED: bits = dev->ledbit; len = LED_MAX; break; | ||
| 533 | case EV_SND: bits = dev->sndbit; len = SND_MAX; break; | ||
| 534 | case EV_FF: bits = dev->ffbit; len = FF_MAX; break; | ||
| 535 | case EV_SW: bits = dev->swbit; len = SW_MAX; break; | ||
| 536 | default: return -EINVAL; | ||
| 537 | } | ||
| 538 | return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode); | ||
| 539 | } | ||
| 540 | 675 | ||
| 541 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) | 676 | case 0: bits = dev->evbit; len = EV_MAX; break; |
| 542 | return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd), | 677 | case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; |
| 543 | p, compat_mode); | 678 | case EV_REL: bits = dev->relbit; len = REL_MAX; break; |
| 679 | case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; | ||
| 680 | case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break; | ||
| 681 | case EV_LED: bits = dev->ledbit; len = LED_MAX; break; | ||
| 682 | case EV_SND: bits = dev->sndbit; len = SND_MAX; break; | ||
| 683 | case EV_FF: bits = dev->ffbit; len = FF_MAX; break; | ||
| 684 | case EV_SW: bits = dev->swbit; len = SW_MAX; break; | ||
| 685 | default: return -EINVAL; | ||
| 686 | } | ||
| 687 | return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode); | ||
| 688 | } | ||
| 544 | 689 | ||
| 545 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) | 690 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) |
| 546 | return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd), | 691 | return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd), |
| 547 | p, compat_mode); | 692 | p, compat_mode); |
| 548 | 693 | ||
| 549 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) | 694 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) |
| 550 | return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd), | 695 | return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd), |
| 551 | p, compat_mode); | 696 | p, compat_mode); |
| 552 | 697 | ||
| 553 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0))) | 698 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) |
| 554 | return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd), | 699 | return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd), |
| 555 | p, compat_mode); | 700 | p, compat_mode); |
| 556 | 701 | ||
| 557 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) | 702 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0))) |
| 558 | return str_to_user(dev->name, _IOC_SIZE(cmd), p); | 703 | return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd), |
| 704 | p, compat_mode); | ||
| 559 | 705 | ||
| 560 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) | 706 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) |
| 561 | return str_to_user(dev->phys, _IOC_SIZE(cmd), p); | 707 | return str_to_user(dev->name, _IOC_SIZE(cmd), p); |
| 562 | 708 | ||
| 563 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) | 709 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) |
| 564 | return str_to_user(dev->uniq, _IOC_SIZE(cmd), p); | 710 | return str_to_user(dev->phys, _IOC_SIZE(cmd), p); |
| 565 | 711 | ||
| 566 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { | 712 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) |
| 713 | return str_to_user(dev->uniq, _IOC_SIZE(cmd), p); | ||
| 567 | 714 | ||
| 568 | t = _IOC_NR(cmd) & ABS_MAX; | 715 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { |
| 569 | 716 | ||
| 570 | abs.value = dev->abs[t]; | 717 | t = _IOC_NR(cmd) & ABS_MAX; |
| 571 | abs.minimum = dev->absmin[t]; | ||
| 572 | abs.maximum = dev->absmax[t]; | ||
| 573 | abs.fuzz = dev->absfuzz[t]; | ||
| 574 | abs.flat = dev->absflat[t]; | ||
| 575 | 718 | ||
| 576 | if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) | 719 | abs.value = dev->abs[t]; |
| 577 | return -EFAULT; | 720 | abs.minimum = dev->absmin[t]; |
| 721 | abs.maximum = dev->absmax[t]; | ||
| 722 | abs.fuzz = dev->absfuzz[t]; | ||
| 723 | abs.flat = dev->absflat[t]; | ||
| 578 | 724 | ||
| 579 | return 0; | 725 | if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) |
| 580 | } | 726 | return -EFAULT; |
| 581 | 727 | ||
| 728 | return 0; | ||
| 582 | } | 729 | } |
| 583 | 730 | ||
| 584 | if (_IOC_DIR(cmd) == _IOC_WRITE) { | 731 | } |
| 732 | |||
| 733 | if (_IOC_DIR(cmd) == _IOC_WRITE) { | ||
| 585 | 734 | ||
| 586 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { | 735 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { |
| 587 | 736 | ||
| 588 | t = _IOC_NR(cmd) & ABS_MAX; | 737 | t = _IOC_NR(cmd) & ABS_MAX; |
| 589 | 738 | ||
| 590 | if (copy_from_user(&abs, p, sizeof(struct input_absinfo))) | 739 | if (copy_from_user(&abs, p, |
| 591 | return -EFAULT; | 740 | sizeof(struct input_absinfo))) |
| 741 | return -EFAULT; | ||
| 592 | 742 | ||
| 593 | dev->abs[t] = abs.value; | 743 | /* |
| 594 | dev->absmin[t] = abs.minimum; | 744 | * Take event lock to ensure that we are not |
| 595 | dev->absmax[t] = abs.maximum; | 745 | * changing device parameters in the middle |
| 596 | dev->absfuzz[t] = abs.fuzz; | 746 | * of event. |
| 597 | dev->absflat[t] = abs.flat; | 747 | */ |
| 748 | spin_lock_irq(&dev->event_lock); | ||
| 598 | 749 | ||
| 599 | return 0; | 750 | dev->abs[t] = abs.value; |
| 600 | } | 751 | dev->absmin[t] = abs.minimum; |
| 752 | dev->absmax[t] = abs.maximum; | ||
| 753 | dev->absfuzz[t] = abs.fuzz; | ||
| 754 | dev->absflat[t] = abs.flat; | ||
| 755 | |||
| 756 | spin_unlock_irq(&dev->event_lock); | ||
| 757 | |||
| 758 | return 0; | ||
| 601 | } | 759 | } |
| 760 | } | ||
| 602 | } | 761 | } |
| 603 | return -EINVAL; | 762 | return -EINVAL; |
| 604 | } | 763 | } |
| 605 | 764 | ||
| 765 | static long evdev_ioctl_handler(struct file *file, unsigned int cmd, | ||
| 766 | void __user *p, int compat_mode) | ||
| 767 | { | ||
| 768 | struct evdev_client *client = file->private_data; | ||
| 769 | struct evdev *evdev = client->evdev; | ||
| 770 | int retval; | ||
| 771 | |||
| 772 | retval = mutex_lock_interruptible(&evdev->mutex); | ||
| 773 | if (retval) | ||
| 774 | return retval; | ||
| 775 | |||
| 776 | if (!evdev->exist) { | ||
| 777 | retval = -ENODEV; | ||
| 778 | goto out; | ||
| 779 | } | ||
| 780 | |||
| 781 | retval = evdev_do_ioctl(file, cmd, p, compat_mode); | ||
| 782 | |||
| 783 | out: | ||
| 784 | mutex_unlock(&evdev->mutex); | ||
| 785 | return retval; | ||
| 786 | } | ||
| 787 | |||
| 606 | static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 788 | static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| 607 | { | 789 | { |
| 608 | return evdev_ioctl_handler(file, cmd, (void __user *)arg, 0); | 790 | return evdev_ioctl_handler(file, cmd, (void __user *)arg, 0); |
| 609 | } | 791 | } |
| 610 | 792 | ||
| 611 | #ifdef CONFIG_COMPAT | 793 | #ifdef CONFIG_COMPAT |
| 612 | static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) | 794 | static long evdev_ioctl_compat(struct file *file, |
| 795 | unsigned int cmd, unsigned long arg) | ||
| 613 | { | 796 | { |
| 614 | return evdev_ioctl_handler(file, cmd, compat_ptr(arg), 1); | 797 | return evdev_ioctl_handler(file, cmd, compat_ptr(arg), 1); |
| 615 | } | 798 | } |
| 616 | #endif | 799 | #endif |
| 617 | 800 | ||
| 618 | static const struct file_operations evdev_fops = { | 801 | static const struct file_operations evdev_fops = { |
| 619 | .owner = THIS_MODULE, | 802 | .owner = THIS_MODULE, |
| 620 | .read = evdev_read, | 803 | .read = evdev_read, |
| 621 | .write = evdev_write, | 804 | .write = evdev_write, |
| 622 | .poll = evdev_poll, | 805 | .poll = evdev_poll, |
| 623 | .open = evdev_open, | 806 | .open = evdev_open, |
| 624 | .release = evdev_release, | 807 | .release = evdev_release, |
| 625 | .unlocked_ioctl = evdev_ioctl, | 808 | .unlocked_ioctl = evdev_ioctl, |
| 626 | #ifdef CONFIG_COMPAT | 809 | #ifdef CONFIG_COMPAT |
| 627 | .compat_ioctl = evdev_ioctl_compat, | 810 | .compat_ioctl = evdev_ioctl_compat, |
| 628 | #endif | 811 | #endif |
| 629 | .fasync = evdev_fasync, | 812 | .fasync = evdev_fasync, |
| 630 | .flush = evdev_flush | 813 | .flush = evdev_flush |
| 631 | }; | 814 | }; |
| 632 | 815 | ||
| 816 | static int evdev_install_chrdev(struct evdev *evdev) | ||
| 817 | { | ||
| 818 | /* | ||
| 819 | * No need to do any locking here as calls to connect and | ||
| 820 | * disconnect are serialized by the input core | ||
| 821 | */ | ||
| 822 | evdev_table[evdev->minor] = evdev; | ||
| 823 | return 0; | ||
| 824 | } | ||
| 825 | |||
| 826 | static void evdev_remove_chrdev(struct evdev *evdev) | ||
| 827 | { | ||
| 828 | /* | ||
| 829 | * Lock evdev table to prevent race with evdev_open() | ||
| 830 | */ | ||
| 831 | mutex_lock(&evdev_table_mutex); | ||
| 832 | evdev_table[evdev->minor] = NULL; | ||
| 833 | mutex_unlock(&evdev_table_mutex); | ||
| 834 | } | ||
| 835 | |||
| 836 | /* | ||
| 837 | * Mark device non-existent. This disables writes, ioctls and | ||
| 838 | * prevents new users from opening the device. Already posted | ||
| 839 | * blocking reads will stay, however new ones will fail. | ||
| 840 | */ | ||
| 841 | static void evdev_mark_dead(struct evdev *evdev) | ||
| 842 | { | ||
| 843 | mutex_lock(&evdev->mutex); | ||
| 844 | evdev->exist = 0; | ||
| 845 | mutex_unlock(&evdev->mutex); | ||
| 846 | } | ||
| 847 | |||
| 848 | static void evdev_cleanup(struct evdev *evdev) | ||
| 849 | { | ||
| 850 | struct input_handle *handle = &evdev->handle; | ||
| 851 | |||
| 852 | evdev_mark_dead(evdev); | ||
| 853 | evdev_hangup(evdev); | ||
| 854 | evdev_remove_chrdev(evdev); | ||
| 855 | |||
| 856 | /* evdev is marked dead so no one else accesses evdev->open */ | ||
| 857 | if (evdev->open) { | ||
| 858 | input_flush_device(handle, NULL); | ||
| 859 | input_close_device(handle); | ||
| 860 | } | ||
| 861 | } | ||
| 862 | |||
| 863 | /* | ||
| 864 | * Create new evdev device. Note that input core serializes calls | ||
| 865 | * to connect and disconnect so we don't need to lock evdev_table here. | ||
| 866 | */ | ||
| 633 | static int evdev_connect(struct input_handler *handler, struct input_dev *dev, | 867 | static int evdev_connect(struct input_handler *handler, struct input_dev *dev, |
| 634 | const struct input_device_id *id) | 868 | const struct input_device_id *id) |
| 635 | { | 869 | { |
| @@ -637,7 +871,10 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, | |||
| 637 | int minor; | 871 | int minor; |
| 638 | int error; | 872 | int error; |
| 639 | 873 | ||
| 640 | for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++); | 874 | for (minor = 0; minor < EVDEV_MINORS; minor++) |
| 875 | if (!evdev_table[minor]) | ||
| 876 | break; | ||
| 877 | |||
| 641 | if (minor == EVDEV_MINORS) { | 878 | if (minor == EVDEV_MINORS) { |
| 642 | printk(KERN_ERR "evdev: no more free evdev devices\n"); | 879 | printk(KERN_ERR "evdev: no more free evdev devices\n"); |
| 643 | return -ENFILE; | 880 | return -ENFILE; |
| @@ -648,38 +885,44 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, | |||
| 648 | return -ENOMEM; | 885 | return -ENOMEM; |
| 649 | 886 | ||
| 650 | INIT_LIST_HEAD(&evdev->client_list); | 887 | INIT_LIST_HEAD(&evdev->client_list); |
| 888 | spin_lock_init(&evdev->client_lock); | ||
| 889 | mutex_init(&evdev->mutex); | ||
| 651 | init_waitqueue_head(&evdev->wait); | 890 | init_waitqueue_head(&evdev->wait); |
| 652 | 891 | ||
| 892 | snprintf(evdev->name, sizeof(evdev->name), "event%d", minor); | ||
| 653 | evdev->exist = 1; | 893 | evdev->exist = 1; |
| 654 | evdev->minor = minor; | 894 | evdev->minor = minor; |
| 895 | |||
| 655 | evdev->handle.dev = dev; | 896 | evdev->handle.dev = dev; |
| 656 | evdev->handle.name = evdev->name; | 897 | evdev->handle.name = evdev->name; |
| 657 | evdev->handle.handler = handler; | 898 | evdev->handle.handler = handler; |
| 658 | evdev->handle.private = evdev; | 899 | evdev->handle.private = evdev; |
| 659 | snprintf(evdev->name, sizeof(evdev->name), "event%d", minor); | ||
| 660 | 900 | ||
| 661 | snprintf(evdev->dev.bus_id, sizeof(evdev->dev.bus_id), | 901 | strlcpy(evdev->dev.bus_id, evdev->name, sizeof(evdev->dev.bus_id)); |
| 662 | "event%d", minor); | 902 | evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor); |
| 663 | evdev->dev.class = &input_class; | 903 | evdev->dev.class = &input_class; |
| 664 | evdev->dev.parent = &dev->dev; | 904 | evdev->dev.parent = &dev->dev; |
| 665 | evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor); | ||
| 666 | evdev->dev.release = evdev_free; | 905 | evdev->dev.release = evdev_free; |
| 667 | device_initialize(&evdev->dev); | 906 | device_initialize(&evdev->dev); |
| 668 | 907 | ||
| 669 | evdev_table[minor] = evdev; | 908 | error = input_register_handle(&evdev->handle); |
| 670 | |||
| 671 | error = device_add(&evdev->dev); | ||
| 672 | if (error) | 909 | if (error) |
| 673 | goto err_free_evdev; | 910 | goto err_free_evdev; |
| 674 | 911 | ||
| 675 | error = input_register_handle(&evdev->handle); | 912 | error = evdev_install_chrdev(evdev); |
| 913 | if (error) | ||
| 914 | goto err_unregister_handle; | ||
| 915 | |||
| 916 | error = device_add(&evdev->dev); | ||
| 676 | if (error) | 917 | if (error) |
| 677 | goto err_delete_evdev; | 918 | goto err_cleanup_evdev; |
| 678 | 919 | ||
| 679 | return 0; | 920 | return 0; |
| 680 | 921 | ||
| 681 | err_delete_evdev: | 922 | err_cleanup_evdev: |
| 682 | device_del(&evdev->dev); | 923 | evdev_cleanup(evdev); |
| 924 | err_unregister_handle: | ||
| 925 | input_unregister_handle(&evdev->handle); | ||
| 683 | err_free_evdev: | 926 | err_free_evdev: |
| 684 | put_device(&evdev->dev); | 927 | put_device(&evdev->dev); |
| 685 | return error; | 928 | return error; |
| @@ -688,21 +931,10 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, | |||
| 688 | static void evdev_disconnect(struct input_handle *handle) | 931 | static void evdev_disconnect(struct input_handle *handle) |
| 689 | { | 932 | { |
| 690 | struct evdev *evdev = handle->private; | 933 | struct evdev *evdev = handle->private; |
| 691 | struct evdev_client *client; | ||
| 692 | 934 | ||
| 693 | input_unregister_handle(handle); | ||
| 694 | device_del(&evdev->dev); | 935 | device_del(&evdev->dev); |
| 695 | 936 | evdev_cleanup(evdev); | |
| 696 | evdev->exist = 0; | 937 | input_unregister_handle(handle); |
| 697 | |||
| 698 | if (evdev->open) { | ||
| 699 | input_flush_device(handle, NULL); | ||
| 700 | input_close_device(handle); | ||
| 701 | list_for_each_entry(client, &evdev->client_list, node) | ||
| 702 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); | ||
| 703 | wake_up_interruptible(&evdev->wait); | ||
| 704 | } | ||
| 705 | |||
| 706 | put_device(&evdev->dev); | 938 | put_device(&evdev->dev); |
| 707 | } | 939 | } |
| 708 | 940 | ||
| @@ -714,13 +946,13 @@ static const struct input_device_id evdev_ids[] = { | |||
| 714 | MODULE_DEVICE_TABLE(input, evdev_ids); | 946 | MODULE_DEVICE_TABLE(input, evdev_ids); |
| 715 | 947 | ||
| 716 | static struct input_handler evdev_handler = { | 948 | static struct input_handler evdev_handler = { |
| 717 | .event = evdev_event, | 949 | .event = evdev_event, |
| 718 | .connect = evdev_connect, | 950 | .connect = evdev_connect, |
| 719 | .disconnect = evdev_disconnect, | 951 | .disconnect = evdev_disconnect, |
| 720 | .fops = &evdev_fops, | 952 | .fops = &evdev_fops, |
| 721 | .minor = EVDEV_MINOR_BASE, | 953 | .minor = EVDEV_MINOR_BASE, |
| 722 | .name = "evdev", | 954 | .name = "evdev", |
| 723 | .id_table = evdev_ids, | 955 | .id_table = evdev_ids, |
| 724 | }; | 956 | }; |
| 725 | 957 | ||
| 726 | static int __init evdev_init(void) | 958 | static int __init evdev_init(void) |
diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c index b773d4c756a6..92b359894e81 100644 --- a/drivers/input/input-polldev.c +++ b/drivers/input/input-polldev.c | |||
| @@ -70,6 +70,7 @@ static int input_open_polled_device(struct input_dev *input) | |||
| 70 | { | 70 | { |
| 71 | struct input_polled_dev *dev = input->private; | 71 | struct input_polled_dev *dev = input->private; |
| 72 | int error; | 72 | int error; |
| 73 | unsigned long ticks; | ||
| 73 | 74 | ||
| 74 | error = input_polldev_start_workqueue(); | 75 | error = input_polldev_start_workqueue(); |
| 75 | if (error) | 76 | if (error) |
| @@ -78,8 +79,10 @@ static int input_open_polled_device(struct input_dev *input) | |||
| 78 | if (dev->flush) | 79 | if (dev->flush) |
| 79 | dev->flush(dev); | 80 | dev->flush(dev); |
| 80 | 81 | ||
| 81 | queue_delayed_work(polldev_wq, &dev->work, | 82 | ticks = msecs_to_jiffies(dev->poll_interval); |
| 82 | msecs_to_jiffies(dev->poll_interval)); | 83 | if (ticks >= HZ) |
| 84 | ticks = round_jiffies(ticks); | ||
| 85 | queue_delayed_work(polldev_wq, &dev->work, ticks); | ||
| 83 | 86 | ||
| 84 | return 0; | 87 | return 0; |
| 85 | } | 88 | } |
diff --git a/drivers/input/input.c b/drivers/input/input.c index 5dc361c954e2..2f2b020cd629 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
| @@ -17,10 +17,10 @@ | |||
| 17 | #include <linux/major.h> | 17 | #include <linux/major.h> |
| 18 | #include <linux/proc_fs.h> | 18 | #include <linux/proc_fs.h> |
| 19 | #include <linux/seq_file.h> | 19 | #include <linux/seq_file.h> |
| 20 | #include <linux/interrupt.h> | ||
| 21 | #include <linux/poll.h> | 20 | #include <linux/poll.h> |
| 22 | #include <linux/device.h> | 21 | #include <linux/device.h> |
| 23 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
| 23 | #include <linux/rcupdate.h> | ||
| 24 | 24 | ||
| 25 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); | 25 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); |
| 26 | MODULE_DESCRIPTION("Input core"); | 26 | MODULE_DESCRIPTION("Input core"); |
| @@ -31,167 +31,245 @@ MODULE_LICENSE("GPL"); | |||
| 31 | static LIST_HEAD(input_dev_list); | 31 | static LIST_HEAD(input_dev_list); |
| 32 | static LIST_HEAD(input_handler_list); | 32 | static LIST_HEAD(input_handler_list); |
| 33 | 33 | ||
| 34 | /* | ||
| 35 | * input_mutex protects access to both input_dev_list and input_handler_list. | ||
| 36 | * This also causes input_[un]register_device and input_[un]register_handler | ||
| 37 | * be mutually exclusive which simplifies locking in drivers implementing | ||
| 38 | * input handlers. | ||
| 39 | */ | ||
| 40 | static DEFINE_MUTEX(input_mutex); | ||
| 41 | |||
| 34 | static struct input_handler *input_table[8]; | 42 | static struct input_handler *input_table[8]; |
| 35 | 43 | ||
| 36 | /** | 44 | static inline int is_event_supported(unsigned int code, |
| 37 | * input_event() - report new input event | 45 | unsigned long *bm, unsigned int max) |
| 38 | * @dev: device that generated the event | ||
| 39 | * @type: type of the event | ||
| 40 | * @code: event code | ||
| 41 | * @value: value of the event | ||
| 42 | * | ||
| 43 | * This function should be used by drivers implementing various input devices | ||
| 44 | * See also input_inject_event() | ||
| 45 | */ | ||
| 46 | void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | ||
| 47 | { | 46 | { |
| 48 | struct input_handle *handle; | 47 | return code <= max && test_bit(code, bm); |
| 48 | } | ||
| 49 | 49 | ||
| 50 | if (type > EV_MAX || !test_bit(type, dev->evbit)) | 50 | static int input_defuzz_abs_event(int value, int old_val, int fuzz) |
| 51 | return; | 51 | { |
| 52 | if (fuzz) { | ||
| 53 | if (value > old_val - fuzz / 2 && value < old_val + fuzz / 2) | ||
| 54 | return old_val; | ||
| 52 | 55 | ||
| 53 | add_input_randomness(type, code, value); | 56 | if (value > old_val - fuzz && value < old_val + fuzz) |
| 57 | return (old_val * 3 + value) / 4; | ||
| 54 | 58 | ||
| 55 | switch (type) { | 59 | if (value > old_val - fuzz * 2 && value < old_val + fuzz * 2) |
| 56 | 60 | return (old_val + value) / 2; | |
| 57 | case EV_SYN: | 61 | } |
| 58 | switch (code) { | ||
| 59 | case SYN_CONFIG: | ||
| 60 | if (dev->event) | ||
| 61 | dev->event(dev, type, code, value); | ||
| 62 | break; | ||
| 63 | |||
| 64 | case SYN_REPORT: | ||
| 65 | if (dev->sync) | ||
| 66 | return; | ||
| 67 | dev->sync = 1; | ||
| 68 | break; | ||
| 69 | } | ||
| 70 | break; | ||
| 71 | 62 | ||
| 72 | case EV_KEY: | 63 | return value; |
| 64 | } | ||
| 73 | 65 | ||
| 74 | if (code > KEY_MAX || !test_bit(code, dev->keybit) || !!test_bit(code, dev->key) == value) | 66 | /* |
| 75 | return; | 67 | * Pass event through all open handles. This function is called with |
| 68 | * dev->event_lock held and interrupts disabled. | ||
| 69 | */ | ||
| 70 | static void input_pass_event(struct input_dev *dev, | ||
| 71 | unsigned int type, unsigned int code, int value) | ||
| 72 | { | ||
| 73 | struct input_handle *handle; | ||
| 76 | 74 | ||
| 77 | if (value == 2) | 75 | rcu_read_lock(); |
| 78 | break; | ||
| 79 | 76 | ||
| 80 | change_bit(code, dev->key); | 77 | handle = rcu_dereference(dev->grab); |
| 78 | if (handle) | ||
| 79 | handle->handler->event(handle, type, code, value); | ||
| 80 | else | ||
| 81 | list_for_each_entry_rcu(handle, &dev->h_list, d_node) | ||
| 82 | if (handle->open) | ||
| 83 | handle->handler->event(handle, | ||
| 84 | type, code, value); | ||
| 85 | rcu_read_unlock(); | ||
| 86 | } | ||
| 81 | 87 | ||
| 82 | if (test_bit(EV_REP, dev->evbit) && dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] && dev->timer.data && value) { | 88 | /* |
| 83 | dev->repeat_key = code; | 89 | * Generate software autorepeat event. Note that we take |
| 84 | mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_DELAY])); | 90 | * dev->event_lock here to avoid racing with input_event |
| 85 | } | 91 | * which may cause keys get "stuck". |
| 92 | */ | ||
| 93 | static void input_repeat_key(unsigned long data) | ||
| 94 | { | ||
| 95 | struct input_dev *dev = (void *) data; | ||
| 96 | unsigned long flags; | ||
| 86 | 97 | ||
| 87 | break; | 98 | spin_lock_irqsave(&dev->event_lock, flags); |
| 88 | 99 | ||
| 89 | case EV_SW: | 100 | if (test_bit(dev->repeat_key, dev->key) && |
| 101 | is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) { | ||
| 90 | 102 | ||
| 91 | if (code > SW_MAX || !test_bit(code, dev->swbit) || !!test_bit(code, dev->sw) == value) | 103 | input_pass_event(dev, EV_KEY, dev->repeat_key, 2); |
| 92 | return; | ||
| 93 | 104 | ||
| 94 | change_bit(code, dev->sw); | 105 | if (dev->sync) { |
| 106 | /* | ||
| 107 | * Only send SYN_REPORT if we are not in a middle | ||
| 108 | * of driver parsing a new hardware packet. | ||
| 109 | * Otherwise assume that the driver will send | ||
| 110 | * SYN_REPORT once it's done. | ||
| 111 | */ | ||
| 112 | input_pass_event(dev, EV_SYN, SYN_REPORT, 1); | ||
| 113 | } | ||
| 95 | 114 | ||
| 96 | break; | 115 | if (dev->rep[REP_PERIOD]) |
| 116 | mod_timer(&dev->timer, jiffies + | ||
| 117 | msecs_to_jiffies(dev->rep[REP_PERIOD])); | ||
| 118 | } | ||
| 97 | 119 | ||
| 98 | case EV_ABS: | 120 | spin_unlock_irqrestore(&dev->event_lock, flags); |
| 121 | } | ||
| 99 | 122 | ||
| 100 | if (code > ABS_MAX || !test_bit(code, dev->absbit)) | 123 | static void input_start_autorepeat(struct input_dev *dev, int code) |
| 101 | return; | 124 | { |
| 125 | if (test_bit(EV_REP, dev->evbit) && | ||
| 126 | dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] && | ||
| 127 | dev->timer.data) { | ||
| 128 | dev->repeat_key = code; | ||
| 129 | mod_timer(&dev->timer, | ||
| 130 | jiffies + msecs_to_jiffies(dev->rep[REP_DELAY])); | ||
| 131 | } | ||
| 132 | } | ||
| 102 | 133 | ||
| 103 | if (dev->absfuzz[code]) { | 134 | #define INPUT_IGNORE_EVENT 0 |
| 104 | if ((value > dev->abs[code] - (dev->absfuzz[code] >> 1)) && | 135 | #define INPUT_PASS_TO_HANDLERS 1 |
| 105 | (value < dev->abs[code] + (dev->absfuzz[code] >> 1))) | 136 | #define INPUT_PASS_TO_DEVICE 2 |
| 106 | return; | 137 | #define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE) |
| 107 | 138 | ||
| 108 | if ((value > dev->abs[code] - dev->absfuzz[code]) && | 139 | static void input_handle_event(struct input_dev *dev, |
| 109 | (value < dev->abs[code] + dev->absfuzz[code])) | 140 | unsigned int type, unsigned int code, int value) |
| 110 | value = (dev->abs[code] * 3 + value) >> 2; | 141 | { |
| 142 | int disposition = INPUT_IGNORE_EVENT; | ||
| 111 | 143 | ||
| 112 | if ((value > dev->abs[code] - (dev->absfuzz[code] << 1)) && | 144 | switch (type) { |
| 113 | (value < dev->abs[code] + (dev->absfuzz[code] << 1))) | ||
| 114 | value = (dev->abs[code] + value) >> 1; | ||
| 115 | } | ||
| 116 | 145 | ||
| 117 | if (dev->abs[code] == value) | 146 | case EV_SYN: |
| 118 | return; | 147 | switch (code) { |
| 148 | case SYN_CONFIG: | ||
| 149 | disposition = INPUT_PASS_TO_ALL; | ||
| 150 | break; | ||
| 119 | 151 | ||
| 120 | dev->abs[code] = value; | 152 | case SYN_REPORT: |
| 153 | if (!dev->sync) { | ||
| 154 | dev->sync = 1; | ||
| 155 | disposition = INPUT_PASS_TO_HANDLERS; | ||
| 156 | } | ||
| 121 | break; | 157 | break; |
| 158 | } | ||
| 159 | break; | ||
| 122 | 160 | ||
| 123 | case EV_REL: | 161 | case EV_KEY: |
| 162 | if (is_event_supported(code, dev->keybit, KEY_MAX) && | ||
| 163 | !!test_bit(code, dev->key) != value) { | ||
| 124 | 164 | ||
| 125 | if (code > REL_MAX || !test_bit(code, dev->relbit) || (value == 0)) | 165 | if (value != 2) { |
| 126 | return; | 166 | __change_bit(code, dev->key); |
| 167 | if (value) | ||
| 168 | input_start_autorepeat(dev, code); | ||
| 169 | } | ||
| 127 | 170 | ||
| 128 | break; | 171 | disposition = INPUT_PASS_TO_HANDLERS; |
| 172 | } | ||
| 173 | break; | ||
| 129 | 174 | ||
| 130 | case EV_MSC: | 175 | case EV_SW: |
| 176 | if (is_event_supported(code, dev->swbit, SW_MAX) && | ||
| 177 | !!test_bit(code, dev->sw) != value) { | ||
| 131 | 178 | ||
| 132 | if (code > MSC_MAX || !test_bit(code, dev->mscbit)) | 179 | __change_bit(code, dev->sw); |
| 133 | return; | 180 | disposition = INPUT_PASS_TO_HANDLERS; |
| 181 | } | ||
| 182 | break; | ||
| 134 | 183 | ||
| 135 | if (dev->event) | 184 | case EV_ABS: |
| 136 | dev->event(dev, type, code, value); | 185 | if (is_event_supported(code, dev->absbit, ABS_MAX)) { |
| 137 | 186 | ||
| 138 | break; | 187 | value = input_defuzz_abs_event(value, |
| 188 | dev->abs[code], dev->absfuzz[code]); | ||
| 189 | |||
| 190 | if (dev->abs[code] != value) { | ||
| 191 | dev->abs[code] = value; | ||
| 192 | disposition = INPUT_PASS_TO_HANDLERS; | ||
| 193 | } | ||
| 194 | } | ||
| 195 | break; | ||
| 139 | 196 | ||
| 140 | case EV_LED: | 197 | case EV_REL: |
| 198 | if (is_event_supported(code, dev->relbit, REL_MAX) && value) | ||
| 199 | disposition = INPUT_PASS_TO_HANDLERS; | ||
| 141 | 200 | ||
| 142 | if (code > LED_MAX || !test_bit(code, dev->ledbit) || !!test_bit(code, dev->led) == value) | 201 | break; |
| 143 | return; | ||
| 144 | 202 | ||
| 145 | change_bit(code, dev->led); | 203 | case EV_MSC: |
| 204 | if (is_event_supported(code, dev->mscbit, MSC_MAX)) | ||
| 205 | disposition = INPUT_PASS_TO_ALL; | ||
| 146 | 206 | ||
| 147 | if (dev->event) | 207 | break; |
| 148 | dev->event(dev, type, code, value); | ||
| 149 | 208 | ||
| 150 | break; | 209 | case EV_LED: |
| 210 | if (is_event_supported(code, dev->ledbit, LED_MAX) && | ||
| 211 | !!test_bit(code, dev->led) != value) { | ||
| 151 | 212 | ||
| 152 | case EV_SND: | 213 | __change_bit(code, dev->led); |
| 214 | disposition = INPUT_PASS_TO_ALL; | ||
| 215 | } | ||
| 216 | break; | ||
| 153 | 217 | ||
| 154 | if (code > SND_MAX || !test_bit(code, dev->sndbit)) | 218 | case EV_SND: |
| 155 | return; | 219 | if (is_event_supported(code, dev->sndbit, SND_MAX)) { |
| 156 | 220 | ||
| 157 | if (!!test_bit(code, dev->snd) != !!value) | 221 | if (!!test_bit(code, dev->snd) != !!value) |
| 158 | change_bit(code, dev->snd); | 222 | __change_bit(code, dev->snd); |
| 223 | disposition = INPUT_PASS_TO_ALL; | ||
| 224 | } | ||
| 225 | break; | ||
| 159 | 226 | ||
| 160 | if (dev->event) | 227 | case EV_REP: |
| 161 | dev->event(dev, type, code, value); | 228 | if (code <= REP_MAX && value >= 0 && dev->rep[code] != value) { |
| 229 | dev->rep[code] = value; | ||
| 230 | disposition = INPUT_PASS_TO_ALL; | ||
| 231 | } | ||
| 232 | break; | ||
| 162 | 233 | ||
| 163 | break; | 234 | case EV_FF: |
| 235 | if (value >= 0) | ||
| 236 | disposition = INPUT_PASS_TO_ALL; | ||
| 237 | break; | ||
| 238 | } | ||
| 164 | 239 | ||
| 165 | case EV_REP: | 240 | if (type != EV_SYN) |
| 241 | dev->sync = 0; | ||
| 166 | 242 | ||
| 167 | if (code > REP_MAX || value < 0 || dev->rep[code] == value) | 243 | if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event) |
| 168 | return; | 244 | dev->event(dev, type, code, value); |
| 169 | 245 | ||
| 170 | dev->rep[code] = value; | 246 | if (disposition & INPUT_PASS_TO_HANDLERS) |
| 171 | if (dev->event) | 247 | input_pass_event(dev, type, code, value); |
| 172 | dev->event(dev, type, code, value); | 248 | } |
| 173 | 249 | ||
| 174 | break; | 250 | /** |
| 251 | * input_event() - report new input event | ||
| 252 | * @dev: device that generated the event | ||
| 253 | * @type: type of the event | ||
| 254 | * @code: event code | ||
| 255 | * @value: value of the event | ||
| 256 | * | ||
| 257 | * This function should be used by drivers implementing various input | ||
| 258 | * devices. See also input_inject_event(). | ||
| 259 | */ | ||
| 175 | 260 | ||
| 176 | case EV_FF: | 261 | void input_event(struct input_dev *dev, |
| 262 | unsigned int type, unsigned int code, int value) | ||
| 263 | { | ||
| 264 | unsigned long flags; | ||
| 177 | 265 | ||
| 178 | if (value < 0) | 266 | if (is_event_supported(type, dev->evbit, EV_MAX)) { |
| 179 | return; | ||
| 180 | 267 | ||
| 181 | if (dev->event) | 268 | spin_lock_irqsave(&dev->event_lock, flags); |
| 182 | dev->event(dev, type, code, value); | 269 | add_input_randomness(type, code, value); |
| 183 | break; | 270 | input_handle_event(dev, type, code, value); |
| 271 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
| 184 | } | 272 | } |
| 185 | |||
| 186 | if (type != EV_SYN) | ||
| 187 | dev->sync = 0; | ||
| 188 | |||
| 189 | if (dev->grab) | ||
| 190 | dev->grab->handler->event(dev->grab, type, code, value); | ||
| 191 | else | ||
| 192 | list_for_each_entry(handle, &dev->h_list, d_node) | ||
| 193 | if (handle->open) | ||
| 194 | handle->handler->event(handle, type, code, value); | ||
| 195 | } | 273 | } |
| 196 | EXPORT_SYMBOL(input_event); | 274 | EXPORT_SYMBOL(input_event); |
| 197 | 275 | ||
| @@ -202,102 +280,228 @@ EXPORT_SYMBOL(input_event); | |||
| 202 | * @code: event code | 280 | * @code: event code |
| 203 | * @value: value of the event | 281 | * @value: value of the event |
| 204 | * | 282 | * |
| 205 | * Similar to input_event() but will ignore event if device is "grabbed" and handle | 283 | * Similar to input_event() but will ignore event if device is |
| 206 | * injecting event is not the one that owns the device. | 284 | * "grabbed" and handle injecting event is not the one that owns |
| 285 | * the device. | ||
| 207 | */ | 286 | */ |
| 208 | void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) | 287 | void input_inject_event(struct input_handle *handle, |
| 209 | { | 288 | unsigned int type, unsigned int code, int value) |
| 210 | if (!handle->dev->grab || handle->dev->grab == handle) | ||
| 211 | input_event(handle->dev, type, code, value); | ||
| 212 | } | ||
| 213 | EXPORT_SYMBOL(input_inject_event); | ||
| 214 | |||
| 215 | static void input_repeat_key(unsigned long data) | ||
| 216 | { | 289 | { |
| 217 | struct input_dev *dev = (void *) data; | 290 | struct input_dev *dev = handle->dev; |
| 291 | struct input_handle *grab; | ||
| 292 | unsigned long flags; | ||
| 218 | 293 | ||
| 219 | if (!test_bit(dev->repeat_key, dev->key)) | 294 | if (is_event_supported(type, dev->evbit, EV_MAX)) { |
| 220 | return; | 295 | spin_lock_irqsave(&dev->event_lock, flags); |
| 221 | 296 | ||
| 222 | input_event(dev, EV_KEY, dev->repeat_key, 2); | 297 | rcu_read_lock(); |
| 223 | input_sync(dev); | 298 | grab = rcu_dereference(dev->grab); |
| 299 | if (!grab || grab == handle) | ||
| 300 | input_handle_event(dev, type, code, value); | ||
| 301 | rcu_read_unlock(); | ||
| 224 | 302 | ||
| 225 | if (dev->rep[REP_PERIOD]) | 303 | spin_unlock_irqrestore(&dev->event_lock, flags); |
| 226 | mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_PERIOD])); | 304 | } |
| 227 | } | 305 | } |
| 306 | EXPORT_SYMBOL(input_inject_event); | ||
| 228 | 307 | ||
| 308 | /** | ||
| 309 | * input_grab_device - grabs device for exclusive use | ||
| 310 | * @handle: input handle that wants to own the device | ||
| 311 | * | ||
| 312 | * When a device is grabbed by an input handle all events generated by | ||
| 313 | * the device are delivered only to this handle. Also events injected | ||
| 314 | * by other input handles are ignored while device is grabbed. | ||
| 315 | */ | ||
| 229 | int input_grab_device(struct input_handle *handle) | 316 | int input_grab_device(struct input_handle *handle) |
| 230 | { | 317 | { |
| 231 | if (handle->dev->grab) | 318 | struct input_dev *dev = handle->dev; |
| 232 | return -EBUSY; | 319 | int retval; |
| 233 | 320 | ||
| 234 | handle->dev->grab = handle; | 321 | retval = mutex_lock_interruptible(&dev->mutex); |
| 235 | return 0; | 322 | if (retval) |
| 323 | return retval; | ||
| 324 | |||
| 325 | if (dev->grab) { | ||
| 326 | retval = -EBUSY; | ||
| 327 | goto out; | ||
| 328 | } | ||
| 329 | |||
| 330 | rcu_assign_pointer(dev->grab, handle); | ||
| 331 | synchronize_rcu(); | ||
| 332 | |||
| 333 | out: | ||
| 334 | mutex_unlock(&dev->mutex); | ||
| 335 | return retval; | ||
| 236 | } | 336 | } |
| 237 | EXPORT_SYMBOL(input_grab_device); | 337 | EXPORT_SYMBOL(input_grab_device); |
| 238 | 338 | ||
| 239 | void input_release_device(struct input_handle *handle) | 339 | static void __input_release_device(struct input_handle *handle) |
| 240 | { | 340 | { |
| 241 | struct input_dev *dev = handle->dev; | 341 | struct input_dev *dev = handle->dev; |
| 242 | 342 | ||
| 243 | if (dev->grab == handle) { | 343 | if (dev->grab == handle) { |
| 244 | dev->grab = NULL; | 344 | rcu_assign_pointer(dev->grab, NULL); |
| 345 | /* Make sure input_pass_event() notices that grab is gone */ | ||
| 346 | synchronize_rcu(); | ||
| 245 | 347 | ||
| 246 | list_for_each_entry(handle, &dev->h_list, d_node) | 348 | list_for_each_entry(handle, &dev->h_list, d_node) |
| 247 | if (handle->handler->start) | 349 | if (handle->open && handle->handler->start) |
| 248 | handle->handler->start(handle); | 350 | handle->handler->start(handle); |
| 249 | } | 351 | } |
| 250 | } | 352 | } |
| 353 | |||
| 354 | /** | ||
| 355 | * input_release_device - release previously grabbed device | ||
| 356 | * @handle: input handle that owns the device | ||
| 357 | * | ||
| 358 | * Releases previously grabbed device so that other input handles can | ||
| 359 | * start receiving input events. Upon release all handlers attached | ||
| 360 | * to the device have their start() method called so they have a change | ||
| 361 | * to synchronize device state with the rest of the system. | ||
| 362 | */ | ||
| 363 | void input_release_device(struct input_handle *handle) | ||
| 364 | { | ||
| 365 | struct input_dev *dev = handle->dev; | ||
| 366 | |||
| 367 | mutex_lock(&dev->mutex); | ||
| 368 | __input_release_device(handle); | ||
| 369 | mutex_unlock(&dev->mutex); | ||
| 370 | } | ||
| 251 | EXPORT_SYMBOL(input_release_device); | 371 | EXPORT_SYMBOL(input_release_device); |
| 252 | 372 | ||
| 373 | /** | ||
| 374 | * input_open_device - open input device | ||
| 375 | * @handle: handle through which device is being accessed | ||
| 376 | * | ||
| 377 | * This function should be called by input handlers when they | ||
| 378 | * want to start receive events from given input device. | ||
| 379 | */ | ||
| 253 | int input_open_device(struct input_handle *handle) | 380 | int input_open_device(struct input_handle *handle) |
| 254 | { | 381 | { |
| 255 | struct input_dev *dev = handle->dev; | 382 | struct input_dev *dev = handle->dev; |
| 256 | int err; | 383 | int retval; |
| 257 | 384 | ||
| 258 | err = mutex_lock_interruptible(&dev->mutex); | 385 | retval = mutex_lock_interruptible(&dev->mutex); |
| 259 | if (err) | 386 | if (retval) |
| 260 | return err; | 387 | return retval; |
| 388 | |||
| 389 | if (dev->going_away) { | ||
| 390 | retval = -ENODEV; | ||
| 391 | goto out; | ||
| 392 | } | ||
| 261 | 393 | ||
| 262 | handle->open++; | 394 | handle->open++; |
| 263 | 395 | ||
| 264 | if (!dev->users++ && dev->open) | 396 | if (!dev->users++ && dev->open) |
| 265 | err = dev->open(dev); | 397 | retval = dev->open(dev); |
| 266 | 398 | ||
| 267 | if (err) | 399 | if (retval) { |
| 268 | handle->open--; | 400 | dev->users--; |
| 401 | if (!--handle->open) { | ||
| 402 | /* | ||
| 403 | * Make sure we are not delivering any more events | ||
| 404 | * through this handle | ||
| 405 | */ | ||
| 406 | synchronize_rcu(); | ||
| 407 | } | ||
| 408 | } | ||
| 269 | 409 | ||
| 410 | out: | ||
| 270 | mutex_unlock(&dev->mutex); | 411 | mutex_unlock(&dev->mutex); |
| 271 | 412 | return retval; | |
| 272 | return err; | ||
| 273 | } | 413 | } |
| 274 | EXPORT_SYMBOL(input_open_device); | 414 | EXPORT_SYMBOL(input_open_device); |
| 275 | 415 | ||
| 276 | int input_flush_device(struct input_handle* handle, struct file* file) | 416 | int input_flush_device(struct input_handle *handle, struct file *file) |
| 277 | { | 417 | { |
| 278 | if (handle->dev->flush) | 418 | struct input_dev *dev = handle->dev; |
| 279 | return handle->dev->flush(handle->dev, file); | 419 | int retval; |
| 280 | 420 | ||
| 281 | return 0; | 421 | retval = mutex_lock_interruptible(&dev->mutex); |
| 422 | if (retval) | ||
| 423 | return retval; | ||
| 424 | |||
| 425 | if (dev->flush) | ||
| 426 | retval = dev->flush(dev, file); | ||
| 427 | |||
| 428 | mutex_unlock(&dev->mutex); | ||
| 429 | return retval; | ||
| 282 | } | 430 | } |
| 283 | EXPORT_SYMBOL(input_flush_device); | 431 | EXPORT_SYMBOL(input_flush_device); |
| 284 | 432 | ||
| 433 | /** | ||
| 434 | * input_close_device - close input device | ||
| 435 | * @handle: handle through which device is being accessed | ||
| 436 | * | ||
| 437 | * This function should be called by input handlers when they | ||
| 438 | * want to stop receive events from given input device. | ||
| 439 | */ | ||
| 285 | void input_close_device(struct input_handle *handle) | 440 | void input_close_device(struct input_handle *handle) |
| 286 | { | 441 | { |
| 287 | struct input_dev *dev = handle->dev; | 442 | struct input_dev *dev = handle->dev; |
| 288 | 443 | ||
| 289 | input_release_device(handle); | ||
| 290 | |||
| 291 | mutex_lock(&dev->mutex); | 444 | mutex_lock(&dev->mutex); |
| 292 | 445 | ||
| 446 | __input_release_device(handle); | ||
| 447 | |||
| 293 | if (!--dev->users && dev->close) | 448 | if (!--dev->users && dev->close) |
| 294 | dev->close(dev); | 449 | dev->close(dev); |
| 295 | handle->open--; | 450 | |
| 451 | if (!--handle->open) { | ||
| 452 | /* | ||
| 453 | * synchronize_rcu() makes sure that input_pass_event() | ||
| 454 | * completed and that no more input events are delivered | ||
| 455 | * through this handle | ||
| 456 | */ | ||
| 457 | synchronize_rcu(); | ||
| 458 | } | ||
| 296 | 459 | ||
| 297 | mutex_unlock(&dev->mutex); | 460 | mutex_unlock(&dev->mutex); |
| 298 | } | 461 | } |
| 299 | EXPORT_SYMBOL(input_close_device); | 462 | EXPORT_SYMBOL(input_close_device); |
| 300 | 463 | ||
| 464 | /* | ||
| 465 | * Prepare device for unregistering | ||
| 466 | */ | ||
| 467 | static void input_disconnect_device(struct input_dev *dev) | ||
| 468 | { | ||
| 469 | struct input_handle *handle; | ||
| 470 | int code; | ||
| 471 | |||
| 472 | /* | ||
| 473 | * Mark device as going away. Note that we take dev->mutex here | ||
| 474 | * not to protect access to dev->going_away but rather to ensure | ||
| 475 | * that there are no threads in the middle of input_open_device() | ||
| 476 | */ | ||
| 477 | mutex_lock(&dev->mutex); | ||
| 478 | dev->going_away = 1; | ||
| 479 | mutex_unlock(&dev->mutex); | ||
| 480 | |||
| 481 | spin_lock_irq(&dev->event_lock); | ||
| 482 | |||
| 483 | /* | ||
| 484 | * Simulate keyup events for all pressed keys so that handlers | ||
| 485 | * are not left with "stuck" keys. The driver may continue | ||
| 486 | * generate events even after we done here but they will not | ||
| 487 | * reach any handlers. | ||
| 488 | */ | ||
| 489 | if (is_event_supported(EV_KEY, dev->evbit, EV_MAX)) { | ||
| 490 | for (code = 0; code <= KEY_MAX; code++) { | ||
| 491 | if (is_event_supported(code, dev->keybit, KEY_MAX) && | ||
| 492 | test_bit(code, dev->key)) { | ||
| 493 | input_pass_event(dev, EV_KEY, code, 0); | ||
| 494 | } | ||
| 495 | } | ||
| 496 | input_pass_event(dev, EV_SYN, SYN_REPORT, 1); | ||
| 497 | } | ||
| 498 | |||
| 499 | list_for_each_entry(handle, &dev->h_list, d_node) | ||
| 500 | handle->open = 0; | ||
| 501 | |||
| 502 | spin_unlock_irq(&dev->event_lock); | ||
| 503 | } | ||
| 504 | |||
| 301 | static int input_fetch_keycode(struct input_dev *dev, int scancode) | 505 | static int input_fetch_keycode(struct input_dev *dev, int scancode) |
| 302 | { | 506 | { |
| 303 | switch (dev->keycodesize) { | 507 | switch (dev->keycodesize) { |
| @@ -473,7 +677,8 @@ static unsigned int input_proc_devices_poll(struct file *file, poll_table *wait) | |||
| 473 | 677 | ||
| 474 | static void *input_devices_seq_start(struct seq_file *seq, loff_t *pos) | 678 | static void *input_devices_seq_start(struct seq_file *seq, loff_t *pos) |
| 475 | { | 679 | { |
| 476 | /* acquire lock here ... Yes, we do need locking, I knowi, I know... */ | 680 | if (mutex_lock_interruptible(&input_mutex)) |
| 681 | return NULL; | ||
| 477 | 682 | ||
| 478 | return seq_list_start(&input_dev_list, *pos); | 683 | return seq_list_start(&input_dev_list, *pos); |
| 479 | } | 684 | } |
| @@ -485,7 +690,7 @@ static void *input_devices_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
| 485 | 690 | ||
| 486 | static void input_devices_seq_stop(struct seq_file *seq, void *v) | 691 | static void input_devices_seq_stop(struct seq_file *seq, void *v) |
| 487 | { | 692 | { |
| 488 | /* release lock here */ | 693 | mutex_unlock(&input_mutex); |
| 489 | } | 694 | } |
| 490 | 695 | ||
| 491 | static void input_seq_print_bitmap(struct seq_file *seq, const char *name, | 696 | static void input_seq_print_bitmap(struct seq_file *seq, const char *name, |
| @@ -569,7 +774,9 @@ static const struct file_operations input_devices_fileops = { | |||
| 569 | 774 | ||
| 570 | static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos) | 775 | static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos) |
| 571 | { | 776 | { |
| 572 | /* acquire lock here ... Yes, we do need locking, I knowi, I know... */ | 777 | if (mutex_lock_interruptible(&input_mutex)) |
| 778 | return NULL; | ||
| 779 | |||
| 573 | seq->private = (void *)(unsigned long)*pos; | 780 | seq->private = (void *)(unsigned long)*pos; |
| 574 | return seq_list_start(&input_handler_list, *pos); | 781 | return seq_list_start(&input_handler_list, *pos); |
| 575 | } | 782 | } |
| @@ -582,7 +789,7 @@ static void *input_handlers_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
| 582 | 789 | ||
| 583 | static void input_handlers_seq_stop(struct seq_file *seq, void *v) | 790 | static void input_handlers_seq_stop(struct seq_file *seq, void *v) |
| 584 | { | 791 | { |
| 585 | /* release lock here */ | 792 | mutex_unlock(&input_mutex); |
| 586 | } | 793 | } |
| 587 | 794 | ||
| 588 | static int input_handlers_seq_show(struct seq_file *seq, void *v) | 795 | static int input_handlers_seq_show(struct seq_file *seq, void *v) |
| @@ -983,6 +1190,7 @@ struct input_dev *input_allocate_device(void) | |||
| 983 | dev->dev.class = &input_class; | 1190 | dev->dev.class = &input_class; |
| 984 | device_initialize(&dev->dev); | 1191 | device_initialize(&dev->dev); |
| 985 | mutex_init(&dev->mutex); | 1192 | mutex_init(&dev->mutex); |
| 1193 | spin_lock_init(&dev->event_lock); | ||
| 986 | INIT_LIST_HEAD(&dev->h_list); | 1194 | INIT_LIST_HEAD(&dev->h_list); |
| 987 | INIT_LIST_HEAD(&dev->node); | 1195 | INIT_LIST_HEAD(&dev->node); |
| 988 | 1196 | ||
| @@ -1000,7 +1208,7 @@ EXPORT_SYMBOL(input_allocate_device); | |||
| 1000 | * This function should only be used if input_register_device() | 1208 | * This function should only be used if input_register_device() |
| 1001 | * was not called yet or if it failed. Once device was registered | 1209 | * was not called yet or if it failed. Once device was registered |
| 1002 | * use input_unregister_device() and memory will be freed once last | 1210 | * use input_unregister_device() and memory will be freed once last |
| 1003 | * refrence to the device is dropped. | 1211 | * reference to the device is dropped. |
| 1004 | * | 1212 | * |
| 1005 | * Device should be allocated by input_allocate_device(). | 1213 | * Device should be allocated by input_allocate_device(). |
| 1006 | * | 1214 | * |
| @@ -1070,6 +1278,18 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int | |||
| 1070 | } | 1278 | } |
| 1071 | EXPORT_SYMBOL(input_set_capability); | 1279 | EXPORT_SYMBOL(input_set_capability); |
| 1072 | 1280 | ||
| 1281 | /** | ||
| 1282 | * input_register_device - register device with input core | ||
| 1283 | * @dev: device to be registered | ||
| 1284 | * | ||
| 1285 | * This function registers device with input core. The device must be | ||
| 1286 | * allocated with input_allocate_device() and all it's capabilities | ||
| 1287 | * set up before registering. | ||
| 1288 | * If function fails the device must be freed with input_free_device(). | ||
| 1289 | * Once device has been successfully registered it can be unregistered | ||
| 1290 | * with input_unregister_device(); input_free_device() should not be | ||
| 1291 | * called in this case. | ||
| 1292 | */ | ||
| 1073 | int input_register_device(struct input_dev *dev) | 1293 | int input_register_device(struct input_dev *dev) |
| 1074 | { | 1294 | { |
| 1075 | static atomic_t input_no = ATOMIC_INIT(0); | 1295 | static atomic_t input_no = ATOMIC_INIT(0); |
| @@ -1077,7 +1297,7 @@ int input_register_device(struct input_dev *dev) | |||
| 1077 | const char *path; | 1297 | const char *path; |
| 1078 | int error; | 1298 | int error; |
| 1079 | 1299 | ||
| 1080 | set_bit(EV_SYN, dev->evbit); | 1300 | __set_bit(EV_SYN, dev->evbit); |
| 1081 | 1301 | ||
| 1082 | /* | 1302 | /* |
| 1083 | * If delay and period are pre-set by the driver, then autorepeating | 1303 | * If delay and period are pre-set by the driver, then autorepeating |
| @@ -1098,8 +1318,6 @@ int input_register_device(struct input_dev *dev) | |||
| 1098 | if (!dev->setkeycode) | 1318 | if (!dev->setkeycode) |
| 1099 | dev->setkeycode = input_default_setkeycode; | 1319 | dev->setkeycode = input_default_setkeycode; |
| 1100 | 1320 | ||
| 1101 | list_add_tail(&dev->node, &input_dev_list); | ||
| 1102 | |||
| 1103 | snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id), | 1321 | snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id), |
| 1104 | "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1); | 1322 | "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1); |
| 1105 | 1323 | ||
| @@ -1115,49 +1333,79 @@ int input_register_device(struct input_dev *dev) | |||
| 1115 | dev->name ? dev->name : "Unspecified device", path ? path : "N/A"); | 1333 | dev->name ? dev->name : "Unspecified device", path ? path : "N/A"); |
| 1116 | kfree(path); | 1334 | kfree(path); |
| 1117 | 1335 | ||
| 1336 | error = mutex_lock_interruptible(&input_mutex); | ||
| 1337 | if (error) { | ||
| 1338 | device_del(&dev->dev); | ||
| 1339 | return error; | ||
| 1340 | } | ||
| 1341 | |||
| 1342 | list_add_tail(&dev->node, &input_dev_list); | ||
| 1343 | |||
| 1118 | list_for_each_entry(handler, &input_handler_list, node) | 1344 | list_for_each_entry(handler, &input_handler_list, node) |
| 1119 | input_attach_handler(dev, handler); | 1345 | input_attach_handler(dev, handler); |
| 1120 | 1346 | ||
| 1121 | input_wakeup_procfs_readers(); | 1347 | input_wakeup_procfs_readers(); |
| 1122 | 1348 | ||
| 1349 | mutex_unlock(&input_mutex); | ||
| 1350 | |||
| 1123 | return 0; | 1351 | return 0; |
| 1124 | } | 1352 | } |
| 1125 | EXPORT_SYMBOL(input_register_device); | 1353 | EXPORT_SYMBOL(input_register_device); |
| 1126 | 1354 | ||
| 1355 | /** | ||
| 1356 | * input_unregister_device - unregister previously registered device | ||
| 1357 | * @dev: device to be unregistered | ||
| 1358 | * | ||
| 1359 | * This function unregisters an input device. Once device is unregistered | ||
| 1360 | * the caller should not try to access it as it may get freed at any moment. | ||
| 1361 | */ | ||
| 1127 | void input_unregister_device(struct input_dev *dev) | 1362 | void input_unregister_device(struct input_dev *dev) |
| 1128 | { | 1363 | { |
| 1129 | struct input_handle *handle, *next; | 1364 | struct input_handle *handle, *next; |
| 1130 | int code; | ||
| 1131 | 1365 | ||
| 1132 | for (code = 0; code <= KEY_MAX; code++) | 1366 | input_disconnect_device(dev); |
| 1133 | if (test_bit(code, dev->key)) | ||
| 1134 | input_report_key(dev, code, 0); | ||
| 1135 | input_sync(dev); | ||
| 1136 | 1367 | ||
| 1137 | del_timer_sync(&dev->timer); | 1368 | mutex_lock(&input_mutex); |
| 1138 | 1369 | ||
| 1139 | list_for_each_entry_safe(handle, next, &dev->h_list, d_node) | 1370 | list_for_each_entry_safe(handle, next, &dev->h_list, d_node) |
| 1140 | handle->handler->disconnect(handle); | 1371 | handle->handler->disconnect(handle); |
| 1141 | WARN_ON(!list_empty(&dev->h_list)); | 1372 | WARN_ON(!list_empty(&dev->h_list)); |
| 1142 | 1373 | ||
| 1374 | del_timer_sync(&dev->timer); | ||
| 1143 | list_del_init(&dev->node); | 1375 | list_del_init(&dev->node); |
| 1144 | 1376 | ||
| 1145 | device_unregister(&dev->dev); | ||
| 1146 | |||
| 1147 | input_wakeup_procfs_readers(); | 1377 | input_wakeup_procfs_readers(); |
| 1378 | |||
| 1379 | mutex_unlock(&input_mutex); | ||
| 1380 | |||
| 1381 | device_unregister(&dev->dev); | ||
| 1148 | } | 1382 | } |
| 1149 | EXPORT_SYMBOL(input_unregister_device); | 1383 | EXPORT_SYMBOL(input_unregister_device); |
| 1150 | 1384 | ||
| 1385 | /** | ||
| 1386 | * input_register_handler - register a new input handler | ||
| 1387 | * @handler: handler to be registered | ||
| 1388 | * | ||
| 1389 | * This function registers a new input handler (interface) for input | ||
| 1390 | * devices in the system and attaches it to all input devices that | ||
| 1391 | * are compatible with the handler. | ||
| 1392 | */ | ||
| 1151 | int input_register_handler(struct input_handler *handler) | 1393 | int input_register_handler(struct input_handler *handler) |
| 1152 | { | 1394 | { |
| 1153 | struct input_dev *dev; | 1395 | struct input_dev *dev; |
| 1396 | int retval; | ||
| 1397 | |||
| 1398 | retval = mutex_lock_interruptible(&input_mutex); | ||
| 1399 | if (retval) | ||
| 1400 | return retval; | ||
| 1154 | 1401 | ||
| 1155 | INIT_LIST_HEAD(&handler->h_list); | 1402 | INIT_LIST_HEAD(&handler->h_list); |
| 1156 | 1403 | ||
| 1157 | if (handler->fops != NULL) { | 1404 | if (handler->fops != NULL) { |
| 1158 | if (input_table[handler->minor >> 5]) | 1405 | if (input_table[handler->minor >> 5]) { |
| 1159 | return -EBUSY; | 1406 | retval = -EBUSY; |
| 1160 | 1407 | goto out; | |
| 1408 | } | ||
| 1161 | input_table[handler->minor >> 5] = handler; | 1409 | input_table[handler->minor >> 5] = handler; |
| 1162 | } | 1410 | } |
| 1163 | 1411 | ||
| @@ -1167,14 +1415,26 @@ int input_register_handler(struct input_handler *handler) | |||
| 1167 | input_attach_handler(dev, handler); | 1415 | input_attach_handler(dev, handler); |
| 1168 | 1416 | ||
| 1169 | input_wakeup_procfs_readers(); | 1417 | input_wakeup_procfs_readers(); |
| 1170 | return 0; | 1418 | |
| 1419 | out: | ||
| 1420 | mutex_unlock(&input_mutex); | ||
| 1421 | return retval; | ||
| 1171 | } | 1422 | } |
| 1172 | EXPORT_SYMBOL(input_register_handler); | 1423 | EXPORT_SYMBOL(input_register_handler); |
| 1173 | 1424 | ||
| 1425 | /** | ||
| 1426 | * input_unregister_handler - unregisters an input handler | ||
| 1427 | * @handler: handler to be unregistered | ||
| 1428 | * | ||
| 1429 | * This function disconnects a handler from its input devices and | ||
| 1430 | * removes it from lists of known handlers. | ||
| 1431 | */ | ||
| 1174 | void input_unregister_handler(struct input_handler *handler) | 1432 | void input_unregister_handler(struct input_handler *handler) |
| 1175 | { | 1433 | { |
| 1176 | struct input_handle *handle, *next; | 1434 | struct input_handle *handle, *next; |
| 1177 | 1435 | ||
| 1436 | mutex_lock(&input_mutex); | ||
| 1437 | |||
| 1178 | list_for_each_entry_safe(handle, next, &handler->h_list, h_node) | 1438 | list_for_each_entry_safe(handle, next, &handler->h_list, h_node) |
| 1179 | handler->disconnect(handle); | 1439 | handler->disconnect(handle); |
| 1180 | WARN_ON(!list_empty(&handler->h_list)); | 1440 | WARN_ON(!list_empty(&handler->h_list)); |
| @@ -1185,14 +1445,45 @@ void input_unregister_handler(struct input_handler *handler) | |||
| 1185 | input_table[handler->minor >> 5] = NULL; | 1445 | input_table[handler->minor >> 5] = NULL; |
| 1186 | 1446 | ||
| 1187 | input_wakeup_procfs_readers(); | 1447 | input_wakeup_procfs_readers(); |
| 1448 | |||
| 1449 | mutex_unlock(&input_mutex); | ||
| 1188 | } | 1450 | } |
| 1189 | EXPORT_SYMBOL(input_unregister_handler); | 1451 | EXPORT_SYMBOL(input_unregister_handler); |
| 1190 | 1452 | ||
| 1453 | /** | ||
| 1454 | * input_register_handle - register a new input handle | ||
| 1455 | * @handle: handle to register | ||
| 1456 | * | ||
| 1457 | * This function puts a new input handle onto device's | ||
| 1458 | * and handler's lists so that events can flow through | ||
| 1459 | * it once it is opened using input_open_device(). | ||
| 1460 | * | ||
| 1461 | * This function is supposed to be called from handler's | ||
| 1462 | * connect() method. | ||
| 1463 | */ | ||
| 1191 | int input_register_handle(struct input_handle *handle) | 1464 | int input_register_handle(struct input_handle *handle) |
| 1192 | { | 1465 | { |
| 1193 | struct input_handler *handler = handle->handler; | 1466 | struct input_handler *handler = handle->handler; |
| 1467 | struct input_dev *dev = handle->dev; | ||
| 1468 | int error; | ||
| 1469 | |||
| 1470 | /* | ||
| 1471 | * We take dev->mutex here to prevent race with | ||
| 1472 | * input_release_device(). | ||
| 1473 | */ | ||
| 1474 | error = mutex_lock_interruptible(&dev->mutex); | ||
| 1475 | if (error) | ||
| 1476 | return error; | ||
| 1477 | list_add_tail_rcu(&handle->d_node, &dev->h_list); | ||
| 1478 | mutex_unlock(&dev->mutex); | ||
| 1479 | synchronize_rcu(); | ||
| 1194 | 1480 | ||
| 1195 | list_add_tail(&handle->d_node, &handle->dev->h_list); | 1481 | /* |
| 1482 | * Since we are supposed to be called from ->connect() | ||
| 1483 | * which is mutually exclusive with ->disconnect() | ||
| 1484 | * we can't be racing with input_unregister_handle() | ||
| 1485 | * and so separate lock is not needed here. | ||
| 1486 | */ | ||
| 1196 | list_add_tail(&handle->h_node, &handler->h_list); | 1487 | list_add_tail(&handle->h_node, &handler->h_list); |
| 1197 | 1488 | ||
| 1198 | if (handler->start) | 1489 | if (handler->start) |
| @@ -1202,10 +1493,29 @@ int input_register_handle(struct input_handle *handle) | |||
| 1202 | } | 1493 | } |
| 1203 | EXPORT_SYMBOL(input_register_handle); | 1494 | EXPORT_SYMBOL(input_register_handle); |
| 1204 | 1495 | ||
| 1496 | /** | ||
| 1497 | * input_unregister_handle - unregister an input handle | ||
| 1498 | * @handle: handle to unregister | ||
| 1499 | * | ||
| 1500 | * This function removes input handle from device's | ||
| 1501 | * and handler's lists. | ||
| 1502 | * | ||
| 1503 | * This function is supposed to be called from handler's | ||
| 1504 | * disconnect() method. | ||
| 1505 | */ | ||
| 1205 | void input_unregister_handle(struct input_handle *handle) | 1506 | void input_unregister_handle(struct input_handle *handle) |
| 1206 | { | 1507 | { |
| 1508 | struct input_dev *dev = handle->dev; | ||
| 1509 | |||
| 1207 | list_del_init(&handle->h_node); | 1510 | list_del_init(&handle->h_node); |
| 1208 | list_del_init(&handle->d_node); | 1511 | |
| 1512 | /* | ||
| 1513 | * Take dev->mutex to prevent race with input_release_device(). | ||
| 1514 | */ | ||
| 1515 | mutex_lock(&dev->mutex); | ||
| 1516 | list_del_rcu(&handle->d_node); | ||
| 1517 | mutex_unlock(&dev->mutex); | ||
| 1518 | synchronize_rcu(); | ||
| 1209 | } | 1519 | } |
| 1210 | EXPORT_SYMBOL(input_unregister_handle); | 1520 | EXPORT_SYMBOL(input_unregister_handle); |
| 1211 | 1521 | ||
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index a9a0180bfd46..2b201f9aa024 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c | |||
| @@ -43,6 +43,8 @@ struct joydev { | |||
| 43 | struct input_handle handle; | 43 | struct input_handle handle; |
| 44 | wait_queue_head_t wait; | 44 | wait_queue_head_t wait; |
| 45 | struct list_head client_list; | 45 | struct list_head client_list; |
| 46 | spinlock_t client_lock; /* protects client_list */ | ||
| 47 | struct mutex mutex; | ||
| 46 | struct device dev; | 48 | struct device dev; |
| 47 | 49 | ||
| 48 | struct js_corr corr[ABS_MAX + 1]; | 50 | struct js_corr corr[ABS_MAX + 1]; |
| @@ -61,31 +63,61 @@ struct joydev_client { | |||
| 61 | int head; | 63 | int head; |
| 62 | int tail; | 64 | int tail; |
| 63 | int startup; | 65 | int startup; |
| 66 | spinlock_t buffer_lock; /* protects access to buffer, head and tail */ | ||
| 64 | struct fasync_struct *fasync; | 67 | struct fasync_struct *fasync; |
| 65 | struct joydev *joydev; | 68 | struct joydev *joydev; |
| 66 | struct list_head node; | 69 | struct list_head node; |
| 67 | }; | 70 | }; |
| 68 | 71 | ||
| 69 | static struct joydev *joydev_table[JOYDEV_MINORS]; | 72 | static struct joydev *joydev_table[JOYDEV_MINORS]; |
| 73 | static DEFINE_MUTEX(joydev_table_mutex); | ||
| 70 | 74 | ||
| 71 | static int joydev_correct(int value, struct js_corr *corr) | 75 | static int joydev_correct(int value, struct js_corr *corr) |
| 72 | { | 76 | { |
| 73 | switch (corr->type) { | 77 | switch (corr->type) { |
| 74 | case JS_CORR_NONE: | 78 | |
| 75 | break; | 79 | case JS_CORR_NONE: |
| 76 | case JS_CORR_BROKEN: | 80 | break; |
| 77 | value = value > corr->coef[0] ? (value < corr->coef[1] ? 0 : | 81 | |
| 78 | ((corr->coef[3] * (value - corr->coef[1])) >> 14)) : | 82 | case JS_CORR_BROKEN: |
| 79 | ((corr->coef[2] * (value - corr->coef[0])) >> 14); | 83 | value = value > corr->coef[0] ? (value < corr->coef[1] ? 0 : |
| 80 | break; | 84 | ((corr->coef[3] * (value - corr->coef[1])) >> 14)) : |
| 81 | default: | 85 | ((corr->coef[2] * (value - corr->coef[0])) >> 14); |
| 82 | return 0; | 86 | break; |
| 87 | |||
| 88 | default: | ||
| 89 | return 0; | ||
| 83 | } | 90 | } |
| 84 | 91 | ||
| 85 | return value < -32767 ? -32767 : (value > 32767 ? 32767 : value); | 92 | return value < -32767 ? -32767 : (value > 32767 ? 32767 : value); |
| 86 | } | 93 | } |
| 87 | 94 | ||
| 88 | static void joydev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) | 95 | static void joydev_pass_event(struct joydev_client *client, |
| 96 | struct js_event *event) | ||
| 97 | { | ||
| 98 | struct joydev *joydev = client->joydev; | ||
| 99 | |||
| 100 | /* | ||
| 101 | * IRQs already disabled, just acquire the lock | ||
| 102 | */ | ||
| 103 | spin_lock(&client->buffer_lock); | ||
| 104 | |||
| 105 | client->buffer[client->head] = *event; | ||
| 106 | |||
| 107 | if (client->startup == joydev->nabs + joydev->nkey) { | ||
| 108 | client->head++; | ||
| 109 | client->head &= JOYDEV_BUFFER_SIZE - 1; | ||
| 110 | if (client->tail == client->head) | ||
| 111 | client->startup = 0; | ||
| 112 | } | ||
| 113 | |||
| 114 | spin_unlock(&client->buffer_lock); | ||
| 115 | |||
| 116 | kill_fasync(&client->fasync, SIGIO, POLL_IN); | ||
| 117 | } | ||
| 118 | |||
| 119 | static void joydev_event(struct input_handle *handle, | ||
| 120 | unsigned int type, unsigned int code, int value) | ||
| 89 | { | 121 | { |
| 90 | struct joydev *joydev = handle->private; | 122 | struct joydev *joydev = handle->private; |
| 91 | struct joydev_client *client; | 123 | struct joydev_client *client; |
| @@ -93,39 +125,34 @@ static void joydev_event(struct input_handle *handle, unsigned int type, unsigne | |||
| 93 | 125 | ||
| 94 | switch (type) { | 126 | switch (type) { |
| 95 | 127 | ||
| 96 | case EV_KEY: | 128 | case EV_KEY: |
| 97 | if (code < BTN_MISC || value == 2) | 129 | if (code < BTN_MISC || value == 2) |
| 98 | return; | 130 | return; |
| 99 | event.type = JS_EVENT_BUTTON; | 131 | event.type = JS_EVENT_BUTTON; |
| 100 | event.number = joydev->keymap[code - BTN_MISC]; | 132 | event.number = joydev->keymap[code - BTN_MISC]; |
| 101 | event.value = value; | 133 | event.value = value; |
| 102 | break; | 134 | break; |
| 103 | |||
| 104 | case EV_ABS: | ||
| 105 | event.type = JS_EVENT_AXIS; | ||
| 106 | event.number = joydev->absmap[code]; | ||
| 107 | event.value = joydev_correct(value, joydev->corr + event.number); | ||
| 108 | if (event.value == joydev->abs[event.number]) | ||
| 109 | return; | ||
| 110 | joydev->abs[event.number] = event.value; | ||
| 111 | break; | ||
| 112 | 135 | ||
| 113 | default: | 136 | case EV_ABS: |
| 137 | event.type = JS_EVENT_AXIS; | ||
| 138 | event.number = joydev->absmap[code]; | ||
| 139 | event.value = joydev_correct(value, | ||
| 140 | &joydev->corr[event.number]); | ||
| 141 | if (event.value == joydev->abs[event.number]) | ||
| 114 | return; | 142 | return; |
| 143 | joydev->abs[event.number] = event.value; | ||
| 144 | break; | ||
| 145 | |||
| 146 | default: | ||
| 147 | return; | ||
| 115 | } | 148 | } |
| 116 | 149 | ||
| 117 | event.time = jiffies_to_msecs(jiffies); | 150 | event.time = jiffies_to_msecs(jiffies); |
| 118 | 151 | ||
| 119 | list_for_each_entry(client, &joydev->client_list, node) { | 152 | rcu_read_lock(); |
| 120 | 153 | list_for_each_entry_rcu(client, &joydev->client_list, node) | |
| 121 | memcpy(client->buffer + client->head, &event, sizeof(struct js_event)); | 154 | joydev_pass_event(client, &event); |
| 122 | 155 | rcu_read_unlock(); | |
| 123 | if (client->startup == joydev->nabs + joydev->nkey) | ||
| 124 | if (client->tail == (client->head = (client->head + 1) & (JOYDEV_BUFFER_SIZE - 1))) | ||
| 125 | client->startup = 0; | ||
| 126 | |||
| 127 | kill_fasync(&client->fasync, SIGIO, POLL_IN); | ||
| 128 | } | ||
| 129 | 156 | ||
| 130 | wake_up_interruptible(&joydev->wait); | 157 | wake_up_interruptible(&joydev->wait); |
| 131 | } | 158 | } |
| @@ -144,23 +171,83 @@ static void joydev_free(struct device *dev) | |||
| 144 | { | 171 | { |
| 145 | struct joydev *joydev = container_of(dev, struct joydev, dev); | 172 | struct joydev *joydev = container_of(dev, struct joydev, dev); |
| 146 | 173 | ||
| 147 | joydev_table[joydev->minor] = NULL; | ||
| 148 | kfree(joydev); | 174 | kfree(joydev); |
| 149 | } | 175 | } |
| 150 | 176 | ||
| 177 | static void joydev_attach_client(struct joydev *joydev, | ||
| 178 | struct joydev_client *client) | ||
| 179 | { | ||
| 180 | spin_lock(&joydev->client_lock); | ||
| 181 | list_add_tail_rcu(&client->node, &joydev->client_list); | ||
| 182 | spin_unlock(&joydev->client_lock); | ||
| 183 | synchronize_rcu(); | ||
| 184 | } | ||
| 185 | |||
| 186 | static void joydev_detach_client(struct joydev *joydev, | ||
| 187 | struct joydev_client *client) | ||
| 188 | { | ||
| 189 | spin_lock(&joydev->client_lock); | ||
| 190 | list_del_rcu(&client->node); | ||
| 191 | spin_unlock(&joydev->client_lock); | ||
| 192 | synchronize_rcu(); | ||
| 193 | } | ||
| 194 | |||
| 195 | static int joydev_open_device(struct joydev *joydev) | ||
| 196 | { | ||
| 197 | int retval; | ||
| 198 | |||
| 199 | retval = mutex_lock_interruptible(&joydev->mutex); | ||
| 200 | if (retval) | ||
| 201 | return retval; | ||
| 202 | |||
| 203 | if (!joydev->exist) | ||
| 204 | retval = -ENODEV; | ||
| 205 | else if (!joydev->open++) { | ||
| 206 | retval = input_open_device(&joydev->handle); | ||
| 207 | if (retval) | ||
| 208 | joydev->open--; | ||
| 209 | } | ||
| 210 | |||
| 211 | mutex_unlock(&joydev->mutex); | ||
| 212 | return retval; | ||
| 213 | } | ||
| 214 | |||
| 215 | static void joydev_close_device(struct joydev *joydev) | ||
| 216 | { | ||
| 217 | mutex_lock(&joydev->mutex); | ||
| 218 | |||
| 219 | if (joydev->exist && !--joydev->open) | ||
| 220 | input_close_device(&joydev->handle); | ||
| 221 | |||
| 222 | mutex_unlock(&joydev->mutex); | ||
| 223 | } | ||
| 224 | |||
| 225 | /* | ||
| 226 | * Wake up users waiting for IO so they can disconnect from | ||
| 227 | * dead device. | ||
| 228 | */ | ||
| 229 | static void joydev_hangup(struct joydev *joydev) | ||
| 230 | { | ||
| 231 | struct joydev_client *client; | ||
| 232 | |||
| 233 | spin_lock(&joydev->client_lock); | ||
| 234 | list_for_each_entry(client, &joydev->client_list, node) | ||
| 235 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); | ||
| 236 | spin_unlock(&joydev->client_lock); | ||
| 237 | |||
| 238 | wake_up_interruptible(&joydev->wait); | ||
| 239 | } | ||
| 240 | |||
| 151 | static int joydev_release(struct inode *inode, struct file *file) | 241 | static int joydev_release(struct inode *inode, struct file *file) |
| 152 | { | 242 | { |
| 153 | struct joydev_client *client = file->private_data; | 243 | struct joydev_client *client = file->private_data; |
| 154 | struct joydev *joydev = client->joydev; | 244 | struct joydev *joydev = client->joydev; |
| 155 | 245 | ||
| 156 | joydev_fasync(-1, file, 0); | 246 | joydev_fasync(-1, file, 0); |
| 157 | 247 | joydev_detach_client(joydev, client); | |
| 158 | list_del(&client->node); | ||
| 159 | kfree(client); | 248 | kfree(client); |
| 160 | 249 | ||
| 161 | if (!--joydev->open && joydev->exist) | 250 | joydev_close_device(joydev); |
| 162 | input_close_device(&joydev->handle); | ||
| 163 | |||
| 164 | put_device(&joydev->dev); | 251 | put_device(&joydev->dev); |
| 165 | 252 | ||
| 166 | return 0; | 253 | return 0; |
| @@ -176,11 +263,16 @@ static int joydev_open(struct inode *inode, struct file *file) | |||
| 176 | if (i >= JOYDEV_MINORS) | 263 | if (i >= JOYDEV_MINORS) |
| 177 | return -ENODEV; | 264 | return -ENODEV; |
| 178 | 265 | ||
| 266 | error = mutex_lock_interruptible(&joydev_table_mutex); | ||
| 267 | if (error) | ||
| 268 | return error; | ||
| 179 | joydev = joydev_table[i]; | 269 | joydev = joydev_table[i]; |
| 180 | if (!joydev || !joydev->exist) | 270 | if (joydev) |
| 181 | return -ENODEV; | 271 | get_device(&joydev->dev); |
| 272 | mutex_unlock(&joydev_table_mutex); | ||
| 182 | 273 | ||
| 183 | get_device(&joydev->dev); | 274 | if (!joydev) |
| 275 | return -ENODEV; | ||
| 184 | 276 | ||
| 185 | client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL); | 277 | client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL); |
| 186 | if (!client) { | 278 | if (!client) { |
| @@ -188,37 +280,129 @@ static int joydev_open(struct inode *inode, struct file *file) | |||
| 188 | goto err_put_joydev; | 280 | goto err_put_joydev; |
| 189 | } | 281 | } |
| 190 | 282 | ||
| 283 | spin_lock_init(&client->buffer_lock); | ||
| 191 | client->joydev = joydev; | 284 | client->joydev = joydev; |
| 192 | list_add_tail(&client->node, &joydev->client_list); | 285 | joydev_attach_client(joydev, client); |
| 193 | 286 | ||
| 194 | if (!joydev->open++ && joydev->exist) { | 287 | error = joydev_open_device(joydev); |
| 195 | error = input_open_device(&joydev->handle); | 288 | if (error) |
| 196 | if (error) | 289 | goto err_free_client; |
| 197 | goto err_free_client; | ||
| 198 | } | ||
| 199 | 290 | ||
| 200 | file->private_data = client; | 291 | file->private_data = client; |
| 201 | return 0; | 292 | return 0; |
| 202 | 293 | ||
| 203 | err_free_client: | 294 | err_free_client: |
| 204 | list_del(&client->node); | 295 | joydev_detach_client(joydev, client); |
| 205 | kfree(client); | 296 | kfree(client); |
| 206 | err_put_joydev: | 297 | err_put_joydev: |
| 207 | put_device(&joydev->dev); | 298 | put_device(&joydev->dev); |
| 208 | return error; | 299 | return error; |
| 209 | } | 300 | } |
| 210 | 301 | ||
| 211 | static ssize_t joydev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | 302 | static int joydev_generate_startup_event(struct joydev_client *client, |
| 303 | struct input_dev *input, | ||
| 304 | struct js_event *event) | ||
| 212 | { | 305 | { |
| 213 | return -EINVAL; | 306 | struct joydev *joydev = client->joydev; |
| 307 | int have_event; | ||
| 308 | |||
| 309 | spin_lock_irq(&client->buffer_lock); | ||
| 310 | |||
| 311 | have_event = client->startup < joydev->nabs + joydev->nkey; | ||
| 312 | |||
| 313 | if (have_event) { | ||
| 314 | |||
| 315 | event->time = jiffies_to_msecs(jiffies); | ||
| 316 | if (client->startup < joydev->nkey) { | ||
| 317 | event->type = JS_EVENT_BUTTON | JS_EVENT_INIT; | ||
| 318 | event->number = client->startup; | ||
| 319 | event->value = !!test_bit(joydev->keypam[event->number], | ||
| 320 | input->key); | ||
| 321 | } else { | ||
| 322 | event->type = JS_EVENT_AXIS | JS_EVENT_INIT; | ||
| 323 | event->number = client->startup - joydev->nkey; | ||
| 324 | event->value = joydev->abs[event->number]; | ||
| 325 | } | ||
| 326 | client->startup++; | ||
| 327 | } | ||
| 328 | |||
| 329 | spin_unlock_irq(&client->buffer_lock); | ||
| 330 | |||
| 331 | return have_event; | ||
| 332 | } | ||
| 333 | |||
| 334 | static int joydev_fetch_next_event(struct joydev_client *client, | ||
| 335 | struct js_event *event) | ||
| 336 | { | ||
| 337 | int have_event; | ||
| 338 | |||
| 339 | spin_lock_irq(&client->buffer_lock); | ||
| 340 | |||
| 341 | have_event = client->head != client->tail; | ||
| 342 | if (have_event) { | ||
| 343 | *event = client->buffer[client->tail++]; | ||
| 344 | client->tail &= JOYDEV_BUFFER_SIZE - 1; | ||
| 345 | } | ||
| 346 | |||
| 347 | spin_unlock_irq(&client->buffer_lock); | ||
| 348 | |||
| 349 | return have_event; | ||
| 350 | } | ||
| 351 | |||
| 352 | /* | ||
| 353 | * Old joystick interface | ||
| 354 | */ | ||
| 355 | static ssize_t joydev_0x_read(struct joydev_client *client, | ||
| 356 | struct input_dev *input, | ||
| 357 | char __user *buf) | ||
| 358 | { | ||
| 359 | struct joydev *joydev = client->joydev; | ||
| 360 | struct JS_DATA_TYPE data; | ||
| 361 | int i; | ||
| 362 | |||
| 363 | spin_lock_irq(&input->event_lock); | ||
| 364 | |||
| 365 | /* | ||
| 366 | * Get device state | ||
| 367 | */ | ||
| 368 | for (data.buttons = i = 0; i < 32 && i < joydev->nkey; i++) | ||
| 369 | data.buttons |= | ||
| 370 | test_bit(joydev->keypam[i], input->key) ? (1 << i) : 0; | ||
| 371 | data.x = (joydev->abs[0] / 256 + 128) >> joydev->glue.JS_CORR.x; | ||
| 372 | data.y = (joydev->abs[1] / 256 + 128) >> joydev->glue.JS_CORR.y; | ||
| 373 | |||
| 374 | /* | ||
| 375 | * Reset reader's event queue | ||
| 376 | */ | ||
| 377 | spin_lock(&client->buffer_lock); | ||
| 378 | client->startup = 0; | ||
| 379 | client->tail = client->head; | ||
| 380 | spin_unlock(&client->buffer_lock); | ||
| 381 | |||
| 382 | spin_unlock_irq(&input->event_lock); | ||
| 383 | |||
| 384 | if (copy_to_user(buf, &data, sizeof(struct JS_DATA_TYPE))) | ||
| 385 | return -EFAULT; | ||
| 386 | |||
| 387 | return sizeof(struct JS_DATA_TYPE); | ||
| 388 | } | ||
| 389 | |||
| 390 | static inline int joydev_data_pending(struct joydev_client *client) | ||
| 391 | { | ||
| 392 | struct joydev *joydev = client->joydev; | ||
| 393 | |||
| 394 | return client->startup < joydev->nabs + joydev->nkey || | ||
| 395 | client->head != client->tail; | ||
| 214 | } | 396 | } |
| 215 | 397 | ||
| 216 | static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | 398 | static ssize_t joydev_read(struct file *file, char __user *buf, |
| 399 | size_t count, loff_t *ppos) | ||
| 217 | { | 400 | { |
| 218 | struct joydev_client *client = file->private_data; | 401 | struct joydev_client *client = file->private_data; |
| 219 | struct joydev *joydev = client->joydev; | 402 | struct joydev *joydev = client->joydev; |
| 220 | struct input_dev *input = joydev->handle.dev; | 403 | struct input_dev *input = joydev->handle.dev; |
| 221 | int retval = 0; | 404 | struct js_event event; |
| 405 | int retval; | ||
| 222 | 406 | ||
| 223 | if (!joydev->exist) | 407 | if (!joydev->exist) |
| 224 | return -ENODEV; | 408 | return -ENODEV; |
| @@ -226,68 +410,35 @@ static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, lo | |||
| 226 | if (count < sizeof(struct js_event)) | 410 | if (count < sizeof(struct js_event)) |
| 227 | return -EINVAL; | 411 | return -EINVAL; |
| 228 | 412 | ||
| 229 | if (count == sizeof(struct JS_DATA_TYPE)) { | 413 | if (count == sizeof(struct JS_DATA_TYPE)) |
| 230 | 414 | return joydev_0x_read(client, input, buf); | |
| 231 | struct JS_DATA_TYPE data; | ||
| 232 | int i; | ||
| 233 | |||
| 234 | for (data.buttons = i = 0; i < 32 && i < joydev->nkey; i++) | ||
| 235 | data.buttons |= test_bit(joydev->keypam[i], input->key) ? (1 << i) : 0; | ||
| 236 | data.x = (joydev->abs[0] / 256 + 128) >> joydev->glue.JS_CORR.x; | ||
| 237 | data.y = (joydev->abs[1] / 256 + 128) >> joydev->glue.JS_CORR.y; | ||
| 238 | |||
| 239 | if (copy_to_user(buf, &data, sizeof(struct JS_DATA_TYPE))) | ||
| 240 | return -EFAULT; | ||
| 241 | |||
| 242 | client->startup = 0; | ||
| 243 | client->tail = client->head; | ||
| 244 | 415 | ||
| 245 | return sizeof(struct JS_DATA_TYPE); | 416 | if (!joydev_data_pending(client) && (file->f_flags & O_NONBLOCK)) |
| 246 | } | ||
| 247 | |||
| 248 | if (client->startup == joydev->nabs + joydev->nkey && | ||
| 249 | client->head == client->tail && (file->f_flags & O_NONBLOCK)) | ||
| 250 | return -EAGAIN; | 417 | return -EAGAIN; |
| 251 | 418 | ||
| 252 | retval = wait_event_interruptible(joydev->wait, | 419 | retval = wait_event_interruptible(joydev->wait, |
| 253 | !joydev->exist || | 420 | !joydev->exist || joydev_data_pending(client)); |
| 254 | client->startup < joydev->nabs + joydev->nkey || | ||
| 255 | client->head != client->tail); | ||
| 256 | if (retval) | 421 | if (retval) |
| 257 | return retval; | 422 | return retval; |
| 258 | 423 | ||
| 259 | if (!joydev->exist) | 424 | if (!joydev->exist) |
| 260 | return -ENODEV; | 425 | return -ENODEV; |
| 261 | 426 | ||
| 262 | while (client->startup < joydev->nabs + joydev->nkey && retval + sizeof(struct js_event) <= count) { | 427 | while (retval + sizeof(struct js_event) <= count && |
| 263 | 428 | joydev_generate_startup_event(client, input, &event)) { | |
| 264 | struct js_event event; | ||
| 265 | |||
| 266 | event.time = jiffies_to_msecs(jiffies); | ||
| 267 | |||
| 268 | if (client->startup < joydev->nkey) { | ||
| 269 | event.type = JS_EVENT_BUTTON | JS_EVENT_INIT; | ||
| 270 | event.number = client->startup; | ||
| 271 | event.value = !!test_bit(joydev->keypam[event.number], input->key); | ||
| 272 | } else { | ||
| 273 | event.type = JS_EVENT_AXIS | JS_EVENT_INIT; | ||
| 274 | event.number = client->startup - joydev->nkey; | ||
| 275 | event.value = joydev->abs[event.number]; | ||
| 276 | } | ||
| 277 | 429 | ||
| 278 | if (copy_to_user(buf + retval, &event, sizeof(struct js_event))) | 430 | if (copy_to_user(buf + retval, &event, sizeof(struct js_event))) |
| 279 | return -EFAULT; | 431 | return -EFAULT; |
| 280 | 432 | ||
| 281 | client->startup++; | ||
| 282 | retval += sizeof(struct js_event); | 433 | retval += sizeof(struct js_event); |
| 283 | } | 434 | } |
| 284 | 435 | ||
| 285 | while (client->head != client->tail && retval + sizeof(struct js_event) <= count) { | 436 | while (retval + sizeof(struct js_event) <= count && |
| 437 | joydev_fetch_next_event(client, &event)) { | ||
| 286 | 438 | ||
| 287 | if (copy_to_user(buf + retval, client->buffer + client->tail, sizeof(struct js_event))) | 439 | if (copy_to_user(buf + retval, &event, sizeof(struct js_event))) |
| 288 | return -EFAULT; | 440 | return -EFAULT; |
| 289 | 441 | ||
| 290 | client->tail = (client->tail + 1) & (JOYDEV_BUFFER_SIZE - 1); | ||
| 291 | retval += sizeof(struct js_event); | 442 | retval += sizeof(struct js_event); |
| 292 | } | 443 | } |
| 293 | 444 | ||
| @@ -301,126 +452,144 @@ static unsigned int joydev_poll(struct file *file, poll_table *wait) | |||
| 301 | struct joydev *joydev = client->joydev; | 452 | struct joydev *joydev = client->joydev; |
| 302 | 453 | ||
| 303 | poll_wait(file, &joydev->wait, wait); | 454 | poll_wait(file, &joydev->wait, wait); |
| 304 | return ((client->head != client->tail || client->startup < joydev->nabs + joydev->nkey) ? | 455 | return (joydev_data_pending(client) ? (POLLIN | POLLRDNORM) : 0) | |
| 305 | (POLLIN | POLLRDNORM) : 0) | (joydev->exist ? 0 : (POLLHUP | POLLERR)); | 456 | (joydev->exist ? 0 : (POLLHUP | POLLERR)); |
| 306 | } | 457 | } |
| 307 | 458 | ||
| 308 | static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __user *argp) | 459 | static int joydev_ioctl_common(struct joydev *joydev, |
| 460 | unsigned int cmd, void __user *argp) | ||
| 309 | { | 461 | { |
| 310 | struct input_dev *dev = joydev->handle.dev; | 462 | struct input_dev *dev = joydev->handle.dev; |
| 311 | int i, j; | 463 | int i, j; |
| 312 | 464 | ||
| 313 | switch (cmd) { | 465 | switch (cmd) { |
| 314 | 466 | ||
| 315 | case JS_SET_CAL: | 467 | case JS_SET_CAL: |
| 316 | return copy_from_user(&joydev->glue.JS_CORR, argp, | 468 | return copy_from_user(&joydev->glue.JS_CORR, argp, |
| 317 | sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0; | 469 | sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0; |
| 318 | 470 | ||
| 319 | case JS_GET_CAL: | 471 | case JS_GET_CAL: |
| 320 | return copy_to_user(argp, &joydev->glue.JS_CORR, | 472 | return copy_to_user(argp, &joydev->glue.JS_CORR, |
| 321 | sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0; | 473 | sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0; |
| 322 | 474 | ||
| 323 | case JS_SET_TIMEOUT: | 475 | case JS_SET_TIMEOUT: |
| 324 | return get_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); | 476 | return get_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); |
| 325 | 477 | ||
| 326 | case JS_GET_TIMEOUT: | 478 | case JS_GET_TIMEOUT: |
| 327 | return put_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); | 479 | return put_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); |
| 328 | 480 | ||
| 329 | case JSIOCGVERSION: | 481 | case JSIOCGVERSION: |
| 330 | return put_user(JS_VERSION, (__u32 __user *) argp); | 482 | return put_user(JS_VERSION, (__u32 __user *) argp); |
| 331 | 483 | ||
| 332 | case JSIOCGAXES: | 484 | case JSIOCGAXES: |
| 333 | return put_user(joydev->nabs, (__u8 __user *) argp); | 485 | return put_user(joydev->nabs, (__u8 __user *) argp); |
| 334 | 486 | ||
| 335 | case JSIOCGBUTTONS: | 487 | case JSIOCGBUTTONS: |
| 336 | return put_user(joydev->nkey, (__u8 __user *) argp); | 488 | return put_user(joydev->nkey, (__u8 __user *) argp); |
| 337 | 489 | ||
| 338 | case JSIOCSCORR: | 490 | case JSIOCSCORR: |
| 339 | if (copy_from_user(joydev->corr, argp, | 491 | if (copy_from_user(joydev->corr, argp, |
| 340 | sizeof(joydev->corr[0]) * joydev->nabs)) | 492 | sizeof(joydev->corr[0]) * joydev->nabs)) |
| 341 | return -EFAULT; | 493 | return -EFAULT; |
| 342 | for (i = 0; i < joydev->nabs; i++) { | ||
| 343 | j = joydev->abspam[i]; | ||
| 344 | joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i); | ||
| 345 | } | ||
| 346 | return 0; | ||
| 347 | 494 | ||
| 348 | case JSIOCGCORR: | 495 | for (i = 0; i < joydev->nabs; i++) { |
| 349 | return copy_to_user(argp, joydev->corr, | 496 | j = joydev->abspam[i]; |
| 350 | sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0; | 497 | joydev->abs[i] = joydev_correct(dev->abs[j], |
| 498 | &joydev->corr[i]); | ||
| 499 | } | ||
| 500 | return 0; | ||
| 351 | 501 | ||
| 352 | case JSIOCSAXMAP: | 502 | case JSIOCGCORR: |
| 353 | if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1))) | 503 | return copy_to_user(argp, joydev->corr, |
| 354 | return -EFAULT; | 504 | sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0; |
| 355 | for (i = 0; i < joydev->nabs; i++) { | 505 | |
| 356 | if (joydev->abspam[i] > ABS_MAX) | 506 | case JSIOCSAXMAP: |
| 357 | return -EINVAL; | 507 | if (copy_from_user(joydev->abspam, argp, |
| 358 | joydev->absmap[joydev->abspam[i]] = i; | 508 | sizeof(__u8) * (ABS_MAX + 1))) |
| 359 | } | 509 | return -EFAULT; |
| 360 | return 0; | 510 | |
| 361 | 511 | for (i = 0; i < joydev->nabs; i++) { | |
| 362 | case JSIOCGAXMAP: | 512 | if (joydev->abspam[i] > ABS_MAX) |
| 363 | return copy_to_user(argp, joydev->abspam, | 513 | return -EINVAL; |
| 364 | sizeof(__u8) * (ABS_MAX + 1)) ? -EFAULT : 0; | 514 | joydev->absmap[joydev->abspam[i]] = i; |
| 365 | 515 | } | |
| 366 | case JSIOCSBTNMAP: | 516 | return 0; |
| 367 | if (copy_from_user(joydev->keypam, argp, sizeof(__u16) * (KEY_MAX - BTN_MISC + 1))) | 517 | |
| 518 | case JSIOCGAXMAP: | ||
| 519 | return copy_to_user(argp, joydev->abspam, | ||
| 520 | sizeof(__u8) * (ABS_MAX + 1)) ? -EFAULT : 0; | ||
| 521 | |||
| 522 | case JSIOCSBTNMAP: | ||
| 523 | if (copy_from_user(joydev->keypam, argp, | ||
| 524 | sizeof(__u16) * (KEY_MAX - BTN_MISC + 1))) | ||
| 525 | return -EFAULT; | ||
| 526 | |||
| 527 | for (i = 0; i < joydev->nkey; i++) { | ||
| 528 | if (joydev->keypam[i] > KEY_MAX || | ||
| 529 | joydev->keypam[i] < BTN_MISC) | ||
| 530 | return -EINVAL; | ||
| 531 | joydev->keymap[joydev->keypam[i] - BTN_MISC] = i; | ||
| 532 | } | ||
| 533 | |||
| 534 | return 0; | ||
| 535 | |||
| 536 | case JSIOCGBTNMAP: | ||
| 537 | return copy_to_user(argp, joydev->keypam, | ||
| 538 | sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)) ? -EFAULT : 0; | ||
| 539 | |||
| 540 | default: | ||
| 541 | if ((cmd & ~IOCSIZE_MASK) == JSIOCGNAME(0)) { | ||
| 542 | int len; | ||
| 543 | if (!dev->name) | ||
| 544 | return 0; | ||
| 545 | len = strlen(dev->name) + 1; | ||
| 546 | if (len > _IOC_SIZE(cmd)) | ||
| 547 | len = _IOC_SIZE(cmd); | ||
| 548 | if (copy_to_user(argp, dev->name, len)) | ||
| 368 | return -EFAULT; | 549 | return -EFAULT; |
| 369 | for (i = 0; i < joydev->nkey; i++) { | 550 | return len; |
| 370 | if (joydev->keypam[i] > KEY_MAX || joydev->keypam[i] < BTN_MISC) | 551 | } |
| 371 | return -EINVAL; | ||
| 372 | joydev->keymap[joydev->keypam[i] - BTN_MISC] = i; | ||
| 373 | } | ||
| 374 | return 0; | ||
| 375 | |||
| 376 | case JSIOCGBTNMAP: | ||
| 377 | return copy_to_user(argp, joydev->keypam, | ||
| 378 | sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)) ? -EFAULT : 0; | ||
| 379 | |||
| 380 | default: | ||
| 381 | if ((cmd & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) == JSIOCGNAME(0)) { | ||
| 382 | int len; | ||
| 383 | if (!dev->name) | ||
| 384 | return 0; | ||
| 385 | len = strlen(dev->name) + 1; | ||
| 386 | if (len > _IOC_SIZE(cmd)) | ||
| 387 | len = _IOC_SIZE(cmd); | ||
| 388 | if (copy_to_user(argp, dev->name, len)) | ||
| 389 | return -EFAULT; | ||
| 390 | return len; | ||
| 391 | } | ||
| 392 | } | 552 | } |
| 393 | return -EINVAL; | 553 | return -EINVAL; |
| 394 | } | 554 | } |
| 395 | 555 | ||
| 396 | #ifdef CONFIG_COMPAT | 556 | #ifdef CONFIG_COMPAT |
| 397 | static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 557 | static long joydev_compat_ioctl(struct file *file, |
| 558 | unsigned int cmd, unsigned long arg) | ||
| 398 | { | 559 | { |
| 399 | struct joydev_client *client = file->private_data; | 560 | struct joydev_client *client = file->private_data; |
| 400 | struct joydev *joydev = client->joydev; | 561 | struct joydev *joydev = client->joydev; |
| 401 | void __user *argp = (void __user *)arg; | 562 | void __user *argp = (void __user *)arg; |
| 402 | s32 tmp32; | 563 | s32 tmp32; |
| 403 | struct JS_DATA_SAVE_TYPE_32 ds32; | 564 | struct JS_DATA_SAVE_TYPE_32 ds32; |
| 404 | int err; | 565 | int retval; |
| 405 | 566 | ||
| 406 | if (!joydev->exist) | 567 | retval = mutex_lock_interruptible(&joydev->mutex); |
| 407 | return -ENODEV; | 568 | if (retval) |
| 569 | return retval; | ||
| 570 | |||
| 571 | if (!joydev->exist) { | ||
| 572 | retval = -ENODEV; | ||
| 573 | goto out; | ||
| 574 | } | ||
| 575 | |||
| 576 | switch (cmd) { | ||
| 408 | 577 | ||
| 409 | switch(cmd) { | ||
| 410 | case JS_SET_TIMELIMIT: | 578 | case JS_SET_TIMELIMIT: |
| 411 | err = get_user(tmp32, (s32 __user *) arg); | 579 | retval = get_user(tmp32, (s32 __user *) arg); |
| 412 | if (err == 0) | 580 | if (retval == 0) |
| 413 | joydev->glue.JS_TIMELIMIT = tmp32; | 581 | joydev->glue.JS_TIMELIMIT = tmp32; |
| 414 | break; | 582 | break; |
| 583 | |||
| 415 | case JS_GET_TIMELIMIT: | 584 | case JS_GET_TIMELIMIT: |
| 416 | tmp32 = joydev->glue.JS_TIMELIMIT; | 585 | tmp32 = joydev->glue.JS_TIMELIMIT; |
| 417 | err = put_user(tmp32, (s32 __user *) arg); | 586 | retval = put_user(tmp32, (s32 __user *) arg); |
| 418 | break; | 587 | break; |
| 419 | 588 | ||
| 420 | case JS_SET_ALL: | 589 | case JS_SET_ALL: |
| 421 | err = copy_from_user(&ds32, argp, | 590 | retval = copy_from_user(&ds32, argp, |
| 422 | sizeof(ds32)) ? -EFAULT : 0; | 591 | sizeof(ds32)) ? -EFAULT : 0; |
| 423 | if (err == 0) { | 592 | if (retval == 0) { |
| 424 | joydev->glue.JS_TIMEOUT = ds32.JS_TIMEOUT; | 593 | joydev->glue.JS_TIMEOUT = ds32.JS_TIMEOUT; |
| 425 | joydev->glue.BUSY = ds32.BUSY; | 594 | joydev->glue.BUSY = ds32.BUSY; |
| 426 | joydev->glue.JS_EXPIRETIME = ds32.JS_EXPIRETIME; | 595 | joydev->glue.JS_EXPIRETIME = ds32.JS_EXPIRETIME; |
| @@ -438,55 +607,119 @@ static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned lo | |||
| 438 | ds32.JS_SAVE = joydev->glue.JS_SAVE; | 607 | ds32.JS_SAVE = joydev->glue.JS_SAVE; |
| 439 | ds32.JS_CORR = joydev->glue.JS_CORR; | 608 | ds32.JS_CORR = joydev->glue.JS_CORR; |
| 440 | 609 | ||
| 441 | err = copy_to_user(argp, &ds32, sizeof(ds32)) ? -EFAULT : 0; | 610 | retval = copy_to_user(argp, &ds32, sizeof(ds32)) ? -EFAULT : 0; |
| 442 | break; | 611 | break; |
| 443 | 612 | ||
| 444 | default: | 613 | default: |
| 445 | err = joydev_ioctl_common(joydev, cmd, argp); | 614 | retval = joydev_ioctl_common(joydev, cmd, argp); |
| 615 | break; | ||
| 446 | } | 616 | } |
| 447 | return err; | 617 | |
| 618 | out: | ||
| 619 | mutex_unlock(&joydev->mutex); | ||
| 620 | return retval; | ||
| 448 | } | 621 | } |
| 449 | #endif /* CONFIG_COMPAT */ | 622 | #endif /* CONFIG_COMPAT */ |
| 450 | 623 | ||
| 451 | static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 624 | static long joydev_ioctl(struct file *file, |
| 625 | unsigned int cmd, unsigned long arg) | ||
| 452 | { | 626 | { |
| 453 | struct joydev_client *client = file->private_data; | 627 | struct joydev_client *client = file->private_data; |
| 454 | struct joydev *joydev = client->joydev; | 628 | struct joydev *joydev = client->joydev; |
| 455 | void __user *argp = (void __user *)arg; | 629 | void __user *argp = (void __user *)arg; |
| 630 | int retval; | ||
| 456 | 631 | ||
| 457 | if (!joydev->exist) | 632 | retval = mutex_lock_interruptible(&joydev->mutex); |
| 458 | return -ENODEV; | 633 | if (retval) |
| 634 | return retval; | ||
| 635 | |||
| 636 | if (!joydev->exist) { | ||
| 637 | retval = -ENODEV; | ||
| 638 | goto out; | ||
| 639 | } | ||
| 640 | |||
| 641 | switch (cmd) { | ||
| 642 | |||
| 643 | case JS_SET_TIMELIMIT: | ||
| 644 | retval = get_user(joydev->glue.JS_TIMELIMIT, | ||
| 645 | (long __user *) arg); | ||
| 646 | break; | ||
| 647 | |||
| 648 | case JS_GET_TIMELIMIT: | ||
| 649 | retval = put_user(joydev->glue.JS_TIMELIMIT, | ||
| 650 | (long __user *) arg); | ||
| 651 | break; | ||
| 652 | |||
| 653 | case JS_SET_ALL: | ||
| 654 | retval = copy_from_user(&joydev->glue, argp, | ||
| 655 | sizeof(joydev->glue)) ? -EFAULT: 0; | ||
| 656 | break; | ||
| 657 | |||
| 658 | case JS_GET_ALL: | ||
| 659 | retval = copy_to_user(argp, &joydev->glue, | ||
| 660 | sizeof(joydev->glue)) ? -EFAULT : 0; | ||
| 661 | break; | ||
| 459 | 662 | ||
| 460 | switch(cmd) { | 663 | default: |
| 461 | case JS_SET_TIMELIMIT: | 664 | retval = joydev_ioctl_common(joydev, cmd, argp); |
| 462 | return get_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); | 665 | break; |
| 463 | case JS_GET_TIMELIMIT: | ||
| 464 | return put_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); | ||
| 465 | case JS_SET_ALL: | ||
| 466 | return copy_from_user(&joydev->glue, argp, | ||
| 467 | sizeof(joydev->glue)) ? -EFAULT : 0; | ||
| 468 | case JS_GET_ALL: | ||
| 469 | return copy_to_user(argp, &joydev->glue, | ||
| 470 | sizeof(joydev->glue)) ? -EFAULT : 0; | ||
| 471 | default: | ||
| 472 | return joydev_ioctl_common(joydev, cmd, argp); | ||
| 473 | } | 666 | } |
| 667 | out: | ||
| 668 | mutex_unlock(&joydev->mutex); | ||
| 669 | return retval; | ||
| 474 | } | 670 | } |
| 475 | 671 | ||
| 476 | static const struct file_operations joydev_fops = { | 672 | static const struct file_operations joydev_fops = { |
| 477 | .owner = THIS_MODULE, | 673 | .owner = THIS_MODULE, |
| 478 | .read = joydev_read, | 674 | .read = joydev_read, |
| 479 | .write = joydev_write, | 675 | .poll = joydev_poll, |
| 480 | .poll = joydev_poll, | 676 | .open = joydev_open, |
| 481 | .open = joydev_open, | 677 | .release = joydev_release, |
| 482 | .release = joydev_release, | 678 | .unlocked_ioctl = joydev_ioctl, |
| 483 | .ioctl = joydev_ioctl, | ||
| 484 | #ifdef CONFIG_COMPAT | 679 | #ifdef CONFIG_COMPAT |
| 485 | .compat_ioctl = joydev_compat_ioctl, | 680 | .compat_ioctl = joydev_compat_ioctl, |
| 486 | #endif | 681 | #endif |
| 487 | .fasync = joydev_fasync, | 682 | .fasync = joydev_fasync, |
| 488 | }; | 683 | }; |
| 489 | 684 | ||
| 685 | static int joydev_install_chrdev(struct joydev *joydev) | ||
| 686 | { | ||
| 687 | joydev_table[joydev->minor] = joydev; | ||
| 688 | return 0; | ||
| 689 | } | ||
| 690 | |||
| 691 | static void joydev_remove_chrdev(struct joydev *joydev) | ||
| 692 | { | ||
| 693 | mutex_lock(&joydev_table_mutex); | ||
| 694 | joydev_table[joydev->minor] = NULL; | ||
| 695 | mutex_unlock(&joydev_table_mutex); | ||
| 696 | } | ||
| 697 | |||
| 698 | /* | ||
| 699 | * Mark device non-existant. This disables writes, ioctls and | ||
| 700 | * prevents new users from opening the device. Already posted | ||
| 701 | * blocking reads will stay, however new ones will fail. | ||
| 702 | */ | ||
| 703 | static void joydev_mark_dead(struct joydev *joydev) | ||
| 704 | { | ||
| 705 | mutex_lock(&joydev->mutex); | ||
| 706 | joydev->exist = 0; | ||
| 707 | mutex_unlock(&joydev->mutex); | ||
| 708 | } | ||
| 709 | |||
| 710 | static void joydev_cleanup(struct joydev *joydev) | ||
| 711 | { | ||
| 712 | struct input_handle *handle = &joydev->handle; | ||
| 713 | |||
| 714 | joydev_mark_dead(joydev); | ||
| 715 | joydev_hangup(joydev); | ||
| 716 | joydev_remove_chrdev(joydev); | ||
| 717 | |||
| 718 | /* joydev is marked dead so noone else accesses joydev->open */ | ||
| 719 | if (joydev->open) | ||
| 720 | input_close_device(handle); | ||
| 721 | } | ||
| 722 | |||
| 490 | static int joydev_connect(struct input_handler *handler, struct input_dev *dev, | 723 | static int joydev_connect(struct input_handler *handler, struct input_dev *dev, |
| 491 | const struct input_device_id *id) | 724 | const struct input_device_id *id) |
| 492 | { | 725 | { |
| @@ -494,7 +727,10 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, | |||
| 494 | int i, j, t, minor; | 727 | int i, j, t, minor; |
| 495 | int error; | 728 | int error; |
| 496 | 729 | ||
| 497 | for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++); | 730 | for (minor = 0; minor < JOYDEV_MINORS; minor++) |
| 731 | if (!joydev_table[minor]) | ||
| 732 | break; | ||
| 733 | |||
| 498 | if (minor == JOYDEV_MINORS) { | 734 | if (minor == JOYDEV_MINORS) { |
| 499 | printk(KERN_ERR "joydev: no more free joydev devices\n"); | 735 | printk(KERN_ERR "joydev: no more free joydev devices\n"); |
| 500 | return -ENFILE; | 736 | return -ENFILE; |
| @@ -505,15 +741,19 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, | |||
| 505 | return -ENOMEM; | 741 | return -ENOMEM; |
| 506 | 742 | ||
| 507 | INIT_LIST_HEAD(&joydev->client_list); | 743 | INIT_LIST_HEAD(&joydev->client_list); |
| 744 | spin_lock_init(&joydev->client_lock); | ||
| 745 | mutex_init(&joydev->mutex); | ||
| 508 | init_waitqueue_head(&joydev->wait); | 746 | init_waitqueue_head(&joydev->wait); |
| 509 | 747 | ||
| 748 | snprintf(joydev->name, sizeof(joydev->name), "js%d", minor); | ||
| 749 | joydev->exist = 1; | ||
| 510 | joydev->minor = minor; | 750 | joydev->minor = minor; |
| 751 | |||
| 511 | joydev->exist = 1; | 752 | joydev->exist = 1; |
| 512 | joydev->handle.dev = dev; | 753 | joydev->handle.dev = dev; |
| 513 | joydev->handle.name = joydev->name; | 754 | joydev->handle.name = joydev->name; |
| 514 | joydev->handle.handler = handler; | 755 | joydev->handle.handler = handler; |
| 515 | joydev->handle.private = joydev; | 756 | joydev->handle.private = joydev; |
| 516 | snprintf(joydev->name, sizeof(joydev->name), "js%d", minor); | ||
| 517 | 757 | ||
| 518 | for (i = 0; i < ABS_MAX + 1; i++) | 758 | for (i = 0; i < ABS_MAX + 1; i++) |
| 519 | if (test_bit(i, dev->absbit)) { | 759 | if (test_bit(i, dev->absbit)) { |
| @@ -545,67 +785,65 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, | |||
| 545 | } | 785 | } |
| 546 | joydev->corr[i].type = JS_CORR_BROKEN; | 786 | joydev->corr[i].type = JS_CORR_BROKEN; |
| 547 | joydev->corr[i].prec = dev->absfuzz[j]; | 787 | joydev->corr[i].prec = dev->absfuzz[j]; |
| 548 | joydev->corr[i].coef[0] = (dev->absmax[j] + dev->absmin[j]) / 2 - dev->absflat[j]; | 788 | joydev->corr[i].coef[0] = |
| 549 | joydev->corr[i].coef[1] = (dev->absmax[j] + dev->absmin[j]) / 2 + dev->absflat[j]; | 789 | (dev->absmax[j] + dev->absmin[j]) / 2 - dev->absflat[j]; |
| 550 | if (!(t = ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j]))) | 790 | joydev->corr[i].coef[1] = |
| 551 | continue; | 791 | (dev->absmax[j] + dev->absmin[j]) / 2 + dev->absflat[j]; |
| 552 | joydev->corr[i].coef[2] = (1 << 29) / t; | 792 | |
| 553 | joydev->corr[i].coef[3] = (1 << 29) / t; | 793 | t = (dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j]; |
| 554 | 794 | if (t) { | |
| 555 | joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i); | 795 | joydev->corr[i].coef[2] = (1 << 29) / t; |
| 796 | joydev->corr[i].coef[3] = (1 << 29) / t; | ||
| 797 | |||
| 798 | joydev->abs[i] = joydev_correct(dev->abs[j], | ||
| 799 | joydev->corr + i); | ||
| 800 | } | ||
| 556 | } | 801 | } |
| 557 | 802 | ||
| 558 | snprintf(joydev->dev.bus_id, sizeof(joydev->dev.bus_id), | 803 | strlcpy(joydev->dev.bus_id, joydev->name, sizeof(joydev->dev.bus_id)); |
| 559 | "js%d", minor); | 804 | joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor); |
| 560 | joydev->dev.class = &input_class; | 805 | joydev->dev.class = &input_class; |
| 561 | joydev->dev.parent = &dev->dev; | 806 | joydev->dev.parent = &dev->dev; |
| 562 | joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor); | ||
| 563 | joydev->dev.release = joydev_free; | 807 | joydev->dev.release = joydev_free; |
| 564 | device_initialize(&joydev->dev); | 808 | device_initialize(&joydev->dev); |
| 565 | 809 | ||
| 566 | joydev_table[minor] = joydev; | 810 | error = input_register_handle(&joydev->handle); |
| 567 | |||
| 568 | error = device_add(&joydev->dev); | ||
| 569 | if (error) | 811 | if (error) |
| 570 | goto err_free_joydev; | 812 | goto err_free_joydev; |
| 571 | 813 | ||
| 572 | error = input_register_handle(&joydev->handle); | 814 | error = joydev_install_chrdev(joydev); |
| 573 | if (error) | 815 | if (error) |
| 574 | goto err_delete_joydev; | 816 | goto err_unregister_handle; |
| 817 | |||
| 818 | error = device_add(&joydev->dev); | ||
| 819 | if (error) | ||
| 820 | goto err_cleanup_joydev; | ||
| 575 | 821 | ||
| 576 | return 0; | 822 | return 0; |
| 577 | 823 | ||
| 578 | err_delete_joydev: | 824 | err_cleanup_joydev: |
| 579 | device_del(&joydev->dev); | 825 | joydev_cleanup(joydev); |
| 826 | err_unregister_handle: | ||
| 827 | input_unregister_handle(&joydev->handle); | ||
| 580 | err_free_joydev: | 828 | err_free_joydev: |
| 581 | put_device(&joydev->dev); | 829 | put_device(&joydev->dev); |
| 582 | return error; | 830 | return error; |
| 583 | } | 831 | } |
| 584 | 832 | ||
| 585 | |||
| 586 | static void joydev_disconnect(struct input_handle *handle) | 833 | static void joydev_disconnect(struct input_handle *handle) |
| 587 | { | 834 | { |
| 588 | struct joydev *joydev = handle->private; | 835 | struct joydev *joydev = handle->private; |
| 589 | struct joydev_client *client; | ||
| 590 | 836 | ||
| 591 | input_unregister_handle(handle); | ||
| 592 | device_del(&joydev->dev); | 837 | device_del(&joydev->dev); |
| 593 | 838 | joydev_cleanup(joydev); | |
| 594 | joydev->exist = 0; | 839 | input_unregister_handle(handle); |
| 595 | |||
| 596 | if (joydev->open) { | ||
| 597 | input_close_device(handle); | ||
| 598 | list_for_each_entry(client, &joydev->client_list, node) | ||
| 599 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); | ||
| 600 | wake_up_interruptible(&joydev->wait); | ||
| 601 | } | ||
| 602 | |||
| 603 | put_device(&joydev->dev); | 840 | put_device(&joydev->dev); |
| 604 | } | 841 | } |
| 605 | 842 | ||
| 606 | static const struct input_device_id joydev_blacklist[] = { | 843 | static const struct input_device_id joydev_blacklist[] = { |
| 607 | { | 844 | { |
| 608 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, | 845 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | |
| 846 | INPUT_DEVICE_ID_MATCH_KEYBIT, | ||
| 609 | .evbit = { BIT(EV_KEY) }, | 847 | .evbit = { BIT(EV_KEY) }, |
| 610 | .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) }, | 848 | .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) }, |
| 611 | }, /* Avoid itouchpads, touchscreens and tablets */ | 849 | }, /* Avoid itouchpads, touchscreens and tablets */ |
| @@ -614,17 +852,20 @@ static const struct input_device_id joydev_blacklist[] = { | |||
| 614 | 852 | ||
| 615 | static const struct input_device_id joydev_ids[] = { | 853 | static const struct input_device_id joydev_ids[] = { |
| 616 | { | 854 | { |
| 617 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, | 855 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | |
| 856 | INPUT_DEVICE_ID_MATCH_ABSBIT, | ||
| 618 | .evbit = { BIT(EV_ABS) }, | 857 | .evbit = { BIT(EV_ABS) }, |
| 619 | .absbit = { BIT(ABS_X) }, | 858 | .absbit = { BIT(ABS_X) }, |
| 620 | }, | 859 | }, |
| 621 | { | 860 | { |
| 622 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, | 861 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | |
| 862 | INPUT_DEVICE_ID_MATCH_ABSBIT, | ||
| 623 | .evbit = { BIT(EV_ABS) }, | 863 | .evbit = { BIT(EV_ABS) }, |
| 624 | .absbit = { BIT(ABS_WHEEL) }, | 864 | .absbit = { BIT(ABS_WHEEL) }, |
| 625 | }, | 865 | }, |
| 626 | { | 866 | { |
| 627 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, | 867 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | |
| 868 | INPUT_DEVICE_ID_MATCH_ABSBIT, | ||
| 628 | .evbit = { BIT(EV_ABS) }, | 869 | .evbit = { BIT(EV_ABS) }, |
| 629 | .absbit = { BIT(ABS_THROTTLE) }, | 870 | .absbit = { BIT(ABS_THROTTLE) }, |
| 630 | }, | 871 | }, |
| @@ -634,14 +875,14 @@ static const struct input_device_id joydev_ids[] = { | |||
| 634 | MODULE_DEVICE_TABLE(input, joydev_ids); | 875 | MODULE_DEVICE_TABLE(input, joydev_ids); |
| 635 | 876 | ||
| 636 | static struct input_handler joydev_handler = { | 877 | static struct input_handler joydev_handler = { |
| 637 | .event = joydev_event, | 878 | .event = joydev_event, |
| 638 | .connect = joydev_connect, | 879 | .connect = joydev_connect, |
| 639 | .disconnect = joydev_disconnect, | 880 | .disconnect = joydev_disconnect, |
| 640 | .fops = &joydev_fops, | 881 | .fops = &joydev_fops, |
| 641 | .minor = JOYDEV_MINOR_BASE, | 882 | .minor = JOYDEV_MINOR_BASE, |
| 642 | .name = "joydev", | 883 | .name = "joydev", |
| 643 | .id_table = joydev_ids, | 884 | .id_table = joydev_ids, |
| 644 | .blacklist = joydev_blacklist, | 885 | .blacklist = joydev_blacklist, |
| 645 | }; | 886 | }; |
| 646 | 887 | ||
| 647 | static int __init joydev_init(void) | 888 | static int __init joydev_init(void) |
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 28080395899c..623629a69b03 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c | |||
| @@ -223,12 +223,16 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d | |||
| 223 | struct input_dev *dev = xpad->dev; | 223 | struct input_dev *dev = xpad->dev; |
| 224 | 224 | ||
| 225 | /* left stick */ | 225 | /* left stick */ |
| 226 | input_report_abs(dev, ABS_X, (__s16) (((__s16)data[13] << 8) | data[12])); | 226 | input_report_abs(dev, ABS_X, |
| 227 | input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[15] << 8) | data[14])); | 227 | (__s16) le16_to_cpup((__le16 *)(data + 12))); |
| 228 | input_report_abs(dev, ABS_Y, | ||
| 229 | (__s16) le16_to_cpup((__le16 *)(data + 14))); | ||
| 228 | 230 | ||
| 229 | /* right stick */ | 231 | /* right stick */ |
| 230 | input_report_abs(dev, ABS_RX, (__s16) (((__s16)data[17] << 8) | data[16])); | 232 | input_report_abs(dev, ABS_RX, |
| 231 | input_report_abs(dev, ABS_RY, (__s16) (((__s16)data[19] << 8) | data[18])); | 233 | (__s16) le16_to_cpup((__le16 *)(data + 16))); |
| 234 | input_report_abs(dev, ABS_RY, | ||
| 235 | (__s16) le16_to_cpup((__le16 *)(data + 18))); | ||
| 232 | 236 | ||
| 233 | /* triggers left/right */ | 237 | /* triggers left/right */ |
| 234 | input_report_abs(dev, ABS_Z, data[10]); | 238 | input_report_abs(dev, ABS_Z, data[10]); |
| @@ -236,8 +240,10 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d | |||
| 236 | 240 | ||
| 237 | /* digital pad */ | 241 | /* digital pad */ |
| 238 | if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) { | 242 | if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) { |
| 239 | input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); | 243 | input_report_abs(dev, ABS_HAT0X, |
| 240 | input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01)); | 244 | !!(data[2] & 0x08) - !!(data[2] & 0x04)); |
| 245 | input_report_abs(dev, ABS_HAT0Y, | ||
| 246 | !!(data[2] & 0x02) - !!(data[2] & 0x01)); | ||
| 241 | } else /* xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS */ { | 247 | } else /* xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS */ { |
| 242 | input_report_key(dev, BTN_LEFT, data[2] & 0x04); | 248 | input_report_key(dev, BTN_LEFT, data[2] & 0x04); |
| 243 | input_report_key(dev, BTN_RIGHT, data[2] & 0x08); | 249 | input_report_key(dev, BTN_RIGHT, data[2] & 0x08); |
| @@ -274,14 +280,17 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d | |||
| 274 | * http://www.free60.org/wiki/Gamepad | 280 | * http://www.free60.org/wiki/Gamepad |
| 275 | */ | 281 | */ |
| 276 | 282 | ||
| 277 | static void xpad360_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data) | 283 | static void xpad360_process_packet(struct usb_xpad *xpad, |
| 284 | u16 cmd, unsigned char *data) | ||
| 278 | { | 285 | { |
| 279 | struct input_dev *dev = xpad->dev; | 286 | struct input_dev *dev = xpad->dev; |
| 280 | 287 | ||
| 281 | /* digital pad */ | 288 | /* digital pad */ |
| 282 | if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) { | 289 | if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) { |
| 283 | input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); | 290 | input_report_abs(dev, ABS_HAT0X, |
| 284 | input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01)); | 291 | !!(data[2] & 0x08) - !!(data[2] & 0x04)); |
| 292 | input_report_abs(dev, ABS_HAT0Y, | ||
| 293 | !!(data[2] & 0x02) - !!(data[2] & 0x01)); | ||
| 285 | } else if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) { | 294 | } else if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) { |
| 286 | /* dpad as buttons (right, left, down, up) */ | 295 | /* dpad as buttons (right, left, down, up) */ |
| 287 | input_report_key(dev, BTN_LEFT, data[2] & 0x04); | 296 | input_report_key(dev, BTN_LEFT, data[2] & 0x04); |
| @@ -308,12 +317,16 @@ static void xpad360_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char | |||
| 308 | input_report_key(dev, BTN_MODE, data[3] & 0x04); | 317 | input_report_key(dev, BTN_MODE, data[3] & 0x04); |
| 309 | 318 | ||
| 310 | /* left stick */ | 319 | /* left stick */ |
| 311 | input_report_abs(dev, ABS_X, (__s16) (((__s16)data[7] << 8) | (__s16)data[6])); | 320 | input_report_abs(dev, ABS_X, |
| 312 | input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[9] << 8) | (__s16)data[8])); | 321 | (__s16) le16_to_cpup((__le16 *)(data + 6))); |
| 322 | input_report_abs(dev, ABS_Y, | ||
| 323 | (__s16) le16_to_cpup((__le16 *)(data + 8))); | ||
| 313 | 324 | ||
| 314 | /* right stick */ | 325 | /* right stick */ |
| 315 | input_report_abs(dev, ABS_RX, (__s16) (((__s16)data[11] << 8) | (__s16)data[10])); | 326 | input_report_abs(dev, ABS_RX, |
| 316 | input_report_abs(dev, ABS_RY, (__s16) (((__s16)data[13] << 8) | (__s16)data[12])); | 327 | (__s16) le16_to_cpup((__le16 *)(data + 10))); |
| 328 | input_report_abs(dev, ABS_RY, | ||
| 329 | (__s16) le16_to_cpup((__le16 *)(data + 12))); | ||
| 317 | 330 | ||
| 318 | /* triggers left/right */ | 331 | /* triggers left/right */ |
| 319 | input_report_abs(dev, ABS_Z, data[4]); | 332 | input_report_abs(dev, ABS_Z, data[4]); |
| @@ -335,10 +348,12 @@ static void xpad_irq_in(struct urb *urb) | |||
| 335 | case -ENOENT: | 348 | case -ENOENT: |
| 336 | case -ESHUTDOWN: | 349 | case -ESHUTDOWN: |
| 337 | /* this urb is terminated, clean up */ | 350 | /* this urb is terminated, clean up */ |
| 338 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | 351 | dbg("%s - urb shutting down with status: %d", |
| 352 | __FUNCTION__, urb->status); | ||
| 339 | return; | 353 | return; |
| 340 | default: | 354 | default: |
| 341 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | 355 | dbg("%s - nonzero urb status received: %d", |
| 356 | __FUNCTION__, urb->status); | ||
| 342 | goto exit; | 357 | goto exit; |
| 343 | } | 358 | } |
| 344 | 359 | ||
| @@ -367,10 +382,12 @@ static void xpad_irq_out(struct urb *urb) | |||
| 367 | case -ENOENT: | 382 | case -ENOENT: |
| 368 | case -ESHUTDOWN: | 383 | case -ESHUTDOWN: |
| 369 | /* this urb is terminated, clean up */ | 384 | /* this urb is terminated, clean up */ |
| 370 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | 385 | dbg("%s - urb shutting down with status: %d", |
| 386 | __FUNCTION__, urb->status); | ||
| 371 | return; | 387 | return; |
| 372 | default: | 388 | default: |
| 373 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | 389 | dbg("%s - nonzero urb status received: %d", |
| 390 | __FUNCTION__, urb->status); | ||
| 374 | goto exit; | 391 | goto exit; |
| 375 | } | 392 | } |
| 376 | 393 | ||
| @@ -378,7 +395,7 @@ exit: | |||
| 378 | retval = usb_submit_urb(urb, GFP_ATOMIC); | 395 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
| 379 | if (retval) | 396 | if (retval) |
| 380 | err("%s - usb_submit_urb failed with result %d", | 397 | err("%s - usb_submit_urb failed with result %d", |
| 381 | __FUNCTION__, retval); | 398 | __FUNCTION__, retval); |
| 382 | } | 399 | } |
| 383 | 400 | ||
| 384 | static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) | 401 | static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) |
| @@ -595,7 +612,7 @@ static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs) | |||
| 595 | 612 | ||
| 596 | static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) | 613 | static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) |
| 597 | { | 614 | { |
| 598 | struct usb_device *udev = interface_to_usbdev (intf); | 615 | struct usb_device *udev = interface_to_usbdev(intf); |
| 599 | struct usb_xpad *xpad; | 616 | struct usb_xpad *xpad; |
| 600 | struct input_dev *input_dev; | 617 | struct input_dev *input_dev; |
| 601 | struct usb_endpoint_descriptor *ep_irq_in; | 618 | struct usb_endpoint_descriptor *ep_irq_in; |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index c97d5eb0075d..2316a018fae6 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
| @@ -208,6 +208,27 @@ config KEYBOARD_HIL | |||
| 208 | This driver implements support for HIL-keyboards attached | 208 | This driver implements support for HIL-keyboards attached |
| 209 | to your machine, so normally you should say Y here. | 209 | to your machine, so normally you should say Y here. |
| 210 | 210 | ||
| 211 | config KEYBOARD_HP6XX | ||
| 212 | tristate "HP Jornada 6XX Keyboard support" | ||
| 213 | depends on SH_HP6XX | ||
| 214 | select INPUT_POLLDEV | ||
| 215 | help | ||
| 216 | This adds support for the onboard keyboard found on | ||
| 217 | HP Jornada 620/660/680/690. | ||
| 218 | |||
| 219 | To compile this driver as a module, choose M here: the | ||
| 220 | module will be called jornada680_kbd. | ||
| 221 | |||
| 222 | config KEYBOARD_HP7XX | ||
| 223 | tristate "HP Jornada 7XX Keyboard Driver" | ||
| 224 | depends on SA1100_JORNADA720_SSP && SA1100_SSP | ||
| 225 | help | ||
| 226 | Say Y here to add support for the HP Jornada 7xx (710/720/728) | ||
| 227 | onboard keyboard. | ||
| 228 | |||
| 229 | To compile this driver as a module, choose M here: the | ||
| 230 | module will be called jornada720_kbd. | ||
| 231 | |||
| 211 | config KEYBOARD_OMAP | 232 | config KEYBOARD_OMAP |
| 212 | tristate "TI OMAP keypad support" | 233 | tristate "TI OMAP keypad support" |
| 213 | depends on (ARCH_OMAP1 || ARCH_OMAP2) | 234 | depends on (ARCH_OMAP1 || ARCH_OMAP2) |
| @@ -253,4 +274,23 @@ config KEYBOARD_GPIO | |||
| 253 | To compile this driver as a module, choose M here: the | 274 | To compile this driver as a module, choose M here: the |
| 254 | module will be called gpio-keys. | 275 | module will be called gpio-keys. |
| 255 | 276 | ||
| 277 | config KEYBOARD_MAPLE | ||
| 278 | tristate "Maple bus keyboard" | ||
| 279 | depends on SH_DREAMCAST && MAPLE | ||
| 280 | help | ||
| 281 | Say Y here if you have a Dreamcast console running Linux and have | ||
| 282 | a keyboard attached to its Maple bus. | ||
| 283 | |||
| 284 | To compile this driver as a module, choose M here: the | ||
| 285 | module will be called maple_keyb. | ||
| 286 | |||
| 287 | config KEYBOARD_BFIN | ||
| 288 | tristate "Blackfin BF54x keypad support" | ||
| 289 | depends on BF54x | ||
| 290 | help | ||
| 291 | Say Y here if you want to use the BF54x keypad. | ||
| 292 | |||
| 293 | To compile this driver as a module, choose M here: the | ||
| 294 | module will be called bf54x-keys. | ||
| 295 | |||
| 256 | endif | 296 | endif |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 28d211b87b14..e97455fdcc83 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
| @@ -21,4 +21,7 @@ obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o | |||
| 21 | obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keyboard.o | 21 | obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keyboard.o |
| 22 | obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o | 22 | obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o |
| 23 | obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o | 23 | obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o |
| 24 | 24 | obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o | |
| 25 | obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o | ||
| 26 | obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o | ||
| 27 | obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o | ||
diff --git a/drivers/input/keyboard/atakbd.c b/drivers/input/keyboard/atakbd.c index f948d3a14a93..a1800151b6ce 100644 --- a/drivers/input/keyboard/atakbd.c +++ b/drivers/input/keyboard/atakbd.c | |||
| @@ -217,7 +217,7 @@ static void atakbd_interrupt(unsigned char scancode, char down) | |||
| 217 | 217 | ||
| 218 | static int __init atakbd_init(void) | 218 | static int __init atakbd_init(void) |
| 219 | { | 219 | { |
| 220 | int i; | 220 | int i, error; |
| 221 | 221 | ||
| 222 | if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ST_MFP)) | 222 | if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ST_MFP)) |
| 223 | return -EIO; | 223 | return -EIO; |
| @@ -247,9 +247,10 @@ static int __init atakbd_init(void) | |||
| 247 | } | 247 | } |
| 248 | 248 | ||
| 249 | /* error check */ | 249 | /* error check */ |
| 250 | if (input_register_device(atakbd_dev)) { | 250 | error = input_register_device(atakbd_dev); |
| 251 | if (error) { | ||
| 251 | input_free_device(atakbd_dev); | 252 | input_free_device(atakbd_dev); |
| 252 | return -ENOMEM; | 253 | return error; |
| 253 | } | 254 | } |
| 254 | 255 | ||
| 255 | atari_input_keyboard_interrupt_hook = atakbd_interrupt; | 256 | atari_input_keyboard_interrupt_hook = atakbd_interrupt; |
diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c new file mode 100644 index 000000000000..a67b29b089ef --- /dev/null +++ b/drivers/input/keyboard/bf54x-keys.c | |||
| @@ -0,0 +1,382 @@ | |||
| 1 | /* | ||
| 2 | * File: drivers/input/keyboard/bf54x-keys.c | ||
| 3 | * Based on: | ||
| 4 | * Author: Michael Hennerich <hennerich@blackfin.uclinux.org> | ||
| 5 | * | ||
| 6 | * Created: | ||
| 7 | * Description: keypad driver for Analog Devices Blackfin BF54x Processors | ||
| 8 | * | ||
| 9 | * | ||
| 10 | * Modified: | ||
| 11 | * Copyright 2007 Analog Devices Inc. | ||
| 12 | * | ||
| 13 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | ||
| 14 | * | ||
| 15 | * This program is free software; you can redistribute it and/or modify | ||
| 16 | * it under the terms of the GNU General Public License as published by | ||
| 17 | * the Free Software Foundation; either version 2 of the License, or | ||
| 18 | * (at your option) any later version. | ||
| 19 | * | ||
| 20 | * This program is distributed in the hope that it will be useful, | ||
| 21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 23 | * GNU General Public License for more details. | ||
| 24 | * | ||
| 25 | * You should have received a copy of the GNU General Public License | ||
| 26 | * along with this program; if not, see the file COPYING, or write | ||
| 27 | * to the Free Software Foundation, Inc., | ||
| 28 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 29 | */ | ||
| 30 | |||
| 31 | #include <linux/module.h> | ||
| 32 | #include <linux/version.h> | ||
| 33 | |||
| 34 | #include <linux/init.h> | ||
| 35 | #include <linux/fs.h> | ||
| 36 | #include <linux/interrupt.h> | ||
| 37 | #include <linux/irq.h> | ||
| 38 | #include <linux/sched.h> | ||
| 39 | #include <linux/pm.h> | ||
| 40 | #include <linux/sysctl.h> | ||
| 41 | #include <linux/proc_fs.h> | ||
| 42 | #include <linux/delay.h> | ||
| 43 | #include <linux/platform_device.h> | ||
| 44 | #include <linux/input.h> | ||
| 45 | #include <linux/irq.h> | ||
| 46 | |||
| 47 | #include <asm/portmux.h> | ||
| 48 | #include <asm/mach/bf54x_keys.h> | ||
| 49 | |||
| 50 | #define DRV_NAME "bf54x-keys" | ||
| 51 | #define TIME_SCALE 100 /* 100 ns */ | ||
| 52 | #define MAX_MULT (0xFF * TIME_SCALE) | ||
| 53 | #define MAX_RC 8 /* Max Row/Col */ | ||
| 54 | |||
| 55 | static const u16 per_rows[] = { | ||
| 56 | P_KEY_ROW7, | ||
| 57 | P_KEY_ROW6, | ||
| 58 | P_KEY_ROW5, | ||
| 59 | P_KEY_ROW4, | ||
| 60 | P_KEY_ROW3, | ||
| 61 | P_KEY_ROW2, | ||
| 62 | P_KEY_ROW1, | ||
| 63 | P_KEY_ROW0, | ||
| 64 | 0 | ||
| 65 | }; | ||
| 66 | |||
| 67 | static const u16 per_cols[] = { | ||
| 68 | P_KEY_COL7, | ||
| 69 | P_KEY_COL6, | ||
| 70 | P_KEY_COL5, | ||
| 71 | P_KEY_COL4, | ||
| 72 | P_KEY_COL3, | ||
| 73 | P_KEY_COL2, | ||
| 74 | P_KEY_COL1, | ||
| 75 | P_KEY_COL0, | ||
| 76 | 0 | ||
| 77 | }; | ||
| 78 | |||
| 79 | struct bf54x_kpad { | ||
| 80 | struct input_dev *input; | ||
| 81 | int irq; | ||
| 82 | unsigned short lastkey; | ||
| 83 | unsigned short *keycode; | ||
| 84 | struct timer_list timer; | ||
| 85 | unsigned int keyup_test_jiffies; | ||
| 86 | }; | ||
| 87 | |||
| 88 | static inline int bfin_kpad_find_key(struct bf54x_kpad *bf54x_kpad, | ||
| 89 | struct input_dev *input, u16 keyident) | ||
| 90 | { | ||
| 91 | u16 i; | ||
| 92 | |||
| 93 | for (i = 0; i < input->keycodemax; i++) | ||
| 94 | if (bf54x_kpad->keycode[i + input->keycodemax] == keyident) | ||
| 95 | return bf54x_kpad->keycode[i]; | ||
| 96 | return -1; | ||
| 97 | } | ||
| 98 | |||
| 99 | static inline void bfin_keycodecpy(unsigned short *keycode, | ||
| 100 | const unsigned int *pdata_kc, | ||
| 101 | unsigned short keymapsize) | ||
| 102 | { | ||
| 103 | unsigned int i; | ||
| 104 | |||
| 105 | for (i = 0; i < keymapsize; i++) { | ||
| 106 | keycode[i] = pdata_kc[i] & 0xffff; | ||
| 107 | keycode[i + keymapsize] = pdata_kc[i] >> 16; | ||
| 108 | } | ||
| 109 | } | ||
| 110 | |||
| 111 | static inline u16 bfin_kpad_get_prescale(u32 timescale) | ||
| 112 | { | ||
| 113 | u32 sclk = get_sclk(); | ||
| 114 | |||
| 115 | return ((((sclk / 1000) * timescale) / 1024) - 1); | ||
| 116 | } | ||
| 117 | |||
| 118 | static inline u16 bfin_kpad_get_keypressed(struct bf54x_kpad *bf54x_kpad) | ||
| 119 | { | ||
| 120 | return (bfin_read_KPAD_STAT() & KPAD_PRESSED); | ||
| 121 | } | ||
| 122 | |||
| 123 | static inline void bfin_kpad_clear_irq(void) | ||
| 124 | { | ||
| 125 | bfin_write_KPAD_STAT(0xFFFF); | ||
| 126 | bfin_write_KPAD_ROWCOL(0xFFFF); | ||
| 127 | } | ||
| 128 | |||
| 129 | static void bfin_kpad_timer(unsigned long data) | ||
| 130 | { | ||
| 131 | struct platform_device *pdev = (struct platform_device *) data; | ||
| 132 | struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); | ||
| 133 | |||
| 134 | if (bfin_kpad_get_keypressed(bf54x_kpad)) { | ||
| 135 | /* Try again later */ | ||
| 136 | mod_timer(&bf54x_kpad->timer, | ||
| 137 | jiffies + bf54x_kpad->keyup_test_jiffies); | ||
| 138 | return; | ||
| 139 | } | ||
| 140 | |||
| 141 | input_report_key(bf54x_kpad->input, bf54x_kpad->lastkey, 0); | ||
| 142 | input_sync(bf54x_kpad->input); | ||
| 143 | |||
| 144 | /* Clear IRQ Status */ | ||
| 145 | |||
| 146 | bfin_kpad_clear_irq(); | ||
| 147 | enable_irq(bf54x_kpad->irq); | ||
| 148 | } | ||
| 149 | |||
| 150 | static irqreturn_t bfin_kpad_isr(int irq, void *dev_id) | ||
| 151 | { | ||
| 152 | struct platform_device *pdev = dev_id; | ||
| 153 | struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); | ||
| 154 | struct input_dev *input = bf54x_kpad->input; | ||
| 155 | int key; | ||
| 156 | u16 rowcol = bfin_read_KPAD_ROWCOL(); | ||
| 157 | |||
| 158 | key = bfin_kpad_find_key(bf54x_kpad, input, rowcol); | ||
| 159 | |||
| 160 | input_report_key(input, key, 1); | ||
| 161 | input_sync(input); | ||
| 162 | |||
| 163 | if (bfin_kpad_get_keypressed(bf54x_kpad)) { | ||
| 164 | disable_irq(bf54x_kpad->irq); | ||
| 165 | bf54x_kpad->lastkey = key; | ||
| 166 | mod_timer(&bf54x_kpad->timer, | ||
| 167 | jiffies + bf54x_kpad->keyup_test_jiffies); | ||
| 168 | } else { | ||
| 169 | input_report_key(input, key, 0); | ||
| 170 | input_sync(input); | ||
| 171 | |||
| 172 | bfin_kpad_clear_irq(); | ||
| 173 | } | ||
| 174 | |||
| 175 | return IRQ_HANDLED; | ||
| 176 | } | ||
| 177 | |||
| 178 | static int __devinit bfin_kpad_probe(struct platform_device *pdev) | ||
| 179 | { | ||
| 180 | struct bf54x_kpad *bf54x_kpad; | ||
| 181 | struct bfin_kpad_platform_data *pdata = pdev->dev.platform_data; | ||
| 182 | struct input_dev *input; | ||
| 183 | int i, error; | ||
| 184 | |||
| 185 | if (!pdata->rows || !pdata->cols || !pdata->keymap) { | ||
| 186 | printk(KERN_ERR DRV_NAME | ||
| 187 | ": No rows, cols or keymap from pdata\n"); | ||
| 188 | return -EINVAL; | ||
| 189 | } | ||
| 190 | |||
| 191 | if (!pdata->keymapsize || | ||
| 192 | pdata->keymapsize > (pdata->rows * pdata->cols)) { | ||
| 193 | printk(KERN_ERR DRV_NAME ": Invalid keymapsize\n"); | ||
| 194 | return -EINVAL; | ||
| 195 | } | ||
| 196 | |||
| 197 | bf54x_kpad = kzalloc(sizeof(struct bf54x_kpad), GFP_KERNEL); | ||
| 198 | if (!bf54x_kpad) | ||
| 199 | return -ENOMEM; | ||
| 200 | |||
| 201 | platform_set_drvdata(pdev, bf54x_kpad); | ||
| 202 | |||
| 203 | /* Allocate memory for keymap followed by private LUT */ | ||
| 204 | bf54x_kpad->keycode = kmalloc(pdata->keymapsize * | ||
| 205 | sizeof(unsigned short) * 2, GFP_KERNEL); | ||
| 206 | if (!bf54x_kpad->keycode) { | ||
| 207 | error = -ENOMEM; | ||
| 208 | goto out; | ||
| 209 | } | ||
| 210 | |||
| 211 | if (!pdata->debounce_time || !pdata->debounce_time > MAX_MULT || | ||
| 212 | !pdata->coldrive_time || !pdata->coldrive_time > MAX_MULT) { | ||
| 213 | printk(KERN_ERR DRV_NAME | ||
| 214 | ": Invalid Debounce/Columdrive Time from pdata\n"); | ||
| 215 | bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */ | ||
| 216 | } else { | ||
| 217 | bfin_write_KPAD_MSEL( | ||
| 218 | ((pdata->debounce_time / TIME_SCALE) | ||
| 219 | & DBON_SCALE) | | ||
| 220 | (((pdata->coldrive_time / TIME_SCALE) << 8) | ||
| 221 | & COLDRV_SCALE)); | ||
| 222 | |||
| 223 | } | ||
| 224 | |||
| 225 | if (!pdata->keyup_test_interval) | ||
| 226 | bf54x_kpad->keyup_test_jiffies = msecs_to_jiffies(50); | ||
| 227 | else | ||
| 228 | bf54x_kpad->keyup_test_jiffies = | ||
| 229 | msecs_to_jiffies(pdata->keyup_test_interval); | ||
| 230 | |||
| 231 | if (peripheral_request_list((u16 *)&per_rows[MAX_RC - pdata->rows], | ||
| 232 | DRV_NAME)) { | ||
| 233 | printk(KERN_ERR DRV_NAME | ||
| 234 | ": Requesting Peripherals failed\n"); | ||
| 235 | error = -EFAULT; | ||
| 236 | goto out0; | ||
| 237 | } | ||
| 238 | |||
| 239 | if (peripheral_request_list((u16 *)&per_cols[MAX_RC - pdata->cols], | ||
| 240 | DRV_NAME)) { | ||
| 241 | printk(KERN_ERR DRV_NAME | ||
| 242 | ": Requesting Peripherals failed\n"); | ||
| 243 | error = -EFAULT; | ||
| 244 | goto out1; | ||
| 245 | } | ||
| 246 | |||
| 247 | bf54x_kpad->irq = platform_get_irq(pdev, 0); | ||
| 248 | if (bf54x_kpad->irq < 0) { | ||
| 249 | error = -ENODEV; | ||
| 250 | goto out2; | ||
| 251 | } | ||
| 252 | |||
| 253 | error = request_irq(bf54x_kpad->irq, bfin_kpad_isr, | ||
| 254 | IRQF_SAMPLE_RANDOM, DRV_NAME, pdev); | ||
| 255 | if (error) { | ||
| 256 | printk(KERN_ERR DRV_NAME | ||
| 257 | ": unable to claim irq %d; error %d\n", | ||
| 258 | bf54x_kpad->irq, error); | ||
| 259 | error = -EBUSY; | ||
| 260 | goto out2; | ||
| 261 | } | ||
| 262 | |||
| 263 | input = input_allocate_device(); | ||
| 264 | if (!input) { | ||
| 265 | error = -ENOMEM; | ||
| 266 | goto out3; | ||
| 267 | } | ||
| 268 | |||
| 269 | bf54x_kpad->input = input; | ||
| 270 | |||
| 271 | input->name = pdev->name; | ||
| 272 | input->phys = "bf54x-keys/input0"; | ||
| 273 | input->dev.parent = &pdev->dev; | ||
| 274 | |||
| 275 | input_set_drvdata(input, bf54x_kpad); | ||
| 276 | |||
| 277 | input->id.bustype = BUS_HOST; | ||
| 278 | input->id.vendor = 0x0001; | ||
| 279 | input->id.product = 0x0001; | ||
| 280 | input->id.version = 0x0100; | ||
| 281 | |||
| 282 | input->keycodesize = sizeof(unsigned short); | ||
| 283 | input->keycodemax = pdata->keymapsize; | ||
| 284 | input->keycode = bf54x_kpad->keycode; | ||
| 285 | |||
| 286 | bfin_keycodecpy(bf54x_kpad->keycode, pdata->keymap, pdata->keymapsize); | ||
| 287 | |||
| 288 | /* setup input device */ | ||
| 289 | __set_bit(EV_KEY, input->evbit); | ||
| 290 | |||
| 291 | if (pdata->repeat) | ||
| 292 | __set_bit(EV_REP, input->evbit); | ||
| 293 | |||
| 294 | for (i = 0; i < input->keycodemax; i++) | ||
| 295 | __set_bit(bf54x_kpad->keycode[i] & KEY_MAX, input->keybit); | ||
| 296 | __clear_bit(KEY_RESERVED, input->keybit); | ||
| 297 | |||
| 298 | error = input_register_device(input); | ||
| 299 | if (error) { | ||
| 300 | printk(KERN_ERR DRV_NAME | ||
| 301 | ": Unable to register input device (%d)\n", error); | ||
| 302 | goto out4; | ||
| 303 | } | ||
| 304 | |||
| 305 | /* Init Keypad Key Up/Release test timer */ | ||
| 306 | |||
| 307 | setup_timer(&bf54x_kpad->timer, bfin_kpad_timer, (unsigned long) pdev); | ||
| 308 | |||
| 309 | bfin_write_KPAD_PRESCALE(bfin_kpad_get_prescale(TIME_SCALE)); | ||
| 310 | |||
| 311 | bfin_write_KPAD_CTL((((pdata->cols - 1) << 13) & KPAD_COLEN) | | ||
| 312 | (((pdata->rows - 1) << 10) & KPAD_ROWEN) | | ||
| 313 | (2 & KPAD_IRQMODE)); | ||
| 314 | |||
| 315 | bfin_write_KPAD_CTL(bfin_read_KPAD_CTL() | KPAD_EN); | ||
| 316 | |||
| 317 | printk(KERN_ERR DRV_NAME | ||
| 318 | ": Blackfin BF54x Keypad registered IRQ %d\n", bf54x_kpad->irq); | ||
| 319 | |||
| 320 | return 0; | ||
| 321 | |||
| 322 | out4: | ||
| 323 | input_free_device(input); | ||
| 324 | out3: | ||
| 325 | free_irq(bf54x_kpad->irq, pdev); | ||
| 326 | out2: | ||
| 327 | peripheral_free_list((u16 *)&per_cols[MAX_RC - pdata->cols]); | ||
| 328 | out1: | ||
| 329 | peripheral_free_list((u16 *)&per_rows[MAX_RC - pdata->rows]); | ||
| 330 | out0: | ||
| 331 | kfree(bf54x_kpad->keycode); | ||
| 332 | out: | ||
| 333 | kfree(bf54x_kpad); | ||
| 334 | platform_set_drvdata(pdev, NULL); | ||
| 335 | |||
| 336 | return error; | ||
| 337 | } | ||
| 338 | |||
| 339 | static int __devexit bfin_kpad_remove(struct platform_device *pdev) | ||
| 340 | { | ||
| 341 | struct bfin_kpad_platform_data *pdata = pdev->dev.platform_data; | ||
| 342 | struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); | ||
| 343 | |||
| 344 | del_timer_sync(&bf54x_kpad->timer); | ||
| 345 | free_irq(bf54x_kpad->irq, pdev); | ||
| 346 | |||
| 347 | input_unregister_device(bf54x_kpad->input); | ||
| 348 | |||
| 349 | peripheral_free_list((u16 *)&per_rows[MAX_RC - pdata->rows]); | ||
| 350 | peripheral_free_list((u16 *)&per_cols[MAX_RC - pdata->cols]); | ||
| 351 | |||
| 352 | kfree(bf54x_kpad->keycode); | ||
| 353 | kfree(bf54x_kpad); | ||
| 354 | platform_set_drvdata(pdev, NULL); | ||
| 355 | |||
| 356 | return 0; | ||
| 357 | } | ||
| 358 | |||
| 359 | struct platform_driver bfin_kpad_device_driver = { | ||
| 360 | .probe = bfin_kpad_probe, | ||
| 361 | .remove = __devexit_p(bfin_kpad_remove), | ||
| 362 | .driver = { | ||
| 363 | .name = DRV_NAME, | ||
| 364 | } | ||
| 365 | }; | ||
| 366 | |||
| 367 | static int __init bfin_kpad_init(void) | ||
| 368 | { | ||
| 369 | return platform_driver_register(&bfin_kpad_device_driver); | ||
| 370 | } | ||
| 371 | |||
| 372 | static void __exit bfin_kpad_exit(void) | ||
| 373 | { | ||
| 374 | platform_driver_unregister(&bfin_kpad_device_driver); | ||
| 375 | } | ||
| 376 | |||
| 377 | module_init(bfin_kpad_init); | ||
| 378 | module_exit(bfin_kpad_exit); | ||
| 379 | |||
| 380 | MODULE_LICENSE("GPL"); | ||
| 381 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
| 382 | MODULE_DESCRIPTION("Keypad driver for BF54x Processors"); | ||
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index f0b22b8b2769..e2a3293bc67e 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c | |||
| @@ -54,6 +54,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
| 54 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | 54 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; |
| 55 | struct input_dev *input; | 55 | struct input_dev *input; |
| 56 | int i, error; | 56 | int i, error; |
| 57 | int wakeup = 0; | ||
| 57 | 58 | ||
| 58 | input = input_allocate_device(); | 59 | input = input_allocate_device(); |
| 59 | if (!input) | 60 | if (!input) |
| @@ -77,31 +78,51 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
| 77 | int irq = gpio_to_irq(button->gpio); | 78 | int irq = gpio_to_irq(button->gpio); |
| 78 | unsigned int type = button->type ?: EV_KEY; | 79 | unsigned int type = button->type ?: EV_KEY; |
| 79 | 80 | ||
| 80 | set_irq_type(irq, IRQ_TYPE_EDGE_BOTH); | 81 | if (irq < 0) { |
| 81 | error = request_irq(irq, gpio_keys_isr, IRQF_SAMPLE_RANDOM, | 82 | error = irq; |
| 82 | button->desc ? button->desc : "gpio_keys", | 83 | printk(KERN_ERR |
| 83 | pdev); | 84 | "gpio-keys: " |
| 85 | "Unable to get irq number for GPIO %d," | ||
| 86 | "error %d\n", | ||
| 87 | button->gpio, error); | ||
| 88 | goto fail; | ||
| 89 | } | ||
| 90 | |||
| 91 | error = request_irq(irq, gpio_keys_isr, | ||
| 92 | IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_RISING | | ||
| 93 | IRQF_TRIGGER_FALLING, | ||
| 94 | button->desc ? button->desc : "gpio_keys", | ||
| 95 | pdev); | ||
| 84 | if (error) { | 96 | if (error) { |
| 85 | printk(KERN_ERR "gpio-keys: unable to claim irq %d; error %d\n", | 97 | printk(KERN_ERR |
| 98 | "gpio-keys: Unable to claim irq %d; error %d\n", | ||
| 86 | irq, error); | 99 | irq, error); |
| 87 | goto fail; | 100 | goto fail; |
| 88 | } | 101 | } |
| 89 | 102 | ||
| 103 | if (button->wakeup) | ||
| 104 | wakeup = 1; | ||
| 105 | |||
| 90 | input_set_capability(input, type, button->code); | 106 | input_set_capability(input, type, button->code); |
| 91 | } | 107 | } |
| 92 | 108 | ||
| 93 | error = input_register_device(input); | 109 | error = input_register_device(input); |
| 94 | if (error) { | 110 | if (error) { |
| 95 | printk(KERN_ERR "Unable to register gpio-keys input device\n"); | 111 | printk(KERN_ERR |
| 112 | "gpio-keys: Unable to register input device, " | ||
| 113 | "error: %d\n", error); | ||
| 96 | goto fail; | 114 | goto fail; |
| 97 | } | 115 | } |
| 98 | 116 | ||
| 117 | device_init_wakeup(&pdev->dev, wakeup); | ||
| 118 | |||
| 99 | return 0; | 119 | return 0; |
| 100 | 120 | ||
| 101 | fail: | 121 | fail: |
| 102 | for (i = i - 1; i >= 0; i--) | 122 | while (--i >= 0) |
| 103 | free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev); | 123 | free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev); |
| 104 | 124 | ||
| 125 | platform_set_drvdata(pdev, NULL); | ||
| 105 | input_free_device(input); | 126 | input_free_device(input); |
| 106 | 127 | ||
| 107 | return error; | 128 | return error; |
| @@ -113,6 +134,8 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) | |||
| 113 | struct input_dev *input = platform_get_drvdata(pdev); | 134 | struct input_dev *input = platform_get_drvdata(pdev); |
| 114 | int i; | 135 | int i; |
| 115 | 136 | ||
| 137 | device_init_wakeup(&pdev->dev, 0); | ||
| 138 | |||
| 116 | for (i = 0; i < pdata->nbuttons; i++) { | 139 | for (i = 0; i < pdata->nbuttons; i++) { |
| 117 | int irq = gpio_to_irq(pdata->buttons[i].gpio); | 140 | int irq = gpio_to_irq(pdata->buttons[i].gpio); |
| 118 | free_irq(irq, pdev); | 141 | free_irq(irq, pdev); |
| @@ -123,9 +146,53 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) | |||
| 123 | return 0; | 146 | return 0; |
| 124 | } | 147 | } |
| 125 | 148 | ||
| 149 | |||
| 150 | #ifdef CONFIG_PM | ||
| 151 | static int gpio_keys_suspend(struct platform_device *pdev, pm_message_t state) | ||
| 152 | { | ||
| 153 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | ||
| 154 | int i; | ||
| 155 | |||
| 156 | if (device_may_wakeup(&pdev->dev)) { | ||
| 157 | for (i = 0; i < pdata->nbuttons; i++) { | ||
| 158 | struct gpio_keys_button *button = &pdata->buttons[i]; | ||
| 159 | if (button->wakeup) { | ||
| 160 | int irq = gpio_to_irq(button->gpio); | ||
| 161 | enable_irq_wake(irq); | ||
| 162 | } | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 166 | return 0; | ||
| 167 | } | ||
| 168 | |||
| 169 | static int gpio_keys_resume(struct platform_device *pdev) | ||
| 170 | { | ||
| 171 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | ||
| 172 | int i; | ||
| 173 | |||
| 174 | if (device_may_wakeup(&pdev->dev)) { | ||
| 175 | for (i = 0; i < pdata->nbuttons; i++) { | ||
| 176 | struct gpio_keys_button *button = &pdata->buttons[i]; | ||
| 177 | if (button->wakeup) { | ||
| 178 | int irq = gpio_to_irq(button->gpio); | ||
| 179 | disable_irq_wake(irq); | ||
| 180 | } | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 184 | return 0; | ||
| 185 | } | ||
| 186 | #else | ||
| 187 | #define gpio_keys_suspend NULL | ||
| 188 | #define gpio_keys_resume NULL | ||
| 189 | #endif | ||
| 190 | |||
| 126 | struct platform_driver gpio_keys_device_driver = { | 191 | struct platform_driver gpio_keys_device_driver = { |
| 127 | .probe = gpio_keys_probe, | 192 | .probe = gpio_keys_probe, |
| 128 | .remove = __devexit_p(gpio_keys_remove), | 193 | .remove = __devexit_p(gpio_keys_remove), |
| 194 | .suspend = gpio_keys_suspend, | ||
| 195 | .resume = gpio_keys_resume, | ||
| 129 | .driver = { | 196 | .driver = { |
| 130 | .name = "gpio-keys", | 197 | .name = "gpio-keys", |
| 131 | } | 198 | } |
diff --git a/drivers/input/keyboard/jornada680_kbd.c b/drivers/input/keyboard/jornada680_kbd.c new file mode 100644 index 000000000000..bec1cf483723 --- /dev/null +++ b/drivers/input/keyboard/jornada680_kbd.c | |||
| @@ -0,0 +1,277 @@ | |||
| 1 | /* | ||
| 2 | * drivers/input/keyboard/jornada680_kbd.c | ||
| 3 | * | ||
| 4 | * HP Jornada 620/660/680/690 scan keyboard platform driver | ||
| 5 | * Copyright (C) 2007 Kristoffer Ericson <Kristoffer.Ericson@gmail.com> | ||
| 6 | * | ||
| 7 | * Based on hp680_keyb.c | ||
| 8 | * Copyright (C) 2006 Paul Mundt | ||
| 9 | * Copyright (C) 2005 Andriy Skulysh | ||
| 10 | * Split from drivers/input/keyboard/hp600_keyb.c | ||
| 11 | * Copyright (C) 2000 Yaegashi Takeshi (hp6xx kbd scan routine and translation table) | ||
| 12 | * Copyright (C) 2000 Niibe Yutaka (HP620 Keyb translation table) | ||
| 13 | * | ||
| 14 | * This program is free software; you can redistribute it and/or modify it | ||
| 15 | * under the terms of the GNU General Public License version 2 as | ||
| 16 | * published by the Free Software Foundation. | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include <linux/input.h> | ||
| 20 | #include <linux/kernel.h> | ||
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/init.h> | ||
| 23 | #include <linux/input-polldev.h> | ||
| 24 | #include <linux/jiffies.h> | ||
| 25 | #include <linux/platform_device.h> | ||
| 26 | #include <linux/interrupt.h> | ||
| 27 | |||
| 28 | #include <asm/delay.h> | ||
| 29 | #include <asm/io.h> | ||
| 30 | |||
| 31 | #define PCCR 0xa4000104 | ||
| 32 | #define PDCR 0xa4000106 | ||
| 33 | #define PECR 0xa4000108 | ||
| 34 | #define PFCR 0xa400010a | ||
| 35 | #define PCDR 0xa4000124 | ||
| 36 | #define PDDR 0xa4000126 | ||
| 37 | #define PEDR 0xa4000128 | ||
| 38 | #define PFDR 0xa400012a | ||
| 39 | #define PGDR 0xa400012c | ||
| 40 | #define PHDR 0xa400012e | ||
| 41 | #define PJDR 0xa4000130 | ||
| 42 | #define PKDR 0xa4000132 | ||
| 43 | #define PLDR 0xa4000134 | ||
| 44 | |||
| 45 | static const unsigned short jornada_scancodes[] = { | ||
| 46 | /* PTD1 */ KEY_CAPSLOCK, KEY_MACRO, KEY_LEFTCTRL, 0, KEY_ESC, 0, 0, 0, /* 1 -> 8 */ | ||
| 47 | KEY_F1, KEY_F2, KEY_F3, KEY_F8, KEY_F7, KEY_F2, KEY_F4, KEY_F5, /* 9 -> 16 */ | ||
| 48 | /* PTD5 */ KEY_SLASH, KEY_APOSTROPHE, KEY_ENTER, 0, KEY_Z, 0, 0, 0, /* 17 -> 24 */ | ||
| 49 | KEY_X, KEY_C, KEY_V, KEY_DOT, KEY_COMMA, KEY_M, KEY_B, KEY_N, /* 25 -> 32 */ | ||
| 50 | /* PTD7 */ KEY_KP2, KEY_KP6, 0, 0, 0, 0, 0, 0, /* 33 -> 40 */ | ||
| 51 | 0, 0, 0, KEY_KP4, 0, 0, KEY_LEFTALT, KEY_HANJA, /* 41 -> 48 */ | ||
| 52 | /* PTE0 */ 0, 0, 0, 0, KEY_FINANCE, 0, 0, 0, /* 49 -> 56 */ | ||
| 53 | KEY_LEFTCTRL, 0, KEY_SPACE, KEY_KPDOT, KEY_VOLUMEUP, 249, 0, 0, /* 57 -> 64 */ | ||
| 54 | /* PTE1 */ KEY_SEMICOLON, KEY_RIGHTBRACE, KEY_BACKSLASH, 0, KEY_A, 0, 0, 0,/* 65 -> 72 */ | ||
| 55 | KEY_S, KEY_D, KEY_F, KEY_L, KEY_K, KEY_J, KEY_G, KEY_H, /* 73 -> 80 */ | ||
| 56 | /* PTE3 */ KEY_KP8, KEY_LEFTMETA, KEY_RIGHTSHIFT, 0, KEY_TAB, 0, 0,0, /* 81 -> 88 */ | ||
| 57 | 0, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, /* 89 -> 96 */ | ||
| 58 | /* PTE6 */ KEY_P, KEY_LEFTBRACE, KEY_BACKSPACE, 0, KEY_Q, 0, 0, 0, /* 97 -> 104 */ | ||
| 59 | KEY_W, KEY_E, KEY_R, KEY_O, KEY_I, KEY_U, KEY_T, KEY_R, /* 105 -> 112 */ | ||
| 60 | /* PTE7 */ KEY_0, KEY_MINUS, KEY_EQUAL, 0, KEY_1, 0, 0, 0, /* 113 -> 120 */ | ||
| 61 | KEY_2, KEY_3, KEY_4, KEY_9, KEY_8, KEY_7, KEY_5, KEY_6, /* 121 -> 128 */ | ||
| 62 | /* **** */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 63 | 0, 0, 0, 0, 0 | ||
| 64 | }; | ||
| 65 | |||
| 66 | #define JORNADA_SCAN_SIZE 18 | ||
| 67 | |||
| 68 | struct jornadakbd { | ||
| 69 | struct input_polled_dev *poll_dev; | ||
| 70 | unsigned short keymap[ARRAY_SIZE(jornada_scancodes)]; | ||
| 71 | unsigned char length; | ||
| 72 | unsigned char old_scan[JORNADA_SCAN_SIZE]; | ||
| 73 | unsigned char new_scan[JORNADA_SCAN_SIZE]; | ||
| 74 | }; | ||
| 75 | |||
| 76 | static void jornada_parse_kbd(struct jornadakbd *jornadakbd) | ||
| 77 | { | ||
| 78 | struct input_dev *input_dev = jornadakbd->poll_dev->input; | ||
| 79 | unsigned short *keymap = jornadakbd->keymap; | ||
| 80 | unsigned int sync_me = 0; | ||
| 81 | unsigned int i, j; | ||
| 82 | |||
| 83 | for (i = 0; i < JORNADA_SCAN_SIZE; i++) { | ||
| 84 | unsigned char new = jornadakbd->new_scan[i]; | ||
| 85 | unsigned char old = jornadakbd->old_scan[i]; | ||
| 86 | unsigned int xor = new ^ old; | ||
| 87 | |||
| 88 | if (xor == 0) | ||
| 89 | continue; | ||
| 90 | |||
| 91 | for (j = 0; j < 8; j++) { | ||
| 92 | unsigned int bit = 1 << j; | ||
| 93 | if (xor & bit) { | ||
| 94 | unsigned int scancode = (i << 3) + j; | ||
| 95 | input_event(input_dev, | ||
| 96 | EV_MSC, MSC_SCAN, scancode); | ||
| 97 | input_report_key(input_dev, | ||
| 98 | keymap[scancode], | ||
| 99 | !(new & bit)); | ||
| 100 | sync_me = 1; | ||
| 101 | } | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | if (sync_me) | ||
| 106 | input_sync(input_dev); | ||
| 107 | } | ||
| 108 | |||
| 109 | static void jornada_scan_keyb(unsigned char *s) | ||
| 110 | { | ||
| 111 | int i; | ||
| 112 | unsigned short ec_static, dc_static; /* = UINT16_t */ | ||
| 113 | unsigned char matrix_switch[] = { | ||
| 114 | 0xfd, 0xff, /* PTD1 PD(1) */ | ||
| 115 | 0xdf, 0xff, /* PTD5 PD(5) */ | ||
| 116 | 0x7f, 0xff, /* PTD7 PD(7) */ | ||
| 117 | 0xff, 0xfe, /* PTE0 PE(0) */ | ||
| 118 | 0xff, 0xfd, /* PTE1 PE(1) */ | ||
| 119 | 0xff, 0xf7, /* PTE3 PE(3) */ | ||
| 120 | 0xff, 0xbf, /* PTE6 PE(6) */ | ||
| 121 | 0xff, 0x7f, /* PTE7 PE(7) */ | ||
| 122 | }, *t = matrix_switch; | ||
| 123 | /* PD(x) : | ||
| 124 | 1. 0xcc0c & (1~(1 << (2*(x)+1))))) | ||
| 125 | 2. (0xf0cf & 0xfffff) */ | ||
| 126 | /* PE(x) : | ||
| 127 | 1. 0xcc0c & 0xffff | ||
| 128 | 2. 0xf0cf & (1~(1 << (2*(x)+1))))) */ | ||
| 129 | unsigned short matrix_PDE[] = { | ||
| 130 | 0xcc04, 0xf0cf, /* PD(1) */ | ||
| 131 | 0xc40c, 0xf0cf, /* PD(5) */ | ||
| 132 | 0x4c0c, 0xf0cf, /* PD(7) */ | ||
| 133 | 0xcc0c, 0xf0cd, /* PE(0) */ | ||
| 134 | 0xcc0c, 0xf0c7, /* PE(1) */ | ||
| 135 | 0xcc0c, 0xf04f, /* PE(3) */ | ||
| 136 | 0xcc0c, 0xd0cf, /* PE(6) */ | ||
| 137 | 0xcc0c, 0x70cf, /* PE(7) */ | ||
| 138 | }, *y = matrix_PDE; | ||
| 139 | |||
| 140 | /* Save these control reg bits */ | ||
| 141 | dc_static = (ctrl_inw(PDCR) & (~0xcc0c)); | ||
| 142 | ec_static = (ctrl_inw(PECR) & (~0xf0cf)); | ||
| 143 | |||
| 144 | for (i = 0; i < 8; i++) { | ||
| 145 | /* disable output for all but the one we want to scan */ | ||
| 146 | ctrl_outw((dc_static | *y++), PDCR); | ||
| 147 | ctrl_outw((ec_static | *y++), PECR); | ||
| 148 | udelay(5); | ||
| 149 | |||
| 150 | /* Get scanline row */ | ||
| 151 | ctrl_outb(*t++, PDDR); | ||
| 152 | ctrl_outb(*t++, PEDR); | ||
| 153 | udelay(50); | ||
| 154 | |||
| 155 | /* Read data */ | ||
| 156 | *s++ = ctrl_inb(PCDR); | ||
| 157 | *s++ = ctrl_inb(PFDR); | ||
| 158 | } | ||
| 159 | /* Scan no lines */ | ||
| 160 | ctrl_outb(0xff, PDDR); | ||
| 161 | ctrl_outb(0xff, PEDR); | ||
| 162 | |||
| 163 | /* Enable all scanlines */ | ||
| 164 | ctrl_outw((dc_static | (0x5555 & 0xcc0c)),PDCR); | ||
| 165 | ctrl_outw((ec_static | (0x5555 & 0xf0cf)),PECR); | ||
| 166 | |||
| 167 | /* Ignore extra keys and events */ | ||
| 168 | *s++ = ctrl_inb(PGDR); | ||
| 169 | *s++ = ctrl_inb(PHDR); | ||
| 170 | } | ||
| 171 | |||
| 172 | static void jornadakbd680_poll(struct input_polled_dev *dev) | ||
| 173 | { | ||
| 174 | struct jornadakbd *jornadakbd = dev->private; | ||
| 175 | |||
| 176 | jornada_scan_keyb(jornadakbd->new_scan); | ||
| 177 | jornada_parse_kbd(jornadakbd); | ||
| 178 | memcpy(jornadakbd->old_scan, jornadakbd->new_scan, JORNADA_SCAN_SIZE); | ||
| 179 | } | ||
| 180 | |||
| 181 | static int __devinit jornada680kbd_probe(struct platform_device *pdev) | ||
| 182 | { | ||
| 183 | struct jornadakbd *jornadakbd; | ||
| 184 | struct input_polled_dev *poll_dev; | ||
| 185 | struct input_dev *input_dev; | ||
| 186 | int i, error; | ||
| 187 | |||
| 188 | jornadakbd = kzalloc(sizeof(struct jornadakbd), GFP_KERNEL); | ||
| 189 | if (!jornadakbd) | ||
| 190 | return -ENOMEM; | ||
| 191 | |||
| 192 | poll_dev = input_allocate_polled_device(); | ||
| 193 | if (!poll_dev) { | ||
| 194 | error = -ENOMEM; | ||
| 195 | goto failed; | ||
| 196 | } | ||
| 197 | |||
| 198 | platform_set_drvdata(pdev, jornadakbd); | ||
| 199 | |||
| 200 | jornadakbd->poll_dev = poll_dev; | ||
| 201 | |||
| 202 | memcpy(jornadakbd->keymap, jornada_scancodes, | ||
| 203 | sizeof(jornadakbd->keymap)); | ||
| 204 | |||
| 205 | poll_dev->private = jornadakbd; | ||
| 206 | poll_dev->poll = jornadakbd680_poll; | ||
| 207 | poll_dev->poll_interval = 50; /* msec */ | ||
| 208 | |||
| 209 | input_dev = poll_dev->input; | ||
| 210 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | ||
| 211 | input_dev->name = "HP Jornada 680 keyboard"; | ||
| 212 | input_dev->phys = "jornadakbd/input0"; | ||
| 213 | input_dev->keycode = jornadakbd->keymap; | ||
| 214 | input_dev->keycodesize = sizeof(unsigned short); | ||
| 215 | input_dev->keycodemax = ARRAY_SIZE(jornada_scancodes); | ||
| 216 | input_dev->dev.parent = &pdev->dev; | ||
| 217 | input_dev->id.bustype = BUS_HOST; | ||
| 218 | |||
| 219 | for (i = 0; i < 128; i++) | ||
| 220 | if (jornadakbd->keymap[i]) | ||
| 221 | __set_bit(jornadakbd->keymap[i], input_dev->keybit); | ||
| 222 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
| 223 | |||
| 224 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | ||
| 225 | |||
| 226 | error = input_register_polled_device(jornadakbd->poll_dev); | ||
| 227 | if (error) | ||
| 228 | goto failed; | ||
| 229 | |||
| 230 | return 0; | ||
| 231 | |||
| 232 | failed: | ||
| 233 | printk(KERN_ERR "Jornadakbd: failed to register driver, error: %d\n", | ||
| 234 | error); | ||
| 235 | platform_set_drvdata(pdev, NULL); | ||
| 236 | input_free_polled_device(poll_dev); | ||
| 237 | kfree(jornadakbd); | ||
| 238 | return error; | ||
| 239 | |||
| 240 | } | ||
| 241 | |||
| 242 | static int __devexit jornada680kbd_remove(struct platform_device *pdev) | ||
| 243 | { | ||
| 244 | struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); | ||
| 245 | |||
| 246 | platform_set_drvdata(pdev, NULL); | ||
| 247 | input_unregister_polled_device(jornadakbd->poll_dev); | ||
| 248 | input_free_polled_device(jornadakbd->poll_dev); | ||
| 249 | kfree(jornadakbd); | ||
| 250 | |||
| 251 | return 0; | ||
| 252 | } | ||
| 253 | |||
| 254 | static struct platform_driver jornada680kbd_driver = { | ||
| 255 | .driver = { | ||
| 256 | .name = "jornada680_kbd", | ||
| 257 | }, | ||
| 258 | .probe = jornada680kbd_probe, | ||
| 259 | .remove = __devexit_p(jornada680kbd_remove), | ||
| 260 | }; | ||
| 261 | |||
| 262 | static int __init jornada680kbd_init(void) | ||
| 263 | { | ||
| 264 | return platform_driver_register(&jornada680kbd_driver); | ||
| 265 | } | ||
| 266 | |||
| 267 | static void __exit jornada680kbd_exit(void) | ||
| 268 | { | ||
| 269 | platform_driver_unregister(&jornada680kbd_driver); | ||
| 270 | } | ||
| 271 | |||
| 272 | module_init(jornada680kbd_init); | ||
| 273 | module_exit(jornada680kbd_exit); | ||
| 274 | |||
| 275 | MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>"); | ||
| 276 | MODULE_DESCRIPTION("HP Jornada 620/660/680/690 Keyboard Driver"); | ||
| 277 | MODULE_LICENSE("GPLv2"); | ||
diff --git a/drivers/input/keyboard/jornada720_kbd.c b/drivers/input/keyboard/jornada720_kbd.c new file mode 100644 index 000000000000..e6696b3c9416 --- /dev/null +++ b/drivers/input/keyboard/jornada720_kbd.c | |||
| @@ -0,0 +1,185 @@ | |||
| 1 | /* | ||
| 2 | * drivers/input/keyboard/jornada720_kbd.c | ||
| 3 | * | ||
| 4 | * HP Jornada 720 keyboard platform driver | ||
| 5 | * | ||
| 6 | * Copyright (C) 2006/2007 Kristoffer Ericson <Kristoffer.Ericson@Gmail.com> | ||
| 7 | * | ||
| 8 | * Copyright (C) 2006 jornada 720 kbd driver by | ||
| 9 | Filip Zyzniewsk <Filip.Zyzniewski@tefnet.plX | ||
| 10 | * based on (C) 2004 jornada 720 kbd driver by | ||
| 11 | Alex Lange <chicken@handhelds.org> | ||
| 12 | * | ||
| 13 | * This program is free software; you can redistribute it and/or modify | ||
| 14 | * it under the terms of the GNU General Public License version 2 as | ||
| 15 | * published by the Free Software Foundation. | ||
| 16 | * | ||
| 17 | */ | ||
| 18 | #include <linux/device.h> | ||
| 19 | #include <linux/errno.h> | ||
| 20 | #include <linux/init.h> | ||
| 21 | #include <linux/interrupt.h> | ||
| 22 | #include <linux/init.h> | ||
| 23 | #include <linux/input.h> | ||
| 24 | #include <linux/kernel.h> | ||
| 25 | #include <linux/module.h> | ||
| 26 | #include <linux/platform_device.h> | ||
| 27 | |||
| 28 | #include <asm/arch/jornada720.h> | ||
| 29 | #include <asm/hardware.h> | ||
| 30 | |||
| 31 | MODULE_AUTHOR("Kristoffer Ericson <Kristoffer.Ericson@gmail.com>"); | ||
| 32 | MODULE_DESCRIPTION("HP Jornada 710/720/728 keyboard driver"); | ||
| 33 | MODULE_LICENSE("GPLv2"); | ||
| 34 | |||
| 35 | static unsigned short jornada_std_keymap[128] = { /* ROW */ | ||
| 36 | 0, KEY_ESC, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, /* #1 */ | ||
| 37 | KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_MUTE, /* -> */ | ||
| 38 | 0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, /* #2 */ | ||
| 39 | KEY_0, KEY_MINUS, KEY_EQUAL,0, 0, 0, /* -> */ | ||
| 40 | 0, KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O, /* #3 */ | ||
| 41 | KEY_P, KEY_BACKSLASH, KEY_BACKSPACE, 0, 0, 0, /* -> */ | ||
| 42 | 0, KEY_A, KEY_S, KEY_D, KEY_F, KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, /* #4 */ | ||
| 43 | KEY_SEMICOLON, KEY_LEFTBRACE, KEY_RIGHTBRACE, 0, 0, 0, /* -> */ | ||
| 44 | 0, KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, KEY_M, KEY_COMMA, /* #5 */ | ||
| 45 | KEY_DOT, KEY_KPMINUS, KEY_APOSTROPHE, KEY_ENTER, 0, 0,0, /* -> */ | ||
| 46 | 0, KEY_TAB, 0, KEY_LEFTSHIFT, 0, KEY_APOSTROPHE, 0, 0, 0, 0, /* #6 */ | ||
| 47 | KEY_UP, 0, KEY_RIGHTSHIFT, 0, 0, 0,0, 0, 0, 0, 0, KEY_LEFTALT, KEY_GRAVE, /* -> */ | ||
| 48 | 0, 0, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0,0, KEY_KPASTERISK, /* -> */ | ||
| 49 | KEY_LEFTCTRL, 0, KEY_SPACE, 0, 0, 0, KEY_SLASH, KEY_DELETE, 0, 0, /* -> */ | ||
| 50 | 0, 0, 0, KEY_POWER, /* -> */ | ||
| 51 | }; | ||
| 52 | |||
| 53 | struct jornadakbd { | ||
| 54 | unsigned short keymap[ARRAY_SIZE(jornada_std_keymap)]; | ||
| 55 | struct input_dev *input; | ||
| 56 | }; | ||
| 57 | |||
| 58 | static irqreturn_t jornada720_kbd_interrupt(int irq, void *dev_id) | ||
| 59 | { | ||
| 60 | struct platform_device *pdev = dev_id; | ||
| 61 | struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); | ||
| 62 | struct input_dev *input = jornadakbd->input; | ||
| 63 | u8 count, kbd_data, scan_code; | ||
| 64 | |||
| 65 | /* startup ssp with spinlock */ | ||
| 66 | jornada_ssp_start(); | ||
| 67 | |||
| 68 | if (jornada_ssp_inout(GETSCANKEYCODE) != TXDUMMY) { | ||
| 69 | printk(KERN_DEBUG | ||
| 70 | "jornada720_kbd: " | ||
| 71 | "GetKeycode command failed with ETIMEDOUT, " | ||
| 72 | "flushed bus\n"); | ||
| 73 | } else { | ||
| 74 | /* How many keycodes are waiting for us? */ | ||
| 75 | count = jornada_ssp_byte(TXDUMMY); | ||
| 76 | |||
| 77 | /* Lets drag them out one at a time */ | ||
| 78 | while (count--) { | ||
| 79 | /* Exchange TxDummy for location (keymap[kbddata]) */ | ||
| 80 | kbd_data = jornada_ssp_byte(TXDUMMY); | ||
| 81 | scan_code = kbd_data & 0x7f; | ||
| 82 | |||
| 83 | input_event(input, EV_MSC, MSC_SCAN, scan_code); | ||
| 84 | input_report_key(input, jornadakbd->keymap[scan_code], | ||
| 85 | !(kbd_data & 0x80)); | ||
| 86 | input_sync(input); | ||
| 87 | } | ||
| 88 | } | ||
| 89 | |||
| 90 | /* release spinlock and turn off ssp */ | ||
| 91 | jornada_ssp_end(); | ||
| 92 | |||
| 93 | return IRQ_HANDLED; | ||
| 94 | }; | ||
| 95 | |||
| 96 | static int __devinit jornada720_kbd_probe(struct platform_device *pdev) | ||
| 97 | { | ||
| 98 | struct jornadakbd *jornadakbd; | ||
| 99 | struct input_dev *input_dev; | ||
| 100 | int i, err; | ||
| 101 | |||
| 102 | jornadakbd = kzalloc(sizeof(struct jornadakbd), GFP_KERNEL); | ||
| 103 | input_dev = input_allocate_device(); | ||
| 104 | if (!jornadakbd || !input_dev) { | ||
| 105 | err = -ENOMEM; | ||
| 106 | goto fail1; | ||
| 107 | } | ||
| 108 | |||
| 109 | platform_set_drvdata(pdev, jornadakbd); | ||
| 110 | |||
| 111 | memcpy(jornadakbd->keymap, jornada_std_keymap, | ||
| 112 | sizeof(jornada_std_keymap)); | ||
| 113 | jornadakbd->input = input_dev; | ||
| 114 | |||
| 115 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | ||
| 116 | input_dev->name = "HP Jornada 720 keyboard"; | ||
| 117 | input_dev->phys = "jornadakbd/input0"; | ||
| 118 | input_dev->keycode = jornadakbd->keymap; | ||
| 119 | input_dev->keycodesize = sizeof(unsigned short); | ||
| 120 | input_dev->keycodemax = ARRAY_SIZE(jornada_std_keymap); | ||
| 121 | input_dev->id.bustype = BUS_HOST; | ||
| 122 | input_dev->dev.parent = &pdev->dev; | ||
| 123 | |||
| 124 | for (i = 0; i < ARRAY_SIZE(jornadakbd->keymap); i++) | ||
| 125 | __set_bit(jornadakbd->keymap[i], input_dev->keybit); | ||
| 126 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
| 127 | |||
| 128 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | ||
| 129 | |||
| 130 | err = request_irq(IRQ_GPIO0, | ||
| 131 | jornada720_kbd_interrupt, | ||
| 132 | IRQF_DISABLED | IRQF_TRIGGER_FALLING, | ||
| 133 | "jornadakbd", pdev); | ||
| 134 | if (err) { | ||
| 135 | printk(KERN_INFO "jornadakbd720_kbd: Unable to grab IRQ\n"); | ||
| 136 | goto fail1; | ||
| 137 | } | ||
| 138 | |||
| 139 | err = input_register_device(jornadakbd->input); | ||
| 140 | if (err) | ||
| 141 | goto fail2; | ||
| 142 | |||
| 143 | return 0; | ||
| 144 | |||
| 145 | fail2: /* IRQ, DEVICE, MEMORY */ | ||
| 146 | free_irq(IRQ_GPIO0, pdev); | ||
| 147 | fail1: /* DEVICE, MEMORY */ | ||
| 148 | platform_set_drvdata(pdev, NULL); | ||
| 149 | input_free_device(input_dev); | ||
| 150 | kfree(jornadakbd); | ||
| 151 | return err; | ||
| 152 | }; | ||
| 153 | |||
| 154 | static int __devexit jornada720_kbd_remove(struct platform_device *pdev) | ||
| 155 | { | ||
| 156 | struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); | ||
| 157 | |||
| 158 | free_irq(IRQ_GPIO0, pdev); | ||
| 159 | platform_set_drvdata(pdev, NULL); | ||
| 160 | input_unregister_device(jornadakbd->input); | ||
| 161 | kfree(jornadakbd); | ||
| 162 | |||
| 163 | return 0; | ||
| 164 | } | ||
| 165 | |||
| 166 | static struct platform_driver jornada720_kbd_driver = { | ||
| 167 | .driver = { | ||
| 168 | .name = "jornada720_kbd", | ||
| 169 | }, | ||
| 170 | .probe = jornada720_kbd_probe, | ||
| 171 | .remove = __devexit_p(jornada720_kbd_remove), | ||
| 172 | }; | ||
| 173 | |||
| 174 | static int __init jornada720_kbd_init(void) | ||
| 175 | { | ||
| 176 | return platform_driver_register(&jornada720_kbd_driver); | ||
| 177 | } | ||
| 178 | |||
| 179 | static void __exit jornada720_kbd_exit(void) | ||
| 180 | { | ||
| 181 | platform_driver_unregister(&jornada720_kbd_driver); | ||
| 182 | } | ||
| 183 | |||
| 184 | module_init(jornada720_kbd_init); | ||
| 185 | module_exit(jornada720_kbd_exit); | ||
diff --git a/drivers/input/keyboard/maple_keyb.c b/drivers/input/keyboard/maple_keyb.c new file mode 100644 index 000000000000..2b404284c28a --- /dev/null +++ b/drivers/input/keyboard/maple_keyb.c | |||
| @@ -0,0 +1,252 @@ | |||
| 1 | /* | ||
| 2 | * SEGA Dreamcast keyboard driver | ||
| 3 | * Based on drivers/usb/usbkbd.c | ||
| 4 | * Copyright YAEGASHI Takeshi, 2001 | ||
| 5 | * Porting to 2.6 Copyright Adrian McMenamin, 2007 | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, see the file COPYING, or write | ||
| 19 | * to the Free Software Foundation, Inc., | ||
| 20 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/kernel.h> | ||
| 24 | #include <linux/slab.h> | ||
| 25 | #include <linux/input.h> | ||
| 26 | #include <linux/module.h> | ||
| 27 | #include <linux/init.h> | ||
| 28 | #include <linux/timer.h> | ||
| 29 | #include <linux/maple.h> | ||
| 30 | #include <asm/mach/maple.h> | ||
| 31 | |||
| 32 | /* Very simple mutex to ensure proper cleanup */ | ||
| 33 | static DEFINE_MUTEX(maple_keyb_mutex); | ||
| 34 | |||
| 35 | #define NR_SCANCODES 256 | ||
| 36 | |||
| 37 | MODULE_AUTHOR("YAEGASHI Takeshi, Adrian McMenamin"); | ||
| 38 | MODULE_DESCRIPTION("SEGA Dreamcast keyboard driver"); | ||
| 39 | MODULE_LICENSE("GPL"); | ||
| 40 | |||
| 41 | struct dc_kbd { | ||
| 42 | struct input_dev *dev; | ||
| 43 | unsigned short keycode[NR_SCANCODES]; | ||
| 44 | unsigned char new[8]; | ||
| 45 | unsigned char old[8]; | ||
| 46 | }; | ||
| 47 | |||
| 48 | static const unsigned short dc_kbd_keycode[NR_SCANCODES] = { | ||
| 49 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_A, KEY_B, KEY_C, KEY_D, | ||
| 50 | KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, KEY_L, | ||
| 51 | KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, | ||
| 52 | KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z, KEY_1, KEY_2, | ||
| 53 | KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0, | ||
| 54 | KEY_ENTER, KEY_ESC, KEY_BACKSPACE, KEY_TAB, KEY_SPACE, KEY_MINUS, KEY_EQUAL, KEY_LEFTBRACE, | ||
| 55 | KEY_RIGHTBRACE, KEY_BACKSLASH, KEY_BACKSLASH, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_GRAVE, KEY_COMMA, | ||
| 56 | KEY_DOT, KEY_SLASH, KEY_CAPSLOCK, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, | ||
| 57 | KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, KEY_SYSRQ, | ||
| 58 | KEY_SCROLLLOCK, KEY_PAUSE, KEY_INSERT, KEY_HOME, KEY_PAGEUP, KEY_DELETE, | ||
| 59 | KEY_END, KEY_PAGEDOWN, KEY_RIGHT, KEY_LEFT, KEY_DOWN, KEY_UP, | ||
| 60 | KEY_NUMLOCK, KEY_KPSLASH, KEY_KPASTERISK, KEY_KPMINUS, KEY_KPPLUS, KEY_KPENTER, KEY_KP1, KEY_KP2, | ||
| 61 | KEY_KP3, KEY_KP4, KEY_KP5, KEY_KP6, KEY_KP7, KEY_KP8, KEY_KP9, KEY_KP0, KEY_KPDOT, | ||
| 62 | KEY_102ND, KEY_COMPOSE, KEY_POWER, KEY_KPEQUAL, KEY_F13, KEY_F14, KEY_F15, | ||
| 63 | KEY_F16, KEY_F17, KEY_F18, KEY_F19, KEY_F20, | ||
| 64 | KEY_F21, KEY_F22, KEY_F23, KEY_F24, KEY_OPEN, KEY_HELP, KEY_PROPS, KEY_FRONT, | ||
| 65 | KEY_STOP, KEY_AGAIN, KEY_UNDO, KEY_CUT, KEY_COPY, KEY_PASTE, KEY_FIND, KEY_MUTE, | ||
| 66 | KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_KPCOMMA, KEY_RESERVED, KEY_RO, KEY_KATAKANAHIRAGANA , KEY_YEN, | ||
| 67 | KEY_HENKAN, KEY_MUHENKAN, KEY_KPJPCOMMA, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
| 68 | KEY_HANGEUL, KEY_HANJA, KEY_KATAKANA, KEY_HIRAGANA, KEY_ZENKAKUHANKAKU, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
| 69 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
| 70 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
| 71 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
| 72 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
| 73 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
| 74 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
| 75 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
| 76 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
| 77 | KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, | ||
| 78 | KEY_LEFTCTRL, KEY_LEFTSHIFT, KEY_LEFTALT, KEY_LEFTMETA, KEY_RIGHTCTRL, KEY_RIGHTSHIFT, KEY_RIGHTALT, KEY_RIGHTMETA, | ||
| 79 | KEY_PLAYPAUSE, KEY_STOPCD, KEY_PREVIOUSSONG, KEY_NEXTSONG, KEY_EJECTCD, KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_MUTE, | ||
| 80 | KEY_WWW, KEY_BACK, KEY_FORWARD, KEY_STOP, KEY_FIND, KEY_SCROLLUP, KEY_SCROLLDOWN, KEY_EDIT, KEY_SLEEP, | ||
| 81 | KEY_SCREENLOCK, KEY_REFRESH, KEY_CALC, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED | ||
| 82 | }; | ||
| 83 | |||
| 84 | static void dc_scan_kbd(struct dc_kbd *kbd) | ||
| 85 | { | ||
| 86 | struct input_dev *dev = kbd->dev; | ||
| 87 | void *ptr; | ||
| 88 | int code, keycode; | ||
| 89 | int i; | ||
| 90 | |||
| 91 | for (i = 0; i < 8; i++) { | ||
| 92 | code = i + 224; | ||
| 93 | keycode = kbd->keycode[code]; | ||
| 94 | input_event(dev, EV_MSC, MSC_SCAN, code); | ||
| 95 | input_report_key(dev, keycode, (kbd->new[0] >> i) & 1); | ||
| 96 | } | ||
| 97 | |||
| 98 | for (i = 2; i < 8; i++) { | ||
| 99 | ptr = memchr(kbd->new + 2, kbd->old[i], 6); | ||
| 100 | code = kbd->old[i]; | ||
| 101 | if (code > 3 && ptr == NULL) { | ||
| 102 | keycode = kbd->keycode[code]; | ||
| 103 | if (keycode) { | ||
| 104 | input_event(dev, EV_MSC, MSC_SCAN, code); | ||
| 105 | input_report_key(dev, keycode, 0); | ||
| 106 | } else | ||
| 107 | printk(KERN_DEBUG "maple_keyb: " | ||
| 108 | "Unknown key (scancode %#x) released.", | ||
| 109 | code); | ||
| 110 | } | ||
| 111 | ptr = memchr(kbd->old + 2, kbd->new[i], 6); | ||
| 112 | code = kbd->new[i]; | ||
| 113 | if (code > 3 && ptr) { | ||
| 114 | keycode = kbd->keycode[code]; | ||
| 115 | if (keycode) { | ||
| 116 | input_event(dev, EV_MSC, MSC_SCAN, code); | ||
| 117 | input_report_key(dev, keycode, 1); | ||
| 118 | } else | ||
| 119 | printk(KERN_DEBUG "maple_keyb: " | ||
| 120 | "Unknown key (scancode %#x) pressed.", | ||
| 121 | code); | ||
| 122 | } | ||
| 123 | } | ||
| 124 | input_sync(dev); | ||
| 125 | memcpy(kbd->old, kbd->new, 8); | ||
| 126 | } | ||
| 127 | |||
| 128 | static void dc_kbd_callback(struct mapleq *mq) | ||
| 129 | { | ||
| 130 | struct maple_device *mapledev = mq->dev; | ||
| 131 | struct dc_kbd *kbd = mapledev->private_data; | ||
| 132 | unsigned long *buf = mq->recvbuf; | ||
| 133 | |||
| 134 | /* | ||
| 135 | * We should always be getting the lock because the only | ||
| 136 | * time it may be locked if driver is in cleanup phase. | ||
| 137 | */ | ||
| 138 | if (likely(mutex_trylock(&maple_keyb_mutex))) { | ||
| 139 | |||
| 140 | if (buf[1] == mapledev->function) { | ||
| 141 | memcpy(kbd->new, buf + 2, 8); | ||
| 142 | dc_scan_kbd(kbd); | ||
| 143 | } | ||
| 144 | |||
| 145 | mutex_unlock(&maple_keyb_mutex); | ||
| 146 | } | ||
| 147 | } | ||
| 148 | |||
| 149 | static int dc_kbd_connect(struct maple_device *mdev) | ||
| 150 | { | ||
| 151 | int i, error; | ||
| 152 | struct dc_kbd *kbd; | ||
| 153 | struct input_dev *dev; | ||
| 154 | |||
| 155 | if (!(mdev->function & MAPLE_FUNC_KEYBOARD)) | ||
| 156 | return -EINVAL; | ||
| 157 | |||
| 158 | kbd = kzalloc(sizeof(struct dc_kbd), GFP_KERNEL); | ||
| 159 | dev = input_allocate_device(); | ||
| 160 | if (!kbd || !dev) { | ||
| 161 | error = -ENOMEM; | ||
| 162 | goto fail; | ||
| 163 | } | ||
| 164 | |||
| 165 | mdev->private_data = kbd; | ||
| 166 | |||
| 167 | kbd->dev = dev; | ||
| 168 | memcpy(kbd->keycode, dc_kbd_keycode, sizeof(kbd->keycode)); | ||
| 169 | |||
| 170 | dev->name = mdev->product_name; | ||
| 171 | dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | ||
| 172 | dev->keycode = kbd->keycode; | ||
| 173 | dev->keycodesize = sizeof (unsigned short); | ||
| 174 | dev->keycodemax = ARRAY_SIZE(kbd->keycode); | ||
| 175 | dev->id.bustype = BUS_HOST; | ||
| 176 | dev->dev.parent = &mdev->dev; | ||
| 177 | |||
| 178 | for (i = 0; i < NR_SCANCODES; i++) | ||
| 179 | __set_bit(dc_kbd_keycode[i], dev->keybit); | ||
| 180 | __clear_bit(KEY_RESERVED, dev->keybit); | ||
| 181 | |||
| 182 | input_set_capability(dev, EV_MSC, MSC_SCAN); | ||
| 183 | input_set_drvdata(dev, kbd); | ||
| 184 | |||
| 185 | error = input_register_device(dev); | ||
| 186 | if (error) | ||
| 187 | goto fail; | ||
| 188 | |||
| 189 | /* Maple polling is locked to VBLANK - which may be just 50/s */ | ||
| 190 | maple_getcond_callback(mdev, dc_kbd_callback, HZ/50, MAPLE_FUNC_KEYBOARD); | ||
| 191 | return 0; | ||
| 192 | |||
| 193 | fail: | ||
| 194 | input_free_device(dev); | ||
| 195 | kfree(kbd); | ||
| 196 | mdev->private_data = NULL; | ||
| 197 | return error; | ||
| 198 | } | ||
| 199 | |||
| 200 | static void dc_kbd_disconnect(struct maple_device *mdev) | ||
| 201 | { | ||
| 202 | struct dc_kbd *kbd; | ||
| 203 | |||
| 204 | mutex_lock(&maple_keyb_mutex); | ||
| 205 | |||
| 206 | kbd = mdev->private_data; | ||
| 207 | mdev->private_data = NULL; | ||
| 208 | input_unregister_device(kbd->dev); | ||
| 209 | kfree(kbd); | ||
| 210 | |||
| 211 | mutex_unlock(&maple_keyb_mutex); | ||
| 212 | } | ||
| 213 | |||
| 214 | /* allow the keyboard to be used */ | ||
| 215 | static int probe_maple_kbd(struct device *dev) | ||
| 216 | { | ||
| 217 | struct maple_device *mdev = to_maple_dev(dev); | ||
| 218 | struct maple_driver *mdrv = to_maple_driver(dev->driver); | ||
| 219 | int error; | ||
| 220 | |||
| 221 | error = dc_kbd_connect(mdev); | ||
| 222 | if (error) | ||
| 223 | return error; | ||
| 224 | |||
| 225 | mdev->driver = mdrv; | ||
| 226 | mdev->registered = 1; | ||
| 227 | |||
| 228 | return 0; | ||
| 229 | } | ||
| 230 | |||
| 231 | static struct maple_driver dc_kbd_driver = { | ||
| 232 | .function = MAPLE_FUNC_KEYBOARD, | ||
| 233 | .connect = dc_kbd_connect, | ||
| 234 | .disconnect = dc_kbd_disconnect, | ||
| 235 | .drv = { | ||
| 236 | .name = "Dreamcast_keyboard", | ||
| 237 | .probe = probe_maple_kbd, | ||
| 238 | }, | ||
| 239 | }; | ||
| 240 | |||
| 241 | static int __init dc_kbd_init(void) | ||
| 242 | { | ||
| 243 | return maple_driver_register(&dc_kbd_driver.drv); | ||
| 244 | } | ||
| 245 | |||
| 246 | static void __exit dc_kbd_exit(void) | ||
| 247 | { | ||
| 248 | driver_unregister(&dc_kbd_driver.drv); | ||
| 249 | } | ||
| 250 | |||
| 251 | module_init(dc_kbd_init); | ||
| 252 | module_exit(dc_kbd_exit); | ||
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index 3a228634f101..76f1969552c5 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c | |||
| @@ -233,7 +233,7 @@ static void omap_kp_tasklet(unsigned long data) | |||
| 233 | omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); | 233 | omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); |
| 234 | kp_cur_group = -1; | 234 | kp_cur_group = -1; |
| 235 | } | 235 | } |
| 236 | } | 236 | } |
| 237 | } | 237 | } |
| 238 | 238 | ||
| 239 | static ssize_t omap_kp_enable_show(struct device *dev, | 239 | static ssize_t omap_kp_enable_show(struct device *dev, |
| @@ -318,7 +318,7 @@ static int __init omap_kp_probe(struct platform_device *pdev) | |||
| 318 | keymap = pdata->keymap; | 318 | keymap = pdata->keymap; |
| 319 | 319 | ||
| 320 | if (pdata->rep) | 320 | if (pdata->rep) |
| 321 | set_bit(EV_REP, input_dev->evbit); | 321 | __set_bit(EV_REP, input_dev->evbit); |
| 322 | 322 | ||
| 323 | if (pdata->delay) | 323 | if (pdata->delay) |
| 324 | omap_kp->delay = pdata->delay; | 324 | omap_kp->delay = pdata->delay; |
| @@ -365,9 +365,9 @@ static int __init omap_kp_probe(struct platform_device *pdev) | |||
| 365 | goto err2; | 365 | goto err2; |
| 366 | 366 | ||
| 367 | /* setup input device */ | 367 | /* setup input device */ |
| 368 | set_bit(EV_KEY, input_dev->evbit); | 368 | __set_bit(EV_KEY, input_dev->evbit); |
| 369 | for (i = 0; keymap[i] != 0; i++) | 369 | for (i = 0; keymap[i] != 0; i++) |
| 370 | set_bit(keymap[i] & KEY_MAX, input_dev->keybit); | 370 | __set_bit(keymap[i] & KEY_MAX, input_dev->keybit); |
| 371 | input_dev->name = "omap-keypad"; | 371 | input_dev->name = "omap-keypad"; |
| 372 | input_dev->phys = "omap-keypad/input0"; | 372 | input_dev->phys = "omap-keypad/input0"; |
| 373 | input_dev->dev.parent = &pdev->dev; | 373 | input_dev->dev.parent = &pdev->dev; |
| @@ -377,10 +377,6 @@ static int __init omap_kp_probe(struct platform_device *pdev) | |||
| 377 | input_dev->id.product = 0x0001; | 377 | input_dev->id.product = 0x0001; |
| 378 | input_dev->id.version = 0x0100; | 378 | input_dev->id.version = 0x0100; |
| 379 | 379 | ||
| 380 | input_dev->keycode = keymap; | ||
| 381 | input_dev->keycodesize = sizeof(unsigned int); | ||
| 382 | input_dev->keycodemax = pdata->keymapsize; | ||
| 383 | |||
| 384 | ret = input_register_device(omap_kp->input); | 380 | ret = input_register_device(omap_kp->input); |
| 385 | if (ret < 0) { | 381 | if (ret < 0) { |
| 386 | printk(KERN_ERR "Unable to register omap-keypad input device\n"); | 382 | printk(KERN_ERR "Unable to register omap-keypad input device\n"); |
| @@ -403,15 +399,15 @@ static int __init omap_kp_probe(struct platform_device *pdev) | |||
| 403 | } else { | 399 | } else { |
| 404 | for (irq_idx = 0; irq_idx < omap_kp->rows; irq_idx++) { | 400 | for (irq_idx = 0; irq_idx < omap_kp->rows; irq_idx++) { |
| 405 | if (request_irq(OMAP_GPIO_IRQ(row_gpios[irq_idx]), | 401 | if (request_irq(OMAP_GPIO_IRQ(row_gpios[irq_idx]), |
| 406 | omap_kp_interrupt, | 402 | omap_kp_interrupt, |
| 407 | IRQF_TRIGGER_FALLING, | 403 | IRQF_TRIGGER_FALLING, |
| 408 | "omap-keypad", omap_kp) < 0) | 404 | "omap-keypad", omap_kp) < 0) |
| 409 | goto err5; | 405 | goto err5; |
| 410 | } | 406 | } |
| 411 | } | 407 | } |
| 412 | return 0; | 408 | return 0; |
| 413 | err5: | 409 | err5: |
| 414 | for (i = irq_idx-1; i >=0; i--) | 410 | for (i = irq_idx - 1; i >=0; i--) |
| 415 | free_irq(row_gpios[i], 0); | 411 | free_irq(row_gpios[i], 0); |
| 416 | err4: | 412 | err4: |
| 417 | input_unregister_device(omap_kp->input); | 413 | input_unregister_device(omap_kp->input); |
| @@ -440,9 +436,9 @@ static int omap_kp_remove(struct platform_device *pdev) | |||
| 440 | if (cpu_is_omap24xx()) { | 436 | if (cpu_is_omap24xx()) { |
| 441 | int i; | 437 | int i; |
| 442 | for (i = 0; i < omap_kp->cols; i++) | 438 | for (i = 0; i < omap_kp->cols; i++) |
| 443 | omap_free_gpio(col_gpios[i]); | 439 | omap_free_gpio(col_gpios[i]); |
| 444 | for (i = 0; i < omap_kp->rows; i++) { | 440 | for (i = 0; i < omap_kp->rows; i++) { |
| 445 | omap_free_gpio(row_gpios[i]); | 441 | omap_free_gpio(row_gpios[i]); |
| 446 | free_irq(OMAP_GPIO_IRQ(row_gpios[i]), 0); | 442 | free_irq(OMAP_GPIO_IRQ(row_gpios[i]), 0); |
| 447 | } | 443 | } |
| 448 | } else { | 444 | } else { |
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 2c5f11a4f6b4..64d70a9b714c 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
| @@ -48,11 +48,13 @@ static const struct alps_model_info alps_model_data[] = { | |||
| 48 | { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ | 48 | { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ |
| 49 | { { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, | 49 | { { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, |
| 50 | { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS }, /* Dell Latitude D800 */ | 50 | { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS }, /* Dell Latitude D800 */ |
| 51 | { { 0x73, 0x00, 0x0a }, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ | ||
| 51 | { { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, | 52 | { { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, |
| 52 | { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ | 53 | { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ |
| 53 | { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ | 54 | { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ |
| 54 | { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, | 55 | { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, |
| 55 | { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ | 56 | { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ |
| 57 | { { 0x73, 0x02, 0x50 }, 0xcf, 0xff, ALPS_FW_BK_1 } /* Dell Vostro 1400 */ | ||
| 56 | }; | 58 | }; |
| 57 | 59 | ||
| 58 | /* | 60 | /* |
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index a1804bfdbb8c..0117817bf538 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c | |||
| @@ -502,18 +502,23 @@ static void atp_complete(struct urb* urb) | |||
| 502 | 502 | ||
| 503 | /* reset the accumulator on release */ | 503 | /* reset the accumulator on release */ |
| 504 | memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); | 504 | memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); |
| 505 | } | ||
| 506 | |||
| 507 | /* Geyser 3 will continue to send packets continually after | ||
| 508 | the first touch unless reinitialised. Do so if it's been | ||
| 509 | idle for a while in order to avoid waking the kernel up | ||
| 510 | several hundred times a second */ | ||
| 505 | 511 | ||
| 506 | /* Geyser 3 will continue to send packets continually after | 512 | if (atp_is_geyser_3(dev)) { |
| 507 | the first touch unless reinitialised. Do so if it's been | 513 | if (!x && !y && !key) { |
| 508 | idle for a while in order to avoid waking the kernel up | ||
| 509 | several hundred times a second */ | ||
| 510 | if (!key && atp_is_geyser_3(dev)) { | ||
| 511 | dev->idlecount++; | 514 | dev->idlecount++; |
| 512 | if (dev->idlecount == 10) { | 515 | if (dev->idlecount == 10) { |
| 513 | dev->valid = 0; | 516 | dev->valid = 0; |
| 514 | schedule_work(&dev->work); | 517 | schedule_work(&dev->work); |
| 515 | } | 518 | } |
| 516 | } | 519 | } |
| 520 | else | ||
| 521 | dev->idlecount = 0; | ||
| 517 | } | 522 | } |
| 518 | 523 | ||
| 519 | input_report_key(dev->input, BTN_LEFT, key); | 524 | input_report_key(dev->input, BTN_LEFT, key); |
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index 608674d0be8b..d7de4c53b3d8 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c | |||
| @@ -97,6 +97,14 @@ static const struct dmi_system_id lifebook_dmi_table[] = { | |||
| 97 | .callback = lifebook_set_6byte_proto, | 97 | .callback = lifebook_set_6byte_proto, |
| 98 | }, | 98 | }, |
| 99 | { | 99 | { |
| 100 | .ident = "CF-72", | ||
| 101 | .matches = { | ||
| 102 | DMI_MATCH(DMI_PRODUCT_NAME, "CF-72"), | ||
| 103 | }, | ||
| 104 | .callback = lifebook_set_serio_phys, | ||
| 105 | .driver_data = "isa0060/serio3", | ||
| 106 | }, | ||
| 107 | { | ||
| 100 | .ident = "Lifebook B142", | 108 | .ident = "Lifebook B142", |
| 101 | .matches = { | 109 | .matches = { |
| 102 | DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"), | 110 | DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"), |
| @@ -282,7 +290,7 @@ static int lifebook_create_relative_device(struct psmouse *psmouse) | |||
| 282 | int lifebook_init(struct psmouse *psmouse) | 290 | int lifebook_init(struct psmouse *psmouse) |
| 283 | { | 291 | { |
| 284 | struct input_dev *dev1 = psmouse->dev; | 292 | struct input_dev *dev1 = psmouse->dev; |
| 285 | int max_coord = lifebook_use_6byte_proto ? 1024 : 4096; | 293 | int max_coord = lifebook_use_6byte_proto ? 4096 : 1024; |
| 286 | 294 | ||
| 287 | if (lifebook_absolute_mode(psmouse)) | 295 | if (lifebook_absolute_mode(psmouse)) |
| 288 | return -1; | 296 | return -1; |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index b9f0fb2530e2..073525756532 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
| @@ -648,9 +648,10 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
| 648 | 648 | ||
| 649 | /* | 649 | /* |
| 650 | * Reset to defaults in case the device got confused by extended | 650 | * Reset to defaults in case the device got confused by extended |
| 651 | * protocol probes. Note that we do full reset becuase some mice | 651 | * protocol probes. Note that we follow up with full reset because |
| 652 | * put themselves to sleep when see PSMOUSE_RESET_DIS. | 652 | * some mice put themselves to sleep when they see PSMOUSE_RESET_DIS. |
| 653 | */ | 653 | */ |
| 654 | ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS); | ||
| 654 | psmouse_reset(psmouse); | 655 | psmouse_reset(psmouse); |
| 655 | 656 | ||
| 656 | if (max_proto >= PSMOUSE_IMEX && im_explorer_detect(psmouse, set_properties) == 0) | 657 | if (max_proto >= PSMOUSE_IMEX && im_explorer_detect(psmouse, set_properties) == 0) |
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 9173916b8be5..79146d6ed2ab 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c | |||
| @@ -61,9 +61,11 @@ struct mousedev { | |||
| 61 | int open; | 61 | int open; |
| 62 | int minor; | 62 | int minor; |
| 63 | char name[16]; | 63 | char name[16]; |
| 64 | struct input_handle handle; | ||
| 64 | wait_queue_head_t wait; | 65 | wait_queue_head_t wait; |
| 65 | struct list_head client_list; | 66 | struct list_head client_list; |
| 66 | struct input_handle handle; | 67 | spinlock_t client_lock; /* protects client_list */ |
| 68 | struct mutex mutex; | ||
| 67 | struct device dev; | 69 | struct device dev; |
| 68 | 70 | ||
| 69 | struct list_head mixdev_node; | 71 | struct list_head mixdev_node; |
| @@ -113,108 +115,137 @@ static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 }; | |||
| 113 | static struct input_handler mousedev_handler; | 115 | static struct input_handler mousedev_handler; |
| 114 | 116 | ||
| 115 | static struct mousedev *mousedev_table[MOUSEDEV_MINORS]; | 117 | static struct mousedev *mousedev_table[MOUSEDEV_MINORS]; |
| 118 | static DEFINE_MUTEX(mousedev_table_mutex); | ||
| 116 | static struct mousedev *mousedev_mix; | 119 | static struct mousedev *mousedev_mix; |
| 117 | static LIST_HEAD(mousedev_mix_list); | 120 | static LIST_HEAD(mousedev_mix_list); |
| 118 | 121 | ||
| 122 | static void mixdev_open_devices(void); | ||
| 123 | static void mixdev_close_devices(void); | ||
| 124 | |||
| 119 | #define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03]) | 125 | #define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03]) |
| 120 | #define fy(i) (mousedev->old_y[(mousedev->pkt_count - (i)) & 03]) | 126 | #define fy(i) (mousedev->old_y[(mousedev->pkt_count - (i)) & 03]) |
| 121 | 127 | ||
| 122 | static void mousedev_touchpad_event(struct input_dev *dev, struct mousedev *mousedev, unsigned int code, int value) | 128 | static void mousedev_touchpad_event(struct input_dev *dev, |
| 129 | struct mousedev *mousedev, | ||
| 130 | unsigned int code, int value) | ||
| 123 | { | 131 | { |
| 124 | int size, tmp; | 132 | int size, tmp; |
| 125 | enum { FRACTION_DENOM = 128 }; | 133 | enum { FRACTION_DENOM = 128 }; |
| 126 | 134 | ||
| 127 | switch (code) { | 135 | switch (code) { |
| 128 | case ABS_X: | ||
| 129 | fx(0) = value; | ||
| 130 | if (mousedev->touch && mousedev->pkt_count >= 2) { | ||
| 131 | size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; | ||
| 132 | if (size == 0) | ||
| 133 | size = 256 * 2; | ||
| 134 | tmp = ((value - fx(2)) * (256 * FRACTION_DENOM)) / size; | ||
| 135 | tmp += mousedev->frac_dx; | ||
| 136 | mousedev->packet.dx = tmp / FRACTION_DENOM; | ||
| 137 | mousedev->frac_dx = tmp - mousedev->packet.dx * FRACTION_DENOM; | ||
| 138 | } | ||
| 139 | break; | ||
| 140 | 136 | ||
| 141 | case ABS_Y: | 137 | case ABS_X: |
| 142 | fy(0) = value; | 138 | fx(0) = value; |
| 143 | if (mousedev->touch && mousedev->pkt_count >= 2) { | 139 | if (mousedev->touch && mousedev->pkt_count >= 2) { |
| 144 | /* use X size to keep the same scale */ | 140 | size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; |
| 145 | size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; | 141 | if (size == 0) |
| 146 | if (size == 0) | 142 | size = 256 * 2; |
| 147 | size = 256 * 2; | 143 | tmp = ((value - fx(2)) * 256 * FRACTION_DENOM) / size; |
| 148 | tmp = -((value - fy(2)) * (256 * FRACTION_DENOM)) / size; | 144 | tmp += mousedev->frac_dx; |
| 149 | tmp += mousedev->frac_dy; | 145 | mousedev->packet.dx = tmp / FRACTION_DENOM; |
| 150 | mousedev->packet.dy = tmp / FRACTION_DENOM; | 146 | mousedev->frac_dx = |
| 151 | mousedev->frac_dy = tmp - mousedev->packet.dy * FRACTION_DENOM; | 147 | tmp - mousedev->packet.dx * FRACTION_DENOM; |
| 152 | } | 148 | } |
| 153 | break; | 149 | break; |
| 150 | |||
| 151 | case ABS_Y: | ||
| 152 | fy(0) = value; | ||
| 153 | if (mousedev->touch && mousedev->pkt_count >= 2) { | ||
| 154 | /* use X size to keep the same scale */ | ||
| 155 | size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; | ||
| 156 | if (size == 0) | ||
| 157 | size = 256 * 2; | ||
| 158 | tmp = -((value - fy(2)) * 256 * FRACTION_DENOM) / size; | ||
| 159 | tmp += mousedev->frac_dy; | ||
| 160 | mousedev->packet.dy = tmp / FRACTION_DENOM; | ||
| 161 | mousedev->frac_dy = tmp - | ||
| 162 | mousedev->packet.dy * FRACTION_DENOM; | ||
| 163 | } | ||
| 164 | break; | ||
| 154 | } | 165 | } |
| 155 | } | 166 | } |
| 156 | 167 | ||
| 157 | static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev, unsigned int code, int value) | 168 | static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev, |
| 169 | unsigned int code, int value) | ||
| 158 | { | 170 | { |
| 159 | int size; | 171 | int size; |
| 160 | 172 | ||
| 161 | switch (code) { | 173 | switch (code) { |
| 162 | case ABS_X: | ||
| 163 | size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; | ||
| 164 | if (size == 0) | ||
| 165 | size = xres ? : 1; | ||
| 166 | if (value > dev->absmax[ABS_X]) | ||
| 167 | value = dev->absmax[ABS_X]; | ||
| 168 | if (value < dev->absmin[ABS_X]) | ||
| 169 | value = dev->absmin[ABS_X]; | ||
| 170 | mousedev->packet.x = ((value - dev->absmin[ABS_X]) * xres) / size; | ||
| 171 | mousedev->packet.abs_event = 1; | ||
| 172 | break; | ||
| 173 | 174 | ||
| 174 | case ABS_Y: | 175 | case ABS_X: |
| 175 | size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y]; | 176 | size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; |
| 176 | if (size == 0) | 177 | if (size == 0) |
| 177 | size = yres ? : 1; | 178 | size = xres ? : 1; |
| 178 | if (value > dev->absmax[ABS_Y]) | 179 | if (value > dev->absmax[ABS_X]) |
| 179 | value = dev->absmax[ABS_Y]; | 180 | value = dev->absmax[ABS_X]; |
| 180 | if (value < dev->absmin[ABS_Y]) | 181 | if (value < dev->absmin[ABS_X]) |
| 181 | value = dev->absmin[ABS_Y]; | 182 | value = dev->absmin[ABS_X]; |
| 182 | mousedev->packet.y = yres - ((value - dev->absmin[ABS_Y]) * yres) / size; | 183 | mousedev->packet.x = |
| 183 | mousedev->packet.abs_event = 1; | 184 | ((value - dev->absmin[ABS_X]) * xres) / size; |
| 184 | break; | 185 | mousedev->packet.abs_event = 1; |
| 186 | break; | ||
| 187 | |||
| 188 | case ABS_Y: | ||
| 189 | size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y]; | ||
| 190 | if (size == 0) | ||
| 191 | size = yres ? : 1; | ||
| 192 | if (value > dev->absmax[ABS_Y]) | ||
| 193 | value = dev->absmax[ABS_Y]; | ||
| 194 | if (value < dev->absmin[ABS_Y]) | ||
| 195 | value = dev->absmin[ABS_Y]; | ||
| 196 | mousedev->packet.y = yres - | ||
| 197 | ((value - dev->absmin[ABS_Y]) * yres) / size; | ||
| 198 | mousedev->packet.abs_event = 1; | ||
| 199 | break; | ||
| 185 | } | 200 | } |
| 186 | } | 201 | } |
| 187 | 202 | ||
| 188 | static void mousedev_rel_event(struct mousedev *mousedev, unsigned int code, int value) | 203 | static void mousedev_rel_event(struct mousedev *mousedev, |
| 204 | unsigned int code, int value) | ||
| 189 | { | 205 | { |
| 190 | switch (code) { | 206 | switch (code) { |
| 191 | case REL_X: mousedev->packet.dx += value; break; | 207 | case REL_X: |
| 192 | case REL_Y: mousedev->packet.dy -= value; break; | 208 | mousedev->packet.dx += value; |
| 193 | case REL_WHEEL: mousedev->packet.dz -= value; break; | 209 | break; |
| 210 | |||
| 211 | case REL_Y: | ||
| 212 | mousedev->packet.dy -= value; | ||
| 213 | break; | ||
| 214 | |||
| 215 | case REL_WHEEL: | ||
| 216 | mousedev->packet.dz -= value; | ||
| 217 | break; | ||
| 194 | } | 218 | } |
| 195 | } | 219 | } |
| 196 | 220 | ||
| 197 | static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int value) | 221 | static void mousedev_key_event(struct mousedev *mousedev, |
| 222 | unsigned int code, int value) | ||
| 198 | { | 223 | { |
| 199 | int index; | 224 | int index; |
| 200 | 225 | ||
| 201 | switch (code) { | 226 | switch (code) { |
| 202 | case BTN_TOUCH: | 227 | |
| 203 | case BTN_0: | 228 | case BTN_TOUCH: |
| 204 | case BTN_LEFT: index = 0; break; | 229 | case BTN_0: |
| 205 | case BTN_STYLUS: | 230 | case BTN_LEFT: index = 0; break; |
| 206 | case BTN_1: | 231 | |
| 207 | case BTN_RIGHT: index = 1; break; | 232 | case BTN_STYLUS: |
| 208 | case BTN_2: | 233 | case BTN_1: |
| 209 | case BTN_FORWARD: | 234 | case BTN_RIGHT: index = 1; break; |
| 210 | case BTN_STYLUS2: | 235 | |
| 211 | case BTN_MIDDLE: index = 2; break; | 236 | case BTN_2: |
| 212 | case BTN_3: | 237 | case BTN_FORWARD: |
| 213 | case BTN_BACK: | 238 | case BTN_STYLUS2: |
| 214 | case BTN_SIDE: index = 3; break; | 239 | case BTN_MIDDLE: index = 2; break; |
| 215 | case BTN_4: | 240 | |
| 216 | case BTN_EXTRA: index = 4; break; | 241 | case BTN_3: |
| 217 | default: return; | 242 | case BTN_BACK: |
| 243 | case BTN_SIDE: index = 3; break; | ||
| 244 | |||
| 245 | case BTN_4: | ||
| 246 | case BTN_EXTRA: index = 4; break; | ||
| 247 | |||
| 248 | default: return; | ||
| 218 | } | 249 | } |
| 219 | 250 | ||
| 220 | if (value) { | 251 | if (value) { |
| @@ -226,19 +257,23 @@ static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int | |||
| 226 | } | 257 | } |
| 227 | } | 258 | } |
| 228 | 259 | ||
| 229 | static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_hw_data *packet) | 260 | static void mousedev_notify_readers(struct mousedev *mousedev, |
| 261 | struct mousedev_hw_data *packet) | ||
| 230 | { | 262 | { |
| 231 | struct mousedev_client *client; | 263 | struct mousedev_client *client; |
| 232 | struct mousedev_motion *p; | 264 | struct mousedev_motion *p; |
| 233 | unsigned long flags; | 265 | unsigned int new_head; |
| 234 | int wake_readers = 0; | 266 | int wake_readers = 0; |
| 235 | 267 | ||
| 236 | list_for_each_entry(client, &mousedev->client_list, node) { | 268 | rcu_read_lock(); |
| 237 | spin_lock_irqsave(&client->packet_lock, flags); | 269 | list_for_each_entry_rcu(client, &mousedev->client_list, node) { |
| 270 | |||
| 271 | /* Just acquire the lock, interrupts already disabled */ | ||
| 272 | spin_lock(&client->packet_lock); | ||
| 238 | 273 | ||
| 239 | p = &client->packets[client->head]; | 274 | p = &client->packets[client->head]; |
| 240 | if (client->ready && p->buttons != mousedev->packet.buttons) { | 275 | if (client->ready && p->buttons != mousedev->packet.buttons) { |
| 241 | unsigned int new_head = (client->head + 1) % PACKET_QUEUE_LEN; | 276 | new_head = (client->head + 1) % PACKET_QUEUE_LEN; |
| 242 | if (new_head != client->tail) { | 277 | if (new_head != client->tail) { |
| 243 | p = &client->packets[client->head = new_head]; | 278 | p = &client->packets[client->head = new_head]; |
| 244 | memset(p, 0, sizeof(struct mousedev_motion)); | 279 | memset(p, 0, sizeof(struct mousedev_motion)); |
| @@ -253,25 +288,29 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h | |||
| 253 | } | 288 | } |
| 254 | 289 | ||
| 255 | client->pos_x += packet->dx; | 290 | client->pos_x += packet->dx; |
| 256 | client->pos_x = client->pos_x < 0 ? 0 : (client->pos_x >= xres ? xres : client->pos_x); | 291 | client->pos_x = client->pos_x < 0 ? |
| 292 | 0 : (client->pos_x >= xres ? xres : client->pos_x); | ||
| 257 | client->pos_y += packet->dy; | 293 | client->pos_y += packet->dy; |
| 258 | client->pos_y = client->pos_y < 0 ? 0 : (client->pos_y >= yres ? yres : client->pos_y); | 294 | client->pos_y = client->pos_y < 0 ? |
| 295 | 0 : (client->pos_y >= yres ? yres : client->pos_y); | ||
| 259 | 296 | ||
| 260 | p->dx += packet->dx; | 297 | p->dx += packet->dx; |
| 261 | p->dy += packet->dy; | 298 | p->dy += packet->dy; |
| 262 | p->dz += packet->dz; | 299 | p->dz += packet->dz; |
| 263 | p->buttons = mousedev->packet.buttons; | 300 | p->buttons = mousedev->packet.buttons; |
| 264 | 301 | ||
| 265 | if (p->dx || p->dy || p->dz || p->buttons != client->last_buttons) | 302 | if (p->dx || p->dy || p->dz || |
| 303 | p->buttons != client->last_buttons) | ||
| 266 | client->ready = 1; | 304 | client->ready = 1; |
| 267 | 305 | ||
| 268 | spin_unlock_irqrestore(&client->packet_lock, flags); | 306 | spin_unlock(&client->packet_lock); |
| 269 | 307 | ||
| 270 | if (client->ready) { | 308 | if (client->ready) { |
| 271 | kill_fasync(&client->fasync, SIGIO, POLL_IN); | 309 | kill_fasync(&client->fasync, SIGIO, POLL_IN); |
| 272 | wake_readers = 1; | 310 | wake_readers = 1; |
| 273 | } | 311 | } |
| 274 | } | 312 | } |
| 313 | rcu_read_unlock(); | ||
| 275 | 314 | ||
| 276 | if (wake_readers) | 315 | if (wake_readers) |
| 277 | wake_up_interruptible(&mousedev->wait); | 316 | wake_up_interruptible(&mousedev->wait); |
| @@ -281,7 +320,8 @@ static void mousedev_touchpad_touch(struct mousedev *mousedev, int value) | |||
| 281 | { | 320 | { |
| 282 | if (!value) { | 321 | if (!value) { |
| 283 | if (mousedev->touch && | 322 | if (mousedev->touch && |
| 284 | time_before(jiffies, mousedev->touch + msecs_to_jiffies(tap_time))) { | 323 | time_before(jiffies, |
| 324 | mousedev->touch + msecs_to_jiffies(tap_time))) { | ||
| 285 | /* | 325 | /* |
| 286 | * Toggle left button to emulate tap. | 326 | * Toggle left button to emulate tap. |
| 287 | * We rely on the fact that mousedev_mix always has 0 | 327 | * We rely on the fact that mousedev_mix always has 0 |
| @@ -290,7 +330,8 @@ static void mousedev_touchpad_touch(struct mousedev *mousedev, int value) | |||
| 290 | set_bit(0, &mousedev->packet.buttons); | 330 | set_bit(0, &mousedev->packet.buttons); |
| 291 | set_bit(0, &mousedev_mix->packet.buttons); | 331 | set_bit(0, &mousedev_mix->packet.buttons); |
| 292 | mousedev_notify_readers(mousedev, &mousedev_mix->packet); | 332 | mousedev_notify_readers(mousedev, &mousedev_mix->packet); |
| 293 | mousedev_notify_readers(mousedev_mix, &mousedev_mix->packet); | 333 | mousedev_notify_readers(mousedev_mix, |
| 334 | &mousedev_mix->packet); | ||
| 294 | clear_bit(0, &mousedev->packet.buttons); | 335 | clear_bit(0, &mousedev->packet.buttons); |
| 295 | clear_bit(0, &mousedev_mix->packet.buttons); | 336 | clear_bit(0, &mousedev_mix->packet.buttons); |
| 296 | } | 337 | } |
| @@ -302,54 +343,61 @@ static void mousedev_touchpad_touch(struct mousedev *mousedev, int value) | |||
| 302 | mousedev->touch = jiffies; | 343 | mousedev->touch = jiffies; |
| 303 | } | 344 | } |
| 304 | 345 | ||
| 305 | static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) | 346 | static void mousedev_event(struct input_handle *handle, |
| 347 | unsigned int type, unsigned int code, int value) | ||
| 306 | { | 348 | { |
| 307 | struct mousedev *mousedev = handle->private; | 349 | struct mousedev *mousedev = handle->private; |
| 308 | 350 | ||
| 309 | switch (type) { | 351 | switch (type) { |
| 310 | case EV_ABS: | ||
| 311 | /* Ignore joysticks */ | ||
| 312 | if (test_bit(BTN_TRIGGER, handle->dev->keybit)) | ||
| 313 | return; | ||
| 314 | 352 | ||
| 315 | if (test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) | 353 | case EV_ABS: |
| 316 | mousedev_touchpad_event(handle->dev, mousedev, code, value); | 354 | /* Ignore joysticks */ |
| 317 | else | 355 | if (test_bit(BTN_TRIGGER, handle->dev->keybit)) |
| 318 | mousedev_abs_event(handle->dev, mousedev, code, value); | 356 | return; |
| 319 | 357 | ||
| 320 | break; | 358 | if (test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) |
| 359 | mousedev_touchpad_event(handle->dev, | ||
| 360 | mousedev, code, value); | ||
| 361 | else | ||
| 362 | mousedev_abs_event(handle->dev, mousedev, code, value); | ||
| 321 | 363 | ||
| 322 | case EV_REL: | 364 | break; |
| 323 | mousedev_rel_event(mousedev, code, value); | ||
| 324 | break; | ||
| 325 | 365 | ||
| 326 | case EV_KEY: | 366 | case EV_REL: |
| 327 | if (value != 2) { | 367 | mousedev_rel_event(mousedev, code, value); |
| 328 | if (code == BTN_TOUCH && test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) | 368 | break; |
| 329 | mousedev_touchpad_touch(mousedev, value); | ||
| 330 | else | ||
| 331 | mousedev_key_event(mousedev, code, value); | ||
| 332 | } | ||
| 333 | break; | ||
| 334 | 369 | ||
| 335 | case EV_SYN: | 370 | case EV_KEY: |
| 336 | if (code == SYN_REPORT) { | 371 | if (value != 2) { |
| 337 | if (mousedev->touch) { | 372 | if (code == BTN_TOUCH && |
| 338 | mousedev->pkt_count++; | 373 | test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) |
| 339 | /* Input system eats duplicate events, but we need all of them | 374 | mousedev_touchpad_touch(mousedev, value); |
| 340 | * to do correct averaging so apply present one forward | 375 | else |
| 341 | */ | 376 | mousedev_key_event(mousedev, code, value); |
| 342 | fx(0) = fx(1); | 377 | } |
| 343 | fy(0) = fy(1); | 378 | break; |
| 344 | } | 379 | |
| 345 | 380 | case EV_SYN: | |
| 346 | mousedev_notify_readers(mousedev, &mousedev->packet); | 381 | if (code == SYN_REPORT) { |
| 347 | mousedev_notify_readers(mousedev_mix, &mousedev->packet); | 382 | if (mousedev->touch) { |
| 348 | 383 | mousedev->pkt_count++; | |
| 349 | mousedev->packet.dx = mousedev->packet.dy = mousedev->packet.dz = 0; | 384 | /* |
| 350 | mousedev->packet.abs_event = 0; | 385 | * Input system eats duplicate events, |
| 386 | * but we need all of them to do correct | ||
| 387 | * averaging so apply present one forward | ||
| 388 | */ | ||
| 389 | fx(0) = fx(1); | ||
| 390 | fy(0) = fy(1); | ||
| 351 | } | 391 | } |
| 352 | break; | 392 | |
| 393 | mousedev_notify_readers(mousedev, &mousedev->packet); | ||
| 394 | mousedev_notify_readers(mousedev_mix, &mousedev->packet); | ||
| 395 | |||
| 396 | mousedev->packet.dx = mousedev->packet.dy = | ||
| 397 | mousedev->packet.dz = 0; | ||
| 398 | mousedev->packet.abs_event = 0; | ||
| 399 | } | ||
| 400 | break; | ||
| 353 | } | 401 | } |
| 354 | } | 402 | } |
| 355 | 403 | ||
| @@ -367,41 +415,48 @@ static void mousedev_free(struct device *dev) | |||
| 367 | { | 415 | { |
| 368 | struct mousedev *mousedev = container_of(dev, struct mousedev, dev); | 416 | struct mousedev *mousedev = container_of(dev, struct mousedev, dev); |
| 369 | 417 | ||
| 370 | mousedev_table[mousedev->minor] = NULL; | ||
| 371 | kfree(mousedev); | 418 | kfree(mousedev); |
| 372 | } | 419 | } |
| 373 | 420 | ||
| 374 | static int mixdev_add_device(struct mousedev *mousedev) | 421 | static int mousedev_open_device(struct mousedev *mousedev) |
| 375 | { | 422 | { |
| 376 | int error; | 423 | int retval; |
| 377 | 424 | ||
| 378 | if (mousedev_mix->open) { | 425 | retval = mutex_lock_interruptible(&mousedev->mutex); |
| 379 | error = input_open_device(&mousedev->handle); | 426 | if (retval) |
| 380 | if (error) | 427 | return retval; |
| 381 | return error; | ||
| 382 | 428 | ||
| 383 | mousedev->open++; | 429 | if (mousedev->minor == MOUSEDEV_MIX) |
| 384 | mousedev->mixdev_open = 1; | 430 | mixdev_open_devices(); |
| 431 | else if (!mousedev->exist) | ||
| 432 | retval = -ENODEV; | ||
| 433 | else if (!mousedev->open++) { | ||
| 434 | retval = input_open_device(&mousedev->handle); | ||
| 435 | if (retval) | ||
| 436 | mousedev->open--; | ||
| 385 | } | 437 | } |
| 386 | 438 | ||
| 387 | get_device(&mousedev->dev); | 439 | mutex_unlock(&mousedev->mutex); |
| 388 | list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list); | 440 | return retval; |
| 389 | |||
| 390 | return 0; | ||
| 391 | } | 441 | } |
| 392 | 442 | ||
| 393 | static void mixdev_remove_device(struct mousedev *mousedev) | 443 | static void mousedev_close_device(struct mousedev *mousedev) |
| 394 | { | 444 | { |
| 395 | if (mousedev->mixdev_open) { | 445 | mutex_lock(&mousedev->mutex); |
| 396 | mousedev->mixdev_open = 0; | ||
| 397 | if (!--mousedev->open && mousedev->exist) | ||
| 398 | input_close_device(&mousedev->handle); | ||
| 399 | } | ||
| 400 | 446 | ||
| 401 | list_del_init(&mousedev->mixdev_node); | 447 | if (mousedev->minor == MOUSEDEV_MIX) |
| 402 | put_device(&mousedev->dev); | 448 | mixdev_close_devices(); |
| 449 | else if (mousedev->exist && !--mousedev->open) | ||
| 450 | input_close_device(&mousedev->handle); | ||
| 451 | |||
| 452 | mutex_unlock(&mousedev->mutex); | ||
| 403 | } | 453 | } |
| 404 | 454 | ||
| 455 | /* | ||
| 456 | * Open all available devices so they can all be multiplexed in one. | ||
| 457 | * stream. Note that this function is called with mousedev_mix->mutex | ||
| 458 | * held. | ||
| 459 | */ | ||
| 405 | static void mixdev_open_devices(void) | 460 | static void mixdev_open_devices(void) |
| 406 | { | 461 | { |
| 407 | struct mousedev *mousedev; | 462 | struct mousedev *mousedev; |
| @@ -411,16 +466,19 @@ static void mixdev_open_devices(void) | |||
| 411 | 466 | ||
| 412 | list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) { | 467 | list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) { |
| 413 | if (!mousedev->mixdev_open) { | 468 | if (!mousedev->mixdev_open) { |
| 414 | if (!mousedev->open && mousedev->exist) | 469 | if (mousedev_open_device(mousedev)) |
| 415 | if (input_open_device(&mousedev->handle)) | 470 | continue; |
| 416 | continue; | ||
| 417 | 471 | ||
| 418 | mousedev->open++; | ||
| 419 | mousedev->mixdev_open = 1; | 472 | mousedev->mixdev_open = 1; |
| 420 | } | 473 | } |
| 421 | } | 474 | } |
| 422 | } | 475 | } |
| 423 | 476 | ||
| 477 | /* | ||
| 478 | * Close all devices that were opened as part of multiplexed | ||
| 479 | * device. Note that this function is called with mousedev_mix->mutex | ||
| 480 | * held. | ||
| 481 | */ | ||
| 424 | static void mixdev_close_devices(void) | 482 | static void mixdev_close_devices(void) |
| 425 | { | 483 | { |
| 426 | struct mousedev *mousedev; | 484 | struct mousedev *mousedev; |
| @@ -431,33 +489,45 @@ static void mixdev_close_devices(void) | |||
| 431 | list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) { | 489 | list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) { |
| 432 | if (mousedev->mixdev_open) { | 490 | if (mousedev->mixdev_open) { |
| 433 | mousedev->mixdev_open = 0; | 491 | mousedev->mixdev_open = 0; |
| 434 | if (!--mousedev->open && mousedev->exist) | 492 | mousedev_close_device(mousedev); |
| 435 | input_close_device(&mousedev->handle); | ||
| 436 | } | 493 | } |
| 437 | } | 494 | } |
| 438 | } | 495 | } |
| 439 | 496 | ||
| 497 | |||
| 498 | static void mousedev_attach_client(struct mousedev *mousedev, | ||
| 499 | struct mousedev_client *client) | ||
| 500 | { | ||
| 501 | spin_lock(&mousedev->client_lock); | ||
| 502 | list_add_tail_rcu(&client->node, &mousedev->client_list); | ||
| 503 | spin_unlock(&mousedev->client_lock); | ||
| 504 | synchronize_rcu(); | ||
| 505 | } | ||
| 506 | |||
| 507 | static void mousedev_detach_client(struct mousedev *mousedev, | ||
| 508 | struct mousedev_client *client) | ||
| 509 | { | ||
| 510 | spin_lock(&mousedev->client_lock); | ||
| 511 | list_del_rcu(&client->node); | ||
| 512 | spin_unlock(&mousedev->client_lock); | ||
| 513 | synchronize_rcu(); | ||
| 514 | } | ||
| 515 | |||
| 440 | static int mousedev_release(struct inode *inode, struct file *file) | 516 | static int mousedev_release(struct inode *inode, struct file *file) |
| 441 | { | 517 | { |
| 442 | struct mousedev_client *client = file->private_data; | 518 | struct mousedev_client *client = file->private_data; |
| 443 | struct mousedev *mousedev = client->mousedev; | 519 | struct mousedev *mousedev = client->mousedev; |
| 444 | 520 | ||
| 445 | mousedev_fasync(-1, file, 0); | 521 | mousedev_fasync(-1, file, 0); |
| 446 | 522 | mousedev_detach_client(mousedev, client); | |
| 447 | list_del(&client->node); | ||
| 448 | kfree(client); | 523 | kfree(client); |
| 449 | 524 | ||
| 450 | if (mousedev->minor == MOUSEDEV_MIX) | 525 | mousedev_close_device(mousedev); |
| 451 | mixdev_close_devices(); | ||
| 452 | else if (!--mousedev->open && mousedev->exist) | ||
| 453 | input_close_device(&mousedev->handle); | ||
| 454 | |||
| 455 | put_device(&mousedev->dev); | 526 | put_device(&mousedev->dev); |
| 456 | 527 | ||
| 457 | return 0; | 528 | return 0; |
| 458 | } | 529 | } |
| 459 | 530 | ||
| 460 | |||
| 461 | static int mousedev_open(struct inode *inode, struct file *file) | 531 | static int mousedev_open(struct inode *inode, struct file *file) |
| 462 | { | 532 | { |
| 463 | struct mousedev_client *client; | 533 | struct mousedev_client *client; |
| @@ -475,12 +545,17 @@ static int mousedev_open(struct inode *inode, struct file *file) | |||
| 475 | if (i >= MOUSEDEV_MINORS) | 545 | if (i >= MOUSEDEV_MINORS) |
| 476 | return -ENODEV; | 546 | return -ENODEV; |
| 477 | 547 | ||
| 548 | error = mutex_lock_interruptible(&mousedev_table_mutex); | ||
| 549 | if (error) | ||
| 550 | return error; | ||
| 478 | mousedev = mousedev_table[i]; | 551 | mousedev = mousedev_table[i]; |
| 552 | if (mousedev) | ||
| 553 | get_device(&mousedev->dev); | ||
| 554 | mutex_unlock(&mousedev_table_mutex); | ||
| 555 | |||
| 479 | if (!mousedev) | 556 | if (!mousedev) |
| 480 | return -ENODEV; | 557 | return -ENODEV; |
| 481 | 558 | ||
| 482 | get_device(&mousedev->dev); | ||
| 483 | |||
| 484 | client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL); | 559 | client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL); |
| 485 | if (!client) { | 560 | if (!client) { |
| 486 | error = -ENOMEM; | 561 | error = -ENOMEM; |
| @@ -491,21 +566,17 @@ static int mousedev_open(struct inode *inode, struct file *file) | |||
| 491 | client->pos_x = xres / 2; | 566 | client->pos_x = xres / 2; |
| 492 | client->pos_y = yres / 2; | 567 | client->pos_y = yres / 2; |
| 493 | client->mousedev = mousedev; | 568 | client->mousedev = mousedev; |
| 494 | list_add_tail(&client->node, &mousedev->client_list); | 569 | mousedev_attach_client(mousedev, client); |
| 495 | 570 | ||
| 496 | if (mousedev->minor == MOUSEDEV_MIX) | 571 | error = mousedev_open_device(mousedev); |
| 497 | mixdev_open_devices(); | 572 | if (error) |
| 498 | else if (!mousedev->open++ && mousedev->exist) { | 573 | goto err_free_client; |
| 499 | error = input_open_device(&mousedev->handle); | ||
| 500 | if (error) | ||
| 501 | goto err_free_client; | ||
| 502 | } | ||
| 503 | 574 | ||
| 504 | file->private_data = client; | 575 | file->private_data = client; |
| 505 | return 0; | 576 | return 0; |
| 506 | 577 | ||
| 507 | err_free_client: | 578 | err_free_client: |
| 508 | list_del(&client->node); | 579 | mousedev_detach_client(mousedev, client); |
| 509 | kfree(client); | 580 | kfree(client); |
| 510 | err_put_mousedev: | 581 | err_put_mousedev: |
| 511 | put_device(&mousedev->dev); | 582 | put_device(&mousedev->dev); |
| @@ -517,41 +588,41 @@ static inline int mousedev_limit_delta(int delta, int limit) | |||
| 517 | return delta > limit ? limit : (delta < -limit ? -limit : delta); | 588 | return delta > limit ? limit : (delta < -limit ? -limit : delta); |
| 518 | } | 589 | } |
| 519 | 590 | ||
| 520 | static void mousedev_packet(struct mousedev_client *client, signed char *ps2_data) | 591 | static void mousedev_packet(struct mousedev_client *client, |
| 592 | signed char *ps2_data) | ||
| 521 | { | 593 | { |
| 522 | struct mousedev_motion *p; | 594 | struct mousedev_motion *p = &client->packets[client->tail]; |
| 523 | unsigned long flags; | ||
| 524 | |||
| 525 | spin_lock_irqsave(&client->packet_lock, flags); | ||
| 526 | p = &client->packets[client->tail]; | ||
| 527 | 595 | ||
| 528 | ps2_data[0] = 0x08 | ((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07); | 596 | ps2_data[0] = 0x08 | |
| 597 | ((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07); | ||
| 529 | ps2_data[1] = mousedev_limit_delta(p->dx, 127); | 598 | ps2_data[1] = mousedev_limit_delta(p->dx, 127); |
| 530 | ps2_data[2] = mousedev_limit_delta(p->dy, 127); | 599 | ps2_data[2] = mousedev_limit_delta(p->dy, 127); |
| 531 | p->dx -= ps2_data[1]; | 600 | p->dx -= ps2_data[1]; |
| 532 | p->dy -= ps2_data[2]; | 601 | p->dy -= ps2_data[2]; |
| 533 | 602 | ||
| 534 | switch (client->mode) { | 603 | switch (client->mode) { |
| 535 | case MOUSEDEV_EMUL_EXPS: | 604 | case MOUSEDEV_EMUL_EXPS: |
| 536 | ps2_data[3] = mousedev_limit_delta(p->dz, 7); | 605 | ps2_data[3] = mousedev_limit_delta(p->dz, 7); |
| 537 | p->dz -= ps2_data[3]; | 606 | p->dz -= ps2_data[3]; |
| 538 | ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1); | 607 | ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1); |
| 539 | client->bufsiz = 4; | 608 | client->bufsiz = 4; |
| 540 | break; | 609 | break; |
| 541 | 610 | ||
| 542 | case MOUSEDEV_EMUL_IMPS: | 611 | case MOUSEDEV_EMUL_IMPS: |
| 543 | ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1); | 612 | ps2_data[0] |= |
| 544 | ps2_data[3] = mousedev_limit_delta(p->dz, 127); | 613 | ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1); |
| 545 | p->dz -= ps2_data[3]; | 614 | ps2_data[3] = mousedev_limit_delta(p->dz, 127); |
| 546 | client->bufsiz = 4; | 615 | p->dz -= ps2_data[3]; |
| 547 | break; | 616 | client->bufsiz = 4; |
| 548 | 617 | break; | |
| 549 | case MOUSEDEV_EMUL_PS2: | 618 | |
| 550 | default: | 619 | case MOUSEDEV_EMUL_PS2: |
| 551 | ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1); | 620 | default: |
| 552 | p->dz = 0; | 621 | ps2_data[0] |= |
| 553 | client->bufsiz = 3; | 622 | ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1); |
| 554 | break; | 623 | p->dz = 0; |
| 624 | client->bufsiz = 3; | ||
| 625 | break; | ||
| 555 | } | 626 | } |
| 556 | 627 | ||
| 557 | if (!p->dx && !p->dy && !p->dz) { | 628 | if (!p->dx && !p->dy && !p->dz) { |
| @@ -561,12 +632,56 @@ static void mousedev_packet(struct mousedev_client *client, signed char *ps2_dat | |||
| 561 | } else | 632 | } else |
| 562 | client->tail = (client->tail + 1) % PACKET_QUEUE_LEN; | 633 | client->tail = (client->tail + 1) % PACKET_QUEUE_LEN; |
| 563 | } | 634 | } |
| 564 | |||
| 565 | spin_unlock_irqrestore(&client->packet_lock, flags); | ||
| 566 | } | 635 | } |
| 567 | 636 | ||
| 637 | static void mousedev_generate_response(struct mousedev_client *client, | ||
| 638 | int command) | ||
| 639 | { | ||
| 640 | client->ps2[0] = 0xfa; /* ACK */ | ||
| 641 | |||
| 642 | switch (command) { | ||
| 568 | 643 | ||
| 569 | static ssize_t mousedev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | 644 | case 0xeb: /* Poll */ |
| 645 | mousedev_packet(client, &client->ps2[1]); | ||
| 646 | client->bufsiz++; /* account for leading ACK */ | ||
| 647 | break; | ||
| 648 | |||
| 649 | case 0xf2: /* Get ID */ | ||
| 650 | switch (client->mode) { | ||
| 651 | case MOUSEDEV_EMUL_PS2: | ||
| 652 | client->ps2[1] = 0; | ||
| 653 | break; | ||
| 654 | case MOUSEDEV_EMUL_IMPS: | ||
| 655 | client->ps2[1] = 3; | ||
| 656 | break; | ||
| 657 | case MOUSEDEV_EMUL_EXPS: | ||
| 658 | client->ps2[1] = 4; | ||
| 659 | break; | ||
| 660 | } | ||
| 661 | client->bufsiz = 2; | ||
| 662 | break; | ||
| 663 | |||
| 664 | case 0xe9: /* Get info */ | ||
| 665 | client->ps2[1] = 0x60; client->ps2[2] = 3; client->ps2[3] = 200; | ||
| 666 | client->bufsiz = 4; | ||
| 667 | break; | ||
| 668 | |||
| 669 | case 0xff: /* Reset */ | ||
| 670 | client->impsseq = client->imexseq = 0; | ||
| 671 | client->mode = MOUSEDEV_EMUL_PS2; | ||
| 672 | client->ps2[1] = 0xaa; client->ps2[2] = 0x00; | ||
| 673 | client->bufsiz = 3; | ||
| 674 | break; | ||
| 675 | |||
| 676 | default: | ||
| 677 | client->bufsiz = 1; | ||
| 678 | break; | ||
| 679 | } | ||
| 680 | client->buffer = client->bufsiz; | ||
| 681 | } | ||
| 682 | |||
| 683 | static ssize_t mousedev_write(struct file *file, const char __user *buffer, | ||
| 684 | size_t count, loff_t *ppos) | ||
| 570 | { | 685 | { |
| 571 | struct mousedev_client *client = file->private_data; | 686 | struct mousedev_client *client = file->private_data; |
| 572 | unsigned char c; | 687 | unsigned char c; |
| @@ -577,6 +692,8 @@ static ssize_t mousedev_write(struct file *file, const char __user *buffer, size | |||
| 577 | if (get_user(c, buffer + i)) | 692 | if (get_user(c, buffer + i)) |
| 578 | return -EFAULT; | 693 | return -EFAULT; |
| 579 | 694 | ||
| 695 | spin_lock_irq(&client->packet_lock); | ||
| 696 | |||
| 580 | if (c == mousedev_imex_seq[client->imexseq]) { | 697 | if (c == mousedev_imex_seq[client->imexseq]) { |
| 581 | if (++client->imexseq == MOUSEDEV_SEQ_LEN) { | 698 | if (++client->imexseq == MOUSEDEV_SEQ_LEN) { |
| 582 | client->imexseq = 0; | 699 | client->imexseq = 0; |
| @@ -593,68 +710,39 @@ static ssize_t mousedev_write(struct file *file, const char __user *buffer, size | |||
| 593 | } else | 710 | } else |
| 594 | client->impsseq = 0; | 711 | client->impsseq = 0; |
| 595 | 712 | ||
| 596 | client->ps2[0] = 0xfa; | 713 | mousedev_generate_response(client, c); |
| 597 | |||
| 598 | switch (c) { | ||
| 599 | |||
| 600 | case 0xeb: /* Poll */ | ||
| 601 | mousedev_packet(client, &client->ps2[1]); | ||
| 602 | client->bufsiz++; /* account for leading ACK */ | ||
| 603 | break; | ||
| 604 | |||
| 605 | case 0xf2: /* Get ID */ | ||
| 606 | switch (client->mode) { | ||
| 607 | case MOUSEDEV_EMUL_PS2: client->ps2[1] = 0; break; | ||
| 608 | case MOUSEDEV_EMUL_IMPS: client->ps2[1] = 3; break; | ||
| 609 | case MOUSEDEV_EMUL_EXPS: client->ps2[1] = 4; break; | ||
| 610 | } | ||
| 611 | client->bufsiz = 2; | ||
| 612 | break; | ||
| 613 | |||
| 614 | case 0xe9: /* Get info */ | ||
| 615 | client->ps2[1] = 0x60; client->ps2[2] = 3; client->ps2[3] = 200; | ||
| 616 | client->bufsiz = 4; | ||
| 617 | break; | ||
| 618 | |||
| 619 | case 0xff: /* Reset */ | ||
| 620 | client->impsseq = client->imexseq = 0; | ||
| 621 | client->mode = MOUSEDEV_EMUL_PS2; | ||
| 622 | client->ps2[1] = 0xaa; client->ps2[2] = 0x00; | ||
| 623 | client->bufsiz = 3; | ||
| 624 | break; | ||
| 625 | |||
| 626 | default: | ||
| 627 | client->bufsiz = 1; | ||
| 628 | break; | ||
| 629 | } | ||
| 630 | 714 | ||
| 631 | client->buffer = client->bufsiz; | 715 | spin_unlock_irq(&client->packet_lock); |
| 632 | } | 716 | } |
| 633 | 717 | ||
| 634 | kill_fasync(&client->fasync, SIGIO, POLL_IN); | 718 | kill_fasync(&client->fasync, SIGIO, POLL_IN); |
| 635 | |||
| 636 | wake_up_interruptible(&client->mousedev->wait); | 719 | wake_up_interruptible(&client->mousedev->wait); |
| 637 | 720 | ||
| 638 | return count; | 721 | return count; |
| 639 | } | 722 | } |
| 640 | 723 | ||
| 641 | static ssize_t mousedev_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) | 724 | static ssize_t mousedev_read(struct file *file, char __user *buffer, |
| 725 | size_t count, loff_t *ppos) | ||
| 642 | { | 726 | { |
| 643 | struct mousedev_client *client = file->private_data; | 727 | struct mousedev_client *client = file->private_data; |
| 728 | struct mousedev *mousedev = client->mousedev; | ||
| 729 | signed char data[sizeof(client->ps2)]; | ||
| 644 | int retval = 0; | 730 | int retval = 0; |
| 645 | 731 | ||
| 646 | if (!client->ready && !client->buffer && (file->f_flags & O_NONBLOCK)) | 732 | if (!client->ready && !client->buffer && mousedev->exist && |
| 733 | (file->f_flags & O_NONBLOCK)) | ||
| 647 | return -EAGAIN; | 734 | return -EAGAIN; |
| 648 | 735 | ||
| 649 | retval = wait_event_interruptible(client->mousedev->wait, | 736 | retval = wait_event_interruptible(mousedev->wait, |
| 650 | !client->mousedev->exist || client->ready || client->buffer); | 737 | !mousedev->exist || client->ready || client->buffer); |
| 651 | |||
| 652 | if (retval) | 738 | if (retval) |
| 653 | return retval; | 739 | return retval; |
| 654 | 740 | ||
| 655 | if (!client->mousedev->exist) | 741 | if (!mousedev->exist) |
| 656 | return -ENODEV; | 742 | return -ENODEV; |
| 657 | 743 | ||
| 744 | spin_lock_irq(&client->packet_lock); | ||
| 745 | |||
| 658 | if (!client->buffer && client->ready) { | 746 | if (!client->buffer && client->ready) { |
| 659 | mousedev_packet(client, client->ps2); | 747 | mousedev_packet(client, client->ps2); |
| 660 | client->buffer = client->bufsiz; | 748 | client->buffer = client->bufsiz; |
| @@ -663,9 +751,12 @@ static ssize_t mousedev_read(struct file *file, char __user *buffer, size_t coun | |||
| 663 | if (count > client->buffer) | 751 | if (count > client->buffer) |
| 664 | count = client->buffer; | 752 | count = client->buffer; |
| 665 | 753 | ||
| 754 | memcpy(data, client->ps2 + client->bufsiz - client->buffer, count); | ||
| 666 | client->buffer -= count; | 755 | client->buffer -= count; |
| 667 | 756 | ||
| 668 | if (copy_to_user(buffer, client->ps2 + client->bufsiz - client->buffer - count, count)) | 757 | spin_unlock_irq(&client->packet_lock); |
| 758 | |||
| 759 | if (copy_to_user(buffer, data, count)) | ||
| 669 | return -EFAULT; | 760 | return -EFAULT; |
| 670 | 761 | ||
| 671 | return count; | 762 | return count; |
| @@ -692,6 +783,60 @@ static const struct file_operations mousedev_fops = { | |||
| 692 | .fasync = mousedev_fasync, | 783 | .fasync = mousedev_fasync, |
| 693 | }; | 784 | }; |
| 694 | 785 | ||
| 786 | static int mousedev_install_chrdev(struct mousedev *mousedev) | ||
| 787 | { | ||
| 788 | mousedev_table[mousedev->minor] = mousedev; | ||
| 789 | return 0; | ||
| 790 | } | ||
| 791 | |||
| 792 | static void mousedev_remove_chrdev(struct mousedev *mousedev) | ||
| 793 | { | ||
| 794 | mutex_lock(&mousedev_table_mutex); | ||
| 795 | mousedev_table[mousedev->minor] = NULL; | ||
| 796 | mutex_unlock(&mousedev_table_mutex); | ||
| 797 | } | ||
| 798 | |||
| 799 | /* | ||
| 800 | * Mark device non-existent. This disables writes, ioctls and | ||
| 801 | * prevents new users from opening the device. Already posted | ||
| 802 | * blocking reads will stay, however new ones will fail. | ||
| 803 | */ | ||
| 804 | static void mousedev_mark_dead(struct mousedev *mousedev) | ||
| 805 | { | ||
| 806 | mutex_lock(&mousedev->mutex); | ||
| 807 | mousedev->exist = 0; | ||
| 808 | mutex_unlock(&mousedev->mutex); | ||
| 809 | } | ||
| 810 | |||
| 811 | /* | ||
| 812 | * Wake up users waiting for IO so they can disconnect from | ||
| 813 | * dead device. | ||
| 814 | */ | ||
| 815 | static void mousedev_hangup(struct mousedev *mousedev) | ||
| 816 | { | ||
| 817 | struct mousedev_client *client; | ||
| 818 | |||
| 819 | spin_lock(&mousedev->client_lock); | ||
| 820 | list_for_each_entry(client, &mousedev->client_list, node) | ||
| 821 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); | ||
| 822 | spin_unlock(&mousedev->client_lock); | ||
| 823 | |||
| 824 | wake_up_interruptible(&mousedev->wait); | ||
| 825 | } | ||
| 826 | |||
| 827 | static void mousedev_cleanup(struct mousedev *mousedev) | ||
| 828 | { | ||
| 829 | struct input_handle *handle = &mousedev->handle; | ||
| 830 | |||
| 831 | mousedev_mark_dead(mousedev); | ||
| 832 | mousedev_hangup(mousedev); | ||
| 833 | mousedev_remove_chrdev(mousedev); | ||
| 834 | |||
| 835 | /* mousedev is marked dead so no one else accesses mousedev->open */ | ||
| 836 | if (mousedev->open) | ||
| 837 | input_close_device(handle); | ||
| 838 | } | ||
| 839 | |||
| 695 | static struct mousedev *mousedev_create(struct input_dev *dev, | 840 | static struct mousedev *mousedev_create(struct input_dev *dev, |
| 696 | struct input_handler *handler, | 841 | struct input_handler *handler, |
| 697 | int minor) | 842 | int minor) |
| @@ -707,6 +852,10 @@ static struct mousedev *mousedev_create(struct input_dev *dev, | |||
| 707 | 852 | ||
| 708 | INIT_LIST_HEAD(&mousedev->client_list); | 853 | INIT_LIST_HEAD(&mousedev->client_list); |
| 709 | INIT_LIST_HEAD(&mousedev->mixdev_node); | 854 | INIT_LIST_HEAD(&mousedev->mixdev_node); |
| 855 | spin_lock_init(&mousedev->client_lock); | ||
| 856 | mutex_init(&mousedev->mutex); | ||
| 857 | lockdep_set_subclass(&mousedev->mutex, | ||
| 858 | minor == MOUSEDEV_MIX ? MOUSEDEV_MIX : 0); | ||
| 710 | init_waitqueue_head(&mousedev->wait); | 859 | init_waitqueue_head(&mousedev->wait); |
| 711 | 860 | ||
| 712 | if (minor == MOUSEDEV_MIX) | 861 | if (minor == MOUSEDEV_MIX) |
| @@ -731,14 +880,27 @@ static struct mousedev *mousedev_create(struct input_dev *dev, | |||
| 731 | mousedev->dev.release = mousedev_free; | 880 | mousedev->dev.release = mousedev_free; |
| 732 | device_initialize(&mousedev->dev); | 881 | device_initialize(&mousedev->dev); |
| 733 | 882 | ||
| 734 | mousedev_table[minor] = mousedev; | 883 | if (minor != MOUSEDEV_MIX) { |
| 884 | error = input_register_handle(&mousedev->handle); | ||
| 885 | if (error) | ||
| 886 | goto err_free_mousedev; | ||
| 887 | } | ||
| 888 | |||
| 889 | error = mousedev_install_chrdev(mousedev); | ||
| 890 | if (error) | ||
| 891 | goto err_unregister_handle; | ||
| 735 | 892 | ||
| 736 | error = device_add(&mousedev->dev); | 893 | error = device_add(&mousedev->dev); |
| 737 | if (error) | 894 | if (error) |
| 738 | goto err_free_mousedev; | 895 | goto err_cleanup_mousedev; |
| 739 | 896 | ||
| 740 | return mousedev; | 897 | return mousedev; |
| 741 | 898 | ||
| 899 | err_cleanup_mousedev: | ||
| 900 | mousedev_cleanup(mousedev); | ||
| 901 | err_unregister_handle: | ||
| 902 | if (minor != MOUSEDEV_MIX) | ||
| 903 | input_unregister_handle(&mousedev->handle); | ||
| 742 | err_free_mousedev: | 904 | err_free_mousedev: |
| 743 | put_device(&mousedev->dev); | 905 | put_device(&mousedev->dev); |
| 744 | err_out: | 906 | err_out: |
| @@ -747,29 +909,64 @@ static struct mousedev *mousedev_create(struct input_dev *dev, | |||
| 747 | 909 | ||
| 748 | static void mousedev_destroy(struct mousedev *mousedev) | 910 | static void mousedev_destroy(struct mousedev *mousedev) |
| 749 | { | 911 | { |
| 750 | struct mousedev_client *client; | ||
| 751 | |||
| 752 | device_del(&mousedev->dev); | 912 | device_del(&mousedev->dev); |
| 753 | mousedev->exist = 0; | 913 | mousedev_cleanup(mousedev); |
| 914 | if (mousedev->minor != MOUSEDEV_MIX) | ||
| 915 | input_unregister_handle(&mousedev->handle); | ||
| 916 | put_device(&mousedev->dev); | ||
| 917 | } | ||
| 754 | 918 | ||
| 755 | if (mousedev->open) { | 919 | static int mixdev_add_device(struct mousedev *mousedev) |
| 756 | input_close_device(&mousedev->handle); | 920 | { |
| 757 | list_for_each_entry(client, &mousedev->client_list, node) | 921 | int retval; |
| 758 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); | 922 | |
| 759 | wake_up_interruptible(&mousedev->wait); | 923 | retval = mutex_lock_interruptible(&mousedev_mix->mutex); |
| 924 | if (retval) | ||
| 925 | return retval; | ||
| 926 | |||
| 927 | if (mousedev_mix->open) { | ||
| 928 | retval = mousedev_open_device(mousedev); | ||
| 929 | if (retval) | ||
| 930 | goto out; | ||
| 931 | |||
| 932 | mousedev->mixdev_open = 1; | ||
| 760 | } | 933 | } |
| 761 | 934 | ||
| 935 | get_device(&mousedev->dev); | ||
| 936 | list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list); | ||
| 937 | |||
| 938 | out: | ||
| 939 | mutex_unlock(&mousedev_mix->mutex); | ||
| 940 | return retval; | ||
| 941 | } | ||
| 942 | |||
| 943 | static void mixdev_remove_device(struct mousedev *mousedev) | ||
| 944 | { | ||
| 945 | mutex_lock(&mousedev_mix->mutex); | ||
| 946 | |||
| 947 | if (mousedev->mixdev_open) { | ||
| 948 | mousedev->mixdev_open = 0; | ||
| 949 | mousedev_close_device(mousedev); | ||
| 950 | } | ||
| 951 | |||
| 952 | list_del_init(&mousedev->mixdev_node); | ||
| 953 | mutex_unlock(&mousedev_mix->mutex); | ||
| 954 | |||
| 762 | put_device(&mousedev->dev); | 955 | put_device(&mousedev->dev); |
| 763 | } | 956 | } |
| 764 | 957 | ||
| 765 | static int mousedev_connect(struct input_handler *handler, struct input_dev *dev, | 958 | static int mousedev_connect(struct input_handler *handler, |
| 959 | struct input_dev *dev, | ||
| 766 | const struct input_device_id *id) | 960 | const struct input_device_id *id) |
| 767 | { | 961 | { |
| 768 | struct mousedev *mousedev; | 962 | struct mousedev *mousedev; |
| 769 | int minor; | 963 | int minor; |
| 770 | int error; | 964 | int error; |
| 771 | 965 | ||
| 772 | for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++); | 966 | for (minor = 0; minor < MOUSEDEV_MINORS; minor++) |
| 967 | if (!mousedev_table[minor]) | ||
| 968 | break; | ||
| 969 | |||
| 773 | if (minor == MOUSEDEV_MINORS) { | 970 | if (minor == MOUSEDEV_MINORS) { |
| 774 | printk(KERN_ERR "mousedev: no more free mousedev devices\n"); | 971 | printk(KERN_ERR "mousedev: no more free mousedev devices\n"); |
| 775 | return -ENFILE; | 972 | return -ENFILE; |
| @@ -779,21 +976,13 @@ static int mousedev_connect(struct input_handler *handler, struct input_dev *dev | |||
| 779 | if (IS_ERR(mousedev)) | 976 | if (IS_ERR(mousedev)) |
| 780 | return PTR_ERR(mousedev); | 977 | return PTR_ERR(mousedev); |
| 781 | 978 | ||
| 782 | error = input_register_handle(&mousedev->handle); | ||
| 783 | if (error) | ||
| 784 | goto err_delete_mousedev; | ||
| 785 | |||
| 786 | error = mixdev_add_device(mousedev); | 979 | error = mixdev_add_device(mousedev); |
| 787 | if (error) | 980 | if (error) { |
| 788 | goto err_unregister_handle; | 981 | mousedev_destroy(mousedev); |
| 982 | return error; | ||
| 983 | } | ||
| 789 | 984 | ||
| 790 | return 0; | 985 | return 0; |
| 791 | |||
| 792 | err_unregister_handle: | ||
| 793 | input_unregister_handle(&mousedev->handle); | ||
| 794 | err_delete_mousedev: | ||
| 795 | device_unregister(&mousedev->dev); | ||
| 796 | return error; | ||
| 797 | } | 986 | } |
| 798 | 987 | ||
| 799 | static void mousedev_disconnect(struct input_handle *handle) | 988 | static void mousedev_disconnect(struct input_handle *handle) |
| @@ -801,33 +990,42 @@ static void mousedev_disconnect(struct input_handle *handle) | |||
| 801 | struct mousedev *mousedev = handle->private; | 990 | struct mousedev *mousedev = handle->private; |
| 802 | 991 | ||
| 803 | mixdev_remove_device(mousedev); | 992 | mixdev_remove_device(mousedev); |
| 804 | input_unregister_handle(handle); | ||
| 805 | mousedev_destroy(mousedev); | 993 | mousedev_destroy(mousedev); |
| 806 | } | 994 | } |
| 807 | 995 | ||
| 808 | static const struct input_device_id mousedev_ids[] = { | 996 | static const struct input_device_id mousedev_ids[] = { |
| 809 | { | 997 | { |
| 810 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT, | 998 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | |
| 999 | INPUT_DEVICE_ID_MATCH_KEYBIT | | ||
| 1000 | INPUT_DEVICE_ID_MATCH_RELBIT, | ||
| 811 | .evbit = { BIT(EV_KEY) | BIT(EV_REL) }, | 1001 | .evbit = { BIT(EV_KEY) | BIT(EV_REL) }, |
| 812 | .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) }, | 1002 | .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) }, |
| 813 | .relbit = { BIT(REL_X) | BIT(REL_Y) }, | 1003 | .relbit = { BIT(REL_X) | BIT(REL_Y) }, |
| 814 | }, /* A mouse like device, at least one button, two relative axes */ | 1004 | }, /* A mouse like device, at least one button, |
| 1005 | two relative axes */ | ||
| 815 | { | 1006 | { |
| 816 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_RELBIT, | 1007 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | |
| 1008 | INPUT_DEVICE_ID_MATCH_RELBIT, | ||
| 817 | .evbit = { BIT(EV_KEY) | BIT(EV_REL) }, | 1009 | .evbit = { BIT(EV_KEY) | BIT(EV_REL) }, |
| 818 | .relbit = { BIT(REL_WHEEL) }, | 1010 | .relbit = { BIT(REL_WHEEL) }, |
| 819 | }, /* A separate scrollwheel */ | 1011 | }, /* A separate scrollwheel */ |
| 820 | { | 1012 | { |
| 821 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, | 1013 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | |
| 1014 | INPUT_DEVICE_ID_MATCH_KEYBIT | | ||
| 1015 | INPUT_DEVICE_ID_MATCH_ABSBIT, | ||
| 822 | .evbit = { BIT(EV_KEY) | BIT(EV_ABS) }, | 1016 | .evbit = { BIT(EV_KEY) | BIT(EV_ABS) }, |
| 823 | .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) }, | 1017 | .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) }, |
| 824 | .absbit = { BIT(ABS_X) | BIT(ABS_Y) }, | 1018 | .absbit = { BIT(ABS_X) | BIT(ABS_Y) }, |
| 825 | }, /* A tablet like device, at least touch detection, two absolute axes */ | 1019 | }, /* A tablet like device, at least touch detection, |
| 1020 | two absolute axes */ | ||
| 826 | { | 1021 | { |
| 827 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, | 1022 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | |
| 1023 | INPUT_DEVICE_ID_MATCH_KEYBIT | | ||
| 1024 | INPUT_DEVICE_ID_MATCH_ABSBIT, | ||
| 828 | .evbit = { BIT(EV_KEY) | BIT(EV_ABS) }, | 1025 | .evbit = { BIT(EV_KEY) | BIT(EV_ABS) }, |
| 829 | .keybit = { [LONG(BTN_TOOL_FINGER)] = BIT(BTN_TOOL_FINGER) }, | 1026 | .keybit = { [LONG(BTN_TOOL_FINGER)] = BIT(BTN_TOOL_FINGER) }, |
| 830 | .absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_TOOL_WIDTH) }, | 1027 | .absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | |
| 1028 | BIT(ABS_TOOL_WIDTH) }, | ||
| 831 | }, /* A touchpad */ | 1029 | }, /* A touchpad */ |
| 832 | 1030 | ||
| 833 | { }, /* Terminating entry */ | 1031 | { }, /* Terminating entry */ |
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index c2eea2767e10..11dafc0ee994 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
| @@ -385,6 +385,8 @@ static int i8042_enable_kbd_port(void) | |||
| 385 | i8042_ctr |= I8042_CTR_KBDINT; | 385 | i8042_ctr |= I8042_CTR_KBDINT; |
| 386 | 386 | ||
| 387 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | 387 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { |
| 388 | i8042_ctr &= ~I8042_CTR_KBDINT; | ||
| 389 | i8042_ctr |= I8042_CTR_KBDDIS; | ||
| 388 | printk(KERN_ERR "i8042.c: Failed to enable KBD port.\n"); | 390 | printk(KERN_ERR "i8042.c: Failed to enable KBD port.\n"); |
| 389 | return -EIO; | 391 | return -EIO; |
| 390 | } | 392 | } |
| @@ -402,6 +404,8 @@ static int i8042_enable_aux_port(void) | |||
| 402 | i8042_ctr |= I8042_CTR_AUXINT; | 404 | i8042_ctr |= I8042_CTR_AUXINT; |
| 403 | 405 | ||
| 404 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { | 406 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { |
| 407 | i8042_ctr &= ~I8042_CTR_AUXINT; | ||
| 408 | i8042_ctr |= I8042_CTR_AUXDIS; | ||
| 405 | printk(KERN_ERR "i8042.c: Failed to enable AUX port.\n"); | 409 | printk(KERN_ERR "i8042.c: Failed to enable AUX port.\n"); |
| 406 | return -EIO; | 410 | return -EIO; |
| 407 | } | 411 | } |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index f929fcdbae2e..e3e0baa1a158 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
| @@ -126,6 +126,16 @@ config TOUCHSCREEN_HP600 | |||
| 126 | To compile this driver as a module, choose M here: the | 126 | To compile this driver as a module, choose M here: the |
| 127 | module will be called hp680_ts_input. | 127 | module will be called hp680_ts_input. |
| 128 | 128 | ||
| 129 | config TOUCHSCREEN_HP7XX | ||
| 130 | tristate "HP Jornada 710/720/728 touchscreen" | ||
| 131 | depends on SA1100_JORNADA720_SSP | ||
| 132 | help | ||
| 133 | Say Y here if you have a HP Jornada 710/720/728 and want | ||
| 134 | to support the built-in touchscreen. | ||
| 135 | |||
| 136 | To compile this driver as a module, choose M here: the | ||
| 137 | module will be called jornada720_ts. | ||
| 138 | |||
| 129 | config TOUCHSCREEN_PENMOUNT | 139 | config TOUCHSCREEN_PENMOUNT |
| 130 | tristate "Penmount serial touchscreen" | 140 | tristate "Penmount serial touchscreen" |
| 131 | select SERIO | 141 | select SERIO |
| @@ -191,6 +201,7 @@ config TOUCHSCREEN_USB_COMPOSITE | |||
| 191 | - Gunze AHL61 | 201 | - Gunze AHL61 |
| 192 | - DMC TSC-10/25 | 202 | - DMC TSC-10/25 |
| 193 | - IRTOUCHSYSTEMS/UNITOP | 203 | - IRTOUCHSYSTEMS/UNITOP |
| 204 | - IdealTEK URTC1000 | ||
| 194 | 205 | ||
| 195 | Have a look at <http://linux.chapter7.ch/touchkit/> for | 206 | Have a look at <http://linux.chapter7.ch/touchkit/> for |
| 196 | a usage description and the required user-space stuff. | 207 | a usage description and the required user-space stuff. |
| @@ -238,4 +249,14 @@ config TOUCHSCREEN_USB_IRTOUCH | |||
| 238 | bool "IRTOUCHSYSTEMS/UNITOP device support" if EMBEDDED | 249 | bool "IRTOUCHSYSTEMS/UNITOP device support" if EMBEDDED |
| 239 | depends on TOUCHSCREEN_USB_COMPOSITE | 250 | depends on TOUCHSCREEN_USB_COMPOSITE |
| 240 | 251 | ||
| 252 | config TOUCHSCREEN_USB_IDEALTEK | ||
| 253 | default y | ||
| 254 | bool "IdealTEK URTC1000 device support" if EMBEDDED | ||
| 255 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
| 256 | |||
| 257 | config TOUCHSCREEN_USB_GENERAL_TOUCH | ||
| 258 | default y | ||
| 259 | bool "GeneralTouch Touchscreen device support" if EMBEDDED | ||
| 260 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
| 261 | |||
| 241 | endif | 262 | endif |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 5de8933c4993..35d4097df35a 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
| @@ -13,6 +13,7 @@ obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o | |||
| 13 | obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o | 13 | obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o |
| 14 | obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o | 14 | obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o |
| 15 | obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o | 15 | obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o |
| 16 | obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o | ||
| 16 | obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o | 17 | obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o |
| 17 | obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o | 18 | obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o |
| 18 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o | 19 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o |
diff --git a/drivers/input/touchscreen/jornada720_ts.c b/drivers/input/touchscreen/jornada720_ts.c new file mode 100644 index 000000000000..42a1c9a1940e --- /dev/null +++ b/drivers/input/touchscreen/jornada720_ts.c | |||
| @@ -0,0 +1,182 @@ | |||
| 1 | /* | ||
| 2 | * drivers/input/touchscreen/jornada720_ts.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Kristoffer Ericson <Kristoffer.Ericson@gmail.com> | ||
| 5 | * | ||
| 6 | * Copyright (C) 2006 Filip Zyzniewski <filip.zyzniewski@tefnet.pl> | ||
| 7 | * based on HP Jornada 56x touchscreen driver by Alex Lange <chicken@handhelds.org> | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2 as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | * | ||
| 13 | * HP Jornada 710/720/729 Touchscreen Driver | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/platform_device.h> | ||
| 17 | #include <linux/init.h> | ||
| 18 | #include <linux/input.h> | ||
| 19 | #include <linux/interrupt.h> | ||
| 20 | #include <linux/module.h> | ||
| 21 | |||
| 22 | #include <asm/hardware.h> | ||
| 23 | #include <asm/arch/jornada720.h> | ||
| 24 | |||
| 25 | MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>"); | ||
| 26 | MODULE_DESCRIPTION("HP Jornada 710/720/728 touchscreen driver"); | ||
| 27 | MODULE_LICENSE("GPLv2"); | ||
| 28 | |||
| 29 | struct jornada_ts { | ||
| 30 | struct input_dev *dev; | ||
| 31 | int x_data[4]; /* X sample values */ | ||
| 32 | int y_data[4]; /* Y sample values */ | ||
| 33 | }; | ||
| 34 | |||
| 35 | static void jornada720_ts_collect_data(struct jornada_ts *jornada_ts) | ||
| 36 | { | ||
| 37 | |||
| 38 | /* 3 low word X samples */ | ||
| 39 | jornada_ts->x_data[0] = jornada_ssp_byte(TXDUMMY); | ||
| 40 | jornada_ts->x_data[1] = jornada_ssp_byte(TXDUMMY); | ||
| 41 | jornada_ts->x_data[2] = jornada_ssp_byte(TXDUMMY); | ||
| 42 | |||
| 43 | /* 3 low word Y samples */ | ||
| 44 | jornada_ts->y_data[0] = jornada_ssp_byte(TXDUMMY); | ||
| 45 | jornada_ts->y_data[1] = jornada_ssp_byte(TXDUMMY); | ||
| 46 | jornada_ts->y_data[2] = jornada_ssp_byte(TXDUMMY); | ||
| 47 | |||
| 48 | /* combined x samples bits */ | ||
| 49 | jornada_ts->x_data[3] = jornada_ssp_byte(TXDUMMY); | ||
| 50 | |||
| 51 | /* combined y samples bits */ | ||
| 52 | jornada_ts->y_data[3] = jornada_ssp_byte(TXDUMMY); | ||
| 53 | } | ||
| 54 | |||
| 55 | static int jornada720_ts_average(int coords[4]) | ||
| 56 | { | ||
| 57 | int coord, high_bits = coords[3]; | ||
| 58 | |||
| 59 | coord = coords[0] | ((high_bits & 0x03) << 8); | ||
| 60 | coord += coords[1] | ((high_bits & 0x0c) << 6); | ||
| 61 | coord += coords[2] | ((high_bits & 0x30) << 4); | ||
| 62 | |||
| 63 | return coord / 3; | ||
| 64 | } | ||
| 65 | |||
| 66 | static irqreturn_t jornada720_ts_interrupt(int irq, void *dev_id) | ||
| 67 | { | ||
| 68 | struct platform_device *pdev = dev_id; | ||
| 69 | struct jornada_ts *jornada_ts = platform_get_drvdata(pdev); | ||
| 70 | struct input_dev *input = jornada_ts->dev; | ||
| 71 | int x, y; | ||
| 72 | |||
| 73 | /* If GPIO_GPIO9 is set to high then report pen up */ | ||
| 74 | if (GPLR & GPIO_GPIO(9)) { | ||
| 75 | input_report_key(input, BTN_TOUCH, 0); | ||
| 76 | input_sync(input); | ||
| 77 | } else { | ||
| 78 | jornada_ssp_start(); | ||
| 79 | |||
| 80 | /* proper reply to request is always TXDUMMY */ | ||
| 81 | if (jornada_ssp_inout(GETTOUCHSAMPLES) == TXDUMMY) { | ||
| 82 | jornada720_ts_collect_data(jornada_ts); | ||
| 83 | |||
| 84 | x = jornada720_ts_average(jornada_ts->x_data); | ||
| 85 | y = jornada720_ts_average(jornada_ts->y_data); | ||
| 86 | |||
| 87 | input_report_key(input, BTN_TOUCH, 1); | ||
| 88 | input_report_abs(input, ABS_X, x); | ||
| 89 | input_report_abs(input, ABS_Y, y); | ||
| 90 | input_sync(input); | ||
| 91 | } | ||
| 92 | |||
| 93 | jornada_ssp_end(); | ||
| 94 | } | ||
| 95 | |||
| 96 | return IRQ_HANDLED; | ||
| 97 | } | ||
| 98 | |||
| 99 | static int __devinit jornada720_ts_probe(struct platform_device *pdev) | ||
| 100 | { | ||
| 101 | struct jornada_ts *jornada_ts; | ||
| 102 | struct input_dev *input_dev; | ||
| 103 | int error; | ||
| 104 | |||
| 105 | jornada_ts = kzalloc(sizeof(struct jornada_ts), GFP_KERNEL); | ||
| 106 | input_dev = input_allocate_device(); | ||
| 107 | |||
| 108 | if (!jornada_ts || !input_dev) { | ||
| 109 | error = -ENOMEM; | ||
| 110 | goto fail1; | ||
| 111 | } | ||
| 112 | |||
| 113 | platform_set_drvdata(pdev, jornada_ts); | ||
| 114 | |||
| 115 | jornada_ts->dev = input_dev; | ||
| 116 | |||
| 117 | input_dev->name = "HP Jornada 7xx Touchscreen"; | ||
| 118 | input_dev->phys = "jornadats/input0"; | ||
| 119 | input_dev->id.bustype = BUS_HOST; | ||
| 120 | input_dev->dev.parent = &pdev->dev; | ||
| 121 | |||
| 122 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | ||
| 123 | input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); | ||
| 124 | input_set_abs_params(input_dev, ABS_X, 270, 3900, 0, 0); | ||
| 125 | input_set_abs_params(input_dev, ABS_Y, 180, 3700, 0, 0); | ||
| 126 | |||
| 127 | error = request_irq(IRQ_GPIO9, | ||
| 128 | jornada720_ts_interrupt, | ||
| 129 | IRQF_DISABLED | IRQF_TRIGGER_RISING, | ||
| 130 | "HP7XX Touchscreen driver", pdev); | ||
| 131 | if (error) { | ||
| 132 | printk(KERN_INFO "HP7XX TS : Unable to acquire irq!\n"); | ||
| 133 | goto fail1; | ||
| 134 | } | ||
| 135 | |||
| 136 | error = input_register_device(jornada_ts->dev); | ||
| 137 | if (error) | ||
| 138 | goto fail2; | ||
| 139 | |||
| 140 | return 0; | ||
| 141 | |||
| 142 | fail2: | ||
| 143 | free_irq(IRQ_GPIO9, pdev); | ||
| 144 | fail1: | ||
| 145 | platform_set_drvdata(pdev, NULL); | ||
| 146 | input_free_device(input_dev); | ||
| 147 | kfree(jornada_ts); | ||
| 148 | return error; | ||
| 149 | } | ||
| 150 | |||
| 151 | static int __devexit jornada720_ts_remove(struct platform_device *pdev) | ||
| 152 | { | ||
| 153 | struct jornada_ts *jornada_ts = platform_get_drvdata(pdev); | ||
| 154 | |||
| 155 | free_irq(IRQ_GPIO9, pdev); | ||
| 156 | platform_set_drvdata(pdev, NULL); | ||
| 157 | input_unregister_device(jornada_ts->dev); | ||
| 158 | kfree(jornada_ts); | ||
| 159 | |||
| 160 | return 0; | ||
| 161 | } | ||
| 162 | |||
| 163 | static struct platform_driver jornada720_ts_driver = { | ||
| 164 | .probe = jornada720_ts_probe, | ||
| 165 | .remove = __devexit_p(jornada720_ts_remove), | ||
| 166 | .driver = { | ||
| 167 | .name = "jornada_ts", | ||
| 168 | }, | ||
| 169 | }; | ||
| 170 | |||
| 171 | static int __init jornada720_ts_init(void) | ||
| 172 | { | ||
| 173 | return platform_driver_register(&jornada720_ts_driver); | ||
| 174 | } | ||
| 175 | |||
| 176 | static void __exit jornada720_ts_exit(void) | ||
| 177 | { | ||
| 178 | platform_driver_unregister(&jornada720_ts_driver); | ||
| 179 | } | ||
| 180 | |||
| 181 | module_init(jornada720_ts_init); | ||
| 182 | module_exit(jornada720_ts_exit); | ||
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index 36f944019158..86aed64ec0fb 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c | |||
| @@ -130,8 +130,7 @@ static unsigned int ucb1400_adc_read(struct ucb1400 *ucb, u16 adc_channel) | |||
| 130 | if (val & UCB_ADC_DAT_VALID) | 130 | if (val & UCB_ADC_DAT_VALID) |
| 131 | break; | 131 | break; |
| 132 | /* yield to other processes */ | 132 | /* yield to other processes */ |
| 133 | set_current_state(TASK_INTERRUPTIBLE); | 133 | schedule_timeout_uninterruptible(1); |
| 134 | schedule_timeout(1); | ||
| 135 | } | 134 | } |
| 136 | 135 | ||
| 137 | return UCB_ADC_DAT_VALUE(val); | 136 | return UCB_ADC_DAT_VALUE(val); |
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 741f6c6f1e50..9fb3d5c30999 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | * - Gunze AHL61 | 10 | * - Gunze AHL61 |
| 11 | * - DMC TSC-10/25 | 11 | * - DMC TSC-10/25 |
| 12 | * - IRTOUCHSYSTEMS/UNITOP | 12 | * - IRTOUCHSYSTEMS/UNITOP |
| 13 | * - IdealTEK URTC1000 | ||
| 13 | * | 14 | * |
| 14 | * Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch> | 15 | * Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch> |
| 15 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) | 16 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) |
| @@ -92,7 +93,7 @@ struct usbtouch_usb { | |||
| 92 | }; | 93 | }; |
| 93 | 94 | ||
| 94 | 95 | ||
| 95 | #if defined(CONFIG_TOUCHSCREEN_USB_EGALAX) || defined(CONFIG_TOUCHSCREEN_USB_ETURBO) | 96 | #if defined(CONFIG_TOUCHSCREEN_USB_EGALAX) || defined(CONFIG_TOUCHSCREEN_USB_ETURBO) || defined(CONFIG_TOUCHSCREEN_USB_IDEALTEK) |
| 96 | #define MULTI_PACKET | 97 | #define MULTI_PACKET |
| 97 | #endif | 98 | #endif |
| 98 | 99 | ||
| @@ -112,6 +113,8 @@ enum { | |||
| 112 | DEVTYPE_GUNZE, | 113 | DEVTYPE_GUNZE, |
| 113 | DEVTYPE_DMC_TSC10, | 114 | DEVTYPE_DMC_TSC10, |
| 114 | DEVTYPE_IRTOUCH, | 115 | DEVTYPE_IRTOUCH, |
| 116 | DEVTYPE_IDEALTEK, | ||
| 117 | DEVTYPE_GENERAL_TOUCH, | ||
| 115 | }; | 118 | }; |
| 116 | 119 | ||
| 117 | static struct usb_device_id usbtouch_devices[] = { | 120 | static struct usb_device_id usbtouch_devices[] = { |
| @@ -157,6 +160,14 @@ static struct usb_device_id usbtouch_devices[] = { | |||
| 157 | {USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, | 160 | {USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, |
| 158 | #endif | 161 | #endif |
| 159 | 162 | ||
| 163 | #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK | ||
| 164 | {USB_DEVICE(0x1391, 0x1000), .driver_info = DEVTYPE_IDEALTEK}, | ||
| 165 | #endif | ||
| 166 | |||
| 167 | #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH | ||
| 168 | {USB_DEVICE(0x0dfc, 0x0001), .driver_info = DEVTYPE_GENERAL_TOUCH}, | ||
| 169 | #endif | ||
| 170 | |||
| 160 | {} | 171 | {} |
| 161 | }; | 172 | }; |
| 162 | 173 | ||
| @@ -396,7 +407,8 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) | |||
| 396 | TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT); | 407 | TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT); |
| 397 | if (ret < 0) | 408 | if (ret < 0) |
| 398 | return ret; | 409 | return ret; |
| 399 | if (buf[0] != 0x06 || buf[1] != 0x00) | 410 | if ((buf[0] != 0x06 || buf[1] != 0x00) && |
| 411 | (buf[0] != 0x15 || buf[1] != 0x01)) | ||
| 400 | return -ENODEV; | 412 | return -ENODEV; |
| 401 | 413 | ||
| 402 | /* start sending data */ | 414 | /* start sending data */ |
| @@ -438,6 +450,57 @@ static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |||
| 438 | 450 | ||
| 439 | 451 | ||
| 440 | /***************************************************************************** | 452 | /***************************************************************************** |
| 453 | * IdealTEK URTC1000 Part | ||
| 454 | */ | ||
| 455 | #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK | ||
| 456 | static int idealtek_get_pkt_len(unsigned char *buf, int len) | ||
| 457 | { | ||
| 458 | if (buf[0] & 0x80) | ||
| 459 | return 5; | ||
| 460 | if (buf[0] == 0x01) | ||
| 461 | return len; | ||
| 462 | return 0; | ||
| 463 | } | ||
| 464 | |||
| 465 | static int idealtek_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
| 466 | { | ||
| 467 | switch (pkt[0] & 0x98) { | ||
| 468 | case 0x88: | ||
| 469 | /* touch data in IdealTEK mode */ | ||
| 470 | dev->x = (pkt[1] << 5) | (pkt[2] >> 2); | ||
| 471 | dev->y = (pkt[3] << 5) | (pkt[4] >> 2); | ||
| 472 | dev->touch = (pkt[0] & 0x40) ? 1 : 0; | ||
| 473 | return 1; | ||
| 474 | |||
| 475 | case 0x98: | ||
| 476 | /* touch data in MT emulation mode */ | ||
| 477 | dev->x = (pkt[2] << 5) | (pkt[1] >> 2); | ||
| 478 | dev->y = (pkt[4] << 5) | (pkt[3] >> 2); | ||
| 479 | dev->touch = (pkt[0] & 0x40) ? 1 : 0; | ||
| 480 | return 1; | ||
| 481 | |||
| 482 | default: | ||
| 483 | return 0; | ||
| 484 | } | ||
| 485 | } | ||
| 486 | #endif | ||
| 487 | |||
| 488 | /***************************************************************************** | ||
| 489 | * General Touch Part | ||
| 490 | */ | ||
| 491 | #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH | ||
| 492 | static int general_touch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
| 493 | { | ||
| 494 | dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1] ; | ||
| 495 | dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3] ; | ||
| 496 | dev->press = pkt[5] & 0xff; | ||
| 497 | dev->touch = pkt[0] & 0x01; | ||
| 498 | |||
| 499 | return 1; | ||
| 500 | } | ||
| 501 | #endif | ||
| 502 | |||
| 503 | /***************************************************************************** | ||
| 441 | * the different device descriptors | 504 | * the different device descriptors |
| 442 | */ | 505 | */ |
| 443 | static struct usbtouch_device_info usbtouch_dev_info[] = { | 506 | static struct usbtouch_device_info usbtouch_dev_info[] = { |
| @@ -537,6 +600,32 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { | |||
| 537 | .read_data = irtouch_read_data, | 600 | .read_data = irtouch_read_data, |
| 538 | }, | 601 | }, |
| 539 | #endif | 602 | #endif |
| 603 | |||
| 604 | #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK | ||
| 605 | [DEVTYPE_IDEALTEK] = { | ||
| 606 | .min_xc = 0x0, | ||
| 607 | .max_xc = 0x0fff, | ||
| 608 | .min_yc = 0x0, | ||
| 609 | .max_yc = 0x0fff, | ||
| 610 | .rept_size = 8, | ||
| 611 | .flags = USBTOUCH_FLG_BUFFER, | ||
| 612 | .process_pkt = usbtouch_process_multi, | ||
| 613 | .get_pkt_len = idealtek_get_pkt_len, | ||
| 614 | .read_data = idealtek_read_data, | ||
| 615 | }, | ||
| 616 | #endif | ||
| 617 | |||
| 618 | #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH | ||
| 619 | [DEVTYPE_GENERAL_TOUCH] = { | ||
| 620 | .min_xc = 0x0, | ||
| 621 | .max_xc = 0x0500, | ||
| 622 | .min_yc = 0x0, | ||
| 623 | .max_yc = 0x0500, | ||
| 624 | .rept_size = 7, | ||
| 625 | .read_data = general_touch_read_data, | ||
| 626 | } | ||
| 627 | #endif | ||
| 628 | |||
| 540 | }; | 629 | }; |
| 541 | 630 | ||
| 542 | 631 | ||
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c deleted file mode 100644 index d2f882e98e5e..000000000000 --- a/drivers/input/tsdev.c +++ /dev/null | |||
| @@ -1,533 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * $Id: tsdev.c,v 1.15 2002/04/10 16:50:19 jsimmons Exp $ | ||
| 3 | * | ||
| 4 | * Copyright (c) 2001 "Crazy" james Simmons | ||
| 5 | * | ||
| 6 | * Compaq touchscreen protocol driver. The protocol emulated by this driver | ||
| 7 | * is obsolete; for new programs use the tslib library which can read directly | ||
| 8 | * from evdev and perform dejittering, variance filtering and calibration - | ||
| 9 | * all in user space, not at kernel level. The meaning of this driver is | ||
| 10 | * to allow usage of newer input drivers with old applications that use the | ||
| 11 | * old /dev/h3600_ts and /dev/h3600_tsraw devices. | ||
| 12 | * | ||
| 13 | * 09-Apr-2004: Andrew Zabolotny <zap@homelink.ru> | ||
| 14 | * Fixed to actually work, not just output random numbers. | ||
| 15 | * Added support for both h3600_ts and h3600_tsraw protocol | ||
| 16 | * emulation. | ||
| 17 | */ | ||
| 18 | |||
| 19 | /* | ||
| 20 | * This program is free software; you can redistribute it and/or modify | ||
| 21 | * it under the terms of the GNU General Public License as published by | ||
| 22 | * the Free Software Foundation; either version 2 of the License, or | ||
| 23 | * (at your option) any later version. | ||
| 24 | * | ||
| 25 | * This program is distributed in the hope that it will be useful, | ||
| 26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 28 | * GNU General Public License for more details. | ||
| 29 | * | ||
| 30 | * You should have received a copy of the GNU General Public License | ||
| 31 | * along with this program; if not, write to the Free Software | ||
| 32 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 33 | * | ||
| 34 | * Should you need to contact me, the author, you can do so either by | ||
| 35 | * e-mail - mail your message to <jsimmons@infradead.org>. | ||
| 36 | */ | ||
| 37 | |||
| 38 | #define TSDEV_MINOR_BASE 128 | ||
| 39 | #define TSDEV_MINORS 32 | ||
| 40 | /* First 16 devices are h3600_ts compatible; second 16 are h3600_tsraw */ | ||
| 41 | #define TSDEV_MINOR_MASK 15 | ||
| 42 | #define TSDEV_BUFFER_SIZE 64 | ||
| 43 | |||
| 44 | #include <linux/slab.h> | ||
| 45 | #include <linux/poll.h> | ||
| 46 | #include <linux/module.h> | ||
| 47 | #include <linux/moduleparam.h> | ||
| 48 | #include <linux/init.h> | ||
| 49 | #include <linux/input.h> | ||
| 50 | #include <linux/major.h> | ||
| 51 | #include <linux/random.h> | ||
| 52 | #include <linux/time.h> | ||
| 53 | #include <linux/device.h> | ||
| 54 | |||
| 55 | #ifndef CONFIG_INPUT_TSDEV_SCREEN_X | ||
| 56 | #define CONFIG_INPUT_TSDEV_SCREEN_X 240 | ||
| 57 | #endif | ||
| 58 | #ifndef CONFIG_INPUT_TSDEV_SCREEN_Y | ||
| 59 | #define CONFIG_INPUT_TSDEV_SCREEN_Y 320 | ||
| 60 | #endif | ||
| 61 | |||
| 62 | /* This driver emulates both protocols of the old h3600_ts and h3600_tsraw | ||
| 63 | * devices. The first one must output X/Y data in 'cooked' format, e.g. | ||
| 64 | * filtered, dejittered and calibrated. Second device just outputs raw | ||
| 65 | * data received from the hardware. | ||
| 66 | * | ||
| 67 | * This driver doesn't support filtering and dejittering; it supports only | ||
| 68 | * calibration. Filtering and dejittering must be done in the low-level | ||
| 69 | * driver, if needed, because it may gain additional benefits from knowing | ||
| 70 | * the low-level details, the nature of noise and so on. | ||
| 71 | * | ||
| 72 | * The driver precomputes a calibration matrix given the initial xres and | ||
| 73 | * yres values (quite innacurate for most touchscreens) that will result | ||
| 74 | * in a more or less expected range of output values. The driver supports | ||
| 75 | * the TS_SET_CAL ioctl, which will replace the calibration matrix with a | ||
| 76 | * new one, supposedly generated from the values taken from the raw device. | ||
| 77 | */ | ||
| 78 | |||
| 79 | MODULE_AUTHOR("James Simmons <jsimmons@transvirtual.com>"); | ||
| 80 | MODULE_DESCRIPTION("Input driver to touchscreen converter"); | ||
| 81 | MODULE_LICENSE("GPL"); | ||
| 82 | |||
| 83 | static int xres = CONFIG_INPUT_TSDEV_SCREEN_X; | ||
| 84 | module_param(xres, uint, 0); | ||
| 85 | MODULE_PARM_DESC(xres, "Horizontal screen resolution (can be negative for X-mirror)"); | ||
| 86 | |||
| 87 | static int yres = CONFIG_INPUT_TSDEV_SCREEN_Y; | ||
| 88 | module_param(yres, uint, 0); | ||
| 89 | MODULE_PARM_DESC(yres, "Vertical screen resolution (can be negative for Y-mirror)"); | ||
| 90 | |||
| 91 | /* From Compaq's Touch Screen Specification version 0.2 (draft) */ | ||
| 92 | struct ts_event { | ||
| 93 | short pressure; | ||
| 94 | short x; | ||
| 95 | short y; | ||
| 96 | short millisecs; | ||
| 97 | }; | ||
| 98 | |||
| 99 | struct ts_calibration { | ||
| 100 | int xscale; | ||
| 101 | int xtrans; | ||
| 102 | int yscale; | ||
| 103 | int ytrans; | ||
| 104 | int xyswap; | ||
| 105 | }; | ||
| 106 | |||
| 107 | struct tsdev { | ||
| 108 | int exist; | ||
| 109 | int open; | ||
| 110 | int minor; | ||
| 111 | char name[8]; | ||
| 112 | struct input_handle handle; | ||
| 113 | wait_queue_head_t wait; | ||
| 114 | struct list_head client_list; | ||
| 115 | struct device dev; | ||
| 116 | |||
| 117 | int x, y, pressure; | ||
| 118 | struct ts_calibration cal; | ||
| 119 | }; | ||
| 120 | |||
| 121 | struct tsdev_client { | ||
| 122 | struct fasync_struct *fasync; | ||
| 123 | struct list_head node; | ||
| 124 | struct tsdev *tsdev; | ||
| 125 | int head, tail; | ||
| 126 | struct ts_event event[TSDEV_BUFFER_SIZE]; | ||
| 127 | int raw; | ||
| 128 | }; | ||
| 129 | |||
| 130 | /* The following ioctl codes are defined ONLY for backward compatibility. | ||
| 131 | * Don't use tsdev for new developement; use the tslib library instead. | ||
| 132 | * Touchscreen calibration is a fully userspace task. | ||
| 133 | */ | ||
| 134 | /* Use 'f' as magic number */ | ||
| 135 | #define IOC_H3600_TS_MAGIC 'f' | ||
| 136 | #define TS_GET_CAL _IOR(IOC_H3600_TS_MAGIC, 10, struct ts_calibration) | ||
| 137 | #define TS_SET_CAL _IOW(IOC_H3600_TS_MAGIC, 11, struct ts_calibration) | ||
| 138 | |||
| 139 | static struct tsdev *tsdev_table[TSDEV_MINORS/2]; | ||
| 140 | |||
| 141 | static int tsdev_fasync(int fd, struct file *file, int on) | ||
| 142 | { | ||
| 143 | struct tsdev_client *client = file->private_data; | ||
| 144 | int retval; | ||
| 145 | |||
| 146 | retval = fasync_helper(fd, file, on, &client->fasync); | ||
| 147 | return retval < 0 ? retval : 0; | ||
| 148 | } | ||
| 149 | |||
| 150 | static int tsdev_open(struct inode *inode, struct file *file) | ||
| 151 | { | ||
| 152 | int i = iminor(inode) - TSDEV_MINOR_BASE; | ||
| 153 | struct tsdev_client *client; | ||
| 154 | struct tsdev *tsdev; | ||
| 155 | int error; | ||
| 156 | |||
| 157 | printk(KERN_WARNING "tsdev (compaq touchscreen emulation) is scheduled " | ||
| 158 | "for removal.\nSee Documentation/feature-removal-schedule.txt " | ||
| 159 | "for details.\n"); | ||
| 160 | |||
| 161 | if (i >= TSDEV_MINORS) | ||
| 162 | return -ENODEV; | ||
| 163 | |||
| 164 | tsdev = tsdev_table[i & TSDEV_MINOR_MASK]; | ||
| 165 | if (!tsdev || !tsdev->exist) | ||
| 166 | return -ENODEV; | ||
| 167 | |||
| 168 | get_device(&tsdev->dev); | ||
| 169 | |||
| 170 | client = kzalloc(sizeof(struct tsdev_client), GFP_KERNEL); | ||
| 171 | if (!client) { | ||
| 172 | error = -ENOMEM; | ||
| 173 | goto err_put_tsdev; | ||
| 174 | } | ||
| 175 | |||
| 176 | client->tsdev = tsdev; | ||
| 177 | client->raw = (i >= TSDEV_MINORS / 2) ? 1 : 0; | ||
| 178 | list_add_tail(&client->node, &tsdev->client_list); | ||
| 179 | |||
| 180 | if (!tsdev->open++ && tsdev->exist) { | ||
| 181 | error = input_open_device(&tsdev->handle); | ||
| 182 | if (error) | ||
| 183 | goto err_free_client; | ||
| 184 | } | ||
| 185 | |||
| 186 | file->private_data = client; | ||
| 187 | return 0; | ||
| 188 | |||
| 189 | err_free_client: | ||
| 190 | list_del(&client->node); | ||
| 191 | kfree(client); | ||
| 192 | err_put_tsdev: | ||
| 193 | put_device(&tsdev->dev); | ||
| 194 | return error; | ||
| 195 | } | ||
| 196 | |||
| 197 | static void tsdev_free(struct device *dev) | ||
| 198 | { | ||
| 199 | struct tsdev *tsdev = container_of(dev, struct tsdev, dev); | ||
| 200 | |||
| 201 | tsdev_table[tsdev->minor] = NULL; | ||
| 202 | kfree(tsdev); | ||
| 203 | } | ||
| 204 | |||
| 205 | static int tsdev_release(struct inode *inode, struct file *file) | ||
| 206 | { | ||
| 207 | struct tsdev_client *client = file->private_data; | ||
| 208 | struct tsdev *tsdev = client->tsdev; | ||
| 209 | |||
| 210 | tsdev_fasync(-1, file, 0); | ||
| 211 | |||
| 212 | list_del(&client->node); | ||
| 213 | kfree(client); | ||
| 214 | |||
| 215 | if (!--tsdev->open && tsdev->exist) | ||
| 216 | input_close_device(&tsdev->handle); | ||
| 217 | |||
| 218 | put_device(&tsdev->dev); | ||
| 219 | |||
| 220 | return 0; | ||
| 221 | } | ||
| 222 | |||
| 223 | static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count, | ||
| 224 | loff_t *ppos) | ||
| 225 | { | ||
| 226 | struct tsdev_client *client = file->private_data; | ||
| 227 | struct tsdev *tsdev = client->tsdev; | ||
| 228 | int retval = 0; | ||
| 229 | |||
| 230 | if (client->head == client->tail && tsdev->exist && (file->f_flags & O_NONBLOCK)) | ||
| 231 | return -EAGAIN; | ||
| 232 | |||
| 233 | retval = wait_event_interruptible(tsdev->wait, | ||
| 234 | client->head != client->tail || !tsdev->exist); | ||
| 235 | if (retval) | ||
| 236 | return retval; | ||
| 237 | |||
| 238 | if (!tsdev->exist) | ||
| 239 | return -ENODEV; | ||
| 240 | |||
| 241 | while (client->head != client->tail && | ||
| 242 | retval + sizeof (struct ts_event) <= count) { | ||
| 243 | if (copy_to_user (buffer + retval, client->event + client->tail, | ||
| 244 | sizeof (struct ts_event))) | ||
| 245 | return -EFAULT; | ||
| 246 | client->tail = (client->tail + 1) & (TSDEV_BUFFER_SIZE - 1); | ||
| 247 | retval += sizeof (struct ts_event); | ||
| 248 | } | ||
| 249 | |||
| 250 | return retval; | ||
| 251 | } | ||
| 252 | |||
| 253 | /* No kernel lock - fine */ | ||
| 254 | static unsigned int tsdev_poll(struct file *file, poll_table *wait) | ||
| 255 | { | ||
| 256 | struct tsdev_client *client = file->private_data; | ||
| 257 | struct tsdev *tsdev = client->tsdev; | ||
| 258 | |||
| 259 | poll_wait(file, &tsdev->wait, wait); | ||
| 260 | return ((client->head == client->tail) ? 0 : (POLLIN | POLLRDNORM)) | | ||
| 261 | (tsdev->exist ? 0 : (POLLHUP | POLLERR)); | ||
| 262 | } | ||
| 263 | |||
| 264 | static int tsdev_ioctl(struct inode *inode, struct file *file, | ||
| 265 | unsigned int cmd, unsigned long arg) | ||
| 266 | { | ||
| 267 | struct tsdev_client *client = file->private_data; | ||
| 268 | struct tsdev *tsdev = client->tsdev; | ||
| 269 | int retval = 0; | ||
| 270 | |||
| 271 | switch (cmd) { | ||
| 272 | case TS_GET_CAL: | ||
| 273 | if (copy_to_user((void __user *)arg, &tsdev->cal, | ||
| 274 | sizeof (struct ts_calibration))) | ||
| 275 | retval = -EFAULT; | ||
| 276 | break; | ||
| 277 | |||
| 278 | case TS_SET_CAL: | ||
| 279 | if (copy_from_user(&tsdev->cal, (void __user *)arg, | ||
| 280 | sizeof (struct ts_calibration))) | ||
| 281 | retval = -EFAULT; | ||
| 282 | break; | ||
| 283 | |||
| 284 | default: | ||
| 285 | retval = -EINVAL; | ||
| 286 | break; | ||
| 287 | } | ||
| 288 | |||
| 289 | return retval; | ||
| 290 | } | ||
| 291 | |||
| 292 | static const struct file_operations tsdev_fops = { | ||
| 293 | .owner = THIS_MODULE, | ||
| 294 | .open = tsdev_open, | ||
| 295 | .release = tsdev_release, | ||
| 296 | .read = tsdev_read, | ||
| 297 | .poll = tsdev_poll, | ||
| 298 | .fasync = tsdev_fasync, | ||
| 299 | .ioctl = tsdev_ioctl, | ||
| 300 | }; | ||
| 301 | |||
| 302 | static void tsdev_event(struct input_handle *handle, unsigned int type, | ||
| 303 | unsigned int code, int value) | ||
| 304 | { | ||
| 305 | struct tsdev *tsdev = handle->private; | ||
| 306 | struct tsdev_client *client; | ||
| 307 | struct timeval time; | ||
| 308 | |||
| 309 | switch (type) { | ||
| 310 | case EV_ABS: | ||
| 311 | switch (code) { | ||
| 312 | case ABS_X: | ||
| 313 | tsdev->x = value; | ||
| 314 | break; | ||
| 315 | |||
| 316 | case ABS_Y: | ||
| 317 | tsdev->y = value; | ||
| 318 | break; | ||
| 319 | |||
| 320 | case ABS_PRESSURE: | ||
| 321 | if (value > handle->dev->absmax[ABS_PRESSURE]) | ||
| 322 | value = handle->dev->absmax[ABS_PRESSURE]; | ||
| 323 | value -= handle->dev->absmin[ABS_PRESSURE]; | ||
| 324 | if (value < 0) | ||
| 325 | value = 0; | ||
| 326 | tsdev->pressure = value; | ||
| 327 | break; | ||
| 328 | } | ||
| 329 | break; | ||
| 330 | |||
| 331 | case EV_REL: | ||
| 332 | switch (code) { | ||
| 333 | case REL_X: | ||
| 334 | tsdev->x += value; | ||
| 335 | if (tsdev->x < 0) | ||
| 336 | tsdev->x = 0; | ||
| 337 | else if (tsdev->x > xres) | ||
| 338 | tsdev->x = xres; | ||
| 339 | break; | ||
| 340 | |||
| 341 | case REL_Y: | ||
| 342 | tsdev->y += value; | ||
| 343 | if (tsdev->y < 0) | ||
| 344 | tsdev->y = 0; | ||
| 345 | else if (tsdev->y > yres) | ||
| 346 | tsdev->y = yres; | ||
| 347 | break; | ||
| 348 | } | ||
| 349 | break; | ||
| 350 | |||
| 351 | case EV_KEY: | ||
| 352 | if (code == BTN_TOUCH || code == BTN_MOUSE) { | ||
| 353 | switch (value) { | ||
| 354 | case 0: | ||
| 355 | tsdev->pressure = 0; | ||
| 356 | break; | ||
| 357 | |||
| 358 | case 1: | ||
| 359 | if (!tsdev->pressure) | ||
| 360 | tsdev->pressure = 1; | ||
| 361 | break; | ||
| 362 | } | ||
| 363 | } | ||
| 364 | break; | ||
| 365 | } | ||
| 366 | |||
| 367 | if (type != EV_SYN || code != SYN_REPORT) | ||
| 368 | return; | ||
| 369 | |||
| 370 | list_for_each_entry(client, &tsdev->client_list, node) { | ||
| 371 | int x, y, tmp; | ||
| 372 | |||
| 373 | do_gettimeofday(&time); | ||
| 374 | client->event[client->head].millisecs = time.tv_usec / 1000; | ||
| 375 | client->event[client->head].pressure = tsdev->pressure; | ||
| 376 | |||
| 377 | x = tsdev->x; | ||
| 378 | y = tsdev->y; | ||
| 379 | |||
| 380 | /* Calibration */ | ||
| 381 | if (!client->raw) { | ||
| 382 | x = ((x * tsdev->cal.xscale) >> 8) + tsdev->cal.xtrans; | ||
| 383 | y = ((y * tsdev->cal.yscale) >> 8) + tsdev->cal.ytrans; | ||
| 384 | if (tsdev->cal.xyswap) { | ||
| 385 | tmp = x; x = y; y = tmp; | ||
| 386 | } | ||
| 387 | } | ||
| 388 | |||
| 389 | client->event[client->head].x = x; | ||
| 390 | client->event[client->head].y = y; | ||
| 391 | client->head = (client->head + 1) & (TSDEV_BUFFER_SIZE - 1); | ||
| 392 | kill_fasync(&client->fasync, SIGIO, POLL_IN); | ||
| 393 | } | ||
| 394 | wake_up_interruptible(&tsdev->wait); | ||
| 395 | } | ||
| 396 | |||
| 397 | static int tsdev_connect(struct input_handler *handler, struct input_dev *dev, | ||
| 398 | const struct input_device_id *id) | ||
| 399 | { | ||
| 400 | struct tsdev *tsdev; | ||
| 401 | int minor, delta; | ||
| 402 | int error; | ||
| 403 | |||
| 404 | for (minor = 0; minor < TSDEV_MINORS / 2 && tsdev_table[minor]; minor++); | ||
| 405 | if (minor >= TSDEV_MINORS / 2) { | ||
| 406 | printk(KERN_ERR | ||
| 407 | "tsdev: You have way too many touchscreens\n"); | ||
| 408 | return -ENFILE; | ||
| 409 | } | ||
| 410 | |||
| 411 | tsdev = kzalloc(sizeof(struct tsdev), GFP_KERNEL); | ||
| 412 | if (!tsdev) | ||
| 413 | return -ENOMEM; | ||
| 414 | |||
| 415 | INIT_LIST_HEAD(&tsdev->client_list); | ||
| 416 | init_waitqueue_head(&tsdev->wait); | ||
| 417 | |||
| 418 | tsdev->exist = 1; | ||
| 419 | tsdev->minor = minor; | ||
| 420 | tsdev->handle.dev = dev; | ||
| 421 | tsdev->handle.name = tsdev->name; | ||
| 422 | tsdev->handle.handler = handler; | ||
| 423 | tsdev->handle.private = tsdev; | ||
| 424 | snprintf(tsdev->name, sizeof(tsdev->name), "ts%d", minor); | ||
| 425 | |||
| 426 | /* Precompute the rough calibration matrix */ | ||
| 427 | delta = dev->absmax [ABS_X] - dev->absmin [ABS_X] + 1; | ||
| 428 | if (delta == 0) | ||
| 429 | delta = 1; | ||
| 430 | tsdev->cal.xscale = (xres << 8) / delta; | ||
| 431 | tsdev->cal.xtrans = - ((dev->absmin [ABS_X] * tsdev->cal.xscale) >> 8); | ||
| 432 | |||
| 433 | delta = dev->absmax [ABS_Y] - dev->absmin [ABS_Y] + 1; | ||
| 434 | if (delta == 0) | ||
| 435 | delta = 1; | ||
| 436 | tsdev->cal.yscale = (yres << 8) / delta; | ||
| 437 | tsdev->cal.ytrans = - ((dev->absmin [ABS_Y] * tsdev->cal.yscale) >> 8); | ||
| 438 | |||
| 439 | snprintf(tsdev->dev.bus_id, sizeof(tsdev->dev.bus_id), | ||
| 440 | "ts%d", minor); | ||
| 441 | tsdev->dev.class = &input_class; | ||
| 442 | tsdev->dev.parent = &dev->dev; | ||
| 443 | tsdev->dev.devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor); | ||
| 444 | tsdev->dev.release = tsdev_free; | ||
| 445 | device_initialize(&tsdev->dev); | ||
| 446 | |||
| 447 | tsdev_table[minor] = tsdev; | ||
| 448 | |||
| 449 | error = device_add(&tsdev->dev); | ||
| 450 | if (error) | ||
| 451 | goto err_free_tsdev; | ||
| 452 | |||
| 453 | error = input_register_handle(&tsdev->handle); | ||
| 454 | if (error) | ||
| 455 | goto err_delete_tsdev; | ||
| 456 | |||
| 457 | return 0; | ||
| 458 | |||
| 459 | err_delete_tsdev: | ||
| 460 | device_del(&tsdev->dev); | ||
| 461 | err_free_tsdev: | ||
| 462 | put_device(&tsdev->dev); | ||
| 463 | return error; | ||
| 464 | } | ||
| 465 | |||
| 466 | static void tsdev_disconnect(struct input_handle *handle) | ||
| 467 | { | ||
| 468 | struct tsdev *tsdev = handle->private; | ||
| 469 | struct tsdev_client *client; | ||
| 470 | |||
| 471 | input_unregister_handle(handle); | ||
| 472 | device_del(&tsdev->dev); | ||
| 473 | |||
| 474 | tsdev->exist = 0; | ||
| 475 | |||
| 476 | if (tsdev->open) { | ||
| 477 | input_close_device(handle); | ||
| 478 | list_for_each_entry(client, &tsdev->client_list, node) | ||
| 479 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); | ||
| 480 | wake_up_interruptible(&tsdev->wait); | ||
| 481 | } | ||
| 482 | |||
| 483 | put_device(&tsdev->dev); | ||
| 484 | } | ||
| 485 | |||
| 486 | static const struct input_device_id tsdev_ids[] = { | ||
| 487 | { | ||
| 488 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT, | ||
| 489 | .evbit = { BIT(EV_KEY) | BIT(EV_REL) }, | ||
| 490 | .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) }, | ||
| 491 | .relbit = { BIT(REL_X) | BIT(REL_Y) }, | ||
| 492 | }, /* A mouse like device, at least one button, two relative axes */ | ||
| 493 | |||
| 494 | { | ||
| 495 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, | ||
| 496 | .evbit = { BIT(EV_KEY) | BIT(EV_ABS) }, | ||
| 497 | .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) }, | ||
| 498 | .absbit = { BIT(ABS_X) | BIT(ABS_Y) }, | ||
| 499 | }, /* A tablet like device, at least touch detection, two absolute axes */ | ||
| 500 | |||
| 501 | { | ||
| 502 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, | ||
| 503 | .evbit = { BIT(EV_ABS) }, | ||
| 504 | .absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) }, | ||
| 505 | }, /* A tablet like device with several gradations of pressure */ | ||
| 506 | |||
| 507 | {} /* Terminating entry */ | ||
| 508 | }; | ||
| 509 | |||
| 510 | MODULE_DEVICE_TABLE(input, tsdev_ids); | ||
| 511 | |||
| 512 | static struct input_handler tsdev_handler = { | ||
| 513 | .event = tsdev_event, | ||
| 514 | .connect = tsdev_connect, | ||
| 515 | .disconnect = tsdev_disconnect, | ||
| 516 | .fops = &tsdev_fops, | ||
| 517 | .minor = TSDEV_MINOR_BASE, | ||
| 518 | .name = "tsdev", | ||
| 519 | .id_table = tsdev_ids, | ||
| 520 | }; | ||
| 521 | |||
| 522 | static int __init tsdev_init(void) | ||
| 523 | { | ||
| 524 | return input_register_handler(&tsdev_handler); | ||
| 525 | } | ||
| 526 | |||
| 527 | static void __exit tsdev_exit(void) | ||
| 528 | { | ||
| 529 | input_unregister_handler(&tsdev_handler); | ||
| 530 | } | ||
| 531 | |||
| 532 | module_init(tsdev_init); | ||
| 533 | module_exit(tsdev_exit); | ||
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c index 7c9cb7e19f2e..b39d1f5b378e 100644 --- a/drivers/isdn/i4l/isdn_net.c +++ b/drivers/isdn/i4l/isdn_net.c | |||
| @@ -328,7 +328,7 @@ isdn_net_autohup(void) | |||
| 328 | l->cps = (l->transcount * HZ) / (jiffies - last_jiffies); | 328 | l->cps = (l->transcount * HZ) / (jiffies - last_jiffies); |
| 329 | l->transcount = 0; | 329 | l->transcount = 0; |
| 330 | if (dev->net_verbose > 3) | 330 | if (dev->net_verbose > 3) |
| 331 | printk(KERN_DEBUG "%s: %d bogocps\n", l->name, l->cps); | 331 | printk(KERN_DEBUG "%s: %d bogocps\n", p->dev->name, l->cps); |
| 332 | if ((l->flags & ISDN_NET_CONNECTED) && (!l->dialstate)) { | 332 | if ((l->flags & ISDN_NET_CONNECTED) && (!l->dialstate)) { |
| 333 | anymore = 1; | 333 | anymore = 1; |
| 334 | l->huptimer++; | 334 | l->huptimer++; |
| @@ -350,12 +350,12 @@ isdn_net_autohup(void) | |||
| 350 | if (l->hupflags & ISDN_CHARGEHUP) { | 350 | if (l->hupflags & ISDN_CHARGEHUP) { |
| 351 | if (l->hupflags & ISDN_WAITCHARGE) { | 351 | if (l->hupflags & ISDN_WAITCHARGE) { |
| 352 | printk(KERN_DEBUG "isdn_net: Hupflags of %s are %X\n", | 352 | printk(KERN_DEBUG "isdn_net: Hupflags of %s are %X\n", |
| 353 | l->name, l->hupflags); | 353 | p->dev->name, l->hupflags); |
| 354 | isdn_net_hangup(p->dev); | 354 | isdn_net_hangup(p->dev); |
| 355 | } else if (time_after(jiffies, l->chargetime + l->chargeint)) { | 355 | } else if (time_after(jiffies, l->chargetime + l->chargeint)) { |
| 356 | printk(KERN_DEBUG | 356 | printk(KERN_DEBUG |
| 357 | "isdn_net: %s: chtime = %lu, chint = %d\n", | 357 | "isdn_net: %s: chtime = %lu, chint = %d\n", |
| 358 | l->name, l->chargetime, l->chargeint); | 358 | p->dev->name, l->chargetime, l->chargeint); |
| 359 | isdn_net_hangup(p->dev); | 359 | isdn_net_hangup(p->dev); |
| 360 | } | 360 | } |
| 361 | } else | 361 | } else |
| @@ -442,8 +442,8 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c) | |||
| 442 | #endif | 442 | #endif |
| 443 | isdn_net_lp_disconnected(lp); | 443 | isdn_net_lp_disconnected(lp); |
| 444 | isdn_all_eaz(lp->isdn_device, lp->isdn_channel); | 444 | isdn_all_eaz(lp->isdn_device, lp->isdn_channel); |
| 445 | printk(KERN_INFO "%s: remote hangup\n", lp->name); | 445 | printk(KERN_INFO "%s: remote hangup\n", p->dev->name); |
| 446 | printk(KERN_INFO "%s: Chargesum is %d\n", lp->name, | 446 | printk(KERN_INFO "%s: Chargesum is %d\n", p->dev->name, |
| 447 | lp->charge); | 447 | lp->charge); |
| 448 | isdn_net_unbind_channel(lp); | 448 | isdn_net_unbind_channel(lp); |
| 449 | return 1; | 449 | return 1; |
| @@ -487,7 +487,7 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c) | |||
| 487 | isdn_net_add_to_bundle(nd, lp); | 487 | isdn_net_add_to_bundle(nd, lp); |
| 488 | } | 488 | } |
| 489 | } | 489 | } |
| 490 | printk(KERN_INFO "isdn_net: %s connected\n", lp->name); | 490 | printk(KERN_INFO "isdn_net: %s connected\n", p->dev->name); |
| 491 | /* If first Chargeinfo comes before B-Channel connect, | 491 | /* If first Chargeinfo comes before B-Channel connect, |
| 492 | * we correct the timestamp here. | 492 | * we correct the timestamp here. |
| 493 | */ | 493 | */ |
| @@ -534,7 +534,7 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c) | |||
| 534 | lp->hupflags |= ISDN_HAVECHARGE; | 534 | lp->hupflags |= ISDN_HAVECHARGE; |
| 535 | lp->chargetime = jiffies; | 535 | lp->chargetime = jiffies; |
| 536 | printk(KERN_DEBUG "isdn_net: Got CINF chargetime of %s now %lu\n", | 536 | printk(KERN_DEBUG "isdn_net: Got CINF chargetime of %s now %lu\n", |
| 537 | lp->name, lp->chargetime); | 537 | p->dev->name, lp->chargetime); |
| 538 | return 1; | 538 | return 1; |
| 539 | } | 539 | } |
| 540 | } | 540 | } |
| @@ -565,7 +565,7 @@ isdn_net_dial(void) | |||
| 565 | 565 | ||
| 566 | #ifdef ISDN_DEBUG_NET_DIAL | 566 | #ifdef ISDN_DEBUG_NET_DIAL |
| 567 | if (lp->dialstate) | 567 | if (lp->dialstate) |
| 568 | printk(KERN_DEBUG "%s: dialstate=%d\n", lp->name, lp->dialstate); | 568 | printk(KERN_DEBUG "%s: dialstate=%d\n", p->dev->name, lp->dialstate); |
| 569 | #endif | 569 | #endif |
| 570 | switch (lp->dialstate) { | 570 | switch (lp->dialstate) { |
| 571 | case 0: | 571 | case 0: |
| @@ -578,7 +578,7 @@ isdn_net_dial(void) | |||
| 578 | lp->dial = lp->phone[1]; | 578 | lp->dial = lp->phone[1]; |
| 579 | if (!lp->dial) { | 579 | if (!lp->dial) { |
| 580 | printk(KERN_WARNING "%s: phone number deleted?\n", | 580 | printk(KERN_WARNING "%s: phone number deleted?\n", |
| 581 | lp->name); | 581 | p->dev->name); |
| 582 | isdn_net_hangup(p->dev); | 582 | isdn_net_hangup(p->dev); |
| 583 | break; | 583 | break; |
| 584 | } | 584 | } |
| @@ -632,13 +632,13 @@ isdn_net_dial(void) | |||
| 632 | cmd.arg = lp->isdn_channel; | 632 | cmd.arg = lp->isdn_channel; |
| 633 | if (!lp->dial) { | 633 | if (!lp->dial) { |
| 634 | printk(KERN_WARNING "%s: phone number deleted?\n", | 634 | printk(KERN_WARNING "%s: phone number deleted?\n", |
| 635 | lp->name); | 635 | p->dev->name); |
| 636 | isdn_net_hangup(p->dev); | 636 | isdn_net_hangup(p->dev); |
| 637 | break; | 637 | break; |
| 638 | } | 638 | } |
| 639 | if (!strncmp(lp->dial->num, "LEASED", strlen("LEASED"))) { | 639 | if (!strncmp(lp->dial->num, "LEASED", strlen("LEASED"))) { |
| 640 | lp->dialstate = 4; | 640 | lp->dialstate = 4; |
| 641 | printk(KERN_INFO "%s: Open leased line ...\n", lp->name); | 641 | printk(KERN_INFO "%s: Open leased line ...\n", p->dev->name); |
| 642 | } else { | 642 | } else { |
| 643 | if(lp->dialtimeout > 0) | 643 | if(lp->dialtimeout > 0) |
| 644 | if (time_after(jiffies, lp->dialstarted + lp->dialtimeout)) { | 644 | if (time_after(jiffies, lp->dialstarted + lp->dialtimeout)) { |
| @@ -688,7 +688,7 @@ isdn_net_dial(void) | |||
| 688 | dev->usage[i] |= ISDN_USAGE_OUTGOING; | 688 | dev->usage[i] |= ISDN_USAGE_OUTGOING; |
| 689 | isdn_info_update(); | 689 | isdn_info_update(); |
| 690 | } | 690 | } |
| 691 | printk(KERN_INFO "%s: dialing %d %s... %s\n", lp->name, | 691 | printk(KERN_INFO "%s: dialing %d %s... %s\n", p->dev->name, |
| 692 | lp->dialretry, cmd.parm.setup.phone, | 692 | lp->dialretry, cmd.parm.setup.phone, |
| 693 | (cmd.parm.setup.si1 == 1) ? "DOV" : ""); | 693 | (cmd.parm.setup.si1 == 1) ? "DOV" : ""); |
| 694 | lp->dtimer = 0; | 694 | lp->dtimer = 0; |
| @@ -797,7 +797,7 @@ isdn_net_dial(void) | |||
| 797 | */ | 797 | */ |
| 798 | if (lp->dtimer++ > lp->cbdelay) | 798 | if (lp->dtimer++ > lp->cbdelay) |
| 799 | { | 799 | { |
| 800 | printk(KERN_INFO "%s: hangup waiting for callback ...\n", lp->name); | 800 | printk(KERN_INFO "%s: hangup waiting for callback ...\n", p->dev->name); |
| 801 | lp->dtimer = 0; | 801 | lp->dtimer = 0; |
| 802 | lp->dialstate = 4; | 802 | lp->dialstate = 4; |
| 803 | cmd.driver = lp->isdn_device; | 803 | cmd.driver = lp->isdn_device; |
| @@ -810,7 +810,7 @@ isdn_net_dial(void) | |||
| 810 | break; | 810 | break; |
| 811 | default: | 811 | default: |
| 812 | printk(KERN_WARNING "isdn_net: Illegal dialstate %d for device %s\n", | 812 | printk(KERN_WARNING "isdn_net: Illegal dialstate %d for device %s\n", |
| 813 | lp->dialstate, lp->name); | 813 | lp->dialstate, p->dev->name); |
| 814 | } | 814 | } |
| 815 | p = (isdn_net_dev *) p->next; | 815 | p = (isdn_net_dev *) p->next; |
| 816 | } | 816 | } |
| @@ -836,11 +836,11 @@ isdn_net_hangup(struct net_device *d) | |||
| 836 | if (slp->flags & ISDN_NET_CONNECTED) { | 836 | if (slp->flags & ISDN_NET_CONNECTED) { |
| 837 | printk(KERN_INFO | 837 | printk(KERN_INFO |
| 838 | "isdn_net: hang up slave %s before %s\n", | 838 | "isdn_net: hang up slave %s before %s\n", |
| 839 | slp->name, lp->name); | 839 | lp->slave->name, d->name); |
| 840 | isdn_net_hangup(lp->slave); | 840 | isdn_net_hangup(lp->slave); |
| 841 | } | 841 | } |
| 842 | } | 842 | } |
| 843 | printk(KERN_INFO "isdn_net: local hangup %s\n", lp->name); | 843 | printk(KERN_INFO "isdn_net: local hangup %s\n", d->name); |
| 844 | #ifdef CONFIG_ISDN_PPP | 844 | #ifdef CONFIG_ISDN_PPP |
| 845 | if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) | 845 | if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) |
| 846 | isdn_ppp_free(lp); | 846 | isdn_ppp_free(lp); |
| @@ -858,7 +858,7 @@ isdn_net_hangup(struct net_device *d) | |||
| 858 | cmd.command = ISDN_CMD_HANGUP; | 858 | cmd.command = ISDN_CMD_HANGUP; |
| 859 | cmd.arg = lp->isdn_channel; | 859 | cmd.arg = lp->isdn_channel; |
| 860 | isdn_command(&cmd); | 860 | isdn_command(&cmd); |
| 861 | printk(KERN_INFO "%s: Chargesum is %d\n", lp->name, lp->charge); | 861 | printk(KERN_INFO "%s: Chargesum is %d\n", d->name, lp->charge); |
| 862 | isdn_all_eaz(lp->isdn_device, lp->isdn_channel); | 862 | isdn_all_eaz(lp->isdn_device, lp->isdn_channel); |
| 863 | } | 863 | } |
| 864 | isdn_net_unbind_channel(lp); | 864 | isdn_net_unbind_channel(lp); |
| @@ -885,7 +885,7 @@ isdn_net_log_skb(struct sk_buff * skb, isdn_net_local * lp) | |||
| 885 | /* fall back to old isdn_net_log_packet method() */ | 885 | /* fall back to old isdn_net_log_packet method() */ |
| 886 | char * buf = skb->data; | 886 | char * buf = skb->data; |
| 887 | 887 | ||
| 888 | printk(KERN_DEBUG "isdn_net: protocol %04x is buggy, dev %s\n", skb->protocol, lp->name); | 888 | printk(KERN_DEBUG "isdn_net: protocol %04x is buggy, dev %s\n", skb->protocol, lp->netdev->dev->name); |
| 889 | p = buf; | 889 | p = buf; |
| 890 | proto = ETH_P_IP; | 890 | proto = ETH_P_IP; |
| 891 | switch (lp->p_encap) { | 891 | switch (lp->p_encap) { |
| @@ -1023,7 +1023,7 @@ void isdn_net_writebuf_skb(isdn_net_local *lp, struct sk_buff *skb) | |||
| 1023 | ret = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb); | 1023 | ret = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb); |
| 1024 | if (ret != len) { | 1024 | if (ret != len) { |
| 1025 | /* we should never get here */ | 1025 | /* we should never get here */ |
| 1026 | printk(KERN_WARNING "%s: HL driver queue full\n", lp->name); | 1026 | printk(KERN_WARNING "%s: HL driver queue full\n", lp->netdev->dev->name); |
| 1027 | goto error; | 1027 | goto error; |
| 1028 | } | 1028 | } |
| 1029 | 1029 | ||
| @@ -1461,7 +1461,7 @@ isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
| 1461 | mod_timer(&lp->cisco_timer, expires); | 1461 | mod_timer(&lp->cisco_timer, expires); |
| 1462 | printk(KERN_INFO "%s: Keepalive period set " | 1462 | printk(KERN_INFO "%s: Keepalive period set " |
| 1463 | "to %d seconds.\n", | 1463 | "to %d seconds.\n", |
| 1464 | lp->name, lp->cisco_keepalive_period); | 1464 | dev->name, lp->cisco_keepalive_period); |
| 1465 | } | 1465 | } |
| 1466 | break; | 1466 | break; |
| 1467 | 1467 | ||
| @@ -1512,7 +1512,7 @@ isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data) | |||
| 1512 | lp->cisco_line_state = 0; | 1512 | lp->cisco_line_state = 0; |
| 1513 | printk (KERN_WARNING | 1513 | printk (KERN_WARNING |
| 1514 | "UPDOWN: Line protocol on Interface %s," | 1514 | "UPDOWN: Line protocol on Interface %s," |
| 1515 | " changed state to down\n", lp->name); | 1515 | " changed state to down\n", lp->netdev->dev->name); |
| 1516 | /* should stop routing higher-level data accross */ | 1516 | /* should stop routing higher-level data accross */ |
| 1517 | } else if ((!lp->cisco_line_state) && | 1517 | } else if ((!lp->cisco_line_state) && |
| 1518 | (myseq_diff >= 0) && (myseq_diff <= 2)) { | 1518 | (myseq_diff >= 0) && (myseq_diff <= 2)) { |
| @@ -1520,14 +1520,14 @@ isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data) | |||
| 1520 | lp->cisco_line_state = 1; | 1520 | lp->cisco_line_state = 1; |
| 1521 | printk (KERN_WARNING | 1521 | printk (KERN_WARNING |
| 1522 | "UPDOWN: Line protocol on Interface %s," | 1522 | "UPDOWN: Line protocol on Interface %s," |
| 1523 | " changed state to up\n", lp->name); | 1523 | " changed state to up\n", lp->netdev->dev->name); |
| 1524 | /* restart routing higher-level data accross */ | 1524 | /* restart routing higher-level data accross */ |
| 1525 | } | 1525 | } |
| 1526 | 1526 | ||
| 1527 | if (lp->cisco_debserint) | 1527 | if (lp->cisco_debserint) |
| 1528 | printk (KERN_DEBUG "%s: HDLC " | 1528 | printk (KERN_DEBUG "%s: HDLC " |
| 1529 | "myseq %lu, mineseen %lu%c, yourseen %lu, %s\n", | 1529 | "myseq %lu, mineseen %lu%c, yourseen %lu, %s\n", |
| 1530 | lp->name, last_cisco_myseq, lp->cisco_mineseen, | 1530 | lp->netdev->dev->name, last_cisco_myseq, lp->cisco_mineseen, |
| 1531 | ((last_cisco_myseq == lp->cisco_mineseen) ? '*' : 040), | 1531 | ((last_cisco_myseq == lp->cisco_mineseen) ? '*' : 040), |
| 1532 | lp->cisco_yourseq, | 1532 | lp->cisco_yourseq, |
| 1533 | ((lp->cisco_line_state) ? "line up" : "line down")); | 1533 | ((lp->cisco_line_state) ? "line up" : "line down")); |
| @@ -1682,7 +1682,7 @@ isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb) | |||
| 1682 | "remote ip: %d.%d.%d.%d, " | 1682 | "remote ip: %d.%d.%d.%d, " |
| 1683 | "local ip: %d.%d.%d.%d " | 1683 | "local ip: %d.%d.%d.%d " |
| 1684 | "mask: %d.%d.%d.%d\n", | 1684 | "mask: %d.%d.%d.%d\n", |
| 1685 | lp->name, | 1685 | lp->netdev->dev->name, |
| 1686 | HIPQUAD(addr), | 1686 | HIPQUAD(addr), |
| 1687 | HIPQUAD(local), | 1687 | HIPQUAD(local), |
| 1688 | HIPQUAD(mask)); | 1688 | HIPQUAD(mask)); |
| @@ -1690,7 +1690,7 @@ isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb) | |||
| 1690 | slarp_reply_out: | 1690 | slarp_reply_out: |
| 1691 | printk(KERN_INFO "%s: got invalid slarp " | 1691 | printk(KERN_INFO "%s: got invalid slarp " |
| 1692 | "reply (%d.%d.%d.%d/%d.%d.%d.%d) " | 1692 | "reply (%d.%d.%d.%d/%d.%d.%d.%d) " |
| 1693 | "- ignored\n", lp->name, | 1693 | "- ignored\n", lp->netdev->dev->name, |
| 1694 | HIPQUAD(addr), HIPQUAD(mask)); | 1694 | HIPQUAD(addr), HIPQUAD(mask)); |
| 1695 | break; | 1695 | break; |
| 1696 | case CISCO_SLARP_KEEPALIVE: | 1696 | case CISCO_SLARP_KEEPALIVE: |
| @@ -1701,7 +1701,8 @@ isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb) | |||
| 1701 | lp->cisco_last_slarp_in) { | 1701 | lp->cisco_last_slarp_in) { |
| 1702 | printk(KERN_DEBUG "%s: Keepalive period mismatch - " | 1702 | printk(KERN_DEBUG "%s: Keepalive period mismatch - " |
| 1703 | "is %d but should be %d.\n", | 1703 | "is %d but should be %d.\n", |
| 1704 | lp->name, period, lp->cisco_keepalive_period); | 1704 | lp->netdev->dev->name, period, |
| 1705 | lp->cisco_keepalive_period); | ||
| 1705 | } | 1706 | } |
| 1706 | lp->cisco_last_slarp_in = jiffies; | 1707 | lp->cisco_last_slarp_in = jiffies; |
| 1707 | p += get_u32(p, &my_seq); | 1708 | p += get_u32(p, &my_seq); |
| @@ -1732,12 +1733,12 @@ isdn_net_ciscohdlck_receive(isdn_net_local *lp, struct sk_buff *skb) | |||
| 1732 | 1733 | ||
| 1733 | if (addr != CISCO_ADDR_UNICAST && addr != CISCO_ADDR_BROADCAST) { | 1734 | if (addr != CISCO_ADDR_UNICAST && addr != CISCO_ADDR_BROADCAST) { |
| 1734 | printk(KERN_WARNING "%s: Unknown Cisco addr 0x%02x\n", | 1735 | printk(KERN_WARNING "%s: Unknown Cisco addr 0x%02x\n", |
| 1735 | lp->name, addr); | 1736 | lp->netdev->dev->name, addr); |
| 1736 | goto out_free; | 1737 | goto out_free; |
| 1737 | } | 1738 | } |
| 1738 | if (ctrl != CISCO_CTRL) { | 1739 | if (ctrl != CISCO_CTRL) { |
| 1739 | printk(KERN_WARNING "%s: Unknown Cisco ctrl 0x%02x\n", | 1740 | printk(KERN_WARNING "%s: Unknown Cisco ctrl 0x%02x\n", |
| 1740 | lp->name, ctrl); | 1741 | lp->netdev->dev->name, ctrl); |
| 1741 | goto out_free; | 1742 | goto out_free; |
| 1742 | } | 1743 | } |
| 1743 | 1744 | ||
| @@ -1748,7 +1749,8 @@ isdn_net_ciscohdlck_receive(isdn_net_local *lp, struct sk_buff *skb) | |||
| 1748 | case CISCO_TYPE_CDP: | 1749 | case CISCO_TYPE_CDP: |
| 1749 | if (lp->cisco_debserint) | 1750 | if (lp->cisco_debserint) |
| 1750 | printk(KERN_DEBUG "%s: Received CDP packet. use " | 1751 | printk(KERN_DEBUG "%s: Received CDP packet. use " |
| 1751 | "\"no cdp enable\" on cisco.\n", lp->name); | 1752 | "\"no cdp enable\" on cisco.\n", |
| 1753 | lp->netdev->dev->name); | ||
| 1752 | goto out_free; | 1754 | goto out_free; |
| 1753 | default: | 1755 | default: |
| 1754 | /* no special cisco protocol */ | 1756 | /* no special cisco protocol */ |
| @@ -1843,7 +1845,7 @@ isdn_net_receive(struct net_device *ndev, struct sk_buff *skb) | |||
| 1843 | }; | 1845 | }; |
| 1844 | #endif /* CONFIG_ISDN_X25 */ | 1846 | #endif /* CONFIG_ISDN_X25 */ |
| 1845 | printk(KERN_WARNING "%s: unknown encapsulation, dropping\n", | 1847 | printk(KERN_WARNING "%s: unknown encapsulation, dropping\n", |
| 1846 | lp->name); | 1848 | lp->netdev->dev->name); |
| 1847 | kfree_skb(skb); | 1849 | kfree_skb(skb); |
| 1848 | return; | 1850 | return; |
| 1849 | } | 1851 | } |
| @@ -2174,7 +2176,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) | |||
| 2174 | wret = matchret; | 2176 | wret = matchret; |
| 2175 | #ifdef ISDN_DEBUG_NET_ICALL | 2177 | #ifdef ISDN_DEBUG_NET_ICALL |
| 2176 | printk(KERN_DEBUG "n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d\n", | 2178 | printk(KERN_DEBUG "n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d\n", |
| 2177 | lp->name, lp->msn, lp->flags, lp->dialstate); | 2179 | p->dev->name, lp->msn, lp->flags, lp->dialstate); |
| 2178 | #endif | 2180 | #endif |
| 2179 | if ((!matchret) && /* EAZ is matching */ | 2181 | if ((!matchret) && /* EAZ is matching */ |
| 2180 | (((!(lp->flags & ISDN_NET_CONNECTED)) && /* but not connected */ | 2182 | (((!(lp->flags & ISDN_NET_CONNECTED)) && /* but not connected */ |
| @@ -2277,7 +2279,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) | |||
| 2277 | * */ | 2279 | * */ |
| 2278 | if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) { | 2280 | if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) { |
| 2279 | printk(KERN_INFO "incoming call, interface %s `stopped' -> rejected\n", | 2281 | printk(KERN_INFO "incoming call, interface %s `stopped' -> rejected\n", |
| 2280 | lp->name); | 2282 | p->dev->name); |
| 2281 | return 3; | 2283 | return 3; |
| 2282 | } | 2284 | } |
| 2283 | /* | 2285 | /* |
| @@ -2286,7 +2288,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) | |||
| 2286 | */ | 2288 | */ |
| 2287 | if (!isdn_net_device_started(p)) { | 2289 | if (!isdn_net_device_started(p)) { |
| 2288 | printk(KERN_INFO "%s: incoming call, interface down -> rejected\n", | 2290 | printk(KERN_INFO "%s: incoming call, interface down -> rejected\n", |
| 2289 | lp->name); | 2291 | p->dev->name); |
| 2290 | return 3; | 2292 | return 3; |
| 2291 | } | 2293 | } |
| 2292 | /* Interface is up, now see if it's a slave. If so, see if | 2294 | /* Interface is up, now see if it's a slave. If so, see if |
| @@ -2294,8 +2296,8 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) | |||
| 2294 | */ | 2296 | */ |
| 2295 | if (lp->master) { | 2297 | if (lp->master) { |
| 2296 | isdn_net_local *mlp = (isdn_net_local *) lp->master->priv; | 2298 | isdn_net_local *mlp = (isdn_net_local *) lp->master->priv; |
| 2297 | printk(KERN_DEBUG "ICALLslv: %s\n", lp->name); | 2299 | printk(KERN_DEBUG "ICALLslv: %s\n", p->dev->name); |
| 2298 | printk(KERN_DEBUG "master=%s\n", mlp->name); | 2300 | printk(KERN_DEBUG "master=%s\n", lp->master->name); |
| 2299 | if (mlp->flags & ISDN_NET_CONNECTED) { | 2301 | if (mlp->flags & ISDN_NET_CONNECTED) { |
| 2300 | printk(KERN_DEBUG "master online\n"); | 2302 | printk(KERN_DEBUG "master online\n"); |
| 2301 | /* Master is online, find parent-slave (master if first slave) */ | 2303 | /* Master is online, find parent-slave (master if first slave) */ |
| @@ -2322,11 +2324,11 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) | |||
| 2322 | * */ | 2324 | * */ |
| 2323 | if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) { | 2325 | if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) { |
| 2324 | printk(KERN_INFO "incoming call for callback, interface %s `off' -> rejected\n", | 2326 | printk(KERN_INFO "incoming call for callback, interface %s `off' -> rejected\n", |
| 2325 | lp->name); | 2327 | p->dev->name); |
| 2326 | return 3; | 2328 | return 3; |
| 2327 | } | 2329 | } |
| 2328 | printk(KERN_DEBUG "%s: call from %s -> %s, start callback\n", | 2330 | printk(KERN_DEBUG "%s: call from %s -> %s, start callback\n", |
| 2329 | lp->name, nr, eaz); | 2331 | p->dev->name, nr, eaz); |
| 2330 | if (lp->phone[1]) { | 2332 | if (lp->phone[1]) { |
| 2331 | /* Grab a free ISDN-Channel */ | 2333 | /* Grab a free ISDN-Channel */ |
| 2332 | spin_lock_irqsave(&dev->lock, flags); | 2334 | spin_lock_irqsave(&dev->lock, flags); |
| @@ -2340,7 +2342,8 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) | |||
| 2340 | lp->msn) | 2342 | lp->msn) |
| 2341 | ) < 0) { | 2343 | ) < 0) { |
| 2342 | 2344 | ||
| 2343 | printk(KERN_WARNING "isdn_net_find_icall: No channel for %s\n", lp->name); | 2345 | printk(KERN_WARNING "isdn_net_find_icall: No channel for %s\n", |
| 2346 | p->dev->name); | ||
| 2344 | spin_unlock_irqrestore(&dev->lock, flags); | 2347 | spin_unlock_irqrestore(&dev->lock, flags); |
| 2345 | return 0; | 2348 | return 0; |
| 2346 | } | 2349 | } |
| @@ -2361,11 +2364,12 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) | |||
| 2361 | /* Initiate dialing by returning 2 or 4 */ | 2364 | /* Initiate dialing by returning 2 or 4 */ |
| 2362 | return (lp->flags & ISDN_NET_CBHUP) ? 2 : 4; | 2365 | return (lp->flags & ISDN_NET_CBHUP) ? 2 : 4; |
| 2363 | } else | 2366 | } else |
| 2364 | printk(KERN_WARNING "isdn_net: %s: No phone number\n", lp->name); | 2367 | printk(KERN_WARNING "isdn_net: %s: No phone number\n", |
| 2368 | p->dev->name); | ||
| 2365 | return 0; | 2369 | return 0; |
| 2366 | } else { | 2370 | } else { |
| 2367 | printk(KERN_DEBUG "%s: call from %s -> %s accepted\n", lp->name, nr, | 2371 | printk(KERN_DEBUG "%s: call from %s -> %s accepted\n", |
| 2368 | eaz); | 2372 | p->dev->name, nr, eaz); |
| 2369 | /* if this interface is dialing, it does it probably on a different | 2373 | /* if this interface is dialing, it does it probably on a different |
| 2370 | device, so free this device */ | 2374 | device, so free this device */ |
| 2371 | if ((lp->dialstate == 4) || (lp->dialstate == 12)) { | 2375 | if ((lp->dialstate == 4) || (lp->dialstate == 12)) { |
| @@ -2424,7 +2428,7 @@ isdn_net_findif(char *name) | |||
| 2424 | isdn_net_dev *p = dev->netdev; | 2428 | isdn_net_dev *p = dev->netdev; |
| 2425 | 2429 | ||
| 2426 | while (p) { | 2430 | while (p) { |
| 2427 | if (!strcmp(p->local->name, name)) | 2431 | if (!strcmp(p->dev->name, name)) |
| 2428 | return p; | 2432 | return p; |
| 2429 | p = (isdn_net_dev *) p->next; | 2433 | p = (isdn_net_dev *) p->next; |
| 2430 | } | 2434 | } |
| @@ -2453,7 +2457,8 @@ isdn_net_force_dial_lp(isdn_net_local * lp) | |||
| 2453 | lp->pre_device, | 2457 | lp->pre_device, |
| 2454 | lp->pre_channel, | 2458 | lp->pre_channel, |
| 2455 | lp->msn)) < 0) { | 2459 | lp->msn)) < 0) { |
| 2456 | printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n", lp->name); | 2460 | printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n", |
| 2461 | lp->netdev->dev->name); | ||
| 2457 | spin_unlock_irqrestore(&dev->lock, flags); | 2462 | spin_unlock_irqrestore(&dev->lock, flags); |
| 2458 | return -EAGAIN; | 2463 | return -EAGAIN; |
| 2459 | } | 2464 | } |
| @@ -2556,7 +2561,7 @@ isdn_net_new(char *name, struct net_device *master) | |||
| 2556 | return NULL; | 2561 | return NULL; |
| 2557 | } | 2562 | } |
| 2558 | if (name == NULL) | 2563 | if (name == NULL) |
| 2559 | name = " "; | 2564 | return NULL; |
| 2560 | if (!(netdev = kzalloc(sizeof(isdn_net_dev), GFP_KERNEL))) { | 2565 | if (!(netdev = kzalloc(sizeof(isdn_net_dev), GFP_KERNEL))) { |
| 2561 | printk(KERN_WARNING "isdn_net: Could not allocate net-device\n"); | 2566 | printk(KERN_WARNING "isdn_net: Could not allocate net-device\n"); |
| 2562 | return NULL; | 2567 | return NULL; |
| @@ -2568,7 +2573,6 @@ isdn_net_new(char *name, struct net_device *master) | |||
| 2568 | return NULL; | 2573 | return NULL; |
| 2569 | } | 2574 | } |
| 2570 | netdev->local = netdev->dev->priv; | 2575 | netdev->local = netdev->dev->priv; |
| 2571 | strcpy(netdev->local->name, netdev->dev->name); | ||
| 2572 | netdev->dev->init = isdn_net_init; | 2576 | netdev->dev->init = isdn_net_init; |
| 2573 | if (master) { | 2577 | if (master) { |
| 2574 | /* Device shall be a slave */ | 2578 | /* Device shall be a slave */ |
| @@ -2673,7 +2677,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg) | |||
| 2673 | #endif | 2677 | #endif |
| 2674 | if (isdn_net_device_started(p)) { | 2678 | if (isdn_net_device_started(p)) { |
| 2675 | printk(KERN_WARNING "%s: cannot change encap when if is up\n", | 2679 | printk(KERN_WARNING "%s: cannot change encap when if is up\n", |
| 2676 | lp->name); | 2680 | p->dev->name); |
| 2677 | return -EBUSY; | 2681 | return -EBUSY; |
| 2678 | } | 2682 | } |
| 2679 | #ifdef CONFIG_ISDN_X25 | 2683 | #ifdef CONFIG_ISDN_X25 |
| @@ -2698,7 +2702,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg) | |||
| 2698 | case ISDN_NET_ENCAP_SYNCPPP: | 2702 | case ISDN_NET_ENCAP_SYNCPPP: |
| 2699 | #ifndef CONFIG_ISDN_PPP | 2703 | #ifndef CONFIG_ISDN_PPP |
| 2700 | printk(KERN_WARNING "%s: SyncPPP support not configured\n", | 2704 | printk(KERN_WARNING "%s: SyncPPP support not configured\n", |
| 2701 | lp->name); | 2705 | p->dev->name); |
| 2702 | return -EINVAL; | 2706 | return -EINVAL; |
| 2703 | #else | 2707 | #else |
| 2704 | p->dev->type = ARPHRD_PPP; /* change ARP type */ | 2708 | p->dev->type = ARPHRD_PPP; /* change ARP type */ |
| @@ -2709,7 +2713,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg) | |||
| 2709 | case ISDN_NET_ENCAP_X25IFACE: | 2713 | case ISDN_NET_ENCAP_X25IFACE: |
| 2710 | #ifndef CONFIG_ISDN_X25 | 2714 | #ifndef CONFIG_ISDN_X25 |
| 2711 | printk(KERN_WARNING "%s: isdn-x25 support not configured\n", | 2715 | printk(KERN_WARNING "%s: isdn-x25 support not configured\n", |
| 2712 | p->local->name); | 2716 | p->dev->name); |
| 2713 | return -EINVAL; | 2717 | return -EINVAL; |
| 2714 | #else | 2718 | #else |
| 2715 | p->dev->type = ARPHRD_X25; /* change ARP type */ | 2719 | p->dev->type = ARPHRD_X25; /* change ARP type */ |
| @@ -2725,7 +2729,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg) | |||
| 2725 | break; | 2729 | break; |
| 2726 | printk(KERN_WARNING | 2730 | printk(KERN_WARNING |
| 2727 | "%s: encapsulation protocol %d not supported\n", | 2731 | "%s: encapsulation protocol %d not supported\n", |
| 2728 | p->local->name, cfg->p_encap); | 2732 | p->dev->name, cfg->p_encap); |
| 2729 | return -EINVAL; | 2733 | return -EINVAL; |
| 2730 | } | 2734 | } |
| 2731 | if (strlen(cfg->drvid)) { | 2735 | if (strlen(cfg->drvid)) { |
| @@ -2902,13 +2906,18 @@ isdn_net_getcfg(isdn_net_ioctl_cfg * cfg) | |||
| 2902 | cfg->pppbind = lp->pppbind; | 2906 | cfg->pppbind = lp->pppbind; |
| 2903 | cfg->dialtimeout = lp->dialtimeout >= 0 ? lp->dialtimeout / HZ : -1; | 2907 | cfg->dialtimeout = lp->dialtimeout >= 0 ? lp->dialtimeout / HZ : -1; |
| 2904 | cfg->dialwait = lp->dialwait / HZ; | 2908 | cfg->dialwait = lp->dialwait / HZ; |
| 2905 | if (lp->slave) | 2909 | if (lp->slave) { |
| 2906 | strcpy(cfg->slave, ((isdn_net_local *) lp->slave->priv)->name); | 2910 | if (strlen(lp->slave->name) > 8) |
| 2907 | else | 2911 | strcpy(cfg->slave, "too-long"); |
| 2912 | else | ||
| 2913 | strcpy(cfg->slave, lp->slave->name); | ||
| 2914 | } else | ||
| 2908 | cfg->slave[0] = '\0'; | 2915 | cfg->slave[0] = '\0'; |
| 2909 | if (lp->master) | 2916 | if (lp->master) { |
| 2910 | strcpy(cfg->master, ((isdn_net_local *) lp->master->priv)->name); | 2917 | if (strlen(lp->master->name) > 8) |
| 2911 | else | 2918 | strcpy(cfg->master, "too-long"); |
| 2919 | strcpy(cfg->master, lp->master->name); | ||
| 2920 | } else | ||
| 2912 | cfg->master[0] = '\0'; | 2921 | cfg->master[0] = '\0'; |
| 2913 | return 0; | 2922 | return 0; |
| 2914 | } | 2923 | } |
| @@ -2978,7 +2987,8 @@ isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone __user *peer) | |||
| 2978 | isdn_net_dev *p = isdn_net_findif(phone->name); | 2987 | isdn_net_dev *p = isdn_net_findif(phone->name); |
| 2979 | int ch, dv, idx; | 2988 | int ch, dv, idx; |
| 2980 | 2989 | ||
| 2981 | if (!p) return -ENODEV; | 2990 | if (!p) |
| 2991 | return -ENODEV; | ||
| 2982 | /* | 2992 | /* |
| 2983 | * Theoretical race: while this executes, the remote number might | 2993 | * Theoretical race: while this executes, the remote number might |
| 2984 | * become invalid (hang up) or change (new connection), resulting | 2994 | * become invalid (hang up) or change (new connection), resulting |
| @@ -2987,14 +2997,18 @@ isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone __user *peer) | |||
| 2987 | */ | 2997 | */ |
| 2988 | ch = p->local->isdn_channel; | 2998 | ch = p->local->isdn_channel; |
| 2989 | dv = p->local->isdn_device; | 2999 | dv = p->local->isdn_device; |
| 2990 | if(ch<0 && dv<0) return -ENOTCONN; | 3000 | if(ch < 0 && dv < 0) |
| 3001 | return -ENOTCONN; | ||
| 2991 | idx = isdn_dc2minor(dv, ch); | 3002 | idx = isdn_dc2minor(dv, ch); |
| 2992 | if (idx<0) return -ENODEV; | 3003 | if (idx <0 ) |
| 3004 | return -ENODEV; | ||
| 2993 | /* for pre-bound channels, we need this extra check */ | 3005 | /* for pre-bound channels, we need this extra check */ |
| 2994 | if ( strncmp(dev->num[idx],"???",3) == 0 ) return -ENOTCONN; | 3006 | if (strncmp(dev->num[idx], "???", 3) == 0) |
| 2995 | strncpy(phone->phone,dev->num[idx],ISDN_MSNLEN); | 3007 | return -ENOTCONN; |
| 2996 | phone->outgoing=USG_OUTGOING(dev->usage[idx]); | 3008 | strncpy(phone->phone, dev->num[idx], ISDN_MSNLEN); |
| 2997 | if ( copy_to_user(peer,phone,sizeof(*peer)) ) return -EFAULT; | 3009 | phone->outgoing = USG_OUTGOING(dev->usage[idx]); |
| 3010 | if (copy_to_user(peer, phone, sizeof(*peer))) | ||
| 3011 | return -EFAULT; | ||
| 2998 | return 0; | 3012 | return 0; |
| 2999 | } | 3013 | } |
| 3000 | /* | 3014 | /* |
| @@ -3113,18 +3127,18 @@ isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q) | |||
| 3113 | dev->netdev = p->next; | 3127 | dev->netdev = p->next; |
| 3114 | if (p->local->slave) { | 3128 | if (p->local->slave) { |
| 3115 | /* If this interface has a slave, remove it also */ | 3129 | /* If this interface has a slave, remove it also */ |
| 3116 | char *slavename = ((isdn_net_local *) (p->local->slave->priv))->name; | 3130 | char *slavename = p->local->slave->name; |
| 3117 | isdn_net_dev *n = dev->netdev; | 3131 | isdn_net_dev *n = dev->netdev; |
| 3118 | q = NULL; | 3132 | q = NULL; |
| 3119 | while (n) { | 3133 | while (n) { |
| 3120 | if (!strcmp(n->local->name, slavename)) { | 3134 | if (!strcmp(n->dev->name, slavename)) { |
| 3121 | spin_unlock_irqrestore(&dev->lock, flags); | 3135 | spin_unlock_irqrestore(&dev->lock, flags); |
| 3122 | isdn_net_realrm(n, q); | 3136 | isdn_net_realrm(n, q); |
| 3123 | spin_lock_irqsave(&dev->lock, flags); | 3137 | spin_lock_irqsave(&dev->lock, flags); |
| 3124 | break; | 3138 | break; |
| 3125 | } | 3139 | } |
| 3126 | q = n; | 3140 | q = n; |
| 3127 | n = (isdn_net_dev *) n->next; | 3141 | n = (isdn_net_dev *)n->next; |
| 3128 | } | 3142 | } |
| 3129 | } | 3143 | } |
| 3130 | spin_unlock_irqrestore(&dev->lock, flags); | 3144 | spin_unlock_irqrestore(&dev->lock, flags); |
| @@ -3152,7 +3166,7 @@ isdn_net_rm(char *name) | |||
| 3152 | p = dev->netdev; | 3166 | p = dev->netdev; |
| 3153 | q = NULL; | 3167 | q = NULL; |
| 3154 | while (p) { | 3168 | while (p) { |
| 3155 | if (!strcmp(p->local->name, name)) { | 3169 | if (!strcmp(p->dev->name, name)) { |
| 3156 | spin_unlock_irqrestore(&dev->lock, flags); | 3170 | spin_unlock_irqrestore(&dev->lock, flags); |
| 3157 | return (isdn_net_realrm(p, q)); | 3171 | return (isdn_net_realrm(p, q)); |
| 3158 | } | 3172 | } |
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c index 0e5e59f84344..9f5fe372f83d 100644 --- a/drivers/isdn/i4l/isdn_ppp.c +++ b/drivers/isdn/i4l/isdn_ppp.c | |||
| @@ -190,9 +190,11 @@ isdn_ppp_bind(isdn_net_local * lp) | |||
| 190 | retval = -1; | 190 | retval = -1; |
| 191 | goto out; | 191 | goto out; |
| 192 | } | 192 | } |
| 193 | unit = isdn_ppp_if_get_unit(lp->name); /* get unit number from interface name .. ugly! */ | 193 | /* get unit number from interface name .. ugly! */ |
| 194 | unit = isdn_ppp_if_get_unit(lp->netdev->dev->name); | ||
| 194 | if (unit < 0) { | 195 | if (unit < 0) { |
| 195 | printk(KERN_ERR "isdn_ppp_bind: illegal interface name %s.\n", lp->name); | 196 | printk(KERN_ERR "isdn_ppp_bind: illegal interface name %s.\n", |
| 197 | lp->netdev->dev->name); | ||
| 196 | retval = -1; | 198 | retval = -1; |
| 197 | goto out; | 199 | goto out; |
| 198 | } | 200 | } |
| @@ -507,7 +509,8 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg) | |||
| 507 | case PPPIOCGIFNAME: | 509 | case PPPIOCGIFNAME: |
| 508 | if(!lp) | 510 | if(!lp) |
| 509 | return -EINVAL; | 511 | return -EINVAL; |
| 510 | if ((r = set_arg(argp, lp->name, strlen(lp->name)))) | 512 | if ((r = set_arg(argp, lp->netdev->dev->name, |
| 513 | strlen(lp->netdev->dev->name)))) | ||
| 511 | return r; | 514 | return r; |
| 512 | break; | 515 | break; |
| 513 | case PPPIOCGMPFLAGS: /* get configuration flags */ | 516 | case PPPIOCGMPFLAGS: /* get configuration flags */ |
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig index 56cd8998fe4b..77f50b63a970 100644 --- a/drivers/macintosh/Kconfig +++ b/drivers/macintosh/Kconfig | |||
| @@ -172,6 +172,7 @@ config INPUT_ADBHID | |||
| 172 | 172 | ||
| 173 | config MAC_EMUMOUSEBTN | 173 | config MAC_EMUMOUSEBTN |
| 174 | bool "Support for mouse button 2+3 emulation" | 174 | bool "Support for mouse button 2+3 emulation" |
| 175 | select INPUT | ||
| 175 | help | 176 | help |
| 176 | This provides generic support for emulating the 2nd and 3rd mouse | 177 | This provides generic support for emulating the 2nd and 3rd mouse |
| 177 | button with keypresses. If you say Y here, the emulation is still | 178 | button with keypresses. If you say Y here, the emulation is still |
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c index 48d17bf6c927..8cce016b3d09 100644 --- a/drivers/macintosh/adbhid.c +++ b/drivers/macintosh/adbhid.c | |||
| @@ -52,6 +52,11 @@ | |||
| 52 | 52 | ||
| 53 | MODULE_AUTHOR("Franz Sirl <Franz.Sirl-kernel@lauterbach.com>"); | 53 | MODULE_AUTHOR("Franz Sirl <Franz.Sirl-kernel@lauterbach.com>"); |
| 54 | 54 | ||
| 55 | static int restore_capslock_events; | ||
| 56 | module_param(restore_capslock_events, int, 0644); | ||
| 57 | MODULE_PARM_DESC(restore_capslock_events, | ||
| 58 | "Produce keypress events for capslock on both keyup and keydown."); | ||
| 59 | |||
| 55 | #define KEYB_KEYREG 0 /* register # for key up/down data */ | 60 | #define KEYB_KEYREG 0 /* register # for key up/down data */ |
| 56 | #define KEYB_LEDREG 2 /* register # for leds on ADB keyboard */ | 61 | #define KEYB_LEDREG 2 /* register # for leds on ADB keyboard */ |
| 57 | #define MOUSE_DATAREG 0 /* reg# for movement/button codes from mouse */ | 62 | #define MOUSE_DATAREG 0 /* reg# for movement/button codes from mouse */ |
| @@ -217,6 +222,8 @@ struct adbhid { | |||
| 217 | #define FLAG_FN_KEY_PRESSED 0x00000001 | 222 | #define FLAG_FN_KEY_PRESSED 0x00000001 |
| 218 | #define FLAG_POWER_FROM_FN 0x00000002 | 223 | #define FLAG_POWER_FROM_FN 0x00000002 |
| 219 | #define FLAG_EMU_FWDEL_DOWN 0x00000004 | 224 | #define FLAG_EMU_FWDEL_DOWN 0x00000004 |
| 225 | #define FLAG_CAPSLOCK_TRANSLATE 0x00000008 | ||
| 226 | #define FLAG_CAPSLOCK_DOWN 0x00000010 | ||
| 220 | 227 | ||
| 221 | static struct adbhid *adbhid[16]; | 228 | static struct adbhid *adbhid[16]; |
| 222 | 229 | ||
| @@ -272,19 +279,50 @@ adbhid_keyboard_input(unsigned char *data, int nb, int apoll) | |||
| 272 | } | 279 | } |
| 273 | 280 | ||
| 274 | static void | 281 | static void |
| 275 | adbhid_input_keycode(int id, int keycode, int repeat) | 282 | adbhid_input_keycode(int id, int scancode, int repeat) |
| 276 | { | 283 | { |
| 277 | struct adbhid *ahid = adbhid[id]; | 284 | struct adbhid *ahid = adbhid[id]; |
| 278 | int up_flag, key; | 285 | int keycode, up_flag; |
| 279 | 286 | ||
| 280 | up_flag = (keycode & 0x80); | 287 | keycode = scancode & 0x7f; |
| 281 | keycode &= 0x7f; | 288 | up_flag = scancode & 0x80; |
| 289 | |||
| 290 | if (restore_capslock_events) { | ||
| 291 | if (keycode == ADB_KEY_CAPSLOCK && !up_flag) { | ||
| 292 | /* Key pressed, turning on the CapsLock LED. | ||
| 293 | * The next 0xff will be interpreted as a release. */ | ||
| 294 | ahid->flags |= FLAG_CAPSLOCK_TRANSLATE | ||
| 295 | | FLAG_CAPSLOCK_DOWN; | ||
| 296 | } else if (scancode == 0xff) { | ||
| 297 | /* Scancode 0xff usually signifies that the capslock | ||
| 298 | * key was either pressed or released. */ | ||
| 299 | if (ahid->flags & FLAG_CAPSLOCK_TRANSLATE) { | ||
| 300 | keycode = ADB_KEY_CAPSLOCK; | ||
| 301 | if (ahid->flags & FLAG_CAPSLOCK_DOWN) { | ||
| 302 | /* Key released */ | ||
| 303 | up_flag = 1; | ||
| 304 | ahid->flags &= ~FLAG_CAPSLOCK_DOWN; | ||
| 305 | } else { | ||
| 306 | /* Key pressed */ | ||
| 307 | up_flag = 0; | ||
| 308 | ahid->flags &= ~FLAG_CAPSLOCK_TRANSLATE; | ||
| 309 | } | ||
| 310 | } else { | ||
| 311 | printk(KERN_INFO "Spurious caps lock event " | ||
| 312 | "(scancode 0xff)."); | ||
| 313 | } | ||
| 314 | } | ||
| 315 | } | ||
| 282 | 316 | ||
| 283 | switch (keycode) { | 317 | switch (keycode) { |
| 284 | case ADB_KEY_CAPSLOCK: /* Generate down/up events for CapsLock everytime. */ | 318 | case ADB_KEY_CAPSLOCK: |
| 285 | input_report_key(ahid->input, KEY_CAPSLOCK, 1); | 319 | if (!restore_capslock_events) { |
| 286 | input_report_key(ahid->input, KEY_CAPSLOCK, 0); | 320 | /* Generate down/up events for CapsLock everytime. */ |
| 287 | input_sync(ahid->input); | 321 | input_report_key(ahid->input, KEY_CAPSLOCK, 1); |
| 322 | input_sync(ahid->input); | ||
| 323 | input_report_key(ahid->input, KEY_CAPSLOCK, 0); | ||
| 324 | input_sync(ahid->input); | ||
| 325 | } | ||
| 288 | return; | 326 | return; |
| 289 | #ifdef CONFIG_PPC_PMAC | 327 | #ifdef CONFIG_PPC_PMAC |
| 290 | case ADB_KEY_POWER_OLD: /* Power key on PBook 3400 needs remapping */ | 328 | case ADB_KEY_POWER_OLD: /* Power key on PBook 3400 needs remapping */ |
| @@ -296,7 +334,7 @@ adbhid_input_keycode(int id, int keycode, int repeat) | |||
| 296 | keycode = ADB_KEY_POWER; | 334 | keycode = ADB_KEY_POWER; |
| 297 | } | 335 | } |
| 298 | break; | 336 | break; |
| 299 | case ADB_KEY_POWER: | 337 | case ADB_KEY_POWER: |
| 300 | /* Fn + Command will produce a bogus "power" keycode */ | 338 | /* Fn + Command will produce a bogus "power" keycode */ |
| 301 | if (ahid->flags & FLAG_FN_KEY_PRESSED) { | 339 | if (ahid->flags & FLAG_FN_KEY_PRESSED) { |
| 302 | keycode = ADB_KEY_CMD; | 340 | keycode = ADB_KEY_CMD; |
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 216948dd71a5..81e068fa7ac5 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c | |||
| @@ -945,15 +945,15 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
| 945 | KEY_UNKNOWN, /* 0x0C: FN+BACKSPACE */ | 945 | KEY_UNKNOWN, /* 0x0C: FN+BACKSPACE */ |
| 946 | KEY_UNKNOWN, /* 0x0D: FN+INSERT */ | 946 | KEY_UNKNOWN, /* 0x0D: FN+INSERT */ |
| 947 | KEY_UNKNOWN, /* 0x0E: FN+DELETE */ | 947 | KEY_UNKNOWN, /* 0x0E: FN+DELETE */ |
| 948 | KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */ | 948 | KEY_BRIGHTNESSUP, /* 0x0F: FN+HOME (brightness up) */ |
| 949 | /* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */ | 949 | /* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */ |
| 950 | KEY_RESERVED, /* 0x10: FN+END (brightness down) */ | 950 | KEY_BRIGHTNESSDOWN, /* 0x10: FN+END (brightness down) */ |
| 951 | KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */ | 951 | KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */ |
| 952 | KEY_UNKNOWN, /* 0x12: FN+PGDOWN */ | 952 | KEY_UNKNOWN, /* 0x12: FN+PGDOWN */ |
| 953 | KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */ | 953 | KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */ |
| 954 | KEY_RESERVED, /* 0x14: VOLUME UP */ | 954 | KEY_VOLUMEUP, /* 0x14: VOLUME UP */ |
| 955 | KEY_RESERVED, /* 0x15: VOLUME DOWN */ | 955 | KEY_VOLUMEDOWN, /* 0x15: VOLUME DOWN */ |
| 956 | KEY_RESERVED, /* 0x16: MUTE */ | 956 | KEY_MUTE, /* 0x16: MUTE */ |
| 957 | KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */ | 957 | KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */ |
| 958 | /* (assignments unknown, please report if found) */ | 958 | /* (assignments unknown, please report if found) */ |
| 959 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, | 959 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, |
| @@ -974,9 +974,9 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
| 974 | KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */ | 974 | KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */ |
| 975 | KEY_UNKNOWN, /* 0x12: FN+PGDOWN */ | 975 | KEY_UNKNOWN, /* 0x12: FN+PGDOWN */ |
| 976 | KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */ | 976 | KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */ |
| 977 | KEY_RESERVED, /* 0x14: VOLUME UP */ | 977 | KEY_VOLUMEUP, /* 0x14: VOLUME UP */ |
| 978 | KEY_RESERVED, /* 0x15: VOLUME DOWN */ | 978 | KEY_VOLUMEDOWN, /* 0x15: VOLUME DOWN */ |
| 979 | KEY_RESERVED, /* 0x16: MUTE */ | 979 | KEY_MUTE, /* 0x16: MUTE */ |
| 980 | KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */ | 980 | KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */ |
| 981 | /* (assignments unknown, please report if found) */ | 981 | /* (assignments unknown, please report if found) */ |
| 982 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, | 982 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, |
diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c index cb933ac475d5..82113295c266 100644 --- a/drivers/mtd/maps/pxa2xx-flash.c +++ b/drivers/mtd/maps/pxa2xx-flash.c | |||
| @@ -14,20 +14,20 @@ | |||
| 14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
| 15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
| 16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
| 17 | #include <linux/dma-mapping.h> | ||
| 18 | #include <linux/mtd/mtd.h> | 17 | #include <linux/mtd/mtd.h> |
| 19 | #include <linux/mtd/map.h> | 18 | #include <linux/mtd/map.h> |
| 20 | #include <linux/mtd/partitions.h> | 19 | #include <linux/mtd/partitions.h> |
| 21 | 20 | ||
| 22 | #include <asm/io.h> | 21 | #include <asm/io.h> |
| 23 | #include <asm/hardware.h> | 22 | #include <asm/hardware.h> |
| 23 | #include <asm/cacheflush.h> | ||
| 24 | 24 | ||
| 25 | #include <asm/mach/flash.h> | 25 | #include <asm/mach/flash.h> |
| 26 | 26 | ||
| 27 | static void pxa2xx_map_inval_cache(struct map_info *map, unsigned long from, | 27 | static void pxa2xx_map_inval_cache(struct map_info *map, unsigned long from, |
| 28 | ssize_t len) | 28 | ssize_t len) |
| 29 | { | 29 | { |
| 30 | consistent_sync((char *)map->cached + from, len, DMA_FROM_DEVICE); | 30 | flush_ioremap_region(map->phys, map->cached, from, len); |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | struct pxa2xx_flash_info { | 33 | struct pxa2xx_flash_info { |
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 9c635a237a9d..8f99a0626616 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
| @@ -1780,6 +1780,15 @@ config SC92031 | |||
| 1780 | To compile this driver as a module, choose M here: the module | 1780 | To compile this driver as a module, choose M here: the module |
| 1781 | will be called sc92031. This is recommended. | 1781 | will be called sc92031. This is recommended. |
| 1782 | 1782 | ||
| 1783 | config CPMAC | ||
| 1784 | tristate "TI AR7 CPMAC Ethernet support (EXPERIMENTAL)" | ||
| 1785 | depends on NET_ETHERNET && EXPERIMENTAL && AR7 | ||
| 1786 | select PHYLIB | ||
| 1787 | select FIXED_PHY | ||
| 1788 | select FIXED_MII_100_FDX | ||
| 1789 | help | ||
| 1790 | TI AR7 CPMAC Ethernet support | ||
| 1791 | |||
| 1783 | config NET_POCKET | 1792 | config NET_POCKET |
| 1784 | bool "Pocket and portable adapters" | 1793 | bool "Pocket and portable adapters" |
| 1785 | depends on PARPORT | 1794 | depends on PARPORT |
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index d2e0f35da42e..22f78cbd126b 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile | |||
| @@ -159,6 +159,7 @@ obj-$(CONFIG_8139CP) += 8139cp.o | |||
| 159 | obj-$(CONFIG_8139TOO) += 8139too.o | 159 | obj-$(CONFIG_8139TOO) += 8139too.o |
| 160 | obj-$(CONFIG_ZNET) += znet.o | 160 | obj-$(CONFIG_ZNET) += znet.o |
| 161 | obj-$(CONFIG_LAN_SAA9730) += saa9730.o | 161 | obj-$(CONFIG_LAN_SAA9730) += saa9730.o |
| 162 | obj-$(CONFIG_CPMAC) += cpmac.o | ||
| 162 | obj-$(CONFIG_DEPCA) += depca.o | 163 | obj-$(CONFIG_DEPCA) += depca.o |
| 163 | obj-$(CONFIG_EWRK3) += ewrk3.o | 164 | obj-$(CONFIG_EWRK3) += ewrk3.o |
| 164 | obj-$(CONFIG_ATP) += atp.o | 165 | obj-$(CONFIG_ATP) += atp.o |
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index b46c5d8a77bd..185f98e3964c 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c | |||
| @@ -54,13 +54,16 @@ | |||
| 54 | #include <linux/delay.h> | 54 | #include <linux/delay.h> |
| 55 | #include <linux/crc32.h> | 55 | #include <linux/crc32.h> |
| 56 | #include <linux/phy.h> | 56 | #include <linux/phy.h> |
| 57 | |||
| 58 | #include <asm/cpu.h> | ||
| 57 | #include <asm/mipsregs.h> | 59 | #include <asm/mipsregs.h> |
| 58 | #include <asm/irq.h> | 60 | #include <asm/irq.h> |
| 59 | #include <asm/io.h> | 61 | #include <asm/io.h> |
| 60 | #include <asm/processor.h> | 62 | #include <asm/processor.h> |
| 61 | 63 | ||
| 62 | #include <asm/mach-au1x00/au1000.h> | 64 | #include <au1000.h> |
| 63 | #include <asm/cpu.h> | 65 | #include <prom.h> |
| 66 | |||
| 64 | #include "au1000_eth.h" | 67 | #include "au1000_eth.h" |
| 65 | 68 | ||
| 66 | #ifdef AU1000_ETH_DEBUG | 69 | #ifdef AU1000_ETH_DEBUG |
| @@ -96,11 +99,6 @@ static void mdio_write(struct net_device *, int, int, u16); | |||
| 96 | static void au1000_adjust_link(struct net_device *); | 99 | static void au1000_adjust_link(struct net_device *); |
| 97 | static void enable_mac(struct net_device *, int); | 100 | static void enable_mac(struct net_device *, int); |
| 98 | 101 | ||
| 99 | // externs | ||
| 100 | extern int get_ethernet_addr(char *ethernet_addr); | ||
| 101 | extern void str2eaddr(unsigned char *ea, unsigned char *str); | ||
| 102 | extern char * prom_getcmdline(void); | ||
| 103 | |||
| 104 | /* | 102 | /* |
| 105 | * Theory of operation | 103 | * Theory of operation |
| 106 | * | 104 | * |
| @@ -619,7 +617,6 @@ static struct net_device * au1000_probe(int port_num) | |||
| 619 | struct au1000_private *aup = NULL; | 617 | struct au1000_private *aup = NULL; |
| 620 | struct net_device *dev = NULL; | 618 | struct net_device *dev = NULL; |
| 621 | db_dest_t *pDB, *pDBfree; | 619 | db_dest_t *pDB, *pDBfree; |
| 622 | char *pmac, *argptr; | ||
| 623 | char ethaddr[6]; | 620 | char ethaddr[6]; |
| 624 | int irq, i, err; | 621 | int irq, i, err; |
| 625 | u32 base, macen; | 622 | u32 base, macen; |
| @@ -677,21 +674,12 @@ static struct net_device * au1000_probe(int port_num) | |||
| 677 | au_macs[port_num] = aup; | 674 | au_macs[port_num] = aup; |
| 678 | 675 | ||
| 679 | if (port_num == 0) { | 676 | if (port_num == 0) { |
| 680 | /* Check the environment variables first */ | 677 | if (prom_get_ethernet_addr(ethaddr) == 0) |
| 681 | if (get_ethernet_addr(ethaddr) == 0) | ||
| 682 | memcpy(au1000_mac_addr, ethaddr, sizeof(au1000_mac_addr)); | 678 | memcpy(au1000_mac_addr, ethaddr, sizeof(au1000_mac_addr)); |
| 683 | else { | 679 | else { |
| 684 | /* Check command line */ | 680 | printk(KERN_INFO "%s: No MAC address found\n", |
| 685 | argptr = prom_getcmdline(); | 681 | dev->name); |
| 686 | if ((pmac = strstr(argptr, "ethaddr=")) == NULL) | ||
| 687 | printk(KERN_INFO "%s: No MAC address found\n", | ||
| 688 | dev->name); | ||
| 689 | /* Use the hard coded MAC addresses */ | 682 | /* Use the hard coded MAC addresses */ |
| 690 | else { | ||
| 691 | str2eaddr(ethaddr, pmac + strlen("ethaddr=")); | ||
| 692 | memcpy(au1000_mac_addr, ethaddr, | ||
| 693 | sizeof(au1000_mac_addr)); | ||
| 694 | } | ||
| 695 | } | 683 | } |
| 696 | 684 | ||
| 697 | setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR); | 685 | setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR); |
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 64bfec32e2a6..db80f243dd37 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
| @@ -98,6 +98,7 @@ static char *xmit_hash_policy = NULL; | |||
| 98 | static int arp_interval = BOND_LINK_ARP_INTERV; | 98 | static int arp_interval = BOND_LINK_ARP_INTERV; |
| 99 | static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, }; | 99 | static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, }; |
| 100 | static char *arp_validate = NULL; | 100 | static char *arp_validate = NULL; |
| 101 | static int fail_over_mac = 0; | ||
| 101 | struct bond_params bonding_defaults; | 102 | struct bond_params bonding_defaults; |
| 102 | 103 | ||
| 103 | module_param(max_bonds, int, 0); | 104 | module_param(max_bonds, int, 0); |
| @@ -131,6 +132,8 @@ module_param_array(arp_ip_target, charp, NULL, 0); | |||
| 131 | MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form"); | 132 | MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form"); |
| 132 | module_param(arp_validate, charp, 0); | 133 | module_param(arp_validate, charp, 0); |
| 133 | MODULE_PARM_DESC(arp_validate, "validate src/dst of ARP probes: none (default), active, backup or all"); | 134 | MODULE_PARM_DESC(arp_validate, "validate src/dst of ARP probes: none (default), active, backup or all"); |
| 135 | module_param(fail_over_mac, int, 0); | ||
| 136 | MODULE_PARM_DESC(fail_over_mac, "For active-backup, do not set all slaves to the same MAC. 0 of off (default), 1 for on."); | ||
| 134 | 137 | ||
| 135 | /*----------------------------- Global variables ----------------------------*/ | 138 | /*----------------------------- Global variables ----------------------------*/ |
| 136 | 139 | ||
| @@ -1096,7 +1099,21 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) | |||
| 1096 | if (new_active) { | 1099 | if (new_active) { |
| 1097 | bond_set_slave_active_flags(new_active); | 1100 | bond_set_slave_active_flags(new_active); |
| 1098 | } | 1101 | } |
| 1099 | bond_send_gratuitous_arp(bond); | 1102 | |
| 1103 | /* when bonding does not set the slave MAC address, the bond MAC | ||
| 1104 | * address is the one of the active slave. | ||
| 1105 | */ | ||
| 1106 | if (new_active && bond->params.fail_over_mac) | ||
| 1107 | memcpy(bond->dev->dev_addr, new_active->dev->dev_addr, | ||
| 1108 | new_active->dev->addr_len); | ||
| 1109 | if (bond->curr_active_slave && | ||
| 1110 | test_bit(__LINK_STATE_LINKWATCH_PENDING, | ||
| 1111 | &bond->curr_active_slave->dev->state)) { | ||
| 1112 | dprintk("delaying gratuitous arp on %s\n", | ||
| 1113 | bond->curr_active_slave->dev->name); | ||
| 1114 | bond->send_grat_arp = 1; | ||
| 1115 | } else | ||
| 1116 | bond_send_gratuitous_arp(bond); | ||
| 1100 | } | 1117 | } |
| 1101 | } | 1118 | } |
| 1102 | 1119 | ||
| @@ -1217,7 +1234,8 @@ static int bond_compute_features(struct bonding *bond) | |||
| 1217 | struct slave *slave; | 1234 | struct slave *slave; |
| 1218 | struct net_device *bond_dev = bond->dev; | 1235 | struct net_device *bond_dev = bond->dev; |
| 1219 | unsigned long features = bond_dev->features; | 1236 | unsigned long features = bond_dev->features; |
| 1220 | unsigned short max_hard_header_len = ETH_HLEN; | 1237 | unsigned short max_hard_header_len = max((u16)ETH_HLEN, |
| 1238 | bond_dev->hard_header_len); | ||
| 1221 | int i; | 1239 | int i; |
| 1222 | 1240 | ||
| 1223 | features &= ~(NETIF_F_ALL_CSUM | BOND_VLAN_FEATURES); | 1241 | features &= ~(NETIF_F_ALL_CSUM | BOND_VLAN_FEATURES); |
| @@ -1238,6 +1256,23 @@ static int bond_compute_features(struct bonding *bond) | |||
| 1238 | return 0; | 1256 | return 0; |
| 1239 | } | 1257 | } |
| 1240 | 1258 | ||
| 1259 | |||
| 1260 | static void bond_setup_by_slave(struct net_device *bond_dev, | ||
| 1261 | struct net_device *slave_dev) | ||
| 1262 | { | ||
| 1263 | struct bonding *bond = bond_dev->priv; | ||
| 1264 | |||
| 1265 | bond_dev->neigh_setup = slave_dev->neigh_setup; | ||
| 1266 | |||
| 1267 | bond_dev->type = slave_dev->type; | ||
| 1268 | bond_dev->hard_header_len = slave_dev->hard_header_len; | ||
| 1269 | bond_dev->addr_len = slave_dev->addr_len; | ||
| 1270 | |||
| 1271 | memcpy(bond_dev->broadcast, slave_dev->broadcast, | ||
| 1272 | slave_dev->addr_len); | ||
| 1273 | bond->setup_by_slave = 1; | ||
| 1274 | } | ||
| 1275 | |||
| 1241 | /* enslave device <slave> to bond device <master> */ | 1276 | /* enslave device <slave> to bond device <master> */ |
| 1242 | int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | 1277 | int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) |
| 1243 | { | 1278 | { |
| @@ -1258,8 +1293,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
| 1258 | 1293 | ||
| 1259 | /* bond must be initialized by bond_open() before enslaving */ | 1294 | /* bond must be initialized by bond_open() before enslaving */ |
| 1260 | if (!(bond_dev->flags & IFF_UP)) { | 1295 | if (!(bond_dev->flags & IFF_UP)) { |
| 1261 | dprintk("Error, master_dev is not up\n"); | 1296 | printk(KERN_WARNING DRV_NAME |
| 1262 | return -EPERM; | 1297 | " %s: master_dev is not up in bond_enslave\n", |
| 1298 | bond_dev->name); | ||
| 1263 | } | 1299 | } |
| 1264 | 1300 | ||
| 1265 | /* already enslaved */ | 1301 | /* already enslaved */ |
| @@ -1312,14 +1348,42 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
| 1312 | goto err_undo_flags; | 1348 | goto err_undo_flags; |
| 1313 | } | 1349 | } |
| 1314 | 1350 | ||
| 1351 | /* set bonding device ether type by slave - bonding netdevices are | ||
| 1352 | * created with ether_setup, so when the slave type is not ARPHRD_ETHER | ||
| 1353 | * there is a need to override some of the type dependent attribs/funcs. | ||
| 1354 | * | ||
| 1355 | * bond ether type mutual exclusion - don't allow slaves of dissimilar | ||
| 1356 | * ether type (eg ARPHRD_ETHER and ARPHRD_INFINIBAND) share the same bond | ||
| 1357 | */ | ||
| 1358 | if (bond->slave_cnt == 0) { | ||
| 1359 | if (slave_dev->type != ARPHRD_ETHER) | ||
| 1360 | bond_setup_by_slave(bond_dev, slave_dev); | ||
| 1361 | } else if (bond_dev->type != slave_dev->type) { | ||
| 1362 | printk(KERN_ERR DRV_NAME ": %s ether type (%d) is different " | ||
| 1363 | "from other slaves (%d), can not enslave it.\n", | ||
| 1364 | slave_dev->name, | ||
| 1365 | slave_dev->type, bond_dev->type); | ||
| 1366 | res = -EINVAL; | ||
| 1367 | goto err_undo_flags; | ||
| 1368 | } | ||
| 1369 | |||
| 1315 | if (slave_dev->set_mac_address == NULL) { | 1370 | if (slave_dev->set_mac_address == NULL) { |
| 1316 | printk(KERN_ERR DRV_NAME | 1371 | if (bond->slave_cnt == 0) { |
| 1317 | ": %s: Error: The slave device you specified does " | 1372 | printk(KERN_WARNING DRV_NAME |
| 1318 | "not support setting the MAC address. " | 1373 | ": %s: Warning: The first slave device " |
| 1319 | "Your kernel likely does not support slave " | 1374 | "specified does not support setting the MAC " |
| 1320 | "devices.\n", bond_dev->name); | 1375 | "address. Enabling the fail_over_mac option.", |
| 1321 | res = -EOPNOTSUPP; | 1376 | bond_dev->name); |
| 1322 | goto err_undo_flags; | 1377 | bond->params.fail_over_mac = 1; |
| 1378 | } else if (!bond->params.fail_over_mac) { | ||
| 1379 | printk(KERN_ERR DRV_NAME | ||
| 1380 | ": %s: Error: The slave device specified " | ||
| 1381 | "does not support setting the MAC address, " | ||
| 1382 | "but fail_over_mac is not enabled.\n" | ||
| 1383 | , bond_dev->name); | ||
| 1384 | res = -EOPNOTSUPP; | ||
| 1385 | goto err_undo_flags; | ||
| 1386 | } | ||
| 1323 | } | 1387 | } |
| 1324 | 1388 | ||
| 1325 | new_slave = kzalloc(sizeof(struct slave), GFP_KERNEL); | 1389 | new_slave = kzalloc(sizeof(struct slave), GFP_KERNEL); |
| @@ -1340,16 +1404,18 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
| 1340 | */ | 1404 | */ |
| 1341 | memcpy(new_slave->perm_hwaddr, slave_dev->dev_addr, ETH_ALEN); | 1405 | memcpy(new_slave->perm_hwaddr, slave_dev->dev_addr, ETH_ALEN); |
| 1342 | 1406 | ||
| 1343 | /* | 1407 | if (!bond->params.fail_over_mac) { |
| 1344 | * Set slave to master's mac address. The application already | 1408 | /* |
| 1345 | * set the master's mac address to that of the first slave | 1409 | * Set slave to master's mac address. The application already |
| 1346 | */ | 1410 | * set the master's mac address to that of the first slave |
| 1347 | memcpy(addr.sa_data, bond_dev->dev_addr, bond_dev->addr_len); | 1411 | */ |
| 1348 | addr.sa_family = slave_dev->type; | 1412 | memcpy(addr.sa_data, bond_dev->dev_addr, bond_dev->addr_len); |
| 1349 | res = dev_set_mac_address(slave_dev, &addr); | 1413 | addr.sa_family = slave_dev->type; |
| 1350 | if (res) { | 1414 | res = dev_set_mac_address(slave_dev, &addr); |
| 1351 | dprintk("Error %d calling set_mac_address\n", res); | 1415 | if (res) { |
| 1352 | goto err_free; | 1416 | dprintk("Error %d calling set_mac_address\n", res); |
| 1417 | goto err_free; | ||
| 1418 | } | ||
| 1353 | } | 1419 | } |
| 1354 | 1420 | ||
| 1355 | res = netdev_set_master(slave_dev, bond_dev); | 1421 | res = netdev_set_master(slave_dev, bond_dev); |
| @@ -1574,9 +1640,11 @@ err_close: | |||
| 1574 | dev_close(slave_dev); | 1640 | dev_close(slave_dev); |
| 1575 | 1641 | ||
| 1576 | err_restore_mac: | 1642 | err_restore_mac: |
| 1577 | memcpy(addr.sa_data, new_slave->perm_hwaddr, ETH_ALEN); | 1643 | if (!bond->params.fail_over_mac) { |
| 1578 | addr.sa_family = slave_dev->type; | 1644 | memcpy(addr.sa_data, new_slave->perm_hwaddr, ETH_ALEN); |
| 1579 | dev_set_mac_address(slave_dev, &addr); | 1645 | addr.sa_family = slave_dev->type; |
| 1646 | dev_set_mac_address(slave_dev, &addr); | ||
| 1647 | } | ||
| 1580 | 1648 | ||
| 1581 | err_free: | 1649 | err_free: |
| 1582 | kfree(new_slave); | 1650 | kfree(new_slave); |
| @@ -1749,10 +1817,12 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) | |||
| 1749 | /* close slave before restoring its mac address */ | 1817 | /* close slave before restoring its mac address */ |
| 1750 | dev_close(slave_dev); | 1818 | dev_close(slave_dev); |
| 1751 | 1819 | ||
| 1752 | /* restore original ("permanent") mac address */ | 1820 | if (!bond->params.fail_over_mac) { |
| 1753 | memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN); | 1821 | /* restore original ("permanent") mac address */ |
| 1754 | addr.sa_family = slave_dev->type; | 1822 | memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN); |
| 1755 | dev_set_mac_address(slave_dev, &addr); | 1823 | addr.sa_family = slave_dev->type; |
| 1824 | dev_set_mac_address(slave_dev, &addr); | ||
| 1825 | } | ||
| 1756 | 1826 | ||
| 1757 | slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB | | 1827 | slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB | |
| 1758 | IFF_SLAVE_INACTIVE | IFF_BONDING | | 1828 | IFF_SLAVE_INACTIVE | IFF_BONDING | |
| @@ -1764,6 +1834,35 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) | |||
| 1764 | } | 1834 | } |
| 1765 | 1835 | ||
| 1766 | /* | 1836 | /* |
| 1837 | * Destroy a bonding device. | ||
| 1838 | * Must be under rtnl_lock when this function is called. | ||
| 1839 | */ | ||
| 1840 | void bond_destroy(struct bonding *bond) | ||
| 1841 | { | ||
| 1842 | bond_deinit(bond->dev); | ||
| 1843 | bond_destroy_sysfs_entry(bond); | ||
| 1844 | unregister_netdevice(bond->dev); | ||
| 1845 | } | ||
| 1846 | |||
| 1847 | /* | ||
| 1848 | * First release a slave and than destroy the bond if no more slaves iare left. | ||
| 1849 | * Must be under rtnl_lock when this function is called. | ||
| 1850 | */ | ||
| 1851 | int bond_release_and_destroy(struct net_device *bond_dev, struct net_device *slave_dev) | ||
| 1852 | { | ||
| 1853 | struct bonding *bond = bond_dev->priv; | ||
| 1854 | int ret; | ||
| 1855 | |||
| 1856 | ret = bond_release(bond_dev, slave_dev); | ||
| 1857 | if ((ret == 0) && (bond->slave_cnt == 0)) { | ||
| 1858 | printk(KERN_INFO DRV_NAME ": %s: destroying bond %s.\n", | ||
| 1859 | bond_dev->name, bond_dev->name); | ||
| 1860 | bond_destroy(bond); | ||
| 1861 | } | ||
| 1862 | return ret; | ||
| 1863 | } | ||
| 1864 | |||
| 1865 | /* | ||
| 1767 | * This function releases all slaves. | 1866 | * This function releases all slaves. |
| 1768 | */ | 1867 | */ |
| 1769 | static int bond_release_all(struct net_device *bond_dev) | 1868 | static int bond_release_all(struct net_device *bond_dev) |
| @@ -1839,10 +1938,12 @@ static int bond_release_all(struct net_device *bond_dev) | |||
| 1839 | /* close slave before restoring its mac address */ | 1938 | /* close slave before restoring its mac address */ |
| 1840 | dev_close(slave_dev); | 1939 | dev_close(slave_dev); |
| 1841 | 1940 | ||
| 1842 | /* restore original ("permanent") mac address*/ | 1941 | if (!bond->params.fail_over_mac) { |
| 1843 | memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN); | 1942 | /* restore original ("permanent") mac address*/ |
| 1844 | addr.sa_family = slave_dev->type; | 1943 | memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN); |
| 1845 | dev_set_mac_address(slave_dev, &addr); | 1944 | addr.sa_family = slave_dev->type; |
| 1945 | dev_set_mac_address(slave_dev, &addr); | ||
| 1946 | } | ||
| 1846 | 1947 | ||
| 1847 | slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB | | 1948 | slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB | |
| 1848 | IFF_SLAVE_INACTIVE); | 1949 | IFF_SLAVE_INACTIVE); |
| @@ -2013,6 +2114,17 @@ void bond_mii_monitor(struct net_device *bond_dev) | |||
| 2013 | * program could monitor the link itself if needed. | 2114 | * program could monitor the link itself if needed. |
| 2014 | */ | 2115 | */ |
| 2015 | 2116 | ||
| 2117 | if (bond->send_grat_arp) { | ||
| 2118 | if (bond->curr_active_slave && test_bit(__LINK_STATE_LINKWATCH_PENDING, | ||
| 2119 | &bond->curr_active_slave->dev->state)) | ||
| 2120 | dprintk("Needs to send gratuitous arp but not yet\n"); | ||
| 2121 | else { | ||
| 2122 | dprintk("sending delayed gratuitous arp on on %s\n", | ||
| 2123 | bond->curr_active_slave->dev->name); | ||
| 2124 | bond_send_gratuitous_arp(bond); | ||
| 2125 | bond->send_grat_arp = 0; | ||
| 2126 | } | ||
| 2127 | } | ||
| 2016 | read_lock(&bond->curr_slave_lock); | 2128 | read_lock(&bond->curr_slave_lock); |
| 2017 | oldcurrent = bond->curr_active_slave; | 2129 | oldcurrent = bond->curr_active_slave; |
| 2018 | read_unlock(&bond->curr_slave_lock); | 2130 | read_unlock(&bond->curr_slave_lock); |
| @@ -2414,7 +2526,7 @@ static void bond_send_gratuitous_arp(struct bonding *bond) | |||
| 2414 | 2526 | ||
| 2415 | if (bond->master_ip) { | 2527 | if (bond->master_ip) { |
| 2416 | bond_arp_send(slave->dev, ARPOP_REPLY, bond->master_ip, | 2528 | bond_arp_send(slave->dev, ARPOP_REPLY, bond->master_ip, |
| 2417 | bond->master_ip, 0); | 2529 | bond->master_ip, 0); |
| 2418 | } | 2530 | } |
| 2419 | 2531 | ||
| 2420 | list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { | 2532 | list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { |
| @@ -2951,9 +3063,15 @@ static void bond_info_show_master(struct seq_file *seq) | |||
| 2951 | curr = bond->curr_active_slave; | 3063 | curr = bond->curr_active_slave; |
| 2952 | read_unlock(&bond->curr_slave_lock); | 3064 | read_unlock(&bond->curr_slave_lock); |
| 2953 | 3065 | ||
| 2954 | seq_printf(seq, "Bonding Mode: %s\n", | 3066 | seq_printf(seq, "Bonding Mode: %s", |
| 2955 | bond_mode_name(bond->params.mode)); | 3067 | bond_mode_name(bond->params.mode)); |
| 2956 | 3068 | ||
| 3069 | if (bond->params.mode == BOND_MODE_ACTIVEBACKUP && | ||
| 3070 | bond->params.fail_over_mac) | ||
| 3071 | seq_printf(seq, " (fail_over_mac)"); | ||
| 3072 | |||
| 3073 | seq_printf(seq, "\n"); | ||
| 3074 | |||
| 2957 | if (bond->params.mode == BOND_MODE_XOR || | 3075 | if (bond->params.mode == BOND_MODE_XOR || |
| 2958 | bond->params.mode == BOND_MODE_8023AD) { | 3076 | bond->params.mode == BOND_MODE_8023AD) { |
| 2959 | seq_printf(seq, "Transmit Hash Policy: %s (%d)\n", | 3077 | seq_printf(seq, "Transmit Hash Policy: %s (%d)\n", |
| @@ -3248,6 +3366,11 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave | |||
| 3248 | * ... Or is it this? | 3366 | * ... Or is it this? |
| 3249 | */ | 3367 | */ |
| 3250 | break; | 3368 | break; |
| 3369 | case NETDEV_GOING_DOWN: | ||
| 3370 | dprintk("slave %s is going down\n", slave_dev->name); | ||
| 3371 | if (bond->setup_by_slave) | ||
| 3372 | bond_release_and_destroy(bond_dev, slave_dev); | ||
| 3373 | break; | ||
| 3251 | case NETDEV_CHANGEMTU: | 3374 | case NETDEV_CHANGEMTU: |
| 3252 | /* | 3375 | /* |
| 3253 | * TODO: Should slaves be allowed to | 3376 | * TODO: Should slaves be allowed to |
| @@ -3880,6 +4003,13 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr) | |||
| 3880 | 4003 | ||
| 3881 | dprintk("bond=%p, name=%s\n", bond, (bond_dev ? bond_dev->name : "None")); | 4004 | dprintk("bond=%p, name=%s\n", bond, (bond_dev ? bond_dev->name : "None")); |
| 3882 | 4005 | ||
| 4006 | /* | ||
| 4007 | * If fail_over_mac is enabled, do nothing and return success. | ||
| 4008 | * Returning an error causes ifenslave to fail. | ||
| 4009 | */ | ||
| 4010 | if (bond->params.fail_over_mac) | ||
| 4011 | return 0; | ||
| 4012 | |||
| 3883 | if (!is_valid_ether_addr(sa->sa_data)) { | 4013 | if (!is_valid_ether_addr(sa->sa_data)) { |
| 3884 | return -EADDRNOTAVAIL; | 4014 | return -EADDRNOTAVAIL; |
| 3885 | } | 4015 | } |
| @@ -4217,6 +4347,8 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params) | |||
| 4217 | bond->current_arp_slave = NULL; | 4347 | bond->current_arp_slave = NULL; |
| 4218 | bond->primary_slave = NULL; | 4348 | bond->primary_slave = NULL; |
| 4219 | bond->dev = bond_dev; | 4349 | bond->dev = bond_dev; |
| 4350 | bond->send_grat_arp = 0; | ||
| 4351 | bond->setup_by_slave = 0; | ||
| 4220 | INIT_LIST_HEAD(&bond->vlan_list); | 4352 | INIT_LIST_HEAD(&bond->vlan_list); |
| 4221 | 4353 | ||
| 4222 | /* Initialize the device entry points */ | 4354 | /* Initialize the device entry points */ |
| @@ -4265,7 +4397,6 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params) | |||
| 4265 | #ifdef CONFIG_PROC_FS | 4397 | #ifdef CONFIG_PROC_FS |
| 4266 | bond_create_proc_entry(bond); | 4398 | bond_create_proc_entry(bond); |
| 4267 | #endif | 4399 | #endif |
| 4268 | |||
| 4269 | list_add_tail(&bond->bond_list, &bond_dev_list); | 4400 | list_add_tail(&bond->bond_list, &bond_dev_list); |
| 4270 | 4401 | ||
| 4271 | return 0; | 4402 | return 0; |
| @@ -4599,6 +4730,11 @@ static int bond_check_params(struct bond_params *params) | |||
| 4599 | primary = NULL; | 4730 | primary = NULL; |
| 4600 | } | 4731 | } |
| 4601 | 4732 | ||
| 4733 | if (fail_over_mac && (bond_mode != BOND_MODE_ACTIVEBACKUP)) | ||
| 4734 | printk(KERN_WARNING DRV_NAME | ||
| 4735 | ": Warning: fail_over_mac only affects " | ||
| 4736 | "active-backup mode.\n"); | ||
| 4737 | |||
| 4602 | /* fill params struct with the proper values */ | 4738 | /* fill params struct with the proper values */ |
| 4603 | params->mode = bond_mode; | 4739 | params->mode = bond_mode; |
| 4604 | params->xmit_policy = xmit_hashtype; | 4740 | params->xmit_policy = xmit_hashtype; |
| @@ -4610,6 +4746,7 @@ static int bond_check_params(struct bond_params *params) | |||
| 4610 | params->use_carrier = use_carrier; | 4746 | params->use_carrier = use_carrier; |
| 4611 | params->lacp_fast = lacp_fast; | 4747 | params->lacp_fast = lacp_fast; |
| 4612 | params->primary[0] = 0; | 4748 | params->primary[0] = 0; |
| 4749 | params->fail_over_mac = fail_over_mac; | ||
| 4613 | 4750 | ||
| 4614 | if (primary) { | 4751 | if (primary) { |
| 4615 | strncpy(params->primary, primary, IFNAMSIZ); | 4752 | strncpy(params->primary, primary, IFNAMSIZ); |
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 6f49ca7e9b66..80c0c8c415ed 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c | |||
| @@ -164,9 +164,7 @@ static ssize_t bonding_store_bonds(struct class *cls, const char *buffer, size_t | |||
| 164 | printk(KERN_INFO DRV_NAME | 164 | printk(KERN_INFO DRV_NAME |
| 165 | ": %s is being deleted...\n", | 165 | ": %s is being deleted...\n", |
| 166 | bond->dev->name); | 166 | bond->dev->name); |
| 167 | bond_deinit(bond->dev); | 167 | bond_destroy(bond); |
| 168 | bond_destroy_sysfs_entry(bond); | ||
| 169 | unregister_netdevice(bond->dev); | ||
| 170 | rtnl_unlock(); | 168 | rtnl_unlock(); |
| 171 | goto out; | 169 | goto out; |
| 172 | } | 170 | } |
| @@ -260,17 +258,16 @@ static ssize_t bonding_store_slaves(struct device *d, | |||
| 260 | char command[IFNAMSIZ + 1] = { 0, }; | 258 | char command[IFNAMSIZ + 1] = { 0, }; |
| 261 | char *ifname; | 259 | char *ifname; |
| 262 | int i, res, found, ret = count; | 260 | int i, res, found, ret = count; |
| 261 | u32 original_mtu; | ||
| 263 | struct slave *slave; | 262 | struct slave *slave; |
| 264 | struct net_device *dev = NULL; | 263 | struct net_device *dev = NULL; |
| 265 | struct bonding *bond = to_bond(d); | 264 | struct bonding *bond = to_bond(d); |
| 266 | 265 | ||
| 267 | /* Quick sanity check -- is the bond interface up? */ | 266 | /* Quick sanity check -- is the bond interface up? */ |
| 268 | if (!(bond->dev->flags & IFF_UP)) { | 267 | if (!(bond->dev->flags & IFF_UP)) { |
| 269 | printk(KERN_ERR DRV_NAME | 268 | printk(KERN_WARNING DRV_NAME |
| 270 | ": %s: Unable to update slaves because interface is down.\n", | 269 | ": %s: doing slave updates when interface is down.\n", |
| 271 | bond->dev->name); | 270 | bond->dev->name); |
| 272 | ret = -EPERM; | ||
| 273 | goto out; | ||
| 274 | } | 271 | } |
| 275 | 272 | ||
| 276 | /* Note: We can't hold bond->lock here, as bond_create grabs it. */ | 273 | /* Note: We can't hold bond->lock here, as bond_create grabs it. */ |
| @@ -327,6 +324,7 @@ static ssize_t bonding_store_slaves(struct device *d, | |||
| 327 | } | 324 | } |
| 328 | 325 | ||
| 329 | /* Set the slave's MTU to match the bond */ | 326 | /* Set the slave's MTU to match the bond */ |
| 327 | original_mtu = dev->mtu; | ||
| 330 | if (dev->mtu != bond->dev->mtu) { | 328 | if (dev->mtu != bond->dev->mtu) { |
| 331 | if (dev->change_mtu) { | 329 | if (dev->change_mtu) { |
| 332 | res = dev->change_mtu(dev, | 330 | res = dev->change_mtu(dev, |
| @@ -341,6 +339,9 @@ static ssize_t bonding_store_slaves(struct device *d, | |||
| 341 | } | 339 | } |
| 342 | rtnl_lock(); | 340 | rtnl_lock(); |
| 343 | res = bond_enslave(bond->dev, dev); | 341 | res = bond_enslave(bond->dev, dev); |
| 342 | bond_for_each_slave(bond, slave, i) | ||
| 343 | if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) | ||
| 344 | slave->original_mtu = original_mtu; | ||
| 344 | rtnl_unlock(); | 345 | rtnl_unlock(); |
| 345 | if (res) { | 346 | if (res) { |
| 346 | ret = res; | 347 | ret = res; |
| @@ -353,13 +354,17 @@ static ssize_t bonding_store_slaves(struct device *d, | |||
| 353 | bond_for_each_slave(bond, slave, i) | 354 | bond_for_each_slave(bond, slave, i) |
| 354 | if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) { | 355 | if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) { |
| 355 | dev = slave->dev; | 356 | dev = slave->dev; |
| 357 | original_mtu = slave->original_mtu; | ||
| 356 | break; | 358 | break; |
| 357 | } | 359 | } |
| 358 | if (dev) { | 360 | if (dev) { |
| 359 | printk(KERN_INFO DRV_NAME ": %s: Removing slave %s\n", | 361 | printk(KERN_INFO DRV_NAME ": %s: Removing slave %s\n", |
| 360 | bond->dev->name, dev->name); | 362 | bond->dev->name, dev->name); |
| 361 | rtnl_lock(); | 363 | rtnl_lock(); |
| 362 | res = bond_release(bond->dev, dev); | 364 | if (bond->setup_by_slave) |
| 365 | res = bond_release_and_destroy(bond->dev, dev); | ||
| 366 | else | ||
| 367 | res = bond_release(bond->dev, dev); | ||
| 363 | rtnl_unlock(); | 368 | rtnl_unlock(); |
| 364 | if (res) { | 369 | if (res) { |
| 365 | ret = res; | 370 | ret = res; |
| @@ -367,9 +372,9 @@ static ssize_t bonding_store_slaves(struct device *d, | |||
| 367 | } | 372 | } |
| 368 | /* set the slave MTU to the default */ | 373 | /* set the slave MTU to the default */ |
| 369 | if (dev->change_mtu) { | 374 | if (dev->change_mtu) { |
| 370 | dev->change_mtu(dev, 1500); | 375 | dev->change_mtu(dev, original_mtu); |
| 371 | } else { | 376 | } else { |
| 372 | dev->mtu = 1500; | 377 | dev->mtu = original_mtu; |
| 373 | } | 378 | } |
| 374 | } | 379 | } |
| 375 | else { | 380 | else { |
| @@ -563,6 +568,54 @@ static ssize_t bonding_store_arp_validate(struct device *d, | |||
| 563 | static DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate, bonding_store_arp_validate); | 568 | static DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate, bonding_store_arp_validate); |
| 564 | 569 | ||
| 565 | /* | 570 | /* |
| 571 | * Show and store fail_over_mac. User only allowed to change the | ||
| 572 | * value when there are no slaves. | ||
| 573 | */ | ||
| 574 | static ssize_t bonding_show_fail_over_mac(struct device *d, struct device_attribute *attr, char *buf) | ||
| 575 | { | ||
| 576 | struct bonding *bond = to_bond(d); | ||
| 577 | |||
| 578 | return sprintf(buf, "%d\n", bond->params.fail_over_mac) + 1; | ||
| 579 | } | ||
| 580 | |||
| 581 | static ssize_t bonding_store_fail_over_mac(struct device *d, struct device_attribute *attr, const char *buf, size_t count) | ||
| 582 | { | ||
| 583 | int new_value; | ||
| 584 | int ret = count; | ||
| 585 | struct bonding *bond = to_bond(d); | ||
| 586 | |||
| 587 | if (bond->slave_cnt != 0) { | ||
| 588 | printk(KERN_ERR DRV_NAME | ||
| 589 | ": %s: Can't alter fail_over_mac with slaves in bond.\n", | ||
| 590 | bond->dev->name); | ||
| 591 | ret = -EPERM; | ||
| 592 | goto out; | ||
| 593 | } | ||
| 594 | |||
| 595 | if (sscanf(buf, "%d", &new_value) != 1) { | ||
| 596 | printk(KERN_ERR DRV_NAME | ||
| 597 | ": %s: no fail_over_mac value specified.\n", | ||
| 598 | bond->dev->name); | ||
| 599 | ret = -EINVAL; | ||
| 600 | goto out; | ||
| 601 | } | ||
| 602 | |||
| 603 | if ((new_value == 0) || (new_value == 1)) { | ||
| 604 | bond->params.fail_over_mac = new_value; | ||
| 605 | printk(KERN_INFO DRV_NAME ": %s: Setting fail_over_mac to %d.\n", | ||
| 606 | bond->dev->name, new_value); | ||
| 607 | } else { | ||
| 608 | printk(KERN_INFO DRV_NAME | ||
| 609 | ": %s: Ignoring invalid fail_over_mac value %d.\n", | ||
| 610 | bond->dev->name, new_value); | ||
| 611 | } | ||
| 612 | out: | ||
| 613 | return ret; | ||
| 614 | } | ||
| 615 | |||
| 616 | static DEVICE_ATTR(fail_over_mac, S_IRUGO | S_IWUSR, bonding_show_fail_over_mac, bonding_store_fail_over_mac); | ||
| 617 | |||
| 618 | /* | ||
| 566 | * Show and set the arp timer interval. There are two tricky bits | 619 | * Show and set the arp timer interval. There are two tricky bits |
| 567 | * here. First, if ARP monitoring is activated, then we must disable | 620 | * here. First, if ARP monitoring is activated, then we must disable |
| 568 | * MII monitoring. Second, if the ARP timer isn't running, we must | 621 | * MII monitoring. Second, if the ARP timer isn't running, we must |
| @@ -1383,6 +1436,7 @@ static DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL); | |||
| 1383 | static struct attribute *per_bond_attrs[] = { | 1436 | static struct attribute *per_bond_attrs[] = { |
| 1384 | &dev_attr_slaves.attr, | 1437 | &dev_attr_slaves.attr, |
| 1385 | &dev_attr_mode.attr, | 1438 | &dev_attr_mode.attr, |
| 1439 | &dev_attr_fail_over_mac.attr, | ||
| 1386 | &dev_attr_arp_validate.attr, | 1440 | &dev_attr_arp_validate.attr, |
| 1387 | &dev_attr_arp_interval.attr, | 1441 | &dev_attr_arp_interval.attr, |
| 1388 | &dev_attr_arp_ip_target.attr, | 1442 | &dev_attr_arp_ip_target.attr, |
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 2a6af7d23728..a8bbd563265c 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h | |||
| @@ -22,8 +22,8 @@ | |||
| 22 | #include "bond_3ad.h" | 22 | #include "bond_3ad.h" |
| 23 | #include "bond_alb.h" | 23 | #include "bond_alb.h" |
| 24 | 24 | ||
| 25 | #define DRV_VERSION "3.1.3" | 25 | #define DRV_VERSION "3.2.0" |
| 26 | #define DRV_RELDATE "June 13, 2007" | 26 | #define DRV_RELDATE "September 13, 2007" |
| 27 | #define DRV_NAME "bonding" | 27 | #define DRV_NAME "bonding" |
| 28 | #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" | 28 | #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" |
| 29 | 29 | ||
| @@ -128,6 +128,7 @@ struct bond_params { | |||
| 128 | int arp_interval; | 128 | int arp_interval; |
| 129 | int arp_validate; | 129 | int arp_validate; |
| 130 | int use_carrier; | 130 | int use_carrier; |
| 131 | int fail_over_mac; | ||
| 131 | int updelay; | 132 | int updelay; |
| 132 | int downdelay; | 133 | int downdelay; |
| 133 | int lacp_fast; | 134 | int lacp_fast; |
| @@ -156,6 +157,7 @@ struct slave { | |||
| 156 | s8 link; /* one of BOND_LINK_XXXX */ | 157 | s8 link; /* one of BOND_LINK_XXXX */ |
| 157 | s8 state; /* one of BOND_STATE_XXXX */ | 158 | s8 state; /* one of BOND_STATE_XXXX */ |
| 158 | u32 original_flags; | 159 | u32 original_flags; |
| 160 | u32 original_mtu; | ||
| 159 | u32 link_failure_count; | 161 | u32 link_failure_count; |
| 160 | u16 speed; | 162 | u16 speed; |
| 161 | u8 duplex; | 163 | u8 duplex; |
| @@ -185,6 +187,8 @@ struct bonding { | |||
| 185 | struct timer_list mii_timer; | 187 | struct timer_list mii_timer; |
| 186 | struct timer_list arp_timer; | 188 | struct timer_list arp_timer; |
| 187 | s8 kill_timers; | 189 | s8 kill_timers; |
| 190 | s8 send_grat_arp; | ||
| 191 | s8 setup_by_slave; | ||
| 188 | struct net_device_stats stats; | 192 | struct net_device_stats stats; |
| 189 | #ifdef CONFIG_PROC_FS | 193 | #ifdef CONFIG_PROC_FS |
| 190 | struct proc_dir_entry *proc_entry; | 194 | struct proc_dir_entry *proc_entry; |
| @@ -292,6 +296,8 @@ static inline void bond_unset_master_alb_flags(struct bonding *bond) | |||
| 292 | struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr); | 296 | struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr); |
| 293 | int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev); | 297 | int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev); |
| 294 | int bond_create(char *name, struct bond_params *params, struct bonding **newbond); | 298 | int bond_create(char *name, struct bond_params *params, struct bonding **newbond); |
| 299 | void bond_destroy(struct bonding *bond); | ||
| 300 | int bond_release_and_destroy(struct net_device *bond_dev, struct net_device *slave_dev); | ||
| 295 | void bond_deinit(struct net_device *bond_dev); | 301 | void bond_deinit(struct net_device *bond_dev); |
| 296 | int bond_create_sysfs(void); | 302 | int bond_create_sysfs(void); |
| 297 | void bond_destroy_sysfs(void); | 303 | void bond_destroy_sysfs(void); |
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 563bf5f6fa2a..7df31b5561cc 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c | |||
| @@ -4443,7 +4443,7 @@ static struct { | |||
| 4443 | {REG_MAC_COLL_EXCESS}, | 4443 | {REG_MAC_COLL_EXCESS}, |
| 4444 | {REG_MAC_COLL_LATE} | 4444 | {REG_MAC_COLL_LATE} |
| 4445 | }; | 4445 | }; |
| 4446 | #define CAS_REG_LEN (sizeof(ethtool_register_table)/sizeof(int)) | 4446 | #define CAS_REG_LEN ARRAY_SIZE(ethtool_register_table) |
| 4447 | #define CAS_MAX_REGS (sizeof (u32)*CAS_REG_LEN) | 4447 | #define CAS_MAX_REGS (sizeof (u32)*CAS_REG_LEN) |
| 4448 | 4448 | ||
| 4449 | static void cas_read_regs(struct cas *cp, u8 *ptr, int len) | 4449 | static void cas_read_regs(struct cas *cp, u8 *ptr, int len) |
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c new file mode 100644 index 000000000000..ed53aaab4c02 --- /dev/null +++ b/drivers/net/cpmac.c | |||
| @@ -0,0 +1,1174 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2006, 2007 Eugene Konev | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License as published by | ||
| 6 | * the Free Software Foundation; either version 2 of the License, or | ||
| 7 | * (at your option) any later version. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License | ||
| 15 | * along with this program; if not, write to the Free Software | ||
| 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/init.h> | ||
| 21 | #include <linux/moduleparam.h> | ||
| 22 | |||
| 23 | #include <linux/sched.h> | ||
| 24 | #include <linux/kernel.h> | ||
| 25 | #include <linux/slab.h> | ||
| 26 | #include <linux/errno.h> | ||
| 27 | #include <linux/types.h> | ||
| 28 | #include <linux/delay.h> | ||
| 29 | #include <linux/version.h> | ||
| 30 | |||
| 31 | #include <linux/netdevice.h> | ||
| 32 | #include <linux/etherdevice.h> | ||
| 33 | #include <linux/ethtool.h> | ||
| 34 | #include <linux/skbuff.h> | ||
| 35 | #include <linux/mii.h> | ||
| 36 | #include <linux/phy.h> | ||
| 37 | #include <linux/platform_device.h> | ||
| 38 | #include <linux/dma-mapping.h> | ||
| 39 | #include <asm/gpio.h> | ||
| 40 | |||
| 41 | MODULE_AUTHOR("Eugene Konev <ejka@imfi.kspu.ru>"); | ||
| 42 | MODULE_DESCRIPTION("TI AR7 ethernet driver (CPMAC)"); | ||
| 43 | MODULE_LICENSE("GPL"); | ||
| 44 | |||
| 45 | static int debug_level = 8; | ||
| 46 | static int dumb_switch; | ||
| 47 | |||
| 48 | /* Next 2 are only used in cpmac_probe, so it's pointless to change them */ | ||
| 49 | module_param(debug_level, int, 0444); | ||
| 50 | module_param(dumb_switch, int, 0444); | ||
| 51 | |||
| 52 | MODULE_PARM_DESC(debug_level, "Number of NETIF_MSG bits to enable"); | ||
| 53 | MODULE_PARM_DESC(dumb_switch, "Assume switch is not connected to MDIO bus"); | ||
| 54 | |||
| 55 | #define CPMAC_VERSION "0.5.0" | ||
| 56 | /* stolen from net/ieee80211.h */ | ||
| 57 | #ifndef MAC_FMT | ||
| 58 | #define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" | ||
| 59 | #define MAC_ARG(x) ((u8*)(x))[0], ((u8*)(x))[1], ((u8*)(x))[2], \ | ||
| 60 | ((u8*)(x))[3], ((u8*)(x))[4], ((u8*)(x))[5] | ||
| 61 | #endif | ||
| 62 | /* frame size + 802.1q tag */ | ||
| 63 | #define CPMAC_SKB_SIZE (ETH_FRAME_LEN + 4) | ||
| 64 | #define CPMAC_QUEUES 8 | ||
| 65 | |||
| 66 | /* Ethernet registers */ | ||
| 67 | #define CPMAC_TX_CONTROL 0x0004 | ||
| 68 | #define CPMAC_TX_TEARDOWN 0x0008 | ||
| 69 | #define CPMAC_RX_CONTROL 0x0014 | ||
| 70 | #define CPMAC_RX_TEARDOWN 0x0018 | ||
| 71 | #define CPMAC_MBP 0x0100 | ||
| 72 | # define MBP_RXPASSCRC 0x40000000 | ||
| 73 | # define MBP_RXQOS 0x20000000 | ||
| 74 | # define MBP_RXNOCHAIN 0x10000000 | ||
| 75 | # define MBP_RXCMF 0x01000000 | ||
| 76 | # define MBP_RXSHORT 0x00800000 | ||
| 77 | # define MBP_RXCEF 0x00400000 | ||
| 78 | # define MBP_RXPROMISC 0x00200000 | ||
| 79 | # define MBP_PROMISCCHAN(channel) (((channel) & 0x7) << 16) | ||
| 80 | # define MBP_RXBCAST 0x00002000 | ||
| 81 | # define MBP_BCASTCHAN(channel) (((channel) & 0x7) << 8) | ||
| 82 | # define MBP_RXMCAST 0x00000020 | ||
| 83 | # define MBP_MCASTCHAN(channel) ((channel) & 0x7) | ||
| 84 | #define CPMAC_UNICAST_ENABLE 0x0104 | ||
| 85 | #define CPMAC_UNICAST_CLEAR 0x0108 | ||
| 86 | #define CPMAC_MAX_LENGTH 0x010c | ||
| 87 | #define CPMAC_BUFFER_OFFSET 0x0110 | ||
| 88 | #define CPMAC_MAC_CONTROL 0x0160 | ||
| 89 | # define MAC_TXPTYPE 0x00000200 | ||
| 90 | # define MAC_TXPACE 0x00000040 | ||
| 91 | # define MAC_MII 0x00000020 | ||
| 92 | # define MAC_TXFLOW 0x00000010 | ||
| 93 | # define MAC_RXFLOW 0x00000008 | ||
| 94 | # define MAC_MTEST 0x00000004 | ||
| 95 | # define MAC_LOOPBACK 0x00000002 | ||
| 96 | # define MAC_FDX 0x00000001 | ||
| 97 | #define CPMAC_MAC_STATUS 0x0164 | ||
| 98 | # define MAC_STATUS_QOS 0x00000004 | ||
| 99 | # define MAC_STATUS_RXFLOW 0x00000002 | ||
| 100 | # define MAC_STATUS_TXFLOW 0x00000001 | ||
| 101 | #define CPMAC_TX_INT_ENABLE 0x0178 | ||
| 102 | #define CPMAC_TX_INT_CLEAR 0x017c | ||
| 103 | #define CPMAC_MAC_INT_VECTOR 0x0180 | ||
| 104 | # define MAC_INT_STATUS 0x00080000 | ||
| 105 | # define MAC_INT_HOST 0x00040000 | ||
| 106 | # define MAC_INT_RX 0x00020000 | ||
| 107 | # define MAC_INT_TX 0x00010000 | ||
| 108 | #define CPMAC_MAC_EOI_VECTOR 0x0184 | ||
| 109 | #define CPMAC_RX_INT_ENABLE 0x0198 | ||
| 110 | #define CPMAC_RX_INT_CLEAR 0x019c | ||
| 111 | #define CPMAC_MAC_INT_ENABLE 0x01a8 | ||
| 112 | #define CPMAC_MAC_INT_CLEAR 0x01ac | ||
| 113 | #define CPMAC_MAC_ADDR_LO(channel) (0x01b0 + (channel) * 4) | ||
| 114 | #define CPMAC_MAC_ADDR_MID 0x01d0 | ||
| 115 | #define CPMAC_MAC_ADDR_HI 0x01d4 | ||
| 116 | #define CPMAC_MAC_HASH_LO 0x01d8 | ||
| 117 | #define CPMAC_MAC_HASH_HI 0x01dc | ||
| 118 | #define CPMAC_TX_PTR(channel) (0x0600 + (channel) * 4) | ||
| 119 | #define CPMAC_RX_PTR(channel) (0x0620 + (channel) * 4) | ||
| 120 | #define CPMAC_TX_ACK(channel) (0x0640 + (channel) * 4) | ||
| 121 | #define CPMAC_RX_ACK(channel) (0x0660 + (channel) * 4) | ||
| 122 | #define CPMAC_REG_END 0x0680 | ||
| 123 | /* | ||
| 124 | * Rx/Tx statistics | ||
| 125 | * TODO: use some of them to fill stats in cpmac_stats() | ||
| 126 | */ | ||
| 127 | #define CPMAC_STATS_RX_GOOD 0x0200 | ||
| 128 | #define CPMAC_STATS_RX_BCAST 0x0204 | ||
| 129 | #define CPMAC_STATS_RX_MCAST 0x0208 | ||
| 130 | #define CPMAC_STATS_RX_PAUSE 0x020c | ||
| 131 | #define CPMAC_STATS_RX_CRC 0x0210 | ||
| 132 | #define CPMAC_STATS_RX_ALIGN 0x0214 | ||
| 133 | #define CPMAC_STATS_RX_OVER 0x0218 | ||
| 134 | #define CPMAC_STATS_RX_JABBER 0x021c | ||
| 135 | #define CPMAC_STATS_RX_UNDER 0x0220 | ||
| 136 | #define CPMAC_STATS_RX_FRAG 0x0224 | ||
| 137 | #define CPMAC_STATS_RX_FILTER 0x0228 | ||
| 138 | #define CPMAC_STATS_RX_QOSFILTER 0x022c | ||
| 139 | #define CPMAC_STATS_RX_OCTETS 0x0230 | ||
| 140 | |||
| 141 | #define CPMAC_STATS_TX_GOOD 0x0234 | ||
| 142 | #define CPMAC_STATS_TX_BCAST 0x0238 | ||
| 143 | #define CPMAC_STATS_TX_MCAST 0x023c | ||
| 144 | #define CPMAC_STATS_TX_PAUSE 0x0240 | ||
| 145 | #define CPMAC_STATS_TX_DEFER 0x0244 | ||
| 146 | #define CPMAC_STATS_TX_COLLISION 0x0248 | ||
| 147 | #define CPMAC_STATS_TX_SINGLECOLL 0x024c | ||
| 148 | #define CPMAC_STATS_TX_MULTICOLL 0x0250 | ||
| 149 | #define CPMAC_STATS_TX_EXCESSCOLL 0x0254 | ||
| 150 | #define CPMAC_STATS_TX_LATECOLL 0x0258 | ||
| 151 | #define CPMAC_STATS_TX_UNDERRUN 0x025c | ||
| 152 | #define CPMAC_STATS_TX_CARRIERSENSE 0x0260 | ||
| 153 | #define CPMAC_STATS_TX_OCTETS 0x0264 | ||
| 154 | |||
| 155 | #define cpmac_read(base, reg) (readl((void __iomem *)(base) + (reg))) | ||
| 156 | #define cpmac_write(base, reg, val) (writel(val, (void __iomem *)(base) + \ | ||
| 157 | (reg))) | ||
| 158 | |||
| 159 | /* MDIO bus */ | ||
| 160 | #define CPMAC_MDIO_VERSION 0x0000 | ||
| 161 | #define CPMAC_MDIO_CONTROL 0x0004 | ||
| 162 | # define MDIOC_IDLE 0x80000000 | ||
| 163 | # define MDIOC_ENABLE 0x40000000 | ||
| 164 | # define MDIOC_PREAMBLE 0x00100000 | ||
| 165 | # define MDIOC_FAULT 0x00080000 | ||
| 166 | # define MDIOC_FAULTDETECT 0x00040000 | ||
| 167 | # define MDIOC_INTTEST 0x00020000 | ||
| 168 | # define MDIOC_CLKDIV(div) ((div) & 0xff) | ||
| 169 | #define CPMAC_MDIO_ALIVE 0x0008 | ||
| 170 | #define CPMAC_MDIO_LINK 0x000c | ||
| 171 | #define CPMAC_MDIO_ACCESS(channel) (0x0080 + (channel) * 8) | ||
| 172 | # define MDIO_BUSY 0x80000000 | ||
| 173 | # define MDIO_WRITE 0x40000000 | ||
| 174 | # define MDIO_REG(reg) (((reg) & 0x1f) << 21) | ||
| 175 | # define MDIO_PHY(phy) (((phy) & 0x1f) << 16) | ||
| 176 | # define MDIO_DATA(data) ((data) & 0xffff) | ||
| 177 | #define CPMAC_MDIO_PHYSEL(channel) (0x0084 + (channel) * 8) | ||
| 178 | # define PHYSEL_LINKSEL 0x00000040 | ||
| 179 | # define PHYSEL_LINKINT 0x00000020 | ||
| 180 | |||
| 181 | struct cpmac_desc { | ||
| 182 | u32 hw_next; | ||
| 183 | u32 hw_data; | ||
| 184 | u16 buflen; | ||
| 185 | u16 bufflags; | ||
| 186 | u16 datalen; | ||
| 187 | u16 dataflags; | ||
| 188 | #define CPMAC_SOP 0x8000 | ||
| 189 | #define CPMAC_EOP 0x4000 | ||
| 190 | #define CPMAC_OWN 0x2000 | ||
| 191 | #define CPMAC_EOQ 0x1000 | ||
| 192 | struct sk_buff *skb; | ||
| 193 | struct cpmac_desc *next; | ||
| 194 | dma_addr_t mapping; | ||
| 195 | dma_addr_t data_mapping; | ||
| 196 | }; | ||
| 197 | |||
| 198 | struct cpmac_priv { | ||
| 199 | spinlock_t lock; | ||
| 200 | spinlock_t rx_lock; | ||
| 201 | struct cpmac_desc *rx_head; | ||
| 202 | int ring_size; | ||
| 203 | struct cpmac_desc *desc_ring; | ||
| 204 | dma_addr_t dma_ring; | ||
| 205 | void __iomem *regs; | ||
| 206 | struct mii_bus *mii_bus; | ||
| 207 | struct phy_device *phy; | ||
| 208 | char phy_name[BUS_ID_SIZE]; | ||
| 209 | int oldlink, oldspeed, oldduplex; | ||
| 210 | u32 msg_enable; | ||
| 211 | struct net_device *dev; | ||
| 212 | struct work_struct reset_work; | ||
| 213 | struct platform_device *pdev; | ||
| 214 | }; | ||
| 215 | |||
| 216 | static irqreturn_t cpmac_irq(int, void *); | ||
| 217 | static void cpmac_hw_start(struct net_device *dev); | ||
| 218 | static void cpmac_hw_stop(struct net_device *dev); | ||
| 219 | static int cpmac_stop(struct net_device *dev); | ||
| 220 | static int cpmac_open(struct net_device *dev); | ||
| 221 | |||
| 222 | static void cpmac_dump_regs(struct net_device *dev) | ||
| 223 | { | ||
| 224 | int i; | ||
| 225 | struct cpmac_priv *priv = netdev_priv(dev); | ||
| 226 | for (i = 0; i < CPMAC_REG_END; i += 4) { | ||
| 227 | if (i % 16 == 0) { | ||
| 228 | if (i) | ||
| 229 | printk("\n"); | ||
| 230 | printk(KERN_DEBUG "%s: reg[%p]:", dev->name, | ||
| 231 | priv->regs + i); | ||
| 232 | } | ||
| 233 | printk(" %08x", cpmac_read(priv->regs, i)); | ||
| 234 | } | ||
| 235 | printk("\n"); | ||
| 236 | } | ||
| 237 | |||
| 238 | static void cpmac_dump_desc(struct net_device *dev, struct cpmac_desc *desc) | ||
| 239 | { | ||
| 240 | int i; | ||
| 241 | printk(KERN_DEBUG "%s: desc[%p]:", dev->name, desc); | ||
| 242 | for (i = 0; i < sizeof(*desc) / 4; i++) | ||
| 243 | printk(" %08x", ((u32 *)desc)[i]); | ||
| 244 | printk("\n"); | ||
| 245 | } | ||
| 246 | |||
| 247 | static void cpmac_dump_skb(struct net_device *dev, struct sk_buff *skb) | ||
| 248 | { | ||
| 249 | int i; | ||
| 250 | printk(KERN_DEBUG "%s: skb 0x%p, len=%d\n", dev->name, skb, skb->len); | ||
| 251 | for (i = 0; i < skb->len; i++) { | ||
| 252 | if (i % 16 == 0) { | ||
| 253 | if (i) | ||
| 254 | printk("\n"); | ||
| 255 | printk(KERN_DEBUG "%s: data[%p]:", dev->name, | ||
| 256 | skb->data + i); | ||
| 257 | } | ||
| 258 | printk(" %02x", ((u8 *)skb->data)[i]); | ||
| 259 | } | ||
| 260 | printk("\n"); | ||
| 261 | } | ||
| 262 | |||
| 263 | static int cpmac_mdio_read(struct mii_bus *bus, int phy_id, int reg) | ||
| 264 | { | ||
| 265 | u32 val; | ||
| 266 | |||
| 267 | while (cpmac_read(bus->priv, CPMAC_MDIO_ACCESS(0)) & MDIO_BUSY) | ||
| 268 | cpu_relax(); | ||
| 269 | cpmac_write(bus->priv, CPMAC_MDIO_ACCESS(0), MDIO_BUSY | MDIO_REG(reg) | | ||
| 270 | MDIO_PHY(phy_id)); | ||
| 271 | while ((val = cpmac_read(bus->priv, CPMAC_MDIO_ACCESS(0))) & MDIO_BUSY) | ||
| 272 | cpu_relax(); | ||
| 273 | return MDIO_DATA(val); | ||
| 274 | } | ||
| 275 | |||
| 276 | static int cpmac_mdio_write(struct mii_bus *bus, int phy_id, | ||
| 277 | int reg, u16 val) | ||
| 278 | { | ||
| 279 | while (cpmac_read(bus->priv, CPMAC_MDIO_ACCESS(0)) & MDIO_BUSY) | ||
| 280 | cpu_relax(); | ||
| 281 | cpmac_write(bus->priv, CPMAC_MDIO_ACCESS(0), MDIO_BUSY | MDIO_WRITE | | ||
| 282 | MDIO_REG(reg) | MDIO_PHY(phy_id) | MDIO_DATA(val)); | ||
| 283 | return 0; | ||
| 284 | } | ||
| 285 | |||
| 286 | static int cpmac_mdio_reset(struct mii_bus *bus) | ||
| 287 | { | ||
| 288 | ar7_device_reset(AR7_RESET_BIT_MDIO); | ||
| 289 | cpmac_write(bus->priv, CPMAC_MDIO_CONTROL, MDIOC_ENABLE | | ||
| 290 | MDIOC_CLKDIV(ar7_cpmac_freq() / 2200000 - 1)); | ||
| 291 | return 0; | ||
| 292 | } | ||
| 293 | |||
| 294 | static int mii_irqs[PHY_MAX_ADDR] = { PHY_POLL, }; | ||
| 295 | |||
| 296 | static struct mii_bus cpmac_mii = { | ||
| 297 | .name = "cpmac-mii", | ||
| 298 | .read = cpmac_mdio_read, | ||
| 299 | .write = cpmac_mdio_write, | ||
| 300 | .reset = cpmac_mdio_reset, | ||
| 301 | .irq = mii_irqs, | ||
| 302 | }; | ||
| 303 | |||
| 304 | static int cpmac_config(struct net_device *dev, struct ifmap *map) | ||
| 305 | { | ||
| 306 | if (dev->flags & IFF_UP) | ||
| 307 | return -EBUSY; | ||
| 308 | |||
| 309 | /* Don't allow changing the I/O address */ | ||
| 310 | if (map->base_addr != dev->base_addr) | ||
| 311 | return -EOPNOTSUPP; | ||
| 312 | |||
| 313 | /* ignore other fields */ | ||
| 314 | return 0; | ||
| 315 | } | ||
| 316 | |||
| 317 | static void cpmac_set_multicast_list(struct net_device *dev) | ||
| 318 | { | ||
| 319 | struct dev_mc_list *iter; | ||
| 320 | int i; | ||
| 321 | u8 tmp; | ||
| 322 | u32 mbp, bit, hash[2] = { 0, }; | ||
| 323 | struct cpmac_priv *priv = netdev_priv(dev); | ||
| 324 | |||
| 325 | mbp = cpmac_read(priv->regs, CPMAC_MBP); | ||
| 326 | if (dev->flags & IFF_PROMISC) { | ||
| 327 | cpmac_write(priv->regs, CPMAC_MBP, (mbp & ~MBP_PROMISCCHAN(0)) | | ||
| 328 | MBP_RXPROMISC); | ||
| 329 | } else { | ||
| 330 | cpmac_write(priv->regs, CPMAC_MBP, mbp & ~MBP_RXPROMISC); | ||
| 331 | if (dev->flags & IFF_ALLMULTI) { | ||
| 332 | /* enable all multicast mode */ | ||
| 333 | cpmac_write(priv->regs, CPMAC_MAC_HASH_LO, 0xffffffff); | ||
| 334 | cpmac_write(priv->regs, CPMAC_MAC_HASH_HI, 0xffffffff); | ||
| 335 | } else { | ||
| 336 | /* | ||
| 337 | * cpmac uses some strange mac address hashing | ||
| 338 | * (not crc32) | ||
| 339 | */ | ||
| 340 | for (i = 0, iter = dev->mc_list; i < dev->mc_count; | ||
| 341 | i++, iter = iter->next) { | ||
| 342 | bit = 0; | ||
| 343 | tmp = iter->dmi_addr[0]; | ||
| 344 | bit ^= (tmp >> 2) ^ (tmp << 4); | ||
| 345 | tmp = iter->dmi_addr[1]; | ||
| 346 | bit ^= (tmp >> 4) ^ (tmp << 2); | ||
| 347 | tmp = iter->dmi_addr[2]; | ||
| 348 | bit ^= (tmp >> 6) ^ tmp; | ||
| 349 | tmp = iter->dmi_addr[3]; | ||
| 350 | bit ^= (tmp >> 2) ^ (tmp << 4); | ||
| 351 | tmp = iter->dmi_addr[4]; | ||
| 352 | bit ^= (tmp >> 4) ^ (tmp << 2); | ||
| 353 | tmp = iter->dmi_addr[5]; | ||
| 354 | bit ^= (tmp >> 6) ^ tmp; | ||
| 355 | bit &= 0x3f; | ||
| 356 | hash[bit / 32] |= 1 << (bit % 32); | ||
| 357 | } | ||
| 358 | |||
| 359 | cpmac_write(priv->regs, CPMAC_MAC_HASH_LO, hash[0]); | ||
| 360 | cpmac_write(priv->regs, CPMAC_MAC_HASH_HI, hash[1]); | ||
| 361 | } | ||
| 362 | } | ||
| 363 | } | ||
| 364 | |||
| 365 | static struct sk_buff *cpmac_rx_one(struct net_device *dev, | ||
| 366 | struct cpmac_priv *priv, | ||
| 367 | struct cpmac_desc *desc) | ||
| 368 | { | ||
| 369 | struct sk_buff *skb, *result = NULL; | ||
| 370 | |||
| 371 | if (unlikely(netif_msg_hw(priv))) | ||
| 372 | cpmac_dump_desc(dev, desc); | ||
| 373 | cpmac_write(priv->regs, CPMAC_RX_ACK(0), (u32)desc->mapping); | ||
| 374 | if (unlikely(!desc->datalen)) { | ||
| 375 | if (netif_msg_rx_err(priv) && net_ratelimit()) | ||
| 376 | printk(KERN_WARNING "%s: rx: spurious interrupt\n", | ||
| 377 | dev->name); | ||
| 378 | return NULL; | ||
| 379 | } | ||
| 380 | |||
| 381 | skb = netdev_alloc_skb(dev, CPMAC_SKB_SIZE); | ||
| 382 | if (likely(skb)) { | ||
| 383 | skb_reserve(skb, 2); | ||
| 384 | skb_put(desc->skb, desc->datalen); | ||
| 385 | desc->skb->protocol = eth_type_trans(desc->skb, dev); | ||
| 386 | desc->skb->ip_summed = CHECKSUM_NONE; | ||
| 387 | dev->stats.rx_packets++; | ||
| 388 | dev->stats.rx_bytes += desc->datalen; | ||
| 389 | result = desc->skb; | ||
| 390 | dma_unmap_single(&dev->dev, desc->data_mapping, CPMAC_SKB_SIZE, | ||
| 391 | DMA_FROM_DEVICE); | ||
| 392 | desc->skb = skb; | ||
| 393 | desc->data_mapping = dma_map_single(&dev->dev, skb->data, | ||
| 394 | CPMAC_SKB_SIZE, | ||
| 395 | DMA_FROM_DEVICE); | ||
| 396 | desc->hw_data = (u32)desc->data_mapping; | ||
| 397 | if (unlikely(netif_msg_pktdata(priv))) { | ||
| 398 | printk(KERN_DEBUG "%s: received packet:\n", dev->name); | ||
| 399 | cpmac_dump_skb(dev, result); | ||
| 400 | } | ||
| 401 | } else { | ||
| 402 | if (netif_msg_rx_err(priv) && net_ratelimit()) | ||
| 403 | printk(KERN_WARNING | ||
| 404 | "%s: low on skbs, dropping packet\n", dev->name); | ||
| 405 | dev->stats.rx_dropped++; | ||
| 406 | } | ||
| 407 | |||
| 408 | desc->buflen = CPMAC_SKB_SIZE; | ||
| 409 | desc->dataflags = CPMAC_OWN; | ||
| 410 | |||
| 411 | return result; | ||
| 412 | } | ||
| 413 | |||
| 414 | static int cpmac_poll(struct net_device *dev, int *budget) | ||
| 415 | { | ||
| 416 | struct sk_buff *skb; | ||
| 417 | struct cpmac_desc *desc; | ||
| 418 | int received = 0, quota = min(dev->quota, *budget); | ||
| 419 | struct cpmac_priv *priv = netdev_priv(dev); | ||
| 420 | |||
| 421 | spin_lock(&priv->rx_lock); | ||
| 422 | if (unlikely(!priv->rx_head)) { | ||
| 423 | if (netif_msg_rx_err(priv) && net_ratelimit()) | ||
| 424 | printk(KERN_WARNING "%s: rx: polling, but no queue\n", | ||
| 425 | dev->name); | ||
| 426 | netif_rx_complete(dev); | ||
| 427 | return 0; | ||
| 428 | } | ||
| 429 | |||
| 430 | desc = priv->rx_head; | ||
| 431 | while ((received < quota) && ((desc->dataflags & CPMAC_OWN) == 0)) { | ||
| 432 | skb = cpmac_rx_one(dev, priv, desc); | ||
| 433 | if (likely(skb)) { | ||
| 434 | netif_receive_skb(skb); | ||
| 435 | received++; | ||
| 436 | } | ||
| 437 | desc = desc->next; | ||
| 438 | } | ||
| 439 | |||
| 440 | priv->rx_head = desc; | ||
| 441 | spin_unlock(&priv->rx_lock); | ||
| 442 | *budget -= received; | ||
| 443 | dev->quota -= received; | ||
| 444 | if (unlikely(netif_msg_rx_status(priv))) | ||
| 445 | printk(KERN_DEBUG "%s: poll processed %d packets\n", dev->name, | ||
| 446 | received); | ||
| 447 | if (desc->dataflags & CPMAC_OWN) { | ||
| 448 | netif_rx_complete(dev); | ||
| 449 | cpmac_write(priv->regs, CPMAC_RX_PTR(0), (u32)desc->mapping); | ||
| 450 | cpmac_write(priv->regs, CPMAC_RX_INT_ENABLE, 1); | ||
| 451 | return 0; | ||
| 452 | } | ||
| 453 | |||
| 454 | return 1; | ||
| 455 | } | ||
| 456 | |||
| 457 | static int cpmac_start_xmit(struct sk_buff *skb, struct net_device *dev) | ||
| 458 | { | ||
| 459 | int queue, len; | ||
| 460 | struct cpmac_desc *desc; | ||
| 461 | struct cpmac_priv *priv = netdev_priv(dev); | ||
| 462 | |||
| 463 | if (unlikely(skb_padto(skb, ETH_ZLEN))) { | ||
| 464 | if (netif_msg_tx_err(priv) && net_ratelimit()) | ||
| 465 | printk(KERN_WARNING | ||
| 466 | "%s: tx: padding failed, dropping\n", dev->name); | ||
| 467 | spin_lock(&priv->lock); | ||
| 468 | dev->stats.tx_dropped++; | ||
| 469 | spin_unlock(&priv->lock); | ||
| 470 | return -ENOMEM; | ||
| 471 | } | ||
| 472 | |||
| 473 | len = max(skb->len, ETH_ZLEN); | ||
| 474 | queue = skb->queue_mapping; | ||
| 475 | #ifdef CONFIG_NETDEVICES_MULTIQUEUE | ||
| 476 | netif_stop_subqueue(dev, queue); | ||
| 477 | #else | ||
| 478 | netif_stop_queue(dev); | ||
| 479 | #endif | ||
| 480 | |||
| 481 | desc = &priv->desc_ring[queue]; | ||
| 482 | if (unlikely(desc->dataflags & CPMAC_OWN)) { | ||
| 483 | if (netif_msg_tx_err(priv) && net_ratelimit()) | ||
| 484 | printk(KERN_WARNING "%s: tx dma ring full, dropping\n", | ||
| 485 | dev->name); | ||
| 486 | spin_lock(&priv->lock); | ||
| 487 | dev->stats.tx_dropped++; | ||
| 488 | spin_unlock(&priv->lock); | ||
| 489 | dev_kfree_skb_any(skb); | ||
| 490 | return -ENOMEM; | ||
| 491 | } | ||
| 492 | |||
| 493 | spin_lock(&priv->lock); | ||
| 494 | dev->trans_start = jiffies; | ||
| 495 | spin_unlock(&priv->lock); | ||
| 496 | desc->dataflags = CPMAC_SOP | CPMAC_EOP | CPMAC_OWN; | ||
| 497 | desc->skb = skb; | ||
| 498 | desc->data_mapping = dma_map_single(&dev->dev, skb->data, len, | ||
| 499 | DMA_TO_DEVICE); | ||
| 500 | desc->hw_data = (u32)desc->data_mapping; | ||
| 501 | desc->datalen = len; | ||
| 502 | desc->buflen = len; | ||
| 503 | if (unlikely(netif_msg_tx_queued(priv))) | ||
| 504 | printk(KERN_DEBUG "%s: sending 0x%p, len=%d\n", dev->name, skb, | ||
| 505 | skb->len); | ||
| 506 | if (unlikely(netif_msg_hw(priv))) | ||
| 507 | cpmac_dump_desc(dev, desc); | ||
| 508 | if (unlikely(netif_msg_pktdata(priv))) | ||
| 509 | cpmac_dump_skb(dev, skb); | ||
| 510 | cpmac_write(priv->regs, CPMAC_TX_PTR(queue), (u32)desc->mapping); | ||
| 511 | |||
| 512 | return 0; | ||
| 513 | } | ||
| 514 | |||
| 515 | static void cpmac_end_xmit(struct net_device *dev, int queue) | ||
| 516 | { | ||
| 517 | struct cpmac_desc *desc; | ||
| 518 | struct cpmac_priv *priv = netdev_priv(dev); | ||
| 519 | |||
| 520 | desc = &priv->desc_ring[queue]; | ||
| 521 | cpmac_write(priv->regs, CPMAC_TX_ACK(queue), (u32)desc->mapping); | ||
| 522 | if (likely(desc->skb)) { | ||
| 523 | spin_lock(&priv->lock); | ||
| 524 | dev->stats.tx_packets++; | ||
| 525 | dev->stats.tx_bytes += desc->skb->len; | ||
| 526 | spin_unlock(&priv->lock); | ||
| 527 | dma_unmap_single(&dev->dev, desc->data_mapping, desc->skb->len, | ||
| 528 | DMA_TO_DEVICE); | ||
| 529 | |||
| 530 | if (unlikely(netif_msg_tx_done(priv))) | ||
| 531 | printk(KERN_DEBUG "%s: sent 0x%p, len=%d\n", dev->name, | ||
| 532 | desc->skb, desc->skb->len); | ||
| 533 | |||
| 534 | dev_kfree_skb_irq(desc->skb); | ||
| 535 | desc->skb = NULL; | ||
| 536 | #ifdef CONFIG_NETDEVICES_MULTIQUEUE | ||
| 537 | if (netif_subqueue_stopped(dev, queue)) | ||
| 538 | netif_wake_subqueue(dev, queue); | ||
| 539 | #else | ||
| 540 | if (netif_queue_stopped(dev)) | ||
| 541 | netif_wake_queue(dev); | ||
| 542 | #endif | ||
| 543 | } else { | ||
| 544 | if (netif_msg_tx_err(priv) && net_ratelimit()) | ||
| 545 | printk(KERN_WARNING | ||
| 546 | "%s: end_xmit: spurious interrupt\n", dev->name); | ||
| 547 | #ifdef CONFIG_NETDEVICES_MULTIQUEUE | ||
| 548 | if (netif_subqueue_stopped(dev, queue)) | ||
| 549 | netif_wake_subqueue(dev, queue); | ||
| 550 | #else | ||
| 551 | if (netif_queue_stopped(dev)) | ||
| 552 | netif_wake_queue(dev); | ||
| 553 | #endif | ||
| 554 | } | ||
| 555 | } | ||
| 556 | |||
| 557 | static void cpmac_hw_stop(struct net_device *dev) | ||
| 558 | { | ||
| 559 | int i; | ||
| 560 | struct cpmac_priv *priv = netdev_priv(dev); | ||
| 561 | struct plat_cpmac_data *pdata = priv->pdev->dev.platform_data; | ||
| 562 | |||
| 563 | ar7_device_reset(pdata->reset_bit); | ||
| 564 | cpmac_write(priv->regs, CPMAC_RX_CONTROL, | ||
| 565 | cpmac_read(priv->regs, CPMAC_RX_CONTROL) & ~1); | ||
| 566 | cpmac_write(priv->regs, CPMAC_TX_CONTROL, | ||
| 567 | cpmac_read(priv->regs, CPMAC_TX_CONTROL) & ~1); | ||
| 568 | for (i = 0; i < 8; i++) { | ||
| 569 | cpmac_write(priv->regs, CPMAC_TX_PTR(i), 0); | ||
| 570 | cpmac_write(priv->regs, CPMAC_RX_PTR(i), 0); | ||
| 571 | } | ||
| 572 | cpmac_write(priv->regs, CPMAC_UNICAST_CLEAR, 0xff); | ||
| 573 | cpmac_write(priv->regs, CPMAC_RX_INT_CLEAR, 0xff); | ||
| 574 | cpmac_write(priv->regs, CPMAC_TX_INT_CLEAR, 0xff); | ||
| 575 | cpmac_write(priv->regs, CPMAC_MAC_INT_CLEAR, 0xff); | ||
| 576 | cpmac_write(priv->regs, CPMAC_MAC_CONTROL, | ||
| 577 | cpmac_read(priv->regs, CPMAC_MAC_CONTROL) & ~MAC_MII); | ||
| 578 | } | ||
| 579 | |||
| 580 | static void cpmac_hw_start(struct net_device *dev) | ||
| 581 | { | ||
| 582 | int i; | ||
| 583 | struct cpmac_priv *priv = netdev_priv(dev); | ||
| 584 | struct plat_cpmac_data *pdata = priv->pdev->dev.platform_data; | ||
| 585 | |||
| 586 | ar7_device_reset(pdata->reset_bit); | ||
| 587 | for (i = 0; i < 8; i++) { | ||
| 588 | cpmac_write(priv->regs, CPMAC_TX_PTR(i), 0); | ||
| 589 | cpmac_write(priv->regs, CPMAC_RX_PTR(i), 0); | ||
| 590 | } | ||
| 591 | cpmac_write(priv->regs, CPMAC_RX_PTR(0), priv->rx_head->mapping); | ||
| 592 | |||
| 593 | cpmac_write(priv->regs, CPMAC_MBP, MBP_RXSHORT | MBP_RXBCAST | | ||
| 594 | MBP_RXMCAST); | ||
| 595 | cpmac_write(priv->regs, CPMAC_BUFFER_OFFSET, 0); | ||
| 596 | for (i = 0; i < 8; i++) | ||
| 597 | cpmac_write(priv->regs, CPMAC_MAC_ADDR_LO(i), dev->dev_addr[5]); | ||
| 598 | cpmac_write(priv->regs, CPMAC_MAC_ADDR_MID, dev->dev_addr[4]); | ||
| 599 | cpmac_write(priv->regs, CPMAC_MAC_ADDR_HI, dev->dev_addr[0] | | ||
| 600 | (dev->dev_addr[1] << 8) | (dev->dev_addr[2] << 16) | | ||
| 601 | (dev->dev_addr[3] << 24)); | ||
| 602 | cpmac_write(priv->regs, CPMAC_MAX_LENGTH, CPMAC_SKB_SIZE); | ||
| 603 | cpmac_write(priv->regs, CPMAC_UNICAST_CLEAR, 0xff); | ||
| 604 | cpmac_write(priv->regs, CPMAC_RX_INT_CLEAR, 0xff); | ||
| 605 | cpmac_write(priv->regs, CPMAC_TX_INT_CLEAR, 0xff); | ||
| 606 | cpmac_write(priv->regs, CPMAC_MAC_INT_CLEAR, 0xff); | ||
| 607 | cpmac_write(priv->regs, CPMAC_UNICAST_ENABLE, 1); | ||
| 608 | cpmac_write(priv->regs, CPMAC_RX_INT_ENABLE, 1); | ||
| 609 | cpmac_write(priv->regs, CPMAC_TX_INT_ENABLE, 0xff); | ||
| 610 | cpmac_write(priv->regs, CPMAC_MAC_INT_ENABLE, 3); | ||
| 611 | |||
| 612 | cpmac_write(priv->regs, CPMAC_RX_CONTROL, | ||
| 613 | cpmac_read(priv->regs, CPMAC_RX_CONTROL) | 1); | ||
| 614 | cpmac_write(priv->regs, CPMAC_TX_CONTROL, | ||
| 615 | cpmac_read(priv->regs, CPMAC_TX_CONTROL) | 1); | ||
| 616 | cpmac_write(priv->regs, CPMAC_MAC_CONTROL, | ||
| 617 | cpmac_read(priv->regs, CPMAC_MAC_CONTROL) | MAC_MII | | ||
| 618 | MAC_FDX); | ||
| 619 | } | ||
| 620 | |||
| 621 | static void cpmac_clear_rx(struct net_device *dev) | ||
| 622 | { | ||
| 623 | struct cpmac_priv *priv = netdev_priv(dev); | ||
| 624 | struct cpmac_desc *desc; | ||
| 625 | int i; | ||
| 626 | if (unlikely(!priv->rx_head)) | ||
| 627 | return; | ||
| 628 | desc = priv->rx_head; | ||
| 629 | for (i = 0; i < priv->ring_size; i++) { | ||
| 630 | if ((desc->dataflags & CPMAC_OWN) == 0) { | ||
| 631 | if (netif_msg_rx_err(priv) && net_ratelimit()) | ||
| 632 | printk(KERN_WARNING "%s: packet dropped\n", | ||
| 633 | dev->name); | ||
| 634 | if (unlikely(netif_msg_hw(priv))) | ||
| 635 | cpmac_dump_desc(dev, desc); | ||
| 636 | desc->dataflags = CPMAC_OWN; | ||
| 637 | dev->stats.rx_dropped++; | ||
| 638 | } | ||
| 639 | desc = desc->next; | ||
| 640 | } | ||
| 641 | } | ||
| 642 | |||
| 643 | static void cpmac_clear_tx(struct net_device *dev) | ||
| 644 | { | ||
| 645 | struct cpmac_priv *priv = netdev_priv(dev); | ||
| 646 | int i; | ||
| 647 | if (unlikely(!priv->desc_ring)) | ||
| 648 | return; | ||
| 649 | for (i = 0; i < CPMAC_QUEUES; i++) | ||
| 650 | if (priv->desc_ring[i].skb) { | ||
| 651 | dev_kfree_skb_any(priv->desc_ring[i].skb); | ||
| 652 | if (netif_subqueue_stopped(dev, i)) | ||
| 653 | netif_wake_subqueue(dev, i); | ||
| 654 | } | ||
| 655 | } | ||
| 656 | |||
| 657 | static void cpmac_hw_error(struct work_struct *work) | ||
| 658 | { | ||
| 659 | struct cpmac_priv *priv = | ||
| 660 | container_of(work, struct cpmac_priv, reset_work); | ||
| 661 | |||
| 662 | spin_lock(&priv->rx_lock); | ||
| 663 | cpmac_clear_rx(priv->dev); | ||
| 664 | spin_unlock(&priv->rx_lock); | ||
| 665 | cpmac_clear_tx(priv->dev); | ||
| 666 | cpmac_hw_start(priv->dev); | ||
| 667 | netif_start_queue(priv->dev); | ||
| 668 | } | ||
| 669 | |||
| 670 | static irqreturn_t cpmac_irq(int irq, void *dev_id) | ||
| 671 | { | ||
| 672 | struct net_device *dev = dev_id; | ||
| 673 | struct cpmac_priv *priv; | ||
| 674 | int queue; | ||
| 675 | u32 status; | ||
| 676 | |||
| 677 | if (!dev) | ||
| 678 | return IRQ_NONE; | ||
| 679 | |||
| 680 | priv = netdev_priv(dev); | ||
| 681 | |||
| 682 | status = cpmac_read(priv->regs, CPMAC_MAC_INT_VECTOR); | ||
| 683 | |||
| 684 | if (unlikely(netif_msg_intr(priv))) | ||
| 685 | printk(KERN_DEBUG "%s: interrupt status: 0x%08x\n", dev->name, | ||
| 686 | status); | ||
| 687 | |||
| 688 | if (status & MAC_INT_TX) | ||
| 689 | cpmac_end_xmit(dev, (status & 7)); | ||
| 690 | |||
| 691 | if (status & MAC_INT_RX) { | ||
| 692 | queue = (status >> 8) & 7; | ||
| 693 | netif_rx_schedule(dev); | ||
| 694 | cpmac_write(priv->regs, CPMAC_RX_INT_CLEAR, 1 << queue); | ||
| 695 | } | ||
| 696 | |||
| 697 | cpmac_write(priv->regs, CPMAC_MAC_EOI_VECTOR, 0); | ||
| 698 | |||
| 699 | if (unlikely(status & (MAC_INT_HOST | MAC_INT_STATUS))) { | ||
| 700 | if (netif_msg_drv(priv) && net_ratelimit()) | ||
| 701 | printk(KERN_ERR "%s: hw error, resetting...\n", | ||
| 702 | dev->name); | ||
| 703 | netif_stop_queue(dev); | ||
| 704 | cpmac_hw_stop(dev); | ||
| 705 | schedule_work(&priv->reset_work); | ||
| 706 | if (unlikely(netif_msg_hw(priv))) | ||
| 707 | cpmac_dump_regs(dev); | ||
| 708 | } | ||
| 709 | |||
| 710 | return IRQ_HANDLED; | ||
| 711 | } | ||
| 712 | |||
| 713 | static void cpmac_tx_timeout(struct net_device *dev) | ||
| 714 | { | ||
| 715 | struct cpmac_priv *priv = netdev_priv(dev); | ||
| 716 | int i; | ||
| 717 | |||
| 718 | spin_lock(&priv->lock); | ||
| 719 | dev->stats.tx_errors++; | ||
| 720 | spin_unlock(&priv->lock); | ||
| 721 | if (netif_msg_tx_err(priv) && net_ratelimit()) | ||
| 722 | printk(KERN_WARNING "%s: transmit timeout\n", dev->name); | ||
| 723 | /* | ||
| 724 | * FIXME: waking up random queue is not the best thing to | ||
| 725 | * do... on the other hand why we got here at all? | ||
| 726 | */ | ||
| 727 | #ifdef CONFIG_NETDEVICES_MULTIQUEUE | ||
| 728 | for (i = 0; i < CPMAC_QUEUES; i++) | ||
| 729 | if (priv->desc_ring[i].skb) { | ||
| 730 | dev_kfree_skb_any(priv->desc_ring[i].skb); | ||
| 731 | netif_wake_subqueue(dev, i); | ||
| 732 | break; | ||
| 733 | } | ||
| 734 | #else | ||
| 735 | if (priv->desc_ring[0].skb) | ||
| 736 | dev_kfree_skb_any(priv->desc_ring[0].skb); | ||
| 737 | netif_wake_queue(dev); | ||
| 738 | #endif | ||
| 739 | } | ||
| 740 | |||
| 741 | static int cpmac_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | ||
| 742 | { | ||
| 743 | struct cpmac_priv *priv = netdev_priv(dev); | ||
| 744 | if (!(netif_running(dev))) | ||
| 745 | return -EINVAL; | ||
| 746 | if (!priv->phy) | ||
| 747 | return -EINVAL; | ||
| 748 | if ((cmd == SIOCGMIIPHY) || (cmd == SIOCGMIIREG) || | ||
| 749 | (cmd == SIOCSMIIREG)) | ||
| 750 | return phy_mii_ioctl(priv->phy, if_mii(ifr), cmd); | ||
| 751 | |||
| 752 | return -EOPNOTSUPP; | ||
| 753 | } | ||
| 754 | |||
| 755 | static int cpmac_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | ||
| 756 | { | ||
| 757 | struct cpmac_priv *priv = netdev_priv(dev); | ||
| 758 | |||
| 759 | if (priv->phy) | ||
| 760 | return phy_ethtool_gset(priv->phy, cmd); | ||
| 761 | |||
| 762 | return -EINVAL; | ||
| 763 | } | ||
| 764 | |||
| 765 | static int cpmac_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | ||
| 766 | { | ||
| 767 | struct cpmac_priv *priv = netdev_priv(dev); | ||
| 768 | |||
| 769 | if (!capable(CAP_NET_ADMIN)) | ||
| 770 | return -EPERM; | ||
| 771 | |||
| 772 | if (priv->phy) | ||
| 773 | return phy_ethtool_sset(priv->phy, cmd); | ||
| 774 | |||
| 775 | return -EINVAL; | ||
| 776 | } | ||
| 777 | |||
| 778 | static void cpmac_get_ringparam(struct net_device *dev, struct ethtool_ringparam* ring) | ||
| 779 | { | ||
| 780 | struct cpmac_priv *priv = netdev_priv(dev); | ||
| 781 | |||
| 782 | ring->rx_max_pending = 1024; | ||
| 783 | ring->rx_mini_max_pending = 1; | ||
| 784 | ring->rx_jumbo_max_pending = 1; | ||
| 785 | ring->tx_max_pending = 1; | ||
| 786 | |||
| 787 | ring->rx_pending = priv->ring_size; | ||
| 788 | ring->rx_mini_pending = 1; | ||
| 789 | ring->rx_jumbo_pending = 1; | ||
| 790 | ring->tx_pending = 1; | ||
| 791 | } | ||
| 792 | |||
| 793 | static int cpmac_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ring) | ||
| 794 | { | ||
| 795 | struct cpmac_priv *priv = netdev_priv(dev); | ||
| 796 | |||
| 797 | if (dev->flags && IFF_UP) | ||
| 798 | return -EBUSY; | ||
| 799 | priv->ring_size = ring->rx_pending; | ||
| 800 | return 0; | ||
| 801 | } | ||
| 802 | |||
| 803 | static void cpmac_get_drvinfo(struct net_device *dev, | ||
| 804 | struct ethtool_drvinfo *info) | ||
| 805 | { | ||
| 806 | strcpy(info->driver, "cpmac"); | ||
| 807 | strcpy(info->version, CPMAC_VERSION); | ||
| 808 | info->fw_version[0] = '\0'; | ||
| 809 | sprintf(info->bus_info, "%s", "cpmac"); | ||
| 810 | info->regdump_len = 0; | ||
| 811 | } | ||
| 812 | |||
| 813 | static const struct ethtool_ops cpmac_ethtool_ops = { | ||
| 814 | .get_settings = cpmac_get_settings, | ||
| 815 | .set_settings = cpmac_set_settings, | ||
| 816 | .get_drvinfo = cpmac_get_drvinfo, | ||
| 817 | .get_link = ethtool_op_get_link, | ||
| 818 | .get_ringparam = cpmac_get_ringparam, | ||
| 819 | .set_ringparam = cpmac_set_ringparam, | ||
| 820 | }; | ||
| 821 | |||
| 822 | static void cpmac_adjust_link(struct net_device *dev) | ||
| 823 | { | ||
| 824 | struct cpmac_priv *priv = netdev_priv(dev); | ||
| 825 | int new_state = 0; | ||
| 826 | |||
| 827 | spin_lock(&priv->lock); | ||
| 828 | if (priv->phy->link) { | ||
| 829 | netif_start_queue(dev); | ||
| 830 | if (priv->phy->duplex != priv->oldduplex) { | ||
| 831 | new_state = 1; | ||
| 832 | priv->oldduplex = priv->phy->duplex; | ||
| 833 | } | ||
| 834 | |||
| 835 | if (priv->phy->speed != priv->oldspeed) { | ||
| 836 | new_state = 1; | ||
| 837 | priv->oldspeed = priv->phy->speed; | ||
| 838 | } | ||
| 839 | |||
| 840 | if (!priv->oldlink) { | ||
| 841 | new_state = 1; | ||
| 842 | priv->oldlink = 1; | ||
| 843 | netif_schedule(dev); | ||
| 844 | } | ||
| 845 | } else if (priv->oldlink) { | ||
| 846 | netif_stop_queue(dev); | ||
| 847 | new_state = 1; | ||
| 848 | priv->oldlink = 0; | ||
| 849 | priv->oldspeed = 0; | ||
| 850 | priv->oldduplex = -1; | ||
| 851 | } | ||
| 852 | |||
| 853 | if (new_state && netif_msg_link(priv) && net_ratelimit()) | ||
| 854 | phy_print_status(priv->phy); | ||
| 855 | |||
| 856 | spin_unlock(&priv->lock); | ||
| 857 | } | ||
| 858 | |||
| 859 | static int cpmac_open(struct net_device *dev) | ||
| 860 | { | ||
| 861 | int i, size, res; | ||
| 862 | struct cpmac_priv *priv = netdev_priv(dev); | ||
| 863 | struct resource *mem; | ||
| 864 | struct cpmac_desc *desc; | ||
| 865 | struct sk_buff *skb; | ||
| 866 | |||
| 867 | priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, | ||
| 868 | 0, PHY_INTERFACE_MODE_MII); | ||
| 869 | if (IS_ERR(priv->phy)) { | ||
| 870 | if (netif_msg_drv(priv)) | ||
| 871 | printk(KERN_ERR "%s: Could not attach to PHY\n", | ||
| 872 | dev->name); | ||
| 873 | return PTR_ERR(priv->phy); | ||
| 874 | } | ||
| 875 | |||
| 876 | mem = platform_get_resource_byname(priv->pdev, IORESOURCE_MEM, "regs"); | ||
| 877 | if (!request_mem_region(mem->start, mem->end - mem->start, dev->name)) { | ||
| 878 | if (netif_msg_drv(priv)) | ||
| 879 | printk(KERN_ERR "%s: failed to request registers\n", | ||
| 880 | dev->name); | ||
| 881 | res = -ENXIO; | ||
| 882 | goto fail_reserve; | ||
| 883 | } | ||
| 884 | |||
| 885 | priv->regs = ioremap(mem->start, mem->end - mem->start); | ||
| 886 | if (!priv->regs) { | ||
| 887 | if (netif_msg_drv(priv)) | ||
| 888 | printk(KERN_ERR "%s: failed to remap registers\n", | ||
| 889 | dev->name); | ||
| 890 | res = -ENXIO; | ||
| 891 | goto fail_remap; | ||
| 892 | } | ||
| 893 | |||
| 894 | size = priv->ring_size + CPMAC_QUEUES; | ||
| 895 | priv->desc_ring = dma_alloc_coherent(&dev->dev, | ||
| 896 | sizeof(struct cpmac_desc) * size, | ||
| 897 | &priv->dma_ring, | ||
| 898 | GFP_KERNEL); | ||
| 899 | if (!priv->desc_ring) { | ||
| 900 | res = -ENOMEM; | ||
| 901 | goto fail_alloc; | ||
| 902 | } | ||
| 903 | |||
| 904 | for (i = 0; i < size; i++) | ||
| 905 | priv->desc_ring[i].mapping = priv->dma_ring + sizeof(*desc) * i; | ||
| 906 | |||
| 907 | priv->rx_head = &priv->desc_ring[CPMAC_QUEUES]; | ||
| 908 | for (i = 0, desc = priv->rx_head; i < priv->ring_size; i++, desc++) { | ||
| 909 | skb = netdev_alloc_skb(dev, CPMAC_SKB_SIZE); | ||
| 910 | if (unlikely(!skb)) { | ||
| 911 | res = -ENOMEM; | ||
| 912 | goto fail_desc; | ||
| 913 | } | ||
| 914 | skb_reserve(skb, 2); | ||
| 915 | desc->skb = skb; | ||
| 916 | desc->data_mapping = dma_map_single(&dev->dev, skb->data, | ||
| 917 | CPMAC_SKB_SIZE, | ||
| 918 | DMA_FROM_DEVICE); | ||
| 919 | desc->hw_data = (u32)desc->data_mapping; | ||
| 920 | desc->buflen = CPMAC_SKB_SIZE; | ||
| 921 | desc->dataflags = CPMAC_OWN; | ||
| 922 | desc->next = &priv->rx_head[(i + 1) % priv->ring_size]; | ||
| 923 | desc->hw_next = (u32)desc->next->mapping; | ||
| 924 | } | ||
| 925 | |||
| 926 | if ((res = request_irq(dev->irq, cpmac_irq, IRQF_SHARED, | ||
| 927 | dev->name, dev))) { | ||
| 928 | if (netif_msg_drv(priv)) | ||
| 929 | printk(KERN_ERR "%s: failed to obtain irq\n", | ||
| 930 | dev->name); | ||
| 931 | goto fail_irq; | ||
| 932 | } | ||
| 933 | |||
| 934 | INIT_WORK(&priv->reset_work, cpmac_hw_error); | ||
| 935 | cpmac_hw_start(dev); | ||
| 936 | |||
| 937 | priv->phy->state = PHY_CHANGELINK; | ||
| 938 | phy_start(priv->phy); | ||
| 939 | |||
| 940 | return 0; | ||
| 941 | |||
| 942 | fail_irq: | ||
| 943 | fail_desc: | ||
| 944 | for (i = 0; i < priv->ring_size; i++) { | ||
| 945 | if (priv->rx_head[i].skb) { | ||
| 946 | dma_unmap_single(&dev->dev, | ||
| 947 | priv->rx_head[i].data_mapping, | ||
| 948 | CPMAC_SKB_SIZE, | ||
| 949 | DMA_FROM_DEVICE); | ||
| 950 | kfree_skb(priv->rx_head[i].skb); | ||
| 951 | } | ||
| 952 | } | ||
| 953 | fail_alloc: | ||
| 954 | kfree(priv->desc_ring); | ||
| 955 | iounmap(priv->regs); | ||
| 956 | |||
| 957 | fail_remap: | ||
| 958 | release_mem_region(mem->start, mem->end - mem->start); | ||
| 959 | |||
| 960 | fail_reserve: | ||
| 961 | phy_disconnect(priv->phy); | ||
| 962 | |||
| 963 | return res; | ||
| 964 | } | ||
| 965 | |||
| 966 | static int cpmac_stop(struct net_device *dev) | ||
| 967 | { | ||
| 968 | int i; | ||
| 969 | struct cpmac_priv *priv = netdev_priv(dev); | ||
| 970 | struct resource *mem; | ||
| 971 | |||
| 972 | netif_stop_queue(dev); | ||
| 973 | |||
| 974 | cancel_work_sync(&priv->reset_work); | ||
| 975 | phy_stop(priv->phy); | ||
| 976 | phy_disconnect(priv->phy); | ||
| 977 | priv->phy = NULL; | ||
| 978 | |||
| 979 | cpmac_hw_stop(dev); | ||
| 980 | |||
| 981 | for (i = 0; i < 8; i++) | ||
| 982 | cpmac_write(priv->regs, CPMAC_TX_PTR(i), 0); | ||
| 983 | cpmac_write(priv->regs, CPMAC_RX_PTR(0), 0); | ||
| 984 | cpmac_write(priv->regs, CPMAC_MBP, 0); | ||
| 985 | |||
| 986 | free_irq(dev->irq, dev); | ||
| 987 | iounmap(priv->regs); | ||
| 988 | mem = platform_get_resource_byname(priv->pdev, IORESOURCE_MEM, "regs"); | ||
| 989 | release_mem_region(mem->start, mem->end - mem->start); | ||
| 990 | priv->rx_head = &priv->desc_ring[CPMAC_QUEUES]; | ||
| 991 | for (i = 0; i < priv->ring_size; i++) { | ||
| 992 | if (priv->rx_head[i].skb) { | ||
| 993 | dma_unmap_single(&dev->dev, | ||
| 994 | priv->rx_head[i].data_mapping, | ||
| 995 | CPMAC_SKB_SIZE, | ||
| 996 | DMA_FROM_DEVICE); | ||
| 997 | kfree_skb(priv->rx_head[i].skb); | ||
| 998 | } | ||
| 999 | } | ||
| 1000 | |||
| 1001 | dma_free_coherent(&dev->dev, sizeof(struct cpmac_desc) * | ||
| 1002 | (CPMAC_QUEUES + priv->ring_size), | ||
| 1003 | priv->desc_ring, priv->dma_ring); | ||
| 1004 | return 0; | ||
| 1005 | } | ||
| 1006 | |||
| 1007 | static int external_switch; | ||
| 1008 | |||
| 1009 | static int __devinit cpmac_probe(struct platform_device *pdev) | ||
| 1010 | { | ||
| 1011 | int rc, phy_id; | ||
| 1012 | struct resource *mem; | ||
| 1013 | struct cpmac_priv *priv; | ||
| 1014 | struct net_device *dev; | ||
| 1015 | struct plat_cpmac_data *pdata; | ||
| 1016 | |||
| 1017 | pdata = pdev->dev.platform_data; | ||
| 1018 | |||
| 1019 | for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) { | ||
| 1020 | if (!(pdata->phy_mask & (1 << phy_id))) | ||
| 1021 | continue; | ||
| 1022 | if (!cpmac_mii.phy_map[phy_id]) | ||
| 1023 | continue; | ||
| 1024 | break; | ||
| 1025 | } | ||
| 1026 | |||
| 1027 | if (phy_id == PHY_MAX_ADDR) { | ||
| 1028 | if (external_switch || dumb_switch) | ||
| 1029 | phy_id = 0; | ||
| 1030 | else { | ||
| 1031 | printk(KERN_ERR "cpmac: no PHY present\n"); | ||
| 1032 | return -ENODEV; | ||
| 1033 | } | ||
| 1034 | } | ||
| 1035 | |||
| 1036 | dev = alloc_etherdev_mq(sizeof(*priv), CPMAC_QUEUES); | ||
| 1037 | |||
| 1038 | if (!dev) { | ||
| 1039 | printk(KERN_ERR "cpmac: Unable to allocate net_device\n"); | ||
| 1040 | return -ENOMEM; | ||
| 1041 | } | ||
| 1042 | |||
| 1043 | platform_set_drvdata(pdev, dev); | ||
| 1044 | priv = netdev_priv(dev); | ||
| 1045 | |||
| 1046 | priv->pdev = pdev; | ||
| 1047 | mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); | ||
| 1048 | if (!mem) { | ||
| 1049 | rc = -ENODEV; | ||
| 1050 | goto fail; | ||
| 1051 | } | ||
| 1052 | |||
| 1053 | dev->irq = platform_get_irq_byname(pdev, "irq"); | ||
| 1054 | |||
| 1055 | dev->open = cpmac_open; | ||
| 1056 | dev->stop = cpmac_stop; | ||
| 1057 | dev->set_config = cpmac_config; | ||
| 1058 | dev->hard_start_xmit = cpmac_start_xmit; | ||
| 1059 | dev->do_ioctl = cpmac_ioctl; | ||
| 1060 | dev->set_multicast_list = cpmac_set_multicast_list; | ||
| 1061 | dev->tx_timeout = cpmac_tx_timeout; | ||
| 1062 | dev->ethtool_ops = &cpmac_ethtool_ops; | ||
| 1063 | dev->poll = cpmac_poll; | ||
| 1064 | dev->weight = 64; | ||
| 1065 | dev->features |= NETIF_F_MULTI_QUEUE; | ||
| 1066 | |||
| 1067 | spin_lock_init(&priv->lock); | ||
| 1068 | spin_lock_init(&priv->rx_lock); | ||
| 1069 | priv->dev = dev; | ||
| 1070 | priv->ring_size = 64; | ||
| 1071 | priv->msg_enable = netif_msg_init(debug_level, 0xff); | ||
| 1072 | memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr)); | ||
| 1073 | if (phy_id == 31) { | ||
| 1074 | snprintf(priv->phy_name, BUS_ID_SIZE, PHY_ID_FMT, | ||
| 1075 | cpmac_mii.id, phy_id); | ||
| 1076 | } else | ||
| 1077 | snprintf(priv->phy_name, BUS_ID_SIZE, "fixed@%d:%d", 100, 1); | ||
| 1078 | |||
| 1079 | if ((rc = register_netdev(dev))) { | ||
| 1080 | printk(KERN_ERR "cpmac: error %i registering device %s\n", rc, | ||
| 1081 | dev->name); | ||
| 1082 | goto fail; | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | if (netif_msg_probe(priv)) { | ||
| 1086 | printk(KERN_INFO | ||
| 1087 | "cpmac: device %s (regs: %p, irq: %d, phy: %s, mac: " | ||
| 1088 | MAC_FMT ")\n", dev->name, (void *)mem->start, dev->irq, | ||
| 1089 | priv->phy_name, MAC_ARG(dev->dev_addr)); | ||
| 1090 | } | ||
| 1091 | return 0; | ||
| 1092 | |||
| 1093 | fail: | ||
| 1094 | free_netdev(dev); | ||
| 1095 | return rc; | ||
| 1096 | } | ||
| 1097 | |||
| 1098 | static int __devexit cpmac_remove(struct platform_device *pdev) | ||
| 1099 | { | ||
| 1100 | struct net_device *dev = platform_get_drvdata(pdev); | ||
| 1101 | unregister_netdev(dev); | ||
| 1102 | free_netdev(dev); | ||
| 1103 | return 0; | ||
| 1104 | } | ||
| 1105 | |||
| 1106 | static struct platform_driver cpmac_driver = { | ||
| 1107 | .driver.name = "cpmac", | ||
| 1108 | .probe = cpmac_probe, | ||
| 1109 | .remove = __devexit_p(cpmac_remove), | ||
| 1110 | }; | ||
| 1111 | |||
| 1112 | int __devinit cpmac_init(void) | ||
| 1113 | { | ||
| 1114 | u32 mask; | ||
| 1115 | int i, res; | ||
| 1116 | |||
| 1117 | cpmac_mii.priv = ioremap(AR7_REGS_MDIO, 256); | ||
| 1118 | |||
| 1119 | if (!cpmac_mii.priv) { | ||
| 1120 | printk(KERN_ERR "Can't ioremap mdio registers\n"); | ||
| 1121 | return -ENXIO; | ||
| 1122 | } | ||
| 1123 | |||
| 1124 | #warning FIXME: unhardcode gpio&reset bits | ||
| 1125 | ar7_gpio_disable(26); | ||
| 1126 | ar7_gpio_disable(27); | ||
| 1127 | ar7_device_reset(AR7_RESET_BIT_CPMAC_LO); | ||
| 1128 | ar7_device_reset(AR7_RESET_BIT_CPMAC_HI); | ||
| 1129 | ar7_device_reset(AR7_RESET_BIT_EPHY); | ||
| 1130 | |||
| 1131 | cpmac_mii.reset(&cpmac_mii); | ||
| 1132 | |||
| 1133 | for (i = 0; i < 300000; i++) | ||
| 1134 | if ((mask = cpmac_read(cpmac_mii.priv, CPMAC_MDIO_ALIVE))) | ||
| 1135 | break; | ||
| 1136 | else | ||
| 1137 | cpu_relax(); | ||
| 1138 | |||
| 1139 | mask &= 0x7fffffff; | ||
| 1140 | if (mask & (mask - 1)) { | ||
| 1141 | external_switch = 1; | ||
| 1142 | mask = 0; | ||
| 1143 | } | ||
| 1144 | |||
| 1145 | cpmac_mii.phy_mask = ~(mask | 0x80000000); | ||
| 1146 | |||
| 1147 | res = mdiobus_register(&cpmac_mii); | ||
| 1148 | if (res) | ||
| 1149 | goto fail_mii; | ||
| 1150 | |||
| 1151 | res = platform_driver_register(&cpmac_driver); | ||
| 1152 | if (res) | ||
| 1153 | goto fail_cpmac; | ||
| 1154 | |||
| 1155 | return 0; | ||
| 1156 | |||
| 1157 | fail_cpmac: | ||
| 1158 | mdiobus_unregister(&cpmac_mii); | ||
| 1159 | |||
| 1160 | fail_mii: | ||
| 1161 | iounmap(cpmac_mii.priv); | ||
| 1162 | |||
| 1163 | return res; | ||
| 1164 | } | ||
| 1165 | |||
| 1166 | void __devexit cpmac_exit(void) | ||
| 1167 | { | ||
| 1168 | platform_driver_unregister(&cpmac_driver); | ||
| 1169 | mdiobus_unregister(&cpmac_mii); | ||
| 1170 | iounmap(cpmac_mii.priv); | ||
| 1171 | } | ||
| 1172 | |||
| 1173 | module_init(cpmac_init); | ||
| 1174 | module_exit(cpmac_exit); | ||
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 0db5e6fabe73..558440c15b6c 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
| @@ -168,7 +168,6 @@ static int gfar_probe(struct platform_device *pdev) | |||
| 168 | struct gfar_private *priv = NULL; | 168 | struct gfar_private *priv = NULL; |
| 169 | struct gianfar_platform_data *einfo; | 169 | struct gianfar_platform_data *einfo; |
| 170 | struct resource *r; | 170 | struct resource *r; |
| 171 | int idx; | ||
| 172 | int err = 0; | 171 | int err = 0; |
| 173 | DECLARE_MAC_BUF(mac); | 172 | DECLARE_MAC_BUF(mac); |
| 174 | 173 | ||
| @@ -261,7 +260,9 @@ static int gfar_probe(struct platform_device *pdev) | |||
| 261 | dev->hard_start_xmit = gfar_start_xmit; | 260 | dev->hard_start_xmit = gfar_start_xmit; |
| 262 | dev->tx_timeout = gfar_timeout; | 261 | dev->tx_timeout = gfar_timeout; |
| 263 | dev->watchdog_timeo = TX_TIMEOUT; | 262 | dev->watchdog_timeo = TX_TIMEOUT; |
| 263 | #ifdef CONFIG_GFAR_NAPI | ||
| 264 | netif_napi_add(dev, &priv->napi, gfar_poll, GFAR_DEV_WEIGHT); | 264 | netif_napi_add(dev, &priv->napi, gfar_poll, GFAR_DEV_WEIGHT); |
| 265 | #endif | ||
| 265 | #ifdef CONFIG_NET_POLL_CONTROLLER | 266 | #ifdef CONFIG_NET_POLL_CONTROLLER |
| 266 | dev->poll_controller = gfar_netpoll; | 267 | dev->poll_controller = gfar_netpoll; |
| 267 | #endif | 268 | #endif |
| @@ -931,9 +932,14 @@ tx_skb_fail: | |||
| 931 | /* Returns 0 for success. */ | 932 | /* Returns 0 for success. */ |
| 932 | static int gfar_enet_open(struct net_device *dev) | 933 | static int gfar_enet_open(struct net_device *dev) |
| 933 | { | 934 | { |
| 935 | #ifdef CONFIG_GFAR_NAPI | ||
| 936 | struct gfar_private *priv = netdev_priv(dev); | ||
| 937 | #endif | ||
| 934 | int err; | 938 | int err; |
| 935 | 939 | ||
| 940 | #ifdef CONFIG_GFAR_NAPI | ||
| 936 | napi_enable(&priv->napi); | 941 | napi_enable(&priv->napi); |
| 942 | #endif | ||
| 937 | 943 | ||
| 938 | /* Initialize a bunch of registers */ | 944 | /* Initialize a bunch of registers */ |
| 939 | init_registers(dev); | 945 | init_registers(dev); |
| @@ -943,13 +949,17 @@ static int gfar_enet_open(struct net_device *dev) | |||
| 943 | err = init_phy(dev); | 949 | err = init_phy(dev); |
| 944 | 950 | ||
| 945 | if(err) { | 951 | if(err) { |
| 952 | #ifdef CONFIG_GFAR_NAPI | ||
| 946 | napi_disable(&priv->napi); | 953 | napi_disable(&priv->napi); |
| 954 | #endif | ||
| 947 | return err; | 955 | return err; |
| 948 | } | 956 | } |
| 949 | 957 | ||
| 950 | err = startup_gfar(dev); | 958 | err = startup_gfar(dev); |
| 951 | if (err) | 959 | if (err) |
| 960 | #ifdef CONFIG_GFAR_NAPI | ||
| 952 | napi_disable(&priv->napi); | 961 | napi_disable(&priv->napi); |
| 962 | #endif | ||
| 953 | 963 | ||
| 954 | netif_start_queue(dev); | 964 | netif_start_queue(dev); |
| 955 | 965 | ||
| @@ -1103,7 +1113,9 @@ static int gfar_close(struct net_device *dev) | |||
| 1103 | { | 1113 | { |
| 1104 | struct gfar_private *priv = netdev_priv(dev); | 1114 | struct gfar_private *priv = netdev_priv(dev); |
| 1105 | 1115 | ||
| 1116 | #ifdef CONFIG_GFAR_NAPI | ||
| 1106 | napi_disable(&priv->napi); | 1117 | napi_disable(&priv->napi); |
| 1118 | #endif | ||
| 1107 | 1119 | ||
| 1108 | stop_gfar(dev); | 1120 | stop_gfar(dev); |
| 1109 | 1121 | ||
diff --git a/drivers/net/ibm_emac/ibm_emac_mal.c b/drivers/net/ibm_emac/ibm_emac_mal.c index 4e49e8c4f871..dcd8826fc749 100644 --- a/drivers/net/ibm_emac/ibm_emac_mal.c +++ b/drivers/net/ibm_emac/ibm_emac_mal.c | |||
| @@ -413,7 +413,10 @@ static int __init mal_probe(struct ocp_device *ocpdev) | |||
| 413 | ocpdev->def->index); | 413 | ocpdev->def->index); |
| 414 | return -ENOMEM; | 414 | return -ENOMEM; |
| 415 | } | 415 | } |
| 416 | mal->dcrbase = maldata->dcr_base; | 416 | |
| 417 | /* XXX This only works for native dcr for now */ | ||
| 418 | mal->dcrhost = dcr_map(NULL, maldata->dcr_base, 0); | ||
| 419 | |||
| 417 | mal->def = ocpdev->def; | 420 | mal->def = ocpdev->def; |
| 418 | 421 | ||
| 419 | INIT_LIST_HEAD(&mal->poll_list); | 422 | INIT_LIST_HEAD(&mal->poll_list); |
diff --git a/drivers/net/ibm_emac/ibm_emac_mal.h b/drivers/net/ibm_emac/ibm_emac_mal.h index 8f54d621994d..b8adbe6d4b01 100644 --- a/drivers/net/ibm_emac/ibm_emac_mal.h +++ b/drivers/net/ibm_emac/ibm_emac_mal.h | |||
| @@ -191,7 +191,6 @@ struct mal_commac { | |||
| 191 | }; | 191 | }; |
| 192 | 192 | ||
| 193 | struct ibm_ocp_mal { | 193 | struct ibm_ocp_mal { |
| 194 | int dcrbase; | ||
| 195 | dcr_host_t dcrhost; | 194 | dcr_host_t dcrhost; |
| 196 | 195 | ||
| 197 | struct list_head poll_list; | 196 | struct list_head poll_list; |
| @@ -209,12 +208,12 @@ struct ibm_ocp_mal { | |||
| 209 | 208 | ||
| 210 | static inline u32 get_mal_dcrn(struct ibm_ocp_mal *mal, int reg) | 209 | static inline u32 get_mal_dcrn(struct ibm_ocp_mal *mal, int reg) |
| 211 | { | 210 | { |
| 212 | return dcr_read(mal->dcrhost, mal->dcrbase + reg); | 211 | return dcr_read(mal->dcrhost, reg); |
| 213 | } | 212 | } |
| 214 | 213 | ||
| 215 | static inline void set_mal_dcrn(struct ibm_ocp_mal *mal, int reg, u32 val) | 214 | static inline void set_mal_dcrn(struct ibm_ocp_mal *mal, int reg, u32 val) |
| 216 | { | 215 | { |
| 217 | dcr_write(mal->dcrhost, mal->dcrbase + reg, val); | 216 | dcr_write(mal->dcrhost, reg, val); |
| 218 | } | 217 | } |
| 219 | 218 | ||
| 220 | /* Register MAL devices */ | 219 | /* Register MAL devices */ |
diff --git a/drivers/net/ibm_newemac/mal.c b/drivers/net/ibm_newemac/mal.c index 58854117b1a9..39f4cb6b0cf3 100644 --- a/drivers/net/ibm_newemac/mal.c +++ b/drivers/net/ibm_newemac/mal.c | |||
| @@ -461,6 +461,7 @@ static int __devinit mal_probe(struct of_device *ofdev, | |||
| 461 | struct mal_instance *mal; | 461 | struct mal_instance *mal; |
| 462 | int err = 0, i, bd_size; | 462 | int err = 0, i, bd_size; |
| 463 | int index = mal_count++; | 463 | int index = mal_count++; |
| 464 | unsigned int dcr_base; | ||
| 464 | const u32 *prop; | 465 | const u32 *prop; |
| 465 | u32 cfg; | 466 | u32 cfg; |
| 466 | 467 | ||
| @@ -497,14 +498,14 @@ static int __devinit mal_probe(struct of_device *ofdev, | |||
| 497 | } | 498 | } |
| 498 | mal->num_rx_chans = prop[0]; | 499 | mal->num_rx_chans = prop[0]; |
| 499 | 500 | ||
| 500 | mal->dcr_base = dcr_resource_start(ofdev->node, 0); | 501 | dcr_base = dcr_resource_start(ofdev->node, 0); |
| 501 | if (mal->dcr_base == 0) { | 502 | if (dcr_base == 0) { |
| 502 | printk(KERN_ERR | 503 | printk(KERN_ERR |
| 503 | "mal%d: can't find DCR resource!\n", index); | 504 | "mal%d: can't find DCR resource!\n", index); |
| 504 | err = -ENODEV; | 505 | err = -ENODEV; |
| 505 | goto fail; | 506 | goto fail; |
| 506 | } | 507 | } |
| 507 | mal->dcr_host = dcr_map(ofdev->node, mal->dcr_base, 0x100); | 508 | mal->dcr_host = dcr_map(ofdev->node, dcr_base, 0x100); |
| 508 | if (!DCR_MAP_OK(mal->dcr_host)) { | 509 | if (!DCR_MAP_OK(mal->dcr_host)) { |
| 509 | printk(KERN_ERR | 510 | printk(KERN_ERR |
| 510 | "mal%d: failed to map DCRs !\n", index); | 511 | "mal%d: failed to map DCRs !\n", index); |
| @@ -626,7 +627,7 @@ static int __devinit mal_probe(struct of_device *ofdev, | |||
| 626 | fail2: | 627 | fail2: |
| 627 | dma_free_coherent(&ofdev->dev, bd_size, mal->bd_virt, mal->bd_dma); | 628 | dma_free_coherent(&ofdev->dev, bd_size, mal->bd_virt, mal->bd_dma); |
| 628 | fail_unmap: | 629 | fail_unmap: |
| 629 | dcr_unmap(mal->dcr_host, mal->dcr_base, 0x100); | 630 | dcr_unmap(mal->dcr_host, 0x100); |
| 630 | fail: | 631 | fail: |
| 631 | kfree(mal); | 632 | kfree(mal); |
| 632 | 633 | ||
diff --git a/drivers/net/ibm_newemac/mal.h b/drivers/net/ibm_newemac/mal.h index cb1a16d589fe..784edb8ea822 100644 --- a/drivers/net/ibm_newemac/mal.h +++ b/drivers/net/ibm_newemac/mal.h | |||
| @@ -185,7 +185,6 @@ struct mal_commac { | |||
| 185 | 185 | ||
| 186 | struct mal_instance { | 186 | struct mal_instance { |
| 187 | int version; | 187 | int version; |
| 188 | int dcr_base; | ||
| 189 | dcr_host_t dcr_host; | 188 | dcr_host_t dcr_host; |
| 190 | 189 | ||
| 191 | int num_tx_chans; /* Number of TX channels */ | 190 | int num_tx_chans; /* Number of TX channels */ |
| @@ -213,12 +212,12 @@ struct mal_instance { | |||
| 213 | 212 | ||
| 214 | static inline u32 get_mal_dcrn(struct mal_instance *mal, int reg) | 213 | static inline u32 get_mal_dcrn(struct mal_instance *mal, int reg) |
| 215 | { | 214 | { |
| 216 | return dcr_read(mal->dcr_host, mal->dcr_base + reg); | 215 | return dcr_read(mal->dcr_host, reg); |
| 217 | } | 216 | } |
| 218 | 217 | ||
| 219 | static inline void set_mal_dcrn(struct mal_instance *mal, int reg, u32 val) | 218 | static inline void set_mal_dcrn(struct mal_instance *mal, int reg, u32 val) |
| 220 | { | 219 | { |
| 221 | dcr_write(mal->dcr_host, mal->dcr_base + reg, val); | 220 | dcr_write(mal->dcr_host, reg, val); |
| 222 | } | 221 | } |
| 223 | 222 | ||
| 224 | /* Register MAL devices */ | 223 | /* Register MAL devices */ |
diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c index 3e5eca1aa987..a82d8f98383d 100644 --- a/drivers/net/irda/donauboe.c +++ b/drivers/net/irda/donauboe.c | |||
| @@ -840,7 +840,7 @@ toshoboe_probe (struct toshoboe_cb *self) | |||
| 840 | 840 | ||
| 841 | /* test 1: SIR filter and back to back */ | 841 | /* test 1: SIR filter and back to back */ |
| 842 | 842 | ||
| 843 | for (j = 0; j < (sizeof (bauds) / sizeof (int)); ++j) | 843 | for (j = 0; j < ARRAY_SIZE(bauds); ++j) |
| 844 | { | 844 | { |
| 845 | int fir = (j > 1); | 845 | int fir = (j > 1); |
| 846 | toshoboe_stopchip (self); | 846 | toshoboe_stopchip (self); |
diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c index d3825c8ee994..5c154fe13859 100644 --- a/drivers/net/jazzsonic.c +++ b/drivers/net/jazzsonic.c | |||
| @@ -208,7 +208,6 @@ static int __init jazz_sonic_probe(struct platform_device *pdev) | |||
| 208 | struct sonic_local *lp; | 208 | struct sonic_local *lp; |
| 209 | struct resource *res; | 209 | struct resource *res; |
| 210 | int err = 0; | 210 | int err = 0; |
| 211 | int i; | ||
| 212 | DECLARE_MAC_BUF(mac); | 211 | DECLARE_MAC_BUF(mac); |
| 213 | 212 | ||
| 214 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 213 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index be25aa33971c..662b8d16803c 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c | |||
| @@ -265,17 +265,16 @@ static __net_init int loopback_net_init(struct net *net) | |||
| 265 | if (err) | 265 | if (err) |
| 266 | goto out_free_netdev; | 266 | goto out_free_netdev; |
| 267 | 267 | ||
| 268 | err = 0; | ||
| 269 | net->loopback_dev = dev; | 268 | net->loopback_dev = dev; |
| 269 | return 0; | ||
| 270 | 270 | ||
| 271 | out: | ||
| 272 | if (err) | ||
| 273 | panic("loopback: Failed to register netdevice: %d\n", err); | ||
| 274 | return err; | ||
| 275 | 271 | ||
| 276 | out_free_netdev: | 272 | out_free_netdev: |
| 277 | free_netdev(dev); | 273 | free_netdev(dev); |
| 278 | goto out; | 274 | out: |
| 275 | if (net == &init_net) | ||
| 276 | panic("loopback: Failed to register netdevice: %d\n", err); | ||
| 277 | return err; | ||
| 279 | } | 278 | } |
| 280 | 279 | ||
| 281 | static __net_exit void loopback_net_exit(struct net *net) | 280 | static __net_exit void loopback_net_exit(struct net *net) |
diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c index d593175ab6f0..37707a0c0498 100644 --- a/drivers/net/mipsnet.c +++ b/drivers/net/mipsnet.c | |||
| @@ -7,12 +7,12 @@ | |||
| 7 | #define DEBUG | 7 | #define DEBUG |
| 8 | 8 | ||
| 9 | #include <linux/init.h> | 9 | #include <linux/init.h> |
| 10 | #include <linux/io.h> | ||
| 10 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
| 11 | #include <linux/module.h> | 12 | #include <linux/module.h> |
| 12 | #include <linux/netdevice.h> | 13 | #include <linux/netdevice.h> |
| 13 | #include <linux/etherdevice.h> | 14 | #include <linux/etherdevice.h> |
| 14 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
| 15 | #include <asm/io.h> | ||
| 16 | #include <asm/mips-boards/simint.h> | 16 | #include <asm/mips-boards/simint.h> |
| 17 | 17 | ||
| 18 | #include "mipsnet.h" /* actual device IO mapping */ | 18 | #include "mipsnet.h" /* actual device IO mapping */ |
| @@ -33,9 +33,8 @@ static int ioiocpy_frommipsnet(struct net_device *dev, unsigned char *kdata, | |||
| 33 | if (available_len < len) | 33 | if (available_len < len) |
| 34 | return -EFAULT; | 34 | return -EFAULT; |
| 35 | 35 | ||
| 36 | for (; len > 0; len--, kdata++) { | 36 | for (; len > 0; len--, kdata++) |
| 37 | *kdata = inb(mipsnet_reg_address(dev, rxDataBuffer)); | 37 | *kdata = inb(mipsnet_reg_address(dev, rxDataBuffer)); |
| 38 | } | ||
| 39 | 38 | ||
| 40 | return inl(mipsnet_reg_address(dev, rxDataCount)); | 39 | return inl(mipsnet_reg_address(dev, rxDataCount)); |
| 41 | } | 40 | } |
| @@ -47,16 +46,15 @@ static inline ssize_t mipsnet_put_todevice(struct net_device *dev, | |||
| 47 | char *buf_ptr = skb->data; | 46 | char *buf_ptr = skb->data; |
| 48 | 47 | ||
| 49 | pr_debug("%s: %s(): telling MIPSNET txDataCount(%d)\n", | 48 | pr_debug("%s: %s(): telling MIPSNET txDataCount(%d)\n", |
| 50 | dev->name, __FUNCTION__, skb->len); | 49 | dev->name, __FUNCTION__, skb->len); |
| 51 | 50 | ||
| 52 | outl(skb->len, mipsnet_reg_address(dev, txDataCount)); | 51 | outl(skb->len, mipsnet_reg_address(dev, txDataCount)); |
| 53 | 52 | ||
| 54 | pr_debug("%s: %s(): sending data to MIPSNET txDataBuffer(%d)\n", | 53 | pr_debug("%s: %s(): sending data to MIPSNET txDataBuffer(%d)\n", |
| 55 | dev->name, __FUNCTION__, skb->len); | 54 | dev->name, __FUNCTION__, skb->len); |
| 56 | 55 | ||
| 57 | for (; count_to_go; buf_ptr++, count_to_go--) { | 56 | for (; count_to_go; buf_ptr++, count_to_go--) |
| 58 | outb(*buf_ptr, mipsnet_reg_address(dev, txDataBuffer)); | 57 | outb(*buf_ptr, mipsnet_reg_address(dev, txDataBuffer)); |
| 59 | } | ||
| 60 | 58 | ||
| 61 | dev->stats.tx_packets++; | 59 | dev->stats.tx_packets++; |
| 62 | dev->stats.tx_bytes += skb->len; | 60 | dev->stats.tx_bytes += skb->len; |
| @@ -67,7 +65,7 @@ static inline ssize_t mipsnet_put_todevice(struct net_device *dev, | |||
| 67 | static int mipsnet_xmit(struct sk_buff *skb, struct net_device *dev) | 65 | static int mipsnet_xmit(struct sk_buff *skb, struct net_device *dev) |
| 68 | { | 66 | { |
| 69 | pr_debug("%s:%s(): transmitting %d bytes\n", | 67 | pr_debug("%s:%s(): transmitting %d bytes\n", |
| 70 | dev->name, __FUNCTION__, skb->len); | 68 | dev->name, __FUNCTION__, skb->len); |
| 71 | 69 | ||
| 72 | /* Only one packet at a time. Once TXDONE interrupt is serviced, the | 70 | /* Only one packet at a time. Once TXDONE interrupt is serviced, the |
| 73 | * queue will be restarted. | 71 | * queue will be restarted. |
| @@ -83,7 +81,8 @@ static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t count) | |||
| 83 | struct sk_buff *skb; | 81 | struct sk_buff *skb; |
| 84 | size_t len = count; | 82 | size_t len = count; |
| 85 | 83 | ||
| 86 | if (!(skb = alloc_skb(len + 2, GFP_KERNEL))) { | 84 | skb = alloc_skb(len + 2, GFP_KERNEL); |
| 85 | if (!skb) { | ||
| 87 | dev->stats.rx_dropped++; | 86 | dev->stats.rx_dropped++; |
| 88 | return -ENOMEM; | 87 | return -ENOMEM; |
| 89 | } | 88 | } |
| @@ -96,7 +95,7 @@ static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t count) | |||
| 96 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 95 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
| 97 | 96 | ||
| 98 | pr_debug("%s:%s(): pushing RXed data to kernel\n", | 97 | pr_debug("%s:%s(): pushing RXed data to kernel\n", |
| 99 | dev->name, __FUNCTION__); | 98 | dev->name, __FUNCTION__); |
| 100 | netif_rx(skb); | 99 | netif_rx(skb); |
| 101 | 100 | ||
| 102 | dev->stats.rx_packets++; | 101 | dev->stats.rx_packets++; |
| @@ -114,42 +113,44 @@ static irqreturn_t mipsnet_interrupt(int irq, void *dev_id) | |||
| 114 | 113 | ||
| 115 | if (irq == dev->irq) { | 114 | if (irq == dev->irq) { |
| 116 | pr_debug("%s:%s(): irq %d for device\n", | 115 | pr_debug("%s:%s(): irq %d for device\n", |
| 117 | dev->name, __FUNCTION__, irq); | 116 | dev->name, __FUNCTION__, irq); |
| 118 | 117 | ||
| 119 | retval = IRQ_HANDLED; | 118 | retval = IRQ_HANDLED; |
| 120 | 119 | ||
| 121 | interruptFlags = | 120 | interruptFlags = |
| 122 | inl(mipsnet_reg_address(dev, interruptControl)); | 121 | inl(mipsnet_reg_address(dev, interruptControl)); |
| 123 | pr_debug("%s:%s(): intCtl=0x%016llx\n", dev->name, | 122 | pr_debug("%s:%s(): intCtl=0x%016llx\n", dev->name, |
| 124 | __FUNCTION__, interruptFlags); | 123 | __FUNCTION__, interruptFlags); |
| 125 | 124 | ||
| 126 | if (interruptFlags & MIPSNET_INTCTL_TXDONE) { | 125 | if (interruptFlags & MIPSNET_INTCTL_TXDONE) { |
| 127 | pr_debug("%s:%s(): got TXDone\n", | 126 | pr_debug("%s:%s(): got TXDone\n", |
| 128 | dev->name, __FUNCTION__); | 127 | dev->name, __FUNCTION__); |
| 129 | outl(MIPSNET_INTCTL_TXDONE, | 128 | outl(MIPSNET_INTCTL_TXDONE, |
| 130 | mipsnet_reg_address(dev, interruptControl)); | 129 | mipsnet_reg_address(dev, interruptControl)); |
| 131 | // only one packet at a time, we are done. | 130 | /* only one packet at a time, we are done. */ |
| 132 | netif_wake_queue(dev); | 131 | netif_wake_queue(dev); |
| 133 | } else if (interruptFlags & MIPSNET_INTCTL_RXDONE) { | 132 | } else if (interruptFlags & MIPSNET_INTCTL_RXDONE) { |
| 134 | pr_debug("%s:%s(): got RX data\n", | 133 | pr_debug("%s:%s(): got RX data\n", |
| 135 | dev->name, __FUNCTION__); | 134 | dev->name, __FUNCTION__); |
| 136 | mipsnet_get_fromdev(dev, | 135 | mipsnet_get_fromdev(dev, |
| 137 | inl(mipsnet_reg_address(dev, rxDataCount))); | 136 | inl(mipsnet_reg_address(dev, rxDataCount))); |
| 138 | pr_debug("%s:%s(): clearing RX int\n", | 137 | pr_debug("%s:%s(): clearing RX int\n", |
| 139 | dev->name, __FUNCTION__); | 138 | dev->name, __FUNCTION__); |
| 140 | outl(MIPSNET_INTCTL_RXDONE, | 139 | outl(MIPSNET_INTCTL_RXDONE, |
| 141 | mipsnet_reg_address(dev, interruptControl)); | 140 | mipsnet_reg_address(dev, interruptControl)); |
| 142 | 141 | ||
| 143 | } else if (interruptFlags & MIPSNET_INTCTL_TESTBIT) { | 142 | } else if (interruptFlags & MIPSNET_INTCTL_TESTBIT) { |
| 144 | pr_debug("%s:%s(): got test interrupt\n", | 143 | pr_debug("%s:%s(): got test interrupt\n", |
| 145 | dev->name, __FUNCTION__); | 144 | dev->name, __FUNCTION__); |
| 146 | // TESTBIT is cleared on read. | 145 | /* |
| 147 | // And takes effect after a write with 0 | 146 | * TESTBIT is cleared on read. |
| 147 | * And takes effect after a write with 0 | ||
| 148 | */ | ||
| 148 | outl(0, mipsnet_reg_address(dev, interruptControl)); | 149 | outl(0, mipsnet_reg_address(dev, interruptControl)); |
| 149 | } else { | 150 | } else { |
| 150 | pr_debug("%s:%s(): no valid fags 0x%016llx\n", | 151 | pr_debug("%s:%s(): no valid fags 0x%016llx\n", |
| 151 | dev->name, __FUNCTION__, interruptFlags); | 152 | dev->name, __FUNCTION__, interruptFlags); |
| 152 | // Maybe shared IRQ, just ignore, no clearing. | 153 | /* Maybe shared IRQ, just ignore, no clearing. */ |
| 153 | retval = IRQ_NONE; | 154 | retval = IRQ_NONE; |
| 154 | } | 155 | } |
| 155 | 156 | ||
| @@ -159,7 +160,7 @@ static irqreturn_t mipsnet_interrupt(int irq, void *dev_id) | |||
| 159 | retval = IRQ_NONE; | 160 | retval = IRQ_NONE; |
| 160 | } | 161 | } |
| 161 | return retval; | 162 | return retval; |
| 162 | } //mipsnet_interrupt() | 163 | } |
| 163 | 164 | ||
| 164 | static int mipsnet_open(struct net_device *dev) | 165 | static int mipsnet_open(struct net_device *dev) |
| 165 | { | 166 | { |
| @@ -171,18 +172,18 @@ static int mipsnet_open(struct net_device *dev) | |||
| 171 | 172 | ||
| 172 | if (err) { | 173 | if (err) { |
| 173 | pr_debug("%s: %s(): can't get irq %d\n", | 174 | pr_debug("%s: %s(): can't get irq %d\n", |
| 174 | dev->name, __FUNCTION__, dev->irq); | 175 | dev->name, __FUNCTION__, dev->irq); |
| 175 | release_region(dev->base_addr, MIPSNET_IO_EXTENT); | 176 | release_region(dev->base_addr, MIPSNET_IO_EXTENT); |
| 176 | return err; | 177 | return err; |
| 177 | } | 178 | } |
| 178 | 179 | ||
| 179 | pr_debug("%s: %s(): got IO region at 0x%04lx and irq %d for dev.\n", | 180 | pr_debug("%s: %s(): got IO region at 0x%04lx and irq %d for dev.\n", |
| 180 | dev->name, __FUNCTION__, dev->base_addr, dev->irq); | 181 | dev->name, __FUNCTION__, dev->base_addr, dev->irq); |
| 181 | 182 | ||
| 182 | 183 | ||
| 183 | netif_start_queue(dev); | 184 | netif_start_queue(dev); |
| 184 | 185 | ||
| 185 | // test interrupt handler | 186 | /* test interrupt handler */ |
| 186 | outl(MIPSNET_INTCTL_TESTBIT, | 187 | outl(MIPSNET_INTCTL_TESTBIT, |
| 187 | mipsnet_reg_address(dev, interruptControl)); | 188 | mipsnet_reg_address(dev, interruptControl)); |
| 188 | 189 | ||
| @@ -199,8 +200,6 @@ static int mipsnet_close(struct net_device *dev) | |||
| 199 | 200 | ||
| 200 | static void mipsnet_set_mclist(struct net_device *dev) | 201 | static void mipsnet_set_mclist(struct net_device *dev) |
| 201 | { | 202 | { |
| 202 | // we don't do anything | ||
| 203 | return; | ||
| 204 | } | 203 | } |
| 205 | 204 | ||
| 206 | static int __init mipsnet_probe(struct device *dev) | 205 | static int __init mipsnet_probe(struct device *dev) |
| @@ -226,13 +225,13 @@ static int __init mipsnet_probe(struct device *dev) | |||
| 226 | */ | 225 | */ |
| 227 | netdev->base_addr = 0x4200; | 226 | netdev->base_addr = 0x4200; |
| 228 | netdev->irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB0 + | 227 | netdev->irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB0 + |
| 229 | inl(mipsnet_reg_address(netdev, interruptInfo)); | 228 | inl(mipsnet_reg_address(netdev, interruptInfo)); |
| 230 | 229 | ||
| 231 | // Get the io region now, get irq on open() | 230 | /* Get the io region now, get irq on open() */ |
| 232 | if (!request_region(netdev->base_addr, MIPSNET_IO_EXTENT, "mipsnet")) { | 231 | if (!request_region(netdev->base_addr, MIPSNET_IO_EXTENT, "mipsnet")) { |
| 233 | pr_debug("%s: %s(): IO region {start: 0x%04lux, len: %d} " | 232 | pr_debug("%s: %s(): IO region {start: 0x%04lux, len: %d} " |
| 234 | "for dev is not availble.\n", netdev->name, | 233 | "for dev is not availble.\n", netdev->name, |
| 235 | __FUNCTION__, netdev->base_addr, MIPSNET_IO_EXTENT); | 234 | __FUNCTION__, netdev->base_addr, MIPSNET_IO_EXTENT); |
| 236 | err = -EBUSY; | 235 | err = -EBUSY; |
| 237 | goto out_free_netdev; | 236 | goto out_free_netdev; |
| 238 | } | 237 | } |
diff --git a/drivers/net/mipsnet.h b/drivers/net/mipsnet.h index 026c732024c9..0132c6714a40 100644 --- a/drivers/net/mipsnet.h +++ b/drivers/net/mipsnet.h | |||
| @@ -9,32 +9,34 @@ | |||
| 9 | /* | 9 | /* |
| 10 | * Id of this Net device, as seen by the core. | 10 | * Id of this Net device, as seen by the core. |
| 11 | */ | 11 | */ |
| 12 | #define MIPS_NET_DEV_ID ((uint64_t) \ | 12 | #define MIPS_NET_DEV_ID ((uint64_t) \ |
| 13 | ((uint64_t)'M'<< 0)| \ | 13 | ((uint64_t) 'M' << 0)| \ |
| 14 | ((uint64_t)'I'<< 8)| \ | 14 | ((uint64_t) 'I' << 8)| \ |
| 15 | ((uint64_t)'P'<<16)| \ | 15 | ((uint64_t) 'P' << 16)| \ |
| 16 | ((uint64_t)'S'<<24)| \ | 16 | ((uint64_t) 'S' << 24)| \ |
| 17 | ((uint64_t)'N'<<32)| \ | 17 | ((uint64_t) 'N' << 32)| \ |
| 18 | ((uint64_t)'E'<<40)| \ | 18 | ((uint64_t) 'E' << 40)| \ |
| 19 | ((uint64_t)'T'<<48)| \ | 19 | ((uint64_t) 'T' << 48)| \ |
| 20 | ((uint64_t)'0'<<56)) | 20 | ((uint64_t) '0' << 56)) |
| 21 | 21 | ||
| 22 | /* | 22 | /* |
| 23 | * Net status/control block as seen by sw in the core. | 23 | * Net status/control block as seen by sw in the core. |
| 24 | * (Why not use bit fields? can't be bothered with cross-platform struct | 24 | * (Why not use bit fields? can't be bothered with cross-platform struct |
| 25 | * packing.) | 25 | * packing.) |
| 26 | */ | 26 | */ |
| 27 | typedef struct _net_control_block { | 27 | struct net_control_block { |
| 28 | /// dev info for probing | 28 | /* |
| 29 | /// reads as MIPSNET%d where %d is some form of version | 29 | * dev info for probing |
| 30 | uint64_t devId; /*0x00 */ | 30 | * reads as MIPSNET%d where %d is some form of version |
| 31 | */ | ||
| 32 | uint64_t devId; /* 0x00 */ | ||
| 31 | 33 | ||
| 32 | /* | 34 | /* |
| 33 | * read only busy flag. | 35 | * read only busy flag. |
| 34 | * Set and cleared by the Net Device to indicate that an rx or a tx | 36 | * Set and cleared by the Net Device to indicate that an rx or a tx |
| 35 | * is in progress. | 37 | * is in progress. |
| 36 | */ | 38 | */ |
| 37 | uint32_t busy; /*0x08 */ | 39 | uint32_t busy; /* 0x08 */ |
| 38 | 40 | ||
| 39 | /* | 41 | /* |
| 40 | * Set by the Net Device. | 42 | * Set by the Net Device. |
| @@ -43,16 +45,16 @@ typedef struct _net_control_block { | |||
| 43 | * rxDataBuffer. The value will decrease till 0 until all the data | 45 | * rxDataBuffer. The value will decrease till 0 until all the data |
| 44 | * from rxDataBuffer has been read. | 46 | * from rxDataBuffer has been read. |
| 45 | */ | 47 | */ |
| 46 | uint32_t rxDataCount; /*0x0c */ | 48 | uint32_t rxDataCount; /* 0x0c */ |
| 47 | #define MIPSNET_MAX_RXTX_DATACOUNT (1<<16) | 49 | #define MIPSNET_MAX_RXTX_DATACOUNT (1<<16) |
| 48 | 50 | ||
| 49 | /* | 51 | /* |
| 50 | * Settable from the MIPS core, cleared by the Net Device. | 52 | * Settable from the MIPS core, cleared by the Net Device. The core |
| 51 | * The core should set the number of bytes it wants to send, | 53 | * should set the number of bytes it wants to send, then it should |
| 52 | * then it should write those bytes of data to txDataBuffer. | 54 | * write those bytes of data to txDataBuffer. The device will clear |
| 53 | * The device will clear txDataCount has been processed (not necessarily sent). | 55 | * txDataCount has been processed (not necessarily sent). |
| 54 | */ | 56 | */ |
| 55 | uint32_t txDataCount; /*0x10 */ | 57 | uint32_t txDataCount; /* 0x10 */ |
| 56 | 58 | ||
| 57 | /* | 59 | /* |
| 58 | * Interrupt control | 60 | * Interrupt control |
| @@ -69,39 +71,42 @@ typedef struct _net_control_block { | |||
| 69 | * To clear the test interrupt, write 0 to this register. | 71 | * To clear the test interrupt, write 0 to this register. |
| 70 | */ | 72 | */ |
| 71 | uint32_t interruptControl; /*0x14 */ | 73 | uint32_t interruptControl; /*0x14 */ |
| 72 | #define MIPSNET_INTCTL_TXDONE ((uint32_t)(1<< 0)) | 74 | #define MIPSNET_INTCTL_TXDONE ((uint32_t)(1 << 0)) |
| 73 | #define MIPSNET_INTCTL_RXDONE ((uint32_t)(1<< 1)) | 75 | #define MIPSNET_INTCTL_RXDONE ((uint32_t)(1 << 1)) |
| 74 | #define MIPSNET_INTCTL_TESTBIT ((uint32_t)(1<<31)) | 76 | #define MIPSNET_INTCTL_TESTBIT ((uint32_t)(1 << 31)) |
| 75 | #define MIPSNET_INTCTL_ALLSOURCES (MIPSNET_INTCTL_TXDONE|MIPSNET_INTCTL_RXDONE|MIPSNET_INTCTL_TESTBIT) | 77 | #define MIPSNET_INTCTL_ALLSOURCES (MIPSNET_INTCTL_TXDONE | \ |
| 78 | MIPSNET_INTCTL_RXDONE | \ | ||
| 79 | MIPSNET_INTCTL_TESTBIT) | ||
| 76 | 80 | ||
| 77 | /* | 81 | /* |
| 78 | * Readonly core-specific interrupt info for the device to signal the core. | 82 | * Readonly core-specific interrupt info for the device to signal the |
| 79 | * The meaning of the contents of this field might change. | 83 | * core. The meaning of the contents of this field might change. |
| 80 | */ | 84 | * |
| 81 | /*###\todo: the whole memIntf interrupt scheme is messy: the device should have | 85 | * TODO: the whole memIntf interrupt scheme is messy: the device should |
| 82 | * no control what so ever of what VPE/register set is being used. | 86 | * have no control what so ever of what VPE/register set is being |
| 83 | * The MemIntf should only expose interrupt lines, and something in the | 87 | * used. The MemIntf should only expose interrupt lines, and |
| 84 | * config should be responsible for the line<->core/vpe bindings. | 88 | * something in the config should be responsible for the |
| 89 | * line<->core/vpe bindings. | ||
| 85 | */ | 90 | */ |
| 86 | uint32_t interruptInfo; /*0x18 */ | 91 | uint32_t interruptInfo; /* 0x18 */ |
| 87 | 92 | ||
| 88 | /* | 93 | /* |
| 89 | * This is where the received data is read out. | 94 | * This is where the received data is read out. |
| 90 | * There is more data to read until rxDataReady is 0. | 95 | * There is more data to read until rxDataReady is 0. |
| 91 | * Only 1 byte at this regs offset is used. | 96 | * Only 1 byte at this regs offset is used. |
| 92 | */ | 97 | */ |
| 93 | uint32_t rxDataBuffer; /*0x1c */ | 98 | uint32_t rxDataBuffer; /* 0x1c */ |
| 94 | 99 | ||
| 95 | /* | 100 | /* |
| 96 | * This is where the data to transmit is written. | 101 | * This is where the data to transmit is written. Data should be |
| 97 | * Data should be written for the amount specified in the txDataCount register. | 102 | * written for the amount specified in the txDataCount register. Only |
| 98 | * Only 1 byte at this regs offset is used. | 103 | * 1 byte at this regs offset is used. |
| 99 | */ | 104 | */ |
| 100 | uint32_t txDataBuffer; /*0x20 */ | 105 | uint32_t txDataBuffer; /* 0x20 */ |
| 101 | } MIPS_T_NetControl; | 106 | }; |
| 102 | 107 | ||
| 103 | #define MIPSNET_IO_EXTENT 0x40 /* being generous */ | 108 | #define MIPSNET_IO_EXTENT 0x40 /* being generous */ |
| 104 | 109 | ||
| 105 | #define field_offset(field) ((int)&((MIPS_T_NetControl*)(0))->field) | 110 | #define field_offset(field) (offsetof(struct net_control_block, field)) |
| 106 | 111 | ||
| 107 | #endif /* __MIPSNET_H */ | 112 | #endif /* __MIPSNET_H */ |
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index e8afa101433e..64c8151f2004 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c | |||
| @@ -75,7 +75,7 @@ | |||
| 75 | #include "myri10ge_mcp.h" | 75 | #include "myri10ge_mcp.h" |
| 76 | #include "myri10ge_mcp_gen_header.h" | 76 | #include "myri10ge_mcp_gen_header.h" |
| 77 | 77 | ||
| 78 | #define MYRI10GE_VERSION_STR "1.3.2-1.269" | 78 | #define MYRI10GE_VERSION_STR "1.3.2-1.287" |
| 79 | 79 | ||
| 80 | MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); | 80 | MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); |
| 81 | MODULE_AUTHOR("Maintainer: help@myri.com"); | 81 | MODULE_AUTHOR("Maintainer: help@myri.com"); |
| @@ -214,6 +214,8 @@ struct myri10ge_priv { | |||
| 214 | unsigned long serial_number; | 214 | unsigned long serial_number; |
| 215 | int vendor_specific_offset; | 215 | int vendor_specific_offset; |
| 216 | int fw_multicast_support; | 216 | int fw_multicast_support; |
| 217 | unsigned long features; | ||
| 218 | u32 max_tso6; | ||
| 217 | u32 read_dma; | 219 | u32 read_dma; |
| 218 | u32 write_dma; | 220 | u32 write_dma; |
| 219 | u32 read_write_dma; | 221 | u32 read_write_dma; |
| @@ -311,6 +313,7 @@ MODULE_PARM_DESC(myri10ge_wcfifo, "Enable WC Fifo when WC is enabled\n"); | |||
| 311 | #define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8) | 313 | #define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8) |
| 312 | 314 | ||
| 313 | static void myri10ge_set_multicast_list(struct net_device *dev); | 315 | static void myri10ge_set_multicast_list(struct net_device *dev); |
| 316 | static int myri10ge_sw_tso(struct sk_buff *skb, struct net_device *dev); | ||
| 314 | 317 | ||
| 315 | static inline void put_be32(__be32 val, __be32 __iomem * p) | 318 | static inline void put_be32(__be32 val, __be32 __iomem * p) |
| 316 | { | 319 | { |
| @@ -612,6 +615,7 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp) | |||
| 612 | __be32 buf[16]; | 615 | __be32 buf[16]; |
| 613 | u32 dma_low, dma_high, size; | 616 | u32 dma_low, dma_high, size; |
| 614 | int status, i; | 617 | int status, i; |
| 618 | struct myri10ge_cmd cmd; | ||
| 615 | 619 | ||
| 616 | size = 0; | 620 | size = 0; |
| 617 | status = myri10ge_load_hotplug_firmware(mgp, &size); | 621 | status = myri10ge_load_hotplug_firmware(mgp, &size); |
| @@ -688,6 +692,14 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp) | |||
| 688 | dev_info(&mgp->pdev->dev, "handoff confirmed\n"); | 692 | dev_info(&mgp->pdev->dev, "handoff confirmed\n"); |
| 689 | myri10ge_dummy_rdma(mgp, 1); | 693 | myri10ge_dummy_rdma(mgp, 1); |
| 690 | 694 | ||
| 695 | /* probe for IPv6 TSO support */ | ||
| 696 | mgp->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO; | ||
| 697 | status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_MAX_TSO6_HDR_SIZE, | ||
| 698 | &cmd, 0); | ||
| 699 | if (status == 0) { | ||
| 700 | mgp->max_tso6 = cmd.data0; | ||
| 701 | mgp->features |= NETIF_F_TSO6; | ||
| 702 | } | ||
| 691 | return 0; | 703 | return 0; |
| 692 | } | 704 | } |
| 693 | 705 | ||
| @@ -1047,7 +1059,8 @@ myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, | |||
| 1047 | 1059 | ||
| 1048 | hlen = MYRI10GE_HLEN > len ? len : MYRI10GE_HLEN; | 1060 | hlen = MYRI10GE_HLEN > len ? len : MYRI10GE_HLEN; |
| 1049 | 1061 | ||
| 1050 | /* allocate an skb to attach the page(s) to. */ | 1062 | /* allocate an skb to attach the page(s) to. This is done |
| 1063 | * after trying LRO, so as to avoid skb allocation overheads */ | ||
| 1051 | 1064 | ||
| 1052 | skb = netdev_alloc_skb(dev, MYRI10GE_HLEN + 16); | 1065 | skb = netdev_alloc_skb(dev, MYRI10GE_HLEN + 16); |
| 1053 | if (unlikely(skb == NULL)) { | 1066 | if (unlikely(skb == NULL)) { |
| @@ -1217,7 +1230,8 @@ static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp) | |||
| 1217 | 1230 | ||
| 1218 | static int myri10ge_poll(struct napi_struct *napi, int budget) | 1231 | static int myri10ge_poll(struct napi_struct *napi, int budget) |
| 1219 | { | 1232 | { |
| 1220 | struct myri10ge_priv *mgp = container_of(napi, struct myri10ge_priv, napi); | 1233 | struct myri10ge_priv *mgp = |
| 1234 | container_of(napi, struct myri10ge_priv, napi); | ||
| 1221 | struct net_device *netdev = mgp->dev; | 1235 | struct net_device *netdev = mgp->dev; |
| 1222 | struct myri10ge_rx_done *rx_done = &mgp->rx_done; | 1236 | struct myri10ge_rx_done *rx_done = &mgp->rx_done; |
| 1223 | int work_done; | 1237 | int work_done; |
| @@ -1382,6 +1396,18 @@ static int myri10ge_set_rx_csum(struct net_device *netdev, u32 csum_enabled) | |||
| 1382 | return 0; | 1396 | return 0; |
| 1383 | } | 1397 | } |
| 1384 | 1398 | ||
| 1399 | static int myri10ge_set_tso(struct net_device *netdev, u32 tso_enabled) | ||
| 1400 | { | ||
| 1401 | struct myri10ge_priv *mgp = netdev_priv(netdev); | ||
| 1402 | unsigned long flags = mgp->features & (NETIF_F_TSO6 | NETIF_F_TSO); | ||
| 1403 | |||
| 1404 | if (tso_enabled) | ||
| 1405 | netdev->features |= flags; | ||
| 1406 | else | ||
| 1407 | netdev->features &= ~flags; | ||
| 1408 | return 0; | ||
| 1409 | } | ||
| 1410 | |||
| 1385 | static const char myri10ge_gstrings_stats[][ETH_GSTRING_LEN] = { | 1411 | static const char myri10ge_gstrings_stats[][ETH_GSTRING_LEN] = { |
| 1386 | "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", | 1412 | "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", |
| 1387 | "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", | 1413 | "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", |
| @@ -1506,7 +1532,7 @@ static const struct ethtool_ops myri10ge_ethtool_ops = { | |||
| 1506 | .set_rx_csum = myri10ge_set_rx_csum, | 1532 | .set_rx_csum = myri10ge_set_rx_csum, |
| 1507 | .set_tx_csum = ethtool_op_set_tx_hw_csum, | 1533 | .set_tx_csum = ethtool_op_set_tx_hw_csum, |
| 1508 | .set_sg = ethtool_op_set_sg, | 1534 | .set_sg = ethtool_op_set_sg, |
| 1509 | .set_tso = ethtool_op_set_tso, | 1535 | .set_tso = myri10ge_set_tso, |
| 1510 | .get_link = ethtool_op_get_link, | 1536 | .get_link = ethtool_op_get_link, |
| 1511 | .get_strings = myri10ge_get_strings, | 1537 | .get_strings = myri10ge_get_strings, |
| 1512 | .get_sset_count = myri10ge_get_sset_count, | 1538 | .get_sset_count = myri10ge_get_sset_count, |
| @@ -2164,7 +2190,8 @@ again: | |||
| 2164 | pseudo_hdr_offset = cksum_offset + skb->csum_offset; | 2190 | pseudo_hdr_offset = cksum_offset + skb->csum_offset; |
| 2165 | /* If the headers are excessively large, then we must | 2191 | /* If the headers are excessively large, then we must |
| 2166 | * fall back to a software checksum */ | 2192 | * fall back to a software checksum */ |
| 2167 | if (unlikely(cksum_offset > 255 || pseudo_hdr_offset > 127)) { | 2193 | if (unlikely(!mss && (cksum_offset > 255 || |
| 2194 | pseudo_hdr_offset > 127))) { | ||
| 2168 | if (skb_checksum_help(skb)) | 2195 | if (skb_checksum_help(skb)) |
| 2169 | goto drop; | 2196 | goto drop; |
| 2170 | cksum_offset = 0; | 2197 | cksum_offset = 0; |
| @@ -2184,9 +2211,18 @@ again: | |||
| 2184 | /* negative cum_len signifies to the | 2211 | /* negative cum_len signifies to the |
| 2185 | * send loop that we are still in the | 2212 | * send loop that we are still in the |
| 2186 | * header portion of the TSO packet. | 2213 | * header portion of the TSO packet. |
| 2187 | * TSO header must be at most 134 bytes long */ | 2214 | * TSO header can be at most 1KB long */ |
| 2188 | cum_len = -(skb_transport_offset(skb) + tcp_hdrlen(skb)); | 2215 | cum_len = -(skb_transport_offset(skb) + tcp_hdrlen(skb)); |
| 2189 | 2216 | ||
| 2217 | /* for IPv6 TSO, the checksum offset stores the | ||
| 2218 | * TCP header length, to save the firmware from | ||
| 2219 | * the need to parse the headers */ | ||
| 2220 | if (skb_is_gso_v6(skb)) { | ||
| 2221 | cksum_offset = tcp_hdrlen(skb); | ||
| 2222 | /* Can only handle headers <= max_tso6 long */ | ||
| 2223 | if (unlikely(-cum_len > mgp->max_tso6)) | ||
| 2224 | return myri10ge_sw_tso(skb, dev); | ||
| 2225 | } | ||
| 2190 | /* for TSO, pseudo_hdr_offset holds mss. | 2226 | /* for TSO, pseudo_hdr_offset holds mss. |
| 2191 | * The firmware figures out where to put | 2227 | * The firmware figures out where to put |
| 2192 | * the checksum by parsing the header. */ | 2228 | * the checksum by parsing the header. */ |
| @@ -2301,10 +2337,12 @@ again: | |||
| 2301 | req++; | 2337 | req++; |
| 2302 | count++; | 2338 | count++; |
| 2303 | rdma_count++; | 2339 | rdma_count++; |
| 2304 | if (unlikely(cksum_offset > seglen)) | 2340 | if (cksum_offset != 0 && !(mss && skb_is_gso_v6(skb))) { |
| 2305 | cksum_offset -= seglen; | 2341 | if (unlikely(cksum_offset > seglen)) |
| 2306 | else | 2342 | cksum_offset -= seglen; |
| 2307 | cksum_offset = 0; | 2343 | else |
| 2344 | cksum_offset = 0; | ||
| 2345 | } | ||
| 2308 | } | 2346 | } |
| 2309 | if (frag_idx == frag_cnt) | 2347 | if (frag_idx == frag_cnt) |
| 2310 | break; | 2348 | break; |
| @@ -2387,6 +2425,41 @@ drop: | |||
| 2387 | 2425 | ||
| 2388 | } | 2426 | } |
| 2389 | 2427 | ||
| 2428 | static int myri10ge_sw_tso(struct sk_buff *skb, struct net_device *dev) | ||
| 2429 | { | ||
| 2430 | struct sk_buff *segs, *curr; | ||
| 2431 | struct myri10ge_priv *mgp = dev->priv; | ||
| 2432 | int status; | ||
| 2433 | |||
| 2434 | segs = skb_gso_segment(skb, dev->features & ~NETIF_F_TSO6); | ||
| 2435 | if (unlikely(IS_ERR(segs))) | ||
| 2436 | goto drop; | ||
| 2437 | |||
| 2438 | while (segs) { | ||
| 2439 | curr = segs; | ||
| 2440 | segs = segs->next; | ||
| 2441 | curr->next = NULL; | ||
| 2442 | status = myri10ge_xmit(curr, dev); | ||
| 2443 | if (status != 0) { | ||
| 2444 | dev_kfree_skb_any(curr); | ||
| 2445 | if (segs != NULL) { | ||
| 2446 | curr = segs; | ||
| 2447 | segs = segs->next; | ||
| 2448 | curr->next = NULL; | ||
| 2449 | dev_kfree_skb_any(segs); | ||
| 2450 | } | ||
| 2451 | goto drop; | ||
| 2452 | } | ||
| 2453 | } | ||
| 2454 | dev_kfree_skb_any(skb); | ||
| 2455 | return 0; | ||
| 2456 | |||
| 2457 | drop: | ||
| 2458 | dev_kfree_skb_any(skb); | ||
| 2459 | mgp->stats.tx_dropped += 1; | ||
| 2460 | return 0; | ||
| 2461 | } | ||
| 2462 | |||
| 2390 | static struct net_device_stats *myri10ge_get_stats(struct net_device *dev) | 2463 | static struct net_device_stats *myri10ge_get_stats(struct net_device *dev) |
| 2391 | { | 2464 | { |
| 2392 | struct myri10ge_priv *mgp = netdev_priv(dev); | 2465 | struct myri10ge_priv *mgp = netdev_priv(dev); |
| @@ -2706,7 +2779,6 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp) | |||
| 2706 | } | 2779 | } |
| 2707 | 2780 | ||
| 2708 | #ifdef CONFIG_PM | 2781 | #ifdef CONFIG_PM |
| 2709 | |||
| 2710 | static int myri10ge_suspend(struct pci_dev *pdev, pm_message_t state) | 2782 | static int myri10ge_suspend(struct pci_dev *pdev, pm_message_t state) |
| 2711 | { | 2783 | { |
| 2712 | struct myri10ge_priv *mgp; | 2784 | struct myri10ge_priv *mgp; |
| @@ -2787,7 +2859,6 @@ abort_with_enabled: | |||
| 2787 | return -EIO; | 2859 | return -EIO; |
| 2788 | 2860 | ||
| 2789 | } | 2861 | } |
| 2790 | |||
| 2791 | #endif /* CONFIG_PM */ | 2862 | #endif /* CONFIG_PM */ |
| 2792 | 2863 | ||
| 2793 | static u32 myri10ge_read_reboot(struct myri10ge_priv *mgp) | 2864 | static u32 myri10ge_read_reboot(struct myri10ge_priv *mgp) |
| @@ -2954,8 +3025,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 2954 | 3025 | ||
| 2955 | mgp = netdev_priv(netdev); | 3026 | mgp = netdev_priv(netdev); |
| 2956 | mgp->dev = netdev; | 3027 | mgp->dev = netdev; |
| 2957 | netif_napi_add(netdev, &mgp->napi, | 3028 | netif_napi_add(netdev, &mgp->napi, myri10ge_poll, myri10ge_napi_weight); |
| 2958 | myri10ge_poll, myri10ge_napi_weight); | ||
| 2959 | mgp->pdev = pdev; | 3029 | mgp->pdev = pdev; |
| 2960 | mgp->csum_flag = MXGEFW_FLAGS_CKSUM; | 3030 | mgp->csum_flag = MXGEFW_FLAGS_CKSUM; |
| 2961 | mgp->pause = myri10ge_flow_control; | 3031 | mgp->pause = myri10ge_flow_control; |
| @@ -3077,7 +3147,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 3077 | netdev->change_mtu = myri10ge_change_mtu; | 3147 | netdev->change_mtu = myri10ge_change_mtu; |
| 3078 | netdev->set_multicast_list = myri10ge_set_multicast_list; | 3148 | netdev->set_multicast_list = myri10ge_set_multicast_list; |
| 3079 | netdev->set_mac_address = myri10ge_set_mac_address; | 3149 | netdev->set_mac_address = myri10ge_set_mac_address; |
| 3080 | netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO; | 3150 | netdev->features = mgp->features; |
| 3081 | if (dac_enabled) | 3151 | if (dac_enabled) |
| 3082 | netdev->features |= NETIF_F_HIGHDMA; | 3152 | netdev->features |= NETIF_F_HIGHDMA; |
| 3083 | 3153 | ||
diff --git a/drivers/net/myri10ge/myri10ge_mcp.h b/drivers/net/myri10ge/myri10ge_mcp.h index a1d2a22296a9..58e57178c563 100644 --- a/drivers/net/myri10ge/myri10ge_mcp.h +++ b/drivers/net/myri10ge/myri10ge_mcp.h | |||
| @@ -10,7 +10,7 @@ struct mcp_dma_addr { | |||
| 10 | __be32 low; | 10 | __be32 low; |
| 11 | }; | 11 | }; |
| 12 | 12 | ||
| 13 | /* 4 Bytes */ | 13 | /* 4 Bytes. 8 Bytes for NDIS drivers. */ |
| 14 | struct mcp_slot { | 14 | struct mcp_slot { |
| 15 | __sum16 checksum; | 15 | __sum16 checksum; |
| 16 | __be16 length; | 16 | __be16 length; |
| @@ -205,8 +205,87 @@ enum myri10ge_mcp_cmd_type { | |||
| 205 | /* same than DMA_TEST (same args) but abort with UNALIGNED on unaligned | 205 | /* same than DMA_TEST (same args) but abort with UNALIGNED on unaligned |
| 206 | * chipset */ | 206 | * chipset */ |
| 207 | 207 | ||
| 208 | MXGEFW_CMD_UNALIGNED_STATUS | 208 | MXGEFW_CMD_UNALIGNED_STATUS, |
| 209 | /* return data = boolean, true if the chipset is known to be unaligned */ | 209 | /* return data = boolean, true if the chipset is known to be unaligned */ |
| 210 | |||
| 211 | MXGEFW_CMD_ALWAYS_USE_N_BIG_BUFFERS, | ||
| 212 | /* data0 = number of big buffers to use. It must be 0 or a power of 2. | ||
| 213 | * 0 indicates that the NIC consumes as many buffers as they are required | ||
| 214 | * for packet. This is the default behavior. | ||
| 215 | * A power of 2 number indicates that the NIC always uses the specified | ||
| 216 | * number of buffers for each big receive packet. | ||
| 217 | * It is up to the driver to ensure that this value is big enough for | ||
| 218 | * the NIC to be able to receive maximum-sized packets. | ||
| 219 | */ | ||
| 220 | |||
| 221 | MXGEFW_CMD_GET_MAX_RSS_QUEUES, | ||
| 222 | MXGEFW_CMD_ENABLE_RSS_QUEUES, | ||
| 223 | /* data0 = number of slices n (0, 1, ..., n-1) to enable | ||
| 224 | * data1 = interrupt mode. 0=share one INTx/MSI, 1=use one MSI-X per queue. | ||
| 225 | * If all queues share one interrupt, the driver must have set | ||
| 226 | * RSS_SHARED_INTERRUPT_DMA before enabling queues. | ||
| 227 | */ | ||
| 228 | MXGEFW_CMD_GET_RSS_SHARED_INTERRUPT_MASK_OFFSET, | ||
| 229 | MXGEFW_CMD_SET_RSS_SHARED_INTERRUPT_DMA, | ||
| 230 | /* data0, data1 = bus address lsw, msw */ | ||
| 231 | MXGEFW_CMD_GET_RSS_TABLE_OFFSET, | ||
| 232 | /* get the offset of the indirection table */ | ||
| 233 | MXGEFW_CMD_SET_RSS_TABLE_SIZE, | ||
| 234 | /* set the size of the indirection table */ | ||
| 235 | MXGEFW_CMD_GET_RSS_KEY_OFFSET, | ||
| 236 | /* get the offset of the secret key */ | ||
| 237 | MXGEFW_CMD_RSS_KEY_UPDATED, | ||
| 238 | /* tell nic that the secret key's been updated */ | ||
| 239 | MXGEFW_CMD_SET_RSS_ENABLE, | ||
| 240 | /* data0 = enable/disable rss | ||
| 241 | * 0: disable rss. nic does not distribute receive packets. | ||
| 242 | * 1: enable rss. nic distributes receive packets among queues. | ||
| 243 | * data1 = hash type | ||
| 244 | * 1: IPV4 | ||
| 245 | * 2: TCP_IPV4 | ||
| 246 | * 3: IPV4 | TCP_IPV4 | ||
| 247 | */ | ||
| 248 | |||
| 249 | MXGEFW_CMD_GET_MAX_TSO6_HDR_SIZE, | ||
| 250 | /* Return data = the max. size of the entire headers of a IPv6 TSO packet. | ||
| 251 | * If the header size of a IPv6 TSO packet is larger than the specified | ||
| 252 | * value, then the driver must not use TSO. | ||
| 253 | * This size restriction only applies to IPv6 TSO. | ||
| 254 | * For IPv4 TSO, the maximum size of the headers is fixed, and the NIC | ||
| 255 | * always has enough header buffer to store maximum-sized headers. | ||
| 256 | */ | ||
| 257 | |||
| 258 | MXGEFW_CMD_SET_TSO_MODE, | ||
| 259 | /* data0 = TSO mode. | ||
| 260 | * 0: Linux/FreeBSD style (NIC default) | ||
| 261 | * 1: NDIS/NetBSD style | ||
| 262 | */ | ||
| 263 | |||
| 264 | MXGEFW_CMD_MDIO_READ, | ||
| 265 | /* data0 = dev_addr (PMA/PMD or PCS ...), data1 = register/addr */ | ||
| 266 | MXGEFW_CMD_MDIO_WRITE, | ||
| 267 | /* data0 = dev_addr, data1 = register/addr, data2 = value */ | ||
| 268 | |||
| 269 | MXGEFW_CMD_XFP_I2C_READ, | ||
| 270 | /* Starts to get a fresh copy of one byte or of the whole xfp i2c table, the | ||
| 271 | * obtained data is cached inside the xaui-xfi chip : | ||
| 272 | * data0 : "all" flag : 0 => get one byte, 1=> get 256 bytes, | ||
| 273 | * data1 : if (data0 == 0): index of byte to refresh [ not used otherwise ] | ||
| 274 | * The operation might take ~1ms for a single byte or ~65ms when refreshing all 256 bytes | ||
| 275 | * During the i2c operation, MXGEFW_CMD_XFP_I2C_READ or MXGEFW_CMD_XFP_BYTE attempts | ||
| 276 | * will return MXGEFW_CMD_ERROR_BUSY | ||
| 277 | */ | ||
| 278 | MXGEFW_CMD_XFP_BYTE, | ||
| 279 | /* Return the last obtained copy of a given byte in the xfp i2c table | ||
| 280 | * (copy cached during the last relevant MXGEFW_CMD_XFP_I2C_READ) | ||
| 281 | * data0 : index of the desired table entry | ||
| 282 | * Return data = the byte stored at the requested index in the table | ||
| 283 | */ | ||
| 284 | |||
| 285 | MXGEFW_CMD_GET_VPUMP_OFFSET, | ||
| 286 | /* Return data = NIC memory offset of mcp_vpump_public_global */ | ||
| 287 | MXGEFW_CMD_RESET_VPUMP, | ||
| 288 | /* Resets the VPUMP state */ | ||
| 210 | }; | 289 | }; |
| 211 | 290 | ||
| 212 | enum myri10ge_mcp_cmd_status { | 291 | enum myri10ge_mcp_cmd_status { |
| @@ -220,7 +299,10 @@ enum myri10ge_mcp_cmd_status { | |||
| 220 | MXGEFW_CMD_ERROR_BAD_PORT, | 299 | MXGEFW_CMD_ERROR_BAD_PORT, |
| 221 | MXGEFW_CMD_ERROR_RESOURCES, | 300 | MXGEFW_CMD_ERROR_RESOURCES, |
| 222 | MXGEFW_CMD_ERROR_MULTICAST, | 301 | MXGEFW_CMD_ERROR_MULTICAST, |
| 223 | MXGEFW_CMD_ERROR_UNALIGNED | 302 | MXGEFW_CMD_ERROR_UNALIGNED, |
| 303 | MXGEFW_CMD_ERROR_NO_MDIO, | ||
| 304 | MXGEFW_CMD_ERROR_XFP_FAILURE, | ||
| 305 | MXGEFW_CMD_ERROR_XFP_ABSENT | ||
| 224 | }; | 306 | }; |
| 225 | 307 | ||
| 226 | #define MXGEFW_OLD_IRQ_DATA_LEN 40 | 308 | #define MXGEFW_OLD_IRQ_DATA_LEN 40 |
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 527f9dcc7f69..50e1ec67ef9c 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c | |||
| @@ -1576,7 +1576,7 @@ static int netdev_open(struct net_device *dev) | |||
| 1576 | 1576 | ||
| 1577 | /* Set the timer to check for link beat. */ | 1577 | /* Set the timer to check for link beat. */ |
| 1578 | init_timer(&np->timer); | 1578 | init_timer(&np->timer); |
| 1579 | np->timer.expires = jiffies + NATSEMI_TIMER_FREQ; | 1579 | np->timer.expires = round_jiffies(jiffies + NATSEMI_TIMER_FREQ); |
| 1580 | np->timer.data = (unsigned long)dev; | 1580 | np->timer.data = (unsigned long)dev; |
| 1581 | np->timer.function = &netdev_timer; /* timer handler */ | 1581 | np->timer.function = &netdev_timer; /* timer handler */ |
| 1582 | add_timer(&np->timer); | 1582 | add_timer(&np->timer); |
| @@ -1856,7 +1856,11 @@ static void netdev_timer(unsigned long data) | |||
| 1856 | next_tick = 1; | 1856 | next_tick = 1; |
| 1857 | } | 1857 | } |
| 1858 | } | 1858 | } |
| 1859 | mod_timer(&np->timer, jiffies + next_tick); | 1859 | |
| 1860 | if (next_tick > 1) | ||
| 1861 | mod_timer(&np->timer, round_jiffies(jiffies + next_tick)); | ||
| 1862 | else | ||
| 1863 | mod_timer(&np->timer, jiffies + next_tick); | ||
| 1860 | } | 1864 | } |
| 1861 | 1865 | ||
| 1862 | static void dump_ring(struct net_device *dev) | 1866 | static void dump_ring(struct net_device *dev) |
| @@ -3310,13 +3314,19 @@ static int natsemi_resume (struct pci_dev *pdev) | |||
| 3310 | { | 3314 | { |
| 3311 | struct net_device *dev = pci_get_drvdata (pdev); | 3315 | struct net_device *dev = pci_get_drvdata (pdev); |
| 3312 | struct netdev_private *np = netdev_priv(dev); | 3316 | struct netdev_private *np = netdev_priv(dev); |
| 3317 | int ret = 0; | ||
| 3313 | 3318 | ||
| 3314 | rtnl_lock(); | 3319 | rtnl_lock(); |
| 3315 | if (netif_device_present(dev)) | 3320 | if (netif_device_present(dev)) |
| 3316 | goto out; | 3321 | goto out; |
| 3317 | if (netif_running(dev)) { | 3322 | if (netif_running(dev)) { |
| 3318 | BUG_ON(!np->hands_off); | 3323 | BUG_ON(!np->hands_off); |
| 3319 | pci_enable_device(pdev); | 3324 | ret = pci_enable_device(pdev); |
| 3325 | if (ret < 0) { | ||
| 3326 | dev_err(&pdev->dev, | ||
| 3327 | "pci_enable_device() failed: %d\n", ret); | ||
| 3328 | goto out; | ||
| 3329 | } | ||
| 3320 | /* pci_power_on(pdev); */ | 3330 | /* pci_power_on(pdev); */ |
| 3321 | 3331 | ||
| 3322 | napi_enable(&np->napi); | 3332 | napi_enable(&np->napi); |
| @@ -3331,12 +3341,12 @@ static int natsemi_resume (struct pci_dev *pdev) | |||
| 3331 | spin_unlock_irq(&np->lock); | 3341 | spin_unlock_irq(&np->lock); |
| 3332 | enable_irq(dev->irq); | 3342 | enable_irq(dev->irq); |
| 3333 | 3343 | ||
| 3334 | mod_timer(&np->timer, jiffies + 1*HZ); | 3344 | mod_timer(&np->timer, round_jiffies(jiffies + 1*HZ)); |
| 3335 | } | 3345 | } |
| 3336 | netif_device_attach(dev); | 3346 | netif_device_attach(dev); |
| 3337 | out: | 3347 | out: |
| 3338 | rtnl_unlock(); | 3348 | rtnl_unlock(); |
| 3339 | return 0; | 3349 | return ret; |
| 3340 | } | 3350 | } |
| 3341 | 3351 | ||
| 3342 | #endif /* CONFIG_PM */ | 3352 | #endif /* CONFIG_PM */ |
diff --git a/drivers/net/ne-h8300.c b/drivers/net/ne-h8300.c index 368f2560856d..fbc7531d3c7d 100644 --- a/drivers/net/ne-h8300.c +++ b/drivers/net/ne-h8300.c | |||
| @@ -93,7 +93,7 @@ static int __init init_reg_offset(struct net_device *dev,unsigned long base_addr | |||
| 93 | bus_width = *(volatile unsigned char *)ABWCR; | 93 | bus_width = *(volatile unsigned char *)ABWCR; |
| 94 | bus_width &= 1 << ((base_addr >> 21) & 7); | 94 | bus_width &= 1 << ((base_addr >> 21) & 7); |
| 95 | 95 | ||
| 96 | for (i = 0; i < sizeof(reg_offset) / sizeof(u32); i++) | 96 | for (i = 0; i < ARRAY_SIZE(reg_offset); i++) |
| 97 | if (bus_width == 0) | 97 | if (bus_width == 0) |
| 98 | reg_offset[i] = i * 2 + 1; | 98 | reg_offset[i] = i * 2 + 1; |
| 99 | else | 99 | else |
| @@ -115,7 +115,7 @@ static int h8300_ne_irq[] = {EXT_IRQ5}; | |||
| 115 | 115 | ||
| 116 | static inline int init_dev(struct net_device *dev) | 116 | static inline int init_dev(struct net_device *dev) |
| 117 | { | 117 | { |
| 118 | if (h8300_ne_count < (sizeof(h8300_ne_base) / sizeof(unsigned long))) { | 118 | if (h8300_ne_count < ARRAY_SIZE(h8300_ne_base)) { |
| 119 | dev->base_addr = h8300_ne_base[h8300_ne_count]; | 119 | dev->base_addr = h8300_ne_base[h8300_ne_count]; |
| 120 | dev->irq = h8300_ne_irq[h8300_ne_count]; | 120 | dev->irq = h8300_ne_irq[h8300_ne_count]; |
| 121 | h8300_ne_count++; | 121 | h8300_ne_count++; |
diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 43bfe7e6b6f5..ed1f9bbb2a32 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c | |||
| @@ -6123,19 +6123,19 @@ static int __devinit niu_pci_probe_sprom(struct niu *np) | |||
| 6123 | val = nr64(ESPC_PHY_TYPE); | 6123 | val = nr64(ESPC_PHY_TYPE); |
| 6124 | switch (np->port) { | 6124 | switch (np->port) { |
| 6125 | case 0: | 6125 | case 0: |
| 6126 | val = (val & ESPC_PHY_TYPE_PORT0) >> | 6126 | val8 = (val & ESPC_PHY_TYPE_PORT0) >> |
| 6127 | ESPC_PHY_TYPE_PORT0_SHIFT; | 6127 | ESPC_PHY_TYPE_PORT0_SHIFT; |
| 6128 | break; | 6128 | break; |
| 6129 | case 1: | 6129 | case 1: |
| 6130 | val = (val & ESPC_PHY_TYPE_PORT1) >> | 6130 | val8 = (val & ESPC_PHY_TYPE_PORT1) >> |
| 6131 | ESPC_PHY_TYPE_PORT1_SHIFT; | 6131 | ESPC_PHY_TYPE_PORT1_SHIFT; |
| 6132 | break; | 6132 | break; |
| 6133 | case 2: | 6133 | case 2: |
| 6134 | val = (val & ESPC_PHY_TYPE_PORT2) >> | 6134 | val8 = (val & ESPC_PHY_TYPE_PORT2) >> |
| 6135 | ESPC_PHY_TYPE_PORT2_SHIFT; | 6135 | ESPC_PHY_TYPE_PORT2_SHIFT; |
| 6136 | break; | 6136 | break; |
| 6137 | case 3: | 6137 | case 3: |
| 6138 | val = (val & ESPC_PHY_TYPE_PORT3) >> | 6138 | val8 = (val & ESPC_PHY_TYPE_PORT3) >> |
| 6139 | ESPC_PHY_TYPE_PORT3_SHIFT; | 6139 | ESPC_PHY_TYPE_PORT3_SHIFT; |
| 6140 | break; | 6140 | break; |
| 6141 | default: | 6141 | default: |
| @@ -6143,9 +6143,9 @@ static int __devinit niu_pci_probe_sprom(struct niu *np) | |||
| 6143 | np->port); | 6143 | np->port); |
| 6144 | return -EINVAL; | 6144 | return -EINVAL; |
| 6145 | } | 6145 | } |
| 6146 | niudbg(PROBE, "SPROM: PHY type %llx\n", (unsigned long long) val); | 6146 | niudbg(PROBE, "SPROM: PHY type %x\n", val8); |
| 6147 | 6147 | ||
| 6148 | switch (val) { | 6148 | switch (val8) { |
| 6149 | case ESPC_PHY_TYPE_1G_COPPER: | 6149 | case ESPC_PHY_TYPE_1G_COPPER: |
| 6150 | /* 1G copper, MII */ | 6150 | /* 1G copper, MII */ |
| 6151 | np->flags &= ~(NIU_FLAGS_FIBER | | 6151 | np->flags &= ~(NIU_FLAGS_FIBER | |
| @@ -6175,8 +6175,7 @@ static int __devinit niu_pci_probe_sprom(struct niu *np) | |||
| 6175 | break; | 6175 | break; |
| 6176 | 6176 | ||
| 6177 | default: | 6177 | default: |
| 6178 | dev_err(np->device, PFX "Bogus SPROM phy type %llu\n", | 6178 | dev_err(np->device, PFX "Bogus SPROM phy type %u\n", val8); |
| 6179 | (unsigned long long) val); | ||
| 6180 | return -EINVAL; | 6179 | return -EINVAL; |
| 6181 | } | 6180 | } |
| 6182 | 6181 | ||
| @@ -6213,7 +6212,7 @@ static int __devinit niu_pci_probe_sprom(struct niu *np) | |||
| 6213 | val = nr64(ESPC_MOD_STR_LEN); | 6212 | val = nr64(ESPC_MOD_STR_LEN); |
| 6214 | niudbg(PROBE, "SPROM: MOD_STR_LEN[%llu]\n", | 6213 | niudbg(PROBE, "SPROM: MOD_STR_LEN[%llu]\n", |
| 6215 | (unsigned long long) val); | 6214 | (unsigned long long) val); |
| 6216 | if (val > 8 * 4) | 6215 | if (val >= 8 * 4) |
| 6217 | return -EINVAL; | 6216 | return -EINVAL; |
| 6218 | 6217 | ||
| 6219 | for (i = 0; i < val; i += 4) { | 6218 | for (i = 0; i < val; i += 4) { |
| @@ -6229,7 +6228,7 @@ static int __devinit niu_pci_probe_sprom(struct niu *np) | |||
| 6229 | val = nr64(ESPC_BD_MOD_STR_LEN); | 6228 | val = nr64(ESPC_BD_MOD_STR_LEN); |
| 6230 | niudbg(PROBE, "SPROM: BD_MOD_STR_LEN[%llu]\n", | 6229 | niudbg(PROBE, "SPROM: BD_MOD_STR_LEN[%llu]\n", |
| 6231 | (unsigned long long) val); | 6230 | (unsigned long long) val); |
| 6232 | if (val > 4 * 4) | 6231 | if (val >= 4 * 4) |
| 6233 | return -EINVAL; | 6232 | return -EINVAL; |
| 6234 | 6233 | ||
| 6235 | for (i = 0; i < val; i += 4) { | 6234 | for (i = 0; i < val; i += 4) { |
diff --git a/drivers/net/saa9730.c b/drivers/net/saa9730.c index 14361e885415..c65199df8a7f 100644 --- a/drivers/net/saa9730.c +++ b/drivers/net/saa9730.c | |||
| @@ -97,13 +97,16 @@ static void evm_saa9730_unblock_lan_int(struct lan_saa9730_private *lp) | |||
| 97 | &lp->evm_saa9730_regs->InterruptBlock1); | 97 | &lp->evm_saa9730_regs->InterruptBlock1); |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | static void __attribute_used__ show_saa9730_regs(struct lan_saa9730_private *lp) | 100 | static void __used show_saa9730_regs(struct net_device *dev) |
| 101 | { | 101 | { |
| 102 | struct lan_saa9730_private *lp = netdev_priv(dev); | ||
| 102 | int i, j; | 103 | int i, j; |
| 104 | |||
| 103 | printk("TxmBufferA = %p\n", lp->TxmBuffer[0][0]); | 105 | printk("TxmBufferA = %p\n", lp->TxmBuffer[0][0]); |
| 104 | printk("TxmBufferB = %p\n", lp->TxmBuffer[1][0]); | 106 | printk("TxmBufferB = %p\n", lp->TxmBuffer[1][0]); |
| 105 | printk("RcvBufferA = %p\n", lp->RcvBuffer[0][0]); | 107 | printk("RcvBufferA = %p\n", lp->RcvBuffer[0][0]); |
| 106 | printk("RcvBufferB = %p\n", lp->RcvBuffer[1][0]); | 108 | printk("RcvBufferB = %p\n", lp->RcvBuffer[1][0]); |
| 109 | |||
| 107 | for (i = 0; i < LAN_SAA9730_BUFFERS; i++) { | 110 | for (i = 0; i < LAN_SAA9730_BUFFERS; i++) { |
| 108 | for (j = 0; j < LAN_SAA9730_TXM_Q_SIZE; j++) { | 111 | for (j = 0; j < LAN_SAA9730_TXM_Q_SIZE; j++) { |
| 109 | printk("TxmBuffer[%d][%d] = %x\n", i, j, | 112 | printk("TxmBuffer[%d][%d] = %x\n", i, j, |
| @@ -146,11 +149,13 @@ static void __attribute_used__ show_saa9730_regs(struct lan_saa9730_private *lp) | |||
| 146 | readl(&lp->lan_saa9730_regs->RxCtl)); | 149 | readl(&lp->lan_saa9730_regs->RxCtl)); |
| 147 | printk("lp->lan_saa9730_regs->RxStatus = %x\n", | 150 | printk("lp->lan_saa9730_regs->RxStatus = %x\n", |
| 148 | readl(&lp->lan_saa9730_regs->RxStatus)); | 151 | readl(&lp->lan_saa9730_regs->RxStatus)); |
| 152 | |||
| 149 | for (i = 0; i < LAN_SAA9730_CAM_DWORDS; i++) { | 153 | for (i = 0; i < LAN_SAA9730_CAM_DWORDS; i++) { |
| 150 | writel(i, &lp->lan_saa9730_regs->CamAddress); | 154 | writel(i, &lp->lan_saa9730_regs->CamAddress); |
| 151 | printk("lp->lan_saa9730_regs->CamData = %x\n", | 155 | printk("lp->lan_saa9730_regs->CamData = %x\n", |
| 152 | readl(&lp->lan_saa9730_regs->CamData)); | 156 | readl(&lp->lan_saa9730_regs->CamData)); |
| 153 | } | 157 | } |
| 158 | |||
| 154 | printk("dev->stats.tx_packets = %lx\n", dev->stats.tx_packets); | 159 | printk("dev->stats.tx_packets = %lx\n", dev->stats.tx_packets); |
| 155 | printk("dev->stats.tx_errors = %lx\n", dev->stats.tx_errors); | 160 | printk("dev->stats.tx_errors = %lx\n", dev->stats.tx_errors); |
| 156 | printk("dev->stats.tx_aborted_errors = %lx\n", | 161 | printk("dev->stats.tx_aborted_errors = %lx\n", |
| @@ -855,7 +860,7 @@ static void lan_saa9730_tx_timeout(struct net_device *dev) | |||
| 855 | /* Transmitter timeout, serious problems */ | 860 | /* Transmitter timeout, serious problems */ |
| 856 | dev->stats.tx_errors++; | 861 | dev->stats.tx_errors++; |
| 857 | printk("%s: transmit timed out, reset\n", dev->name); | 862 | printk("%s: transmit timed out, reset\n", dev->name); |
| 858 | /*show_saa9730_regs(lp); */ | 863 | /*show_saa9730_regs(dev); */ |
| 859 | lan_saa9730_restart(lp); | 864 | lan_saa9730_restart(lp); |
| 860 | 865 | ||
| 861 | dev->trans_start = jiffies; | 866 | dev->trans_start = jiffies; |
diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c index a679f4310ce1..8038f2882c9b 100644 --- a/drivers/net/tc35815.c +++ b/drivers/net/tc35815.c | |||
| @@ -1461,7 +1461,6 @@ static irqreturn_t tc35815_interrupt(int irq, void *dev_id) | |||
| 1461 | } | 1461 | } |
| 1462 | return IRQ_NONE; | 1462 | return IRQ_NONE; |
| 1463 | #else | 1463 | #else |
| 1464 | struct tc35815_local *lp = dev->priv; | ||
| 1465 | int handled; | 1464 | int handled; |
| 1466 | u32 status; | 1465 | u32 status; |
| 1467 | 1466 | ||
diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c index 8d04654f0c59..4e1b84e6d66a 100644 --- a/drivers/net/tehuti.c +++ b/drivers/net/tehuti.c | |||
| @@ -1906,7 +1906,7 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 1906 | 1906 | ||
| 1907 | /************** pci *****************/ | 1907 | /************** pci *****************/ |
| 1908 | if ((err = pci_enable_device(pdev))) /* it trigers interrupt, dunno why. */ | 1908 | if ((err = pci_enable_device(pdev))) /* it trigers interrupt, dunno why. */ |
| 1909 | RET(err); /* it's not a problem though */ | 1909 | goto err_pci; /* it's not a problem though */ |
| 1910 | 1910 | ||
| 1911 | if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)) && | 1911 | if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)) && |
| 1912 | !(err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))) { | 1912 | !(err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))) { |
| @@ -2076,6 +2076,7 @@ err_out_res: | |||
| 2076 | pci_release_regions(pdev); | 2076 | pci_release_regions(pdev); |
| 2077 | err_dma: | 2077 | err_dma: |
| 2078 | pci_disable_device(pdev); | 2078 | pci_disable_device(pdev); |
| 2079 | err_pci: | ||
| 2079 | vfree(nic); | 2080 | vfree(nic); |
| 2080 | 2081 | ||
| 2081 | RET(err); | 2082 | RET(err); |
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 30b1cca8144c..014dc2cfe4d6 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
| @@ -64,8 +64,8 @@ | |||
| 64 | 64 | ||
| 65 | #define DRV_MODULE_NAME "tg3" | 65 | #define DRV_MODULE_NAME "tg3" |
| 66 | #define PFX DRV_MODULE_NAME ": " | 66 | #define PFX DRV_MODULE_NAME ": " |
| 67 | #define DRV_MODULE_VERSION "3.83" | 67 | #define DRV_MODULE_VERSION "3.84" |
| 68 | #define DRV_MODULE_RELDATE "October 10, 2007" | 68 | #define DRV_MODULE_RELDATE "October 12, 2007" |
| 69 | 69 | ||
| 70 | #define TG3_DEF_MAC_MODE 0 | 70 | #define TG3_DEF_MAC_MODE 0 |
| 71 | #define TG3_DEF_RX_MODE 0 | 71 | #define TG3_DEF_RX_MODE 0 |
| @@ -5056,6 +5056,12 @@ static void tg3_restore_pci_state(struct tg3 *tp) | |||
| 5056 | 5056 | ||
| 5057 | pci_write_config_dword(tp->pdev, TG3PCI_COMMAND, tp->pci_cmd); | 5057 | pci_write_config_dword(tp->pdev, TG3PCI_COMMAND, tp->pci_cmd); |
| 5058 | 5058 | ||
| 5059 | if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) { | ||
| 5060 | pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE, | ||
| 5061 | tp->pci_cacheline_sz); | ||
| 5062 | pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER, | ||
| 5063 | tp->pci_lat_timer); | ||
| 5064 | } | ||
| 5059 | /* Make sure PCI-X relaxed ordering bit is clear. */ | 5065 | /* Make sure PCI-X relaxed ordering bit is clear. */ |
| 5060 | if (tp->pcix_cap) { | 5066 | if (tp->pcix_cap) { |
| 5061 | u16 pcix_cmd; | 5067 | u16 pcix_cmd; |
| @@ -9034,7 +9040,7 @@ static int tg3_do_mem_test(struct tg3 *tp, u32 offset, u32 len) | |||
| 9034 | int i; | 9040 | int i; |
| 9035 | u32 j; | 9041 | u32 j; |
| 9036 | 9042 | ||
| 9037 | for (i = 0; i < sizeof(test_pattern)/sizeof(u32); i++) { | 9043 | for (i = 0; i < ARRAY_SIZE(test_pattern); i++) { |
| 9038 | for (j = 0; j < len; j += 4) { | 9044 | for (j = 0; j < len; j += 4) { |
| 9039 | u32 val; | 9045 | u32 val; |
| 9040 | 9046 | ||
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c index 9b9cd83fb8b6..41f34bb91cad 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c | |||
| @@ -1041,7 +1041,7 @@ static struct InfoLeaf infoleaf_array[] = { | |||
| 1041 | {DC21142, dc21142_infoleaf}, | 1041 | {DC21142, dc21142_infoleaf}, |
| 1042 | {DC21143, dc21143_infoleaf} | 1042 | {DC21143, dc21143_infoleaf} |
| 1043 | }; | 1043 | }; |
| 1044 | #define INFOLEAF_SIZE (sizeof(infoleaf_array)/(sizeof(int)+sizeof(int *))) | 1044 | #define INFOLEAF_SIZE ARRAY_SIZE(infoleaf_array) |
| 1045 | 1045 | ||
| 1046 | /* | 1046 | /* |
| 1047 | ** List the SROM info block functions | 1047 | ** List the SROM info block functions |
| @@ -1056,7 +1056,7 @@ static int (*dc_infoblock[])(struct net_device *dev, u_char, u_char *) = { | |||
| 1056 | compact_infoblock | 1056 | compact_infoblock |
| 1057 | }; | 1057 | }; |
| 1058 | 1058 | ||
| 1059 | #define COMPACT (sizeof(dc_infoblock)/sizeof(int *) - 1) | 1059 | #define COMPACT (ARRAY_SIZE(dc_infoblock) - 1) |
| 1060 | 1060 | ||
| 1061 | /* | 1061 | /* |
| 1062 | ** Miscellaneous defines... | 1062 | ** Miscellaneous defines... |
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index d00e7d41f6a5..bec413ba9bca 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c | |||
| @@ -63,7 +63,7 @@ | |||
| 63 | #define UGETH_MSG_DEFAULT (NETIF_MSG_IFUP << 1 ) - 1 | 63 | #define UGETH_MSG_DEFAULT (NETIF_MSG_IFUP << 1 ) - 1 |
| 64 | 64 | ||
| 65 | void uec_set_ethtool_ops(struct net_device *netdev); | 65 | void uec_set_ethtool_ops(struct net_device *netdev); |
| 66 | 66 | ||
| 67 | static DEFINE_SPINLOCK(ugeth_lock); | 67 | static DEFINE_SPINLOCK(ugeth_lock); |
| 68 | 68 | ||
| 69 | static struct { | 69 | static struct { |
| @@ -3454,9 +3454,12 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit | |||
| 3454 | u16 length, howmany = 0; | 3454 | u16 length, howmany = 0; |
| 3455 | u32 bd_status; | 3455 | u32 bd_status; |
| 3456 | u8 *bdBuffer; | 3456 | u8 *bdBuffer; |
| 3457 | struct net_device * dev; | ||
| 3457 | 3458 | ||
| 3458 | ugeth_vdbg("%s: IN", __FUNCTION__); | 3459 | ugeth_vdbg("%s: IN", __FUNCTION__); |
| 3459 | 3460 | ||
| 3461 | dev = ugeth->dev; | ||
| 3462 | |||
| 3460 | /* collect received buffers */ | 3463 | /* collect received buffers */ |
| 3461 | bd = ugeth->rxBd[rxQ]; | 3464 | bd = ugeth->rxBd[rxQ]; |
| 3462 | 3465 | ||
diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c index b39a541b2509..05df0a345b60 100644 --- a/drivers/net/wan/sdla.c +++ b/drivers/net/wan/sdla.c | |||
| @@ -1342,11 +1342,11 @@ static int sdla_set_config(struct net_device *dev, struct ifmap *map) | |||
| 1342 | if (flp->initialized) | 1342 | if (flp->initialized) |
| 1343 | return(-EINVAL); | 1343 | return(-EINVAL); |
| 1344 | 1344 | ||
| 1345 | for(i=0;i < sizeof(valid_port) / sizeof (int) ; i++) | 1345 | for(i=0; i < ARRAY_SIZE(valid_port); i++) |
| 1346 | if (valid_port[i] == map->base_addr) | 1346 | if (valid_port[i] == map->base_addr) |
| 1347 | break; | 1347 | break; |
| 1348 | 1348 | ||
| 1349 | if (i == sizeof(valid_port) / sizeof(int)) | 1349 | if (i == ARRAY_SIZE(valid_port)) |
| 1350 | return(-EINVAL); | 1350 | return(-EINVAL); |
| 1351 | 1351 | ||
| 1352 | if (!request_region(map->base_addr, SDLA_IO_EXTENTS, dev->name)){ | 1352 | if (!request_region(map->base_addr, SDLA_IO_EXTENTS, dev->name)){ |
| @@ -1487,12 +1487,12 @@ got_type: | |||
| 1487 | } | 1487 | } |
| 1488 | } | 1488 | } |
| 1489 | 1489 | ||
| 1490 | for(i=0;i < sizeof(valid_mem) / sizeof (int) ; i++) | 1490 | for(i=0; i < ARRAY_SIZE(valid_mem); i++) |
| 1491 | if (valid_mem[i] == map->mem_start) | 1491 | if (valid_mem[i] == map->mem_start) |
| 1492 | break; | 1492 | break; |
| 1493 | 1493 | ||
| 1494 | err = -EINVAL; | 1494 | err = -EINVAL; |
| 1495 | if (i == sizeof(valid_mem) / sizeof(int)) | 1495 | if (i == ARRAY_SIZE(valid_mem)) |
| 1496 | goto fail2; | 1496 | goto fail2; |
| 1497 | 1497 | ||
| 1498 | if (flp->type == SDLA_S502A && (map->mem_start & 0xF000) >> 12 == 0x0E) | 1498 | if (flp->type == SDLA_S502A && (map->mem_start & 0xF000) >> 12 == 0x0E) |
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index f464b82c7d5f..7fd505cc4f7a 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c | |||
| @@ -74,22 +74,12 @@ struct netfront_info { | |||
| 74 | 74 | ||
| 75 | struct napi_struct napi; | 75 | struct napi_struct napi; |
| 76 | 76 | ||
| 77 | struct xen_netif_tx_front_ring tx; | ||
| 78 | struct xen_netif_rx_front_ring rx; | ||
| 79 | |||
| 80 | spinlock_t tx_lock; | ||
| 81 | spinlock_t rx_lock; | ||
| 82 | |||
| 83 | unsigned int evtchn; | 77 | unsigned int evtchn; |
| 78 | struct xenbus_device *xbdev; | ||
| 84 | 79 | ||
| 85 | /* Receive-ring batched refills. */ | 80 | spinlock_t tx_lock; |
| 86 | #define RX_MIN_TARGET 8 | 81 | struct xen_netif_tx_front_ring tx; |
| 87 | #define RX_DFL_MIN_TARGET 64 | 82 | int tx_ring_ref; |
| 88 | #define RX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256) | ||
| 89 | unsigned rx_min_target, rx_max_target, rx_target; | ||
| 90 | struct sk_buff_head rx_batch; | ||
| 91 | |||
| 92 | struct timer_list rx_refill_timer; | ||
| 93 | 83 | ||
| 94 | /* | 84 | /* |
| 95 | * {tx,rx}_skbs store outstanding skbuffs. Free tx_skb entries | 85 | * {tx,rx}_skbs store outstanding skbuffs. Free tx_skb entries |
| @@ -108,14 +98,23 @@ struct netfront_info { | |||
| 108 | grant_ref_t grant_tx_ref[NET_TX_RING_SIZE]; | 98 | grant_ref_t grant_tx_ref[NET_TX_RING_SIZE]; |
| 109 | unsigned tx_skb_freelist; | 99 | unsigned tx_skb_freelist; |
| 110 | 100 | ||
| 101 | spinlock_t rx_lock ____cacheline_aligned_in_smp; | ||
| 102 | struct xen_netif_rx_front_ring rx; | ||
| 103 | int rx_ring_ref; | ||
| 104 | |||
| 105 | /* Receive-ring batched refills. */ | ||
| 106 | #define RX_MIN_TARGET 8 | ||
| 107 | #define RX_DFL_MIN_TARGET 64 | ||
| 108 | #define RX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256) | ||
| 109 | unsigned rx_min_target, rx_max_target, rx_target; | ||
| 110 | struct sk_buff_head rx_batch; | ||
| 111 | |||
| 112 | struct timer_list rx_refill_timer; | ||
| 113 | |||
| 111 | struct sk_buff *rx_skbs[NET_RX_RING_SIZE]; | 114 | struct sk_buff *rx_skbs[NET_RX_RING_SIZE]; |
| 112 | grant_ref_t gref_rx_head; | 115 | grant_ref_t gref_rx_head; |
| 113 | grant_ref_t grant_rx_ref[NET_RX_RING_SIZE]; | 116 | grant_ref_t grant_rx_ref[NET_RX_RING_SIZE]; |
| 114 | 117 | ||
| 115 | struct xenbus_device *xbdev; | ||
| 116 | int tx_ring_ref; | ||
| 117 | int rx_ring_ref; | ||
| 118 | |||
| 119 | unsigned long rx_pfn_array[NET_RX_RING_SIZE]; | 118 | unsigned long rx_pfn_array[NET_RX_RING_SIZE]; |
| 120 | struct multicall_entry rx_mcl[NET_RX_RING_SIZE+1]; | 119 | struct multicall_entry rx_mcl[NET_RX_RING_SIZE+1]; |
| 121 | struct mmu_update rx_mmu[NET_RX_RING_SIZE]; | 120 | struct mmu_update rx_mmu[NET_RX_RING_SIZE]; |
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index e8010a702e73..3ac080ee6e2f 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c | |||
| @@ -5213,6 +5213,10 @@ static int __init gdth_init(void) | |||
| 5213 | #endif /* CONFIG_PCI */ | 5213 | #endif /* CONFIG_PCI */ |
| 5214 | 5214 | ||
| 5215 | TRACE2(("gdth_detect() %d controller detected\n", gdth_ctr_count)); | 5215 | TRACE2(("gdth_detect() %d controller detected\n", gdth_ctr_count)); |
| 5216 | |||
| 5217 | if (list_empty(&gdth_instances)) | ||
| 5218 | return -ENODEV; | ||
| 5219 | |||
| 5216 | #ifdef GDTH_STATISTICS | 5220 | #ifdef GDTH_STATISTICS |
| 5217 | TRACE2(("gdth_detect(): Initializing timer !\n")); | 5221 | TRACE2(("gdth_detect(): Initializing timer !\n")); |
| 5218 | init_timer(&gdth_timer); | 5222 | init_timer(&gdth_timer); |
diff --git a/fs/Kconfig b/fs/Kconfig index bb02b39380a3..815d201d8600 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
| @@ -1755,6 +1755,14 @@ config SUNRPC | |||
| 1755 | config SUNRPC_GSS | 1755 | config SUNRPC_GSS |
| 1756 | tristate | 1756 | tristate |
| 1757 | 1757 | ||
| 1758 | config SUNRPC_XPRT_RDMA | ||
| 1759 | tristate "RDMA transport for sunrpc (EXPERIMENTAL)" | ||
| 1760 | depends on SUNRPC && INFINIBAND && EXPERIMENTAL | ||
| 1761 | default m | ||
| 1762 | help | ||
| 1763 | Adds a client RPC transport for supporting kernel NFS over RDMA | ||
| 1764 | mounts, including Infiniband and iWARP. Experimental. | ||
| 1765 | |||
| 1758 | config SUNRPC_BIND34 | 1766 | config SUNRPC_BIND34 |
| 1759 | bool "Support for rpcbind versions 3 & 4 (EXPERIMENTAL)" | 1767 | bool "Support for rpcbind versions 3 & 4 (EXPERIMENTAL)" |
| 1760 | depends on SUNRPC && EXPERIMENTAL | 1768 | depends on SUNRPC && EXPERIMENTAL |
diff --git a/fs/inode.c b/fs/inode.c index 29f5068f819b..f97de0aeb3b6 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
| @@ -142,6 +142,15 @@ static struct inode *alloc_inode(struct super_block *sb) | |||
| 142 | return NULL; | 142 | return NULL; |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | spin_lock_init(&inode->i_lock); | ||
| 146 | lockdep_set_class(&inode->i_lock, &sb->s_type->i_lock_key); | ||
| 147 | |||
| 148 | mutex_init(&inode->i_mutex); | ||
| 149 | lockdep_set_class(&inode->i_mutex, &sb->s_type->i_mutex_key); | ||
| 150 | |||
| 151 | init_rwsem(&inode->i_alloc_sem); | ||
| 152 | lockdep_set_class(&inode->i_alloc_sem, &sb->s_type->i_alloc_sem_key); | ||
| 153 | |||
| 145 | mapping->a_ops = &empty_aops; | 154 | mapping->a_ops = &empty_aops; |
| 146 | mapping->host = inode; | 155 | mapping->host = inode; |
| 147 | mapping->flags = 0; | 156 | mapping->flags = 0; |
| @@ -190,8 +199,6 @@ void inode_init_once(struct inode *inode) | |||
| 190 | INIT_HLIST_NODE(&inode->i_hash); | 199 | INIT_HLIST_NODE(&inode->i_hash); |
| 191 | INIT_LIST_HEAD(&inode->i_dentry); | 200 | INIT_LIST_HEAD(&inode->i_dentry); |
| 192 | INIT_LIST_HEAD(&inode->i_devices); | 201 | INIT_LIST_HEAD(&inode->i_devices); |
| 193 | mutex_init(&inode->i_mutex); | ||
| 194 | init_rwsem(&inode->i_alloc_sem); | ||
| 195 | INIT_RADIX_TREE(&inode->i_data.page_tree, GFP_ATOMIC); | 202 | INIT_RADIX_TREE(&inode->i_data.page_tree, GFP_ATOMIC); |
| 196 | rwlock_init(&inode->i_data.tree_lock); | 203 | rwlock_init(&inode->i_data.tree_lock); |
| 197 | spin_lock_init(&inode->i_data.i_mmap_lock); | 204 | spin_lock_init(&inode->i_data.i_mmap_lock); |
| @@ -199,7 +206,6 @@ void inode_init_once(struct inode *inode) | |||
| 199 | spin_lock_init(&inode->i_data.private_lock); | 206 | spin_lock_init(&inode->i_data.private_lock); |
| 200 | INIT_RAW_PRIO_TREE_ROOT(&inode->i_data.i_mmap); | 207 | INIT_RAW_PRIO_TREE_ROOT(&inode->i_data.i_mmap); |
| 201 | INIT_LIST_HEAD(&inode->i_data.i_mmap_nonlinear); | 208 | INIT_LIST_HEAD(&inode->i_data.i_mmap_nonlinear); |
| 202 | spin_lock_init(&inode->i_lock); | ||
| 203 | i_size_ordered_init(inode); | 209 | i_size_ordered_init(inode); |
| 204 | #ifdef CONFIG_INOTIFY | 210 | #ifdef CONFIG_INOTIFY |
| 205 | INIT_LIST_HEAD(&inode->inotify_watches); | 211 | INIT_LIST_HEAD(&inode->inotify_watches); |
| @@ -561,6 +567,18 @@ EXPORT_SYMBOL(new_inode); | |||
| 561 | 567 | ||
| 562 | void unlock_new_inode(struct inode *inode) | 568 | void unlock_new_inode(struct inode *inode) |
| 563 | { | 569 | { |
| 570 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
| 571 | struct file_system_type *type = inode->i_sb->s_type; | ||
| 572 | /* | ||
| 573 | * ensure nobody is actually holding i_mutex | ||
| 574 | */ | ||
| 575 | mutex_destroy(&inode->i_mutex); | ||
| 576 | mutex_init(&inode->i_mutex); | ||
| 577 | if (inode->i_mode & S_IFDIR) | ||
| 578 | lockdep_set_class(&inode->i_mutex, &type->i_mutex_dir_key); | ||
| 579 | else | ||
| 580 | lockdep_set_class(&inode->i_mutex, &type->i_mutex_key); | ||
| 581 | #endif | ||
| 564 | /* | 582 | /* |
| 565 | * This is special! We do not need the spinlock | 583 | * This is special! We do not need the spinlock |
| 566 | * when clearing I_LOCK, because we're guaranteed | 584 | * when clearing I_LOCK, because we're guaranteed |
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index 772b6531a2a2..8df5bac0b7a5 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c | |||
| @@ -233,6 +233,8 @@ out: | |||
| 233 | return ret; | 233 | return ret; |
| 234 | } | 234 | } |
| 235 | 235 | ||
| 236 | static struct lock_class_key jbd_handle_key; | ||
| 237 | |||
| 236 | /* Allocate a new handle. This should probably be in a slab... */ | 238 | /* Allocate a new handle. This should probably be in a slab... */ |
| 237 | static handle_t *new_handle(int nblocks) | 239 | static handle_t *new_handle(int nblocks) |
| 238 | { | 240 | { |
| @@ -243,6 +245,8 @@ static handle_t *new_handle(int nblocks) | |||
| 243 | handle->h_buffer_credits = nblocks; | 245 | handle->h_buffer_credits = nblocks; |
| 244 | handle->h_ref = 1; | 246 | handle->h_ref = 1; |
| 245 | 247 | ||
| 248 | lockdep_init_map(&handle->h_lockdep_map, "jbd_handle", &jbd_handle_key, 0); | ||
| 249 | |||
| 246 | return handle; | 250 | return handle; |
| 247 | } | 251 | } |
| 248 | 252 | ||
| @@ -286,6 +290,9 @@ handle_t *journal_start(journal_t *journal, int nblocks) | |||
| 286 | current->journal_info = NULL; | 290 | current->journal_info = NULL; |
| 287 | handle = ERR_PTR(err); | 291 | handle = ERR_PTR(err); |
| 288 | } | 292 | } |
| 293 | |||
| 294 | lock_acquire(&handle->h_lockdep_map, 0, 0, 0, 2, _THIS_IP_); | ||
| 295 | |||
| 289 | return handle; | 296 | return handle; |
| 290 | } | 297 | } |
| 291 | 298 | ||
| @@ -1411,6 +1418,8 @@ int journal_stop(handle_t *handle) | |||
| 1411 | spin_unlock(&journal->j_state_lock); | 1418 | spin_unlock(&journal->j_state_lock); |
| 1412 | } | 1419 | } |
| 1413 | 1420 | ||
| 1421 | lock_release(&handle->h_lockdep_map, 1, _THIS_IP_); | ||
| 1422 | |||
| 1414 | jbd_free_handle(handle); | 1423 | jbd_free_handle(handle); |
| 1415 | return err; | 1424 | return err; |
| 1416 | } | 1425 | } |
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index 3353ed8421a7..908b23fadd05 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <linux/utsname.h> | 10 | #include <linux/utsname.h> |
| 11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
| 12 | #include <linux/sunrpc/clnt.h> | 12 | #include <linux/sunrpc/clnt.h> |
| 13 | #include <linux/sunrpc/xprtsock.h> | ||
| 13 | #include <linux/sunrpc/svc.h> | 14 | #include <linux/sunrpc/svc.h> |
| 14 | #include <linux/lockd/lockd.h> | 15 | #include <linux/lockd/lockd.h> |
| 15 | #include <linux/lockd/sm_inter.h> | 16 | #include <linux/lockd/sm_inter.h> |
| @@ -132,7 +133,7 @@ nsm_create(void) | |||
| 132 | .sin_port = 0, | 133 | .sin_port = 0, |
| 133 | }; | 134 | }; |
| 134 | struct rpc_create_args args = { | 135 | struct rpc_create_args args = { |
| 135 | .protocol = IPPROTO_UDP, | 136 | .protocol = XPRT_TRANSPORT_UDP, |
| 136 | .address = (struct sockaddr *)&sin, | 137 | .address = (struct sockaddr *)&sin, |
| 137 | .addrsize = sizeof(sin), | 138 | .addrsize = sizeof(sin), |
| 138 | .servername = "localhost", | 139 | .servername = "localhost", |
diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c index 5316e307a49d..633653bff944 100644 --- a/fs/lockd/xdr.c +++ b/fs/lockd/xdr.c | |||
| @@ -62,8 +62,9 @@ static __be32 *nlm_decode_cookie(__be32 *p, struct nlm_cookie *c) | |||
| 62 | } | 62 | } |
| 63 | else | 63 | else |
| 64 | { | 64 | { |
| 65 | printk(KERN_NOTICE | 65 | dprintk("lockd: bad cookie size %d (only cookies under " |
| 66 | "lockd: bad cookie size %d (only cookies under %d bytes are supported.)\n", len, NLM_MAXCOOKIELEN); | 66 | "%d bytes are supported.)\n", |
| 67 | len, NLM_MAXCOOKIELEN); | ||
| 67 | return NULL; | 68 | return NULL; |
| 68 | } | 69 | } |
| 69 | return p; | 70 | return p; |
| @@ -84,8 +85,7 @@ nlm_decode_fh(__be32 *p, struct nfs_fh *f) | |||
| 84 | unsigned int len; | 85 | unsigned int len; |
| 85 | 86 | ||
| 86 | if ((len = ntohl(*p++)) != NFS2_FHSIZE) { | 87 | if ((len = ntohl(*p++)) != NFS2_FHSIZE) { |
| 87 | printk(KERN_NOTICE | 88 | dprintk("lockd: bad fhandle size %d (should be %d)\n", |
| 88 | "lockd: bad fhandle size %d (should be %d)\n", | ||
| 89 | len, NFS2_FHSIZE); | 89 | len, NFS2_FHSIZE); |
| 90 | return NULL; | 90 | return NULL; |
| 91 | } | 91 | } |
diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c index 846fc1d639dd..43ff9397e6c6 100644 --- a/fs/lockd/xdr4.c +++ b/fs/lockd/xdr4.c | |||
| @@ -64,8 +64,9 @@ nlm4_decode_cookie(__be32 *p, struct nlm_cookie *c) | |||
| 64 | } | 64 | } |
| 65 | else | 65 | else |
| 66 | { | 66 | { |
| 67 | printk(KERN_NOTICE | 67 | dprintk("lockd: bad cookie size %d (only cookies under " |
| 68 | "lockd: bad cookie size %d (only cookies under %d bytes are supported.)\n", len, NLM_MAXCOOKIELEN); | 68 | "%d bytes are supported.)\n", |
| 69 | len, NLM_MAXCOOKIELEN); | ||
| 69 | return NULL; | 70 | return NULL; |
| 70 | } | 71 | } |
| 71 | return p; | 72 | return p; |
| @@ -86,8 +87,7 @@ nlm4_decode_fh(__be32 *p, struct nfs_fh *f) | |||
| 86 | memset(f->data, 0, sizeof(f->data)); | 87 | memset(f->data, 0, sizeof(f->data)); |
| 87 | f->size = ntohl(*p++); | 88 | f->size = ntohl(*p++); |
| 88 | if (f->size > NFS_MAXFHSIZE) { | 89 | if (f->size > NFS_MAXFHSIZE) { |
| 89 | printk(KERN_NOTICE | 90 | dprintk("lockd: bad fhandle size %d (should be <=%d)\n", |
| 90 | "lockd: bad fhandle size %d (should be <=%d)\n", | ||
| 91 | f->size, NFS_MAXFHSIZE); | 91 | f->size, NFS_MAXFHSIZE); |
| 92 | return NULL; | 92 | return NULL; |
| 93 | } | 93 | } |
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile index b55cb236cf74..df0f41e09885 100644 --- a/fs/nfs/Makefile +++ b/fs/nfs/Makefile | |||
| @@ -16,4 +16,3 @@ nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \ | |||
| 16 | nfs4namespace.o | 16 | nfs4namespace.o |
| 17 | nfs-$(CONFIG_NFS_DIRECTIO) += direct.o | 17 | nfs-$(CONFIG_NFS_DIRECTIO) += direct.o |
| 18 | nfs-$(CONFIG_SYSCTL) += sysctl.o | 18 | nfs-$(CONFIG_SYSCTL) += sysctl.o |
| 19 | nfs-objs := $(nfs-y) | ||
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index a204484072f3..a532ee12740a 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
| @@ -23,6 +23,8 @@ | |||
| 23 | #include <linux/sunrpc/clnt.h> | 23 | #include <linux/sunrpc/clnt.h> |
| 24 | #include <linux/sunrpc/stats.h> | 24 | #include <linux/sunrpc/stats.h> |
| 25 | #include <linux/sunrpc/metrics.h> | 25 | #include <linux/sunrpc/metrics.h> |
| 26 | #include <linux/sunrpc/xprtsock.h> | ||
| 27 | #include <linux/sunrpc/xprtrdma.h> | ||
| 26 | #include <linux/nfs_fs.h> | 28 | #include <linux/nfs_fs.h> |
| 27 | #include <linux/nfs_mount.h> | 29 | #include <linux/nfs_mount.h> |
| 28 | #include <linux/nfs4_mount.h> | 30 | #include <linux/nfs4_mount.h> |
| @@ -340,7 +342,8 @@ static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, | |||
| 340 | to->to_retries = 2; | 342 | to->to_retries = 2; |
| 341 | 343 | ||
| 342 | switch (proto) { | 344 | switch (proto) { |
| 343 | case IPPROTO_TCP: | 345 | case XPRT_TRANSPORT_TCP: |
| 346 | case XPRT_TRANSPORT_RDMA: | ||
| 344 | if (!to->to_initval) | 347 | if (!to->to_initval) |
| 345 | to->to_initval = 60 * HZ; | 348 | to->to_initval = 60 * HZ; |
| 346 | if (to->to_initval > NFS_MAX_TCP_TIMEOUT) | 349 | if (to->to_initval > NFS_MAX_TCP_TIMEOUT) |
| @@ -349,7 +352,7 @@ static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, | |||
| 349 | to->to_maxval = to->to_initval + (to->to_increment * to->to_retries); | 352 | to->to_maxval = to->to_initval + (to->to_increment * to->to_retries); |
| 350 | to->to_exponential = 0; | 353 | to->to_exponential = 0; |
| 351 | break; | 354 | break; |
| 352 | case IPPROTO_UDP: | 355 | case XPRT_TRANSPORT_UDP: |
| 353 | default: | 356 | default: |
| 354 | if (!to->to_initval) | 357 | if (!to->to_initval) |
| 355 | to->to_initval = 11 * HZ / 10; | 358 | to->to_initval = 11 * HZ / 10; |
| @@ -501,9 +504,9 @@ static int nfs_init_server_rpcclient(struct nfs_server *server, rpc_authflavor_t | |||
| 501 | /* | 504 | /* |
| 502 | * Initialise an NFS2 or NFS3 client | 505 | * Initialise an NFS2 or NFS3 client |
| 503 | */ | 506 | */ |
| 504 | static int nfs_init_client(struct nfs_client *clp, const struct nfs_mount_data *data) | 507 | static int nfs_init_client(struct nfs_client *clp, |
| 508 | const struct nfs_parsed_mount_data *data) | ||
| 505 | { | 509 | { |
| 506 | int proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP; | ||
| 507 | int error; | 510 | int error; |
| 508 | 511 | ||
| 509 | if (clp->cl_cons_state == NFS_CS_READY) { | 512 | if (clp->cl_cons_state == NFS_CS_READY) { |
| @@ -522,8 +525,8 @@ static int nfs_init_client(struct nfs_client *clp, const struct nfs_mount_data * | |||
| 522 | * Create a client RPC handle for doing FSSTAT with UNIX auth only | 525 | * Create a client RPC handle for doing FSSTAT with UNIX auth only |
| 523 | * - RFC 2623, sec 2.3.2 | 526 | * - RFC 2623, sec 2.3.2 |
| 524 | */ | 527 | */ |
| 525 | error = nfs_create_rpc_client(clp, proto, data->timeo, data->retrans, | 528 | error = nfs_create_rpc_client(clp, data->nfs_server.protocol, |
| 526 | RPC_AUTH_UNIX, 0); | 529 | data->timeo, data->retrans, RPC_AUTH_UNIX, 0); |
| 527 | if (error < 0) | 530 | if (error < 0) |
| 528 | goto error; | 531 | goto error; |
| 529 | nfs_mark_client_ready(clp, NFS_CS_READY); | 532 | nfs_mark_client_ready(clp, NFS_CS_READY); |
| @@ -538,7 +541,8 @@ error: | |||
| 538 | /* | 541 | /* |
| 539 | * Create a version 2 or 3 client | 542 | * Create a version 2 or 3 client |
| 540 | */ | 543 | */ |
| 541 | static int nfs_init_server(struct nfs_server *server, const struct nfs_mount_data *data) | 544 | static int nfs_init_server(struct nfs_server *server, |
| 545 | const struct nfs_parsed_mount_data *data) | ||
| 542 | { | 546 | { |
| 543 | struct nfs_client *clp; | 547 | struct nfs_client *clp; |
| 544 | int error, nfsvers = 2; | 548 | int error, nfsvers = 2; |
| @@ -551,7 +555,8 @@ static int nfs_init_server(struct nfs_server *server, const struct nfs_mount_dat | |||
| 551 | #endif | 555 | #endif |
| 552 | 556 | ||
| 553 | /* Allocate or find a client reference we can use */ | 557 | /* Allocate or find a client reference we can use */ |
| 554 | clp = nfs_get_client(data->hostname, &data->addr, nfsvers); | 558 | clp = nfs_get_client(data->nfs_server.hostname, |
| 559 | &data->nfs_server.address, nfsvers); | ||
| 555 | if (IS_ERR(clp)) { | 560 | if (IS_ERR(clp)) { |
| 556 | dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp)); | 561 | dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp)); |
| 557 | return PTR_ERR(clp); | 562 | return PTR_ERR(clp); |
| @@ -581,7 +586,7 @@ static int nfs_init_server(struct nfs_server *server, const struct nfs_mount_dat | |||
| 581 | if (error < 0) | 586 | if (error < 0) |
| 582 | goto error; | 587 | goto error; |
| 583 | 588 | ||
| 584 | error = nfs_init_server_rpcclient(server, data->pseudoflavor); | 589 | error = nfs_init_server_rpcclient(server, data->auth_flavors[0]); |
| 585 | if (error < 0) | 590 | if (error < 0) |
| 586 | goto error; | 591 | goto error; |
| 587 | 592 | ||
| @@ -760,7 +765,7 @@ void nfs_free_server(struct nfs_server *server) | |||
| 760 | * Create a version 2 or 3 volume record | 765 | * Create a version 2 or 3 volume record |
| 761 | * - keyed on server and FSID | 766 | * - keyed on server and FSID |
| 762 | */ | 767 | */ |
| 763 | struct nfs_server *nfs_create_server(const struct nfs_mount_data *data, | 768 | struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data, |
| 764 | struct nfs_fh *mntfh) | 769 | struct nfs_fh *mntfh) |
| 765 | { | 770 | { |
| 766 | struct nfs_server *server; | 771 | struct nfs_server *server; |
| @@ -906,7 +911,7 @@ error: | |||
| 906 | * Create a version 4 volume record | 911 | * Create a version 4 volume record |
| 907 | */ | 912 | */ |
| 908 | static int nfs4_init_server(struct nfs_server *server, | 913 | static int nfs4_init_server(struct nfs_server *server, |
| 909 | const struct nfs4_mount_data *data, rpc_authflavor_t authflavour) | 914 | const struct nfs_parsed_mount_data *data) |
| 910 | { | 915 | { |
| 911 | int error; | 916 | int error; |
| 912 | 917 | ||
| @@ -926,7 +931,7 @@ static int nfs4_init_server(struct nfs_server *server, | |||
| 926 | server->acdirmin = data->acdirmin * HZ; | 931 | server->acdirmin = data->acdirmin * HZ; |
| 927 | server->acdirmax = data->acdirmax * HZ; | 932 | server->acdirmax = data->acdirmax * HZ; |
| 928 | 933 | ||
| 929 | error = nfs_init_server_rpcclient(server, authflavour); | 934 | error = nfs_init_server_rpcclient(server, data->auth_flavors[0]); |
| 930 | 935 | ||
| 931 | /* Done */ | 936 | /* Done */ |
| 932 | dprintk("<-- nfs4_init_server() = %d\n", error); | 937 | dprintk("<-- nfs4_init_server() = %d\n", error); |
| @@ -937,12 +942,7 @@ static int nfs4_init_server(struct nfs_server *server, | |||
| 937 | * Create a version 4 volume record | 942 | * Create a version 4 volume record |
| 938 | * - keyed on server and FSID | 943 | * - keyed on server and FSID |
| 939 | */ | 944 | */ |
| 940 | struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *data, | 945 | struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data, |
| 941 | const char *hostname, | ||
| 942 | const struct sockaddr_in *addr, | ||
| 943 | const char *mntpath, | ||
| 944 | const char *ip_addr, | ||
| 945 | rpc_authflavor_t authflavour, | ||
| 946 | struct nfs_fh *mntfh) | 946 | struct nfs_fh *mntfh) |
| 947 | { | 947 | { |
| 948 | struct nfs_fattr fattr; | 948 | struct nfs_fattr fattr; |
| @@ -956,13 +956,18 @@ struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *data, | |||
| 956 | return ERR_PTR(-ENOMEM); | 956 | return ERR_PTR(-ENOMEM); |
| 957 | 957 | ||
| 958 | /* Get a client record */ | 958 | /* Get a client record */ |
| 959 | error = nfs4_set_client(server, hostname, addr, ip_addr, authflavour, | 959 | error = nfs4_set_client(server, |
| 960 | data->proto, data->timeo, data->retrans); | 960 | data->nfs_server.hostname, |
| 961 | &data->nfs_server.address, | ||
| 962 | data->client_address, | ||
| 963 | data->auth_flavors[0], | ||
| 964 | data->nfs_server.protocol, | ||
| 965 | data->timeo, data->retrans); | ||
| 961 | if (error < 0) | 966 | if (error < 0) |
| 962 | goto error; | 967 | goto error; |
| 963 | 968 | ||
| 964 | /* set up the general RPC client */ | 969 | /* set up the general RPC client */ |
| 965 | error = nfs4_init_server(server, data, authflavour); | 970 | error = nfs4_init_server(server, data); |
| 966 | if (error < 0) | 971 | if (error < 0) |
| 967 | goto error; | 972 | goto error; |
| 968 | 973 | ||
| @@ -971,7 +976,7 @@ struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *data, | |||
| 971 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); | 976 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); |
| 972 | 977 | ||
| 973 | /* Probe the root fh to retrieve its FSID */ | 978 | /* Probe the root fh to retrieve its FSID */ |
| 974 | error = nfs4_path_walk(server, mntfh, mntpath); | 979 | error = nfs4_path_walk(server, mntfh, data->nfs_server.export_path); |
| 975 | if (error < 0) | 980 | if (error < 0) |
| 976 | goto error; | 981 | goto error; |
| 977 | 982 | ||
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index c55a761c22bb..af8b235d405d 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
| @@ -52,7 +52,7 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_ | |||
| 52 | for (fl = inode->i_flock; fl != 0; fl = fl->fl_next) { | 52 | for (fl = inode->i_flock; fl != 0; fl = fl->fl_next) { |
| 53 | if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) | 53 | if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) |
| 54 | continue; | 54 | continue; |
| 55 | if ((struct nfs_open_context *)fl->fl_file->private_data != ctx) | 55 | if (nfs_file_open_context(fl->fl_file) != ctx) |
| 56 | continue; | 56 | continue; |
| 57 | status = nfs4_lock_delegation_recall(state, fl); | 57 | status = nfs4_lock_delegation_recall(state, fl); |
| 58 | if (status >= 0) | 58 | if (status >= 0) |
| @@ -109,6 +109,7 @@ again: | |||
| 109 | void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res) | 109 | void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res) |
| 110 | { | 110 | { |
| 111 | struct nfs_delegation *delegation = NFS_I(inode)->delegation; | 111 | struct nfs_delegation *delegation = NFS_I(inode)->delegation; |
| 112 | struct rpc_cred *oldcred; | ||
| 112 | 113 | ||
| 113 | if (delegation == NULL) | 114 | if (delegation == NULL) |
| 114 | return; | 115 | return; |
| @@ -116,11 +117,12 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, st | |||
| 116 | sizeof(delegation->stateid.data)); | 117 | sizeof(delegation->stateid.data)); |
| 117 | delegation->type = res->delegation_type; | 118 | delegation->type = res->delegation_type; |
| 118 | delegation->maxsize = res->maxsize; | 119 | delegation->maxsize = res->maxsize; |
| 119 | put_rpccred(cred); | 120 | oldcred = delegation->cred; |
| 120 | delegation->cred = get_rpccred(cred); | 121 | delegation->cred = get_rpccred(cred); |
| 121 | delegation->flags &= ~NFS_DELEGATION_NEED_RECLAIM; | 122 | delegation->flags &= ~NFS_DELEGATION_NEED_RECLAIM; |
| 122 | NFS_I(inode)->delegation_state = delegation->type; | 123 | NFS_I(inode)->delegation_state = delegation->type; |
| 123 | smp_wmb(); | 124 | smp_wmb(); |
| 125 | put_rpccred(oldcred); | ||
| 124 | } | 126 | } |
| 125 | 127 | ||
| 126 | /* | 128 | /* |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index e4a04d16b8b0..8ec7fbd8240c 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
| @@ -200,9 +200,6 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) | |||
| 200 | desc->timestamp = timestamp; | 200 | desc->timestamp = timestamp; |
| 201 | desc->timestamp_valid = 1; | 201 | desc->timestamp_valid = 1; |
| 202 | SetPageUptodate(page); | 202 | SetPageUptodate(page); |
| 203 | spin_lock(&inode->i_lock); | ||
| 204 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME; | ||
| 205 | spin_unlock(&inode->i_lock); | ||
| 206 | /* Ensure consistent page alignment of the data. | 203 | /* Ensure consistent page alignment of the data. |
| 207 | * Note: assumes we have exclusive access to this mapping either | 204 | * Note: assumes we have exclusive access to this mapping either |
| 208 | * through inode->i_mutex or some other mechanism. | 205 | * through inode->i_mutex or some other mechanism. |
| @@ -214,9 +211,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) | |||
| 214 | unlock_page(page); | 211 | unlock_page(page); |
| 215 | return 0; | 212 | return 0; |
| 216 | error: | 213 | error: |
| 217 | SetPageError(page); | ||
| 218 | unlock_page(page); | 214 | unlock_page(page); |
| 219 | nfs_zap_caches(inode); | ||
| 220 | desc->error = error; | 215 | desc->error = error; |
| 221 | return -EIO; | 216 | return -EIO; |
| 222 | } | 217 | } |
| @@ -407,7 +402,7 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
| 407 | struct file *file = desc->file; | 402 | struct file *file = desc->file; |
| 408 | struct nfs_entry *entry = desc->entry; | 403 | struct nfs_entry *entry = desc->entry; |
| 409 | struct dentry *dentry = NULL; | 404 | struct dentry *dentry = NULL; |
| 410 | unsigned long fileid; | 405 | u64 fileid; |
| 411 | int loop_count = 0, | 406 | int loop_count = 0, |
| 412 | res; | 407 | res; |
| 413 | 408 | ||
| @@ -418,7 +413,7 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
| 418 | unsigned d_type = DT_UNKNOWN; | 413 | unsigned d_type = DT_UNKNOWN; |
| 419 | /* Note: entry->prev_cookie contains the cookie for | 414 | /* Note: entry->prev_cookie contains the cookie for |
| 420 | * retrieving the current dirent on the server */ | 415 | * retrieving the current dirent on the server */ |
| 421 | fileid = nfs_fileid_to_ino_t(entry->ino); | 416 | fileid = entry->ino; |
| 422 | 417 | ||
| 423 | /* Get a dentry if we have one */ | 418 | /* Get a dentry if we have one */ |
| 424 | if (dentry != NULL) | 419 | if (dentry != NULL) |
| @@ -428,11 +423,12 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
| 428 | /* Use readdirplus info */ | 423 | /* Use readdirplus info */ |
| 429 | if (dentry != NULL && dentry->d_inode != NULL) { | 424 | if (dentry != NULL && dentry->d_inode != NULL) { |
| 430 | d_type = dt_type(dentry->d_inode); | 425 | d_type = dt_type(dentry->d_inode); |
| 431 | fileid = dentry->d_inode->i_ino; | 426 | fileid = NFS_FILEID(dentry->d_inode); |
| 432 | } | 427 | } |
| 433 | 428 | ||
| 434 | res = filldir(dirent, entry->name, entry->len, | 429 | res = filldir(dirent, entry->name, entry->len, |
| 435 | file->f_pos, fileid, d_type); | 430 | file->f_pos, nfs_compat_user_ino64(fileid), |
| 431 | d_type); | ||
| 436 | if (res < 0) | 432 | if (res < 0) |
| 437 | break; | 433 | break; |
| 438 | file->f_pos++; | 434 | file->f_pos++; |
| @@ -490,9 +486,6 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
| 490 | page, | 486 | page, |
| 491 | NFS_SERVER(inode)->dtsize, | 487 | NFS_SERVER(inode)->dtsize, |
| 492 | desc->plus); | 488 | desc->plus); |
| 493 | spin_lock(&inode->i_lock); | ||
| 494 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME; | ||
| 495 | spin_unlock(&inode->i_lock); | ||
| 496 | desc->page = page; | 489 | desc->page = page; |
| 497 | desc->ptr = kmap(page); /* matching kunmap in nfs_do_filldir */ | 490 | desc->ptr = kmap(page); /* matching kunmap in nfs_do_filldir */ |
| 498 | if (desc->error >= 0) { | 491 | if (desc->error >= 0) { |
| @@ -558,7 +551,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 558 | memset(desc, 0, sizeof(*desc)); | 551 | memset(desc, 0, sizeof(*desc)); |
| 559 | 552 | ||
| 560 | desc->file = filp; | 553 | desc->file = filp; |
| 561 | desc->dir_cookie = &((struct nfs_open_context *)filp->private_data)->dir_cookie; | 554 | desc->dir_cookie = &nfs_file_open_context(filp)->dir_cookie; |
| 562 | desc->decode = NFS_PROTO(inode)->decode_dirent; | 555 | desc->decode = NFS_PROTO(inode)->decode_dirent; |
| 563 | desc->plus = NFS_USE_READDIRPLUS(inode); | 556 | desc->plus = NFS_USE_READDIRPLUS(inode); |
| 564 | 557 | ||
| @@ -623,7 +616,7 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin) | |||
| 623 | } | 616 | } |
| 624 | if (offset != filp->f_pos) { | 617 | if (offset != filp->f_pos) { |
| 625 | filp->f_pos = offset; | 618 | filp->f_pos = offset; |
| 626 | ((struct nfs_open_context *)filp->private_data)->dir_cookie = 0; | 619 | nfs_file_open_context(filp)->dir_cookie = 0; |
| 627 | } | 620 | } |
| 628 | out: | 621 | out: |
| 629 | mutex_unlock(&filp->f_path.dentry->d_inode->i_mutex); | 622 | mutex_unlock(&filp->f_path.dentry->d_inode->i_mutex); |
| @@ -650,36 +643,18 @@ static int nfs_fsync_dir(struct file *filp, struct dentry *dentry, int datasync) | |||
| 650 | */ | 643 | */ |
| 651 | static int nfs_check_verifier(struct inode *dir, struct dentry *dentry) | 644 | static int nfs_check_verifier(struct inode *dir, struct dentry *dentry) |
| 652 | { | 645 | { |
| 653 | unsigned long verf; | ||
| 654 | |||
| 655 | if (IS_ROOT(dentry)) | 646 | if (IS_ROOT(dentry)) |
| 656 | return 1; | 647 | return 1; |
| 657 | verf = dentry->d_time; | 648 | if (!nfs_verify_change_attribute(dir, dentry->d_time)) |
| 658 | if (nfs_caches_unstable(dir) | 649 | return 0; |
| 659 | || verf != NFS_I(dir)->cache_change_attribute) | 650 | /* Revalidate nfsi->cache_change_attribute before we declare a match */ |
| 651 | if (nfs_revalidate_inode(NFS_SERVER(dir), dir) < 0) | ||
| 652 | return 0; | ||
| 653 | if (!nfs_verify_change_attribute(dir, dentry->d_time)) | ||
| 660 | return 0; | 654 | return 0; |
| 661 | return 1; | 655 | return 1; |
| 662 | } | 656 | } |
| 663 | 657 | ||
| 664 | static inline void nfs_set_verifier(struct dentry * dentry, unsigned long verf) | ||
| 665 | { | ||
| 666 | dentry->d_time = verf; | ||
| 667 | } | ||
| 668 | |||
| 669 | static void nfs_refresh_verifier(struct dentry * dentry, unsigned long verf) | ||
| 670 | { | ||
| 671 | nfs_set_verifier(dentry, verf); | ||
| 672 | } | ||
| 673 | |||
| 674 | /* | ||
| 675 | * Whenever an NFS operation succeeds, we know that the dentry | ||
| 676 | * is valid, so we update the revalidation timestamp. | ||
| 677 | */ | ||
| 678 | static inline void nfs_renew_times(struct dentry * dentry) | ||
| 679 | { | ||
| 680 | dentry->d_time = jiffies; | ||
| 681 | } | ||
| 682 | |||
| 683 | /* | 658 | /* |
| 684 | * Return the intent data that applies to this particular path component | 659 | * Return the intent data that applies to this particular path component |
| 685 | * | 660 | * |
| @@ -695,6 +670,19 @@ static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd, unsigne | |||
| 695 | } | 670 | } |
| 696 | 671 | ||
| 697 | /* | 672 | /* |
| 673 | * Use intent information to check whether or not we're going to do | ||
| 674 | * an O_EXCL create using this path component. | ||
| 675 | */ | ||
| 676 | static int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd) | ||
| 677 | { | ||
| 678 | if (NFS_PROTO(dir)->version == 2) | ||
| 679 | return 0; | ||
| 680 | if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_CREATE) == 0) | ||
| 681 | return 0; | ||
| 682 | return (nd->intent.open.flags & O_EXCL) != 0; | ||
| 683 | } | ||
| 684 | |||
| 685 | /* | ||
| 698 | * Inode and filehandle revalidation for lookups. | 686 | * Inode and filehandle revalidation for lookups. |
| 699 | * | 687 | * |
| 700 | * We force revalidation in the cases where the VFS sets LOOKUP_REVAL, | 688 | * We force revalidation in the cases where the VFS sets LOOKUP_REVAL, |
| @@ -717,6 +705,7 @@ int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd) | |||
| 717 | (S_ISREG(inode->i_mode) || | 705 | (S_ISREG(inode->i_mode) || |
| 718 | S_ISDIR(inode->i_mode))) | 706 | S_ISDIR(inode->i_mode))) |
| 719 | goto out_force; | 707 | goto out_force; |
| 708 | return 0; | ||
| 720 | } | 709 | } |
| 721 | return nfs_revalidate_inode(server, inode); | 710 | return nfs_revalidate_inode(server, inode); |
| 722 | out_force: | 711 | out_force: |
| @@ -759,7 +748,6 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) | |||
| 759 | int error; | 748 | int error; |
| 760 | struct nfs_fh fhandle; | 749 | struct nfs_fh fhandle; |
| 761 | struct nfs_fattr fattr; | 750 | struct nfs_fattr fattr; |
| 762 | unsigned long verifier; | ||
| 763 | 751 | ||
| 764 | parent = dget_parent(dentry); | 752 | parent = dget_parent(dentry); |
| 765 | lock_kernel(); | 753 | lock_kernel(); |
| @@ -767,10 +755,6 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) | |||
| 767 | nfs_inc_stats(dir, NFSIOS_DENTRYREVALIDATE); | 755 | nfs_inc_stats(dir, NFSIOS_DENTRYREVALIDATE); |
| 768 | inode = dentry->d_inode; | 756 | inode = dentry->d_inode; |
| 769 | 757 | ||
| 770 | /* Revalidate parent directory attribute cache */ | ||
| 771 | if (nfs_revalidate_inode(NFS_SERVER(dir), dir) < 0) | ||
| 772 | goto out_zap_parent; | ||
| 773 | |||
| 774 | if (!inode) { | 758 | if (!inode) { |
| 775 | if (nfs_neg_need_reval(dir, dentry, nd)) | 759 | if (nfs_neg_need_reval(dir, dentry, nd)) |
| 776 | goto out_bad; | 760 | goto out_bad; |
| @@ -785,7 +769,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) | |||
| 785 | } | 769 | } |
| 786 | 770 | ||
| 787 | /* Force a full look up iff the parent directory has changed */ | 771 | /* Force a full look up iff the parent directory has changed */ |
| 788 | if (nfs_check_verifier(dir, dentry)) { | 772 | if (!nfs_is_exclusive_create(dir, nd) && nfs_check_verifier(dir, dentry)) { |
| 789 | if (nfs_lookup_verify_inode(inode, nd)) | 773 | if (nfs_lookup_verify_inode(inode, nd)) |
| 790 | goto out_zap_parent; | 774 | goto out_zap_parent; |
| 791 | goto out_valid; | 775 | goto out_valid; |
| @@ -794,7 +778,6 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) | |||
| 794 | if (NFS_STALE(inode)) | 778 | if (NFS_STALE(inode)) |
| 795 | goto out_bad; | 779 | goto out_bad; |
| 796 | 780 | ||
| 797 | verifier = nfs_save_change_attribute(dir); | ||
| 798 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); | 781 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); |
| 799 | if (error) | 782 | if (error) |
| 800 | goto out_bad; | 783 | goto out_bad; |
| @@ -803,8 +786,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) | |||
| 803 | if ((error = nfs_refresh_inode(inode, &fattr)) != 0) | 786 | if ((error = nfs_refresh_inode(inode, &fattr)) != 0) |
| 804 | goto out_bad; | 787 | goto out_bad; |
| 805 | 788 | ||
| 806 | nfs_renew_times(dentry); | 789 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
| 807 | nfs_refresh_verifier(dentry, verifier); | ||
| 808 | out_valid: | 790 | out_valid: |
| 809 | unlock_kernel(); | 791 | unlock_kernel(); |
| 810 | dput(parent); | 792 | dput(parent); |
| @@ -815,7 +797,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) | |||
| 815 | out_zap_parent: | 797 | out_zap_parent: |
| 816 | nfs_zap_caches(dir); | 798 | nfs_zap_caches(dir); |
| 817 | out_bad: | 799 | out_bad: |
| 818 | NFS_CACHEINV(dir); | 800 | nfs_mark_for_revalidate(dir); |
| 819 | if (inode && S_ISDIR(inode->i_mode)) { | 801 | if (inode && S_ISDIR(inode->i_mode)) { |
| 820 | /* Purge readdir caches. */ | 802 | /* Purge readdir caches. */ |
| 821 | nfs_zap_caches(inode); | 803 | nfs_zap_caches(inode); |
| @@ -872,8 +854,6 @@ static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode) | |||
| 872 | nfs_complete_unlink(dentry, inode); | 854 | nfs_complete_unlink(dentry, inode); |
| 873 | unlock_kernel(); | 855 | unlock_kernel(); |
| 874 | } | 856 | } |
| 875 | /* When creating a negative dentry, we want to renew d_time */ | ||
| 876 | nfs_renew_times(dentry); | ||
| 877 | iput(inode); | 857 | iput(inode); |
| 878 | } | 858 | } |
| 879 | 859 | ||
| @@ -883,30 +863,6 @@ struct dentry_operations nfs_dentry_operations = { | |||
| 883 | .d_iput = nfs_dentry_iput, | 863 | .d_iput = nfs_dentry_iput, |
| 884 | }; | 864 | }; |
| 885 | 865 | ||
| 886 | /* | ||
| 887 | * Use intent information to check whether or not we're going to do | ||
| 888 | * an O_EXCL create using this path component. | ||
| 889 | */ | ||
| 890 | static inline | ||
| 891 | int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd) | ||
| 892 | { | ||
| 893 | if (NFS_PROTO(dir)->version == 2) | ||
| 894 | return 0; | ||
| 895 | if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_CREATE) == 0) | ||
| 896 | return 0; | ||
| 897 | return (nd->intent.open.flags & O_EXCL) != 0; | ||
| 898 | } | ||
| 899 | |||
| 900 | static inline int nfs_reval_fsid(struct inode *dir, const struct nfs_fattr *fattr) | ||
| 901 | { | ||
| 902 | struct nfs_server *server = NFS_SERVER(dir); | ||
| 903 | |||
| 904 | if (!nfs_fsid_equal(&server->fsid, &fattr->fsid)) | ||
| 905 | /* Revalidate fsid using the parent directory */ | ||
| 906 | return __nfs_revalidate_inode(server, dir); | ||
| 907 | return 0; | ||
| 908 | } | ||
| 909 | |||
| 910 | static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) | 866 | static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) |
| 911 | { | 867 | { |
| 912 | struct dentry *res; | 868 | struct dentry *res; |
| @@ -945,11 +901,6 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru | |||
| 945 | res = ERR_PTR(error); | 901 | res = ERR_PTR(error); |
| 946 | goto out_unlock; | 902 | goto out_unlock; |
| 947 | } | 903 | } |
| 948 | error = nfs_reval_fsid(dir, &fattr); | ||
| 949 | if (error < 0) { | ||
| 950 | res = ERR_PTR(error); | ||
| 951 | goto out_unlock; | ||
| 952 | } | ||
| 953 | inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr); | 904 | inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr); |
| 954 | res = (struct dentry *)inode; | 905 | res = (struct dentry *)inode; |
| 955 | if (IS_ERR(res)) | 906 | if (IS_ERR(res)) |
| @@ -958,17 +909,10 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru | |||
| 958 | no_entry: | 909 | no_entry: |
| 959 | res = d_materialise_unique(dentry, inode); | 910 | res = d_materialise_unique(dentry, inode); |
| 960 | if (res != NULL) { | 911 | if (res != NULL) { |
| 961 | struct dentry *parent; | ||
| 962 | if (IS_ERR(res)) | 912 | if (IS_ERR(res)) |
| 963 | goto out_unlock; | 913 | goto out_unlock; |
| 964 | /* Was a directory renamed! */ | ||
| 965 | parent = dget_parent(res); | ||
| 966 | if (!IS_ROOT(parent)) | ||
| 967 | nfs_mark_for_revalidate(parent->d_inode); | ||
| 968 | dput(parent); | ||
| 969 | dentry = res; | 914 | dentry = res; |
| 970 | } | 915 | } |
| 971 | nfs_renew_times(dentry); | ||
| 972 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 916 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
| 973 | out_unlock: | 917 | out_unlock: |
| 974 | unlock_kernel(); | 918 | unlock_kernel(); |
| @@ -1020,28 +964,16 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry | |||
| 1020 | } | 964 | } |
| 1021 | dentry->d_op = NFS_PROTO(dir)->dentry_ops; | 965 | dentry->d_op = NFS_PROTO(dir)->dentry_ops; |
| 1022 | 966 | ||
| 1023 | /* Let vfs_create() deal with O_EXCL */ | 967 | /* Let vfs_create() deal with O_EXCL. Instantiate, but don't hash |
| 968 | * the dentry. */ | ||
| 1024 | if (nd->intent.open.flags & O_EXCL) { | 969 | if (nd->intent.open.flags & O_EXCL) { |
| 1025 | d_add(dentry, NULL); | 970 | d_instantiate(dentry, NULL); |
| 1026 | goto out; | 971 | goto out; |
| 1027 | } | 972 | } |
| 1028 | 973 | ||
| 1029 | /* Open the file on the server */ | 974 | /* Open the file on the server */ |
| 1030 | lock_kernel(); | 975 | lock_kernel(); |
| 1031 | /* Revalidate parent directory attribute cache */ | 976 | res = nfs4_atomic_open(dir, dentry, nd); |
| 1032 | error = nfs_revalidate_inode(NFS_SERVER(dir), dir); | ||
| 1033 | if (error < 0) { | ||
| 1034 | res = ERR_PTR(error); | ||
| 1035 | unlock_kernel(); | ||
| 1036 | goto out; | ||
| 1037 | } | ||
| 1038 | |||
| 1039 | if (nd->intent.open.flags & O_CREAT) { | ||
| 1040 | nfs_begin_data_update(dir); | ||
| 1041 | res = nfs4_atomic_open(dir, dentry, nd); | ||
| 1042 | nfs_end_data_update(dir); | ||
| 1043 | } else | ||
| 1044 | res = nfs4_atomic_open(dir, dentry, nd); | ||
| 1045 | unlock_kernel(); | 977 | unlock_kernel(); |
| 1046 | if (IS_ERR(res)) { | 978 | if (IS_ERR(res)) { |
| 1047 | error = PTR_ERR(res); | 979 | error = PTR_ERR(res); |
| @@ -1063,8 +995,6 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry | |||
| 1063 | } | 995 | } |
| 1064 | } else if (res != NULL) | 996 | } else if (res != NULL) |
| 1065 | dentry = res; | 997 | dentry = res; |
| 1066 | nfs_renew_times(dentry); | ||
| 1067 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
| 1068 | out: | 998 | out: |
| 1069 | return res; | 999 | return res; |
| 1070 | no_open: | 1000 | no_open: |
| @@ -1076,7 +1006,6 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
| 1076 | struct dentry *parent = NULL; | 1006 | struct dentry *parent = NULL; |
| 1077 | struct inode *inode = dentry->d_inode; | 1007 | struct inode *inode = dentry->d_inode; |
| 1078 | struct inode *dir; | 1008 | struct inode *dir; |
| 1079 | unsigned long verifier; | ||
| 1080 | int openflags, ret = 0; | 1009 | int openflags, ret = 0; |
| 1081 | 1010 | ||
| 1082 | parent = dget_parent(dentry); | 1011 | parent = dget_parent(dentry); |
| @@ -1086,8 +1015,12 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
| 1086 | /* We can't create new files in nfs_open_revalidate(), so we | 1015 | /* We can't create new files in nfs_open_revalidate(), so we |
| 1087 | * optimize away revalidation of negative dentries. | 1016 | * optimize away revalidation of negative dentries. |
| 1088 | */ | 1017 | */ |
| 1089 | if (inode == NULL) | 1018 | if (inode == NULL) { |
| 1019 | if (!nfs_neg_need_reval(dir, dentry, nd)) | ||
| 1020 | ret = 1; | ||
| 1090 | goto out; | 1021 | goto out; |
| 1022 | } | ||
| 1023 | |||
| 1091 | /* NFS only supports OPEN on regular files */ | 1024 | /* NFS only supports OPEN on regular files */ |
| 1092 | if (!S_ISREG(inode->i_mode)) | 1025 | if (!S_ISREG(inode->i_mode)) |
| 1093 | goto no_open; | 1026 | goto no_open; |
| @@ -1104,10 +1037,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
| 1104 | * change attribute *before* we do the RPC call. | 1037 | * change attribute *before* we do the RPC call. |
| 1105 | */ | 1038 | */ |
| 1106 | lock_kernel(); | 1039 | lock_kernel(); |
| 1107 | verifier = nfs_save_change_attribute(dir); | ||
| 1108 | ret = nfs4_open_revalidate(dir, dentry, openflags, nd); | 1040 | ret = nfs4_open_revalidate(dir, dentry, openflags, nd); |
| 1109 | if (!ret) | ||
| 1110 | nfs_refresh_verifier(dentry, verifier); | ||
| 1111 | unlock_kernel(); | 1041 | unlock_kernel(); |
| 1112 | out: | 1042 | out: |
| 1113 | dput(parent); | 1043 | dput(parent); |
| @@ -1133,6 +1063,7 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc) | |||
| 1133 | .len = entry->len, | 1063 | .len = entry->len, |
| 1134 | }; | 1064 | }; |
| 1135 | struct inode *inode; | 1065 | struct inode *inode; |
| 1066 | unsigned long verf = nfs_save_change_attribute(dir); | ||
| 1136 | 1067 | ||
| 1137 | switch (name.len) { | 1068 | switch (name.len) { |
| 1138 | case 2: | 1069 | case 2: |
| @@ -1143,6 +1074,14 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc) | |||
| 1143 | if (name.name[0] == '.') | 1074 | if (name.name[0] == '.') |
| 1144 | return dget(parent); | 1075 | return dget(parent); |
| 1145 | } | 1076 | } |
| 1077 | |||
| 1078 | spin_lock(&dir->i_lock); | ||
| 1079 | if (NFS_I(dir)->cache_validity & NFS_INO_INVALID_DATA) { | ||
| 1080 | spin_unlock(&dir->i_lock); | ||
| 1081 | return NULL; | ||
| 1082 | } | ||
| 1083 | spin_unlock(&dir->i_lock); | ||
| 1084 | |||
| 1146 | name.hash = full_name_hash(name.name, name.len); | 1085 | name.hash = full_name_hash(name.name, name.len); |
| 1147 | dentry = d_lookup(parent, &name); | 1086 | dentry = d_lookup(parent, &name); |
| 1148 | if (dentry != NULL) { | 1087 | if (dentry != NULL) { |
| @@ -1183,12 +1122,8 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc) | |||
| 1183 | dentry = alias; | 1122 | dentry = alias; |
| 1184 | } | 1123 | } |
| 1185 | 1124 | ||
| 1186 | nfs_renew_times(dentry); | ||
| 1187 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
| 1188 | return dentry; | ||
| 1189 | out_renew: | 1125 | out_renew: |
| 1190 | nfs_renew_times(dentry); | 1126 | nfs_set_verifier(dentry, verf); |
| 1191 | nfs_refresh_verifier(dentry, nfs_save_change_attribute(dir)); | ||
| 1192 | return dentry; | 1127 | return dentry; |
| 1193 | } | 1128 | } |
| 1194 | 1129 | ||
| @@ -1198,32 +1133,40 @@ out_renew: | |||
| 1198 | int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, | 1133 | int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, |
| 1199 | struct nfs_fattr *fattr) | 1134 | struct nfs_fattr *fattr) |
| 1200 | { | 1135 | { |
| 1136 | struct dentry *parent = dget_parent(dentry); | ||
| 1137 | struct inode *dir = parent->d_inode; | ||
| 1201 | struct inode *inode; | 1138 | struct inode *inode; |
| 1202 | int error = -EACCES; | 1139 | int error = -EACCES; |
| 1203 | 1140 | ||
| 1141 | d_drop(dentry); | ||
| 1142 | |||
| 1204 | /* We may have been initialized further down */ | 1143 | /* We may have been initialized further down */ |
| 1205 | if (dentry->d_inode) | 1144 | if (dentry->d_inode) |
| 1206 | return 0; | 1145 | goto out; |
| 1207 | if (fhandle->size == 0) { | 1146 | if (fhandle->size == 0) { |
| 1208 | struct inode *dir = dentry->d_parent->d_inode; | ||
| 1209 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); | 1147 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); |
| 1210 | if (error) | 1148 | if (error) |
| 1211 | return error; | 1149 | goto out_error; |
| 1212 | } | 1150 | } |
| 1151 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
| 1213 | if (!(fattr->valid & NFS_ATTR_FATTR)) { | 1152 | if (!(fattr->valid & NFS_ATTR_FATTR)) { |
| 1214 | struct nfs_server *server = NFS_SB(dentry->d_sb); | 1153 | struct nfs_server *server = NFS_SB(dentry->d_sb); |
| 1215 | error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr); | 1154 | error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr); |
| 1216 | if (error < 0) | 1155 | if (error < 0) |
| 1217 | return error; | 1156 | goto out_error; |
| 1218 | } | 1157 | } |
| 1219 | inode = nfs_fhget(dentry->d_sb, fhandle, fattr); | 1158 | inode = nfs_fhget(dentry->d_sb, fhandle, fattr); |
| 1220 | error = PTR_ERR(inode); | 1159 | error = PTR_ERR(inode); |
| 1221 | if (IS_ERR(inode)) | 1160 | if (IS_ERR(inode)) |
| 1222 | return error; | 1161 | goto out_error; |
| 1223 | d_instantiate(dentry, inode); | 1162 | d_add(dentry, inode); |
| 1224 | if (d_unhashed(dentry)) | 1163 | out: |
| 1225 | d_rehash(dentry); | 1164 | dput(parent); |
| 1226 | return 0; | 1165 | return 0; |
| 1166 | out_error: | ||
| 1167 | nfs_mark_for_revalidate(dir); | ||
| 1168 | dput(parent); | ||
| 1169 | return error; | ||
| 1227 | } | 1170 | } |
| 1228 | 1171 | ||
| 1229 | /* | 1172 | /* |
| @@ -1249,13 +1192,9 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
| 1249 | open_flags = nd->intent.open.flags; | 1192 | open_flags = nd->intent.open.flags; |
| 1250 | 1193 | ||
| 1251 | lock_kernel(); | 1194 | lock_kernel(); |
| 1252 | nfs_begin_data_update(dir); | ||
| 1253 | error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, nd); | 1195 | error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, nd); |
| 1254 | nfs_end_data_update(dir); | ||
| 1255 | if (error != 0) | 1196 | if (error != 0) |
| 1256 | goto out_err; | 1197 | goto out_err; |
| 1257 | nfs_renew_times(dentry); | ||
| 1258 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
| 1259 | unlock_kernel(); | 1198 | unlock_kernel(); |
| 1260 | return 0; | 1199 | return 0; |
| 1261 | out_err: | 1200 | out_err: |
| @@ -1283,13 +1222,9 @@ nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) | |||
| 1283 | attr.ia_valid = ATTR_MODE; | 1222 | attr.ia_valid = ATTR_MODE; |
| 1284 | 1223 | ||
| 1285 | lock_kernel(); | 1224 | lock_kernel(); |
| 1286 | nfs_begin_data_update(dir); | ||
| 1287 | status = NFS_PROTO(dir)->mknod(dir, dentry, &attr, rdev); | 1225 | status = NFS_PROTO(dir)->mknod(dir, dentry, &attr, rdev); |
| 1288 | nfs_end_data_update(dir); | ||
| 1289 | if (status != 0) | 1226 | if (status != 0) |
| 1290 | goto out_err; | 1227 | goto out_err; |
| 1291 | nfs_renew_times(dentry); | ||
| 1292 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
| 1293 | unlock_kernel(); | 1228 | unlock_kernel(); |
| 1294 | return 0; | 1229 | return 0; |
| 1295 | out_err: | 1230 | out_err: |
| @@ -1313,13 +1248,9 @@ static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 1313 | attr.ia_mode = mode | S_IFDIR; | 1248 | attr.ia_mode = mode | S_IFDIR; |
| 1314 | 1249 | ||
| 1315 | lock_kernel(); | 1250 | lock_kernel(); |
| 1316 | nfs_begin_data_update(dir); | ||
| 1317 | error = NFS_PROTO(dir)->mkdir(dir, dentry, &attr); | 1251 | error = NFS_PROTO(dir)->mkdir(dir, dentry, &attr); |
| 1318 | nfs_end_data_update(dir); | ||
| 1319 | if (error != 0) | 1252 | if (error != 0) |
| 1320 | goto out_err; | 1253 | goto out_err; |
| 1321 | nfs_renew_times(dentry); | ||
| 1322 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
| 1323 | unlock_kernel(); | 1254 | unlock_kernel(); |
| 1324 | return 0; | 1255 | return 0; |
| 1325 | out_err: | 1256 | out_err: |
| @@ -1336,12 +1267,10 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 1336 | dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); | 1267 | dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); |
| 1337 | 1268 | ||
| 1338 | lock_kernel(); | 1269 | lock_kernel(); |
| 1339 | nfs_begin_data_update(dir); | ||
| 1340 | error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name); | 1270 | error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name); |
| 1341 | /* Ensure the VFS deletes this inode */ | 1271 | /* Ensure the VFS deletes this inode */ |
| 1342 | if (error == 0 && dentry->d_inode != NULL) | 1272 | if (error == 0 && dentry->d_inode != NULL) |
| 1343 | clear_nlink(dentry->d_inode); | 1273 | clear_nlink(dentry->d_inode); |
| 1344 | nfs_end_data_update(dir); | ||
| 1345 | unlock_kernel(); | 1274 | unlock_kernel(); |
| 1346 | 1275 | ||
| 1347 | return error; | 1276 | return error; |
| @@ -1350,9 +1279,9 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 1350 | static int nfs_sillyrename(struct inode *dir, struct dentry *dentry) | 1279 | static int nfs_sillyrename(struct inode *dir, struct dentry *dentry) |
| 1351 | { | 1280 | { |
| 1352 | static unsigned int sillycounter; | 1281 | static unsigned int sillycounter; |
| 1353 | const int i_inosize = sizeof(dir->i_ino)*2; | 1282 | const int fileidsize = sizeof(NFS_FILEID(dentry->d_inode))*2; |
| 1354 | const int countersize = sizeof(sillycounter)*2; | 1283 | const int countersize = sizeof(sillycounter)*2; |
| 1355 | const int slen = sizeof(".nfs") + i_inosize + countersize - 1; | 1284 | const int slen = sizeof(".nfs")+fileidsize+countersize-1; |
| 1356 | char silly[slen+1]; | 1285 | char silly[slen+1]; |
| 1357 | struct qstr qsilly; | 1286 | struct qstr qsilly; |
| 1358 | struct dentry *sdentry; | 1287 | struct dentry *sdentry; |
| @@ -1370,8 +1299,9 @@ static int nfs_sillyrename(struct inode *dir, struct dentry *dentry) | |||
| 1370 | if (dentry->d_flags & DCACHE_NFSFS_RENAMED) | 1299 | if (dentry->d_flags & DCACHE_NFSFS_RENAMED) |
| 1371 | goto out; | 1300 | goto out; |
| 1372 | 1301 | ||
| 1373 | sprintf(silly, ".nfs%*.*lx", | 1302 | sprintf(silly, ".nfs%*.*Lx", |
| 1374 | i_inosize, i_inosize, dentry->d_inode->i_ino); | 1303 | fileidsize, fileidsize, |
| 1304 | (unsigned long long)NFS_FILEID(dentry->d_inode)); | ||
| 1375 | 1305 | ||
| 1376 | /* Return delegation in anticipation of the rename */ | 1306 | /* Return delegation in anticipation of the rename */ |
| 1377 | nfs_inode_return_delegation(dentry->d_inode); | 1307 | nfs_inode_return_delegation(dentry->d_inode); |
| @@ -1398,19 +1328,14 @@ static int nfs_sillyrename(struct inode *dir, struct dentry *dentry) | |||
| 1398 | 1328 | ||
| 1399 | qsilly.name = silly; | 1329 | qsilly.name = silly; |
| 1400 | qsilly.len = strlen(silly); | 1330 | qsilly.len = strlen(silly); |
| 1401 | nfs_begin_data_update(dir); | ||
| 1402 | if (dentry->d_inode) { | 1331 | if (dentry->d_inode) { |
| 1403 | nfs_begin_data_update(dentry->d_inode); | ||
| 1404 | error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, | 1332 | error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, |
| 1405 | dir, &qsilly); | 1333 | dir, &qsilly); |
| 1406 | nfs_mark_for_revalidate(dentry->d_inode); | 1334 | nfs_mark_for_revalidate(dentry->d_inode); |
| 1407 | nfs_end_data_update(dentry->d_inode); | ||
| 1408 | } else | 1335 | } else |
| 1409 | error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, | 1336 | error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, |
| 1410 | dir, &qsilly); | 1337 | dir, &qsilly); |
| 1411 | nfs_end_data_update(dir); | ||
| 1412 | if (!error) { | 1338 | if (!error) { |
| 1413 | nfs_renew_times(dentry); | ||
| 1414 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1339 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
| 1415 | d_move(dentry, sdentry); | 1340 | d_move(dentry, sdentry); |
| 1416 | error = nfs_async_unlink(dir, dentry); | 1341 | error = nfs_async_unlink(dir, dentry); |
| @@ -1443,19 +1368,15 @@ static int nfs_safe_remove(struct dentry *dentry) | |||
| 1443 | goto out; | 1368 | goto out; |
| 1444 | } | 1369 | } |
| 1445 | 1370 | ||
| 1446 | nfs_begin_data_update(dir); | ||
| 1447 | if (inode != NULL) { | 1371 | if (inode != NULL) { |
| 1448 | nfs_inode_return_delegation(inode); | 1372 | nfs_inode_return_delegation(inode); |
| 1449 | nfs_begin_data_update(inode); | ||
| 1450 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); | 1373 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); |
| 1451 | /* The VFS may want to delete this inode */ | 1374 | /* The VFS may want to delete this inode */ |
| 1452 | if (error == 0) | 1375 | if (error == 0) |
| 1453 | drop_nlink(inode); | 1376 | drop_nlink(inode); |
| 1454 | nfs_mark_for_revalidate(inode); | 1377 | nfs_mark_for_revalidate(inode); |
| 1455 | nfs_end_data_update(inode); | ||
| 1456 | } else | 1378 | } else |
| 1457 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); | 1379 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); |
| 1458 | nfs_end_data_update(dir); | ||
| 1459 | out: | 1380 | out: |
| 1460 | return error; | 1381 | return error; |
| 1461 | } | 1382 | } |
| @@ -1493,7 +1414,6 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry) | |||
| 1493 | spin_unlock(&dcache_lock); | 1414 | spin_unlock(&dcache_lock); |
| 1494 | error = nfs_safe_remove(dentry); | 1415 | error = nfs_safe_remove(dentry); |
| 1495 | if (!error) { | 1416 | if (!error) { |
| 1496 | nfs_renew_times(dentry); | ||
| 1497 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1417 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
| 1498 | } else if (need_rehash) | 1418 | } else if (need_rehash) |
| 1499 | d_rehash(dentry); | 1419 | d_rehash(dentry); |
| @@ -1548,9 +1468,7 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *sym | |||
| 1548 | memset(kaddr + pathlen, 0, PAGE_SIZE - pathlen); | 1468 | memset(kaddr + pathlen, 0, PAGE_SIZE - pathlen); |
| 1549 | kunmap_atomic(kaddr, KM_USER0); | 1469 | kunmap_atomic(kaddr, KM_USER0); |
| 1550 | 1470 | ||
| 1551 | nfs_begin_data_update(dir); | ||
| 1552 | error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr); | 1471 | error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr); |
| 1553 | nfs_end_data_update(dir); | ||
| 1554 | if (error != 0) { | 1472 | if (error != 0) { |
| 1555 | dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s) error %d\n", | 1473 | dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s) error %d\n", |
| 1556 | dir->i_sb->s_id, dir->i_ino, | 1474 | dir->i_sb->s_id, dir->i_ino, |
| @@ -1590,15 +1508,12 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) | |||
| 1590 | dentry->d_parent->d_name.name, dentry->d_name.name); | 1508 | dentry->d_parent->d_name.name, dentry->d_name.name); |
| 1591 | 1509 | ||
| 1592 | lock_kernel(); | 1510 | lock_kernel(); |
| 1593 | nfs_begin_data_update(dir); | 1511 | d_drop(dentry); |
| 1594 | nfs_begin_data_update(inode); | ||
| 1595 | error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name); | 1512 | error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name); |
| 1596 | if (error == 0) { | 1513 | if (error == 0) { |
| 1597 | atomic_inc(&inode->i_count); | 1514 | atomic_inc(&inode->i_count); |
| 1598 | d_instantiate(dentry, inode); | 1515 | d_add(dentry, inode); |
| 1599 | } | 1516 | } |
| 1600 | nfs_end_data_update(inode); | ||
| 1601 | nfs_end_data_update(dir); | ||
| 1602 | unlock_kernel(); | 1517 | unlock_kernel(); |
| 1603 | return error; | 1518 | return error; |
| 1604 | } | 1519 | } |
| @@ -1701,22 +1616,16 @@ go_ahead: | |||
| 1701 | d_delete(new_dentry); | 1616 | d_delete(new_dentry); |
| 1702 | } | 1617 | } |
| 1703 | 1618 | ||
| 1704 | nfs_begin_data_update(old_dir); | ||
| 1705 | nfs_begin_data_update(new_dir); | ||
| 1706 | nfs_begin_data_update(old_inode); | ||
| 1707 | error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name, | 1619 | error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name, |
| 1708 | new_dir, &new_dentry->d_name); | 1620 | new_dir, &new_dentry->d_name); |
| 1709 | nfs_mark_for_revalidate(old_inode); | 1621 | nfs_mark_for_revalidate(old_inode); |
| 1710 | nfs_end_data_update(old_inode); | ||
| 1711 | nfs_end_data_update(new_dir); | ||
| 1712 | nfs_end_data_update(old_dir); | ||
| 1713 | out: | 1622 | out: |
| 1714 | if (rehash) | 1623 | if (rehash) |
| 1715 | d_rehash(rehash); | 1624 | d_rehash(rehash); |
| 1716 | if (!error) { | 1625 | if (!error) { |
| 1717 | d_move(old_dentry, new_dentry); | 1626 | d_move(old_dentry, new_dentry); |
| 1718 | nfs_renew_times(new_dentry); | 1627 | nfs_set_verifier(new_dentry, |
| 1719 | nfs_refresh_verifier(new_dentry, nfs_save_change_attribute(new_dir)); | 1628 | nfs_save_change_attribute(new_dir)); |
| 1720 | } | 1629 | } |
| 1721 | 1630 | ||
| 1722 | /* new dentry created? */ | 1631 | /* new dentry created? */ |
| @@ -1842,7 +1751,7 @@ static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, st | |||
| 1842 | return NULL; | 1751 | return NULL; |
| 1843 | } | 1752 | } |
| 1844 | 1753 | ||
| 1845 | int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, struct nfs_access_entry *res) | 1754 | static int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, struct nfs_access_entry *res) |
| 1846 | { | 1755 | { |
| 1847 | struct nfs_inode *nfsi = NFS_I(inode); | 1756 | struct nfs_inode *nfsi = NFS_I(inode); |
| 1848 | struct nfs_access_entry *cache; | 1757 | struct nfs_access_entry *cache; |
| @@ -1854,7 +1763,7 @@ int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, struct nfs | |||
| 1854 | cache = nfs_access_search_rbtree(inode, cred); | 1763 | cache = nfs_access_search_rbtree(inode, cred); |
| 1855 | if (cache == NULL) | 1764 | if (cache == NULL) |
| 1856 | goto out; | 1765 | goto out; |
| 1857 | if (time_after(jiffies, cache->jiffies + NFS_ATTRTIMEO(inode))) | 1766 | if (!time_in_range(jiffies, cache->jiffies, cache->jiffies + nfsi->attrtimeo)) |
| 1858 | goto out_stale; | 1767 | goto out_stale; |
| 1859 | res->jiffies = cache->jiffies; | 1768 | res->jiffies = cache->jiffies; |
| 1860 | res->cred = cache->cred; | 1769 | res->cred = cache->cred; |
| @@ -1909,7 +1818,7 @@ found: | |||
| 1909 | nfs_access_free_entry(entry); | 1818 | nfs_access_free_entry(entry); |
| 1910 | } | 1819 | } |
| 1911 | 1820 | ||
| 1912 | void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set) | 1821 | static void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set) |
| 1913 | { | 1822 | { |
| 1914 | struct nfs_access_entry *cache = kmalloc(sizeof(*cache), GFP_KERNEL); | 1823 | struct nfs_access_entry *cache = kmalloc(sizeof(*cache), GFP_KERNEL); |
| 1915 | if (cache == NULL) | 1824 | if (cache == NULL) |
| @@ -1957,6 +1866,24 @@ out: | |||
| 1957 | return -EACCES; | 1866 | return -EACCES; |
| 1958 | } | 1867 | } |
| 1959 | 1868 | ||
| 1869 | static int nfs_open_permission_mask(int openflags) | ||
| 1870 | { | ||
| 1871 | int mask = 0; | ||
| 1872 | |||
| 1873 | if (openflags & FMODE_READ) | ||
| 1874 | mask |= MAY_READ; | ||
| 1875 | if (openflags & FMODE_WRITE) | ||
| 1876 | mask |= MAY_WRITE; | ||
| 1877 | if (openflags & FMODE_EXEC) | ||
| 1878 | mask |= MAY_EXEC; | ||
| 1879 | return mask; | ||
| 1880 | } | ||
| 1881 | |||
| 1882 | int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags) | ||
| 1883 | { | ||
| 1884 | return nfs_do_access(inode, cred, nfs_open_permission_mask(openflags)); | ||
| 1885 | } | ||
| 1886 | |||
| 1960 | int nfs_permission(struct inode *inode, int mask, struct nameidata *nd) | 1887 | int nfs_permission(struct inode *inode, int mask, struct nameidata *nd) |
| 1961 | { | 1888 | { |
| 1962 | struct rpc_cred *cred; | 1889 | struct rpc_cred *cred; |
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index fcf4d384610e..32fe97211eea 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
| @@ -368,7 +368,7 @@ static ssize_t nfs_direct_read(struct kiocb *iocb, unsigned long user_addr, size | |||
| 368 | return -ENOMEM; | 368 | return -ENOMEM; |
| 369 | 369 | ||
| 370 | dreq->inode = inode; | 370 | dreq->inode = inode; |
| 371 | dreq->ctx = get_nfs_open_context((struct nfs_open_context *)iocb->ki_filp->private_data); | 371 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); |
| 372 | if (!is_sync_kiocb(iocb)) | 372 | if (!is_sync_kiocb(iocb)) |
| 373 | dreq->iocb = iocb; | 373 | dreq->iocb = iocb; |
| 374 | 374 | ||
| @@ -510,7 +510,6 @@ static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode | |||
| 510 | nfs_direct_write_reschedule(dreq); | 510 | nfs_direct_write_reschedule(dreq); |
| 511 | break; | 511 | break; |
| 512 | default: | 512 | default: |
| 513 | nfs_end_data_update(inode); | ||
| 514 | if (dreq->commit_data != NULL) | 513 | if (dreq->commit_data != NULL) |
| 515 | nfs_commit_free(dreq->commit_data); | 514 | nfs_commit_free(dreq->commit_data); |
| 516 | nfs_direct_free_writedata(dreq); | 515 | nfs_direct_free_writedata(dreq); |
| @@ -533,7 +532,6 @@ static inline void nfs_alloc_commit_data(struct nfs_direct_req *dreq) | |||
| 533 | 532 | ||
| 534 | static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode *inode) | 533 | static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode *inode) |
| 535 | { | 534 | { |
| 536 | nfs_end_data_update(inode); | ||
| 537 | nfs_direct_free_writedata(dreq); | 535 | nfs_direct_free_writedata(dreq); |
| 538 | nfs_zap_mapping(inode, inode->i_mapping); | 536 | nfs_zap_mapping(inode, inode->i_mapping); |
| 539 | nfs_direct_complete(dreq); | 537 | nfs_direct_complete(dreq); |
| @@ -718,14 +716,12 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, siz | |||
| 718 | sync = FLUSH_STABLE; | 716 | sync = FLUSH_STABLE; |
| 719 | 717 | ||
| 720 | dreq->inode = inode; | 718 | dreq->inode = inode; |
| 721 | dreq->ctx = get_nfs_open_context((struct nfs_open_context *)iocb->ki_filp->private_data); | 719 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); |
| 722 | if (!is_sync_kiocb(iocb)) | 720 | if (!is_sync_kiocb(iocb)) |
| 723 | dreq->iocb = iocb; | 721 | dreq->iocb = iocb; |
| 724 | 722 | ||
| 725 | nfs_add_stats(inode, NFSIOS_DIRECTWRITTENBYTES, count); | 723 | nfs_add_stats(inode, NFSIOS_DIRECTWRITTENBYTES, count); |
| 726 | 724 | ||
| 727 | nfs_begin_data_update(inode); | ||
| 728 | |||
| 729 | rpc_clnt_sigmask(clnt, &oldset); | 725 | rpc_clnt_sigmask(clnt, &oldset); |
| 730 | result = nfs_direct_write_schedule(dreq, user_addr, count, pos, sync); | 726 | result = nfs_direct_write_schedule(dreq, user_addr, count, pos, sync); |
| 731 | if (!result) | 727 | if (!result) |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 579cf8a7d4a7..c664bb921425 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <asm/system.h> | 33 | #include <asm/system.h> |
| 34 | 34 | ||
| 35 | #include "delegation.h" | 35 | #include "delegation.h" |
| 36 | #include "internal.h" | ||
| 36 | #include "iostat.h" | 37 | #include "iostat.h" |
| 37 | 38 | ||
| 38 | #define NFSDBG_FACILITY NFSDBG_FILE | 39 | #define NFSDBG_FACILITY NFSDBG_FILE |
| @@ -55,6 +56,8 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl); | |||
| 55 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl); | 56 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl); |
| 56 | static int nfs_setlease(struct file *file, long arg, struct file_lock **fl); | 57 | static int nfs_setlease(struct file *file, long arg, struct file_lock **fl); |
| 57 | 58 | ||
| 59 | static struct vm_operations_struct nfs_file_vm_ops; | ||
| 60 | |||
| 58 | const struct file_operations nfs_file_operations = { | 61 | const struct file_operations nfs_file_operations = { |
| 59 | .llseek = nfs_file_llseek, | 62 | .llseek = nfs_file_llseek, |
| 60 | .read = do_sync_read, | 63 | .read = do_sync_read, |
| @@ -174,13 +177,38 @@ static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) | |||
| 174 | } | 177 | } |
| 175 | 178 | ||
| 176 | /* | 179 | /* |
| 180 | * Helper for nfs_file_flush() and nfs_fsync() | ||
| 181 | * | ||
| 182 | * Notice that it clears the NFS_CONTEXT_ERROR_WRITE before synching to | ||
| 183 | * disk, but it retrieves and clears ctx->error after synching, despite | ||
| 184 | * the two being set at the same time in nfs_context_set_write_error(). | ||
| 185 | * This is because the former is used to notify the _next_ call to | ||
| 186 | * nfs_file_write() that a write error occured, and hence cause it to | ||
| 187 | * fall back to doing a synchronous write. | ||
| 188 | */ | ||
| 189 | static int nfs_do_fsync(struct nfs_open_context *ctx, struct inode *inode) | ||
| 190 | { | ||
| 191 | int have_error, status; | ||
| 192 | int ret = 0; | ||
| 193 | |||
| 194 | have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); | ||
| 195 | status = nfs_wb_all(inode); | ||
| 196 | have_error |= test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); | ||
| 197 | if (have_error) | ||
| 198 | ret = xchg(&ctx->error, 0); | ||
| 199 | if (!ret) | ||
| 200 | ret = status; | ||
| 201 | return ret; | ||
| 202 | } | ||
| 203 | |||
| 204 | /* | ||
| 177 | * Flush all dirty pages, and check for write errors. | 205 | * Flush all dirty pages, and check for write errors. |
| 178 | * | 206 | * |
| 179 | */ | 207 | */ |
| 180 | static int | 208 | static int |
| 181 | nfs_file_flush(struct file *file, fl_owner_t id) | 209 | nfs_file_flush(struct file *file, fl_owner_t id) |
| 182 | { | 210 | { |
| 183 | struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data; | 211 | struct nfs_open_context *ctx = nfs_file_open_context(file); |
| 184 | struct inode *inode = file->f_path.dentry->d_inode; | 212 | struct inode *inode = file->f_path.dentry->d_inode; |
| 185 | int status; | 213 | int status; |
| 186 | 214 | ||
| @@ -189,16 +217,11 @@ nfs_file_flush(struct file *file, fl_owner_t id) | |||
| 189 | if ((file->f_mode & FMODE_WRITE) == 0) | 217 | if ((file->f_mode & FMODE_WRITE) == 0) |
| 190 | return 0; | 218 | return 0; |
| 191 | nfs_inc_stats(inode, NFSIOS_VFSFLUSH); | 219 | nfs_inc_stats(inode, NFSIOS_VFSFLUSH); |
| 192 | lock_kernel(); | 220 | |
| 193 | /* Ensure that data+attribute caches are up to date after close() */ | 221 | /* Ensure that data+attribute caches are up to date after close() */ |
| 194 | status = nfs_wb_all(inode); | 222 | status = nfs_do_fsync(ctx, inode); |
| 195 | if (!status) { | 223 | if (!status) |
| 196 | status = ctx->error; | 224 | nfs_revalidate_inode(NFS_SERVER(inode), inode); |
| 197 | ctx->error = 0; | ||
| 198 | if (!status) | ||
| 199 | nfs_revalidate_inode(NFS_SERVER(inode), inode); | ||
| 200 | } | ||
| 201 | unlock_kernel(); | ||
| 202 | return status; | 225 | return status; |
| 203 | } | 226 | } |
| 204 | 227 | ||
| @@ -257,8 +280,11 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma) | |||
| 257 | dentry->d_parent->d_name.name, dentry->d_name.name); | 280 | dentry->d_parent->d_name.name, dentry->d_name.name); |
| 258 | 281 | ||
| 259 | status = nfs_revalidate_mapping(inode, file->f_mapping); | 282 | status = nfs_revalidate_mapping(inode, file->f_mapping); |
| 260 | if (!status) | 283 | if (!status) { |
| 261 | status = generic_file_mmap(file, vma); | 284 | vma->vm_ops = &nfs_file_vm_ops; |
| 285 | vma->vm_flags |= VM_CAN_NONLINEAR; | ||
| 286 | file_accessed(file); | ||
| 287 | } | ||
| 262 | return status; | 288 | return status; |
| 263 | } | 289 | } |
| 264 | 290 | ||
| @@ -270,21 +296,13 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma) | |||
| 270 | static int | 296 | static int |
| 271 | nfs_fsync(struct file *file, struct dentry *dentry, int datasync) | 297 | nfs_fsync(struct file *file, struct dentry *dentry, int datasync) |
| 272 | { | 298 | { |
| 273 | struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data; | 299 | struct nfs_open_context *ctx = nfs_file_open_context(file); |
| 274 | struct inode *inode = dentry->d_inode; | 300 | struct inode *inode = dentry->d_inode; |
| 275 | int status; | ||
| 276 | 301 | ||
| 277 | dfprintk(VFS, "nfs: fsync(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino); | 302 | dfprintk(VFS, "nfs: fsync(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino); |
| 278 | 303 | ||
| 279 | nfs_inc_stats(inode, NFSIOS_VFSFSYNC); | 304 | nfs_inc_stats(inode, NFSIOS_VFSFSYNC); |
| 280 | lock_kernel(); | 305 | return nfs_do_fsync(ctx, inode); |
| 281 | status = nfs_wb_all(inode); | ||
| 282 | if (!status) { | ||
| 283 | status = ctx->error; | ||
| 284 | ctx->error = 0; | ||
| 285 | } | ||
| 286 | unlock_kernel(); | ||
| 287 | return status; | ||
| 288 | } | 306 | } |
| 289 | 307 | ||
| 290 | /* | 308 | /* |
| @@ -333,7 +351,7 @@ static int nfs_launder_page(struct page *page) | |||
| 333 | const struct address_space_operations nfs_file_aops = { | 351 | const struct address_space_operations nfs_file_aops = { |
| 334 | .readpage = nfs_readpage, | 352 | .readpage = nfs_readpage, |
| 335 | .readpages = nfs_readpages, | 353 | .readpages = nfs_readpages, |
| 336 | .set_page_dirty = nfs_set_page_dirty, | 354 | .set_page_dirty = __set_page_dirty_nobuffers, |
| 337 | .writepage = nfs_writepage, | 355 | .writepage = nfs_writepage, |
| 338 | .writepages = nfs_writepages, | 356 | .writepages = nfs_writepages, |
| 339 | .prepare_write = nfs_prepare_write, | 357 | .prepare_write = nfs_prepare_write, |
| @@ -346,6 +364,43 @@ const struct address_space_operations nfs_file_aops = { | |||
| 346 | .launder_page = nfs_launder_page, | 364 | .launder_page = nfs_launder_page, |
| 347 | }; | 365 | }; |
| 348 | 366 | ||
| 367 | static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct page *page) | ||
| 368 | { | ||
| 369 | struct file *filp = vma->vm_file; | ||
| 370 | unsigned pagelen; | ||
| 371 | int ret = -EINVAL; | ||
| 372 | |||
| 373 | lock_page(page); | ||
| 374 | if (page->mapping != vma->vm_file->f_path.dentry->d_inode->i_mapping) | ||
| 375 | goto out_unlock; | ||
| 376 | pagelen = nfs_page_length(page); | ||
| 377 | if (pagelen == 0) | ||
| 378 | goto out_unlock; | ||
| 379 | ret = nfs_prepare_write(filp, page, 0, pagelen); | ||
| 380 | if (!ret) | ||
| 381 | ret = nfs_commit_write(filp, page, 0, pagelen); | ||
| 382 | out_unlock: | ||
| 383 | unlock_page(page); | ||
| 384 | return ret; | ||
| 385 | } | ||
| 386 | |||
| 387 | static struct vm_operations_struct nfs_file_vm_ops = { | ||
| 388 | .fault = filemap_fault, | ||
| 389 | .page_mkwrite = nfs_vm_page_mkwrite, | ||
| 390 | }; | ||
| 391 | |||
| 392 | static int nfs_need_sync_write(struct file *filp, struct inode *inode) | ||
| 393 | { | ||
| 394 | struct nfs_open_context *ctx; | ||
| 395 | |||
| 396 | if (IS_SYNC(inode) || (filp->f_flags & O_SYNC)) | ||
| 397 | return 1; | ||
| 398 | ctx = nfs_file_open_context(filp); | ||
| 399 | if (test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags)) | ||
| 400 | return 1; | ||
| 401 | return 0; | ||
| 402 | } | ||
| 403 | |||
| 349 | static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, | 404 | static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, |
| 350 | unsigned long nr_segs, loff_t pos) | 405 | unsigned long nr_segs, loff_t pos) |
| 351 | { | 406 | { |
| @@ -382,8 +437,8 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, | |||
| 382 | nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count); | 437 | nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count); |
| 383 | result = generic_file_aio_write(iocb, iov, nr_segs, pos); | 438 | result = generic_file_aio_write(iocb, iov, nr_segs, pos); |
| 384 | /* Return error values for O_SYNC and IS_SYNC() */ | 439 | /* Return error values for O_SYNC and IS_SYNC() */ |
| 385 | if (result >= 0 && (IS_SYNC(inode) || (iocb->ki_filp->f_flags & O_SYNC))) { | 440 | if (result >= 0 && nfs_need_sync_write(iocb->ki_filp, inode)) { |
| 386 | int err = nfs_fsync(iocb->ki_filp, dentry, 1); | 441 | int err = nfs_do_fsync(nfs_file_open_context(iocb->ki_filp), inode); |
| 387 | if (err < 0) | 442 | if (err < 0) |
| 388 | result = err; | 443 | result = err; |
| 389 | } | 444 | } |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 71a49c3acabd..035c769b715e 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
| @@ -49,6 +49,11 @@ | |||
| 49 | 49 | ||
| 50 | #define NFSDBG_FACILITY NFSDBG_VFS | 50 | #define NFSDBG_FACILITY NFSDBG_VFS |
| 51 | 51 | ||
| 52 | #define NFS_64_BIT_INODE_NUMBERS_ENABLED 1 | ||
| 53 | |||
| 54 | /* Default is to see 64-bit inode numbers */ | ||
| 55 | static int enable_ino64 = NFS_64_BIT_INODE_NUMBERS_ENABLED; | ||
| 56 | |||
| 52 | static void nfs_invalidate_inode(struct inode *); | 57 | static void nfs_invalidate_inode(struct inode *); |
| 53 | static int nfs_update_inode(struct inode *, struct nfs_fattr *); | 58 | static int nfs_update_inode(struct inode *, struct nfs_fattr *); |
| 54 | 59 | ||
| @@ -62,6 +67,25 @@ nfs_fattr_to_ino_t(struct nfs_fattr *fattr) | |||
| 62 | return nfs_fileid_to_ino_t(fattr->fileid); | 67 | return nfs_fileid_to_ino_t(fattr->fileid); |
| 63 | } | 68 | } |
| 64 | 69 | ||
| 70 | /** | ||
| 71 | * nfs_compat_user_ino64 - returns the user-visible inode number | ||
| 72 | * @fileid: 64-bit fileid | ||
| 73 | * | ||
| 74 | * This function returns a 32-bit inode number if the boot parameter | ||
| 75 | * nfs.enable_ino64 is zero. | ||
| 76 | */ | ||
| 77 | u64 nfs_compat_user_ino64(u64 fileid) | ||
| 78 | { | ||
| 79 | int ino; | ||
| 80 | |||
| 81 | if (enable_ino64) | ||
| 82 | return fileid; | ||
| 83 | ino = fileid; | ||
| 84 | if (sizeof(ino) < sizeof(fileid)) | ||
| 85 | ino ^= fileid >> (sizeof(fileid)-sizeof(ino)) * 8; | ||
| 86 | return ino; | ||
| 87 | } | ||
| 88 | |||
| 65 | int nfs_write_inode(struct inode *inode, int sync) | 89 | int nfs_write_inode(struct inode *inode, int sync) |
| 66 | { | 90 | { |
| 67 | int ret; | 91 | int ret; |
| @@ -85,7 +109,6 @@ void nfs_clear_inode(struct inode *inode) | |||
| 85 | */ | 109 | */ |
| 86 | BUG_ON(nfs_have_writebacks(inode)); | 110 | BUG_ON(nfs_have_writebacks(inode)); |
| 87 | BUG_ON(!list_empty(&NFS_I(inode)->open_files)); | 111 | BUG_ON(!list_empty(&NFS_I(inode)->open_files)); |
| 88 | BUG_ON(atomic_read(&NFS_I(inode)->data_updates) != 0); | ||
| 89 | nfs_zap_acl_cache(inode); | 112 | nfs_zap_acl_cache(inode); |
| 90 | nfs_access_zap_cache(inode); | 113 | nfs_access_zap_cache(inode); |
| 91 | } | 114 | } |
| @@ -118,8 +141,8 @@ static void nfs_zap_caches_locked(struct inode *inode) | |||
| 118 | 141 | ||
| 119 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); | 142 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); |
| 120 | 143 | ||
| 121 | NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode); | 144 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
| 122 | NFS_ATTRTIMEO_UPDATE(inode) = jiffies; | 145 | nfsi->attrtimeo_timestamp = jiffies; |
| 123 | 146 | ||
| 124 | memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode))); | 147 | memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode))); |
| 125 | if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) | 148 | if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) |
| @@ -156,6 +179,13 @@ static void nfs_zap_acl_cache(struct inode *inode) | |||
| 156 | spin_unlock(&inode->i_lock); | 179 | spin_unlock(&inode->i_lock); |
| 157 | } | 180 | } |
| 158 | 181 | ||
| 182 | void nfs_invalidate_atime(struct inode *inode) | ||
| 183 | { | ||
| 184 | spin_lock(&inode->i_lock); | ||
| 185 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME; | ||
| 186 | spin_unlock(&inode->i_lock); | ||
| 187 | } | ||
| 188 | |||
| 159 | /* | 189 | /* |
| 160 | * Invalidate, but do not unhash, the inode. | 190 | * Invalidate, but do not unhash, the inode. |
| 161 | * NB: must be called with inode->i_lock held! | 191 | * NB: must be called with inode->i_lock held! |
| @@ -338,7 +368,6 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 338 | return 0; | 368 | return 0; |
| 339 | 369 | ||
| 340 | lock_kernel(); | 370 | lock_kernel(); |
| 341 | nfs_begin_data_update(inode); | ||
| 342 | /* Write all dirty data */ | 371 | /* Write all dirty data */ |
| 343 | if (S_ISREG(inode->i_mode)) { | 372 | if (S_ISREG(inode->i_mode)) { |
| 344 | filemap_write_and_wait(inode->i_mapping); | 373 | filemap_write_and_wait(inode->i_mapping); |
| @@ -352,7 +381,6 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 352 | error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr); | 381 | error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr); |
| 353 | if (error == 0) | 382 | if (error == 0) |
| 354 | nfs_refresh_inode(inode, &fattr); | 383 | nfs_refresh_inode(inode, &fattr); |
| 355 | nfs_end_data_update(inode); | ||
| 356 | unlock_kernel(); | 384 | unlock_kernel(); |
| 357 | return error; | 385 | return error; |
| 358 | } | 386 | } |
| @@ -431,7 +459,7 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
| 431 | 459 | ||
| 432 | /* Flush out writes to the server in order to update c/mtime */ | 460 | /* Flush out writes to the server in order to update c/mtime */ |
| 433 | if (S_ISREG(inode->i_mode)) | 461 | if (S_ISREG(inode->i_mode)) |
| 434 | nfs_sync_mapping_range(inode->i_mapping, 0, 0, FLUSH_NOCOMMIT); | 462 | nfs_wb_nocommit(inode); |
| 435 | 463 | ||
| 436 | /* | 464 | /* |
| 437 | * We may force a getattr if the user cares about atime. | 465 | * We may force a getattr if the user cares about atime. |
| @@ -450,8 +478,10 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
| 450 | err = __nfs_revalidate_inode(NFS_SERVER(inode), inode); | 478 | err = __nfs_revalidate_inode(NFS_SERVER(inode), inode); |
| 451 | else | 479 | else |
| 452 | err = nfs_revalidate_inode(NFS_SERVER(inode), inode); | 480 | err = nfs_revalidate_inode(NFS_SERVER(inode), inode); |
| 453 | if (!err) | 481 | if (!err) { |
| 454 | generic_fillattr(inode, stat); | 482 | generic_fillattr(inode, stat); |
| 483 | stat->ino = nfs_compat_user_ino64(NFS_FILEID(inode)); | ||
| 484 | } | ||
| 455 | return err; | 485 | return err; |
| 456 | } | 486 | } |
| 457 | 487 | ||
| @@ -536,7 +566,7 @@ struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_c | |||
| 536 | static void nfs_file_clear_open_context(struct file *filp) | 566 | static void nfs_file_clear_open_context(struct file *filp) |
| 537 | { | 567 | { |
| 538 | struct inode *inode = filp->f_path.dentry->d_inode; | 568 | struct inode *inode = filp->f_path.dentry->d_inode; |
| 539 | struct nfs_open_context *ctx = (struct nfs_open_context *)filp->private_data; | 569 | struct nfs_open_context *ctx = nfs_file_open_context(filp); |
| 540 | 570 | ||
| 541 | if (ctx) { | 571 | if (ctx) { |
| 542 | filp->private_data = NULL; | 572 | filp->private_data = NULL; |
| @@ -598,16 +628,10 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
| 598 | status = nfs_wait_on_inode(inode); | 628 | status = nfs_wait_on_inode(inode); |
| 599 | if (status < 0) | 629 | if (status < 0) |
| 600 | goto out; | 630 | goto out; |
| 601 | if (NFS_STALE(inode)) { | 631 | |
| 602 | status = -ESTALE; | 632 | status = -ESTALE; |
| 603 | /* Do we trust the cached ESTALE? */ | 633 | if (NFS_STALE(inode)) |
| 604 | if (NFS_ATTRTIMEO(inode) != 0) { | 634 | goto out; |
| 605 | if (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME)) { | ||
| 606 | /* no */ | ||
| 607 | } else | ||
| 608 | goto out; | ||
| 609 | } | ||
| 610 | } | ||
| 611 | 635 | ||
| 612 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); | 636 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); |
| 613 | if (status != 0) { | 637 | if (status != 0) { |
| @@ -654,7 +678,7 @@ int nfs_attribute_timeout(struct inode *inode) | |||
| 654 | 678 | ||
| 655 | if (nfs_have_delegation(inode, FMODE_READ)) | 679 | if (nfs_have_delegation(inode, FMODE_READ)) |
| 656 | return 0; | 680 | return 0; |
| 657 | return time_after(jiffies, nfsi->read_cache_jiffies+nfsi->attrtimeo); | 681 | return !time_in_range(jiffies, nfsi->read_cache_jiffies, nfsi->read_cache_jiffies + nfsi->attrtimeo); |
| 658 | } | 682 | } |
| 659 | 683 | ||
| 660 | /** | 684 | /** |
| @@ -683,11 +707,8 @@ static int nfs_invalidate_mapping_nolock(struct inode *inode, struct address_spa | |||
| 683 | } | 707 | } |
| 684 | spin_lock(&inode->i_lock); | 708 | spin_lock(&inode->i_lock); |
| 685 | nfsi->cache_validity &= ~NFS_INO_INVALID_DATA; | 709 | nfsi->cache_validity &= ~NFS_INO_INVALID_DATA; |
| 686 | if (S_ISDIR(inode->i_mode)) { | 710 | if (S_ISDIR(inode->i_mode)) |
| 687 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); | 711 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); |
| 688 | /* This ensures we revalidate child dentries */ | ||
| 689 | nfsi->cache_change_attribute = jiffies; | ||
| 690 | } | ||
| 691 | spin_unlock(&inode->i_lock); | 712 | spin_unlock(&inode->i_lock); |
| 692 | nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE); | 713 | nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE); |
| 693 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n", | 714 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n", |
| @@ -756,56 +777,27 @@ out: | |||
| 756 | return ret; | 777 | return ret; |
| 757 | } | 778 | } |
| 758 | 779 | ||
| 759 | /** | ||
| 760 | * nfs_begin_data_update | ||
| 761 | * @inode - pointer to inode | ||
| 762 | * Declare that a set of operations will update file data on the server | ||
| 763 | */ | ||
| 764 | void nfs_begin_data_update(struct inode *inode) | ||
| 765 | { | ||
| 766 | atomic_inc(&NFS_I(inode)->data_updates); | ||
| 767 | } | ||
| 768 | |||
| 769 | /** | ||
| 770 | * nfs_end_data_update | ||
| 771 | * @inode - pointer to inode | ||
| 772 | * Declare end of the operations that will update file data | ||
| 773 | * This will mark the inode as immediately needing revalidation | ||
| 774 | * of its attribute cache. | ||
| 775 | */ | ||
| 776 | void nfs_end_data_update(struct inode *inode) | ||
| 777 | { | ||
| 778 | struct nfs_inode *nfsi = NFS_I(inode); | ||
| 779 | |||
| 780 | /* Directories: invalidate page cache */ | ||
| 781 | if (S_ISDIR(inode->i_mode)) { | ||
| 782 | spin_lock(&inode->i_lock); | ||
| 783 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | ||
| 784 | spin_unlock(&inode->i_lock); | ||
| 785 | } | ||
| 786 | nfsi->cache_change_attribute = jiffies; | ||
| 787 | atomic_dec(&nfsi->data_updates); | ||
| 788 | } | ||
| 789 | |||
| 790 | static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) | 780 | static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) |
| 791 | { | 781 | { |
| 792 | struct nfs_inode *nfsi = NFS_I(inode); | 782 | struct nfs_inode *nfsi = NFS_I(inode); |
| 793 | unsigned long now = jiffies; | ||
| 794 | 783 | ||
| 784 | if ((fattr->valid & NFS_ATTR_WCC_V4) != 0 && | ||
| 785 | nfsi->change_attr == fattr->pre_change_attr) { | ||
| 786 | nfsi->change_attr = fattr->change_attr; | ||
| 787 | if (S_ISDIR(inode->i_mode)) | ||
| 788 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | ||
| 789 | } | ||
| 795 | /* If we have atomic WCC data, we may update some attributes */ | 790 | /* If we have atomic WCC data, we may update some attributes */ |
| 796 | if ((fattr->valid & NFS_ATTR_WCC) != 0) { | 791 | if ((fattr->valid & NFS_ATTR_WCC) != 0) { |
| 797 | if (timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) { | 792 | if (timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) |
| 798 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | 793 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); |
| 799 | nfsi->cache_change_attribute = now; | ||
| 800 | } | ||
| 801 | if (timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) { | 794 | if (timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) { |
| 802 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | 795 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); |
| 803 | nfsi->cache_change_attribute = now; | 796 | if (S_ISDIR(inode->i_mode)) |
| 797 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | ||
| 804 | } | 798 | } |
| 805 | if (inode->i_size == fattr->pre_size && nfsi->npages == 0) { | 799 | if (inode->i_size == fattr->pre_size && nfsi->npages == 0) |
| 806 | inode->i_size = fattr->size; | 800 | inode->i_size = fattr->size; |
| 807 | nfsi->cache_change_attribute = now; | ||
| 808 | } | ||
| 809 | } | 801 | } |
| 810 | } | 802 | } |
| 811 | 803 | ||
| @@ -822,7 +814,7 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat | |||
| 822 | { | 814 | { |
| 823 | struct nfs_inode *nfsi = NFS_I(inode); | 815 | struct nfs_inode *nfsi = NFS_I(inode); |
| 824 | loff_t cur_size, new_isize; | 816 | loff_t cur_size, new_isize; |
| 825 | int data_unstable; | 817 | unsigned long invalid = 0; |
| 826 | 818 | ||
| 827 | 819 | ||
| 828 | /* Has the inode gone and changed behind our back? */ | 820 | /* Has the inode gone and changed behind our back? */ |
| @@ -831,37 +823,41 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat | |||
| 831 | return -EIO; | 823 | return -EIO; |
| 832 | } | 824 | } |
| 833 | 825 | ||
| 834 | /* Are we in the process of updating data on the server? */ | ||
| 835 | data_unstable = nfs_caches_unstable(inode); | ||
| 836 | |||
| 837 | /* Do atomic weak cache consistency updates */ | 826 | /* Do atomic weak cache consistency updates */ |
| 838 | nfs_wcc_update_inode(inode, fattr); | 827 | nfs_wcc_update_inode(inode, fattr); |
| 839 | 828 | ||
| 840 | if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && | 829 | if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && |
| 841 | nfsi->change_attr != fattr->change_attr) | 830 | nfsi->change_attr != fattr->change_attr) |
| 842 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 831 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; |
| 843 | 832 | ||
| 844 | /* Verify a few of the more important attributes */ | 833 | /* Verify a few of the more important attributes */ |
| 845 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) | 834 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) |
| 846 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 835 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; |
| 847 | 836 | ||
| 848 | cur_size = i_size_read(inode); | 837 | cur_size = i_size_read(inode); |
| 849 | new_isize = nfs_size_to_loff_t(fattr->size); | 838 | new_isize = nfs_size_to_loff_t(fattr->size); |
| 850 | if (cur_size != new_isize && nfsi->npages == 0) | 839 | if (cur_size != new_isize && nfsi->npages == 0) |
| 851 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 840 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; |
| 852 | 841 | ||
| 853 | /* Have any file permissions changed? */ | 842 | /* Have any file permissions changed? */ |
| 854 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) | 843 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) |
| 855 | || inode->i_uid != fattr->uid | 844 | || inode->i_uid != fattr->uid |
| 856 | || inode->i_gid != fattr->gid) | 845 | || inode->i_gid != fattr->gid) |
| 857 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; | 846 | invalid |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; |
| 858 | 847 | ||
| 859 | /* Has the link count changed? */ | 848 | /* Has the link count changed? */ |
| 860 | if (inode->i_nlink != fattr->nlink) | 849 | if (inode->i_nlink != fattr->nlink) |
| 861 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; | 850 | invalid |= NFS_INO_INVALID_ATTR; |
| 862 | 851 | ||
| 863 | if (!timespec_equal(&inode->i_atime, &fattr->atime)) | 852 | if (!timespec_equal(&inode->i_atime, &fattr->atime)) |
| 864 | nfsi->cache_validity |= NFS_INO_INVALID_ATIME; | 853 | invalid |= NFS_INO_INVALID_ATIME; |
| 854 | |||
| 855 | if (invalid != 0) | ||
| 856 | nfsi->cache_validity |= invalid; | ||
| 857 | else | ||
| 858 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR | ||
| 859 | | NFS_INO_INVALID_ATIME | ||
| 860 | | NFS_INO_REVAL_PAGECACHE); | ||
| 865 | 861 | ||
| 866 | nfsi->read_cache_jiffies = fattr->time_start; | 862 | nfsi->read_cache_jiffies = fattr->time_start; |
| 867 | return 0; | 863 | return 0; |
| @@ -911,17 +907,41 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
| 911 | int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) | 907 | int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) |
| 912 | { | 908 | { |
| 913 | struct nfs_inode *nfsi = NFS_I(inode); | 909 | struct nfs_inode *nfsi = NFS_I(inode); |
| 914 | int status = 0; | ||
| 915 | 910 | ||
| 916 | spin_lock(&inode->i_lock); | 911 | spin_lock(&inode->i_lock); |
| 917 | if (unlikely((fattr->valid & NFS_ATTR_FATTR) == 0)) { | 912 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; |
| 918 | nfsi->cache_validity |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 913 | if (S_ISDIR(inode->i_mode)) |
| 919 | goto out; | 914 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; |
| 920 | } | ||
| 921 | status = nfs_update_inode(inode, fattr); | ||
| 922 | out: | ||
| 923 | spin_unlock(&inode->i_lock); | 915 | spin_unlock(&inode->i_lock); |
| 924 | return status; | 916 | return nfs_refresh_inode(inode, fattr); |
| 917 | } | ||
| 918 | |||
| 919 | /** | ||
| 920 | * nfs_post_op_update_inode_force_wcc - try to update the inode attribute cache | ||
| 921 | * @inode - pointer to inode | ||
| 922 | * @fattr - updated attributes | ||
| 923 | * | ||
| 924 | * After an operation that has changed the inode metadata, mark the | ||
| 925 | * attribute cache as being invalid, then try to update it. Fake up | ||
| 926 | * weak cache consistency data, if none exist. | ||
| 927 | * | ||
| 928 | * This function is mainly designed to be used by the ->write_done() functions. | ||
| 929 | */ | ||
| 930 | int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr) | ||
| 931 | { | ||
| 932 | if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && | ||
| 933 | (fattr->valid & NFS_ATTR_WCC_V4) == 0) { | ||
| 934 | fattr->pre_change_attr = NFS_I(inode)->change_attr; | ||
| 935 | fattr->valid |= NFS_ATTR_WCC_V4; | ||
| 936 | } | ||
| 937 | if ((fattr->valid & NFS_ATTR_FATTR) != 0 && | ||
| 938 | (fattr->valid & NFS_ATTR_WCC) == 0) { | ||
| 939 | memcpy(&fattr->pre_ctime, &inode->i_ctime, sizeof(fattr->pre_ctime)); | ||
| 940 | memcpy(&fattr->pre_mtime, &inode->i_mtime, sizeof(fattr->pre_mtime)); | ||
| 941 | fattr->pre_size = inode->i_size; | ||
| 942 | fattr->valid |= NFS_ATTR_WCC; | ||
| 943 | } | ||
| 944 | return nfs_post_op_update_inode(inode, fattr); | ||
| 925 | } | 945 | } |
| 926 | 946 | ||
| 927 | /* | 947 | /* |
| @@ -941,9 +961,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
| 941 | struct nfs_server *server; | 961 | struct nfs_server *server; |
| 942 | struct nfs_inode *nfsi = NFS_I(inode); | 962 | struct nfs_inode *nfsi = NFS_I(inode); |
| 943 | loff_t cur_isize, new_isize; | 963 | loff_t cur_isize, new_isize; |
| 944 | unsigned int invalid = 0; | 964 | unsigned long invalid = 0; |
| 945 | unsigned long now = jiffies; | 965 | unsigned long now = jiffies; |
| 946 | int data_stable; | ||
| 947 | 966 | ||
| 948 | dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n", | 967 | dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n", |
| 949 | __FUNCTION__, inode->i_sb->s_id, inode->i_ino, | 968 | __FUNCTION__, inode->i_sb->s_id, inode->i_ino, |
| @@ -968,57 +987,51 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
| 968 | * Update the read time so we don't revalidate too often. | 987 | * Update the read time so we don't revalidate too often. |
| 969 | */ | 988 | */ |
| 970 | nfsi->read_cache_jiffies = fattr->time_start; | 989 | nfsi->read_cache_jiffies = fattr->time_start; |
| 971 | nfsi->last_updated = now; | ||
| 972 | 990 | ||
| 973 | /* Fix a wraparound issue with nfsi->cache_change_attribute */ | 991 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ATIME |
| 974 | if (time_before(now, nfsi->cache_change_attribute)) | 992 | | NFS_INO_REVAL_PAGECACHE); |
| 975 | nfsi->cache_change_attribute = now - 600*HZ; | ||
| 976 | |||
| 977 | /* Are we racing with known updates of the metadata on the server? */ | ||
| 978 | data_stable = nfs_verify_change_attribute(inode, fattr->time_start); | ||
| 979 | if (data_stable) | ||
| 980 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_ATIME); | ||
| 981 | 993 | ||
| 982 | /* Do atomic weak cache consistency updates */ | 994 | /* Do atomic weak cache consistency updates */ |
| 983 | nfs_wcc_update_inode(inode, fattr); | 995 | nfs_wcc_update_inode(inode, fattr); |
| 984 | 996 | ||
| 997 | /* More cache consistency checks */ | ||
| 998 | if (!(fattr->valid & NFS_ATTR_FATTR_V4)) { | ||
| 999 | /* NFSv2/v3: Check if the mtime agrees */ | ||
| 1000 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { | ||
| 1001 | dprintk("NFS: mtime change on server for file %s/%ld\n", | ||
| 1002 | inode->i_sb->s_id, inode->i_ino); | ||
| 1003 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | ||
| 1004 | nfsi->cache_change_attribute = now; | ||
| 1005 | } | ||
| 1006 | /* If ctime has changed we should definitely clear access+acl caches */ | ||
| 1007 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) | ||
| 1008 | invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
| 1009 | } else if (nfsi->change_attr != fattr->change_attr) { | ||
| 1010 | dprintk("NFS: change_attr change on server for file %s/%ld\n", | ||
| 1011 | inode->i_sb->s_id, inode->i_ino); | ||
| 1012 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
| 1013 | nfsi->cache_change_attribute = now; | ||
| 1014 | } | ||
| 1015 | |||
| 985 | /* Check if our cached file size is stale */ | 1016 | /* Check if our cached file size is stale */ |
| 986 | new_isize = nfs_size_to_loff_t(fattr->size); | 1017 | new_isize = nfs_size_to_loff_t(fattr->size); |
| 987 | cur_isize = i_size_read(inode); | 1018 | cur_isize = i_size_read(inode); |
| 988 | if (new_isize != cur_isize) { | 1019 | if (new_isize != cur_isize) { |
| 989 | /* Do we perhaps have any outstanding writes? */ | 1020 | /* Do we perhaps have any outstanding writes, or has |
| 990 | if (nfsi->npages == 0) { | 1021 | * the file grown beyond our last write? */ |
| 991 | /* No, but did we race with nfs_end_data_update()? */ | 1022 | if (nfsi->npages == 0 || new_isize > cur_isize) { |
| 992 | if (data_stable) { | ||
| 993 | inode->i_size = new_isize; | ||
| 994 | invalid |= NFS_INO_INVALID_DATA; | ||
| 995 | } | ||
| 996 | invalid |= NFS_INO_INVALID_ATTR; | ||
| 997 | } else if (new_isize > cur_isize) { | ||
| 998 | inode->i_size = new_isize; | 1023 | inode->i_size = new_isize; |
| 999 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1024 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
| 1000 | } | 1025 | } |
| 1001 | nfsi->cache_change_attribute = now; | ||
| 1002 | dprintk("NFS: isize change on server for file %s/%ld\n", | 1026 | dprintk("NFS: isize change on server for file %s/%ld\n", |
| 1003 | inode->i_sb->s_id, inode->i_ino); | 1027 | inode->i_sb->s_id, inode->i_ino); |
| 1004 | } | 1028 | } |
| 1005 | 1029 | ||
| 1006 | /* Check if the mtime agrees */ | ||
| 1007 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { | ||
| 1008 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | ||
| 1009 | dprintk("NFS: mtime change on server for file %s/%ld\n", | ||
| 1010 | inode->i_sb->s_id, inode->i_ino); | ||
| 1011 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | ||
| 1012 | nfsi->cache_change_attribute = now; | ||
| 1013 | } | ||
| 1014 | 1030 | ||
| 1015 | /* If ctime has changed we should definitely clear access+acl caches */ | 1031 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); |
| 1016 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) { | 1032 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); |
| 1017 | invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
| 1018 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | ||
| 1019 | nfsi->cache_change_attribute = now; | ||
| 1020 | } | ||
| 1021 | memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); | 1033 | memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); |
| 1034 | nfsi->change_attr = fattr->change_attr; | ||
| 1022 | 1035 | ||
| 1023 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) || | 1036 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) || |
| 1024 | inode->i_uid != fattr->uid || | 1037 | inode->i_uid != fattr->uid || |
| @@ -1039,31 +1052,29 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
| 1039 | inode->i_blocks = fattr->du.nfs2.blocks; | 1052 | inode->i_blocks = fattr->du.nfs2.blocks; |
| 1040 | } | 1053 | } |
| 1041 | 1054 | ||
| 1042 | if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && | ||
| 1043 | nfsi->change_attr != fattr->change_attr) { | ||
| 1044 | dprintk("NFS: change_attr change on server for file %s/%ld\n", | ||
| 1045 | inode->i_sb->s_id, inode->i_ino); | ||
| 1046 | nfsi->change_attr = fattr->change_attr; | ||
| 1047 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
| 1048 | nfsi->cache_change_attribute = now; | ||
| 1049 | } | ||
| 1050 | |||
| 1051 | /* Update attrtimeo value if we're out of the unstable period */ | 1055 | /* Update attrtimeo value if we're out of the unstable period */ |
| 1052 | if (invalid & NFS_INO_INVALID_ATTR) { | 1056 | if (invalid & NFS_INO_INVALID_ATTR) { |
| 1053 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); | 1057 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); |
| 1054 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 1058 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
| 1055 | nfsi->attrtimeo_timestamp = now; | 1059 | nfsi->attrtimeo_timestamp = now; |
| 1056 | } else if (time_after(now, nfsi->attrtimeo_timestamp+nfsi->attrtimeo)) { | 1060 | nfsi->last_updated = now; |
| 1057 | if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode)) | 1061 | } else { |
| 1058 | nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode); | 1062 | if (!time_in_range(now, nfsi->attrtimeo_timestamp, nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) { |
| 1059 | nfsi->attrtimeo_timestamp = now; | 1063 | if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode)) |
| 1064 | nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode); | ||
| 1065 | nfsi->attrtimeo_timestamp = now; | ||
| 1066 | } | ||
| 1067 | /* | ||
| 1068 | * Avoid jiffy wraparound issues with nfsi->last_updated | ||
| 1069 | */ | ||
| 1070 | if (!time_in_range(nfsi->last_updated, nfsi->read_cache_jiffies, now)) | ||
| 1071 | nfsi->last_updated = nfsi->read_cache_jiffies; | ||
| 1060 | } | 1072 | } |
| 1073 | invalid &= ~NFS_INO_INVALID_ATTR; | ||
| 1061 | /* Don't invalidate the data if we were to blame */ | 1074 | /* Don't invalidate the data if we were to blame */ |
| 1062 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) | 1075 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) |
| 1063 | || S_ISLNK(inode->i_mode))) | 1076 | || S_ISLNK(inode->i_mode))) |
| 1064 | invalid &= ~NFS_INO_INVALID_DATA; | 1077 | invalid &= ~NFS_INO_INVALID_DATA; |
| 1065 | if (data_stable) | ||
| 1066 | invalid &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME|NFS_INO_REVAL_PAGECACHE); | ||
| 1067 | if (!nfs_have_delegation(inode, FMODE_READ) || | 1078 | if (!nfs_have_delegation(inode, FMODE_READ) || |
| 1068 | (nfsi->cache_validity & NFS_INO_REVAL_FORCED)) | 1079 | (nfsi->cache_validity & NFS_INO_REVAL_FORCED)) |
| 1069 | nfsi->cache_validity |= invalid; | 1080 | nfsi->cache_validity |= invalid; |
| @@ -1152,7 +1163,6 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag | |||
| 1152 | INIT_LIST_HEAD(&nfsi->access_cache_entry_lru); | 1163 | INIT_LIST_HEAD(&nfsi->access_cache_entry_lru); |
| 1153 | INIT_LIST_HEAD(&nfsi->access_cache_inode_lru); | 1164 | INIT_LIST_HEAD(&nfsi->access_cache_inode_lru); |
| 1154 | INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC); | 1165 | INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC); |
| 1155 | atomic_set(&nfsi->data_updates, 0); | ||
| 1156 | nfsi->ncommit = 0; | 1166 | nfsi->ncommit = 0; |
| 1157 | nfsi->npages = 0; | 1167 | nfsi->npages = 0; |
| 1158 | nfs4_init_once(nfsi); | 1168 | nfs4_init_once(nfsi); |
| @@ -1249,6 +1259,7 @@ static void __exit exit_nfs_fs(void) | |||
| 1249 | /* Not quite true; I just maintain it */ | 1259 | /* Not quite true; I just maintain it */ |
| 1250 | MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>"); | 1260 | MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>"); |
| 1251 | MODULE_LICENSE("GPL"); | 1261 | MODULE_LICENSE("GPL"); |
| 1262 | module_param(enable_ino64, bool, 0644); | ||
| 1252 | 1263 | ||
| 1253 | module_init(init_nfs_fs) | 1264 | module_init(init_nfs_fs) |
| 1254 | module_exit(exit_nfs_fs) | 1265 | module_exit(exit_nfs_fs) |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 76cf55d57101..f3acf48412be 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
| @@ -5,8 +5,6 @@ | |||
| 5 | #include <linux/mount.h> | 5 | #include <linux/mount.h> |
| 6 | 6 | ||
| 7 | struct nfs_string; | 7 | struct nfs_string; |
| 8 | struct nfs_mount_data; | ||
| 9 | struct nfs4_mount_data; | ||
| 10 | 8 | ||
| 11 | /* Maximum number of readahead requests | 9 | /* Maximum number of readahead requests |
| 12 | * FIXME: this should really be a sysctl so that users may tune it to suit | 10 | * FIXME: this should really be a sysctl so that users may tune it to suit |
| @@ -27,20 +25,50 @@ struct nfs_clone_mount { | |||
| 27 | rpc_authflavor_t authflavor; | 25 | rpc_authflavor_t authflavor; |
| 28 | }; | 26 | }; |
| 29 | 27 | ||
| 28 | /* | ||
| 29 | * In-kernel mount arguments | ||
| 30 | */ | ||
| 31 | struct nfs_parsed_mount_data { | ||
| 32 | int flags; | ||
| 33 | int rsize, wsize; | ||
| 34 | int timeo, retrans; | ||
| 35 | int acregmin, acregmax, | ||
| 36 | acdirmin, acdirmax; | ||
| 37 | int namlen; | ||
| 38 | unsigned int bsize; | ||
| 39 | unsigned int auth_flavor_len; | ||
| 40 | rpc_authflavor_t auth_flavors[1]; | ||
| 41 | char *client_address; | ||
| 42 | |||
| 43 | struct { | ||
| 44 | struct sockaddr_in address; | ||
| 45 | char *hostname; | ||
| 46 | unsigned int program; | ||
| 47 | unsigned int version; | ||
| 48 | unsigned short port; | ||
| 49 | int protocol; | ||
| 50 | } mount_server; | ||
| 51 | |||
| 52 | struct { | ||
| 53 | struct sockaddr_in address; | ||
| 54 | char *hostname; | ||
| 55 | char *export_path; | ||
| 56 | unsigned int program; | ||
| 57 | int protocol; | ||
| 58 | } nfs_server; | ||
| 59 | }; | ||
| 60 | |||
| 30 | /* client.c */ | 61 | /* client.c */ |
| 31 | extern struct rpc_program nfs_program; | 62 | extern struct rpc_program nfs_program; |
| 32 | 63 | ||
| 33 | extern void nfs_put_client(struct nfs_client *); | 64 | extern void nfs_put_client(struct nfs_client *); |
| 34 | extern struct nfs_client *nfs_find_client(const struct sockaddr_in *, int); | 65 | extern struct nfs_client *nfs_find_client(const struct sockaddr_in *, int); |
| 35 | extern struct nfs_server *nfs_create_server(const struct nfs_mount_data *, | 66 | extern struct nfs_server *nfs_create_server( |
| 36 | struct nfs_fh *); | 67 | const struct nfs_parsed_mount_data *, |
| 37 | extern struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *, | 68 | struct nfs_fh *); |
| 38 | const char *, | 69 | extern struct nfs_server *nfs4_create_server( |
| 39 | const struct sockaddr_in *, | 70 | const struct nfs_parsed_mount_data *, |
| 40 | const char *, | 71 | struct nfs_fh *); |
| 41 | const char *, | ||
| 42 | rpc_authflavor_t, | ||
| 43 | struct nfs_fh *); | ||
| 44 | extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *, | 72 | extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *, |
| 45 | struct nfs_fh *); | 73 | struct nfs_fh *); |
| 46 | extern void nfs_free_server(struct nfs_server *server); | 74 | extern void nfs_free_server(struct nfs_server *server); |
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index c5fce7567200..668ab96c7b59 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c | |||
| @@ -251,6 +251,7 @@ nfs_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args) | |||
| 251 | replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readres_sz) << 2; | 251 | replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readres_sz) << 2; |
| 252 | xdr_inline_pages(&req->rq_rcv_buf, replen, | 252 | xdr_inline_pages(&req->rq_rcv_buf, replen, |
| 253 | args->pages, args->pgbase, count); | 253 | args->pages, args->pgbase, count); |
| 254 | req->rq_rcv_buf.flags |= XDRBUF_READ; | ||
| 254 | return 0; | 255 | return 0; |
| 255 | } | 256 | } |
| 256 | 257 | ||
| @@ -271,7 +272,7 @@ nfs_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) | |||
| 271 | res->eof = 0; | 272 | res->eof = 0; |
| 272 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; | 273 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; |
| 273 | if (iov->iov_len < hdrlen) { | 274 | if (iov->iov_len < hdrlen) { |
| 274 | printk(KERN_WARNING "NFS: READ reply header overflowed:" | 275 | dprintk("NFS: READ reply header overflowed:" |
| 275 | "length %d > %Zu\n", hdrlen, iov->iov_len); | 276 | "length %d > %Zu\n", hdrlen, iov->iov_len); |
| 276 | return -errno_NFSERR_IO; | 277 | return -errno_NFSERR_IO; |
| 277 | } else if (iov->iov_len != hdrlen) { | 278 | } else if (iov->iov_len != hdrlen) { |
| @@ -281,7 +282,7 @@ nfs_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) | |||
| 281 | 282 | ||
| 282 | recvd = req->rq_rcv_buf.len - hdrlen; | 283 | recvd = req->rq_rcv_buf.len - hdrlen; |
| 283 | if (count > recvd) { | 284 | if (count > recvd) { |
| 284 | printk(KERN_WARNING "NFS: server cheating in read reply: " | 285 | dprintk("NFS: server cheating in read reply: " |
| 285 | "count %d > recvd %d\n", count, recvd); | 286 | "count %d > recvd %d\n", count, recvd); |
| 286 | count = recvd; | 287 | count = recvd; |
| 287 | } | 288 | } |
| @@ -313,6 +314,7 @@ nfs_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args) | |||
| 313 | 314 | ||
| 314 | /* Copy the page array */ | 315 | /* Copy the page array */ |
| 315 | xdr_encode_pages(sndbuf, args->pages, args->pgbase, count); | 316 | xdr_encode_pages(sndbuf, args->pages, args->pgbase, count); |
| 317 | sndbuf->flags |= XDRBUF_WRITE; | ||
| 316 | return 0; | 318 | return 0; |
| 317 | } | 319 | } |
| 318 | 320 | ||
| @@ -431,7 +433,7 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy) | |||
| 431 | 433 | ||
| 432 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; | 434 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; |
| 433 | if (iov->iov_len < hdrlen) { | 435 | if (iov->iov_len < hdrlen) { |
| 434 | printk(KERN_WARNING "NFS: READDIR reply header overflowed:" | 436 | dprintk("NFS: READDIR reply header overflowed:" |
| 435 | "length %d > %Zu\n", hdrlen, iov->iov_len); | 437 | "length %d > %Zu\n", hdrlen, iov->iov_len); |
| 436 | return -errno_NFSERR_IO; | 438 | return -errno_NFSERR_IO; |
| 437 | } else if (iov->iov_len != hdrlen) { | 439 | } else if (iov->iov_len != hdrlen) { |
| @@ -454,7 +456,7 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy) | |||
| 454 | len = ntohl(*p++); | 456 | len = ntohl(*p++); |
| 455 | p += XDR_QUADLEN(len) + 1; /* name plus cookie */ | 457 | p += XDR_QUADLEN(len) + 1; /* name plus cookie */ |
| 456 | if (len > NFS2_MAXNAMLEN) { | 458 | if (len > NFS2_MAXNAMLEN) { |
| 457 | printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)!\n", | 459 | dprintk("NFS: giant filename in readdir (len 0x%x)!\n", |
| 458 | len); | 460 | len); |
| 459 | goto err_unmap; | 461 | goto err_unmap; |
| 460 | } | 462 | } |
| @@ -471,7 +473,7 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy) | |||
| 471 | entry[0] = entry[1] = 0; | 473 | entry[0] = entry[1] = 0; |
| 472 | /* truncate listing ? */ | 474 | /* truncate listing ? */ |
| 473 | if (!nr) { | 475 | if (!nr) { |
| 474 | printk(KERN_NOTICE "NFS: readdir reply truncated!\n"); | 476 | dprintk("NFS: readdir reply truncated!\n"); |
| 475 | entry[1] = 1; | 477 | entry[1] = 1; |
| 476 | } | 478 | } |
| 477 | goto out; | 479 | goto out; |
| @@ -583,12 +585,12 @@ nfs_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, void *dummy) | |||
| 583 | /* Convert length of symlink */ | 585 | /* Convert length of symlink */ |
| 584 | len = ntohl(*p++); | 586 | len = ntohl(*p++); |
| 585 | if (len >= rcvbuf->page_len || len <= 0) { | 587 | if (len >= rcvbuf->page_len || len <= 0) { |
| 586 | dprintk(KERN_WARNING "nfs: server returned giant symlink!\n"); | 588 | dprintk("nfs: server returned giant symlink!\n"); |
| 587 | return -ENAMETOOLONG; | 589 | return -ENAMETOOLONG; |
| 588 | } | 590 | } |
| 589 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; | 591 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; |
| 590 | if (iov->iov_len < hdrlen) { | 592 | if (iov->iov_len < hdrlen) { |
| 591 | printk(KERN_WARNING "NFS: READLINK reply header overflowed:" | 593 | dprintk("NFS: READLINK reply header overflowed:" |
| 592 | "length %d > %Zu\n", hdrlen, iov->iov_len); | 594 | "length %d > %Zu\n", hdrlen, iov->iov_len); |
| 593 | return -errno_NFSERR_IO; | 595 | return -errno_NFSERR_IO; |
| 594 | } else if (iov->iov_len != hdrlen) { | 596 | } else if (iov->iov_len != hdrlen) { |
| @@ -597,7 +599,7 @@ nfs_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, void *dummy) | |||
| 597 | } | 599 | } |
| 598 | recvd = req->rq_rcv_buf.len - hdrlen; | 600 | recvd = req->rq_rcv_buf.len - hdrlen; |
| 599 | if (recvd < len) { | 601 | if (recvd < len) { |
| 600 | printk(KERN_WARNING "NFS: server cheating in readlink reply: " | 602 | dprintk("NFS: server cheating in readlink reply: " |
| 601 | "count %u > recvd %u\n", len, recvd); | 603 | "count %u > recvd %u\n", len, recvd); |
| 602 | return -EIO; | 604 | return -EIO; |
| 603 | } | 605 | } |
| @@ -695,7 +697,7 @@ nfs_stat_to_errno(int stat) | |||
| 695 | if (nfs_errtbl[i].stat == stat) | 697 | if (nfs_errtbl[i].stat == stat) |
| 696 | return nfs_errtbl[i].errno; | 698 | return nfs_errtbl[i].errno; |
| 697 | } | 699 | } |
| 698 | printk(KERN_ERR "nfs_stat_to_errno: bad nfs status return value: %d\n", stat); | 700 | dprintk("nfs_stat_to_errno: bad nfs status return value: %d\n", stat); |
| 699 | return nfs_errtbl[i].errno; | 701 | return nfs_errtbl[i].errno; |
| 700 | } | 702 | } |
| 701 | 703 | ||
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c index 7322da4d2055..9b7362565c0c 100644 --- a/fs/nfs/nfs3acl.c +++ b/fs/nfs/nfs3acl.c | |||
| @@ -317,13 +317,11 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, | |||
| 317 | } | 317 | } |
| 318 | 318 | ||
| 319 | dprintk("NFS call setacl\n"); | 319 | dprintk("NFS call setacl\n"); |
| 320 | nfs_begin_data_update(inode); | ||
| 321 | msg.rpc_proc = &server->client_acl->cl_procinfo[ACLPROC3_SETACL]; | 320 | msg.rpc_proc = &server->client_acl->cl_procinfo[ACLPROC3_SETACL]; |
| 322 | status = rpc_call_sync(server->client_acl, &msg, 0); | 321 | status = rpc_call_sync(server->client_acl, &msg, 0); |
| 323 | spin_lock(&inode->i_lock); | 322 | spin_lock(&inode->i_lock); |
| 324 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ACCESS; | 323 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ACCESS; |
| 325 | spin_unlock(&inode->i_lock); | 324 | spin_unlock(&inode->i_lock); |
| 326 | nfs_end_data_update(inode); | ||
| 327 | dprintk("NFS reply setacl: %d\n", status); | 325 | dprintk("NFS reply setacl: %d\n", status); |
| 328 | 326 | ||
| 329 | /* pages may have been allocated at the xdr layer. */ | 327 | /* pages may have been allocated at the xdr layer. */ |
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index c7ca5d70870b..4cdc2361a669 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
| @@ -166,6 +166,7 @@ nfs3_proc_lookup(struct inode *dir, struct qstr *name, | |||
| 166 | nfs_fattr_init(&dir_attr); | 166 | nfs_fattr_init(&dir_attr); |
| 167 | nfs_fattr_init(fattr); | 167 | nfs_fattr_init(fattr); |
| 168 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 168 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
| 169 | nfs_refresh_inode(dir, &dir_attr); | ||
| 169 | if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR)) { | 170 | if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR)) { |
| 170 | msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR]; | 171 | msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR]; |
| 171 | msg.rpc_argp = fhandle; | 172 | msg.rpc_argp = fhandle; |
| @@ -173,8 +174,6 @@ nfs3_proc_lookup(struct inode *dir, struct qstr *name, | |||
| 173 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 174 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
| 174 | } | 175 | } |
| 175 | dprintk("NFS reply lookup: %d\n", status); | 176 | dprintk("NFS reply lookup: %d\n", status); |
| 176 | if (status >= 0) | ||
| 177 | status = nfs_refresh_inode(dir, &dir_attr); | ||
| 178 | return status; | 177 | return status; |
| 179 | } | 178 | } |
| 180 | 179 | ||
| @@ -607,6 +606,9 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | |||
| 607 | 606 | ||
| 608 | nfs_fattr_init(&dir_attr); | 607 | nfs_fattr_init(&dir_attr); |
| 609 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 608 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
| 609 | |||
| 610 | nfs_invalidate_atime(dir); | ||
| 611 | |||
| 610 | nfs_refresh_inode(dir, &dir_attr); | 612 | nfs_refresh_inode(dir, &dir_attr); |
| 611 | dprintk("NFS reply readdir: %d\n", status); | 613 | dprintk("NFS reply readdir: %d\n", status); |
| 612 | return status; | 614 | return status; |
| @@ -724,9 +726,9 @@ static int nfs3_read_done(struct rpc_task *task, struct nfs_read_data *data) | |||
| 724 | { | 726 | { |
| 725 | if (nfs3_async_handle_jukebox(task, data->inode)) | 727 | if (nfs3_async_handle_jukebox(task, data->inode)) |
| 726 | return -EAGAIN; | 728 | return -EAGAIN; |
| 727 | /* Call back common NFS readpage processing */ | 729 | |
| 728 | if (task->tk_status >= 0) | 730 | nfs_invalidate_atime(data->inode); |
| 729 | nfs_refresh_inode(data->inode, &data->fattr); | 731 | nfs_refresh_inode(data->inode, &data->fattr); |
| 730 | return 0; | 732 | return 0; |
| 731 | } | 733 | } |
| 732 | 734 | ||
| @@ -747,7 +749,7 @@ static int nfs3_write_done(struct rpc_task *task, struct nfs_write_data *data) | |||
| 747 | if (nfs3_async_handle_jukebox(task, data->inode)) | 749 | if (nfs3_async_handle_jukebox(task, data->inode)) |
| 748 | return -EAGAIN; | 750 | return -EAGAIN; |
| 749 | if (task->tk_status >= 0) | 751 | if (task->tk_status >= 0) |
| 750 | nfs_post_op_update_inode(data->inode, data->res.fattr); | 752 | nfs_post_op_update_inode_force_wcc(data->inode, data->res.fattr); |
| 751 | return 0; | 753 | return 0; |
| 752 | } | 754 | } |
| 753 | 755 | ||
| @@ -775,8 +777,7 @@ static int nfs3_commit_done(struct rpc_task *task, struct nfs_write_data *data) | |||
| 775 | { | 777 | { |
| 776 | if (nfs3_async_handle_jukebox(task, data->inode)) | 778 | if (nfs3_async_handle_jukebox(task, data->inode)) |
| 777 | return -EAGAIN; | 779 | return -EAGAIN; |
| 778 | if (task->tk_status >= 0) | 780 | nfs_refresh_inode(data->inode, data->res.fattr); |
| 779 | nfs_post_op_update_inode(data->inode, data->res.fattr); | ||
| 780 | return 0; | 781 | return 0; |
| 781 | } | 782 | } |
| 782 | 783 | ||
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c index d9e08f0cf2a0..616d3267b7e7 100644 --- a/fs/nfs/nfs3xdr.c +++ b/fs/nfs/nfs3xdr.c | |||
| @@ -346,6 +346,7 @@ nfs3_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args) | |||
| 346 | replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readres_sz) << 2; | 346 | replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readres_sz) << 2; |
| 347 | xdr_inline_pages(&req->rq_rcv_buf, replen, | 347 | xdr_inline_pages(&req->rq_rcv_buf, replen, |
| 348 | args->pages, args->pgbase, count); | 348 | args->pages, args->pgbase, count); |
| 349 | req->rq_rcv_buf.flags |= XDRBUF_READ; | ||
| 349 | return 0; | 350 | return 0; |
| 350 | } | 351 | } |
| 351 | 352 | ||
| @@ -367,6 +368,7 @@ nfs3_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args) | |||
| 367 | 368 | ||
| 368 | /* Copy the page array */ | 369 | /* Copy the page array */ |
| 369 | xdr_encode_pages(sndbuf, args->pages, args->pgbase, count); | 370 | xdr_encode_pages(sndbuf, args->pages, args->pgbase, count); |
| 371 | sndbuf->flags |= XDRBUF_WRITE; | ||
| 370 | return 0; | 372 | return 0; |
| 371 | } | 373 | } |
| 372 | 374 | ||
| @@ -524,7 +526,7 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res | |||
| 524 | 526 | ||
| 525 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; | 527 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; |
| 526 | if (iov->iov_len < hdrlen) { | 528 | if (iov->iov_len < hdrlen) { |
| 527 | printk(KERN_WARNING "NFS: READDIR reply header overflowed:" | 529 | dprintk("NFS: READDIR reply header overflowed:" |
| 528 | "length %d > %Zu\n", hdrlen, iov->iov_len); | 530 | "length %d > %Zu\n", hdrlen, iov->iov_len); |
| 529 | return -errno_NFSERR_IO; | 531 | return -errno_NFSERR_IO; |
| 530 | } else if (iov->iov_len != hdrlen) { | 532 | } else if (iov->iov_len != hdrlen) { |
| @@ -547,7 +549,7 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res | |||
| 547 | len = ntohl(*p++); /* string length */ | 549 | len = ntohl(*p++); /* string length */ |
| 548 | p += XDR_QUADLEN(len) + 2; /* name + cookie */ | 550 | p += XDR_QUADLEN(len) + 2; /* name + cookie */ |
| 549 | if (len > NFS3_MAXNAMLEN) { | 551 | if (len > NFS3_MAXNAMLEN) { |
| 550 | printk(KERN_WARNING "NFS: giant filename in readdir (len %x)!\n", | 552 | dprintk("NFS: giant filename in readdir (len %x)!\n", |
| 551 | len); | 553 | len); |
| 552 | goto err_unmap; | 554 | goto err_unmap; |
| 553 | } | 555 | } |
| @@ -567,7 +569,7 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res | |||
| 567 | goto short_pkt; | 569 | goto short_pkt; |
| 568 | len = ntohl(*p++); | 570 | len = ntohl(*p++); |
| 569 | if (len > NFS3_FHSIZE) { | 571 | if (len > NFS3_FHSIZE) { |
| 570 | printk(KERN_WARNING "NFS: giant filehandle in " | 572 | dprintk("NFS: giant filehandle in " |
| 571 | "readdir (len %x)!\n", len); | 573 | "readdir (len %x)!\n", len); |
| 572 | goto err_unmap; | 574 | goto err_unmap; |
| 573 | } | 575 | } |
| @@ -588,7 +590,7 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res | |||
| 588 | entry[0] = entry[1] = 0; | 590 | entry[0] = entry[1] = 0; |
| 589 | /* truncate listing ? */ | 591 | /* truncate listing ? */ |
| 590 | if (!nr) { | 592 | if (!nr) { |
| 591 | printk(KERN_NOTICE "NFS: readdir reply truncated!\n"); | 593 | dprintk("NFS: readdir reply truncated!\n"); |
| 592 | entry[1] = 1; | 594 | entry[1] = 1; |
| 593 | } | 595 | } |
| 594 | goto out; | 596 | goto out; |
| @@ -826,22 +828,23 @@ nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) | |||
| 826 | /* Convert length of symlink */ | 828 | /* Convert length of symlink */ |
| 827 | len = ntohl(*p++); | 829 | len = ntohl(*p++); |
| 828 | if (len >= rcvbuf->page_len || len <= 0) { | 830 | if (len >= rcvbuf->page_len || len <= 0) { |
| 829 | dprintk(KERN_WARNING "nfs: server returned giant symlink!\n"); | 831 | dprintk("nfs: server returned giant symlink!\n"); |
| 830 | return -ENAMETOOLONG; | 832 | return -ENAMETOOLONG; |
| 831 | } | 833 | } |
| 832 | 834 | ||
| 833 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; | 835 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; |
| 834 | if (iov->iov_len < hdrlen) { | 836 | if (iov->iov_len < hdrlen) { |
| 835 | printk(KERN_WARNING "NFS: READLINK reply header overflowed:" | 837 | dprintk("NFS: READLINK reply header overflowed:" |
| 836 | "length %d > %Zu\n", hdrlen, iov->iov_len); | 838 | "length %d > %Zu\n", hdrlen, iov->iov_len); |
| 837 | return -errno_NFSERR_IO; | 839 | return -errno_NFSERR_IO; |
| 838 | } else if (iov->iov_len != hdrlen) { | 840 | } else if (iov->iov_len != hdrlen) { |
| 839 | dprintk("NFS: READLINK header is short. iovec will be shifted.\n"); | 841 | dprintk("NFS: READLINK header is short. " |
| 842 | "iovec will be shifted.\n"); | ||
| 840 | xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen); | 843 | xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen); |
| 841 | } | 844 | } |
| 842 | recvd = req->rq_rcv_buf.len - hdrlen; | 845 | recvd = req->rq_rcv_buf.len - hdrlen; |
| 843 | if (recvd < len) { | 846 | if (recvd < len) { |
| 844 | printk(KERN_WARNING "NFS: server cheating in readlink reply: " | 847 | dprintk("NFS: server cheating in readlink reply: " |
| 845 | "count %u > recvd %u\n", len, recvd); | 848 | "count %u > recvd %u\n", len, recvd); |
| 846 | return -EIO; | 849 | return -EIO; |
| 847 | } | 850 | } |
| @@ -876,13 +879,13 @@ nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) | |||
| 876 | ocount = ntohl(*p++); | 879 | ocount = ntohl(*p++); |
| 877 | 880 | ||
| 878 | if (ocount != count) { | 881 | if (ocount != count) { |
| 879 | printk(KERN_WARNING "NFS: READ count doesn't match RPC opaque count.\n"); | 882 | dprintk("NFS: READ count doesn't match RPC opaque count.\n"); |
| 880 | return -errno_NFSERR_IO; | 883 | return -errno_NFSERR_IO; |
| 881 | } | 884 | } |
| 882 | 885 | ||
| 883 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; | 886 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; |
| 884 | if (iov->iov_len < hdrlen) { | 887 | if (iov->iov_len < hdrlen) { |
| 885 | printk(KERN_WARNING "NFS: READ reply header overflowed:" | 888 | dprintk("NFS: READ reply header overflowed:" |
| 886 | "length %d > %Zu\n", hdrlen, iov->iov_len); | 889 | "length %d > %Zu\n", hdrlen, iov->iov_len); |
| 887 | return -errno_NFSERR_IO; | 890 | return -errno_NFSERR_IO; |
| 888 | } else if (iov->iov_len != hdrlen) { | 891 | } else if (iov->iov_len != hdrlen) { |
| @@ -892,7 +895,7 @@ nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) | |||
| 892 | 895 | ||
| 893 | recvd = req->rq_rcv_buf.len - hdrlen; | 896 | recvd = req->rq_rcv_buf.len - hdrlen; |
| 894 | if (count > recvd) { | 897 | if (count > recvd) { |
| 895 | printk(KERN_WARNING "NFS: server cheating in read reply: " | 898 | dprintk("NFS: server cheating in read reply: " |
| 896 | "count %d > recvd %d\n", count, recvd); | 899 | "count %d > recvd %d\n", count, recvd); |
| 897 | count = recvd; | 900 | count = recvd; |
| 898 | res->eof = 0; | 901 | res->eof = 0; |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 4b90e17555a9..cb99fd90a9ac 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -62,10 +62,8 @@ struct nfs4_opendata; | |||
| 62 | static int _nfs4_proc_open(struct nfs4_opendata *data); | 62 | static int _nfs4_proc_open(struct nfs4_opendata *data); |
| 63 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); | 63 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); |
| 64 | static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *); | 64 | static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *); |
| 65 | static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry); | ||
| 66 | static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception); | 65 | static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception); |
| 67 | static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp); | 66 | static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp); |
| 68 | static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags); | ||
| 69 | static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr); | 67 | static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr); |
| 70 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr); | 68 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr); |
| 71 | 69 | ||
| @@ -177,7 +175,7 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent | |||
| 177 | *p++ = xdr_one; /* bitmap length */ | 175 | *p++ = xdr_one; /* bitmap length */ |
| 178 | *p++ = htonl(FATTR4_WORD0_FILEID); /* bitmap */ | 176 | *p++ = htonl(FATTR4_WORD0_FILEID); /* bitmap */ |
| 179 | *p++ = htonl(8); /* attribute buffer length */ | 177 | *p++ = htonl(8); /* attribute buffer length */ |
| 180 | p = xdr_encode_hyper(p, dentry->d_inode->i_ino); | 178 | p = xdr_encode_hyper(p, NFS_FILEID(dentry->d_inode)); |
| 181 | } | 179 | } |
| 182 | 180 | ||
| 183 | *p++ = xdr_one; /* next */ | 181 | *p++ = xdr_one; /* next */ |
| @@ -189,7 +187,7 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent | |||
| 189 | *p++ = xdr_one; /* bitmap length */ | 187 | *p++ = xdr_one; /* bitmap length */ |
| 190 | *p++ = htonl(FATTR4_WORD0_FILEID); /* bitmap */ | 188 | *p++ = htonl(FATTR4_WORD0_FILEID); /* bitmap */ |
| 191 | *p++ = htonl(8); /* attribute buffer length */ | 189 | *p++ = htonl(8); /* attribute buffer length */ |
| 192 | p = xdr_encode_hyper(p, dentry->d_parent->d_inode->i_ino); | 190 | p = xdr_encode_hyper(p, NFS_FILEID(dentry->d_parent->d_inode)); |
| 193 | 191 | ||
| 194 | readdir->pgbase = (char *)p - (char *)start; | 192 | readdir->pgbase = (char *)p - (char *)start; |
| 195 | readdir->count -= readdir->pgbase; | 193 | readdir->count -= readdir->pgbase; |
| @@ -211,8 +209,9 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) | |||
| 211 | 209 | ||
| 212 | spin_lock(&dir->i_lock); | 210 | spin_lock(&dir->i_lock); |
| 213 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_DATA; | 211 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_DATA; |
| 214 | if (cinfo->before == nfsi->change_attr && cinfo->atomic) | 212 | if (!cinfo->atomic || cinfo->before != nfsi->change_attr) |
| 215 | nfsi->change_attr = cinfo->after; | 213 | nfsi->cache_change_attribute = jiffies; |
| 214 | nfsi->change_attr = cinfo->after; | ||
| 216 | spin_unlock(&dir->i_lock); | 215 | spin_unlock(&dir->i_lock); |
| 217 | } | 216 | } |
| 218 | 217 | ||
| @@ -454,7 +453,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata) | |||
| 454 | memcpy(stateid.data, delegation->stateid.data, sizeof(stateid.data)); | 453 | memcpy(stateid.data, delegation->stateid.data, sizeof(stateid.data)); |
| 455 | rcu_read_unlock(); | 454 | rcu_read_unlock(); |
| 456 | lock_kernel(); | 455 | lock_kernel(); |
| 457 | ret = _nfs4_do_access(state->inode, state->owner->so_cred, open_mode); | 456 | ret = nfs_may_open(state->inode, state->owner->so_cred, open_mode); |
| 458 | unlock_kernel(); | 457 | unlock_kernel(); |
| 459 | if (ret != 0) | 458 | if (ret != 0) |
| 460 | goto out; | 459 | goto out; |
| @@ -948,36 +947,6 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) | |||
| 948 | return 0; | 947 | return 0; |
| 949 | } | 948 | } |
| 950 | 949 | ||
| 951 | static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags) | ||
| 952 | { | ||
| 953 | struct nfs_access_entry cache; | ||
| 954 | int mask = 0; | ||
| 955 | int status; | ||
| 956 | |||
| 957 | if (openflags & FMODE_READ) | ||
| 958 | mask |= MAY_READ; | ||
| 959 | if (openflags & FMODE_WRITE) | ||
| 960 | mask |= MAY_WRITE; | ||
| 961 | if (openflags & FMODE_EXEC) | ||
| 962 | mask |= MAY_EXEC; | ||
| 963 | status = nfs_access_get_cached(inode, cred, &cache); | ||
| 964 | if (status == 0) | ||
| 965 | goto out; | ||
| 966 | |||
| 967 | /* Be clever: ask server to check for all possible rights */ | ||
| 968 | cache.mask = MAY_EXEC | MAY_WRITE | MAY_READ; | ||
| 969 | cache.cred = cred; | ||
| 970 | cache.jiffies = jiffies; | ||
| 971 | status = _nfs4_proc_access(inode, &cache); | ||
| 972 | if (status != 0) | ||
| 973 | return status; | ||
| 974 | nfs_access_add_cache(inode, &cache); | ||
| 975 | out: | ||
| 976 | if ((cache.mask & mask) == mask) | ||
| 977 | return 0; | ||
| 978 | return -EACCES; | ||
| 979 | } | ||
| 980 | |||
| 981 | static int nfs4_recover_expired_lease(struct nfs_server *server) | 950 | static int nfs4_recover_expired_lease(struct nfs_server *server) |
| 982 | { | 951 | { |
| 983 | struct nfs_client *clp = server->nfs_client; | 952 | struct nfs_client *clp = server->nfs_client; |
| @@ -1381,7 +1350,7 @@ static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct | |||
| 1381 | 1350 | ||
| 1382 | /* If the open_intent is for execute, we have an extra check to make */ | 1351 | /* If the open_intent is for execute, we have an extra check to make */ |
| 1383 | if (nd->intent.open.flags & FMODE_EXEC) { | 1352 | if (nd->intent.open.flags & FMODE_EXEC) { |
| 1384 | ret = _nfs4_do_access(state->inode, | 1353 | ret = nfs_may_open(state->inode, |
| 1385 | state->owner->so_cred, | 1354 | state->owner->so_cred, |
| 1386 | nd->intent.open.flags); | 1355 | nd->intent.open.flags); |
| 1387 | if (ret < 0) | 1356 | if (ret < 0) |
| @@ -1390,7 +1359,7 @@ static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct | |||
| 1390 | filp = lookup_instantiate_filp(nd, path->dentry, NULL); | 1359 | filp = lookup_instantiate_filp(nd, path->dentry, NULL); |
| 1391 | if (!IS_ERR(filp)) { | 1360 | if (!IS_ERR(filp)) { |
| 1392 | struct nfs_open_context *ctx; | 1361 | struct nfs_open_context *ctx; |
| 1393 | ctx = (struct nfs_open_context *)filp->private_data; | 1362 | ctx = nfs_file_open_context(filp); |
| 1394 | ctx->state = state; | 1363 | ctx->state = state; |
| 1395 | return 0; | 1364 | return 0; |
| 1396 | } | 1365 | } |
| @@ -1428,13 +1397,16 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | |||
| 1428 | state = nfs4_do_open(dir, &path, nd->intent.open.flags, &attr, cred); | 1397 | state = nfs4_do_open(dir, &path, nd->intent.open.flags, &attr, cred); |
| 1429 | put_rpccred(cred); | 1398 | put_rpccred(cred); |
| 1430 | if (IS_ERR(state)) { | 1399 | if (IS_ERR(state)) { |
| 1431 | if (PTR_ERR(state) == -ENOENT) | 1400 | if (PTR_ERR(state) == -ENOENT) { |
| 1432 | d_add(dentry, NULL); | 1401 | d_add(dentry, NULL); |
| 1402 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
| 1403 | } | ||
| 1433 | return (struct dentry *)state; | 1404 | return (struct dentry *)state; |
| 1434 | } | 1405 | } |
| 1435 | res = d_add_unique(dentry, igrab(state->inode)); | 1406 | res = d_add_unique(dentry, igrab(state->inode)); |
| 1436 | if (res != NULL) | 1407 | if (res != NULL) |
| 1437 | path.dentry = res; | 1408 | path.dentry = res; |
| 1409 | nfs_set_verifier(path.dentry, nfs_save_change_attribute(dir)); | ||
| 1438 | nfs4_intent_set_file(nd, &path, state); | 1410 | nfs4_intent_set_file(nd, &path, state); |
| 1439 | return res; | 1411 | return res; |
| 1440 | } | 1412 | } |
| @@ -1468,6 +1440,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st | |||
| 1468 | } | 1440 | } |
| 1469 | } | 1441 | } |
| 1470 | if (state->inode == dentry->d_inode) { | 1442 | if (state->inode == dentry->d_inode) { |
| 1443 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
| 1471 | nfs4_intent_set_file(nd, &path, state); | 1444 | nfs4_intent_set_file(nd, &path, state); |
| 1472 | return 1; | 1445 | return 1; |
| 1473 | } | 1446 | } |
| @@ -1757,10 +1730,16 @@ static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, struct nfs_fh | |||
| 1757 | 1730 | ||
| 1758 | static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) | 1731 | static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) |
| 1759 | { | 1732 | { |
| 1733 | struct nfs_server *server = NFS_SERVER(inode); | ||
| 1734 | struct nfs_fattr fattr; | ||
| 1760 | struct nfs4_accessargs args = { | 1735 | struct nfs4_accessargs args = { |
| 1761 | .fh = NFS_FH(inode), | 1736 | .fh = NFS_FH(inode), |
| 1737 | .bitmask = server->attr_bitmask, | ||
| 1738 | }; | ||
| 1739 | struct nfs4_accessres res = { | ||
| 1740 | .server = server, | ||
| 1741 | .fattr = &fattr, | ||
| 1762 | }; | 1742 | }; |
| 1763 | struct nfs4_accessres res = { 0 }; | ||
| 1764 | struct rpc_message msg = { | 1743 | struct rpc_message msg = { |
| 1765 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ACCESS], | 1744 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ACCESS], |
| 1766 | .rpc_argp = &args, | 1745 | .rpc_argp = &args, |
| @@ -1786,6 +1765,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry | |||
| 1786 | if (mode & MAY_EXEC) | 1765 | if (mode & MAY_EXEC) |
| 1787 | args.access |= NFS4_ACCESS_EXECUTE; | 1766 | args.access |= NFS4_ACCESS_EXECUTE; |
| 1788 | } | 1767 | } |
| 1768 | nfs_fattr_init(&fattr); | ||
| 1789 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); | 1769 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); |
| 1790 | if (!status) { | 1770 | if (!status) { |
| 1791 | entry->mask = 0; | 1771 | entry->mask = 0; |
| @@ -1795,6 +1775,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry | |||
| 1795 | entry->mask |= MAY_WRITE; | 1775 | entry->mask |= MAY_WRITE; |
| 1796 | if (res.access & (NFS4_ACCESS_LOOKUP|NFS4_ACCESS_EXECUTE)) | 1776 | if (res.access & (NFS4_ACCESS_LOOKUP|NFS4_ACCESS_EXECUTE)) |
| 1797 | entry->mask |= MAY_EXEC; | 1777 | entry->mask |= MAY_EXEC; |
| 1778 | nfs_refresh_inode(inode, &fattr); | ||
| 1798 | } | 1779 | } |
| 1799 | return status; | 1780 | return status; |
| 1800 | } | 1781 | } |
| @@ -1900,11 +1881,13 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
| 1900 | } | 1881 | } |
| 1901 | state = nfs4_do_open(dir, &path, flags, sattr, cred); | 1882 | state = nfs4_do_open(dir, &path, flags, sattr, cred); |
| 1902 | put_rpccred(cred); | 1883 | put_rpccred(cred); |
| 1884 | d_drop(dentry); | ||
| 1903 | if (IS_ERR(state)) { | 1885 | if (IS_ERR(state)) { |
| 1904 | status = PTR_ERR(state); | 1886 | status = PTR_ERR(state); |
| 1905 | goto out; | 1887 | goto out; |
| 1906 | } | 1888 | } |
| 1907 | d_instantiate(dentry, igrab(state->inode)); | 1889 | d_add(dentry, igrab(state->inode)); |
| 1890 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
| 1908 | if (flags & O_EXCL) { | 1891 | if (flags & O_EXCL) { |
| 1909 | struct nfs_fattr fattr; | 1892 | struct nfs_fattr fattr; |
| 1910 | status = nfs4_do_setattr(state->inode, &fattr, sattr, state); | 1893 | status = nfs4_do_setattr(state->inode, &fattr, sattr, state); |
| @@ -2218,6 +2201,9 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | |||
| 2218 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 2201 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
| 2219 | if (status == 0) | 2202 | if (status == 0) |
| 2220 | memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); | 2203 | memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); |
| 2204 | |||
| 2205 | nfs_invalidate_atime(dir); | ||
| 2206 | |||
| 2221 | dprintk("%s: returns %d\n", __FUNCTION__, status); | 2207 | dprintk("%s: returns %d\n", __FUNCTION__, status); |
| 2222 | return status; | 2208 | return status; |
| 2223 | } | 2209 | } |
| @@ -2414,6 +2400,8 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data) | |||
| 2414 | rpc_restart_call(task); | 2400 | rpc_restart_call(task); |
| 2415 | return -EAGAIN; | 2401 | return -EAGAIN; |
| 2416 | } | 2402 | } |
| 2403 | |||
| 2404 | nfs_invalidate_atime(data->inode); | ||
| 2417 | if (task->tk_status > 0) | 2405 | if (task->tk_status > 0) |
| 2418 | renew_lease(server, data->timestamp); | 2406 | renew_lease(server, data->timestamp); |
| 2419 | return 0; | 2407 | return 0; |
| @@ -2443,7 +2431,7 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) | |||
| 2443 | } | 2431 | } |
| 2444 | if (task->tk_status >= 0) { | 2432 | if (task->tk_status >= 0) { |
| 2445 | renew_lease(NFS_SERVER(inode), data->timestamp); | 2433 | renew_lease(NFS_SERVER(inode), data->timestamp); |
| 2446 | nfs_post_op_update_inode(inode, data->res.fattr); | 2434 | nfs_post_op_update_inode_force_wcc(inode, data->res.fattr); |
| 2447 | } | 2435 | } |
| 2448 | return 0; | 2436 | return 0; |
| 2449 | } | 2437 | } |
| @@ -2485,8 +2473,7 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) | |||
| 2485 | rpc_restart_call(task); | 2473 | rpc_restart_call(task); |
| 2486 | return -EAGAIN; | 2474 | return -EAGAIN; |
| 2487 | } | 2475 | } |
| 2488 | if (task->tk_status >= 0) | 2476 | nfs_refresh_inode(inode, data->res.fattr); |
| 2489 | nfs_post_op_update_inode(inode, data->res.fattr); | ||
| 2490 | return 0; | 2477 | return 0; |
| 2491 | } | 2478 | } |
| 2492 | 2479 | ||
| @@ -3056,7 +3043,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co | |||
| 3056 | if (status == 0) { | 3043 | if (status == 0) { |
| 3057 | status = data->rpc_status; | 3044 | status = data->rpc_status; |
| 3058 | if (status == 0) | 3045 | if (status == 0) |
| 3059 | nfs_post_op_update_inode(inode, &data->fattr); | 3046 | nfs_refresh_inode(inode, &data->fattr); |
| 3060 | } | 3047 | } |
| 3061 | rpc_put_task(task); | 3048 | rpc_put_task(task); |
| 3062 | return status; | 3049 | return status; |
| @@ -3303,7 +3290,7 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock * | |||
| 3303 | status = -ENOMEM; | 3290 | status = -ENOMEM; |
| 3304 | if (seqid == NULL) | 3291 | if (seqid == NULL) |
| 3305 | goto out; | 3292 | goto out; |
| 3306 | task = nfs4_do_unlck(request, request->fl_file->private_data, lsp, seqid); | 3293 | task = nfs4_do_unlck(request, nfs_file_open_context(request->fl_file), lsp, seqid); |
| 3307 | status = PTR_ERR(task); | 3294 | status = PTR_ERR(task); |
| 3308 | if (IS_ERR(task)) | 3295 | if (IS_ERR(task)) |
| 3309 | goto out; | 3296 | goto out; |
| @@ -3447,7 +3434,7 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f | |||
| 3447 | int ret; | 3434 | int ret; |
| 3448 | 3435 | ||
| 3449 | dprintk("%s: begin!\n", __FUNCTION__); | 3436 | dprintk("%s: begin!\n", __FUNCTION__); |
| 3450 | data = nfs4_alloc_lockdata(fl, fl->fl_file->private_data, | 3437 | data = nfs4_alloc_lockdata(fl, nfs_file_open_context(fl->fl_file), |
| 3451 | fl->fl_u.nfs4_fl.owner); | 3438 | fl->fl_u.nfs4_fl.owner); |
| 3452 | if (data == NULL) | 3439 | if (data == NULL) |
| 3453 | return -ENOMEM; | 3440 | return -ENOMEM; |
| @@ -3573,7 +3560,7 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request) | |||
| 3573 | int status; | 3560 | int status; |
| 3574 | 3561 | ||
| 3575 | /* verify open state */ | 3562 | /* verify open state */ |
| 3576 | ctx = (struct nfs_open_context *)filp->private_data; | 3563 | ctx = nfs_file_open_context(filp); |
| 3577 | state = ctx->state; | 3564 | state = ctx->state; |
| 3578 | 3565 | ||
| 3579 | if (request->fl_start < 0 || request->fl_end < 0) | 3566 | if (request->fl_start < 0 || request->fl_end < 0) |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 3e4adf8c8312..bfb36261cecb 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
| @@ -774,7 +774,7 @@ static int nfs4_reclaim_locks(struct nfs4_state_recovery_ops *ops, struct nfs4_s | |||
| 774 | for (fl = inode->i_flock; fl != 0; fl = fl->fl_next) { | 774 | for (fl = inode->i_flock; fl != 0; fl = fl->fl_next) { |
| 775 | if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) | 775 | if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) |
| 776 | continue; | 776 | continue; |
| 777 | if (((struct nfs_open_context *)fl->fl_file->private_data)->state != state) | 777 | if (nfs_file_open_context(fl->fl_file)->state != state) |
| 778 | continue; | 778 | continue; |
| 779 | status = ops->recover_lock(state, fl); | 779 | status = ops->recover_lock(state, fl); |
| 780 | if (status >= 0) | 780 | if (status >= 0) |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index badd73b7ca12..51dd3804866f 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
| @@ -376,10 +376,12 @@ static int nfs4_stat_to_errno(int); | |||
| 376 | decode_locku_maxsz) | 376 | decode_locku_maxsz) |
| 377 | #define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \ | 377 | #define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \ |
| 378 | encode_putfh_maxsz + \ | 378 | encode_putfh_maxsz + \ |
| 379 | encode_access_maxsz) | 379 | encode_access_maxsz + \ |
| 380 | encode_getattr_maxsz) | ||
| 380 | #define NFS4_dec_access_sz (compound_decode_hdr_maxsz + \ | 381 | #define NFS4_dec_access_sz (compound_decode_hdr_maxsz + \ |
| 381 | decode_putfh_maxsz + \ | 382 | decode_putfh_maxsz + \ |
| 382 | decode_access_maxsz) | 383 | decode_access_maxsz + \ |
| 384 | decode_getattr_maxsz) | ||
| 383 | #define NFS4_enc_getattr_sz (compound_encode_hdr_maxsz + \ | 385 | #define NFS4_enc_getattr_sz (compound_encode_hdr_maxsz + \ |
| 384 | encode_putfh_maxsz + \ | 386 | encode_putfh_maxsz + \ |
| 385 | encode_getattr_maxsz) | 387 | encode_getattr_maxsz) |
| @@ -562,7 +564,6 @@ struct compound_hdr { | |||
| 562 | 564 | ||
| 563 | #define RESERVE_SPACE(nbytes) do { \ | 565 | #define RESERVE_SPACE(nbytes) do { \ |
| 564 | p = xdr_reserve_space(xdr, nbytes); \ | 566 | p = xdr_reserve_space(xdr, nbytes); \ |
| 565 | if (!p) printk("RESERVE_SPACE(%d) failed in function %s\n", (int) (nbytes), __FUNCTION__); \ | ||
| 566 | BUG_ON(!p); \ | 567 | BUG_ON(!p); \ |
| 567 | } while (0) | 568 | } while (0) |
| 568 | 569 | ||
| @@ -628,8 +629,8 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const s | |||
| 628 | if (iap->ia_valid & ATTR_UID) { | 629 | if (iap->ia_valid & ATTR_UID) { |
| 629 | owner_namelen = nfs_map_uid_to_name(server->nfs_client, iap->ia_uid, owner_name); | 630 | owner_namelen = nfs_map_uid_to_name(server->nfs_client, iap->ia_uid, owner_name); |
| 630 | if (owner_namelen < 0) { | 631 | if (owner_namelen < 0) { |
| 631 | printk(KERN_WARNING "nfs: couldn't resolve uid %d to string\n", | 632 | dprintk("nfs: couldn't resolve uid %d to string\n", |
| 632 | iap->ia_uid); | 633 | iap->ia_uid); |
| 633 | /* XXX */ | 634 | /* XXX */ |
| 634 | strcpy(owner_name, "nobody"); | 635 | strcpy(owner_name, "nobody"); |
| 635 | owner_namelen = sizeof("nobody") - 1; | 636 | owner_namelen = sizeof("nobody") - 1; |
| @@ -640,8 +641,8 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const s | |||
| 640 | if (iap->ia_valid & ATTR_GID) { | 641 | if (iap->ia_valid & ATTR_GID) { |
| 641 | owner_grouplen = nfs_map_gid_to_group(server->nfs_client, iap->ia_gid, owner_group); | 642 | owner_grouplen = nfs_map_gid_to_group(server->nfs_client, iap->ia_gid, owner_group); |
| 642 | if (owner_grouplen < 0) { | 643 | if (owner_grouplen < 0) { |
| 643 | printk(KERN_WARNING "nfs4: couldn't resolve gid %d to string\n", | 644 | dprintk("nfs: couldn't resolve gid %d to string\n", |
| 644 | iap->ia_gid); | 645 | iap->ia_gid); |
| 645 | strcpy(owner_group, "nobody"); | 646 | strcpy(owner_group, "nobody"); |
| 646 | owner_grouplen = sizeof("nobody") - 1; | 647 | owner_grouplen = sizeof("nobody") - 1; |
| 647 | /* goto out; */ | 648 | /* goto out; */ |
| @@ -711,7 +712,7 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const s | |||
| 711 | * Now we backfill the bitmap and the attribute buffer length. | 712 | * Now we backfill the bitmap and the attribute buffer length. |
| 712 | */ | 713 | */ |
| 713 | if (len != ((char *)p - (char *)q) + 4) { | 714 | if (len != ((char *)p - (char *)q) + 4) { |
| 714 | printk ("encode_attr: Attr length calculation error! %u != %Zu\n", | 715 | printk(KERN_ERR "nfs: Attr length error, %u != %Zu\n", |
| 715 | len, ((char *)p - (char *)q) + 4); | 716 | len, ((char *)p - (char *)q) + 4); |
| 716 | BUG(); | 717 | BUG(); |
| 717 | } | 718 | } |
| @@ -1376,14 +1377,20 @@ static int nfs4_xdr_enc_access(struct rpc_rqst *req, __be32 *p, const struct nfs | |||
| 1376 | { | 1377 | { |
| 1377 | struct xdr_stream xdr; | 1378 | struct xdr_stream xdr; |
| 1378 | struct compound_hdr hdr = { | 1379 | struct compound_hdr hdr = { |
| 1379 | .nops = 2, | 1380 | .nops = 3, |
| 1380 | }; | 1381 | }; |
| 1381 | int status; | 1382 | int status; |
| 1382 | 1383 | ||
| 1383 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | 1384 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); |
| 1384 | encode_compound_hdr(&xdr, &hdr); | 1385 | encode_compound_hdr(&xdr, &hdr); |
| 1385 | if ((status = encode_putfh(&xdr, args->fh)) == 0) | 1386 | status = encode_putfh(&xdr, args->fh); |
| 1386 | status = encode_access(&xdr, args->access); | 1387 | if (status != 0) |
| 1388 | goto out; | ||
| 1389 | status = encode_access(&xdr, args->access); | ||
| 1390 | if (status != 0) | ||
| 1391 | goto out; | ||
| 1392 | status = encode_getfattr(&xdr, args->bitmask); | ||
| 1393 | out: | ||
| 1387 | return status; | 1394 | return status; |
| 1388 | } | 1395 | } |
| 1389 | 1396 | ||
| @@ -1857,6 +1864,7 @@ static int nfs4_xdr_enc_read(struct rpc_rqst *req, __be32 *p, struct nfs_readarg | |||
| 1857 | replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_dec_read_sz) << 2; | 1864 | replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_dec_read_sz) << 2; |
| 1858 | xdr_inline_pages(&req->rq_rcv_buf, replen, | 1865 | xdr_inline_pages(&req->rq_rcv_buf, replen, |
| 1859 | args->pages, args->pgbase, args->count); | 1866 | args->pages, args->pgbase, args->count); |
| 1867 | req->rq_rcv_buf.flags |= XDRBUF_READ; | ||
| 1860 | out: | 1868 | out: |
| 1861 | return status; | 1869 | return status; |
| 1862 | } | 1870 | } |
| @@ -1933,6 +1941,7 @@ static int nfs4_xdr_enc_write(struct rpc_rqst *req, __be32 *p, struct nfs_writea | |||
| 1933 | status = encode_write(&xdr, args); | 1941 | status = encode_write(&xdr, args); |
| 1934 | if (status) | 1942 | if (status) |
| 1935 | goto out; | 1943 | goto out; |
| 1944 | req->rq_snd_buf.flags |= XDRBUF_WRITE; | ||
| 1936 | status = encode_getfattr(&xdr, args->bitmask); | 1945 | status = encode_getfattr(&xdr, args->bitmask); |
| 1937 | out: | 1946 | out: |
| 1938 | return status; | 1947 | return status; |
| @@ -2180,9 +2189,9 @@ out: | |||
| 2180 | #define READ_BUF(nbytes) do { \ | 2189 | #define READ_BUF(nbytes) do { \ |
| 2181 | p = xdr_inline_decode(xdr, nbytes); \ | 2190 | p = xdr_inline_decode(xdr, nbytes); \ |
| 2182 | if (unlikely(!p)) { \ | 2191 | if (unlikely(!p)) { \ |
| 2183 | printk(KERN_INFO "%s: prematurely hit end of receive" \ | 2192 | dprintk("nfs: %s: prematurely hit end of receive" \ |
| 2184 | " buffer\n", __FUNCTION__); \ | 2193 | " buffer\n", __FUNCTION__); \ |
| 2185 | printk(KERN_INFO "%s: xdr->p=%p, bytes=%u, xdr->end=%p\n", \ | 2194 | dprintk("nfs: %s: xdr->p=%p, bytes=%u, xdr->end=%p\n", \ |
| 2186 | __FUNCTION__, xdr->p, nbytes, xdr->end); \ | 2195 | __FUNCTION__, xdr->p, nbytes, xdr->end); \ |
| 2187 | return -EIO; \ | 2196 | return -EIO; \ |
| 2188 | } \ | 2197 | } \ |
| @@ -2223,9 +2232,8 @@ static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected) | |||
| 2223 | READ_BUF(8); | 2232 | READ_BUF(8); |
| 2224 | READ32(opnum); | 2233 | READ32(opnum); |
| 2225 | if (opnum != expected) { | 2234 | if (opnum != expected) { |
| 2226 | printk(KERN_NOTICE | 2235 | dprintk("nfs: Server returned operation" |
| 2227 | "nfs4_decode_op_hdr: Server returned operation" | 2236 | " %d but we issued a request for %d\n", |
| 2228 | " %d but we issued a request for %d\n", | ||
| 2229 | opnum, expected); | 2237 | opnum, expected); |
| 2230 | return -EIO; | 2238 | return -EIO; |
| 2231 | } | 2239 | } |
| @@ -2758,7 +2766,7 @@ static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, struct nf | |||
| 2758 | dprintk("%s: nfs_map_name_to_uid failed!\n", | 2766 | dprintk("%s: nfs_map_name_to_uid failed!\n", |
| 2759 | __FUNCTION__); | 2767 | __FUNCTION__); |
| 2760 | } else | 2768 | } else |
| 2761 | printk(KERN_WARNING "%s: name too long (%u)!\n", | 2769 | dprintk("%s: name too long (%u)!\n", |
| 2762 | __FUNCTION__, len); | 2770 | __FUNCTION__, len); |
| 2763 | bitmap[1] &= ~FATTR4_WORD1_OWNER; | 2771 | bitmap[1] &= ~FATTR4_WORD1_OWNER; |
| 2764 | } | 2772 | } |
| @@ -2783,7 +2791,7 @@ static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, struct nf | |||
| 2783 | dprintk("%s: nfs_map_group_to_gid failed!\n", | 2791 | dprintk("%s: nfs_map_group_to_gid failed!\n", |
| 2784 | __FUNCTION__); | 2792 | __FUNCTION__); |
| 2785 | } else | 2793 | } else |
| 2786 | printk(KERN_WARNING "%s: name too long (%u)!\n", | 2794 | dprintk("%s: name too long (%u)!\n", |
| 2787 | __FUNCTION__, len); | 2795 | __FUNCTION__, len); |
| 2788 | bitmap[1] &= ~FATTR4_WORD1_OWNER_GROUP; | 2796 | bitmap[1] &= ~FATTR4_WORD1_OWNER_GROUP; |
| 2789 | } | 2797 | } |
| @@ -2950,7 +2958,8 @@ static int verify_attr_len(struct xdr_stream *xdr, __be32 *savep, uint32_t attrl | |||
| 2950 | unsigned int nwords = xdr->p - savep; | 2958 | unsigned int nwords = xdr->p - savep; |
| 2951 | 2959 | ||
| 2952 | if (unlikely(attrwords != nwords)) { | 2960 | if (unlikely(attrwords != nwords)) { |
| 2953 | printk(KERN_WARNING "%s: server returned incorrect attribute length: %u %c %u\n", | 2961 | dprintk("%s: server returned incorrect attribute length: " |
| 2962 | "%u %c %u\n", | ||
| 2954 | __FUNCTION__, | 2963 | __FUNCTION__, |
| 2955 | attrwords << 2, | 2964 | attrwords << 2, |
| 2956 | (attrwords < nwords) ? '<' : '>', | 2965 | (attrwords < nwords) ? '<' : '>', |
| @@ -3451,7 +3460,7 @@ static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_ | |||
| 3451 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; | 3460 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; |
| 3452 | recvd = req->rq_rcv_buf.len - hdrlen; | 3461 | recvd = req->rq_rcv_buf.len - hdrlen; |
| 3453 | if (count > recvd) { | 3462 | if (count > recvd) { |
| 3454 | printk(KERN_WARNING "NFS: server cheating in read reply: " | 3463 | dprintk("NFS: server cheating in read reply: " |
| 3455 | "count %u > recvd %u\n", count, recvd); | 3464 | "count %u > recvd %u\n", count, recvd); |
| 3456 | count = recvd; | 3465 | count = recvd; |
| 3457 | eof = 0; | 3466 | eof = 0; |
| @@ -3500,7 +3509,8 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n | |||
| 3500 | p += 2; /* cookie */ | 3509 | p += 2; /* cookie */ |
| 3501 | len = ntohl(*p++); /* filename length */ | 3510 | len = ntohl(*p++); /* filename length */ |
| 3502 | if (len > NFS4_MAXNAMLEN) { | 3511 | if (len > NFS4_MAXNAMLEN) { |
| 3503 | printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)\n", len); | 3512 | dprintk("NFS: giant filename in readdir (len 0x%x)\n", |
| 3513 | len); | ||
| 3504 | goto err_unmap; | 3514 | goto err_unmap; |
| 3505 | } | 3515 | } |
| 3506 | xlen = XDR_QUADLEN(len); | 3516 | xlen = XDR_QUADLEN(len); |
| @@ -3528,7 +3538,7 @@ short_pkt: | |||
| 3528 | entry[0] = entry[1] = 0; | 3538 | entry[0] = entry[1] = 0; |
| 3529 | /* truncate listing ? */ | 3539 | /* truncate listing ? */ |
| 3530 | if (!nr) { | 3540 | if (!nr) { |
| 3531 | printk(KERN_NOTICE "NFS: readdir reply truncated!\n"); | 3541 | dprintk("NFS: readdir reply truncated!\n"); |
| 3532 | entry[1] = 1; | 3542 | entry[1] = 1; |
| 3533 | } | 3543 | } |
| 3534 | goto out; | 3544 | goto out; |
| @@ -3554,13 +3564,13 @@ static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req) | |||
| 3554 | READ_BUF(4); | 3564 | READ_BUF(4); |
| 3555 | READ32(len); | 3565 | READ32(len); |
| 3556 | if (len >= rcvbuf->page_len || len <= 0) { | 3566 | if (len >= rcvbuf->page_len || len <= 0) { |
| 3557 | dprintk(KERN_WARNING "nfs: server returned giant symlink!\n"); | 3567 | dprintk("nfs: server returned giant symlink!\n"); |
| 3558 | return -ENAMETOOLONG; | 3568 | return -ENAMETOOLONG; |
| 3559 | } | 3569 | } |
| 3560 | hdrlen = (char *) xdr->p - (char *) iov->iov_base; | 3570 | hdrlen = (char *) xdr->p - (char *) iov->iov_base; |
| 3561 | recvd = req->rq_rcv_buf.len - hdrlen; | 3571 | recvd = req->rq_rcv_buf.len - hdrlen; |
| 3562 | if (recvd < len) { | 3572 | if (recvd < len) { |
| 3563 | printk(KERN_WARNING "NFS: server cheating in readlink reply: " | 3573 | dprintk("NFS: server cheating in readlink reply: " |
| 3564 | "count %u > recvd %u\n", len, recvd); | 3574 | "count %u > recvd %u\n", len, recvd); |
| 3565 | return -EIO; | 3575 | return -EIO; |
| 3566 | } | 3576 | } |
| @@ -3643,7 +3653,7 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
| 3643 | hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base; | 3653 | hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base; |
| 3644 | recvd = req->rq_rcv_buf.len - hdrlen; | 3654 | recvd = req->rq_rcv_buf.len - hdrlen; |
| 3645 | if (attrlen > recvd) { | 3655 | if (attrlen > recvd) { |
| 3646 | printk(KERN_WARNING "NFS: server cheating in getattr" | 3656 | dprintk("NFS: server cheating in getattr" |
| 3647 | " acl reply: attrlen %u > recvd %u\n", | 3657 | " acl reply: attrlen %u > recvd %u\n", |
| 3648 | attrlen, recvd); | 3658 | attrlen, recvd); |
| 3649 | return -EINVAL; | 3659 | return -EINVAL; |
| @@ -3688,8 +3698,7 @@ static int decode_setclientid(struct xdr_stream *xdr, struct nfs_client *clp) | |||
| 3688 | READ_BUF(8); | 3698 | READ_BUF(8); |
| 3689 | READ32(opnum); | 3699 | READ32(opnum); |
| 3690 | if (opnum != OP_SETCLIENTID) { | 3700 | if (opnum != OP_SETCLIENTID) { |
| 3691 | printk(KERN_NOTICE | 3701 | dprintk("nfs: decode_setclientid: Server returned operation" |
| 3692 | "nfs4_decode_setclientid: Server returned operation" | ||
| 3693 | " %d\n", opnum); | 3702 | " %d\n", opnum); |
| 3694 | return -EIO; | 3703 | return -EIO; |
| 3695 | } | 3704 | } |
| @@ -3783,8 +3792,13 @@ static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_ac | |||
| 3783 | xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); | 3792 | xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); |
| 3784 | if ((status = decode_compound_hdr(&xdr, &hdr)) != 0) | 3793 | if ((status = decode_compound_hdr(&xdr, &hdr)) != 0) |
| 3785 | goto out; | 3794 | goto out; |
| 3786 | if ((status = decode_putfh(&xdr)) == 0) | 3795 | status = decode_putfh(&xdr); |
| 3787 | status = decode_access(&xdr, res); | 3796 | if (status != 0) |
| 3797 | goto out; | ||
| 3798 | status = decode_access(&xdr, res); | ||
| 3799 | if (status != 0) | ||
| 3800 | goto out; | ||
| 3801 | decode_getfattr(&xdr, res->fattr, res->server); | ||
| 3788 | out: | 3802 | out: |
| 3789 | return status; | 3803 | return status; |
| 3790 | } | 3804 | } |
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c index 3490322d1145..e87b44ee9ac9 100644 --- a/fs/nfs/nfsroot.c +++ b/fs/nfs/nfsroot.c | |||
| @@ -76,6 +76,7 @@ | |||
| 76 | #include <linux/fs.h> | 76 | #include <linux/fs.h> |
| 77 | #include <linux/init.h> | 77 | #include <linux/init.h> |
| 78 | #include <linux/sunrpc/clnt.h> | 78 | #include <linux/sunrpc/clnt.h> |
| 79 | #include <linux/sunrpc/xprtsock.h> | ||
| 79 | #include <linux/nfs.h> | 80 | #include <linux/nfs.h> |
| 80 | #include <linux/nfs_fs.h> | 81 | #include <linux/nfs_fs.h> |
| 81 | #include <linux/nfs_mount.h> | 82 | #include <linux/nfs_mount.h> |
| @@ -491,7 +492,7 @@ static int __init root_nfs_get_handle(void) | |||
| 491 | struct sockaddr_in sin; | 492 | struct sockaddr_in sin; |
| 492 | int status; | 493 | int status; |
| 493 | int protocol = (nfs_data.flags & NFS_MOUNT_TCP) ? | 494 | int protocol = (nfs_data.flags & NFS_MOUNT_TCP) ? |
| 494 | IPPROTO_TCP : IPPROTO_UDP; | 495 | XPRT_TRANSPORT_TCP : XPRT_TRANSPORT_UDP; |
| 495 | int version = (nfs_data.flags & NFS_MOUNT_VER3) ? | 496 | int version = (nfs_data.flags & NFS_MOUNT_VER3) ? |
| 496 | NFS_MNT3_VERSION : NFS_MNT_VERSION; | 497 | NFS_MNT3_VERSION : NFS_MNT_VERSION; |
| 497 | 498 | ||
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index 845cdde1d8b7..97669ed05500 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
| @@ -476,6 +476,8 @@ nfs_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | |||
| 476 | dprintk("NFS call readdir %d\n", (unsigned int)cookie); | 476 | dprintk("NFS call readdir %d\n", (unsigned int)cookie); |
| 477 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 477 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
| 478 | 478 | ||
| 479 | nfs_invalidate_atime(dir); | ||
| 480 | |||
| 479 | dprintk("NFS reply readdir: %d\n", status); | 481 | dprintk("NFS reply readdir: %d\n", status); |
| 480 | return status; | 482 | return status; |
| 481 | } | 483 | } |
| @@ -550,6 +552,7 @@ nfs_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 550 | 552 | ||
| 551 | static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data) | 553 | static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data) |
| 552 | { | 554 | { |
| 555 | nfs_invalidate_atime(data->inode); | ||
| 553 | if (task->tk_status >= 0) { | 556 | if (task->tk_status >= 0) { |
| 554 | nfs_refresh_inode(data->inode, data->res.fattr); | 557 | nfs_refresh_inode(data->inode, data->res.fattr); |
| 555 | /* Emulate the eof flag, which isn't normally needed in NFSv2 | 558 | /* Emulate the eof flag, which isn't normally needed in NFSv2 |
| @@ -576,7 +579,7 @@ static void nfs_proc_read_setup(struct nfs_read_data *data) | |||
| 576 | static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data) | 579 | static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data) |
| 577 | { | 580 | { |
| 578 | if (task->tk_status >= 0) | 581 | if (task->tk_status >= 0) |
| 579 | nfs_post_op_update_inode(data->inode, data->res.fattr); | 582 | nfs_post_op_update_inode_force_wcc(data->inode, data->res.fattr); |
| 580 | return 0; | 583 | return 0; |
| 581 | } | 584 | } |
| 582 | 585 | ||
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 19e05633f4e3..4587a86adaac 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
| @@ -341,9 +341,6 @@ int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data) | |||
| 341 | set_bit(NFS_INO_STALE, &NFS_FLAGS(data->inode)); | 341 | set_bit(NFS_INO_STALE, &NFS_FLAGS(data->inode)); |
| 342 | nfs_mark_for_revalidate(data->inode); | 342 | nfs_mark_for_revalidate(data->inode); |
| 343 | } | 343 | } |
| 344 | spin_lock(&data->inode->i_lock); | ||
| 345 | NFS_I(data->inode)->cache_validity |= NFS_INO_INVALID_ATIME; | ||
| 346 | spin_unlock(&data->inode->i_lock); | ||
| 347 | return 0; | 344 | return 0; |
| 348 | } | 345 | } |
| 349 | 346 | ||
| @@ -497,8 +494,7 @@ int nfs_readpage(struct file *file, struct page *page) | |||
| 497 | if (ctx == NULL) | 494 | if (ctx == NULL) |
| 498 | goto out_unlock; | 495 | goto out_unlock; |
| 499 | } else | 496 | } else |
| 500 | ctx = get_nfs_open_context((struct nfs_open_context *) | 497 | ctx = get_nfs_open_context(nfs_file_open_context(file)); |
| 501 | file->private_data); | ||
| 502 | 498 | ||
| 503 | error = nfs_readpage_async(ctx, inode, page); | 499 | error = nfs_readpage_async(ctx, inode, page); |
| 504 | 500 | ||
| @@ -576,8 +572,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping, | |||
| 576 | if (desc.ctx == NULL) | 572 | if (desc.ctx == NULL) |
| 577 | return -EBADF; | 573 | return -EBADF; |
| 578 | } else | 574 | } else |
| 579 | desc.ctx = get_nfs_open_context((struct nfs_open_context *) | 575 | desc.ctx = get_nfs_open_context(nfs_file_open_context(filp)); |
| 580 | filp->private_data); | ||
| 581 | if (rsize < PAGE_CACHE_SIZE) | 576 | if (rsize < PAGE_CACHE_SIZE) |
| 582 | nfs_pageio_init(&pgio, inode, nfs_pagein_multi, rsize, 0); | 577 | nfs_pageio_init(&pgio, inode, nfs_pagein_multi, rsize, 0); |
| 583 | else | 578 | else |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index b878528b64c1..fa517ae9207f 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
| @@ -33,6 +33,8 @@ | |||
| 33 | #include <linux/sunrpc/clnt.h> | 33 | #include <linux/sunrpc/clnt.h> |
| 34 | #include <linux/sunrpc/stats.h> | 34 | #include <linux/sunrpc/stats.h> |
| 35 | #include <linux/sunrpc/metrics.h> | 35 | #include <linux/sunrpc/metrics.h> |
| 36 | #include <linux/sunrpc/xprtsock.h> | ||
| 37 | #include <linux/sunrpc/xprtrdma.h> | ||
| 36 | #include <linux/nfs_fs.h> | 38 | #include <linux/nfs_fs.h> |
| 37 | #include <linux/nfs_mount.h> | 39 | #include <linux/nfs_mount.h> |
| 38 | #include <linux/nfs4_mount.h> | 40 | #include <linux/nfs4_mount.h> |
| @@ -58,36 +60,6 @@ | |||
| 58 | 60 | ||
| 59 | #define NFSDBG_FACILITY NFSDBG_VFS | 61 | #define NFSDBG_FACILITY NFSDBG_VFS |
| 60 | 62 | ||
| 61 | |||
| 62 | struct nfs_parsed_mount_data { | ||
| 63 | int flags; | ||
| 64 | int rsize, wsize; | ||
| 65 | int timeo, retrans; | ||
| 66 | int acregmin, acregmax, | ||
| 67 | acdirmin, acdirmax; | ||
| 68 | int namlen; | ||
| 69 | unsigned int bsize; | ||
| 70 | unsigned int auth_flavor_len; | ||
| 71 | rpc_authflavor_t auth_flavors[1]; | ||
| 72 | char *client_address; | ||
| 73 | |||
| 74 | struct { | ||
| 75 | struct sockaddr_in address; | ||
| 76 | unsigned int program; | ||
| 77 | unsigned int version; | ||
| 78 | unsigned short port; | ||
| 79 | int protocol; | ||
| 80 | } mount_server; | ||
| 81 | |||
| 82 | struct { | ||
| 83 | struct sockaddr_in address; | ||
| 84 | char *hostname; | ||
| 85 | char *export_path; | ||
| 86 | unsigned int program; | ||
| 87 | int protocol; | ||
| 88 | } nfs_server; | ||
| 89 | }; | ||
| 90 | |||
| 91 | enum { | 63 | enum { |
| 92 | /* Mount options that take no arguments */ | 64 | /* Mount options that take no arguments */ |
| 93 | Opt_soft, Opt_hard, | 65 | Opt_soft, Opt_hard, |
| @@ -97,7 +69,7 @@ enum { | |||
| 97 | Opt_ac, Opt_noac, | 69 | Opt_ac, Opt_noac, |
| 98 | Opt_lock, Opt_nolock, | 70 | Opt_lock, Opt_nolock, |
| 99 | Opt_v2, Opt_v3, | 71 | Opt_v2, Opt_v3, |
| 100 | Opt_udp, Opt_tcp, | 72 | Opt_udp, Opt_tcp, Opt_rdma, |
| 101 | Opt_acl, Opt_noacl, | 73 | Opt_acl, Opt_noacl, |
| 102 | Opt_rdirplus, Opt_nordirplus, | 74 | Opt_rdirplus, Opt_nordirplus, |
| 103 | Opt_sharecache, Opt_nosharecache, | 75 | Opt_sharecache, Opt_nosharecache, |
| @@ -116,7 +88,7 @@ enum { | |||
| 116 | 88 | ||
| 117 | /* Mount options that take string arguments */ | 89 | /* Mount options that take string arguments */ |
| 118 | Opt_sec, Opt_proto, Opt_mountproto, | 90 | Opt_sec, Opt_proto, Opt_mountproto, |
| 119 | Opt_addr, Opt_mounthost, Opt_clientaddr, | 91 | Opt_addr, Opt_mountaddr, Opt_clientaddr, |
| 120 | 92 | ||
| 121 | /* Mount options that are ignored */ | 93 | /* Mount options that are ignored */ |
| 122 | Opt_userspace, Opt_deprecated, | 94 | Opt_userspace, Opt_deprecated, |
| @@ -143,6 +115,7 @@ static match_table_t nfs_mount_option_tokens = { | |||
| 143 | { Opt_v3, "v3" }, | 115 | { Opt_v3, "v3" }, |
| 144 | { Opt_udp, "udp" }, | 116 | { Opt_udp, "udp" }, |
| 145 | { Opt_tcp, "tcp" }, | 117 | { Opt_tcp, "tcp" }, |
| 118 | { Opt_rdma, "rdma" }, | ||
| 146 | { Opt_acl, "acl" }, | 119 | { Opt_acl, "acl" }, |
| 147 | { Opt_noacl, "noacl" }, | 120 | { Opt_noacl, "noacl" }, |
| 148 | { Opt_rdirplus, "rdirplus" }, | 121 | { Opt_rdirplus, "rdirplus" }, |
| @@ -175,13 +148,14 @@ static match_table_t nfs_mount_option_tokens = { | |||
| 175 | { Opt_mountproto, "mountproto=%s" }, | 148 | { Opt_mountproto, "mountproto=%s" }, |
| 176 | { Opt_addr, "addr=%s" }, | 149 | { Opt_addr, "addr=%s" }, |
| 177 | { Opt_clientaddr, "clientaddr=%s" }, | 150 | { Opt_clientaddr, "clientaddr=%s" }, |
| 178 | { Opt_mounthost, "mounthost=%s" }, | 151 | { Opt_userspace, "mounthost=%s" }, |
| 152 | { Opt_mountaddr, "mountaddr=%s" }, | ||
| 179 | 153 | ||
| 180 | { Opt_err, NULL } | 154 | { Opt_err, NULL } |
| 181 | }; | 155 | }; |
| 182 | 156 | ||
| 183 | enum { | 157 | enum { |
| 184 | Opt_xprt_udp, Opt_xprt_tcp, | 158 | Opt_xprt_udp, Opt_xprt_tcp, Opt_xprt_rdma, |
| 185 | 159 | ||
| 186 | Opt_xprt_err | 160 | Opt_xprt_err |
| 187 | }; | 161 | }; |
| @@ -189,6 +163,7 @@ enum { | |||
| 189 | static match_table_t nfs_xprt_protocol_tokens = { | 163 | static match_table_t nfs_xprt_protocol_tokens = { |
| 190 | { Opt_xprt_udp, "udp" }, | 164 | { Opt_xprt_udp, "udp" }, |
| 191 | { Opt_xprt_tcp, "tcp" }, | 165 | { Opt_xprt_tcp, "tcp" }, |
| 166 | { Opt_xprt_rdma, "rdma" }, | ||
| 192 | 167 | ||
| 193 | { Opt_xprt_err, NULL } | 168 | { Opt_xprt_err, NULL } |
| 194 | }; | 169 | }; |
| @@ -449,7 +424,7 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, | |||
| 449 | const char *nostr; | 424 | const char *nostr; |
| 450 | } nfs_info[] = { | 425 | } nfs_info[] = { |
| 451 | { NFS_MOUNT_SOFT, ",soft", ",hard" }, | 426 | { NFS_MOUNT_SOFT, ",soft", ",hard" }, |
| 452 | { NFS_MOUNT_INTR, ",intr", "" }, | 427 | { NFS_MOUNT_INTR, ",intr", ",nointr" }, |
| 453 | { NFS_MOUNT_NOCTO, ",nocto", "" }, | 428 | { NFS_MOUNT_NOCTO, ",nocto", "" }, |
| 454 | { NFS_MOUNT_NOAC, ",noac", "" }, | 429 | { NFS_MOUNT_NOAC, ",noac", "" }, |
| 455 | { NFS_MOUNT_NONLM, ",nolock", "" }, | 430 | { NFS_MOUNT_NONLM, ",nolock", "" }, |
| @@ -460,8 +435,6 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, | |||
| 460 | }; | 435 | }; |
| 461 | const struct proc_nfs_info *nfs_infop; | 436 | const struct proc_nfs_info *nfs_infop; |
| 462 | struct nfs_client *clp = nfss->nfs_client; | 437 | struct nfs_client *clp = nfss->nfs_client; |
| 463 | char buf[12]; | ||
| 464 | const char *proto; | ||
| 465 | 438 | ||
| 466 | seq_printf(m, ",vers=%d", clp->rpc_ops->version); | 439 | seq_printf(m, ",vers=%d", clp->rpc_ops->version); |
| 467 | seq_printf(m, ",rsize=%d", nfss->rsize); | 440 | seq_printf(m, ",rsize=%d", nfss->rsize); |
| @@ -480,18 +453,8 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, | |||
| 480 | else | 453 | else |
| 481 | seq_puts(m, nfs_infop->nostr); | 454 | seq_puts(m, nfs_infop->nostr); |
| 482 | } | 455 | } |
| 483 | switch (nfss->client->cl_xprt->prot) { | 456 | seq_printf(m, ",proto=%s", |
| 484 | case IPPROTO_TCP: | 457 | rpc_peeraddr2str(nfss->client, RPC_DISPLAY_PROTO)); |
| 485 | proto = "tcp"; | ||
| 486 | break; | ||
| 487 | case IPPROTO_UDP: | ||
| 488 | proto = "udp"; | ||
| 489 | break; | ||
| 490 | default: | ||
| 491 | snprintf(buf, sizeof(buf), "%u", nfss->client->cl_xprt->prot); | ||
| 492 | proto = buf; | ||
| 493 | } | ||
| 494 | seq_printf(m, ",proto=%s", proto); | ||
| 495 | seq_printf(m, ",timeo=%lu", 10U * clp->retrans_timeo / HZ); | 458 | seq_printf(m, ",timeo=%lu", 10U * clp->retrans_timeo / HZ); |
| 496 | seq_printf(m, ",retrans=%u", clp->retrans_count); | 459 | seq_printf(m, ",retrans=%u", clp->retrans_count); |
| 497 | seq_printf(m, ",sec=%s", nfs_pseudoflavour_to_name(nfss->client->cl_auth->au_flavor)); | 460 | seq_printf(m, ",sec=%s", nfs_pseudoflavour_to_name(nfss->client->cl_auth->au_flavor)); |
| @@ -506,8 +469,8 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
| 506 | 469 | ||
| 507 | nfs_show_mount_options(m, nfss, 0); | 470 | nfs_show_mount_options(m, nfss, 0); |
| 508 | 471 | ||
| 509 | seq_puts(m, ",addr="); | 472 | seq_printf(m, ",addr="NIPQUAD_FMT, |
| 510 | seq_escape(m, nfss->nfs_client->cl_hostname, " \t\n\\"); | 473 | NIPQUAD(nfss->nfs_client->cl_addr.sin_addr)); |
| 511 | 474 | ||
| 512 | return 0; | 475 | return 0; |
| 513 | } | 476 | } |
| @@ -698,13 +661,19 @@ static int nfs_parse_mount_options(char *raw, | |||
| 698 | break; | 661 | break; |
| 699 | case Opt_udp: | 662 | case Opt_udp: |
| 700 | mnt->flags &= ~NFS_MOUNT_TCP; | 663 | mnt->flags &= ~NFS_MOUNT_TCP; |
| 701 | mnt->nfs_server.protocol = IPPROTO_UDP; | 664 | mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP; |
| 702 | mnt->timeo = 7; | 665 | mnt->timeo = 7; |
| 703 | mnt->retrans = 5; | 666 | mnt->retrans = 5; |
| 704 | break; | 667 | break; |
| 705 | case Opt_tcp: | 668 | case Opt_tcp: |
| 706 | mnt->flags |= NFS_MOUNT_TCP; | 669 | mnt->flags |= NFS_MOUNT_TCP; |
| 707 | mnt->nfs_server.protocol = IPPROTO_TCP; | 670 | mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP; |
| 671 | mnt->timeo = 600; | ||
| 672 | mnt->retrans = 2; | ||
| 673 | break; | ||
| 674 | case Opt_rdma: | ||
| 675 | mnt->flags |= NFS_MOUNT_TCP; /* for side protocols */ | ||
| 676 | mnt->nfs_server.protocol = XPRT_TRANSPORT_RDMA; | ||
| 708 | mnt->timeo = 600; | 677 | mnt->timeo = 600; |
| 709 | mnt->retrans = 2; | 678 | mnt->retrans = 2; |
| 710 | break; | 679 | break; |
| @@ -913,13 +882,20 @@ static int nfs_parse_mount_options(char *raw, | |||
| 913 | switch (token) { | 882 | switch (token) { |
| 914 | case Opt_xprt_udp: | 883 | case Opt_xprt_udp: |
| 915 | mnt->flags &= ~NFS_MOUNT_TCP; | 884 | mnt->flags &= ~NFS_MOUNT_TCP; |
| 916 | mnt->nfs_server.protocol = IPPROTO_UDP; | 885 | mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP; |
| 917 | mnt->timeo = 7; | 886 | mnt->timeo = 7; |
| 918 | mnt->retrans = 5; | 887 | mnt->retrans = 5; |
| 919 | break; | 888 | break; |
| 920 | case Opt_xprt_tcp: | 889 | case Opt_xprt_tcp: |
| 921 | mnt->flags |= NFS_MOUNT_TCP; | 890 | mnt->flags |= NFS_MOUNT_TCP; |
| 922 | mnt->nfs_server.protocol = IPPROTO_TCP; | 891 | mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP; |
| 892 | mnt->timeo = 600; | ||
| 893 | mnt->retrans = 2; | ||
| 894 | break; | ||
| 895 | case Opt_xprt_rdma: | ||
| 896 | /* vector side protocols to TCP */ | ||
| 897 | mnt->flags |= NFS_MOUNT_TCP; | ||
| 898 | mnt->nfs_server.protocol = XPRT_TRANSPORT_RDMA; | ||
| 923 | mnt->timeo = 600; | 899 | mnt->timeo = 600; |
| 924 | mnt->retrans = 2; | 900 | mnt->retrans = 2; |
| 925 | break; | 901 | break; |
| @@ -937,11 +913,12 @@ static int nfs_parse_mount_options(char *raw, | |||
| 937 | 913 | ||
| 938 | switch (token) { | 914 | switch (token) { |
| 939 | case Opt_xprt_udp: | 915 | case Opt_xprt_udp: |
| 940 | mnt->mount_server.protocol = IPPROTO_UDP; | 916 | mnt->mount_server.protocol = XPRT_TRANSPORT_UDP; |
| 941 | break; | 917 | break; |
| 942 | case Opt_xprt_tcp: | 918 | case Opt_xprt_tcp: |
| 943 | mnt->mount_server.protocol = IPPROTO_TCP; | 919 | mnt->mount_server.protocol = XPRT_TRANSPORT_TCP; |
| 944 | break; | 920 | break; |
| 921 | case Opt_xprt_rdma: /* not used for side protocols */ | ||
| 945 | default: | 922 | default: |
| 946 | goto out_unrec_xprt; | 923 | goto out_unrec_xprt; |
| 947 | } | 924 | } |
| @@ -961,7 +938,7 @@ static int nfs_parse_mount_options(char *raw, | |||
| 961 | goto out_nomem; | 938 | goto out_nomem; |
| 962 | mnt->client_address = string; | 939 | mnt->client_address = string; |
| 963 | break; | 940 | break; |
| 964 | case Opt_mounthost: | 941 | case Opt_mountaddr: |
| 965 | string = match_strdup(args); | 942 | string = match_strdup(args); |
| 966 | if (string == NULL) | 943 | if (string == NULL) |
| 967 | goto out_nomem; | 944 | goto out_nomem; |
| @@ -1027,16 +1004,10 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args, | |||
| 1027 | sin = args->mount_server.address; | 1004 | sin = args->mount_server.address; |
| 1028 | else | 1005 | else |
| 1029 | sin = args->nfs_server.address; | 1006 | sin = args->nfs_server.address; |
| 1030 | if (args->mount_server.port == 0) { | 1007 | /* |
| 1031 | status = rpcb_getport_sync(&sin, | 1008 | * autobind will be used if mount_server.port == 0 |
| 1032 | args->mount_server.program, | 1009 | */ |
| 1033 | args->mount_server.version, | 1010 | sin.sin_port = htons(args->mount_server.port); |
| 1034 | args->mount_server.protocol); | ||
| 1035 | if (status < 0) | ||
| 1036 | goto out_err; | ||
| 1037 | sin.sin_port = htons(status); | ||
| 1038 | } else | ||
| 1039 | sin.sin_port = htons(args->mount_server.port); | ||
| 1040 | 1011 | ||
| 1041 | /* | 1012 | /* |
| 1042 | * Now ask the mount server to map our export path | 1013 | * Now ask the mount server to map our export path |
| @@ -1049,14 +1020,11 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args, | |||
| 1049 | args->mount_server.version, | 1020 | args->mount_server.version, |
| 1050 | args->mount_server.protocol, | 1021 | args->mount_server.protocol, |
| 1051 | root_fh); | 1022 | root_fh); |
| 1052 | if (status < 0) | 1023 | if (status == 0) |
| 1053 | goto out_err; | 1024 | return 0; |
| 1054 | |||
| 1055 | return status; | ||
| 1056 | 1025 | ||
| 1057 | out_err: | 1026 | dfprintk(MOUNT, "NFS: unable to mount server " NIPQUAD_FMT |
| 1058 | dfprintk(MOUNT, "NFS: unable to contact server on host " | 1027 | ", error %d\n", NIPQUAD(sin.sin_addr.s_addr), status); |
| 1059 | NIPQUAD_FMT "\n", NIPQUAD(sin.sin_addr.s_addr)); | ||
| 1060 | return status; | 1028 | return status; |
| 1061 | } | 1029 | } |
| 1062 | 1030 | ||
| @@ -1079,15 +1047,31 @@ out_err: | |||
| 1079 | * XXX: as far as I can tell, changing the NFS program number is not | 1047 | * XXX: as far as I can tell, changing the NFS program number is not |
| 1080 | * supported in the NFS client. | 1048 | * supported in the NFS client. |
| 1081 | */ | 1049 | */ |
| 1082 | static int nfs_validate_mount_data(struct nfs_mount_data **options, | 1050 | static int nfs_validate_mount_data(void *options, |
| 1051 | struct nfs_parsed_mount_data *args, | ||
| 1083 | struct nfs_fh *mntfh, | 1052 | struct nfs_fh *mntfh, |
| 1084 | const char *dev_name) | 1053 | const char *dev_name) |
| 1085 | { | 1054 | { |
| 1086 | struct nfs_mount_data *data = *options; | 1055 | struct nfs_mount_data *data = (struct nfs_mount_data *)options; |
| 1087 | 1056 | ||
| 1088 | if (data == NULL) | 1057 | if (data == NULL) |
| 1089 | goto out_no_data; | 1058 | goto out_no_data; |
| 1090 | 1059 | ||
| 1060 | memset(args, 0, sizeof(*args)); | ||
| 1061 | args->flags = (NFS_MOUNT_VER3 | NFS_MOUNT_TCP); | ||
| 1062 | args->rsize = NFS_MAX_FILE_IO_SIZE; | ||
| 1063 | args->wsize = NFS_MAX_FILE_IO_SIZE; | ||
| 1064 | args->timeo = 600; | ||
| 1065 | args->retrans = 2; | ||
| 1066 | args->acregmin = 3; | ||
| 1067 | args->acregmax = 60; | ||
| 1068 | args->acdirmin = 30; | ||
| 1069 | args->acdirmax = 60; | ||
| 1070 | args->mount_server.protocol = XPRT_TRANSPORT_UDP; | ||
| 1071 | args->mount_server.program = NFS_MNT_PROGRAM; | ||
| 1072 | args->nfs_server.protocol = XPRT_TRANSPORT_TCP; | ||
| 1073 | args->nfs_server.program = NFS_PROGRAM; | ||
| 1074 | |||
| 1091 | switch (data->version) { | 1075 | switch (data->version) { |
| 1092 | case 1: | 1076 | case 1: |
| 1093 | data->namlen = 0; | 1077 | data->namlen = 0; |
| @@ -1116,92 +1100,73 @@ static int nfs_validate_mount_data(struct nfs_mount_data **options, | |||
| 1116 | if (mntfh->size < sizeof(mntfh->data)) | 1100 | if (mntfh->size < sizeof(mntfh->data)) |
| 1117 | memset(mntfh->data + mntfh->size, 0, | 1101 | memset(mntfh->data + mntfh->size, 0, |
| 1118 | sizeof(mntfh->data) - mntfh->size); | 1102 | sizeof(mntfh->data) - mntfh->size); |
| 1103 | |||
| 1104 | if (!nfs_verify_server_address((struct sockaddr *) &data->addr)) | ||
| 1105 | goto out_no_address; | ||
| 1106 | |||
| 1107 | /* | ||
| 1108 | * Translate to nfs_parsed_mount_data, which nfs_fill_super | ||
| 1109 | * can deal with. | ||
| 1110 | */ | ||
| 1111 | args->flags = data->flags; | ||
| 1112 | args->rsize = data->rsize; | ||
| 1113 | args->wsize = data->wsize; | ||
| 1114 | args->flags = data->flags; | ||
| 1115 | args->timeo = data->timeo; | ||
| 1116 | args->retrans = data->retrans; | ||
| 1117 | args->acregmin = data->acregmin; | ||
| 1118 | args->acregmax = data->acregmax; | ||
| 1119 | args->acdirmin = data->acdirmin; | ||
| 1120 | args->acdirmax = data->acdirmax; | ||
| 1121 | args->nfs_server.address = data->addr; | ||
| 1122 | if (!(data->flags & NFS_MOUNT_TCP)) | ||
| 1123 | args->nfs_server.protocol = XPRT_TRANSPORT_UDP; | ||
| 1124 | /* N.B. caller will free nfs_server.hostname in all cases */ | ||
| 1125 | args->nfs_server.hostname = kstrdup(data->hostname, GFP_KERNEL); | ||
| 1126 | args->namlen = data->namlen; | ||
| 1127 | args->bsize = data->bsize; | ||
| 1128 | args->auth_flavors[0] = data->pseudoflavor; | ||
| 1119 | break; | 1129 | break; |
| 1120 | default: { | 1130 | default: { |
| 1121 | unsigned int len; | 1131 | unsigned int len; |
| 1122 | char *c; | 1132 | char *c; |
| 1123 | int status; | 1133 | int status; |
| 1124 | struct nfs_parsed_mount_data args = { | ||
| 1125 | .flags = (NFS_MOUNT_VER3 | NFS_MOUNT_TCP), | ||
| 1126 | .rsize = NFS_MAX_FILE_IO_SIZE, | ||
| 1127 | .wsize = NFS_MAX_FILE_IO_SIZE, | ||
| 1128 | .timeo = 600, | ||
| 1129 | .retrans = 2, | ||
| 1130 | .acregmin = 3, | ||
| 1131 | .acregmax = 60, | ||
| 1132 | .acdirmin = 30, | ||
| 1133 | .acdirmax = 60, | ||
| 1134 | .mount_server.protocol = IPPROTO_UDP, | ||
| 1135 | .mount_server.program = NFS_MNT_PROGRAM, | ||
| 1136 | .nfs_server.protocol = IPPROTO_TCP, | ||
| 1137 | .nfs_server.program = NFS_PROGRAM, | ||
| 1138 | }; | ||
| 1139 | |||
| 1140 | if (nfs_parse_mount_options((char *) *options, &args) == 0) | ||
| 1141 | return -EINVAL; | ||
| 1142 | 1134 | ||
| 1143 | data = kzalloc(sizeof(*data), GFP_KERNEL); | 1135 | if (nfs_parse_mount_options((char *)options, args) == 0) |
| 1144 | if (data == NULL) | 1136 | return -EINVAL; |
| 1145 | return -ENOMEM; | ||
| 1146 | 1137 | ||
| 1147 | /* | 1138 | if (!nfs_verify_server_address((struct sockaddr *) |
| 1148 | * NB: after this point, caller will free "data" | 1139 | &args->nfs_server.address)) |
| 1149 | * if we return an error | 1140 | goto out_no_address; |
| 1150 | */ | ||
| 1151 | *options = data; | ||
| 1152 | 1141 | ||
| 1153 | c = strchr(dev_name, ':'); | 1142 | c = strchr(dev_name, ':'); |
| 1154 | if (c == NULL) | 1143 | if (c == NULL) |
| 1155 | return -EINVAL; | 1144 | return -EINVAL; |
| 1156 | len = c - dev_name; | 1145 | len = c - dev_name; |
| 1157 | if (len > sizeof(data->hostname)) | 1146 | /* N.B. caller will free nfs_server.hostname in all cases */ |
| 1158 | return -ENAMETOOLONG; | 1147 | args->nfs_server.hostname = kstrndup(dev_name, len, GFP_KERNEL); |
| 1159 | strncpy(data->hostname, dev_name, len); | ||
| 1160 | args.nfs_server.hostname = data->hostname; | ||
| 1161 | 1148 | ||
| 1162 | c++; | 1149 | c++; |
| 1163 | if (strlen(c) > NFS_MAXPATHLEN) | 1150 | if (strlen(c) > NFS_MAXPATHLEN) |
| 1164 | return -ENAMETOOLONG; | 1151 | return -ENAMETOOLONG; |
| 1165 | args.nfs_server.export_path = c; | 1152 | args->nfs_server.export_path = c; |
| 1166 | 1153 | ||
| 1167 | status = nfs_try_mount(&args, mntfh); | 1154 | status = nfs_try_mount(args, mntfh); |
| 1168 | if (status) | 1155 | if (status) |
| 1169 | return status; | 1156 | return status; |
| 1170 | 1157 | ||
| 1171 | /* | ||
| 1172 | * Translate to nfs_mount_data, which nfs_fill_super | ||
| 1173 | * can deal with. | ||
| 1174 | */ | ||
| 1175 | data->version = 6; | ||
| 1176 | data->flags = args.flags; | ||
| 1177 | data->rsize = args.rsize; | ||
| 1178 | data->wsize = args.wsize; | ||
| 1179 | data->timeo = args.timeo; | ||
| 1180 | data->retrans = args.retrans; | ||
| 1181 | data->acregmin = args.acregmin; | ||
| 1182 | data->acregmax = args.acregmax; | ||
| 1183 | data->acdirmin = args.acdirmin; | ||
| 1184 | data->acdirmax = args.acdirmax; | ||
| 1185 | data->addr = args.nfs_server.address; | ||
| 1186 | data->namlen = args.namlen; | ||
| 1187 | data->bsize = args.bsize; | ||
| 1188 | data->pseudoflavor = args.auth_flavors[0]; | ||
| 1189 | |||
| 1190 | break; | 1158 | break; |
| 1191 | } | 1159 | } |
| 1192 | } | 1160 | } |
| 1193 | 1161 | ||
| 1194 | if (!(data->flags & NFS_MOUNT_SECFLAVOUR)) | 1162 | if (!(args->flags & NFS_MOUNT_SECFLAVOUR)) |
| 1195 | data->pseudoflavor = RPC_AUTH_UNIX; | 1163 | args->auth_flavors[0] = RPC_AUTH_UNIX; |
| 1196 | 1164 | ||
| 1197 | #ifndef CONFIG_NFS_V3 | 1165 | #ifndef CONFIG_NFS_V3 |
| 1198 | if (data->flags & NFS_MOUNT_VER3) | 1166 | if (args->flags & NFS_MOUNT_VER3) |
| 1199 | goto out_v3_not_compiled; | 1167 | goto out_v3_not_compiled; |
| 1200 | #endif /* !CONFIG_NFS_V3 */ | 1168 | #endif /* !CONFIG_NFS_V3 */ |
| 1201 | 1169 | ||
| 1202 | if (!nfs_verify_server_address((struct sockaddr *) &data->addr)) | ||
| 1203 | goto out_no_address; | ||
| 1204 | |||
| 1205 | return 0; | 1170 | return 0; |
| 1206 | 1171 | ||
| 1207 | out_no_data: | 1172 | out_no_data: |
| @@ -1258,7 +1223,8 @@ static inline void nfs_initialise_sb(struct super_block *sb) | |||
| 1258 | /* | 1223 | /* |
| 1259 | * Finish setting up an NFS2/3 superblock | 1224 | * Finish setting up an NFS2/3 superblock |
| 1260 | */ | 1225 | */ |
| 1261 | static void nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data) | 1226 | static void nfs_fill_super(struct super_block *sb, |
| 1227 | struct nfs_parsed_mount_data *data) | ||
| 1262 | { | 1228 | { |
| 1263 | struct nfs_server *server = NFS_SB(sb); | 1229 | struct nfs_server *server = NFS_SB(sb); |
| 1264 | 1230 | ||
| @@ -1379,7 +1345,7 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
| 1379 | struct nfs_server *server = NULL; | 1345 | struct nfs_server *server = NULL; |
| 1380 | struct super_block *s; | 1346 | struct super_block *s; |
| 1381 | struct nfs_fh mntfh; | 1347 | struct nfs_fh mntfh; |
| 1382 | struct nfs_mount_data *data = raw_data; | 1348 | struct nfs_parsed_mount_data data; |
| 1383 | struct dentry *mntroot; | 1349 | struct dentry *mntroot; |
| 1384 | int (*compare_super)(struct super_block *, void *) = nfs_compare_super; | 1350 | int (*compare_super)(struct super_block *, void *) = nfs_compare_super; |
| 1385 | struct nfs_sb_mountdata sb_mntdata = { | 1351 | struct nfs_sb_mountdata sb_mntdata = { |
| @@ -1388,12 +1354,12 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
| 1388 | int error; | 1354 | int error; |
| 1389 | 1355 | ||
| 1390 | /* Validate the mount data */ | 1356 | /* Validate the mount data */ |
| 1391 | error = nfs_validate_mount_data(&data, &mntfh, dev_name); | 1357 | error = nfs_validate_mount_data(raw_data, &data, &mntfh, dev_name); |
| 1392 | if (error < 0) | 1358 | if (error < 0) |
| 1393 | goto out; | 1359 | goto out; |
| 1394 | 1360 | ||
| 1395 | /* Get a volume representation */ | 1361 | /* Get a volume representation */ |
| 1396 | server = nfs_create_server(data, &mntfh); | 1362 | server = nfs_create_server(&data, &mntfh); |
| 1397 | if (IS_ERR(server)) { | 1363 | if (IS_ERR(server)) { |
| 1398 | error = PTR_ERR(server); | 1364 | error = PTR_ERR(server); |
| 1399 | goto out; | 1365 | goto out; |
| @@ -1417,7 +1383,7 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
| 1417 | 1383 | ||
| 1418 | if (!s->s_root) { | 1384 | if (!s->s_root) { |
| 1419 | /* initial superblock/root creation */ | 1385 | /* initial superblock/root creation */ |
| 1420 | nfs_fill_super(s, data); | 1386 | nfs_fill_super(s, &data); |
| 1421 | } | 1387 | } |
| 1422 | 1388 | ||
| 1423 | mntroot = nfs_get_root(s, &mntfh); | 1389 | mntroot = nfs_get_root(s, &mntfh); |
| @@ -1432,8 +1398,7 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
| 1432 | error = 0; | 1398 | error = 0; |
| 1433 | 1399 | ||
| 1434 | out: | 1400 | out: |
| 1435 | if (data != raw_data) | 1401 | kfree(data.nfs_server.hostname); |
| 1436 | kfree(data); | ||
| 1437 | return error; | 1402 | return error; |
| 1438 | 1403 | ||
| 1439 | out_err_nosb: | 1404 | out_err_nosb: |
| @@ -1559,38 +1524,49 @@ static void nfs4_fill_super(struct super_block *sb) | |||
| 1559 | /* | 1524 | /* |
| 1560 | * Validate NFSv4 mount options | 1525 | * Validate NFSv4 mount options |
| 1561 | */ | 1526 | */ |
| 1562 | static int nfs4_validate_mount_data(struct nfs4_mount_data **options, | 1527 | static int nfs4_validate_mount_data(void *options, |
| 1563 | const char *dev_name, | 1528 | struct nfs_parsed_mount_data *args, |
| 1564 | struct sockaddr_in *addr, | 1529 | const char *dev_name) |
| 1565 | rpc_authflavor_t *authflavour, | ||
| 1566 | char **hostname, | ||
| 1567 | char **mntpath, | ||
| 1568 | char **ip_addr) | ||
| 1569 | { | 1530 | { |
| 1570 | struct nfs4_mount_data *data = *options; | 1531 | struct nfs4_mount_data *data = (struct nfs4_mount_data *)options; |
| 1571 | char *c; | 1532 | char *c; |
| 1572 | 1533 | ||
| 1573 | if (data == NULL) | 1534 | if (data == NULL) |
| 1574 | goto out_no_data; | 1535 | goto out_no_data; |
| 1575 | 1536 | ||
| 1537 | memset(args, 0, sizeof(*args)); | ||
| 1538 | args->rsize = NFS_MAX_FILE_IO_SIZE; | ||
| 1539 | args->wsize = NFS_MAX_FILE_IO_SIZE; | ||
| 1540 | args->timeo = 600; | ||
| 1541 | args->retrans = 2; | ||
| 1542 | args->acregmin = 3; | ||
| 1543 | args->acregmax = 60; | ||
| 1544 | args->acdirmin = 30; | ||
| 1545 | args->acdirmax = 60; | ||
| 1546 | args->nfs_server.protocol = XPRT_TRANSPORT_TCP; | ||
| 1547 | |||
| 1576 | switch (data->version) { | 1548 | switch (data->version) { |
| 1577 | case 1: | 1549 | case 1: |
| 1578 | if (data->host_addrlen != sizeof(*addr)) | 1550 | if (data->host_addrlen != sizeof(args->nfs_server.address)) |
| 1579 | goto out_no_address; | 1551 | goto out_no_address; |
| 1580 | if (copy_from_user(addr, data->host_addr, sizeof(*addr))) | 1552 | if (copy_from_user(&args->nfs_server.address, |
| 1553 | data->host_addr, | ||
| 1554 | sizeof(args->nfs_server.address))) | ||
| 1581 | return -EFAULT; | 1555 | return -EFAULT; |
| 1582 | if (addr->sin_port == 0) | 1556 | if (args->nfs_server.address.sin_port == 0) |
| 1583 | addr->sin_port = htons(NFS_PORT); | 1557 | args->nfs_server.address.sin_port = htons(NFS_PORT); |
| 1584 | if (!nfs_verify_server_address((struct sockaddr *) addr)) | 1558 | if (!nfs_verify_server_address((struct sockaddr *) |
| 1559 | &args->nfs_server.address)) | ||
| 1585 | goto out_no_address; | 1560 | goto out_no_address; |
| 1586 | 1561 | ||
| 1587 | switch (data->auth_flavourlen) { | 1562 | switch (data->auth_flavourlen) { |
| 1588 | case 0: | 1563 | case 0: |
| 1589 | *authflavour = RPC_AUTH_UNIX; | 1564 | args->auth_flavors[0] = RPC_AUTH_UNIX; |
| 1590 | break; | 1565 | break; |
| 1591 | case 1: | 1566 | case 1: |
| 1592 | if (copy_from_user(authflavour, data->auth_flavours, | 1567 | if (copy_from_user(&args->auth_flavors[0], |
| 1593 | sizeof(*authflavour))) | 1568 | data->auth_flavours, |
| 1569 | sizeof(args->auth_flavors[0]))) | ||
| 1594 | return -EFAULT; | 1570 | return -EFAULT; |
| 1595 | break; | 1571 | break; |
| 1596 | default: | 1572 | default: |
| @@ -1600,75 +1576,57 @@ static int nfs4_validate_mount_data(struct nfs4_mount_data **options, | |||
| 1600 | c = strndup_user(data->hostname.data, NFS4_MAXNAMLEN); | 1576 | c = strndup_user(data->hostname.data, NFS4_MAXNAMLEN); |
| 1601 | if (IS_ERR(c)) | 1577 | if (IS_ERR(c)) |
| 1602 | return PTR_ERR(c); | 1578 | return PTR_ERR(c); |
| 1603 | *hostname = c; | 1579 | args->nfs_server.hostname = c; |
| 1604 | 1580 | ||
| 1605 | c = strndup_user(data->mnt_path.data, NFS4_MAXPATHLEN); | 1581 | c = strndup_user(data->mnt_path.data, NFS4_MAXPATHLEN); |
| 1606 | if (IS_ERR(c)) | 1582 | if (IS_ERR(c)) |
| 1607 | return PTR_ERR(c); | 1583 | return PTR_ERR(c); |
| 1608 | *mntpath = c; | 1584 | args->nfs_server.export_path = c; |
| 1609 | dfprintk(MOUNT, "NFS: MNTPATH: '%s'\n", *mntpath); | 1585 | dfprintk(MOUNT, "NFS: MNTPATH: '%s'\n", c); |
| 1610 | 1586 | ||
| 1611 | c = strndup_user(data->client_addr.data, 16); | 1587 | c = strndup_user(data->client_addr.data, 16); |
| 1612 | if (IS_ERR(c)) | 1588 | if (IS_ERR(c)) |
| 1613 | return PTR_ERR(c); | 1589 | return PTR_ERR(c); |
| 1614 | *ip_addr = c; | 1590 | args->client_address = c; |
| 1591 | |||
| 1592 | /* | ||
| 1593 | * Translate to nfs_parsed_mount_data, which nfs4_fill_super | ||
| 1594 | * can deal with. | ||
| 1595 | */ | ||
| 1596 | |||
| 1597 | args->flags = data->flags & NFS4_MOUNT_FLAGMASK; | ||
| 1598 | args->rsize = data->rsize; | ||
| 1599 | args->wsize = data->wsize; | ||
| 1600 | args->timeo = data->timeo; | ||
| 1601 | args->retrans = data->retrans; | ||
| 1602 | args->acregmin = data->acregmin; | ||
| 1603 | args->acregmax = data->acregmax; | ||
| 1604 | args->acdirmin = data->acdirmin; | ||
| 1605 | args->acdirmax = data->acdirmax; | ||
| 1606 | args->nfs_server.protocol = data->proto; | ||
| 1615 | 1607 | ||
| 1616 | break; | 1608 | break; |
| 1617 | default: { | 1609 | default: { |
| 1618 | unsigned int len; | 1610 | unsigned int len; |
| 1619 | struct nfs_parsed_mount_data args = { | 1611 | |
| 1620 | .rsize = NFS_MAX_FILE_IO_SIZE, | 1612 | if (nfs_parse_mount_options((char *)options, args) == 0) |
| 1621 | .wsize = NFS_MAX_FILE_IO_SIZE, | ||
| 1622 | .timeo = 600, | ||
| 1623 | .retrans = 2, | ||
| 1624 | .acregmin = 3, | ||
| 1625 | .acregmax = 60, | ||
| 1626 | .acdirmin = 30, | ||
| 1627 | .acdirmax = 60, | ||
| 1628 | .nfs_server.protocol = IPPROTO_TCP, | ||
| 1629 | }; | ||
| 1630 | |||
| 1631 | if (nfs_parse_mount_options((char *) *options, &args) == 0) | ||
| 1632 | return -EINVAL; | 1613 | return -EINVAL; |
| 1633 | 1614 | ||
| 1634 | if (!nfs_verify_server_address((struct sockaddr *) | 1615 | if (!nfs_verify_server_address((struct sockaddr *) |
| 1635 | &args.nfs_server.address)) | 1616 | &args->nfs_server.address)) |
| 1636 | return -EINVAL; | 1617 | return -EINVAL; |
| 1637 | *addr = args.nfs_server.address; | ||
| 1638 | 1618 | ||
| 1639 | switch (args.auth_flavor_len) { | 1619 | switch (args->auth_flavor_len) { |
| 1640 | case 0: | 1620 | case 0: |
| 1641 | *authflavour = RPC_AUTH_UNIX; | 1621 | args->auth_flavors[0] = RPC_AUTH_UNIX; |
| 1642 | break; | 1622 | break; |
| 1643 | case 1: | 1623 | case 1: |
| 1644 | *authflavour = (rpc_authflavor_t) args.auth_flavors[0]; | ||
| 1645 | break; | 1624 | break; |
| 1646 | default: | 1625 | default: |
| 1647 | goto out_inval_auth; | 1626 | goto out_inval_auth; |
| 1648 | } | 1627 | } |
| 1649 | 1628 | ||
| 1650 | /* | 1629 | /* |
| 1651 | * Translate to nfs4_mount_data, which nfs4_fill_super | ||
| 1652 | * can deal with. | ||
| 1653 | */ | ||
| 1654 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
| 1655 | if (data == NULL) | ||
| 1656 | return -ENOMEM; | ||
| 1657 | *options = data; | ||
| 1658 | |||
| 1659 | data->version = 1; | ||
| 1660 | data->flags = args.flags & NFS4_MOUNT_FLAGMASK; | ||
| 1661 | data->rsize = args.rsize; | ||
| 1662 | data->wsize = args.wsize; | ||
| 1663 | data->timeo = args.timeo; | ||
| 1664 | data->retrans = args.retrans; | ||
| 1665 | data->acregmin = args.acregmin; | ||
| 1666 | data->acregmax = args.acregmax; | ||
| 1667 | data->acdirmin = args.acdirmin; | ||
| 1668 | data->acdirmax = args.acdirmax; | ||
| 1669 | data->proto = args.nfs_server.protocol; | ||
| 1670 | |||
| 1671 | /* | ||
| 1672 | * Split "dev_name" into "hostname:mntpath". | 1630 | * Split "dev_name" into "hostname:mntpath". |
| 1673 | */ | 1631 | */ |
| 1674 | c = strchr(dev_name, ':'); | 1632 | c = strchr(dev_name, ':'); |
| @@ -1678,27 +1636,25 @@ static int nfs4_validate_mount_data(struct nfs4_mount_data **options, | |||
| 1678 | len = c - dev_name; | 1636 | len = c - dev_name; |
| 1679 | if (len > NFS4_MAXNAMLEN) | 1637 | if (len > NFS4_MAXNAMLEN) |
| 1680 | return -ENAMETOOLONG; | 1638 | return -ENAMETOOLONG; |
| 1681 | *hostname = kzalloc(len, GFP_KERNEL); | 1639 | args->nfs_server.hostname = kzalloc(len, GFP_KERNEL); |
| 1682 | if (*hostname == NULL) | 1640 | if (args->nfs_server.hostname == NULL) |
| 1683 | return -ENOMEM; | 1641 | return -ENOMEM; |
| 1684 | strncpy(*hostname, dev_name, len - 1); | 1642 | strncpy(args->nfs_server.hostname, dev_name, len - 1); |
| 1685 | 1643 | ||
| 1686 | c++; /* step over the ':' */ | 1644 | c++; /* step over the ':' */ |
| 1687 | len = strlen(c); | 1645 | len = strlen(c); |
| 1688 | if (len > NFS4_MAXPATHLEN) | 1646 | if (len > NFS4_MAXPATHLEN) |
| 1689 | return -ENAMETOOLONG; | 1647 | return -ENAMETOOLONG; |
| 1690 | *mntpath = kzalloc(len + 1, GFP_KERNEL); | 1648 | args->nfs_server.export_path = kzalloc(len + 1, GFP_KERNEL); |
| 1691 | if (*mntpath == NULL) | 1649 | if (args->nfs_server.export_path == NULL) |
| 1692 | return -ENOMEM; | 1650 | return -ENOMEM; |
| 1693 | strncpy(*mntpath, c, len); | 1651 | strncpy(args->nfs_server.export_path, c, len); |
| 1694 | 1652 | ||
| 1695 | dprintk("MNTPATH: %s\n", *mntpath); | 1653 | dprintk("MNTPATH: %s\n", args->nfs_server.export_path); |
| 1696 | 1654 | ||
| 1697 | if (args.client_address == NULL) | 1655 | if (args->client_address == NULL) |
| 1698 | goto out_no_client_address; | 1656 | goto out_no_client_address; |
| 1699 | 1657 | ||
| 1700 | *ip_addr = args.client_address; | ||
| 1701 | |||
| 1702 | break; | 1658 | break; |
| 1703 | } | 1659 | } |
| 1704 | } | 1660 | } |
| @@ -1729,14 +1685,11 @@ out_no_client_address: | |||
| 1729 | static int nfs4_get_sb(struct file_system_type *fs_type, | 1685 | static int nfs4_get_sb(struct file_system_type *fs_type, |
| 1730 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) | 1686 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) |
| 1731 | { | 1687 | { |
| 1732 | struct nfs4_mount_data *data = raw_data; | 1688 | struct nfs_parsed_mount_data data; |
| 1733 | struct super_block *s; | 1689 | struct super_block *s; |
| 1734 | struct nfs_server *server; | 1690 | struct nfs_server *server; |
| 1735 | struct sockaddr_in addr; | ||
| 1736 | rpc_authflavor_t authflavour; | ||
| 1737 | struct nfs_fh mntfh; | 1691 | struct nfs_fh mntfh; |
| 1738 | struct dentry *mntroot; | 1692 | struct dentry *mntroot; |
| 1739 | char *mntpath = NULL, *hostname = NULL, *ip_addr = NULL; | ||
| 1740 | int (*compare_super)(struct super_block *, void *) = nfs_compare_super; | 1693 | int (*compare_super)(struct super_block *, void *) = nfs_compare_super; |
| 1741 | struct nfs_sb_mountdata sb_mntdata = { | 1694 | struct nfs_sb_mountdata sb_mntdata = { |
| 1742 | .mntflags = flags, | 1695 | .mntflags = flags, |
| @@ -1744,14 +1697,12 @@ static int nfs4_get_sb(struct file_system_type *fs_type, | |||
| 1744 | int error; | 1697 | int error; |
| 1745 | 1698 | ||
| 1746 | /* Validate the mount data */ | 1699 | /* Validate the mount data */ |
| 1747 | error = nfs4_validate_mount_data(&data, dev_name, &addr, &authflavour, | 1700 | error = nfs4_validate_mount_data(raw_data, &data, dev_name); |
| 1748 | &hostname, &mntpath, &ip_addr); | ||
| 1749 | if (error < 0) | 1701 | if (error < 0) |
| 1750 | goto out; | 1702 | goto out; |
| 1751 | 1703 | ||
| 1752 | /* Get a volume representation */ | 1704 | /* Get a volume representation */ |
| 1753 | server = nfs4_create_server(data, hostname, &addr, mntpath, ip_addr, | 1705 | server = nfs4_create_server(&data, &mntfh); |
| 1754 | authflavour, &mntfh); | ||
| 1755 | if (IS_ERR(server)) { | 1706 | if (IS_ERR(server)) { |
| 1756 | error = PTR_ERR(server); | 1707 | error = PTR_ERR(server); |
| 1757 | goto out; | 1708 | goto out; |
| @@ -1790,9 +1741,9 @@ static int nfs4_get_sb(struct file_system_type *fs_type, | |||
| 1790 | error = 0; | 1741 | error = 0; |
| 1791 | 1742 | ||
| 1792 | out: | 1743 | out: |
| 1793 | kfree(ip_addr); | 1744 | kfree(data.client_address); |
| 1794 | kfree(mntpath); | 1745 | kfree(data.nfs_server.export_path); |
| 1795 | kfree(hostname); | 1746 | kfree(data.nfs_server.hostname); |
| 1796 | return error; | 1747 | return error; |
| 1797 | 1748 | ||
| 1798 | out_free: | 1749 | out_free: |
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index 045ab805c17f..1aed850d18f2 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c | |||
| @@ -66,7 +66,6 @@ static void nfs_async_unlink_init(struct rpc_task *task, void *calldata) | |||
| 66 | .rpc_cred = data->cred, | 66 | .rpc_cred = data->cred, |
| 67 | }; | 67 | }; |
| 68 | 68 | ||
| 69 | nfs_begin_data_update(dir); | ||
| 70 | NFS_PROTO(dir)->unlink_setup(&msg, dir); | 69 | NFS_PROTO(dir)->unlink_setup(&msg, dir); |
| 71 | rpc_call_setup(task, &msg, 0); | 70 | rpc_call_setup(task, &msg, 0); |
| 72 | } | 71 | } |
| @@ -84,8 +83,6 @@ static void nfs_async_unlink_done(struct rpc_task *task, void *calldata) | |||
| 84 | 83 | ||
| 85 | if (!NFS_PROTO(dir)->unlink_done(task, dir)) | 84 | if (!NFS_PROTO(dir)->unlink_done(task, dir)) |
| 86 | rpc_restart_call(task); | 85 | rpc_restart_call(task); |
| 87 | else | ||
| 88 | nfs_end_data_update(dir); | ||
| 89 | } | 86 | } |
| 90 | 87 | ||
| 91 | /** | 88 | /** |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 0d7a77cc394b..e2bb66c34406 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
| @@ -110,6 +110,13 @@ void nfs_writedata_release(void *wdata) | |||
| 110 | nfs_writedata_free(wdata); | 110 | nfs_writedata_free(wdata); |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error) | ||
| 114 | { | ||
| 115 | ctx->error = error; | ||
| 116 | smp_wmb(); | ||
| 117 | set_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); | ||
| 118 | } | ||
| 119 | |||
| 113 | static struct nfs_page *nfs_page_find_request_locked(struct page *page) | 120 | static struct nfs_page *nfs_page_find_request_locked(struct page *page) |
| 114 | { | 121 | { |
| 115 | struct nfs_page *req = NULL; | 122 | struct nfs_page *req = NULL; |
| @@ -243,10 +250,7 @@ static void nfs_end_page_writeback(struct page *page) | |||
| 243 | 250 | ||
| 244 | /* | 251 | /* |
| 245 | * Find an associated nfs write request, and prepare to flush it out | 252 | * Find an associated nfs write request, and prepare to flush it out |
| 246 | * Returns 1 if there was no write request, or if the request was | 253 | * May return an error if the user signalled nfs_wait_on_request(). |
| 247 | * already tagged by nfs_set_page_dirty.Returns 0 if the request | ||
| 248 | * was not tagged. | ||
| 249 | * May also return an error if the user signalled nfs_wait_on_request(). | ||
| 250 | */ | 254 | */ |
| 251 | static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, | 255 | static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, |
| 252 | struct page *page) | 256 | struct page *page) |
| @@ -261,7 +265,7 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, | |||
| 261 | req = nfs_page_find_request_locked(page); | 265 | req = nfs_page_find_request_locked(page); |
| 262 | if (req == NULL) { | 266 | if (req == NULL) { |
| 263 | spin_unlock(&inode->i_lock); | 267 | spin_unlock(&inode->i_lock); |
| 264 | return 1; | 268 | return 0; |
| 265 | } | 269 | } |
| 266 | if (nfs_lock_request_dontget(req)) | 270 | if (nfs_lock_request_dontget(req)) |
| 267 | break; | 271 | break; |
| @@ -282,7 +286,7 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, | |||
| 282 | spin_unlock(&inode->i_lock); | 286 | spin_unlock(&inode->i_lock); |
| 283 | nfs_unlock_request(req); | 287 | nfs_unlock_request(req); |
| 284 | nfs_pageio_complete(pgio); | 288 | nfs_pageio_complete(pgio); |
| 285 | return 1; | 289 | return 0; |
| 286 | } | 290 | } |
| 287 | if (nfs_set_page_writeback(page) != 0) { | 291 | if (nfs_set_page_writeback(page) != 0) { |
| 288 | spin_unlock(&inode->i_lock); | 292 | spin_unlock(&inode->i_lock); |
| @@ -290,70 +294,56 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, | |||
| 290 | } | 294 | } |
| 291 | radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, | 295 | radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, |
| 292 | NFS_PAGE_TAG_LOCKED); | 296 | NFS_PAGE_TAG_LOCKED); |
| 293 | ret = test_bit(PG_NEED_FLUSH, &req->wb_flags); | ||
| 294 | spin_unlock(&inode->i_lock); | 297 | spin_unlock(&inode->i_lock); |
| 295 | nfs_pageio_add_request(pgio, req); | 298 | nfs_pageio_add_request(pgio, req); |
| 296 | return ret; | 299 | return 0; |
| 297 | } | 300 | } |
| 298 | 301 | ||
| 299 | /* | 302 | static int nfs_do_writepage(struct page *page, struct writeback_control *wbc, struct nfs_pageio_descriptor *pgio) |
| 300 | * Write an mmapped page to the server. | ||
| 301 | */ | ||
| 302 | static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc) | ||
| 303 | { | 303 | { |
| 304 | struct nfs_pageio_descriptor mypgio, *pgio; | ||
| 305 | struct nfs_open_context *ctx; | ||
| 306 | struct inode *inode = page->mapping->host; | 304 | struct inode *inode = page->mapping->host; |
| 307 | unsigned offset; | ||
| 308 | int err; | ||
| 309 | 305 | ||
| 310 | nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE); | 306 | nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE); |
| 311 | nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1); | 307 | nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1); |
| 312 | 308 | ||
| 313 | if (wbc->for_writepages) | ||
| 314 | pgio = wbc->fs_private; | ||
| 315 | else { | ||
| 316 | nfs_pageio_init_write(&mypgio, inode, wb_priority(wbc)); | ||
| 317 | pgio = &mypgio; | ||
| 318 | } | ||
| 319 | |||
| 320 | nfs_pageio_cond_complete(pgio, page->index); | 309 | nfs_pageio_cond_complete(pgio, page->index); |
| 310 | return nfs_page_async_flush(pgio, page); | ||
| 311 | } | ||
| 321 | 312 | ||
| 322 | err = nfs_page_async_flush(pgio, page); | 313 | /* |
| 323 | if (err <= 0) | 314 | * Write an mmapped page to the server. |
| 324 | goto out; | 315 | */ |
| 325 | err = 0; | 316 | static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc) |
| 326 | offset = nfs_page_length(page); | 317 | { |
| 327 | if (!offset) | 318 | struct nfs_pageio_descriptor pgio; |
| 328 | goto out; | 319 | int err; |
| 329 | |||
| 330 | nfs_pageio_cond_complete(pgio, page->index); | ||
| 331 | 320 | ||
| 332 | ctx = nfs_find_open_context(inode, NULL, FMODE_WRITE); | 321 | nfs_pageio_init_write(&pgio, page->mapping->host, wb_priority(wbc)); |
| 333 | if (ctx == NULL) { | 322 | err = nfs_do_writepage(page, wbc, &pgio); |
| 334 | err = -EBADF; | 323 | nfs_pageio_complete(&pgio); |
| 335 | goto out; | 324 | if (err < 0) |
| 336 | } | 325 | return err; |
| 337 | err = nfs_writepage_setup(ctx, page, 0, offset); | 326 | if (pgio.pg_error < 0) |
| 338 | put_nfs_open_context(ctx); | 327 | return pgio.pg_error; |
| 339 | if (err != 0) | 328 | return 0; |
| 340 | goto out; | ||
| 341 | err = nfs_page_async_flush(pgio, page); | ||
| 342 | if (err > 0) | ||
| 343 | err = 0; | ||
| 344 | out: | ||
| 345 | if (!wbc->for_writepages) | ||
| 346 | nfs_pageio_complete(pgio); | ||
| 347 | return err; | ||
| 348 | } | 329 | } |
| 349 | 330 | ||
| 350 | int nfs_writepage(struct page *page, struct writeback_control *wbc) | 331 | int nfs_writepage(struct page *page, struct writeback_control *wbc) |
| 351 | { | 332 | { |
| 352 | int err; | 333 | int ret; |
| 334 | |||
| 335 | ret = nfs_writepage_locked(page, wbc); | ||
| 336 | unlock_page(page); | ||
| 337 | return ret; | ||
| 338 | } | ||
| 339 | |||
| 340 | static int nfs_writepages_callback(struct page *page, struct writeback_control *wbc, void *data) | ||
| 341 | { | ||
| 342 | int ret; | ||
| 353 | 343 | ||
| 354 | err = nfs_writepage_locked(page, wbc); | 344 | ret = nfs_do_writepage(page, wbc, data); |
| 355 | unlock_page(page); | 345 | unlock_page(page); |
| 356 | return err; | 346 | return ret; |
| 357 | } | 347 | } |
| 358 | 348 | ||
| 359 | int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) | 349 | int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) |
| @@ -365,12 +355,11 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) | |||
| 365 | nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGES); | 355 | nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGES); |
| 366 | 356 | ||
| 367 | nfs_pageio_init_write(&pgio, inode, wb_priority(wbc)); | 357 | nfs_pageio_init_write(&pgio, inode, wb_priority(wbc)); |
| 368 | wbc->fs_private = &pgio; | 358 | err = write_cache_pages(mapping, wbc, nfs_writepages_callback, &pgio); |
| 369 | err = generic_writepages(mapping, wbc); | ||
| 370 | nfs_pageio_complete(&pgio); | 359 | nfs_pageio_complete(&pgio); |
| 371 | if (err) | 360 | if (err < 0) |
| 372 | return err; | 361 | return err; |
| 373 | if (pgio.pg_error) | 362 | if (pgio.pg_error < 0) |
| 374 | return pgio.pg_error; | 363 | return pgio.pg_error; |
| 375 | return 0; | 364 | return 0; |
| 376 | } | 365 | } |
| @@ -389,14 +378,11 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req) | |||
| 389 | return error; | 378 | return error; |
| 390 | if (!nfsi->npages) { | 379 | if (!nfsi->npages) { |
| 391 | igrab(inode); | 380 | igrab(inode); |
| 392 | nfs_begin_data_update(inode); | ||
| 393 | if (nfs_have_delegation(inode, FMODE_WRITE)) | 381 | if (nfs_have_delegation(inode, FMODE_WRITE)) |
| 394 | nfsi->change_attr++; | 382 | nfsi->change_attr++; |
| 395 | } | 383 | } |
| 396 | SetPagePrivate(req->wb_page); | 384 | SetPagePrivate(req->wb_page); |
| 397 | set_page_private(req->wb_page, (unsigned long)req); | 385 | set_page_private(req->wb_page, (unsigned long)req); |
| 398 | if (PageDirty(req->wb_page)) | ||
| 399 | set_bit(PG_NEED_FLUSH, &req->wb_flags); | ||
| 400 | nfsi->npages++; | 386 | nfsi->npages++; |
| 401 | kref_get(&req->wb_kref); | 387 | kref_get(&req->wb_kref); |
| 402 | return 0; | 388 | return 0; |
| @@ -416,12 +402,9 @@ static void nfs_inode_remove_request(struct nfs_page *req) | |||
| 416 | set_page_private(req->wb_page, 0); | 402 | set_page_private(req->wb_page, 0); |
| 417 | ClearPagePrivate(req->wb_page); | 403 | ClearPagePrivate(req->wb_page); |
| 418 | radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index); | 404 | radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index); |
| 419 | if (test_and_clear_bit(PG_NEED_FLUSH, &req->wb_flags)) | ||
| 420 | __set_page_dirty_nobuffers(req->wb_page); | ||
| 421 | nfsi->npages--; | 405 | nfsi->npages--; |
| 422 | if (!nfsi->npages) { | 406 | if (!nfsi->npages) { |
| 423 | spin_unlock(&inode->i_lock); | 407 | spin_unlock(&inode->i_lock); |
| 424 | nfs_end_data_update(inode); | ||
| 425 | iput(inode); | 408 | iput(inode); |
| 426 | } else | 409 | } else |
| 427 | spin_unlock(&inode->i_lock); | 410 | spin_unlock(&inode->i_lock); |
| @@ -682,7 +665,7 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx, | |||
| 682 | 665 | ||
| 683 | int nfs_flush_incompatible(struct file *file, struct page *page) | 666 | int nfs_flush_incompatible(struct file *file, struct page *page) |
| 684 | { | 667 | { |
| 685 | struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data; | 668 | struct nfs_open_context *ctx = nfs_file_open_context(file); |
| 686 | struct nfs_page *req; | 669 | struct nfs_page *req; |
| 687 | int do_flush, status; | 670 | int do_flush, status; |
| 688 | /* | 671 | /* |
| @@ -716,7 +699,7 @@ int nfs_flush_incompatible(struct file *file, struct page *page) | |||
| 716 | int nfs_updatepage(struct file *file, struct page *page, | 699 | int nfs_updatepage(struct file *file, struct page *page, |
| 717 | unsigned int offset, unsigned int count) | 700 | unsigned int offset, unsigned int count) |
| 718 | { | 701 | { |
| 719 | struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data; | 702 | struct nfs_open_context *ctx = nfs_file_open_context(file); |
| 720 | struct inode *inode = page->mapping->host; | 703 | struct inode *inode = page->mapping->host; |
| 721 | int status = 0; | 704 | int status = 0; |
| 722 | 705 | ||
| @@ -967,7 +950,7 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata) | |||
| 967 | 950 | ||
| 968 | if (task->tk_status < 0) { | 951 | if (task->tk_status < 0) { |
| 969 | nfs_set_pageerror(page); | 952 | nfs_set_pageerror(page); |
| 970 | req->wb_context->error = task->tk_status; | 953 | nfs_context_set_write_error(req->wb_context, task->tk_status); |
| 971 | dprintk(", error = %d\n", task->tk_status); | 954 | dprintk(", error = %d\n", task->tk_status); |
| 972 | goto out; | 955 | goto out; |
| 973 | } | 956 | } |
| @@ -1030,7 +1013,7 @@ static void nfs_writeback_done_full(struct rpc_task *task, void *calldata) | |||
| 1030 | 1013 | ||
| 1031 | if (task->tk_status < 0) { | 1014 | if (task->tk_status < 0) { |
| 1032 | nfs_set_pageerror(page); | 1015 | nfs_set_pageerror(page); |
| 1033 | req->wb_context->error = task->tk_status; | 1016 | nfs_context_set_write_error(req->wb_context, task->tk_status); |
| 1034 | dprintk(", error = %d\n", task->tk_status); | 1017 | dprintk(", error = %d\n", task->tk_status); |
| 1035 | goto remove_request; | 1018 | goto remove_request; |
| 1036 | } | 1019 | } |
| @@ -1244,7 +1227,7 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata) | |||
| 1244 | req->wb_bytes, | 1227 | req->wb_bytes, |
| 1245 | (long long)req_offset(req)); | 1228 | (long long)req_offset(req)); |
| 1246 | if (task->tk_status < 0) { | 1229 | if (task->tk_status < 0) { |
| 1247 | req->wb_context->error = task->tk_status; | 1230 | nfs_context_set_write_error(req->wb_context, task->tk_status); |
| 1248 | nfs_inode_remove_request(req); | 1231 | nfs_inode_remove_request(req); |
| 1249 | dprintk(", error = %d\n", task->tk_status); | 1232 | dprintk(", error = %d\n", task->tk_status); |
| 1250 | goto next; | 1233 | goto next; |
| @@ -1347,53 +1330,52 @@ long nfs_sync_mapping_wait(struct address_space *mapping, struct writeback_contr | |||
| 1347 | return ret; | 1330 | return ret; |
| 1348 | } | 1331 | } |
| 1349 | 1332 | ||
| 1350 | /* | 1333 | static int __nfs_write_mapping(struct address_space *mapping, struct writeback_control *wbc, int how) |
| 1351 | * flush the inode to disk. | ||
| 1352 | */ | ||
| 1353 | int nfs_wb_all(struct inode *inode) | ||
| 1354 | { | 1334 | { |
| 1355 | struct address_space *mapping = inode->i_mapping; | ||
| 1356 | struct writeback_control wbc = { | ||
| 1357 | .bdi = mapping->backing_dev_info, | ||
| 1358 | .sync_mode = WB_SYNC_ALL, | ||
| 1359 | .nr_to_write = LONG_MAX, | ||
| 1360 | .for_writepages = 1, | ||
| 1361 | .range_cyclic = 1, | ||
| 1362 | }; | ||
| 1363 | int ret; | 1335 | int ret; |
| 1364 | 1336 | ||
| 1365 | ret = nfs_writepages(mapping, &wbc); | 1337 | ret = nfs_writepages(mapping, wbc); |
| 1366 | if (ret < 0) | 1338 | if (ret < 0) |
| 1367 | goto out; | 1339 | goto out; |
| 1368 | ret = nfs_sync_mapping_wait(mapping, &wbc, 0); | 1340 | ret = nfs_sync_mapping_wait(mapping, wbc, how); |
| 1369 | if (ret >= 0) | 1341 | if (ret < 0) |
| 1370 | return 0; | 1342 | goto out; |
| 1343 | return 0; | ||
| 1371 | out: | 1344 | out: |
| 1372 | __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); | 1345 | __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); |
| 1373 | return ret; | 1346 | return ret; |
| 1374 | } | 1347 | } |
| 1375 | 1348 | ||
| 1376 | int nfs_sync_mapping_range(struct address_space *mapping, loff_t range_start, loff_t range_end, int how) | 1349 | /* Two pass sync: first using WB_SYNC_NONE, then WB_SYNC_ALL */ |
| 1350 | static int nfs_write_mapping(struct address_space *mapping, int how) | ||
| 1377 | { | 1351 | { |
| 1378 | struct writeback_control wbc = { | 1352 | struct writeback_control wbc = { |
| 1379 | .bdi = mapping->backing_dev_info, | 1353 | .bdi = mapping->backing_dev_info, |
| 1380 | .sync_mode = WB_SYNC_ALL, | 1354 | .sync_mode = WB_SYNC_NONE, |
| 1381 | .nr_to_write = LONG_MAX, | 1355 | .nr_to_write = LONG_MAX, |
| 1382 | .range_start = range_start, | ||
| 1383 | .range_end = range_end, | ||
| 1384 | .for_writepages = 1, | 1356 | .for_writepages = 1, |
| 1357 | .range_cyclic = 1, | ||
| 1385 | }; | 1358 | }; |
| 1386 | int ret; | 1359 | int ret; |
| 1387 | 1360 | ||
| 1388 | ret = nfs_writepages(mapping, &wbc); | 1361 | ret = __nfs_write_mapping(mapping, &wbc, how); |
| 1389 | if (ret < 0) | 1362 | if (ret < 0) |
| 1390 | goto out; | 1363 | return ret; |
| 1391 | ret = nfs_sync_mapping_wait(mapping, &wbc, how); | 1364 | wbc.sync_mode = WB_SYNC_ALL; |
| 1392 | if (ret >= 0) | 1365 | return __nfs_write_mapping(mapping, &wbc, how); |
| 1393 | return 0; | 1366 | } |
| 1394 | out: | 1367 | |
| 1395 | __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); | 1368 | /* |
| 1396 | return ret; | 1369 | * flush the inode to disk. |
| 1370 | */ | ||
| 1371 | int nfs_wb_all(struct inode *inode) | ||
| 1372 | { | ||
| 1373 | return nfs_write_mapping(inode->i_mapping, 0); | ||
| 1374 | } | ||
| 1375 | |||
| 1376 | int nfs_wb_nocommit(struct inode *inode) | ||
| 1377 | { | ||
| 1378 | return nfs_write_mapping(inode->i_mapping, FLUSH_NOCOMMIT); | ||
| 1397 | } | 1379 | } |
| 1398 | 1380 | ||
| 1399 | int nfs_wb_page_cancel(struct inode *inode, struct page *page) | 1381 | int nfs_wb_page_cancel(struct inode *inode, struct page *page) |
| @@ -1477,35 +1459,6 @@ int nfs_wb_page(struct inode *inode, struct page* page) | |||
| 1477 | return nfs_wb_page_priority(inode, page, FLUSH_STABLE); | 1459 | return nfs_wb_page_priority(inode, page, FLUSH_STABLE); |
| 1478 | } | 1460 | } |
| 1479 | 1461 | ||
| 1480 | int nfs_set_page_dirty(struct page *page) | ||
| 1481 | { | ||
| 1482 | struct address_space *mapping = page->mapping; | ||
| 1483 | struct inode *inode; | ||
| 1484 | struct nfs_page *req; | ||
| 1485 | int ret; | ||
| 1486 | |||
| 1487 | if (!mapping) | ||
| 1488 | goto out_raced; | ||
| 1489 | inode = mapping->host; | ||
| 1490 | if (!inode) | ||
| 1491 | goto out_raced; | ||
| 1492 | spin_lock(&inode->i_lock); | ||
| 1493 | req = nfs_page_find_request_locked(page); | ||
| 1494 | if (req != NULL) { | ||
| 1495 | /* Mark any existing write requests for flushing */ | ||
| 1496 | ret = !test_and_set_bit(PG_NEED_FLUSH, &req->wb_flags); | ||
| 1497 | spin_unlock(&inode->i_lock); | ||
| 1498 | nfs_release_request(req); | ||
| 1499 | return ret; | ||
| 1500 | } | ||
| 1501 | ret = __set_page_dirty_nobuffers(page); | ||
| 1502 | spin_unlock(&inode->i_lock); | ||
| 1503 | return ret; | ||
| 1504 | out_raced: | ||
| 1505 | return !TestSetPageDirty(page); | ||
| 1506 | } | ||
| 1507 | |||
| 1508 | |||
| 1509 | int __init nfs_init_writepagecache(void) | 1462 | int __init nfs_init_writepagecache(void) |
| 1510 | { | 1463 | { |
| 1511 | nfs_wdata_cachep = kmem_cache_create("nfs_write_data", | 1464 | nfs_wdata_cachep = kmem_cache_create("nfs_write_data", |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index e15f2cf8ac15..57333944af7f 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
| @@ -102,7 +102,8 @@ check_filename(char *str, int len, __be32 err) | |||
| 102 | out: \ | 102 | out: \ |
| 103 | return status; \ | 103 | return status; \ |
| 104 | xdr_error: \ | 104 | xdr_error: \ |
| 105 | printk(KERN_NOTICE "xdr error! (%s:%d)\n", __FILE__, __LINE__); \ | 105 | dprintk("NFSD: xdr error (%s:%d)\n", \ |
| 106 | __FILE__, __LINE__); \ | ||
| 106 | status = nfserr_bad_xdr; \ | 107 | status = nfserr_bad_xdr; \ |
| 107 | goto out | 108 | goto out |
| 108 | 109 | ||
| @@ -124,7 +125,8 @@ xdr_error: \ | |||
| 124 | if (!(x = (p==argp->tmp || p == argp->tmpp) ? \ | 125 | if (!(x = (p==argp->tmp || p == argp->tmpp) ? \ |
| 125 | savemem(argp, p, nbytes) : \ | 126 | savemem(argp, p, nbytes) : \ |
| 126 | (char *)p)) { \ | 127 | (char *)p)) { \ |
| 127 | printk(KERN_NOTICE "xdr error! (%s:%d)\n", __FILE__, __LINE__); \ | 128 | dprintk("NFSD: xdr error (%s:%d)\n", \ |
| 129 | __FILE__, __LINE__); \ | ||
| 128 | goto xdr_error; \ | 130 | goto xdr_error; \ |
| 129 | } \ | 131 | } \ |
| 130 | p += XDR_QUADLEN(nbytes); \ | 132 | p += XDR_QUADLEN(nbytes); \ |
| @@ -140,7 +142,8 @@ xdr_error: \ | |||
| 140 | p = argp->p; \ | 142 | p = argp->p; \ |
| 141 | argp->p += XDR_QUADLEN(nbytes); \ | 143 | argp->p += XDR_QUADLEN(nbytes); \ |
| 142 | } else if (!(p = read_buf(argp, nbytes))) { \ | 144 | } else if (!(p = read_buf(argp, nbytes))) { \ |
| 143 | printk(KERN_NOTICE "xdr error! (%s:%d)\n", __FILE__, __LINE__); \ | 145 | dprintk("NFSD: xdr error (%s:%d)\n", \ |
| 146 | __FILE__, __LINE__); \ | ||
| 144 | goto xdr_error; \ | 147 | goto xdr_error; \ |
| 145 | } \ | 148 | } \ |
| 146 | } while (0) | 149 | } while (0) |
| @@ -948,7 +951,8 @@ nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write) | |||
| 948 | */ | 951 | */ |
| 949 | avail = (char*)argp->end - (char*)argp->p; | 952 | avail = (char*)argp->end - (char*)argp->p; |
| 950 | if (avail + argp->pagelen < write->wr_buflen) { | 953 | if (avail + argp->pagelen < write->wr_buflen) { |
| 951 | printk(KERN_NOTICE "xdr error! (%s:%d)\n", __FILE__, __LINE__); | 954 | dprintk("NFSD: xdr error (%s:%d)\n", |
| 955 | __FILE__, __LINE__); | ||
| 952 | goto xdr_error; | 956 | goto xdr_error; |
| 953 | } | 957 | } |
| 954 | argp->rqstp->rq_vec[0].iov_base = p; | 958 | argp->rqstp->rq_vec[0].iov_base = p; |
| @@ -1019,7 +1023,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) | |||
| 1019 | argp->ops = kmalloc(argp->opcnt * sizeof(*argp->ops), GFP_KERNEL); | 1023 | argp->ops = kmalloc(argp->opcnt * sizeof(*argp->ops), GFP_KERNEL); |
| 1020 | if (!argp->ops) { | 1024 | if (!argp->ops) { |
| 1021 | argp->ops = argp->iops; | 1025 | argp->ops = argp->iops; |
| 1022 | printk(KERN_INFO "nfsd: couldn't allocate room for COMPOUND\n"); | 1026 | dprintk("nfsd: couldn't allocate room for COMPOUND\n"); |
| 1023 | goto xdr_error; | 1027 | goto xdr_error; |
| 1024 | } | 1028 | } |
| 1025 | } | 1029 | } |
| @@ -1326,7 +1330,7 @@ static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp, __be32 * | |||
| 1326 | path = exp->ex_path; | 1330 | path = exp->ex_path; |
| 1327 | 1331 | ||
| 1328 | if (strncmp(path, rootpath, strlen(rootpath))) { | 1332 | if (strncmp(path, rootpath, strlen(rootpath))) { |
| 1329 | printk("nfsd: fs_locations failed;" | 1333 | dprintk("nfsd: fs_locations failed;" |
| 1330 | "%s is not contained in %s\n", path, rootpath); | 1334 | "%s is not contained in %s\n", path, rootpath); |
| 1331 | *stat = nfserr_notsupp; | 1335 | *stat = nfserr_notsupp; |
| 1332 | return NULL; | 1336 | return NULL; |
diff --git a/include/asm-blackfin/mach-bf548/bf54x_keys.h b/include/asm-blackfin/mach-bf548/bf54x_keys.h new file mode 100644 index 000000000000..1fb4ec77cc25 --- /dev/null +++ b/include/asm-blackfin/mach-bf548/bf54x_keys.h | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | #ifndef _BFIN_KPAD_H | ||
| 2 | #define _BFIN_KPAD_H | ||
| 3 | |||
| 4 | struct bfin_kpad_platform_data { | ||
| 5 | int rows; | ||
| 6 | int cols; | ||
| 7 | const unsigned int *keymap; | ||
| 8 | unsigned short keymapsize; | ||
| 9 | unsigned short repeat; | ||
| 10 | u32 debounce_time; /* in ns */ | ||
| 11 | u32 coldrive_time; /* in ns */ | ||
| 12 | u32 keyup_test_interval; /* in ms */ | ||
| 13 | }; | ||
| 14 | |||
| 15 | #define KEYVAL(col, row, val) (((1 << col) << 24) | ((1 << row) << 16) | (val)) | ||
| 16 | |||
| 17 | #endif | ||
diff --git a/include/asm-mips/mach-au1x00/prom.h b/include/asm-mips/mach-au1x00/prom.h new file mode 100644 index 000000000000..e38715577c51 --- /dev/null +++ b/include/asm-mips/mach-au1x00/prom.h | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | #ifndef __AU1X00_PROM_H | ||
| 2 | #define __AU1X00_PROM_H | ||
| 3 | |||
| 4 | extern int prom_argc; | ||
| 5 | extern char **prom_argv; | ||
| 6 | extern char **prom_envp; | ||
| 7 | |||
| 8 | extern void prom_init_cmdline(void); | ||
| 9 | extern char *prom_getcmdline(void); | ||
| 10 | extern char *prom_getenv(char *envname); | ||
| 11 | extern int prom_get_ethernet_addr(char *ethernet_addr); | ||
| 12 | |||
| 13 | #endif | ||
diff --git a/include/asm-powerpc/dcr-mmio.h b/include/asm-powerpc/dcr-mmio.h index 6b82c3ba495a..08532ff1899c 100644 --- a/include/asm-powerpc/dcr-mmio.h +++ b/include/asm-powerpc/dcr-mmio.h | |||
| @@ -33,16 +33,16 @@ typedef struct { | |||
| 33 | 33 | ||
| 34 | extern dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n, | 34 | extern dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n, |
| 35 | unsigned int dcr_c); | 35 | unsigned int dcr_c); |
| 36 | extern void dcr_unmap(dcr_host_t host, unsigned int dcr_n, unsigned int dcr_c); | 36 | extern void dcr_unmap(dcr_host_t host, unsigned int dcr_c); |
| 37 | 37 | ||
| 38 | static inline u32 dcr_read(dcr_host_t host, unsigned int dcr_n) | 38 | static inline u32 dcr_read(dcr_host_t host, unsigned int dcr_n) |
| 39 | { | 39 | { |
| 40 | return in_be32(host.token + dcr_n * host.stride); | 40 | return in_be32(host.token + ((host.base + dcr_n) * host.stride)); |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | static inline void dcr_write(dcr_host_t host, unsigned int dcr_n, u32 value) | 43 | static inline void dcr_write(dcr_host_t host, unsigned int dcr_n, u32 value) |
| 44 | { | 44 | { |
| 45 | out_be32(host.token + dcr_n * host.stride, value); | 45 | out_be32(host.token + ((host.base + dcr_n) * host.stride), value); |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | extern u64 of_translate_dcr_address(struct device_node *dev, | 48 | extern u64 of_translate_dcr_address(struct device_node *dev, |
diff --git a/include/asm-powerpc/dcr-native.h b/include/asm-powerpc/dcr-native.h index f41058c0f6cb..8dbb1ab0aa04 100644 --- a/include/asm-powerpc/dcr-native.h +++ b/include/asm-powerpc/dcr-native.h | |||
| @@ -29,9 +29,9 @@ typedef struct { | |||
| 29 | #define DCR_MAP_OK(host) (1) | 29 | #define DCR_MAP_OK(host) (1) |
| 30 | 30 | ||
| 31 | #define dcr_map(dev, dcr_n, dcr_c) ((dcr_host_t){ .base = (dcr_n) }) | 31 | #define dcr_map(dev, dcr_n, dcr_c) ((dcr_host_t){ .base = (dcr_n) }) |
| 32 | #define dcr_unmap(host, dcr_n, dcr_c) do {} while (0) | 32 | #define dcr_unmap(host, dcr_c) do {} while (0) |
| 33 | #define dcr_read(host, dcr_n) mfdcr(dcr_n) | 33 | #define dcr_read(host, dcr_n) mfdcr(dcr_n + host.base) |
| 34 | #define dcr_write(host, dcr_n, value) mtdcr(dcr_n, value) | 34 | #define dcr_write(host, dcr_n, value) mtdcr(dcr_n + host.base, value) |
| 35 | 35 | ||
| 36 | /* Device Control Registers */ | 36 | /* Device Control Registers */ |
| 37 | void __mtdcr(int reg, unsigned int val); | 37 | void __mtdcr(int reg, unsigned int val); |
diff --git a/include/asm-x86/irqflags_32.h b/include/asm-x86/irqflags_32.h index eff8585cb741..d058b04e0083 100644 --- a/include/asm-x86/irqflags_32.h +++ b/include/asm-x86/irqflags_32.h | |||
| @@ -160,4 +160,17 @@ static inline int raw_irqs_disabled(void) | |||
| 160 | # define TRACE_IRQS_OFF | 160 | # define TRACE_IRQS_OFF |
| 161 | #endif | 161 | #endif |
| 162 | 162 | ||
| 163 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
| 164 | # define LOCKDEP_SYS_EXIT \ | ||
| 165 | pushl %eax; \ | ||
| 166 | pushl %ecx; \ | ||
| 167 | pushl %edx; \ | ||
| 168 | call lockdep_sys_exit; \ | ||
| 169 | popl %edx; \ | ||
| 170 | popl %ecx; \ | ||
| 171 | popl %eax; | ||
| 172 | #else | ||
| 173 | # define LOCKDEP_SYS_EXIT | ||
| 174 | #endif | ||
| 175 | |||
| 163 | #endif | 176 | #endif |
diff --git a/include/asm-x86/irqflags_64.h b/include/asm-x86/irqflags_64.h index 86e70fe23659..5341ea1f815a 100644 --- a/include/asm-x86/irqflags_64.h +++ b/include/asm-x86/irqflags_64.h | |||
| @@ -137,6 +137,20 @@ static inline void halt(void) | |||
| 137 | # define TRACE_IRQS_ON | 137 | # define TRACE_IRQS_ON |
| 138 | # define TRACE_IRQS_OFF | 138 | # define TRACE_IRQS_OFF |
| 139 | # endif | 139 | # endif |
| 140 | # ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
| 141 | # define LOCKDEP_SYS_EXIT call lockdep_sys_exit_thunk | ||
| 142 | # define LOCKDEP_SYS_EXIT_IRQ \ | ||
| 143 | TRACE_IRQS_ON; \ | ||
| 144 | sti; \ | ||
| 145 | SAVE_REST; \ | ||
| 146 | LOCKDEP_SYS_EXIT; \ | ||
| 147 | RESTORE_REST; \ | ||
| 148 | cli; \ | ||
| 149 | TRACE_IRQS_OFF; | ||
| 150 | # else | ||
| 151 | # define LOCKDEP_SYS_EXIT | ||
| 152 | # define LOCKDEP_SYS_EXIT_IRQ | ||
| 153 | # endif | ||
| 140 | #endif | 154 | #endif |
| 141 | 155 | ||
| 142 | #endif | 156 | #endif |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 16421f662a7a..6d760f1ad875 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -1302,8 +1302,14 @@ struct file_system_type { | |||
| 1302 | struct module *owner; | 1302 | struct module *owner; |
| 1303 | struct file_system_type * next; | 1303 | struct file_system_type * next; |
| 1304 | struct list_head fs_supers; | 1304 | struct list_head fs_supers; |
| 1305 | |||
| 1305 | struct lock_class_key s_lock_key; | 1306 | struct lock_class_key s_lock_key; |
| 1306 | struct lock_class_key s_umount_key; | 1307 | struct lock_class_key s_umount_key; |
| 1308 | |||
| 1309 | struct lock_class_key i_lock_key; | ||
| 1310 | struct lock_class_key i_mutex_key; | ||
| 1311 | struct lock_class_key i_mutex_dir_key; | ||
| 1312 | struct lock_class_key i_alloc_sem_key; | ||
| 1307 | }; | 1313 | }; |
| 1308 | 1314 | ||
| 1309 | extern int get_sb_bdev(struct file_system_type *fs_type, | 1315 | extern int get_sb_bdev(struct file_system_type *fs_type, |
diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h index 265d17830a0f..c6d3a9de5634 100644 --- a/include/linux/gpio_keys.h +++ b/include/linux/gpio_keys.h | |||
| @@ -8,6 +8,7 @@ struct gpio_keys_button { | |||
| 8 | int active_low; | 8 | int active_low; |
| 9 | char *desc; | 9 | char *desc; |
| 10 | int type; /* input event type (EV_KEY, EV_SW) */ | 10 | int type; /* input event type (EV_KEY, EV_SW) */ |
| 11 | int wakeup; /* configure the button as a wake-up source */ | ||
| 11 | }; | 12 | }; |
| 12 | 13 | ||
| 13 | struct gpio_keys_platform_data { | 14 | struct gpio_keys_platform_data { |
diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h index 99e3a1a00099..58e43e566457 100644 --- a/include/linux/if_bridge.h +++ b/include/linux/if_bridge.h | |||
| @@ -107,7 +107,7 @@ struct __fdb_entry | |||
| 107 | extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *)); | 107 | extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *)); |
| 108 | extern struct sk_buff *(*br_handle_frame_hook)(struct net_bridge_port *p, | 108 | extern struct sk_buff *(*br_handle_frame_hook)(struct net_bridge_port *p, |
| 109 | struct sk_buff *skb); | 109 | struct sk_buff *skb); |
| 110 | extern int (*br_should_route_hook)(struct sk_buff **pskb); | 110 | extern int (*br_should_route_hook)(struct sk_buff *skb); |
| 111 | 111 | ||
| 112 | #endif | 112 | #endif |
| 113 | 113 | ||
diff --git a/include/linux/input.h b/include/linux/input.h index 52d1bd434a50..f30da6fc08e3 100644 --- a/include/linux/input.h +++ b/include/linux/input.h | |||
| @@ -856,7 +856,7 @@ struct ff_rumble_effect { | |||
| 856 | * defining effect parameters | 856 | * defining effect parameters |
| 857 | * | 857 | * |
| 858 | * This structure is sent through ioctl from the application to the driver. | 858 | * This structure is sent through ioctl from the application to the driver. |
| 859 | * To create a new effect aplication should set its @id to -1; the kernel | 859 | * To create a new effect application should set its @id to -1; the kernel |
| 860 | * will return assigned @id which can later be used to update or delete | 860 | * will return assigned @id which can later be used to update or delete |
| 861 | * this effect. | 861 | * this effect. |
| 862 | * | 862 | * |
| @@ -936,9 +936,82 @@ struct ff_effect { | |||
| 936 | #define BIT(x) (1UL<<((x)%BITS_PER_LONG)) | 936 | #define BIT(x) (1UL<<((x)%BITS_PER_LONG)) |
| 937 | #define LONG(x) ((x)/BITS_PER_LONG) | 937 | #define LONG(x) ((x)/BITS_PER_LONG) |
| 938 | 938 | ||
| 939 | /** | ||
| 940 | * struct input_dev - represents an input device | ||
| 941 | * @name: name of the device | ||
| 942 | * @phys: physical path to the device in the system hierarchy | ||
| 943 | * @uniq: unique identification code for the device (if device has it) | ||
| 944 | * @id: id of the device (struct input_id) | ||
| 945 | * @evbit: bitmap of types of events supported by the device (EV_KEY, | ||
| 946 | * EV_REL, etc.) | ||
| 947 | * @keybit: bitmap of keys/buttons this device has | ||
| 948 | * @relbit: bitmap of relative axes for the device | ||
| 949 | * @absbit: bitmap of absolute axes for the device | ||
| 950 | * @mscbit: bitmap of miscellaneous events supported by the device | ||
| 951 | * @ledbit: bitmap of leds present on the device | ||
| 952 | * @sndbit: bitmap of sound effects supported by the device | ||
| 953 | * @ffbit: bitmap of force feedback effects supported by the device | ||
| 954 | * @swbit: bitmap of switches present on the device | ||
| 955 | * @keycodemax: size of keycode table | ||
| 956 | * @keycodesize: size of elements in keycode table | ||
| 957 | * @keycode: map of scancodes to keycodes for this device | ||
| 958 | * @setkeycode: optional method to alter current keymap, used to implement | ||
| 959 | * sparse keymaps. If not supplied default mechanism will be used | ||
| 960 | * @getkeycode: optional method to retrieve current keymap. If not supplied | ||
| 961 | * default mechanism will be used | ||
| 962 | * @ff: force feedback structure associated with the device if device | ||
| 963 | * supports force feedback effects | ||
| 964 | * @repeat_key: stores key code of the last key pressed; used to implement | ||
| 965 | * software autorepeat | ||
| 966 | * @timer: timer for software autorepeat | ||
| 967 | * @sync: set to 1 when there were no new events since last EV_SYNC | ||
| 968 | * @abs: current values for reports from absolute axes | ||
| 969 | * @rep: current values for autorepeat parameters (delay, rate) | ||
| 970 | * @key: reflects current state of device's keys/buttons | ||
| 971 | * @led: reflects current state of device's LEDs | ||
| 972 | * @snd: reflects current state of sound effects | ||
| 973 | * @sw: reflects current state of device's switches | ||
| 974 | * @absmax: maximum values for events coming from absolute axes | ||
| 975 | * @absmin: minimum values for events coming from absolute axes | ||
| 976 | * @absfuzz: describes noisiness for axes | ||
| 977 | * @absflat: size of the center flat position (used by joydev) | ||
| 978 | * @open: this method is called when the very first user calls | ||
| 979 | * input_open_device(). The driver must prepare the device | ||
| 980 | * to start generating events (start polling thread, | ||
| 981 | * request an IRQ, submit URB, etc.) | ||
| 982 | * @close: this method is called when the very last user calls | ||
| 983 | * input_close_device(). | ||
| 984 | * @flush: purges the device. Most commonly used to get rid of force | ||
| 985 | * feedback effects loaded into the device when disconnecting | ||
| 986 | * from it | ||
| 987 | * @event: event handler for events sent _to_ the device, like EV_LED | ||
| 988 | * or EV_SND. The device is expected to carry out the requested | ||
| 989 | * action (turn on a LED, play sound, etc.) The call is protected | ||
| 990 | * by @event_lock and must not sleep | ||
| 991 | * @grab: input handle that currently has the device grabbed (via | ||
| 992 | * EVIOCGRAB ioctl). When a handle grabs a device it becomes sole | ||
| 993 | * recipient for all input events coming from the device | ||
| 994 | * @event_lock: this spinlock is is taken when input core receives | ||
| 995 | * and processes a new event for the device (in input_event()). | ||
| 996 | * Code that accesses and/or modifies parameters of a device | ||
| 997 | * (such as keymap or absmin, absmax, absfuzz, etc.) after device | ||
| 998 | * has been registered with input core must take this lock. | ||
| 999 | * @mutex: serializes calls to open(), close() and flush() methods | ||
| 1000 | * @users: stores number of users (input handlers) that opened this | ||
| 1001 | * device. It is used by input_open_device() and input_close_device() | ||
| 1002 | * to make sure that dev->open() is only called when the first | ||
| 1003 | * user opens device and dev->close() is called when the very | ||
| 1004 | * last user closes the device | ||
| 1005 | * @going_away: marks devices that are in a middle of unregistering and | ||
| 1006 | * causes input_open_device*() fail with -ENODEV. | ||
| 1007 | * @dev: driver model's view of this device | ||
| 1008 | * @h_list: list of input handles associated with the device. When | ||
| 1009 | * accessing the list dev->mutex must be held | ||
| 1010 | * @node: used to place the device onto input_dev_list | ||
| 1011 | */ | ||
| 939 | struct input_dev { | 1012 | struct input_dev { |
| 940 | 1013 | ||
| 941 | void *private; | 1014 | void *private; /* do not use */ |
| 942 | 1015 | ||
| 943 | const char *name; | 1016 | const char *name; |
| 944 | const char *phys; | 1017 | const char *phys; |
| @@ -966,8 +1039,6 @@ struct input_dev { | |||
| 966 | unsigned int repeat_key; | 1039 | unsigned int repeat_key; |
| 967 | struct timer_list timer; | 1040 | struct timer_list timer; |
| 968 | 1041 | ||
| 969 | int state; | ||
| 970 | |||
| 971 | int sync; | 1042 | int sync; |
| 972 | 1043 | ||
| 973 | int abs[ABS_MAX + 1]; | 1044 | int abs[ABS_MAX + 1]; |
| @@ -990,8 +1061,11 @@ struct input_dev { | |||
| 990 | 1061 | ||
| 991 | struct input_handle *grab; | 1062 | struct input_handle *grab; |
| 992 | 1063 | ||
| 993 | struct mutex mutex; /* serializes open and close operations */ | 1064 | spinlock_t event_lock; |
| 1065 | struct mutex mutex; | ||
| 1066 | |||
| 994 | unsigned int users; | 1067 | unsigned int users; |
| 1068 | int going_away; | ||
| 995 | 1069 | ||
| 996 | struct device dev; | 1070 | struct device dev; |
| 997 | union { /* temporarily so while we switching to struct device */ | 1071 | union { /* temporarily so while we switching to struct device */ |
| @@ -1057,7 +1131,9 @@ struct input_handle; | |||
| 1057 | /** | 1131 | /** |
| 1058 | * struct input_handler - implements one of interfaces for input devices | 1132 | * struct input_handler - implements one of interfaces for input devices |
| 1059 | * @private: driver-specific data | 1133 | * @private: driver-specific data |
| 1060 | * @event: event handler | 1134 | * @event: event handler. This method is being called by input core with |
| 1135 | * interrupts disabled and dev->event_lock spinlock held and so | ||
| 1136 | * it may not sleep | ||
| 1061 | * @connect: called when attaching a handler to an input device | 1137 | * @connect: called when attaching a handler to an input device |
| 1062 | * @disconnect: disconnects a handler from input device | 1138 | * @disconnect: disconnects a handler from input device |
| 1063 | * @start: starts handler for given handle. This function is called by | 1139 | * @start: starts handler for given handle. This function is called by |
| @@ -1069,10 +1145,18 @@ struct input_handle; | |||
| 1069 | * @name: name of the handler, to be shown in /proc/bus/input/handlers | 1145 | * @name: name of the handler, to be shown in /proc/bus/input/handlers |
| 1070 | * @id_table: pointer to a table of input_device_ids this driver can | 1146 | * @id_table: pointer to a table of input_device_ids this driver can |
| 1071 | * handle | 1147 | * handle |
| 1072 | * @blacklist: prointer to a table of input_device_ids this driver should | 1148 | * @blacklist: pointer to a table of input_device_ids this driver should |
| 1073 | * ignore even if they match @id_table | 1149 | * ignore even if they match @id_table |
| 1074 | * @h_list: list of input handles associated with the handler | 1150 | * @h_list: list of input handles associated with the handler |
| 1075 | * @node: for placing the driver onto input_handler_list | 1151 | * @node: for placing the driver onto input_handler_list |
| 1152 | * | ||
| 1153 | * Input handlers attach to input devices and create input handles. There | ||
| 1154 | * are likely several handlers attached to any given input device at the | ||
| 1155 | * same time. All of them will get their copy of input event generated by | ||
| 1156 | * the device. | ||
| 1157 | * | ||
| 1158 | * Note that input core serializes calls to connect() and disconnect() | ||
| 1159 | * methods. | ||
| 1076 | */ | 1160 | */ |
| 1077 | struct input_handler { | 1161 | struct input_handler { |
| 1078 | 1162 | ||
| @@ -1094,6 +1178,18 @@ struct input_handler { | |||
| 1094 | struct list_head node; | 1178 | struct list_head node; |
| 1095 | }; | 1179 | }; |
| 1096 | 1180 | ||
| 1181 | /** | ||
| 1182 | * struct input_handle - links input device with an input handler | ||
| 1183 | * @private: handler-specific data | ||
| 1184 | * @open: counter showing whether the handle is 'open', i.e. should deliver | ||
| 1185 | * events from its device | ||
| 1186 | * @name: name given to the handle by handler that created it | ||
| 1187 | * @dev: input device the handle is attached to | ||
| 1188 | * @handler: handler that works with the device through this handle | ||
| 1189 | * @d_node: used to put the handle on device's list of attached handles | ||
| 1190 | * @h_node: used to put the handle on handler's list of handles from which | ||
| 1191 | * it gets events | ||
| 1192 | */ | ||
| 1097 | struct input_handle { | 1193 | struct input_handle { |
| 1098 | 1194 | ||
| 1099 | void *private; | 1195 | void *private; |
| @@ -1136,10 +1232,10 @@ static inline void input_set_drvdata(struct input_dev *dev, void *data) | |||
| 1136 | dev->private = data; | 1232 | dev->private = data; |
| 1137 | } | 1233 | } |
| 1138 | 1234 | ||
| 1139 | int input_register_device(struct input_dev *); | 1235 | int __must_check input_register_device(struct input_dev *); |
| 1140 | void input_unregister_device(struct input_dev *); | 1236 | void input_unregister_device(struct input_dev *); |
| 1141 | 1237 | ||
| 1142 | int input_register_handler(struct input_handler *); | 1238 | int __must_check input_register_handler(struct input_handler *); |
| 1143 | void input_unregister_handler(struct input_handler *); | 1239 | void input_unregister_handler(struct input_handler *); |
| 1144 | 1240 | ||
| 1145 | int input_register_handle(struct input_handle *); | 1241 | int input_register_handle(struct input_handle *); |
| @@ -1216,7 +1312,7 @@ extern struct class input_class; | |||
| 1216 | * @max_effects: maximum number of effects supported by device | 1312 | * @max_effects: maximum number of effects supported by device |
| 1217 | * @effects: pointer to an array of effects currently loaded into device | 1313 | * @effects: pointer to an array of effects currently loaded into device |
| 1218 | * @effect_owners: array of effect owners; when file handle owning | 1314 | * @effect_owners: array of effect owners; when file handle owning |
| 1219 | * an effect gets closed the effcet is automatically erased | 1315 | * an effect gets closed the effect is automatically erased |
| 1220 | * | 1316 | * |
| 1221 | * Every force-feedback device must implement upload() and playback() | 1317 | * Every force-feedback device must implement upload() and playback() |
| 1222 | * methods; erase() is optional. set_gain() and set_autocenter() need | 1318 | * methods; erase() is optional. set_gain() and set_autocenter() need |
diff --git a/include/linux/isdn.h b/include/linux/isdn.h index ad09506554a3..d5dda4b643ac 100644 --- a/include/linux/isdn.h +++ b/include/linux/isdn.h | |||
| @@ -286,7 +286,6 @@ typedef struct { | |||
| 286 | /* Local interface-data */ | 286 | /* Local interface-data */ |
| 287 | typedef struct isdn_net_local_s { | 287 | typedef struct isdn_net_local_s { |
| 288 | ulong magic; | 288 | ulong magic; |
| 289 | char name[10]; /* Name of device */ | ||
| 290 | struct net_device_stats stats; /* Ethernet Statistics */ | 289 | struct net_device_stats stats; /* Ethernet Statistics */ |
| 291 | int isdn_device; /* Index to isdn-device */ | 290 | int isdn_device; /* Index to isdn-device */ |
| 292 | int isdn_channel; /* Index to isdn-channel */ | 291 | int isdn_channel; /* Index to isdn-channel */ |
diff --git a/include/linux/jbd.h b/include/linux/jbd.h index 452737551260..700a93b79189 100644 --- a/include/linux/jbd.h +++ b/include/linux/jbd.h | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <linux/bit_spinlock.h> | 30 | #include <linux/bit_spinlock.h> |
| 31 | #include <linux/mutex.h> | 31 | #include <linux/mutex.h> |
| 32 | #include <linux/timer.h> | 32 | #include <linux/timer.h> |
| 33 | #include <linux/lockdep.h> | ||
| 33 | 34 | ||
| 34 | #include <asm/semaphore.h> | 35 | #include <asm/semaphore.h> |
| 35 | #endif | 36 | #endif |
| @@ -396,6 +397,10 @@ struct handle_s | |||
| 396 | unsigned int h_sync: 1; /* sync-on-close */ | 397 | unsigned int h_sync: 1; /* sync-on-close */ |
| 397 | unsigned int h_jdata: 1; /* force data journaling */ | 398 | unsigned int h_jdata: 1; /* force data journaling */ |
| 398 | unsigned int h_aborted: 1; /* fatal error on handle */ | 399 | unsigned int h_aborted: 1; /* fatal error on handle */ |
| 400 | |||
| 401 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
| 402 | struct lockdep_map h_lockdep_map; | ||
| 403 | #endif | ||
| 399 | }; | 404 | }; |
| 400 | 405 | ||
| 401 | 406 | ||
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index d7a5e034c3a2..e757a74b9d17 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h | |||
| @@ -109,6 +109,10 @@ static inline u64 get_jiffies_64(void) | |||
| 109 | ((long)(a) - (long)(b) >= 0)) | 109 | ((long)(a) - (long)(b) >= 0)) |
| 110 | #define time_before_eq(a,b) time_after_eq(b,a) | 110 | #define time_before_eq(a,b) time_after_eq(b,a) |
| 111 | 111 | ||
| 112 | #define time_in_range(a,b,c) \ | ||
| 113 | (time_after_eq(a,b) && \ | ||
| 114 | time_before_eq(a,c)) | ||
| 115 | |||
| 112 | /* Same as above, but does so with platform independent 64bit types. | 116 | /* Same as above, but does so with platform independent 64bit types. |
| 113 | * These must be used when utilizing jiffies_64 (i.e. return value of | 117 | * These must be used when utilizing jiffies_64 (i.e. return value of |
| 114 | * get_jiffies_64() */ | 118 | * get_jiffies_64() */ |
diff --git a/include/linux/keyboard.h b/include/linux/keyboard.h index 7ddbc30aa8e7..33b5c2e325b9 100644 --- a/include/linux/keyboard.h +++ b/include/linux/keyboard.h | |||
| @@ -416,6 +416,7 @@ extern unsigned short plain_map[NR_KEYS]; | |||
| 416 | #define K_SHIFTRLOCK K(KT_LOCK,KG_SHIFTR) | 416 | #define K_SHIFTRLOCK K(KT_LOCK,KG_SHIFTR) |
| 417 | #define K_CTRLLLOCK K(KT_LOCK,KG_CTRLL) | 417 | #define K_CTRLLLOCK K(KT_LOCK,KG_CTRLL) |
| 418 | #define K_CTRLRLOCK K(KT_LOCK,KG_CTRLR) | 418 | #define K_CTRLRLOCK K(KT_LOCK,KG_CTRLR) |
| 419 | #define K_CAPSSHIFTLOCK K(KT_LOCK,KG_CAPSSHIFT) | ||
| 419 | 420 | ||
| 420 | #define K_SHIFT_SLOCK K(KT_SLOCK,KG_SHIFT) | 421 | #define K_SHIFT_SLOCK K(KT_SLOCK,KG_SHIFT) |
| 421 | #define K_CTRL_SLOCK K(KT_SLOCK,KG_CTRL) | 422 | #define K_CTRL_SLOCK K(KT_SLOCK,KG_CTRL) |
| @@ -425,8 +426,9 @@ extern unsigned short plain_map[NR_KEYS]; | |||
| 425 | #define K_SHIFTR_SLOCK K(KT_SLOCK,KG_SHIFTR) | 426 | #define K_SHIFTR_SLOCK K(KT_SLOCK,KG_SHIFTR) |
| 426 | #define K_CTRLL_SLOCK K(KT_SLOCK,KG_CTRLL) | 427 | #define K_CTRLL_SLOCK K(KT_SLOCK,KG_CTRLL) |
| 427 | #define K_CTRLR_SLOCK K(KT_SLOCK,KG_CTRLR) | 428 | #define K_CTRLR_SLOCK K(KT_SLOCK,KG_CTRLR) |
| 429 | #define K_CAPSSHIFT_SLOCK K(KT_SLOCK,KG_CAPSSHIFT) | ||
| 428 | 430 | ||
| 429 | #define NR_LOCK 8 | 431 | #define NR_LOCK 9 |
| 430 | 432 | ||
| 431 | #define K_BRL_BLANK K(KT_BRL, 0) | 433 | #define K_BRL_BLANK K(KT_BRL, 0) |
| 432 | #define K_BRL_DOT1 K(KT_BRL, 1) | 434 | #define K_BRL_DOT1 K(KT_BRL, 1) |
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h index 0e843bf65877..f6279f68a827 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h | |||
| @@ -238,6 +238,7 @@ extern void lockdep_info(void); | |||
| 238 | extern void lockdep_reset(void); | 238 | extern void lockdep_reset(void); |
| 239 | extern void lockdep_reset_lock(struct lockdep_map *lock); | 239 | extern void lockdep_reset_lock(struct lockdep_map *lock); |
| 240 | extern void lockdep_free_key_range(void *start, unsigned long size); | 240 | extern void lockdep_free_key_range(void *start, unsigned long size); |
| 241 | extern void lockdep_sys_exit(void); | ||
| 241 | 242 | ||
| 242 | extern void lockdep_off(void); | 243 | extern void lockdep_off(void); |
| 243 | extern void lockdep_on(void); | 244 | extern void lockdep_on(void); |
| @@ -252,6 +253,13 @@ extern void lockdep_init_map(struct lockdep_map *lock, const char *name, | |||
| 252 | struct lock_class_key *key, int subclass); | 253 | struct lock_class_key *key, int subclass); |
| 253 | 254 | ||
| 254 | /* | 255 | /* |
| 256 | * To initialize a lockdep_map statically use this macro. | ||
| 257 | * Note that _name must not be NULL. | ||
| 258 | */ | ||
| 259 | #define STATIC_LOCKDEP_MAP_INIT(_name, _key) \ | ||
| 260 | { .name = (_name), .key = (void *)(_key), } | ||
| 261 | |||
| 262 | /* | ||
| 255 | * Reinitialize a lock key - for cases where there is special locking or | 263 | * Reinitialize a lock key - for cases where there is special locking or |
| 256 | * special initialization of locks so that the validator gets the scope | 264 | * special initialization of locks so that the validator gets the scope |
| 257 | * of dependencies wrong: they are either too broad (they need a class-split) | 265 | * of dependencies wrong: they are either too broad (they need a class-split) |
| @@ -317,6 +325,7 @@ static inline void lockdep_on(void) | |||
| 317 | # define INIT_LOCKDEP | 325 | # define INIT_LOCKDEP |
| 318 | # define lockdep_reset() do { debug_locks = 1; } while (0) | 326 | # define lockdep_reset() do { debug_locks = 1; } while (0) |
| 319 | # define lockdep_free_key_range(start, size) do { } while (0) | 327 | # define lockdep_free_key_range(start, size) do { } while (0) |
| 328 | # define lockdep_sys_exit() do { } while (0) | ||
| 320 | /* | 329 | /* |
| 321 | * The class key takes no space if lockdep is disabled: | 330 | * The class key takes no space if lockdep is disabled: |
| 322 | */ | 331 | */ |
diff --git a/include/linux/mutex.h b/include/linux/mutex.h index 0d50ea3df689..6a735c72f23f 100644 --- a/include/linux/mutex.h +++ b/include/linux/mutex.h | |||
| @@ -120,14 +120,17 @@ static inline int fastcall mutex_is_locked(struct mutex *lock) | |||
| 120 | * See kernel/mutex.c for detailed documentation of these APIs. | 120 | * See kernel/mutex.c for detailed documentation of these APIs. |
| 121 | * Also see Documentation/mutex-design.txt. | 121 | * Also see Documentation/mutex-design.txt. |
| 122 | */ | 122 | */ |
| 123 | extern void fastcall mutex_lock(struct mutex *lock); | ||
| 124 | extern int __must_check fastcall mutex_lock_interruptible(struct mutex *lock); | ||
| 125 | |||
| 126 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 123 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
| 127 | extern void mutex_lock_nested(struct mutex *lock, unsigned int subclass); | 124 | extern void mutex_lock_nested(struct mutex *lock, unsigned int subclass); |
| 128 | extern int __must_check mutex_lock_interruptible_nested(struct mutex *lock, | 125 | extern int __must_check mutex_lock_interruptible_nested(struct mutex *lock, |
| 129 | unsigned int subclass); | 126 | unsigned int subclass); |
| 127 | |||
| 128 | #define mutex_lock(lock) mutex_lock_nested(lock, 0) | ||
| 129 | #define mutex_lock_interruptible(lock) mutex_lock_interruptible_nested(lock, 0) | ||
| 130 | #else | 130 | #else |
| 131 | extern void fastcall mutex_lock(struct mutex *lock); | ||
| 132 | extern int __must_check fastcall mutex_lock_interruptible(struct mutex *lock); | ||
| 133 | |||
| 131 | # define mutex_lock_nested(lock, subclass) mutex_lock(lock) | 134 | # define mutex_lock_nested(lock, subclass) mutex_lock(lock) |
| 132 | # define mutex_lock_interruptible_nested(lock, subclass) mutex_lock_interruptible(lock) | 135 | # define mutex_lock_interruptible_nested(lock, subclass) mutex_lock_interruptible(lock) |
| 133 | #endif | 136 | #endif |
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 1dd075eda595..16adac688af5 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h | |||
| @@ -51,7 +51,7 @@ struct sk_buff; | |||
| 51 | struct net_device; | 51 | struct net_device; |
| 52 | 52 | ||
| 53 | typedef unsigned int nf_hookfn(unsigned int hooknum, | 53 | typedef unsigned int nf_hookfn(unsigned int hooknum, |
| 54 | struct sk_buff **skb, | 54 | struct sk_buff *skb, |
| 55 | const struct net_device *in, | 55 | const struct net_device *in, |
| 56 | const struct net_device *out, | 56 | const struct net_device *out, |
| 57 | int (*okfn)(struct sk_buff *)); | 57 | int (*okfn)(struct sk_buff *)); |
| @@ -183,7 +183,7 @@ void nf_log_packet(int pf, | |||
| 183 | struct nf_loginfo *li, | 183 | struct nf_loginfo *li, |
| 184 | const char *fmt, ...); | 184 | const char *fmt, ...); |
| 185 | 185 | ||
| 186 | int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb, | 186 | int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb, |
| 187 | struct net_device *indev, struct net_device *outdev, | 187 | struct net_device *indev, struct net_device *outdev, |
| 188 | int (*okfn)(struct sk_buff *), int thresh); | 188 | int (*okfn)(struct sk_buff *), int thresh); |
| 189 | 189 | ||
| @@ -195,7 +195,7 @@ int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb, | |||
| 195 | * value indicates the packet has been consumed by the hook. | 195 | * value indicates the packet has been consumed by the hook. |
| 196 | */ | 196 | */ |
| 197 | static inline int nf_hook_thresh(int pf, unsigned int hook, | 197 | static inline int nf_hook_thresh(int pf, unsigned int hook, |
| 198 | struct sk_buff **pskb, | 198 | struct sk_buff *skb, |
| 199 | struct net_device *indev, | 199 | struct net_device *indev, |
| 200 | struct net_device *outdev, | 200 | struct net_device *outdev, |
| 201 | int (*okfn)(struct sk_buff *), int thresh, | 201 | int (*okfn)(struct sk_buff *), int thresh, |
| @@ -207,14 +207,14 @@ static inline int nf_hook_thresh(int pf, unsigned int hook, | |||
| 207 | if (list_empty(&nf_hooks[pf][hook])) | 207 | if (list_empty(&nf_hooks[pf][hook])) |
| 208 | return 1; | 208 | return 1; |
| 209 | #endif | 209 | #endif |
| 210 | return nf_hook_slow(pf, hook, pskb, indev, outdev, okfn, thresh); | 210 | return nf_hook_slow(pf, hook, skb, indev, outdev, okfn, thresh); |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | static inline int nf_hook(int pf, unsigned int hook, struct sk_buff **pskb, | 213 | static inline int nf_hook(int pf, unsigned int hook, struct sk_buff *skb, |
| 214 | struct net_device *indev, struct net_device *outdev, | 214 | struct net_device *indev, struct net_device *outdev, |
| 215 | int (*okfn)(struct sk_buff *)) | 215 | int (*okfn)(struct sk_buff *)) |
| 216 | { | 216 | { |
| 217 | return nf_hook_thresh(pf, hook, pskb, indev, outdev, okfn, INT_MIN, 1); | 217 | return nf_hook_thresh(pf, hook, skb, indev, outdev, okfn, INT_MIN, 1); |
| 218 | } | 218 | } |
| 219 | 219 | ||
| 220 | /* Activate hook; either okfn or kfree_skb called, unless a hook | 220 | /* Activate hook; either okfn or kfree_skb called, unless a hook |
| @@ -241,13 +241,13 @@ static inline int nf_hook(int pf, unsigned int hook, struct sk_buff **pskb, | |||
| 241 | 241 | ||
| 242 | #define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh) \ | 242 | #define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh) \ |
| 243 | ({int __ret; \ | 243 | ({int __ret; \ |
| 244 | if ((__ret=nf_hook_thresh(pf, hook, &(skb), indev, outdev, okfn, thresh, 1)) == 1)\ | 244 | if ((__ret=nf_hook_thresh(pf, hook, (skb), indev, outdev, okfn, thresh, 1)) == 1)\ |
| 245 | __ret = (okfn)(skb); \ | 245 | __ret = (okfn)(skb); \ |
| 246 | __ret;}) | 246 | __ret;}) |
| 247 | 247 | ||
| 248 | #define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) \ | 248 | #define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) \ |
| 249 | ({int __ret; \ | 249 | ({int __ret; \ |
| 250 | if ((__ret=nf_hook_thresh(pf, hook, &(skb), indev, outdev, okfn, INT_MIN, cond)) == 1)\ | 250 | if ((__ret=nf_hook_thresh(pf, hook, (skb), indev, outdev, okfn, INT_MIN, cond)) == 1)\ |
| 251 | __ret = (okfn)(skb); \ | 251 | __ret = (okfn)(skb); \ |
| 252 | __ret;}) | 252 | __ret;}) |
| 253 | 253 | ||
| @@ -287,7 +287,7 @@ extern void nf_invalidate_cache(int pf); | |||
| 287 | /* Call this before modifying an existing packet: ensures it is | 287 | /* Call this before modifying an existing packet: ensures it is |
| 288 | modifiable and linear to the point you care about (writable_len). | 288 | modifiable and linear to the point you care about (writable_len). |
| 289 | Returns true or false. */ | 289 | Returns true or false. */ |
| 290 | extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len); | 290 | extern int skb_make_writable(struct sk_buff *skb, unsigned int writable_len); |
| 291 | 291 | ||
| 292 | static inline void nf_csum_replace4(__sum16 *sum, __be32 from, __be32 to) | 292 | static inline void nf_csum_replace4(__sum16 *sum, __be32 from, __be32 to) |
| 293 | { | 293 | { |
| @@ -317,7 +317,7 @@ struct nf_afinfo { | |||
| 317 | unsigned int dataoff, u_int8_t protocol); | 317 | unsigned int dataoff, u_int8_t protocol); |
| 318 | void (*saveroute)(const struct sk_buff *skb, | 318 | void (*saveroute)(const struct sk_buff *skb, |
| 319 | struct nf_info *info); | 319 | struct nf_info *info); |
| 320 | int (*reroute)(struct sk_buff **skb, | 320 | int (*reroute)(struct sk_buff *skb, |
| 321 | const struct nf_info *info); | 321 | const struct nf_info *info); |
| 322 | int route_key_size; | 322 | int route_key_size; |
| 323 | }; | 323 | }; |
| @@ -371,15 +371,15 @@ extern struct proc_dir_entry *proc_net_netfilter; | |||
| 371 | #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb) | 371 | #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb) |
| 372 | #define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb) | 372 | #define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb) |
| 373 | static inline int nf_hook_thresh(int pf, unsigned int hook, | 373 | static inline int nf_hook_thresh(int pf, unsigned int hook, |
| 374 | struct sk_buff **pskb, | 374 | struct sk_buff *skb, |
| 375 | struct net_device *indev, | 375 | struct net_device *indev, |
| 376 | struct net_device *outdev, | 376 | struct net_device *outdev, |
| 377 | int (*okfn)(struct sk_buff *), int thresh, | 377 | int (*okfn)(struct sk_buff *), int thresh, |
| 378 | int cond) | 378 | int cond) |
| 379 | { | 379 | { |
| 380 | return okfn(*pskb); | 380 | return okfn(skb); |
| 381 | } | 381 | } |
| 382 | static inline int nf_hook(int pf, unsigned int hook, struct sk_buff **pskb, | 382 | static inline int nf_hook(int pf, unsigned int hook, struct sk_buff *skb, |
| 383 | struct net_device *indev, struct net_device *outdev, | 383 | struct net_device *indev, struct net_device *outdev, |
| 384 | int (*okfn)(struct sk_buff *)) | 384 | int (*okfn)(struct sk_buff *)) |
| 385 | { | 385 | { |
diff --git a/include/linux/netfilter/nf_conntrack_amanda.h b/include/linux/netfilter/nf_conntrack_amanda.h index 26c223544ae8..0bb5a6976bf3 100644 --- a/include/linux/netfilter/nf_conntrack_amanda.h +++ b/include/linux/netfilter/nf_conntrack_amanda.h | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | #define _NF_CONNTRACK_AMANDA_H | 2 | #define _NF_CONNTRACK_AMANDA_H |
| 3 | /* AMANDA tracking. */ | 3 | /* AMANDA tracking. */ |
| 4 | 4 | ||
| 5 | extern unsigned int (*nf_nat_amanda_hook)(struct sk_buff **pskb, | 5 | extern unsigned int (*nf_nat_amanda_hook)(struct sk_buff *skb, |
| 6 | enum ip_conntrack_info ctinfo, | 6 | enum ip_conntrack_info ctinfo, |
| 7 | unsigned int matchoff, | 7 | unsigned int matchoff, |
| 8 | unsigned int matchlen, | 8 | unsigned int matchlen, |
diff --git a/include/linux/netfilter/nf_conntrack_ftp.h b/include/linux/netfilter/nf_conntrack_ftp.h index b7c360ffd0d0..47727d7546ea 100644 --- a/include/linux/netfilter/nf_conntrack_ftp.h +++ b/include/linux/netfilter/nf_conntrack_ftp.h | |||
| @@ -32,7 +32,7 @@ struct nf_conntrack_expect; | |||
| 32 | 32 | ||
| 33 | /* For NAT to hook in when we find a packet which describes what other | 33 | /* For NAT to hook in when we find a packet which describes what other |
| 34 | * connection we should expect. */ | 34 | * connection we should expect. */ |
| 35 | extern unsigned int (*nf_nat_ftp_hook)(struct sk_buff **pskb, | 35 | extern unsigned int (*nf_nat_ftp_hook)(struct sk_buff *skb, |
| 36 | enum ip_conntrack_info ctinfo, | 36 | enum ip_conntrack_info ctinfo, |
| 37 | enum nf_ct_ftp_type type, | 37 | enum nf_ct_ftp_type type, |
| 38 | unsigned int matchoff, | 38 | unsigned int matchoff, |
diff --git a/include/linux/netfilter/nf_conntrack_h323.h b/include/linux/netfilter/nf_conntrack_h323.h index 08e2f4977c2e..aabd24ac7631 100644 --- a/include/linux/netfilter/nf_conntrack_h323.h +++ b/include/linux/netfilter/nf_conntrack_h323.h | |||
| @@ -36,27 +36,27 @@ extern void nf_conntrack_h245_expect(struct nf_conn *new, | |||
| 36 | struct nf_conntrack_expect *this); | 36 | struct nf_conntrack_expect *this); |
| 37 | extern void nf_conntrack_q931_expect(struct nf_conn *new, | 37 | extern void nf_conntrack_q931_expect(struct nf_conn *new, |
| 38 | struct nf_conntrack_expect *this); | 38 | struct nf_conntrack_expect *this); |
| 39 | extern int (*set_h245_addr_hook) (struct sk_buff **pskb, | 39 | extern int (*set_h245_addr_hook) (struct sk_buff *skb, |
| 40 | unsigned char **data, int dataoff, | 40 | unsigned char **data, int dataoff, |
| 41 | H245_TransportAddress *taddr, | 41 | H245_TransportAddress *taddr, |
| 42 | union nf_conntrack_address *addr, | 42 | union nf_conntrack_address *addr, |
| 43 | __be16 port); | 43 | __be16 port); |
| 44 | extern int (*set_h225_addr_hook) (struct sk_buff **pskb, | 44 | extern int (*set_h225_addr_hook) (struct sk_buff *skb, |
| 45 | unsigned char **data, int dataoff, | 45 | unsigned char **data, int dataoff, |
| 46 | TransportAddress *taddr, | 46 | TransportAddress *taddr, |
| 47 | union nf_conntrack_address *addr, | 47 | union nf_conntrack_address *addr, |
| 48 | __be16 port); | 48 | __be16 port); |
| 49 | extern int (*set_sig_addr_hook) (struct sk_buff **pskb, | 49 | extern int (*set_sig_addr_hook) (struct sk_buff *skb, |
| 50 | struct nf_conn *ct, | 50 | struct nf_conn *ct, |
| 51 | enum ip_conntrack_info ctinfo, | 51 | enum ip_conntrack_info ctinfo, |
| 52 | unsigned char **data, | 52 | unsigned char **data, |
| 53 | TransportAddress *taddr, int count); | 53 | TransportAddress *taddr, int count); |
| 54 | extern int (*set_ras_addr_hook) (struct sk_buff **pskb, | 54 | extern int (*set_ras_addr_hook) (struct sk_buff *skb, |
| 55 | struct nf_conn *ct, | 55 | struct nf_conn *ct, |
| 56 | enum ip_conntrack_info ctinfo, | 56 | enum ip_conntrack_info ctinfo, |
| 57 | unsigned char **data, | 57 | unsigned char **data, |
| 58 | TransportAddress *taddr, int count); | 58 | TransportAddress *taddr, int count); |
| 59 | extern int (*nat_rtp_rtcp_hook) (struct sk_buff **pskb, | 59 | extern int (*nat_rtp_rtcp_hook) (struct sk_buff *skb, |
| 60 | struct nf_conn *ct, | 60 | struct nf_conn *ct, |
| 61 | enum ip_conntrack_info ctinfo, | 61 | enum ip_conntrack_info ctinfo, |
| 62 | unsigned char **data, int dataoff, | 62 | unsigned char **data, int dataoff, |
| @@ -64,24 +64,24 @@ extern int (*nat_rtp_rtcp_hook) (struct sk_buff **pskb, | |||
| 64 | __be16 port, __be16 rtp_port, | 64 | __be16 port, __be16 rtp_port, |
| 65 | struct nf_conntrack_expect *rtp_exp, | 65 | struct nf_conntrack_expect *rtp_exp, |
| 66 | struct nf_conntrack_expect *rtcp_exp); | 66 | struct nf_conntrack_expect *rtcp_exp); |
| 67 | extern int (*nat_t120_hook) (struct sk_buff **pskb, struct nf_conn *ct, | 67 | extern int (*nat_t120_hook) (struct sk_buff *skb, struct nf_conn *ct, |
| 68 | enum ip_conntrack_info ctinfo, | 68 | enum ip_conntrack_info ctinfo, |
| 69 | unsigned char **data, int dataoff, | 69 | unsigned char **data, int dataoff, |
| 70 | H245_TransportAddress *taddr, __be16 port, | 70 | H245_TransportAddress *taddr, __be16 port, |
| 71 | struct nf_conntrack_expect *exp); | 71 | struct nf_conntrack_expect *exp); |
| 72 | extern int (*nat_h245_hook) (struct sk_buff **pskb, struct nf_conn *ct, | 72 | extern int (*nat_h245_hook) (struct sk_buff *skb, struct nf_conn *ct, |
| 73 | enum ip_conntrack_info ctinfo, | 73 | enum ip_conntrack_info ctinfo, |
| 74 | unsigned char **data, int dataoff, | 74 | unsigned char **data, int dataoff, |
| 75 | TransportAddress *taddr, __be16 port, | 75 | TransportAddress *taddr, __be16 port, |
| 76 | struct nf_conntrack_expect *exp); | 76 | struct nf_conntrack_expect *exp); |
| 77 | extern int (*nat_callforwarding_hook) (struct sk_buff **pskb, | 77 | extern int (*nat_callforwarding_hook) (struct sk_buff *skb, |
| 78 | struct nf_conn *ct, | 78 | struct nf_conn *ct, |
| 79 | enum ip_conntrack_info ctinfo, | 79 | enum ip_conntrack_info ctinfo, |
| 80 | unsigned char **data, int dataoff, | 80 | unsigned char **data, int dataoff, |
| 81 | TransportAddress *taddr, | 81 | TransportAddress *taddr, |
| 82 | __be16 port, | 82 | __be16 port, |
| 83 | struct nf_conntrack_expect *exp); | 83 | struct nf_conntrack_expect *exp); |
| 84 | extern int (*nat_q931_hook) (struct sk_buff **pskb, struct nf_conn *ct, | 84 | extern int (*nat_q931_hook) (struct sk_buff *skb, struct nf_conn *ct, |
| 85 | enum ip_conntrack_info ctinfo, | 85 | enum ip_conntrack_info ctinfo, |
| 86 | unsigned char **data, TransportAddress *taddr, | 86 | unsigned char **data, TransportAddress *taddr, |
| 87 | int idx, __be16 port, | 87 | int idx, __be16 port, |
diff --git a/include/linux/netfilter/nf_conntrack_irc.h b/include/linux/netfilter/nf_conntrack_irc.h index 2ab6b8255911..36282bf71b63 100644 --- a/include/linux/netfilter/nf_conntrack_irc.h +++ b/include/linux/netfilter/nf_conntrack_irc.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #define IRC_PORT 6667 | 6 | #define IRC_PORT 6667 |
| 7 | 7 | ||
| 8 | extern unsigned int (*nf_nat_irc_hook)(struct sk_buff **pskb, | 8 | extern unsigned int (*nf_nat_irc_hook)(struct sk_buff *skb, |
| 9 | enum ip_conntrack_info ctinfo, | 9 | enum ip_conntrack_info ctinfo, |
| 10 | unsigned int matchoff, | 10 | unsigned int matchoff, |
| 11 | unsigned int matchlen, | 11 | unsigned int matchlen, |
diff --git a/include/linux/netfilter/nf_conntrack_pptp.h b/include/linux/netfilter/nf_conntrack_pptp.h index c93061f33144..23435496d24a 100644 --- a/include/linux/netfilter/nf_conntrack_pptp.h +++ b/include/linux/netfilter/nf_conntrack_pptp.h | |||
| @@ -301,13 +301,13 @@ struct nf_conn; | |||
| 301 | struct nf_conntrack_expect; | 301 | struct nf_conntrack_expect; |
| 302 | 302 | ||
| 303 | extern int | 303 | extern int |
| 304 | (*nf_nat_pptp_hook_outbound)(struct sk_buff **pskb, | 304 | (*nf_nat_pptp_hook_outbound)(struct sk_buff *skb, |
| 305 | struct nf_conn *ct, enum ip_conntrack_info ctinfo, | 305 | struct nf_conn *ct, enum ip_conntrack_info ctinfo, |
| 306 | struct PptpControlHeader *ctlh, | 306 | struct PptpControlHeader *ctlh, |
| 307 | union pptp_ctrl_union *pptpReq); | 307 | union pptp_ctrl_union *pptpReq); |
| 308 | 308 | ||
| 309 | extern int | 309 | extern int |
| 310 | (*nf_nat_pptp_hook_inbound)(struct sk_buff **pskb, | 310 | (*nf_nat_pptp_hook_inbound)(struct sk_buff *skb, |
| 311 | struct nf_conn *ct, enum ip_conntrack_info ctinfo, | 311 | struct nf_conn *ct, enum ip_conntrack_info ctinfo, |
| 312 | struct PptpControlHeader *ctlh, | 312 | struct PptpControlHeader *ctlh, |
| 313 | union pptp_ctrl_union *pptpReq); | 313 | union pptp_ctrl_union *pptpReq); |
diff --git a/include/linux/netfilter/nf_conntrack_sip.h b/include/linux/netfilter/nf_conntrack_sip.h index bb7f2041db74..9fff19779bd5 100644 --- a/include/linux/netfilter/nf_conntrack_sip.h +++ b/include/linux/netfilter/nf_conntrack_sip.h | |||
| @@ -21,11 +21,11 @@ enum sip_header_pos { | |||
| 21 | POS_SDP_HEADER, | 21 | POS_SDP_HEADER, |
| 22 | }; | 22 | }; |
| 23 | 23 | ||
| 24 | extern unsigned int (*nf_nat_sip_hook)(struct sk_buff **pskb, | 24 | extern unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb, |
| 25 | enum ip_conntrack_info ctinfo, | 25 | enum ip_conntrack_info ctinfo, |
| 26 | struct nf_conn *ct, | 26 | struct nf_conn *ct, |
| 27 | const char **dptr); | 27 | const char **dptr); |
| 28 | extern unsigned int (*nf_nat_sdp_hook)(struct sk_buff **pskb, | 28 | extern unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb, |
| 29 | enum ip_conntrack_info ctinfo, | 29 | enum ip_conntrack_info ctinfo, |
| 30 | struct nf_conntrack_expect *exp, | 30 | struct nf_conntrack_expect *exp, |
| 31 | const char *dptr); | 31 | const char *dptr); |
diff --git a/include/linux/netfilter/nf_conntrack_tftp.h b/include/linux/netfilter/nf_conntrack_tftp.h index 0d79b7ae051f..c78d38fdb050 100644 --- a/include/linux/netfilter/nf_conntrack_tftp.h +++ b/include/linux/netfilter/nf_conntrack_tftp.h | |||
| @@ -13,7 +13,7 @@ struct tftphdr { | |||
| 13 | #define TFTP_OPCODE_ACK 4 | 13 | #define TFTP_OPCODE_ACK 4 |
| 14 | #define TFTP_OPCODE_ERROR 5 | 14 | #define TFTP_OPCODE_ERROR 5 |
| 15 | 15 | ||
| 16 | extern unsigned int (*nf_nat_tftp_hook)(struct sk_buff **pskb, | 16 | extern unsigned int (*nf_nat_tftp_hook)(struct sk_buff *skb, |
| 17 | enum ip_conntrack_info ctinfo, | 17 | enum ip_conntrack_info ctinfo, |
| 18 | struct nf_conntrack_expect *exp); | 18 | struct nf_conntrack_expect *exp); |
| 19 | 19 | ||
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 64f425a855bb..03e6ce979eaa 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h | |||
| @@ -191,7 +191,7 @@ struct xt_target | |||
| 191 | /* Returns verdict. Argument order changed since 2.6.9, as this | 191 | /* Returns verdict. Argument order changed since 2.6.9, as this |
| 192 | must now handle non-linear skbs, using skb_copy_bits and | 192 | must now handle non-linear skbs, using skb_copy_bits and |
| 193 | skb_ip_make_writable. */ | 193 | skb_ip_make_writable. */ |
| 194 | unsigned int (*target)(struct sk_buff **pskb, | 194 | unsigned int (*target)(struct sk_buff *skb, |
| 195 | const struct net_device *in, | 195 | const struct net_device *in, |
| 196 | const struct net_device *out, | 196 | const struct net_device *out, |
| 197 | unsigned int hooknum, | 197 | unsigned int hooknum, |
diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h index 584cd1b18f12..2fc73fa8e37f 100644 --- a/include/linux/netfilter_arp/arp_tables.h +++ b/include/linux/netfilter_arp/arp_tables.h | |||
| @@ -287,7 +287,7 @@ struct arpt_error | |||
| 287 | extern int arpt_register_table(struct arpt_table *table, | 287 | extern int arpt_register_table(struct arpt_table *table, |
| 288 | const struct arpt_replace *repl); | 288 | const struct arpt_replace *repl); |
| 289 | extern void arpt_unregister_table(struct arpt_table *table); | 289 | extern void arpt_unregister_table(struct arpt_table *table); |
| 290 | extern unsigned int arpt_do_table(struct sk_buff **pskb, | 290 | extern unsigned int arpt_do_table(struct sk_buff *skb, |
| 291 | unsigned int hook, | 291 | unsigned int hook, |
| 292 | const struct net_device *in, | 292 | const struct net_device *in, |
| 293 | const struct net_device *out, | 293 | const struct net_device *out, |
diff --git a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h index 94e0a7dc0cb2..892f5b7771c7 100644 --- a/include/linux/netfilter_bridge/ebtables.h +++ b/include/linux/netfilter_bridge/ebtables.h | |||
| @@ -237,7 +237,7 @@ struct ebt_target | |||
| 237 | struct list_head list; | 237 | struct list_head list; |
| 238 | const char name[EBT_FUNCTION_MAXNAMELEN]; | 238 | const char name[EBT_FUNCTION_MAXNAMELEN]; |
| 239 | /* returns one of the standard verdicts */ | 239 | /* returns one of the standard verdicts */ |
| 240 | int (*target)(struct sk_buff **pskb, unsigned int hooknr, | 240 | int (*target)(struct sk_buff *skb, unsigned int hooknr, |
| 241 | const struct net_device *in, const struct net_device *out, | 241 | const struct net_device *in, const struct net_device *out, |
| 242 | const void *targetdata, unsigned int datalen); | 242 | const void *targetdata, unsigned int datalen); |
| 243 | /* 0 == let it in */ | 243 | /* 0 == let it in */ |
| @@ -294,7 +294,7 @@ extern int ebt_register_watcher(struct ebt_watcher *watcher); | |||
| 294 | extern void ebt_unregister_watcher(struct ebt_watcher *watcher); | 294 | extern void ebt_unregister_watcher(struct ebt_watcher *watcher); |
| 295 | extern int ebt_register_target(struct ebt_target *target); | 295 | extern int ebt_register_target(struct ebt_target *target); |
| 296 | extern void ebt_unregister_target(struct ebt_target *target); | 296 | extern void ebt_unregister_target(struct ebt_target *target); |
| 297 | extern unsigned int ebt_do_table(unsigned int hook, struct sk_buff **pskb, | 297 | extern unsigned int ebt_do_table(unsigned int hook, struct sk_buff *skb, |
| 298 | const struct net_device *in, const struct net_device *out, | 298 | const struct net_device *in, const struct net_device *out, |
| 299 | struct ebt_table *table); | 299 | struct ebt_table *table); |
| 300 | 300 | ||
diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h index ceae87a4c891..1a63adf5c4c1 100644 --- a/include/linux/netfilter_ipv4.h +++ b/include/linux/netfilter_ipv4.h | |||
| @@ -75,8 +75,8 @@ enum nf_ip_hook_priorities { | |||
| 75 | #define SO_ORIGINAL_DST 80 | 75 | #define SO_ORIGINAL_DST 80 |
| 76 | 76 | ||
| 77 | #ifdef __KERNEL__ | 77 | #ifdef __KERNEL__ |
| 78 | extern int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type); | 78 | extern int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type); |
| 79 | extern int ip_xfrm_me_harder(struct sk_buff **pskb); | 79 | extern int ip_xfrm_me_harder(struct sk_buff *skb); |
| 80 | extern __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, | 80 | extern __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, |
| 81 | unsigned int dataoff, u_int8_t protocol); | 81 | unsigned int dataoff, u_int8_t protocol); |
| 82 | #endif /*__KERNEL__*/ | 82 | #endif /*__KERNEL__*/ |
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h index e992cd6b28f5..d79ed69cbc1f 100644 --- a/include/linux/netfilter_ipv4/ip_tables.h +++ b/include/linux/netfilter_ipv4/ip_tables.h | |||
| @@ -337,7 +337,7 @@ struct ipt_error | |||
| 337 | .target.errorname = "ERROR", \ | 337 | .target.errorname = "ERROR", \ |
| 338 | } | 338 | } |
| 339 | 339 | ||
| 340 | extern unsigned int ipt_do_table(struct sk_buff **pskb, | 340 | extern unsigned int ipt_do_table(struct sk_buff *skb, |
| 341 | unsigned int hook, | 341 | unsigned int hook, |
| 342 | const struct net_device *in, | 342 | const struct net_device *in, |
| 343 | const struct net_device *out, | 343 | const struct net_device *out, |
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h index 9a720f05888f..7dc481ce7cba 100644 --- a/include/linux/netfilter_ipv6/ip6_tables.h +++ b/include/linux/netfilter_ipv6/ip6_tables.h | |||
| @@ -336,7 +336,7 @@ extern void ip6t_init(void) __init; | |||
| 336 | extern int ip6t_register_table(struct xt_table *table, | 336 | extern int ip6t_register_table(struct xt_table *table, |
| 337 | const struct ip6t_replace *repl); | 337 | const struct ip6t_replace *repl); |
| 338 | extern void ip6t_unregister_table(struct xt_table *table); | 338 | extern void ip6t_unregister_table(struct xt_table *table); |
| 339 | extern unsigned int ip6t_do_table(struct sk_buff **pskb, | 339 | extern unsigned int ip6t_do_table(struct sk_buff *skb, |
| 340 | unsigned int hook, | 340 | unsigned int hook, |
| 341 | const struct net_device *in, | 341 | const struct net_device *in, |
| 342 | const struct net_device *out, | 342 | const struct net_device *out, |
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 7250eeadd7b5..c5164c257f71 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
| @@ -47,10 +47,8 @@ | |||
| 47 | #include <linux/nfs3.h> | 47 | #include <linux/nfs3.h> |
| 48 | #include <linux/nfs4.h> | 48 | #include <linux/nfs4.h> |
| 49 | #include <linux/nfs_xdr.h> | 49 | #include <linux/nfs_xdr.h> |
| 50 | |||
| 51 | #include <linux/nfs_fs_sb.h> | 50 | #include <linux/nfs_fs_sb.h> |
| 52 | 51 | ||
| 53 | #include <linux/rwsem.h> | ||
| 54 | #include <linux/mempool.h> | 52 | #include <linux/mempool.h> |
| 55 | 53 | ||
| 56 | /* | 54 | /* |
| @@ -77,6 +75,9 @@ struct nfs_open_context { | |||
| 77 | struct nfs4_state *state; | 75 | struct nfs4_state *state; |
| 78 | fl_owner_t lockowner; | 76 | fl_owner_t lockowner; |
| 79 | int mode; | 77 | int mode; |
| 78 | |||
| 79 | unsigned long flags; | ||
| 80 | #define NFS_CONTEXT_ERROR_WRITE (0) | ||
| 80 | int error; | 81 | int error; |
| 81 | 82 | ||
| 82 | struct list_head list; | 83 | struct list_head list; |
| @@ -133,11 +134,6 @@ struct nfs_inode { | |||
| 133 | * server. | 134 | * server. |
| 134 | */ | 135 | */ |
| 135 | unsigned long cache_change_attribute; | 136 | unsigned long cache_change_attribute; |
| 136 | /* | ||
| 137 | * Counter indicating the number of outstanding requests that | ||
| 138 | * will cause a file data update. | ||
| 139 | */ | ||
| 140 | atomic_t data_updates; | ||
| 141 | 137 | ||
| 142 | struct rb_root access_cache; | 138 | struct rb_root access_cache; |
| 143 | struct list_head access_cache_entry_lru; | 139 | struct list_head access_cache_entry_lru; |
| @@ -205,27 +201,18 @@ static inline struct nfs_inode *NFS_I(struct inode *inode) | |||
| 205 | #define NFS_CLIENT(inode) (NFS_SERVER(inode)->client) | 201 | #define NFS_CLIENT(inode) (NFS_SERVER(inode)->client) |
| 206 | #define NFS_PROTO(inode) (NFS_SERVER(inode)->nfs_client->rpc_ops) | 202 | #define NFS_PROTO(inode) (NFS_SERVER(inode)->nfs_client->rpc_ops) |
| 207 | #define NFS_COOKIEVERF(inode) (NFS_I(inode)->cookieverf) | 203 | #define NFS_COOKIEVERF(inode) (NFS_I(inode)->cookieverf) |
| 208 | #define NFS_READTIME(inode) (NFS_I(inode)->read_cache_jiffies) | ||
| 209 | #define NFS_CHANGE_ATTR(inode) (NFS_I(inode)->change_attr) | ||
| 210 | #define NFS_ATTRTIMEO(inode) (NFS_I(inode)->attrtimeo) | ||
| 211 | #define NFS_MINATTRTIMEO(inode) \ | 204 | #define NFS_MINATTRTIMEO(inode) \ |
| 212 | (S_ISDIR(inode->i_mode)? NFS_SERVER(inode)->acdirmin \ | 205 | (S_ISDIR(inode->i_mode)? NFS_SERVER(inode)->acdirmin \ |
| 213 | : NFS_SERVER(inode)->acregmin) | 206 | : NFS_SERVER(inode)->acregmin) |
| 214 | #define NFS_MAXATTRTIMEO(inode) \ | 207 | #define NFS_MAXATTRTIMEO(inode) \ |
| 215 | (S_ISDIR(inode->i_mode)? NFS_SERVER(inode)->acdirmax \ | 208 | (S_ISDIR(inode->i_mode)? NFS_SERVER(inode)->acdirmax \ |
| 216 | : NFS_SERVER(inode)->acregmax) | 209 | : NFS_SERVER(inode)->acregmax) |
| 217 | #define NFS_ATTRTIMEO_UPDATE(inode) (NFS_I(inode)->attrtimeo_timestamp) | ||
| 218 | 210 | ||
| 219 | #define NFS_FLAGS(inode) (NFS_I(inode)->flags) | 211 | #define NFS_FLAGS(inode) (NFS_I(inode)->flags) |
| 220 | #define NFS_STALE(inode) (test_bit(NFS_INO_STALE, &NFS_FLAGS(inode))) | 212 | #define NFS_STALE(inode) (test_bit(NFS_INO_STALE, &NFS_FLAGS(inode))) |
| 221 | 213 | ||
| 222 | #define NFS_FILEID(inode) (NFS_I(inode)->fileid) | 214 | #define NFS_FILEID(inode) (NFS_I(inode)->fileid) |
| 223 | 215 | ||
| 224 | static inline int nfs_caches_unstable(struct inode *inode) | ||
| 225 | { | ||
| 226 | return atomic_read(&NFS_I(inode)->data_updates) != 0; | ||
| 227 | } | ||
| 228 | |||
| 229 | static inline void nfs_mark_for_revalidate(struct inode *inode) | 216 | static inline void nfs_mark_for_revalidate(struct inode *inode) |
| 230 | { | 217 | { |
| 231 | struct nfs_inode *nfsi = NFS_I(inode); | 218 | struct nfs_inode *nfsi = NFS_I(inode); |
| @@ -237,12 +224,6 @@ static inline void nfs_mark_for_revalidate(struct inode *inode) | |||
| 237 | spin_unlock(&inode->i_lock); | 224 | spin_unlock(&inode->i_lock); |
| 238 | } | 225 | } |
| 239 | 226 | ||
| 240 | static inline void NFS_CACHEINV(struct inode *inode) | ||
| 241 | { | ||
| 242 | if (!nfs_caches_unstable(inode)) | ||
| 243 | nfs_mark_for_revalidate(inode); | ||
| 244 | } | ||
| 245 | |||
| 246 | static inline int nfs_server_capable(struct inode *inode, int cap) | 227 | static inline int nfs_server_capable(struct inode *inode, int cap) |
| 247 | { | 228 | { |
| 248 | return NFS_SERVER(inode)->caps & cap; | 229 | return NFS_SERVER(inode)->caps & cap; |
| @@ -253,28 +234,33 @@ static inline int NFS_USE_READDIRPLUS(struct inode *inode) | |||
| 253 | return test_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode)); | 234 | return test_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode)); |
| 254 | } | 235 | } |
| 255 | 236 | ||
| 237 | static inline void nfs_set_verifier(struct dentry * dentry, unsigned long verf) | ||
| 238 | { | ||
| 239 | dentry->d_time = verf; | ||
| 240 | } | ||
| 241 | |||
| 256 | /** | 242 | /** |
| 257 | * nfs_save_change_attribute - Returns the inode attribute change cookie | 243 | * nfs_save_change_attribute - Returns the inode attribute change cookie |
| 258 | * @inode - pointer to inode | 244 | * @dir - pointer to parent directory inode |
| 259 | * The "change attribute" is updated every time we finish an operation | 245 | * The "change attribute" is updated every time we finish an operation |
| 260 | * that will result in a metadata change on the server. | 246 | * that will result in a metadata change on the server. |
| 261 | */ | 247 | */ |
| 262 | static inline long nfs_save_change_attribute(struct inode *inode) | 248 | static inline unsigned long nfs_save_change_attribute(struct inode *dir) |
| 263 | { | 249 | { |
| 264 | return NFS_I(inode)->cache_change_attribute; | 250 | return NFS_I(dir)->cache_change_attribute; |
| 265 | } | 251 | } |
| 266 | 252 | ||
| 267 | /** | 253 | /** |
| 268 | * nfs_verify_change_attribute - Detects NFS inode cache updates | 254 | * nfs_verify_change_attribute - Detects NFS remote directory changes |
| 269 | * @inode - pointer to inode | 255 | * @dir - pointer to parent directory inode |
| 270 | * @chattr - previously saved change attribute | 256 | * @chattr - previously saved change attribute |
| 271 | * Return "false" if metadata has been updated (or is in the process of | 257 | * Return "false" if the verifiers doesn't match the change attribute. |
| 272 | * being updated) since the change attribute was saved. | 258 | * This would usually indicate that the directory contents have changed on |
| 259 | * the server, and that any dentries need revalidating. | ||
| 273 | */ | 260 | */ |
| 274 | static inline int nfs_verify_change_attribute(struct inode *inode, unsigned long chattr) | 261 | static inline int nfs_verify_change_attribute(struct inode *dir, unsigned long chattr) |
| 275 | { | 262 | { |
| 276 | return !nfs_caches_unstable(inode) | 263 | return chattr == NFS_I(dir)->cache_change_attribute; |
| 277 | && time_after_eq(chattr, NFS_I(inode)->cache_change_attribute); | ||
| 278 | } | 264 | } |
| 279 | 265 | ||
| 280 | /* | 266 | /* |
| @@ -283,15 +269,14 @@ static inline int nfs_verify_change_attribute(struct inode *inode, unsigned long | |||
| 283 | extern int nfs_sync_mapping(struct address_space *mapping); | 269 | extern int nfs_sync_mapping(struct address_space *mapping); |
| 284 | extern void nfs_zap_mapping(struct inode *inode, struct address_space *mapping); | 270 | extern void nfs_zap_mapping(struct inode *inode, struct address_space *mapping); |
| 285 | extern void nfs_zap_caches(struct inode *); | 271 | extern void nfs_zap_caches(struct inode *); |
| 272 | extern void nfs_invalidate_atime(struct inode *); | ||
| 286 | extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *, | 273 | extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *, |
| 287 | struct nfs_fattr *); | 274 | struct nfs_fattr *); |
| 288 | extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *); | 275 | extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *); |
| 289 | extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr); | 276 | extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr); |
| 277 | extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr); | ||
| 290 | extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *); | 278 | extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *); |
| 291 | extern int nfs_permission(struct inode *, int, struct nameidata *); | 279 | extern int nfs_permission(struct inode *, int, struct nameidata *); |
| 292 | extern int nfs_access_get_cached(struct inode *, struct rpc_cred *, struct nfs_access_entry *); | ||
| 293 | extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *); | ||
| 294 | extern void nfs_access_zap_cache(struct inode *inode); | ||
| 295 | extern int nfs_open(struct inode *, struct file *); | 280 | extern int nfs_open(struct inode *, struct file *); |
| 296 | extern int nfs_release(struct inode *, struct file *); | 281 | extern int nfs_release(struct inode *, struct file *); |
| 297 | extern int nfs_attribute_timeout(struct inode *inode); | 282 | extern int nfs_attribute_timeout(struct inode *inode); |
| @@ -301,13 +286,10 @@ extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *map | |||
| 301 | extern int nfs_revalidate_mapping_nolock(struct inode *inode, struct address_space *mapping); | 286 | extern int nfs_revalidate_mapping_nolock(struct inode *inode, struct address_space *mapping); |
| 302 | extern int nfs_setattr(struct dentry *, struct iattr *); | 287 | extern int nfs_setattr(struct dentry *, struct iattr *); |
| 303 | extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr); | 288 | extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr); |
| 304 | extern void nfs_begin_attr_update(struct inode *); | ||
| 305 | extern void nfs_end_attr_update(struct inode *); | ||
| 306 | extern void nfs_begin_data_update(struct inode *); | ||
| 307 | extern void nfs_end_data_update(struct inode *); | ||
| 308 | extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx); | 289 | extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx); |
| 309 | extern void put_nfs_open_context(struct nfs_open_context *ctx); | 290 | extern void put_nfs_open_context(struct nfs_open_context *ctx); |
| 310 | extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, int mode); | 291 | extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, int mode); |
| 292 | extern u64 nfs_compat_user_ino64(u64 fileid); | ||
| 311 | 293 | ||
| 312 | /* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */ | 294 | /* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */ |
| 313 | extern __be32 root_nfs_parse_addr(char *name); /*__init*/ | 295 | extern __be32 root_nfs_parse_addr(char *name); /*__init*/ |
| @@ -328,14 +310,15 @@ extern const struct inode_operations nfs3_file_inode_operations; | |||
| 328 | extern const struct file_operations nfs_file_operations; | 310 | extern const struct file_operations nfs_file_operations; |
| 329 | extern const struct address_space_operations nfs_file_aops; | 311 | extern const struct address_space_operations nfs_file_aops; |
| 330 | 312 | ||
| 331 | static inline struct rpc_cred *nfs_file_cred(struct file *file) | 313 | static inline struct nfs_open_context *nfs_file_open_context(struct file *filp) |
| 332 | { | 314 | { |
| 333 | if (file != NULL) { | 315 | return filp->private_data; |
| 334 | struct nfs_open_context *ctx; | 316 | } |
| 335 | 317 | ||
| 336 | ctx = (struct nfs_open_context*)file->private_data; | 318 | static inline struct rpc_cred *nfs_file_cred(struct file *file) |
| 337 | return ctx->cred; | 319 | { |
| 338 | } | 320 | if (file != NULL) |
| 321 | return nfs_file_open_context(file)->cred; | ||
| 339 | return NULL; | 322 | return NULL; |
| 340 | } | 323 | } |
| 341 | 324 | ||
| @@ -378,6 +361,8 @@ extern const struct file_operations nfs_dir_operations; | |||
| 378 | extern struct dentry_operations nfs_dentry_operations; | 361 | extern struct dentry_operations nfs_dentry_operations; |
| 379 | 362 | ||
| 380 | extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr); | 363 | extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr); |
| 364 | extern int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags); | ||
| 365 | extern void nfs_access_zap_cache(struct inode *inode); | ||
| 381 | 366 | ||
| 382 | /* | 367 | /* |
| 383 | * linux/fs/nfs/symlink.c | 368 | * linux/fs/nfs/symlink.c |
| @@ -420,15 +405,14 @@ extern int nfs_flush_incompatible(struct file *file, struct page *page); | |||
| 420 | extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int); | 405 | extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int); |
| 421 | extern int nfs_writeback_done(struct rpc_task *, struct nfs_write_data *); | 406 | extern int nfs_writeback_done(struct rpc_task *, struct nfs_write_data *); |
| 422 | extern void nfs_writedata_release(void *); | 407 | extern void nfs_writedata_release(void *); |
| 423 | extern int nfs_set_page_dirty(struct page *); | ||
| 424 | 408 | ||
| 425 | /* | 409 | /* |
| 426 | * Try to write back everything synchronously (but check the | 410 | * Try to write back everything synchronously (but check the |
| 427 | * return value!) | 411 | * return value!) |
| 428 | */ | 412 | */ |
| 429 | extern long nfs_sync_mapping_wait(struct address_space *, struct writeback_control *, int); | 413 | extern long nfs_sync_mapping_wait(struct address_space *, struct writeback_control *, int); |
| 430 | extern int nfs_sync_mapping_range(struct address_space *, loff_t, loff_t, int); | ||
| 431 | extern int nfs_wb_all(struct inode *inode); | 414 | extern int nfs_wb_all(struct inode *inode); |
| 415 | extern int nfs_wb_nocommit(struct inode *inode); | ||
| 432 | extern int nfs_wb_page(struct inode *inode, struct page* page); | 416 | extern int nfs_wb_page(struct inode *inode, struct page* page); |
| 433 | extern int nfs_wb_page_priority(struct inode *inode, struct page* page, int how); | 417 | extern int nfs_wb_page_priority(struct inode *inode, struct page* page, int how); |
| 434 | extern int nfs_wb_page_cancel(struct inode *inode, struct page* page); | 418 | extern int nfs_wb_page_cancel(struct inode *inode, struct page* page); |
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h index 78e60798d10e..30dbcc185e69 100644 --- a/include/linux/nfs_page.h +++ b/include/linux/nfs_page.h | |||
| @@ -30,7 +30,6 @@ | |||
| 30 | #define PG_BUSY 0 | 30 | #define PG_BUSY 0 |
| 31 | #define PG_NEED_COMMIT 1 | 31 | #define PG_NEED_COMMIT 1 |
| 32 | #define PG_NEED_RESCHED 2 | 32 | #define PG_NEED_RESCHED 2 |
| 33 | #define PG_NEED_FLUSH 3 | ||
| 34 | 33 | ||
| 35 | struct nfs_inode; | 34 | struct nfs_inode; |
| 36 | struct nfs_page { | 35 | struct nfs_page { |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index cf74a4db84a5..daab252f2e5c 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
| @@ -62,7 +62,8 @@ struct nfs_fattr { | |||
| 62 | #define NFS_ATTR_FATTR 0x0002 /* post-op attributes */ | 62 | #define NFS_ATTR_FATTR 0x0002 /* post-op attributes */ |
| 63 | #define NFS_ATTR_FATTR_V3 0x0004 /* NFSv3 attributes */ | 63 | #define NFS_ATTR_FATTR_V3 0x0004 /* NFSv3 attributes */ |
| 64 | #define NFS_ATTR_FATTR_V4 0x0008 /* NFSv4 change attribute */ | 64 | #define NFS_ATTR_FATTR_V4 0x0008 /* NFSv4 change attribute */ |
| 65 | #define NFS_ATTR_FATTR_V4_REFERRAL 0x0010 /* NFSv4 referral */ | 65 | #define NFS_ATTR_WCC_V4 0x0010 /* pre-op change attribute */ |
| 66 | #define NFS_ATTR_FATTR_V4_REFERRAL 0x0020 /* NFSv4 referral */ | ||
| 66 | 67 | ||
| 67 | /* | 68 | /* |
| 68 | * Info on the file system | 69 | * Info on the file system |
| @@ -538,10 +539,13 @@ typedef u64 clientid4; | |||
| 538 | 539 | ||
| 539 | struct nfs4_accessargs { | 540 | struct nfs4_accessargs { |
| 540 | const struct nfs_fh * fh; | 541 | const struct nfs_fh * fh; |
| 542 | const u32 * bitmask; | ||
| 541 | u32 access; | 543 | u32 access; |
| 542 | }; | 544 | }; |
| 543 | 545 | ||
| 544 | struct nfs4_accessres { | 546 | struct nfs4_accessres { |
| 547 | const struct nfs_server * server; | ||
| 548 | struct nfs_fattr * fattr; | ||
| 545 | u32 supported; | 549 | u32 supported; |
| 546 | u32 access; | 550 | u32 access; |
| 547 | }; | 551 | }; |
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index fe17d7d750c2..76c1a530edc5 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | #include <linux/percpu.h> | 41 | #include <linux/percpu.h> |
| 42 | #include <linux/cpumask.h> | 42 | #include <linux/cpumask.h> |
| 43 | #include <linux/seqlock.h> | 43 | #include <linux/seqlock.h> |
| 44 | #include <linux/lockdep.h> | ||
| 44 | 45 | ||
| 45 | /** | 46 | /** |
| 46 | * struct rcu_head - callback structure for use with RCU | 47 | * struct rcu_head - callback structure for use with RCU |
| @@ -133,6 +134,15 @@ static inline void rcu_bh_qsctr_inc(int cpu) | |||
| 133 | extern int rcu_pending(int cpu); | 134 | extern int rcu_pending(int cpu); |
| 134 | extern int rcu_needs_cpu(int cpu); | 135 | extern int rcu_needs_cpu(int cpu); |
| 135 | 136 | ||
| 137 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
| 138 | extern struct lockdep_map rcu_lock_map; | ||
| 139 | # define rcu_read_acquire() lock_acquire(&rcu_lock_map, 0, 0, 2, 1, _THIS_IP_) | ||
| 140 | # define rcu_read_release() lock_release(&rcu_lock_map, 1, _THIS_IP_) | ||
| 141 | #else | ||
| 142 | # define rcu_read_acquire() do { } while (0) | ||
| 143 | # define rcu_read_release() do { } while (0) | ||
| 144 | #endif | ||
| 145 | |||
| 136 | /** | 146 | /** |
| 137 | * rcu_read_lock - mark the beginning of an RCU read-side critical section. | 147 | * rcu_read_lock - mark the beginning of an RCU read-side critical section. |
| 138 | * | 148 | * |
| @@ -166,6 +176,7 @@ extern int rcu_needs_cpu(int cpu); | |||
| 166 | do { \ | 176 | do { \ |
| 167 | preempt_disable(); \ | 177 | preempt_disable(); \ |
| 168 | __acquire(RCU); \ | 178 | __acquire(RCU); \ |
| 179 | rcu_read_acquire(); \ | ||
| 169 | } while(0) | 180 | } while(0) |
| 170 | 181 | ||
| 171 | /** | 182 | /** |
| @@ -175,6 +186,7 @@ extern int rcu_needs_cpu(int cpu); | |||
| 175 | */ | 186 | */ |
| 176 | #define rcu_read_unlock() \ | 187 | #define rcu_read_unlock() \ |
| 177 | do { \ | 188 | do { \ |
| 189 | rcu_read_release(); \ | ||
| 178 | __release(RCU); \ | 190 | __release(RCU); \ |
| 179 | preempt_enable(); \ | 191 | preempt_enable(); \ |
| 180 | } while(0) | 192 | } while(0) |
| @@ -204,6 +216,7 @@ extern int rcu_needs_cpu(int cpu); | |||
| 204 | do { \ | 216 | do { \ |
| 205 | local_bh_disable(); \ | 217 | local_bh_disable(); \ |
| 206 | __acquire(RCU_BH); \ | 218 | __acquire(RCU_BH); \ |
| 219 | rcu_read_acquire(); \ | ||
| 207 | } while(0) | 220 | } while(0) |
| 208 | 221 | ||
| 209 | /* | 222 | /* |
| @@ -213,6 +226,7 @@ extern int rcu_needs_cpu(int cpu); | |||
| 213 | */ | 226 | */ |
| 214 | #define rcu_read_unlock_bh() \ | 227 | #define rcu_read_unlock_bh() \ |
| 215 | do { \ | 228 | do { \ |
| 229 | rcu_read_release(); \ | ||
| 216 | __release(RCU_BH); \ | 230 | __release(RCU_BH); \ |
| 217 | local_bh_enable(); \ | 231 | local_bh_enable(); \ |
| 218 | } while(0) | 232 | } while(0) |
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index a656cecd373c..f93f22b3d2ff 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
| @@ -357,6 +357,7 @@ static inline struct sk_buff *alloc_skb_fclone(unsigned int size, | |||
| 357 | } | 357 | } |
| 358 | 358 | ||
| 359 | extern void kfree_skbmem(struct sk_buff *skb); | 359 | extern void kfree_skbmem(struct sk_buff *skb); |
| 360 | extern struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src); | ||
| 360 | extern struct sk_buff *skb_clone(struct sk_buff *skb, | 361 | extern struct sk_buff *skb_clone(struct sk_buff *skb, |
| 361 | gfp_t priority); | 362 | gfp_t priority); |
| 362 | extern struct sk_buff *skb_copy(const struct sk_buff *skb, | 363 | extern struct sk_buff *skb_copy(const struct sk_buff *skb, |
| @@ -1781,6 +1782,11 @@ static inline int skb_is_gso(const struct sk_buff *skb) | |||
| 1781 | return skb_shinfo(skb)->gso_size; | 1782 | return skb_shinfo(skb)->gso_size; |
| 1782 | } | 1783 | } |
| 1783 | 1784 | ||
| 1785 | static inline int skb_is_gso_v6(const struct sk_buff *skb) | ||
| 1786 | { | ||
| 1787 | return skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6; | ||
| 1788 | } | ||
| 1789 | |||
| 1784 | static inline void skb_forward_csum(struct sk_buff *skb) | 1790 | static inline void skb_forward_csum(struct sk_buff *skb) |
| 1785 | { | 1791 | { |
| 1786 | /* Unfortunately we don't support this one. Any brave souls? */ | 1792 | /* Unfortunately we don't support this one. Any brave souls? */ |
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index c0d9d14983b3..d9d5c5ad826c 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h | |||
| @@ -117,7 +117,7 @@ struct rpc_create_args { | |||
| 117 | 117 | ||
| 118 | struct rpc_clnt *rpc_create(struct rpc_create_args *args); | 118 | struct rpc_clnt *rpc_create(struct rpc_create_args *args); |
| 119 | struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *, | 119 | struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *, |
| 120 | struct rpc_program *, int); | 120 | struct rpc_program *, u32); |
| 121 | struct rpc_clnt *rpc_clone_client(struct rpc_clnt *); | 121 | struct rpc_clnt *rpc_clone_client(struct rpc_clnt *); |
| 122 | void rpc_shutdown_client(struct rpc_clnt *); | 122 | void rpc_shutdown_client(struct rpc_clnt *); |
| 123 | void rpc_release_client(struct rpc_clnt *); | 123 | void rpc_release_client(struct rpc_clnt *); |
diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h index 3912cf16361e..3347c72b848a 100644 --- a/include/linux/sunrpc/debug.h +++ b/include/linux/sunrpc/debug.h | |||
| @@ -88,6 +88,11 @@ enum { | |||
| 88 | CTL_SLOTTABLE_TCP, | 88 | CTL_SLOTTABLE_TCP, |
| 89 | CTL_MIN_RESVPORT, | 89 | CTL_MIN_RESVPORT, |
| 90 | CTL_MAX_RESVPORT, | 90 | CTL_MAX_RESVPORT, |
| 91 | CTL_SLOTTABLE_RDMA, | ||
| 92 | CTL_RDMA_MAXINLINEREAD, | ||
| 93 | CTL_RDMA_MAXINLINEWRITE, | ||
| 94 | CTL_RDMA_WRITEPADDING, | ||
| 95 | CTL_RDMA_MEMREG, | ||
| 91 | }; | 96 | }; |
| 92 | 97 | ||
| 93 | #endif /* _LINUX_SUNRPC_DEBUG_H_ */ | 98 | #endif /* _LINUX_SUNRPC_DEBUG_H_ */ |
diff --git a/include/linux/sunrpc/msg_prot.h b/include/linux/sunrpc/msg_prot.h index 784d4c3ef651..c4beb5775111 100644 --- a/include/linux/sunrpc/msg_prot.h +++ b/include/linux/sunrpc/msg_prot.h | |||
| @@ -138,6 +138,19 @@ typedef __be32 rpc_fraghdr; | |||
| 138 | #define RPC_MAX_HEADER_WITH_AUTH \ | 138 | #define RPC_MAX_HEADER_WITH_AUTH \ |
| 139 | (RPC_CALLHDRSIZE + 2*(2+RPC_MAX_AUTH_SIZE/4)) | 139 | (RPC_CALLHDRSIZE + 2*(2+RPC_MAX_AUTH_SIZE/4)) |
| 140 | 140 | ||
| 141 | /* | ||
| 142 | * RFC1833/RFC3530 rpcbind (v3+) well-known netid's. | ||
| 143 | */ | ||
| 144 | #define RPCBIND_NETID_UDP "udp" | ||
| 145 | #define RPCBIND_NETID_TCP "tcp" | ||
| 146 | #define RPCBIND_NETID_UDP6 "udp6" | ||
| 147 | #define RPCBIND_NETID_TCP6 "tcp6" | ||
| 148 | |||
| 149 | /* | ||
| 150 | * Note that RFC 1833 does not put any size restrictions on the | ||
| 151 | * netid string, but all currently defined netid's fit in 4 bytes. | ||
| 152 | */ | ||
| 153 | #define RPCBIND_MAXNETIDLEN (4u) | ||
| 141 | 154 | ||
| 142 | #endif /* __KERNEL__ */ | 155 | #endif /* __KERNEL__ */ |
| 143 | #endif /* _LINUX_SUNRPC_MSGPROT_H_ */ | 156 | #endif /* _LINUX_SUNRPC_MSGPROT_H_ */ |
diff --git a/include/linux/sunrpc/rpc_rdma.h b/include/linux/sunrpc/rpc_rdma.h new file mode 100644 index 000000000000..0013a0d8dc6b --- /dev/null +++ b/include/linux/sunrpc/rpc_rdma.h | |||
| @@ -0,0 +1,116 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved. | ||
| 3 | * | ||
| 4 | * This software is available to you under a choice of one of two | ||
| 5 | * licenses. You may choose to be licensed under the terms of the GNU | ||
| 6 | * General Public License (GPL) Version 2, available from the file | ||
| 7 | * COPYING in the main directory of this source tree, or the BSD-type | ||
| 8 | * license below: | ||
| 9 | * | ||
| 10 | * Redistribution and use in source and binary forms, with or without | ||
| 11 | * modification, are permitted provided that the following conditions | ||
| 12 | * are met: | ||
| 13 | * | ||
| 14 | * Redistributions of source code must retain the above copyright | ||
| 15 | * notice, this list of conditions and the following disclaimer. | ||
| 16 | * | ||
| 17 | * Redistributions in binary form must reproduce the above | ||
| 18 | * copyright notice, this list of conditions and the following | ||
| 19 | * disclaimer in the documentation and/or other materials provided | ||
| 20 | * with the distribution. | ||
| 21 | * | ||
| 22 | * Neither the name of the Network Appliance, Inc. nor the names of | ||
| 23 | * its contributors may be used to endorse or promote products | ||
| 24 | * derived from this software without specific prior written | ||
| 25 | * permission. | ||
| 26 | * | ||
| 27 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| 28 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| 29 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
| 30 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| 31 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
| 32 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
| 33 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
| 34 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
| 35 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 36 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
| 37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 38 | */ | ||
| 39 | |||
| 40 | #ifndef _LINUX_SUNRPC_RPC_RDMA_H | ||
| 41 | #define _LINUX_SUNRPC_RPC_RDMA_H | ||
| 42 | |||
| 43 | struct rpcrdma_segment { | ||
| 44 | uint32_t rs_handle; /* Registered memory handle */ | ||
| 45 | uint32_t rs_length; /* Length of the chunk in bytes */ | ||
| 46 | uint64_t rs_offset; /* Chunk virtual address or offset */ | ||
| 47 | }; | ||
| 48 | |||
| 49 | /* | ||
| 50 | * read chunk(s), encoded as a linked list. | ||
| 51 | */ | ||
| 52 | struct rpcrdma_read_chunk { | ||
| 53 | uint32_t rc_discrim; /* 1 indicates presence */ | ||
| 54 | uint32_t rc_position; /* Position in XDR stream */ | ||
| 55 | struct rpcrdma_segment rc_target; | ||
| 56 | }; | ||
| 57 | |||
| 58 | /* | ||
| 59 | * write chunk, and reply chunk. | ||
| 60 | */ | ||
| 61 | struct rpcrdma_write_chunk { | ||
| 62 | struct rpcrdma_segment wc_target; | ||
| 63 | }; | ||
| 64 | |||
| 65 | /* | ||
| 66 | * write chunk(s), encoded as a counted array. | ||
| 67 | */ | ||
| 68 | struct rpcrdma_write_array { | ||
| 69 | uint32_t wc_discrim; /* 1 indicates presence */ | ||
| 70 | uint32_t wc_nchunks; /* Array count */ | ||
| 71 | struct rpcrdma_write_chunk wc_array[0]; | ||
| 72 | }; | ||
| 73 | |||
| 74 | struct rpcrdma_msg { | ||
| 75 | uint32_t rm_xid; /* Mirrors the RPC header xid */ | ||
| 76 | uint32_t rm_vers; /* Version of this protocol */ | ||
| 77 | uint32_t rm_credit; /* Buffers requested/granted */ | ||
| 78 | uint32_t rm_type; /* Type of message (enum rpcrdma_proc) */ | ||
| 79 | union { | ||
| 80 | |||
| 81 | struct { /* no chunks */ | ||
| 82 | uint32_t rm_empty[3]; /* 3 empty chunk lists */ | ||
| 83 | } rm_nochunks; | ||
| 84 | |||
| 85 | struct { /* no chunks and padded */ | ||
| 86 | uint32_t rm_align; /* Padding alignment */ | ||
| 87 | uint32_t rm_thresh; /* Padding threshold */ | ||
| 88 | uint32_t rm_pempty[3]; /* 3 empty chunk lists */ | ||
| 89 | } rm_padded; | ||
| 90 | |||
| 91 | uint32_t rm_chunks[0]; /* read, write and reply chunks */ | ||
| 92 | |||
| 93 | } rm_body; | ||
| 94 | }; | ||
| 95 | |||
| 96 | #define RPCRDMA_HDRLEN_MIN 28 | ||
| 97 | |||
| 98 | enum rpcrdma_errcode { | ||
| 99 | ERR_VERS = 1, | ||
| 100 | ERR_CHUNK = 2 | ||
| 101 | }; | ||
| 102 | |||
| 103 | struct rpcrdma_err_vers { | ||
| 104 | uint32_t rdma_vers_low; /* Version range supported by peer */ | ||
| 105 | uint32_t rdma_vers_high; | ||
| 106 | }; | ||
| 107 | |||
| 108 | enum rpcrdma_proc { | ||
| 109 | RDMA_MSG = 0, /* An RPC call or reply msg */ | ||
| 110 | RDMA_NOMSG = 1, /* An RPC call or reply msg - separate body */ | ||
| 111 | RDMA_MSGP = 2, /* An RPC call or reply msg with padding */ | ||
| 112 | RDMA_DONE = 3, /* Client signals reply completion */ | ||
| 113 | RDMA_ERROR = 4 /* An RPC RDMA encoding error */ | ||
| 114 | }; | ||
| 115 | |||
| 116 | #endif /* _LINUX_SUNRPC_RPC_RDMA_H */ | ||
diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h index c6b53d181bfa..0751c9464d0f 100644 --- a/include/linux/sunrpc/xdr.h +++ b/include/linux/sunrpc/xdr.h | |||
| @@ -70,7 +70,10 @@ struct xdr_buf { | |||
| 70 | 70 | ||
| 71 | struct page ** pages; /* Array of contiguous pages */ | 71 | struct page ** pages; /* Array of contiguous pages */ |
| 72 | unsigned int page_base, /* Start of page data */ | 72 | unsigned int page_base, /* Start of page data */ |
| 73 | page_len; /* Length of page data */ | 73 | page_len, /* Length of page data */ |
| 74 | flags; /* Flags for data disposition */ | ||
| 75 | #define XDRBUF_READ 0x01 /* target of file read */ | ||
| 76 | #define XDRBUF_WRITE 0x02 /* source of file write */ | ||
| 74 | 77 | ||
| 75 | unsigned int buflen, /* Total length of storage buffer */ | 78 | unsigned int buflen, /* Total length of storage buffer */ |
| 76 | len; /* Length of XDR encoded message */ | 79 | len; /* Length of XDR encoded message */ |
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index d11cedd14f0f..30b17b3bc1a9 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h | |||
| @@ -19,25 +19,11 @@ | |||
| 19 | 19 | ||
| 20 | #ifdef __KERNEL__ | 20 | #ifdef __KERNEL__ |
| 21 | 21 | ||
| 22 | extern unsigned int xprt_udp_slot_table_entries; | ||
| 23 | extern unsigned int xprt_tcp_slot_table_entries; | ||
| 24 | |||
| 25 | #define RPC_MIN_SLOT_TABLE (2U) | 22 | #define RPC_MIN_SLOT_TABLE (2U) |
| 26 | #define RPC_DEF_SLOT_TABLE (16U) | 23 | #define RPC_DEF_SLOT_TABLE (16U) |
| 27 | #define RPC_MAX_SLOT_TABLE (128U) | 24 | #define RPC_MAX_SLOT_TABLE (128U) |
| 28 | 25 | ||
| 29 | /* | 26 | /* |
| 30 | * Parameters for choosing a free port | ||
| 31 | */ | ||
| 32 | extern unsigned int xprt_min_resvport; | ||
| 33 | extern unsigned int xprt_max_resvport; | ||
| 34 | |||
| 35 | #define RPC_MIN_RESVPORT (1U) | ||
| 36 | #define RPC_MAX_RESVPORT (65535U) | ||
| 37 | #define RPC_DEF_MIN_RESVPORT (665U) | ||
| 38 | #define RPC_DEF_MAX_RESVPORT (1023U) | ||
| 39 | |||
| 40 | /* | ||
| 41 | * This describes a timeout strategy | 27 | * This describes a timeout strategy |
| 42 | */ | 28 | */ |
| 43 | struct rpc_timeout { | 29 | struct rpc_timeout { |
| @@ -53,6 +39,10 @@ enum rpc_display_format_t { | |||
| 53 | RPC_DISPLAY_PORT, | 39 | RPC_DISPLAY_PORT, |
| 54 | RPC_DISPLAY_PROTO, | 40 | RPC_DISPLAY_PROTO, |
| 55 | RPC_DISPLAY_ALL, | 41 | RPC_DISPLAY_ALL, |
| 42 | RPC_DISPLAY_HEX_ADDR, | ||
| 43 | RPC_DISPLAY_HEX_PORT, | ||
| 44 | RPC_DISPLAY_UNIVERSAL_ADDR, | ||
| 45 | RPC_DISPLAY_NETID, | ||
| 56 | RPC_DISPLAY_MAX, | 46 | RPC_DISPLAY_MAX, |
| 57 | }; | 47 | }; |
| 58 | 48 | ||
| @@ -196,14 +186,22 @@ struct rpc_xprt { | |||
| 196 | char * address_strings[RPC_DISPLAY_MAX]; | 186 | char * address_strings[RPC_DISPLAY_MAX]; |
| 197 | }; | 187 | }; |
| 198 | 188 | ||
| 199 | struct rpc_xprtsock_create { | 189 | struct xprt_create { |
| 200 | int proto; /* IPPROTO_UDP or IPPROTO_TCP */ | 190 | int ident; /* XPRT_TRANSPORT identifier */ |
| 201 | struct sockaddr * srcaddr; /* optional local address */ | 191 | struct sockaddr * srcaddr; /* optional local address */ |
| 202 | struct sockaddr * dstaddr; /* remote peer address */ | 192 | struct sockaddr * dstaddr; /* remote peer address */ |
| 203 | size_t addrlen; | 193 | size_t addrlen; |
| 204 | struct rpc_timeout * timeout; /* optional timeout parameters */ | 194 | struct rpc_timeout * timeout; /* optional timeout parameters */ |
| 205 | }; | 195 | }; |
| 206 | 196 | ||
| 197 | struct xprt_class { | ||
| 198 | struct list_head list; | ||
| 199 | int ident; /* XPRT_TRANSPORT identifier */ | ||
| 200 | struct rpc_xprt * (*setup)(struct xprt_create *); | ||
| 201 | struct module *owner; | ||
| 202 | char name[32]; | ||
| 203 | }; | ||
| 204 | |||
| 207 | /* | 205 | /* |
| 208 | * Transport operations used by ULPs | 206 | * Transport operations used by ULPs |
| 209 | */ | 207 | */ |
| @@ -212,7 +210,7 @@ void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long | |||
| 212 | /* | 210 | /* |
| 213 | * Generic internal transport functions | 211 | * Generic internal transport functions |
| 214 | */ | 212 | */ |
| 215 | struct rpc_xprt * xprt_create_transport(struct rpc_xprtsock_create *args); | 213 | struct rpc_xprt *xprt_create_transport(struct xprt_create *args); |
| 216 | void xprt_connect(struct rpc_task *task); | 214 | void xprt_connect(struct rpc_task *task); |
| 217 | void xprt_reserve(struct rpc_task *task); | 215 | void xprt_reserve(struct rpc_task *task); |
| 218 | int xprt_reserve_xprt(struct rpc_task *task); | 216 | int xprt_reserve_xprt(struct rpc_task *task); |
| @@ -235,6 +233,8 @@ static inline __be32 *xprt_skip_transport_header(struct rpc_xprt *xprt, __be32 * | |||
| 235 | /* | 233 | /* |
| 236 | * Transport switch helper functions | 234 | * Transport switch helper functions |
| 237 | */ | 235 | */ |
| 236 | int xprt_register_transport(struct xprt_class *type); | ||
| 237 | int xprt_unregister_transport(struct xprt_class *type); | ||
| 238 | void xprt_set_retrans_timeout_def(struct rpc_task *task); | 238 | void xprt_set_retrans_timeout_def(struct rpc_task *task); |
| 239 | void xprt_set_retrans_timeout_rtt(struct rpc_task *task); | 239 | void xprt_set_retrans_timeout_rtt(struct rpc_task *task); |
| 240 | void xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status); | 240 | void xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status); |
| @@ -248,14 +248,6 @@ void xprt_release_rqst_cong(struct rpc_task *task); | |||
| 248 | void xprt_disconnect(struct rpc_xprt *xprt); | 248 | void xprt_disconnect(struct rpc_xprt *xprt); |
| 249 | 249 | ||
| 250 | /* | 250 | /* |
| 251 | * Socket transport setup operations | ||
| 252 | */ | ||
| 253 | struct rpc_xprt * xs_setup_udp(struct rpc_xprtsock_create *args); | ||
| 254 | struct rpc_xprt * xs_setup_tcp(struct rpc_xprtsock_create *args); | ||
| 255 | int init_socket_xprt(void); | ||
| 256 | void cleanup_socket_xprt(void); | ||
| 257 | |||
| 258 | /* | ||
| 259 | * Reserved bit positions in xprt->state | 251 | * Reserved bit positions in xprt->state |
| 260 | */ | 252 | */ |
| 261 | #define XPRT_LOCKED (0) | 253 | #define XPRT_LOCKED (0) |
diff --git a/include/linux/sunrpc/xprtrdma.h b/include/linux/sunrpc/xprtrdma.h new file mode 100644 index 000000000000..4de56b1d372b --- /dev/null +++ b/include/linux/sunrpc/xprtrdma.h | |||
| @@ -0,0 +1,85 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved. | ||
| 3 | * | ||
| 4 | * This software is available to you under a choice of one of two | ||
| 5 | * licenses. You may choose to be licensed under the terms of the GNU | ||
| 6 | * General Public License (GPL) Version 2, available from the file | ||
| 7 | * COPYING in the main directory of this source tree, or the BSD-type | ||
| 8 | * license below: | ||
| 9 | * | ||
| 10 | * Redistribution and use in source and binary forms, with or without | ||
| 11 | * modification, are permitted provided that the following conditions | ||
| 12 | * are met: | ||
| 13 | * | ||
| 14 | * Redistributions of source code must retain the above copyright | ||
| 15 | * notice, this list of conditions and the following disclaimer. | ||
| 16 | * | ||
| 17 | * Redistributions in binary form must reproduce the above | ||
| 18 | * copyright notice, this list of conditions and the following | ||
| 19 | * disclaimer in the documentation and/or other materials provided | ||
| 20 | * with the distribution. | ||
| 21 | * | ||
| 22 | * Neither the name of the Network Appliance, Inc. nor the names of | ||
| 23 | * its contributors may be used to endorse or promote products | ||
| 24 | * derived from this software without specific prior written | ||
| 25 | * permission. | ||
| 26 | * | ||
| 27 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| 28 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| 29 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
| 30 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| 31 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
| 32 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
| 33 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
| 34 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
| 35 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 36 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
| 37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 38 | */ | ||
| 39 | |||
| 40 | #ifndef _LINUX_SUNRPC_XPRTRDMA_H | ||
| 41 | #define _LINUX_SUNRPC_XPRTRDMA_H | ||
| 42 | |||
| 43 | /* | ||
| 44 | * RPC transport identifier for RDMA | ||
| 45 | */ | ||
| 46 | #define XPRT_TRANSPORT_RDMA 256 | ||
| 47 | |||
| 48 | /* | ||
| 49 | * rpcbind (v3+) RDMA netid. | ||
| 50 | */ | ||
| 51 | #define RPCBIND_NETID_RDMA "rdma" | ||
| 52 | |||
| 53 | /* | ||
| 54 | * Constants. Max RPC/NFS header is big enough to account for | ||
| 55 | * additional marshaling buffers passed down by Linux client. | ||
| 56 | * | ||
| 57 | * RDMA header is currently fixed max size, and is big enough for a | ||
| 58 | * fully-chunked NFS message (read chunks are the largest). Note only | ||
| 59 | * a single chunk type per message is supported currently. | ||
| 60 | */ | ||
| 61 | #define RPCRDMA_MIN_SLOT_TABLE (2U) | ||
| 62 | #define RPCRDMA_DEF_SLOT_TABLE (32U) | ||
| 63 | #define RPCRDMA_MAX_SLOT_TABLE (256U) | ||
| 64 | |||
| 65 | #define RPCRDMA_DEF_INLINE (1024) /* default inline max */ | ||
| 66 | |||
| 67 | #define RPCRDMA_INLINE_PAD_THRESH (512)/* payload threshold to pad (bytes) */ | ||
| 68 | |||
| 69 | #define RDMA_RESOLVE_TIMEOUT (5*HZ) /* TBD 5 seconds */ | ||
| 70 | #define RDMA_CONNECT_RETRY_MAX (2) /* retries if no listener backlog */ | ||
| 71 | |||
| 72 | /* memory registration strategies */ | ||
| 73 | #define RPCRDMA_PERSISTENT_REGISTRATION (1) | ||
| 74 | |||
| 75 | enum rpcrdma_memreg { | ||
| 76 | RPCRDMA_BOUNCEBUFFERS = 0, | ||
| 77 | RPCRDMA_REGISTER, | ||
| 78 | RPCRDMA_MEMWINDOWS, | ||
| 79 | RPCRDMA_MEMWINDOWS_ASYNC, | ||
| 80 | RPCRDMA_MTHCAFMR, | ||
| 81 | RPCRDMA_ALLPHYSICAL, | ||
| 82 | RPCRDMA_LAST | ||
| 83 | }; | ||
| 84 | |||
| 85 | #endif /* _LINUX_SUNRPC_XPRTRDMA_H */ | ||
diff --git a/include/linux/sunrpc/xprtsock.h b/include/linux/sunrpc/xprtsock.h new file mode 100644 index 000000000000..2c6c2c2783d8 --- /dev/null +++ b/include/linux/sunrpc/xprtsock.h | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | /* | ||
| 2 | * linux/include/linux/sunrpc/xprtsock.h | ||
| 3 | * | ||
| 4 | * Declarations for the RPC transport socket provider. | ||
| 5 | */ | ||
| 6 | |||
| 7 | #ifndef _LINUX_SUNRPC_XPRTSOCK_H | ||
| 8 | #define _LINUX_SUNRPC_XPRTSOCK_H | ||
| 9 | |||
| 10 | #ifdef __KERNEL__ | ||
| 11 | |||
| 12 | /* | ||
| 13 | * Socket transport setup operations | ||
| 14 | */ | ||
| 15 | struct rpc_xprt *xs_setup_udp(struct xprt_create *args); | ||
| 16 | struct rpc_xprt *xs_setup_tcp(struct xprt_create *args); | ||
| 17 | |||
| 18 | int init_socket_xprt(void); | ||
| 19 | void cleanup_socket_xprt(void); | ||
| 20 | |||
| 21 | /* | ||
| 22 | * RPC transport identifiers for UDP, TCP | ||
| 23 | * | ||
| 24 | * To preserve compatibility with the historical use of raw IP protocol | ||
| 25 | * id's for transport selection, these are specified with the previous | ||
| 26 | * values. No such restriction exists for new transports, except that | ||
| 27 | * they may not collide with these values (17 and 6, respectively). | ||
| 28 | */ | ||
| 29 | #define XPRT_TRANSPORT_UDP IPPROTO_UDP | ||
| 30 | #define XPRT_TRANSPORT_TCP IPPROTO_TCP | ||
| 31 | |||
| 32 | /* | ||
| 33 | * RPC slot table sizes for UDP, TCP transports | ||
| 34 | */ | ||
| 35 | extern unsigned int xprt_udp_slot_table_entries; | ||
| 36 | extern unsigned int xprt_tcp_slot_table_entries; | ||
| 37 | |||
| 38 | /* | ||
| 39 | * Parameters for choosing a free port | ||
| 40 | */ | ||
| 41 | extern unsigned int xprt_min_resvport; | ||
| 42 | extern unsigned int xprt_max_resvport; | ||
| 43 | |||
| 44 | #define RPC_MIN_RESVPORT (1U) | ||
| 45 | #define RPC_MAX_RESVPORT (65535U) | ||
| 46 | #define RPC_DEF_MIN_RESVPORT (665U) | ||
| 47 | #define RPC_DEF_MAX_RESVPORT (1023U) | ||
| 48 | |||
| 49 | #endif /* __KERNEL__ */ | ||
| 50 | |||
| 51 | #endif /* _LINUX_SUNRPC_XPRTSOCK_H */ | ||
diff --git a/include/linux/tcp.h b/include/linux/tcp.h index c5b94c1a5ee2..bac17c59b24e 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h | |||
| @@ -315,7 +315,7 @@ struct tcp_sock { | |||
| 315 | */ | 315 | */ |
| 316 | u32 snd_ssthresh; /* Slow start size threshold */ | 316 | u32 snd_ssthresh; /* Slow start size threshold */ |
| 317 | u32 snd_cwnd; /* Sending congestion window */ | 317 | u32 snd_cwnd; /* Sending congestion window */ |
| 318 | u16 snd_cwnd_cnt; /* Linear increase counter */ | 318 | u32 snd_cwnd_cnt; /* Linear increase counter */ |
| 319 | u32 snd_cwnd_clamp; /* Do not allow snd_cwnd to grow above this */ | 319 | u32 snd_cwnd_clamp; /* Do not allow snd_cwnd to grow above this */ |
| 320 | u32 snd_cwnd_used; | 320 | u32 snd_cwnd_used; |
| 321 | u32 snd_cwnd_stamp; | 321 | u32 snd_cwnd_stamp; |
diff --git a/include/linux/writeback.h b/include/linux/writeback.h index c7c3337c3a88..d1321a81c9c4 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h | |||
| @@ -62,8 +62,6 @@ struct writeback_control { | |||
| 62 | unsigned for_reclaim:1; /* Invoked from the page allocator */ | 62 | unsigned for_reclaim:1; /* Invoked from the page allocator */ |
| 63 | unsigned for_writepages:1; /* This is a writepages() call */ | 63 | unsigned for_writepages:1; /* This is a writepages() call */ |
| 64 | unsigned range_cyclic:1; /* range_start is cyclic */ | 64 | unsigned range_cyclic:1; /* range_start is cyclic */ |
| 65 | |||
| 66 | void *fs_private; /* For use by ->writepages() */ | ||
| 67 | }; | 65 | }; |
| 68 | 66 | ||
| 69 | /* | 67 | /* |
diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h new file mode 100644 index 000000000000..911c2cd02941 --- /dev/null +++ b/include/net/inet_frag.h | |||
| @@ -0,0 +1,60 @@ | |||
| 1 | #ifndef __NET_FRAG_H__ | ||
| 2 | #define __NET_FRAG_H__ | ||
| 3 | |||
| 4 | struct inet_frag_queue { | ||
| 5 | struct hlist_node list; | ||
| 6 | struct list_head lru_list; /* lru list member */ | ||
| 7 | spinlock_t lock; | ||
| 8 | atomic_t refcnt; | ||
| 9 | struct timer_list timer; /* when will this queue expire? */ | ||
| 10 | struct sk_buff *fragments; /* list of received fragments */ | ||
| 11 | ktime_t stamp; | ||
| 12 | int len; /* total length of orig datagram */ | ||
| 13 | int meat; | ||
| 14 | __u8 last_in; /* first/last segment arrived? */ | ||
| 15 | |||
| 16 | #define COMPLETE 4 | ||
| 17 | #define FIRST_IN 2 | ||
| 18 | #define LAST_IN 1 | ||
| 19 | }; | ||
| 20 | |||
| 21 | #define INETFRAGS_HASHSZ 64 | ||
| 22 | |||
| 23 | struct inet_frags_ctl { | ||
| 24 | int high_thresh; | ||
| 25 | int low_thresh; | ||
| 26 | int timeout; | ||
| 27 | int secret_interval; | ||
| 28 | }; | ||
| 29 | |||
| 30 | struct inet_frags { | ||
| 31 | struct list_head lru_list; | ||
| 32 | struct hlist_head hash[INETFRAGS_HASHSZ]; | ||
| 33 | rwlock_t lock; | ||
| 34 | u32 rnd; | ||
| 35 | int nqueues; | ||
| 36 | int qsize; | ||
| 37 | atomic_t mem; | ||
| 38 | struct timer_list secret_timer; | ||
| 39 | struct inet_frags_ctl *ctl; | ||
| 40 | |||
| 41 | unsigned int (*hashfn)(struct inet_frag_queue *); | ||
| 42 | void (*destructor)(struct inet_frag_queue *); | ||
| 43 | void (*skb_free)(struct sk_buff *); | ||
| 44 | }; | ||
| 45 | |||
| 46 | void inet_frags_init(struct inet_frags *); | ||
| 47 | void inet_frags_fini(struct inet_frags *); | ||
| 48 | |||
| 49 | void inet_frag_kill(struct inet_frag_queue *q, struct inet_frags *f); | ||
| 50 | void inet_frag_destroy(struct inet_frag_queue *q, | ||
| 51 | struct inet_frags *f, int *work); | ||
| 52 | int inet_frag_evictor(struct inet_frags *f); | ||
| 53 | |||
| 54 | static inline void inet_frag_put(struct inet_frag_queue *q, struct inet_frags *f) | ||
| 55 | { | ||
| 56 | if (atomic_dec_and_test(&q->refcnt)) | ||
| 57 | inet_frag_destroy(q, f, NULL); | ||
| 58 | } | ||
| 59 | |||
| 60 | #endif | ||
diff --git a/include/net/ip.h b/include/net/ip.h index 3af3ed9d320b..840dd91b513b 100644 --- a/include/net/ip.h +++ b/include/net/ip.h | |||
| @@ -160,6 +160,7 @@ DECLARE_SNMP_STAT(struct ipstats_mib, ip_statistics); | |||
| 160 | #define IP_INC_STATS(field) SNMP_INC_STATS(ip_statistics, field) | 160 | #define IP_INC_STATS(field) SNMP_INC_STATS(ip_statistics, field) |
| 161 | #define IP_INC_STATS_BH(field) SNMP_INC_STATS_BH(ip_statistics, field) | 161 | #define IP_INC_STATS_BH(field) SNMP_INC_STATS_BH(ip_statistics, field) |
| 162 | #define IP_INC_STATS_USER(field) SNMP_INC_STATS_USER(ip_statistics, field) | 162 | #define IP_INC_STATS_USER(field) SNMP_INC_STATS_USER(ip_statistics, field) |
| 163 | #define IP_ADD_STATS_BH(field, val) SNMP_ADD_STATS_BH(ip_statistics, field, val) | ||
| 163 | DECLARE_SNMP_STAT(struct linux_mib, net_statistics); | 164 | DECLARE_SNMP_STAT(struct linux_mib, net_statistics); |
| 164 | #define NET_INC_STATS(field) SNMP_INC_STATS(net_statistics, field) | 165 | #define NET_INC_STATS(field) SNMP_INC_STATS(net_statistics, field) |
| 165 | #define NET_INC_STATS_BH(field) SNMP_INC_STATS_BH(net_statistics, field) | 166 | #define NET_INC_STATS_BH(field) SNMP_INC_STATS_BH(net_statistics, field) |
| @@ -177,10 +178,8 @@ extern int sysctl_ip_default_ttl; | |||
| 177 | extern int sysctl_ip_nonlocal_bind; | 178 | extern int sysctl_ip_nonlocal_bind; |
| 178 | 179 | ||
| 179 | /* From ip_fragment.c */ | 180 | /* From ip_fragment.c */ |
| 180 | extern int sysctl_ipfrag_high_thresh; | 181 | struct inet_frags_ctl; |
| 181 | extern int sysctl_ipfrag_low_thresh; | 182 | extern struct inet_frags_ctl ip4_frags_ctl; |
| 182 | extern int sysctl_ipfrag_time; | ||
| 183 | extern int sysctl_ipfrag_secret_interval; | ||
| 184 | extern int sysctl_ipfrag_max_dist; | 183 | extern int sysctl_ipfrag_max_dist; |
| 185 | 184 | ||
| 186 | /* From inetpeer.c */ | 185 | /* From inetpeer.c */ |
| @@ -332,9 +331,9 @@ enum ip_defrag_users | |||
| 332 | IP_DEFRAG_VS_FWD | 331 | IP_DEFRAG_VS_FWD |
| 333 | }; | 332 | }; |
| 334 | 333 | ||
| 335 | struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user); | 334 | int ip_defrag(struct sk_buff *skb, u32 user); |
| 336 | extern int ip_frag_nqueues; | 335 | int ip_frag_mem(void); |
| 337 | extern atomic_t ip_frag_mem; | 336 | int ip_frag_nqueues(void); |
| 338 | 337 | ||
| 339 | /* | 338 | /* |
| 340 | * Functions provided by ip_forward.c | 339 | * Functions provided by ip_forward.c |
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 672564e5a81d..41870564df8e 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h | |||
| @@ -464,10 +464,10 @@ struct ip_vs_protocol { | |||
| 464 | unsigned int proto_off, | 464 | unsigned int proto_off, |
| 465 | int inverse); | 465 | int inverse); |
| 466 | 466 | ||
| 467 | int (*snat_handler)(struct sk_buff **pskb, | 467 | int (*snat_handler)(struct sk_buff *skb, |
| 468 | struct ip_vs_protocol *pp, struct ip_vs_conn *cp); | 468 | struct ip_vs_protocol *pp, struct ip_vs_conn *cp); |
| 469 | 469 | ||
| 470 | int (*dnat_handler)(struct sk_buff **pskb, | 470 | int (*dnat_handler)(struct sk_buff *skb, |
| 471 | struct ip_vs_protocol *pp, struct ip_vs_conn *cp); | 471 | struct ip_vs_protocol *pp, struct ip_vs_conn *cp); |
| 472 | 472 | ||
| 473 | int (*csum_check)(struct sk_buff *skb, struct ip_vs_protocol *pp); | 473 | int (*csum_check)(struct sk_buff *skb, struct ip_vs_protocol *pp); |
| @@ -654,11 +654,11 @@ struct ip_vs_app | |||
| 654 | 654 | ||
| 655 | /* output hook: return false if can't linearize. diff set for TCP. */ | 655 | /* output hook: return false if can't linearize. diff set for TCP. */ |
| 656 | int (*pkt_out)(struct ip_vs_app *, struct ip_vs_conn *, | 656 | int (*pkt_out)(struct ip_vs_app *, struct ip_vs_conn *, |
| 657 | struct sk_buff **, int *diff); | 657 | struct sk_buff *, int *diff); |
| 658 | 658 | ||
| 659 | /* input hook: return false if can't linearize. diff set for TCP. */ | 659 | /* input hook: return false if can't linearize. diff set for TCP. */ |
| 660 | int (*pkt_in)(struct ip_vs_app *, struct ip_vs_conn *, | 660 | int (*pkt_in)(struct ip_vs_app *, struct ip_vs_conn *, |
| 661 | struct sk_buff **, int *diff); | 661 | struct sk_buff *, int *diff); |
| 662 | 662 | ||
| 663 | /* ip_vs_app initializer */ | 663 | /* ip_vs_app initializer */ |
| 664 | int (*init_conn)(struct ip_vs_app *, struct ip_vs_conn *); | 664 | int (*init_conn)(struct ip_vs_app *, struct ip_vs_conn *); |
| @@ -832,8 +832,8 @@ register_ip_vs_app_inc(struct ip_vs_app *app, __u16 proto, __u16 port); | |||
| 832 | extern int ip_vs_app_inc_get(struct ip_vs_app *inc); | 832 | extern int ip_vs_app_inc_get(struct ip_vs_app *inc); |
| 833 | extern void ip_vs_app_inc_put(struct ip_vs_app *inc); | 833 | extern void ip_vs_app_inc_put(struct ip_vs_app *inc); |
| 834 | 834 | ||
| 835 | extern int ip_vs_app_pkt_out(struct ip_vs_conn *, struct sk_buff **pskb); | 835 | extern int ip_vs_app_pkt_out(struct ip_vs_conn *, struct sk_buff *skb); |
| 836 | extern int ip_vs_app_pkt_in(struct ip_vs_conn *, struct sk_buff **pskb); | 836 | extern int ip_vs_app_pkt_in(struct ip_vs_conn *, struct sk_buff *skb); |
| 837 | extern int ip_vs_skb_replace(struct sk_buff *skb, gfp_t pri, | 837 | extern int ip_vs_skb_replace(struct sk_buff *skb, gfp_t pri, |
| 838 | char *o_buf, int o_len, char *n_buf, int n_len); | 838 | char *o_buf, int o_len, char *n_buf, int n_len); |
| 839 | extern int ip_vs_app_init(void); | 839 | extern int ip_vs_app_init(void); |
| @@ -984,7 +984,6 @@ static inline char ip_vs_fwd_tag(struct ip_vs_conn *cp) | |||
| 984 | return fwd; | 984 | return fwd; |
| 985 | } | 985 | } |
| 986 | 986 | ||
| 987 | extern int ip_vs_make_skb_writable(struct sk_buff **pskb, int len); | ||
| 988 | extern void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp, | 987 | extern void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp, |
| 989 | struct ip_vs_conn *cp, int dir); | 988 | struct ip_vs_conn *cp, int dir); |
| 990 | 989 | ||
diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 31b3f1b45a2b..cc796cbc1b26 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h | |||
| @@ -120,12 +120,21 @@ extern int sysctl_mld_max_msf; | |||
| 120 | SNMP_INC_STATS##modifier(statname##_statistics, (field)); \ | 120 | SNMP_INC_STATS##modifier(statname##_statistics, (field)); \ |
| 121 | }) | 121 | }) |
| 122 | 122 | ||
| 123 | #define _DEVADD(statname, modifier, idev, field, val) \ | ||
| 124 | ({ \ | ||
| 125 | struct inet6_dev *_idev = (idev); \ | ||
| 126 | if (likely(_idev != NULL)) \ | ||
| 127 | SNMP_ADD_STATS##modifier((_idev)->stats.statname, (field), (val)); \ | ||
| 128 | SNMP_ADD_STATS##modifier(statname##_statistics, (field), (val));\ | ||
| 129 | }) | ||
| 130 | |||
| 123 | /* MIBs */ | 131 | /* MIBs */ |
| 124 | DECLARE_SNMP_STAT(struct ipstats_mib, ipv6_statistics); | 132 | DECLARE_SNMP_STAT(struct ipstats_mib, ipv6_statistics); |
| 125 | 133 | ||
| 126 | #define IP6_INC_STATS(idev,field) _DEVINC(ipv6, , idev, field) | 134 | #define IP6_INC_STATS(idev,field) _DEVINC(ipv6, , idev, field) |
| 127 | #define IP6_INC_STATS_BH(idev,field) _DEVINC(ipv6, _BH, idev, field) | 135 | #define IP6_INC_STATS_BH(idev,field) _DEVINC(ipv6, _BH, idev, field) |
| 128 | #define IP6_INC_STATS_USER(idev,field) _DEVINC(ipv6, _USER, idev, field) | 136 | #define IP6_INC_STATS_USER(idev,field) _DEVINC(ipv6, _USER, idev, field) |
| 137 | #define IP6_ADD_STATS_BH(idev,field,val) _DEVADD(ipv6, _BH, idev, field, val) | ||
| 129 | 138 | ||
| 130 | DECLARE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics); | 139 | DECLARE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics); |
| 131 | DECLARE_SNMP_STAT(struct icmpv6msg_mib, icmpv6msg_statistics); | 140 | DECLARE_SNMP_STAT(struct icmpv6msg_mib, icmpv6msg_statistics); |
| @@ -240,7 +249,7 @@ extern int ip6_ra_control(struct sock *sk, int sel, | |||
| 240 | void (*destructor)(struct sock *)); | 249 | void (*destructor)(struct sock *)); |
| 241 | 250 | ||
| 242 | 251 | ||
| 243 | extern int ipv6_parse_hopopts(struct sk_buff **skbp); | 252 | extern int ipv6_parse_hopopts(struct sk_buff *skb); |
| 244 | 253 | ||
| 245 | extern struct ipv6_txoptions * ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt); | 254 | extern struct ipv6_txoptions * ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt); |
| 246 | extern struct ipv6_txoptions * ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt, | 255 | extern struct ipv6_txoptions * ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt, |
| @@ -252,8 +261,8 @@ struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space, | |||
| 252 | 261 | ||
| 253 | extern int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb); | 262 | extern int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb); |
| 254 | 263 | ||
| 255 | extern int ip6_frag_nqueues; | 264 | int ip6_frag_nqueues(void); |
| 256 | extern atomic_t ip6_frag_mem; | 265 | int ip6_frag_mem(void); |
| 257 | 266 | ||
| 258 | #define IPV6_FRAG_TIMEOUT (60*HZ) /* 60 seconds */ | 267 | #define IPV6_FRAG_TIMEOUT (60*HZ) /* 60 seconds */ |
| 259 | 268 | ||
| @@ -565,10 +574,8 @@ extern int inet6_hash_connect(struct inet_timewait_death_row *death_row, | |||
| 565 | /* | 574 | /* |
| 566 | * reassembly.c | 575 | * reassembly.c |
| 567 | */ | 576 | */ |
| 568 | extern int sysctl_ip6frag_high_thresh; | 577 | struct inet_frags_ctl; |
| 569 | extern int sysctl_ip6frag_low_thresh; | 578 | extern struct inet_frags_ctl ip6_frags_ctl; |
| 570 | extern int sysctl_ip6frag_time; | ||
| 571 | extern int sysctl_ip6frag_secret_interval; | ||
| 572 | 579 | ||
| 573 | extern const struct proto_ops inet6_stream_ops; | 580 | extern const struct proto_ops inet6_stream_ops; |
| 574 | extern const struct proto_ops inet6_dgram_ops; | 581 | extern const struct proto_ops inet6_dgram_ops; |
diff --git a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h index 070d12cb4634..f703533fb4db 100644 --- a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h +++ b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h | |||
| @@ -15,8 +15,7 @@ extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb, | |||
| 15 | struct net_device *out, | 15 | struct net_device *out, |
| 16 | int (*okfn)(struct sk_buff *)); | 16 | int (*okfn)(struct sk_buff *)); |
| 17 | 17 | ||
| 18 | extern unsigned int nf_ct_frag6_timeout; | 18 | struct inet_frags_ctl; |
| 19 | extern unsigned int nf_ct_frag6_low_thresh; | 19 | extern struct inet_frags_ctl nf_frags_ctl; |
| 20 | extern unsigned int nf_ct_frag6_high_thresh; | ||
| 21 | 20 | ||
| 22 | #endif /* _NF_CONNTRACK_IPV6_H*/ | 21 | #endif /* _NF_CONNTRACK_IPV6_H*/ |
diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h index 4056f5f08da1..a532e7b5ed6a 100644 --- a/include/net/netfilter/nf_conntrack_core.h +++ b/include/net/netfilter/nf_conntrack_core.h | |||
| @@ -22,7 +22,7 @@ | |||
| 22 | of connection tracking. */ | 22 | of connection tracking. */ |
| 23 | extern unsigned int nf_conntrack_in(int pf, | 23 | extern unsigned int nf_conntrack_in(int pf, |
| 24 | unsigned int hooknum, | 24 | unsigned int hooknum, |
| 25 | struct sk_buff **pskb); | 25 | struct sk_buff *skb); |
| 26 | 26 | ||
| 27 | extern int nf_conntrack_init(void); | 27 | extern int nf_conntrack_init(void); |
| 28 | extern void nf_conntrack_cleanup(void); | 28 | extern void nf_conntrack_cleanup(void); |
| @@ -60,17 +60,17 @@ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse, | |||
| 60 | extern struct nf_conntrack_tuple_hash * | 60 | extern struct nf_conntrack_tuple_hash * |
| 61 | nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple); | 61 | nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple); |
| 62 | 62 | ||
| 63 | extern int __nf_conntrack_confirm(struct sk_buff **pskb); | 63 | extern int __nf_conntrack_confirm(struct sk_buff *skb); |
| 64 | 64 | ||
| 65 | /* Confirm a connection: returns NF_DROP if packet must be dropped. */ | 65 | /* Confirm a connection: returns NF_DROP if packet must be dropped. */ |
| 66 | static inline int nf_conntrack_confirm(struct sk_buff **pskb) | 66 | static inline int nf_conntrack_confirm(struct sk_buff *skb) |
| 67 | { | 67 | { |
| 68 | struct nf_conn *ct = (struct nf_conn *)(*pskb)->nfct; | 68 | struct nf_conn *ct = (struct nf_conn *)skb->nfct; |
| 69 | int ret = NF_ACCEPT; | 69 | int ret = NF_ACCEPT; |
| 70 | 70 | ||
| 71 | if (ct) { | 71 | if (ct) { |
| 72 | if (!nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) | 72 | if (!nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) |
| 73 | ret = __nf_conntrack_confirm(pskb); | 73 | ret = __nf_conntrack_confirm(skb); |
| 74 | nf_ct_deliver_cached_events(ct); | 74 | nf_ct_deliver_cached_events(ct); |
| 75 | } | 75 | } |
| 76 | return ret; | 76 | return ret; |
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h index 0dcc4c828ce9..d7b2d5483a71 100644 --- a/include/net/netfilter/nf_conntrack_helper.h +++ b/include/net/netfilter/nf_conntrack_helper.h | |||
| @@ -29,7 +29,7 @@ struct nf_conntrack_helper | |||
| 29 | 29 | ||
| 30 | /* Function to call when data passes; return verdict, or -1 to | 30 | /* Function to call when data passes; return verdict, or -1 to |
| 31 | invalidate. */ | 31 | invalidate. */ |
| 32 | int (*help)(struct sk_buff **pskb, | 32 | int (*help)(struct sk_buff *skb, |
| 33 | unsigned int protoff, | 33 | unsigned int protoff, |
| 34 | struct nf_conn *ct, | 34 | struct nf_conn *ct, |
| 35 | enum ip_conntrack_info conntrackinfo); | 35 | enum ip_conntrack_info conntrackinfo); |
diff --git a/include/net/netfilter/nf_nat_core.h b/include/net/netfilter/nf_nat_core.h index c3cd127ba4bb..f29eeb9777e0 100644 --- a/include/net/netfilter/nf_nat_core.h +++ b/include/net/netfilter/nf_nat_core.h | |||
| @@ -10,12 +10,12 @@ | |||
| 10 | extern unsigned int nf_nat_packet(struct nf_conn *ct, | 10 | extern unsigned int nf_nat_packet(struct nf_conn *ct, |
| 11 | enum ip_conntrack_info ctinfo, | 11 | enum ip_conntrack_info ctinfo, |
| 12 | unsigned int hooknum, | 12 | unsigned int hooknum, |
| 13 | struct sk_buff **pskb); | 13 | struct sk_buff *skb); |
| 14 | 14 | ||
| 15 | extern int nf_nat_icmp_reply_translation(struct nf_conn *ct, | 15 | extern int nf_nat_icmp_reply_translation(struct nf_conn *ct, |
| 16 | enum ip_conntrack_info ctinfo, | 16 | enum ip_conntrack_info ctinfo, |
| 17 | unsigned int hooknum, | 17 | unsigned int hooknum, |
| 18 | struct sk_buff **pskb); | 18 | struct sk_buff *skb); |
| 19 | 19 | ||
| 20 | static inline int nf_nat_initialized(struct nf_conn *ct, | 20 | static inline int nf_nat_initialized(struct nf_conn *ct, |
| 21 | enum nf_nat_manip_type manip) | 21 | enum nf_nat_manip_type manip) |
diff --git a/include/net/netfilter/nf_nat_helper.h b/include/net/netfilter/nf_nat_helper.h index ec98ecf95fc8..58dd22687949 100644 --- a/include/net/netfilter/nf_nat_helper.h +++ b/include/net/netfilter/nf_nat_helper.h | |||
| @@ -7,21 +7,21 @@ | |||
| 7 | struct sk_buff; | 7 | struct sk_buff; |
| 8 | 8 | ||
| 9 | /* These return true or false. */ | 9 | /* These return true or false. */ |
| 10 | extern int nf_nat_mangle_tcp_packet(struct sk_buff **skb, | 10 | extern int nf_nat_mangle_tcp_packet(struct sk_buff *skb, |
| 11 | struct nf_conn *ct, | 11 | struct nf_conn *ct, |
| 12 | enum ip_conntrack_info ctinfo, | 12 | enum ip_conntrack_info ctinfo, |
| 13 | unsigned int match_offset, | 13 | unsigned int match_offset, |
| 14 | unsigned int match_len, | 14 | unsigned int match_len, |
| 15 | const char *rep_buffer, | 15 | const char *rep_buffer, |
| 16 | unsigned int rep_len); | 16 | unsigned int rep_len); |
| 17 | extern int nf_nat_mangle_udp_packet(struct sk_buff **skb, | 17 | extern int nf_nat_mangle_udp_packet(struct sk_buff *skb, |
| 18 | struct nf_conn *ct, | 18 | struct nf_conn *ct, |
| 19 | enum ip_conntrack_info ctinfo, | 19 | enum ip_conntrack_info ctinfo, |
| 20 | unsigned int match_offset, | 20 | unsigned int match_offset, |
| 21 | unsigned int match_len, | 21 | unsigned int match_len, |
| 22 | const char *rep_buffer, | 22 | const char *rep_buffer, |
| 23 | unsigned int rep_len); | 23 | unsigned int rep_len); |
| 24 | extern int nf_nat_seq_adjust(struct sk_buff **pskb, | 24 | extern int nf_nat_seq_adjust(struct sk_buff *skb, |
| 25 | struct nf_conn *ct, | 25 | struct nf_conn *ct, |
| 26 | enum ip_conntrack_info ctinfo); | 26 | enum ip_conntrack_info ctinfo); |
| 27 | 27 | ||
diff --git a/include/net/netfilter/nf_nat_protocol.h b/include/net/netfilter/nf_nat_protocol.h index 14c7b2d7263c..04578bfe23e1 100644 --- a/include/net/netfilter/nf_nat_protocol.h +++ b/include/net/netfilter/nf_nat_protocol.h | |||
| @@ -18,7 +18,7 @@ struct nf_nat_protocol | |||
| 18 | 18 | ||
| 19 | /* Translate a packet to the target according to manip type. | 19 | /* Translate a packet to the target according to manip type. |
| 20 | Return true if succeeded. */ | 20 | Return true if succeeded. */ |
| 21 | int (*manip_pkt)(struct sk_buff **pskb, | 21 | int (*manip_pkt)(struct sk_buff *skb, |
| 22 | unsigned int iphdroff, | 22 | unsigned int iphdroff, |
| 23 | const struct nf_conntrack_tuple *tuple, | 23 | const struct nf_conntrack_tuple *tuple, |
| 24 | enum nf_nat_manip_type maniptype); | 24 | enum nf_nat_manip_type maniptype); |
diff --git a/include/net/netfilter/nf_nat_rule.h b/include/net/netfilter/nf_nat_rule.h index f9743187d57f..75d1825031d7 100644 --- a/include/net/netfilter/nf_nat_rule.h +++ b/include/net/netfilter/nf_nat_rule.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | extern int nf_nat_rule_init(void) __init; | 7 | extern int nf_nat_rule_init(void) __init; |
| 8 | extern void nf_nat_rule_cleanup(void); | 8 | extern void nf_nat_rule_cleanup(void); |
| 9 | extern int nf_nat_rule_find(struct sk_buff **pskb, | 9 | extern int nf_nat_rule_find(struct sk_buff *skb, |
| 10 | unsigned int hooknum, | 10 | unsigned int hooknum, |
| 11 | const struct net_device *in, | 11 | const struct net_device *in, |
| 12 | const struct net_device *out, | 12 | const struct net_device *out, |
diff --git a/include/net/protocol.h b/include/net/protocol.h index 105bf12b0c79..1166ffb4b3ec 100644 --- a/include/net/protocol.h +++ b/include/net/protocol.h | |||
| @@ -45,7 +45,7 @@ struct net_protocol { | |||
| 45 | #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) | 45 | #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) |
| 46 | struct inet6_protocol | 46 | struct inet6_protocol |
| 47 | { | 47 | { |
| 48 | int (*handler)(struct sk_buff **skb); | 48 | int (*handler)(struct sk_buff *skb); |
| 49 | 49 | ||
| 50 | void (*err_handler)(struct sk_buff *skb, | 50 | void (*err_handler)(struct sk_buff *skb, |
| 51 | struct inet6_skb_parm *opt, | 51 | struct inet6_skb_parm *opt, |
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 77be396ca633..0e844845f3f4 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
| @@ -1051,7 +1051,7 @@ extern int xfrm4_output(struct sk_buff *skb); | |||
| 1051 | extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family); | 1051 | extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family); |
| 1052 | extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family); | 1052 | extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family); |
| 1053 | extern int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi); | 1053 | extern int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi); |
| 1054 | extern int xfrm6_rcv(struct sk_buff **pskb); | 1054 | extern int xfrm6_rcv(struct sk_buff *skb); |
| 1055 | extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, | 1055 | extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, |
| 1056 | xfrm_address_t *saddr, u8 proto); | 1056 | xfrm_address_t *saddr, u8 proto); |
| 1057 | extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family); | 1057 | extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family); |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 04f3ffb8d9d4..0ae703c157ba 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
| @@ -1525,6 +1525,7 @@ add_names: | |||
| 1525 | context->names[idx].ino = (unsigned long)-1; | 1525 | context->names[idx].ino = (unsigned long)-1; |
| 1526 | } | 1526 | } |
| 1527 | } | 1527 | } |
| 1528 | EXPORT_SYMBOL_GPL(__audit_inode_child); | ||
| 1528 | 1529 | ||
| 1529 | /** | 1530 | /** |
| 1530 | * auditsc_get_stamp - get local copies of audit_context values | 1531 | * auditsc_get_stamp - get local copies of audit_context values |
diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 734da579ad13..a6f1ee9c92d9 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c | |||
| @@ -1521,7 +1521,7 @@ cache_hit: | |||
| 1521 | } | 1521 | } |
| 1522 | 1522 | ||
| 1523 | static int validate_chain(struct task_struct *curr, struct lockdep_map *lock, | 1523 | static int validate_chain(struct task_struct *curr, struct lockdep_map *lock, |
| 1524 | struct held_lock *hlock, int chain_head) | 1524 | struct held_lock *hlock, int chain_head, u64 chain_key) |
| 1525 | { | 1525 | { |
| 1526 | /* | 1526 | /* |
| 1527 | * Trylock needs to maintain the stack of held locks, but it | 1527 | * Trylock needs to maintain the stack of held locks, but it |
| @@ -1534,7 +1534,7 @@ static int validate_chain(struct task_struct *curr, struct lockdep_map *lock, | |||
| 1534 | * graph_lock for us) | 1534 | * graph_lock for us) |
| 1535 | */ | 1535 | */ |
| 1536 | if (!hlock->trylock && (hlock->check == 2) && | 1536 | if (!hlock->trylock && (hlock->check == 2) && |
| 1537 | lookup_chain_cache(curr->curr_chain_key, hlock->class)) { | 1537 | lookup_chain_cache(chain_key, hlock->class)) { |
| 1538 | /* | 1538 | /* |
| 1539 | * Check whether last held lock: | 1539 | * Check whether last held lock: |
| 1540 | * | 1540 | * |
| @@ -1576,7 +1576,7 @@ static int validate_chain(struct task_struct *curr, struct lockdep_map *lock, | |||
| 1576 | #else | 1576 | #else |
| 1577 | static inline int validate_chain(struct task_struct *curr, | 1577 | static inline int validate_chain(struct task_struct *curr, |
| 1578 | struct lockdep_map *lock, struct held_lock *hlock, | 1578 | struct lockdep_map *lock, struct held_lock *hlock, |
| 1579 | int chain_head) | 1579 | int chain_head, u64 chain_key) |
| 1580 | { | 1580 | { |
| 1581 | return 1; | 1581 | return 1; |
| 1582 | } | 1582 | } |
| @@ -2450,11 +2450,11 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass, | |||
| 2450 | chain_head = 1; | 2450 | chain_head = 1; |
| 2451 | } | 2451 | } |
| 2452 | chain_key = iterate_chain_key(chain_key, id); | 2452 | chain_key = iterate_chain_key(chain_key, id); |
| 2453 | curr->curr_chain_key = chain_key; | ||
| 2454 | 2453 | ||
| 2455 | if (!validate_chain(curr, lock, hlock, chain_head)) | 2454 | if (!validate_chain(curr, lock, hlock, chain_head, chain_key)) |
| 2456 | return 0; | 2455 | return 0; |
| 2457 | 2456 | ||
| 2457 | curr->curr_chain_key = chain_key; | ||
| 2458 | curr->lockdep_depth++; | 2458 | curr->lockdep_depth++; |
| 2459 | check_chain_key(curr); | 2459 | check_chain_key(curr); |
| 2460 | #ifdef CONFIG_DEBUG_LOCKDEP | 2460 | #ifdef CONFIG_DEBUG_LOCKDEP |
| @@ -3199,3 +3199,19 @@ void debug_show_held_locks(struct task_struct *task) | |||
| 3199 | } | 3199 | } |
| 3200 | 3200 | ||
| 3201 | EXPORT_SYMBOL_GPL(debug_show_held_locks); | 3201 | EXPORT_SYMBOL_GPL(debug_show_held_locks); |
| 3202 | |||
| 3203 | void lockdep_sys_exit(void) | ||
| 3204 | { | ||
| 3205 | struct task_struct *curr = current; | ||
| 3206 | |||
| 3207 | if (unlikely(curr->lockdep_depth)) { | ||
| 3208 | if (!debug_locks_off()) | ||
| 3209 | return; | ||
| 3210 | printk("\n================================================\n"); | ||
| 3211 | printk( "[ BUG: lock held when returning to user space! ]\n"); | ||
| 3212 | printk( "------------------------------------------------\n"); | ||
| 3213 | printk("%s/%d is leaving the kernel with locks still held!\n", | ||
| 3214 | curr->comm, curr->pid); | ||
| 3215 | lockdep_print_held_locks(curr); | ||
| 3216 | } | ||
| 3217 | } | ||
diff --git a/kernel/lockdep_proc.c b/kernel/lockdep_proc.c index c851b2dcc685..8a135bd163c2 100644 --- a/kernel/lockdep_proc.c +++ b/kernel/lockdep_proc.c | |||
| @@ -25,28 +25,38 @@ | |||
| 25 | 25 | ||
| 26 | static void *l_next(struct seq_file *m, void *v, loff_t *pos) | 26 | static void *l_next(struct seq_file *m, void *v, loff_t *pos) |
| 27 | { | 27 | { |
| 28 | struct lock_class *class = v; | 28 | struct lock_class *class; |
| 29 | 29 | ||
| 30 | (*pos)++; | 30 | (*pos)++; |
| 31 | 31 | ||
| 32 | if (class->lock_entry.next != &all_lock_classes) | 32 | if (v == SEQ_START_TOKEN) |
| 33 | class = list_entry(class->lock_entry.next, struct lock_class, | 33 | class = m->private; |
| 34 | lock_entry); | 34 | else { |
| 35 | else | 35 | class = v; |
| 36 | class = NULL; | 36 | |
| 37 | m->private = class; | 37 | if (class->lock_entry.next != &all_lock_classes) |
| 38 | class = list_entry(class->lock_entry.next, | ||
| 39 | struct lock_class, lock_entry); | ||
| 40 | else | ||
| 41 | class = NULL; | ||
| 42 | } | ||
| 38 | 43 | ||
| 39 | return class; | 44 | return class; |
| 40 | } | 45 | } |
| 41 | 46 | ||
| 42 | static void *l_start(struct seq_file *m, loff_t *pos) | 47 | static void *l_start(struct seq_file *m, loff_t *pos) |
| 43 | { | 48 | { |
| 44 | struct lock_class *class = m->private; | 49 | struct lock_class *class; |
| 50 | loff_t i = 0; | ||
| 45 | 51 | ||
| 46 | if (&class->lock_entry == all_lock_classes.next) | 52 | if (*pos == 0) |
| 47 | seq_printf(m, "all lock classes:\n"); | 53 | return SEQ_START_TOKEN; |
| 48 | 54 | ||
| 49 | return class; | 55 | list_for_each_entry(class, &all_lock_classes, lock_entry) { |
| 56 | if (++i == *pos) | ||
| 57 | return class; | ||
| 58 | } | ||
| 59 | return NULL; | ||
| 50 | } | 60 | } |
| 51 | 61 | ||
| 52 | static void l_stop(struct seq_file *m, void *v) | 62 | static void l_stop(struct seq_file *m, void *v) |
| @@ -101,10 +111,15 @@ static void print_name(struct seq_file *m, struct lock_class *class) | |||
| 101 | static int l_show(struct seq_file *m, void *v) | 111 | static int l_show(struct seq_file *m, void *v) |
| 102 | { | 112 | { |
| 103 | unsigned long nr_forward_deps, nr_backward_deps; | 113 | unsigned long nr_forward_deps, nr_backward_deps; |
| 104 | struct lock_class *class = m->private; | 114 | struct lock_class *class = v; |
| 105 | struct lock_list *entry; | 115 | struct lock_list *entry; |
| 106 | char c1, c2, c3, c4; | 116 | char c1, c2, c3, c4; |
| 107 | 117 | ||
| 118 | if (v == SEQ_START_TOKEN) { | ||
| 119 | seq_printf(m, "all lock classes:\n"); | ||
| 120 | return 0; | ||
| 121 | } | ||
| 122 | |||
| 108 | seq_printf(m, "%p", class->key); | 123 | seq_printf(m, "%p", class->key); |
| 109 | #ifdef CONFIG_DEBUG_LOCKDEP | 124 | #ifdef CONFIG_DEBUG_LOCKDEP |
| 110 | seq_printf(m, " OPS:%8ld", class->ops); | 125 | seq_printf(m, " OPS:%8ld", class->ops); |
| @@ -523,10 +538,11 @@ static void *ls_start(struct seq_file *m, loff_t *pos) | |||
| 523 | { | 538 | { |
| 524 | struct lock_stat_seq *data = m->private; | 539 | struct lock_stat_seq *data = m->private; |
| 525 | 540 | ||
| 526 | if (data->iter == data->stats) | 541 | if (*pos == 0) |
| 527 | seq_header(m); | 542 | return SEQ_START_TOKEN; |
| 528 | 543 | ||
| 529 | if (data->iter == data->iter_end) | 544 | data->iter = data->stats + *pos; |
| 545 | if (data->iter >= data->iter_end) | ||
| 530 | data->iter = NULL; | 546 | data->iter = NULL; |
| 531 | 547 | ||
| 532 | return data->iter; | 548 | return data->iter; |
| @@ -538,8 +554,13 @@ static void *ls_next(struct seq_file *m, void *v, loff_t *pos) | |||
| 538 | 554 | ||
| 539 | (*pos)++; | 555 | (*pos)++; |
| 540 | 556 | ||
| 541 | data->iter = v; | 557 | if (v == SEQ_START_TOKEN) |
| 542 | data->iter++; | 558 | data->iter = data->stats; |
| 559 | else { | ||
| 560 | data->iter = v; | ||
| 561 | data->iter++; | ||
| 562 | } | ||
| 563 | |||
| 543 | if (data->iter == data->iter_end) | 564 | if (data->iter == data->iter_end) |
| 544 | data->iter = NULL; | 565 | data->iter = NULL; |
| 545 | 566 | ||
| @@ -552,9 +573,11 @@ static void ls_stop(struct seq_file *m, void *v) | |||
| 552 | 573 | ||
| 553 | static int ls_show(struct seq_file *m, void *v) | 574 | static int ls_show(struct seq_file *m, void *v) |
| 554 | { | 575 | { |
| 555 | struct lock_stat_seq *data = m->private; | 576 | if (v == SEQ_START_TOKEN) |
| 577 | seq_header(m); | ||
| 578 | else | ||
| 579 | seq_stats(m, v); | ||
| 556 | 580 | ||
| 557 | seq_stats(m, data->iter); | ||
| 558 | return 0; | 581 | return 0; |
| 559 | } | 582 | } |
| 560 | 583 | ||
diff --git a/kernel/mutex.c b/kernel/mutex.c index 691b86564dd9..d7fe50cc556f 100644 --- a/kernel/mutex.c +++ b/kernel/mutex.c | |||
| @@ -51,6 +51,7 @@ __mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key) | |||
| 51 | 51 | ||
| 52 | EXPORT_SYMBOL(__mutex_init); | 52 | EXPORT_SYMBOL(__mutex_init); |
| 53 | 53 | ||
| 54 | #ifndef CONFIG_DEBUG_LOCK_ALLOC | ||
| 54 | /* | 55 | /* |
| 55 | * We split the mutex lock/unlock logic into separate fastpath and | 56 | * We split the mutex lock/unlock logic into separate fastpath and |
| 56 | * slowpath functions, to reduce the register pressure on the fastpath. | 57 | * slowpath functions, to reduce the register pressure on the fastpath. |
| @@ -92,6 +93,7 @@ void inline fastcall __sched mutex_lock(struct mutex *lock) | |||
| 92 | } | 93 | } |
| 93 | 94 | ||
| 94 | EXPORT_SYMBOL(mutex_lock); | 95 | EXPORT_SYMBOL(mutex_lock); |
| 96 | #endif | ||
| 95 | 97 | ||
| 96 | static void fastcall noinline __sched | 98 | static void fastcall noinline __sched |
| 97 | __mutex_unlock_slowpath(atomic_t *lock_count); | 99 | __mutex_unlock_slowpath(atomic_t *lock_count); |
| @@ -122,7 +124,8 @@ EXPORT_SYMBOL(mutex_unlock); | |||
| 122 | * Lock a mutex (possibly interruptible), slowpath: | 124 | * Lock a mutex (possibly interruptible), slowpath: |
| 123 | */ | 125 | */ |
| 124 | static inline int __sched | 126 | static inline int __sched |
| 125 | __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass) | 127 | __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, |
| 128 | unsigned long ip) | ||
| 126 | { | 129 | { |
| 127 | struct task_struct *task = current; | 130 | struct task_struct *task = current; |
| 128 | struct mutex_waiter waiter; | 131 | struct mutex_waiter waiter; |
| @@ -132,7 +135,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass) | |||
| 132 | spin_lock_mutex(&lock->wait_lock, flags); | 135 | spin_lock_mutex(&lock->wait_lock, flags); |
| 133 | 136 | ||
| 134 | debug_mutex_lock_common(lock, &waiter); | 137 | debug_mutex_lock_common(lock, &waiter); |
| 135 | mutex_acquire(&lock->dep_map, subclass, 0, _RET_IP_); | 138 | mutex_acquire(&lock->dep_map, subclass, 0, ip); |
| 136 | debug_mutex_add_waiter(lock, &waiter, task_thread_info(task)); | 139 | debug_mutex_add_waiter(lock, &waiter, task_thread_info(task)); |
| 137 | 140 | ||
| 138 | /* add waiting tasks to the end of the waitqueue (FIFO): */ | 141 | /* add waiting tasks to the end of the waitqueue (FIFO): */ |
| @@ -143,7 +146,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass) | |||
| 143 | if (old_val == 1) | 146 | if (old_val == 1) |
| 144 | goto done; | 147 | goto done; |
| 145 | 148 | ||
| 146 | lock_contended(&lock->dep_map, _RET_IP_); | 149 | lock_contended(&lock->dep_map, ip); |
| 147 | 150 | ||
| 148 | for (;;) { | 151 | for (;;) { |
| 149 | /* | 152 | /* |
| @@ -166,7 +169,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass) | |||
| 166 | if (unlikely(state == TASK_INTERRUPTIBLE && | 169 | if (unlikely(state == TASK_INTERRUPTIBLE && |
| 167 | signal_pending(task))) { | 170 | signal_pending(task))) { |
| 168 | mutex_remove_waiter(lock, &waiter, task_thread_info(task)); | 171 | mutex_remove_waiter(lock, &waiter, task_thread_info(task)); |
| 169 | mutex_release(&lock->dep_map, 1, _RET_IP_); | 172 | mutex_release(&lock->dep_map, 1, ip); |
| 170 | spin_unlock_mutex(&lock->wait_lock, flags); | 173 | spin_unlock_mutex(&lock->wait_lock, flags); |
| 171 | 174 | ||
| 172 | debug_mutex_free_waiter(&waiter); | 175 | debug_mutex_free_waiter(&waiter); |
| @@ -197,20 +200,12 @@ done: | |||
| 197 | return 0; | 200 | return 0; |
| 198 | } | 201 | } |
| 199 | 202 | ||
| 200 | static void fastcall noinline __sched | ||
| 201 | __mutex_lock_slowpath(atomic_t *lock_count) | ||
| 202 | { | ||
| 203 | struct mutex *lock = container_of(lock_count, struct mutex, count); | ||
| 204 | |||
| 205 | __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, 0); | ||
| 206 | } | ||
| 207 | |||
| 208 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 203 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
| 209 | void __sched | 204 | void __sched |
| 210 | mutex_lock_nested(struct mutex *lock, unsigned int subclass) | 205 | mutex_lock_nested(struct mutex *lock, unsigned int subclass) |
| 211 | { | 206 | { |
| 212 | might_sleep(); | 207 | might_sleep(); |
| 213 | __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, subclass); | 208 | __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, subclass, _RET_IP_); |
| 214 | } | 209 | } |
| 215 | 210 | ||
| 216 | EXPORT_SYMBOL_GPL(mutex_lock_nested); | 211 | EXPORT_SYMBOL_GPL(mutex_lock_nested); |
| @@ -219,7 +214,7 @@ int __sched | |||
| 219 | mutex_lock_interruptible_nested(struct mutex *lock, unsigned int subclass) | 214 | mutex_lock_interruptible_nested(struct mutex *lock, unsigned int subclass) |
| 220 | { | 215 | { |
| 221 | might_sleep(); | 216 | might_sleep(); |
| 222 | return __mutex_lock_common(lock, TASK_INTERRUPTIBLE, subclass); | 217 | return __mutex_lock_common(lock, TASK_INTERRUPTIBLE, subclass, _RET_IP_); |
| 223 | } | 218 | } |
| 224 | 219 | ||
| 225 | EXPORT_SYMBOL_GPL(mutex_lock_interruptible_nested); | 220 | EXPORT_SYMBOL_GPL(mutex_lock_interruptible_nested); |
| @@ -271,6 +266,7 @@ __mutex_unlock_slowpath(atomic_t *lock_count) | |||
| 271 | __mutex_unlock_common_slowpath(lock_count, 1); | 266 | __mutex_unlock_common_slowpath(lock_count, 1); |
| 272 | } | 267 | } |
| 273 | 268 | ||
| 269 | #ifndef CONFIG_DEBUG_LOCK_ALLOC | ||
| 274 | /* | 270 | /* |
| 275 | * Here come the less common (and hence less performance-critical) APIs: | 271 | * Here come the less common (and hence less performance-critical) APIs: |
| 276 | * mutex_lock_interruptible() and mutex_trylock(). | 272 | * mutex_lock_interruptible() and mutex_trylock(). |
| @@ -298,13 +294,22 @@ int fastcall __sched mutex_lock_interruptible(struct mutex *lock) | |||
| 298 | 294 | ||
| 299 | EXPORT_SYMBOL(mutex_lock_interruptible); | 295 | EXPORT_SYMBOL(mutex_lock_interruptible); |
| 300 | 296 | ||
| 297 | static void fastcall noinline __sched | ||
| 298 | __mutex_lock_slowpath(atomic_t *lock_count) | ||
| 299 | { | ||
| 300 | struct mutex *lock = container_of(lock_count, struct mutex, count); | ||
| 301 | |||
| 302 | __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, 0, _RET_IP_); | ||
| 303 | } | ||
| 304 | |||
| 301 | static int fastcall noinline __sched | 305 | static int fastcall noinline __sched |
| 302 | __mutex_lock_interruptible_slowpath(atomic_t *lock_count) | 306 | __mutex_lock_interruptible_slowpath(atomic_t *lock_count) |
| 303 | { | 307 | { |
| 304 | struct mutex *lock = container_of(lock_count, struct mutex, count); | 308 | struct mutex *lock = container_of(lock_count, struct mutex, count); |
| 305 | 309 | ||
| 306 | return __mutex_lock_common(lock, TASK_INTERRUPTIBLE, 0); | 310 | return __mutex_lock_common(lock, TASK_INTERRUPTIBLE, 0, _RET_IP_); |
| 307 | } | 311 | } |
| 312 | #endif | ||
| 308 | 313 | ||
| 309 | /* | 314 | /* |
| 310 | * Spinlock based trylock, we take the spinlock and check whether we | 315 | * Spinlock based trylock, we take the spinlock and check whether we |
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index 2c2dd8410dc4..130214f3d229 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c | |||
| @@ -49,6 +49,14 @@ | |||
| 49 | #include <linux/cpu.h> | 49 | #include <linux/cpu.h> |
| 50 | #include <linux/mutex.h> | 50 | #include <linux/mutex.h> |
| 51 | 51 | ||
| 52 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
| 53 | static struct lock_class_key rcu_lock_key; | ||
| 54 | struct lockdep_map rcu_lock_map = | ||
| 55 | STATIC_LOCKDEP_MAP_INIT("rcu_read_lock", &rcu_lock_key); | ||
| 56 | |||
| 57 | EXPORT_SYMBOL_GPL(rcu_lock_map); | ||
| 58 | #endif | ||
| 59 | |||
| 52 | /* Definition for rcupdate control block. */ | 60 | /* Definition for rcupdate control block. */ |
| 53 | static struct rcu_ctrlblk rcu_ctrlblk = { | 61 | static struct rcu_ctrlblk rcu_ctrlblk = { |
| 54 | .cur = -300, | 62 | .cur = -300, |
diff --git a/net/bridge/br.c b/net/bridge/br.c index 848b8fa8bedd..93867bb6cc97 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c | |||
| @@ -23,7 +23,7 @@ | |||
| 23 | 23 | ||
| 24 | #include "br_private.h" | 24 | #include "br_private.h" |
| 25 | 25 | ||
| 26 | int (*br_should_route_hook) (struct sk_buff **pskb) = NULL; | 26 | int (*br_should_route_hook)(struct sk_buff *skb); |
| 27 | 27 | ||
| 28 | static struct llc_sap *br_stp_sap; | 28 | static struct llc_sap *br_stp_sap; |
| 29 | 29 | ||
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 3a8a015c92e0..3cedd4eeeed6 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c | |||
| @@ -126,6 +126,10 @@ struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb) | |||
| 126 | if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) | 126 | if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) |
| 127 | goto drop; | 127 | goto drop; |
| 128 | 128 | ||
| 129 | skb = skb_share_check(skb, GFP_ATOMIC); | ||
| 130 | if (!skb) | ||
| 131 | return NULL; | ||
| 132 | |||
| 129 | if (unlikely(is_link_local(dest))) { | 133 | if (unlikely(is_link_local(dest))) { |
| 130 | /* Pause frames shouldn't be passed up by driver anyway */ | 134 | /* Pause frames shouldn't be passed up by driver anyway */ |
| 131 | if (skb->protocol == htons(ETH_P_PAUSE)) | 135 | if (skb->protocol == htons(ETH_P_PAUSE)) |
| @@ -145,7 +149,7 @@ struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb) | |||
| 145 | case BR_STATE_FORWARDING: | 149 | case BR_STATE_FORWARDING: |
| 146 | 150 | ||
| 147 | if (br_should_route_hook) { | 151 | if (br_should_route_hook) { |
| 148 | if (br_should_route_hook(&skb)) | 152 | if (br_should_route_hook(skb)) |
| 149 | return skb; | 153 | return skb; |
| 150 | dest = eth_hdr(skb)->h_dest; | 154 | dest = eth_hdr(skb)->h_dest; |
| 151 | } | 155 | } |
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 8245f051ccbb..da22f900e89d 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
| @@ -503,18 +503,14 @@ inhdr_error: | |||
| 503 | * receiving device) to make netfilter happy, the REDIRECT | 503 | * receiving device) to make netfilter happy, the REDIRECT |
| 504 | * target in particular. Save the original destination IP | 504 | * target in particular. Save the original destination IP |
| 505 | * address to be able to detect DNAT afterwards. */ | 505 | * address to be able to detect DNAT afterwards. */ |
| 506 | static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, | 506 | static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff *skb, |
| 507 | const struct net_device *in, | 507 | const struct net_device *in, |
| 508 | const struct net_device *out, | 508 | const struct net_device *out, |
| 509 | int (*okfn)(struct sk_buff *)) | 509 | int (*okfn)(struct sk_buff *)) |
| 510 | { | 510 | { |
| 511 | struct iphdr *iph; | 511 | struct iphdr *iph; |
| 512 | struct sk_buff *skb = *pskb; | ||
| 513 | __u32 len = nf_bridge_encap_header_len(skb); | 512 | __u32 len = nf_bridge_encap_header_len(skb); |
| 514 | 513 | ||
| 515 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) | ||
| 516 | return NF_STOLEN; | ||
| 517 | |||
| 518 | if (unlikely(!pskb_may_pull(skb, len))) | 514 | if (unlikely(!pskb_may_pull(skb, len))) |
| 519 | goto out; | 515 | goto out; |
| 520 | 516 | ||
| @@ -584,13 +580,11 @@ out: | |||
| 584 | * took place when the packet entered the bridge), but we | 580 | * took place when the packet entered the bridge), but we |
| 585 | * register an IPv4 PRE_ROUTING 'sabotage' hook that will | 581 | * register an IPv4 PRE_ROUTING 'sabotage' hook that will |
| 586 | * prevent this from happening. */ | 582 | * prevent this from happening. */ |
| 587 | static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff **pskb, | 583 | static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff *skb, |
| 588 | const struct net_device *in, | 584 | const struct net_device *in, |
| 589 | const struct net_device *out, | 585 | const struct net_device *out, |
| 590 | int (*okfn)(struct sk_buff *)) | 586 | int (*okfn)(struct sk_buff *)) |
| 591 | { | 587 | { |
| 592 | struct sk_buff *skb = *pskb; | ||
| 593 | |||
| 594 | if (skb->dst == (struct dst_entry *)&__fake_rtable) { | 588 | if (skb->dst == (struct dst_entry *)&__fake_rtable) { |
| 595 | dst_release(skb->dst); | 589 | dst_release(skb->dst); |
| 596 | skb->dst = NULL; | 590 | skb->dst = NULL; |
| @@ -625,12 +619,11 @@ static int br_nf_forward_finish(struct sk_buff *skb) | |||
| 625 | * but we are still able to filter on the 'real' indev/outdev | 619 | * but we are still able to filter on the 'real' indev/outdev |
| 626 | * because of the physdev module. For ARP, indev and outdev are the | 620 | * because of the physdev module. For ARP, indev and outdev are the |
| 627 | * bridge ports. */ | 621 | * bridge ports. */ |
| 628 | static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb, | 622 | static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff *skb, |
| 629 | const struct net_device *in, | 623 | const struct net_device *in, |
| 630 | const struct net_device *out, | 624 | const struct net_device *out, |
| 631 | int (*okfn)(struct sk_buff *)) | 625 | int (*okfn)(struct sk_buff *)) |
| 632 | { | 626 | { |
| 633 | struct sk_buff *skb = *pskb; | ||
| 634 | struct nf_bridge_info *nf_bridge; | 627 | struct nf_bridge_info *nf_bridge; |
| 635 | struct net_device *parent; | 628 | struct net_device *parent; |
| 636 | int pf; | 629 | int pf; |
| @@ -648,7 +641,7 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb, | |||
| 648 | else | 641 | else |
| 649 | pf = PF_INET6; | 642 | pf = PF_INET6; |
| 650 | 643 | ||
| 651 | nf_bridge_pull_encap_header(*pskb); | 644 | nf_bridge_pull_encap_header(skb); |
| 652 | 645 | ||
| 653 | nf_bridge = skb->nf_bridge; | 646 | nf_bridge = skb->nf_bridge; |
| 654 | if (skb->pkt_type == PACKET_OTHERHOST) { | 647 | if (skb->pkt_type == PACKET_OTHERHOST) { |
| @@ -666,12 +659,11 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb, | |||
| 666 | return NF_STOLEN; | 659 | return NF_STOLEN; |
| 667 | } | 660 | } |
| 668 | 661 | ||
| 669 | static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb, | 662 | static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff *skb, |
| 670 | const struct net_device *in, | 663 | const struct net_device *in, |
| 671 | const struct net_device *out, | 664 | const struct net_device *out, |
| 672 | int (*okfn)(struct sk_buff *)) | 665 | int (*okfn)(struct sk_buff *)) |
| 673 | { | 666 | { |
| 674 | struct sk_buff *skb = *pskb; | ||
| 675 | struct net_device **d = (struct net_device **)(skb->cb); | 667 | struct net_device **d = (struct net_device **)(skb->cb); |
| 676 | 668 | ||
| 677 | #ifdef CONFIG_SYSCTL | 669 | #ifdef CONFIG_SYSCTL |
| @@ -682,12 +674,12 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb, | |||
| 682 | if (skb->protocol != htons(ETH_P_ARP)) { | 674 | if (skb->protocol != htons(ETH_P_ARP)) { |
| 683 | if (!IS_VLAN_ARP(skb)) | 675 | if (!IS_VLAN_ARP(skb)) |
| 684 | return NF_ACCEPT; | 676 | return NF_ACCEPT; |
| 685 | nf_bridge_pull_encap_header(*pskb); | 677 | nf_bridge_pull_encap_header(skb); |
| 686 | } | 678 | } |
| 687 | 679 | ||
| 688 | if (arp_hdr(skb)->ar_pln != 4) { | 680 | if (arp_hdr(skb)->ar_pln != 4) { |
| 689 | if (IS_VLAN_ARP(skb)) | 681 | if (IS_VLAN_ARP(skb)) |
| 690 | nf_bridge_push_encap_header(*pskb); | 682 | nf_bridge_push_encap_header(skb); |
| 691 | return NF_ACCEPT; | 683 | return NF_ACCEPT; |
| 692 | } | 684 | } |
| 693 | *d = (struct net_device *)in; | 685 | *d = (struct net_device *)in; |
| @@ -709,13 +701,12 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb, | |||
| 709 | * NF_BR_PRI_FIRST, so no relevant PF_BRIDGE/INPUT functions have been nor | 701 | * NF_BR_PRI_FIRST, so no relevant PF_BRIDGE/INPUT functions have been nor |
| 710 | * will be executed. | 702 | * will be executed. |
| 711 | */ | 703 | */ |
| 712 | static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb, | 704 | static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff *skb, |
| 713 | const struct net_device *in, | 705 | const struct net_device *in, |
| 714 | const struct net_device *out, | 706 | const struct net_device *out, |
| 715 | int (*okfn)(struct sk_buff *)) | 707 | int (*okfn)(struct sk_buff *)) |
| 716 | { | 708 | { |
| 717 | struct net_device *realindev; | 709 | struct net_device *realindev; |
| 718 | struct sk_buff *skb = *pskb; | ||
| 719 | struct nf_bridge_info *nf_bridge; | 710 | struct nf_bridge_info *nf_bridge; |
| 720 | 711 | ||
| 721 | if (!skb->nf_bridge) | 712 | if (!skb->nf_bridge) |
| @@ -752,13 +743,12 @@ static int br_nf_dev_queue_xmit(struct sk_buff *skb) | |||
| 752 | } | 743 | } |
| 753 | 744 | ||
| 754 | /* PF_BRIDGE/POST_ROUTING ********************************************/ | 745 | /* PF_BRIDGE/POST_ROUTING ********************************************/ |
| 755 | static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, | 746 | static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff *skb, |
| 756 | const struct net_device *in, | 747 | const struct net_device *in, |
| 757 | const struct net_device *out, | 748 | const struct net_device *out, |
| 758 | int (*okfn)(struct sk_buff *)) | 749 | int (*okfn)(struct sk_buff *)) |
| 759 | { | 750 | { |
| 760 | struct sk_buff *skb = *pskb; | 751 | struct nf_bridge_info *nf_bridge = skb->nf_bridge; |
| 761 | struct nf_bridge_info *nf_bridge = (*pskb)->nf_bridge; | ||
| 762 | struct net_device *realoutdev = bridge_parent(skb->dev); | 752 | struct net_device *realoutdev = bridge_parent(skb->dev); |
| 763 | int pf; | 753 | int pf; |
| 764 | 754 | ||
| @@ -828,13 +818,13 @@ print_error: | |||
| 828 | /* IP/SABOTAGE *****************************************************/ | 818 | /* IP/SABOTAGE *****************************************************/ |
| 829 | /* Don't hand locally destined packets to PF_INET(6)/PRE_ROUTING | 819 | /* Don't hand locally destined packets to PF_INET(6)/PRE_ROUTING |
| 830 | * for the second time. */ | 820 | * for the second time. */ |
| 831 | static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff **pskb, | 821 | static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff *skb, |
| 832 | const struct net_device *in, | 822 | const struct net_device *in, |
| 833 | const struct net_device *out, | 823 | const struct net_device *out, |
| 834 | int (*okfn)(struct sk_buff *)) | 824 | int (*okfn)(struct sk_buff *)) |
| 835 | { | 825 | { |
| 836 | if ((*pskb)->nf_bridge && | 826 | if (skb->nf_bridge && |
| 837 | !((*pskb)->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)) { | 827 | !(skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)) { |
| 838 | return NF_STOP; | 828 | return NF_STOP; |
| 839 | } | 829 | } |
| 840 | 830 | ||
diff --git a/net/bridge/netfilter/ebt_arpreply.c b/net/bridge/netfilter/ebt_arpreply.c index ffe468a632e7..48a80e423287 100644 --- a/net/bridge/netfilter/ebt_arpreply.c +++ b/net/bridge/netfilter/ebt_arpreply.c | |||
| @@ -15,7 +15,7 @@ | |||
| 15 | #include <net/arp.h> | 15 | #include <net/arp.h> |
| 16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 17 | 17 | ||
| 18 | static int ebt_target_reply(struct sk_buff **pskb, unsigned int hooknr, | 18 | static int ebt_target_reply(struct sk_buff *skb, unsigned int hooknr, |
| 19 | const struct net_device *in, const struct net_device *out, | 19 | const struct net_device *in, const struct net_device *out, |
| 20 | const void *data, unsigned int datalen) | 20 | const void *data, unsigned int datalen) |
| 21 | { | 21 | { |
| @@ -23,7 +23,6 @@ static int ebt_target_reply(struct sk_buff **pskb, unsigned int hooknr, | |||
| 23 | __be32 _sip, *siptr, _dip, *diptr; | 23 | __be32 _sip, *siptr, _dip, *diptr; |
| 24 | struct arphdr _ah, *ap; | 24 | struct arphdr _ah, *ap; |
| 25 | unsigned char _sha[ETH_ALEN], *shp; | 25 | unsigned char _sha[ETH_ALEN], *shp; |
| 26 | struct sk_buff *skb = *pskb; | ||
| 27 | 26 | ||
| 28 | ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah); | 27 | ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah); |
| 29 | if (ap == NULL) | 28 | if (ap == NULL) |
diff --git a/net/bridge/netfilter/ebt_dnat.c b/net/bridge/netfilter/ebt_dnat.c index 4582659dff0e..74262e9a566a 100644 --- a/net/bridge/netfilter/ebt_dnat.c +++ b/net/bridge/netfilter/ebt_dnat.c | |||
| @@ -8,29 +8,22 @@ | |||
| 8 | * | 8 | * |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | #include <linux/netfilter.h> | ||
| 11 | #include <linux/netfilter_bridge/ebtables.h> | 12 | #include <linux/netfilter_bridge/ebtables.h> |
| 12 | #include <linux/netfilter_bridge/ebt_nat.h> | 13 | #include <linux/netfilter_bridge/ebt_nat.h> |
| 13 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 14 | #include <net/sock.h> | 15 | #include <net/sock.h> |
| 15 | 16 | ||
| 16 | static int ebt_target_dnat(struct sk_buff **pskb, unsigned int hooknr, | 17 | static int ebt_target_dnat(struct sk_buff *skb, unsigned int hooknr, |
| 17 | const struct net_device *in, const struct net_device *out, | 18 | const struct net_device *in, const struct net_device *out, |
| 18 | const void *data, unsigned int datalen) | 19 | const void *data, unsigned int datalen) |
| 19 | { | 20 | { |
| 20 | struct ebt_nat_info *info = (struct ebt_nat_info *)data; | 21 | struct ebt_nat_info *info = (struct ebt_nat_info *)data; |
| 21 | 22 | ||
| 22 | if (skb_shared(*pskb) || skb_cloned(*pskb)) { | 23 | if (skb_make_writable(skb, 0)) |
| 23 | struct sk_buff *nskb; | 24 | return NF_DROP; |
| 24 | 25 | ||
| 25 | nskb = skb_copy(*pskb, GFP_ATOMIC); | 26 | memcpy(eth_hdr(skb)->h_dest, info->mac, ETH_ALEN); |
| 26 | if (!nskb) | ||
| 27 | return NF_DROP; | ||
| 28 | if ((*pskb)->sk) | ||
| 29 | skb_set_owner_w(nskb, (*pskb)->sk); | ||
| 30 | kfree_skb(*pskb); | ||
| 31 | *pskb = nskb; | ||
| 32 | } | ||
| 33 | memcpy(eth_hdr(*pskb)->h_dest, info->mac, ETH_ALEN); | ||
| 34 | return info->target; | 27 | return info->target; |
| 35 | } | 28 | } |
| 36 | 29 | ||
diff --git a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c index 62d23c7b25e6..6cba54309c09 100644 --- a/net/bridge/netfilter/ebt_mark.c +++ b/net/bridge/netfilter/ebt_mark.c | |||
| @@ -17,7 +17,7 @@ | |||
| 17 | #include <linux/netfilter_bridge/ebt_mark_t.h> | 17 | #include <linux/netfilter_bridge/ebt_mark_t.h> |
| 18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
| 19 | 19 | ||
| 20 | static int ebt_target_mark(struct sk_buff **pskb, unsigned int hooknr, | 20 | static int ebt_target_mark(struct sk_buff *skb, unsigned int hooknr, |
| 21 | const struct net_device *in, const struct net_device *out, | 21 | const struct net_device *in, const struct net_device *out, |
| 22 | const void *data, unsigned int datalen) | 22 | const void *data, unsigned int datalen) |
| 23 | { | 23 | { |
| @@ -25,13 +25,13 @@ static int ebt_target_mark(struct sk_buff **pskb, unsigned int hooknr, | |||
| 25 | int action = info->target & -16; | 25 | int action = info->target & -16; |
| 26 | 26 | ||
| 27 | if (action == MARK_SET_VALUE) | 27 | if (action == MARK_SET_VALUE) |
| 28 | (*pskb)->mark = info->mark; | 28 | skb->mark = info->mark; |
| 29 | else if (action == MARK_OR_VALUE) | 29 | else if (action == MARK_OR_VALUE) |
| 30 | (*pskb)->mark |= info->mark; | 30 | skb->mark |= info->mark; |
| 31 | else if (action == MARK_AND_VALUE) | 31 | else if (action == MARK_AND_VALUE) |
| 32 | (*pskb)->mark &= info->mark; | 32 | skb->mark &= info->mark; |
| 33 | else | 33 | else |
| 34 | (*pskb)->mark ^= info->mark; | 34 | skb->mark ^= info->mark; |
| 35 | 35 | ||
| 36 | return info->target | ~EBT_VERDICT_BITS; | 36 | return info->target | ~EBT_VERDICT_BITS; |
| 37 | } | 37 | } |
diff --git a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c index 9f378eab72d0..422cb834cff9 100644 --- a/net/bridge/netfilter/ebt_redirect.c +++ b/net/bridge/netfilter/ebt_redirect.c | |||
| @@ -8,35 +8,28 @@ | |||
| 8 | * | 8 | * |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | #include <linux/netfilter.h> | ||
| 11 | #include <linux/netfilter_bridge/ebtables.h> | 12 | #include <linux/netfilter_bridge/ebtables.h> |
| 12 | #include <linux/netfilter_bridge/ebt_redirect.h> | 13 | #include <linux/netfilter_bridge/ebt_redirect.h> |
| 13 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 14 | #include <net/sock.h> | 15 | #include <net/sock.h> |
| 15 | #include "../br_private.h" | 16 | #include "../br_private.h" |
| 16 | 17 | ||
| 17 | static int ebt_target_redirect(struct sk_buff **pskb, unsigned int hooknr, | 18 | static int ebt_target_redirect(struct sk_buff *skb, unsigned int hooknr, |
| 18 | const struct net_device *in, const struct net_device *out, | 19 | const struct net_device *in, const struct net_device *out, |
| 19 | const void *data, unsigned int datalen) | 20 | const void *data, unsigned int datalen) |
| 20 | { | 21 | { |
| 21 | struct ebt_redirect_info *info = (struct ebt_redirect_info *)data; | 22 | struct ebt_redirect_info *info = (struct ebt_redirect_info *)data; |
| 22 | 23 | ||
| 23 | if (skb_shared(*pskb) || skb_cloned(*pskb)) { | 24 | if (skb_make_writable(skb, 0)) |
| 24 | struct sk_buff *nskb; | 25 | return NF_DROP; |
| 25 | 26 | ||
| 26 | nskb = skb_copy(*pskb, GFP_ATOMIC); | ||
| 27 | if (!nskb) | ||
| 28 | return NF_DROP; | ||
| 29 | if ((*pskb)->sk) | ||
| 30 | skb_set_owner_w(nskb, (*pskb)->sk); | ||
| 31 | kfree_skb(*pskb); | ||
| 32 | *pskb = nskb; | ||
| 33 | } | ||
| 34 | if (hooknr != NF_BR_BROUTING) | 27 | if (hooknr != NF_BR_BROUTING) |
| 35 | memcpy(eth_hdr(*pskb)->h_dest, | 28 | memcpy(eth_hdr(skb)->h_dest, |
| 36 | in->br_port->br->dev->dev_addr, ETH_ALEN); | 29 | in->br_port->br->dev->dev_addr, ETH_ALEN); |
| 37 | else | 30 | else |
| 38 | memcpy(eth_hdr(*pskb)->h_dest, in->dev_addr, ETH_ALEN); | 31 | memcpy(eth_hdr(skb)->h_dest, in->dev_addr, ETH_ALEN); |
| 39 | (*pskb)->pkt_type = PACKET_HOST; | 32 | skb->pkt_type = PACKET_HOST; |
| 40 | return info->target; | 33 | return info->target; |
| 41 | } | 34 | } |
| 42 | 35 | ||
diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c index a50722182bfe..425ac920904d 100644 --- a/net/bridge/netfilter/ebt_snat.c +++ b/net/bridge/netfilter/ebt_snat.c | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | * | 8 | * |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | #include <linux/netfilter.h> | ||
| 11 | #include <linux/netfilter_bridge/ebtables.h> | 12 | #include <linux/netfilter_bridge/ebtables.h> |
| 12 | #include <linux/netfilter_bridge/ebt_nat.h> | 13 | #include <linux/netfilter_bridge/ebt_nat.h> |
| 13 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| @@ -15,34 +16,26 @@ | |||
| 15 | #include <linux/if_arp.h> | 16 | #include <linux/if_arp.h> |
| 16 | #include <net/arp.h> | 17 | #include <net/arp.h> |
| 17 | 18 | ||
| 18 | static int ebt_target_snat(struct sk_buff **pskb, unsigned int hooknr, | 19 | static int ebt_target_snat(struct sk_buff *skb, unsigned int hooknr, |
| 19 | const struct net_device *in, const struct net_device *out, | 20 | const struct net_device *in, const struct net_device *out, |
| 20 | const void *data, unsigned int datalen) | 21 | const void *data, unsigned int datalen) |
| 21 | { | 22 | { |
| 22 | struct ebt_nat_info *info = (struct ebt_nat_info *) data; | 23 | struct ebt_nat_info *info = (struct ebt_nat_info *) data; |
| 23 | 24 | ||
| 24 | if (skb_shared(*pskb) || skb_cloned(*pskb)) { | 25 | if (skb_make_writable(skb, 0)) |
| 25 | struct sk_buff *nskb; | 26 | return NF_DROP; |
| 26 | 27 | ||
| 27 | nskb = skb_copy(*pskb, GFP_ATOMIC); | 28 | memcpy(eth_hdr(skb)->h_source, info->mac, ETH_ALEN); |
| 28 | if (!nskb) | ||
| 29 | return NF_DROP; | ||
| 30 | if ((*pskb)->sk) | ||
| 31 | skb_set_owner_w(nskb, (*pskb)->sk); | ||
| 32 | kfree_skb(*pskb); | ||
| 33 | *pskb = nskb; | ||
| 34 | } | ||
| 35 | memcpy(eth_hdr(*pskb)->h_source, info->mac, ETH_ALEN); | ||
| 36 | if (!(info->target & NAT_ARP_BIT) && | 29 | if (!(info->target & NAT_ARP_BIT) && |
| 37 | eth_hdr(*pskb)->h_proto == htons(ETH_P_ARP)) { | 30 | eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) { |
| 38 | struct arphdr _ah, *ap; | 31 | struct arphdr _ah, *ap; |
| 39 | 32 | ||
| 40 | ap = skb_header_pointer(*pskb, 0, sizeof(_ah), &_ah); | 33 | ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah); |
| 41 | if (ap == NULL) | 34 | if (ap == NULL) |
| 42 | return EBT_DROP; | 35 | return EBT_DROP; |
| 43 | if (ap->ar_hln != ETH_ALEN) | 36 | if (ap->ar_hln != ETH_ALEN) |
| 44 | goto out; | 37 | goto out; |
| 45 | if (skb_store_bits(*pskb, sizeof(_ah), info->mac,ETH_ALEN)) | 38 | if (skb_store_bits(skb, sizeof(_ah), info->mac,ETH_ALEN)) |
| 46 | return EBT_DROP; | 39 | return EBT_DROP; |
| 47 | } | 40 | } |
| 48 | out: | 41 | out: |
diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c index d37ce0478938..e44519ebf1d2 100644 --- a/net/bridge/netfilter/ebtable_broute.c +++ b/net/bridge/netfilter/ebtable_broute.c | |||
| @@ -51,11 +51,11 @@ static struct ebt_table broute_table = | |||
| 51 | .me = THIS_MODULE, | 51 | .me = THIS_MODULE, |
| 52 | }; | 52 | }; |
| 53 | 53 | ||
| 54 | static int ebt_broute(struct sk_buff **pskb) | 54 | static int ebt_broute(struct sk_buff *skb) |
| 55 | { | 55 | { |
| 56 | int ret; | 56 | int ret; |
| 57 | 57 | ||
| 58 | ret = ebt_do_table(NF_BR_BROUTING, pskb, (*pskb)->dev, NULL, | 58 | ret = ebt_do_table(NF_BR_BROUTING, skb, skb->dev, NULL, |
| 59 | &broute_table); | 59 | &broute_table); |
| 60 | if (ret == NF_DROP) | 60 | if (ret == NF_DROP) |
| 61 | return 1; /* route it */ | 61 | return 1; /* route it */ |
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c index 81d84145c417..210493f99bc4 100644 --- a/net/bridge/netfilter/ebtable_filter.c +++ b/net/bridge/netfilter/ebtable_filter.c | |||
| @@ -61,10 +61,10 @@ static struct ebt_table frame_filter = | |||
| 61 | }; | 61 | }; |
| 62 | 62 | ||
| 63 | static unsigned int | 63 | static unsigned int |
| 64 | ebt_hook (unsigned int hook, struct sk_buff **pskb, const struct net_device *in, | 64 | ebt_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in, |
| 65 | const struct net_device *out, int (*okfn)(struct sk_buff *)) | 65 | const struct net_device *out, int (*okfn)(struct sk_buff *)) |
| 66 | { | 66 | { |
| 67 | return ebt_do_table(hook, pskb, in, out, &frame_filter); | 67 | return ebt_do_table(hook, skb, in, out, &frame_filter); |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | static struct nf_hook_ops ebt_ops_filter[] = { | 70 | static struct nf_hook_ops ebt_ops_filter[] = { |
diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c index 9c50488b62eb..3e58c2e5ee21 100644 --- a/net/bridge/netfilter/ebtable_nat.c +++ b/net/bridge/netfilter/ebtable_nat.c | |||
| @@ -61,17 +61,17 @@ static struct ebt_table frame_nat = | |||
| 61 | }; | 61 | }; |
| 62 | 62 | ||
| 63 | static unsigned int | 63 | static unsigned int |
| 64 | ebt_nat_dst(unsigned int hook, struct sk_buff **pskb, const struct net_device *in | 64 | ebt_nat_dst(unsigned int hook, struct sk_buff *skb, const struct net_device *in |
| 65 | , const struct net_device *out, int (*okfn)(struct sk_buff *)) | 65 | , const struct net_device *out, int (*okfn)(struct sk_buff *)) |
| 66 | { | 66 | { |
| 67 | return ebt_do_table(hook, pskb, in, out, &frame_nat); | 67 | return ebt_do_table(hook, skb, in, out, &frame_nat); |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | static unsigned int | 70 | static unsigned int |
| 71 | ebt_nat_src(unsigned int hook, struct sk_buff **pskb, const struct net_device *in | 71 | ebt_nat_src(unsigned int hook, struct sk_buff *skb, const struct net_device *in |
| 72 | , const struct net_device *out, int (*okfn)(struct sk_buff *)) | 72 | , const struct net_device *out, int (*okfn)(struct sk_buff *)) |
| 73 | { | 73 | { |
| 74 | return ebt_do_table(hook, pskb, in, out, &frame_nat); | 74 | return ebt_do_table(hook, skb, in, out, &frame_nat); |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | static struct nf_hook_ops ebt_ops_nat[] = { | 77 | static struct nf_hook_ops ebt_ops_nat[] = { |
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 6018d0e51938..d5a09eaef915 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
| @@ -142,7 +142,7 @@ static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h, | |||
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | /* Do some firewalling */ | 144 | /* Do some firewalling */ |
| 145 | unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb, | 145 | unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb, |
| 146 | const struct net_device *in, const struct net_device *out, | 146 | const struct net_device *in, const struct net_device *out, |
| 147 | struct ebt_table *table) | 147 | struct ebt_table *table) |
| 148 | { | 148 | { |
| @@ -172,19 +172,19 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb, | |||
| 172 | base = private->entries; | 172 | base = private->entries; |
| 173 | i = 0; | 173 | i = 0; |
| 174 | while (i < nentries) { | 174 | while (i < nentries) { |
| 175 | if (ebt_basic_match(point, eth_hdr(*pskb), in, out)) | 175 | if (ebt_basic_match(point, eth_hdr(skb), in, out)) |
| 176 | goto letscontinue; | 176 | goto letscontinue; |
| 177 | 177 | ||
| 178 | if (EBT_MATCH_ITERATE(point, ebt_do_match, *pskb, in, out) != 0) | 178 | if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, in, out) != 0) |
| 179 | goto letscontinue; | 179 | goto letscontinue; |
| 180 | 180 | ||
| 181 | /* increase counter */ | 181 | /* increase counter */ |
| 182 | (*(counter_base + i)).pcnt++; | 182 | (*(counter_base + i)).pcnt++; |
| 183 | (*(counter_base + i)).bcnt+=(**pskb).len; | 183 | (*(counter_base + i)).bcnt += skb->len; |
| 184 | 184 | ||
| 185 | /* these should only watch: not modify, nor tell us | 185 | /* these should only watch: not modify, nor tell us |
| 186 | what to do with the packet */ | 186 | what to do with the packet */ |
| 187 | EBT_WATCHER_ITERATE(point, ebt_do_watcher, *pskb, hook, in, | 187 | EBT_WATCHER_ITERATE(point, ebt_do_watcher, skb, hook, in, |
| 188 | out); | 188 | out); |
| 189 | 189 | ||
| 190 | t = (struct ebt_entry_target *) | 190 | t = (struct ebt_entry_target *) |
| @@ -193,7 +193,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb, | |||
| 193 | if (!t->u.target->target) | 193 | if (!t->u.target->target) |
| 194 | verdict = ((struct ebt_standard_target *)t)->verdict; | 194 | verdict = ((struct ebt_standard_target *)t)->verdict; |
| 195 | else | 195 | else |
| 196 | verdict = t->u.target->target(pskb, hook, | 196 | verdict = t->u.target->target(skb, hook, |
| 197 | in, out, t->data, t->target_size); | 197 | in, out, t->data, t->target_size); |
| 198 | if (verdict == EBT_ACCEPT) { | 198 | if (verdict == EBT_ACCEPT) { |
| 199 | read_unlock_bh(&table->lock); | 199 | read_unlock_bh(&table->lock); |
diff --git a/net/core/dev.c b/net/core/dev.c index 99b7bda37d10..38b03da5c1ca 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -1362,22 +1362,21 @@ int skb_checksum_help(struct sk_buff *skb) | |||
| 1362 | goto out_set_summed; | 1362 | goto out_set_summed; |
| 1363 | } | 1363 | } |
| 1364 | 1364 | ||
| 1365 | if (skb_cloned(skb)) { | 1365 | offset = skb->csum_start - skb_headroom(skb); |
| 1366 | BUG_ON(offset >= skb_headlen(skb)); | ||
| 1367 | csum = skb_checksum(skb, offset, skb->len - offset, 0); | ||
| 1368 | |||
| 1369 | offset += skb->csum_offset; | ||
| 1370 | BUG_ON(offset + sizeof(__sum16) > skb_headlen(skb)); | ||
| 1371 | |||
| 1372 | if (skb_cloned(skb) && | ||
| 1373 | !skb_clone_writable(skb, offset + sizeof(__sum16))) { | ||
| 1366 | ret = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); | 1374 | ret = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); |
| 1367 | if (ret) | 1375 | if (ret) |
| 1368 | goto out; | 1376 | goto out; |
| 1369 | } | 1377 | } |
| 1370 | 1378 | ||
| 1371 | offset = skb->csum_start - skb_headroom(skb); | 1379 | *(__sum16 *)(skb->data + offset) = csum_fold(csum); |
| 1372 | BUG_ON(offset > (int)skb->len); | ||
| 1373 | csum = skb_checksum(skb, offset, skb->len-offset, 0); | ||
| 1374 | |||
| 1375 | offset = skb_headlen(skb) - offset; | ||
| 1376 | BUG_ON(offset <= 0); | ||
| 1377 | BUG_ON(skb->csum_offset + 2 > offset); | ||
| 1378 | |||
| 1379 | *(__sum16 *)(skb->head + skb->csum_start + skb->csum_offset) = | ||
| 1380 | csum_fold(csum); | ||
| 1381 | out_set_summed: | 1380 | out_set_summed: |
| 1382 | skb->ip_summed = CHECKSUM_NONE; | 1381 | skb->ip_summed = CHECKSUM_NONE; |
| 1383 | out: | 1382 | out: |
| @@ -1949,27 +1948,51 @@ static int ing_filter(struct sk_buff *skb) | |||
| 1949 | struct Qdisc *q; | 1948 | struct Qdisc *q; |
| 1950 | struct net_device *dev = skb->dev; | 1949 | struct net_device *dev = skb->dev; |
| 1951 | int result = TC_ACT_OK; | 1950 | int result = TC_ACT_OK; |
| 1951 | u32 ttl = G_TC_RTTL(skb->tc_verd); | ||
| 1952 | 1952 | ||
| 1953 | if (dev->qdisc_ingress) { | 1953 | if (MAX_RED_LOOP < ttl++) { |
| 1954 | __u32 ttl = (__u32) G_TC_RTTL(skb->tc_verd); | 1954 | printk(KERN_WARNING |
| 1955 | if (MAX_RED_LOOP < ttl++) { | 1955 | "Redir loop detected Dropping packet (%d->%d)\n", |
| 1956 | printk(KERN_WARNING "Redir loop detected Dropping packet (%d->%d)\n", | 1956 | skb->iif, dev->ifindex); |
| 1957 | skb->iif, skb->dev->ifindex); | 1957 | return TC_ACT_SHOT; |
| 1958 | return TC_ACT_SHOT; | 1958 | } |
| 1959 | } | 1959 | |
| 1960 | skb->tc_verd = SET_TC_RTTL(skb->tc_verd, ttl); | ||
| 1961 | skb->tc_verd = SET_TC_AT(skb->tc_verd, AT_INGRESS); | ||
| 1960 | 1962 | ||
| 1961 | skb->tc_verd = SET_TC_RTTL(skb->tc_verd,ttl); | 1963 | spin_lock(&dev->ingress_lock); |
| 1964 | if ((q = dev->qdisc_ingress) != NULL) | ||
| 1965 | result = q->enqueue(skb, q); | ||
| 1966 | spin_unlock(&dev->ingress_lock); | ||
| 1962 | 1967 | ||
| 1963 | skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_INGRESS); | 1968 | return result; |
| 1969 | } | ||
| 1970 | |||
| 1971 | static inline struct sk_buff *handle_ing(struct sk_buff *skb, | ||
| 1972 | struct packet_type **pt_prev, | ||
| 1973 | int *ret, struct net_device *orig_dev) | ||
| 1974 | { | ||
| 1975 | if (!skb->dev->qdisc_ingress) | ||
| 1976 | goto out; | ||
| 1964 | 1977 | ||
| 1965 | spin_lock(&dev->ingress_lock); | 1978 | if (*pt_prev) { |
| 1966 | if ((q = dev->qdisc_ingress) != NULL) | 1979 | *ret = deliver_skb(skb, *pt_prev, orig_dev); |
| 1967 | result = q->enqueue(skb, q); | 1980 | *pt_prev = NULL; |
| 1968 | spin_unlock(&dev->ingress_lock); | 1981 | } else { |
| 1982 | /* Huh? Why does turning on AF_PACKET affect this? */ | ||
| 1983 | skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd); | ||
| 1984 | } | ||
| 1969 | 1985 | ||
| 1986 | switch (ing_filter(skb)) { | ||
| 1987 | case TC_ACT_SHOT: | ||
| 1988 | case TC_ACT_STOLEN: | ||
| 1989 | kfree_skb(skb); | ||
| 1990 | return NULL; | ||
| 1970 | } | 1991 | } |
| 1971 | 1992 | ||
| 1972 | return result; | 1993 | out: |
| 1994 | skb->tc_verd = 0; | ||
| 1995 | return skb; | ||
| 1973 | } | 1996 | } |
| 1974 | #endif | 1997 | #endif |
| 1975 | 1998 | ||
| @@ -2021,21 +2044,9 @@ int netif_receive_skb(struct sk_buff *skb) | |||
| 2021 | } | 2044 | } |
| 2022 | 2045 | ||
| 2023 | #ifdef CONFIG_NET_CLS_ACT | 2046 | #ifdef CONFIG_NET_CLS_ACT |
| 2024 | if (pt_prev) { | 2047 | skb = handle_ing(skb, &pt_prev, &ret, orig_dev); |
| 2025 | ret = deliver_skb(skb, pt_prev, orig_dev); | 2048 | if (!skb) |
| 2026 | pt_prev = NULL; /* noone else should process this after*/ | ||
| 2027 | } else { | ||
| 2028 | skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd); | ||
| 2029 | } | ||
| 2030 | |||
| 2031 | ret = ing_filter(skb); | ||
| 2032 | |||
| 2033 | if (ret == TC_ACT_SHOT || (ret == TC_ACT_STOLEN)) { | ||
| 2034 | kfree_skb(skb); | ||
| 2035 | goto out; | 2049 | goto out; |
| 2036 | } | ||
| 2037 | |||
| 2038 | skb->tc_verd = 0; | ||
| 2039 | ncls: | 2050 | ncls: |
| 2040 | #endif | 2051 | #endif |
| 2041 | 2052 | ||
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index c52df858d0be..cd3af59b38a1 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
| @@ -481,6 +481,8 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, const void *pkey, | |||
| 481 | if (!creat) | 481 | if (!creat) |
| 482 | goto out; | 482 | goto out; |
| 483 | 483 | ||
| 484 | ASSERT_RTNL(); | ||
| 485 | |||
| 484 | n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL); | 486 | n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL); |
| 485 | if (!n) | 487 | if (!n) |
| 486 | goto out; | 488 | goto out; |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 944189d96323..70d9b5da96ae 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
| @@ -362,6 +362,97 @@ void kfree_skb(struct sk_buff *skb) | |||
| 362 | __kfree_skb(skb); | 362 | __kfree_skb(skb); |
| 363 | } | 363 | } |
| 364 | 364 | ||
| 365 | static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | ||
| 366 | { | ||
| 367 | new->tstamp = old->tstamp; | ||
| 368 | new->dev = old->dev; | ||
| 369 | new->transport_header = old->transport_header; | ||
| 370 | new->network_header = old->network_header; | ||
| 371 | new->mac_header = old->mac_header; | ||
| 372 | new->dst = dst_clone(old->dst); | ||
| 373 | #ifdef CONFIG_INET | ||
| 374 | new->sp = secpath_get(old->sp); | ||
| 375 | #endif | ||
| 376 | memcpy(new->cb, old->cb, sizeof(old->cb)); | ||
| 377 | new->csum_start = old->csum_start; | ||
| 378 | new->csum_offset = old->csum_offset; | ||
| 379 | new->local_df = old->local_df; | ||
| 380 | new->pkt_type = old->pkt_type; | ||
| 381 | new->ip_summed = old->ip_summed; | ||
| 382 | skb_copy_queue_mapping(new, old); | ||
| 383 | new->priority = old->priority; | ||
| 384 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) | ||
| 385 | new->ipvs_property = old->ipvs_property; | ||
| 386 | #endif | ||
| 387 | new->protocol = old->protocol; | ||
| 388 | new->mark = old->mark; | ||
| 389 | __nf_copy(new, old); | ||
| 390 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | ||
| 391 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | ||
| 392 | new->nf_trace = old->nf_trace; | ||
| 393 | #endif | ||
| 394 | #ifdef CONFIG_NET_SCHED | ||
| 395 | new->tc_index = old->tc_index; | ||
| 396 | #ifdef CONFIG_NET_CLS_ACT | ||
| 397 | new->tc_verd = old->tc_verd; | ||
| 398 | #endif | ||
| 399 | #endif | ||
| 400 | skb_copy_secmark(new, old); | ||
| 401 | } | ||
| 402 | |||
| 403 | static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb) | ||
| 404 | { | ||
| 405 | #define C(x) n->x = skb->x | ||
| 406 | |||
| 407 | n->next = n->prev = NULL; | ||
| 408 | n->sk = NULL; | ||
| 409 | __copy_skb_header(n, skb); | ||
| 410 | |||
| 411 | C(len); | ||
| 412 | C(data_len); | ||
| 413 | C(mac_len); | ||
| 414 | n->cloned = 1; | ||
| 415 | n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len; | ||
| 416 | n->nohdr = 0; | ||
| 417 | n->destructor = NULL; | ||
| 418 | #ifdef CONFIG_NET_CLS_ACT | ||
| 419 | /* FIXME What is this and why don't we do it in copy_skb_header? */ | ||
| 420 | n->tc_verd = SET_TC_VERD(n->tc_verd,0); | ||
| 421 | n->tc_verd = CLR_TC_OK2MUNGE(n->tc_verd); | ||
| 422 | n->tc_verd = CLR_TC_MUNGED(n->tc_verd); | ||
| 423 | C(iif); | ||
| 424 | #endif | ||
| 425 | C(truesize); | ||
| 426 | atomic_set(&n->users, 1); | ||
| 427 | C(head); | ||
| 428 | C(data); | ||
| 429 | C(tail); | ||
| 430 | C(end); | ||
| 431 | |||
| 432 | atomic_inc(&(skb_shinfo(skb)->dataref)); | ||
| 433 | skb->cloned = 1; | ||
| 434 | |||
| 435 | return n; | ||
| 436 | #undef C | ||
| 437 | } | ||
| 438 | |||
| 439 | /** | ||
| 440 | * skb_morph - morph one skb into another | ||
| 441 | * @dst: the skb to receive the contents | ||
| 442 | * @src: the skb to supply the contents | ||
| 443 | * | ||
| 444 | * This is identical to skb_clone except that the target skb is | ||
| 445 | * supplied by the user. | ||
| 446 | * | ||
| 447 | * The target skb is returned upon exit. | ||
| 448 | */ | ||
| 449 | struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src) | ||
| 450 | { | ||
| 451 | skb_release_data(dst); | ||
| 452 | return __skb_clone(dst, src); | ||
| 453 | } | ||
| 454 | EXPORT_SYMBOL_GPL(skb_morph); | ||
| 455 | |||
| 365 | /** | 456 | /** |
| 366 | * skb_clone - duplicate an sk_buff | 457 | * skb_clone - duplicate an sk_buff |
| 367 | * @skb: buffer to clone | 458 | * @skb: buffer to clone |
| @@ -393,66 +484,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) | |||
| 393 | n->fclone = SKB_FCLONE_UNAVAILABLE; | 484 | n->fclone = SKB_FCLONE_UNAVAILABLE; |
| 394 | } | 485 | } |
| 395 | 486 | ||
| 396 | #define C(x) n->x = skb->x | 487 | return __skb_clone(n, skb); |
| 397 | |||
| 398 | n->next = n->prev = NULL; | ||
| 399 | n->sk = NULL; | ||
| 400 | C(tstamp); | ||
| 401 | C(dev); | ||
| 402 | C(transport_header); | ||
| 403 | C(network_header); | ||
| 404 | C(mac_header); | ||
| 405 | C(dst); | ||
| 406 | dst_clone(skb->dst); | ||
| 407 | C(sp); | ||
| 408 | #ifdef CONFIG_INET | ||
| 409 | secpath_get(skb->sp); | ||
| 410 | #endif | ||
| 411 | memcpy(n->cb, skb->cb, sizeof(skb->cb)); | ||
| 412 | C(len); | ||
| 413 | C(data_len); | ||
| 414 | C(mac_len); | ||
| 415 | C(csum); | ||
| 416 | C(local_df); | ||
| 417 | n->cloned = 1; | ||
| 418 | n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len; | ||
| 419 | n->nohdr = 0; | ||
| 420 | C(pkt_type); | ||
| 421 | C(ip_summed); | ||
| 422 | skb_copy_queue_mapping(n, skb); | ||
| 423 | C(priority); | ||
| 424 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) | ||
| 425 | C(ipvs_property); | ||
| 426 | #endif | ||
| 427 | C(protocol); | ||
| 428 | n->destructor = NULL; | ||
| 429 | C(mark); | ||
| 430 | __nf_copy(n, skb); | ||
| 431 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | ||
| 432 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | ||
| 433 | C(nf_trace); | ||
| 434 | #endif | ||
| 435 | #ifdef CONFIG_NET_SCHED | ||
| 436 | C(tc_index); | ||
| 437 | #ifdef CONFIG_NET_CLS_ACT | ||
| 438 | n->tc_verd = SET_TC_VERD(skb->tc_verd,0); | ||
| 439 | n->tc_verd = CLR_TC_OK2MUNGE(n->tc_verd); | ||
| 440 | n->tc_verd = CLR_TC_MUNGED(n->tc_verd); | ||
| 441 | C(iif); | ||
| 442 | #endif | ||
| 443 | #endif | ||
| 444 | skb_copy_secmark(n, skb); | ||
| 445 | C(truesize); | ||
| 446 | atomic_set(&n->users, 1); | ||
| 447 | C(head); | ||
| 448 | C(data); | ||
| 449 | C(tail); | ||
| 450 | C(end); | ||
| 451 | |||
| 452 | atomic_inc(&(skb_shinfo(skb)->dataref)); | ||
| 453 | skb->cloned = 1; | ||
| 454 | |||
| 455 | return n; | ||
| 456 | } | 488 | } |
| 457 | 489 | ||
| 458 | static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | 490 | static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) |
| @@ -463,50 +495,15 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | |||
| 463 | */ | 495 | */ |
| 464 | unsigned long offset = new->data - old->data; | 496 | unsigned long offset = new->data - old->data; |
| 465 | #endif | 497 | #endif |
| 466 | new->sk = NULL; | 498 | |
| 467 | new->dev = old->dev; | 499 | __copy_skb_header(new, old); |
| 468 | skb_copy_queue_mapping(new, old); | 500 | |
| 469 | new->priority = old->priority; | ||
| 470 | new->protocol = old->protocol; | ||
| 471 | new->dst = dst_clone(old->dst); | ||
| 472 | #ifdef CONFIG_INET | ||
| 473 | new->sp = secpath_get(old->sp); | ||
| 474 | #endif | ||
| 475 | new->csum_start = old->csum_start; | ||
| 476 | new->csum_offset = old->csum_offset; | ||
| 477 | new->ip_summed = old->ip_summed; | ||
| 478 | new->transport_header = old->transport_header; | ||
| 479 | new->network_header = old->network_header; | ||
| 480 | new->mac_header = old->mac_header; | ||
| 481 | #ifndef NET_SKBUFF_DATA_USES_OFFSET | 501 | #ifndef NET_SKBUFF_DATA_USES_OFFSET |
| 482 | /* {transport,network,mac}_header are relative to skb->head */ | 502 | /* {transport,network,mac}_header are relative to skb->head */ |
| 483 | new->transport_header += offset; | 503 | new->transport_header += offset; |
| 484 | new->network_header += offset; | 504 | new->network_header += offset; |
| 485 | new->mac_header += offset; | 505 | new->mac_header += offset; |
| 486 | #endif | 506 | #endif |
| 487 | memcpy(new->cb, old->cb, sizeof(old->cb)); | ||
| 488 | new->local_df = old->local_df; | ||
| 489 | new->fclone = SKB_FCLONE_UNAVAILABLE; | ||
| 490 | new->pkt_type = old->pkt_type; | ||
| 491 | new->tstamp = old->tstamp; | ||
| 492 | new->destructor = NULL; | ||
| 493 | new->mark = old->mark; | ||
| 494 | __nf_copy(new, old); | ||
| 495 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | ||
| 496 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | ||
| 497 | new->nf_trace = old->nf_trace; | ||
| 498 | #endif | ||
| 499 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) | ||
| 500 | new->ipvs_property = old->ipvs_property; | ||
| 501 | #endif | ||
| 502 | #ifdef CONFIG_NET_SCHED | ||
| 503 | #ifdef CONFIG_NET_CLS_ACT | ||
| 504 | new->tc_verd = old->tc_verd; | ||
| 505 | #endif | ||
| 506 | new->tc_index = old->tc_index; | ||
| 507 | #endif | ||
| 508 | skb_copy_secmark(new, old); | ||
| 509 | atomic_set(&new->users, 1); | ||
| 510 | skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size; | 507 | skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size; |
| 511 | skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs; | 508 | skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs; |
| 512 | skb_shinfo(new)->gso_type = skb_shinfo(old)->gso_type; | 509 | skb_shinfo(new)->gso_type = skb_shinfo(old)->gso_type; |
| @@ -685,7 +682,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, | |||
| 685 | skb->transport_header += off; | 682 | skb->transport_header += off; |
| 686 | skb->network_header += off; | 683 | skb->network_header += off; |
| 687 | skb->mac_header += off; | 684 | skb->mac_header += off; |
| 688 | skb->csum_start += off; | 685 | skb->csum_start += nhead; |
| 689 | skb->cloned = 0; | 686 | skb->cloned = 0; |
| 690 | skb->hdr_len = 0; | 687 | skb->hdr_len = 0; |
| 691 | skb->nohdr = 0; | 688 | skb->nohdr = 0; |
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 006a3834fbcd..cac53548c2d8 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c | |||
| @@ -767,10 +767,9 @@ discard: | |||
| 767 | return 0; | 767 | return 0; |
| 768 | } | 768 | } |
| 769 | 769 | ||
| 770 | static int dccp_v6_rcv(struct sk_buff **pskb) | 770 | static int dccp_v6_rcv(struct sk_buff *skb) |
| 771 | { | 771 | { |
| 772 | const struct dccp_hdr *dh; | 772 | const struct dccp_hdr *dh; |
| 773 | struct sk_buff *skb = *pskb; | ||
| 774 | struct sock *sk; | 773 | struct sock *sk; |
| 775 | int min_cov; | 774 | int min_cov; |
| 776 | 775 | ||
diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c index f7fba7721e63..43fcd29046d1 100644 --- a/net/decnet/netfilter/dn_rtmsg.c +++ b/net/decnet/netfilter/dn_rtmsg.c | |||
| @@ -88,12 +88,12 @@ static void dnrmg_send_peer(struct sk_buff *skb) | |||
| 88 | 88 | ||
| 89 | 89 | ||
| 90 | static unsigned int dnrmg_hook(unsigned int hook, | 90 | static unsigned int dnrmg_hook(unsigned int hook, |
| 91 | struct sk_buff **pskb, | 91 | struct sk_buff *skb, |
| 92 | const struct net_device *in, | 92 | const struct net_device *in, |
| 93 | const struct net_device *out, | 93 | const struct net_device *out, |
| 94 | int (*okfn)(struct sk_buff *)) | 94 | int (*okfn)(struct sk_buff *)) |
| 95 | { | 95 | { |
| 96 | dnrmg_send_peer(*pskb); | 96 | dnrmg_send_peer(skb); |
| 97 | return NF_ACCEPT; | 97 | return NF_ACCEPT; |
| 98 | } | 98 | } |
| 99 | 99 | ||
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index a02c36d0a13e..93fe3966805d 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile | |||
| @@ -10,7 +10,8 @@ obj-y := route.o inetpeer.o protocol.o \ | |||
| 10 | tcp_minisocks.o tcp_cong.o \ | 10 | tcp_minisocks.o tcp_cong.o \ |
| 11 | datagram.o raw.o udp.o udplite.o \ | 11 | datagram.o raw.o udp.o udplite.o \ |
| 12 | arp.o icmp.o devinet.o af_inet.o igmp.o \ | 12 | arp.o icmp.o devinet.o af_inet.o igmp.o \ |
| 13 | sysctl_net_ipv4.o fib_frontend.o fib_semantics.o | 13 | sysctl_net_ipv4.o fib_frontend.o fib_semantics.o \ |
| 14 | inet_fragment.o | ||
| 14 | 15 | ||
| 15 | obj-$(CONFIG_IP_FIB_HASH) += fib_hash.o | 16 | obj-$(CONFIG_IP_FIB_HASH) += fib_hash.o |
| 16 | obj-$(CONFIG_IP_FIB_TRIE) += fib_trie.o | 17 | obj-$(CONFIG_IP_FIB_TRIE) += fib_trie.o |
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c new file mode 100644 index 000000000000..484cf512858f --- /dev/null +++ b/net/ipv4/inet_fragment.c | |||
| @@ -0,0 +1,174 @@ | |||
| 1 | /* | ||
| 2 | * inet fragments management | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or | ||
| 5 | * modify it under the terms of the GNU General Public License | ||
| 6 | * as published by the Free Software Foundation; either version | ||
| 7 | * 2 of the License, or (at your option) any later version. | ||
| 8 | * | ||
| 9 | * Authors: Pavel Emelyanov <xemul@openvz.org> | ||
| 10 | * Started as consolidation of ipv4/ip_fragment.c, | ||
| 11 | * ipv6/reassembly. and ipv6 nf conntrack reassembly | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/list.h> | ||
| 15 | #include <linux/spinlock.h> | ||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/timer.h> | ||
| 18 | #include <linux/mm.h> | ||
| 19 | #include <linux/random.h> | ||
| 20 | #include <linux/skbuff.h> | ||
| 21 | #include <linux/rtnetlink.h> | ||
| 22 | |||
| 23 | #include <net/inet_frag.h> | ||
| 24 | |||
| 25 | static void inet_frag_secret_rebuild(unsigned long dummy) | ||
| 26 | { | ||
| 27 | struct inet_frags *f = (struct inet_frags *)dummy; | ||
| 28 | unsigned long now = jiffies; | ||
| 29 | int i; | ||
| 30 | |||
| 31 | write_lock(&f->lock); | ||
| 32 | get_random_bytes(&f->rnd, sizeof(u32)); | ||
| 33 | for (i = 0; i < INETFRAGS_HASHSZ; i++) { | ||
| 34 | struct inet_frag_queue *q; | ||
| 35 | struct hlist_node *p, *n; | ||
| 36 | |||
| 37 | hlist_for_each_entry_safe(q, p, n, &f->hash[i], list) { | ||
| 38 | unsigned int hval = f->hashfn(q); | ||
| 39 | |||
| 40 | if (hval != i) { | ||
| 41 | hlist_del(&q->list); | ||
| 42 | |||
| 43 | /* Relink to new hash chain. */ | ||
| 44 | hlist_add_head(&q->list, &f->hash[hval]); | ||
| 45 | } | ||
| 46 | } | ||
| 47 | } | ||
| 48 | write_unlock(&f->lock); | ||
| 49 | |||
| 50 | mod_timer(&f->secret_timer, now + f->ctl->secret_interval); | ||
| 51 | } | ||
| 52 | |||
| 53 | void inet_frags_init(struct inet_frags *f) | ||
| 54 | { | ||
| 55 | int i; | ||
| 56 | |||
| 57 | for (i = 0; i < INETFRAGS_HASHSZ; i++) | ||
| 58 | INIT_HLIST_HEAD(&f->hash[i]); | ||
| 59 | |||
| 60 | INIT_LIST_HEAD(&f->lru_list); | ||
| 61 | rwlock_init(&f->lock); | ||
| 62 | |||
| 63 | f->rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^ | ||
| 64 | (jiffies ^ (jiffies >> 6))); | ||
| 65 | |||
| 66 | f->nqueues = 0; | ||
| 67 | atomic_set(&f->mem, 0); | ||
| 68 | |||
| 69 | init_timer(&f->secret_timer); | ||
| 70 | f->secret_timer.function = inet_frag_secret_rebuild; | ||
| 71 | f->secret_timer.data = (unsigned long)f; | ||
| 72 | f->secret_timer.expires = jiffies + f->ctl->secret_interval; | ||
| 73 | add_timer(&f->secret_timer); | ||
| 74 | } | ||
| 75 | EXPORT_SYMBOL(inet_frags_init); | ||
| 76 | |||
| 77 | void inet_frags_fini(struct inet_frags *f) | ||
| 78 | { | ||
| 79 | del_timer(&f->secret_timer); | ||
| 80 | } | ||
| 81 | EXPORT_SYMBOL(inet_frags_fini); | ||
| 82 | |||
| 83 | static inline void fq_unlink(struct inet_frag_queue *fq, struct inet_frags *f) | ||
| 84 | { | ||
| 85 | write_lock(&f->lock); | ||
| 86 | hlist_del(&fq->list); | ||
| 87 | list_del(&fq->lru_list); | ||
| 88 | f->nqueues--; | ||
| 89 | write_unlock(&f->lock); | ||
| 90 | } | ||
| 91 | |||
| 92 | void inet_frag_kill(struct inet_frag_queue *fq, struct inet_frags *f) | ||
| 93 | { | ||
| 94 | if (del_timer(&fq->timer)) | ||
| 95 | atomic_dec(&fq->refcnt); | ||
| 96 | |||
| 97 | if (!(fq->last_in & COMPLETE)) { | ||
| 98 | fq_unlink(fq, f); | ||
| 99 | atomic_dec(&fq->refcnt); | ||
| 100 | fq->last_in |= COMPLETE; | ||
| 101 | } | ||
| 102 | } | ||
| 103 | |||
| 104 | EXPORT_SYMBOL(inet_frag_kill); | ||
| 105 | |||
| 106 | static inline void frag_kfree_skb(struct inet_frags *f, struct sk_buff *skb, | ||
| 107 | int *work) | ||
| 108 | { | ||
| 109 | if (work) | ||
| 110 | *work -= skb->truesize; | ||
| 111 | |||
| 112 | atomic_sub(skb->truesize, &f->mem); | ||
| 113 | if (f->skb_free) | ||
| 114 | f->skb_free(skb); | ||
| 115 | kfree_skb(skb); | ||
| 116 | } | ||
| 117 | |||
| 118 | void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f, | ||
| 119 | int *work) | ||
| 120 | { | ||
| 121 | struct sk_buff *fp; | ||
| 122 | |||
| 123 | BUG_TRAP(q->last_in & COMPLETE); | ||
| 124 | BUG_TRAP(del_timer(&q->timer) == 0); | ||
| 125 | |||
| 126 | /* Release all fragment data. */ | ||
| 127 | fp = q->fragments; | ||
| 128 | while (fp) { | ||
| 129 | struct sk_buff *xp = fp->next; | ||
| 130 | |||
| 131 | frag_kfree_skb(f, fp, work); | ||
| 132 | fp = xp; | ||
| 133 | } | ||
| 134 | |||
| 135 | if (work) | ||
| 136 | *work -= f->qsize; | ||
| 137 | atomic_sub(f->qsize, &f->mem); | ||
| 138 | |||
| 139 | f->destructor(q); | ||
| 140 | |||
| 141 | } | ||
| 142 | EXPORT_SYMBOL(inet_frag_destroy); | ||
| 143 | |||
| 144 | int inet_frag_evictor(struct inet_frags *f) | ||
| 145 | { | ||
| 146 | struct inet_frag_queue *q; | ||
| 147 | int work, evicted = 0; | ||
| 148 | |||
| 149 | work = atomic_read(&f->mem) - f->ctl->low_thresh; | ||
| 150 | while (work > 0) { | ||
| 151 | read_lock(&f->lock); | ||
| 152 | if (list_empty(&f->lru_list)) { | ||
| 153 | read_unlock(&f->lock); | ||
| 154 | break; | ||
| 155 | } | ||
| 156 | |||
| 157 | q = list_first_entry(&f->lru_list, | ||
| 158 | struct inet_frag_queue, lru_list); | ||
| 159 | atomic_inc(&q->refcnt); | ||
| 160 | read_unlock(&f->lock); | ||
| 161 | |||
| 162 | spin_lock(&q->lock); | ||
| 163 | if (!(q->last_in & COMPLETE)) | ||
| 164 | inet_frag_kill(q, f); | ||
| 165 | spin_unlock(&q->lock); | ||
| 166 | |||
| 167 | if (atomic_dec_and_test(&q->refcnt)) | ||
| 168 | inet_frag_destroy(q, f, &work); | ||
| 169 | evicted++; | ||
| 170 | } | ||
| 171 | |||
| 172 | return evicted; | ||
| 173 | } | ||
| 174 | EXPORT_SYMBOL(inet_frag_evictor); | ||
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index afbf938836f5..877da3ed52e2 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c | |||
| @@ -40,7 +40,7 @@ | |||
| 40 | #include <net/route.h> | 40 | #include <net/route.h> |
| 41 | #include <net/xfrm.h> | 41 | #include <net/xfrm.h> |
| 42 | 42 | ||
| 43 | static inline int ip_forward_finish(struct sk_buff *skb) | 43 | static int ip_forward_finish(struct sk_buff *skb) |
| 44 | { | 44 | { |
| 45 | struct ip_options * opt = &(IPCB(skb)->opt); | 45 | struct ip_options * opt = &(IPCB(skb)->opt); |
| 46 | 46 | ||
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index fabb86db763b..443b3f89192f 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | #include <net/icmp.h> | 39 | #include <net/icmp.h> |
| 40 | #include <net/checksum.h> | 40 | #include <net/checksum.h> |
| 41 | #include <net/inetpeer.h> | 41 | #include <net/inetpeer.h> |
| 42 | #include <net/inet_frag.h> | ||
| 42 | #include <linux/tcp.h> | 43 | #include <linux/tcp.h> |
| 43 | #include <linux/udp.h> | 44 | #include <linux/udp.h> |
| 44 | #include <linux/inet.h> | 45 | #include <linux/inet.h> |
| @@ -49,21 +50,8 @@ | |||
| 49 | * as well. Or notify me, at least. --ANK | 50 | * as well. Or notify me, at least. --ANK |
| 50 | */ | 51 | */ |
| 51 | 52 | ||
| 52 | /* Fragment cache limits. We will commit 256K at one time. Should we | ||
| 53 | * cross that limit we will prune down to 192K. This should cope with | ||
| 54 | * even the most extreme cases without allowing an attacker to measurably | ||
| 55 | * harm machine performance. | ||
| 56 | */ | ||
| 57 | int sysctl_ipfrag_high_thresh __read_mostly = 256*1024; | ||
| 58 | int sysctl_ipfrag_low_thresh __read_mostly = 192*1024; | ||
| 59 | |||
| 60 | int sysctl_ipfrag_max_dist __read_mostly = 64; | 53 | int sysctl_ipfrag_max_dist __read_mostly = 64; |
| 61 | 54 | ||
| 62 | /* Important NOTE! Fragment queue must be destroyed before MSL expires. | ||
| 63 | * RFC791 is wrong proposing to prolongate timer each fragment arrival by TTL. | ||
| 64 | */ | ||
| 65 | int sysctl_ipfrag_time __read_mostly = IP_FRAG_TIME; | ||
| 66 | |||
| 67 | struct ipfrag_skb_cb | 55 | struct ipfrag_skb_cb |
| 68 | { | 56 | { |
| 69 | struct inet_skb_parm h; | 57 | struct inet_skb_parm h; |
| @@ -74,153 +62,102 @@ struct ipfrag_skb_cb | |||
| 74 | 62 | ||
| 75 | /* Describe an entry in the "incomplete datagrams" queue. */ | 63 | /* Describe an entry in the "incomplete datagrams" queue. */ |
| 76 | struct ipq { | 64 | struct ipq { |
| 77 | struct hlist_node list; | 65 | struct inet_frag_queue q; |
| 78 | struct list_head lru_list; /* lru list member */ | 66 | |
| 79 | u32 user; | 67 | u32 user; |
| 80 | __be32 saddr; | 68 | __be32 saddr; |
| 81 | __be32 daddr; | 69 | __be32 daddr; |
| 82 | __be16 id; | 70 | __be16 id; |
| 83 | u8 protocol; | 71 | u8 protocol; |
| 84 | u8 last_in; | ||
| 85 | #define COMPLETE 4 | ||
| 86 | #define FIRST_IN 2 | ||
| 87 | #define LAST_IN 1 | ||
| 88 | |||
| 89 | struct sk_buff *fragments; /* linked list of received fragments */ | ||
| 90 | int len; /* total length of original datagram */ | ||
| 91 | int meat; | ||
| 92 | spinlock_t lock; | ||
| 93 | atomic_t refcnt; | ||
| 94 | struct timer_list timer; /* when will this queue expire? */ | ||
| 95 | ktime_t stamp; | ||
| 96 | int iif; | 72 | int iif; |
| 97 | unsigned int rid; | 73 | unsigned int rid; |
| 98 | struct inet_peer *peer; | 74 | struct inet_peer *peer; |
| 99 | }; | 75 | }; |
| 100 | 76 | ||
| 101 | /* Hash table. */ | 77 | struct inet_frags_ctl ip4_frags_ctl __read_mostly = { |
| 78 | /* | ||
| 79 | * Fragment cache limits. We will commit 256K at one time. Should we | ||
| 80 | * cross that limit we will prune down to 192K. This should cope with | ||
| 81 | * even the most extreme cases without allowing an attacker to | ||
| 82 | * measurably harm machine performance. | ||
| 83 | */ | ||
| 84 | .high_thresh = 256 * 1024, | ||
| 85 | .low_thresh = 192 * 1024, | ||
| 102 | 86 | ||
| 103 | #define IPQ_HASHSZ 64 | 87 | /* |
| 88 | * Important NOTE! Fragment queue must be destroyed before MSL expires. | ||
| 89 | * RFC791 is wrong proposing to prolongate timer each fragment arrival | ||
| 90 | * by TTL. | ||
| 91 | */ | ||
| 92 | .timeout = IP_FRAG_TIME, | ||
| 93 | .secret_interval = 10 * 60 * HZ, | ||
| 94 | }; | ||
| 104 | 95 | ||
| 105 | /* Per-bucket lock is easy to add now. */ | 96 | static struct inet_frags ip4_frags; |
| 106 | static struct hlist_head ipq_hash[IPQ_HASHSZ]; | ||
| 107 | static DEFINE_RWLOCK(ipfrag_lock); | ||
| 108 | static u32 ipfrag_hash_rnd; | ||
| 109 | static LIST_HEAD(ipq_lru_list); | ||
| 110 | int ip_frag_nqueues = 0; | ||
| 111 | 97 | ||
| 112 | static __inline__ void __ipq_unlink(struct ipq *qp) | 98 | int ip_frag_nqueues(void) |
| 113 | { | 99 | { |
| 114 | hlist_del(&qp->list); | 100 | return ip4_frags.nqueues; |
| 115 | list_del(&qp->lru_list); | ||
| 116 | ip_frag_nqueues--; | ||
| 117 | } | 101 | } |
| 118 | 102 | ||
| 119 | static __inline__ void ipq_unlink(struct ipq *ipq) | 103 | int ip_frag_mem(void) |
| 120 | { | 104 | { |
| 121 | write_lock(&ipfrag_lock); | 105 | return atomic_read(&ip4_frags.mem); |
| 122 | __ipq_unlink(ipq); | ||
| 123 | write_unlock(&ipfrag_lock); | ||
| 124 | } | 106 | } |
| 125 | 107 | ||
| 108 | static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, | ||
| 109 | struct net_device *dev); | ||
| 110 | |||
| 126 | static unsigned int ipqhashfn(__be16 id, __be32 saddr, __be32 daddr, u8 prot) | 111 | static unsigned int ipqhashfn(__be16 id, __be32 saddr, __be32 daddr, u8 prot) |
| 127 | { | 112 | { |
| 128 | return jhash_3words((__force u32)id << 16 | prot, | 113 | return jhash_3words((__force u32)id << 16 | prot, |
| 129 | (__force u32)saddr, (__force u32)daddr, | 114 | (__force u32)saddr, (__force u32)daddr, |
| 130 | ipfrag_hash_rnd) & (IPQ_HASHSZ - 1); | 115 | ip4_frags.rnd) & (INETFRAGS_HASHSZ - 1); |
| 131 | } | 116 | } |
| 132 | 117 | ||
| 133 | static struct timer_list ipfrag_secret_timer; | 118 | static unsigned int ip4_hashfn(struct inet_frag_queue *q) |
| 134 | int sysctl_ipfrag_secret_interval __read_mostly = 10 * 60 * HZ; | ||
| 135 | |||
| 136 | static void ipfrag_secret_rebuild(unsigned long dummy) | ||
| 137 | { | 119 | { |
| 138 | unsigned long now = jiffies; | 120 | struct ipq *ipq; |
| 139 | int i; | ||
| 140 | |||
| 141 | write_lock(&ipfrag_lock); | ||
| 142 | get_random_bytes(&ipfrag_hash_rnd, sizeof(u32)); | ||
| 143 | for (i = 0; i < IPQ_HASHSZ; i++) { | ||
| 144 | struct ipq *q; | ||
| 145 | struct hlist_node *p, *n; | ||
| 146 | |||
| 147 | hlist_for_each_entry_safe(q, p, n, &ipq_hash[i], list) { | ||
| 148 | unsigned int hval = ipqhashfn(q->id, q->saddr, | ||
| 149 | q->daddr, q->protocol); | ||
| 150 | |||
| 151 | if (hval != i) { | ||
| 152 | hlist_del(&q->list); | ||
| 153 | 121 | ||
| 154 | /* Relink to new hash chain. */ | 122 | ipq = container_of(q, struct ipq, q); |
| 155 | hlist_add_head(&q->list, &ipq_hash[hval]); | 123 | return ipqhashfn(ipq->id, ipq->saddr, ipq->daddr, ipq->protocol); |
| 156 | } | ||
| 157 | } | ||
| 158 | } | ||
| 159 | write_unlock(&ipfrag_lock); | ||
| 160 | |||
| 161 | mod_timer(&ipfrag_secret_timer, now + sysctl_ipfrag_secret_interval); | ||
| 162 | } | 124 | } |
| 163 | 125 | ||
| 164 | atomic_t ip_frag_mem = ATOMIC_INIT(0); /* Memory used for fragments */ | ||
| 165 | |||
| 166 | /* Memory Tracking Functions. */ | 126 | /* Memory Tracking Functions. */ |
| 167 | static __inline__ void frag_kfree_skb(struct sk_buff *skb, int *work) | 127 | static __inline__ void frag_kfree_skb(struct sk_buff *skb, int *work) |
| 168 | { | 128 | { |
| 169 | if (work) | 129 | if (work) |
| 170 | *work -= skb->truesize; | 130 | *work -= skb->truesize; |
| 171 | atomic_sub(skb->truesize, &ip_frag_mem); | 131 | atomic_sub(skb->truesize, &ip4_frags.mem); |
| 172 | kfree_skb(skb); | 132 | kfree_skb(skb); |
| 173 | } | 133 | } |
| 174 | 134 | ||
| 175 | static __inline__ void frag_free_queue(struct ipq *qp, int *work) | 135 | static __inline__ void ip4_frag_free(struct inet_frag_queue *q) |
| 176 | { | 136 | { |
| 177 | if (work) | 137 | struct ipq *qp; |
| 178 | *work -= sizeof(struct ipq); | 138 | |
| 179 | atomic_sub(sizeof(struct ipq), &ip_frag_mem); | 139 | qp = container_of(q, struct ipq, q); |
| 140 | if (qp->peer) | ||
| 141 | inet_putpeer(qp->peer); | ||
| 180 | kfree(qp); | 142 | kfree(qp); |
| 181 | } | 143 | } |
| 182 | 144 | ||
| 183 | static __inline__ struct ipq *frag_alloc_queue(void) | 145 | static __inline__ struct ipq *frag_alloc_queue(void) |
| 184 | { | 146 | { |
| 185 | struct ipq *qp = kmalloc(sizeof(struct ipq), GFP_ATOMIC); | 147 | struct ipq *qp = kzalloc(sizeof(struct ipq), GFP_ATOMIC); |
| 186 | 148 | ||
| 187 | if (!qp) | 149 | if (!qp) |
| 188 | return NULL; | 150 | return NULL; |
| 189 | atomic_add(sizeof(struct ipq), &ip_frag_mem); | 151 | atomic_add(sizeof(struct ipq), &ip4_frags.mem); |
| 190 | return qp; | 152 | return qp; |
| 191 | } | 153 | } |
| 192 | 154 | ||
| 193 | 155 | ||
| 194 | /* Destruction primitives. */ | 156 | /* Destruction primitives. */ |
| 195 | 157 | ||
| 196 | /* Complete destruction of ipq. */ | 158 | static __inline__ void ipq_put(struct ipq *ipq) |
| 197 | static void ip_frag_destroy(struct ipq *qp, int *work) | ||
| 198 | { | ||
| 199 | struct sk_buff *fp; | ||
| 200 | |||
| 201 | BUG_TRAP(qp->last_in&COMPLETE); | ||
| 202 | BUG_TRAP(del_timer(&qp->timer) == 0); | ||
| 203 | |||
| 204 | if (qp->peer) | ||
| 205 | inet_putpeer(qp->peer); | ||
| 206 | |||
| 207 | /* Release all fragment data. */ | ||
| 208 | fp = qp->fragments; | ||
| 209 | while (fp) { | ||
| 210 | struct sk_buff *xp = fp->next; | ||
| 211 | |||
| 212 | frag_kfree_skb(fp, work); | ||
| 213 | fp = xp; | ||
| 214 | } | ||
| 215 | |||
| 216 | /* Finally, release the queue descriptor itself. */ | ||
| 217 | frag_free_queue(qp, work); | ||
| 218 | } | ||
| 219 | |||
| 220 | static __inline__ void ipq_put(struct ipq *ipq, int *work) | ||
| 221 | { | 159 | { |
| 222 | if (atomic_dec_and_test(&ipq->refcnt)) | 160 | inet_frag_put(&ipq->q, &ip4_frags); |
| 223 | ip_frag_destroy(ipq, work); | ||
| 224 | } | 161 | } |
| 225 | 162 | ||
| 226 | /* Kill ipq entry. It is not destroyed immediately, | 163 | /* Kill ipq entry. It is not destroyed immediately, |
| @@ -228,14 +165,7 @@ static __inline__ void ipq_put(struct ipq *ipq, int *work) | |||
| 228 | */ | 165 | */ |
| 229 | static void ipq_kill(struct ipq *ipq) | 166 | static void ipq_kill(struct ipq *ipq) |
| 230 | { | 167 | { |
| 231 | if (del_timer(&ipq->timer)) | 168 | inet_frag_kill(&ipq->q, &ip4_frags); |
| 232 | atomic_dec(&ipq->refcnt); | ||
| 233 | |||
| 234 | if (!(ipq->last_in & COMPLETE)) { | ||
| 235 | ipq_unlink(ipq); | ||
| 236 | atomic_dec(&ipq->refcnt); | ||
| 237 | ipq->last_in |= COMPLETE; | ||
| 238 | } | ||
| 239 | } | 169 | } |
| 240 | 170 | ||
| 241 | /* Memory limiting on fragments. Evictor trashes the oldest | 171 | /* Memory limiting on fragments. Evictor trashes the oldest |
| @@ -243,33 +173,11 @@ static void ipq_kill(struct ipq *ipq) | |||
| 243 | */ | 173 | */ |
| 244 | static void ip_evictor(void) | 174 | static void ip_evictor(void) |
| 245 | { | 175 | { |
| 246 | struct ipq *qp; | 176 | int evicted; |
| 247 | struct list_head *tmp; | ||
| 248 | int work; | ||
| 249 | |||
| 250 | work = atomic_read(&ip_frag_mem) - sysctl_ipfrag_low_thresh; | ||
| 251 | if (work <= 0) | ||
| 252 | return; | ||
| 253 | |||
| 254 | while (work > 0) { | ||
| 255 | read_lock(&ipfrag_lock); | ||
| 256 | if (list_empty(&ipq_lru_list)) { | ||
| 257 | read_unlock(&ipfrag_lock); | ||
| 258 | return; | ||
| 259 | } | ||
| 260 | tmp = ipq_lru_list.next; | ||
| 261 | qp = list_entry(tmp, struct ipq, lru_list); | ||
| 262 | atomic_inc(&qp->refcnt); | ||
| 263 | read_unlock(&ipfrag_lock); | ||
| 264 | 177 | ||
| 265 | spin_lock(&qp->lock); | 178 | evicted = inet_frag_evictor(&ip4_frags); |
| 266 | if (!(qp->last_in&COMPLETE)) | 179 | if (evicted) |
| 267 | ipq_kill(qp); | 180 | IP_ADD_STATS_BH(IPSTATS_MIB_REASMFAILS, evicted); |
| 268 | spin_unlock(&qp->lock); | ||
| 269 | |||
| 270 | ipq_put(qp, &work); | ||
| 271 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | ||
| 272 | } | ||
| 273 | } | 181 | } |
| 274 | 182 | ||
| 275 | /* | 183 | /* |
| @@ -279,9 +187,9 @@ static void ip_expire(unsigned long arg) | |||
| 279 | { | 187 | { |
| 280 | struct ipq *qp = (struct ipq *) arg; | 188 | struct ipq *qp = (struct ipq *) arg; |
| 281 | 189 | ||
| 282 | spin_lock(&qp->lock); | 190 | spin_lock(&qp->q.lock); |
| 283 | 191 | ||
| 284 | if (qp->last_in & COMPLETE) | 192 | if (qp->q.last_in & COMPLETE) |
| 285 | goto out; | 193 | goto out; |
| 286 | 194 | ||
| 287 | ipq_kill(qp); | 195 | ipq_kill(qp); |
| @@ -289,8 +197,8 @@ static void ip_expire(unsigned long arg) | |||
| 289 | IP_INC_STATS_BH(IPSTATS_MIB_REASMTIMEOUT); | 197 | IP_INC_STATS_BH(IPSTATS_MIB_REASMTIMEOUT); |
| 290 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 198 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); |
| 291 | 199 | ||
| 292 | if ((qp->last_in&FIRST_IN) && qp->fragments != NULL) { | 200 | if ((qp->q.last_in&FIRST_IN) && qp->q.fragments != NULL) { |
| 293 | struct sk_buff *head = qp->fragments; | 201 | struct sk_buff *head = qp->q.fragments; |
| 294 | /* Send an ICMP "Fragment Reassembly Timeout" message. */ | 202 | /* Send an ICMP "Fragment Reassembly Timeout" message. */ |
| 295 | if ((head->dev = dev_get_by_index(&init_net, qp->iif)) != NULL) { | 203 | if ((head->dev = dev_get_by_index(&init_net, qp->iif)) != NULL) { |
| 296 | icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); | 204 | icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); |
| @@ -298,8 +206,8 @@ static void ip_expire(unsigned long arg) | |||
| 298 | } | 206 | } |
| 299 | } | 207 | } |
| 300 | out: | 208 | out: |
| 301 | spin_unlock(&qp->lock); | 209 | spin_unlock(&qp->q.lock); |
| 302 | ipq_put(qp, NULL); | 210 | ipq_put(qp); |
| 303 | } | 211 | } |
| 304 | 212 | ||
| 305 | /* Creation primitives. */ | 213 | /* Creation primitives. */ |
| @@ -312,7 +220,7 @@ static struct ipq *ip_frag_intern(struct ipq *qp_in) | |||
| 312 | #endif | 220 | #endif |
| 313 | unsigned int hash; | 221 | unsigned int hash; |
| 314 | 222 | ||
| 315 | write_lock(&ipfrag_lock); | 223 | write_lock(&ip4_frags.lock); |
| 316 | hash = ipqhashfn(qp_in->id, qp_in->saddr, qp_in->daddr, | 224 | hash = ipqhashfn(qp_in->id, qp_in->saddr, qp_in->daddr, |
| 317 | qp_in->protocol); | 225 | qp_in->protocol); |
| 318 | #ifdef CONFIG_SMP | 226 | #ifdef CONFIG_SMP |
| @@ -320,31 +228,31 @@ static struct ipq *ip_frag_intern(struct ipq *qp_in) | |||
| 320 | * such entry could be created on other cpu, while we | 228 | * such entry could be created on other cpu, while we |
| 321 | * promoted read lock to write lock. | 229 | * promoted read lock to write lock. |
| 322 | */ | 230 | */ |
| 323 | hlist_for_each_entry(qp, n, &ipq_hash[hash], list) { | 231 | hlist_for_each_entry(qp, n, &ip4_frags.hash[hash], q.list) { |
| 324 | if (qp->id == qp_in->id && | 232 | if (qp->id == qp_in->id && |
| 325 | qp->saddr == qp_in->saddr && | 233 | qp->saddr == qp_in->saddr && |
| 326 | qp->daddr == qp_in->daddr && | 234 | qp->daddr == qp_in->daddr && |
| 327 | qp->protocol == qp_in->protocol && | 235 | qp->protocol == qp_in->protocol && |
| 328 | qp->user == qp_in->user) { | 236 | qp->user == qp_in->user) { |
| 329 | atomic_inc(&qp->refcnt); | 237 | atomic_inc(&qp->q.refcnt); |
| 330 | write_unlock(&ipfrag_lock); | 238 | write_unlock(&ip4_frags.lock); |
| 331 | qp_in->last_in |= COMPLETE; | 239 | qp_in->q.last_in |= COMPLETE; |
| 332 | ipq_put(qp_in, NULL); | 240 | ipq_put(qp_in); |
| 333 | return qp; | 241 | return qp; |
| 334 | } | 242 | } |
| 335 | } | 243 | } |
| 336 | #endif | 244 | #endif |
| 337 | qp = qp_in; | 245 | qp = qp_in; |
| 338 | 246 | ||
| 339 | if (!mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time)) | 247 | if (!mod_timer(&qp->q.timer, jiffies + ip4_frags_ctl.timeout)) |
| 340 | atomic_inc(&qp->refcnt); | 248 | atomic_inc(&qp->q.refcnt); |
| 341 | 249 | ||
| 342 | atomic_inc(&qp->refcnt); | 250 | atomic_inc(&qp->q.refcnt); |
| 343 | hlist_add_head(&qp->list, &ipq_hash[hash]); | 251 | hlist_add_head(&qp->q.list, &ip4_frags.hash[hash]); |
| 344 | INIT_LIST_HEAD(&qp->lru_list); | 252 | INIT_LIST_HEAD(&qp->q.lru_list); |
| 345 | list_add_tail(&qp->lru_list, &ipq_lru_list); | 253 | list_add_tail(&qp->q.lru_list, &ip4_frags.lru_list); |
| 346 | ip_frag_nqueues++; | 254 | ip4_frags.nqueues++; |
| 347 | write_unlock(&ipfrag_lock); | 255 | write_unlock(&ip4_frags.lock); |
| 348 | return qp; | 256 | return qp; |
| 349 | } | 257 | } |
| 350 | 258 | ||
| @@ -357,23 +265,18 @@ static struct ipq *ip_frag_create(struct iphdr *iph, u32 user) | |||
| 357 | goto out_nomem; | 265 | goto out_nomem; |
| 358 | 266 | ||
| 359 | qp->protocol = iph->protocol; | 267 | qp->protocol = iph->protocol; |
| 360 | qp->last_in = 0; | ||
| 361 | qp->id = iph->id; | 268 | qp->id = iph->id; |
| 362 | qp->saddr = iph->saddr; | 269 | qp->saddr = iph->saddr; |
| 363 | qp->daddr = iph->daddr; | 270 | qp->daddr = iph->daddr; |
| 364 | qp->user = user; | 271 | qp->user = user; |
| 365 | qp->len = 0; | ||
| 366 | qp->meat = 0; | ||
| 367 | qp->fragments = NULL; | ||
| 368 | qp->iif = 0; | ||
| 369 | qp->peer = sysctl_ipfrag_max_dist ? inet_getpeer(iph->saddr, 1) : NULL; | 272 | qp->peer = sysctl_ipfrag_max_dist ? inet_getpeer(iph->saddr, 1) : NULL; |
| 370 | 273 | ||
| 371 | /* Initialize a timer for this entry. */ | 274 | /* Initialize a timer for this entry. */ |
| 372 | init_timer(&qp->timer); | 275 | init_timer(&qp->q.timer); |
| 373 | qp->timer.data = (unsigned long) qp; /* pointer to queue */ | 276 | qp->q.timer.data = (unsigned long) qp; /* pointer to queue */ |
| 374 | qp->timer.function = ip_expire; /* expire function */ | 277 | qp->q.timer.function = ip_expire; /* expire function */ |
| 375 | spin_lock_init(&qp->lock); | 278 | spin_lock_init(&qp->q.lock); |
| 376 | atomic_set(&qp->refcnt, 1); | 279 | atomic_set(&qp->q.refcnt, 1); |
| 377 | 280 | ||
| 378 | return ip_frag_intern(qp); | 281 | return ip_frag_intern(qp); |
| 379 | 282 | ||
| @@ -395,20 +298,20 @@ static inline struct ipq *ip_find(struct iphdr *iph, u32 user) | |||
| 395 | struct ipq *qp; | 298 | struct ipq *qp; |
| 396 | struct hlist_node *n; | 299 | struct hlist_node *n; |
| 397 | 300 | ||
| 398 | read_lock(&ipfrag_lock); | 301 | read_lock(&ip4_frags.lock); |
| 399 | hash = ipqhashfn(id, saddr, daddr, protocol); | 302 | hash = ipqhashfn(id, saddr, daddr, protocol); |
| 400 | hlist_for_each_entry(qp, n, &ipq_hash[hash], list) { | 303 | hlist_for_each_entry(qp, n, &ip4_frags.hash[hash], q.list) { |
| 401 | if (qp->id == id && | 304 | if (qp->id == id && |
| 402 | qp->saddr == saddr && | 305 | qp->saddr == saddr && |
| 403 | qp->daddr == daddr && | 306 | qp->daddr == daddr && |
| 404 | qp->protocol == protocol && | 307 | qp->protocol == protocol && |
| 405 | qp->user == user) { | 308 | qp->user == user) { |
| 406 | atomic_inc(&qp->refcnt); | 309 | atomic_inc(&qp->q.refcnt); |
| 407 | read_unlock(&ipfrag_lock); | 310 | read_unlock(&ip4_frags.lock); |
| 408 | return qp; | 311 | return qp; |
| 409 | } | 312 | } |
| 410 | } | 313 | } |
| 411 | read_unlock(&ipfrag_lock); | 314 | read_unlock(&ip4_frags.lock); |
| 412 | 315 | ||
| 413 | return ip_frag_create(iph, user); | 316 | return ip_frag_create(iph, user); |
| 414 | } | 317 | } |
| @@ -429,7 +332,7 @@ static inline int ip_frag_too_far(struct ipq *qp) | |||
| 429 | end = atomic_inc_return(&peer->rid); | 332 | end = atomic_inc_return(&peer->rid); |
| 430 | qp->rid = end; | 333 | qp->rid = end; |
| 431 | 334 | ||
| 432 | rc = qp->fragments && (end - start) > max; | 335 | rc = qp->q.fragments && (end - start) > max; |
| 433 | 336 | ||
| 434 | if (rc) { | 337 | if (rc) { |
| 435 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 338 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); |
| @@ -442,39 +345,42 @@ static int ip_frag_reinit(struct ipq *qp) | |||
| 442 | { | 345 | { |
| 443 | struct sk_buff *fp; | 346 | struct sk_buff *fp; |
| 444 | 347 | ||
| 445 | if (!mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time)) { | 348 | if (!mod_timer(&qp->q.timer, jiffies + ip4_frags_ctl.timeout)) { |
| 446 | atomic_inc(&qp->refcnt); | 349 | atomic_inc(&qp->q.refcnt); |
| 447 | return -ETIMEDOUT; | 350 | return -ETIMEDOUT; |
| 448 | } | 351 | } |
| 449 | 352 | ||
| 450 | fp = qp->fragments; | 353 | fp = qp->q.fragments; |
| 451 | do { | 354 | do { |
| 452 | struct sk_buff *xp = fp->next; | 355 | struct sk_buff *xp = fp->next; |
| 453 | frag_kfree_skb(fp, NULL); | 356 | frag_kfree_skb(fp, NULL); |
| 454 | fp = xp; | 357 | fp = xp; |
| 455 | } while (fp); | 358 | } while (fp); |
| 456 | 359 | ||
| 457 | qp->last_in = 0; | 360 | qp->q.last_in = 0; |
| 458 | qp->len = 0; | 361 | qp->q.len = 0; |
| 459 | qp->meat = 0; | 362 | qp->q.meat = 0; |
| 460 | qp->fragments = NULL; | 363 | qp->q.fragments = NULL; |
| 461 | qp->iif = 0; | 364 | qp->iif = 0; |
| 462 | 365 | ||
| 463 | return 0; | 366 | return 0; |
| 464 | } | 367 | } |
| 465 | 368 | ||
| 466 | /* Add new segment to existing queue. */ | 369 | /* Add new segment to existing queue. */ |
| 467 | static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | 370 | static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb) |
| 468 | { | 371 | { |
| 469 | struct sk_buff *prev, *next; | 372 | struct sk_buff *prev, *next; |
| 373 | struct net_device *dev; | ||
| 470 | int flags, offset; | 374 | int flags, offset; |
| 471 | int ihl, end; | 375 | int ihl, end; |
| 376 | int err = -ENOENT; | ||
| 472 | 377 | ||
| 473 | if (qp->last_in & COMPLETE) | 378 | if (qp->q.last_in & COMPLETE) |
| 474 | goto err; | 379 | goto err; |
| 475 | 380 | ||
| 476 | if (!(IPCB(skb)->flags & IPSKB_FRAG_COMPLETE) && | 381 | if (!(IPCB(skb)->flags & IPSKB_FRAG_COMPLETE) && |
| 477 | unlikely(ip_frag_too_far(qp)) && unlikely(ip_frag_reinit(qp))) { | 382 | unlikely(ip_frag_too_far(qp)) && |
| 383 | unlikely(err = ip_frag_reinit(qp))) { | ||
| 478 | ipq_kill(qp); | 384 | ipq_kill(qp); |
| 479 | goto err; | 385 | goto err; |
| 480 | } | 386 | } |
| @@ -487,36 +393,40 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | |||
| 487 | 393 | ||
| 488 | /* Determine the position of this fragment. */ | 394 | /* Determine the position of this fragment. */ |
| 489 | end = offset + skb->len - ihl; | 395 | end = offset + skb->len - ihl; |
| 396 | err = -EINVAL; | ||
| 490 | 397 | ||
| 491 | /* Is this the final fragment? */ | 398 | /* Is this the final fragment? */ |
| 492 | if ((flags & IP_MF) == 0) { | 399 | if ((flags & IP_MF) == 0) { |
| 493 | /* If we already have some bits beyond end | 400 | /* If we already have some bits beyond end |
| 494 | * or have different end, the segment is corrrupted. | 401 | * or have different end, the segment is corrrupted. |
| 495 | */ | 402 | */ |
| 496 | if (end < qp->len || | 403 | if (end < qp->q.len || |
| 497 | ((qp->last_in & LAST_IN) && end != qp->len)) | 404 | ((qp->q.last_in & LAST_IN) && end != qp->q.len)) |
| 498 | goto err; | 405 | goto err; |
| 499 | qp->last_in |= LAST_IN; | 406 | qp->q.last_in |= LAST_IN; |
| 500 | qp->len = end; | 407 | qp->q.len = end; |
| 501 | } else { | 408 | } else { |
| 502 | if (end&7) { | 409 | if (end&7) { |
| 503 | end &= ~7; | 410 | end &= ~7; |
| 504 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) | 411 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) |
| 505 | skb->ip_summed = CHECKSUM_NONE; | 412 | skb->ip_summed = CHECKSUM_NONE; |
| 506 | } | 413 | } |
| 507 | if (end > qp->len) { | 414 | if (end > qp->q.len) { |
| 508 | /* Some bits beyond end -> corruption. */ | 415 | /* Some bits beyond end -> corruption. */ |
| 509 | if (qp->last_in & LAST_IN) | 416 | if (qp->q.last_in & LAST_IN) |
| 510 | goto err; | 417 | goto err; |
| 511 | qp->len = end; | 418 | qp->q.len = end; |
| 512 | } | 419 | } |
| 513 | } | 420 | } |
| 514 | if (end == offset) | 421 | if (end == offset) |
| 515 | goto err; | 422 | goto err; |
| 516 | 423 | ||
| 424 | err = -ENOMEM; | ||
| 517 | if (pskb_pull(skb, ihl) == NULL) | 425 | if (pskb_pull(skb, ihl) == NULL) |
| 518 | goto err; | 426 | goto err; |
| 519 | if (pskb_trim_rcsum(skb, end-offset)) | 427 | |
| 428 | err = pskb_trim_rcsum(skb, end - offset); | ||
| 429 | if (err) | ||
| 520 | goto err; | 430 | goto err; |
| 521 | 431 | ||
| 522 | /* Find out which fragments are in front and at the back of us | 432 | /* Find out which fragments are in front and at the back of us |
| @@ -524,7 +434,7 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | |||
| 524 | * this fragment, right? | 434 | * this fragment, right? |
| 525 | */ | 435 | */ |
| 526 | prev = NULL; | 436 | prev = NULL; |
| 527 | for (next = qp->fragments; next != NULL; next = next->next) { | 437 | for (next = qp->q.fragments; next != NULL; next = next->next) { |
| 528 | if (FRAG_CB(next)->offset >= offset) | 438 | if (FRAG_CB(next)->offset >= offset) |
| 529 | break; /* bingo! */ | 439 | break; /* bingo! */ |
| 530 | prev = next; | 440 | prev = next; |
| @@ -539,8 +449,10 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | |||
| 539 | 449 | ||
| 540 | if (i > 0) { | 450 | if (i > 0) { |
| 541 | offset += i; | 451 | offset += i; |
| 452 | err = -EINVAL; | ||
| 542 | if (end <= offset) | 453 | if (end <= offset) |
| 543 | goto err; | 454 | goto err; |
| 455 | err = -ENOMEM; | ||
| 544 | if (!pskb_pull(skb, i)) | 456 | if (!pskb_pull(skb, i)) |
| 545 | goto err; | 457 | goto err; |
| 546 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) | 458 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) |
| @@ -548,6 +460,8 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | |||
| 548 | } | 460 | } |
| 549 | } | 461 | } |
| 550 | 462 | ||
| 463 | err = -ENOMEM; | ||
| 464 | |||
| 551 | while (next && FRAG_CB(next)->offset < end) { | 465 | while (next && FRAG_CB(next)->offset < end) { |
| 552 | int i = end - FRAG_CB(next)->offset; /* overlap is 'i' bytes */ | 466 | int i = end - FRAG_CB(next)->offset; /* overlap is 'i' bytes */ |
| 553 | 467 | ||
| @@ -558,7 +472,7 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | |||
| 558 | if (!pskb_pull(next, i)) | 472 | if (!pskb_pull(next, i)) |
| 559 | goto err; | 473 | goto err; |
| 560 | FRAG_CB(next)->offset += i; | 474 | FRAG_CB(next)->offset += i; |
| 561 | qp->meat -= i; | 475 | qp->q.meat -= i; |
| 562 | if (next->ip_summed != CHECKSUM_UNNECESSARY) | 476 | if (next->ip_summed != CHECKSUM_UNNECESSARY) |
| 563 | next->ip_summed = CHECKSUM_NONE; | 477 | next->ip_summed = CHECKSUM_NONE; |
| 564 | break; | 478 | break; |
| @@ -573,9 +487,9 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | |||
| 573 | if (prev) | 487 | if (prev) |
| 574 | prev->next = next; | 488 | prev->next = next; |
| 575 | else | 489 | else |
| 576 | qp->fragments = next; | 490 | qp->q.fragments = next; |
| 577 | 491 | ||
| 578 | qp->meat -= free_it->len; | 492 | qp->q.meat -= free_it->len; |
| 579 | frag_kfree_skb(free_it, NULL); | 493 | frag_kfree_skb(free_it, NULL); |
| 580 | } | 494 | } |
| 581 | } | 495 | } |
| @@ -587,50 +501,77 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | |||
| 587 | if (prev) | 501 | if (prev) |
| 588 | prev->next = skb; | 502 | prev->next = skb; |
| 589 | else | 503 | else |
| 590 | qp->fragments = skb; | 504 | qp->q.fragments = skb; |
| 591 | 505 | ||
| 592 | if (skb->dev) | 506 | dev = skb->dev; |
| 593 | qp->iif = skb->dev->ifindex; | 507 | if (dev) { |
| 594 | skb->dev = NULL; | 508 | qp->iif = dev->ifindex; |
| 595 | qp->stamp = skb->tstamp; | 509 | skb->dev = NULL; |
| 596 | qp->meat += skb->len; | 510 | } |
| 597 | atomic_add(skb->truesize, &ip_frag_mem); | 511 | qp->q.stamp = skb->tstamp; |
| 512 | qp->q.meat += skb->len; | ||
| 513 | atomic_add(skb->truesize, &ip4_frags.mem); | ||
| 598 | if (offset == 0) | 514 | if (offset == 0) |
| 599 | qp->last_in |= FIRST_IN; | 515 | qp->q.last_in |= FIRST_IN; |
| 600 | 516 | ||
| 601 | write_lock(&ipfrag_lock); | 517 | if (qp->q.last_in == (FIRST_IN | LAST_IN) && qp->q.meat == qp->q.len) |
| 602 | list_move_tail(&qp->lru_list, &ipq_lru_list); | 518 | return ip_frag_reasm(qp, prev, dev); |
| 603 | write_unlock(&ipfrag_lock); | ||
| 604 | 519 | ||
| 605 | return; | 520 | write_lock(&ip4_frags.lock); |
| 521 | list_move_tail(&qp->q.lru_list, &ip4_frags.lru_list); | ||
| 522 | write_unlock(&ip4_frags.lock); | ||
| 523 | return -EINPROGRESS; | ||
| 606 | 524 | ||
| 607 | err: | 525 | err: |
| 608 | kfree_skb(skb); | 526 | kfree_skb(skb); |
| 527 | return err; | ||
| 609 | } | 528 | } |
| 610 | 529 | ||
| 611 | 530 | ||
| 612 | /* Build a new IP datagram from all its fragments. */ | 531 | /* Build a new IP datagram from all its fragments. */ |
| 613 | 532 | ||
| 614 | static struct sk_buff *ip_frag_reasm(struct ipq *qp, struct net_device *dev) | 533 | static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, |
| 534 | struct net_device *dev) | ||
| 615 | { | 535 | { |
| 616 | struct iphdr *iph; | 536 | struct iphdr *iph; |
| 617 | struct sk_buff *fp, *head = qp->fragments; | 537 | struct sk_buff *fp, *head = qp->q.fragments; |
| 618 | int len; | 538 | int len; |
| 619 | int ihlen; | 539 | int ihlen; |
| 540 | int err; | ||
| 620 | 541 | ||
| 621 | ipq_kill(qp); | 542 | ipq_kill(qp); |
| 622 | 543 | ||
| 544 | /* Make the one we just received the head. */ | ||
| 545 | if (prev) { | ||
| 546 | head = prev->next; | ||
| 547 | fp = skb_clone(head, GFP_ATOMIC); | ||
| 548 | |||
| 549 | if (!fp) | ||
| 550 | goto out_nomem; | ||
| 551 | |||
| 552 | fp->next = head->next; | ||
| 553 | prev->next = fp; | ||
| 554 | |||
| 555 | skb_morph(head, qp->q.fragments); | ||
| 556 | head->next = qp->q.fragments->next; | ||
| 557 | |||
| 558 | kfree_skb(qp->q.fragments); | ||
| 559 | qp->q.fragments = head; | ||
| 560 | } | ||
| 561 | |||
| 623 | BUG_TRAP(head != NULL); | 562 | BUG_TRAP(head != NULL); |
| 624 | BUG_TRAP(FRAG_CB(head)->offset == 0); | 563 | BUG_TRAP(FRAG_CB(head)->offset == 0); |
| 625 | 564 | ||
| 626 | /* Allocate a new buffer for the datagram. */ | 565 | /* Allocate a new buffer for the datagram. */ |
| 627 | ihlen = ip_hdrlen(head); | 566 | ihlen = ip_hdrlen(head); |
| 628 | len = ihlen + qp->len; | 567 | len = ihlen + qp->q.len; |
| 629 | 568 | ||
| 569 | err = -E2BIG; | ||
| 630 | if (len > 65535) | 570 | if (len > 65535) |
| 631 | goto out_oversize; | 571 | goto out_oversize; |
| 632 | 572 | ||
| 633 | /* Head of list must not be cloned. */ | 573 | /* Head of list must not be cloned. */ |
| 574 | err = -ENOMEM; | ||
| 634 | if (skb_cloned(head) && pskb_expand_head(head, 0, 0, GFP_ATOMIC)) | 575 | if (skb_cloned(head) && pskb_expand_head(head, 0, 0, GFP_ATOMIC)) |
| 635 | goto out_nomem; | 576 | goto out_nomem; |
| 636 | 577 | ||
| @@ -654,12 +595,12 @@ static struct sk_buff *ip_frag_reasm(struct ipq *qp, struct net_device *dev) | |||
| 654 | head->len -= clone->len; | 595 | head->len -= clone->len; |
| 655 | clone->csum = 0; | 596 | clone->csum = 0; |
| 656 | clone->ip_summed = head->ip_summed; | 597 | clone->ip_summed = head->ip_summed; |
| 657 | atomic_add(clone->truesize, &ip_frag_mem); | 598 | atomic_add(clone->truesize, &ip4_frags.mem); |
| 658 | } | 599 | } |
| 659 | 600 | ||
| 660 | skb_shinfo(head)->frag_list = head->next; | 601 | skb_shinfo(head)->frag_list = head->next; |
| 661 | skb_push(head, head->data - skb_network_header(head)); | 602 | skb_push(head, head->data - skb_network_header(head)); |
| 662 | atomic_sub(head->truesize, &ip_frag_mem); | 603 | atomic_sub(head->truesize, &ip4_frags.mem); |
| 663 | 604 | ||
| 664 | for (fp=head->next; fp; fp = fp->next) { | 605 | for (fp=head->next; fp; fp = fp->next) { |
| 665 | head->data_len += fp->len; | 606 | head->data_len += fp->len; |
| @@ -669,19 +610,19 @@ static struct sk_buff *ip_frag_reasm(struct ipq *qp, struct net_device *dev) | |||
| 669 | else if (head->ip_summed == CHECKSUM_COMPLETE) | 610 | else if (head->ip_summed == CHECKSUM_COMPLETE) |
| 670 | head->csum = csum_add(head->csum, fp->csum); | 611 | head->csum = csum_add(head->csum, fp->csum); |
| 671 | head->truesize += fp->truesize; | 612 | head->truesize += fp->truesize; |
| 672 | atomic_sub(fp->truesize, &ip_frag_mem); | 613 | atomic_sub(fp->truesize, &ip4_frags.mem); |
| 673 | } | 614 | } |
| 674 | 615 | ||
| 675 | head->next = NULL; | 616 | head->next = NULL; |
| 676 | head->dev = dev; | 617 | head->dev = dev; |
| 677 | head->tstamp = qp->stamp; | 618 | head->tstamp = qp->q.stamp; |
| 678 | 619 | ||
| 679 | iph = ip_hdr(head); | 620 | iph = ip_hdr(head); |
| 680 | iph->frag_off = 0; | 621 | iph->frag_off = 0; |
| 681 | iph->tot_len = htons(len); | 622 | iph->tot_len = htons(len); |
| 682 | IP_INC_STATS_BH(IPSTATS_MIB_REASMOKS); | 623 | IP_INC_STATS_BH(IPSTATS_MIB_REASMOKS); |
| 683 | qp->fragments = NULL; | 624 | qp->q.fragments = NULL; |
| 684 | return head; | 625 | return 0; |
| 685 | 626 | ||
| 686 | out_nomem: | 627 | out_nomem: |
| 687 | LIMIT_NETDEBUG(KERN_ERR "IP: queue_glue: no memory for gluing " | 628 | LIMIT_NETDEBUG(KERN_ERR "IP: queue_glue: no memory for gluing " |
| @@ -694,54 +635,46 @@ out_oversize: | |||
| 694 | NIPQUAD(qp->saddr)); | 635 | NIPQUAD(qp->saddr)); |
| 695 | out_fail: | 636 | out_fail: |
| 696 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 637 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); |
| 697 | return NULL; | 638 | return err; |
| 698 | } | 639 | } |
| 699 | 640 | ||
| 700 | /* Process an incoming IP datagram fragment. */ | 641 | /* Process an incoming IP datagram fragment. */ |
| 701 | struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user) | 642 | int ip_defrag(struct sk_buff *skb, u32 user) |
| 702 | { | 643 | { |
| 703 | struct ipq *qp; | 644 | struct ipq *qp; |
| 704 | struct net_device *dev; | ||
| 705 | 645 | ||
| 706 | IP_INC_STATS_BH(IPSTATS_MIB_REASMREQDS); | 646 | IP_INC_STATS_BH(IPSTATS_MIB_REASMREQDS); |
| 707 | 647 | ||
| 708 | /* Start by cleaning up the memory. */ | 648 | /* Start by cleaning up the memory. */ |
| 709 | if (atomic_read(&ip_frag_mem) > sysctl_ipfrag_high_thresh) | 649 | if (atomic_read(&ip4_frags.mem) > ip4_frags_ctl.high_thresh) |
| 710 | ip_evictor(); | 650 | ip_evictor(); |
| 711 | 651 | ||
| 712 | dev = skb->dev; | ||
| 713 | |||
| 714 | /* Lookup (or create) queue header */ | 652 | /* Lookup (or create) queue header */ |
| 715 | if ((qp = ip_find(ip_hdr(skb), user)) != NULL) { | 653 | if ((qp = ip_find(ip_hdr(skb), user)) != NULL) { |
| 716 | struct sk_buff *ret = NULL; | 654 | int ret; |
| 717 | |||
| 718 | spin_lock(&qp->lock); | ||
| 719 | 655 | ||
| 720 | ip_frag_queue(qp, skb); | 656 | spin_lock(&qp->q.lock); |
| 721 | 657 | ||
| 722 | if (qp->last_in == (FIRST_IN|LAST_IN) && | 658 | ret = ip_frag_queue(qp, skb); |
| 723 | qp->meat == qp->len) | ||
| 724 | ret = ip_frag_reasm(qp, dev); | ||
| 725 | 659 | ||
| 726 | spin_unlock(&qp->lock); | 660 | spin_unlock(&qp->q.lock); |
| 727 | ipq_put(qp, NULL); | 661 | ipq_put(qp); |
| 728 | return ret; | 662 | return ret; |
| 729 | } | 663 | } |
| 730 | 664 | ||
| 731 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 665 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); |
| 732 | kfree_skb(skb); | 666 | kfree_skb(skb); |
| 733 | return NULL; | 667 | return -ENOMEM; |
| 734 | } | 668 | } |
| 735 | 669 | ||
| 736 | void __init ipfrag_init(void) | 670 | void __init ipfrag_init(void) |
| 737 | { | 671 | { |
| 738 | ipfrag_hash_rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^ | 672 | ip4_frags.ctl = &ip4_frags_ctl; |
| 739 | (jiffies ^ (jiffies >> 6))); | 673 | ip4_frags.hashfn = ip4_hashfn; |
| 740 | 674 | ip4_frags.destructor = ip4_frag_free; | |
| 741 | init_timer(&ipfrag_secret_timer); | 675 | ip4_frags.skb_free = NULL; |
| 742 | ipfrag_secret_timer.function = ipfrag_secret_rebuild; | 676 | ip4_frags.qsize = sizeof(struct ipq); |
| 743 | ipfrag_secret_timer.expires = jiffies + sysctl_ipfrag_secret_interval; | 677 | inet_frags_init(&ip4_frags); |
| 744 | add_timer(&ipfrag_secret_timer); | ||
| 745 | } | 678 | } |
| 746 | 679 | ||
| 747 | EXPORT_SYMBOL(ip_defrag); | 680 | EXPORT_SYMBOL(ip_defrag); |
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 41d8964591e7..168c871fcd79 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c | |||
| @@ -172,8 +172,7 @@ int ip_call_ra_chain(struct sk_buff *skb) | |||
| 172 | (!sk->sk_bound_dev_if || | 172 | (!sk->sk_bound_dev_if || |
| 173 | sk->sk_bound_dev_if == skb->dev->ifindex)) { | 173 | sk->sk_bound_dev_if == skb->dev->ifindex)) { |
| 174 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { | 174 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { |
| 175 | skb = ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN); | 175 | if (ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN)) { |
| 176 | if (skb == NULL) { | ||
| 177 | read_unlock(&ip_ra_lock); | 176 | read_unlock(&ip_ra_lock); |
| 178 | return 1; | 177 | return 1; |
| 179 | } | 178 | } |
| @@ -196,7 +195,7 @@ int ip_call_ra_chain(struct sk_buff *skb) | |||
| 196 | return 0; | 195 | return 0; |
| 197 | } | 196 | } |
| 198 | 197 | ||
| 199 | static inline int ip_local_deliver_finish(struct sk_buff *skb) | 198 | static int ip_local_deliver_finish(struct sk_buff *skb) |
| 200 | { | 199 | { |
| 201 | __skb_pull(skb, ip_hdrlen(skb)); | 200 | __skb_pull(skb, ip_hdrlen(skb)); |
| 202 | 201 | ||
| @@ -265,8 +264,7 @@ int ip_local_deliver(struct sk_buff *skb) | |||
| 265 | */ | 264 | */ |
| 266 | 265 | ||
| 267 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { | 266 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { |
| 268 | skb = ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER); | 267 | if (ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER)) |
| 269 | if (!skb) | ||
| 270 | return 0; | 268 | return 0; |
| 271 | } | 269 | } |
| 272 | 270 | ||
| @@ -326,7 +324,7 @@ drop: | |||
| 326 | return -1; | 324 | return -1; |
| 327 | } | 325 | } |
| 328 | 326 | ||
| 329 | static inline int ip_rcv_finish(struct sk_buff *skb) | 327 | static int ip_rcv_finish(struct sk_buff *skb) |
| 330 | { | 328 | { |
| 331 | const struct iphdr *iph = ip_hdr(skb); | 329 | const struct iphdr *iph = ip_hdr(skb); |
| 332 | struct rtable *rt; | 330 | struct rtable *rt; |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 699f06781fd8..f508835ba713 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
| @@ -202,7 +202,7 @@ static inline int ip_skb_dst_mtu(struct sk_buff *skb) | |||
| 202 | skb->dst->dev->mtu : dst_mtu(skb->dst); | 202 | skb->dst->dev->mtu : dst_mtu(skb->dst); |
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | static inline int ip_finish_output(struct sk_buff *skb) | 205 | static int ip_finish_output(struct sk_buff *skb) |
| 206 | { | 206 | { |
| 207 | #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) | 207 | #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) |
| 208 | /* Policy lookup after SNAT yielded a new policy */ | 208 | /* Policy lookup after SNAT yielded a new policy */ |
diff --git a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c index 341474eefa55..664cb8e97c1c 100644 --- a/net/ipv4/ipvs/ip_vs_app.c +++ b/net/ipv4/ipvs/ip_vs_app.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <linux/skbuff.h> | 25 | #include <linux/skbuff.h> |
| 26 | #include <linux/in.h> | 26 | #include <linux/in.h> |
| 27 | #include <linux/ip.h> | 27 | #include <linux/ip.h> |
| 28 | #include <linux/netfilter.h> | ||
| 28 | #include <net/net_namespace.h> | 29 | #include <net/net_namespace.h> |
| 29 | #include <net/protocol.h> | 30 | #include <net/protocol.h> |
| 30 | #include <net/tcp.h> | 31 | #include <net/tcp.h> |
| @@ -328,18 +329,18 @@ static inline void vs_seq_update(struct ip_vs_conn *cp, struct ip_vs_seq *vseq, | |||
| 328 | spin_unlock(&cp->lock); | 329 | spin_unlock(&cp->lock); |
| 329 | } | 330 | } |
| 330 | 331 | ||
| 331 | static inline int app_tcp_pkt_out(struct ip_vs_conn *cp, struct sk_buff **pskb, | 332 | static inline int app_tcp_pkt_out(struct ip_vs_conn *cp, struct sk_buff *skb, |
| 332 | struct ip_vs_app *app) | 333 | struct ip_vs_app *app) |
| 333 | { | 334 | { |
| 334 | int diff; | 335 | int diff; |
| 335 | const unsigned int tcp_offset = ip_hdrlen(*pskb); | 336 | const unsigned int tcp_offset = ip_hdrlen(skb); |
| 336 | struct tcphdr *th; | 337 | struct tcphdr *th; |
| 337 | __u32 seq; | 338 | __u32 seq; |
| 338 | 339 | ||
| 339 | if (!ip_vs_make_skb_writable(pskb, tcp_offset + sizeof(*th))) | 340 | if (!skb_make_writable(skb, tcp_offset + sizeof(*th))) |
| 340 | return 0; | 341 | return 0; |
| 341 | 342 | ||
| 342 | th = (struct tcphdr *)(skb_network_header(*pskb) + tcp_offset); | 343 | th = (struct tcphdr *)(skb_network_header(skb) + tcp_offset); |
| 343 | 344 | ||
| 344 | /* | 345 | /* |
| 345 | * Remember seq number in case this pkt gets resized | 346 | * Remember seq number in case this pkt gets resized |
| @@ -360,7 +361,7 @@ static inline int app_tcp_pkt_out(struct ip_vs_conn *cp, struct sk_buff **pskb, | |||
| 360 | if (app->pkt_out == NULL) | 361 | if (app->pkt_out == NULL) |
| 361 | return 1; | 362 | return 1; |
| 362 | 363 | ||
| 363 | if (!app->pkt_out(app, cp, pskb, &diff)) | 364 | if (!app->pkt_out(app, cp, skb, &diff)) |
| 364 | return 0; | 365 | return 0; |
| 365 | 366 | ||
| 366 | /* | 367 | /* |
| @@ -378,7 +379,7 @@ static inline int app_tcp_pkt_out(struct ip_vs_conn *cp, struct sk_buff **pskb, | |||
| 378 | * called by ipvs packet handler, assumes previously checked cp!=NULL | 379 | * called by ipvs packet handler, assumes previously checked cp!=NULL |
| 379 | * returns false if it can't handle packet (oom) | 380 | * returns false if it can't handle packet (oom) |
| 380 | */ | 381 | */ |
| 381 | int ip_vs_app_pkt_out(struct ip_vs_conn *cp, struct sk_buff **pskb) | 382 | int ip_vs_app_pkt_out(struct ip_vs_conn *cp, struct sk_buff *skb) |
| 382 | { | 383 | { |
| 383 | struct ip_vs_app *app; | 384 | struct ip_vs_app *app; |
| 384 | 385 | ||
| @@ -391,7 +392,7 @@ int ip_vs_app_pkt_out(struct ip_vs_conn *cp, struct sk_buff **pskb) | |||
| 391 | 392 | ||
| 392 | /* TCP is complicated */ | 393 | /* TCP is complicated */ |
| 393 | if (cp->protocol == IPPROTO_TCP) | 394 | if (cp->protocol == IPPROTO_TCP) |
| 394 | return app_tcp_pkt_out(cp, pskb, app); | 395 | return app_tcp_pkt_out(cp, skb, app); |
| 395 | 396 | ||
| 396 | /* | 397 | /* |
| 397 | * Call private output hook function | 398 | * Call private output hook function |
| @@ -399,22 +400,22 @@ int ip_vs_app_pkt_out(struct ip_vs_conn *cp, struct sk_buff **pskb) | |||
| 399 | if (app->pkt_out == NULL) | 400 | if (app->pkt_out == NULL) |
| 400 | return 1; | 401 | return 1; |
| 401 | 402 | ||
| 402 | return app->pkt_out(app, cp, pskb, NULL); | 403 | return app->pkt_out(app, cp, skb, NULL); |
| 403 | } | 404 | } |
| 404 | 405 | ||
| 405 | 406 | ||
| 406 | static inline int app_tcp_pkt_in(struct ip_vs_conn *cp, struct sk_buff **pskb, | 407 | static inline int app_tcp_pkt_in(struct ip_vs_conn *cp, struct sk_buff *skb, |
| 407 | struct ip_vs_app *app) | 408 | struct ip_vs_app *app) |
| 408 | { | 409 | { |
| 409 | int diff; | 410 | int diff; |
| 410 | const unsigned int tcp_offset = ip_hdrlen(*pskb); | 411 | const unsigned int tcp_offset = ip_hdrlen(skb); |
| 411 | struct tcphdr *th; | 412 | struct tcphdr *th; |
| 412 | __u32 seq; | 413 | __u32 seq; |
| 413 | 414 | ||
| 414 | if (!ip_vs_make_skb_writable(pskb, tcp_offset + sizeof(*th))) | 415 | if (!skb_make_writable(skb, tcp_offset + sizeof(*th))) |
| 415 | return 0; | 416 | return 0; |
| 416 | 417 | ||
| 417 | th = (struct tcphdr *)(skb_network_header(*pskb) + tcp_offset); | 418 | th = (struct tcphdr *)(skb_network_header(skb) + tcp_offset); |
| 418 | 419 | ||
| 419 | /* | 420 | /* |
| 420 | * Remember seq number in case this pkt gets resized | 421 | * Remember seq number in case this pkt gets resized |
| @@ -435,7 +436,7 @@ static inline int app_tcp_pkt_in(struct ip_vs_conn *cp, struct sk_buff **pskb, | |||
| 435 | if (app->pkt_in == NULL) | 436 | if (app->pkt_in == NULL) |
| 436 | return 1; | 437 | return 1; |
| 437 | 438 | ||
| 438 | if (!app->pkt_in(app, cp, pskb, &diff)) | 439 | if (!app->pkt_in(app, cp, skb, &diff)) |
| 439 | return 0; | 440 | return 0; |
| 440 | 441 | ||
| 441 | /* | 442 | /* |
| @@ -453,7 +454,7 @@ static inline int app_tcp_pkt_in(struct ip_vs_conn *cp, struct sk_buff **pskb, | |||
| 453 | * called by ipvs packet handler, assumes previously checked cp!=NULL. | 454 | * called by ipvs packet handler, assumes previously checked cp!=NULL. |
| 454 | * returns false if can't handle packet (oom). | 455 | * returns false if can't handle packet (oom). |
| 455 | */ | 456 | */ |
| 456 | int ip_vs_app_pkt_in(struct ip_vs_conn *cp, struct sk_buff **pskb) | 457 | int ip_vs_app_pkt_in(struct ip_vs_conn *cp, struct sk_buff *skb) |
| 457 | { | 458 | { |
| 458 | struct ip_vs_app *app; | 459 | struct ip_vs_app *app; |
| 459 | 460 | ||
| @@ -466,7 +467,7 @@ int ip_vs_app_pkt_in(struct ip_vs_conn *cp, struct sk_buff **pskb) | |||
| 466 | 467 | ||
| 467 | /* TCP is complicated */ | 468 | /* TCP is complicated */ |
| 468 | if (cp->protocol == IPPROTO_TCP) | 469 | if (cp->protocol == IPPROTO_TCP) |
| 469 | return app_tcp_pkt_in(cp, pskb, app); | 470 | return app_tcp_pkt_in(cp, skb, app); |
| 470 | 471 | ||
| 471 | /* | 472 | /* |
| 472 | * Call private input hook function | 473 | * Call private input hook function |
| @@ -474,7 +475,7 @@ int ip_vs_app_pkt_in(struct ip_vs_conn *cp, struct sk_buff **pskb) | |||
| 474 | if (app->pkt_in == NULL) | 475 | if (app->pkt_in == NULL) |
| 475 | return 1; | 476 | return 1; |
| 476 | 477 | ||
| 477 | return app->pkt_in(app, cp, pskb, NULL); | 478 | return app->pkt_in(app, cp, skb, NULL); |
| 478 | } | 479 | } |
| 479 | 480 | ||
| 480 | 481 | ||
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c index fbca2a2ff29f..c6ed7654e839 100644 --- a/net/ipv4/ipvs/ip_vs_core.c +++ b/net/ipv4/ipvs/ip_vs_core.c | |||
| @@ -58,7 +58,6 @@ EXPORT_SYMBOL(ip_vs_conn_put); | |||
| 58 | #ifdef CONFIG_IP_VS_DEBUG | 58 | #ifdef CONFIG_IP_VS_DEBUG |
| 59 | EXPORT_SYMBOL(ip_vs_get_debug_level); | 59 | EXPORT_SYMBOL(ip_vs_get_debug_level); |
| 60 | #endif | 60 | #endif |
| 61 | EXPORT_SYMBOL(ip_vs_make_skb_writable); | ||
| 62 | 61 | ||
| 63 | 62 | ||
| 64 | /* ID used in ICMP lookups */ | 63 | /* ID used in ICMP lookups */ |
| @@ -163,42 +162,6 @@ ip_vs_set_state(struct ip_vs_conn *cp, int direction, | |||
| 163 | } | 162 | } |
| 164 | 163 | ||
| 165 | 164 | ||
| 166 | int ip_vs_make_skb_writable(struct sk_buff **pskb, int writable_len) | ||
| 167 | { | ||
| 168 | struct sk_buff *skb = *pskb; | ||
| 169 | |||
| 170 | /* skb is already used, better copy skb and its payload */ | ||
| 171 | if (unlikely(skb_shared(skb) || skb->sk)) | ||
| 172 | goto copy_skb; | ||
| 173 | |||
| 174 | /* skb data is already used, copy it */ | ||
| 175 | if (unlikely(skb_cloned(skb))) | ||
| 176 | goto copy_data; | ||
| 177 | |||
| 178 | return pskb_may_pull(skb, writable_len); | ||
| 179 | |||
| 180 | copy_data: | ||
| 181 | if (unlikely(writable_len > skb->len)) | ||
| 182 | return 0; | ||
| 183 | return !pskb_expand_head(skb, 0, 0, GFP_ATOMIC); | ||
| 184 | |||
| 185 | copy_skb: | ||
| 186 | if (unlikely(writable_len > skb->len)) | ||
| 187 | return 0; | ||
| 188 | skb = skb_copy(skb, GFP_ATOMIC); | ||
| 189 | if (!skb) | ||
| 190 | return 0; | ||
| 191 | BUG_ON(skb_is_nonlinear(skb)); | ||
| 192 | |||
| 193 | /* Rest of kernel will get very unhappy if we pass it a | ||
| 194 | suddenly-orphaned skbuff */ | ||
| 195 | if ((*pskb)->sk) | ||
| 196 | skb_set_owner_w(skb, (*pskb)->sk); | ||
| 197 | kfree_skb(*pskb); | ||
| 198 | *pskb = skb; | ||
| 199 | return 1; | ||
| 200 | } | ||
| 201 | |||
| 202 | /* | 165 | /* |
| 203 | * IPVS persistent scheduling function | 166 | * IPVS persistent scheduling function |
| 204 | * It creates a connection entry according to its template if exists, | 167 | * It creates a connection entry according to its template if exists, |
| @@ -525,12 +488,12 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb, | |||
| 525 | * for VS/NAT. | 488 | * for VS/NAT. |
| 526 | */ | 489 | */ |
| 527 | static unsigned int ip_vs_post_routing(unsigned int hooknum, | 490 | static unsigned int ip_vs_post_routing(unsigned int hooknum, |
| 528 | struct sk_buff **pskb, | 491 | struct sk_buff *skb, |
| 529 | const struct net_device *in, | 492 | const struct net_device *in, |
| 530 | const struct net_device *out, | 493 | const struct net_device *out, |
| 531 | int (*okfn)(struct sk_buff *)) | 494 | int (*okfn)(struct sk_buff *)) |
| 532 | { | 495 | { |
| 533 | if (!((*pskb)->ipvs_property)) | 496 | if (!skb->ipvs_property) |
| 534 | return NF_ACCEPT; | 497 | return NF_ACCEPT; |
| 535 | /* The packet was sent from IPVS, exit this chain */ | 498 | /* The packet was sent from IPVS, exit this chain */ |
| 536 | return NF_STOP; | 499 | return NF_STOP; |
| @@ -541,13 +504,14 @@ __sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset) | |||
| 541 | return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0)); | 504 | return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0)); |
| 542 | } | 505 | } |
| 543 | 506 | ||
| 544 | static inline struct sk_buff * | 507 | static inline int ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user) |
| 545 | ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user) | ||
| 546 | { | 508 | { |
| 547 | skb = ip_defrag(skb, user); | 509 | int err = ip_defrag(skb, user); |
| 548 | if (skb) | 510 | |
| 511 | if (!err) | ||
| 549 | ip_send_check(ip_hdr(skb)); | 512 | ip_send_check(ip_hdr(skb)); |
| 550 | return skb; | 513 | |
| 514 | return err; | ||
| 551 | } | 515 | } |
| 552 | 516 | ||
| 553 | /* | 517 | /* |
| @@ -605,9 +569,8 @@ void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp, | |||
| 605 | * Currently handles error types - unreachable, quench, ttl exceeded. | 569 | * Currently handles error types - unreachable, quench, ttl exceeded. |
| 606 | * (Only used in VS/NAT) | 570 | * (Only used in VS/NAT) |
| 607 | */ | 571 | */ |
| 608 | static int ip_vs_out_icmp(struct sk_buff **pskb, int *related) | 572 | static int ip_vs_out_icmp(struct sk_buff *skb, int *related) |
| 609 | { | 573 | { |
| 610 | struct sk_buff *skb = *pskb; | ||
| 611 | struct iphdr *iph; | 574 | struct iphdr *iph; |
| 612 | struct icmphdr _icmph, *ic; | 575 | struct icmphdr _icmph, *ic; |
| 613 | struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */ | 576 | struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */ |
| @@ -619,10 +582,8 @@ static int ip_vs_out_icmp(struct sk_buff **pskb, int *related) | |||
| 619 | 582 | ||
| 620 | /* reassemble IP fragments */ | 583 | /* reassemble IP fragments */ |
| 621 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { | 584 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { |
| 622 | skb = ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT); | 585 | if (ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT)) |
| 623 | if (!skb) | ||
| 624 | return NF_STOLEN; | 586 | return NF_STOLEN; |
| 625 | *pskb = skb; | ||
| 626 | } | 587 | } |
| 627 | 588 | ||
| 628 | iph = ip_hdr(skb); | 589 | iph = ip_hdr(skb); |
| @@ -690,9 +651,8 @@ static int ip_vs_out_icmp(struct sk_buff **pskb, int *related) | |||
| 690 | 651 | ||
| 691 | if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol) | 652 | if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol) |
| 692 | offset += 2 * sizeof(__u16); | 653 | offset += 2 * sizeof(__u16); |
| 693 | if (!ip_vs_make_skb_writable(pskb, offset)) | 654 | if (!skb_make_writable(skb, offset)) |
| 694 | goto out; | 655 | goto out; |
| 695 | skb = *pskb; | ||
| 696 | 656 | ||
| 697 | ip_vs_nat_icmp(skb, pp, cp, 1); | 657 | ip_vs_nat_icmp(skb, pp, cp, 1); |
| 698 | 658 | ||
| @@ -724,11 +684,10 @@ static inline int is_tcp_reset(const struct sk_buff *skb) | |||
| 724 | * rewrite addresses of the packet and send it on its way... | 684 | * rewrite addresses of the packet and send it on its way... |
| 725 | */ | 685 | */ |
| 726 | static unsigned int | 686 | static unsigned int |
| 727 | ip_vs_out(unsigned int hooknum, struct sk_buff **pskb, | 687 | ip_vs_out(unsigned int hooknum, struct sk_buff *skb, |
| 728 | const struct net_device *in, const struct net_device *out, | 688 | const struct net_device *in, const struct net_device *out, |
| 729 | int (*okfn)(struct sk_buff *)) | 689 | int (*okfn)(struct sk_buff *)) |
| 730 | { | 690 | { |
| 731 | struct sk_buff *skb = *pskb; | ||
| 732 | struct iphdr *iph; | 691 | struct iphdr *iph; |
| 733 | struct ip_vs_protocol *pp; | 692 | struct ip_vs_protocol *pp; |
| 734 | struct ip_vs_conn *cp; | 693 | struct ip_vs_conn *cp; |
| @@ -741,11 +700,10 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb, | |||
| 741 | 700 | ||
| 742 | iph = ip_hdr(skb); | 701 | iph = ip_hdr(skb); |
| 743 | if (unlikely(iph->protocol == IPPROTO_ICMP)) { | 702 | if (unlikely(iph->protocol == IPPROTO_ICMP)) { |
| 744 | int related, verdict = ip_vs_out_icmp(pskb, &related); | 703 | int related, verdict = ip_vs_out_icmp(skb, &related); |
| 745 | 704 | ||
| 746 | if (related) | 705 | if (related) |
| 747 | return verdict; | 706 | return verdict; |
| 748 | skb = *pskb; | ||
| 749 | iph = ip_hdr(skb); | 707 | iph = ip_hdr(skb); |
| 750 | } | 708 | } |
| 751 | 709 | ||
| @@ -756,11 +714,9 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb, | |||
| 756 | /* reassemble IP fragments */ | 714 | /* reassemble IP fragments */ |
| 757 | if (unlikely(iph->frag_off & htons(IP_MF|IP_OFFSET) && | 715 | if (unlikely(iph->frag_off & htons(IP_MF|IP_OFFSET) && |
| 758 | !pp->dont_defrag)) { | 716 | !pp->dont_defrag)) { |
| 759 | skb = ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT); | 717 | if (ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT)) |
| 760 | if (!skb) | ||
| 761 | return NF_STOLEN; | 718 | return NF_STOLEN; |
| 762 | iph = ip_hdr(skb); | 719 | iph = ip_hdr(skb); |
| 763 | *pskb = skb; | ||
| 764 | } | 720 | } |
| 765 | 721 | ||
| 766 | ihl = iph->ihl << 2; | 722 | ihl = iph->ihl << 2; |
| @@ -802,13 +758,12 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb, | |||
| 802 | 758 | ||
| 803 | IP_VS_DBG_PKT(11, pp, skb, 0, "Outgoing packet"); | 759 | IP_VS_DBG_PKT(11, pp, skb, 0, "Outgoing packet"); |
| 804 | 760 | ||
| 805 | if (!ip_vs_make_skb_writable(pskb, ihl)) | 761 | if (!skb_make_writable(skb, ihl)) |
| 806 | goto drop; | 762 | goto drop; |
| 807 | 763 | ||
| 808 | /* mangle the packet */ | 764 | /* mangle the packet */ |
| 809 | if (pp->snat_handler && !pp->snat_handler(pskb, pp, cp)) | 765 | if (pp->snat_handler && !pp->snat_handler(skb, pp, cp)) |
| 810 | goto drop; | 766 | goto drop; |
| 811 | skb = *pskb; | ||
| 812 | ip_hdr(skb)->saddr = cp->vaddr; | 767 | ip_hdr(skb)->saddr = cp->vaddr; |
| 813 | ip_send_check(ip_hdr(skb)); | 768 | ip_send_check(ip_hdr(skb)); |
| 814 | 769 | ||
| @@ -818,9 +773,8 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb, | |||
| 818 | * if it came from this machine itself. So re-compute | 773 | * if it came from this machine itself. So re-compute |
| 819 | * the routing information. | 774 | * the routing information. |
| 820 | */ | 775 | */ |
| 821 | if (ip_route_me_harder(pskb, RTN_LOCAL) != 0) | 776 | if (ip_route_me_harder(skb, RTN_LOCAL) != 0) |
| 822 | goto drop; | 777 | goto drop; |
| 823 | skb = *pskb; | ||
| 824 | 778 | ||
| 825 | IP_VS_DBG_PKT(10, pp, skb, 0, "After SNAT"); | 779 | IP_VS_DBG_PKT(10, pp, skb, 0, "After SNAT"); |
| 826 | 780 | ||
| @@ -835,7 +789,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb, | |||
| 835 | 789 | ||
| 836 | drop: | 790 | drop: |
| 837 | ip_vs_conn_put(cp); | 791 | ip_vs_conn_put(cp); |
| 838 | kfree_skb(*pskb); | 792 | kfree_skb(skb); |
| 839 | return NF_STOLEN; | 793 | return NF_STOLEN; |
| 840 | } | 794 | } |
| 841 | 795 | ||
| @@ -847,9 +801,8 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb, | |||
| 847 | * Currently handles error types - unreachable, quench, ttl exceeded. | 801 | * Currently handles error types - unreachable, quench, ttl exceeded. |
| 848 | */ | 802 | */ |
| 849 | static int | 803 | static int |
| 850 | ip_vs_in_icmp(struct sk_buff **pskb, int *related, unsigned int hooknum) | 804 | ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) |
| 851 | { | 805 | { |
| 852 | struct sk_buff *skb = *pskb; | ||
| 853 | struct iphdr *iph; | 806 | struct iphdr *iph; |
| 854 | struct icmphdr _icmph, *ic; | 807 | struct icmphdr _icmph, *ic; |
| 855 | struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */ | 808 | struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */ |
| @@ -861,12 +814,9 @@ ip_vs_in_icmp(struct sk_buff **pskb, int *related, unsigned int hooknum) | |||
| 861 | 814 | ||
| 862 | /* reassemble IP fragments */ | 815 | /* reassemble IP fragments */ |
| 863 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { | 816 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { |
| 864 | skb = ip_vs_gather_frags(skb, | 817 | if (ip_vs_gather_frags(skb, hooknum == NF_IP_LOCAL_IN ? |
| 865 | hooknum == NF_IP_LOCAL_IN ? | 818 | IP_DEFRAG_VS_IN : IP_DEFRAG_VS_FWD)) |
| 866 | IP_DEFRAG_VS_IN : IP_DEFRAG_VS_FWD); | ||
| 867 | if (!skb) | ||
| 868 | return NF_STOLEN; | 819 | return NF_STOLEN; |
| 869 | *pskb = skb; | ||
| 870 | } | 820 | } |
| 871 | 821 | ||
| 872 | iph = ip_hdr(skb); | 822 | iph = ip_hdr(skb); |
| @@ -945,11 +895,10 @@ ip_vs_in_icmp(struct sk_buff **pskb, int *related, unsigned int hooknum) | |||
| 945 | * and send it on its way... | 895 | * and send it on its way... |
| 946 | */ | 896 | */ |
| 947 | static unsigned int | 897 | static unsigned int |
| 948 | ip_vs_in(unsigned int hooknum, struct sk_buff **pskb, | 898 | ip_vs_in(unsigned int hooknum, struct sk_buff *skb, |
| 949 | const struct net_device *in, const struct net_device *out, | 899 | const struct net_device *in, const struct net_device *out, |
| 950 | int (*okfn)(struct sk_buff *)) | 900 | int (*okfn)(struct sk_buff *)) |
| 951 | { | 901 | { |
| 952 | struct sk_buff *skb = *pskb; | ||
| 953 | struct iphdr *iph; | 902 | struct iphdr *iph; |
| 954 | struct ip_vs_protocol *pp; | 903 | struct ip_vs_protocol *pp; |
| 955 | struct ip_vs_conn *cp; | 904 | struct ip_vs_conn *cp; |
| @@ -971,11 +920,10 @@ ip_vs_in(unsigned int hooknum, struct sk_buff **pskb, | |||
| 971 | 920 | ||
| 972 | iph = ip_hdr(skb); | 921 | iph = ip_hdr(skb); |
| 973 | if (unlikely(iph->protocol == IPPROTO_ICMP)) { | 922 | if (unlikely(iph->protocol == IPPROTO_ICMP)) { |
| 974 | int related, verdict = ip_vs_in_icmp(pskb, &related, hooknum); | 923 | int related, verdict = ip_vs_in_icmp(skb, &related, hooknum); |
| 975 | 924 | ||
| 976 | if (related) | 925 | if (related) |
| 977 | return verdict; | 926 | return verdict; |
| 978 | skb = *pskb; | ||
| 979 | iph = ip_hdr(skb); | 927 | iph = ip_hdr(skb); |
| 980 | } | 928 | } |
| 981 | 929 | ||
| @@ -1056,16 +1004,16 @@ ip_vs_in(unsigned int hooknum, struct sk_buff **pskb, | |||
| 1056 | * and send them to ip_vs_in_icmp. | 1004 | * and send them to ip_vs_in_icmp. |
| 1057 | */ | 1005 | */ |
| 1058 | static unsigned int | 1006 | static unsigned int |
| 1059 | ip_vs_forward_icmp(unsigned int hooknum, struct sk_buff **pskb, | 1007 | ip_vs_forward_icmp(unsigned int hooknum, struct sk_buff *skb, |
| 1060 | const struct net_device *in, const struct net_device *out, | 1008 | const struct net_device *in, const struct net_device *out, |
| 1061 | int (*okfn)(struct sk_buff *)) | 1009 | int (*okfn)(struct sk_buff *)) |
| 1062 | { | 1010 | { |
| 1063 | int r; | 1011 | int r; |
| 1064 | 1012 | ||
| 1065 | if (ip_hdr(*pskb)->protocol != IPPROTO_ICMP) | 1013 | if (ip_hdr(skb)->protocol != IPPROTO_ICMP) |
| 1066 | return NF_ACCEPT; | 1014 | return NF_ACCEPT; |
| 1067 | 1015 | ||
| 1068 | return ip_vs_in_icmp(pskb, &r, hooknum); | 1016 | return ip_vs_in_icmp(skb, &r, hooknum); |
| 1069 | } | 1017 | } |
| 1070 | 1018 | ||
| 1071 | 1019 | ||
diff --git a/net/ipv4/ipvs/ip_vs_ftp.c b/net/ipv4/ipvs/ip_vs_ftp.c index 344ddbbdc756..59aa166b7678 100644 --- a/net/ipv4/ipvs/ip_vs_ftp.c +++ b/net/ipv4/ipvs/ip_vs_ftp.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <linux/skbuff.h> | 30 | #include <linux/skbuff.h> |
| 31 | #include <linux/in.h> | 31 | #include <linux/in.h> |
| 32 | #include <linux/ip.h> | 32 | #include <linux/ip.h> |
| 33 | #include <linux/netfilter.h> | ||
| 33 | #include <net/protocol.h> | 34 | #include <net/protocol.h> |
| 34 | #include <net/tcp.h> | 35 | #include <net/tcp.h> |
| 35 | #include <asm/unaligned.h> | 36 | #include <asm/unaligned.h> |
| @@ -135,7 +136,7 @@ static int ip_vs_ftp_get_addrport(char *data, char *data_limit, | |||
| 135 | * xxx,xxx,xxx,xxx is the server address, ppp,ppp is the server port number. | 136 | * xxx,xxx,xxx,xxx is the server address, ppp,ppp is the server port number. |
| 136 | */ | 137 | */ |
| 137 | static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp, | 138 | static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp, |
| 138 | struct sk_buff **pskb, int *diff) | 139 | struct sk_buff *skb, int *diff) |
| 139 | { | 140 | { |
| 140 | struct iphdr *iph; | 141 | struct iphdr *iph; |
| 141 | struct tcphdr *th; | 142 | struct tcphdr *th; |
| @@ -155,14 +156,14 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp, | |||
| 155 | return 1; | 156 | return 1; |
| 156 | 157 | ||
| 157 | /* Linear packets are much easier to deal with. */ | 158 | /* Linear packets are much easier to deal with. */ |
| 158 | if (!ip_vs_make_skb_writable(pskb, (*pskb)->len)) | 159 | if (!skb_make_writable(skb, skb->len)) |
| 159 | return 0; | 160 | return 0; |
| 160 | 161 | ||
| 161 | if (cp->app_data == &ip_vs_ftp_pasv) { | 162 | if (cp->app_data == &ip_vs_ftp_pasv) { |
| 162 | iph = ip_hdr(*pskb); | 163 | iph = ip_hdr(skb); |
| 163 | th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]); | 164 | th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]); |
| 164 | data = (char *)th + (th->doff << 2); | 165 | data = (char *)th + (th->doff << 2); |
| 165 | data_limit = skb_tail_pointer(*pskb); | 166 | data_limit = skb_tail_pointer(skb); |
| 166 | 167 | ||
| 167 | if (ip_vs_ftp_get_addrport(data, data_limit, | 168 | if (ip_vs_ftp_get_addrport(data, data_limit, |
| 168 | SERVER_STRING, | 169 | SERVER_STRING, |
| @@ -213,7 +214,7 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp, | |||
| 213 | memcpy(start, buf, buf_len); | 214 | memcpy(start, buf, buf_len); |
| 214 | ret = 1; | 215 | ret = 1; |
| 215 | } else { | 216 | } else { |
| 216 | ret = !ip_vs_skb_replace(*pskb, GFP_ATOMIC, start, | 217 | ret = !ip_vs_skb_replace(skb, GFP_ATOMIC, start, |
| 217 | end-start, buf, buf_len); | 218 | end-start, buf, buf_len); |
| 218 | } | 219 | } |
| 219 | 220 | ||
| @@ -238,7 +239,7 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp, | |||
| 238 | * the client. | 239 | * the client. |
| 239 | */ | 240 | */ |
| 240 | static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp, | 241 | static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp, |
| 241 | struct sk_buff **pskb, int *diff) | 242 | struct sk_buff *skb, int *diff) |
| 242 | { | 243 | { |
| 243 | struct iphdr *iph; | 244 | struct iphdr *iph; |
| 244 | struct tcphdr *th; | 245 | struct tcphdr *th; |
| @@ -256,20 +257,20 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp, | |||
| 256 | return 1; | 257 | return 1; |
| 257 | 258 | ||
| 258 | /* Linear packets are much easier to deal with. */ | 259 | /* Linear packets are much easier to deal with. */ |
| 259 | if (!ip_vs_make_skb_writable(pskb, (*pskb)->len)) | 260 | if (!skb_make_writable(skb, skb->len)) |
| 260 | return 0; | 261 | return 0; |
| 261 | 262 | ||
| 262 | /* | 263 | /* |
| 263 | * Detecting whether it is passive | 264 | * Detecting whether it is passive |
| 264 | */ | 265 | */ |
| 265 | iph = ip_hdr(*pskb); | 266 | iph = ip_hdr(skb); |
| 266 | th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]); | 267 | th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]); |
| 267 | 268 | ||
| 268 | /* Since there may be OPTIONS in the TCP packet and the HLEN is | 269 | /* Since there may be OPTIONS in the TCP packet and the HLEN is |
| 269 | the length of the header in 32-bit multiples, it is accurate | 270 | the length of the header in 32-bit multiples, it is accurate |
| 270 | to calculate data address by th+HLEN*4 */ | 271 | to calculate data address by th+HLEN*4 */ |
| 271 | data = data_start = (char *)th + (th->doff << 2); | 272 | data = data_start = (char *)th + (th->doff << 2); |
| 272 | data_limit = skb_tail_pointer(*pskb); | 273 | data_limit = skb_tail_pointer(skb); |
| 273 | 274 | ||
| 274 | while (data <= data_limit - 6) { | 275 | while (data <= data_limit - 6) { |
| 275 | if (strnicmp(data, "PASV\r\n", 6) == 0) { | 276 | if (strnicmp(data, "PASV\r\n", 6) == 0) { |
diff --git a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c index e65577a77006..12dc0d640b6d 100644 --- a/net/ipv4/ipvs/ip_vs_proto_tcp.c +++ b/net/ipv4/ipvs/ip_vs_proto_tcp.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/tcp.h> /* for tcphdr */ | 20 | #include <linux/tcp.h> /* for tcphdr */ |
| 21 | #include <net/ip.h> | 21 | #include <net/ip.h> |
| 22 | #include <net/tcp.h> /* for csum_tcpudp_magic */ | 22 | #include <net/tcp.h> /* for csum_tcpudp_magic */ |
| 23 | #include <linux/netfilter.h> | ||
| 23 | #include <linux/netfilter_ipv4.h> | 24 | #include <linux/netfilter_ipv4.h> |
| 24 | 25 | ||
| 25 | #include <net/ip_vs.h> | 26 | #include <net/ip_vs.h> |
| @@ -122,27 +123,27 @@ tcp_fast_csum_update(struct tcphdr *tcph, __be32 oldip, __be32 newip, | |||
| 122 | 123 | ||
| 123 | 124 | ||
| 124 | static int | 125 | static int |
| 125 | tcp_snat_handler(struct sk_buff **pskb, | 126 | tcp_snat_handler(struct sk_buff *skb, |
| 126 | struct ip_vs_protocol *pp, struct ip_vs_conn *cp) | 127 | struct ip_vs_protocol *pp, struct ip_vs_conn *cp) |
| 127 | { | 128 | { |
| 128 | struct tcphdr *tcph; | 129 | struct tcphdr *tcph; |
| 129 | const unsigned int tcphoff = ip_hdrlen(*pskb); | 130 | const unsigned int tcphoff = ip_hdrlen(skb); |
| 130 | 131 | ||
| 131 | /* csum_check requires unshared skb */ | 132 | /* csum_check requires unshared skb */ |
| 132 | if (!ip_vs_make_skb_writable(pskb, tcphoff+sizeof(*tcph))) | 133 | if (!skb_make_writable(skb, tcphoff+sizeof(*tcph))) |
| 133 | return 0; | 134 | return 0; |
| 134 | 135 | ||
| 135 | if (unlikely(cp->app != NULL)) { | 136 | if (unlikely(cp->app != NULL)) { |
| 136 | /* Some checks before mangling */ | 137 | /* Some checks before mangling */ |
| 137 | if (pp->csum_check && !pp->csum_check(*pskb, pp)) | 138 | if (pp->csum_check && !pp->csum_check(skb, pp)) |
| 138 | return 0; | 139 | return 0; |
| 139 | 140 | ||
| 140 | /* Call application helper if needed */ | 141 | /* Call application helper if needed */ |
| 141 | if (!ip_vs_app_pkt_out(cp, pskb)) | 142 | if (!ip_vs_app_pkt_out(cp, skb)) |
| 142 | return 0; | 143 | return 0; |
| 143 | } | 144 | } |
| 144 | 145 | ||
| 145 | tcph = (void *)ip_hdr(*pskb) + tcphoff; | 146 | tcph = (void *)ip_hdr(skb) + tcphoff; |
| 146 | tcph->source = cp->vport; | 147 | tcph->source = cp->vport; |
| 147 | 148 | ||
| 148 | /* Adjust TCP checksums */ | 149 | /* Adjust TCP checksums */ |
| @@ -150,17 +151,15 @@ tcp_snat_handler(struct sk_buff **pskb, | |||
| 150 | /* Only port and addr are changed, do fast csum update */ | 151 | /* Only port and addr are changed, do fast csum update */ |
| 151 | tcp_fast_csum_update(tcph, cp->daddr, cp->vaddr, | 152 | tcp_fast_csum_update(tcph, cp->daddr, cp->vaddr, |
| 152 | cp->dport, cp->vport); | 153 | cp->dport, cp->vport); |
| 153 | if ((*pskb)->ip_summed == CHECKSUM_COMPLETE) | 154 | if (skb->ip_summed == CHECKSUM_COMPLETE) |
| 154 | (*pskb)->ip_summed = CHECKSUM_NONE; | 155 | skb->ip_summed = CHECKSUM_NONE; |
| 155 | } else { | 156 | } else { |
| 156 | /* full checksum calculation */ | 157 | /* full checksum calculation */ |
| 157 | tcph->check = 0; | 158 | tcph->check = 0; |
| 158 | (*pskb)->csum = skb_checksum(*pskb, tcphoff, | 159 | skb->csum = skb_checksum(skb, tcphoff, skb->len - tcphoff, 0); |
| 159 | (*pskb)->len - tcphoff, 0); | ||
| 160 | tcph->check = csum_tcpudp_magic(cp->vaddr, cp->caddr, | 160 | tcph->check = csum_tcpudp_magic(cp->vaddr, cp->caddr, |
| 161 | (*pskb)->len - tcphoff, | 161 | skb->len - tcphoff, |
| 162 | cp->protocol, | 162 | cp->protocol, skb->csum); |
| 163 | (*pskb)->csum); | ||
| 164 | IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n", | 163 | IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n", |
| 165 | pp->name, tcph->check, | 164 | pp->name, tcph->check, |
| 166 | (char*)&(tcph->check) - (char*)tcph); | 165 | (char*)&(tcph->check) - (char*)tcph); |
| @@ -170,30 +169,30 @@ tcp_snat_handler(struct sk_buff **pskb, | |||
| 170 | 169 | ||
| 171 | 170 | ||
| 172 | static int | 171 | static int |
| 173 | tcp_dnat_handler(struct sk_buff **pskb, | 172 | tcp_dnat_handler(struct sk_buff *skb, |
| 174 | struct ip_vs_protocol *pp, struct ip_vs_conn *cp) | 173 | struct ip_vs_protocol *pp, struct ip_vs_conn *cp) |
| 175 | { | 174 | { |
| 176 | struct tcphdr *tcph; | 175 | struct tcphdr *tcph; |
| 177 | const unsigned int tcphoff = ip_hdrlen(*pskb); | 176 | const unsigned int tcphoff = ip_hdrlen(skb); |
| 178 | 177 | ||
| 179 | /* csum_check requires unshared skb */ | 178 | /* csum_check requires unshared skb */ |
| 180 | if (!ip_vs_make_skb_writable(pskb, tcphoff+sizeof(*tcph))) | 179 | if (!skb_make_writable(skb, tcphoff+sizeof(*tcph))) |
| 181 | return 0; | 180 | return 0; |
| 182 | 181 | ||
| 183 | if (unlikely(cp->app != NULL)) { | 182 | if (unlikely(cp->app != NULL)) { |
| 184 | /* Some checks before mangling */ | 183 | /* Some checks before mangling */ |
| 185 | if (pp->csum_check && !pp->csum_check(*pskb, pp)) | 184 | if (pp->csum_check && !pp->csum_check(skb, pp)) |
| 186 | return 0; | 185 | return 0; |
| 187 | 186 | ||
| 188 | /* | 187 | /* |
| 189 | * Attempt ip_vs_app call. | 188 | * Attempt ip_vs_app call. |
| 190 | * It will fix ip_vs_conn and iph ack_seq stuff | 189 | * It will fix ip_vs_conn and iph ack_seq stuff |
| 191 | */ | 190 | */ |
| 192 | if (!ip_vs_app_pkt_in(cp, pskb)) | 191 | if (!ip_vs_app_pkt_in(cp, skb)) |
| 193 | return 0; | 192 | return 0; |
| 194 | } | 193 | } |
| 195 | 194 | ||
| 196 | tcph = (void *)ip_hdr(*pskb) + tcphoff; | 195 | tcph = (void *)ip_hdr(skb) + tcphoff; |
| 197 | tcph->dest = cp->dport; | 196 | tcph->dest = cp->dport; |
| 198 | 197 | ||
| 199 | /* | 198 | /* |
| @@ -203,18 +202,16 @@ tcp_dnat_handler(struct sk_buff **pskb, | |||
| 203 | /* Only port and addr are changed, do fast csum update */ | 202 | /* Only port and addr are changed, do fast csum update */ |
| 204 | tcp_fast_csum_update(tcph, cp->vaddr, cp->daddr, | 203 | tcp_fast_csum_update(tcph, cp->vaddr, cp->daddr, |
| 205 | cp->vport, cp->dport); | 204 | cp->vport, cp->dport); |
| 206 | if ((*pskb)->ip_summed == CHECKSUM_COMPLETE) | 205 | if (skb->ip_summed == CHECKSUM_COMPLETE) |
| 207 | (*pskb)->ip_summed = CHECKSUM_NONE; | 206 | skb->ip_summed = CHECKSUM_NONE; |
| 208 | } else { | 207 | } else { |
| 209 | /* full checksum calculation */ | 208 | /* full checksum calculation */ |
| 210 | tcph->check = 0; | 209 | tcph->check = 0; |
| 211 | (*pskb)->csum = skb_checksum(*pskb, tcphoff, | 210 | skb->csum = skb_checksum(skb, tcphoff, skb->len - tcphoff, 0); |
| 212 | (*pskb)->len - tcphoff, 0); | ||
| 213 | tcph->check = csum_tcpudp_magic(cp->caddr, cp->daddr, | 211 | tcph->check = csum_tcpudp_magic(cp->caddr, cp->daddr, |
| 214 | (*pskb)->len - tcphoff, | 212 | skb->len - tcphoff, |
| 215 | cp->protocol, | 213 | cp->protocol, skb->csum); |
| 216 | (*pskb)->csum); | 214 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
| 217 | (*pskb)->ip_summed = CHECKSUM_UNNECESSARY; | ||
| 218 | } | 215 | } |
| 219 | return 1; | 216 | return 1; |
| 220 | } | 217 | } |
diff --git a/net/ipv4/ipvs/ip_vs_proto_udp.c b/net/ipv4/ipvs/ip_vs_proto_udp.c index 8ee5fe6a101d..1fa7b330b9ac 100644 --- a/net/ipv4/ipvs/ip_vs_proto_udp.c +++ b/net/ipv4/ipvs/ip_vs_proto_udp.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/in.h> | 18 | #include <linux/in.h> |
| 19 | #include <linux/ip.h> | 19 | #include <linux/ip.h> |
| 20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
| 21 | #include <linux/netfilter.h> | ||
| 21 | #include <linux/netfilter_ipv4.h> | 22 | #include <linux/netfilter_ipv4.h> |
| 22 | #include <linux/udp.h> | 23 | #include <linux/udp.h> |
| 23 | 24 | ||
| @@ -129,29 +130,29 @@ udp_fast_csum_update(struct udphdr *uhdr, __be32 oldip, __be32 newip, | |||
| 129 | } | 130 | } |
| 130 | 131 | ||
| 131 | static int | 132 | static int |
| 132 | udp_snat_handler(struct sk_buff **pskb, | 133 | udp_snat_handler(struct sk_buff *skb, |
| 133 | struct ip_vs_protocol *pp, struct ip_vs_conn *cp) | 134 | struct ip_vs_protocol *pp, struct ip_vs_conn *cp) |
| 134 | { | 135 | { |
| 135 | struct udphdr *udph; | 136 | struct udphdr *udph; |
| 136 | const unsigned int udphoff = ip_hdrlen(*pskb); | 137 | const unsigned int udphoff = ip_hdrlen(skb); |
| 137 | 138 | ||
| 138 | /* csum_check requires unshared skb */ | 139 | /* csum_check requires unshared skb */ |
| 139 | if (!ip_vs_make_skb_writable(pskb, udphoff+sizeof(*udph))) | 140 | if (!skb_make_writable(skb, udphoff+sizeof(*udph))) |
| 140 | return 0; | 141 | return 0; |
| 141 | 142 | ||
| 142 | if (unlikely(cp->app != NULL)) { | 143 | if (unlikely(cp->app != NULL)) { |
| 143 | /* Some checks before mangling */ | 144 | /* Some checks before mangling */ |
| 144 | if (pp->csum_check && !pp->csum_check(*pskb, pp)) | 145 | if (pp->csum_check && !pp->csum_check(skb, pp)) |
| 145 | return 0; | 146 | return 0; |
| 146 | 147 | ||
| 147 | /* | 148 | /* |
| 148 | * Call application helper if needed | 149 | * Call application helper if needed |
| 149 | */ | 150 | */ |
| 150 | if (!ip_vs_app_pkt_out(cp, pskb)) | 151 | if (!ip_vs_app_pkt_out(cp, skb)) |
| 151 | return 0; | 152 | return 0; |
| 152 | } | 153 | } |
| 153 | 154 | ||
| 154 | udph = (void *)ip_hdr(*pskb) + udphoff; | 155 | udph = (void *)ip_hdr(skb) + udphoff; |
| 155 | udph->source = cp->vport; | 156 | udph->source = cp->vport; |
| 156 | 157 | ||
| 157 | /* | 158 | /* |
| @@ -161,17 +162,15 @@ udp_snat_handler(struct sk_buff **pskb, | |||
| 161 | /* Only port and addr are changed, do fast csum update */ | 162 | /* Only port and addr are changed, do fast csum update */ |
| 162 | udp_fast_csum_update(udph, cp->daddr, cp->vaddr, | 163 | udp_fast_csum_update(udph, cp->daddr, cp->vaddr, |
| 163 | cp->dport, cp->vport); | 164 | cp->dport, cp->vport); |
| 164 | if ((*pskb)->ip_summed == CHECKSUM_COMPLETE) | 165 | if (skb->ip_summed == CHECKSUM_COMPLETE) |
| 165 | (*pskb)->ip_summed = CHECKSUM_NONE; | 166 | skb->ip_summed = CHECKSUM_NONE; |
| 166 | } else { | 167 | } else { |
| 167 | /* full checksum calculation */ | 168 | /* full checksum calculation */ |
| 168 | udph->check = 0; | 169 | udph->check = 0; |
| 169 | (*pskb)->csum = skb_checksum(*pskb, udphoff, | 170 | skb->csum = skb_checksum(skb, udphoff, skb->len - udphoff, 0); |
| 170 | (*pskb)->len - udphoff, 0); | ||
| 171 | udph->check = csum_tcpudp_magic(cp->vaddr, cp->caddr, | 171 | udph->check = csum_tcpudp_magic(cp->vaddr, cp->caddr, |
| 172 | (*pskb)->len - udphoff, | 172 | skb->len - udphoff, |
| 173 | cp->protocol, | 173 | cp->protocol, skb->csum); |
| 174 | (*pskb)->csum); | ||
| 175 | if (udph->check == 0) | 174 | if (udph->check == 0) |
| 176 | udph->check = CSUM_MANGLED_0; | 175 | udph->check = CSUM_MANGLED_0; |
| 177 | IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n", | 176 | IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n", |
| @@ -183,30 +182,30 @@ udp_snat_handler(struct sk_buff **pskb, | |||
| 183 | 182 | ||
| 184 | 183 | ||
| 185 | static int | 184 | static int |
| 186 | udp_dnat_handler(struct sk_buff **pskb, | 185 | udp_dnat_handler(struct sk_buff *skb, |
| 187 | struct ip_vs_protocol *pp, struct ip_vs_conn *cp) | 186 | struct ip_vs_protocol *pp, struct ip_vs_conn *cp) |
| 188 | { | 187 | { |
| 189 | struct udphdr *udph; | 188 | struct udphdr *udph; |
| 190 | unsigned int udphoff = ip_hdrlen(*pskb); | 189 | unsigned int udphoff = ip_hdrlen(skb); |
| 191 | 190 | ||
| 192 | /* csum_check requires unshared skb */ | 191 | /* csum_check requires unshared skb */ |
| 193 | if (!ip_vs_make_skb_writable(pskb, udphoff+sizeof(*udph))) | 192 | if (!skb_make_writable(skb, udphoff+sizeof(*udph))) |
| 194 | return 0; | 193 | return 0; |
| 195 | 194 | ||
| 196 | if (unlikely(cp->app != NULL)) { | 195 | if (unlikely(cp->app != NULL)) { |
| 197 | /* Some checks before mangling */ | 196 | /* Some checks before mangling */ |
| 198 | if (pp->csum_check && !pp->csum_check(*pskb, pp)) | 197 | if (pp->csum_check && !pp->csum_check(skb, pp)) |
| 199 | return 0; | 198 | return 0; |
| 200 | 199 | ||
| 201 | /* | 200 | /* |
| 202 | * Attempt ip_vs_app call. | 201 | * Attempt ip_vs_app call. |
| 203 | * It will fix ip_vs_conn | 202 | * It will fix ip_vs_conn |
| 204 | */ | 203 | */ |
| 205 | if (!ip_vs_app_pkt_in(cp, pskb)) | 204 | if (!ip_vs_app_pkt_in(cp, skb)) |
| 206 | return 0; | 205 | return 0; |
| 207 | } | 206 | } |
| 208 | 207 | ||
| 209 | udph = (void *)ip_hdr(*pskb) + udphoff; | 208 | udph = (void *)ip_hdr(skb) + udphoff; |
| 210 | udph->dest = cp->dport; | 209 | udph->dest = cp->dport; |
| 211 | 210 | ||
| 212 | /* | 211 | /* |
| @@ -216,20 +215,18 @@ udp_dnat_handler(struct sk_buff **pskb, | |||
| 216 | /* Only port and addr are changed, do fast csum update */ | 215 | /* Only port and addr are changed, do fast csum update */ |
| 217 | udp_fast_csum_update(udph, cp->vaddr, cp->daddr, | 216 | udp_fast_csum_update(udph, cp->vaddr, cp->daddr, |
| 218 | cp->vport, cp->dport); | 217 | cp->vport, cp->dport); |
| 219 | if ((*pskb)->ip_summed == CHECKSUM_COMPLETE) | 218 | if (skb->ip_summed == CHECKSUM_COMPLETE) |
| 220 | (*pskb)->ip_summed = CHECKSUM_NONE; | 219 | skb->ip_summed = CHECKSUM_NONE; |
| 221 | } else { | 220 | } else { |
| 222 | /* full checksum calculation */ | 221 | /* full checksum calculation */ |
| 223 | udph->check = 0; | 222 | udph->check = 0; |
| 224 | (*pskb)->csum = skb_checksum(*pskb, udphoff, | 223 | skb->csum = skb_checksum(skb, udphoff, skb->len - udphoff, 0); |
| 225 | (*pskb)->len - udphoff, 0); | ||
| 226 | udph->check = csum_tcpudp_magic(cp->caddr, cp->daddr, | 224 | udph->check = csum_tcpudp_magic(cp->caddr, cp->daddr, |
| 227 | (*pskb)->len - udphoff, | 225 | skb->len - udphoff, |
| 228 | cp->protocol, | 226 | cp->protocol, skb->csum); |
| 229 | (*pskb)->csum); | ||
| 230 | if (udph->check == 0) | 227 | if (udph->check == 0) |
| 231 | udph->check = CSUM_MANGLED_0; | 228 | udph->check = CSUM_MANGLED_0; |
| 232 | (*pskb)->ip_summed = CHECKSUM_UNNECESSARY; | 229 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
| 233 | } | 230 | } |
| 234 | return 1; | 231 | return 1; |
| 235 | } | 232 | } |
diff --git a/net/ipv4/ipvs/ip_vs_xmit.c b/net/ipv4/ipvs/ip_vs_xmit.c index 666e080a74a3..d0a92dec1050 100644 --- a/net/ipv4/ipvs/ip_vs_xmit.c +++ b/net/ipv4/ipvs/ip_vs_xmit.c | |||
| @@ -253,7 +253,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
| 253 | } | 253 | } |
| 254 | 254 | ||
| 255 | /* copy-on-write the packet before mangling it */ | 255 | /* copy-on-write the packet before mangling it */ |
| 256 | if (!ip_vs_make_skb_writable(&skb, sizeof(struct iphdr))) | 256 | if (!skb_make_writable(skb, sizeof(struct iphdr))) |
| 257 | goto tx_error_put; | 257 | goto tx_error_put; |
| 258 | 258 | ||
| 259 | if (skb_cow(skb, rt->u.dst.dev->hard_header_len)) | 259 | if (skb_cow(skb, rt->u.dst.dev->hard_header_len)) |
| @@ -264,7 +264,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
| 264 | skb->dst = &rt->u.dst; | 264 | skb->dst = &rt->u.dst; |
| 265 | 265 | ||
| 266 | /* mangle the packet */ | 266 | /* mangle the packet */ |
| 267 | if (pp->dnat_handler && !pp->dnat_handler(&skb, pp, cp)) | 267 | if (pp->dnat_handler && !pp->dnat_handler(skb, pp, cp)) |
| 268 | goto tx_error; | 268 | goto tx_error; |
| 269 | ip_hdr(skb)->daddr = cp->daddr; | 269 | ip_hdr(skb)->daddr = cp->daddr; |
| 270 | ip_send_check(ip_hdr(skb)); | 270 | ip_send_check(ip_hdr(skb)); |
| @@ -529,7 +529,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
| 529 | } | 529 | } |
| 530 | 530 | ||
| 531 | /* copy-on-write the packet before mangling it */ | 531 | /* copy-on-write the packet before mangling it */ |
| 532 | if (!ip_vs_make_skb_writable(&skb, offset)) | 532 | if (!skb_make_writable(skb, offset)) |
| 533 | goto tx_error_put; | 533 | goto tx_error_put; |
| 534 | 534 | ||
| 535 | if (skb_cow(skb, rt->u.dst.dev->hard_header_len)) | 535 | if (skb_cow(skb, rt->u.dst.dev->hard_header_len)) |
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index b44192924f95..5539debf4973 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c | |||
| @@ -3,14 +3,15 @@ | |||
| 3 | #include <linux/netfilter.h> | 3 | #include <linux/netfilter.h> |
| 4 | #include <linux/netfilter_ipv4.h> | 4 | #include <linux/netfilter_ipv4.h> |
| 5 | #include <linux/ip.h> | 5 | #include <linux/ip.h> |
| 6 | #include <linux/skbuff.h> | ||
| 6 | #include <net/route.h> | 7 | #include <net/route.h> |
| 7 | #include <net/xfrm.h> | 8 | #include <net/xfrm.h> |
| 8 | #include <net/ip.h> | 9 | #include <net/ip.h> |
| 9 | 10 | ||
| 10 | /* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */ | 11 | /* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */ |
| 11 | int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type) | 12 | int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type) |
| 12 | { | 13 | { |
| 13 | const struct iphdr *iph = ip_hdr(*pskb); | 14 | const struct iphdr *iph = ip_hdr(skb); |
| 14 | struct rtable *rt; | 15 | struct rtable *rt; |
| 15 | struct flowi fl = {}; | 16 | struct flowi fl = {}; |
| 16 | struct dst_entry *odst; | 17 | struct dst_entry *odst; |
| @@ -29,14 +30,14 @@ int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type) | |||
| 29 | if (type == RTN_LOCAL) | 30 | if (type == RTN_LOCAL) |
| 30 | fl.nl_u.ip4_u.saddr = iph->saddr; | 31 | fl.nl_u.ip4_u.saddr = iph->saddr; |
| 31 | fl.nl_u.ip4_u.tos = RT_TOS(iph->tos); | 32 | fl.nl_u.ip4_u.tos = RT_TOS(iph->tos); |
| 32 | fl.oif = (*pskb)->sk ? (*pskb)->sk->sk_bound_dev_if : 0; | 33 | fl.oif = skb->sk ? skb->sk->sk_bound_dev_if : 0; |
| 33 | fl.mark = (*pskb)->mark; | 34 | fl.mark = skb->mark; |
| 34 | if (ip_route_output_key(&rt, &fl) != 0) | 35 | if (ip_route_output_key(&rt, &fl) != 0) |
| 35 | return -1; | 36 | return -1; |
| 36 | 37 | ||
| 37 | /* Drop old route. */ | 38 | /* Drop old route. */ |
| 38 | dst_release((*pskb)->dst); | 39 | dst_release(skb->dst); |
| 39 | (*pskb)->dst = &rt->u.dst; | 40 | skb->dst = &rt->u.dst; |
| 40 | } else { | 41 | } else { |
| 41 | /* non-local src, find valid iif to satisfy | 42 | /* non-local src, find valid iif to satisfy |
| 42 | * rp-filter when calling ip_route_input. */ | 43 | * rp-filter when calling ip_route_input. */ |
| @@ -44,8 +45,8 @@ int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type) | |||
| 44 | if (ip_route_output_key(&rt, &fl) != 0) | 45 | if (ip_route_output_key(&rt, &fl) != 0) |
| 45 | return -1; | 46 | return -1; |
| 46 | 47 | ||
| 47 | odst = (*pskb)->dst; | 48 | odst = skb->dst; |
| 48 | if (ip_route_input(*pskb, iph->daddr, iph->saddr, | 49 | if (ip_route_input(skb, iph->daddr, iph->saddr, |
| 49 | RT_TOS(iph->tos), rt->u.dst.dev) != 0) { | 50 | RT_TOS(iph->tos), rt->u.dst.dev) != 0) { |
| 50 | dst_release(&rt->u.dst); | 51 | dst_release(&rt->u.dst); |
| 51 | return -1; | 52 | return -1; |
| @@ -54,70 +55,54 @@ int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type) | |||
| 54 | dst_release(odst); | 55 | dst_release(odst); |
| 55 | } | 56 | } |
| 56 | 57 | ||
| 57 | if ((*pskb)->dst->error) | 58 | if (skb->dst->error) |
| 58 | return -1; | 59 | return -1; |
| 59 | 60 | ||
| 60 | #ifdef CONFIG_XFRM | 61 | #ifdef CONFIG_XFRM |
| 61 | if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED) && | 62 | if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) && |
| 62 | xfrm_decode_session(*pskb, &fl, AF_INET) == 0) | 63 | xfrm_decode_session(skb, &fl, AF_INET) == 0) |
| 63 | if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0)) | 64 | if (xfrm_lookup(&skb->dst, &fl, skb->sk, 0)) |
| 64 | return -1; | 65 | return -1; |
| 65 | #endif | 66 | #endif |
| 66 | 67 | ||
| 67 | /* Change in oif may mean change in hh_len. */ | 68 | /* Change in oif may mean change in hh_len. */ |
| 68 | hh_len = (*pskb)->dst->dev->hard_header_len; | 69 | hh_len = skb->dst->dev->hard_header_len; |
| 69 | if (skb_headroom(*pskb) < hh_len) { | 70 | if (skb_headroom(skb) < hh_len && |
| 70 | struct sk_buff *nskb; | 71 | pskb_expand_head(skb, hh_len - skb_headroom(skb), 0, GFP_ATOMIC)) |
| 71 | 72 | return -1; | |
| 72 | nskb = skb_realloc_headroom(*pskb, hh_len); | ||
| 73 | if (!nskb) | ||
| 74 | return -1; | ||
| 75 | if ((*pskb)->sk) | ||
| 76 | skb_set_owner_w(nskb, (*pskb)->sk); | ||
| 77 | kfree_skb(*pskb); | ||
| 78 | *pskb = nskb; | ||
| 79 | } | ||
| 80 | 73 | ||
| 81 | return 0; | 74 | return 0; |
| 82 | } | 75 | } |
| 83 | EXPORT_SYMBOL(ip_route_me_harder); | 76 | EXPORT_SYMBOL(ip_route_me_harder); |
| 84 | 77 | ||
| 85 | #ifdef CONFIG_XFRM | 78 | #ifdef CONFIG_XFRM |
| 86 | int ip_xfrm_me_harder(struct sk_buff **pskb) | 79 | int ip_xfrm_me_harder(struct sk_buff *skb) |
| 87 | { | 80 | { |
| 88 | struct flowi fl; | 81 | struct flowi fl; |
| 89 | unsigned int hh_len; | 82 | unsigned int hh_len; |
| 90 | struct dst_entry *dst; | 83 | struct dst_entry *dst; |
| 91 | 84 | ||
| 92 | if (IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED) | 85 | if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) |
| 93 | return 0; | 86 | return 0; |
| 94 | if (xfrm_decode_session(*pskb, &fl, AF_INET) < 0) | 87 | if (xfrm_decode_session(skb, &fl, AF_INET) < 0) |
| 95 | return -1; | 88 | return -1; |
| 96 | 89 | ||
| 97 | dst = (*pskb)->dst; | 90 | dst = skb->dst; |
| 98 | if (dst->xfrm) | 91 | if (dst->xfrm) |
| 99 | dst = ((struct xfrm_dst *)dst)->route; | 92 | dst = ((struct xfrm_dst *)dst)->route; |
| 100 | dst_hold(dst); | 93 | dst_hold(dst); |
| 101 | 94 | ||
| 102 | if (xfrm_lookup(&dst, &fl, (*pskb)->sk, 0) < 0) | 95 | if (xfrm_lookup(&dst, &fl, skb->sk, 0) < 0) |
| 103 | return -1; | 96 | return -1; |
| 104 | 97 | ||
| 105 | dst_release((*pskb)->dst); | 98 | dst_release(skb->dst); |
| 106 | (*pskb)->dst = dst; | 99 | skb->dst = dst; |
| 107 | 100 | ||
| 108 | /* Change in oif may mean change in hh_len. */ | 101 | /* Change in oif may mean change in hh_len. */ |
| 109 | hh_len = (*pskb)->dst->dev->hard_header_len; | 102 | hh_len = skb->dst->dev->hard_header_len; |
| 110 | if (skb_headroom(*pskb) < hh_len) { | 103 | if (skb_headroom(skb) < hh_len && |
| 111 | struct sk_buff *nskb; | 104 | pskb_expand_head(skb, hh_len - skb_headroom(skb), 0, GFP_ATOMIC)) |
| 112 | 105 | return -1; | |
| 113 | nskb = skb_realloc_headroom(*pskb, hh_len); | ||
| 114 | if (!nskb) | ||
| 115 | return -1; | ||
| 116 | if ((*pskb)->sk) | ||
| 117 | skb_set_owner_w(nskb, (*pskb)->sk); | ||
| 118 | kfree_skb(*pskb); | ||
| 119 | *pskb = nskb; | ||
| 120 | } | ||
| 121 | return 0; | 106 | return 0; |
| 122 | } | 107 | } |
| 123 | EXPORT_SYMBOL(ip_xfrm_me_harder); | 108 | EXPORT_SYMBOL(ip_xfrm_me_harder); |
| @@ -150,17 +135,17 @@ static void nf_ip_saveroute(const struct sk_buff *skb, struct nf_info *info) | |||
| 150 | } | 135 | } |
| 151 | } | 136 | } |
| 152 | 137 | ||
| 153 | static int nf_ip_reroute(struct sk_buff **pskb, const struct nf_info *info) | 138 | static int nf_ip_reroute(struct sk_buff *skb, const struct nf_info *info) |
| 154 | { | 139 | { |
| 155 | const struct ip_rt_info *rt_info = nf_info_reroute(info); | 140 | const struct ip_rt_info *rt_info = nf_info_reroute(info); |
| 156 | 141 | ||
| 157 | if (info->hook == NF_IP_LOCAL_OUT) { | 142 | if (info->hook == NF_IP_LOCAL_OUT) { |
| 158 | const struct iphdr *iph = ip_hdr(*pskb); | 143 | const struct iphdr *iph = ip_hdr(skb); |
| 159 | 144 | ||
| 160 | if (!(iph->tos == rt_info->tos | 145 | if (!(iph->tos == rt_info->tos |
| 161 | && iph->daddr == rt_info->daddr | 146 | && iph->daddr == rt_info->daddr |
| 162 | && iph->saddr == rt_info->saddr)) | 147 | && iph->saddr == rt_info->saddr)) |
| 163 | return ip_route_me_harder(pskb, RTN_UNSPEC); | 148 | return ip_route_me_harder(skb, RTN_UNSPEC); |
| 164 | } | 149 | } |
| 165 | return 0; | 150 | return 0; |
| 166 | } | 151 | } |
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 29114a9ccd1d..2909c92ecd99 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
| @@ -197,7 +197,7 @@ static inline int arp_checkentry(const struct arpt_arp *arp) | |||
| 197 | return 1; | 197 | return 1; |
| 198 | } | 198 | } |
| 199 | 199 | ||
| 200 | static unsigned int arpt_error(struct sk_buff **pskb, | 200 | static unsigned int arpt_error(struct sk_buff *skb, |
| 201 | const struct net_device *in, | 201 | const struct net_device *in, |
| 202 | const struct net_device *out, | 202 | const struct net_device *out, |
| 203 | unsigned int hooknum, | 203 | unsigned int hooknum, |
| @@ -215,7 +215,7 @@ static inline struct arpt_entry *get_entry(void *base, unsigned int offset) | |||
| 215 | return (struct arpt_entry *)(base + offset); | 215 | return (struct arpt_entry *)(base + offset); |
| 216 | } | 216 | } |
| 217 | 217 | ||
| 218 | unsigned int arpt_do_table(struct sk_buff **pskb, | 218 | unsigned int arpt_do_table(struct sk_buff *skb, |
| 219 | unsigned int hook, | 219 | unsigned int hook, |
| 220 | const struct net_device *in, | 220 | const struct net_device *in, |
| 221 | const struct net_device *out, | 221 | const struct net_device *out, |
| @@ -231,9 +231,9 @@ unsigned int arpt_do_table(struct sk_buff **pskb, | |||
| 231 | struct xt_table_info *private; | 231 | struct xt_table_info *private; |
| 232 | 232 | ||
| 233 | /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ | 233 | /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ |
| 234 | if (!pskb_may_pull((*pskb), (sizeof(struct arphdr) + | 234 | if (!pskb_may_pull(skb, (sizeof(struct arphdr) + |
| 235 | (2 * (*pskb)->dev->addr_len) + | 235 | (2 * skb->dev->addr_len) + |
| 236 | (2 * sizeof(u32))))) | 236 | (2 * sizeof(u32))))) |
| 237 | return NF_DROP; | 237 | return NF_DROP; |
| 238 | 238 | ||
| 239 | indev = in ? in->name : nulldevname; | 239 | indev = in ? in->name : nulldevname; |
| @@ -245,14 +245,14 @@ unsigned int arpt_do_table(struct sk_buff **pskb, | |||
| 245 | e = get_entry(table_base, private->hook_entry[hook]); | 245 | e = get_entry(table_base, private->hook_entry[hook]); |
| 246 | back = get_entry(table_base, private->underflow[hook]); | 246 | back = get_entry(table_base, private->underflow[hook]); |
| 247 | 247 | ||
| 248 | arp = arp_hdr(*pskb); | 248 | arp = arp_hdr(skb); |
| 249 | do { | 249 | do { |
| 250 | if (arp_packet_match(arp, (*pskb)->dev, indev, outdev, &e->arp)) { | 250 | if (arp_packet_match(arp, skb->dev, indev, outdev, &e->arp)) { |
| 251 | struct arpt_entry_target *t; | 251 | struct arpt_entry_target *t; |
| 252 | int hdr_len; | 252 | int hdr_len; |
| 253 | 253 | ||
| 254 | hdr_len = sizeof(*arp) + (2 * sizeof(struct in_addr)) + | 254 | hdr_len = sizeof(*arp) + (2 * sizeof(struct in_addr)) + |
| 255 | (2 * (*pskb)->dev->addr_len); | 255 | (2 * skb->dev->addr_len); |
| 256 | ADD_COUNTER(e->counters, hdr_len, 1); | 256 | ADD_COUNTER(e->counters, hdr_len, 1); |
| 257 | 257 | ||
| 258 | t = arpt_get_target(e); | 258 | t = arpt_get_target(e); |
| @@ -290,14 +290,14 @@ unsigned int arpt_do_table(struct sk_buff **pskb, | |||
| 290 | /* Targets which reenter must return | 290 | /* Targets which reenter must return |
| 291 | * abs. verdicts | 291 | * abs. verdicts |
| 292 | */ | 292 | */ |
| 293 | verdict = t->u.kernel.target->target(pskb, | 293 | verdict = t->u.kernel.target->target(skb, |
| 294 | in, out, | 294 | in, out, |
| 295 | hook, | 295 | hook, |
| 296 | t->u.kernel.target, | 296 | t->u.kernel.target, |
| 297 | t->data); | 297 | t->data); |
| 298 | 298 | ||
| 299 | /* Target might have changed stuff. */ | 299 | /* Target might have changed stuff. */ |
| 300 | arp = arp_hdr(*pskb); | 300 | arp = arp_hdr(skb); |
| 301 | 301 | ||
| 302 | if (verdict == ARPT_CONTINUE) | 302 | if (verdict == ARPT_CONTINUE) |
| 303 | e = (void *)e + e->next_offset; | 303 | e = (void *)e + e->next_offset; |
diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c index c4bdab47597f..45fa4e20094a 100644 --- a/net/ipv4/netfilter/arpt_mangle.c +++ b/net/ipv4/netfilter/arpt_mangle.c | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | /* module that allows mangling of the arp payload */ | 1 | /* module that allows mangling of the arp payload */ |
| 2 | #include <linux/module.h> | 2 | #include <linux/module.h> |
| 3 | #include <linux/netfilter.h> | ||
| 3 | #include <linux/netfilter_arp/arpt_mangle.h> | 4 | #include <linux/netfilter_arp/arpt_mangle.h> |
| 4 | #include <net/sock.h> | 5 | #include <net/sock.h> |
| 5 | 6 | ||
| @@ -8,7 +9,7 @@ MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); | |||
| 8 | MODULE_DESCRIPTION("arptables arp payload mangle target"); | 9 | MODULE_DESCRIPTION("arptables arp payload mangle target"); |
| 9 | 10 | ||
| 10 | static unsigned int | 11 | static unsigned int |
| 11 | target(struct sk_buff **pskb, | 12 | target(struct sk_buff *skb, |
| 12 | const struct net_device *in, const struct net_device *out, | 13 | const struct net_device *in, const struct net_device *out, |
| 13 | unsigned int hooknum, const struct xt_target *target, | 14 | unsigned int hooknum, const struct xt_target *target, |
| 14 | const void *targinfo) | 15 | const void *targinfo) |
| @@ -18,47 +19,38 @@ target(struct sk_buff **pskb, | |||
| 18 | unsigned char *arpptr; | 19 | unsigned char *arpptr; |
| 19 | int pln, hln; | 20 | int pln, hln; |
| 20 | 21 | ||
| 21 | if (skb_shared(*pskb) || skb_cloned(*pskb)) { | 22 | if (skb_make_writable(skb, skb->len)) |
| 22 | struct sk_buff *nskb; | 23 | return NF_DROP; |
| 23 | 24 | ||
| 24 | nskb = skb_copy(*pskb, GFP_ATOMIC); | 25 | arp = arp_hdr(skb); |
| 25 | if (!nskb) | 26 | arpptr = skb_network_header(skb) + sizeof(*arp); |
| 26 | return NF_DROP; | ||
| 27 | if ((*pskb)->sk) | ||
| 28 | skb_set_owner_w(nskb, (*pskb)->sk); | ||
| 29 | kfree_skb(*pskb); | ||
| 30 | *pskb = nskb; | ||
| 31 | } | ||
| 32 | |||
| 33 | arp = arp_hdr(*pskb); | ||
| 34 | arpptr = skb_network_header(*pskb) + sizeof(*arp); | ||
| 35 | pln = arp->ar_pln; | 27 | pln = arp->ar_pln; |
| 36 | hln = arp->ar_hln; | 28 | hln = arp->ar_hln; |
| 37 | /* We assume that pln and hln were checked in the match */ | 29 | /* We assume that pln and hln were checked in the match */ |
| 38 | if (mangle->flags & ARPT_MANGLE_SDEV) { | 30 | if (mangle->flags & ARPT_MANGLE_SDEV) { |
| 39 | if (ARPT_DEV_ADDR_LEN_MAX < hln || | 31 | if (ARPT_DEV_ADDR_LEN_MAX < hln || |
| 40 | (arpptr + hln > skb_tail_pointer(*pskb))) | 32 | (arpptr + hln > skb_tail_pointer(skb))) |
| 41 | return NF_DROP; | 33 | return NF_DROP; |
| 42 | memcpy(arpptr, mangle->src_devaddr, hln); | 34 | memcpy(arpptr, mangle->src_devaddr, hln); |
| 43 | } | 35 | } |
| 44 | arpptr += hln; | 36 | arpptr += hln; |
| 45 | if (mangle->flags & ARPT_MANGLE_SIP) { | 37 | if (mangle->flags & ARPT_MANGLE_SIP) { |
| 46 | if (ARPT_MANGLE_ADDR_LEN_MAX < pln || | 38 | if (ARPT_MANGLE_ADDR_LEN_MAX < pln || |
| 47 | (arpptr + pln > skb_tail_pointer(*pskb))) | 39 | (arpptr + pln > skb_tail_pointer(skb))) |
| 48 | return NF_DROP; | 40 | return NF_DROP; |
| 49 | memcpy(arpptr, &mangle->u_s.src_ip, pln); | 41 | memcpy(arpptr, &mangle->u_s.src_ip, pln); |
| 50 | } | 42 | } |
| 51 | arpptr += pln; | 43 | arpptr += pln; |
| 52 | if (mangle->flags & ARPT_MANGLE_TDEV) { | 44 | if (mangle->flags & ARPT_MANGLE_TDEV) { |
| 53 | if (ARPT_DEV_ADDR_LEN_MAX < hln || | 45 | if (ARPT_DEV_ADDR_LEN_MAX < hln || |
| 54 | (arpptr + hln > skb_tail_pointer(*pskb))) | 46 | (arpptr + hln > skb_tail_pointer(skb))) |
| 55 | return NF_DROP; | 47 | return NF_DROP; |
| 56 | memcpy(arpptr, mangle->tgt_devaddr, hln); | 48 | memcpy(arpptr, mangle->tgt_devaddr, hln); |
| 57 | } | 49 | } |
| 58 | arpptr += hln; | 50 | arpptr += hln; |
| 59 | if (mangle->flags & ARPT_MANGLE_TIP) { | 51 | if (mangle->flags & ARPT_MANGLE_TIP) { |
| 60 | if (ARPT_MANGLE_ADDR_LEN_MAX < pln || | 52 | if (ARPT_MANGLE_ADDR_LEN_MAX < pln || |
| 61 | (arpptr + pln > skb_tail_pointer(*pskb))) | 53 | (arpptr + pln > skb_tail_pointer(skb))) |
| 62 | return NF_DROP; | 54 | return NF_DROP; |
| 63 | memcpy(arpptr, &mangle->u_t.tgt_ip, pln); | 55 | memcpy(arpptr, &mangle->u_t.tgt_ip, pln); |
| 64 | } | 56 | } |
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c index 75c023062533..302d3da5f696 100644 --- a/net/ipv4/netfilter/arptable_filter.c +++ b/net/ipv4/netfilter/arptable_filter.c | |||
| @@ -56,12 +56,12 @@ static struct arpt_table packet_filter = { | |||
| 56 | 56 | ||
| 57 | /* The work comes in here from netfilter.c */ | 57 | /* The work comes in here from netfilter.c */ |
| 58 | static unsigned int arpt_hook(unsigned int hook, | 58 | static unsigned int arpt_hook(unsigned int hook, |
| 59 | struct sk_buff **pskb, | 59 | struct sk_buff *skb, |
| 60 | const struct net_device *in, | 60 | const struct net_device *in, |
| 61 | const struct net_device *out, | 61 | const struct net_device *out, |
| 62 | int (*okfn)(struct sk_buff *)) | 62 | int (*okfn)(struct sk_buff *)) |
| 63 | { | 63 | { |
| 64 | return arpt_do_table(pskb, hook, in, out, &packet_filter); | 64 | return arpt_do_table(skb, hook, in, out, &packet_filter); |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | static struct nf_hook_ops arpt_ops[] = { | 67 | static struct nf_hook_ops arpt_ops[] = { |
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 23cbfc7c80fd..10a2ce09fd8e 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c | |||
| @@ -335,6 +335,7 @@ static int | |||
| 335 | ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) | 335 | ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) |
| 336 | { | 336 | { |
| 337 | int diff; | 337 | int diff; |
| 338 | int err; | ||
| 338 | struct iphdr *user_iph = (struct iphdr *)v->payload; | 339 | struct iphdr *user_iph = (struct iphdr *)v->payload; |
| 339 | 340 | ||
| 340 | if (v->data_len < sizeof(*user_iph)) | 341 | if (v->data_len < sizeof(*user_iph)) |
| @@ -347,25 +348,18 @@ ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) | |||
| 347 | if (v->data_len > 0xFFFF) | 348 | if (v->data_len > 0xFFFF) |
| 348 | return -EINVAL; | 349 | return -EINVAL; |
| 349 | if (diff > skb_tailroom(e->skb)) { | 350 | if (diff > skb_tailroom(e->skb)) { |
| 350 | struct sk_buff *newskb; | 351 | err = pskb_expand_head(e->skb, 0, |
| 351 | 352 | diff - skb_tailroom(e->skb), | |
| 352 | newskb = skb_copy_expand(e->skb, | 353 | GFP_ATOMIC); |
| 353 | skb_headroom(e->skb), | 354 | if (err) { |
| 354 | diff, | 355 | printk(KERN_WARNING "ip_queue: error " |
| 355 | GFP_ATOMIC); | 356 | "in mangle, dropping packet: %d\n", -err); |
| 356 | if (newskb == NULL) { | 357 | return err; |
| 357 | printk(KERN_WARNING "ip_queue: OOM " | ||
| 358 | "in mangle, dropping packet\n"); | ||
| 359 | return -ENOMEM; | ||
| 360 | } | 358 | } |
| 361 | if (e->skb->sk) | ||
| 362 | skb_set_owner_w(newskb, e->skb->sk); | ||
| 363 | kfree_skb(e->skb); | ||
| 364 | e->skb = newskb; | ||
| 365 | } | 359 | } |
| 366 | skb_put(e->skb, diff); | 360 | skb_put(e->skb, diff); |
| 367 | } | 361 | } |
| 368 | if (!skb_make_writable(&e->skb, v->data_len)) | 362 | if (!skb_make_writable(e->skb, v->data_len)) |
| 369 | return -ENOMEM; | 363 | return -ENOMEM; |
| 370 | skb_copy_to_linear_data(e->skb, v->payload, v->data_len); | 364 | skb_copy_to_linear_data(e->skb, v->payload, v->data_len); |
| 371 | e->skb->ip_summed = CHECKSUM_NONE; | 365 | e->skb->ip_summed = CHECKSUM_NONE; |
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 6486894f450c..4b10b98640ac 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
| @@ -169,7 +169,7 @@ ip_checkentry(const struct ipt_ip *ip) | |||
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | static unsigned int | 171 | static unsigned int |
| 172 | ipt_error(struct sk_buff **pskb, | 172 | ipt_error(struct sk_buff *skb, |
| 173 | const struct net_device *in, | 173 | const struct net_device *in, |
| 174 | const struct net_device *out, | 174 | const struct net_device *out, |
| 175 | unsigned int hooknum, | 175 | unsigned int hooknum, |
| @@ -312,7 +312,7 @@ static void trace_packet(struct sk_buff *skb, | |||
| 312 | 312 | ||
| 313 | /* Returns one of the generic firewall policies, like NF_ACCEPT. */ | 313 | /* Returns one of the generic firewall policies, like NF_ACCEPT. */ |
| 314 | unsigned int | 314 | unsigned int |
| 315 | ipt_do_table(struct sk_buff **pskb, | 315 | ipt_do_table(struct sk_buff *skb, |
| 316 | unsigned int hook, | 316 | unsigned int hook, |
| 317 | const struct net_device *in, | 317 | const struct net_device *in, |
| 318 | const struct net_device *out, | 318 | const struct net_device *out, |
| @@ -331,8 +331,8 @@ ipt_do_table(struct sk_buff **pskb, | |||
| 331 | struct xt_table_info *private; | 331 | struct xt_table_info *private; |
| 332 | 332 | ||
| 333 | /* Initialization */ | 333 | /* Initialization */ |
| 334 | ip = ip_hdr(*pskb); | 334 | ip = ip_hdr(skb); |
| 335 | datalen = (*pskb)->len - ip->ihl * 4; | 335 | datalen = skb->len - ip->ihl * 4; |
| 336 | indev = in ? in->name : nulldevname; | 336 | indev = in ? in->name : nulldevname; |
| 337 | outdev = out ? out->name : nulldevname; | 337 | outdev = out ? out->name : nulldevname; |
| 338 | /* We handle fragments by dealing with the first fragment as | 338 | /* We handle fragments by dealing with the first fragment as |
| @@ -359,7 +359,7 @@ ipt_do_table(struct sk_buff **pskb, | |||
| 359 | struct ipt_entry_target *t; | 359 | struct ipt_entry_target *t; |
| 360 | 360 | ||
| 361 | if (IPT_MATCH_ITERATE(e, do_match, | 361 | if (IPT_MATCH_ITERATE(e, do_match, |
| 362 | *pskb, in, out, | 362 | skb, in, out, |
| 363 | offset, &hotdrop) != 0) | 363 | offset, &hotdrop) != 0) |
| 364 | goto no_match; | 364 | goto no_match; |
| 365 | 365 | ||
| @@ -371,8 +371,8 @@ ipt_do_table(struct sk_buff **pskb, | |||
| 371 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | 371 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ |
| 372 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | 372 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) |
| 373 | /* The packet is traced: log it */ | 373 | /* The packet is traced: log it */ |
| 374 | if (unlikely((*pskb)->nf_trace)) | 374 | if (unlikely(skb->nf_trace)) |
| 375 | trace_packet(*pskb, hook, in, out, | 375 | trace_packet(skb, hook, in, out, |
| 376 | table->name, private, e); | 376 | table->name, private, e); |
| 377 | #endif | 377 | #endif |
| 378 | /* Standard target? */ | 378 | /* Standard target? */ |
| @@ -410,7 +410,7 @@ ipt_do_table(struct sk_buff **pskb, | |||
| 410 | ((struct ipt_entry *)table_base)->comefrom | 410 | ((struct ipt_entry *)table_base)->comefrom |
| 411 | = 0xeeeeeeec; | 411 | = 0xeeeeeeec; |
| 412 | #endif | 412 | #endif |
| 413 | verdict = t->u.kernel.target->target(pskb, | 413 | verdict = t->u.kernel.target->target(skb, |
| 414 | in, out, | 414 | in, out, |
| 415 | hook, | 415 | hook, |
| 416 | t->u.kernel.target, | 416 | t->u.kernel.target, |
| @@ -428,8 +428,8 @@ ipt_do_table(struct sk_buff **pskb, | |||
| 428 | = 0x57acc001; | 428 | = 0x57acc001; |
| 429 | #endif | 429 | #endif |
| 430 | /* Target might have changed stuff. */ | 430 | /* Target might have changed stuff. */ |
| 431 | ip = ip_hdr(*pskb); | 431 | ip = ip_hdr(skb); |
| 432 | datalen = (*pskb)->len - ip->ihl * 4; | 432 | datalen = skb->len - ip->ihl * 4; |
| 433 | 433 | ||
| 434 | if (verdict == IPT_CONTINUE) | 434 | if (verdict == IPT_CONTINUE) |
| 435 | e = (void *)e + e->next_offset; | 435 | e = (void *)e + e->next_offset; |
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 27f14e1ebd8b..2f544dac72df 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c | |||
| @@ -289,7 +289,7 @@ clusterip_responsible(const struct clusterip_config *config, u_int32_t hash) | |||
| 289 | ***********************************************************************/ | 289 | ***********************************************************************/ |
| 290 | 290 | ||
| 291 | static unsigned int | 291 | static unsigned int |
| 292 | target(struct sk_buff **pskb, | 292 | target(struct sk_buff *skb, |
| 293 | const struct net_device *in, | 293 | const struct net_device *in, |
| 294 | const struct net_device *out, | 294 | const struct net_device *out, |
| 295 | unsigned int hooknum, | 295 | unsigned int hooknum, |
| @@ -305,7 +305,7 @@ target(struct sk_buff **pskb, | |||
| 305 | * is only decremented by destroy() - and ip_tables guarantees | 305 | * is only decremented by destroy() - and ip_tables guarantees |
| 306 | * that the ->target() function isn't called after ->destroy() */ | 306 | * that the ->target() function isn't called after ->destroy() */ |
| 307 | 307 | ||
| 308 | ct = nf_ct_get(*pskb, &ctinfo); | 308 | ct = nf_ct_get(skb, &ctinfo); |
| 309 | if (ct == NULL) { | 309 | if (ct == NULL) { |
| 310 | printk(KERN_ERR "CLUSTERIP: no conntrack!\n"); | 310 | printk(KERN_ERR "CLUSTERIP: no conntrack!\n"); |
| 311 | /* FIXME: need to drop invalid ones, since replies | 311 | /* FIXME: need to drop invalid ones, since replies |
| @@ -316,7 +316,7 @@ target(struct sk_buff **pskb, | |||
| 316 | 316 | ||
| 317 | /* special case: ICMP error handling. conntrack distinguishes between | 317 | /* special case: ICMP error handling. conntrack distinguishes between |
| 318 | * error messages (RELATED) and information requests (see below) */ | 318 | * error messages (RELATED) and information requests (see below) */ |
| 319 | if (ip_hdr(*pskb)->protocol == IPPROTO_ICMP | 319 | if (ip_hdr(skb)->protocol == IPPROTO_ICMP |
| 320 | && (ctinfo == IP_CT_RELATED | 320 | && (ctinfo == IP_CT_RELATED |
| 321 | || ctinfo == IP_CT_RELATED+IP_CT_IS_REPLY)) | 321 | || ctinfo == IP_CT_RELATED+IP_CT_IS_REPLY)) |
| 322 | return XT_CONTINUE; | 322 | return XT_CONTINUE; |
| @@ -325,7 +325,7 @@ target(struct sk_buff **pskb, | |||
| 325 | * TIMESTAMP, INFO_REQUEST or ADDRESS type icmp packets from here | 325 | * TIMESTAMP, INFO_REQUEST or ADDRESS type icmp packets from here |
| 326 | * on, which all have an ID field [relevant for hashing]. */ | 326 | * on, which all have an ID field [relevant for hashing]. */ |
| 327 | 327 | ||
| 328 | hash = clusterip_hashfn(*pskb, cipinfo->config); | 328 | hash = clusterip_hashfn(skb, cipinfo->config); |
| 329 | 329 | ||
| 330 | switch (ctinfo) { | 330 | switch (ctinfo) { |
| 331 | case IP_CT_NEW: | 331 | case IP_CT_NEW: |
| @@ -355,7 +355,7 @@ target(struct sk_buff **pskb, | |||
| 355 | 355 | ||
| 356 | /* despite being received via linklayer multicast, this is | 356 | /* despite being received via linklayer multicast, this is |
| 357 | * actually a unicast IP packet. TCP doesn't like PACKET_MULTICAST */ | 357 | * actually a unicast IP packet. TCP doesn't like PACKET_MULTICAST */ |
| 358 | (*pskb)->pkt_type = PACKET_HOST; | 358 | skb->pkt_type = PACKET_HOST; |
| 359 | 359 | ||
| 360 | return XT_CONTINUE; | 360 | return XT_CONTINUE; |
| 361 | } | 361 | } |
| @@ -505,12 +505,12 @@ static void arp_print(struct arp_payload *payload) | |||
| 505 | 505 | ||
| 506 | static unsigned int | 506 | static unsigned int |
| 507 | arp_mangle(unsigned int hook, | 507 | arp_mangle(unsigned int hook, |
| 508 | struct sk_buff **pskb, | 508 | struct sk_buff *skb, |
| 509 | const struct net_device *in, | 509 | const struct net_device *in, |
| 510 | const struct net_device *out, | 510 | const struct net_device *out, |
| 511 | int (*okfn)(struct sk_buff *)) | 511 | int (*okfn)(struct sk_buff *)) |
| 512 | { | 512 | { |
| 513 | struct arphdr *arp = arp_hdr(*pskb); | 513 | struct arphdr *arp = arp_hdr(skb); |
| 514 | struct arp_payload *payload; | 514 | struct arp_payload *payload; |
| 515 | struct clusterip_config *c; | 515 | struct clusterip_config *c; |
| 516 | 516 | ||
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c index f1253bd3837f..add110060a22 100644 --- a/net/ipv4/netfilter/ipt_ECN.c +++ b/net/ipv4/netfilter/ipt_ECN.c | |||
| @@ -26,15 +26,15 @@ MODULE_DESCRIPTION("iptables ECN modification module"); | |||
| 26 | /* set ECT codepoint from IP header. | 26 | /* set ECT codepoint from IP header. |
| 27 | * return false if there was an error. */ | 27 | * return false if there was an error. */ |
| 28 | static inline bool | 28 | static inline bool |
| 29 | set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) | 29 | set_ect_ip(struct sk_buff *skb, const struct ipt_ECN_info *einfo) |
| 30 | { | 30 | { |
| 31 | struct iphdr *iph = ip_hdr(*pskb); | 31 | struct iphdr *iph = ip_hdr(skb); |
| 32 | 32 | ||
| 33 | if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) { | 33 | if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) { |
| 34 | __u8 oldtos; | 34 | __u8 oldtos; |
| 35 | if (!skb_make_writable(pskb, sizeof(struct iphdr))) | 35 | if (!skb_make_writable(skb, sizeof(struct iphdr))) |
| 36 | return false; | 36 | return false; |
| 37 | iph = ip_hdr(*pskb); | 37 | iph = ip_hdr(skb); |
| 38 | oldtos = iph->tos; | 38 | oldtos = iph->tos; |
| 39 | iph->tos &= ~IPT_ECN_IP_MASK; | 39 | iph->tos &= ~IPT_ECN_IP_MASK; |
| 40 | iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK); | 40 | iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK); |
| @@ -45,14 +45,13 @@ set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) | |||
| 45 | 45 | ||
| 46 | /* Return false if there was an error. */ | 46 | /* Return false if there was an error. */ |
| 47 | static inline bool | 47 | static inline bool |
| 48 | set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) | 48 | set_ect_tcp(struct sk_buff *skb, const struct ipt_ECN_info *einfo) |
| 49 | { | 49 | { |
| 50 | struct tcphdr _tcph, *tcph; | 50 | struct tcphdr _tcph, *tcph; |
| 51 | __be16 oldval; | 51 | __be16 oldval; |
| 52 | 52 | ||
| 53 | /* Not enought header? */ | 53 | /* Not enought header? */ |
| 54 | tcph = skb_header_pointer(*pskb, ip_hdrlen(*pskb), | 54 | tcph = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_tcph), &_tcph); |
| 55 | sizeof(_tcph), &_tcph); | ||
| 56 | if (!tcph) | 55 | if (!tcph) |
| 57 | return false; | 56 | return false; |
| 58 | 57 | ||
| @@ -62,9 +61,9 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) | |||
| 62 | tcph->cwr == einfo->proto.tcp.cwr)) | 61 | tcph->cwr == einfo->proto.tcp.cwr)) |
| 63 | return true; | 62 | return true; |
| 64 | 63 | ||
| 65 | if (!skb_make_writable(pskb, ip_hdrlen(*pskb) + sizeof(*tcph))) | 64 | if (!skb_make_writable(skb, ip_hdrlen(skb) + sizeof(*tcph))) |
| 66 | return false; | 65 | return false; |
| 67 | tcph = (void *)ip_hdr(*pskb) + ip_hdrlen(*pskb); | 66 | tcph = (void *)ip_hdr(skb) + ip_hdrlen(skb); |
| 68 | 67 | ||
| 69 | oldval = ((__be16 *)tcph)[6]; | 68 | oldval = ((__be16 *)tcph)[6]; |
| 70 | if (einfo->operation & IPT_ECN_OP_SET_ECE) | 69 | if (einfo->operation & IPT_ECN_OP_SET_ECE) |
| @@ -72,13 +71,13 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) | |||
| 72 | if (einfo->operation & IPT_ECN_OP_SET_CWR) | 71 | if (einfo->operation & IPT_ECN_OP_SET_CWR) |
| 73 | tcph->cwr = einfo->proto.tcp.cwr; | 72 | tcph->cwr = einfo->proto.tcp.cwr; |
| 74 | 73 | ||
| 75 | nf_proto_csum_replace2(&tcph->check, *pskb, | 74 | nf_proto_csum_replace2(&tcph->check, skb, |
| 76 | oldval, ((__be16 *)tcph)[6], 0); | 75 | oldval, ((__be16 *)tcph)[6], 0); |
| 77 | return true; | 76 | return true; |
| 78 | } | 77 | } |
| 79 | 78 | ||
| 80 | static unsigned int | 79 | static unsigned int |
| 81 | target(struct sk_buff **pskb, | 80 | target(struct sk_buff *skb, |
| 82 | const struct net_device *in, | 81 | const struct net_device *in, |
| 83 | const struct net_device *out, | 82 | const struct net_device *out, |
| 84 | unsigned int hooknum, | 83 | unsigned int hooknum, |
| @@ -88,12 +87,12 @@ target(struct sk_buff **pskb, | |||
| 88 | const struct ipt_ECN_info *einfo = targinfo; | 87 | const struct ipt_ECN_info *einfo = targinfo; |
| 89 | 88 | ||
| 90 | if (einfo->operation & IPT_ECN_OP_SET_IP) | 89 | if (einfo->operation & IPT_ECN_OP_SET_IP) |
| 91 | if (!set_ect_ip(pskb, einfo)) | 90 | if (!set_ect_ip(skb, einfo)) |
| 92 | return NF_DROP; | 91 | return NF_DROP; |
| 93 | 92 | ||
| 94 | if (einfo->operation & (IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR) | 93 | if (einfo->operation & (IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR) |
| 95 | && ip_hdr(*pskb)->protocol == IPPROTO_TCP) | 94 | && ip_hdr(skb)->protocol == IPPROTO_TCP) |
| 96 | if (!set_ect_tcp(pskb, einfo)) | 95 | if (!set_ect_tcp(skb, einfo)) |
| 97 | return NF_DROP; | 96 | return NF_DROP; |
| 98 | 97 | ||
| 99 | return XT_CONTINUE; | 98 | return XT_CONTINUE; |
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c index 127a5e89bf14..4b5e8216a4e7 100644 --- a/net/ipv4/netfilter/ipt_LOG.c +++ b/net/ipv4/netfilter/ipt_LOG.c | |||
| @@ -418,7 +418,7 @@ ipt_log_packet(unsigned int pf, | |||
| 418 | } | 418 | } |
| 419 | 419 | ||
| 420 | static unsigned int | 420 | static unsigned int |
| 421 | ipt_log_target(struct sk_buff **pskb, | 421 | ipt_log_target(struct sk_buff *skb, |
| 422 | const struct net_device *in, | 422 | const struct net_device *in, |
| 423 | const struct net_device *out, | 423 | const struct net_device *out, |
| 424 | unsigned int hooknum, | 424 | unsigned int hooknum, |
| @@ -432,7 +432,7 @@ ipt_log_target(struct sk_buff **pskb, | |||
| 432 | li.u.log.level = loginfo->level; | 432 | li.u.log.level = loginfo->level; |
| 433 | li.u.log.logflags = loginfo->logflags; | 433 | li.u.log.logflags = loginfo->logflags; |
| 434 | 434 | ||
| 435 | ipt_log_packet(PF_INET, hooknum, *pskb, in, out, &li, | 435 | ipt_log_packet(PF_INET, hooknum, skb, in, out, &li, |
| 436 | loginfo->prefix); | 436 | loginfo->prefix); |
| 437 | return XT_CONTINUE; | 437 | return XT_CONTINUE; |
| 438 | } | 438 | } |
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index 3e0b562b2db7..44b516e7cb79 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c | |||
| @@ -52,7 +52,7 @@ masquerade_check(const char *tablename, | |||
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | static unsigned int | 54 | static unsigned int |
| 55 | masquerade_target(struct sk_buff **pskb, | 55 | masquerade_target(struct sk_buff *skb, |
| 56 | const struct net_device *in, | 56 | const struct net_device *in, |
| 57 | const struct net_device *out, | 57 | const struct net_device *out, |
| 58 | unsigned int hooknum, | 58 | unsigned int hooknum, |
| @@ -69,7 +69,7 @@ masquerade_target(struct sk_buff **pskb, | |||
| 69 | 69 | ||
| 70 | NF_CT_ASSERT(hooknum == NF_IP_POST_ROUTING); | 70 | NF_CT_ASSERT(hooknum == NF_IP_POST_ROUTING); |
| 71 | 71 | ||
| 72 | ct = nf_ct_get(*pskb, &ctinfo); | 72 | ct = nf_ct_get(skb, &ctinfo); |
| 73 | nat = nfct_nat(ct); | 73 | nat = nfct_nat(ct); |
| 74 | 74 | ||
| 75 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED | 75 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED |
| @@ -82,7 +82,7 @@ masquerade_target(struct sk_buff **pskb, | |||
| 82 | return NF_ACCEPT; | 82 | return NF_ACCEPT; |
| 83 | 83 | ||
| 84 | mr = targinfo; | 84 | mr = targinfo; |
| 85 | rt = (struct rtable *)(*pskb)->dst; | 85 | rt = (struct rtable *)skb->dst; |
| 86 | newsrc = inet_select_addr(out, rt->rt_gateway, RT_SCOPE_UNIVERSE); | 86 | newsrc = inet_select_addr(out, rt->rt_gateway, RT_SCOPE_UNIVERSE); |
| 87 | if (!newsrc) { | 87 | if (!newsrc) { |
| 88 | printk("MASQUERADE: %s ate my IP address\n", out->name); | 88 | printk("MASQUERADE: %s ate my IP address\n", out->name); |
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c index 41a011d5a065..f8699291e33d 100644 --- a/net/ipv4/netfilter/ipt_NETMAP.c +++ b/net/ipv4/netfilter/ipt_NETMAP.c | |||
| @@ -43,7 +43,7 @@ check(const char *tablename, | |||
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | static unsigned int | 45 | static unsigned int |
| 46 | target(struct sk_buff **pskb, | 46 | target(struct sk_buff *skb, |
| 47 | const struct net_device *in, | 47 | const struct net_device *in, |
| 48 | const struct net_device *out, | 48 | const struct net_device *out, |
| 49 | unsigned int hooknum, | 49 | unsigned int hooknum, |
| @@ -59,14 +59,14 @@ target(struct sk_buff **pskb, | |||
| 59 | NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING | 59 | NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING |
| 60 | || hooknum == NF_IP_POST_ROUTING | 60 | || hooknum == NF_IP_POST_ROUTING |
| 61 | || hooknum == NF_IP_LOCAL_OUT); | 61 | || hooknum == NF_IP_LOCAL_OUT); |
| 62 | ct = nf_ct_get(*pskb, &ctinfo); | 62 | ct = nf_ct_get(skb, &ctinfo); |
| 63 | 63 | ||
| 64 | netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip); | 64 | netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip); |
| 65 | 65 | ||
| 66 | if (hooknum == NF_IP_PRE_ROUTING || hooknum == NF_IP_LOCAL_OUT) | 66 | if (hooknum == NF_IP_PRE_ROUTING || hooknum == NF_IP_LOCAL_OUT) |
| 67 | new_ip = ip_hdr(*pskb)->daddr & ~netmask; | 67 | new_ip = ip_hdr(skb)->daddr & ~netmask; |
| 68 | else | 68 | else |
| 69 | new_ip = ip_hdr(*pskb)->saddr & ~netmask; | 69 | new_ip = ip_hdr(skb)->saddr & ~netmask; |
| 70 | new_ip |= mr->range[0].min_ip & netmask; | 70 | new_ip |= mr->range[0].min_ip & netmask; |
| 71 | 71 | ||
| 72 | newrange = ((struct nf_nat_range) | 72 | newrange = ((struct nf_nat_range) |
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c index 6ac7a2373316..f7cf7d61a2d4 100644 --- a/net/ipv4/netfilter/ipt_REDIRECT.c +++ b/net/ipv4/netfilter/ipt_REDIRECT.c | |||
| @@ -47,7 +47,7 @@ redirect_check(const char *tablename, | |||
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | static unsigned int | 49 | static unsigned int |
| 50 | redirect_target(struct sk_buff **pskb, | 50 | redirect_target(struct sk_buff *skb, |
| 51 | const struct net_device *in, | 51 | const struct net_device *in, |
| 52 | const struct net_device *out, | 52 | const struct net_device *out, |
| 53 | unsigned int hooknum, | 53 | unsigned int hooknum, |
| @@ -63,7 +63,7 @@ redirect_target(struct sk_buff **pskb, | |||
| 63 | NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING | 63 | NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING |
| 64 | || hooknum == NF_IP_LOCAL_OUT); | 64 | || hooknum == NF_IP_LOCAL_OUT); |
| 65 | 65 | ||
| 66 | ct = nf_ct_get(*pskb, &ctinfo); | 66 | ct = nf_ct_get(skb, &ctinfo); |
| 67 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); | 67 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); |
| 68 | 68 | ||
| 69 | /* Local packets: make them go to loopback */ | 69 | /* Local packets: make them go to loopback */ |
| @@ -76,7 +76,7 @@ redirect_target(struct sk_buff **pskb, | |||
| 76 | newdst = 0; | 76 | newdst = 0; |
| 77 | 77 | ||
| 78 | rcu_read_lock(); | 78 | rcu_read_lock(); |
| 79 | indev = __in_dev_get_rcu((*pskb)->dev); | 79 | indev = __in_dev_get_rcu(skb->dev); |
| 80 | if (indev && (ifa = indev->ifa_list)) | 80 | if (indev && (ifa = indev->ifa_list)) |
| 81 | newdst = ifa->ifa_local; | 81 | newdst = ifa->ifa_local; |
| 82 | rcu_read_unlock(); | 82 | rcu_read_unlock(); |
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index cb038c8fbc9d..dcf4d21d5116 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c | |||
| @@ -131,7 +131,7 @@ static void send_reset(struct sk_buff *oldskb, int hook) | |||
| 131 | ) | 131 | ) |
| 132 | addr_type = RTN_LOCAL; | 132 | addr_type = RTN_LOCAL; |
| 133 | 133 | ||
| 134 | if (ip_route_me_harder(&nskb, addr_type)) | 134 | if (ip_route_me_harder(nskb, addr_type)) |
| 135 | goto free_nskb; | 135 | goto free_nskb; |
| 136 | 136 | ||
| 137 | nskb->ip_summed = CHECKSUM_NONE; | 137 | nskb->ip_summed = CHECKSUM_NONE; |
| @@ -162,7 +162,7 @@ static inline void send_unreach(struct sk_buff *skb_in, int code) | |||
| 162 | icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0); | 162 | icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0); |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | static unsigned int reject(struct sk_buff **pskb, | 165 | static unsigned int reject(struct sk_buff *skb, |
| 166 | const struct net_device *in, | 166 | const struct net_device *in, |
| 167 | const struct net_device *out, | 167 | const struct net_device *out, |
| 168 | unsigned int hooknum, | 168 | unsigned int hooknum, |
| @@ -173,7 +173,7 @@ static unsigned int reject(struct sk_buff **pskb, | |||
| 173 | 173 | ||
| 174 | /* Our naive response construction doesn't deal with IP | 174 | /* Our naive response construction doesn't deal with IP |
| 175 | options, and probably shouldn't try. */ | 175 | options, and probably shouldn't try. */ |
| 176 | if (ip_hdrlen(*pskb) != sizeof(struct iphdr)) | 176 | if (ip_hdrlen(skb) != sizeof(struct iphdr)) |
| 177 | return NF_DROP; | 177 | return NF_DROP; |
| 178 | 178 | ||
| 179 | /* WARNING: This code causes reentry within iptables. | 179 | /* WARNING: This code causes reentry within iptables. |
| @@ -181,28 +181,28 @@ static unsigned int reject(struct sk_buff **pskb, | |||
| 181 | must return an absolute verdict. --RR */ | 181 | must return an absolute verdict. --RR */ |
| 182 | switch (reject->with) { | 182 | switch (reject->with) { |
| 183 | case IPT_ICMP_NET_UNREACHABLE: | 183 | case IPT_ICMP_NET_UNREACHABLE: |
| 184 | send_unreach(*pskb, ICMP_NET_UNREACH); | 184 | send_unreach(skb, ICMP_NET_UNREACH); |
| 185 | break; | 185 | break; |
| 186 | case IPT_ICMP_HOST_UNREACHABLE: | 186 | case IPT_ICMP_HOST_UNREACHABLE: |
| 187 | send_unreach(*pskb, ICMP_HOST_UNREACH); | 187 | send_unreach(skb, ICMP_HOST_UNREACH); |
| 188 | break; | 188 | break; |
| 189 | case IPT_ICMP_PROT_UNREACHABLE: | 189 | case IPT_ICMP_PROT_UNREACHABLE: |
| 190 | send_unreach(*pskb, ICMP_PROT_UNREACH); | 190 | send_unreach(skb, ICMP_PROT_UNREACH); |
| 191 | break; | 191 | break; |
| 192 | case IPT_ICMP_PORT_UNREACHABLE: | 192 | case IPT_ICMP_PORT_UNREACHABLE: |
| 193 | send_unreach(*pskb, ICMP_PORT_UNREACH); | 193 | send_unreach(skb, ICMP_PORT_UNREACH); |
| 194 | break; | 194 | break; |
| 195 | case IPT_ICMP_NET_PROHIBITED: | 195 | case IPT_ICMP_NET_PROHIBITED: |
| 196 | send_unreach(*pskb, ICMP_NET_ANO); | 196 | send_unreach(skb, ICMP_NET_ANO); |
| 197 | break; | 197 | break; |
| 198 | case IPT_ICMP_HOST_PROHIBITED: | 198 | case IPT_ICMP_HOST_PROHIBITED: |
| 199 | send_unreach(*pskb, ICMP_HOST_ANO); | 199 | send_unreach(skb, ICMP_HOST_ANO); |
| 200 | break; | 200 | break; |
| 201 | case IPT_ICMP_ADMIN_PROHIBITED: | 201 | case IPT_ICMP_ADMIN_PROHIBITED: |
| 202 | send_unreach(*pskb, ICMP_PKT_FILTERED); | 202 | send_unreach(skb, ICMP_PKT_FILTERED); |
| 203 | break; | 203 | break; |
| 204 | case IPT_TCP_RESET: | 204 | case IPT_TCP_RESET: |
| 205 | send_reset(*pskb, hooknum); | 205 | send_reset(skb, hooknum); |
| 206 | case IPT_ICMP_ECHOREPLY: | 206 | case IPT_ICMP_ECHOREPLY: |
| 207 | /* Doesn't happen. */ | 207 | /* Doesn't happen. */ |
| 208 | break; | 208 | break; |
diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c index 97641f1a97f6..8988571436b8 100644 --- a/net/ipv4/netfilter/ipt_SAME.c +++ b/net/ipv4/netfilter/ipt_SAME.c | |||
| @@ -104,7 +104,7 @@ same_destroy(const struct xt_target *target, void *targinfo) | |||
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | static unsigned int | 106 | static unsigned int |
| 107 | same_target(struct sk_buff **pskb, | 107 | same_target(struct sk_buff *skb, |
| 108 | const struct net_device *in, | 108 | const struct net_device *in, |
| 109 | const struct net_device *out, | 109 | const struct net_device *out, |
| 110 | unsigned int hooknum, | 110 | unsigned int hooknum, |
| @@ -121,7 +121,7 @@ same_target(struct sk_buff **pskb, | |||
| 121 | 121 | ||
| 122 | NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING || | 122 | NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING || |
| 123 | hooknum == NF_IP_POST_ROUTING); | 123 | hooknum == NF_IP_POST_ROUTING); |
| 124 | ct = nf_ct_get(*pskb, &ctinfo); | 124 | ct = nf_ct_get(skb, &ctinfo); |
| 125 | 125 | ||
| 126 | t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; | 126 | t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; |
| 127 | 127 | ||
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c index 25f5d0b39065..d4573baa7f27 100644 --- a/net/ipv4/netfilter/ipt_TOS.c +++ b/net/ipv4/netfilter/ipt_TOS.c | |||
| @@ -21,7 +21,7 @@ MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | |||
| 21 | MODULE_DESCRIPTION("iptables TOS mangling module"); | 21 | MODULE_DESCRIPTION("iptables TOS mangling module"); |
| 22 | 22 | ||
| 23 | static unsigned int | 23 | static unsigned int |
| 24 | target(struct sk_buff **pskb, | 24 | target(struct sk_buff *skb, |
| 25 | const struct net_device *in, | 25 | const struct net_device *in, |
| 26 | const struct net_device *out, | 26 | const struct net_device *out, |
| 27 | unsigned int hooknum, | 27 | unsigned int hooknum, |
| @@ -29,13 +29,13 @@ target(struct sk_buff **pskb, | |||
| 29 | const void *targinfo) | 29 | const void *targinfo) |
| 30 | { | 30 | { |
| 31 | const struct ipt_tos_target_info *tosinfo = targinfo; | 31 | const struct ipt_tos_target_info *tosinfo = targinfo; |
| 32 | struct iphdr *iph = ip_hdr(*pskb); | 32 | struct iphdr *iph = ip_hdr(skb); |
| 33 | 33 | ||
| 34 | if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) { | 34 | if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) { |
| 35 | __u8 oldtos; | 35 | __u8 oldtos; |
| 36 | if (!skb_make_writable(pskb, sizeof(struct iphdr))) | 36 | if (!skb_make_writable(skb, sizeof(struct iphdr))) |
| 37 | return NF_DROP; | 37 | return NF_DROP; |
| 38 | iph = ip_hdr(*pskb); | 38 | iph = ip_hdr(skb); |
| 39 | oldtos = iph->tos; | 39 | oldtos = iph->tos; |
| 40 | iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos; | 40 | iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos; |
| 41 | nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos)); | 41 | nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos)); |
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c index 2b54e7b0cfe8..c620a0527666 100644 --- a/net/ipv4/netfilter/ipt_TTL.c +++ b/net/ipv4/netfilter/ipt_TTL.c | |||
| @@ -20,7 +20,7 @@ MODULE_DESCRIPTION("IP tables TTL modification module"); | |||
| 20 | MODULE_LICENSE("GPL"); | 20 | MODULE_LICENSE("GPL"); |
| 21 | 21 | ||
| 22 | static unsigned int | 22 | static unsigned int |
| 23 | ipt_ttl_target(struct sk_buff **pskb, | 23 | ipt_ttl_target(struct sk_buff *skb, |
| 24 | const struct net_device *in, const struct net_device *out, | 24 | const struct net_device *in, const struct net_device *out, |
| 25 | unsigned int hooknum, const struct xt_target *target, | 25 | unsigned int hooknum, const struct xt_target *target, |
| 26 | const void *targinfo) | 26 | const void *targinfo) |
| @@ -29,10 +29,10 @@ ipt_ttl_target(struct sk_buff **pskb, | |||
| 29 | const struct ipt_TTL_info *info = targinfo; | 29 | const struct ipt_TTL_info *info = targinfo; |
| 30 | int new_ttl; | 30 | int new_ttl; |
| 31 | 31 | ||
| 32 | if (!skb_make_writable(pskb, (*pskb)->len)) | 32 | if (!skb_make_writable(skb, skb->len)) |
| 33 | return NF_DROP; | 33 | return NF_DROP; |
| 34 | 34 | ||
| 35 | iph = ip_hdr(*pskb); | 35 | iph = ip_hdr(skb); |
| 36 | 36 | ||
| 37 | switch (info->mode) { | 37 | switch (info->mode) { |
| 38 | case IPT_TTL_SET: | 38 | case IPT_TTL_SET: |
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index c636d6d63574..212b830765a4 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c | |||
| @@ -279,7 +279,7 @@ alloc_failure: | |||
| 279 | spin_unlock_bh(&ulog_lock); | 279 | spin_unlock_bh(&ulog_lock); |
| 280 | } | 280 | } |
| 281 | 281 | ||
| 282 | static unsigned int ipt_ulog_target(struct sk_buff **pskb, | 282 | static unsigned int ipt_ulog_target(struct sk_buff *skb, |
| 283 | const struct net_device *in, | 283 | const struct net_device *in, |
| 284 | const struct net_device *out, | 284 | const struct net_device *out, |
| 285 | unsigned int hooknum, | 285 | unsigned int hooknum, |
| @@ -288,7 +288,7 @@ static unsigned int ipt_ulog_target(struct sk_buff **pskb, | |||
| 288 | { | 288 | { |
| 289 | struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo; | 289 | struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo; |
| 290 | 290 | ||
| 291 | ipt_ulog_packet(hooknum, *pskb, in, out, loginfo, NULL); | 291 | ipt_ulog_packet(hooknum, skb, in, out, loginfo, NULL); |
| 292 | 292 | ||
| 293 | return XT_CONTINUE; | 293 | return XT_CONTINUE; |
| 294 | } | 294 | } |
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index 4f51c1d7d2d6..ba3262c60437 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c | |||
| @@ -62,31 +62,31 @@ static struct xt_table packet_filter = { | |||
| 62 | /* The work comes in here from netfilter.c. */ | 62 | /* The work comes in here from netfilter.c. */ |
| 63 | static unsigned int | 63 | static unsigned int |
| 64 | ipt_hook(unsigned int hook, | 64 | ipt_hook(unsigned int hook, |
| 65 | struct sk_buff **pskb, | 65 | struct sk_buff *skb, |
| 66 | const struct net_device *in, | 66 | const struct net_device *in, |
| 67 | const struct net_device *out, | 67 | const struct net_device *out, |
| 68 | int (*okfn)(struct sk_buff *)) | 68 | int (*okfn)(struct sk_buff *)) |
| 69 | { | 69 | { |
| 70 | return ipt_do_table(pskb, hook, in, out, &packet_filter); | 70 | return ipt_do_table(skb, hook, in, out, &packet_filter); |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | static unsigned int | 73 | static unsigned int |
| 74 | ipt_local_out_hook(unsigned int hook, | 74 | ipt_local_out_hook(unsigned int hook, |
| 75 | struct sk_buff **pskb, | 75 | struct sk_buff *skb, |
| 76 | const struct net_device *in, | 76 | const struct net_device *in, |
| 77 | const struct net_device *out, | 77 | const struct net_device *out, |
| 78 | int (*okfn)(struct sk_buff *)) | 78 | int (*okfn)(struct sk_buff *)) |
| 79 | { | 79 | { |
| 80 | /* root is playing with raw sockets. */ | 80 | /* root is playing with raw sockets. */ |
| 81 | if ((*pskb)->len < sizeof(struct iphdr) | 81 | if (skb->len < sizeof(struct iphdr) || |
| 82 | || ip_hdrlen(*pskb) < sizeof(struct iphdr)) { | 82 | ip_hdrlen(skb) < sizeof(struct iphdr)) { |
| 83 | if (net_ratelimit()) | 83 | if (net_ratelimit()) |
| 84 | printk("iptable_filter: ignoring short SOCK_RAW " | 84 | printk("iptable_filter: ignoring short SOCK_RAW " |
| 85 | "packet.\n"); | 85 | "packet.\n"); |
| 86 | return NF_ACCEPT; | 86 | return NF_ACCEPT; |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | return ipt_do_table(pskb, hook, in, out, &packet_filter); | 89 | return ipt_do_table(skb, hook, in, out, &packet_filter); |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | static struct nf_hook_ops ipt_ops[] = { | 92 | static struct nf_hook_ops ipt_ops[] = { |
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index 902446f7cbca..b4360a69d5ca 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c | |||
| @@ -75,17 +75,17 @@ static struct xt_table packet_mangler = { | |||
| 75 | /* The work comes in here from netfilter.c. */ | 75 | /* The work comes in here from netfilter.c. */ |
| 76 | static unsigned int | 76 | static unsigned int |
| 77 | ipt_route_hook(unsigned int hook, | 77 | ipt_route_hook(unsigned int hook, |
| 78 | struct sk_buff **pskb, | 78 | struct sk_buff *skb, |
| 79 | const struct net_device *in, | 79 | const struct net_device *in, |
| 80 | const struct net_device *out, | 80 | const struct net_device *out, |
| 81 | int (*okfn)(struct sk_buff *)) | 81 | int (*okfn)(struct sk_buff *)) |
| 82 | { | 82 | { |
| 83 | return ipt_do_table(pskb, hook, in, out, &packet_mangler); | 83 | return ipt_do_table(skb, hook, in, out, &packet_mangler); |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | static unsigned int | 86 | static unsigned int |
| 87 | ipt_local_hook(unsigned int hook, | 87 | ipt_local_hook(unsigned int hook, |
| 88 | struct sk_buff **pskb, | 88 | struct sk_buff *skb, |
| 89 | const struct net_device *in, | 89 | const struct net_device *in, |
| 90 | const struct net_device *out, | 90 | const struct net_device *out, |
| 91 | int (*okfn)(struct sk_buff *)) | 91 | int (*okfn)(struct sk_buff *)) |
| @@ -97,8 +97,8 @@ ipt_local_hook(unsigned int hook, | |||
| 97 | u_int32_t mark; | 97 | u_int32_t mark; |
| 98 | 98 | ||
| 99 | /* root is playing with raw sockets. */ | 99 | /* root is playing with raw sockets. */ |
| 100 | if ((*pskb)->len < sizeof(struct iphdr) | 100 | if (skb->len < sizeof(struct iphdr) |
| 101 | || ip_hdrlen(*pskb) < sizeof(struct iphdr)) { | 101 | || ip_hdrlen(skb) < sizeof(struct iphdr)) { |
| 102 | if (net_ratelimit()) | 102 | if (net_ratelimit()) |
| 103 | printk("iptable_mangle: ignoring short SOCK_RAW " | 103 | printk("iptable_mangle: ignoring short SOCK_RAW " |
| 104 | "packet.\n"); | 104 | "packet.\n"); |
| @@ -106,22 +106,22 @@ ipt_local_hook(unsigned int hook, | |||
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | /* Save things which could affect route */ | 108 | /* Save things which could affect route */ |
| 109 | mark = (*pskb)->mark; | 109 | mark = skb->mark; |
| 110 | iph = ip_hdr(*pskb); | 110 | iph = ip_hdr(skb); |
| 111 | saddr = iph->saddr; | 111 | saddr = iph->saddr; |
| 112 | daddr = iph->daddr; | 112 | daddr = iph->daddr; |
| 113 | tos = iph->tos; | 113 | tos = iph->tos; |
| 114 | 114 | ||
| 115 | ret = ipt_do_table(pskb, hook, in, out, &packet_mangler); | 115 | ret = ipt_do_table(skb, hook, in, out, &packet_mangler); |
| 116 | /* Reroute for ANY change. */ | 116 | /* Reroute for ANY change. */ |
| 117 | if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) { | 117 | if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) { |
| 118 | iph = ip_hdr(*pskb); | 118 | iph = ip_hdr(skb); |
| 119 | 119 | ||
| 120 | if (iph->saddr != saddr || | 120 | if (iph->saddr != saddr || |
| 121 | iph->daddr != daddr || | 121 | iph->daddr != daddr || |
| 122 | (*pskb)->mark != mark || | 122 | skb->mark != mark || |
| 123 | iph->tos != tos) | 123 | iph->tos != tos) |
| 124 | if (ip_route_me_harder(pskb, RTN_UNSPEC)) | 124 | if (ip_route_me_harder(skb, RTN_UNSPEC)) |
| 125 | ret = NF_DROP; | 125 | ret = NF_DROP; |
| 126 | } | 126 | } |
| 127 | 127 | ||
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index d6e503395684..5de6e57ac55c 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c | |||
| @@ -47,30 +47,30 @@ static struct xt_table packet_raw = { | |||
| 47 | /* The work comes in here from netfilter.c. */ | 47 | /* The work comes in here from netfilter.c. */ |
| 48 | static unsigned int | 48 | static unsigned int |
| 49 | ipt_hook(unsigned int hook, | 49 | ipt_hook(unsigned int hook, |
| 50 | struct sk_buff **pskb, | 50 | struct sk_buff *skb, |
| 51 | const struct net_device *in, | 51 | const struct net_device *in, |
| 52 | const struct net_device *out, | 52 | const struct net_device *out, |
| 53 | int (*okfn)(struct sk_buff *)) | 53 | int (*okfn)(struct sk_buff *)) |
| 54 | { | 54 | { |
| 55 | return ipt_do_table(pskb, hook, in, out, &packet_raw); | 55 | return ipt_do_table(skb, hook, in, out, &packet_raw); |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | static unsigned int | 58 | static unsigned int |
| 59 | ipt_local_hook(unsigned int hook, | 59 | ipt_local_hook(unsigned int hook, |
| 60 | struct sk_buff **pskb, | 60 | struct sk_buff *skb, |
| 61 | const struct net_device *in, | 61 | const struct net_device *in, |
| 62 | const struct net_device *out, | 62 | const struct net_device *out, |
| 63 | int (*okfn)(struct sk_buff *)) | 63 | int (*okfn)(struct sk_buff *)) |
| 64 | { | 64 | { |
| 65 | /* root is playing with raw sockets. */ | 65 | /* root is playing with raw sockets. */ |
| 66 | if ((*pskb)->len < sizeof(struct iphdr) || | 66 | if (skb->len < sizeof(struct iphdr) || |
| 67 | ip_hdrlen(*pskb) < sizeof(struct iphdr)) { | 67 | ip_hdrlen(skb) < sizeof(struct iphdr)) { |
| 68 | if (net_ratelimit()) | 68 | if (net_ratelimit()) |
| 69 | printk("iptable_raw: ignoring short SOCK_RAW" | 69 | printk("iptable_raw: ignoring short SOCK_RAW" |
| 70 | "packet.\n"); | 70 | "packet.\n"); |
| 71 | return NF_ACCEPT; | 71 | return NF_ACCEPT; |
| 72 | } | 72 | } |
| 73 | return ipt_do_table(pskb, hook, in, out, &packet_raw); | 73 | return ipt_do_table(skb, hook, in, out, &packet_raw); |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | /* 'raw' is the very first table. */ | 76 | /* 'raw' is the very first table. */ |
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 2fcb9249a8da..831e9b29806d 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | |||
| @@ -63,19 +63,20 @@ static int ipv4_print_conntrack(struct seq_file *s, | |||
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | /* Returns new sk_buff, or NULL */ | 65 | /* Returns new sk_buff, or NULL */ |
| 66 | static struct sk_buff * | 66 | static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user) |
| 67 | nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user) | ||
| 68 | { | 67 | { |
| 68 | int err; | ||
| 69 | |||
| 69 | skb_orphan(skb); | 70 | skb_orphan(skb); |
| 70 | 71 | ||
| 71 | local_bh_disable(); | 72 | local_bh_disable(); |
| 72 | skb = ip_defrag(skb, user); | 73 | err = ip_defrag(skb, user); |
| 73 | local_bh_enable(); | 74 | local_bh_enable(); |
| 74 | 75 | ||
| 75 | if (skb) | 76 | if (!err) |
| 76 | ip_send_check(ip_hdr(skb)); | 77 | ip_send_check(ip_hdr(skb)); |
| 77 | 78 | ||
| 78 | return skb; | 79 | return err; |
| 79 | } | 80 | } |
| 80 | 81 | ||
| 81 | static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, | 82 | static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, |
| @@ -99,17 +100,17 @@ static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, | |||
| 99 | } | 100 | } |
| 100 | 101 | ||
| 101 | static unsigned int ipv4_confirm(unsigned int hooknum, | 102 | static unsigned int ipv4_confirm(unsigned int hooknum, |
| 102 | struct sk_buff **pskb, | 103 | struct sk_buff *skb, |
| 103 | const struct net_device *in, | 104 | const struct net_device *in, |
| 104 | const struct net_device *out, | 105 | const struct net_device *out, |
| 105 | int (*okfn)(struct sk_buff *)) | 106 | int (*okfn)(struct sk_buff *)) |
| 106 | { | 107 | { |
| 107 | /* We've seen it coming out the other side: confirm it */ | 108 | /* We've seen it coming out the other side: confirm it */ |
| 108 | return nf_conntrack_confirm(pskb); | 109 | return nf_conntrack_confirm(skb); |
| 109 | } | 110 | } |
| 110 | 111 | ||
| 111 | static unsigned int ipv4_conntrack_help(unsigned int hooknum, | 112 | static unsigned int ipv4_conntrack_help(unsigned int hooknum, |
| 112 | struct sk_buff **pskb, | 113 | struct sk_buff *skb, |
| 113 | const struct net_device *in, | 114 | const struct net_device *in, |
| 114 | const struct net_device *out, | 115 | const struct net_device *out, |
| 115 | int (*okfn)(struct sk_buff *)) | 116 | int (*okfn)(struct sk_buff *)) |
| @@ -120,7 +121,7 @@ static unsigned int ipv4_conntrack_help(unsigned int hooknum, | |||
| 120 | struct nf_conntrack_helper *helper; | 121 | struct nf_conntrack_helper *helper; |
| 121 | 122 | ||
| 122 | /* This is where we call the helper: as the packet goes out. */ | 123 | /* This is where we call the helper: as the packet goes out. */ |
| 123 | ct = nf_ct_get(*pskb, &ctinfo); | 124 | ct = nf_ct_get(skb, &ctinfo); |
| 124 | if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY) | 125 | if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY) |
| 125 | return NF_ACCEPT; | 126 | return NF_ACCEPT; |
| 126 | 127 | ||
| @@ -131,56 +132,55 @@ static unsigned int ipv4_conntrack_help(unsigned int hooknum, | |||
| 131 | helper = rcu_dereference(help->helper); | 132 | helper = rcu_dereference(help->helper); |
| 132 | if (!helper) | 133 | if (!helper) |
| 133 | return NF_ACCEPT; | 134 | return NF_ACCEPT; |
| 134 | return helper->help(pskb, skb_network_offset(*pskb) + ip_hdrlen(*pskb), | 135 | return helper->help(skb, skb_network_offset(skb) + ip_hdrlen(skb), |
| 135 | ct, ctinfo); | 136 | ct, ctinfo); |
| 136 | } | 137 | } |
| 137 | 138 | ||
| 138 | static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, | 139 | static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, |
| 139 | struct sk_buff **pskb, | 140 | struct sk_buff *skb, |
| 140 | const struct net_device *in, | 141 | const struct net_device *in, |
| 141 | const struct net_device *out, | 142 | const struct net_device *out, |
| 142 | int (*okfn)(struct sk_buff *)) | 143 | int (*okfn)(struct sk_buff *)) |
| 143 | { | 144 | { |
| 144 | /* Previously seen (loopback)? Ignore. Do this before | 145 | /* Previously seen (loopback)? Ignore. Do this before |
| 145 | fragment check. */ | 146 | fragment check. */ |
| 146 | if ((*pskb)->nfct) | 147 | if (skb->nfct) |
| 147 | return NF_ACCEPT; | 148 | return NF_ACCEPT; |
| 148 | 149 | ||
| 149 | /* Gather fragments. */ | 150 | /* Gather fragments. */ |
| 150 | if (ip_hdr(*pskb)->frag_off & htons(IP_MF | IP_OFFSET)) { | 151 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { |
| 151 | *pskb = nf_ct_ipv4_gather_frags(*pskb, | 152 | if (nf_ct_ipv4_gather_frags(skb, |
| 152 | hooknum == NF_IP_PRE_ROUTING ? | 153 | hooknum == NF_IP_PRE_ROUTING ? |
| 153 | IP_DEFRAG_CONNTRACK_IN : | 154 | IP_DEFRAG_CONNTRACK_IN : |
| 154 | IP_DEFRAG_CONNTRACK_OUT); | 155 | IP_DEFRAG_CONNTRACK_OUT)) |
| 155 | if (!*pskb) | ||
| 156 | return NF_STOLEN; | 156 | return NF_STOLEN; |
| 157 | } | 157 | } |
| 158 | return NF_ACCEPT; | 158 | return NF_ACCEPT; |
| 159 | } | 159 | } |
| 160 | 160 | ||
| 161 | static unsigned int ipv4_conntrack_in(unsigned int hooknum, | 161 | static unsigned int ipv4_conntrack_in(unsigned int hooknum, |
| 162 | struct sk_buff **pskb, | 162 | struct sk_buff *skb, |
| 163 | const struct net_device *in, | 163 | const struct net_device *in, |
| 164 | const struct net_device *out, | 164 | const struct net_device *out, |
| 165 | int (*okfn)(struct sk_buff *)) | 165 | int (*okfn)(struct sk_buff *)) |
| 166 | { | 166 | { |
| 167 | return nf_conntrack_in(PF_INET, hooknum, pskb); | 167 | return nf_conntrack_in(PF_INET, hooknum, skb); |
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | static unsigned int ipv4_conntrack_local(unsigned int hooknum, | 170 | static unsigned int ipv4_conntrack_local(unsigned int hooknum, |
| 171 | struct sk_buff **pskb, | 171 | struct sk_buff *skb, |
| 172 | const struct net_device *in, | 172 | const struct net_device *in, |
| 173 | const struct net_device *out, | 173 | const struct net_device *out, |
| 174 | int (*okfn)(struct sk_buff *)) | 174 | int (*okfn)(struct sk_buff *)) |
| 175 | { | 175 | { |
| 176 | /* root is playing with raw sockets. */ | 176 | /* root is playing with raw sockets. */ |
| 177 | if ((*pskb)->len < sizeof(struct iphdr) | 177 | if (skb->len < sizeof(struct iphdr) || |
| 178 | || ip_hdrlen(*pskb) < sizeof(struct iphdr)) { | 178 | ip_hdrlen(skb) < sizeof(struct iphdr)) { |
| 179 | if (net_ratelimit()) | 179 | if (net_ratelimit()) |
| 180 | printk("ipt_hook: happy cracking.\n"); | 180 | printk("ipt_hook: happy cracking.\n"); |
| 181 | return NF_ACCEPT; | 181 | return NF_ACCEPT; |
| 182 | } | 182 | } |
| 183 | return nf_conntrack_in(PF_INET, hooknum, pskb); | 183 | return nf_conntrack_in(PF_INET, hooknum, skb); |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | /* Connection tracking may drop packets, but never alters them, so | 186 | /* Connection tracking may drop packets, but never alters them, so |
diff --git a/net/ipv4/netfilter/nf_nat_amanda.c b/net/ipv4/netfilter/nf_nat_amanda.c index bd93a1d71052..35a5aa69cd92 100644 --- a/net/ipv4/netfilter/nf_nat_amanda.c +++ b/net/ipv4/netfilter/nf_nat_amanda.c | |||
| @@ -24,7 +24,7 @@ MODULE_DESCRIPTION("Amanda NAT helper"); | |||
| 24 | MODULE_LICENSE("GPL"); | 24 | MODULE_LICENSE("GPL"); |
| 25 | MODULE_ALIAS("ip_nat_amanda"); | 25 | MODULE_ALIAS("ip_nat_amanda"); |
| 26 | 26 | ||
| 27 | static unsigned int help(struct sk_buff **pskb, | 27 | static unsigned int help(struct sk_buff *skb, |
| 28 | enum ip_conntrack_info ctinfo, | 28 | enum ip_conntrack_info ctinfo, |
| 29 | unsigned int matchoff, | 29 | unsigned int matchoff, |
| 30 | unsigned int matchlen, | 30 | unsigned int matchlen, |
| @@ -53,7 +53,7 @@ static unsigned int help(struct sk_buff **pskb, | |||
| 53 | return NF_DROP; | 53 | return NF_DROP; |
| 54 | 54 | ||
| 55 | sprintf(buffer, "%u", port); | 55 | sprintf(buffer, "%u", port); |
| 56 | ret = nf_nat_mangle_udp_packet(pskb, exp->master, ctinfo, | 56 | ret = nf_nat_mangle_udp_packet(skb, exp->master, ctinfo, |
| 57 | matchoff, matchlen, | 57 | matchoff, matchlen, |
| 58 | buffer, strlen(buffer)); | 58 | buffer, strlen(buffer)); |
| 59 | if (ret != NF_ACCEPT) | 59 | if (ret != NF_ACCEPT) |
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 7221aa20e6ff..56e93f692e82 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c | |||
| @@ -349,7 +349,7 @@ EXPORT_SYMBOL(nf_nat_setup_info); | |||
| 349 | /* Returns true if succeeded. */ | 349 | /* Returns true if succeeded. */ |
| 350 | static int | 350 | static int |
| 351 | manip_pkt(u_int16_t proto, | 351 | manip_pkt(u_int16_t proto, |
| 352 | struct sk_buff **pskb, | 352 | struct sk_buff *skb, |
| 353 | unsigned int iphdroff, | 353 | unsigned int iphdroff, |
| 354 | const struct nf_conntrack_tuple *target, | 354 | const struct nf_conntrack_tuple *target, |
| 355 | enum nf_nat_manip_type maniptype) | 355 | enum nf_nat_manip_type maniptype) |
| @@ -357,19 +357,19 @@ manip_pkt(u_int16_t proto, | |||
| 357 | struct iphdr *iph; | 357 | struct iphdr *iph; |
| 358 | struct nf_nat_protocol *p; | 358 | struct nf_nat_protocol *p; |
| 359 | 359 | ||
| 360 | if (!skb_make_writable(pskb, iphdroff + sizeof(*iph))) | 360 | if (!skb_make_writable(skb, iphdroff + sizeof(*iph))) |
| 361 | return 0; | 361 | return 0; |
| 362 | 362 | ||
| 363 | iph = (void *)(*pskb)->data + iphdroff; | 363 | iph = (void *)skb->data + iphdroff; |
| 364 | 364 | ||
| 365 | /* Manipulate protcol part. */ | 365 | /* Manipulate protcol part. */ |
| 366 | 366 | ||
| 367 | /* rcu_read_lock()ed by nf_hook_slow */ | 367 | /* rcu_read_lock()ed by nf_hook_slow */ |
| 368 | p = __nf_nat_proto_find(proto); | 368 | p = __nf_nat_proto_find(proto); |
| 369 | if (!p->manip_pkt(pskb, iphdroff, target, maniptype)) | 369 | if (!p->manip_pkt(skb, iphdroff, target, maniptype)) |
| 370 | return 0; | 370 | return 0; |
| 371 | 371 | ||
| 372 | iph = (void *)(*pskb)->data + iphdroff; | 372 | iph = (void *)skb->data + iphdroff; |
| 373 | 373 | ||
| 374 | if (maniptype == IP_NAT_MANIP_SRC) { | 374 | if (maniptype == IP_NAT_MANIP_SRC) { |
| 375 | nf_csum_replace4(&iph->check, iph->saddr, target->src.u3.ip); | 375 | nf_csum_replace4(&iph->check, iph->saddr, target->src.u3.ip); |
| @@ -385,7 +385,7 @@ manip_pkt(u_int16_t proto, | |||
| 385 | unsigned int nf_nat_packet(struct nf_conn *ct, | 385 | unsigned int nf_nat_packet(struct nf_conn *ct, |
| 386 | enum ip_conntrack_info ctinfo, | 386 | enum ip_conntrack_info ctinfo, |
| 387 | unsigned int hooknum, | 387 | unsigned int hooknum, |
| 388 | struct sk_buff **pskb) | 388 | struct sk_buff *skb) |
| 389 | { | 389 | { |
| 390 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 390 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
| 391 | unsigned long statusbit; | 391 | unsigned long statusbit; |
| @@ -407,7 +407,7 @@ unsigned int nf_nat_packet(struct nf_conn *ct, | |||
| 407 | /* We are aiming to look like inverse of other direction. */ | 407 | /* We are aiming to look like inverse of other direction. */ |
| 408 | nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple); | 408 | nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple); |
| 409 | 409 | ||
| 410 | if (!manip_pkt(target.dst.protonum, pskb, 0, &target, mtype)) | 410 | if (!manip_pkt(target.dst.protonum, skb, 0, &target, mtype)) |
| 411 | return NF_DROP; | 411 | return NF_DROP; |
| 412 | } | 412 | } |
| 413 | return NF_ACCEPT; | 413 | return NF_ACCEPT; |
| @@ -418,7 +418,7 @@ EXPORT_SYMBOL_GPL(nf_nat_packet); | |||
| 418 | int nf_nat_icmp_reply_translation(struct nf_conn *ct, | 418 | int nf_nat_icmp_reply_translation(struct nf_conn *ct, |
| 419 | enum ip_conntrack_info ctinfo, | 419 | enum ip_conntrack_info ctinfo, |
| 420 | unsigned int hooknum, | 420 | unsigned int hooknum, |
| 421 | struct sk_buff **pskb) | 421 | struct sk_buff *skb) |
| 422 | { | 422 | { |
| 423 | struct { | 423 | struct { |
| 424 | struct icmphdr icmp; | 424 | struct icmphdr icmp; |
| @@ -426,24 +426,24 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct, | |||
| 426 | } *inside; | 426 | } *inside; |
| 427 | struct nf_conntrack_l4proto *l4proto; | 427 | struct nf_conntrack_l4proto *l4proto; |
| 428 | struct nf_conntrack_tuple inner, target; | 428 | struct nf_conntrack_tuple inner, target; |
| 429 | int hdrlen = ip_hdrlen(*pskb); | 429 | int hdrlen = ip_hdrlen(skb); |
| 430 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 430 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
| 431 | unsigned long statusbit; | 431 | unsigned long statusbit; |
| 432 | enum nf_nat_manip_type manip = HOOK2MANIP(hooknum); | 432 | enum nf_nat_manip_type manip = HOOK2MANIP(hooknum); |
| 433 | 433 | ||
| 434 | if (!skb_make_writable(pskb, hdrlen + sizeof(*inside))) | 434 | if (!skb_make_writable(skb, hdrlen + sizeof(*inside))) |
| 435 | return 0; | 435 | return 0; |
| 436 | 436 | ||
| 437 | inside = (void *)(*pskb)->data + ip_hdrlen(*pskb); | 437 | inside = (void *)skb->data + ip_hdrlen(skb); |
| 438 | 438 | ||
| 439 | /* We're actually going to mangle it beyond trivial checksum | 439 | /* We're actually going to mangle it beyond trivial checksum |
| 440 | adjustment, so make sure the current checksum is correct. */ | 440 | adjustment, so make sure the current checksum is correct. */ |
| 441 | if (nf_ip_checksum(*pskb, hooknum, hdrlen, 0)) | 441 | if (nf_ip_checksum(skb, hooknum, hdrlen, 0)) |
| 442 | return 0; | 442 | return 0; |
| 443 | 443 | ||
| 444 | /* Must be RELATED */ | 444 | /* Must be RELATED */ |
| 445 | NF_CT_ASSERT((*pskb)->nfctinfo == IP_CT_RELATED || | 445 | NF_CT_ASSERT(skb->nfctinfo == IP_CT_RELATED || |
| 446 | (*pskb)->nfctinfo == IP_CT_RELATED+IP_CT_IS_REPLY); | 446 | skb->nfctinfo == IP_CT_RELATED+IP_CT_IS_REPLY); |
| 447 | 447 | ||
| 448 | /* Redirects on non-null nats must be dropped, else they'll | 448 | /* Redirects on non-null nats must be dropped, else they'll |
| 449 | start talking to each other without our translation, and be | 449 | start talking to each other without our translation, and be |
| @@ -458,15 +458,15 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct, | |||
| 458 | } | 458 | } |
| 459 | 459 | ||
| 460 | pr_debug("icmp_reply_translation: translating error %p manip %u " | 460 | pr_debug("icmp_reply_translation: translating error %p manip %u " |
| 461 | "dir %s\n", *pskb, manip, | 461 | "dir %s\n", skb, manip, |
| 462 | dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY"); | 462 | dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY"); |
| 463 | 463 | ||
| 464 | /* rcu_read_lock()ed by nf_hook_slow */ | 464 | /* rcu_read_lock()ed by nf_hook_slow */ |
| 465 | l4proto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol); | 465 | l4proto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol); |
| 466 | 466 | ||
| 467 | if (!nf_ct_get_tuple(*pskb, | 467 | if (!nf_ct_get_tuple(skb, |
| 468 | ip_hdrlen(*pskb) + sizeof(struct icmphdr), | 468 | ip_hdrlen(skb) + sizeof(struct icmphdr), |
| 469 | (ip_hdrlen(*pskb) + | 469 | (ip_hdrlen(skb) + |
| 470 | sizeof(struct icmphdr) + inside->ip.ihl * 4), | 470 | sizeof(struct icmphdr) + inside->ip.ihl * 4), |
| 471 | (u_int16_t)AF_INET, | 471 | (u_int16_t)AF_INET, |
| 472 | inside->ip.protocol, | 472 | inside->ip.protocol, |
| @@ -478,19 +478,19 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct, | |||
| 478 | pass all hooks (locally-generated ICMP). Consider incoming | 478 | pass all hooks (locally-generated ICMP). Consider incoming |
| 479 | packet: PREROUTING (DST manip), routing produces ICMP, goes | 479 | packet: PREROUTING (DST manip), routing produces ICMP, goes |
| 480 | through POSTROUTING (which must correct the DST manip). */ | 480 | through POSTROUTING (which must correct the DST manip). */ |
| 481 | if (!manip_pkt(inside->ip.protocol, pskb, | 481 | if (!manip_pkt(inside->ip.protocol, skb, |
| 482 | ip_hdrlen(*pskb) + sizeof(inside->icmp), | 482 | ip_hdrlen(skb) + sizeof(inside->icmp), |
| 483 | &ct->tuplehash[!dir].tuple, | 483 | &ct->tuplehash[!dir].tuple, |
| 484 | !manip)) | 484 | !manip)) |
| 485 | return 0; | 485 | return 0; |
| 486 | 486 | ||
| 487 | if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) { | 487 | if (skb->ip_summed != CHECKSUM_PARTIAL) { |
| 488 | /* Reloading "inside" here since manip_pkt inner. */ | 488 | /* Reloading "inside" here since manip_pkt inner. */ |
| 489 | inside = (void *)(*pskb)->data + ip_hdrlen(*pskb); | 489 | inside = (void *)skb->data + ip_hdrlen(skb); |
| 490 | inside->icmp.checksum = 0; | 490 | inside->icmp.checksum = 0; |
| 491 | inside->icmp.checksum = | 491 | inside->icmp.checksum = |
| 492 | csum_fold(skb_checksum(*pskb, hdrlen, | 492 | csum_fold(skb_checksum(skb, hdrlen, |
| 493 | (*pskb)->len - hdrlen, 0)); | 493 | skb->len - hdrlen, 0)); |
| 494 | } | 494 | } |
| 495 | 495 | ||
| 496 | /* Change outer to look the reply to an incoming packet | 496 | /* Change outer to look the reply to an incoming packet |
| @@ -506,7 +506,7 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct, | |||
| 506 | 506 | ||
| 507 | if (ct->status & statusbit) { | 507 | if (ct->status & statusbit) { |
| 508 | nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple); | 508 | nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple); |
| 509 | if (!manip_pkt(0, pskb, 0, &target, manip)) | 509 | if (!manip_pkt(0, skb, 0, &target, manip)) |
| 510 | return 0; | 510 | return 0; |
| 511 | } | 511 | } |
| 512 | 512 | ||
diff --git a/net/ipv4/netfilter/nf_nat_ftp.c b/net/ipv4/netfilter/nf_nat_ftp.c index 3663bd879c39..e1a16d3ea4cb 100644 --- a/net/ipv4/netfilter/nf_nat_ftp.c +++ b/net/ipv4/netfilter/nf_nat_ftp.c | |||
| @@ -28,7 +28,7 @@ MODULE_ALIAS("ip_nat_ftp"); | |||
| 28 | /* FIXME: Time out? --RR */ | 28 | /* FIXME: Time out? --RR */ |
| 29 | 29 | ||
| 30 | static int | 30 | static int |
| 31 | mangle_rfc959_packet(struct sk_buff **pskb, | 31 | mangle_rfc959_packet(struct sk_buff *skb, |
| 32 | __be32 newip, | 32 | __be32 newip, |
| 33 | u_int16_t port, | 33 | u_int16_t port, |
| 34 | unsigned int matchoff, | 34 | unsigned int matchoff, |
| @@ -43,13 +43,13 @@ mangle_rfc959_packet(struct sk_buff **pskb, | |||
| 43 | 43 | ||
| 44 | pr_debug("calling nf_nat_mangle_tcp_packet\n"); | 44 | pr_debug("calling nf_nat_mangle_tcp_packet\n"); |
| 45 | 45 | ||
| 46 | return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, | 46 | return nf_nat_mangle_tcp_packet(skb, ct, ctinfo, matchoff, |
| 47 | matchlen, buffer, strlen(buffer)); | 47 | matchlen, buffer, strlen(buffer)); |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | /* |1|132.235.1.2|6275| */ | 50 | /* |1|132.235.1.2|6275| */ |
| 51 | static int | 51 | static int |
| 52 | mangle_eprt_packet(struct sk_buff **pskb, | 52 | mangle_eprt_packet(struct sk_buff *skb, |
| 53 | __be32 newip, | 53 | __be32 newip, |
| 54 | u_int16_t port, | 54 | u_int16_t port, |
| 55 | unsigned int matchoff, | 55 | unsigned int matchoff, |
| @@ -63,13 +63,13 @@ mangle_eprt_packet(struct sk_buff **pskb, | |||
| 63 | 63 | ||
| 64 | pr_debug("calling nf_nat_mangle_tcp_packet\n"); | 64 | pr_debug("calling nf_nat_mangle_tcp_packet\n"); |
| 65 | 65 | ||
| 66 | return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, | 66 | return nf_nat_mangle_tcp_packet(skb, ct, ctinfo, matchoff, |
| 67 | matchlen, buffer, strlen(buffer)); | 67 | matchlen, buffer, strlen(buffer)); |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | /* |1|132.235.1.2|6275| */ | 70 | /* |1|132.235.1.2|6275| */ |
| 71 | static int | 71 | static int |
| 72 | mangle_epsv_packet(struct sk_buff **pskb, | 72 | mangle_epsv_packet(struct sk_buff *skb, |
| 73 | __be32 newip, | 73 | __be32 newip, |
| 74 | u_int16_t port, | 74 | u_int16_t port, |
| 75 | unsigned int matchoff, | 75 | unsigned int matchoff, |
| @@ -83,11 +83,11 @@ mangle_epsv_packet(struct sk_buff **pskb, | |||
| 83 | 83 | ||
| 84 | pr_debug("calling nf_nat_mangle_tcp_packet\n"); | 84 | pr_debug("calling nf_nat_mangle_tcp_packet\n"); |
| 85 | 85 | ||
| 86 | return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, | 86 | return nf_nat_mangle_tcp_packet(skb, ct, ctinfo, matchoff, |
| 87 | matchlen, buffer, strlen(buffer)); | 87 | matchlen, buffer, strlen(buffer)); |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | static int (*mangle[])(struct sk_buff **, __be32, u_int16_t, | 90 | static int (*mangle[])(struct sk_buff *, __be32, u_int16_t, |
| 91 | unsigned int, unsigned int, struct nf_conn *, | 91 | unsigned int, unsigned int, struct nf_conn *, |
| 92 | enum ip_conntrack_info) | 92 | enum ip_conntrack_info) |
| 93 | = { | 93 | = { |
| @@ -99,7 +99,7 @@ static int (*mangle[])(struct sk_buff **, __be32, u_int16_t, | |||
| 99 | 99 | ||
| 100 | /* So, this packet has hit the connection tracking matching code. | 100 | /* So, this packet has hit the connection tracking matching code. |
| 101 | Mangle it, and change the expectation to match the new version. */ | 101 | Mangle it, and change the expectation to match the new version. */ |
| 102 | static unsigned int nf_nat_ftp(struct sk_buff **pskb, | 102 | static unsigned int nf_nat_ftp(struct sk_buff *skb, |
| 103 | enum ip_conntrack_info ctinfo, | 103 | enum ip_conntrack_info ctinfo, |
| 104 | enum nf_ct_ftp_type type, | 104 | enum nf_ct_ftp_type type, |
| 105 | unsigned int matchoff, | 105 | unsigned int matchoff, |
| @@ -132,7 +132,7 @@ static unsigned int nf_nat_ftp(struct sk_buff **pskb, | |||
| 132 | if (port == 0) | 132 | if (port == 0) |
| 133 | return NF_DROP; | 133 | return NF_DROP; |
| 134 | 134 | ||
| 135 | if (!mangle[type](pskb, newip, port, matchoff, matchlen, ct, ctinfo)) { | 135 | if (!mangle[type](skb, newip, port, matchoff, matchlen, ct, ctinfo)) { |
| 136 | nf_ct_unexpect_related(exp); | 136 | nf_ct_unexpect_related(exp); |
| 137 | return NF_DROP; | 137 | return NF_DROP; |
| 138 | } | 138 | } |
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c index c1b059a73708..a868c8c41328 100644 --- a/net/ipv4/netfilter/nf_nat_h323.c +++ b/net/ipv4/netfilter/nf_nat_h323.c | |||
| @@ -22,12 +22,12 @@ | |||
| 22 | #include <linux/netfilter/nf_conntrack_h323.h> | 22 | #include <linux/netfilter/nf_conntrack_h323.h> |
| 23 | 23 | ||
| 24 | /****************************************************************************/ | 24 | /****************************************************************************/ |
| 25 | static int set_addr(struct sk_buff **pskb, | 25 | static int set_addr(struct sk_buff *skb, |
| 26 | unsigned char **data, int dataoff, | 26 | unsigned char **data, int dataoff, |
| 27 | unsigned int addroff, __be32 ip, __be16 port) | 27 | unsigned int addroff, __be32 ip, __be16 port) |
| 28 | { | 28 | { |
| 29 | enum ip_conntrack_info ctinfo; | 29 | enum ip_conntrack_info ctinfo; |
| 30 | struct nf_conn *ct = nf_ct_get(*pskb, &ctinfo); | 30 | struct nf_conn *ct = nf_ct_get(skb, &ctinfo); |
| 31 | struct { | 31 | struct { |
| 32 | __be32 ip; | 32 | __be32 ip; |
| 33 | __be16 port; | 33 | __be16 port; |
| @@ -38,8 +38,8 @@ static int set_addr(struct sk_buff **pskb, | |||
| 38 | buf.port = port; | 38 | buf.port = port; |
| 39 | addroff += dataoff; | 39 | addroff += dataoff; |
| 40 | 40 | ||
| 41 | if (ip_hdr(*pskb)->protocol == IPPROTO_TCP) { | 41 | if (ip_hdr(skb)->protocol == IPPROTO_TCP) { |
| 42 | if (!nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, | 42 | if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, |
| 43 | addroff, sizeof(buf), | 43 | addroff, sizeof(buf), |
| 44 | (char *) &buf, sizeof(buf))) { | 44 | (char *) &buf, sizeof(buf))) { |
| 45 | if (net_ratelimit()) | 45 | if (net_ratelimit()) |
| @@ -49,14 +49,13 @@ static int set_addr(struct sk_buff **pskb, | |||
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | /* Relocate data pointer */ | 51 | /* Relocate data pointer */ |
| 52 | th = skb_header_pointer(*pskb, ip_hdrlen(*pskb), | 52 | th = skb_header_pointer(skb, ip_hdrlen(skb), |
| 53 | sizeof(_tcph), &_tcph); | 53 | sizeof(_tcph), &_tcph); |
| 54 | if (th == NULL) | 54 | if (th == NULL) |
| 55 | return -1; | 55 | return -1; |
| 56 | *data = (*pskb)->data + ip_hdrlen(*pskb) + | 56 | *data = skb->data + ip_hdrlen(skb) + th->doff * 4 + dataoff; |
| 57 | th->doff * 4 + dataoff; | ||
| 58 | } else { | 57 | } else { |
| 59 | if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo, | 58 | if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, |
| 60 | addroff, sizeof(buf), | 59 | addroff, sizeof(buf), |
| 61 | (char *) &buf, sizeof(buf))) { | 60 | (char *) &buf, sizeof(buf))) { |
| 62 | if (net_ratelimit()) | 61 | if (net_ratelimit()) |
| @@ -67,36 +66,35 @@ static int set_addr(struct sk_buff **pskb, | |||
| 67 | /* nf_nat_mangle_udp_packet uses skb_make_writable() to copy | 66 | /* nf_nat_mangle_udp_packet uses skb_make_writable() to copy |
| 68 | * or pull everything in a linear buffer, so we can safely | 67 | * or pull everything in a linear buffer, so we can safely |
| 69 | * use the skb pointers now */ | 68 | * use the skb pointers now */ |
| 70 | *data = ((*pskb)->data + ip_hdrlen(*pskb) + | 69 | *data = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr); |
| 71 | sizeof(struct udphdr)); | ||
| 72 | } | 70 | } |
| 73 | 71 | ||
| 74 | return 0; | 72 | return 0; |
| 75 | } | 73 | } |
| 76 | 74 | ||
| 77 | /****************************************************************************/ | 75 | /****************************************************************************/ |
| 78 | static int set_h225_addr(struct sk_buff **pskb, | 76 | static int set_h225_addr(struct sk_buff *skb, |
| 79 | unsigned char **data, int dataoff, | 77 | unsigned char **data, int dataoff, |
| 80 | TransportAddress *taddr, | 78 | TransportAddress *taddr, |
| 81 | union nf_conntrack_address *addr, __be16 port) | 79 | union nf_conntrack_address *addr, __be16 port) |
| 82 | { | 80 | { |
| 83 | return set_addr(pskb, data, dataoff, taddr->ipAddress.ip, | 81 | return set_addr(skb, data, dataoff, taddr->ipAddress.ip, |
| 84 | addr->ip, port); | 82 | addr->ip, port); |
| 85 | } | 83 | } |
| 86 | 84 | ||
| 87 | /****************************************************************************/ | 85 | /****************************************************************************/ |
| 88 | static int set_h245_addr(struct sk_buff **pskb, | 86 | static int set_h245_addr(struct sk_buff *skb, |
| 89 | unsigned char **data, int dataoff, | 87 | unsigned char **data, int dataoff, |
| 90 | H245_TransportAddress *taddr, | 88 | H245_TransportAddress *taddr, |
| 91 | union nf_conntrack_address *addr, __be16 port) | 89 | union nf_conntrack_address *addr, __be16 port) |
| 92 | { | 90 | { |
| 93 | return set_addr(pskb, data, dataoff, | 91 | return set_addr(skb, data, dataoff, |
| 94 | taddr->unicastAddress.iPAddress.network, | 92 | taddr->unicastAddress.iPAddress.network, |
| 95 | addr->ip, port); | 93 | addr->ip, port); |
| 96 | } | 94 | } |
| 97 | 95 | ||
| 98 | /****************************************************************************/ | 96 | /****************************************************************************/ |
| 99 | static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct, | 97 | static int set_sig_addr(struct sk_buff *skb, struct nf_conn *ct, |
| 100 | enum ip_conntrack_info ctinfo, | 98 | enum ip_conntrack_info ctinfo, |
| 101 | unsigned char **data, | 99 | unsigned char **data, |
| 102 | TransportAddress *taddr, int count) | 100 | TransportAddress *taddr, int count) |
| @@ -125,7 +123,7 @@ static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 125 | NIPQUAD(addr.ip), port, | 123 | NIPQUAD(addr.ip), port, |
| 126 | NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip), | 124 | NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip), |
| 127 | info->sig_port[!dir]); | 125 | info->sig_port[!dir]); |
| 128 | return set_h225_addr(pskb, data, 0, &taddr[i], | 126 | return set_h225_addr(skb, data, 0, &taddr[i], |
| 129 | &ct->tuplehash[!dir]. | 127 | &ct->tuplehash[!dir]. |
| 130 | tuple.dst.u3, | 128 | tuple.dst.u3, |
| 131 | info->sig_port[!dir]); | 129 | info->sig_port[!dir]); |
| @@ -137,7 +135,7 @@ static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 137 | NIPQUAD(addr.ip), port, | 135 | NIPQUAD(addr.ip), port, |
| 138 | NIPQUAD(ct->tuplehash[!dir].tuple.src.u3.ip), | 136 | NIPQUAD(ct->tuplehash[!dir].tuple.src.u3.ip), |
| 139 | info->sig_port[!dir]); | 137 | info->sig_port[!dir]); |
| 140 | return set_h225_addr(pskb, data, 0, &taddr[i], | 138 | return set_h225_addr(skb, data, 0, &taddr[i], |
| 141 | &ct->tuplehash[!dir]. | 139 | &ct->tuplehash[!dir]. |
| 142 | tuple.src.u3, | 140 | tuple.src.u3, |
| 143 | info->sig_port[!dir]); | 141 | info->sig_port[!dir]); |
| @@ -149,7 +147,7 @@ static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 149 | } | 147 | } |
| 150 | 148 | ||
| 151 | /****************************************************************************/ | 149 | /****************************************************************************/ |
| 152 | static int set_ras_addr(struct sk_buff **pskb, struct nf_conn *ct, | 150 | static int set_ras_addr(struct sk_buff *skb, struct nf_conn *ct, |
| 153 | enum ip_conntrack_info ctinfo, | 151 | enum ip_conntrack_info ctinfo, |
| 154 | unsigned char **data, | 152 | unsigned char **data, |
| 155 | TransportAddress *taddr, int count) | 153 | TransportAddress *taddr, int count) |
| @@ -168,7 +166,7 @@ static int set_ras_addr(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 168 | NIPQUAD(addr.ip), ntohs(port), | 166 | NIPQUAD(addr.ip), ntohs(port), |
| 169 | NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip), | 167 | NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip), |
| 170 | ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port)); | 168 | ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port)); |
| 171 | return set_h225_addr(pskb, data, 0, &taddr[i], | 169 | return set_h225_addr(skb, data, 0, &taddr[i], |
| 172 | &ct->tuplehash[!dir].tuple.dst.u3, | 170 | &ct->tuplehash[!dir].tuple.dst.u3, |
| 173 | ct->tuplehash[!dir].tuple. | 171 | ct->tuplehash[!dir].tuple. |
| 174 | dst.u.udp.port); | 172 | dst.u.udp.port); |
| @@ -179,7 +177,7 @@ static int set_ras_addr(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 179 | } | 177 | } |
| 180 | 178 | ||
| 181 | /****************************************************************************/ | 179 | /****************************************************************************/ |
| 182 | static int nat_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct, | 180 | static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct, |
| 183 | enum ip_conntrack_info ctinfo, | 181 | enum ip_conntrack_info ctinfo, |
| 184 | unsigned char **data, int dataoff, | 182 | unsigned char **data, int dataoff, |
| 185 | H245_TransportAddress *taddr, | 183 | H245_TransportAddress *taddr, |
| @@ -244,7 +242,7 @@ static int nat_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 244 | } | 242 | } |
| 245 | 243 | ||
| 246 | /* Modify signal */ | 244 | /* Modify signal */ |
| 247 | if (set_h245_addr(pskb, data, dataoff, taddr, | 245 | if (set_h245_addr(skb, data, dataoff, taddr, |
| 248 | &ct->tuplehash[!dir].tuple.dst.u3, | 246 | &ct->tuplehash[!dir].tuple.dst.u3, |
| 249 | htons((port & htons(1)) ? nated_port + 1 : | 247 | htons((port & htons(1)) ? nated_port + 1 : |
| 250 | nated_port)) == 0) { | 248 | nated_port)) == 0) { |
| @@ -273,7 +271,7 @@ static int nat_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 273 | } | 271 | } |
| 274 | 272 | ||
| 275 | /****************************************************************************/ | 273 | /****************************************************************************/ |
| 276 | static int nat_t120(struct sk_buff **pskb, struct nf_conn *ct, | 274 | static int nat_t120(struct sk_buff *skb, struct nf_conn *ct, |
| 277 | enum ip_conntrack_info ctinfo, | 275 | enum ip_conntrack_info ctinfo, |
| 278 | unsigned char **data, int dataoff, | 276 | unsigned char **data, int dataoff, |
| 279 | H245_TransportAddress *taddr, __be16 port, | 277 | H245_TransportAddress *taddr, __be16 port, |
| @@ -301,7 +299,7 @@ static int nat_t120(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 301 | } | 299 | } |
| 302 | 300 | ||
| 303 | /* Modify signal */ | 301 | /* Modify signal */ |
| 304 | if (set_h245_addr(pskb, data, dataoff, taddr, | 302 | if (set_h245_addr(skb, data, dataoff, taddr, |
| 305 | &ct->tuplehash[!dir].tuple.dst.u3, | 303 | &ct->tuplehash[!dir].tuple.dst.u3, |
| 306 | htons(nated_port)) < 0) { | 304 | htons(nated_port)) < 0) { |
| 307 | nf_ct_unexpect_related(exp); | 305 | nf_ct_unexpect_related(exp); |
| @@ -318,7 +316,7 @@ static int nat_t120(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 318 | } | 316 | } |
| 319 | 317 | ||
| 320 | /****************************************************************************/ | 318 | /****************************************************************************/ |
| 321 | static int nat_h245(struct sk_buff **pskb, struct nf_conn *ct, | 319 | static int nat_h245(struct sk_buff *skb, struct nf_conn *ct, |
| 322 | enum ip_conntrack_info ctinfo, | 320 | enum ip_conntrack_info ctinfo, |
| 323 | unsigned char **data, int dataoff, | 321 | unsigned char **data, int dataoff, |
| 324 | TransportAddress *taddr, __be16 port, | 322 | TransportAddress *taddr, __be16 port, |
| @@ -351,7 +349,7 @@ static int nat_h245(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 351 | } | 349 | } |
| 352 | 350 | ||
| 353 | /* Modify signal */ | 351 | /* Modify signal */ |
| 354 | if (set_h225_addr(pskb, data, dataoff, taddr, | 352 | if (set_h225_addr(skb, data, dataoff, taddr, |
| 355 | &ct->tuplehash[!dir].tuple.dst.u3, | 353 | &ct->tuplehash[!dir].tuple.dst.u3, |
| 356 | htons(nated_port)) == 0) { | 354 | htons(nated_port)) == 0) { |
| 357 | /* Save ports */ | 355 | /* Save ports */ |
| @@ -406,7 +404,7 @@ static void ip_nat_q931_expect(struct nf_conn *new, | |||
| 406 | } | 404 | } |
| 407 | 405 | ||
| 408 | /****************************************************************************/ | 406 | /****************************************************************************/ |
| 409 | static int nat_q931(struct sk_buff **pskb, struct nf_conn *ct, | 407 | static int nat_q931(struct sk_buff *skb, struct nf_conn *ct, |
| 410 | enum ip_conntrack_info ctinfo, | 408 | enum ip_conntrack_info ctinfo, |
| 411 | unsigned char **data, TransportAddress *taddr, int idx, | 409 | unsigned char **data, TransportAddress *taddr, int idx, |
| 412 | __be16 port, struct nf_conntrack_expect *exp) | 410 | __be16 port, struct nf_conntrack_expect *exp) |
| @@ -439,7 +437,7 @@ static int nat_q931(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 439 | } | 437 | } |
| 440 | 438 | ||
| 441 | /* Modify signal */ | 439 | /* Modify signal */ |
| 442 | if (set_h225_addr(pskb, data, 0, &taddr[idx], | 440 | if (set_h225_addr(skb, data, 0, &taddr[idx], |
| 443 | &ct->tuplehash[!dir].tuple.dst.u3, | 441 | &ct->tuplehash[!dir].tuple.dst.u3, |
| 444 | htons(nated_port)) == 0) { | 442 | htons(nated_port)) == 0) { |
| 445 | /* Save ports */ | 443 | /* Save ports */ |
| @@ -450,7 +448,7 @@ static int nat_q931(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 450 | if (idx > 0 && | 448 | if (idx > 0 && |
| 451 | get_h225_addr(ct, *data, &taddr[0], &addr, &port) && | 449 | get_h225_addr(ct, *data, &taddr[0], &addr, &port) && |
| 452 | (ntohl(addr.ip) & 0xff000000) == 0x7f000000) { | 450 | (ntohl(addr.ip) & 0xff000000) == 0x7f000000) { |
| 453 | set_h225_addr(pskb, data, 0, &taddr[0], | 451 | set_h225_addr(skb, data, 0, &taddr[0], |
| 454 | &ct->tuplehash[!dir].tuple.dst.u3, | 452 | &ct->tuplehash[!dir].tuple.dst.u3, |
| 455 | info->sig_port[!dir]); | 453 | info->sig_port[!dir]); |
| 456 | } | 454 | } |
| @@ -495,7 +493,7 @@ static void ip_nat_callforwarding_expect(struct nf_conn *new, | |||
| 495 | } | 493 | } |
| 496 | 494 | ||
| 497 | /****************************************************************************/ | 495 | /****************************************************************************/ |
| 498 | static int nat_callforwarding(struct sk_buff **pskb, struct nf_conn *ct, | 496 | static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct, |
| 499 | enum ip_conntrack_info ctinfo, | 497 | enum ip_conntrack_info ctinfo, |
| 500 | unsigned char **data, int dataoff, | 498 | unsigned char **data, int dataoff, |
| 501 | TransportAddress *taddr, __be16 port, | 499 | TransportAddress *taddr, __be16 port, |
| @@ -525,7 +523,7 @@ static int nat_callforwarding(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 525 | } | 523 | } |
| 526 | 524 | ||
| 527 | /* Modify signal */ | 525 | /* Modify signal */ |
| 528 | if (!set_h225_addr(pskb, data, dataoff, taddr, | 526 | if (!set_h225_addr(skb, data, dataoff, taddr, |
| 529 | &ct->tuplehash[!dir].tuple.dst.u3, | 527 | &ct->tuplehash[!dir].tuple.dst.u3, |
| 530 | htons(nated_port)) == 0) { | 528 | htons(nated_port)) == 0) { |
| 531 | nf_ct_unexpect_related(exp); | 529 | nf_ct_unexpect_related(exp); |
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index 93d8a0a8f035..8718da00ef2a 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c | |||
| @@ -111,22 +111,14 @@ static void mangle_contents(struct sk_buff *skb, | |||
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | /* Unusual, but possible case. */ | 113 | /* Unusual, but possible case. */ |
| 114 | static int enlarge_skb(struct sk_buff **pskb, unsigned int extra) | 114 | static int enlarge_skb(struct sk_buff *skb, unsigned int extra) |
| 115 | { | 115 | { |
| 116 | struct sk_buff *nskb; | 116 | if (skb->len + extra > 65535) |
| 117 | |||
| 118 | if ((*pskb)->len + extra > 65535) | ||
| 119 | return 0; | 117 | return 0; |
| 120 | 118 | ||
| 121 | nskb = skb_copy_expand(*pskb, skb_headroom(*pskb), extra, GFP_ATOMIC); | 119 | if (pskb_expand_head(skb, 0, extra - skb_tailroom(skb), GFP_ATOMIC)) |
| 122 | if (!nskb) | ||
| 123 | return 0; | 120 | return 0; |
| 124 | 121 | ||
| 125 | /* Transfer socket to new skb. */ | ||
| 126 | if ((*pskb)->sk) | ||
| 127 | skb_set_owner_w(nskb, (*pskb)->sk); | ||
| 128 | kfree_skb(*pskb); | ||
| 129 | *pskb = nskb; | ||
| 130 | return 1; | 122 | return 1; |
| 131 | } | 123 | } |
| 132 | 124 | ||
| @@ -139,7 +131,7 @@ static int enlarge_skb(struct sk_buff **pskb, unsigned int extra) | |||
| 139 | * | 131 | * |
| 140 | * */ | 132 | * */ |
| 141 | int | 133 | int |
| 142 | nf_nat_mangle_tcp_packet(struct sk_buff **pskb, | 134 | nf_nat_mangle_tcp_packet(struct sk_buff *skb, |
| 143 | struct nf_conn *ct, | 135 | struct nf_conn *ct, |
| 144 | enum ip_conntrack_info ctinfo, | 136 | enum ip_conntrack_info ctinfo, |
| 145 | unsigned int match_offset, | 137 | unsigned int match_offset, |
| @@ -147,37 +139,37 @@ nf_nat_mangle_tcp_packet(struct sk_buff **pskb, | |||
| 147 | const char *rep_buffer, | 139 | const char *rep_buffer, |
| 148 | unsigned int rep_len) | 140 | unsigned int rep_len) |
| 149 | { | 141 | { |
| 150 | struct rtable *rt = (struct rtable *)(*pskb)->dst; | 142 | struct rtable *rt = (struct rtable *)skb->dst; |
| 151 | struct iphdr *iph; | 143 | struct iphdr *iph; |
| 152 | struct tcphdr *tcph; | 144 | struct tcphdr *tcph; |
| 153 | int oldlen, datalen; | 145 | int oldlen, datalen; |
| 154 | 146 | ||
| 155 | if (!skb_make_writable(pskb, (*pskb)->len)) | 147 | if (!skb_make_writable(skb, skb->len)) |
| 156 | return 0; | 148 | return 0; |
| 157 | 149 | ||
| 158 | if (rep_len > match_len && | 150 | if (rep_len > match_len && |
| 159 | rep_len - match_len > skb_tailroom(*pskb) && | 151 | rep_len - match_len > skb_tailroom(skb) && |
| 160 | !enlarge_skb(pskb, rep_len - match_len)) | 152 | !enlarge_skb(skb, rep_len - match_len)) |
| 161 | return 0; | 153 | return 0; |
| 162 | 154 | ||
| 163 | SKB_LINEAR_ASSERT(*pskb); | 155 | SKB_LINEAR_ASSERT(skb); |
| 164 | 156 | ||
| 165 | iph = ip_hdr(*pskb); | 157 | iph = ip_hdr(skb); |
| 166 | tcph = (void *)iph + iph->ihl*4; | 158 | tcph = (void *)iph + iph->ihl*4; |
| 167 | 159 | ||
| 168 | oldlen = (*pskb)->len - iph->ihl*4; | 160 | oldlen = skb->len - iph->ihl*4; |
| 169 | mangle_contents(*pskb, iph->ihl*4 + tcph->doff*4, | 161 | mangle_contents(skb, iph->ihl*4 + tcph->doff*4, |
| 170 | match_offset, match_len, rep_buffer, rep_len); | 162 | match_offset, match_len, rep_buffer, rep_len); |
| 171 | 163 | ||
| 172 | datalen = (*pskb)->len - iph->ihl*4; | 164 | datalen = skb->len - iph->ihl*4; |
| 173 | if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) { | 165 | if (skb->ip_summed != CHECKSUM_PARTIAL) { |
| 174 | if (!(rt->rt_flags & RTCF_LOCAL) && | 166 | if (!(rt->rt_flags & RTCF_LOCAL) && |
| 175 | (*pskb)->dev->features & NETIF_F_V4_CSUM) { | 167 | skb->dev->features & NETIF_F_V4_CSUM) { |
| 176 | (*pskb)->ip_summed = CHECKSUM_PARTIAL; | 168 | skb->ip_summed = CHECKSUM_PARTIAL; |
| 177 | (*pskb)->csum_start = skb_headroom(*pskb) + | 169 | skb->csum_start = skb_headroom(skb) + |
| 178 | skb_network_offset(*pskb) + | 170 | skb_network_offset(skb) + |
| 179 | iph->ihl * 4; | 171 | iph->ihl * 4; |
| 180 | (*pskb)->csum_offset = offsetof(struct tcphdr, check); | 172 | skb->csum_offset = offsetof(struct tcphdr, check); |
| 181 | tcph->check = ~tcp_v4_check(datalen, | 173 | tcph->check = ~tcp_v4_check(datalen, |
| 182 | iph->saddr, iph->daddr, 0); | 174 | iph->saddr, iph->daddr, 0); |
| 183 | } else { | 175 | } else { |
| @@ -188,7 +180,7 @@ nf_nat_mangle_tcp_packet(struct sk_buff **pskb, | |||
| 188 | datalen, 0)); | 180 | datalen, 0)); |
| 189 | } | 181 | } |
| 190 | } else | 182 | } else |
| 191 | nf_proto_csum_replace2(&tcph->check, *pskb, | 183 | nf_proto_csum_replace2(&tcph->check, skb, |
| 192 | htons(oldlen), htons(datalen), 1); | 184 | htons(oldlen), htons(datalen), 1); |
| 193 | 185 | ||
| 194 | if (rep_len != match_len) { | 186 | if (rep_len != match_len) { |
| @@ -197,7 +189,7 @@ nf_nat_mangle_tcp_packet(struct sk_buff **pskb, | |||
| 197 | (int)rep_len - (int)match_len, | 189 | (int)rep_len - (int)match_len, |
| 198 | ct, ctinfo); | 190 | ct, ctinfo); |
| 199 | /* Tell TCP window tracking about seq change */ | 191 | /* Tell TCP window tracking about seq change */ |
| 200 | nf_conntrack_tcp_update(*pskb, ip_hdrlen(*pskb), | 192 | nf_conntrack_tcp_update(skb, ip_hdrlen(skb), |
| 201 | ct, CTINFO2DIR(ctinfo)); | 193 | ct, CTINFO2DIR(ctinfo)); |
| 202 | } | 194 | } |
| 203 | return 1; | 195 | return 1; |
| @@ -215,7 +207,7 @@ EXPORT_SYMBOL(nf_nat_mangle_tcp_packet); | |||
| 215 | * should be fairly easy to do. | 207 | * should be fairly easy to do. |
| 216 | */ | 208 | */ |
| 217 | int | 209 | int |
| 218 | nf_nat_mangle_udp_packet(struct sk_buff **pskb, | 210 | nf_nat_mangle_udp_packet(struct sk_buff *skb, |
| 219 | struct nf_conn *ct, | 211 | struct nf_conn *ct, |
| 220 | enum ip_conntrack_info ctinfo, | 212 | enum ip_conntrack_info ctinfo, |
| 221 | unsigned int match_offset, | 213 | unsigned int match_offset, |
| @@ -223,48 +215,48 @@ nf_nat_mangle_udp_packet(struct sk_buff **pskb, | |||
| 223 | const char *rep_buffer, | 215 | const char *rep_buffer, |
| 224 | unsigned int rep_len) | 216 | unsigned int rep_len) |
| 225 | { | 217 | { |
| 226 | struct rtable *rt = (struct rtable *)(*pskb)->dst; | 218 | struct rtable *rt = (struct rtable *)skb->dst; |
| 227 | struct iphdr *iph; | 219 | struct iphdr *iph; |
| 228 | struct udphdr *udph; | 220 | struct udphdr *udph; |
| 229 | int datalen, oldlen; | 221 | int datalen, oldlen; |
| 230 | 222 | ||
| 231 | /* UDP helpers might accidentally mangle the wrong packet */ | 223 | /* UDP helpers might accidentally mangle the wrong packet */ |
| 232 | iph = ip_hdr(*pskb); | 224 | iph = ip_hdr(skb); |
| 233 | if ((*pskb)->len < iph->ihl*4 + sizeof(*udph) + | 225 | if (skb->len < iph->ihl*4 + sizeof(*udph) + |
| 234 | match_offset + match_len) | 226 | match_offset + match_len) |
| 235 | return 0; | 227 | return 0; |
| 236 | 228 | ||
| 237 | if (!skb_make_writable(pskb, (*pskb)->len)) | 229 | if (!skb_make_writable(skb, skb->len)) |
| 238 | return 0; | 230 | return 0; |
| 239 | 231 | ||
| 240 | if (rep_len > match_len && | 232 | if (rep_len > match_len && |
| 241 | rep_len - match_len > skb_tailroom(*pskb) && | 233 | rep_len - match_len > skb_tailroom(skb) && |
| 242 | !enlarge_skb(pskb, rep_len - match_len)) | 234 | !enlarge_skb(skb, rep_len - match_len)) |
| 243 | return 0; | 235 | return 0; |
| 244 | 236 | ||
| 245 | iph = ip_hdr(*pskb); | 237 | iph = ip_hdr(skb); |
| 246 | udph = (void *)iph + iph->ihl*4; | 238 | udph = (void *)iph + iph->ihl*4; |
| 247 | 239 | ||
| 248 | oldlen = (*pskb)->len - iph->ihl*4; | 240 | oldlen = skb->len - iph->ihl*4; |
| 249 | mangle_contents(*pskb, iph->ihl*4 + sizeof(*udph), | 241 | mangle_contents(skb, iph->ihl*4 + sizeof(*udph), |
| 250 | match_offset, match_len, rep_buffer, rep_len); | 242 | match_offset, match_len, rep_buffer, rep_len); |
| 251 | 243 | ||
| 252 | /* update the length of the UDP packet */ | 244 | /* update the length of the UDP packet */ |
| 253 | datalen = (*pskb)->len - iph->ihl*4; | 245 | datalen = skb->len - iph->ihl*4; |
| 254 | udph->len = htons(datalen); | 246 | udph->len = htons(datalen); |
| 255 | 247 | ||
| 256 | /* fix udp checksum if udp checksum was previously calculated */ | 248 | /* fix udp checksum if udp checksum was previously calculated */ |
| 257 | if (!udph->check && (*pskb)->ip_summed != CHECKSUM_PARTIAL) | 249 | if (!udph->check && skb->ip_summed != CHECKSUM_PARTIAL) |
| 258 | return 1; | 250 | return 1; |
| 259 | 251 | ||
| 260 | if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) { | 252 | if (skb->ip_summed != CHECKSUM_PARTIAL) { |
| 261 | if (!(rt->rt_flags & RTCF_LOCAL) && | 253 | if (!(rt->rt_flags & RTCF_LOCAL) && |
| 262 | (*pskb)->dev->features & NETIF_F_V4_CSUM) { | 254 | skb->dev->features & NETIF_F_V4_CSUM) { |
| 263 | (*pskb)->ip_summed = CHECKSUM_PARTIAL; | 255 | skb->ip_summed = CHECKSUM_PARTIAL; |
| 264 | (*pskb)->csum_start = skb_headroom(*pskb) + | 256 | skb->csum_start = skb_headroom(skb) + |
| 265 | skb_network_offset(*pskb) + | 257 | skb_network_offset(skb) + |
| 266 | iph->ihl * 4; | 258 | iph->ihl * 4; |
| 267 | (*pskb)->csum_offset = offsetof(struct udphdr, check); | 259 | skb->csum_offset = offsetof(struct udphdr, check); |
| 268 | udph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, | 260 | udph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, |
| 269 | datalen, IPPROTO_UDP, | 261 | datalen, IPPROTO_UDP, |
| 270 | 0); | 262 | 0); |
| @@ -278,7 +270,7 @@ nf_nat_mangle_udp_packet(struct sk_buff **pskb, | |||
| 278 | udph->check = CSUM_MANGLED_0; | 270 | udph->check = CSUM_MANGLED_0; |
| 279 | } | 271 | } |
| 280 | } else | 272 | } else |
| 281 | nf_proto_csum_replace2(&udph->check, *pskb, | 273 | nf_proto_csum_replace2(&udph->check, skb, |
| 282 | htons(oldlen), htons(datalen), 1); | 274 | htons(oldlen), htons(datalen), 1); |
| 283 | 275 | ||
| 284 | return 1; | 276 | return 1; |
| @@ -330,7 +322,7 @@ sack_adjust(struct sk_buff *skb, | |||
| 330 | 322 | ||
| 331 | /* TCP SACK sequence number adjustment */ | 323 | /* TCP SACK sequence number adjustment */ |
| 332 | static inline unsigned int | 324 | static inline unsigned int |
| 333 | nf_nat_sack_adjust(struct sk_buff **pskb, | 325 | nf_nat_sack_adjust(struct sk_buff *skb, |
| 334 | struct tcphdr *tcph, | 326 | struct tcphdr *tcph, |
| 335 | struct nf_conn *ct, | 327 | struct nf_conn *ct, |
| 336 | enum ip_conntrack_info ctinfo) | 328 | enum ip_conntrack_info ctinfo) |
| @@ -338,17 +330,17 @@ nf_nat_sack_adjust(struct sk_buff **pskb, | |||
| 338 | unsigned int dir, optoff, optend; | 330 | unsigned int dir, optoff, optend; |
| 339 | struct nf_conn_nat *nat = nfct_nat(ct); | 331 | struct nf_conn_nat *nat = nfct_nat(ct); |
| 340 | 332 | ||
| 341 | optoff = ip_hdrlen(*pskb) + sizeof(struct tcphdr); | 333 | optoff = ip_hdrlen(skb) + sizeof(struct tcphdr); |
| 342 | optend = ip_hdrlen(*pskb) + tcph->doff * 4; | 334 | optend = ip_hdrlen(skb) + tcph->doff * 4; |
| 343 | 335 | ||
| 344 | if (!skb_make_writable(pskb, optend)) | 336 | if (!skb_make_writable(skb, optend)) |
| 345 | return 0; | 337 | return 0; |
| 346 | 338 | ||
| 347 | dir = CTINFO2DIR(ctinfo); | 339 | dir = CTINFO2DIR(ctinfo); |
| 348 | 340 | ||
| 349 | while (optoff < optend) { | 341 | while (optoff < optend) { |
| 350 | /* Usually: option, length. */ | 342 | /* Usually: option, length. */ |
| 351 | unsigned char *op = (*pskb)->data + optoff; | 343 | unsigned char *op = skb->data + optoff; |
| 352 | 344 | ||
| 353 | switch (op[0]) { | 345 | switch (op[0]) { |
| 354 | case TCPOPT_EOL: | 346 | case TCPOPT_EOL: |
| @@ -365,7 +357,7 @@ nf_nat_sack_adjust(struct sk_buff **pskb, | |||
| 365 | if (op[0] == TCPOPT_SACK && | 357 | if (op[0] == TCPOPT_SACK && |
| 366 | op[1] >= 2+TCPOLEN_SACK_PERBLOCK && | 358 | op[1] >= 2+TCPOLEN_SACK_PERBLOCK && |
| 367 | ((op[1] - 2) % TCPOLEN_SACK_PERBLOCK) == 0) | 359 | ((op[1] - 2) % TCPOLEN_SACK_PERBLOCK) == 0) |
| 368 | sack_adjust(*pskb, tcph, optoff+2, | 360 | sack_adjust(skb, tcph, optoff+2, |
| 369 | optoff+op[1], &nat->seq[!dir]); | 361 | optoff+op[1], &nat->seq[!dir]); |
| 370 | optoff += op[1]; | 362 | optoff += op[1]; |
| 371 | } | 363 | } |
| @@ -375,7 +367,7 @@ nf_nat_sack_adjust(struct sk_buff **pskb, | |||
| 375 | 367 | ||
| 376 | /* TCP sequence number adjustment. Returns 1 on success, 0 on failure */ | 368 | /* TCP sequence number adjustment. Returns 1 on success, 0 on failure */ |
| 377 | int | 369 | int |
| 378 | nf_nat_seq_adjust(struct sk_buff **pskb, | 370 | nf_nat_seq_adjust(struct sk_buff *skb, |
| 379 | struct nf_conn *ct, | 371 | struct nf_conn *ct, |
| 380 | enum ip_conntrack_info ctinfo) | 372 | enum ip_conntrack_info ctinfo) |
| 381 | { | 373 | { |
| @@ -390,10 +382,10 @@ nf_nat_seq_adjust(struct sk_buff **pskb, | |||
| 390 | this_way = &nat->seq[dir]; | 382 | this_way = &nat->seq[dir]; |
| 391 | other_way = &nat->seq[!dir]; | 383 | other_way = &nat->seq[!dir]; |
| 392 | 384 | ||
| 393 | if (!skb_make_writable(pskb, ip_hdrlen(*pskb) + sizeof(*tcph))) | 385 | if (!skb_make_writable(skb, ip_hdrlen(skb) + sizeof(*tcph))) |
| 394 | return 0; | 386 | return 0; |
| 395 | 387 | ||
| 396 | tcph = (void *)(*pskb)->data + ip_hdrlen(*pskb); | 388 | tcph = (void *)skb->data + ip_hdrlen(skb); |
| 397 | if (after(ntohl(tcph->seq), this_way->correction_pos)) | 389 | if (after(ntohl(tcph->seq), this_way->correction_pos)) |
| 398 | newseq = htonl(ntohl(tcph->seq) + this_way->offset_after); | 390 | newseq = htonl(ntohl(tcph->seq) + this_way->offset_after); |
| 399 | else | 391 | else |
| @@ -405,8 +397,8 @@ nf_nat_seq_adjust(struct sk_buff **pskb, | |||
| 405 | else | 397 | else |
| 406 | newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before); | 398 | newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before); |
| 407 | 399 | ||
| 408 | nf_proto_csum_replace4(&tcph->check, *pskb, tcph->seq, newseq, 0); | 400 | nf_proto_csum_replace4(&tcph->check, skb, tcph->seq, newseq, 0); |
| 409 | nf_proto_csum_replace4(&tcph->check, *pskb, tcph->ack_seq, newack, 0); | 401 | nf_proto_csum_replace4(&tcph->check, skb, tcph->ack_seq, newack, 0); |
| 410 | 402 | ||
| 411 | pr_debug("Adjusting sequence number from %u->%u, ack from %u->%u\n", | 403 | pr_debug("Adjusting sequence number from %u->%u, ack from %u->%u\n", |
| 412 | ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq), | 404 | ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq), |
| @@ -415,10 +407,10 @@ nf_nat_seq_adjust(struct sk_buff **pskb, | |||
| 415 | tcph->seq = newseq; | 407 | tcph->seq = newseq; |
| 416 | tcph->ack_seq = newack; | 408 | tcph->ack_seq = newack; |
| 417 | 409 | ||
| 418 | if (!nf_nat_sack_adjust(pskb, tcph, ct, ctinfo)) | 410 | if (!nf_nat_sack_adjust(skb, tcph, ct, ctinfo)) |
| 419 | return 0; | 411 | return 0; |
| 420 | 412 | ||
| 421 | nf_conntrack_tcp_update(*pskb, ip_hdrlen(*pskb), ct, dir); | 413 | nf_conntrack_tcp_update(skb, ip_hdrlen(skb), ct, dir); |
| 422 | 414 | ||
| 423 | return 1; | 415 | return 1; |
| 424 | } | 416 | } |
diff --git a/net/ipv4/netfilter/nf_nat_irc.c b/net/ipv4/netfilter/nf_nat_irc.c index bcf274bba602..766e2c16c6b9 100644 --- a/net/ipv4/netfilter/nf_nat_irc.c +++ b/net/ipv4/netfilter/nf_nat_irc.c | |||
| @@ -27,7 +27,7 @@ MODULE_DESCRIPTION("IRC (DCC) NAT helper"); | |||
| 27 | MODULE_LICENSE("GPL"); | 27 | MODULE_LICENSE("GPL"); |
| 28 | MODULE_ALIAS("ip_nat_irc"); | 28 | MODULE_ALIAS("ip_nat_irc"); |
| 29 | 29 | ||
| 30 | static unsigned int help(struct sk_buff **pskb, | 30 | static unsigned int help(struct sk_buff *skb, |
| 31 | enum ip_conntrack_info ctinfo, | 31 | enum ip_conntrack_info ctinfo, |
| 32 | unsigned int matchoff, | 32 | unsigned int matchoff, |
| 33 | unsigned int matchlen, | 33 | unsigned int matchlen, |
| @@ -58,7 +58,7 @@ static unsigned int help(struct sk_buff **pskb, | |||
| 58 | pr_debug("nf_nat_irc: inserting '%s' == %u.%u.%u.%u, port %u\n", | 58 | pr_debug("nf_nat_irc: inserting '%s' == %u.%u.%u.%u, port %u\n", |
| 59 | buffer, NIPQUAD(ip), port); | 59 | buffer, NIPQUAD(ip), port); |
| 60 | 60 | ||
| 61 | ret = nf_nat_mangle_tcp_packet(pskb, exp->master, ctinfo, | 61 | ret = nf_nat_mangle_tcp_packet(skb, exp->master, ctinfo, |
| 62 | matchoff, matchlen, buffer, | 62 | matchoff, matchlen, buffer, |
| 63 | strlen(buffer)); | 63 | strlen(buffer)); |
| 64 | if (ret != NF_ACCEPT) | 64 | if (ret != NF_ACCEPT) |
diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c index 984ec8308b2e..e1385a099079 100644 --- a/net/ipv4/netfilter/nf_nat_pptp.c +++ b/net/ipv4/netfilter/nf_nat_pptp.c | |||
| @@ -110,7 +110,7 @@ static void pptp_nat_expected(struct nf_conn *ct, | |||
| 110 | 110 | ||
| 111 | /* outbound packets == from PNS to PAC */ | 111 | /* outbound packets == from PNS to PAC */ |
| 112 | static int | 112 | static int |
| 113 | pptp_outbound_pkt(struct sk_buff **pskb, | 113 | pptp_outbound_pkt(struct sk_buff *skb, |
| 114 | struct nf_conn *ct, | 114 | struct nf_conn *ct, |
| 115 | enum ip_conntrack_info ctinfo, | 115 | enum ip_conntrack_info ctinfo, |
| 116 | struct PptpControlHeader *ctlh, | 116 | struct PptpControlHeader *ctlh, |
| @@ -175,7 +175,7 @@ pptp_outbound_pkt(struct sk_buff **pskb, | |||
| 175 | ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_callid)); | 175 | ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_callid)); |
| 176 | 176 | ||
| 177 | /* mangle packet */ | 177 | /* mangle packet */ |
| 178 | if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, | 178 | if (nf_nat_mangle_tcp_packet(skb, ct, ctinfo, |
| 179 | cid_off + sizeof(struct pptp_pkt_hdr) + | 179 | cid_off + sizeof(struct pptp_pkt_hdr) + |
| 180 | sizeof(struct PptpControlHeader), | 180 | sizeof(struct PptpControlHeader), |
| 181 | sizeof(new_callid), (char *)&new_callid, | 181 | sizeof(new_callid), (char *)&new_callid, |
| @@ -213,7 +213,7 @@ pptp_exp_gre(struct nf_conntrack_expect *expect_orig, | |||
| 213 | 213 | ||
| 214 | /* inbound packets == from PAC to PNS */ | 214 | /* inbound packets == from PAC to PNS */ |
| 215 | static int | 215 | static int |
| 216 | pptp_inbound_pkt(struct sk_buff **pskb, | 216 | pptp_inbound_pkt(struct sk_buff *skb, |
| 217 | struct nf_conn *ct, | 217 | struct nf_conn *ct, |
| 218 | enum ip_conntrack_info ctinfo, | 218 | enum ip_conntrack_info ctinfo, |
| 219 | struct PptpControlHeader *ctlh, | 219 | struct PptpControlHeader *ctlh, |
| @@ -268,7 +268,7 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
| 268 | pr_debug("altering peer call id from 0x%04x to 0x%04x\n", | 268 | pr_debug("altering peer call id from 0x%04x to 0x%04x\n", |
| 269 | ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid)); | 269 | ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid)); |
| 270 | 270 | ||
| 271 | if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, | 271 | if (nf_nat_mangle_tcp_packet(skb, ct, ctinfo, |
| 272 | pcid_off + sizeof(struct pptp_pkt_hdr) + | 272 | pcid_off + sizeof(struct pptp_pkt_hdr) + |
| 273 | sizeof(struct PptpControlHeader), | 273 | sizeof(struct PptpControlHeader), |
| 274 | sizeof(new_pcid), (char *)&new_pcid, | 274 | sizeof(new_pcid), (char *)&new_pcid, |
diff --git a/net/ipv4/netfilter/nf_nat_proto_gre.c b/net/ipv4/netfilter/nf_nat_proto_gre.c index d562290b1820..b820f9960356 100644 --- a/net/ipv4/netfilter/nf_nat_proto_gre.c +++ b/net/ipv4/netfilter/nf_nat_proto_gre.c | |||
| @@ -98,21 +98,21 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
| 98 | 98 | ||
| 99 | /* manipulate a GRE packet according to maniptype */ | 99 | /* manipulate a GRE packet according to maniptype */ |
| 100 | static int | 100 | static int |
| 101 | gre_manip_pkt(struct sk_buff **pskb, unsigned int iphdroff, | 101 | gre_manip_pkt(struct sk_buff *skb, unsigned int iphdroff, |
| 102 | const struct nf_conntrack_tuple *tuple, | 102 | const struct nf_conntrack_tuple *tuple, |
| 103 | enum nf_nat_manip_type maniptype) | 103 | enum nf_nat_manip_type maniptype) |
| 104 | { | 104 | { |
| 105 | struct gre_hdr *greh; | 105 | struct gre_hdr *greh; |
| 106 | struct gre_hdr_pptp *pgreh; | 106 | struct gre_hdr_pptp *pgreh; |
| 107 | struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff); | 107 | struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); |
| 108 | unsigned int hdroff = iphdroff + iph->ihl * 4; | 108 | unsigned int hdroff = iphdroff + iph->ihl * 4; |
| 109 | 109 | ||
| 110 | /* pgreh includes two optional 32bit fields which are not required | 110 | /* pgreh includes two optional 32bit fields which are not required |
| 111 | * to be there. That's where the magic '8' comes from */ | 111 | * to be there. That's where the magic '8' comes from */ |
| 112 | if (!skb_make_writable(pskb, hdroff + sizeof(*pgreh) - 8)) | 112 | if (!skb_make_writable(skb, hdroff + sizeof(*pgreh) - 8)) |
| 113 | return 0; | 113 | return 0; |
| 114 | 114 | ||
| 115 | greh = (void *)(*pskb)->data + hdroff; | 115 | greh = (void *)skb->data + hdroff; |
| 116 | pgreh = (struct gre_hdr_pptp *)greh; | 116 | pgreh = (struct gre_hdr_pptp *)greh; |
| 117 | 117 | ||
| 118 | /* we only have destination manip of a packet, since 'source key' | 118 | /* we only have destination manip of a packet, since 'source key' |
diff --git a/net/ipv4/netfilter/nf_nat_proto_icmp.c b/net/ipv4/netfilter/nf_nat_proto_icmp.c index 898d73771155..b9fc724388fc 100644 --- a/net/ipv4/netfilter/nf_nat_proto_icmp.c +++ b/net/ipv4/netfilter/nf_nat_proto_icmp.c | |||
| @@ -52,20 +52,20 @@ icmp_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | static int | 54 | static int |
| 55 | icmp_manip_pkt(struct sk_buff **pskb, | 55 | icmp_manip_pkt(struct sk_buff *skb, |
| 56 | unsigned int iphdroff, | 56 | unsigned int iphdroff, |
| 57 | const struct nf_conntrack_tuple *tuple, | 57 | const struct nf_conntrack_tuple *tuple, |
| 58 | enum nf_nat_manip_type maniptype) | 58 | enum nf_nat_manip_type maniptype) |
| 59 | { | 59 | { |
| 60 | struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff); | 60 | struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); |
| 61 | struct icmphdr *hdr; | 61 | struct icmphdr *hdr; |
| 62 | unsigned int hdroff = iphdroff + iph->ihl*4; | 62 | unsigned int hdroff = iphdroff + iph->ihl*4; |
| 63 | 63 | ||
| 64 | if (!skb_make_writable(pskb, hdroff + sizeof(*hdr))) | 64 | if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) |
| 65 | return 0; | 65 | return 0; |
| 66 | 66 | ||
| 67 | hdr = (struct icmphdr *)((*pskb)->data + hdroff); | 67 | hdr = (struct icmphdr *)(skb->data + hdroff); |
| 68 | nf_proto_csum_replace2(&hdr->checksum, *pskb, | 68 | nf_proto_csum_replace2(&hdr->checksum, skb, |
| 69 | hdr->un.echo.id, tuple->src.u.icmp.id, 0); | 69 | hdr->un.echo.id, tuple->src.u.icmp.id, 0); |
| 70 | hdr->un.echo.id = tuple->src.u.icmp.id; | 70 | hdr->un.echo.id = tuple->src.u.icmp.id; |
| 71 | return 1; | 71 | return 1; |
diff --git a/net/ipv4/netfilter/nf_nat_proto_tcp.c b/net/ipv4/netfilter/nf_nat_proto_tcp.c index 5bbbb2acdc70..6bab2e184455 100644 --- a/net/ipv4/netfilter/nf_nat_proto_tcp.c +++ b/net/ipv4/netfilter/nf_nat_proto_tcp.c | |||
| @@ -88,12 +88,12 @@ tcp_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | static int | 90 | static int |
| 91 | tcp_manip_pkt(struct sk_buff **pskb, | 91 | tcp_manip_pkt(struct sk_buff *skb, |
| 92 | unsigned int iphdroff, | 92 | unsigned int iphdroff, |
| 93 | const struct nf_conntrack_tuple *tuple, | 93 | const struct nf_conntrack_tuple *tuple, |
| 94 | enum nf_nat_manip_type maniptype) | 94 | enum nf_nat_manip_type maniptype) |
| 95 | { | 95 | { |
| 96 | struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff); | 96 | struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); |
| 97 | struct tcphdr *hdr; | 97 | struct tcphdr *hdr; |
| 98 | unsigned int hdroff = iphdroff + iph->ihl*4; | 98 | unsigned int hdroff = iphdroff + iph->ihl*4; |
| 99 | __be32 oldip, newip; | 99 | __be32 oldip, newip; |
| @@ -103,14 +103,14 @@ tcp_manip_pkt(struct sk_buff **pskb, | |||
| 103 | /* this could be a inner header returned in icmp packet; in such | 103 | /* this could be a inner header returned in icmp packet; in such |
| 104 | cases we cannot update the checksum field since it is outside of | 104 | cases we cannot update the checksum field since it is outside of |
| 105 | the 8 bytes of transport layer headers we are guaranteed */ | 105 | the 8 bytes of transport layer headers we are guaranteed */ |
| 106 | if ((*pskb)->len >= hdroff + sizeof(struct tcphdr)) | 106 | if (skb->len >= hdroff + sizeof(struct tcphdr)) |
| 107 | hdrsize = sizeof(struct tcphdr); | 107 | hdrsize = sizeof(struct tcphdr); |
| 108 | 108 | ||
| 109 | if (!skb_make_writable(pskb, hdroff + hdrsize)) | 109 | if (!skb_make_writable(skb, hdroff + hdrsize)) |
| 110 | return 0; | 110 | return 0; |
| 111 | 111 | ||
| 112 | iph = (struct iphdr *)((*pskb)->data + iphdroff); | 112 | iph = (struct iphdr *)(skb->data + iphdroff); |
| 113 | hdr = (struct tcphdr *)((*pskb)->data + hdroff); | 113 | hdr = (struct tcphdr *)(skb->data + hdroff); |
| 114 | 114 | ||
| 115 | if (maniptype == IP_NAT_MANIP_SRC) { | 115 | if (maniptype == IP_NAT_MANIP_SRC) { |
| 116 | /* Get rid of src ip and src pt */ | 116 | /* Get rid of src ip and src pt */ |
| @@ -132,8 +132,8 @@ tcp_manip_pkt(struct sk_buff **pskb, | |||
| 132 | if (hdrsize < sizeof(*hdr)) | 132 | if (hdrsize < sizeof(*hdr)) |
| 133 | return 1; | 133 | return 1; |
| 134 | 134 | ||
| 135 | nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1); | 135 | nf_proto_csum_replace4(&hdr->check, skb, oldip, newip, 1); |
| 136 | nf_proto_csum_replace2(&hdr->check, *pskb, oldport, newport, 0); | 136 | nf_proto_csum_replace2(&hdr->check, skb, oldport, newport, 0); |
| 137 | return 1; | 137 | return 1; |
| 138 | } | 138 | } |
| 139 | 139 | ||
diff --git a/net/ipv4/netfilter/nf_nat_proto_udp.c b/net/ipv4/netfilter/nf_nat_proto_udp.c index a0af4fd95584..cbf1a61e2908 100644 --- a/net/ipv4/netfilter/nf_nat_proto_udp.c +++ b/net/ipv4/netfilter/nf_nat_proto_udp.c | |||
| @@ -86,22 +86,22 @@ udp_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | static int | 88 | static int |
| 89 | udp_manip_pkt(struct sk_buff **pskb, | 89 | udp_manip_pkt(struct sk_buff *skb, |
| 90 | unsigned int iphdroff, | 90 | unsigned int iphdroff, |
| 91 | const struct nf_conntrack_tuple *tuple, | 91 | const struct nf_conntrack_tuple *tuple, |
| 92 | enum nf_nat_manip_type maniptype) | 92 | enum nf_nat_manip_type maniptype) |
| 93 | { | 93 | { |
| 94 | struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff); | 94 | struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); |
| 95 | struct udphdr *hdr; | 95 | struct udphdr *hdr; |
| 96 | unsigned int hdroff = iphdroff + iph->ihl*4; | 96 | unsigned int hdroff = iphdroff + iph->ihl*4; |
| 97 | __be32 oldip, newip; | 97 | __be32 oldip, newip; |
| 98 | __be16 *portptr, newport; | 98 | __be16 *portptr, newport; |
| 99 | 99 | ||
| 100 | if (!skb_make_writable(pskb, hdroff + sizeof(*hdr))) | 100 | if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) |
| 101 | return 0; | 101 | return 0; |
| 102 | 102 | ||
| 103 | iph = (struct iphdr *)((*pskb)->data + iphdroff); | 103 | iph = (struct iphdr *)(skb->data + iphdroff); |
| 104 | hdr = (struct udphdr *)((*pskb)->data + hdroff); | 104 | hdr = (struct udphdr *)(skb->data + hdroff); |
| 105 | 105 | ||
| 106 | if (maniptype == IP_NAT_MANIP_SRC) { | 106 | if (maniptype == IP_NAT_MANIP_SRC) { |
| 107 | /* Get rid of src ip and src pt */ | 107 | /* Get rid of src ip and src pt */ |
| @@ -116,9 +116,9 @@ udp_manip_pkt(struct sk_buff **pskb, | |||
| 116 | newport = tuple->dst.u.udp.port; | 116 | newport = tuple->dst.u.udp.port; |
| 117 | portptr = &hdr->dest; | 117 | portptr = &hdr->dest; |
| 118 | } | 118 | } |
| 119 | if (hdr->check || (*pskb)->ip_summed == CHECKSUM_PARTIAL) { | 119 | if (hdr->check || skb->ip_summed == CHECKSUM_PARTIAL) { |
| 120 | nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1); | 120 | nf_proto_csum_replace4(&hdr->check, skb, oldip, newip, 1); |
| 121 | nf_proto_csum_replace2(&hdr->check, *pskb, *portptr, newport, | 121 | nf_proto_csum_replace2(&hdr->check, skb, *portptr, newport, |
| 122 | 0); | 122 | 0); |
| 123 | if (!hdr->check) | 123 | if (!hdr->check) |
| 124 | hdr->check = CSUM_MANGLED_0; | 124 | hdr->check = CSUM_MANGLED_0; |
diff --git a/net/ipv4/netfilter/nf_nat_proto_unknown.c b/net/ipv4/netfilter/nf_nat_proto_unknown.c index f50d0203f9c0..cfd2742e9706 100644 --- a/net/ipv4/netfilter/nf_nat_proto_unknown.c +++ b/net/ipv4/netfilter/nf_nat_proto_unknown.c | |||
| @@ -37,7 +37,7 @@ static int unknown_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | static int | 39 | static int |
| 40 | unknown_manip_pkt(struct sk_buff **pskb, | 40 | unknown_manip_pkt(struct sk_buff *skb, |
| 41 | unsigned int iphdroff, | 41 | unsigned int iphdroff, |
| 42 | const struct nf_conntrack_tuple *tuple, | 42 | const struct nf_conntrack_tuple *tuple, |
| 43 | enum nf_nat_manip_type maniptype) | 43 | enum nf_nat_manip_type maniptype) |
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c index 76ec59ae524d..46b25ab5f78b 100644 --- a/net/ipv4/netfilter/nf_nat_rule.c +++ b/net/ipv4/netfilter/nf_nat_rule.c | |||
| @@ -65,7 +65,7 @@ static struct xt_table nat_table = { | |||
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | /* Source NAT */ | 67 | /* Source NAT */ |
| 68 | static unsigned int ipt_snat_target(struct sk_buff **pskb, | 68 | static unsigned int ipt_snat_target(struct sk_buff *skb, |
| 69 | const struct net_device *in, | 69 | const struct net_device *in, |
| 70 | const struct net_device *out, | 70 | const struct net_device *out, |
| 71 | unsigned int hooknum, | 71 | unsigned int hooknum, |
| @@ -78,7 +78,7 @@ static unsigned int ipt_snat_target(struct sk_buff **pskb, | |||
| 78 | 78 | ||
| 79 | NF_CT_ASSERT(hooknum == NF_IP_POST_ROUTING); | 79 | NF_CT_ASSERT(hooknum == NF_IP_POST_ROUTING); |
| 80 | 80 | ||
| 81 | ct = nf_ct_get(*pskb, &ctinfo); | 81 | ct = nf_ct_get(skb, &ctinfo); |
| 82 | 82 | ||
| 83 | /* Connection must be valid and new. */ | 83 | /* Connection must be valid and new. */ |
| 84 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || | 84 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || |
| @@ -107,7 +107,7 @@ static void warn_if_extra_mangle(__be32 dstip, __be32 srcip) | |||
| 107 | ip_rt_put(rt); | 107 | ip_rt_put(rt); |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | static unsigned int ipt_dnat_target(struct sk_buff **pskb, | 110 | static unsigned int ipt_dnat_target(struct sk_buff *skb, |
| 111 | const struct net_device *in, | 111 | const struct net_device *in, |
| 112 | const struct net_device *out, | 112 | const struct net_device *out, |
| 113 | unsigned int hooknum, | 113 | unsigned int hooknum, |
| @@ -121,14 +121,14 @@ static unsigned int ipt_dnat_target(struct sk_buff **pskb, | |||
| 121 | NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING || | 121 | NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING || |
| 122 | hooknum == NF_IP_LOCAL_OUT); | 122 | hooknum == NF_IP_LOCAL_OUT); |
| 123 | 123 | ||
| 124 | ct = nf_ct_get(*pskb, &ctinfo); | 124 | ct = nf_ct_get(skb, &ctinfo); |
| 125 | 125 | ||
| 126 | /* Connection must be valid and new. */ | 126 | /* Connection must be valid and new. */ |
| 127 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); | 127 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); |
| 128 | 128 | ||
| 129 | if (hooknum == NF_IP_LOCAL_OUT && | 129 | if (hooknum == NF_IP_LOCAL_OUT && |
| 130 | mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) | 130 | mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) |
| 131 | warn_if_extra_mangle(ip_hdr(*pskb)->daddr, | 131 | warn_if_extra_mangle(ip_hdr(skb)->daddr, |
| 132 | mr->range[0].min_ip); | 132 | mr->range[0].min_ip); |
| 133 | 133 | ||
| 134 | return nf_nat_setup_info(ct, &mr->range[0], hooknum); | 134 | return nf_nat_setup_info(ct, &mr->range[0], hooknum); |
| @@ -204,7 +204,7 @@ alloc_null_binding_confirmed(struct nf_conn *ct, unsigned int hooknum) | |||
| 204 | return nf_nat_setup_info(ct, &range, hooknum); | 204 | return nf_nat_setup_info(ct, &range, hooknum); |
| 205 | } | 205 | } |
| 206 | 206 | ||
| 207 | int nf_nat_rule_find(struct sk_buff **pskb, | 207 | int nf_nat_rule_find(struct sk_buff *skb, |
| 208 | unsigned int hooknum, | 208 | unsigned int hooknum, |
| 209 | const struct net_device *in, | 209 | const struct net_device *in, |
| 210 | const struct net_device *out, | 210 | const struct net_device *out, |
| @@ -212,7 +212,7 @@ int nf_nat_rule_find(struct sk_buff **pskb, | |||
| 212 | { | 212 | { |
| 213 | int ret; | 213 | int ret; |
| 214 | 214 | ||
| 215 | ret = ipt_do_table(pskb, hooknum, in, out, &nat_table); | 215 | ret = ipt_do_table(skb, hooknum, in, out, &nat_table); |
| 216 | 216 | ||
| 217 | if (ret == NF_ACCEPT) { | 217 | if (ret == NF_ACCEPT) { |
| 218 | if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum))) | 218 | if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum))) |
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c index e14d41976c27..ce9edbcc01e3 100644 --- a/net/ipv4/netfilter/nf_nat_sip.c +++ b/net/ipv4/netfilter/nf_nat_sip.c | |||
| @@ -60,7 +60,7 @@ static void addr_map_init(struct nf_conn *ct, struct addr_map *map) | |||
| 60 | } | 60 | } |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | static int map_sip_addr(struct sk_buff **pskb, enum ip_conntrack_info ctinfo, | 63 | static int map_sip_addr(struct sk_buff *skb, enum ip_conntrack_info ctinfo, |
| 64 | struct nf_conn *ct, const char **dptr, size_t dlen, | 64 | struct nf_conn *ct, const char **dptr, size_t dlen, |
| 65 | enum sip_header_pos pos, struct addr_map *map) | 65 | enum sip_header_pos pos, struct addr_map *map) |
| 66 | { | 66 | { |
| @@ -84,15 +84,15 @@ static int map_sip_addr(struct sk_buff **pskb, enum ip_conntrack_info ctinfo, | |||
| 84 | } else | 84 | } else |
| 85 | return 1; | 85 | return 1; |
| 86 | 86 | ||
| 87 | if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo, | 87 | if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, |
| 88 | matchoff, matchlen, addr, addrlen)) | 88 | matchoff, matchlen, addr, addrlen)) |
| 89 | return 0; | 89 | return 0; |
| 90 | *dptr = (*pskb)->data + ip_hdrlen(*pskb) + sizeof(struct udphdr); | 90 | *dptr = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr); |
| 91 | return 1; | 91 | return 1; |
| 92 | 92 | ||
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | static unsigned int ip_nat_sip(struct sk_buff **pskb, | 95 | static unsigned int ip_nat_sip(struct sk_buff *skb, |
| 96 | enum ip_conntrack_info ctinfo, | 96 | enum ip_conntrack_info ctinfo, |
| 97 | struct nf_conn *ct, | 97 | struct nf_conn *ct, |
| 98 | const char **dptr) | 98 | const char **dptr) |
| @@ -101,8 +101,8 @@ static unsigned int ip_nat_sip(struct sk_buff **pskb, | |||
| 101 | struct addr_map map; | 101 | struct addr_map map; |
| 102 | int dataoff, datalen; | 102 | int dataoff, datalen; |
| 103 | 103 | ||
| 104 | dataoff = ip_hdrlen(*pskb) + sizeof(struct udphdr); | 104 | dataoff = ip_hdrlen(skb) + sizeof(struct udphdr); |
| 105 | datalen = (*pskb)->len - dataoff; | 105 | datalen = skb->len - dataoff; |
| 106 | if (datalen < sizeof("SIP/2.0") - 1) | 106 | if (datalen < sizeof("SIP/2.0") - 1) |
| 107 | return NF_ACCEPT; | 107 | return NF_ACCEPT; |
| 108 | 108 | ||
| @@ -121,19 +121,19 @@ static unsigned int ip_nat_sip(struct sk_buff **pskb, | |||
| 121 | else | 121 | else |
| 122 | pos = POS_REQ_URI; | 122 | pos = POS_REQ_URI; |
| 123 | 123 | ||
| 124 | if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, pos, &map)) | 124 | if (!map_sip_addr(skb, ctinfo, ct, dptr, datalen, pos, &map)) |
| 125 | return NF_DROP; | 125 | return NF_DROP; |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_FROM, &map) || | 128 | if (!map_sip_addr(skb, ctinfo, ct, dptr, datalen, POS_FROM, &map) || |
| 129 | !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_TO, &map) || | 129 | !map_sip_addr(skb, ctinfo, ct, dptr, datalen, POS_TO, &map) || |
| 130 | !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_VIA, &map) || | 130 | !map_sip_addr(skb, ctinfo, ct, dptr, datalen, POS_VIA, &map) || |
| 131 | !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_CONTACT, &map)) | 131 | !map_sip_addr(skb, ctinfo, ct, dptr, datalen, POS_CONTACT, &map)) |
| 132 | return NF_DROP; | 132 | return NF_DROP; |
| 133 | return NF_ACCEPT; | 133 | return NF_ACCEPT; |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | static unsigned int mangle_sip_packet(struct sk_buff **pskb, | 136 | static unsigned int mangle_sip_packet(struct sk_buff *skb, |
| 137 | enum ip_conntrack_info ctinfo, | 137 | enum ip_conntrack_info ctinfo, |
| 138 | struct nf_conn *ct, | 138 | struct nf_conn *ct, |
| 139 | const char **dptr, size_t dlen, | 139 | const char **dptr, size_t dlen, |
| @@ -145,16 +145,16 @@ static unsigned int mangle_sip_packet(struct sk_buff **pskb, | |||
| 145 | if (ct_sip_get_info(ct, *dptr, dlen, &matchoff, &matchlen, pos) <= 0) | 145 | if (ct_sip_get_info(ct, *dptr, dlen, &matchoff, &matchlen, pos) <= 0) |
| 146 | return 0; | 146 | return 0; |
| 147 | 147 | ||
| 148 | if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo, | 148 | if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, |
| 149 | matchoff, matchlen, buffer, bufflen)) | 149 | matchoff, matchlen, buffer, bufflen)) |
| 150 | return 0; | 150 | return 0; |
| 151 | 151 | ||
| 152 | /* We need to reload this. Thanks Patrick. */ | 152 | /* We need to reload this. Thanks Patrick. */ |
| 153 | *dptr = (*pskb)->data + ip_hdrlen(*pskb) + sizeof(struct udphdr); | 153 | *dptr = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr); |
| 154 | return 1; | 154 | return 1; |
| 155 | } | 155 | } |
| 156 | 156 | ||
| 157 | static int mangle_content_len(struct sk_buff **pskb, | 157 | static int mangle_content_len(struct sk_buff *skb, |
| 158 | enum ip_conntrack_info ctinfo, | 158 | enum ip_conntrack_info ctinfo, |
| 159 | struct nf_conn *ct, | 159 | struct nf_conn *ct, |
| 160 | const char *dptr) | 160 | const char *dptr) |
| @@ -163,22 +163,22 @@ static int mangle_content_len(struct sk_buff **pskb, | |||
| 163 | char buffer[sizeof("65536")]; | 163 | char buffer[sizeof("65536")]; |
| 164 | int bufflen; | 164 | int bufflen; |
| 165 | 165 | ||
| 166 | dataoff = ip_hdrlen(*pskb) + sizeof(struct udphdr); | 166 | dataoff = ip_hdrlen(skb) + sizeof(struct udphdr); |
| 167 | 167 | ||
| 168 | /* Get actual SDP lenght */ | 168 | /* Get actual SDP lenght */ |
| 169 | if (ct_sip_get_info(ct, dptr, (*pskb)->len - dataoff, &matchoff, | 169 | if (ct_sip_get_info(ct, dptr, skb->len - dataoff, &matchoff, |
| 170 | &matchlen, POS_SDP_HEADER) > 0) { | 170 | &matchlen, POS_SDP_HEADER) > 0) { |
| 171 | 171 | ||
| 172 | /* since ct_sip_get_info() give us a pointer passing 'v=' | 172 | /* since ct_sip_get_info() give us a pointer passing 'v=' |
| 173 | we need to add 2 bytes in this count. */ | 173 | we need to add 2 bytes in this count. */ |
| 174 | int c_len = (*pskb)->len - dataoff - matchoff + 2; | 174 | int c_len = skb->len - dataoff - matchoff + 2; |
| 175 | 175 | ||
| 176 | /* Now, update SDP length */ | 176 | /* Now, update SDP length */ |
| 177 | if (ct_sip_get_info(ct, dptr, (*pskb)->len - dataoff, &matchoff, | 177 | if (ct_sip_get_info(ct, dptr, skb->len - dataoff, &matchoff, |
| 178 | &matchlen, POS_CONTENT) > 0) { | 178 | &matchlen, POS_CONTENT) > 0) { |
| 179 | 179 | ||
| 180 | bufflen = sprintf(buffer, "%u", c_len); | 180 | bufflen = sprintf(buffer, "%u", c_len); |
| 181 | return nf_nat_mangle_udp_packet(pskb, ct, ctinfo, | 181 | return nf_nat_mangle_udp_packet(skb, ct, ctinfo, |
| 182 | matchoff, matchlen, | 182 | matchoff, matchlen, |
| 183 | buffer, bufflen); | 183 | buffer, bufflen); |
| 184 | } | 184 | } |
| @@ -186,7 +186,7 @@ static int mangle_content_len(struct sk_buff **pskb, | |||
| 186 | return 0; | 186 | return 0; |
| 187 | } | 187 | } |
| 188 | 188 | ||
| 189 | static unsigned int mangle_sdp(struct sk_buff **pskb, | 189 | static unsigned int mangle_sdp(struct sk_buff *skb, |
| 190 | enum ip_conntrack_info ctinfo, | 190 | enum ip_conntrack_info ctinfo, |
| 191 | struct nf_conn *ct, | 191 | struct nf_conn *ct, |
| 192 | __be32 newip, u_int16_t port, | 192 | __be32 newip, u_int16_t port, |
| @@ -195,25 +195,25 @@ static unsigned int mangle_sdp(struct sk_buff **pskb, | |||
| 195 | char buffer[sizeof("nnn.nnn.nnn.nnn")]; | 195 | char buffer[sizeof("nnn.nnn.nnn.nnn")]; |
| 196 | unsigned int dataoff, bufflen; | 196 | unsigned int dataoff, bufflen; |
| 197 | 197 | ||
| 198 | dataoff = ip_hdrlen(*pskb) + sizeof(struct udphdr); | 198 | dataoff = ip_hdrlen(skb) + sizeof(struct udphdr); |
| 199 | 199 | ||
| 200 | /* Mangle owner and contact info. */ | 200 | /* Mangle owner and contact info. */ |
| 201 | bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip)); | 201 | bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip)); |
| 202 | if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff, | 202 | if (!mangle_sip_packet(skb, ctinfo, ct, &dptr, skb->len - dataoff, |
| 203 | buffer, bufflen, POS_OWNER_IP4)) | 203 | buffer, bufflen, POS_OWNER_IP4)) |
| 204 | return 0; | 204 | return 0; |
| 205 | 205 | ||
| 206 | if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff, | 206 | if (!mangle_sip_packet(skb, ctinfo, ct, &dptr, skb->len - dataoff, |
| 207 | buffer, bufflen, POS_CONNECTION_IP4)) | 207 | buffer, bufflen, POS_CONNECTION_IP4)) |
| 208 | return 0; | 208 | return 0; |
| 209 | 209 | ||
| 210 | /* Mangle media port. */ | 210 | /* Mangle media port. */ |
| 211 | bufflen = sprintf(buffer, "%u", port); | 211 | bufflen = sprintf(buffer, "%u", port); |
| 212 | if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff, | 212 | if (!mangle_sip_packet(skb, ctinfo, ct, &dptr, skb->len - dataoff, |
| 213 | buffer, bufflen, POS_MEDIA)) | 213 | buffer, bufflen, POS_MEDIA)) |
| 214 | return 0; | 214 | return 0; |
| 215 | 215 | ||
| 216 | return mangle_content_len(pskb, ctinfo, ct, dptr); | 216 | return mangle_content_len(skb, ctinfo, ct, dptr); |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | static void ip_nat_sdp_expect(struct nf_conn *ct, | 219 | static void ip_nat_sdp_expect(struct nf_conn *ct, |
| @@ -241,7 +241,7 @@ static void ip_nat_sdp_expect(struct nf_conn *ct, | |||
| 241 | 241 | ||
| 242 | /* So, this packet has hit the connection tracking matching code. | 242 | /* So, this packet has hit the connection tracking matching code. |
| 243 | Mangle it, and change the expectation to match the new version. */ | 243 | Mangle it, and change the expectation to match the new version. */ |
| 244 | static unsigned int ip_nat_sdp(struct sk_buff **pskb, | 244 | static unsigned int ip_nat_sdp(struct sk_buff *skb, |
| 245 | enum ip_conntrack_info ctinfo, | 245 | enum ip_conntrack_info ctinfo, |
| 246 | struct nf_conntrack_expect *exp, | 246 | struct nf_conntrack_expect *exp, |
| 247 | const char *dptr) | 247 | const char *dptr) |
| @@ -277,7 +277,7 @@ static unsigned int ip_nat_sdp(struct sk_buff **pskb, | |||
| 277 | if (port == 0) | 277 | if (port == 0) |
| 278 | return NF_DROP; | 278 | return NF_DROP; |
| 279 | 279 | ||
| 280 | if (!mangle_sdp(pskb, ctinfo, ct, newip, port, dptr)) { | 280 | if (!mangle_sdp(skb, ctinfo, ct, newip, port, dptr)) { |
| 281 | nf_ct_unexpect_related(exp); | 281 | nf_ct_unexpect_related(exp); |
| 282 | return NF_DROP; | 282 | return NF_DROP; |
| 283 | } | 283 | } |
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c index 6bfcd3a90f08..03709d6b4b06 100644 --- a/net/ipv4/netfilter/nf_nat_snmp_basic.c +++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c | |||
| @@ -1188,9 +1188,9 @@ static int snmp_parse_mangle(unsigned char *msg, | |||
| 1188 | */ | 1188 | */ |
| 1189 | static int snmp_translate(struct nf_conn *ct, | 1189 | static int snmp_translate(struct nf_conn *ct, |
| 1190 | enum ip_conntrack_info ctinfo, | 1190 | enum ip_conntrack_info ctinfo, |
| 1191 | struct sk_buff **pskb) | 1191 | struct sk_buff *skb) |
| 1192 | { | 1192 | { |
| 1193 | struct iphdr *iph = ip_hdr(*pskb); | 1193 | struct iphdr *iph = ip_hdr(skb); |
| 1194 | struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl); | 1194 | struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl); |
| 1195 | u_int16_t udplen = ntohs(udph->len); | 1195 | u_int16_t udplen = ntohs(udph->len); |
| 1196 | u_int16_t paylen = udplen - sizeof(struct udphdr); | 1196 | u_int16_t paylen = udplen - sizeof(struct udphdr); |
| @@ -1225,13 +1225,13 @@ static int snmp_translate(struct nf_conn *ct, | |||
| 1225 | 1225 | ||
| 1226 | /* We don't actually set up expectations, just adjust internal IP | 1226 | /* We don't actually set up expectations, just adjust internal IP |
| 1227 | * addresses if this is being NATted */ | 1227 | * addresses if this is being NATted */ |
| 1228 | static int help(struct sk_buff **pskb, unsigned int protoff, | 1228 | static int help(struct sk_buff *skb, unsigned int protoff, |
| 1229 | struct nf_conn *ct, | 1229 | struct nf_conn *ct, |
| 1230 | enum ip_conntrack_info ctinfo) | 1230 | enum ip_conntrack_info ctinfo) |
| 1231 | { | 1231 | { |
| 1232 | int dir = CTINFO2DIR(ctinfo); | 1232 | int dir = CTINFO2DIR(ctinfo); |
| 1233 | unsigned int ret; | 1233 | unsigned int ret; |
| 1234 | struct iphdr *iph = ip_hdr(*pskb); | 1234 | struct iphdr *iph = ip_hdr(skb); |
| 1235 | struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl); | 1235 | struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl); |
| 1236 | 1236 | ||
| 1237 | /* SNMP replies and originating SNMP traps get mangled */ | 1237 | /* SNMP replies and originating SNMP traps get mangled */ |
| @@ -1250,7 +1250,7 @@ static int help(struct sk_buff **pskb, unsigned int protoff, | |||
| 1250 | * enough room for a UDP header. Just verify the UDP length field so we | 1250 | * enough room for a UDP header. Just verify the UDP length field so we |
| 1251 | * can mess around with the payload. | 1251 | * can mess around with the payload. |
| 1252 | */ | 1252 | */ |
| 1253 | if (ntohs(udph->len) != (*pskb)->len - (iph->ihl << 2)) { | 1253 | if (ntohs(udph->len) != skb->len - (iph->ihl << 2)) { |
| 1254 | if (net_ratelimit()) | 1254 | if (net_ratelimit()) |
| 1255 | printk(KERN_WARNING "SNMP: dropping malformed packet " | 1255 | printk(KERN_WARNING "SNMP: dropping malformed packet " |
| 1256 | "src=%u.%u.%u.%u dst=%u.%u.%u.%u\n", | 1256 | "src=%u.%u.%u.%u dst=%u.%u.%u.%u\n", |
| @@ -1258,11 +1258,11 @@ static int help(struct sk_buff **pskb, unsigned int protoff, | |||
| 1258 | return NF_DROP; | 1258 | return NF_DROP; |
| 1259 | } | 1259 | } |
| 1260 | 1260 | ||
| 1261 | if (!skb_make_writable(pskb, (*pskb)->len)) | 1261 | if (!skb_make_writable(skb, skb->len)) |
| 1262 | return NF_DROP; | 1262 | return NF_DROP; |
| 1263 | 1263 | ||
| 1264 | spin_lock_bh(&snmp_lock); | 1264 | spin_lock_bh(&snmp_lock); |
| 1265 | ret = snmp_translate(ct, ctinfo, pskb); | 1265 | ret = snmp_translate(ct, ctinfo, skb); |
| 1266 | spin_unlock_bh(&snmp_lock); | 1266 | spin_unlock_bh(&snmp_lock); |
| 1267 | return ret; | 1267 | return ret; |
| 1268 | } | 1268 | } |
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c index 46cc99def165..7db76ea9af91 100644 --- a/net/ipv4/netfilter/nf_nat_standalone.c +++ b/net/ipv4/netfilter/nf_nat_standalone.c | |||
| @@ -67,7 +67,7 @@ static void nat_decode_session(struct sk_buff *skb, struct flowi *fl) | |||
| 67 | 67 | ||
| 68 | static unsigned int | 68 | static unsigned int |
| 69 | nf_nat_fn(unsigned int hooknum, | 69 | nf_nat_fn(unsigned int hooknum, |
| 70 | struct sk_buff **pskb, | 70 | struct sk_buff *skb, |
| 71 | const struct net_device *in, | 71 | const struct net_device *in, |
| 72 | const struct net_device *out, | 72 | const struct net_device *out, |
| 73 | int (*okfn)(struct sk_buff *)) | 73 | int (*okfn)(struct sk_buff *)) |
| @@ -80,9 +80,9 @@ nf_nat_fn(unsigned int hooknum, | |||
| 80 | 80 | ||
| 81 | /* We never see fragments: conntrack defrags on pre-routing | 81 | /* We never see fragments: conntrack defrags on pre-routing |
| 82 | and local-out, and nf_nat_out protects post-routing. */ | 82 | and local-out, and nf_nat_out protects post-routing. */ |
| 83 | NF_CT_ASSERT(!(ip_hdr(*pskb)->frag_off & htons(IP_MF | IP_OFFSET))); | 83 | NF_CT_ASSERT(!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET))); |
| 84 | 84 | ||
| 85 | ct = nf_ct_get(*pskb, &ctinfo); | 85 | ct = nf_ct_get(skb, &ctinfo); |
| 86 | /* Can't track? It's not due to stress, or conntrack would | 86 | /* Can't track? It's not due to stress, or conntrack would |
| 87 | have dropped it. Hence it's the user's responsibilty to | 87 | have dropped it. Hence it's the user's responsibilty to |
| 88 | packet filter it out, or implement conntrack/NAT for that | 88 | packet filter it out, or implement conntrack/NAT for that |
| @@ -91,10 +91,10 @@ nf_nat_fn(unsigned int hooknum, | |||
| 91 | /* Exception: ICMP redirect to new connection (not in | 91 | /* Exception: ICMP redirect to new connection (not in |
| 92 | hash table yet). We must not let this through, in | 92 | hash table yet). We must not let this through, in |
| 93 | case we're doing NAT to the same network. */ | 93 | case we're doing NAT to the same network. */ |
| 94 | if (ip_hdr(*pskb)->protocol == IPPROTO_ICMP) { | 94 | if (ip_hdr(skb)->protocol == IPPROTO_ICMP) { |
| 95 | struct icmphdr _hdr, *hp; | 95 | struct icmphdr _hdr, *hp; |
| 96 | 96 | ||
| 97 | hp = skb_header_pointer(*pskb, ip_hdrlen(*pskb), | 97 | hp = skb_header_pointer(skb, ip_hdrlen(skb), |
| 98 | sizeof(_hdr), &_hdr); | 98 | sizeof(_hdr), &_hdr); |
| 99 | if (hp != NULL && | 99 | if (hp != NULL && |
| 100 | hp->type == ICMP_REDIRECT) | 100 | hp->type == ICMP_REDIRECT) |
| @@ -119,9 +119,9 @@ nf_nat_fn(unsigned int hooknum, | |||
| 119 | switch (ctinfo) { | 119 | switch (ctinfo) { |
| 120 | case IP_CT_RELATED: | 120 | case IP_CT_RELATED: |
| 121 | case IP_CT_RELATED+IP_CT_IS_REPLY: | 121 | case IP_CT_RELATED+IP_CT_IS_REPLY: |
| 122 | if (ip_hdr(*pskb)->protocol == IPPROTO_ICMP) { | 122 | if (ip_hdr(skb)->protocol == IPPROTO_ICMP) { |
| 123 | if (!nf_nat_icmp_reply_translation(ct, ctinfo, | 123 | if (!nf_nat_icmp_reply_translation(ct, ctinfo, |
| 124 | hooknum, pskb)) | 124 | hooknum, skb)) |
| 125 | return NF_DROP; | 125 | return NF_DROP; |
| 126 | else | 126 | else |
| 127 | return NF_ACCEPT; | 127 | return NF_ACCEPT; |
| @@ -141,7 +141,7 @@ nf_nat_fn(unsigned int hooknum, | |||
| 141 | /* LOCAL_IN hook doesn't have a chain! */ | 141 | /* LOCAL_IN hook doesn't have a chain! */ |
| 142 | ret = alloc_null_binding(ct, hooknum); | 142 | ret = alloc_null_binding(ct, hooknum); |
| 143 | else | 143 | else |
| 144 | ret = nf_nat_rule_find(pskb, hooknum, in, out, | 144 | ret = nf_nat_rule_find(skb, hooknum, in, out, |
| 145 | ct); | 145 | ct); |
| 146 | 146 | ||
| 147 | if (ret != NF_ACCEPT) { | 147 | if (ret != NF_ACCEPT) { |
| @@ -159,31 +159,31 @@ nf_nat_fn(unsigned int hooknum, | |||
| 159 | ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY)); | 159 | ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY)); |
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | return nf_nat_packet(ct, ctinfo, hooknum, pskb); | 162 | return nf_nat_packet(ct, ctinfo, hooknum, skb); |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | static unsigned int | 165 | static unsigned int |
| 166 | nf_nat_in(unsigned int hooknum, | 166 | nf_nat_in(unsigned int hooknum, |
| 167 | struct sk_buff **pskb, | 167 | struct sk_buff *skb, |
| 168 | const struct net_device *in, | 168 | const struct net_device *in, |
| 169 | const struct net_device *out, | 169 | const struct net_device *out, |
| 170 | int (*okfn)(struct sk_buff *)) | 170 | int (*okfn)(struct sk_buff *)) |
| 171 | { | 171 | { |
| 172 | unsigned int ret; | 172 | unsigned int ret; |
| 173 | __be32 daddr = ip_hdr(*pskb)->daddr; | 173 | __be32 daddr = ip_hdr(skb)->daddr; |
| 174 | 174 | ||
| 175 | ret = nf_nat_fn(hooknum, pskb, in, out, okfn); | 175 | ret = nf_nat_fn(hooknum, skb, in, out, okfn); |
| 176 | if (ret != NF_DROP && ret != NF_STOLEN && | 176 | if (ret != NF_DROP && ret != NF_STOLEN && |
| 177 | daddr != ip_hdr(*pskb)->daddr) { | 177 | daddr != ip_hdr(skb)->daddr) { |
| 178 | dst_release((*pskb)->dst); | 178 | dst_release(skb->dst); |
| 179 | (*pskb)->dst = NULL; | 179 | skb->dst = NULL; |
| 180 | } | 180 | } |
| 181 | return ret; | 181 | return ret; |
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | static unsigned int | 184 | static unsigned int |
| 185 | nf_nat_out(unsigned int hooknum, | 185 | nf_nat_out(unsigned int hooknum, |
| 186 | struct sk_buff **pskb, | 186 | struct sk_buff *skb, |
| 187 | const struct net_device *in, | 187 | const struct net_device *in, |
| 188 | const struct net_device *out, | 188 | const struct net_device *out, |
| 189 | int (*okfn)(struct sk_buff *)) | 189 | int (*okfn)(struct sk_buff *)) |
| @@ -195,14 +195,14 @@ nf_nat_out(unsigned int hooknum, | |||
| 195 | unsigned int ret; | 195 | unsigned int ret; |
| 196 | 196 | ||
| 197 | /* root is playing with raw sockets. */ | 197 | /* root is playing with raw sockets. */ |
| 198 | if ((*pskb)->len < sizeof(struct iphdr) || | 198 | if (skb->len < sizeof(struct iphdr) || |
| 199 | ip_hdrlen(*pskb) < sizeof(struct iphdr)) | 199 | ip_hdrlen(skb) < sizeof(struct iphdr)) |
| 200 | return NF_ACCEPT; | 200 | return NF_ACCEPT; |
| 201 | 201 | ||
| 202 | ret = nf_nat_fn(hooknum, pskb, in, out, okfn); | 202 | ret = nf_nat_fn(hooknum, skb, in, out, okfn); |
| 203 | #ifdef CONFIG_XFRM | 203 | #ifdef CONFIG_XFRM |
| 204 | if (ret != NF_DROP && ret != NF_STOLEN && | 204 | if (ret != NF_DROP && ret != NF_STOLEN && |
| 205 | (ct = nf_ct_get(*pskb, &ctinfo)) != NULL) { | 205 | (ct = nf_ct_get(skb, &ctinfo)) != NULL) { |
| 206 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 206 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
| 207 | 207 | ||
| 208 | if (ct->tuplehash[dir].tuple.src.u3.ip != | 208 | if (ct->tuplehash[dir].tuple.src.u3.ip != |
| @@ -210,7 +210,7 @@ nf_nat_out(unsigned int hooknum, | |||
| 210 | || ct->tuplehash[dir].tuple.src.u.all != | 210 | || ct->tuplehash[dir].tuple.src.u.all != |
| 211 | ct->tuplehash[!dir].tuple.dst.u.all | 211 | ct->tuplehash[!dir].tuple.dst.u.all |
| 212 | ) | 212 | ) |
| 213 | return ip_xfrm_me_harder(pskb) == 0 ? ret : NF_DROP; | 213 | return ip_xfrm_me_harder(skb) == 0 ? ret : NF_DROP; |
| 214 | } | 214 | } |
| 215 | #endif | 215 | #endif |
| 216 | return ret; | 216 | return ret; |
| @@ -218,7 +218,7 @@ nf_nat_out(unsigned int hooknum, | |||
| 218 | 218 | ||
| 219 | static unsigned int | 219 | static unsigned int |
| 220 | nf_nat_local_fn(unsigned int hooknum, | 220 | nf_nat_local_fn(unsigned int hooknum, |
| 221 | struct sk_buff **pskb, | 221 | struct sk_buff *skb, |
| 222 | const struct net_device *in, | 222 | const struct net_device *in, |
| 223 | const struct net_device *out, | 223 | const struct net_device *out, |
| 224 | int (*okfn)(struct sk_buff *)) | 224 | int (*okfn)(struct sk_buff *)) |
| @@ -228,24 +228,24 @@ nf_nat_local_fn(unsigned int hooknum, | |||
| 228 | unsigned int ret; | 228 | unsigned int ret; |
| 229 | 229 | ||
| 230 | /* root is playing with raw sockets. */ | 230 | /* root is playing with raw sockets. */ |
| 231 | if ((*pskb)->len < sizeof(struct iphdr) || | 231 | if (skb->len < sizeof(struct iphdr) || |
| 232 | ip_hdrlen(*pskb) < sizeof(struct iphdr)) | 232 | ip_hdrlen(skb) < sizeof(struct iphdr)) |
| 233 | return NF_ACCEPT; | 233 | return NF_ACCEPT; |
| 234 | 234 | ||
| 235 | ret = nf_nat_fn(hooknum, pskb, in, out, okfn); | 235 | ret = nf_nat_fn(hooknum, skb, in, out, okfn); |
| 236 | if (ret != NF_DROP && ret != NF_STOLEN && | 236 | if (ret != NF_DROP && ret != NF_STOLEN && |
| 237 | (ct = nf_ct_get(*pskb, &ctinfo)) != NULL) { | 237 | (ct = nf_ct_get(skb, &ctinfo)) != NULL) { |
| 238 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 238 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
| 239 | 239 | ||
| 240 | if (ct->tuplehash[dir].tuple.dst.u3.ip != | 240 | if (ct->tuplehash[dir].tuple.dst.u3.ip != |
| 241 | ct->tuplehash[!dir].tuple.src.u3.ip) { | 241 | ct->tuplehash[!dir].tuple.src.u3.ip) { |
| 242 | if (ip_route_me_harder(pskb, RTN_UNSPEC)) | 242 | if (ip_route_me_harder(skb, RTN_UNSPEC)) |
| 243 | ret = NF_DROP; | 243 | ret = NF_DROP; |
| 244 | } | 244 | } |
| 245 | #ifdef CONFIG_XFRM | 245 | #ifdef CONFIG_XFRM |
| 246 | else if (ct->tuplehash[dir].tuple.dst.u.all != | 246 | else if (ct->tuplehash[dir].tuple.dst.u.all != |
| 247 | ct->tuplehash[!dir].tuple.src.u.all) | 247 | ct->tuplehash[!dir].tuple.src.u.all) |
| 248 | if (ip_xfrm_me_harder(pskb)) | 248 | if (ip_xfrm_me_harder(skb)) |
| 249 | ret = NF_DROP; | 249 | ret = NF_DROP; |
| 250 | #endif | 250 | #endif |
| 251 | } | 251 | } |
| @@ -254,7 +254,7 @@ nf_nat_local_fn(unsigned int hooknum, | |||
| 254 | 254 | ||
| 255 | static unsigned int | 255 | static unsigned int |
| 256 | nf_nat_adjust(unsigned int hooknum, | 256 | nf_nat_adjust(unsigned int hooknum, |
| 257 | struct sk_buff **pskb, | 257 | struct sk_buff *skb, |
| 258 | const struct net_device *in, | 258 | const struct net_device *in, |
| 259 | const struct net_device *out, | 259 | const struct net_device *out, |
| 260 | int (*okfn)(struct sk_buff *)) | 260 | int (*okfn)(struct sk_buff *)) |
| @@ -262,10 +262,10 @@ nf_nat_adjust(unsigned int hooknum, | |||
| 262 | struct nf_conn *ct; | 262 | struct nf_conn *ct; |
| 263 | enum ip_conntrack_info ctinfo; | 263 | enum ip_conntrack_info ctinfo; |
| 264 | 264 | ||
| 265 | ct = nf_ct_get(*pskb, &ctinfo); | 265 | ct = nf_ct_get(skb, &ctinfo); |
| 266 | if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) { | 266 | if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) { |
| 267 | pr_debug("nf_nat_standalone: adjusting sequence number\n"); | 267 | pr_debug("nf_nat_standalone: adjusting sequence number\n"); |
| 268 | if (!nf_nat_seq_adjust(pskb, ct, ctinfo)) | 268 | if (!nf_nat_seq_adjust(skb, ct, ctinfo)) |
| 269 | return NF_DROP; | 269 | return NF_DROP; |
| 270 | } | 270 | } |
| 271 | return NF_ACCEPT; | 271 | return NF_ACCEPT; |
diff --git a/net/ipv4/netfilter/nf_nat_tftp.c b/net/ipv4/netfilter/nf_nat_tftp.c index 04dfeaefec02..0ecec701cb44 100644 --- a/net/ipv4/netfilter/nf_nat_tftp.c +++ b/net/ipv4/netfilter/nf_nat_tftp.c | |||
| @@ -20,7 +20,7 @@ MODULE_DESCRIPTION("TFTP NAT helper"); | |||
| 20 | MODULE_LICENSE("GPL"); | 20 | MODULE_LICENSE("GPL"); |
| 21 | MODULE_ALIAS("ip_nat_tftp"); | 21 | MODULE_ALIAS("ip_nat_tftp"); |
| 22 | 22 | ||
| 23 | static unsigned int help(struct sk_buff **pskb, | 23 | static unsigned int help(struct sk_buff *skb, |
| 24 | enum ip_conntrack_info ctinfo, | 24 | enum ip_conntrack_info ctinfo, |
| 25 | struct nf_conntrack_expect *exp) | 25 | struct nf_conntrack_expect *exp) |
| 26 | { | 26 | { |
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index e5b05b039101..fd16cb8f8abe 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c | |||
| @@ -70,8 +70,8 @@ static int sockstat_seq_show(struct seq_file *seq, void *v) | |||
| 70 | seq_printf(seq, "UDP: inuse %d\n", fold_prot_inuse(&udp_prot)); | 70 | seq_printf(seq, "UDP: inuse %d\n", fold_prot_inuse(&udp_prot)); |
| 71 | seq_printf(seq, "UDPLITE: inuse %d\n", fold_prot_inuse(&udplite_prot)); | 71 | seq_printf(seq, "UDPLITE: inuse %d\n", fold_prot_inuse(&udplite_prot)); |
| 72 | seq_printf(seq, "RAW: inuse %d\n", fold_prot_inuse(&raw_prot)); | 72 | seq_printf(seq, "RAW: inuse %d\n", fold_prot_inuse(&raw_prot)); |
| 73 | seq_printf(seq, "FRAG: inuse %d memory %d\n", ip_frag_nqueues, | 73 | seq_printf(seq, "FRAG: inuse %d memory %d\n", |
| 74 | atomic_read(&ip_frag_mem)); | 74 | ip_frag_nqueues(), ip_frag_mem()); |
| 75 | return 0; | 75 | return 0; |
| 76 | } | 76 | } |
| 77 | 77 | ||
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index eb286abcf5dc..c98ef16effd2 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <net/route.h> | 19 | #include <net/route.h> |
| 20 | #include <net/tcp.h> | 20 | #include <net/tcp.h> |
| 21 | #include <net/cipso_ipv4.h> | 21 | #include <net/cipso_ipv4.h> |
| 22 | #include <net/inet_frag.h> | ||
| 22 | 23 | ||
| 23 | /* From af_inet.c */ | 24 | /* From af_inet.c */ |
| 24 | extern int sysctl_ip_nonlocal_bind; | 25 | extern int sysctl_ip_nonlocal_bind; |
| @@ -357,7 +358,7 @@ ctl_table ipv4_table[] = { | |||
| 357 | { | 358 | { |
| 358 | .ctl_name = NET_IPV4_IPFRAG_HIGH_THRESH, | 359 | .ctl_name = NET_IPV4_IPFRAG_HIGH_THRESH, |
| 359 | .procname = "ipfrag_high_thresh", | 360 | .procname = "ipfrag_high_thresh", |
| 360 | .data = &sysctl_ipfrag_high_thresh, | 361 | .data = &ip4_frags_ctl.high_thresh, |
| 361 | .maxlen = sizeof(int), | 362 | .maxlen = sizeof(int), |
| 362 | .mode = 0644, | 363 | .mode = 0644, |
| 363 | .proc_handler = &proc_dointvec | 364 | .proc_handler = &proc_dointvec |
| @@ -365,7 +366,7 @@ ctl_table ipv4_table[] = { | |||
| 365 | { | 366 | { |
| 366 | .ctl_name = NET_IPV4_IPFRAG_LOW_THRESH, | 367 | .ctl_name = NET_IPV4_IPFRAG_LOW_THRESH, |
| 367 | .procname = "ipfrag_low_thresh", | 368 | .procname = "ipfrag_low_thresh", |
| 368 | .data = &sysctl_ipfrag_low_thresh, | 369 | .data = &ip4_frags_ctl.low_thresh, |
| 369 | .maxlen = sizeof(int), | 370 | .maxlen = sizeof(int), |
| 370 | .mode = 0644, | 371 | .mode = 0644, |
| 371 | .proc_handler = &proc_dointvec | 372 | .proc_handler = &proc_dointvec |
| @@ -381,7 +382,7 @@ ctl_table ipv4_table[] = { | |||
| 381 | { | 382 | { |
| 382 | .ctl_name = NET_IPV4_IPFRAG_TIME, | 383 | .ctl_name = NET_IPV4_IPFRAG_TIME, |
| 383 | .procname = "ipfrag_time", | 384 | .procname = "ipfrag_time", |
| 384 | .data = &sysctl_ipfrag_time, | 385 | .data = &ip4_frags_ctl.timeout, |
| 385 | .maxlen = sizeof(int), | 386 | .maxlen = sizeof(int), |
| 386 | .mode = 0644, | 387 | .mode = 0644, |
| 387 | .proc_handler = &proc_dointvec_jiffies, | 388 | .proc_handler = &proc_dointvec_jiffies, |
| @@ -732,7 +733,7 @@ ctl_table ipv4_table[] = { | |||
| 732 | { | 733 | { |
| 733 | .ctl_name = NET_IPV4_IPFRAG_SECRET_INTERVAL, | 734 | .ctl_name = NET_IPV4_IPFRAG_SECRET_INTERVAL, |
| 734 | .procname = "ipfrag_secret_interval", | 735 | .procname = "ipfrag_secret_interval", |
| 735 | .data = &sysctl_ipfrag_secret_interval, | 736 | .data = &ip4_frags_ctl.secret_interval, |
| 736 | .maxlen = sizeof(int), | 737 | .maxlen = sizeof(int), |
| 737 | .mode = 0644, | 738 | .mode = 0644, |
| 738 | .proc_handler = &proc_dointvec_jiffies, | 739 | .proc_handler = &proc_dointvec_jiffies, |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 0a42e9340346..0f00966b1784 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
| @@ -1995,8 +1995,7 @@ static void tcp_verify_retransmit_hint(struct tcp_sock *tp, | |||
| 1995 | } | 1995 | } |
| 1996 | 1996 | ||
| 1997 | /* Mark head of queue up as lost. */ | 1997 | /* Mark head of queue up as lost. */ |
| 1998 | static void tcp_mark_head_lost(struct sock *sk, | 1998 | static void tcp_mark_head_lost(struct sock *sk, int packets) |
| 1999 | int packets, u32 high_seq) | ||
| 2000 | { | 1999 | { |
| 2001 | struct tcp_sock *tp = tcp_sk(sk); | 2000 | struct tcp_sock *tp = tcp_sk(sk); |
| 2002 | struct sk_buff *skb; | 2001 | struct sk_buff *skb; |
| @@ -2019,7 +2018,7 @@ static void tcp_mark_head_lost(struct sock *sk, | |||
| 2019 | tp->lost_skb_hint = skb; | 2018 | tp->lost_skb_hint = skb; |
| 2020 | tp->lost_cnt_hint = cnt; | 2019 | tp->lost_cnt_hint = cnt; |
| 2021 | cnt += tcp_skb_pcount(skb); | 2020 | cnt += tcp_skb_pcount(skb); |
| 2022 | if (cnt > packets || after(TCP_SKB_CB(skb)->end_seq, high_seq)) | 2021 | if (cnt > packets || after(TCP_SKB_CB(skb)->end_seq, tp->high_seq)) |
| 2023 | break; | 2022 | break; |
| 2024 | if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_SACKED_ACKED|TCPCB_LOST))) { | 2023 | if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_SACKED_ACKED|TCPCB_LOST))) { |
| 2025 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; | 2024 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; |
| @@ -2040,9 +2039,9 @@ static void tcp_update_scoreboard(struct sock *sk) | |||
| 2040 | int lost = tp->fackets_out - tp->reordering; | 2039 | int lost = tp->fackets_out - tp->reordering; |
| 2041 | if (lost <= 0) | 2040 | if (lost <= 0) |
| 2042 | lost = 1; | 2041 | lost = 1; |
| 2043 | tcp_mark_head_lost(sk, lost, tp->high_seq); | 2042 | tcp_mark_head_lost(sk, lost); |
| 2044 | } else { | 2043 | } else { |
| 2045 | tcp_mark_head_lost(sk, 1, tp->high_seq); | 2044 | tcp_mark_head_lost(sk, 1); |
| 2046 | } | 2045 | } |
| 2047 | 2046 | ||
| 2048 | /* New heuristics: it is possible only after we switched | 2047 | /* New heuristics: it is possible only after we switched |
| @@ -2381,7 +2380,7 @@ tcp_fastretrans_alert(struct sock *sk, int pkts_acked, int flag) | |||
| 2381 | before(tp->snd_una, tp->high_seq) && | 2380 | before(tp->snd_una, tp->high_seq) && |
| 2382 | icsk->icsk_ca_state != TCP_CA_Open && | 2381 | icsk->icsk_ca_state != TCP_CA_Open && |
| 2383 | tp->fackets_out > tp->reordering) { | 2382 | tp->fackets_out > tp->reordering) { |
| 2384 | tcp_mark_head_lost(sk, tp->fackets_out-tp->reordering, tp->high_seq); | 2383 | tcp_mark_head_lost(sk, tp->fackets_out - tp->reordering); |
| 2385 | NET_INC_STATS_BH(LINUX_MIB_TCPLOSS); | 2384 | NET_INC_STATS_BH(LINUX_MIB_TCPLOSS); |
| 2386 | } | 2385 | } |
| 2387 | 2386 | ||
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index 434ef302ba83..a4edd666318b 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c | |||
| @@ -78,7 +78,7 @@ static int xfrm4_output_finish2(struct sk_buff *skb) | |||
| 78 | while (likely((err = xfrm4_output_one(skb)) == 0)) { | 78 | while (likely((err = xfrm4_output_one(skb)) == 0)) { |
| 79 | nf_reset(skb); | 79 | nf_reset(skb); |
| 80 | 80 | ||
| 81 | err = nf_hook(PF_INET, NF_IP_LOCAL_OUT, &skb, NULL, | 81 | err = nf_hook(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, |
| 82 | skb->dst->dev, dst_output); | 82 | skb->dst->dev, dst_output); |
| 83 | if (unlikely(err != 1)) | 83 | if (unlikely(err != 1)) |
| 84 | break; | 84 | break; |
| @@ -86,7 +86,7 @@ static int xfrm4_output_finish2(struct sk_buff *skb) | |||
| 86 | if (!skb->dst->xfrm) | 86 | if (!skb->dst->xfrm) |
| 87 | return dst_output(skb); | 87 | return dst_output(skb); |
| 88 | 88 | ||
| 89 | err = nf_hook(PF_INET, NF_IP_POST_ROUTING, &skb, NULL, | 89 | err = nf_hook(PF_INET, NF_IP_POST_ROUTING, skb, NULL, |
| 90 | skb->dst->dev, xfrm4_output_finish2); | 90 | skb->dst->dev, xfrm4_output_finish2); |
| 91 | if (unlikely(err != 1)) | 91 | if (unlikely(err != 1)) |
| 92 | break; | 92 | break; |
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index c82d4d49f71f..1e89efd38a0c 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c | |||
| @@ -102,7 +102,7 @@ EXPORT_SYMBOL_GPL(ipv6_find_tlv); | |||
| 102 | 102 | ||
| 103 | struct tlvtype_proc { | 103 | struct tlvtype_proc { |
| 104 | int type; | 104 | int type; |
| 105 | int (*func)(struct sk_buff **skbp, int offset); | 105 | int (*func)(struct sk_buff *skb, int offset); |
| 106 | }; | 106 | }; |
| 107 | 107 | ||
| 108 | /********************* | 108 | /********************* |
| @@ -111,10 +111,8 @@ struct tlvtype_proc { | |||
| 111 | 111 | ||
| 112 | /* An unknown option is detected, decide what to do */ | 112 | /* An unknown option is detected, decide what to do */ |
| 113 | 113 | ||
| 114 | static int ip6_tlvopt_unknown(struct sk_buff **skbp, int optoff) | 114 | static int ip6_tlvopt_unknown(struct sk_buff *skb, int optoff) |
| 115 | { | 115 | { |
| 116 | struct sk_buff *skb = *skbp; | ||
| 117 | |||
| 118 | switch ((skb_network_header(skb)[optoff] & 0xC0) >> 6) { | 116 | switch ((skb_network_header(skb)[optoff] & 0xC0) >> 6) { |
| 119 | case 0: /* ignore */ | 117 | case 0: /* ignore */ |
| 120 | return 1; | 118 | return 1; |
| @@ -139,9 +137,8 @@ static int ip6_tlvopt_unknown(struct sk_buff **skbp, int optoff) | |||
| 139 | 137 | ||
| 140 | /* Parse tlv encoded option header (hop-by-hop or destination) */ | 138 | /* Parse tlv encoded option header (hop-by-hop or destination) */ |
| 141 | 139 | ||
| 142 | static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp) | 140 | static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff *skb) |
| 143 | { | 141 | { |
| 144 | struct sk_buff *skb = *skbp; | ||
| 145 | struct tlvtype_proc *curr; | 142 | struct tlvtype_proc *curr; |
| 146 | const unsigned char *nh = skb_network_header(skb); | 143 | const unsigned char *nh = skb_network_header(skb); |
| 147 | int off = skb_network_header_len(skb); | 144 | int off = skb_network_header_len(skb); |
| @@ -172,13 +169,13 @@ static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp) | |||
| 172 | /* type specific length/alignment | 169 | /* type specific length/alignment |
| 173 | checks will be performed in the | 170 | checks will be performed in the |
| 174 | func(). */ | 171 | func(). */ |
| 175 | if (curr->func(skbp, off) == 0) | 172 | if (curr->func(skb, off) == 0) |
| 176 | return 0; | 173 | return 0; |
| 177 | break; | 174 | break; |
| 178 | } | 175 | } |
| 179 | } | 176 | } |
| 180 | if (curr->type < 0) { | 177 | if (curr->type < 0) { |
| 181 | if (ip6_tlvopt_unknown(skbp, off) == 0) | 178 | if (ip6_tlvopt_unknown(skb, off) == 0) |
| 182 | return 0; | 179 | return 0; |
| 183 | } | 180 | } |
| 184 | break; | 181 | break; |
| @@ -198,9 +195,8 @@ bad: | |||
| 198 | *****************************/ | 195 | *****************************/ |
| 199 | 196 | ||
| 200 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | 197 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
| 201 | static int ipv6_dest_hao(struct sk_buff **skbp, int optoff) | 198 | static int ipv6_dest_hao(struct sk_buff *skb, int optoff) |
| 202 | { | 199 | { |
| 203 | struct sk_buff *skb = *skbp; | ||
| 204 | struct ipv6_destopt_hao *hao; | 200 | struct ipv6_destopt_hao *hao; |
| 205 | struct inet6_skb_parm *opt = IP6CB(skb); | 201 | struct inet6_skb_parm *opt = IP6CB(skb); |
| 206 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); | 202 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); |
| @@ -234,22 +230,13 @@ static int ipv6_dest_hao(struct sk_buff **skbp, int optoff) | |||
| 234 | goto discard; | 230 | goto discard; |
| 235 | 231 | ||
| 236 | if (skb_cloned(skb)) { | 232 | if (skb_cloned(skb)) { |
| 237 | struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC); | 233 | if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) |
| 238 | struct inet6_skb_parm *opt2; | ||
| 239 | |||
| 240 | if (skb2 == NULL) | ||
| 241 | goto discard; | 234 | goto discard; |
| 242 | 235 | ||
| 243 | opt2 = IP6CB(skb2); | ||
| 244 | memcpy(opt2, opt, sizeof(*opt2)); | ||
| 245 | |||
| 246 | kfree_skb(skb); | ||
| 247 | |||
| 248 | /* update all variable using below by copied skbuff */ | 236 | /* update all variable using below by copied skbuff */ |
| 249 | *skbp = skb = skb2; | 237 | hao = (struct ipv6_destopt_hao *)(skb_network_header(skb) + |
| 250 | hao = (struct ipv6_destopt_hao *)(skb_network_header(skb2) + | ||
| 251 | optoff); | 238 | optoff); |
| 252 | ipv6h = ipv6_hdr(skb2); | 239 | ipv6h = ipv6_hdr(skb); |
| 253 | } | 240 | } |
| 254 | 241 | ||
| 255 | if (skb->ip_summed == CHECKSUM_COMPLETE) | 242 | if (skb->ip_summed == CHECKSUM_COMPLETE) |
| @@ -280,9 +267,8 @@ static struct tlvtype_proc tlvprocdestopt_lst[] = { | |||
| 280 | {-1, NULL} | 267 | {-1, NULL} |
| 281 | }; | 268 | }; |
| 282 | 269 | ||
| 283 | static int ipv6_destopt_rcv(struct sk_buff **skbp) | 270 | static int ipv6_destopt_rcv(struct sk_buff *skb) |
| 284 | { | 271 | { |
| 285 | struct sk_buff *skb = *skbp; | ||
| 286 | struct inet6_skb_parm *opt = IP6CB(skb); | 272 | struct inet6_skb_parm *opt = IP6CB(skb); |
| 287 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | 273 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
| 288 | __u16 dstbuf; | 274 | __u16 dstbuf; |
| @@ -304,9 +290,8 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) | |||
| 304 | #endif | 290 | #endif |
| 305 | 291 | ||
| 306 | dst = dst_clone(skb->dst); | 292 | dst = dst_clone(skb->dst); |
| 307 | if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) { | 293 | if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) { |
| 308 | dst_release(dst); | 294 | dst_release(dst); |
| 309 | skb = *skbp; | ||
| 310 | skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3; | 295 | skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3; |
| 311 | opt = IP6CB(skb); | 296 | opt = IP6CB(skb); |
| 312 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | 297 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
| @@ -337,10 +322,8 @@ void __init ipv6_destopt_init(void) | |||
| 337 | NONE header. No data in packet. | 322 | NONE header. No data in packet. |
| 338 | ********************************/ | 323 | ********************************/ |
| 339 | 324 | ||
| 340 | static int ipv6_nodata_rcv(struct sk_buff **skbp) | 325 | static int ipv6_nodata_rcv(struct sk_buff *skb) |
| 341 | { | 326 | { |
| 342 | struct sk_buff *skb = *skbp; | ||
| 343 | |||
| 344 | kfree_skb(skb); | 327 | kfree_skb(skb); |
| 345 | return 0; | 328 | return 0; |
| 346 | } | 329 | } |
| @@ -360,9 +343,8 @@ void __init ipv6_nodata_init(void) | |||
| 360 | Routing header. | 343 | Routing header. |
| 361 | ********************************/ | 344 | ********************************/ |
| 362 | 345 | ||
| 363 | static int ipv6_rthdr_rcv(struct sk_buff **skbp) | 346 | static int ipv6_rthdr_rcv(struct sk_buff *skb) |
| 364 | { | 347 | { |
| 365 | struct sk_buff *skb = *skbp; | ||
| 366 | struct inet6_skb_parm *opt = IP6CB(skb); | 348 | struct inet6_skb_parm *opt = IP6CB(skb); |
| 367 | struct in6_addr *addr = NULL; | 349 | struct in6_addr *addr = NULL; |
| 368 | struct in6_addr daddr; | 350 | struct in6_addr daddr; |
| @@ -464,18 +446,14 @@ looped_back: | |||
| 464 | Do not damage packets queued somewhere. | 446 | Do not damage packets queued somewhere. |
| 465 | */ | 447 | */ |
| 466 | if (skb_cloned(skb)) { | 448 | if (skb_cloned(skb)) { |
| 467 | struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC); | ||
| 468 | /* the copy is a forwarded packet */ | 449 | /* the copy is a forwarded packet */ |
| 469 | if (skb2 == NULL) { | 450 | if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { |
| 470 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | 451 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
| 471 | IPSTATS_MIB_OUTDISCARDS); | 452 | IPSTATS_MIB_OUTDISCARDS); |
| 472 | kfree_skb(skb); | 453 | kfree_skb(skb); |
| 473 | return -1; | 454 | return -1; |
| 474 | } | 455 | } |
| 475 | kfree_skb(skb); | 456 | hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb); |
| 476 | *skbp = skb = skb2; | ||
| 477 | opt = IP6CB(skb2); | ||
| 478 | hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb2); | ||
| 479 | } | 457 | } |
| 480 | 458 | ||
| 481 | if (skb->ip_summed == CHECKSUM_COMPLETE) | 459 | if (skb->ip_summed == CHECKSUM_COMPLETE) |
| @@ -578,9 +556,8 @@ static inline struct inet6_dev *ipv6_skb_idev(struct sk_buff *skb) | |||
| 578 | 556 | ||
| 579 | /* Router Alert as of RFC 2711 */ | 557 | /* Router Alert as of RFC 2711 */ |
| 580 | 558 | ||
| 581 | static int ipv6_hop_ra(struct sk_buff **skbp, int optoff) | 559 | static int ipv6_hop_ra(struct sk_buff *skb, int optoff) |
| 582 | { | 560 | { |
| 583 | struct sk_buff *skb = *skbp; | ||
| 584 | const unsigned char *nh = skb_network_header(skb); | 561 | const unsigned char *nh = skb_network_header(skb); |
| 585 | 562 | ||
| 586 | if (nh[optoff + 1] == 2) { | 563 | if (nh[optoff + 1] == 2) { |
| @@ -595,9 +572,8 @@ static int ipv6_hop_ra(struct sk_buff **skbp, int optoff) | |||
| 595 | 572 | ||
| 596 | /* Jumbo payload */ | 573 | /* Jumbo payload */ |
| 597 | 574 | ||
| 598 | static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff) | 575 | static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff) |
| 599 | { | 576 | { |
| 600 | struct sk_buff *skb = *skbp; | ||
| 601 | const unsigned char *nh = skb_network_header(skb); | 577 | const unsigned char *nh = skb_network_header(skb); |
| 602 | u32 pkt_len; | 578 | u32 pkt_len; |
| 603 | 579 | ||
| @@ -648,9 +624,8 @@ static struct tlvtype_proc tlvprochopopt_lst[] = { | |||
| 648 | { -1, } | 624 | { -1, } |
| 649 | }; | 625 | }; |
| 650 | 626 | ||
| 651 | int ipv6_parse_hopopts(struct sk_buff **skbp) | 627 | int ipv6_parse_hopopts(struct sk_buff *skb) |
| 652 | { | 628 | { |
| 653 | struct sk_buff *skb = *skbp; | ||
| 654 | struct inet6_skb_parm *opt = IP6CB(skb); | 629 | struct inet6_skb_parm *opt = IP6CB(skb); |
| 655 | 630 | ||
| 656 | /* | 631 | /* |
| @@ -667,8 +642,7 @@ int ipv6_parse_hopopts(struct sk_buff **skbp) | |||
| 667 | } | 642 | } |
| 668 | 643 | ||
| 669 | opt->hop = sizeof(struct ipv6hdr); | 644 | opt->hop = sizeof(struct ipv6hdr); |
| 670 | if (ip6_parse_tlv(tlvprochopopt_lst, skbp)) { | 645 | if (ip6_parse_tlv(tlvprochopopt_lst, skb)) { |
| 671 | skb = *skbp; | ||
| 672 | skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3; | 646 | skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3; |
| 673 | opt = IP6CB(skb); | 647 | opt = IP6CB(skb); |
| 674 | opt->nhoff = sizeof(struct ipv6hdr); | 648 | opt->nhoff = sizeof(struct ipv6hdr); |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 47b8ce232e84..9bb031fa1c2f 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
| @@ -82,7 +82,7 @@ EXPORT_SYMBOL(icmpv6msg_statistics); | |||
| 82 | static DEFINE_PER_CPU(struct socket *, __icmpv6_socket) = NULL; | 82 | static DEFINE_PER_CPU(struct socket *, __icmpv6_socket) = NULL; |
| 83 | #define icmpv6_socket __get_cpu_var(__icmpv6_socket) | 83 | #define icmpv6_socket __get_cpu_var(__icmpv6_socket) |
| 84 | 84 | ||
| 85 | static int icmpv6_rcv(struct sk_buff **pskb); | 85 | static int icmpv6_rcv(struct sk_buff *skb); |
| 86 | 86 | ||
| 87 | static struct inet6_protocol icmpv6_protocol = { | 87 | static struct inet6_protocol icmpv6_protocol = { |
| 88 | .handler = icmpv6_rcv, | 88 | .handler = icmpv6_rcv, |
| @@ -614,9 +614,8 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info) | |||
| 614 | * Handle icmp messages | 614 | * Handle icmp messages |
| 615 | */ | 615 | */ |
| 616 | 616 | ||
| 617 | static int icmpv6_rcv(struct sk_buff **pskb) | 617 | static int icmpv6_rcv(struct sk_buff *skb) |
| 618 | { | 618 | { |
| 619 | struct sk_buff *skb = *pskb; | ||
| 620 | struct net_device *dev = skb->dev; | 619 | struct net_device *dev = skb->dev; |
| 621 | struct inet6_dev *idev = __in6_dev_get(dev); | 620 | struct inet6_dev *idev = __in6_dev_get(dev); |
| 622 | struct in6_addr *saddr, *daddr; | 621 | struct in6_addr *saddr, *daddr; |
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 25b931709749..78de42ada844 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c | |||
| @@ -146,7 +146,7 @@ void __inet6_csk_dst_store(struct sock *sk, struct dst_entry *dst, | |||
| 146 | __ip6_dst_store(sk, dst, daddr, saddr); | 146 | __ip6_dst_store(sk, dst, daddr, saddr); |
| 147 | 147 | ||
| 148 | #ifdef CONFIG_XFRM | 148 | #ifdef CONFIG_XFRM |
| 149 | if (dst) { | 149 | { |
| 150 | struct rt6_info *rt = (struct rt6_info *)dst; | 150 | struct rt6_info *rt = (struct rt6_info *)dst; |
| 151 | rt->rt6i_flow_cache_genid = atomic_read(&flow_cache_genid); | 151 | rt->rt6i_flow_cache_genid = atomic_read(&flow_cache_genid); |
| 152 | } | 152 | } |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 9149fc239759..fac6f7f9dd73 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
| @@ -125,7 +125,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | if (hdr->nexthdr == NEXTHDR_HOP) { | 127 | if (hdr->nexthdr == NEXTHDR_HOP) { |
| 128 | if (ipv6_parse_hopopts(&skb) < 0) { | 128 | if (ipv6_parse_hopopts(skb) < 0) { |
| 129 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS); | 129 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS); |
| 130 | rcu_read_unlock(); | 130 | rcu_read_unlock(); |
| 131 | return 0; | 131 | return 0; |
| @@ -149,7 +149,7 @@ out: | |||
| 149 | */ | 149 | */ |
| 150 | 150 | ||
| 151 | 151 | ||
| 152 | static inline int ip6_input_finish(struct sk_buff *skb) | 152 | static int ip6_input_finish(struct sk_buff *skb) |
| 153 | { | 153 | { |
| 154 | struct inet6_protocol *ipprot; | 154 | struct inet6_protocol *ipprot; |
| 155 | struct sock *raw_sk; | 155 | struct sock *raw_sk; |
| @@ -199,7 +199,7 @@ resubmit: | |||
| 199 | !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) | 199 | !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) |
| 200 | goto discard; | 200 | goto discard; |
| 201 | 201 | ||
| 202 | ret = ipprot->handler(&skb); | 202 | ret = ipprot->handler(skb); |
| 203 | if (ret > 0) | 203 | if (ret > 0) |
| 204 | goto resubmit; | 204 | goto resubmit; |
| 205 | else if (ret == 0) | 205 | else if (ret == 0) |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 011082ed921a..13565dfb1b45 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
| @@ -70,7 +70,7 @@ static __inline__ void ipv6_select_ident(struct sk_buff *skb, struct frag_hdr *f | |||
| 70 | spin_unlock_bh(&ip6_id_lock); | 70 | spin_unlock_bh(&ip6_id_lock); |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | static inline int ip6_output_finish(struct sk_buff *skb) | 73 | static int ip6_output_finish(struct sk_buff *skb) |
| 74 | { | 74 | { |
| 75 | struct dst_entry *dst = skb->dst; | 75 | struct dst_entry *dst = skb->dst; |
| 76 | 76 | ||
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 38b149613915..b1326c2bf8aa 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c | |||
| @@ -68,15 +68,15 @@ static void nf_ip6_saveroute(const struct sk_buff *skb, struct nf_info *info) | |||
| 68 | } | 68 | } |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | static int nf_ip6_reroute(struct sk_buff **pskb, const struct nf_info *info) | 71 | static int nf_ip6_reroute(struct sk_buff *skb, const struct nf_info *info) |
| 72 | { | 72 | { |
| 73 | struct ip6_rt_info *rt_info = nf_info_reroute(info); | 73 | struct ip6_rt_info *rt_info = nf_info_reroute(info); |
| 74 | 74 | ||
| 75 | if (info->hook == NF_IP6_LOCAL_OUT) { | 75 | if (info->hook == NF_IP6_LOCAL_OUT) { |
| 76 | struct ipv6hdr *iph = ipv6_hdr(*pskb); | 76 | struct ipv6hdr *iph = ipv6_hdr(skb); |
| 77 | if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) || | 77 | if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) || |
| 78 | !ipv6_addr_equal(&iph->saddr, &rt_info->saddr)) | 78 | !ipv6_addr_equal(&iph->saddr, &rt_info->saddr)) |
| 79 | return ip6_route_me_harder(*pskb); | 79 | return ip6_route_me_harder(skb); |
| 80 | } | 80 | } |
| 81 | return 0; | 81 | return 0; |
| 82 | } | 82 | } |
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 0473145ac534..6413a30d9f68 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c | |||
| @@ -332,6 +332,7 @@ static int | |||
| 332 | ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) | 332 | ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) |
| 333 | { | 333 | { |
| 334 | int diff; | 334 | int diff; |
| 335 | int err; | ||
| 335 | struct ipv6hdr *user_iph = (struct ipv6hdr *)v->payload; | 336 | struct ipv6hdr *user_iph = (struct ipv6hdr *)v->payload; |
| 336 | 337 | ||
| 337 | if (v->data_len < sizeof(*user_iph)) | 338 | if (v->data_len < sizeof(*user_iph)) |
| @@ -344,25 +345,18 @@ ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) | |||
| 344 | if (v->data_len > 0xFFFF) | 345 | if (v->data_len > 0xFFFF) |
| 345 | return -EINVAL; | 346 | return -EINVAL; |
| 346 | if (diff > skb_tailroom(e->skb)) { | 347 | if (diff > skb_tailroom(e->skb)) { |
| 347 | struct sk_buff *newskb; | 348 | err = pskb_expand_head(e->skb, 0, |
| 348 | 349 | diff - skb_tailroom(e->skb), | |
| 349 | newskb = skb_copy_expand(e->skb, | 350 | GFP_ATOMIC); |
| 350 | skb_headroom(e->skb), | 351 | if (err) { |
| 351 | diff, | ||
| 352 | GFP_ATOMIC); | ||
| 353 | if (newskb == NULL) { | ||
| 354 | printk(KERN_WARNING "ip6_queue: OOM " | 352 | printk(KERN_WARNING "ip6_queue: OOM " |
| 355 | "in mangle, dropping packet\n"); | 353 | "in mangle, dropping packet\n"); |
| 356 | return -ENOMEM; | 354 | return err; |
| 357 | } | 355 | } |
| 358 | if (e->skb->sk) | ||
| 359 | skb_set_owner_w(newskb, e->skb->sk); | ||
| 360 | kfree_skb(e->skb); | ||
| 361 | e->skb = newskb; | ||
| 362 | } | 356 | } |
| 363 | skb_put(e->skb, diff); | 357 | skb_put(e->skb, diff); |
| 364 | } | 358 | } |
| 365 | if (!skb_make_writable(&e->skb, v->data_len)) | 359 | if (!skb_make_writable(e->skb, v->data_len)) |
| 366 | return -ENOMEM; | 360 | return -ENOMEM; |
| 367 | skb_copy_to_linear_data(e->skb, v->payload, v->data_len); | 361 | skb_copy_to_linear_data(e->skb, v->payload, v->data_len); |
| 368 | e->skb->ip_summed = CHECKSUM_NONE; | 362 | e->skb->ip_summed = CHECKSUM_NONE; |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index cd9df02bb85c..acaba1537931 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
| @@ -205,7 +205,7 @@ ip6_checkentry(const struct ip6t_ip6 *ipv6) | |||
| 205 | } | 205 | } |
| 206 | 206 | ||
| 207 | static unsigned int | 207 | static unsigned int |
| 208 | ip6t_error(struct sk_buff **pskb, | 208 | ip6t_error(struct sk_buff *skb, |
| 209 | const struct net_device *in, | 209 | const struct net_device *in, |
| 210 | const struct net_device *out, | 210 | const struct net_device *out, |
| 211 | unsigned int hooknum, | 211 | unsigned int hooknum, |
| @@ -350,7 +350,7 @@ static void trace_packet(struct sk_buff *skb, | |||
| 350 | 350 | ||
| 351 | /* Returns one of the generic firewall policies, like NF_ACCEPT. */ | 351 | /* Returns one of the generic firewall policies, like NF_ACCEPT. */ |
| 352 | unsigned int | 352 | unsigned int |
| 353 | ip6t_do_table(struct sk_buff **pskb, | 353 | ip6t_do_table(struct sk_buff *skb, |
| 354 | unsigned int hook, | 354 | unsigned int hook, |
| 355 | const struct net_device *in, | 355 | const struct net_device *in, |
| 356 | const struct net_device *out, | 356 | const struct net_device *out, |
| @@ -389,17 +389,17 @@ ip6t_do_table(struct sk_buff **pskb, | |||
| 389 | do { | 389 | do { |
| 390 | IP_NF_ASSERT(e); | 390 | IP_NF_ASSERT(e); |
| 391 | IP_NF_ASSERT(back); | 391 | IP_NF_ASSERT(back); |
| 392 | if (ip6_packet_match(*pskb, indev, outdev, &e->ipv6, | 392 | if (ip6_packet_match(skb, indev, outdev, &e->ipv6, |
| 393 | &protoff, &offset, &hotdrop)) { | 393 | &protoff, &offset, &hotdrop)) { |
| 394 | struct ip6t_entry_target *t; | 394 | struct ip6t_entry_target *t; |
| 395 | 395 | ||
| 396 | if (IP6T_MATCH_ITERATE(e, do_match, | 396 | if (IP6T_MATCH_ITERATE(e, do_match, |
| 397 | *pskb, in, out, | 397 | skb, in, out, |
| 398 | offset, protoff, &hotdrop) != 0) | 398 | offset, protoff, &hotdrop) != 0) |
| 399 | goto no_match; | 399 | goto no_match; |
| 400 | 400 | ||
| 401 | ADD_COUNTER(e->counters, | 401 | ADD_COUNTER(e->counters, |
| 402 | ntohs(ipv6_hdr(*pskb)->payload_len) | 402 | ntohs(ipv6_hdr(skb)->payload_len) |
| 403 | + IPV6_HDR_LEN, | 403 | + IPV6_HDR_LEN, |
| 404 | 1); | 404 | 1); |
| 405 | 405 | ||
| @@ -409,8 +409,8 @@ ip6t_do_table(struct sk_buff **pskb, | |||
| 409 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | 409 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ |
| 410 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | 410 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) |
| 411 | /* The packet is traced: log it */ | 411 | /* The packet is traced: log it */ |
| 412 | if (unlikely((*pskb)->nf_trace)) | 412 | if (unlikely(skb->nf_trace)) |
| 413 | trace_packet(*pskb, hook, in, out, | 413 | trace_packet(skb, hook, in, out, |
| 414 | table->name, private, e); | 414 | table->name, private, e); |
| 415 | #endif | 415 | #endif |
| 416 | /* Standard target? */ | 416 | /* Standard target? */ |
| @@ -448,7 +448,7 @@ ip6t_do_table(struct sk_buff **pskb, | |||
| 448 | ((struct ip6t_entry *)table_base)->comefrom | 448 | ((struct ip6t_entry *)table_base)->comefrom |
| 449 | = 0xeeeeeeec; | 449 | = 0xeeeeeeec; |
| 450 | #endif | 450 | #endif |
| 451 | verdict = t->u.kernel.target->target(pskb, | 451 | verdict = t->u.kernel.target->target(skb, |
| 452 | in, out, | 452 | in, out, |
| 453 | hook, | 453 | hook, |
| 454 | t->u.kernel.target, | 454 | t->u.kernel.target, |
diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c index ad4d94310b87..9afc836fd454 100644 --- a/net/ipv6/netfilter/ip6t_HL.c +++ b/net/ipv6/netfilter/ip6t_HL.c | |||
| @@ -18,7 +18,7 @@ MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>"); | |||
| 18 | MODULE_DESCRIPTION("IP6 tables Hop Limit modification module"); | 18 | MODULE_DESCRIPTION("IP6 tables Hop Limit modification module"); |
| 19 | MODULE_LICENSE("GPL"); | 19 | MODULE_LICENSE("GPL"); |
| 20 | 20 | ||
| 21 | static unsigned int ip6t_hl_target(struct sk_buff **pskb, | 21 | static unsigned int ip6t_hl_target(struct sk_buff *skb, |
| 22 | const struct net_device *in, | 22 | const struct net_device *in, |
| 23 | const struct net_device *out, | 23 | const struct net_device *out, |
| 24 | unsigned int hooknum, | 24 | unsigned int hooknum, |
| @@ -29,10 +29,10 @@ static unsigned int ip6t_hl_target(struct sk_buff **pskb, | |||
| 29 | const struct ip6t_HL_info *info = targinfo; | 29 | const struct ip6t_HL_info *info = targinfo; |
| 30 | int new_hl; | 30 | int new_hl; |
| 31 | 31 | ||
| 32 | if (!skb_make_writable(pskb, (*pskb)->len)) | 32 | if (!skb_make_writable(skb, skb->len)) |
| 33 | return NF_DROP; | 33 | return NF_DROP; |
| 34 | 34 | ||
| 35 | ip6h = ipv6_hdr(*pskb); | 35 | ip6h = ipv6_hdr(skb); |
| 36 | 36 | ||
| 37 | switch (info->mode) { | 37 | switch (info->mode) { |
| 38 | case IP6T_HL_SET: | 38 | case IP6T_HL_SET: |
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index 6ab99001dccc..7a48c342df46 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c | |||
| @@ -431,7 +431,7 @@ ip6t_log_packet(unsigned int pf, | |||
| 431 | } | 431 | } |
| 432 | 432 | ||
| 433 | static unsigned int | 433 | static unsigned int |
| 434 | ip6t_log_target(struct sk_buff **pskb, | 434 | ip6t_log_target(struct sk_buff *skb, |
| 435 | const struct net_device *in, | 435 | const struct net_device *in, |
| 436 | const struct net_device *out, | 436 | const struct net_device *out, |
| 437 | unsigned int hooknum, | 437 | unsigned int hooknum, |
| @@ -445,8 +445,7 @@ ip6t_log_target(struct sk_buff **pskb, | |||
| 445 | li.u.log.level = loginfo->level; | 445 | li.u.log.level = loginfo->level; |
| 446 | li.u.log.logflags = loginfo->logflags; | 446 | li.u.log.logflags = loginfo->logflags; |
| 447 | 447 | ||
| 448 | ip6t_log_packet(PF_INET6, hooknum, *pskb, in, out, &li, | 448 | ip6t_log_packet(PF_INET6, hooknum, skb, in, out, &li, loginfo->prefix); |
| 449 | loginfo->prefix); | ||
| 450 | return XT_CONTINUE; | 449 | return XT_CONTINUE; |
| 451 | } | 450 | } |
| 452 | 451 | ||
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index 3fd08d5567a6..1a7d2917545d 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c | |||
| @@ -172,7 +172,7 @@ send_unreach(struct sk_buff *skb_in, unsigned char code, unsigned int hooknum) | |||
| 172 | icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0, NULL); | 172 | icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0, NULL); |
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | static unsigned int reject6_target(struct sk_buff **pskb, | 175 | static unsigned int reject6_target(struct sk_buff *skb, |
| 176 | const struct net_device *in, | 176 | const struct net_device *in, |
| 177 | const struct net_device *out, | 177 | const struct net_device *out, |
| 178 | unsigned int hooknum, | 178 | unsigned int hooknum, |
| @@ -187,25 +187,25 @@ static unsigned int reject6_target(struct sk_buff **pskb, | |||
| 187 | must return an absolute verdict. --RR */ | 187 | must return an absolute verdict. --RR */ |
| 188 | switch (reject->with) { | 188 | switch (reject->with) { |
| 189 | case IP6T_ICMP6_NO_ROUTE: | 189 | case IP6T_ICMP6_NO_ROUTE: |
| 190 | send_unreach(*pskb, ICMPV6_NOROUTE, hooknum); | 190 | send_unreach(skb, ICMPV6_NOROUTE, hooknum); |
| 191 | break; | 191 | break; |
| 192 | case IP6T_ICMP6_ADM_PROHIBITED: | 192 | case IP6T_ICMP6_ADM_PROHIBITED: |
| 193 | send_unreach(*pskb, ICMPV6_ADM_PROHIBITED, hooknum); | 193 | send_unreach(skb, ICMPV6_ADM_PROHIBITED, hooknum); |
| 194 | break; | 194 | break; |
| 195 | case IP6T_ICMP6_NOT_NEIGHBOUR: | 195 | case IP6T_ICMP6_NOT_NEIGHBOUR: |
| 196 | send_unreach(*pskb, ICMPV6_NOT_NEIGHBOUR, hooknum); | 196 | send_unreach(skb, ICMPV6_NOT_NEIGHBOUR, hooknum); |
| 197 | break; | 197 | break; |
| 198 | case IP6T_ICMP6_ADDR_UNREACH: | 198 | case IP6T_ICMP6_ADDR_UNREACH: |
| 199 | send_unreach(*pskb, ICMPV6_ADDR_UNREACH, hooknum); | 199 | send_unreach(skb, ICMPV6_ADDR_UNREACH, hooknum); |
| 200 | break; | 200 | break; |
| 201 | case IP6T_ICMP6_PORT_UNREACH: | 201 | case IP6T_ICMP6_PORT_UNREACH: |
| 202 | send_unreach(*pskb, ICMPV6_PORT_UNREACH, hooknum); | 202 | send_unreach(skb, ICMPV6_PORT_UNREACH, hooknum); |
| 203 | break; | 203 | break; |
| 204 | case IP6T_ICMP6_ECHOREPLY: | 204 | case IP6T_ICMP6_ECHOREPLY: |
| 205 | /* Do nothing */ | 205 | /* Do nothing */ |
| 206 | break; | 206 | break; |
| 207 | case IP6T_TCP_RESET: | 207 | case IP6T_TCP_RESET: |
| 208 | send_reset(*pskb); | 208 | send_reset(skb); |
| 209 | break; | 209 | break; |
| 210 | default: | 210 | default: |
| 211 | if (net_ratelimit()) | 211 | if (net_ratelimit()) |
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index 7e32e2aaf7f7..1d26b202bf30 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c | |||
| @@ -60,32 +60,32 @@ static struct xt_table packet_filter = { | |||
| 60 | /* The work comes in here from netfilter.c. */ | 60 | /* The work comes in here from netfilter.c. */ |
| 61 | static unsigned int | 61 | static unsigned int |
| 62 | ip6t_hook(unsigned int hook, | 62 | ip6t_hook(unsigned int hook, |
| 63 | struct sk_buff **pskb, | 63 | struct sk_buff *skb, |
| 64 | const struct net_device *in, | 64 | const struct net_device *in, |
| 65 | const struct net_device *out, | 65 | const struct net_device *out, |
| 66 | int (*okfn)(struct sk_buff *)) | 66 | int (*okfn)(struct sk_buff *)) |
| 67 | { | 67 | { |
| 68 | return ip6t_do_table(pskb, hook, in, out, &packet_filter); | 68 | return ip6t_do_table(skb, hook, in, out, &packet_filter); |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | static unsigned int | 71 | static unsigned int |
| 72 | ip6t_local_out_hook(unsigned int hook, | 72 | ip6t_local_out_hook(unsigned int hook, |
| 73 | struct sk_buff **pskb, | 73 | struct sk_buff *skb, |
| 74 | const struct net_device *in, | 74 | const struct net_device *in, |
| 75 | const struct net_device *out, | 75 | const struct net_device *out, |
| 76 | int (*okfn)(struct sk_buff *)) | 76 | int (*okfn)(struct sk_buff *)) |
| 77 | { | 77 | { |
| 78 | #if 0 | 78 | #if 0 |
| 79 | /* root is playing with raw sockets. */ | 79 | /* root is playing with raw sockets. */ |
| 80 | if ((*pskb)->len < sizeof(struct iphdr) | 80 | if (skb->len < sizeof(struct iphdr) |
| 81 | || ip_hdrlen(*pskb) < sizeof(struct iphdr)) { | 81 | || ip_hdrlen(skb) < sizeof(struct iphdr)) { |
| 82 | if (net_ratelimit()) | 82 | if (net_ratelimit()) |
| 83 | printk("ip6t_hook: happy cracking.\n"); | 83 | printk("ip6t_hook: happy cracking.\n"); |
| 84 | return NF_ACCEPT; | 84 | return NF_ACCEPT; |
| 85 | } | 85 | } |
| 86 | #endif | 86 | #endif |
| 87 | 87 | ||
| 88 | return ip6t_do_table(pskb, hook, in, out, &packet_filter); | 88 | return ip6t_do_table(skb, hook, in, out, &packet_filter); |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | static struct nf_hook_ops ip6t_ops[] = { | 91 | static struct nf_hook_ops ip6t_ops[] = { |
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index f0a9efa67fb5..a0b6381f1e8c 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c | |||
| @@ -68,17 +68,17 @@ static struct xt_table packet_mangler = { | |||
| 68 | /* The work comes in here from netfilter.c. */ | 68 | /* The work comes in here from netfilter.c. */ |
| 69 | static unsigned int | 69 | static unsigned int |
| 70 | ip6t_route_hook(unsigned int hook, | 70 | ip6t_route_hook(unsigned int hook, |
| 71 | struct sk_buff **pskb, | 71 | struct sk_buff *skb, |
| 72 | const struct net_device *in, | 72 | const struct net_device *in, |
| 73 | const struct net_device *out, | 73 | const struct net_device *out, |
| 74 | int (*okfn)(struct sk_buff *)) | 74 | int (*okfn)(struct sk_buff *)) |
| 75 | { | 75 | { |
| 76 | return ip6t_do_table(pskb, hook, in, out, &packet_mangler); | 76 | return ip6t_do_table(skb, hook, in, out, &packet_mangler); |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | static unsigned int | 79 | static unsigned int |
| 80 | ip6t_local_hook(unsigned int hook, | 80 | ip6t_local_hook(unsigned int hook, |
| 81 | struct sk_buff **pskb, | 81 | struct sk_buff *skb, |
| 82 | const struct net_device *in, | 82 | const struct net_device *in, |
| 83 | const struct net_device *out, | 83 | const struct net_device *out, |
| 84 | int (*okfn)(struct sk_buff *)) | 84 | int (*okfn)(struct sk_buff *)) |
| @@ -91,8 +91,8 @@ ip6t_local_hook(unsigned int hook, | |||
| 91 | 91 | ||
| 92 | #if 0 | 92 | #if 0 |
| 93 | /* root is playing with raw sockets. */ | 93 | /* root is playing with raw sockets. */ |
| 94 | if ((*pskb)->len < sizeof(struct iphdr) | 94 | if (skb->len < sizeof(struct iphdr) |
| 95 | || ip_hdrlen(*pskb) < sizeof(struct iphdr)) { | 95 | || ip_hdrlen(skb) < sizeof(struct iphdr)) { |
| 96 | if (net_ratelimit()) | 96 | if (net_ratelimit()) |
| 97 | printk("ip6t_hook: happy cracking.\n"); | 97 | printk("ip6t_hook: happy cracking.\n"); |
| 98 | return NF_ACCEPT; | 98 | return NF_ACCEPT; |
| @@ -100,22 +100,22 @@ ip6t_local_hook(unsigned int hook, | |||
| 100 | #endif | 100 | #endif |
| 101 | 101 | ||
| 102 | /* save source/dest address, mark, hoplimit, flowlabel, priority, */ | 102 | /* save source/dest address, mark, hoplimit, flowlabel, priority, */ |
| 103 | memcpy(&saddr, &ipv6_hdr(*pskb)->saddr, sizeof(saddr)); | 103 | memcpy(&saddr, &ipv6_hdr(skb)->saddr, sizeof(saddr)); |
| 104 | memcpy(&daddr, &ipv6_hdr(*pskb)->daddr, sizeof(daddr)); | 104 | memcpy(&daddr, &ipv6_hdr(skb)->daddr, sizeof(daddr)); |
| 105 | mark = (*pskb)->mark; | 105 | mark = skb->mark; |
| 106 | hop_limit = ipv6_hdr(*pskb)->hop_limit; | 106 | hop_limit = ipv6_hdr(skb)->hop_limit; |
| 107 | 107 | ||
| 108 | /* flowlabel and prio (includes version, which shouldn't change either */ | 108 | /* flowlabel and prio (includes version, which shouldn't change either */ |
| 109 | flowlabel = *((u_int32_t *)ipv6_hdr(*pskb)); | 109 | flowlabel = *((u_int32_t *)ipv6_hdr(skb)); |
| 110 | 110 | ||
| 111 | ret = ip6t_do_table(pskb, hook, in, out, &packet_mangler); | 111 | ret = ip6t_do_table(skb, hook, in, out, &packet_mangler); |
| 112 | 112 | ||
| 113 | if (ret != NF_DROP && ret != NF_STOLEN | 113 | if (ret != NF_DROP && ret != NF_STOLEN |
| 114 | && (memcmp(&ipv6_hdr(*pskb)->saddr, &saddr, sizeof(saddr)) | 114 | && (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr)) |
| 115 | || memcmp(&ipv6_hdr(*pskb)->daddr, &daddr, sizeof(daddr)) | 115 | || memcmp(&ipv6_hdr(skb)->daddr, &daddr, sizeof(daddr)) |
| 116 | || (*pskb)->mark != mark | 116 | || skb->mark != mark |
| 117 | || ipv6_hdr(*pskb)->hop_limit != hop_limit)) | 117 | || ipv6_hdr(skb)->hop_limit != hop_limit)) |
| 118 | return ip6_route_me_harder(*pskb) == 0 ? ret : NF_DROP; | 118 | return ip6_route_me_harder(skb) == 0 ? ret : NF_DROP; |
| 119 | 119 | ||
| 120 | return ret; | 120 | return ret; |
| 121 | } | 121 | } |
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index ec290e4ebdd8..8f7109f991e6 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c | |||
| @@ -46,12 +46,12 @@ static struct xt_table packet_raw = { | |||
| 46 | /* The work comes in here from netfilter.c. */ | 46 | /* The work comes in here from netfilter.c. */ |
| 47 | static unsigned int | 47 | static unsigned int |
| 48 | ip6t_hook(unsigned int hook, | 48 | ip6t_hook(unsigned int hook, |
| 49 | struct sk_buff **pskb, | 49 | struct sk_buff *skb, |
| 50 | const struct net_device *in, | 50 | const struct net_device *in, |
| 51 | const struct net_device *out, | 51 | const struct net_device *out, |
| 52 | int (*okfn)(struct sk_buff *)) | 52 | int (*okfn)(struct sk_buff *)) |
| 53 | { | 53 | { |
| 54 | return ip6t_do_table(pskb, hook, in, out, &packet_raw); | 54 | return ip6t_do_table(skb, hook, in, out, &packet_raw); |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | static struct nf_hook_ops ip6t_ops[] = { | 57 | static struct nf_hook_ops ip6t_ops[] = { |
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 37a3db926953..0e40948f4fc6 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/icmp.h> | 18 | #include <linux/icmp.h> |
| 19 | #include <linux/sysctl.h> | 19 | #include <linux/sysctl.h> |
| 20 | #include <net/ipv6.h> | 20 | #include <net/ipv6.h> |
| 21 | #include <net/inet_frag.h> | ||
| 21 | 22 | ||
| 22 | #include <linux/netfilter_ipv6.h> | 23 | #include <linux/netfilter_ipv6.h> |
| 23 | #include <net/netfilter/nf_conntrack.h> | 24 | #include <net/netfilter/nf_conntrack.h> |
| @@ -145,7 +146,7 @@ static int ipv6_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, | |||
| 145 | } | 146 | } |
| 146 | 147 | ||
| 147 | static unsigned int ipv6_confirm(unsigned int hooknum, | 148 | static unsigned int ipv6_confirm(unsigned int hooknum, |
| 148 | struct sk_buff **pskb, | 149 | struct sk_buff *skb, |
| 149 | const struct net_device *in, | 150 | const struct net_device *in, |
| 150 | const struct net_device *out, | 151 | const struct net_device *out, |
| 151 | int (*okfn)(struct sk_buff *)) | 152 | int (*okfn)(struct sk_buff *)) |
| @@ -155,12 +156,12 @@ static unsigned int ipv6_confirm(unsigned int hooknum, | |||
| 155 | struct nf_conntrack_helper *helper; | 156 | struct nf_conntrack_helper *helper; |
| 156 | enum ip_conntrack_info ctinfo; | 157 | enum ip_conntrack_info ctinfo; |
| 157 | unsigned int ret, protoff; | 158 | unsigned int ret, protoff; |
| 158 | unsigned int extoff = (u8 *)(ipv6_hdr(*pskb) + 1) - (*pskb)->data; | 159 | unsigned int extoff = (u8 *)(ipv6_hdr(skb) + 1) - skb->data; |
| 159 | unsigned char pnum = ipv6_hdr(*pskb)->nexthdr; | 160 | unsigned char pnum = ipv6_hdr(skb)->nexthdr; |
| 160 | 161 | ||
| 161 | 162 | ||
| 162 | /* This is where we call the helper: as the packet goes out. */ | 163 | /* This is where we call the helper: as the packet goes out. */ |
| 163 | ct = nf_ct_get(*pskb, &ctinfo); | 164 | ct = nf_ct_get(skb, &ctinfo); |
| 164 | if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY) | 165 | if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY) |
| 165 | goto out; | 166 | goto out; |
| 166 | 167 | ||
| @@ -172,23 +173,23 @@ static unsigned int ipv6_confirm(unsigned int hooknum, | |||
| 172 | if (!helper) | 173 | if (!helper) |
| 173 | goto out; | 174 | goto out; |
| 174 | 175 | ||
| 175 | protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum, | 176 | protoff = nf_ct_ipv6_skip_exthdr(skb, extoff, &pnum, |
| 176 | (*pskb)->len - extoff); | 177 | skb->len - extoff); |
| 177 | if (protoff > (*pskb)->len || pnum == NEXTHDR_FRAGMENT) { | 178 | if (protoff > skb->len || pnum == NEXTHDR_FRAGMENT) { |
| 178 | pr_debug("proto header not found\n"); | 179 | pr_debug("proto header not found\n"); |
| 179 | return NF_ACCEPT; | 180 | return NF_ACCEPT; |
| 180 | } | 181 | } |
| 181 | 182 | ||
| 182 | ret = helper->help(pskb, protoff, ct, ctinfo); | 183 | ret = helper->help(skb, protoff, ct, ctinfo); |
| 183 | if (ret != NF_ACCEPT) | 184 | if (ret != NF_ACCEPT) |
| 184 | return ret; | 185 | return ret; |
| 185 | out: | 186 | out: |
| 186 | /* We've seen it coming out the other side: confirm it */ | 187 | /* We've seen it coming out the other side: confirm it */ |
| 187 | return nf_conntrack_confirm(pskb); | 188 | return nf_conntrack_confirm(skb); |
| 188 | } | 189 | } |
| 189 | 190 | ||
| 190 | static unsigned int ipv6_defrag(unsigned int hooknum, | 191 | static unsigned int ipv6_defrag(unsigned int hooknum, |
| 191 | struct sk_buff **pskb, | 192 | struct sk_buff *skb, |
| 192 | const struct net_device *in, | 193 | const struct net_device *in, |
| 193 | const struct net_device *out, | 194 | const struct net_device *out, |
| 194 | int (*okfn)(struct sk_buff *)) | 195 | int (*okfn)(struct sk_buff *)) |
| @@ -196,17 +197,17 @@ static unsigned int ipv6_defrag(unsigned int hooknum, | |||
| 196 | struct sk_buff *reasm; | 197 | struct sk_buff *reasm; |
| 197 | 198 | ||
| 198 | /* Previously seen (loopback)? */ | 199 | /* Previously seen (loopback)? */ |
| 199 | if ((*pskb)->nfct) | 200 | if (skb->nfct) |
| 200 | return NF_ACCEPT; | 201 | return NF_ACCEPT; |
| 201 | 202 | ||
| 202 | reasm = nf_ct_frag6_gather(*pskb); | 203 | reasm = nf_ct_frag6_gather(skb); |
| 203 | 204 | ||
| 204 | /* queued */ | 205 | /* queued */ |
| 205 | if (reasm == NULL) | 206 | if (reasm == NULL) |
| 206 | return NF_STOLEN; | 207 | return NF_STOLEN; |
| 207 | 208 | ||
| 208 | /* error occured or not fragmented */ | 209 | /* error occured or not fragmented */ |
| 209 | if (reasm == *pskb) | 210 | if (reasm == skb) |
| 210 | return NF_ACCEPT; | 211 | return NF_ACCEPT; |
| 211 | 212 | ||
| 212 | nf_ct_frag6_output(hooknum, reasm, (struct net_device *)in, | 213 | nf_ct_frag6_output(hooknum, reasm, (struct net_device *)in, |
| @@ -216,12 +217,12 @@ static unsigned int ipv6_defrag(unsigned int hooknum, | |||
| 216 | } | 217 | } |
| 217 | 218 | ||
| 218 | static unsigned int ipv6_conntrack_in(unsigned int hooknum, | 219 | static unsigned int ipv6_conntrack_in(unsigned int hooknum, |
| 219 | struct sk_buff **pskb, | 220 | struct sk_buff *skb, |
| 220 | const struct net_device *in, | 221 | const struct net_device *in, |
| 221 | const struct net_device *out, | 222 | const struct net_device *out, |
| 222 | int (*okfn)(struct sk_buff *)) | 223 | int (*okfn)(struct sk_buff *)) |
| 223 | { | 224 | { |
| 224 | struct sk_buff *reasm = (*pskb)->nfct_reasm; | 225 | struct sk_buff *reasm = skb->nfct_reasm; |
| 225 | 226 | ||
| 226 | /* This packet is fragmented and has reassembled packet. */ | 227 | /* This packet is fragmented and has reassembled packet. */ |
| 227 | if (reasm) { | 228 | if (reasm) { |
| @@ -229,32 +230,32 @@ static unsigned int ipv6_conntrack_in(unsigned int hooknum, | |||
| 229 | if (!reasm->nfct) { | 230 | if (!reasm->nfct) { |
| 230 | unsigned int ret; | 231 | unsigned int ret; |
| 231 | 232 | ||
| 232 | ret = nf_conntrack_in(PF_INET6, hooknum, &reasm); | 233 | ret = nf_conntrack_in(PF_INET6, hooknum, reasm); |
| 233 | if (ret != NF_ACCEPT) | 234 | if (ret != NF_ACCEPT) |
| 234 | return ret; | 235 | return ret; |
| 235 | } | 236 | } |
| 236 | nf_conntrack_get(reasm->nfct); | 237 | nf_conntrack_get(reasm->nfct); |
| 237 | (*pskb)->nfct = reasm->nfct; | 238 | skb->nfct = reasm->nfct; |
| 238 | (*pskb)->nfctinfo = reasm->nfctinfo; | 239 | skb->nfctinfo = reasm->nfctinfo; |
| 239 | return NF_ACCEPT; | 240 | return NF_ACCEPT; |
| 240 | } | 241 | } |
| 241 | 242 | ||
| 242 | return nf_conntrack_in(PF_INET6, hooknum, pskb); | 243 | return nf_conntrack_in(PF_INET6, hooknum, skb); |
| 243 | } | 244 | } |
| 244 | 245 | ||
| 245 | static unsigned int ipv6_conntrack_local(unsigned int hooknum, | 246 | static unsigned int ipv6_conntrack_local(unsigned int hooknum, |
| 246 | struct sk_buff **pskb, | 247 | struct sk_buff *skb, |
| 247 | const struct net_device *in, | 248 | const struct net_device *in, |
| 248 | const struct net_device *out, | 249 | const struct net_device *out, |
| 249 | int (*okfn)(struct sk_buff *)) | 250 | int (*okfn)(struct sk_buff *)) |
| 250 | { | 251 | { |
| 251 | /* root is playing with raw sockets. */ | 252 | /* root is playing with raw sockets. */ |
| 252 | if ((*pskb)->len < sizeof(struct ipv6hdr)) { | 253 | if (skb->len < sizeof(struct ipv6hdr)) { |
| 253 | if (net_ratelimit()) | 254 | if (net_ratelimit()) |
| 254 | printk("ipv6_conntrack_local: packet too short\n"); | 255 | printk("ipv6_conntrack_local: packet too short\n"); |
| 255 | return NF_ACCEPT; | 256 | return NF_ACCEPT; |
| 256 | } | 257 | } |
| 257 | return ipv6_conntrack_in(hooknum, pskb, in, out, okfn); | 258 | return ipv6_conntrack_in(hooknum, skb, in, out, okfn); |
| 258 | } | 259 | } |
| 259 | 260 | ||
| 260 | static struct nf_hook_ops ipv6_conntrack_ops[] = { | 261 | static struct nf_hook_ops ipv6_conntrack_ops[] = { |
| @@ -307,7 +308,7 @@ static ctl_table nf_ct_ipv6_sysctl_table[] = { | |||
| 307 | { | 308 | { |
| 308 | .ctl_name = NET_NF_CONNTRACK_FRAG6_TIMEOUT, | 309 | .ctl_name = NET_NF_CONNTRACK_FRAG6_TIMEOUT, |
| 309 | .procname = "nf_conntrack_frag6_timeout", | 310 | .procname = "nf_conntrack_frag6_timeout", |
| 310 | .data = &nf_ct_frag6_timeout, | 311 | .data = &nf_frags_ctl.timeout, |
| 311 | .maxlen = sizeof(unsigned int), | 312 | .maxlen = sizeof(unsigned int), |
| 312 | .mode = 0644, | 313 | .mode = 0644, |
| 313 | .proc_handler = &proc_dointvec_jiffies, | 314 | .proc_handler = &proc_dointvec_jiffies, |
| @@ -315,7 +316,7 @@ static ctl_table nf_ct_ipv6_sysctl_table[] = { | |||
| 315 | { | 316 | { |
| 316 | .ctl_name = NET_NF_CONNTRACK_FRAG6_LOW_THRESH, | 317 | .ctl_name = NET_NF_CONNTRACK_FRAG6_LOW_THRESH, |
| 317 | .procname = "nf_conntrack_frag6_low_thresh", | 318 | .procname = "nf_conntrack_frag6_low_thresh", |
| 318 | .data = &nf_ct_frag6_low_thresh, | 319 | .data = &nf_frags_ctl.low_thresh, |
| 319 | .maxlen = sizeof(unsigned int), | 320 | .maxlen = sizeof(unsigned int), |
| 320 | .mode = 0644, | 321 | .mode = 0644, |
| 321 | .proc_handler = &proc_dointvec, | 322 | .proc_handler = &proc_dointvec, |
| @@ -323,7 +324,7 @@ static ctl_table nf_ct_ipv6_sysctl_table[] = { | |||
| 323 | { | 324 | { |
| 324 | .ctl_name = NET_NF_CONNTRACK_FRAG6_HIGH_THRESH, | 325 | .ctl_name = NET_NF_CONNTRACK_FRAG6_HIGH_THRESH, |
| 325 | .procname = "nf_conntrack_frag6_high_thresh", | 326 | .procname = "nf_conntrack_frag6_high_thresh", |
| 326 | .data = &nf_ct_frag6_high_thresh, | 327 | .data = &nf_frags_ctl.high_thresh, |
| 327 | .maxlen = sizeof(unsigned int), | 328 | .maxlen = sizeof(unsigned int), |
| 328 | .mode = 0644, | 329 | .mode = 0644, |
| 329 | .proc_handler = &proc_dointvec, | 330 | .proc_handler = &proc_dointvec, |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 25442a8c1ba8..726fafd41961 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | 31 | ||
| 32 | #include <net/sock.h> | 32 | #include <net/sock.h> |
| 33 | #include <net/snmp.h> | 33 | #include <net/snmp.h> |
| 34 | #include <net/inet_frag.h> | ||
| 34 | 35 | ||
| 35 | #include <net/ipv6.h> | 36 | #include <net/ipv6.h> |
| 36 | #include <net/protocol.h> | 37 | #include <net/protocol.h> |
| @@ -48,10 +49,6 @@ | |||
| 48 | #define NF_CT_FRAG6_LOW_THRESH 196608 /* == 192*1024 */ | 49 | #define NF_CT_FRAG6_LOW_THRESH 196608 /* == 192*1024 */ |
| 49 | #define NF_CT_FRAG6_TIMEOUT IPV6_FRAG_TIMEOUT | 50 | #define NF_CT_FRAG6_TIMEOUT IPV6_FRAG_TIMEOUT |
| 50 | 51 | ||
| 51 | unsigned int nf_ct_frag6_high_thresh __read_mostly = 256*1024; | ||
| 52 | unsigned int nf_ct_frag6_low_thresh __read_mostly = 192*1024; | ||
| 53 | unsigned long nf_ct_frag6_timeout __read_mostly = IPV6_FRAG_TIMEOUT; | ||
| 54 | |||
| 55 | struct nf_ct_frag6_skb_cb | 52 | struct nf_ct_frag6_skb_cb |
| 56 | { | 53 | { |
| 57 | struct inet6_skb_parm h; | 54 | struct inet6_skb_parm h; |
| @@ -63,51 +60,24 @@ struct nf_ct_frag6_skb_cb | |||
| 63 | 60 | ||
| 64 | struct nf_ct_frag6_queue | 61 | struct nf_ct_frag6_queue |
| 65 | { | 62 | { |
| 66 | struct hlist_node list; | 63 | struct inet_frag_queue q; |
| 67 | struct list_head lru_list; /* lru list member */ | ||
| 68 | 64 | ||
| 69 | __be32 id; /* fragment id */ | 65 | __be32 id; /* fragment id */ |
| 70 | struct in6_addr saddr; | 66 | struct in6_addr saddr; |
| 71 | struct in6_addr daddr; | 67 | struct in6_addr daddr; |
| 72 | 68 | ||
| 73 | spinlock_t lock; | ||
| 74 | atomic_t refcnt; | ||
| 75 | struct timer_list timer; /* expire timer */ | ||
| 76 | struct sk_buff *fragments; | ||
| 77 | int len; | ||
| 78 | int meat; | ||
| 79 | ktime_t stamp; | ||
| 80 | unsigned int csum; | 69 | unsigned int csum; |
| 81 | __u8 last_in; /* has first/last segment arrived? */ | ||
| 82 | #define COMPLETE 4 | ||
| 83 | #define FIRST_IN 2 | ||
| 84 | #define LAST_IN 1 | ||
| 85 | __u16 nhoffset; | 70 | __u16 nhoffset; |
| 86 | }; | 71 | }; |
| 87 | 72 | ||
| 88 | /* Hash table. */ | 73 | struct inet_frags_ctl nf_frags_ctl __read_mostly = { |
| 89 | 74 | .high_thresh = 256 * 1024, | |
| 90 | #define FRAG6Q_HASHSZ 64 | 75 | .low_thresh = 192 * 1024, |
| 91 | 76 | .timeout = IPV6_FRAG_TIMEOUT, | |
| 92 | static struct hlist_head nf_ct_frag6_hash[FRAG6Q_HASHSZ]; | 77 | .secret_interval = 10 * 60 * HZ, |
| 93 | static DEFINE_RWLOCK(nf_ct_frag6_lock); | 78 | }; |
| 94 | static u32 nf_ct_frag6_hash_rnd; | ||
| 95 | static LIST_HEAD(nf_ct_frag6_lru_list); | ||
| 96 | int nf_ct_frag6_nqueues = 0; | ||
| 97 | |||
| 98 | static __inline__ void __fq_unlink(struct nf_ct_frag6_queue *fq) | ||
| 99 | { | ||
| 100 | hlist_del(&fq->list); | ||
| 101 | list_del(&fq->lru_list); | ||
| 102 | nf_ct_frag6_nqueues--; | ||
| 103 | } | ||
| 104 | 79 | ||
| 105 | static __inline__ void fq_unlink(struct nf_ct_frag6_queue *fq) | 80 | static struct inet_frags nf_frags; |
| 106 | { | ||
| 107 | write_lock(&nf_ct_frag6_lock); | ||
| 108 | __fq_unlink(fq); | ||
| 109 | write_unlock(&nf_ct_frag6_lock); | ||
| 110 | } | ||
| 111 | 81 | ||
| 112 | static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr, | 82 | static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr, |
| 113 | struct in6_addr *daddr) | 83 | struct in6_addr *daddr) |
| @@ -120,7 +90,7 @@ static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr, | |||
| 120 | 90 | ||
| 121 | a += JHASH_GOLDEN_RATIO; | 91 | a += JHASH_GOLDEN_RATIO; |
| 122 | b += JHASH_GOLDEN_RATIO; | 92 | b += JHASH_GOLDEN_RATIO; |
| 123 | c += nf_ct_frag6_hash_rnd; | 93 | c += nf_frags.rnd; |
| 124 | __jhash_mix(a, b, c); | 94 | __jhash_mix(a, b, c); |
| 125 | 95 | ||
| 126 | a += (__force u32)saddr->s6_addr32[3]; | 96 | a += (__force u32)saddr->s6_addr32[3]; |
| @@ -133,100 +103,54 @@ static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr, | |||
| 133 | c += (__force u32)id; | 103 | c += (__force u32)id; |
| 134 | __jhash_mix(a, b, c); | 104 | __jhash_mix(a, b, c); |
| 135 | 105 | ||
| 136 | return c & (FRAG6Q_HASHSZ - 1); | 106 | return c & (INETFRAGS_HASHSZ - 1); |
| 137 | } | 107 | } |
| 138 | 108 | ||
| 139 | static struct timer_list nf_ct_frag6_secret_timer; | 109 | static unsigned int nf_hashfn(struct inet_frag_queue *q) |
| 140 | int nf_ct_frag6_secret_interval = 10 * 60 * HZ; | ||
| 141 | |||
| 142 | static void nf_ct_frag6_secret_rebuild(unsigned long dummy) | ||
| 143 | { | 110 | { |
| 144 | unsigned long now = jiffies; | 111 | struct nf_ct_frag6_queue *nq; |
| 145 | int i; | ||
| 146 | |||
| 147 | write_lock(&nf_ct_frag6_lock); | ||
| 148 | get_random_bytes(&nf_ct_frag6_hash_rnd, sizeof(u32)); | ||
| 149 | for (i = 0; i < FRAG6Q_HASHSZ; i++) { | ||
| 150 | struct nf_ct_frag6_queue *q; | ||
| 151 | struct hlist_node *p, *n; | ||
| 152 | |||
| 153 | hlist_for_each_entry_safe(q, p, n, &nf_ct_frag6_hash[i], list) { | ||
| 154 | unsigned int hval = ip6qhashfn(q->id, | ||
| 155 | &q->saddr, | ||
| 156 | &q->daddr); | ||
| 157 | if (hval != i) { | ||
| 158 | hlist_del(&q->list); | ||
| 159 | /* Relink to new hash chain. */ | ||
| 160 | hlist_add_head(&q->list, | ||
| 161 | &nf_ct_frag6_hash[hval]); | ||
| 162 | } | ||
| 163 | } | ||
| 164 | } | ||
| 165 | write_unlock(&nf_ct_frag6_lock); | ||
| 166 | 112 | ||
| 167 | mod_timer(&nf_ct_frag6_secret_timer, now + nf_ct_frag6_secret_interval); | 113 | nq = container_of(q, struct nf_ct_frag6_queue, q); |
| 114 | return ip6qhashfn(nq->id, &nq->saddr, &nq->daddr); | ||
| 168 | } | 115 | } |
| 169 | 116 | ||
| 170 | atomic_t nf_ct_frag6_mem = ATOMIC_INIT(0); | 117 | static void nf_skb_free(struct sk_buff *skb) |
| 118 | { | ||
| 119 | if (NFCT_FRAG6_CB(skb)->orig) | ||
| 120 | kfree_skb(NFCT_FRAG6_CB(skb)->orig); | ||
| 121 | } | ||
| 171 | 122 | ||
| 172 | /* Memory Tracking Functions. */ | 123 | /* Memory Tracking Functions. */ |
| 173 | static inline void frag_kfree_skb(struct sk_buff *skb, unsigned int *work) | 124 | static inline void frag_kfree_skb(struct sk_buff *skb, unsigned int *work) |
| 174 | { | 125 | { |
| 175 | if (work) | 126 | if (work) |
| 176 | *work -= skb->truesize; | 127 | *work -= skb->truesize; |
| 177 | atomic_sub(skb->truesize, &nf_ct_frag6_mem); | 128 | atomic_sub(skb->truesize, &nf_frags.mem); |
| 178 | if (NFCT_FRAG6_CB(skb)->orig) | 129 | nf_skb_free(skb); |
| 179 | kfree_skb(NFCT_FRAG6_CB(skb)->orig); | ||
| 180 | |||
| 181 | kfree_skb(skb); | 130 | kfree_skb(skb); |
| 182 | } | 131 | } |
| 183 | 132 | ||
| 184 | static inline void frag_free_queue(struct nf_ct_frag6_queue *fq, | 133 | static void nf_frag_free(struct inet_frag_queue *q) |
| 185 | unsigned int *work) | ||
| 186 | { | 134 | { |
| 187 | if (work) | 135 | kfree(container_of(q, struct nf_ct_frag6_queue, q)); |
| 188 | *work -= sizeof(struct nf_ct_frag6_queue); | ||
| 189 | atomic_sub(sizeof(struct nf_ct_frag6_queue), &nf_ct_frag6_mem); | ||
| 190 | kfree(fq); | ||
| 191 | } | 136 | } |
| 192 | 137 | ||
| 193 | static inline struct nf_ct_frag6_queue *frag_alloc_queue(void) | 138 | static inline struct nf_ct_frag6_queue *frag_alloc_queue(void) |
| 194 | { | 139 | { |
| 195 | struct nf_ct_frag6_queue *fq = kmalloc(sizeof(struct nf_ct_frag6_queue), GFP_ATOMIC); | 140 | struct nf_ct_frag6_queue *fq; |
| 196 | 141 | ||
| 197 | if (!fq) | 142 | fq = kzalloc(sizeof(struct nf_ct_frag6_queue), GFP_ATOMIC); |
| 143 | if (fq == NULL) | ||
| 198 | return NULL; | 144 | return NULL; |
| 199 | atomic_add(sizeof(struct nf_ct_frag6_queue), &nf_ct_frag6_mem); | 145 | atomic_add(sizeof(struct nf_ct_frag6_queue), &nf_frags.mem); |
| 200 | return fq; | 146 | return fq; |
| 201 | } | 147 | } |
| 202 | 148 | ||
| 203 | /* Destruction primitives. */ | 149 | /* Destruction primitives. */ |
| 204 | 150 | ||
| 205 | /* Complete destruction of fq. */ | 151 | static __inline__ void fq_put(struct nf_ct_frag6_queue *fq) |
| 206 | static void nf_ct_frag6_destroy(struct nf_ct_frag6_queue *fq, | ||
| 207 | unsigned int *work) | ||
| 208 | { | 152 | { |
| 209 | struct sk_buff *fp; | 153 | inet_frag_put(&fq->q, &nf_frags); |
| 210 | |||
| 211 | BUG_TRAP(fq->last_in&COMPLETE); | ||
| 212 | BUG_TRAP(del_timer(&fq->timer) == 0); | ||
| 213 | |||
| 214 | /* Release all fragment data. */ | ||
| 215 | fp = fq->fragments; | ||
| 216 | while (fp) { | ||
| 217 | struct sk_buff *xp = fp->next; | ||
| 218 | |||
| 219 | frag_kfree_skb(fp, work); | ||
| 220 | fp = xp; | ||
| 221 | } | ||
| 222 | |||
| 223 | frag_free_queue(fq, work); | ||
| 224 | } | ||
| 225 | |||
| 226 | static __inline__ void fq_put(struct nf_ct_frag6_queue *fq, unsigned int *work) | ||
| 227 | { | ||
| 228 | if (atomic_dec_and_test(&fq->refcnt)) | ||
| 229 | nf_ct_frag6_destroy(fq, work); | ||
| 230 | } | 154 | } |
| 231 | 155 | ||
| 232 | /* Kill fq entry. It is not destroyed immediately, | 156 | /* Kill fq entry. It is not destroyed immediately, |
| @@ -234,62 +158,28 @@ static __inline__ void fq_put(struct nf_ct_frag6_queue *fq, unsigned int *work) | |||
| 234 | */ | 158 | */ |
| 235 | static __inline__ void fq_kill(struct nf_ct_frag6_queue *fq) | 159 | static __inline__ void fq_kill(struct nf_ct_frag6_queue *fq) |
| 236 | { | 160 | { |
| 237 | if (del_timer(&fq->timer)) | 161 | inet_frag_kill(&fq->q, &nf_frags); |
| 238 | atomic_dec(&fq->refcnt); | ||
| 239 | |||
| 240 | if (!(fq->last_in & COMPLETE)) { | ||
| 241 | fq_unlink(fq); | ||
| 242 | atomic_dec(&fq->refcnt); | ||
| 243 | fq->last_in |= COMPLETE; | ||
| 244 | } | ||
| 245 | } | 162 | } |
| 246 | 163 | ||
| 247 | static void nf_ct_frag6_evictor(void) | 164 | static void nf_ct_frag6_evictor(void) |
| 248 | { | 165 | { |
| 249 | struct nf_ct_frag6_queue *fq; | 166 | inet_frag_evictor(&nf_frags); |
| 250 | struct list_head *tmp; | ||
| 251 | unsigned int work; | ||
| 252 | |||
| 253 | work = atomic_read(&nf_ct_frag6_mem); | ||
| 254 | if (work <= nf_ct_frag6_low_thresh) | ||
| 255 | return; | ||
| 256 | |||
| 257 | work -= nf_ct_frag6_low_thresh; | ||
| 258 | while (work > 0) { | ||
| 259 | read_lock(&nf_ct_frag6_lock); | ||
| 260 | if (list_empty(&nf_ct_frag6_lru_list)) { | ||
| 261 | read_unlock(&nf_ct_frag6_lock); | ||
| 262 | return; | ||
| 263 | } | ||
| 264 | tmp = nf_ct_frag6_lru_list.next; | ||
| 265 | BUG_ON(tmp == NULL); | ||
| 266 | fq = list_entry(tmp, struct nf_ct_frag6_queue, lru_list); | ||
| 267 | atomic_inc(&fq->refcnt); | ||
| 268 | read_unlock(&nf_ct_frag6_lock); | ||
| 269 | |||
| 270 | spin_lock(&fq->lock); | ||
| 271 | if (!(fq->last_in&COMPLETE)) | ||
| 272 | fq_kill(fq); | ||
| 273 | spin_unlock(&fq->lock); | ||
| 274 | |||
| 275 | fq_put(fq, &work); | ||
| 276 | } | ||
| 277 | } | 167 | } |
| 278 | 168 | ||
| 279 | static void nf_ct_frag6_expire(unsigned long data) | 169 | static void nf_ct_frag6_expire(unsigned long data) |
| 280 | { | 170 | { |
| 281 | struct nf_ct_frag6_queue *fq = (struct nf_ct_frag6_queue *) data; | 171 | struct nf_ct_frag6_queue *fq = (struct nf_ct_frag6_queue *) data; |
| 282 | 172 | ||
| 283 | spin_lock(&fq->lock); | 173 | spin_lock(&fq->q.lock); |
| 284 | 174 | ||
| 285 | if (fq->last_in & COMPLETE) | 175 | if (fq->q.last_in & COMPLETE) |
| 286 | goto out; | 176 | goto out; |
| 287 | 177 | ||
| 288 | fq_kill(fq); | 178 | fq_kill(fq); |
| 289 | 179 | ||
| 290 | out: | 180 | out: |
| 291 | spin_unlock(&fq->lock); | 181 | spin_unlock(&fq->q.lock); |
| 292 | fq_put(fq, NULL); | 182 | fq_put(fq); |
| 293 | } | 183 | } |
| 294 | 184 | ||
| 295 | /* Creation primitives. */ | 185 | /* Creation primitives. */ |
| @@ -302,31 +192,31 @@ static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash, | |||
| 302 | struct hlist_node *n; | 192 | struct hlist_node *n; |
| 303 | #endif | 193 | #endif |
| 304 | 194 | ||
| 305 | write_lock(&nf_ct_frag6_lock); | 195 | write_lock(&nf_frags.lock); |
| 306 | #ifdef CONFIG_SMP | 196 | #ifdef CONFIG_SMP |
| 307 | hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) { | 197 | hlist_for_each_entry(fq, n, &nf_frags.hash[hash], q.list) { |
| 308 | if (fq->id == fq_in->id && | 198 | if (fq->id == fq_in->id && |
| 309 | ipv6_addr_equal(&fq_in->saddr, &fq->saddr) && | 199 | ipv6_addr_equal(&fq_in->saddr, &fq->saddr) && |
| 310 | ipv6_addr_equal(&fq_in->daddr, &fq->daddr)) { | 200 | ipv6_addr_equal(&fq_in->daddr, &fq->daddr)) { |
| 311 | atomic_inc(&fq->refcnt); | 201 | atomic_inc(&fq->q.refcnt); |
| 312 | write_unlock(&nf_ct_frag6_lock); | 202 | write_unlock(&nf_frags.lock); |
| 313 | fq_in->last_in |= COMPLETE; | 203 | fq_in->q.last_in |= COMPLETE; |
| 314 | fq_put(fq_in, NULL); | 204 | fq_put(fq_in); |
| 315 | return fq; | 205 | return fq; |
| 316 | } | 206 | } |
| 317 | } | 207 | } |
| 318 | #endif | 208 | #endif |
| 319 | fq = fq_in; | 209 | fq = fq_in; |
| 320 | 210 | ||
| 321 | if (!mod_timer(&fq->timer, jiffies + nf_ct_frag6_timeout)) | 211 | if (!mod_timer(&fq->q.timer, jiffies + nf_frags_ctl.timeout)) |
| 322 | atomic_inc(&fq->refcnt); | 212 | atomic_inc(&fq->q.refcnt); |
| 323 | 213 | ||
| 324 | atomic_inc(&fq->refcnt); | 214 | atomic_inc(&fq->q.refcnt); |
| 325 | hlist_add_head(&fq->list, &nf_ct_frag6_hash[hash]); | 215 | hlist_add_head(&fq->q.list, &nf_frags.hash[hash]); |
| 326 | INIT_LIST_HEAD(&fq->lru_list); | 216 | INIT_LIST_HEAD(&fq->q.lru_list); |
| 327 | list_add_tail(&fq->lru_list, &nf_ct_frag6_lru_list); | 217 | list_add_tail(&fq->q.lru_list, &nf_frags.lru_list); |
| 328 | nf_ct_frag6_nqueues++; | 218 | nf_frags.nqueues++; |
| 329 | write_unlock(&nf_ct_frag6_lock); | 219 | write_unlock(&nf_frags.lock); |
| 330 | return fq; | 220 | return fq; |
| 331 | } | 221 | } |
| 332 | 222 | ||
| @@ -341,15 +231,13 @@ nf_ct_frag6_create(unsigned int hash, __be32 id, struct in6_addr *src, str | |||
| 341 | goto oom; | 231 | goto oom; |
| 342 | } | 232 | } |
| 343 | 233 | ||
| 344 | memset(fq, 0, sizeof(struct nf_ct_frag6_queue)); | ||
| 345 | |||
| 346 | fq->id = id; | 234 | fq->id = id; |
| 347 | ipv6_addr_copy(&fq->saddr, src); | 235 | ipv6_addr_copy(&fq->saddr, src); |
| 348 | ipv6_addr_copy(&fq->daddr, dst); | 236 | ipv6_addr_copy(&fq->daddr, dst); |
| 349 | 237 | ||
| 350 | setup_timer(&fq->timer, nf_ct_frag6_expire, (unsigned long)fq); | 238 | setup_timer(&fq->q.timer, nf_ct_frag6_expire, (unsigned long)fq); |
| 351 | spin_lock_init(&fq->lock); | 239 | spin_lock_init(&fq->q.lock); |
| 352 | atomic_set(&fq->refcnt, 1); | 240 | atomic_set(&fq->q.refcnt, 1); |
| 353 | 241 | ||
| 354 | return nf_ct_frag6_intern(hash, fq); | 242 | return nf_ct_frag6_intern(hash, fq); |
| 355 | 243 | ||
| @@ -364,17 +252,17 @@ fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst) | |||
| 364 | struct hlist_node *n; | 252 | struct hlist_node *n; |
| 365 | unsigned int hash = ip6qhashfn(id, src, dst); | 253 | unsigned int hash = ip6qhashfn(id, src, dst); |
| 366 | 254 | ||
| 367 | read_lock(&nf_ct_frag6_lock); | 255 | read_lock(&nf_frags.lock); |
| 368 | hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) { | 256 | hlist_for_each_entry(fq, n, &nf_frags.hash[hash], q.list) { |
| 369 | if (fq->id == id && | 257 | if (fq->id == id && |
| 370 | ipv6_addr_equal(src, &fq->saddr) && | 258 | ipv6_addr_equal(src, &fq->saddr) && |
| 371 | ipv6_addr_equal(dst, &fq->daddr)) { | 259 | ipv6_addr_equal(dst, &fq->daddr)) { |
| 372 | atomic_inc(&fq->refcnt); | 260 | atomic_inc(&fq->q.refcnt); |
| 373 | read_unlock(&nf_ct_frag6_lock); | 261 | read_unlock(&nf_frags.lock); |
| 374 | return fq; | 262 | return fq; |
| 375 | } | 263 | } |
| 376 | } | 264 | } |
| 377 | read_unlock(&nf_ct_frag6_lock); | 265 | read_unlock(&nf_frags.lock); |
| 378 | 266 | ||
| 379 | return nf_ct_frag6_create(hash, id, src, dst); | 267 | return nf_ct_frag6_create(hash, id, src, dst); |
| 380 | } | 268 | } |
| @@ -386,7 +274,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
| 386 | struct sk_buff *prev, *next; | 274 | struct sk_buff *prev, *next; |
| 387 | int offset, end; | 275 | int offset, end; |
| 388 | 276 | ||
| 389 | if (fq->last_in & COMPLETE) { | 277 | if (fq->q.last_in & COMPLETE) { |
| 390 | pr_debug("Allready completed\n"); | 278 | pr_debug("Allready completed\n"); |
| 391 | goto err; | 279 | goto err; |
| 392 | } | 280 | } |
| @@ -412,13 +300,13 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
| 412 | /* If we already have some bits beyond end | 300 | /* If we already have some bits beyond end |
| 413 | * or have different end, the segment is corrupted. | 301 | * or have different end, the segment is corrupted. |
| 414 | */ | 302 | */ |
| 415 | if (end < fq->len || | 303 | if (end < fq->q.len || |
| 416 | ((fq->last_in & LAST_IN) && end != fq->len)) { | 304 | ((fq->q.last_in & LAST_IN) && end != fq->q.len)) { |
| 417 | pr_debug("already received last fragment\n"); | 305 | pr_debug("already received last fragment\n"); |
| 418 | goto err; | 306 | goto err; |
| 419 | } | 307 | } |
| 420 | fq->last_in |= LAST_IN; | 308 | fq->q.last_in |= LAST_IN; |
| 421 | fq->len = end; | 309 | fq->q.len = end; |
| 422 | } else { | 310 | } else { |
| 423 | /* Check if the fragment is rounded to 8 bytes. | 311 | /* Check if the fragment is rounded to 8 bytes. |
| 424 | * Required by the RFC. | 312 | * Required by the RFC. |
| @@ -430,13 +318,13 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
| 430 | pr_debug("end of fragment not rounded to 8 bytes.\n"); | 318 | pr_debug("end of fragment not rounded to 8 bytes.\n"); |
| 431 | return -1; | 319 | return -1; |
| 432 | } | 320 | } |
| 433 | if (end > fq->len) { | 321 | if (end > fq->q.len) { |
| 434 | /* Some bits beyond end -> corruption. */ | 322 | /* Some bits beyond end -> corruption. */ |
| 435 | if (fq->last_in & LAST_IN) { | 323 | if (fq->q.last_in & LAST_IN) { |
| 436 | pr_debug("last packet already reached.\n"); | 324 | pr_debug("last packet already reached.\n"); |
| 437 | goto err; | 325 | goto err; |
| 438 | } | 326 | } |
| 439 | fq->len = end; | 327 | fq->q.len = end; |
| 440 | } | 328 | } |
| 441 | } | 329 | } |
| 442 | 330 | ||
| @@ -458,7 +346,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
| 458 | * this fragment, right? | 346 | * this fragment, right? |
| 459 | */ | 347 | */ |
| 460 | prev = NULL; | 348 | prev = NULL; |
| 461 | for (next = fq->fragments; next != NULL; next = next->next) { | 349 | for (next = fq->q.fragments; next != NULL; next = next->next) { |
| 462 | if (NFCT_FRAG6_CB(next)->offset >= offset) | 350 | if (NFCT_FRAG6_CB(next)->offset >= offset) |
| 463 | break; /* bingo! */ | 351 | break; /* bingo! */ |
| 464 | prev = next; | 352 | prev = next; |
| @@ -503,7 +391,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
| 503 | 391 | ||
| 504 | /* next fragment */ | 392 | /* next fragment */ |
| 505 | NFCT_FRAG6_CB(next)->offset += i; | 393 | NFCT_FRAG6_CB(next)->offset += i; |
| 506 | fq->meat -= i; | 394 | fq->q.meat -= i; |
| 507 | if (next->ip_summed != CHECKSUM_UNNECESSARY) | 395 | if (next->ip_summed != CHECKSUM_UNNECESSARY) |
| 508 | next->ip_summed = CHECKSUM_NONE; | 396 | next->ip_summed = CHECKSUM_NONE; |
| 509 | break; | 397 | break; |
| @@ -518,9 +406,9 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
| 518 | if (prev) | 406 | if (prev) |
| 519 | prev->next = next; | 407 | prev->next = next; |
| 520 | else | 408 | else |
| 521 | fq->fragments = next; | 409 | fq->q.fragments = next; |
| 522 | 410 | ||
| 523 | fq->meat -= free_it->len; | 411 | fq->q.meat -= free_it->len; |
| 524 | frag_kfree_skb(free_it, NULL); | 412 | frag_kfree_skb(free_it, NULL); |
| 525 | } | 413 | } |
| 526 | } | 414 | } |
| @@ -532,23 +420,23 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
| 532 | if (prev) | 420 | if (prev) |
| 533 | prev->next = skb; | 421 | prev->next = skb; |
| 534 | else | 422 | else |
| 535 | fq->fragments = skb; | 423 | fq->q.fragments = skb; |
| 536 | 424 | ||
| 537 | skb->dev = NULL; | 425 | skb->dev = NULL; |
| 538 | fq->stamp = skb->tstamp; | 426 | fq->q.stamp = skb->tstamp; |
| 539 | fq->meat += skb->len; | 427 | fq->q.meat += skb->len; |
| 540 | atomic_add(skb->truesize, &nf_ct_frag6_mem); | 428 | atomic_add(skb->truesize, &nf_frags.mem); |
| 541 | 429 | ||
| 542 | /* The first fragment. | 430 | /* The first fragment. |
| 543 | * nhoffset is obtained from the first fragment, of course. | 431 | * nhoffset is obtained from the first fragment, of course. |
| 544 | */ | 432 | */ |
| 545 | if (offset == 0) { | 433 | if (offset == 0) { |
| 546 | fq->nhoffset = nhoff; | 434 | fq->nhoffset = nhoff; |
| 547 | fq->last_in |= FIRST_IN; | 435 | fq->q.last_in |= FIRST_IN; |
| 548 | } | 436 | } |
| 549 | write_lock(&nf_ct_frag6_lock); | 437 | write_lock(&nf_frags.lock); |
| 550 | list_move_tail(&fq->lru_list, &nf_ct_frag6_lru_list); | 438 | list_move_tail(&fq->q.lru_list, &nf_frags.lru_list); |
| 551 | write_unlock(&nf_ct_frag6_lock); | 439 | write_unlock(&nf_frags.lock); |
| 552 | return 0; | 440 | return 0; |
| 553 | 441 | ||
| 554 | err: | 442 | err: |
| @@ -567,7 +455,7 @@ err: | |||
| 567 | static struct sk_buff * | 455 | static struct sk_buff * |
| 568 | nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | 456 | nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) |
| 569 | { | 457 | { |
| 570 | struct sk_buff *fp, *op, *head = fq->fragments; | 458 | struct sk_buff *fp, *op, *head = fq->q.fragments; |
| 571 | int payload_len; | 459 | int payload_len; |
| 572 | 460 | ||
| 573 | fq_kill(fq); | 461 | fq_kill(fq); |
| @@ -577,7 +465,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | |||
| 577 | 465 | ||
| 578 | /* Unfragmented part is taken from the first segment. */ | 466 | /* Unfragmented part is taken from the first segment. */ |
| 579 | payload_len = ((head->data - skb_network_header(head)) - | 467 | payload_len = ((head->data - skb_network_header(head)) - |
| 580 | sizeof(struct ipv6hdr) + fq->len - | 468 | sizeof(struct ipv6hdr) + fq->q.len - |
| 581 | sizeof(struct frag_hdr)); | 469 | sizeof(struct frag_hdr)); |
| 582 | if (payload_len > IPV6_MAXPLEN) { | 470 | if (payload_len > IPV6_MAXPLEN) { |
| 583 | pr_debug("payload len is too large.\n"); | 471 | pr_debug("payload len is too large.\n"); |
| @@ -614,7 +502,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | |||
| 614 | clone->ip_summed = head->ip_summed; | 502 | clone->ip_summed = head->ip_summed; |
| 615 | 503 | ||
| 616 | NFCT_FRAG6_CB(clone)->orig = NULL; | 504 | NFCT_FRAG6_CB(clone)->orig = NULL; |
| 617 | atomic_add(clone->truesize, &nf_ct_frag6_mem); | 505 | atomic_add(clone->truesize, &nf_frags.mem); |
| 618 | } | 506 | } |
| 619 | 507 | ||
| 620 | /* We have to remove fragment header from datagram and to relocate | 508 | /* We have to remove fragment header from datagram and to relocate |
| @@ -628,7 +516,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | |||
| 628 | skb_shinfo(head)->frag_list = head->next; | 516 | skb_shinfo(head)->frag_list = head->next; |
| 629 | skb_reset_transport_header(head); | 517 | skb_reset_transport_header(head); |
| 630 | skb_push(head, head->data - skb_network_header(head)); | 518 | skb_push(head, head->data - skb_network_header(head)); |
| 631 | atomic_sub(head->truesize, &nf_ct_frag6_mem); | 519 | atomic_sub(head->truesize, &nf_frags.mem); |
| 632 | 520 | ||
| 633 | for (fp=head->next; fp; fp = fp->next) { | 521 | for (fp=head->next; fp; fp = fp->next) { |
| 634 | head->data_len += fp->len; | 522 | head->data_len += fp->len; |
| @@ -638,12 +526,12 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | |||
| 638 | else if (head->ip_summed == CHECKSUM_COMPLETE) | 526 | else if (head->ip_summed == CHECKSUM_COMPLETE) |
| 639 | head->csum = csum_add(head->csum, fp->csum); | 527 | head->csum = csum_add(head->csum, fp->csum); |
| 640 | head->truesize += fp->truesize; | 528 | head->truesize += fp->truesize; |
| 641 | atomic_sub(fp->truesize, &nf_ct_frag6_mem); | 529 | atomic_sub(fp->truesize, &nf_frags.mem); |
| 642 | } | 530 | } |
| 643 | 531 | ||
| 644 | head->next = NULL; | 532 | head->next = NULL; |
| 645 | head->dev = dev; | 533 | head->dev = dev; |
| 646 | head->tstamp = fq->stamp; | 534 | head->tstamp = fq->q.stamp; |
| 647 | ipv6_hdr(head)->payload_len = htons(payload_len); | 535 | ipv6_hdr(head)->payload_len = htons(payload_len); |
| 648 | 536 | ||
| 649 | /* Yes, and fold redundant checksum back. 8) */ | 537 | /* Yes, and fold redundant checksum back. 8) */ |
| @@ -652,7 +540,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | |||
| 652 | skb_network_header_len(head), | 540 | skb_network_header_len(head), |
| 653 | head->csum); | 541 | head->csum); |
| 654 | 542 | ||
| 655 | fq->fragments = NULL; | 543 | fq->q.fragments = NULL; |
| 656 | 544 | ||
| 657 | /* all original skbs are linked into the NFCT_FRAG6_CB(head).orig */ | 545 | /* all original skbs are linked into the NFCT_FRAG6_CB(head).orig */ |
| 658 | fp = skb_shinfo(head)->frag_list; | 546 | fp = skb_shinfo(head)->frag_list; |
| @@ -788,7 +676,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb) | |||
| 788 | goto ret_orig; | 676 | goto ret_orig; |
| 789 | } | 677 | } |
| 790 | 678 | ||
| 791 | if (atomic_read(&nf_ct_frag6_mem) > nf_ct_frag6_high_thresh) | 679 | if (atomic_read(&nf_frags.mem) > nf_frags_ctl.high_thresh) |
| 792 | nf_ct_frag6_evictor(); | 680 | nf_ct_frag6_evictor(); |
| 793 | 681 | ||
| 794 | fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr); | 682 | fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr); |
| @@ -797,23 +685,23 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb) | |||
| 797 | goto ret_orig; | 685 | goto ret_orig; |
| 798 | } | 686 | } |
| 799 | 687 | ||
| 800 | spin_lock(&fq->lock); | 688 | spin_lock(&fq->q.lock); |
| 801 | 689 | ||
| 802 | if (nf_ct_frag6_queue(fq, clone, fhdr, nhoff) < 0) { | 690 | if (nf_ct_frag6_queue(fq, clone, fhdr, nhoff) < 0) { |
| 803 | spin_unlock(&fq->lock); | 691 | spin_unlock(&fq->q.lock); |
| 804 | pr_debug("Can't insert skb to queue\n"); | 692 | pr_debug("Can't insert skb to queue\n"); |
| 805 | fq_put(fq, NULL); | 693 | fq_put(fq); |
| 806 | goto ret_orig; | 694 | goto ret_orig; |
| 807 | } | 695 | } |
| 808 | 696 | ||
| 809 | if (fq->last_in == (FIRST_IN|LAST_IN) && fq->meat == fq->len) { | 697 | if (fq->q.last_in == (FIRST_IN|LAST_IN) && fq->q.meat == fq->q.len) { |
| 810 | ret_skb = nf_ct_frag6_reasm(fq, dev); | 698 | ret_skb = nf_ct_frag6_reasm(fq, dev); |
| 811 | if (ret_skb == NULL) | 699 | if (ret_skb == NULL) |
| 812 | pr_debug("Can't reassemble fragmented packets\n"); | 700 | pr_debug("Can't reassemble fragmented packets\n"); |
| 813 | } | 701 | } |
| 814 | spin_unlock(&fq->lock); | 702 | spin_unlock(&fq->q.lock); |
| 815 | 703 | ||
| 816 | fq_put(fq, NULL); | 704 | fq_put(fq); |
| 817 | return ret_skb; | 705 | return ret_skb; |
| 818 | 706 | ||
| 819 | ret_orig: | 707 | ret_orig: |
| @@ -859,20 +747,20 @@ int nf_ct_frag6_kfree_frags(struct sk_buff *skb) | |||
| 859 | 747 | ||
| 860 | int nf_ct_frag6_init(void) | 748 | int nf_ct_frag6_init(void) |
| 861 | { | 749 | { |
| 862 | nf_ct_frag6_hash_rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^ | 750 | nf_frags.ctl = &nf_frags_ctl; |
| 863 | (jiffies ^ (jiffies >> 6))); | 751 | nf_frags.hashfn = nf_hashfn; |
| 864 | 752 | nf_frags.destructor = nf_frag_free; | |
| 865 | setup_timer(&nf_ct_frag6_secret_timer, nf_ct_frag6_secret_rebuild, 0); | 753 | nf_frags.skb_free = nf_skb_free; |
| 866 | nf_ct_frag6_secret_timer.expires = jiffies | 754 | nf_frags.qsize = sizeof(struct nf_ct_frag6_queue); |
| 867 | + nf_ct_frag6_secret_interval; | 755 | inet_frags_init(&nf_frags); |
| 868 | add_timer(&nf_ct_frag6_secret_timer); | ||
| 869 | 756 | ||
| 870 | return 0; | 757 | return 0; |
| 871 | } | 758 | } |
| 872 | 759 | ||
| 873 | void nf_ct_frag6_cleanup(void) | 760 | void nf_ct_frag6_cleanup(void) |
| 874 | { | 761 | { |
| 875 | del_timer(&nf_ct_frag6_secret_timer); | 762 | inet_frags_fini(&nf_frags); |
| 876 | nf_ct_frag6_low_thresh = 0; | 763 | |
| 764 | nf_frags_ctl.low_thresh = 0; | ||
| 877 | nf_ct_frag6_evictor(); | 765 | nf_ct_frag6_evictor(); |
| 878 | } | 766 | } |
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index db945018579e..be526ad92543 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c | |||
| @@ -54,7 +54,7 @@ static int sockstat6_seq_show(struct seq_file *seq, void *v) | |||
| 54 | seq_printf(seq, "RAW6: inuse %d\n", | 54 | seq_printf(seq, "RAW6: inuse %d\n", |
| 55 | fold_prot_inuse(&rawv6_prot)); | 55 | fold_prot_inuse(&rawv6_prot)); |
| 56 | seq_printf(seq, "FRAG6: inuse %d memory %d\n", | 56 | seq_printf(seq, "FRAG6: inuse %d memory %d\n", |
| 57 | ip6_frag_nqueues, atomic_read(&ip6_frag_mem)); | 57 | ip6_frag_nqueues(), ip6_frag_mem()); |
| 58 | return 0; | 58 | return 0; |
| 59 | } | 59 | } |
| 60 | 60 | ||
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 31601c993541..6ad19cfc2025 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
| @@ -42,6 +42,7 @@ | |||
| 42 | #include <linux/icmpv6.h> | 42 | #include <linux/icmpv6.h> |
| 43 | #include <linux/random.h> | 43 | #include <linux/random.h> |
| 44 | #include <linux/jhash.h> | 44 | #include <linux/jhash.h> |
| 45 | #include <linux/skbuff.h> | ||
| 45 | 46 | ||
| 46 | #include <net/sock.h> | 47 | #include <net/sock.h> |
| 47 | #include <net/snmp.h> | 48 | #include <net/snmp.h> |
| @@ -53,11 +54,7 @@ | |||
| 53 | #include <net/rawv6.h> | 54 | #include <net/rawv6.h> |
| 54 | #include <net/ndisc.h> | 55 | #include <net/ndisc.h> |
| 55 | #include <net/addrconf.h> | 56 | #include <net/addrconf.h> |
| 56 | 57 | #include <net/inet_frag.h> | |
| 57 | int sysctl_ip6frag_high_thresh __read_mostly = 256*1024; | ||
| 58 | int sysctl_ip6frag_low_thresh __read_mostly = 192*1024; | ||
| 59 | |||
| 60 | int sysctl_ip6frag_time __read_mostly = IPV6_FRAG_TIMEOUT; | ||
| 61 | 58 | ||
| 62 | struct ip6frag_skb_cb | 59 | struct ip6frag_skb_cb |
| 63 | { | 60 | { |
| @@ -74,53 +71,39 @@ struct ip6frag_skb_cb | |||
| 74 | 71 | ||
| 75 | struct frag_queue | 72 | struct frag_queue |
| 76 | { | 73 | { |
| 77 | struct hlist_node list; | 74 | struct inet_frag_queue q; |
| 78 | struct list_head lru_list; /* lru list member */ | ||
| 79 | 75 | ||
| 80 | __be32 id; /* fragment id */ | 76 | __be32 id; /* fragment id */ |
| 81 | struct in6_addr saddr; | 77 | struct in6_addr saddr; |
| 82 | struct in6_addr daddr; | 78 | struct in6_addr daddr; |
| 83 | 79 | ||
| 84 | spinlock_t lock; | ||
| 85 | atomic_t refcnt; | ||
| 86 | struct timer_list timer; /* expire timer */ | ||
| 87 | struct sk_buff *fragments; | ||
| 88 | int len; | ||
| 89 | int meat; | ||
| 90 | int iif; | 80 | int iif; |
| 91 | ktime_t stamp; | ||
| 92 | unsigned int csum; | 81 | unsigned int csum; |
| 93 | __u8 last_in; /* has first/last segment arrived? */ | ||
| 94 | #define COMPLETE 4 | ||
| 95 | #define FIRST_IN 2 | ||
| 96 | #define LAST_IN 1 | ||
| 97 | __u16 nhoffset; | 82 | __u16 nhoffset; |
| 98 | }; | 83 | }; |
| 99 | 84 | ||
| 100 | /* Hash table. */ | 85 | struct inet_frags_ctl ip6_frags_ctl __read_mostly = { |
| 101 | 86 | .high_thresh = 256 * 1024, | |
| 102 | #define IP6Q_HASHSZ 64 | 87 | .low_thresh = 192 * 1024, |
| 88 | .timeout = IPV6_FRAG_TIMEOUT, | ||
| 89 | .secret_interval = 10 * 60 * HZ, | ||
| 90 | }; | ||
| 103 | 91 | ||
| 104 | static struct hlist_head ip6_frag_hash[IP6Q_HASHSZ]; | 92 | static struct inet_frags ip6_frags; |
| 105 | static DEFINE_RWLOCK(ip6_frag_lock); | ||
| 106 | static u32 ip6_frag_hash_rnd; | ||
| 107 | static LIST_HEAD(ip6_frag_lru_list); | ||
| 108 | int ip6_frag_nqueues = 0; | ||
| 109 | 93 | ||
| 110 | static __inline__ void __fq_unlink(struct frag_queue *fq) | 94 | int ip6_frag_nqueues(void) |
| 111 | { | 95 | { |
| 112 | hlist_del(&fq->list); | 96 | return ip6_frags.nqueues; |
| 113 | list_del(&fq->lru_list); | ||
| 114 | ip6_frag_nqueues--; | ||
| 115 | } | 97 | } |
| 116 | 98 | ||
| 117 | static __inline__ void fq_unlink(struct frag_queue *fq) | 99 | int ip6_frag_mem(void) |
| 118 | { | 100 | { |
| 119 | write_lock(&ip6_frag_lock); | 101 | return atomic_read(&ip6_frags.mem); |
| 120 | __fq_unlink(fq); | ||
| 121 | write_unlock(&ip6_frag_lock); | ||
| 122 | } | 102 | } |
| 123 | 103 | ||
| 104 | static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, | ||
| 105 | struct net_device *dev); | ||
| 106 | |||
| 124 | /* | 107 | /* |
| 125 | * callers should be careful not to use the hash value outside the ipfrag_lock | 108 | * callers should be careful not to use the hash value outside the ipfrag_lock |
| 126 | * as doing so could race with ipfrag_hash_rnd being recalculated. | 109 | * as doing so could race with ipfrag_hash_rnd being recalculated. |
| @@ -136,7 +119,7 @@ static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr, | |||
| 136 | 119 | ||
| 137 | a += JHASH_GOLDEN_RATIO; | 120 | a += JHASH_GOLDEN_RATIO; |
| 138 | b += JHASH_GOLDEN_RATIO; | 121 | b += JHASH_GOLDEN_RATIO; |
| 139 | c += ip6_frag_hash_rnd; | 122 | c += ip6_frags.rnd; |
| 140 | __jhash_mix(a, b, c); | 123 | __jhash_mix(a, b, c); |
| 141 | 124 | ||
| 142 | a += (__force u32)saddr->s6_addr32[3]; | 125 | a += (__force u32)saddr->s6_addr32[3]; |
| @@ -149,60 +132,29 @@ static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr, | |||
| 149 | c += (__force u32)id; | 132 | c += (__force u32)id; |
| 150 | __jhash_mix(a, b, c); | 133 | __jhash_mix(a, b, c); |
| 151 | 134 | ||
| 152 | return c & (IP6Q_HASHSZ - 1); | 135 | return c & (INETFRAGS_HASHSZ - 1); |
| 153 | } | 136 | } |
| 154 | 137 | ||
| 155 | static struct timer_list ip6_frag_secret_timer; | 138 | static unsigned int ip6_hashfn(struct inet_frag_queue *q) |
| 156 | int sysctl_ip6frag_secret_interval __read_mostly = 10 * 60 * HZ; | ||
| 157 | |||
| 158 | static void ip6_frag_secret_rebuild(unsigned long dummy) | ||
| 159 | { | 139 | { |
| 160 | unsigned long now = jiffies; | 140 | struct frag_queue *fq; |
| 161 | int i; | ||
| 162 | |||
| 163 | write_lock(&ip6_frag_lock); | ||
| 164 | get_random_bytes(&ip6_frag_hash_rnd, sizeof(u32)); | ||
| 165 | for (i = 0; i < IP6Q_HASHSZ; i++) { | ||
| 166 | struct frag_queue *q; | ||
| 167 | struct hlist_node *p, *n; | ||
| 168 | |||
| 169 | hlist_for_each_entry_safe(q, p, n, &ip6_frag_hash[i], list) { | ||
| 170 | unsigned int hval = ip6qhashfn(q->id, | ||
| 171 | &q->saddr, | ||
| 172 | &q->daddr); | ||
| 173 | |||
| 174 | if (hval != i) { | ||
| 175 | hlist_del(&q->list); | ||
| 176 | |||
| 177 | /* Relink to new hash chain. */ | ||
| 178 | hlist_add_head(&q->list, | ||
| 179 | &ip6_frag_hash[hval]); | ||
| 180 | |||
| 181 | } | ||
| 182 | } | ||
| 183 | } | ||
| 184 | write_unlock(&ip6_frag_lock); | ||
| 185 | 141 | ||
| 186 | mod_timer(&ip6_frag_secret_timer, now + sysctl_ip6frag_secret_interval); | 142 | fq = container_of(q, struct frag_queue, q); |
| 143 | return ip6qhashfn(fq->id, &fq->saddr, &fq->daddr); | ||
| 187 | } | 144 | } |
| 188 | 145 | ||
| 189 | atomic_t ip6_frag_mem = ATOMIC_INIT(0); | ||
| 190 | |||
| 191 | /* Memory Tracking Functions. */ | 146 | /* Memory Tracking Functions. */ |
| 192 | static inline void frag_kfree_skb(struct sk_buff *skb, int *work) | 147 | static inline void frag_kfree_skb(struct sk_buff *skb, int *work) |
| 193 | { | 148 | { |
| 194 | if (work) | 149 | if (work) |
| 195 | *work -= skb->truesize; | 150 | *work -= skb->truesize; |
| 196 | atomic_sub(skb->truesize, &ip6_frag_mem); | 151 | atomic_sub(skb->truesize, &ip6_frags.mem); |
| 197 | kfree_skb(skb); | 152 | kfree_skb(skb); |
| 198 | } | 153 | } |
| 199 | 154 | ||
| 200 | static inline void frag_free_queue(struct frag_queue *fq, int *work) | 155 | static void ip6_frag_free(struct inet_frag_queue *fq) |
| 201 | { | 156 | { |
| 202 | if (work) | 157 | kfree(container_of(fq, struct frag_queue, q)); |
| 203 | *work -= sizeof(struct frag_queue); | ||
| 204 | atomic_sub(sizeof(struct frag_queue), &ip6_frag_mem); | ||
| 205 | kfree(fq); | ||
| 206 | } | 158 | } |
| 207 | 159 | ||
| 208 | static inline struct frag_queue *frag_alloc_queue(void) | 160 | static inline struct frag_queue *frag_alloc_queue(void) |
| @@ -211,36 +163,15 @@ static inline struct frag_queue *frag_alloc_queue(void) | |||
| 211 | 163 | ||
| 212 | if(!fq) | 164 | if(!fq) |
| 213 | return NULL; | 165 | return NULL; |
| 214 | atomic_add(sizeof(struct frag_queue), &ip6_frag_mem); | 166 | atomic_add(sizeof(struct frag_queue), &ip6_frags.mem); |
| 215 | return fq; | 167 | return fq; |
| 216 | } | 168 | } |
| 217 | 169 | ||
| 218 | /* Destruction primitives. */ | 170 | /* Destruction primitives. */ |
| 219 | 171 | ||
| 220 | /* Complete destruction of fq. */ | 172 | static __inline__ void fq_put(struct frag_queue *fq) |
| 221 | static void ip6_frag_destroy(struct frag_queue *fq, int *work) | ||
| 222 | { | ||
| 223 | struct sk_buff *fp; | ||
| 224 | |||
| 225 | BUG_TRAP(fq->last_in&COMPLETE); | ||
| 226 | BUG_TRAP(del_timer(&fq->timer) == 0); | ||
| 227 | |||
| 228 | /* Release all fragment data. */ | ||
| 229 | fp = fq->fragments; | ||
| 230 | while (fp) { | ||
| 231 | struct sk_buff *xp = fp->next; | ||
| 232 | |||
| 233 | frag_kfree_skb(fp, work); | ||
| 234 | fp = xp; | ||
| 235 | } | ||
| 236 | |||
| 237 | frag_free_queue(fq, work); | ||
| 238 | } | ||
| 239 | |||
| 240 | static __inline__ void fq_put(struct frag_queue *fq, int *work) | ||
| 241 | { | 173 | { |
| 242 | if (atomic_dec_and_test(&fq->refcnt)) | 174 | inet_frag_put(&fq->q, &ip6_frags); |
| 243 | ip6_frag_destroy(fq, work); | ||
| 244 | } | 175 | } |
| 245 | 176 | ||
| 246 | /* Kill fq entry. It is not destroyed immediately, | 177 | /* Kill fq entry. It is not destroyed immediately, |
| @@ -248,45 +179,16 @@ static __inline__ void fq_put(struct frag_queue *fq, int *work) | |||
| 248 | */ | 179 | */ |
| 249 | static __inline__ void fq_kill(struct frag_queue *fq) | 180 | static __inline__ void fq_kill(struct frag_queue *fq) |
| 250 | { | 181 | { |
| 251 | if (del_timer(&fq->timer)) | 182 | inet_frag_kill(&fq->q, &ip6_frags); |
| 252 | atomic_dec(&fq->refcnt); | ||
| 253 | |||
| 254 | if (!(fq->last_in & COMPLETE)) { | ||
| 255 | fq_unlink(fq); | ||
| 256 | atomic_dec(&fq->refcnt); | ||
| 257 | fq->last_in |= COMPLETE; | ||
| 258 | } | ||
| 259 | } | 183 | } |
| 260 | 184 | ||
| 261 | static void ip6_evictor(struct inet6_dev *idev) | 185 | static void ip6_evictor(struct inet6_dev *idev) |
| 262 | { | 186 | { |
| 263 | struct frag_queue *fq; | 187 | int evicted; |
| 264 | struct list_head *tmp; | 188 | |
| 265 | int work; | 189 | evicted = inet_frag_evictor(&ip6_frags); |
| 266 | 190 | if (evicted) | |
| 267 | work = atomic_read(&ip6_frag_mem) - sysctl_ip6frag_low_thresh; | 191 | IP6_ADD_STATS_BH(idev, IPSTATS_MIB_REASMFAILS, evicted); |
| 268 | if (work <= 0) | ||
| 269 | return; | ||
| 270 | |||
| 271 | while(work > 0) { | ||
| 272 | read_lock(&ip6_frag_lock); | ||
| 273 | if (list_empty(&ip6_frag_lru_list)) { | ||
| 274 | read_unlock(&ip6_frag_lock); | ||
| 275 | return; | ||
| 276 | } | ||
| 277 | tmp = ip6_frag_lru_list.next; | ||
| 278 | fq = list_entry(tmp, struct frag_queue, lru_list); | ||
| 279 | atomic_inc(&fq->refcnt); | ||
| 280 | read_unlock(&ip6_frag_lock); | ||
| 281 | |||
| 282 | spin_lock(&fq->lock); | ||
| 283 | if (!(fq->last_in&COMPLETE)) | ||
| 284 | fq_kill(fq); | ||
| 285 | spin_unlock(&fq->lock); | ||
| 286 | |||
| 287 | fq_put(fq, &work); | ||
| 288 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_REASMFAILS); | ||
| 289 | } | ||
| 290 | } | 192 | } |
| 291 | 193 | ||
| 292 | static void ip6_frag_expire(unsigned long data) | 194 | static void ip6_frag_expire(unsigned long data) |
| @@ -294,9 +196,9 @@ static void ip6_frag_expire(unsigned long data) | |||
| 294 | struct frag_queue *fq = (struct frag_queue *) data; | 196 | struct frag_queue *fq = (struct frag_queue *) data; |
| 295 | struct net_device *dev = NULL; | 197 | struct net_device *dev = NULL; |
| 296 | 198 | ||
| 297 | spin_lock(&fq->lock); | 199 | spin_lock(&fq->q.lock); |
| 298 | 200 | ||
| 299 | if (fq->last_in & COMPLETE) | 201 | if (fq->q.last_in & COMPLETE) |
| 300 | goto out; | 202 | goto out; |
| 301 | 203 | ||
| 302 | fq_kill(fq); | 204 | fq_kill(fq); |
| @@ -311,7 +213,7 @@ static void ip6_frag_expire(unsigned long data) | |||
| 311 | rcu_read_unlock(); | 213 | rcu_read_unlock(); |
| 312 | 214 | ||
| 313 | /* Don't send error if the first segment did not arrive. */ | 215 | /* Don't send error if the first segment did not arrive. */ |
| 314 | if (!(fq->last_in&FIRST_IN) || !fq->fragments) | 216 | if (!(fq->q.last_in&FIRST_IN) || !fq->q.fragments) |
| 315 | goto out; | 217 | goto out; |
| 316 | 218 | ||
| 317 | /* | 219 | /* |
| @@ -319,13 +221,13 @@ static void ip6_frag_expire(unsigned long data) | |||
| 319 | segment was received. And do not use fq->dev | 221 | segment was received. And do not use fq->dev |
| 320 | pointer directly, device might already disappeared. | 222 | pointer directly, device might already disappeared. |
| 321 | */ | 223 | */ |
| 322 | fq->fragments->dev = dev; | 224 | fq->q.fragments->dev = dev; |
| 323 | icmpv6_send(fq->fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0, dev); | 225 | icmpv6_send(fq->q.fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0, dev); |
| 324 | out: | 226 | out: |
| 325 | if (dev) | 227 | if (dev) |
| 326 | dev_put(dev); | 228 | dev_put(dev); |
| 327 | spin_unlock(&fq->lock); | 229 | spin_unlock(&fq->q.lock); |
| 328 | fq_put(fq, NULL); | 230 | fq_put(fq); |
| 329 | } | 231 | } |
| 330 | 232 | ||
| 331 | /* Creation primitives. */ | 233 | /* Creation primitives. */ |
| @@ -339,32 +241,32 @@ static struct frag_queue *ip6_frag_intern(struct frag_queue *fq_in) | |||
| 339 | struct hlist_node *n; | 241 | struct hlist_node *n; |
| 340 | #endif | 242 | #endif |
| 341 | 243 | ||
| 342 | write_lock(&ip6_frag_lock); | 244 | write_lock(&ip6_frags.lock); |
| 343 | hash = ip6qhashfn(fq_in->id, &fq_in->saddr, &fq_in->daddr); | 245 | hash = ip6qhashfn(fq_in->id, &fq_in->saddr, &fq_in->daddr); |
| 344 | #ifdef CONFIG_SMP | 246 | #ifdef CONFIG_SMP |
| 345 | hlist_for_each_entry(fq, n, &ip6_frag_hash[hash], list) { | 247 | hlist_for_each_entry(fq, n, &ip6_frags.hash[hash], q.list) { |
| 346 | if (fq->id == fq_in->id && | 248 | if (fq->id == fq_in->id && |
| 347 | ipv6_addr_equal(&fq_in->saddr, &fq->saddr) && | 249 | ipv6_addr_equal(&fq_in->saddr, &fq->saddr) && |
| 348 | ipv6_addr_equal(&fq_in->daddr, &fq->daddr)) { | 250 | ipv6_addr_equal(&fq_in->daddr, &fq->daddr)) { |
| 349 | atomic_inc(&fq->refcnt); | 251 | atomic_inc(&fq->q.refcnt); |
| 350 | write_unlock(&ip6_frag_lock); | 252 | write_unlock(&ip6_frags.lock); |
| 351 | fq_in->last_in |= COMPLETE; | 253 | fq_in->q.last_in |= COMPLETE; |
| 352 | fq_put(fq_in, NULL); | 254 | fq_put(fq_in); |
| 353 | return fq; | 255 | return fq; |
| 354 | } | 256 | } |
| 355 | } | 257 | } |
| 356 | #endif | 258 | #endif |
| 357 | fq = fq_in; | 259 | fq = fq_in; |
| 358 | 260 | ||
| 359 | if (!mod_timer(&fq->timer, jiffies + sysctl_ip6frag_time)) | 261 | if (!mod_timer(&fq->q.timer, jiffies + ip6_frags_ctl.timeout)) |
| 360 | atomic_inc(&fq->refcnt); | 262 | atomic_inc(&fq->q.refcnt); |
| 361 | 263 | ||
| 362 | atomic_inc(&fq->refcnt); | 264 | atomic_inc(&fq->q.refcnt); |
| 363 | hlist_add_head(&fq->list, &ip6_frag_hash[hash]); | 265 | hlist_add_head(&fq->q.list, &ip6_frags.hash[hash]); |
| 364 | INIT_LIST_HEAD(&fq->lru_list); | 266 | INIT_LIST_HEAD(&fq->q.lru_list); |
| 365 | list_add_tail(&fq->lru_list, &ip6_frag_lru_list); | 267 | list_add_tail(&fq->q.lru_list, &ip6_frags.lru_list); |
| 366 | ip6_frag_nqueues++; | 268 | ip6_frags.nqueues++; |
| 367 | write_unlock(&ip6_frag_lock); | 269 | write_unlock(&ip6_frags.lock); |
| 368 | return fq; | 270 | return fq; |
| 369 | } | 271 | } |
| 370 | 272 | ||
| @@ -382,11 +284,11 @@ ip6_frag_create(__be32 id, struct in6_addr *src, struct in6_addr *dst, | |||
| 382 | ipv6_addr_copy(&fq->saddr, src); | 284 | ipv6_addr_copy(&fq->saddr, src); |
| 383 | ipv6_addr_copy(&fq->daddr, dst); | 285 | ipv6_addr_copy(&fq->daddr, dst); |
| 384 | 286 | ||
| 385 | init_timer(&fq->timer); | 287 | init_timer(&fq->q.timer); |
| 386 | fq->timer.function = ip6_frag_expire; | 288 | fq->q.timer.function = ip6_frag_expire; |
| 387 | fq->timer.data = (long) fq; | 289 | fq->q.timer.data = (long) fq; |
| 388 | spin_lock_init(&fq->lock); | 290 | spin_lock_init(&fq->q.lock); |
| 389 | atomic_set(&fq->refcnt, 1); | 291 | atomic_set(&fq->q.refcnt, 1); |
| 390 | 292 | ||
| 391 | return ip6_frag_intern(fq); | 293 | return ip6_frag_intern(fq); |
| 392 | 294 | ||
| @@ -403,30 +305,31 @@ fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst, | |||
| 403 | struct hlist_node *n; | 305 | struct hlist_node *n; |
| 404 | unsigned int hash; | 306 | unsigned int hash; |
| 405 | 307 | ||
| 406 | read_lock(&ip6_frag_lock); | 308 | read_lock(&ip6_frags.lock); |
| 407 | hash = ip6qhashfn(id, src, dst); | 309 | hash = ip6qhashfn(id, src, dst); |
| 408 | hlist_for_each_entry(fq, n, &ip6_frag_hash[hash], list) { | 310 | hlist_for_each_entry(fq, n, &ip6_frags.hash[hash], q.list) { |
| 409 | if (fq->id == id && | 311 | if (fq->id == id && |
| 410 | ipv6_addr_equal(src, &fq->saddr) && | 312 | ipv6_addr_equal(src, &fq->saddr) && |
| 411 | ipv6_addr_equal(dst, &fq->daddr)) { | 313 | ipv6_addr_equal(dst, &fq->daddr)) { |
| 412 | atomic_inc(&fq->refcnt); | 314 | atomic_inc(&fq->q.refcnt); |
| 413 | read_unlock(&ip6_frag_lock); | 315 | read_unlock(&ip6_frags.lock); |
| 414 | return fq; | 316 | return fq; |
| 415 | } | 317 | } |
| 416 | } | 318 | } |
| 417 | read_unlock(&ip6_frag_lock); | 319 | read_unlock(&ip6_frags.lock); |
| 418 | 320 | ||
| 419 | return ip6_frag_create(id, src, dst, idev); | 321 | return ip6_frag_create(id, src, dst, idev); |
| 420 | } | 322 | } |
| 421 | 323 | ||
| 422 | 324 | ||
| 423 | static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | 325 | static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, |
| 424 | struct frag_hdr *fhdr, int nhoff) | 326 | struct frag_hdr *fhdr, int nhoff) |
| 425 | { | 327 | { |
| 426 | struct sk_buff *prev, *next; | 328 | struct sk_buff *prev, *next; |
| 329 | struct net_device *dev; | ||
| 427 | int offset, end; | 330 | int offset, end; |
| 428 | 331 | ||
| 429 | if (fq->last_in & COMPLETE) | 332 | if (fq->q.last_in & COMPLETE) |
| 430 | goto err; | 333 | goto err; |
| 431 | 334 | ||
| 432 | offset = ntohs(fhdr->frag_off) & ~0x7; | 335 | offset = ntohs(fhdr->frag_off) & ~0x7; |
| @@ -439,7 +342,7 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
| 439 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, | 342 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, |
| 440 | ((u8 *)&fhdr->frag_off - | 343 | ((u8 *)&fhdr->frag_off - |
| 441 | skb_network_header(skb))); | 344 | skb_network_header(skb))); |
| 442 | return; | 345 | return -1; |
| 443 | } | 346 | } |
| 444 | 347 | ||
| 445 | if (skb->ip_summed == CHECKSUM_COMPLETE) { | 348 | if (skb->ip_summed == CHECKSUM_COMPLETE) { |
| @@ -454,11 +357,11 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
| 454 | /* If we already have some bits beyond end | 357 | /* If we already have some bits beyond end |
| 455 | * or have different end, the segment is corrupted. | 358 | * or have different end, the segment is corrupted. |
| 456 | */ | 359 | */ |
| 457 | if (end < fq->len || | 360 | if (end < fq->q.len || |
| 458 | ((fq->last_in & LAST_IN) && end != fq->len)) | 361 | ((fq->q.last_in & LAST_IN) && end != fq->q.len)) |
| 459 | goto err; | 362 | goto err; |
| 460 | fq->last_in |= LAST_IN; | 363 | fq->q.last_in |= LAST_IN; |
| 461 | fq->len = end; | 364 | fq->q.len = end; |
| 462 | } else { | 365 | } else { |
| 463 | /* Check if the fragment is rounded to 8 bytes. | 366 | /* Check if the fragment is rounded to 8 bytes. |
| 464 | * Required by the RFC. | 367 | * Required by the RFC. |
| @@ -471,13 +374,13 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
| 471 | IPSTATS_MIB_INHDRERRORS); | 374 | IPSTATS_MIB_INHDRERRORS); |
| 472 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, | 375 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, |
| 473 | offsetof(struct ipv6hdr, payload_len)); | 376 | offsetof(struct ipv6hdr, payload_len)); |
| 474 | return; | 377 | return -1; |
| 475 | } | 378 | } |
| 476 | if (end > fq->len) { | 379 | if (end > fq->q.len) { |
| 477 | /* Some bits beyond end -> corruption. */ | 380 | /* Some bits beyond end -> corruption. */ |
| 478 | if (fq->last_in & LAST_IN) | 381 | if (fq->q.last_in & LAST_IN) |
| 479 | goto err; | 382 | goto err; |
| 480 | fq->len = end; | 383 | fq->q.len = end; |
| 481 | } | 384 | } |
| 482 | } | 385 | } |
| 483 | 386 | ||
| @@ -496,7 +399,7 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
| 496 | * this fragment, right? | 399 | * this fragment, right? |
| 497 | */ | 400 | */ |
| 498 | prev = NULL; | 401 | prev = NULL; |
| 499 | for(next = fq->fragments; next != NULL; next = next->next) { | 402 | for(next = fq->q.fragments; next != NULL; next = next->next) { |
| 500 | if (FRAG6_CB(next)->offset >= offset) | 403 | if (FRAG6_CB(next)->offset >= offset) |
| 501 | break; /* bingo! */ | 404 | break; /* bingo! */ |
| 502 | prev = next; | 405 | prev = next; |
| @@ -533,7 +436,7 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
| 533 | if (!pskb_pull(next, i)) | 436 | if (!pskb_pull(next, i)) |
| 534 | goto err; | 437 | goto err; |
| 535 | FRAG6_CB(next)->offset += i; /* next fragment */ | 438 | FRAG6_CB(next)->offset += i; /* next fragment */ |
| 536 | fq->meat -= i; | 439 | fq->q.meat -= i; |
| 537 | if (next->ip_summed != CHECKSUM_UNNECESSARY) | 440 | if (next->ip_summed != CHECKSUM_UNNECESSARY) |
| 538 | next->ip_summed = CHECKSUM_NONE; | 441 | next->ip_summed = CHECKSUM_NONE; |
| 539 | break; | 442 | break; |
| @@ -548,9 +451,9 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
| 548 | if (prev) | 451 | if (prev) |
| 549 | prev->next = next; | 452 | prev->next = next; |
| 550 | else | 453 | else |
| 551 | fq->fragments = next; | 454 | fq->q.fragments = next; |
| 552 | 455 | ||
| 553 | fq->meat -= free_it->len; | 456 | fq->q.meat -= free_it->len; |
| 554 | frag_kfree_skb(free_it, NULL); | 457 | frag_kfree_skb(free_it, NULL); |
| 555 | } | 458 | } |
| 556 | } | 459 | } |
| @@ -562,30 +465,37 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
| 562 | if (prev) | 465 | if (prev) |
| 563 | prev->next = skb; | 466 | prev->next = skb; |
| 564 | else | 467 | else |
| 565 | fq->fragments = skb; | 468 | fq->q.fragments = skb; |
| 566 | 469 | ||
| 567 | if (skb->dev) | 470 | dev = skb->dev; |
| 568 | fq->iif = skb->dev->ifindex; | 471 | if (dev) { |
| 569 | skb->dev = NULL; | 472 | fq->iif = dev->ifindex; |
| 570 | fq->stamp = skb->tstamp; | 473 | skb->dev = NULL; |
| 571 | fq->meat += skb->len; | 474 | } |
| 572 | atomic_add(skb->truesize, &ip6_frag_mem); | 475 | fq->q.stamp = skb->tstamp; |
| 476 | fq->q.meat += skb->len; | ||
| 477 | atomic_add(skb->truesize, &ip6_frags.mem); | ||
| 573 | 478 | ||
| 574 | /* The first fragment. | 479 | /* The first fragment. |
| 575 | * nhoffset is obtained from the first fragment, of course. | 480 | * nhoffset is obtained from the first fragment, of course. |
| 576 | */ | 481 | */ |
| 577 | if (offset == 0) { | 482 | if (offset == 0) { |
| 578 | fq->nhoffset = nhoff; | 483 | fq->nhoffset = nhoff; |
| 579 | fq->last_in |= FIRST_IN; | 484 | fq->q.last_in |= FIRST_IN; |
| 580 | } | 485 | } |
| 581 | write_lock(&ip6_frag_lock); | 486 | |
| 582 | list_move_tail(&fq->lru_list, &ip6_frag_lru_list); | 487 | if (fq->q.last_in == (FIRST_IN | LAST_IN) && fq->q.meat == fq->q.len) |
| 583 | write_unlock(&ip6_frag_lock); | 488 | return ip6_frag_reasm(fq, prev, dev); |
| 584 | return; | 489 | |
| 490 | write_lock(&ip6_frags.lock); | ||
| 491 | list_move_tail(&fq->q.lru_list, &ip6_frags.lru_list); | ||
| 492 | write_unlock(&ip6_frags.lock); | ||
| 493 | return -1; | ||
| 585 | 494 | ||
| 586 | err: | 495 | err: |
| 587 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMFAILS); | 496 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMFAILS); |
| 588 | kfree_skb(skb); | 497 | kfree_skb(skb); |
| 498 | return -1; | ||
| 589 | } | 499 | } |
| 590 | 500 | ||
| 591 | /* | 501 | /* |
| @@ -597,21 +507,39 @@ err: | |||
| 597 | * queue is eligible for reassembly i.e. it is not COMPLETE, | 507 | * queue is eligible for reassembly i.e. it is not COMPLETE, |
| 598 | * the last and the first frames arrived and all the bits are here. | 508 | * the last and the first frames arrived and all the bits are here. |
| 599 | */ | 509 | */ |
| 600 | static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, | 510 | static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, |
| 601 | struct net_device *dev) | 511 | struct net_device *dev) |
| 602 | { | 512 | { |
| 603 | struct sk_buff *fp, *head = fq->fragments; | 513 | struct sk_buff *fp, *head = fq->q.fragments; |
| 604 | int payload_len; | 514 | int payload_len; |
| 605 | unsigned int nhoff; | 515 | unsigned int nhoff; |
| 606 | 516 | ||
| 607 | fq_kill(fq); | 517 | fq_kill(fq); |
| 608 | 518 | ||
| 519 | /* Make the one we just received the head. */ | ||
| 520 | if (prev) { | ||
| 521 | head = prev->next; | ||
| 522 | fp = skb_clone(head, GFP_ATOMIC); | ||
| 523 | |||
| 524 | if (!fp) | ||
| 525 | goto out_oom; | ||
| 526 | |||
| 527 | fp->next = head->next; | ||
| 528 | prev->next = fp; | ||
| 529 | |||
| 530 | skb_morph(head, fq->q.fragments); | ||
| 531 | head->next = fq->q.fragments->next; | ||
| 532 | |||
| 533 | kfree_skb(fq->q.fragments); | ||
| 534 | fq->q.fragments = head; | ||
| 535 | } | ||
| 536 | |||
| 609 | BUG_TRAP(head != NULL); | 537 | BUG_TRAP(head != NULL); |
| 610 | BUG_TRAP(FRAG6_CB(head)->offset == 0); | 538 | BUG_TRAP(FRAG6_CB(head)->offset == 0); |
| 611 | 539 | ||
| 612 | /* Unfragmented part is taken from the first segment. */ | 540 | /* Unfragmented part is taken from the first segment. */ |
| 613 | payload_len = ((head->data - skb_network_header(head)) - | 541 | payload_len = ((head->data - skb_network_header(head)) - |
| 614 | sizeof(struct ipv6hdr) + fq->len - | 542 | sizeof(struct ipv6hdr) + fq->q.len - |
| 615 | sizeof(struct frag_hdr)); | 543 | sizeof(struct frag_hdr)); |
| 616 | if (payload_len > IPV6_MAXPLEN) | 544 | if (payload_len > IPV6_MAXPLEN) |
| 617 | goto out_oversize; | 545 | goto out_oversize; |
| @@ -640,7 +568,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, | |||
| 640 | head->len -= clone->len; | 568 | head->len -= clone->len; |
| 641 | clone->csum = 0; | 569 | clone->csum = 0; |
| 642 | clone->ip_summed = head->ip_summed; | 570 | clone->ip_summed = head->ip_summed; |
| 643 | atomic_add(clone->truesize, &ip6_frag_mem); | 571 | atomic_add(clone->truesize, &ip6_frags.mem); |
| 644 | } | 572 | } |
| 645 | 573 | ||
| 646 | /* We have to remove fragment header from datagram and to relocate | 574 | /* We have to remove fragment header from datagram and to relocate |
| @@ -655,7 +583,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, | |||
| 655 | skb_shinfo(head)->frag_list = head->next; | 583 | skb_shinfo(head)->frag_list = head->next; |
| 656 | skb_reset_transport_header(head); | 584 | skb_reset_transport_header(head); |
| 657 | skb_push(head, head->data - skb_network_header(head)); | 585 | skb_push(head, head->data - skb_network_header(head)); |
| 658 | atomic_sub(head->truesize, &ip6_frag_mem); | 586 | atomic_sub(head->truesize, &ip6_frags.mem); |
| 659 | 587 | ||
| 660 | for (fp=head->next; fp; fp = fp->next) { | 588 | for (fp=head->next; fp; fp = fp->next) { |
| 661 | head->data_len += fp->len; | 589 | head->data_len += fp->len; |
| @@ -665,17 +593,15 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, | |||
| 665 | else if (head->ip_summed == CHECKSUM_COMPLETE) | 593 | else if (head->ip_summed == CHECKSUM_COMPLETE) |
| 666 | head->csum = csum_add(head->csum, fp->csum); | 594 | head->csum = csum_add(head->csum, fp->csum); |
| 667 | head->truesize += fp->truesize; | 595 | head->truesize += fp->truesize; |
| 668 | atomic_sub(fp->truesize, &ip6_frag_mem); | 596 | atomic_sub(fp->truesize, &ip6_frags.mem); |
| 669 | } | 597 | } |
| 670 | 598 | ||
| 671 | head->next = NULL; | 599 | head->next = NULL; |
| 672 | head->dev = dev; | 600 | head->dev = dev; |
| 673 | head->tstamp = fq->stamp; | 601 | head->tstamp = fq->q.stamp; |
| 674 | ipv6_hdr(head)->payload_len = htons(payload_len); | 602 | ipv6_hdr(head)->payload_len = htons(payload_len); |
| 675 | IP6CB(head)->nhoff = nhoff; | 603 | IP6CB(head)->nhoff = nhoff; |
| 676 | 604 | ||
| 677 | *skb_in = head; | ||
| 678 | |||
| 679 | /* Yes, and fold redundant checksum back. 8) */ | 605 | /* Yes, and fold redundant checksum back. 8) */ |
| 680 | if (head->ip_summed == CHECKSUM_COMPLETE) | 606 | if (head->ip_summed == CHECKSUM_COMPLETE) |
| 681 | head->csum = csum_partial(skb_network_header(head), | 607 | head->csum = csum_partial(skb_network_header(head), |
| @@ -685,7 +611,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, | |||
| 685 | rcu_read_lock(); | 611 | rcu_read_lock(); |
| 686 | IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMOKS); | 612 | IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMOKS); |
| 687 | rcu_read_unlock(); | 613 | rcu_read_unlock(); |
| 688 | fq->fragments = NULL; | 614 | fq->q.fragments = NULL; |
| 689 | return 1; | 615 | return 1; |
| 690 | 616 | ||
| 691 | out_oversize: | 617 | out_oversize: |
| @@ -702,10 +628,8 @@ out_fail: | |||
| 702 | return -1; | 628 | return -1; |
| 703 | } | 629 | } |
| 704 | 630 | ||
| 705 | static int ipv6_frag_rcv(struct sk_buff **skbp) | 631 | static int ipv6_frag_rcv(struct sk_buff *skb) |
| 706 | { | 632 | { |
| 707 | struct sk_buff *skb = *skbp; | ||
| 708 | struct net_device *dev = skb->dev; | ||
| 709 | struct frag_hdr *fhdr; | 633 | struct frag_hdr *fhdr; |
| 710 | struct frag_queue *fq; | 634 | struct frag_queue *fq; |
| 711 | struct ipv6hdr *hdr = ipv6_hdr(skb); | 635 | struct ipv6hdr *hdr = ipv6_hdr(skb); |
| @@ -739,23 +663,19 @@ static int ipv6_frag_rcv(struct sk_buff **skbp) | |||
| 739 | return 1; | 663 | return 1; |
| 740 | } | 664 | } |
| 741 | 665 | ||
| 742 | if (atomic_read(&ip6_frag_mem) > sysctl_ip6frag_high_thresh) | 666 | if (atomic_read(&ip6_frags.mem) > ip6_frags_ctl.high_thresh) |
| 743 | ip6_evictor(ip6_dst_idev(skb->dst)); | 667 | ip6_evictor(ip6_dst_idev(skb->dst)); |
| 744 | 668 | ||
| 745 | if ((fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr, | 669 | if ((fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr, |
| 746 | ip6_dst_idev(skb->dst))) != NULL) { | 670 | ip6_dst_idev(skb->dst))) != NULL) { |
| 747 | int ret = -1; | 671 | int ret; |
| 748 | 672 | ||
| 749 | spin_lock(&fq->lock); | 673 | spin_lock(&fq->q.lock); |
| 750 | 674 | ||
| 751 | ip6_frag_queue(fq, skb, fhdr, IP6CB(skb)->nhoff); | 675 | ret = ip6_frag_queue(fq, skb, fhdr, IP6CB(skb)->nhoff); |
| 752 | 676 | ||
| 753 | if (fq->last_in == (FIRST_IN|LAST_IN) && | 677 | spin_unlock(&fq->q.lock); |
| 754 | fq->meat == fq->len) | 678 | fq_put(fq); |
| 755 | ret = ip6_frag_reasm(fq, skbp, dev); | ||
| 756 | |||
| 757 | spin_unlock(&fq->lock); | ||
| 758 | fq_put(fq, NULL); | ||
| 759 | return ret; | 679 | return ret; |
| 760 | } | 680 | } |
| 761 | 681 | ||
| @@ -775,11 +695,10 @@ void __init ipv6_frag_init(void) | |||
| 775 | if (inet6_add_protocol(&frag_protocol, IPPROTO_FRAGMENT) < 0) | 695 | if (inet6_add_protocol(&frag_protocol, IPPROTO_FRAGMENT) < 0) |
| 776 | printk(KERN_ERR "ipv6_frag_init: Could not register protocol\n"); | 696 | printk(KERN_ERR "ipv6_frag_init: Could not register protocol\n"); |
| 777 | 697 | ||
| 778 | ip6_frag_hash_rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^ | 698 | ip6_frags.ctl = &ip6_frags_ctl; |
| 779 | (jiffies ^ (jiffies >> 6))); | 699 | ip6_frags.hashfn = ip6_hashfn; |
| 780 | 700 | ip6_frags.destructor = ip6_frag_free; | |
| 781 | init_timer(&ip6_frag_secret_timer); | 701 | ip6_frags.skb_free = NULL; |
| 782 | ip6_frag_secret_timer.function = ip6_frag_secret_rebuild; | 702 | ip6_frags.qsize = sizeof(struct frag_queue); |
| 783 | ip6_frag_secret_timer.expires = jiffies + sysctl_ip6frag_secret_interval; | 703 | inet_frags_init(&ip6_frags); |
| 784 | add_timer(&ip6_frag_secret_timer); | ||
| 785 | } | 704 | } |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 6ff19f9eb9ee..cce9941c11c6 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
| @@ -663,7 +663,7 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *d | |||
| 663 | return rt; | 663 | return rt; |
| 664 | } | 664 | } |
| 665 | 665 | ||
| 666 | static struct rt6_info *ip6_pol_route_input(struct fib6_table *table, | 666 | static struct rt6_info *ip6_pol_route(struct fib6_table *table, int oif, |
| 667 | struct flowi *fl, int flags) | 667 | struct flowi *fl, int flags) |
| 668 | { | 668 | { |
| 669 | struct fib6_node *fn; | 669 | struct fib6_node *fn; |
| @@ -682,7 +682,7 @@ restart_2: | |||
| 682 | fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); | 682 | fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); |
| 683 | 683 | ||
| 684 | restart: | 684 | restart: |
| 685 | rt = rt6_select(fn, fl->iif, strict | reachable); | 685 | rt = rt6_select(fn, oif, strict | reachable); |
| 686 | BACKTRACK(&fl->fl6_src); | 686 | BACKTRACK(&fl->fl6_src); |
| 687 | if (rt == &ip6_null_entry || | 687 | if (rt == &ip6_null_entry || |
| 688 | rt->rt6i_flags & RTF_CACHE) | 688 | rt->rt6i_flags & RTF_CACHE) |
| @@ -735,6 +735,12 @@ out2: | |||
| 735 | return rt; | 735 | return rt; |
| 736 | } | 736 | } |
| 737 | 737 | ||
| 738 | static struct rt6_info *ip6_pol_route_input(struct fib6_table *table, | ||
| 739 | struct flowi *fl, int flags) | ||
| 740 | { | ||
| 741 | return ip6_pol_route(table, fl->iif, fl, flags); | ||
| 742 | } | ||
| 743 | |||
| 738 | void ip6_route_input(struct sk_buff *skb) | 744 | void ip6_route_input(struct sk_buff *skb) |
| 739 | { | 745 | { |
| 740 | struct ipv6hdr *iph = ipv6_hdr(skb); | 746 | struct ipv6hdr *iph = ipv6_hdr(skb); |
| @@ -761,72 +767,7 @@ void ip6_route_input(struct sk_buff *skb) | |||
| 761 | static struct rt6_info *ip6_pol_route_output(struct fib6_table *table, | 767 | static struct rt6_info *ip6_pol_route_output(struct fib6_table *table, |
| 762 | struct flowi *fl, int flags) | 768 | struct flowi *fl, int flags) |
| 763 | { | 769 | { |
| 764 | struct fib6_node *fn; | 770 | return ip6_pol_route(table, fl->oif, fl, flags); |
| 765 | struct rt6_info *rt, *nrt; | ||
| 766 | int strict = 0; | ||
| 767 | int attempts = 3; | ||
| 768 | int err; | ||
| 769 | int reachable = ipv6_devconf.forwarding ? 0 : RT6_LOOKUP_F_REACHABLE; | ||
| 770 | |||
| 771 | strict |= flags & RT6_LOOKUP_F_IFACE; | ||
| 772 | |||
| 773 | relookup: | ||
| 774 | read_lock_bh(&table->tb6_lock); | ||
| 775 | |||
| 776 | restart_2: | ||
| 777 | fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); | ||
| 778 | |||
| 779 | restart: | ||
| 780 | rt = rt6_select(fn, fl->oif, strict | reachable); | ||
| 781 | BACKTRACK(&fl->fl6_src); | ||
| 782 | if (rt == &ip6_null_entry || | ||
| 783 | rt->rt6i_flags & RTF_CACHE) | ||
| 784 | goto out; | ||
| 785 | |||
| 786 | dst_hold(&rt->u.dst); | ||
| 787 | read_unlock_bh(&table->tb6_lock); | ||
| 788 | |||
| 789 | if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) | ||
| 790 | nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src); | ||
| 791 | else { | ||
| 792 | #if CLONE_OFFLINK_ROUTE | ||
| 793 | nrt = rt6_alloc_clone(rt, &fl->fl6_dst); | ||
| 794 | #else | ||
| 795 | goto out2; | ||
| 796 | #endif | ||
| 797 | } | ||
| 798 | |||
| 799 | dst_release(&rt->u.dst); | ||
| 800 | rt = nrt ? : &ip6_null_entry; | ||
| 801 | |||
| 802 | dst_hold(&rt->u.dst); | ||
| 803 | if (nrt) { | ||
| 804 | err = ip6_ins_rt(nrt); | ||
| 805 | if (!err) | ||
| 806 | goto out2; | ||
| 807 | } | ||
| 808 | |||
| 809 | if (--attempts <= 0) | ||
| 810 | goto out2; | ||
| 811 | |||
| 812 | /* | ||
| 813 | * Race condition! In the gap, when table->tb6_lock was | ||
| 814 | * released someone could insert this route. Relookup. | ||
| 815 | */ | ||
| 816 | dst_release(&rt->u.dst); | ||
| 817 | goto relookup; | ||
| 818 | |||
| 819 | out: | ||
| 820 | if (reachable) { | ||
| 821 | reachable = 0; | ||
| 822 | goto restart_2; | ||
| 823 | } | ||
| 824 | dst_hold(&rt->u.dst); | ||
| 825 | read_unlock_bh(&table->tb6_lock); | ||
| 826 | out2: | ||
| 827 | rt->u.dst.lastuse = jiffies; | ||
| 828 | rt->u.dst.__use++; | ||
| 829 | return rt; | ||
| 830 | } | 771 | } |
| 831 | 772 | ||
| 832 | struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) | 773 | struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) |
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c index 3fb44277207b..68bb2548e469 100644 --- a/net/ipv6/sysctl_net_ipv6.c +++ b/net/ipv6/sysctl_net_ipv6.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <net/ndisc.h> | 12 | #include <net/ndisc.h> |
| 13 | #include <net/ipv6.h> | 13 | #include <net/ipv6.h> |
| 14 | #include <net/addrconf.h> | 14 | #include <net/addrconf.h> |
| 15 | #include <net/inet_frag.h> | ||
| 15 | 16 | ||
| 16 | #ifdef CONFIG_SYSCTL | 17 | #ifdef CONFIG_SYSCTL |
| 17 | 18 | ||
| @@ -41,7 +42,7 @@ static ctl_table ipv6_table[] = { | |||
| 41 | { | 42 | { |
| 42 | .ctl_name = NET_IPV6_IP6FRAG_HIGH_THRESH, | 43 | .ctl_name = NET_IPV6_IP6FRAG_HIGH_THRESH, |
| 43 | .procname = "ip6frag_high_thresh", | 44 | .procname = "ip6frag_high_thresh", |
| 44 | .data = &sysctl_ip6frag_high_thresh, | 45 | .data = &ip6_frags_ctl.high_thresh, |
| 45 | .maxlen = sizeof(int), | 46 | .maxlen = sizeof(int), |
| 46 | .mode = 0644, | 47 | .mode = 0644, |
| 47 | .proc_handler = &proc_dointvec | 48 | .proc_handler = &proc_dointvec |
| @@ -49,7 +50,7 @@ static ctl_table ipv6_table[] = { | |||
| 49 | { | 50 | { |
| 50 | .ctl_name = NET_IPV6_IP6FRAG_LOW_THRESH, | 51 | .ctl_name = NET_IPV6_IP6FRAG_LOW_THRESH, |
| 51 | .procname = "ip6frag_low_thresh", | 52 | .procname = "ip6frag_low_thresh", |
| 52 | .data = &sysctl_ip6frag_low_thresh, | 53 | .data = &ip6_frags_ctl.low_thresh, |
| 53 | .maxlen = sizeof(int), | 54 | .maxlen = sizeof(int), |
| 54 | .mode = 0644, | 55 | .mode = 0644, |
| 55 | .proc_handler = &proc_dointvec | 56 | .proc_handler = &proc_dointvec |
| @@ -57,7 +58,7 @@ static ctl_table ipv6_table[] = { | |||
| 57 | { | 58 | { |
| 58 | .ctl_name = NET_IPV6_IP6FRAG_TIME, | 59 | .ctl_name = NET_IPV6_IP6FRAG_TIME, |
| 59 | .procname = "ip6frag_time", | 60 | .procname = "ip6frag_time", |
| 60 | .data = &sysctl_ip6frag_time, | 61 | .data = &ip6_frags_ctl.timeout, |
| 61 | .maxlen = sizeof(int), | 62 | .maxlen = sizeof(int), |
| 62 | .mode = 0644, | 63 | .mode = 0644, |
| 63 | .proc_handler = &proc_dointvec_jiffies, | 64 | .proc_handler = &proc_dointvec_jiffies, |
| @@ -66,7 +67,7 @@ static ctl_table ipv6_table[] = { | |||
| 66 | { | 67 | { |
| 67 | .ctl_name = NET_IPV6_IP6FRAG_SECRET_INTERVAL, | 68 | .ctl_name = NET_IPV6_IP6FRAG_SECRET_INTERVAL, |
| 68 | .procname = "ip6frag_secret_interval", | 69 | .procname = "ip6frag_secret_interval", |
| 69 | .data = &sysctl_ip6frag_secret_interval, | 70 | .data = &ip6_frags_ctl.secret_interval, |
| 70 | .maxlen = sizeof(int), | 71 | .maxlen = sizeof(int), |
| 71 | .mode = 0644, | 72 | .mode = 0644, |
| 72 | .proc_handler = &proc_dointvec_jiffies, | 73 | .proc_handler = &proc_dointvec_jiffies, |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index a07b59c528f3..737b755342bd 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
| @@ -1668,9 +1668,8 @@ ipv6_pktoptions: | |||
| 1668 | return 0; | 1668 | return 0; |
| 1669 | } | 1669 | } |
| 1670 | 1670 | ||
| 1671 | static int tcp_v6_rcv(struct sk_buff **pskb) | 1671 | static int tcp_v6_rcv(struct sk_buff *skb) |
| 1672 | { | 1672 | { |
| 1673 | struct sk_buff *skb = *pskb; | ||
| 1674 | struct tcphdr *th; | 1673 | struct tcphdr *th; |
| 1675 | struct sock *sk; | 1674 | struct sock *sk; |
| 1676 | int ret; | 1675 | int ret; |
diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c index 23e2809878ae..6323921b40be 100644 --- a/net/ipv6/tunnel6.c +++ b/net/ipv6/tunnel6.c | |||
| @@ -87,9 +87,8 @@ int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family) | |||
| 87 | 87 | ||
| 88 | EXPORT_SYMBOL(xfrm6_tunnel_deregister); | 88 | EXPORT_SYMBOL(xfrm6_tunnel_deregister); |
| 89 | 89 | ||
| 90 | static int tunnel6_rcv(struct sk_buff **pskb) | 90 | static int tunnel6_rcv(struct sk_buff *skb) |
| 91 | { | 91 | { |
| 92 | struct sk_buff *skb = *pskb; | ||
| 93 | struct xfrm6_tunnel *handler; | 92 | struct xfrm6_tunnel *handler; |
| 94 | 93 | ||
| 95 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) | 94 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) |
| @@ -106,9 +105,8 @@ drop: | |||
| 106 | return 0; | 105 | return 0; |
| 107 | } | 106 | } |
| 108 | 107 | ||
| 109 | static int tunnel46_rcv(struct sk_buff **pskb) | 108 | static int tunnel46_rcv(struct sk_buff *skb) |
| 110 | { | 109 | { |
| 111 | struct sk_buff *skb = *pskb; | ||
| 112 | struct xfrm6_tunnel *handler; | 110 | struct xfrm6_tunnel *handler; |
| 113 | 111 | ||
| 114 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) | 112 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 82ff26dd4470..caebad6ee510 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
| @@ -405,10 +405,9 @@ static inline int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh, | |||
| 405 | return 0; | 405 | return 0; |
| 406 | } | 406 | } |
| 407 | 407 | ||
| 408 | int __udp6_lib_rcv(struct sk_buff **pskb, struct hlist_head udptable[], | 408 | int __udp6_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[], |
| 409 | int proto) | 409 | int proto) |
| 410 | { | 410 | { |
| 411 | struct sk_buff *skb = *pskb; | ||
| 412 | struct sock *sk; | 411 | struct sock *sk; |
| 413 | struct udphdr *uh; | 412 | struct udphdr *uh; |
| 414 | struct net_device *dev = skb->dev; | 413 | struct net_device *dev = skb->dev; |
| @@ -494,9 +493,9 @@ discard: | |||
| 494 | return 0; | 493 | return 0; |
| 495 | } | 494 | } |
| 496 | 495 | ||
| 497 | static __inline__ int udpv6_rcv(struct sk_buff **pskb) | 496 | static __inline__ int udpv6_rcv(struct sk_buff *skb) |
| 498 | { | 497 | { |
| 499 | return __udp6_lib_rcv(pskb, udp_hash, IPPROTO_UDP); | 498 | return __udp6_lib_rcv(skb, udp_hash, IPPROTO_UDP); |
| 500 | } | 499 | } |
| 501 | 500 | ||
| 502 | /* | 501 | /* |
diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h index 6e252f318f7c..2d3fda601232 100644 --- a/net/ipv6/udp_impl.h +++ b/net/ipv6/udp_impl.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | #include <net/addrconf.h> | 6 | #include <net/addrconf.h> |
| 7 | #include <net/inet_common.h> | 7 | #include <net/inet_common.h> |
| 8 | 8 | ||
| 9 | extern int __udp6_lib_rcv(struct sk_buff **, struct hlist_head [], int ); | 9 | extern int __udp6_lib_rcv(struct sk_buff *, struct hlist_head [], int ); |
| 10 | extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *, | 10 | extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *, |
| 11 | int , int , int , __be32 , struct hlist_head []); | 11 | int , int , int , __be32 , struct hlist_head []); |
| 12 | 12 | ||
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c index f54016a55004..766566f7de47 100644 --- a/net/ipv6/udplite.c +++ b/net/ipv6/udplite.c | |||
| @@ -17,9 +17,9 @@ | |||
| 17 | 17 | ||
| 18 | DEFINE_SNMP_STAT(struct udp_mib, udplite_stats_in6) __read_mostly; | 18 | DEFINE_SNMP_STAT(struct udp_mib, udplite_stats_in6) __read_mostly; |
| 19 | 19 | ||
| 20 | static int udplitev6_rcv(struct sk_buff **pskb) | 20 | static int udplitev6_rcv(struct sk_buff *skb) |
| 21 | { | 21 | { |
| 22 | return __udp6_lib_rcv(pskb, udplite_hash, IPPROTO_UDPLITE); | 22 | return __udp6_lib_rcv(skb, udplite_hash, IPPROTO_UDPLITE); |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | static void udplitev6_err(struct sk_buff *skb, | 25 | static void udplitev6_err(struct sk_buff *skb, |
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c index c858537cec4b..02f69e544f6f 100644 --- a/net/ipv6/xfrm6_input.c +++ b/net/ipv6/xfrm6_input.c | |||
| @@ -133,9 +133,9 @@ drop: | |||
| 133 | 133 | ||
| 134 | EXPORT_SYMBOL(xfrm6_rcv_spi); | 134 | EXPORT_SYMBOL(xfrm6_rcv_spi); |
| 135 | 135 | ||
| 136 | int xfrm6_rcv(struct sk_buff **pskb) | 136 | int xfrm6_rcv(struct sk_buff *skb) |
| 137 | { | 137 | { |
| 138 | return xfrm6_rcv_spi(*pskb, 0); | 138 | return xfrm6_rcv_spi(skb, 0); |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | EXPORT_SYMBOL(xfrm6_rcv); | 141 | EXPORT_SYMBOL(xfrm6_rcv); |
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 4618c18e611d..a5a32c17249d 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c | |||
| @@ -80,7 +80,7 @@ static int xfrm6_output_finish2(struct sk_buff *skb) | |||
| 80 | while (likely((err = xfrm6_output_one(skb)) == 0)) { | 80 | while (likely((err = xfrm6_output_one(skb)) == 0)) { |
| 81 | nf_reset(skb); | 81 | nf_reset(skb); |
| 82 | 82 | ||
| 83 | err = nf_hook(PF_INET6, NF_IP6_LOCAL_OUT, &skb, NULL, | 83 | err = nf_hook(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, |
| 84 | skb->dst->dev, dst_output); | 84 | skb->dst->dev, dst_output); |
| 85 | if (unlikely(err != 1)) | 85 | if (unlikely(err != 1)) |
| 86 | break; | 86 | break; |
| @@ -88,7 +88,7 @@ static int xfrm6_output_finish2(struct sk_buff *skb) | |||
| 88 | if (!skb->dst->xfrm) | 88 | if (!skb->dst->xfrm) |
| 89 | return dst_output(skb); | 89 | return dst_output(skb); |
| 90 | 90 | ||
| 91 | err = nf_hook(PF_INET6, NF_IP6_POST_ROUTING, &skb, NULL, | 91 | err = nf_hook(PF_INET6, NF_IP6_POST_ROUTING, skb, NULL, |
| 92 | skb->dst->dev, xfrm6_output_finish2); | 92 | skb->dst->dev, xfrm6_output_finish2); |
| 93 | if (unlikely(err != 1)) | 93 | if (unlikely(err != 1)) |
| 94 | break; | 94 | break; |
diff --git a/net/netfilter/core.c b/net/netfilter/core.c index a523fa4136ed..bed9ba01e8ec 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c | |||
| @@ -117,7 +117,7 @@ void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n) | |||
| 117 | EXPORT_SYMBOL(nf_unregister_hooks); | 117 | EXPORT_SYMBOL(nf_unregister_hooks); |
| 118 | 118 | ||
| 119 | unsigned int nf_iterate(struct list_head *head, | 119 | unsigned int nf_iterate(struct list_head *head, |
| 120 | struct sk_buff **skb, | 120 | struct sk_buff *skb, |
| 121 | int hook, | 121 | int hook, |
| 122 | const struct net_device *indev, | 122 | const struct net_device *indev, |
| 123 | const struct net_device *outdev, | 123 | const struct net_device *outdev, |
| @@ -160,7 +160,7 @@ unsigned int nf_iterate(struct list_head *head, | |||
| 160 | 160 | ||
| 161 | /* Returns 1 if okfn() needs to be executed by the caller, | 161 | /* Returns 1 if okfn() needs to be executed by the caller, |
| 162 | * -EPERM for NF_DROP, 0 otherwise. */ | 162 | * -EPERM for NF_DROP, 0 otherwise. */ |
| 163 | int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb, | 163 | int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb, |
| 164 | struct net_device *indev, | 164 | struct net_device *indev, |
| 165 | struct net_device *outdev, | 165 | struct net_device *outdev, |
| 166 | int (*okfn)(struct sk_buff *), | 166 | int (*okfn)(struct sk_buff *), |
| @@ -175,17 +175,17 @@ int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb, | |||
| 175 | 175 | ||
| 176 | elem = &nf_hooks[pf][hook]; | 176 | elem = &nf_hooks[pf][hook]; |
| 177 | next_hook: | 177 | next_hook: |
| 178 | verdict = nf_iterate(&nf_hooks[pf][hook], pskb, hook, indev, | 178 | verdict = nf_iterate(&nf_hooks[pf][hook], skb, hook, indev, |
| 179 | outdev, &elem, okfn, hook_thresh); | 179 | outdev, &elem, okfn, hook_thresh); |
| 180 | if (verdict == NF_ACCEPT || verdict == NF_STOP) { | 180 | if (verdict == NF_ACCEPT || verdict == NF_STOP) { |
| 181 | ret = 1; | 181 | ret = 1; |
| 182 | goto unlock; | 182 | goto unlock; |
| 183 | } else if (verdict == NF_DROP) { | 183 | } else if (verdict == NF_DROP) { |
| 184 | kfree_skb(*pskb); | 184 | kfree_skb(skb); |
| 185 | ret = -EPERM; | 185 | ret = -EPERM; |
| 186 | } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) { | 186 | } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) { |
| 187 | NFDEBUG("nf_hook: Verdict = QUEUE.\n"); | 187 | NFDEBUG("nf_hook: Verdict = QUEUE.\n"); |
| 188 | if (!nf_queue(*pskb, elem, pf, hook, indev, outdev, okfn, | 188 | if (!nf_queue(skb, elem, pf, hook, indev, outdev, okfn, |
| 189 | verdict >> NF_VERDICT_BITS)) | 189 | verdict >> NF_VERDICT_BITS)) |
| 190 | goto next_hook; | 190 | goto next_hook; |
| 191 | } | 191 | } |
| @@ -196,34 +196,24 @@ unlock: | |||
| 196 | EXPORT_SYMBOL(nf_hook_slow); | 196 | EXPORT_SYMBOL(nf_hook_slow); |
| 197 | 197 | ||
| 198 | 198 | ||
| 199 | int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len) | 199 | int skb_make_writable(struct sk_buff *skb, unsigned int writable_len) |
| 200 | { | 200 | { |
| 201 | struct sk_buff *nskb; | 201 | if (writable_len > skb->len) |
| 202 | |||
| 203 | if (writable_len > (*pskb)->len) | ||
| 204 | return 0; | 202 | return 0; |
| 205 | 203 | ||
| 206 | /* Not exclusive use of packet? Must copy. */ | 204 | /* Not exclusive use of packet? Must copy. */ |
| 207 | if (skb_cloned(*pskb) && !skb_clone_writable(*pskb, writable_len)) | 205 | if (!skb_cloned(skb)) { |
| 208 | goto copy_skb; | 206 | if (writable_len <= skb_headlen(skb)) |
| 209 | if (skb_shared(*pskb)) | 207 | return 1; |
| 210 | goto copy_skb; | 208 | } else if (skb_clone_writable(skb, writable_len)) |
| 211 | 209 | return 1; | |
| 212 | return pskb_may_pull(*pskb, writable_len); | 210 | |
| 213 | 211 | if (writable_len <= skb_headlen(skb)) | |
| 214 | copy_skb: | 212 | writable_len = 0; |
| 215 | nskb = skb_copy(*pskb, GFP_ATOMIC); | 213 | else |
| 216 | if (!nskb) | 214 | writable_len -= skb_headlen(skb); |
| 217 | return 0; | 215 | |
| 218 | BUG_ON(skb_is_nonlinear(nskb)); | 216 | return !!__pskb_pull_tail(skb, writable_len); |
| 219 | |||
| 220 | /* Rest of kernel will get very unhappy if we pass it a | ||
| 221 | suddenly-orphaned skbuff */ | ||
| 222 | if ((*pskb)->sk) | ||
| 223 | skb_set_owner_w(nskb, (*pskb)->sk); | ||
| 224 | kfree_skb(*pskb); | ||
| 225 | *pskb = nskb; | ||
| 226 | return 1; | ||
| 227 | } | 217 | } |
| 228 | EXPORT_SYMBOL(skb_make_writable); | 218 | EXPORT_SYMBOL(skb_make_writable); |
| 229 | 219 | ||
diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c index e42ab230ad88..7b8239c0cd5e 100644 --- a/net/netfilter/nf_conntrack_amanda.c +++ b/net/netfilter/nf_conntrack_amanda.c | |||
| @@ -36,7 +36,7 @@ MODULE_PARM_DESC(master_timeout, "timeout for the master connection"); | |||
| 36 | module_param(ts_algo, charp, 0400); | 36 | module_param(ts_algo, charp, 0400); |
| 37 | MODULE_PARM_DESC(ts_algo, "textsearch algorithm to use (default kmp)"); | 37 | MODULE_PARM_DESC(ts_algo, "textsearch algorithm to use (default kmp)"); |
| 38 | 38 | ||
| 39 | unsigned int (*nf_nat_amanda_hook)(struct sk_buff **pskb, | 39 | unsigned int (*nf_nat_amanda_hook)(struct sk_buff *skb, |
| 40 | enum ip_conntrack_info ctinfo, | 40 | enum ip_conntrack_info ctinfo, |
| 41 | unsigned int matchoff, | 41 | unsigned int matchoff, |
| 42 | unsigned int matchlen, | 42 | unsigned int matchlen, |
| @@ -79,7 +79,7 @@ static struct { | |||
| 79 | }, | 79 | }, |
| 80 | }; | 80 | }; |
| 81 | 81 | ||
| 82 | static int amanda_help(struct sk_buff **pskb, | 82 | static int amanda_help(struct sk_buff *skb, |
| 83 | unsigned int protoff, | 83 | unsigned int protoff, |
| 84 | struct nf_conn *ct, | 84 | struct nf_conn *ct, |
| 85 | enum ip_conntrack_info ctinfo) | 85 | enum ip_conntrack_info ctinfo) |
| @@ -101,25 +101,25 @@ static int amanda_help(struct sk_buff **pskb, | |||
| 101 | 101 | ||
| 102 | /* increase the UDP timeout of the master connection as replies from | 102 | /* increase the UDP timeout of the master connection as replies from |
| 103 | * Amanda clients to the server can be quite delayed */ | 103 | * Amanda clients to the server can be quite delayed */ |
| 104 | nf_ct_refresh(ct, *pskb, master_timeout * HZ); | 104 | nf_ct_refresh(ct, skb, master_timeout * HZ); |
| 105 | 105 | ||
| 106 | /* No data? */ | 106 | /* No data? */ |
| 107 | dataoff = protoff + sizeof(struct udphdr); | 107 | dataoff = protoff + sizeof(struct udphdr); |
| 108 | if (dataoff >= (*pskb)->len) { | 108 | if (dataoff >= skb->len) { |
| 109 | if (net_ratelimit()) | 109 | if (net_ratelimit()) |
| 110 | printk("amanda_help: skblen = %u\n", (*pskb)->len); | 110 | printk("amanda_help: skblen = %u\n", skb->len); |
| 111 | return NF_ACCEPT; | 111 | return NF_ACCEPT; |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | memset(&ts, 0, sizeof(ts)); | 114 | memset(&ts, 0, sizeof(ts)); |
| 115 | start = skb_find_text(*pskb, dataoff, (*pskb)->len, | 115 | start = skb_find_text(skb, dataoff, skb->len, |
| 116 | search[SEARCH_CONNECT].ts, &ts); | 116 | search[SEARCH_CONNECT].ts, &ts); |
| 117 | if (start == UINT_MAX) | 117 | if (start == UINT_MAX) |
| 118 | goto out; | 118 | goto out; |
| 119 | start += dataoff + search[SEARCH_CONNECT].len; | 119 | start += dataoff + search[SEARCH_CONNECT].len; |
| 120 | 120 | ||
| 121 | memset(&ts, 0, sizeof(ts)); | 121 | memset(&ts, 0, sizeof(ts)); |
| 122 | stop = skb_find_text(*pskb, start, (*pskb)->len, | 122 | stop = skb_find_text(skb, start, skb->len, |
| 123 | search[SEARCH_NEWLINE].ts, &ts); | 123 | search[SEARCH_NEWLINE].ts, &ts); |
| 124 | if (stop == UINT_MAX) | 124 | if (stop == UINT_MAX) |
| 125 | goto out; | 125 | goto out; |
| @@ -127,13 +127,13 @@ static int amanda_help(struct sk_buff **pskb, | |||
| 127 | 127 | ||
| 128 | for (i = SEARCH_DATA; i <= SEARCH_INDEX; i++) { | 128 | for (i = SEARCH_DATA; i <= SEARCH_INDEX; i++) { |
| 129 | memset(&ts, 0, sizeof(ts)); | 129 | memset(&ts, 0, sizeof(ts)); |
| 130 | off = skb_find_text(*pskb, start, stop, search[i].ts, &ts); | 130 | off = skb_find_text(skb, start, stop, search[i].ts, &ts); |
| 131 | if (off == UINT_MAX) | 131 | if (off == UINT_MAX) |
| 132 | continue; | 132 | continue; |
| 133 | off += start + search[i].len; | 133 | off += start + search[i].len; |
| 134 | 134 | ||
| 135 | len = min_t(unsigned int, sizeof(pbuf) - 1, stop - off); | 135 | len = min_t(unsigned int, sizeof(pbuf) - 1, stop - off); |
| 136 | if (skb_copy_bits(*pskb, off, pbuf, len)) | 136 | if (skb_copy_bits(skb, off, pbuf, len)) |
| 137 | break; | 137 | break; |
| 138 | pbuf[len] = '\0'; | 138 | pbuf[len] = '\0'; |
| 139 | 139 | ||
| @@ -153,7 +153,7 @@ static int amanda_help(struct sk_buff **pskb, | |||
| 153 | 153 | ||
| 154 | nf_nat_amanda = rcu_dereference(nf_nat_amanda_hook); | 154 | nf_nat_amanda = rcu_dereference(nf_nat_amanda_hook); |
| 155 | if (nf_nat_amanda && ct->status & IPS_NAT_MASK) | 155 | if (nf_nat_amanda && ct->status & IPS_NAT_MASK) |
| 156 | ret = nf_nat_amanda(pskb, ctinfo, off - dataoff, | 156 | ret = nf_nat_amanda(skb, ctinfo, off - dataoff, |
| 157 | len, exp); | 157 | len, exp); |
| 158 | else if (nf_ct_expect_related(exp) != 0) | 158 | else if (nf_ct_expect_related(exp) != 0) |
| 159 | ret = NF_DROP; | 159 | ret = NF_DROP; |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 83c30b45d170..4d6171bc0829 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
| @@ -307,7 +307,7 @@ EXPORT_SYMBOL_GPL(nf_conntrack_hash_insert); | |||
| 307 | 307 | ||
| 308 | /* Confirm a connection given skb; places it in hash table */ | 308 | /* Confirm a connection given skb; places it in hash table */ |
| 309 | int | 309 | int |
| 310 | __nf_conntrack_confirm(struct sk_buff **pskb) | 310 | __nf_conntrack_confirm(struct sk_buff *skb) |
| 311 | { | 311 | { |
| 312 | unsigned int hash, repl_hash; | 312 | unsigned int hash, repl_hash; |
| 313 | struct nf_conntrack_tuple_hash *h; | 313 | struct nf_conntrack_tuple_hash *h; |
| @@ -316,7 +316,7 @@ __nf_conntrack_confirm(struct sk_buff **pskb) | |||
| 316 | struct hlist_node *n; | 316 | struct hlist_node *n; |
| 317 | enum ip_conntrack_info ctinfo; | 317 | enum ip_conntrack_info ctinfo; |
| 318 | 318 | ||
| 319 | ct = nf_ct_get(*pskb, &ctinfo); | 319 | ct = nf_ct_get(skb, &ctinfo); |
| 320 | 320 | ||
| 321 | /* ipt_REJECT uses nf_conntrack_attach to attach related | 321 | /* ipt_REJECT uses nf_conntrack_attach to attach related |
| 322 | ICMP/TCP RST packets in other direction. Actual packet | 322 | ICMP/TCP RST packets in other direction. Actual packet |
| @@ -367,14 +367,14 @@ __nf_conntrack_confirm(struct sk_buff **pskb) | |||
| 367 | write_unlock_bh(&nf_conntrack_lock); | 367 | write_unlock_bh(&nf_conntrack_lock); |
| 368 | help = nfct_help(ct); | 368 | help = nfct_help(ct); |
| 369 | if (help && help->helper) | 369 | if (help && help->helper) |
| 370 | nf_conntrack_event_cache(IPCT_HELPER, *pskb); | 370 | nf_conntrack_event_cache(IPCT_HELPER, skb); |
| 371 | #ifdef CONFIG_NF_NAT_NEEDED | 371 | #ifdef CONFIG_NF_NAT_NEEDED |
| 372 | if (test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status) || | 372 | if (test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status) || |
| 373 | test_bit(IPS_DST_NAT_DONE_BIT, &ct->status)) | 373 | test_bit(IPS_DST_NAT_DONE_BIT, &ct->status)) |
| 374 | nf_conntrack_event_cache(IPCT_NATINFO, *pskb); | 374 | nf_conntrack_event_cache(IPCT_NATINFO, skb); |
| 375 | #endif | 375 | #endif |
| 376 | nf_conntrack_event_cache(master_ct(ct) ? | 376 | nf_conntrack_event_cache(master_ct(ct) ? |
| 377 | IPCT_RELATED : IPCT_NEW, *pskb); | 377 | IPCT_RELATED : IPCT_NEW, skb); |
| 378 | return NF_ACCEPT; | 378 | return NF_ACCEPT; |
| 379 | 379 | ||
| 380 | out: | 380 | out: |
| @@ -632,7 +632,7 @@ resolve_normal_ct(struct sk_buff *skb, | |||
| 632 | } | 632 | } |
| 633 | 633 | ||
| 634 | unsigned int | 634 | unsigned int |
| 635 | nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb) | 635 | nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff *skb) |
| 636 | { | 636 | { |
| 637 | struct nf_conn *ct; | 637 | struct nf_conn *ct; |
| 638 | enum ip_conntrack_info ctinfo; | 638 | enum ip_conntrack_info ctinfo; |
| @@ -644,14 +644,14 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb) | |||
| 644 | int ret; | 644 | int ret; |
| 645 | 645 | ||
| 646 | /* Previously seen (loopback or untracked)? Ignore. */ | 646 | /* Previously seen (loopback or untracked)? Ignore. */ |
| 647 | if ((*pskb)->nfct) { | 647 | if (skb->nfct) { |
| 648 | NF_CT_STAT_INC_ATOMIC(ignore); | 648 | NF_CT_STAT_INC_ATOMIC(ignore); |
| 649 | return NF_ACCEPT; | 649 | return NF_ACCEPT; |
| 650 | } | 650 | } |
| 651 | 651 | ||
| 652 | /* rcu_read_lock()ed by nf_hook_slow */ | 652 | /* rcu_read_lock()ed by nf_hook_slow */ |
| 653 | l3proto = __nf_ct_l3proto_find((u_int16_t)pf); | 653 | l3proto = __nf_ct_l3proto_find((u_int16_t)pf); |
| 654 | ret = l3proto->get_l4proto(*pskb, skb_network_offset(*pskb), | 654 | ret = l3proto->get_l4proto(skb, skb_network_offset(skb), |
| 655 | &dataoff, &protonum); | 655 | &dataoff, &protonum); |
| 656 | if (ret <= 0) { | 656 | if (ret <= 0) { |
| 657 | pr_debug("not prepared to track yet or error occured\n"); | 657 | pr_debug("not prepared to track yet or error occured\n"); |
| @@ -666,13 +666,13 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb) | |||
| 666 | * inverse of the return code tells to the netfilter | 666 | * inverse of the return code tells to the netfilter |
| 667 | * core what to do with the packet. */ | 667 | * core what to do with the packet. */ |
| 668 | if (l4proto->error != NULL && | 668 | if (l4proto->error != NULL && |
| 669 | (ret = l4proto->error(*pskb, dataoff, &ctinfo, pf, hooknum)) <= 0) { | 669 | (ret = l4proto->error(skb, dataoff, &ctinfo, pf, hooknum)) <= 0) { |
| 670 | NF_CT_STAT_INC_ATOMIC(error); | 670 | NF_CT_STAT_INC_ATOMIC(error); |
| 671 | NF_CT_STAT_INC_ATOMIC(invalid); | 671 | NF_CT_STAT_INC_ATOMIC(invalid); |
| 672 | return -ret; | 672 | return -ret; |
| 673 | } | 673 | } |
| 674 | 674 | ||
| 675 | ct = resolve_normal_ct(*pskb, dataoff, pf, protonum, l3proto, l4proto, | 675 | ct = resolve_normal_ct(skb, dataoff, pf, protonum, l3proto, l4proto, |
| 676 | &set_reply, &ctinfo); | 676 | &set_reply, &ctinfo); |
| 677 | if (!ct) { | 677 | if (!ct) { |
| 678 | /* Not valid part of a connection */ | 678 | /* Not valid part of a connection */ |
| @@ -686,21 +686,21 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb) | |||
| 686 | return NF_DROP; | 686 | return NF_DROP; |
| 687 | } | 687 | } |
| 688 | 688 | ||
| 689 | NF_CT_ASSERT((*pskb)->nfct); | 689 | NF_CT_ASSERT(skb->nfct); |
| 690 | 690 | ||
| 691 | ret = l4proto->packet(ct, *pskb, dataoff, ctinfo, pf, hooknum); | 691 | ret = l4proto->packet(ct, skb, dataoff, ctinfo, pf, hooknum); |
| 692 | if (ret < 0) { | 692 | if (ret < 0) { |
| 693 | /* Invalid: inverse of the return code tells | 693 | /* Invalid: inverse of the return code tells |
| 694 | * the netfilter core what to do */ | 694 | * the netfilter core what to do */ |
| 695 | pr_debug("nf_conntrack_in: Can't track with proto module\n"); | 695 | pr_debug("nf_conntrack_in: Can't track with proto module\n"); |
| 696 | nf_conntrack_put((*pskb)->nfct); | 696 | nf_conntrack_put(skb->nfct); |
| 697 | (*pskb)->nfct = NULL; | 697 | skb->nfct = NULL; |
| 698 | NF_CT_STAT_INC_ATOMIC(invalid); | 698 | NF_CT_STAT_INC_ATOMIC(invalid); |
| 699 | return -ret; | 699 | return -ret; |
| 700 | } | 700 | } |
| 701 | 701 | ||
| 702 | if (set_reply && !test_and_set_bit(IPS_SEEN_REPLY_BIT, &ct->status)) | 702 | if (set_reply && !test_and_set_bit(IPS_SEEN_REPLY_BIT, &ct->status)) |
| 703 | nf_conntrack_event_cache(IPCT_STATUS, *pskb); | 703 | nf_conntrack_event_cache(IPCT_STATUS, skb); |
| 704 | 704 | ||
| 705 | return ret; | 705 | return ret; |
| 706 | } | 706 | } |
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index c763ee74ea02..6df259067f7e 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c | |||
| @@ -43,7 +43,7 @@ module_param_array(ports, ushort, &ports_c, 0400); | |||
| 43 | static int loose; | 43 | static int loose; |
| 44 | module_param(loose, bool, 0600); | 44 | module_param(loose, bool, 0600); |
| 45 | 45 | ||
| 46 | unsigned int (*nf_nat_ftp_hook)(struct sk_buff **pskb, | 46 | unsigned int (*nf_nat_ftp_hook)(struct sk_buff *skb, |
| 47 | enum ip_conntrack_info ctinfo, | 47 | enum ip_conntrack_info ctinfo, |
| 48 | enum nf_ct_ftp_type type, | 48 | enum nf_ct_ftp_type type, |
| 49 | unsigned int matchoff, | 49 | unsigned int matchoff, |
| @@ -344,7 +344,7 @@ static void update_nl_seq(u32 nl_seq, struct nf_ct_ftp_master *info, int dir, | |||
| 344 | } | 344 | } |
| 345 | } | 345 | } |
| 346 | 346 | ||
| 347 | static int help(struct sk_buff **pskb, | 347 | static int help(struct sk_buff *skb, |
| 348 | unsigned int protoff, | 348 | unsigned int protoff, |
| 349 | struct nf_conn *ct, | 349 | struct nf_conn *ct, |
| 350 | enum ip_conntrack_info ctinfo) | 350 | enum ip_conntrack_info ctinfo) |
| @@ -371,21 +371,21 @@ static int help(struct sk_buff **pskb, | |||
| 371 | return NF_ACCEPT; | 371 | return NF_ACCEPT; |
| 372 | } | 372 | } |
| 373 | 373 | ||
| 374 | th = skb_header_pointer(*pskb, protoff, sizeof(_tcph), &_tcph); | 374 | th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); |
| 375 | if (th == NULL) | 375 | if (th == NULL) |
| 376 | return NF_ACCEPT; | 376 | return NF_ACCEPT; |
| 377 | 377 | ||
| 378 | dataoff = protoff + th->doff * 4; | 378 | dataoff = protoff + th->doff * 4; |
| 379 | /* No data? */ | 379 | /* No data? */ |
| 380 | if (dataoff >= (*pskb)->len) { | 380 | if (dataoff >= skb->len) { |
| 381 | pr_debug("ftp: dataoff(%u) >= skblen(%u)\n", dataoff, | 381 | pr_debug("ftp: dataoff(%u) >= skblen(%u)\n", dataoff, |
| 382 | (*pskb)->len); | 382 | skb->len); |
| 383 | return NF_ACCEPT; | 383 | return NF_ACCEPT; |
| 384 | } | 384 | } |
| 385 | datalen = (*pskb)->len - dataoff; | 385 | datalen = skb->len - dataoff; |
| 386 | 386 | ||
| 387 | spin_lock_bh(&nf_ftp_lock); | 387 | spin_lock_bh(&nf_ftp_lock); |
| 388 | fb_ptr = skb_header_pointer(*pskb, dataoff, datalen, ftp_buffer); | 388 | fb_ptr = skb_header_pointer(skb, dataoff, datalen, ftp_buffer); |
| 389 | BUG_ON(fb_ptr == NULL); | 389 | BUG_ON(fb_ptr == NULL); |
| 390 | 390 | ||
| 391 | ends_in_nl = (fb_ptr[datalen - 1] == '\n'); | 391 | ends_in_nl = (fb_ptr[datalen - 1] == '\n'); |
| @@ -491,7 +491,7 @@ static int help(struct sk_buff **pskb, | |||
| 491 | * (possibly changed) expectation itself. */ | 491 | * (possibly changed) expectation itself. */ |
| 492 | nf_nat_ftp = rcu_dereference(nf_nat_ftp_hook); | 492 | nf_nat_ftp = rcu_dereference(nf_nat_ftp_hook); |
| 493 | if (nf_nat_ftp && ct->status & IPS_NAT_MASK) | 493 | if (nf_nat_ftp && ct->status & IPS_NAT_MASK) |
| 494 | ret = nf_nat_ftp(pskb, ctinfo, search[dir][i].ftptype, | 494 | ret = nf_nat_ftp(skb, ctinfo, search[dir][i].ftptype, |
| 495 | matchoff, matchlen, exp); | 495 | matchoff, matchlen, exp); |
| 496 | else { | 496 | else { |
| 497 | /* Can't expect this? Best to drop packet now. */ | 497 | /* Can't expect this? Best to drop packet now. */ |
| @@ -508,7 +508,7 @@ out_update_nl: | |||
| 508 | /* Now if this ends in \n, update ftp info. Seq may have been | 508 | /* Now if this ends in \n, update ftp info. Seq may have been |
| 509 | * adjusted by NAT code. */ | 509 | * adjusted by NAT code. */ |
| 510 | if (ends_in_nl) | 510 | if (ends_in_nl) |
| 511 | update_nl_seq(seq, ct_ftp_info, dir, *pskb); | 511 | update_nl_seq(seq, ct_ftp_info, dir, skb); |
| 512 | out: | 512 | out: |
| 513 | spin_unlock_bh(&nf_ftp_lock); | 513 | spin_unlock_bh(&nf_ftp_lock); |
| 514 | return ret; | 514 | return ret; |
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index a8a9dfbe7a67..f23fd9598e19 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c | |||
| @@ -47,27 +47,27 @@ MODULE_PARM_DESC(callforward_filter, "only create call forwarding expectations " | |||
| 47 | "(determined by routing information)"); | 47 | "(determined by routing information)"); |
| 48 | 48 | ||
| 49 | /* Hooks for NAT */ | 49 | /* Hooks for NAT */ |
| 50 | int (*set_h245_addr_hook) (struct sk_buff **pskb, | 50 | int (*set_h245_addr_hook) (struct sk_buff *skb, |
| 51 | unsigned char **data, int dataoff, | 51 | unsigned char **data, int dataoff, |
| 52 | H245_TransportAddress *taddr, | 52 | H245_TransportAddress *taddr, |
| 53 | union nf_conntrack_address *addr, __be16 port) | 53 | union nf_conntrack_address *addr, __be16 port) |
| 54 | __read_mostly; | 54 | __read_mostly; |
| 55 | int (*set_h225_addr_hook) (struct sk_buff **pskb, | 55 | int (*set_h225_addr_hook) (struct sk_buff *skb, |
| 56 | unsigned char **data, int dataoff, | 56 | unsigned char **data, int dataoff, |
| 57 | TransportAddress *taddr, | 57 | TransportAddress *taddr, |
| 58 | union nf_conntrack_address *addr, __be16 port) | 58 | union nf_conntrack_address *addr, __be16 port) |
| 59 | __read_mostly; | 59 | __read_mostly; |
| 60 | int (*set_sig_addr_hook) (struct sk_buff **pskb, | 60 | int (*set_sig_addr_hook) (struct sk_buff *skb, |
| 61 | struct nf_conn *ct, | 61 | struct nf_conn *ct, |
| 62 | enum ip_conntrack_info ctinfo, | 62 | enum ip_conntrack_info ctinfo, |
| 63 | unsigned char **data, | 63 | unsigned char **data, |
| 64 | TransportAddress *taddr, int count) __read_mostly; | 64 | TransportAddress *taddr, int count) __read_mostly; |
| 65 | int (*set_ras_addr_hook) (struct sk_buff **pskb, | 65 | int (*set_ras_addr_hook) (struct sk_buff *skb, |
| 66 | struct nf_conn *ct, | 66 | struct nf_conn *ct, |
| 67 | enum ip_conntrack_info ctinfo, | 67 | enum ip_conntrack_info ctinfo, |
| 68 | unsigned char **data, | 68 | unsigned char **data, |
| 69 | TransportAddress *taddr, int count) __read_mostly; | 69 | TransportAddress *taddr, int count) __read_mostly; |
| 70 | int (*nat_rtp_rtcp_hook) (struct sk_buff **pskb, | 70 | int (*nat_rtp_rtcp_hook) (struct sk_buff *skb, |
| 71 | struct nf_conn *ct, | 71 | struct nf_conn *ct, |
| 72 | enum ip_conntrack_info ctinfo, | 72 | enum ip_conntrack_info ctinfo, |
| 73 | unsigned char **data, int dataoff, | 73 | unsigned char **data, int dataoff, |
| @@ -75,25 +75,25 @@ int (*nat_rtp_rtcp_hook) (struct sk_buff **pskb, | |||
| 75 | __be16 port, __be16 rtp_port, | 75 | __be16 port, __be16 rtp_port, |
| 76 | struct nf_conntrack_expect *rtp_exp, | 76 | struct nf_conntrack_expect *rtp_exp, |
| 77 | struct nf_conntrack_expect *rtcp_exp) __read_mostly; | 77 | struct nf_conntrack_expect *rtcp_exp) __read_mostly; |
| 78 | int (*nat_t120_hook) (struct sk_buff **pskb, | 78 | int (*nat_t120_hook) (struct sk_buff *skb, |
| 79 | struct nf_conn *ct, | 79 | struct nf_conn *ct, |
| 80 | enum ip_conntrack_info ctinfo, | 80 | enum ip_conntrack_info ctinfo, |
| 81 | unsigned char **data, int dataoff, | 81 | unsigned char **data, int dataoff, |
| 82 | H245_TransportAddress *taddr, __be16 port, | 82 | H245_TransportAddress *taddr, __be16 port, |
| 83 | struct nf_conntrack_expect *exp) __read_mostly; | 83 | struct nf_conntrack_expect *exp) __read_mostly; |
| 84 | int (*nat_h245_hook) (struct sk_buff **pskb, | 84 | int (*nat_h245_hook) (struct sk_buff *skb, |
| 85 | struct nf_conn *ct, | 85 | struct nf_conn *ct, |
| 86 | enum ip_conntrack_info ctinfo, | 86 | enum ip_conntrack_info ctinfo, |
| 87 | unsigned char **data, int dataoff, | 87 | unsigned char **data, int dataoff, |
| 88 | TransportAddress *taddr, __be16 port, | 88 | TransportAddress *taddr, __be16 port, |
| 89 | struct nf_conntrack_expect *exp) __read_mostly; | 89 | struct nf_conntrack_expect *exp) __read_mostly; |
| 90 | int (*nat_callforwarding_hook) (struct sk_buff **pskb, | 90 | int (*nat_callforwarding_hook) (struct sk_buff *skb, |
| 91 | struct nf_conn *ct, | 91 | struct nf_conn *ct, |
| 92 | enum ip_conntrack_info ctinfo, | 92 | enum ip_conntrack_info ctinfo, |
| 93 | unsigned char **data, int dataoff, | 93 | unsigned char **data, int dataoff, |
| 94 | TransportAddress *taddr, __be16 port, | 94 | TransportAddress *taddr, __be16 port, |
| 95 | struct nf_conntrack_expect *exp) __read_mostly; | 95 | struct nf_conntrack_expect *exp) __read_mostly; |
| 96 | int (*nat_q931_hook) (struct sk_buff **pskb, | 96 | int (*nat_q931_hook) (struct sk_buff *skb, |
| 97 | struct nf_conn *ct, | 97 | struct nf_conn *ct, |
| 98 | enum ip_conntrack_info ctinfo, | 98 | enum ip_conntrack_info ctinfo, |
| 99 | unsigned char **data, TransportAddress *taddr, int idx, | 99 | unsigned char **data, TransportAddress *taddr, int idx, |
| @@ -108,7 +108,7 @@ static struct nf_conntrack_helper nf_conntrack_helper_q931[]; | |||
| 108 | static struct nf_conntrack_helper nf_conntrack_helper_ras[]; | 108 | static struct nf_conntrack_helper nf_conntrack_helper_ras[]; |
| 109 | 109 | ||
| 110 | /****************************************************************************/ | 110 | /****************************************************************************/ |
| 111 | static int get_tpkt_data(struct sk_buff **pskb, unsigned int protoff, | 111 | static int get_tpkt_data(struct sk_buff *skb, unsigned int protoff, |
| 112 | struct nf_conn *ct, enum ip_conntrack_info ctinfo, | 112 | struct nf_conn *ct, enum ip_conntrack_info ctinfo, |
| 113 | unsigned char **data, int *datalen, int *dataoff) | 113 | unsigned char **data, int *datalen, int *dataoff) |
| 114 | { | 114 | { |
| @@ -122,7 +122,7 @@ static int get_tpkt_data(struct sk_buff **pskb, unsigned int protoff, | |||
| 122 | int tpktoff; | 122 | int tpktoff; |
| 123 | 123 | ||
| 124 | /* Get TCP header */ | 124 | /* Get TCP header */ |
| 125 | th = skb_header_pointer(*pskb, protoff, sizeof(_tcph), &_tcph); | 125 | th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); |
| 126 | if (th == NULL) | 126 | if (th == NULL) |
| 127 | return 0; | 127 | return 0; |
| 128 | 128 | ||
| @@ -130,13 +130,13 @@ static int get_tpkt_data(struct sk_buff **pskb, unsigned int protoff, | |||
| 130 | tcpdataoff = protoff + th->doff * 4; | 130 | tcpdataoff = protoff + th->doff * 4; |
| 131 | 131 | ||
| 132 | /* Get TCP data length */ | 132 | /* Get TCP data length */ |
| 133 | tcpdatalen = (*pskb)->len - tcpdataoff; | 133 | tcpdatalen = skb->len - tcpdataoff; |
| 134 | if (tcpdatalen <= 0) /* No TCP data */ | 134 | if (tcpdatalen <= 0) /* No TCP data */ |
| 135 | goto clear_out; | 135 | goto clear_out; |
| 136 | 136 | ||
| 137 | if (*data == NULL) { /* first TPKT */ | 137 | if (*data == NULL) { /* first TPKT */ |
| 138 | /* Get first TPKT pointer */ | 138 | /* Get first TPKT pointer */ |
| 139 | tpkt = skb_header_pointer(*pskb, tcpdataoff, tcpdatalen, | 139 | tpkt = skb_header_pointer(skb, tcpdataoff, tcpdatalen, |
| 140 | h323_buffer); | 140 | h323_buffer); |
| 141 | BUG_ON(tpkt == NULL); | 141 | BUG_ON(tpkt == NULL); |
| 142 | 142 | ||
| @@ -248,7 +248,7 @@ static int get_h245_addr(struct nf_conn *ct, unsigned char *data, | |||
| 248 | } | 248 | } |
| 249 | 249 | ||
| 250 | /****************************************************************************/ | 250 | /****************************************************************************/ |
| 251 | static int expect_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct, | 251 | static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct, |
| 252 | enum ip_conntrack_info ctinfo, | 252 | enum ip_conntrack_info ctinfo, |
| 253 | unsigned char **data, int dataoff, | 253 | unsigned char **data, int dataoff, |
| 254 | H245_TransportAddress *taddr) | 254 | H245_TransportAddress *taddr) |
| @@ -297,7 +297,7 @@ static int expect_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 297 | (nat_rtp_rtcp = rcu_dereference(nat_rtp_rtcp_hook)) && | 297 | (nat_rtp_rtcp = rcu_dereference(nat_rtp_rtcp_hook)) && |
| 298 | ct->status & IPS_NAT_MASK) { | 298 | ct->status & IPS_NAT_MASK) { |
| 299 | /* NAT needed */ | 299 | /* NAT needed */ |
| 300 | ret = nat_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, | 300 | ret = nat_rtp_rtcp(skb, ct, ctinfo, data, dataoff, |
| 301 | taddr, port, rtp_port, rtp_exp, rtcp_exp); | 301 | taddr, port, rtp_port, rtp_exp, rtcp_exp); |
| 302 | } else { /* Conntrack only */ | 302 | } else { /* Conntrack only */ |
| 303 | if (nf_ct_expect_related(rtp_exp) == 0) { | 303 | if (nf_ct_expect_related(rtp_exp) == 0) { |
| @@ -321,7 +321,7 @@ static int expect_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 321 | } | 321 | } |
| 322 | 322 | ||
| 323 | /****************************************************************************/ | 323 | /****************************************************************************/ |
| 324 | static int expect_t120(struct sk_buff **pskb, | 324 | static int expect_t120(struct sk_buff *skb, |
| 325 | struct nf_conn *ct, | 325 | struct nf_conn *ct, |
| 326 | enum ip_conntrack_info ctinfo, | 326 | enum ip_conntrack_info ctinfo, |
| 327 | unsigned char **data, int dataoff, | 327 | unsigned char **data, int dataoff, |
| @@ -355,7 +355,7 @@ static int expect_t120(struct sk_buff **pskb, | |||
| 355 | (nat_t120 = rcu_dereference(nat_t120_hook)) && | 355 | (nat_t120 = rcu_dereference(nat_t120_hook)) && |
| 356 | ct->status & IPS_NAT_MASK) { | 356 | ct->status & IPS_NAT_MASK) { |
| 357 | /* NAT needed */ | 357 | /* NAT needed */ |
| 358 | ret = nat_t120(pskb, ct, ctinfo, data, dataoff, taddr, | 358 | ret = nat_t120(skb, ct, ctinfo, data, dataoff, taddr, |
| 359 | port, exp); | 359 | port, exp); |
| 360 | } else { /* Conntrack only */ | 360 | } else { /* Conntrack only */ |
| 361 | if (nf_ct_expect_related(exp) == 0) { | 361 | if (nf_ct_expect_related(exp) == 0) { |
| @@ -371,7 +371,7 @@ static int expect_t120(struct sk_buff **pskb, | |||
| 371 | } | 371 | } |
| 372 | 372 | ||
| 373 | /****************************************************************************/ | 373 | /****************************************************************************/ |
| 374 | static int process_h245_channel(struct sk_buff **pskb, | 374 | static int process_h245_channel(struct sk_buff *skb, |
| 375 | struct nf_conn *ct, | 375 | struct nf_conn *ct, |
| 376 | enum ip_conntrack_info ctinfo, | 376 | enum ip_conntrack_info ctinfo, |
| 377 | unsigned char **data, int dataoff, | 377 | unsigned char **data, int dataoff, |
| @@ -381,7 +381,7 @@ static int process_h245_channel(struct sk_buff **pskb, | |||
| 381 | 381 | ||
| 382 | if (channel->options & eH2250LogicalChannelParameters_mediaChannel) { | 382 | if (channel->options & eH2250LogicalChannelParameters_mediaChannel) { |
| 383 | /* RTP */ | 383 | /* RTP */ |
| 384 | ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, | 384 | ret = expect_rtp_rtcp(skb, ct, ctinfo, data, dataoff, |
| 385 | &channel->mediaChannel); | 385 | &channel->mediaChannel); |
| 386 | if (ret < 0) | 386 | if (ret < 0) |
| 387 | return -1; | 387 | return -1; |
| @@ -390,7 +390,7 @@ static int process_h245_channel(struct sk_buff **pskb, | |||
| 390 | if (channel-> | 390 | if (channel-> |
| 391 | options & eH2250LogicalChannelParameters_mediaControlChannel) { | 391 | options & eH2250LogicalChannelParameters_mediaControlChannel) { |
| 392 | /* RTCP */ | 392 | /* RTCP */ |
| 393 | ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, | 393 | ret = expect_rtp_rtcp(skb, ct, ctinfo, data, dataoff, |
| 394 | &channel->mediaControlChannel); | 394 | &channel->mediaControlChannel); |
| 395 | if (ret < 0) | 395 | if (ret < 0) |
| 396 | return -1; | 396 | return -1; |
| @@ -400,7 +400,7 @@ static int process_h245_channel(struct sk_buff **pskb, | |||
| 400 | } | 400 | } |
| 401 | 401 | ||
| 402 | /****************************************************************************/ | 402 | /****************************************************************************/ |
| 403 | static int process_olc(struct sk_buff **pskb, struct nf_conn *ct, | 403 | static int process_olc(struct sk_buff *skb, struct nf_conn *ct, |
| 404 | enum ip_conntrack_info ctinfo, | 404 | enum ip_conntrack_info ctinfo, |
| 405 | unsigned char **data, int dataoff, | 405 | unsigned char **data, int dataoff, |
| 406 | OpenLogicalChannel *olc) | 406 | OpenLogicalChannel *olc) |
| @@ -412,7 +412,7 @@ static int process_olc(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 412 | if (olc->forwardLogicalChannelParameters.multiplexParameters.choice == | 412 | if (olc->forwardLogicalChannelParameters.multiplexParameters.choice == |
| 413 | eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters) | 413 | eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters) |
| 414 | { | 414 | { |
| 415 | ret = process_h245_channel(pskb, ct, ctinfo, data, dataoff, | 415 | ret = process_h245_channel(skb, ct, ctinfo, data, dataoff, |
| 416 | &olc-> | 416 | &olc-> |
| 417 | forwardLogicalChannelParameters. | 417 | forwardLogicalChannelParameters. |
| 418 | multiplexParameters. | 418 | multiplexParameters. |
| @@ -430,7 +430,7 @@ static int process_olc(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 430 | eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)) | 430 | eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)) |
| 431 | { | 431 | { |
| 432 | ret = | 432 | ret = |
| 433 | process_h245_channel(pskb, ct, ctinfo, data, dataoff, | 433 | process_h245_channel(skb, ct, ctinfo, data, dataoff, |
| 434 | &olc-> | 434 | &olc-> |
| 435 | reverseLogicalChannelParameters. | 435 | reverseLogicalChannelParameters. |
| 436 | multiplexParameters. | 436 | multiplexParameters. |
| @@ -448,7 +448,7 @@ static int process_olc(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 448 | t120.choice == eDataProtocolCapability_separateLANStack && | 448 | t120.choice == eDataProtocolCapability_separateLANStack && |
| 449 | olc->separateStack.networkAddress.choice == | 449 | olc->separateStack.networkAddress.choice == |
| 450 | eNetworkAccessParameters_networkAddress_localAreaAddress) { | 450 | eNetworkAccessParameters_networkAddress_localAreaAddress) { |
| 451 | ret = expect_t120(pskb, ct, ctinfo, data, dataoff, | 451 | ret = expect_t120(skb, ct, ctinfo, data, dataoff, |
| 452 | &olc->separateStack.networkAddress. | 452 | &olc->separateStack.networkAddress. |
| 453 | localAreaAddress); | 453 | localAreaAddress); |
| 454 | if (ret < 0) | 454 | if (ret < 0) |
| @@ -459,7 +459,7 @@ static int process_olc(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 459 | } | 459 | } |
| 460 | 460 | ||
| 461 | /****************************************************************************/ | 461 | /****************************************************************************/ |
| 462 | static int process_olca(struct sk_buff **pskb, struct nf_conn *ct, | 462 | static int process_olca(struct sk_buff *skb, struct nf_conn *ct, |
| 463 | enum ip_conntrack_info ctinfo, | 463 | enum ip_conntrack_info ctinfo, |
| 464 | unsigned char **data, int dataoff, | 464 | unsigned char **data, int dataoff, |
| 465 | OpenLogicalChannelAck *olca) | 465 | OpenLogicalChannelAck *olca) |
| @@ -477,7 +477,7 @@ static int process_olca(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 477 | choice == | 477 | choice == |
| 478 | eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)) | 478 | eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)) |
| 479 | { | 479 | { |
| 480 | ret = process_h245_channel(pskb, ct, ctinfo, data, dataoff, | 480 | ret = process_h245_channel(skb, ct, ctinfo, data, dataoff, |
| 481 | &olca-> | 481 | &olca-> |
| 482 | reverseLogicalChannelParameters. | 482 | reverseLogicalChannelParameters. |
| 483 | multiplexParameters. | 483 | multiplexParameters. |
| @@ -496,7 +496,7 @@ static int process_olca(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 496 | if (ack->options & | 496 | if (ack->options & |
| 497 | eH2250LogicalChannelAckParameters_mediaChannel) { | 497 | eH2250LogicalChannelAckParameters_mediaChannel) { |
| 498 | /* RTP */ | 498 | /* RTP */ |
| 499 | ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, | 499 | ret = expect_rtp_rtcp(skb, ct, ctinfo, data, dataoff, |
| 500 | &ack->mediaChannel); | 500 | &ack->mediaChannel); |
| 501 | if (ret < 0) | 501 | if (ret < 0) |
| 502 | return -1; | 502 | return -1; |
| @@ -505,7 +505,7 @@ static int process_olca(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 505 | if (ack->options & | 505 | if (ack->options & |
| 506 | eH2250LogicalChannelAckParameters_mediaControlChannel) { | 506 | eH2250LogicalChannelAckParameters_mediaControlChannel) { |
| 507 | /* RTCP */ | 507 | /* RTCP */ |
| 508 | ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, | 508 | ret = expect_rtp_rtcp(skb, ct, ctinfo, data, dataoff, |
| 509 | &ack->mediaControlChannel); | 509 | &ack->mediaControlChannel); |
| 510 | if (ret < 0) | 510 | if (ret < 0) |
| 511 | return -1; | 511 | return -1; |
| @@ -515,7 +515,7 @@ static int process_olca(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 515 | if ((olca->options & eOpenLogicalChannelAck_separateStack) && | 515 | if ((olca->options & eOpenLogicalChannelAck_separateStack) && |
| 516 | olca->separateStack.networkAddress.choice == | 516 | olca->separateStack.networkAddress.choice == |
| 517 | eNetworkAccessParameters_networkAddress_localAreaAddress) { | 517 | eNetworkAccessParameters_networkAddress_localAreaAddress) { |
| 518 | ret = expect_t120(pskb, ct, ctinfo, data, dataoff, | 518 | ret = expect_t120(skb, ct, ctinfo, data, dataoff, |
| 519 | &olca->separateStack.networkAddress. | 519 | &olca->separateStack.networkAddress. |
| 520 | localAreaAddress); | 520 | localAreaAddress); |
| 521 | if (ret < 0) | 521 | if (ret < 0) |
| @@ -526,7 +526,7 @@ static int process_olca(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 526 | } | 526 | } |
| 527 | 527 | ||
| 528 | /****************************************************************************/ | 528 | /****************************************************************************/ |
| 529 | static int process_h245(struct sk_buff **pskb, struct nf_conn *ct, | 529 | static int process_h245(struct sk_buff *skb, struct nf_conn *ct, |
| 530 | enum ip_conntrack_info ctinfo, | 530 | enum ip_conntrack_info ctinfo, |
| 531 | unsigned char **data, int dataoff, | 531 | unsigned char **data, int dataoff, |
| 532 | MultimediaSystemControlMessage *mscm) | 532 | MultimediaSystemControlMessage *mscm) |
| @@ -535,7 +535,7 @@ static int process_h245(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 535 | case eMultimediaSystemControlMessage_request: | 535 | case eMultimediaSystemControlMessage_request: |
| 536 | if (mscm->request.choice == | 536 | if (mscm->request.choice == |
| 537 | eRequestMessage_openLogicalChannel) { | 537 | eRequestMessage_openLogicalChannel) { |
| 538 | return process_olc(pskb, ct, ctinfo, data, dataoff, | 538 | return process_olc(skb, ct, ctinfo, data, dataoff, |
| 539 | &mscm->request.openLogicalChannel); | 539 | &mscm->request.openLogicalChannel); |
| 540 | } | 540 | } |
| 541 | pr_debug("nf_ct_h323: H.245 Request %d\n", | 541 | pr_debug("nf_ct_h323: H.245 Request %d\n", |
| @@ -544,7 +544,7 @@ static int process_h245(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 544 | case eMultimediaSystemControlMessage_response: | 544 | case eMultimediaSystemControlMessage_response: |
| 545 | if (mscm->response.choice == | 545 | if (mscm->response.choice == |
| 546 | eResponseMessage_openLogicalChannelAck) { | 546 | eResponseMessage_openLogicalChannelAck) { |
| 547 | return process_olca(pskb, ct, ctinfo, data, dataoff, | 547 | return process_olca(skb, ct, ctinfo, data, dataoff, |
| 548 | &mscm->response. | 548 | &mscm->response. |
| 549 | openLogicalChannelAck); | 549 | openLogicalChannelAck); |
| 550 | } | 550 | } |
| @@ -560,7 +560,7 @@ static int process_h245(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 560 | } | 560 | } |
| 561 | 561 | ||
| 562 | /****************************************************************************/ | 562 | /****************************************************************************/ |
| 563 | static int h245_help(struct sk_buff **pskb, unsigned int protoff, | 563 | static int h245_help(struct sk_buff *skb, unsigned int protoff, |
| 564 | struct nf_conn *ct, enum ip_conntrack_info ctinfo) | 564 | struct nf_conn *ct, enum ip_conntrack_info ctinfo) |
| 565 | { | 565 | { |
| 566 | static MultimediaSystemControlMessage mscm; | 566 | static MultimediaSystemControlMessage mscm; |
| @@ -574,12 +574,12 @@ static int h245_help(struct sk_buff **pskb, unsigned int protoff, | |||
| 574 | ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { | 574 | ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { |
| 575 | return NF_ACCEPT; | 575 | return NF_ACCEPT; |
| 576 | } | 576 | } |
| 577 | pr_debug("nf_ct_h245: skblen = %u\n", (*pskb)->len); | 577 | pr_debug("nf_ct_h245: skblen = %u\n", skb->len); |
| 578 | 578 | ||
| 579 | spin_lock_bh(&nf_h323_lock); | 579 | spin_lock_bh(&nf_h323_lock); |
| 580 | 580 | ||
| 581 | /* Process each TPKT */ | 581 | /* Process each TPKT */ |
| 582 | while (get_tpkt_data(pskb, protoff, ct, ctinfo, | 582 | while (get_tpkt_data(skb, protoff, ct, ctinfo, |
| 583 | &data, &datalen, &dataoff)) { | 583 | &data, &datalen, &dataoff)) { |
| 584 | pr_debug("nf_ct_h245: TPKT len=%d ", datalen); | 584 | pr_debug("nf_ct_h245: TPKT len=%d ", datalen); |
| 585 | NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple); | 585 | NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple); |
| @@ -596,7 +596,7 @@ static int h245_help(struct sk_buff **pskb, unsigned int protoff, | |||
| 596 | } | 596 | } |
| 597 | 597 | ||
| 598 | /* Process H.245 signal */ | 598 | /* Process H.245 signal */ |
| 599 | if (process_h245(pskb, ct, ctinfo, &data, dataoff, &mscm) < 0) | 599 | if (process_h245(skb, ct, ctinfo, &data, dataoff, &mscm) < 0) |
| 600 | goto drop; | 600 | goto drop; |
| 601 | } | 601 | } |
| 602 | 602 | ||
| @@ -654,7 +654,7 @@ int get_h225_addr(struct nf_conn *ct, unsigned char *data, | |||
| 654 | } | 654 | } |
| 655 | 655 | ||
| 656 | /****************************************************************************/ | 656 | /****************************************************************************/ |
| 657 | static int expect_h245(struct sk_buff **pskb, struct nf_conn *ct, | 657 | static int expect_h245(struct sk_buff *skb, struct nf_conn *ct, |
| 658 | enum ip_conntrack_info ctinfo, | 658 | enum ip_conntrack_info ctinfo, |
| 659 | unsigned char **data, int dataoff, | 659 | unsigned char **data, int dataoff, |
| 660 | TransportAddress *taddr) | 660 | TransportAddress *taddr) |
| @@ -687,7 +687,7 @@ static int expect_h245(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 687 | (nat_h245 = rcu_dereference(nat_h245_hook)) && | 687 | (nat_h245 = rcu_dereference(nat_h245_hook)) && |
| 688 | ct->status & IPS_NAT_MASK) { | 688 | ct->status & IPS_NAT_MASK) { |
| 689 | /* NAT needed */ | 689 | /* NAT needed */ |
| 690 | ret = nat_h245(pskb, ct, ctinfo, data, dataoff, taddr, | 690 | ret = nat_h245(skb, ct, ctinfo, data, dataoff, taddr, |
| 691 | port, exp); | 691 | port, exp); |
| 692 | } else { /* Conntrack only */ | 692 | } else { /* Conntrack only */ |
| 693 | if (nf_ct_expect_related(exp) == 0) { | 693 | if (nf_ct_expect_related(exp) == 0) { |
| @@ -758,7 +758,7 @@ static int callforward_do_filter(union nf_conntrack_address *src, | |||
| 758 | } | 758 | } |
| 759 | 759 | ||
| 760 | /****************************************************************************/ | 760 | /****************************************************************************/ |
| 761 | static int expect_callforwarding(struct sk_buff **pskb, | 761 | static int expect_callforwarding(struct sk_buff *skb, |
| 762 | struct nf_conn *ct, | 762 | struct nf_conn *ct, |
| 763 | enum ip_conntrack_info ctinfo, | 763 | enum ip_conntrack_info ctinfo, |
| 764 | unsigned char **data, int dataoff, | 764 | unsigned char **data, int dataoff, |
| @@ -798,7 +798,7 @@ static int expect_callforwarding(struct sk_buff **pskb, | |||
| 798 | (nat_callforwarding = rcu_dereference(nat_callforwarding_hook)) && | 798 | (nat_callforwarding = rcu_dereference(nat_callforwarding_hook)) && |
| 799 | ct->status & IPS_NAT_MASK) { | 799 | ct->status & IPS_NAT_MASK) { |
| 800 | /* Need NAT */ | 800 | /* Need NAT */ |
| 801 | ret = nat_callforwarding(pskb, ct, ctinfo, data, dataoff, | 801 | ret = nat_callforwarding(skb, ct, ctinfo, data, dataoff, |
| 802 | taddr, port, exp); | 802 | taddr, port, exp); |
| 803 | } else { /* Conntrack only */ | 803 | } else { /* Conntrack only */ |
| 804 | if (nf_ct_expect_related(exp) == 0) { | 804 | if (nf_ct_expect_related(exp) == 0) { |
| @@ -814,7 +814,7 @@ static int expect_callforwarding(struct sk_buff **pskb, | |||
| 814 | } | 814 | } |
| 815 | 815 | ||
| 816 | /****************************************************************************/ | 816 | /****************************************************************************/ |
| 817 | static int process_setup(struct sk_buff **pskb, struct nf_conn *ct, | 817 | static int process_setup(struct sk_buff *skb, struct nf_conn *ct, |
| 818 | enum ip_conntrack_info ctinfo, | 818 | enum ip_conntrack_info ctinfo, |
| 819 | unsigned char **data, int dataoff, | 819 | unsigned char **data, int dataoff, |
| 820 | Setup_UUIE *setup) | 820 | Setup_UUIE *setup) |
| @@ -829,7 +829,7 @@ static int process_setup(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 829 | pr_debug("nf_ct_q931: Setup\n"); | 829 | pr_debug("nf_ct_q931: Setup\n"); |
| 830 | 830 | ||
| 831 | if (setup->options & eSetup_UUIE_h245Address) { | 831 | if (setup->options & eSetup_UUIE_h245Address) { |
| 832 | ret = expect_h245(pskb, ct, ctinfo, data, dataoff, | 832 | ret = expect_h245(skb, ct, ctinfo, data, dataoff, |
| 833 | &setup->h245Address); | 833 | &setup->h245Address); |
| 834 | if (ret < 0) | 834 | if (ret < 0) |
| 835 | return -1; | 835 | return -1; |
| @@ -846,7 +846,7 @@ static int process_setup(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 846 | NIP6(*(struct in6_addr *)&addr), ntohs(port), | 846 | NIP6(*(struct in6_addr *)&addr), ntohs(port), |
| 847 | NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.src.u3), | 847 | NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.src.u3), |
| 848 | ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port)); | 848 | ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port)); |
| 849 | ret = set_h225_addr(pskb, data, dataoff, | 849 | ret = set_h225_addr(skb, data, dataoff, |
| 850 | &setup->destCallSignalAddress, | 850 | &setup->destCallSignalAddress, |
| 851 | &ct->tuplehash[!dir].tuple.src.u3, | 851 | &ct->tuplehash[!dir].tuple.src.u3, |
| 852 | ct->tuplehash[!dir].tuple.src.u.tcp.port); | 852 | ct->tuplehash[!dir].tuple.src.u.tcp.port); |
| @@ -864,7 +864,7 @@ static int process_setup(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 864 | NIP6(*(struct in6_addr *)&addr), ntohs(port), | 864 | NIP6(*(struct in6_addr *)&addr), ntohs(port), |
| 865 | NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.dst.u3), | 865 | NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.dst.u3), |
| 866 | ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port)); | 866 | ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port)); |
| 867 | ret = set_h225_addr(pskb, data, dataoff, | 867 | ret = set_h225_addr(skb, data, dataoff, |
| 868 | &setup->sourceCallSignalAddress, | 868 | &setup->sourceCallSignalAddress, |
| 869 | &ct->tuplehash[!dir].tuple.dst.u3, | 869 | &ct->tuplehash[!dir].tuple.dst.u3, |
| 870 | ct->tuplehash[!dir].tuple.dst.u.tcp.port); | 870 | ct->tuplehash[!dir].tuple.dst.u.tcp.port); |
| @@ -874,7 +874,7 @@ static int process_setup(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 874 | 874 | ||
| 875 | if (setup->options & eSetup_UUIE_fastStart) { | 875 | if (setup->options & eSetup_UUIE_fastStart) { |
| 876 | for (i = 0; i < setup->fastStart.count; i++) { | 876 | for (i = 0; i < setup->fastStart.count; i++) { |
| 877 | ret = process_olc(pskb, ct, ctinfo, data, dataoff, | 877 | ret = process_olc(skb, ct, ctinfo, data, dataoff, |
| 878 | &setup->fastStart.item[i]); | 878 | &setup->fastStart.item[i]); |
| 879 | if (ret < 0) | 879 | if (ret < 0) |
| 880 | return -1; | 880 | return -1; |
| @@ -885,7 +885,7 @@ static int process_setup(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 885 | } | 885 | } |
| 886 | 886 | ||
| 887 | /****************************************************************************/ | 887 | /****************************************************************************/ |
| 888 | static int process_callproceeding(struct sk_buff **pskb, | 888 | static int process_callproceeding(struct sk_buff *skb, |
| 889 | struct nf_conn *ct, | 889 | struct nf_conn *ct, |
| 890 | enum ip_conntrack_info ctinfo, | 890 | enum ip_conntrack_info ctinfo, |
| 891 | unsigned char **data, int dataoff, | 891 | unsigned char **data, int dataoff, |
| @@ -897,7 +897,7 @@ static int process_callproceeding(struct sk_buff **pskb, | |||
| 897 | pr_debug("nf_ct_q931: CallProceeding\n"); | 897 | pr_debug("nf_ct_q931: CallProceeding\n"); |
| 898 | 898 | ||
| 899 | if (callproc->options & eCallProceeding_UUIE_h245Address) { | 899 | if (callproc->options & eCallProceeding_UUIE_h245Address) { |
| 900 | ret = expect_h245(pskb, ct, ctinfo, data, dataoff, | 900 | ret = expect_h245(skb, ct, ctinfo, data, dataoff, |
| 901 | &callproc->h245Address); | 901 | &callproc->h245Address); |
| 902 | if (ret < 0) | 902 | if (ret < 0) |
| 903 | return -1; | 903 | return -1; |
| @@ -905,7 +905,7 @@ static int process_callproceeding(struct sk_buff **pskb, | |||
| 905 | 905 | ||
| 906 | if (callproc->options & eCallProceeding_UUIE_fastStart) { | 906 | if (callproc->options & eCallProceeding_UUIE_fastStart) { |
| 907 | for (i = 0; i < callproc->fastStart.count; i++) { | 907 | for (i = 0; i < callproc->fastStart.count; i++) { |
| 908 | ret = process_olc(pskb, ct, ctinfo, data, dataoff, | 908 | ret = process_olc(skb, ct, ctinfo, data, dataoff, |
| 909 | &callproc->fastStart.item[i]); | 909 | &callproc->fastStart.item[i]); |
| 910 | if (ret < 0) | 910 | if (ret < 0) |
| 911 | return -1; | 911 | return -1; |
| @@ -916,7 +916,7 @@ static int process_callproceeding(struct sk_buff **pskb, | |||
| 916 | } | 916 | } |
| 917 | 917 | ||
| 918 | /****************************************************************************/ | 918 | /****************************************************************************/ |
| 919 | static int process_connect(struct sk_buff **pskb, struct nf_conn *ct, | 919 | static int process_connect(struct sk_buff *skb, struct nf_conn *ct, |
| 920 | enum ip_conntrack_info ctinfo, | 920 | enum ip_conntrack_info ctinfo, |
| 921 | unsigned char **data, int dataoff, | 921 | unsigned char **data, int dataoff, |
| 922 | Connect_UUIE *connect) | 922 | Connect_UUIE *connect) |
| @@ -927,7 +927,7 @@ static int process_connect(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 927 | pr_debug("nf_ct_q931: Connect\n"); | 927 | pr_debug("nf_ct_q931: Connect\n"); |
| 928 | 928 | ||
| 929 | if (connect->options & eConnect_UUIE_h245Address) { | 929 | if (connect->options & eConnect_UUIE_h245Address) { |
| 930 | ret = expect_h245(pskb, ct, ctinfo, data, dataoff, | 930 | ret = expect_h245(skb, ct, ctinfo, data, dataoff, |
| 931 | &connect->h245Address); | 931 | &connect->h245Address); |
| 932 | if (ret < 0) | 932 | if (ret < 0) |
| 933 | return -1; | 933 | return -1; |
| @@ -935,7 +935,7 @@ static int process_connect(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 935 | 935 | ||
| 936 | if (connect->options & eConnect_UUIE_fastStart) { | 936 | if (connect->options & eConnect_UUIE_fastStart) { |
| 937 | for (i = 0; i < connect->fastStart.count; i++) { | 937 | for (i = 0; i < connect->fastStart.count; i++) { |
| 938 | ret = process_olc(pskb, ct, ctinfo, data, dataoff, | 938 | ret = process_olc(skb, ct, ctinfo, data, dataoff, |
| 939 | &connect->fastStart.item[i]); | 939 | &connect->fastStart.item[i]); |
| 940 | if (ret < 0) | 940 | if (ret < 0) |
| 941 | return -1; | 941 | return -1; |
| @@ -946,7 +946,7 @@ static int process_connect(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 946 | } | 946 | } |
| 947 | 947 | ||
| 948 | /****************************************************************************/ | 948 | /****************************************************************************/ |
| 949 | static int process_alerting(struct sk_buff **pskb, struct nf_conn *ct, | 949 | static int process_alerting(struct sk_buff *skb, struct nf_conn *ct, |
| 950 | enum ip_conntrack_info ctinfo, | 950 | enum ip_conntrack_info ctinfo, |
| 951 | unsigned char **data, int dataoff, | 951 | unsigned char **data, int dataoff, |
| 952 | Alerting_UUIE *alert) | 952 | Alerting_UUIE *alert) |
| @@ -957,7 +957,7 @@ static int process_alerting(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 957 | pr_debug("nf_ct_q931: Alerting\n"); | 957 | pr_debug("nf_ct_q931: Alerting\n"); |
| 958 | 958 | ||
| 959 | if (alert->options & eAlerting_UUIE_h245Address) { | 959 | if (alert->options & eAlerting_UUIE_h245Address) { |
| 960 | ret = expect_h245(pskb, ct, ctinfo, data, dataoff, | 960 | ret = expect_h245(skb, ct, ctinfo, data, dataoff, |
| 961 | &alert->h245Address); | 961 | &alert->h245Address); |
| 962 | if (ret < 0) | 962 | if (ret < 0) |
| 963 | return -1; | 963 | return -1; |
| @@ -965,7 +965,7 @@ static int process_alerting(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 965 | 965 | ||
| 966 | if (alert->options & eAlerting_UUIE_fastStart) { | 966 | if (alert->options & eAlerting_UUIE_fastStart) { |
| 967 | for (i = 0; i < alert->fastStart.count; i++) { | 967 | for (i = 0; i < alert->fastStart.count; i++) { |
| 968 | ret = process_olc(pskb, ct, ctinfo, data, dataoff, | 968 | ret = process_olc(skb, ct, ctinfo, data, dataoff, |
| 969 | &alert->fastStart.item[i]); | 969 | &alert->fastStart.item[i]); |
| 970 | if (ret < 0) | 970 | if (ret < 0) |
| 971 | return -1; | 971 | return -1; |
| @@ -976,7 +976,7 @@ static int process_alerting(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 976 | } | 976 | } |
| 977 | 977 | ||
| 978 | /****************************************************************************/ | 978 | /****************************************************************************/ |
| 979 | static int process_facility(struct sk_buff **pskb, struct nf_conn *ct, | 979 | static int process_facility(struct sk_buff *skb, struct nf_conn *ct, |
| 980 | enum ip_conntrack_info ctinfo, | 980 | enum ip_conntrack_info ctinfo, |
| 981 | unsigned char **data, int dataoff, | 981 | unsigned char **data, int dataoff, |
| 982 | Facility_UUIE *facility) | 982 | Facility_UUIE *facility) |
| @@ -988,7 +988,7 @@ static int process_facility(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 988 | 988 | ||
| 989 | if (facility->reason.choice == eFacilityReason_callForwarded) { | 989 | if (facility->reason.choice == eFacilityReason_callForwarded) { |
| 990 | if (facility->options & eFacility_UUIE_alternativeAddress) | 990 | if (facility->options & eFacility_UUIE_alternativeAddress) |
| 991 | return expect_callforwarding(pskb, ct, ctinfo, data, | 991 | return expect_callforwarding(skb, ct, ctinfo, data, |
| 992 | dataoff, | 992 | dataoff, |
| 993 | &facility-> | 993 | &facility-> |
| 994 | alternativeAddress); | 994 | alternativeAddress); |
| @@ -996,7 +996,7 @@ static int process_facility(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 996 | } | 996 | } |
| 997 | 997 | ||
| 998 | if (facility->options & eFacility_UUIE_h245Address) { | 998 | if (facility->options & eFacility_UUIE_h245Address) { |
| 999 | ret = expect_h245(pskb, ct, ctinfo, data, dataoff, | 999 | ret = expect_h245(skb, ct, ctinfo, data, dataoff, |
| 1000 | &facility->h245Address); | 1000 | &facility->h245Address); |
| 1001 | if (ret < 0) | 1001 | if (ret < 0) |
| 1002 | return -1; | 1002 | return -1; |
| @@ -1004,7 +1004,7 @@ static int process_facility(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1004 | 1004 | ||
| 1005 | if (facility->options & eFacility_UUIE_fastStart) { | 1005 | if (facility->options & eFacility_UUIE_fastStart) { |
| 1006 | for (i = 0; i < facility->fastStart.count; i++) { | 1006 | for (i = 0; i < facility->fastStart.count; i++) { |
| 1007 | ret = process_olc(pskb, ct, ctinfo, data, dataoff, | 1007 | ret = process_olc(skb, ct, ctinfo, data, dataoff, |
| 1008 | &facility->fastStart.item[i]); | 1008 | &facility->fastStart.item[i]); |
| 1009 | if (ret < 0) | 1009 | if (ret < 0) |
| 1010 | return -1; | 1010 | return -1; |
| @@ -1015,7 +1015,7 @@ static int process_facility(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1015 | } | 1015 | } |
| 1016 | 1016 | ||
| 1017 | /****************************************************************************/ | 1017 | /****************************************************************************/ |
| 1018 | static int process_progress(struct sk_buff **pskb, struct nf_conn *ct, | 1018 | static int process_progress(struct sk_buff *skb, struct nf_conn *ct, |
| 1019 | enum ip_conntrack_info ctinfo, | 1019 | enum ip_conntrack_info ctinfo, |
| 1020 | unsigned char **data, int dataoff, | 1020 | unsigned char **data, int dataoff, |
| 1021 | Progress_UUIE *progress) | 1021 | Progress_UUIE *progress) |
| @@ -1026,7 +1026,7 @@ static int process_progress(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1026 | pr_debug("nf_ct_q931: Progress\n"); | 1026 | pr_debug("nf_ct_q931: Progress\n"); |
| 1027 | 1027 | ||
| 1028 | if (progress->options & eProgress_UUIE_h245Address) { | 1028 | if (progress->options & eProgress_UUIE_h245Address) { |
| 1029 | ret = expect_h245(pskb, ct, ctinfo, data, dataoff, | 1029 | ret = expect_h245(skb, ct, ctinfo, data, dataoff, |
| 1030 | &progress->h245Address); | 1030 | &progress->h245Address); |
| 1031 | if (ret < 0) | 1031 | if (ret < 0) |
| 1032 | return -1; | 1032 | return -1; |
| @@ -1034,7 +1034,7 @@ static int process_progress(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1034 | 1034 | ||
| 1035 | if (progress->options & eProgress_UUIE_fastStart) { | 1035 | if (progress->options & eProgress_UUIE_fastStart) { |
| 1036 | for (i = 0; i < progress->fastStart.count; i++) { | 1036 | for (i = 0; i < progress->fastStart.count; i++) { |
| 1037 | ret = process_olc(pskb, ct, ctinfo, data, dataoff, | 1037 | ret = process_olc(skb, ct, ctinfo, data, dataoff, |
| 1038 | &progress->fastStart.item[i]); | 1038 | &progress->fastStart.item[i]); |
| 1039 | if (ret < 0) | 1039 | if (ret < 0) |
| 1040 | return -1; | 1040 | return -1; |
| @@ -1045,7 +1045,7 @@ static int process_progress(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1045 | } | 1045 | } |
| 1046 | 1046 | ||
| 1047 | /****************************************************************************/ | 1047 | /****************************************************************************/ |
| 1048 | static int process_q931(struct sk_buff **pskb, struct nf_conn *ct, | 1048 | static int process_q931(struct sk_buff *skb, struct nf_conn *ct, |
| 1049 | enum ip_conntrack_info ctinfo, | 1049 | enum ip_conntrack_info ctinfo, |
| 1050 | unsigned char **data, int dataoff, Q931 *q931) | 1050 | unsigned char **data, int dataoff, Q931 *q931) |
| 1051 | { | 1051 | { |
| @@ -1055,28 +1055,28 @@ static int process_q931(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1055 | 1055 | ||
| 1056 | switch (pdu->h323_message_body.choice) { | 1056 | switch (pdu->h323_message_body.choice) { |
| 1057 | case eH323_UU_PDU_h323_message_body_setup: | 1057 | case eH323_UU_PDU_h323_message_body_setup: |
| 1058 | ret = process_setup(pskb, ct, ctinfo, data, dataoff, | 1058 | ret = process_setup(skb, ct, ctinfo, data, dataoff, |
| 1059 | &pdu->h323_message_body.setup); | 1059 | &pdu->h323_message_body.setup); |
| 1060 | break; | 1060 | break; |
| 1061 | case eH323_UU_PDU_h323_message_body_callProceeding: | 1061 | case eH323_UU_PDU_h323_message_body_callProceeding: |
| 1062 | ret = process_callproceeding(pskb, ct, ctinfo, data, dataoff, | 1062 | ret = process_callproceeding(skb, ct, ctinfo, data, dataoff, |
| 1063 | &pdu->h323_message_body. | 1063 | &pdu->h323_message_body. |
| 1064 | callProceeding); | 1064 | callProceeding); |
| 1065 | break; | 1065 | break; |
| 1066 | case eH323_UU_PDU_h323_message_body_connect: | 1066 | case eH323_UU_PDU_h323_message_body_connect: |
| 1067 | ret = process_connect(pskb, ct, ctinfo, data, dataoff, | 1067 | ret = process_connect(skb, ct, ctinfo, data, dataoff, |
| 1068 | &pdu->h323_message_body.connect); | 1068 | &pdu->h323_message_body.connect); |
| 1069 | break; | 1069 | break; |
| 1070 | case eH323_UU_PDU_h323_message_body_alerting: | 1070 | case eH323_UU_PDU_h323_message_body_alerting: |
| 1071 | ret = process_alerting(pskb, ct, ctinfo, data, dataoff, | 1071 | ret = process_alerting(skb, ct, ctinfo, data, dataoff, |
| 1072 | &pdu->h323_message_body.alerting); | 1072 | &pdu->h323_message_body.alerting); |
| 1073 | break; | 1073 | break; |
| 1074 | case eH323_UU_PDU_h323_message_body_facility: | 1074 | case eH323_UU_PDU_h323_message_body_facility: |
| 1075 | ret = process_facility(pskb, ct, ctinfo, data, dataoff, | 1075 | ret = process_facility(skb, ct, ctinfo, data, dataoff, |
| 1076 | &pdu->h323_message_body.facility); | 1076 | &pdu->h323_message_body.facility); |
| 1077 | break; | 1077 | break; |
| 1078 | case eH323_UU_PDU_h323_message_body_progress: | 1078 | case eH323_UU_PDU_h323_message_body_progress: |
| 1079 | ret = process_progress(pskb, ct, ctinfo, data, dataoff, | 1079 | ret = process_progress(skb, ct, ctinfo, data, dataoff, |
| 1080 | &pdu->h323_message_body.progress); | 1080 | &pdu->h323_message_body.progress); |
| 1081 | break; | 1081 | break; |
| 1082 | default: | 1082 | default: |
| @@ -1090,7 +1090,7 @@ static int process_q931(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1090 | 1090 | ||
| 1091 | if (pdu->options & eH323_UU_PDU_h245Control) { | 1091 | if (pdu->options & eH323_UU_PDU_h245Control) { |
| 1092 | for (i = 0; i < pdu->h245Control.count; i++) { | 1092 | for (i = 0; i < pdu->h245Control.count; i++) { |
| 1093 | ret = process_h245(pskb, ct, ctinfo, data, dataoff, | 1093 | ret = process_h245(skb, ct, ctinfo, data, dataoff, |
| 1094 | &pdu->h245Control.item[i]); | 1094 | &pdu->h245Control.item[i]); |
| 1095 | if (ret < 0) | 1095 | if (ret < 0) |
| 1096 | return -1; | 1096 | return -1; |
| @@ -1101,7 +1101,7 @@ static int process_q931(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1101 | } | 1101 | } |
| 1102 | 1102 | ||
| 1103 | /****************************************************************************/ | 1103 | /****************************************************************************/ |
| 1104 | static int q931_help(struct sk_buff **pskb, unsigned int protoff, | 1104 | static int q931_help(struct sk_buff *skb, unsigned int protoff, |
| 1105 | struct nf_conn *ct, enum ip_conntrack_info ctinfo) | 1105 | struct nf_conn *ct, enum ip_conntrack_info ctinfo) |
| 1106 | { | 1106 | { |
| 1107 | static Q931 q931; | 1107 | static Q931 q931; |
| @@ -1115,12 +1115,12 @@ static int q931_help(struct sk_buff **pskb, unsigned int protoff, | |||
| 1115 | ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { | 1115 | ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { |
| 1116 | return NF_ACCEPT; | 1116 | return NF_ACCEPT; |
| 1117 | } | 1117 | } |
| 1118 | pr_debug("nf_ct_q931: skblen = %u\n", (*pskb)->len); | 1118 | pr_debug("nf_ct_q931: skblen = %u\n", skb->len); |
| 1119 | 1119 | ||
| 1120 | spin_lock_bh(&nf_h323_lock); | 1120 | spin_lock_bh(&nf_h323_lock); |
| 1121 | 1121 | ||
| 1122 | /* Process each TPKT */ | 1122 | /* Process each TPKT */ |
| 1123 | while (get_tpkt_data(pskb, protoff, ct, ctinfo, | 1123 | while (get_tpkt_data(skb, protoff, ct, ctinfo, |
| 1124 | &data, &datalen, &dataoff)) { | 1124 | &data, &datalen, &dataoff)) { |
| 1125 | pr_debug("nf_ct_q931: TPKT len=%d ", datalen); | 1125 | pr_debug("nf_ct_q931: TPKT len=%d ", datalen); |
| 1126 | NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple); | 1126 | NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple); |
| @@ -1136,7 +1136,7 @@ static int q931_help(struct sk_buff **pskb, unsigned int protoff, | |||
| 1136 | } | 1136 | } |
| 1137 | 1137 | ||
| 1138 | /* Process Q.931 signal */ | 1138 | /* Process Q.931 signal */ |
| 1139 | if (process_q931(pskb, ct, ctinfo, &data, dataoff, &q931) < 0) | 1139 | if (process_q931(skb, ct, ctinfo, &data, dataoff, &q931) < 0) |
| 1140 | goto drop; | 1140 | goto drop; |
| 1141 | } | 1141 | } |
| 1142 | 1142 | ||
| @@ -1177,20 +1177,20 @@ static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = { | |||
| 1177 | }; | 1177 | }; |
| 1178 | 1178 | ||
| 1179 | /****************************************************************************/ | 1179 | /****************************************************************************/ |
| 1180 | static unsigned char *get_udp_data(struct sk_buff **pskb, unsigned int protoff, | 1180 | static unsigned char *get_udp_data(struct sk_buff *skb, unsigned int protoff, |
| 1181 | int *datalen) | 1181 | int *datalen) |
| 1182 | { | 1182 | { |
| 1183 | struct udphdr _uh, *uh; | 1183 | struct udphdr _uh, *uh; |
| 1184 | int dataoff; | 1184 | int dataoff; |
| 1185 | 1185 | ||
| 1186 | uh = skb_header_pointer(*pskb, protoff, sizeof(_uh), &_uh); | 1186 | uh = skb_header_pointer(skb, protoff, sizeof(_uh), &_uh); |
| 1187 | if (uh == NULL) | 1187 | if (uh == NULL) |
| 1188 | return NULL; | 1188 | return NULL; |
| 1189 | dataoff = protoff + sizeof(_uh); | 1189 | dataoff = protoff + sizeof(_uh); |
| 1190 | if (dataoff >= (*pskb)->len) | 1190 | if (dataoff >= skb->len) |
| 1191 | return NULL; | 1191 | return NULL; |
| 1192 | *datalen = (*pskb)->len - dataoff; | 1192 | *datalen = skb->len - dataoff; |
| 1193 | return skb_header_pointer(*pskb, dataoff, *datalen, h323_buffer); | 1193 | return skb_header_pointer(skb, dataoff, *datalen, h323_buffer); |
| 1194 | } | 1194 | } |
| 1195 | 1195 | ||
| 1196 | /****************************************************************************/ | 1196 | /****************************************************************************/ |
| @@ -1227,7 +1227,7 @@ static int set_expect_timeout(struct nf_conntrack_expect *exp, | |||
| 1227 | } | 1227 | } |
| 1228 | 1228 | ||
| 1229 | /****************************************************************************/ | 1229 | /****************************************************************************/ |
| 1230 | static int expect_q931(struct sk_buff **pskb, struct nf_conn *ct, | 1230 | static int expect_q931(struct sk_buff *skb, struct nf_conn *ct, |
| 1231 | enum ip_conntrack_info ctinfo, | 1231 | enum ip_conntrack_info ctinfo, |
| 1232 | unsigned char **data, | 1232 | unsigned char **data, |
| 1233 | TransportAddress *taddr, int count) | 1233 | TransportAddress *taddr, int count) |
| @@ -1265,7 +1265,7 @@ static int expect_q931(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1265 | 1265 | ||
| 1266 | nat_q931 = rcu_dereference(nat_q931_hook); | 1266 | nat_q931 = rcu_dereference(nat_q931_hook); |
| 1267 | if (nat_q931 && ct->status & IPS_NAT_MASK) { /* Need NAT */ | 1267 | if (nat_q931 && ct->status & IPS_NAT_MASK) { /* Need NAT */ |
| 1268 | ret = nat_q931(pskb, ct, ctinfo, data, taddr, i, port, exp); | 1268 | ret = nat_q931(skb, ct, ctinfo, data, taddr, i, port, exp); |
| 1269 | } else { /* Conntrack only */ | 1269 | } else { /* Conntrack only */ |
| 1270 | if (nf_ct_expect_related(exp) == 0) { | 1270 | if (nf_ct_expect_related(exp) == 0) { |
| 1271 | pr_debug("nf_ct_ras: expect Q.931 "); | 1271 | pr_debug("nf_ct_ras: expect Q.931 "); |
| @@ -1283,7 +1283,7 @@ static int expect_q931(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1283 | } | 1283 | } |
| 1284 | 1284 | ||
| 1285 | /****************************************************************************/ | 1285 | /****************************************************************************/ |
| 1286 | static int process_grq(struct sk_buff **pskb, struct nf_conn *ct, | 1286 | static int process_grq(struct sk_buff *skb, struct nf_conn *ct, |
| 1287 | enum ip_conntrack_info ctinfo, | 1287 | enum ip_conntrack_info ctinfo, |
| 1288 | unsigned char **data, GatekeeperRequest *grq) | 1288 | unsigned char **data, GatekeeperRequest *grq) |
| 1289 | { | 1289 | { |
| @@ -1293,13 +1293,13 @@ static int process_grq(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1293 | 1293 | ||
| 1294 | set_ras_addr = rcu_dereference(set_ras_addr_hook); | 1294 | set_ras_addr = rcu_dereference(set_ras_addr_hook); |
| 1295 | if (set_ras_addr && ct->status & IPS_NAT_MASK) /* NATed */ | 1295 | if (set_ras_addr && ct->status & IPS_NAT_MASK) /* NATed */ |
| 1296 | return set_ras_addr(pskb, ct, ctinfo, data, | 1296 | return set_ras_addr(skb, ct, ctinfo, data, |
| 1297 | &grq->rasAddress, 1); | 1297 | &grq->rasAddress, 1); |
| 1298 | return 0; | 1298 | return 0; |
| 1299 | } | 1299 | } |
| 1300 | 1300 | ||
| 1301 | /****************************************************************************/ | 1301 | /****************************************************************************/ |
| 1302 | static int process_gcf(struct sk_buff **pskb, struct nf_conn *ct, | 1302 | static int process_gcf(struct sk_buff *skb, struct nf_conn *ct, |
| 1303 | enum ip_conntrack_info ctinfo, | 1303 | enum ip_conntrack_info ctinfo, |
| 1304 | unsigned char **data, GatekeeperConfirm *gcf) | 1304 | unsigned char **data, GatekeeperConfirm *gcf) |
| 1305 | { | 1305 | { |
| @@ -1343,7 +1343,7 @@ static int process_gcf(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1343 | } | 1343 | } |
| 1344 | 1344 | ||
| 1345 | /****************************************************************************/ | 1345 | /****************************************************************************/ |
| 1346 | static int process_rrq(struct sk_buff **pskb, struct nf_conn *ct, | 1346 | static int process_rrq(struct sk_buff *skb, struct nf_conn *ct, |
| 1347 | enum ip_conntrack_info ctinfo, | 1347 | enum ip_conntrack_info ctinfo, |
| 1348 | unsigned char **data, RegistrationRequest *rrq) | 1348 | unsigned char **data, RegistrationRequest *rrq) |
| 1349 | { | 1349 | { |
| @@ -1353,7 +1353,7 @@ static int process_rrq(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1353 | 1353 | ||
| 1354 | pr_debug("nf_ct_ras: RRQ\n"); | 1354 | pr_debug("nf_ct_ras: RRQ\n"); |
| 1355 | 1355 | ||
| 1356 | ret = expect_q931(pskb, ct, ctinfo, data, | 1356 | ret = expect_q931(skb, ct, ctinfo, data, |
| 1357 | rrq->callSignalAddress.item, | 1357 | rrq->callSignalAddress.item, |
| 1358 | rrq->callSignalAddress.count); | 1358 | rrq->callSignalAddress.count); |
| 1359 | if (ret < 0) | 1359 | if (ret < 0) |
| @@ -1361,7 +1361,7 @@ static int process_rrq(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1361 | 1361 | ||
| 1362 | set_ras_addr = rcu_dereference(set_ras_addr_hook); | 1362 | set_ras_addr = rcu_dereference(set_ras_addr_hook); |
| 1363 | if (set_ras_addr && ct->status & IPS_NAT_MASK) { | 1363 | if (set_ras_addr && ct->status & IPS_NAT_MASK) { |
| 1364 | ret = set_ras_addr(pskb, ct, ctinfo, data, | 1364 | ret = set_ras_addr(skb, ct, ctinfo, data, |
| 1365 | rrq->rasAddress.item, | 1365 | rrq->rasAddress.item, |
| 1366 | rrq->rasAddress.count); | 1366 | rrq->rasAddress.count); |
| 1367 | if (ret < 0) | 1367 | if (ret < 0) |
| @@ -1378,7 +1378,7 @@ static int process_rrq(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1378 | } | 1378 | } |
| 1379 | 1379 | ||
| 1380 | /****************************************************************************/ | 1380 | /****************************************************************************/ |
| 1381 | static int process_rcf(struct sk_buff **pskb, struct nf_conn *ct, | 1381 | static int process_rcf(struct sk_buff *skb, struct nf_conn *ct, |
| 1382 | enum ip_conntrack_info ctinfo, | 1382 | enum ip_conntrack_info ctinfo, |
| 1383 | unsigned char **data, RegistrationConfirm *rcf) | 1383 | unsigned char **data, RegistrationConfirm *rcf) |
| 1384 | { | 1384 | { |
| @@ -1392,7 +1392,7 @@ static int process_rcf(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1392 | 1392 | ||
| 1393 | set_sig_addr = rcu_dereference(set_sig_addr_hook); | 1393 | set_sig_addr = rcu_dereference(set_sig_addr_hook); |
| 1394 | if (set_sig_addr && ct->status & IPS_NAT_MASK) { | 1394 | if (set_sig_addr && ct->status & IPS_NAT_MASK) { |
| 1395 | ret = set_sig_addr(pskb, ct, ctinfo, data, | 1395 | ret = set_sig_addr(skb, ct, ctinfo, data, |
| 1396 | rcf->callSignalAddress.item, | 1396 | rcf->callSignalAddress.item, |
| 1397 | rcf->callSignalAddress.count); | 1397 | rcf->callSignalAddress.count); |
| 1398 | if (ret < 0) | 1398 | if (ret < 0) |
| @@ -1407,7 +1407,7 @@ static int process_rcf(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1407 | if (info->timeout > 0) { | 1407 | if (info->timeout > 0) { |
| 1408 | pr_debug("nf_ct_ras: set RAS connection timeout to " | 1408 | pr_debug("nf_ct_ras: set RAS connection timeout to " |
| 1409 | "%u seconds\n", info->timeout); | 1409 | "%u seconds\n", info->timeout); |
| 1410 | nf_ct_refresh(ct, *pskb, info->timeout * HZ); | 1410 | nf_ct_refresh(ct, skb, info->timeout * HZ); |
| 1411 | 1411 | ||
| 1412 | /* Set expect timeout */ | 1412 | /* Set expect timeout */ |
| 1413 | read_lock_bh(&nf_conntrack_lock); | 1413 | read_lock_bh(&nf_conntrack_lock); |
| @@ -1427,7 +1427,7 @@ static int process_rcf(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1427 | } | 1427 | } |
| 1428 | 1428 | ||
| 1429 | /****************************************************************************/ | 1429 | /****************************************************************************/ |
| 1430 | static int process_urq(struct sk_buff **pskb, struct nf_conn *ct, | 1430 | static int process_urq(struct sk_buff *skb, struct nf_conn *ct, |
| 1431 | enum ip_conntrack_info ctinfo, | 1431 | enum ip_conntrack_info ctinfo, |
| 1432 | unsigned char **data, UnregistrationRequest *urq) | 1432 | unsigned char **data, UnregistrationRequest *urq) |
| 1433 | { | 1433 | { |
| @@ -1440,7 +1440,7 @@ static int process_urq(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1440 | 1440 | ||
| 1441 | set_sig_addr = rcu_dereference(set_sig_addr_hook); | 1441 | set_sig_addr = rcu_dereference(set_sig_addr_hook); |
| 1442 | if (set_sig_addr && ct->status & IPS_NAT_MASK) { | 1442 | if (set_sig_addr && ct->status & IPS_NAT_MASK) { |
| 1443 | ret = set_sig_addr(pskb, ct, ctinfo, data, | 1443 | ret = set_sig_addr(skb, ct, ctinfo, data, |
| 1444 | urq->callSignalAddress.item, | 1444 | urq->callSignalAddress.item, |
| 1445 | urq->callSignalAddress.count); | 1445 | urq->callSignalAddress.count); |
| 1446 | if (ret < 0) | 1446 | if (ret < 0) |
| @@ -1453,13 +1453,13 @@ static int process_urq(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1453 | info->sig_port[!dir] = 0; | 1453 | info->sig_port[!dir] = 0; |
| 1454 | 1454 | ||
| 1455 | /* Give it 30 seconds for UCF or URJ */ | 1455 | /* Give it 30 seconds for UCF or URJ */ |
| 1456 | nf_ct_refresh(ct, *pskb, 30 * HZ); | 1456 | nf_ct_refresh(ct, skb, 30 * HZ); |
| 1457 | 1457 | ||
| 1458 | return 0; | 1458 | return 0; |
| 1459 | } | 1459 | } |
| 1460 | 1460 | ||
| 1461 | /****************************************************************************/ | 1461 | /****************************************************************************/ |
| 1462 | static int process_arq(struct sk_buff **pskb, struct nf_conn *ct, | 1462 | static int process_arq(struct sk_buff *skb, struct nf_conn *ct, |
| 1463 | enum ip_conntrack_info ctinfo, | 1463 | enum ip_conntrack_info ctinfo, |
| 1464 | unsigned char **data, AdmissionRequest *arq) | 1464 | unsigned char **data, AdmissionRequest *arq) |
| 1465 | { | 1465 | { |
| @@ -1479,7 +1479,7 @@ static int process_arq(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1479 | port == info->sig_port[dir] && | 1479 | port == info->sig_port[dir] && |
| 1480 | set_h225_addr && ct->status & IPS_NAT_MASK) { | 1480 | set_h225_addr && ct->status & IPS_NAT_MASK) { |
| 1481 | /* Answering ARQ */ | 1481 | /* Answering ARQ */ |
| 1482 | return set_h225_addr(pskb, data, 0, | 1482 | return set_h225_addr(skb, data, 0, |
| 1483 | &arq->destCallSignalAddress, | 1483 | &arq->destCallSignalAddress, |
| 1484 | &ct->tuplehash[!dir].tuple.dst.u3, | 1484 | &ct->tuplehash[!dir].tuple.dst.u3, |
| 1485 | info->sig_port[!dir]); | 1485 | info->sig_port[!dir]); |
| @@ -1491,7 +1491,7 @@ static int process_arq(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1491 | !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) && | 1491 | !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) && |
| 1492 | set_h225_addr && ct->status & IPS_NAT_MASK) { | 1492 | set_h225_addr && ct->status & IPS_NAT_MASK) { |
| 1493 | /* Calling ARQ */ | 1493 | /* Calling ARQ */ |
| 1494 | return set_h225_addr(pskb, data, 0, | 1494 | return set_h225_addr(skb, data, 0, |
| 1495 | &arq->srcCallSignalAddress, | 1495 | &arq->srcCallSignalAddress, |
| 1496 | &ct->tuplehash[!dir].tuple.dst.u3, | 1496 | &ct->tuplehash[!dir].tuple.dst.u3, |
| 1497 | port); | 1497 | port); |
| @@ -1501,7 +1501,7 @@ static int process_arq(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1501 | } | 1501 | } |
| 1502 | 1502 | ||
| 1503 | /****************************************************************************/ | 1503 | /****************************************************************************/ |
| 1504 | static int process_acf(struct sk_buff **pskb, struct nf_conn *ct, | 1504 | static int process_acf(struct sk_buff *skb, struct nf_conn *ct, |
| 1505 | enum ip_conntrack_info ctinfo, | 1505 | enum ip_conntrack_info ctinfo, |
| 1506 | unsigned char **data, AdmissionConfirm *acf) | 1506 | unsigned char **data, AdmissionConfirm *acf) |
| 1507 | { | 1507 | { |
| @@ -1522,7 +1522,7 @@ static int process_acf(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1522 | /* Answering ACF */ | 1522 | /* Answering ACF */ |
| 1523 | set_sig_addr = rcu_dereference(set_sig_addr_hook); | 1523 | set_sig_addr = rcu_dereference(set_sig_addr_hook); |
| 1524 | if (set_sig_addr && ct->status & IPS_NAT_MASK) | 1524 | if (set_sig_addr && ct->status & IPS_NAT_MASK) |
| 1525 | return set_sig_addr(pskb, ct, ctinfo, data, | 1525 | return set_sig_addr(skb, ct, ctinfo, data, |
| 1526 | &acf->destCallSignalAddress, 1); | 1526 | &acf->destCallSignalAddress, 1); |
| 1527 | return 0; | 1527 | return 0; |
| 1528 | } | 1528 | } |
| @@ -1548,7 +1548,7 @@ static int process_acf(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1548 | } | 1548 | } |
| 1549 | 1549 | ||
| 1550 | /****************************************************************************/ | 1550 | /****************************************************************************/ |
| 1551 | static int process_lrq(struct sk_buff **pskb, struct nf_conn *ct, | 1551 | static int process_lrq(struct sk_buff *skb, struct nf_conn *ct, |
| 1552 | enum ip_conntrack_info ctinfo, | 1552 | enum ip_conntrack_info ctinfo, |
| 1553 | unsigned char **data, LocationRequest *lrq) | 1553 | unsigned char **data, LocationRequest *lrq) |
| 1554 | { | 1554 | { |
| @@ -1558,13 +1558,13 @@ static int process_lrq(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1558 | 1558 | ||
| 1559 | set_ras_addr = rcu_dereference(set_ras_addr_hook); | 1559 | set_ras_addr = rcu_dereference(set_ras_addr_hook); |
| 1560 | if (set_ras_addr && ct->status & IPS_NAT_MASK) | 1560 | if (set_ras_addr && ct->status & IPS_NAT_MASK) |
| 1561 | return set_ras_addr(pskb, ct, ctinfo, data, | 1561 | return set_ras_addr(skb, ct, ctinfo, data, |
| 1562 | &lrq->replyAddress, 1); | 1562 | &lrq->replyAddress, 1); |
| 1563 | return 0; | 1563 | return 0; |
| 1564 | } | 1564 | } |
| 1565 | 1565 | ||
| 1566 | /****************************************************************************/ | 1566 | /****************************************************************************/ |
| 1567 | static int process_lcf(struct sk_buff **pskb, struct nf_conn *ct, | 1567 | static int process_lcf(struct sk_buff *skb, struct nf_conn *ct, |
| 1568 | enum ip_conntrack_info ctinfo, | 1568 | enum ip_conntrack_info ctinfo, |
| 1569 | unsigned char **data, LocationConfirm *lcf) | 1569 | unsigned char **data, LocationConfirm *lcf) |
| 1570 | { | 1570 | { |
| @@ -1603,7 +1603,7 @@ static int process_lcf(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1603 | } | 1603 | } |
| 1604 | 1604 | ||
| 1605 | /****************************************************************************/ | 1605 | /****************************************************************************/ |
| 1606 | static int process_irr(struct sk_buff **pskb, struct nf_conn *ct, | 1606 | static int process_irr(struct sk_buff *skb, struct nf_conn *ct, |
| 1607 | enum ip_conntrack_info ctinfo, | 1607 | enum ip_conntrack_info ctinfo, |
| 1608 | unsigned char **data, InfoRequestResponse *irr) | 1608 | unsigned char **data, InfoRequestResponse *irr) |
| 1609 | { | 1609 | { |
| @@ -1615,7 +1615,7 @@ static int process_irr(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1615 | 1615 | ||
| 1616 | set_ras_addr = rcu_dereference(set_ras_addr_hook); | 1616 | set_ras_addr = rcu_dereference(set_ras_addr_hook); |
| 1617 | if (set_ras_addr && ct->status & IPS_NAT_MASK) { | 1617 | if (set_ras_addr && ct->status & IPS_NAT_MASK) { |
| 1618 | ret = set_ras_addr(pskb, ct, ctinfo, data, | 1618 | ret = set_ras_addr(skb, ct, ctinfo, data, |
| 1619 | &irr->rasAddress, 1); | 1619 | &irr->rasAddress, 1); |
| 1620 | if (ret < 0) | 1620 | if (ret < 0) |
| 1621 | return -1; | 1621 | return -1; |
| @@ -1623,7 +1623,7 @@ static int process_irr(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1623 | 1623 | ||
| 1624 | set_sig_addr = rcu_dereference(set_sig_addr_hook); | 1624 | set_sig_addr = rcu_dereference(set_sig_addr_hook); |
| 1625 | if (set_sig_addr && ct->status & IPS_NAT_MASK) { | 1625 | if (set_sig_addr && ct->status & IPS_NAT_MASK) { |
| 1626 | ret = set_sig_addr(pskb, ct, ctinfo, data, | 1626 | ret = set_sig_addr(skb, ct, ctinfo, data, |
| 1627 | irr->callSignalAddress.item, | 1627 | irr->callSignalAddress.item, |
| 1628 | irr->callSignalAddress.count); | 1628 | irr->callSignalAddress.count); |
| 1629 | if (ret < 0) | 1629 | if (ret < 0) |
| @@ -1634,40 +1634,40 @@ static int process_irr(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1634 | } | 1634 | } |
| 1635 | 1635 | ||
| 1636 | /****************************************************************************/ | 1636 | /****************************************************************************/ |
| 1637 | static int process_ras(struct sk_buff **pskb, struct nf_conn *ct, | 1637 | static int process_ras(struct sk_buff *skb, struct nf_conn *ct, |
| 1638 | enum ip_conntrack_info ctinfo, | 1638 | enum ip_conntrack_info ctinfo, |
| 1639 | unsigned char **data, RasMessage *ras) | 1639 | unsigned char **data, RasMessage *ras) |
| 1640 | { | 1640 | { |
| 1641 | switch (ras->choice) { | 1641 | switch (ras->choice) { |
| 1642 | case eRasMessage_gatekeeperRequest: | 1642 | case eRasMessage_gatekeeperRequest: |
| 1643 | return process_grq(pskb, ct, ctinfo, data, | 1643 | return process_grq(skb, ct, ctinfo, data, |
| 1644 | &ras->gatekeeperRequest); | 1644 | &ras->gatekeeperRequest); |
| 1645 | case eRasMessage_gatekeeperConfirm: | 1645 | case eRasMessage_gatekeeperConfirm: |
| 1646 | return process_gcf(pskb, ct, ctinfo, data, | 1646 | return process_gcf(skb, ct, ctinfo, data, |
| 1647 | &ras->gatekeeperConfirm); | 1647 | &ras->gatekeeperConfirm); |
| 1648 | case eRasMessage_registrationRequest: | 1648 | case eRasMessage_registrationRequest: |
| 1649 | return process_rrq(pskb, ct, ctinfo, data, | 1649 | return process_rrq(skb, ct, ctinfo, data, |
| 1650 | &ras->registrationRequest); | 1650 | &ras->registrationRequest); |
| 1651 | case eRasMessage_registrationConfirm: | 1651 | case eRasMessage_registrationConfirm: |
| 1652 | return process_rcf(pskb, ct, ctinfo, data, | 1652 | return process_rcf(skb, ct, ctinfo, data, |
| 1653 | &ras->registrationConfirm); | 1653 | &ras->registrationConfirm); |
| 1654 | case eRasMessage_unregistrationRequest: | 1654 | case eRasMessage_unregistrationRequest: |
| 1655 | return process_urq(pskb, ct, ctinfo, data, | 1655 | return process_urq(skb, ct, ctinfo, data, |
| 1656 | &ras->unregistrationRequest); | 1656 | &ras->unregistrationRequest); |
| 1657 | case eRasMessage_admissionRequest: | 1657 | case eRasMessage_admissionRequest: |
| 1658 | return process_arq(pskb, ct, ctinfo, data, | 1658 | return process_arq(skb, ct, ctinfo, data, |
| 1659 | &ras->admissionRequest); | 1659 | &ras->admissionRequest); |
| 1660 | case eRasMessage_admissionConfirm: | 1660 | case eRasMessage_admissionConfirm: |
| 1661 | return process_acf(pskb, ct, ctinfo, data, | 1661 | return process_acf(skb, ct, ctinfo, data, |
| 1662 | &ras->admissionConfirm); | 1662 | &ras->admissionConfirm); |
| 1663 | case eRasMessage_locationRequest: | 1663 | case eRasMessage_locationRequest: |
| 1664 | return process_lrq(pskb, ct, ctinfo, data, | 1664 | return process_lrq(skb, ct, ctinfo, data, |
| 1665 | &ras->locationRequest); | 1665 | &ras->locationRequest); |
| 1666 | case eRasMessage_locationConfirm: | 1666 | case eRasMessage_locationConfirm: |
| 1667 | return process_lcf(pskb, ct, ctinfo, data, | 1667 | return process_lcf(skb, ct, ctinfo, data, |
| 1668 | &ras->locationConfirm); | 1668 | &ras->locationConfirm); |
| 1669 | case eRasMessage_infoRequestResponse: | 1669 | case eRasMessage_infoRequestResponse: |
| 1670 | return process_irr(pskb, ct, ctinfo, data, | 1670 | return process_irr(skb, ct, ctinfo, data, |
| 1671 | &ras->infoRequestResponse); | 1671 | &ras->infoRequestResponse); |
| 1672 | default: | 1672 | default: |
| 1673 | pr_debug("nf_ct_ras: RAS message %d\n", ras->choice); | 1673 | pr_debug("nf_ct_ras: RAS message %d\n", ras->choice); |
| @@ -1678,7 +1678,7 @@ static int process_ras(struct sk_buff **pskb, struct nf_conn *ct, | |||
| 1678 | } | 1678 | } |
| 1679 | 1679 | ||
| 1680 | /****************************************************************************/ | 1680 | /****************************************************************************/ |
| 1681 | static int ras_help(struct sk_buff **pskb, unsigned int protoff, | 1681 | static int ras_help(struct sk_buff *skb, unsigned int protoff, |
| 1682 | struct nf_conn *ct, enum ip_conntrack_info ctinfo) | 1682 | struct nf_conn *ct, enum ip_conntrack_info ctinfo) |
| 1683 | { | 1683 | { |
| 1684 | static RasMessage ras; | 1684 | static RasMessage ras; |
| @@ -1686,12 +1686,12 @@ static int ras_help(struct sk_buff **pskb, unsigned int protoff, | |||
| 1686 | int datalen = 0; | 1686 | int datalen = 0; |
| 1687 | int ret; | 1687 | int ret; |
| 1688 | 1688 | ||
| 1689 | pr_debug("nf_ct_ras: skblen = %u\n", (*pskb)->len); | 1689 | pr_debug("nf_ct_ras: skblen = %u\n", skb->len); |
| 1690 | 1690 | ||
| 1691 | spin_lock_bh(&nf_h323_lock); | 1691 | spin_lock_bh(&nf_h323_lock); |
| 1692 | 1692 | ||
| 1693 | /* Get UDP data */ | 1693 | /* Get UDP data */ |
| 1694 | data = get_udp_data(pskb, protoff, &datalen); | 1694 | data = get_udp_data(skb, protoff, &datalen); |
| 1695 | if (data == NULL) | 1695 | if (data == NULL) |
| 1696 | goto accept; | 1696 | goto accept; |
| 1697 | pr_debug("nf_ct_ras: RAS message len=%d ", datalen); | 1697 | pr_debug("nf_ct_ras: RAS message len=%d ", datalen); |
| @@ -1707,7 +1707,7 @@ static int ras_help(struct sk_buff **pskb, unsigned int protoff, | |||
| 1707 | } | 1707 | } |
| 1708 | 1708 | ||
| 1709 | /* Process RAS message */ | 1709 | /* Process RAS message */ |
| 1710 | if (process_ras(pskb, ct, ctinfo, &data, &ras) < 0) | 1710 | if (process_ras(skb, ct, ctinfo, &data, &ras) < 0) |
| 1711 | goto drop; | 1711 | goto drop; |
| 1712 | 1712 | ||
| 1713 | accept: | 1713 | accept: |
diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c index 1562ca97a349..dfaed4ba83cd 100644 --- a/net/netfilter/nf_conntrack_irc.c +++ b/net/netfilter/nf_conntrack_irc.c | |||
| @@ -30,7 +30,7 @@ static unsigned int dcc_timeout __read_mostly = 300; | |||
| 30 | static char *irc_buffer; | 30 | static char *irc_buffer; |
| 31 | static DEFINE_SPINLOCK(irc_buffer_lock); | 31 | static DEFINE_SPINLOCK(irc_buffer_lock); |
| 32 | 32 | ||
| 33 | unsigned int (*nf_nat_irc_hook)(struct sk_buff **pskb, | 33 | unsigned int (*nf_nat_irc_hook)(struct sk_buff *skb, |
| 34 | enum ip_conntrack_info ctinfo, | 34 | enum ip_conntrack_info ctinfo, |
| 35 | unsigned int matchoff, | 35 | unsigned int matchoff, |
| 36 | unsigned int matchlen, | 36 | unsigned int matchlen, |
| @@ -89,7 +89,7 @@ static int parse_dcc(char *data, char *data_end, u_int32_t *ip, | |||
| 89 | return 0; | 89 | return 0; |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | static int help(struct sk_buff **pskb, unsigned int protoff, | 92 | static int help(struct sk_buff *skb, unsigned int protoff, |
| 93 | struct nf_conn *ct, enum ip_conntrack_info ctinfo) | 93 | struct nf_conn *ct, enum ip_conntrack_info ctinfo) |
| 94 | { | 94 | { |
| 95 | unsigned int dataoff; | 95 | unsigned int dataoff; |
| @@ -116,22 +116,22 @@ static int help(struct sk_buff **pskb, unsigned int protoff, | |||
| 116 | return NF_ACCEPT; | 116 | return NF_ACCEPT; |
| 117 | 117 | ||
| 118 | /* Not a full tcp header? */ | 118 | /* Not a full tcp header? */ |
| 119 | th = skb_header_pointer(*pskb, protoff, sizeof(_tcph), &_tcph); | 119 | th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); |
| 120 | if (th == NULL) | 120 | if (th == NULL) |
| 121 | return NF_ACCEPT; | 121 | return NF_ACCEPT; |
| 122 | 122 | ||
| 123 | /* No data? */ | 123 | /* No data? */ |
| 124 | dataoff = protoff + th->doff*4; | 124 | dataoff = protoff + th->doff*4; |
| 125 | if (dataoff >= (*pskb)->len) | 125 | if (dataoff >= skb->len) |
| 126 | return NF_ACCEPT; | 126 | return NF_ACCEPT; |
| 127 | 127 | ||
| 128 | spin_lock_bh(&irc_buffer_lock); | 128 | spin_lock_bh(&irc_buffer_lock); |
| 129 | ib_ptr = skb_header_pointer(*pskb, dataoff, (*pskb)->len - dataoff, | 129 | ib_ptr = skb_header_pointer(skb, dataoff, skb->len - dataoff, |
| 130 | irc_buffer); | 130 | irc_buffer); |
| 131 | BUG_ON(ib_ptr == NULL); | 131 | BUG_ON(ib_ptr == NULL); |
| 132 | 132 | ||
| 133 | data = ib_ptr; | 133 | data = ib_ptr; |
| 134 | data_limit = ib_ptr + (*pskb)->len - dataoff; | 134 | data_limit = ib_ptr + skb->len - dataoff; |
| 135 | 135 | ||
| 136 | /* strlen("\1DCC SENT t AAAAAAAA P\1\n")=24 | 136 | /* strlen("\1DCC SENT t AAAAAAAA P\1\n")=24 |
| 137 | * 5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */ | 137 | * 5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */ |
| @@ -143,7 +143,7 @@ static int help(struct sk_buff **pskb, unsigned int protoff, | |||
| 143 | data += 5; | 143 | data += 5; |
| 144 | /* we have at least (19+MINMATCHLEN)-5 bytes valid data left */ | 144 | /* we have at least (19+MINMATCHLEN)-5 bytes valid data left */ |
| 145 | 145 | ||
| 146 | iph = ip_hdr(*pskb); | 146 | iph = ip_hdr(skb); |
| 147 | pr_debug("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u\n", | 147 | pr_debug("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u\n", |
| 148 | NIPQUAD(iph->saddr), ntohs(th->source), | 148 | NIPQUAD(iph->saddr), ntohs(th->source), |
| 149 | NIPQUAD(iph->daddr), ntohs(th->dest)); | 149 | NIPQUAD(iph->daddr), ntohs(th->dest)); |
| @@ -193,7 +193,7 @@ static int help(struct sk_buff **pskb, unsigned int protoff, | |||
| 193 | 193 | ||
| 194 | nf_nat_irc = rcu_dereference(nf_nat_irc_hook); | 194 | nf_nat_irc = rcu_dereference(nf_nat_irc_hook); |
| 195 | if (nf_nat_irc && ct->status & IPS_NAT_MASK) | 195 | if (nf_nat_irc && ct->status & IPS_NAT_MASK) |
| 196 | ret = nf_nat_irc(pskb, ctinfo, | 196 | ret = nf_nat_irc(skb, ctinfo, |
| 197 | addr_beg_p - ib_ptr, | 197 | addr_beg_p - ib_ptr, |
| 198 | addr_end_p - addr_beg_p, | 198 | addr_end_p - addr_beg_p, |
| 199 | exp); | 199 | exp); |
diff --git a/net/netfilter/nf_conntrack_netbios_ns.c b/net/netfilter/nf_conntrack_netbios_ns.c index 1d59fabeb5f7..9810d81e2a06 100644 --- a/net/netfilter/nf_conntrack_netbios_ns.c +++ b/net/netfilter/nf_conntrack_netbios_ns.c | |||
| @@ -42,17 +42,17 @@ static unsigned int timeout __read_mostly = 3; | |||
| 42 | module_param(timeout, uint, 0400); | 42 | module_param(timeout, uint, 0400); |
| 43 | MODULE_PARM_DESC(timeout, "timeout for master connection/replies in seconds"); | 43 | MODULE_PARM_DESC(timeout, "timeout for master connection/replies in seconds"); |
| 44 | 44 | ||
| 45 | static int help(struct sk_buff **pskb, unsigned int protoff, | 45 | static int help(struct sk_buff *skb, unsigned int protoff, |
| 46 | struct nf_conn *ct, enum ip_conntrack_info ctinfo) | 46 | struct nf_conn *ct, enum ip_conntrack_info ctinfo) |
| 47 | { | 47 | { |
| 48 | struct nf_conntrack_expect *exp; | 48 | struct nf_conntrack_expect *exp; |
| 49 | struct iphdr *iph = ip_hdr(*pskb); | 49 | struct iphdr *iph = ip_hdr(skb); |
| 50 | struct rtable *rt = (struct rtable *)(*pskb)->dst; | 50 | struct rtable *rt = (struct rtable *)skb->dst; |
| 51 | struct in_device *in_dev; | 51 | struct in_device *in_dev; |
| 52 | __be32 mask = 0; | 52 | __be32 mask = 0; |
| 53 | 53 | ||
| 54 | /* we're only interested in locally generated packets */ | 54 | /* we're only interested in locally generated packets */ |
| 55 | if ((*pskb)->sk == NULL) | 55 | if (skb->sk == NULL) |
| 56 | goto out; | 56 | goto out; |
| 57 | if (rt == NULL || !(rt->rt_flags & RTCF_BROADCAST)) | 57 | if (rt == NULL || !(rt->rt_flags & RTCF_BROADCAST)) |
| 58 | goto out; | 58 | goto out; |
| @@ -91,7 +91,7 @@ static int help(struct sk_buff **pskb, unsigned int protoff, | |||
| 91 | nf_ct_expect_related(exp); | 91 | nf_ct_expect_related(exp); |
| 92 | nf_ct_expect_put(exp); | 92 | nf_ct_expect_put(exp); |
| 93 | 93 | ||
| 94 | nf_ct_refresh(ct, *pskb, timeout * HZ); | 94 | nf_ct_refresh(ct, skb, timeout * HZ); |
| 95 | out: | 95 | out: |
| 96 | return NF_ACCEPT; | 96 | return NF_ACCEPT; |
| 97 | } | 97 | } |
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c index b0804199ab59..099b6df3e2b5 100644 --- a/net/netfilter/nf_conntrack_pptp.c +++ b/net/netfilter/nf_conntrack_pptp.c | |||
| @@ -41,14 +41,14 @@ MODULE_ALIAS("ip_conntrack_pptp"); | |||
| 41 | static DEFINE_SPINLOCK(nf_pptp_lock); | 41 | static DEFINE_SPINLOCK(nf_pptp_lock); |
| 42 | 42 | ||
| 43 | int | 43 | int |
| 44 | (*nf_nat_pptp_hook_outbound)(struct sk_buff **pskb, | 44 | (*nf_nat_pptp_hook_outbound)(struct sk_buff *skb, |
| 45 | struct nf_conn *ct, enum ip_conntrack_info ctinfo, | 45 | struct nf_conn *ct, enum ip_conntrack_info ctinfo, |
| 46 | struct PptpControlHeader *ctlh, | 46 | struct PptpControlHeader *ctlh, |
| 47 | union pptp_ctrl_union *pptpReq) __read_mostly; | 47 | union pptp_ctrl_union *pptpReq) __read_mostly; |
| 48 | EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_outbound); | 48 | EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_outbound); |
| 49 | 49 | ||
| 50 | int | 50 | int |
| 51 | (*nf_nat_pptp_hook_inbound)(struct sk_buff **pskb, | 51 | (*nf_nat_pptp_hook_inbound)(struct sk_buff *skb, |
| 52 | struct nf_conn *ct, enum ip_conntrack_info ctinfo, | 52 | struct nf_conn *ct, enum ip_conntrack_info ctinfo, |
| 53 | struct PptpControlHeader *ctlh, | 53 | struct PptpControlHeader *ctlh, |
| 54 | union pptp_ctrl_union *pptpReq) __read_mostly; | 54 | union pptp_ctrl_union *pptpReq) __read_mostly; |
| @@ -254,7 +254,7 @@ out_unexpect_orig: | |||
| 254 | } | 254 | } |
| 255 | 255 | ||
| 256 | static inline int | 256 | static inline int |
| 257 | pptp_inbound_pkt(struct sk_buff **pskb, | 257 | pptp_inbound_pkt(struct sk_buff *skb, |
| 258 | struct PptpControlHeader *ctlh, | 258 | struct PptpControlHeader *ctlh, |
| 259 | union pptp_ctrl_union *pptpReq, | 259 | union pptp_ctrl_union *pptpReq, |
| 260 | unsigned int reqlen, | 260 | unsigned int reqlen, |
| @@ -367,7 +367,7 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
| 367 | 367 | ||
| 368 | nf_nat_pptp_inbound = rcu_dereference(nf_nat_pptp_hook_inbound); | 368 | nf_nat_pptp_inbound = rcu_dereference(nf_nat_pptp_hook_inbound); |
| 369 | if (nf_nat_pptp_inbound && ct->status & IPS_NAT_MASK) | 369 | if (nf_nat_pptp_inbound && ct->status & IPS_NAT_MASK) |
| 370 | return nf_nat_pptp_inbound(pskb, ct, ctinfo, ctlh, pptpReq); | 370 | return nf_nat_pptp_inbound(skb, ct, ctinfo, ctlh, pptpReq); |
| 371 | return NF_ACCEPT; | 371 | return NF_ACCEPT; |
| 372 | 372 | ||
| 373 | invalid: | 373 | invalid: |
| @@ -380,7 +380,7 @@ invalid: | |||
| 380 | } | 380 | } |
| 381 | 381 | ||
| 382 | static inline int | 382 | static inline int |
| 383 | pptp_outbound_pkt(struct sk_buff **pskb, | 383 | pptp_outbound_pkt(struct sk_buff *skb, |
| 384 | struct PptpControlHeader *ctlh, | 384 | struct PptpControlHeader *ctlh, |
| 385 | union pptp_ctrl_union *pptpReq, | 385 | union pptp_ctrl_union *pptpReq, |
| 386 | unsigned int reqlen, | 386 | unsigned int reqlen, |
| @@ -462,7 +462,7 @@ pptp_outbound_pkt(struct sk_buff **pskb, | |||
| 462 | 462 | ||
| 463 | nf_nat_pptp_outbound = rcu_dereference(nf_nat_pptp_hook_outbound); | 463 | nf_nat_pptp_outbound = rcu_dereference(nf_nat_pptp_hook_outbound); |
| 464 | if (nf_nat_pptp_outbound && ct->status & IPS_NAT_MASK) | 464 | if (nf_nat_pptp_outbound && ct->status & IPS_NAT_MASK) |
| 465 | return nf_nat_pptp_outbound(pskb, ct, ctinfo, ctlh, pptpReq); | 465 | return nf_nat_pptp_outbound(skb, ct, ctinfo, ctlh, pptpReq); |
| 466 | return NF_ACCEPT; | 466 | return NF_ACCEPT; |
| 467 | 467 | ||
| 468 | invalid: | 468 | invalid: |
| @@ -492,7 +492,7 @@ static const unsigned int pptp_msg_size[] = { | |||
| 492 | 492 | ||
| 493 | /* track caller id inside control connection, call expect_related */ | 493 | /* track caller id inside control connection, call expect_related */ |
| 494 | static int | 494 | static int |
| 495 | conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff, | 495 | conntrack_pptp_help(struct sk_buff *skb, unsigned int protoff, |
| 496 | struct nf_conn *ct, enum ip_conntrack_info ctinfo) | 496 | struct nf_conn *ct, enum ip_conntrack_info ctinfo) |
| 497 | 497 | ||
| 498 | { | 498 | { |
| @@ -502,7 +502,7 @@ conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff, | |||
| 502 | struct pptp_pkt_hdr _pptph, *pptph; | 502 | struct pptp_pkt_hdr _pptph, *pptph; |
| 503 | struct PptpControlHeader _ctlh, *ctlh; | 503 | struct PptpControlHeader _ctlh, *ctlh; |
| 504 | union pptp_ctrl_union _pptpReq, *pptpReq; | 504 | union pptp_ctrl_union _pptpReq, *pptpReq; |
| 505 | unsigned int tcplen = (*pskb)->len - protoff; | 505 | unsigned int tcplen = skb->len - protoff; |
| 506 | unsigned int datalen, reqlen, nexthdr_off; | 506 | unsigned int datalen, reqlen, nexthdr_off; |
| 507 | int oldsstate, oldcstate; | 507 | int oldsstate, oldcstate; |
| 508 | int ret; | 508 | int ret; |
| @@ -514,12 +514,12 @@ conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff, | |||
| 514 | return NF_ACCEPT; | 514 | return NF_ACCEPT; |
| 515 | 515 | ||
| 516 | nexthdr_off = protoff; | 516 | nexthdr_off = protoff; |
| 517 | tcph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_tcph), &_tcph); | 517 | tcph = skb_header_pointer(skb, nexthdr_off, sizeof(_tcph), &_tcph); |
| 518 | BUG_ON(!tcph); | 518 | BUG_ON(!tcph); |
| 519 | nexthdr_off += tcph->doff * 4; | 519 | nexthdr_off += tcph->doff * 4; |
| 520 | datalen = tcplen - tcph->doff * 4; | 520 | datalen = tcplen - tcph->doff * 4; |
| 521 | 521 | ||
| 522 | pptph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_pptph), &_pptph); | 522 | pptph = skb_header_pointer(skb, nexthdr_off, sizeof(_pptph), &_pptph); |
| 523 | if (!pptph) { | 523 | if (!pptph) { |
| 524 | pr_debug("no full PPTP header, can't track\n"); | 524 | pr_debug("no full PPTP header, can't track\n"); |
| 525 | return NF_ACCEPT; | 525 | return NF_ACCEPT; |
| @@ -534,7 +534,7 @@ conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff, | |||
| 534 | return NF_ACCEPT; | 534 | return NF_ACCEPT; |
| 535 | } | 535 | } |
| 536 | 536 | ||
| 537 | ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh); | 537 | ctlh = skb_header_pointer(skb, nexthdr_off, sizeof(_ctlh), &_ctlh); |
| 538 | if (!ctlh) | 538 | if (!ctlh) |
| 539 | return NF_ACCEPT; | 539 | return NF_ACCEPT; |
| 540 | nexthdr_off += sizeof(_ctlh); | 540 | nexthdr_off += sizeof(_ctlh); |
| @@ -547,7 +547,7 @@ conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff, | |||
| 547 | if (reqlen > sizeof(*pptpReq)) | 547 | if (reqlen > sizeof(*pptpReq)) |
| 548 | reqlen = sizeof(*pptpReq); | 548 | reqlen = sizeof(*pptpReq); |
| 549 | 549 | ||
| 550 | pptpReq = skb_header_pointer(*pskb, nexthdr_off, reqlen, &_pptpReq); | 550 | pptpReq = skb_header_pointer(skb, nexthdr_off, reqlen, &_pptpReq); |
| 551 | if (!pptpReq) | 551 | if (!pptpReq) |
| 552 | return NF_ACCEPT; | 552 | return NF_ACCEPT; |
| 553 | 553 | ||
| @@ -560,11 +560,11 @@ conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff, | |||
| 560 | * established from PNS->PAC. However, RFC makes no guarantee */ | 560 | * established from PNS->PAC. However, RFC makes no guarantee */ |
| 561 | if (dir == IP_CT_DIR_ORIGINAL) | 561 | if (dir == IP_CT_DIR_ORIGINAL) |
| 562 | /* client -> server (PNS -> PAC) */ | 562 | /* client -> server (PNS -> PAC) */ |
| 563 | ret = pptp_outbound_pkt(pskb, ctlh, pptpReq, reqlen, ct, | 563 | ret = pptp_outbound_pkt(skb, ctlh, pptpReq, reqlen, ct, |
| 564 | ctinfo); | 564 | ctinfo); |
| 565 | else | 565 | else |
| 566 | /* server -> client (PAC -> PNS) */ | 566 | /* server -> client (PAC -> PNS) */ |
| 567 | ret = pptp_inbound_pkt(pskb, ctlh, pptpReq, reqlen, ct, | 567 | ret = pptp_inbound_pkt(skb, ctlh, pptpReq, reqlen, ct, |
| 568 | ctinfo); | 568 | ctinfo); |
| 569 | pr_debug("sstate: %d->%d, cstate: %d->%d\n", | 569 | pr_debug("sstate: %d->%d, cstate: %d->%d\n", |
| 570 | oldsstate, info->sstate, oldcstate, info->cstate); | 570 | oldsstate, info->sstate, oldcstate, info->cstate); |
diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c index 355d371bac93..b5a16c6e21c2 100644 --- a/net/netfilter/nf_conntrack_sane.c +++ b/net/netfilter/nf_conntrack_sane.c | |||
| @@ -56,7 +56,7 @@ struct sane_reply_net_start { | |||
| 56 | /* other fields aren't interesting for conntrack */ | 56 | /* other fields aren't interesting for conntrack */ |
| 57 | }; | 57 | }; |
| 58 | 58 | ||
| 59 | static int help(struct sk_buff **pskb, | 59 | static int help(struct sk_buff *skb, |
| 60 | unsigned int protoff, | 60 | unsigned int protoff, |
| 61 | struct nf_conn *ct, | 61 | struct nf_conn *ct, |
| 62 | enum ip_conntrack_info ctinfo) | 62 | enum ip_conntrack_info ctinfo) |
| @@ -80,19 +80,19 @@ static int help(struct sk_buff **pskb, | |||
| 80 | return NF_ACCEPT; | 80 | return NF_ACCEPT; |
| 81 | 81 | ||
| 82 | /* Not a full tcp header? */ | 82 | /* Not a full tcp header? */ |
| 83 | th = skb_header_pointer(*pskb, protoff, sizeof(_tcph), &_tcph); | 83 | th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); |
| 84 | if (th == NULL) | 84 | if (th == NULL) |
| 85 | return NF_ACCEPT; | 85 | return NF_ACCEPT; |
| 86 | 86 | ||
| 87 | /* No data? */ | 87 | /* No data? */ |
| 88 | dataoff = protoff + th->doff * 4; | 88 | dataoff = protoff + th->doff * 4; |
| 89 | if (dataoff >= (*pskb)->len) | 89 | if (dataoff >= skb->len) |
| 90 | return NF_ACCEPT; | 90 | return NF_ACCEPT; |
| 91 | 91 | ||
| 92 | datalen = (*pskb)->len - dataoff; | 92 | datalen = skb->len - dataoff; |
| 93 | 93 | ||
| 94 | spin_lock_bh(&nf_sane_lock); | 94 | spin_lock_bh(&nf_sane_lock); |
| 95 | sb_ptr = skb_header_pointer(*pskb, dataoff, datalen, sane_buffer); | 95 | sb_ptr = skb_header_pointer(skb, dataoff, datalen, sane_buffer); |
| 96 | BUG_ON(sb_ptr == NULL); | 96 | BUG_ON(sb_ptr == NULL); |
| 97 | 97 | ||
| 98 | if (dir == IP_CT_DIR_ORIGINAL) { | 98 | if (dir == IP_CT_DIR_ORIGINAL) { |
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index d449fa47491c..8f8b5a48df38 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c | |||
| @@ -36,13 +36,13 @@ static unsigned int sip_timeout __read_mostly = SIP_TIMEOUT; | |||
| 36 | module_param(sip_timeout, uint, 0600); | 36 | module_param(sip_timeout, uint, 0600); |
| 37 | MODULE_PARM_DESC(sip_timeout, "timeout for the master SIP session"); | 37 | MODULE_PARM_DESC(sip_timeout, "timeout for the master SIP session"); |
| 38 | 38 | ||
| 39 | unsigned int (*nf_nat_sip_hook)(struct sk_buff **pskb, | 39 | unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb, |
| 40 | enum ip_conntrack_info ctinfo, | 40 | enum ip_conntrack_info ctinfo, |
| 41 | struct nf_conn *ct, | 41 | struct nf_conn *ct, |
| 42 | const char **dptr) __read_mostly; | 42 | const char **dptr) __read_mostly; |
| 43 | EXPORT_SYMBOL_GPL(nf_nat_sip_hook); | 43 | EXPORT_SYMBOL_GPL(nf_nat_sip_hook); |
| 44 | 44 | ||
| 45 | unsigned int (*nf_nat_sdp_hook)(struct sk_buff **pskb, | 45 | unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb, |
| 46 | enum ip_conntrack_info ctinfo, | 46 | enum ip_conntrack_info ctinfo, |
| 47 | struct nf_conntrack_expect *exp, | 47 | struct nf_conntrack_expect *exp, |
| 48 | const char *dptr) __read_mostly; | 48 | const char *dptr) __read_mostly; |
| @@ -363,7 +363,7 @@ int ct_sip_get_info(struct nf_conn *ct, | |||
| 363 | } | 363 | } |
| 364 | EXPORT_SYMBOL_GPL(ct_sip_get_info); | 364 | EXPORT_SYMBOL_GPL(ct_sip_get_info); |
| 365 | 365 | ||
| 366 | static int set_expected_rtp(struct sk_buff **pskb, | 366 | static int set_expected_rtp(struct sk_buff *skb, |
| 367 | struct nf_conn *ct, | 367 | struct nf_conn *ct, |
| 368 | enum ip_conntrack_info ctinfo, | 368 | enum ip_conntrack_info ctinfo, |
| 369 | union nf_conntrack_address *addr, | 369 | union nf_conntrack_address *addr, |
| @@ -385,7 +385,7 @@ static int set_expected_rtp(struct sk_buff **pskb, | |||
| 385 | 385 | ||
| 386 | nf_nat_sdp = rcu_dereference(nf_nat_sdp_hook); | 386 | nf_nat_sdp = rcu_dereference(nf_nat_sdp_hook); |
| 387 | if (nf_nat_sdp && ct->status & IPS_NAT_MASK) | 387 | if (nf_nat_sdp && ct->status & IPS_NAT_MASK) |
| 388 | ret = nf_nat_sdp(pskb, ctinfo, exp, dptr); | 388 | ret = nf_nat_sdp(skb, ctinfo, exp, dptr); |
| 389 | else { | 389 | else { |
| 390 | if (nf_ct_expect_related(exp) != 0) | 390 | if (nf_ct_expect_related(exp) != 0) |
| 391 | ret = NF_DROP; | 391 | ret = NF_DROP; |
| @@ -397,7 +397,7 @@ static int set_expected_rtp(struct sk_buff **pskb, | |||
| 397 | return ret; | 397 | return ret; |
| 398 | } | 398 | } |
| 399 | 399 | ||
| 400 | static int sip_help(struct sk_buff **pskb, | 400 | static int sip_help(struct sk_buff *skb, |
| 401 | unsigned int protoff, | 401 | unsigned int protoff, |
| 402 | struct nf_conn *ct, | 402 | struct nf_conn *ct, |
| 403 | enum ip_conntrack_info ctinfo) | 403 | enum ip_conntrack_info ctinfo) |
| @@ -414,13 +414,13 @@ static int sip_help(struct sk_buff **pskb, | |||
| 414 | 414 | ||
| 415 | /* No Data ? */ | 415 | /* No Data ? */ |
| 416 | dataoff = protoff + sizeof(struct udphdr); | 416 | dataoff = protoff + sizeof(struct udphdr); |
| 417 | if (dataoff >= (*pskb)->len) | 417 | if (dataoff >= skb->len) |
| 418 | return NF_ACCEPT; | 418 | return NF_ACCEPT; |
| 419 | 419 | ||
| 420 | nf_ct_refresh(ct, *pskb, sip_timeout * HZ); | 420 | nf_ct_refresh(ct, skb, sip_timeout * HZ); |
| 421 | 421 | ||
| 422 | if (!skb_is_nonlinear(*pskb)) | 422 | if (!skb_is_nonlinear(skb)) |
| 423 | dptr = (*pskb)->data + dataoff; | 423 | dptr = skb->data + dataoff; |
| 424 | else { | 424 | else { |
| 425 | pr_debug("Copy of skbuff not supported yet.\n"); | 425 | pr_debug("Copy of skbuff not supported yet.\n"); |
| 426 | goto out; | 426 | goto out; |
| @@ -428,13 +428,13 @@ static int sip_help(struct sk_buff **pskb, | |||
| 428 | 428 | ||
| 429 | nf_nat_sip = rcu_dereference(nf_nat_sip_hook); | 429 | nf_nat_sip = rcu_dereference(nf_nat_sip_hook); |
| 430 | if (nf_nat_sip && ct->status & IPS_NAT_MASK) { | 430 | if (nf_nat_sip && ct->status & IPS_NAT_MASK) { |
| 431 | if (!nf_nat_sip(pskb, ctinfo, ct, &dptr)) { | 431 | if (!nf_nat_sip(skb, ctinfo, ct, &dptr)) { |
| 432 | ret = NF_DROP; | 432 | ret = NF_DROP; |
| 433 | goto out; | 433 | goto out; |
| 434 | } | 434 | } |
| 435 | } | 435 | } |
| 436 | 436 | ||
| 437 | datalen = (*pskb)->len - dataoff; | 437 | datalen = skb->len - dataoff; |
| 438 | if (datalen < sizeof("SIP/2.0 200") - 1) | 438 | if (datalen < sizeof("SIP/2.0 200") - 1) |
| 439 | goto out; | 439 | goto out; |
| 440 | 440 | ||
| @@ -464,7 +464,7 @@ static int sip_help(struct sk_buff **pskb, | |||
| 464 | ret = NF_DROP; | 464 | ret = NF_DROP; |
| 465 | goto out; | 465 | goto out; |
| 466 | } | 466 | } |
| 467 | ret = set_expected_rtp(pskb, ct, ctinfo, &addr, | 467 | ret = set_expected_rtp(skb, ct, ctinfo, &addr, |
| 468 | htons(port), dptr); | 468 | htons(port), dptr); |
| 469 | } | 469 | } |
| 470 | } | 470 | } |
diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c index cc19506cf2f8..e894aa1ff3ad 100644 --- a/net/netfilter/nf_conntrack_tftp.c +++ b/net/netfilter/nf_conntrack_tftp.c | |||
| @@ -29,12 +29,12 @@ static int ports_c; | |||
| 29 | module_param_array(ports, ushort, &ports_c, 0400); | 29 | module_param_array(ports, ushort, &ports_c, 0400); |
| 30 | MODULE_PARM_DESC(ports, "Port numbers of TFTP servers"); | 30 | MODULE_PARM_DESC(ports, "Port numbers of TFTP servers"); |
| 31 | 31 | ||
| 32 | unsigned int (*nf_nat_tftp_hook)(struct sk_buff **pskb, | 32 | unsigned int (*nf_nat_tftp_hook)(struct sk_buff *skb, |
| 33 | enum ip_conntrack_info ctinfo, | 33 | enum ip_conntrack_info ctinfo, |
| 34 | struct nf_conntrack_expect *exp) __read_mostly; | 34 | struct nf_conntrack_expect *exp) __read_mostly; |
| 35 | EXPORT_SYMBOL_GPL(nf_nat_tftp_hook); | 35 | EXPORT_SYMBOL_GPL(nf_nat_tftp_hook); |
| 36 | 36 | ||
| 37 | static int tftp_help(struct sk_buff **pskb, | 37 | static int tftp_help(struct sk_buff *skb, |
| 38 | unsigned int protoff, | 38 | unsigned int protoff, |
| 39 | struct nf_conn *ct, | 39 | struct nf_conn *ct, |
| 40 | enum ip_conntrack_info ctinfo) | 40 | enum ip_conntrack_info ctinfo) |
| @@ -46,7 +46,7 @@ static int tftp_help(struct sk_buff **pskb, | |||
| 46 | int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; | 46 | int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; |
| 47 | typeof(nf_nat_tftp_hook) nf_nat_tftp; | 47 | typeof(nf_nat_tftp_hook) nf_nat_tftp; |
| 48 | 48 | ||
| 49 | tfh = skb_header_pointer(*pskb, protoff + sizeof(struct udphdr), | 49 | tfh = skb_header_pointer(skb, protoff + sizeof(struct udphdr), |
| 50 | sizeof(_tftph), &_tftph); | 50 | sizeof(_tftph), &_tftph); |
| 51 | if (tfh == NULL) | 51 | if (tfh == NULL) |
| 52 | return NF_ACCEPT; | 52 | return NF_ACCEPT; |
| @@ -70,7 +70,7 @@ static int tftp_help(struct sk_buff **pskb, | |||
| 70 | 70 | ||
| 71 | nf_nat_tftp = rcu_dereference(nf_nat_tftp_hook); | 71 | nf_nat_tftp = rcu_dereference(nf_nat_tftp_hook); |
| 72 | if (nf_nat_tftp && ct->status & IPS_NAT_MASK) | 72 | if (nf_nat_tftp && ct->status & IPS_NAT_MASK) |
| 73 | ret = nf_nat_tftp(pskb, ctinfo, exp); | 73 | ret = nf_nat_tftp(skb, ctinfo, exp); |
| 74 | else if (nf_ct_expect_related(exp) != 0) | 74 | else if (nf_ct_expect_related(exp) != 0) |
| 75 | ret = NF_DROP; | 75 | ret = NF_DROP; |
| 76 | nf_ct_expect_put(exp); | 76 | nf_ct_expect_put(exp); |
diff --git a/net/netfilter/nf_internals.h b/net/netfilter/nf_internals.h index 0df7fff196a7..196269c1e586 100644 --- a/net/netfilter/nf_internals.h +++ b/net/netfilter/nf_internals.h | |||
| @@ -14,7 +14,7 @@ | |||
| 14 | 14 | ||
| 15 | /* core.c */ | 15 | /* core.c */ |
| 16 | extern unsigned int nf_iterate(struct list_head *head, | 16 | extern unsigned int nf_iterate(struct list_head *head, |
| 17 | struct sk_buff **skb, | 17 | struct sk_buff *skb, |
| 18 | int hook, | 18 | int hook, |
| 19 | const struct net_device *indev, | 19 | const struct net_device *indev, |
| 20 | const struct net_device *outdev, | 20 | const struct net_device *outdev, |
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index a481a349f7bf..0cef1433d660 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c | |||
| @@ -256,14 +256,14 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, | |||
| 256 | 256 | ||
| 257 | if (verdict == NF_ACCEPT) { | 257 | if (verdict == NF_ACCEPT) { |
| 258 | afinfo = nf_get_afinfo(info->pf); | 258 | afinfo = nf_get_afinfo(info->pf); |
| 259 | if (!afinfo || afinfo->reroute(&skb, info) < 0) | 259 | if (!afinfo || afinfo->reroute(skb, info) < 0) |
| 260 | verdict = NF_DROP; | 260 | verdict = NF_DROP; |
| 261 | } | 261 | } |
| 262 | 262 | ||
| 263 | if (verdict == NF_ACCEPT) { | 263 | if (verdict == NF_ACCEPT) { |
| 264 | next_hook: | 264 | next_hook: |
| 265 | verdict = nf_iterate(&nf_hooks[info->pf][info->hook], | 265 | verdict = nf_iterate(&nf_hooks[info->pf][info->hook], |
| 266 | &skb, info->hook, | 266 | skb, info->hook, |
| 267 | info->indev, info->outdev, &elem, | 267 | info->indev, info->outdev, &elem, |
| 268 | info->okfn, INT_MIN); | 268 | info->okfn, INT_MIN); |
| 269 | } | 269 | } |
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 49f0480afe09..3ceeffcf6f9d 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c | |||
| @@ -617,6 +617,7 @@ static int | |||
| 617 | nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e) | 617 | nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e) |
| 618 | { | 618 | { |
| 619 | int diff; | 619 | int diff; |
| 620 | int err; | ||
| 620 | 621 | ||
| 621 | diff = data_len - e->skb->len; | 622 | diff = data_len - e->skb->len; |
| 622 | if (diff < 0) { | 623 | if (diff < 0) { |
| @@ -626,25 +627,18 @@ nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e) | |||
| 626 | if (data_len > 0xFFFF) | 627 | if (data_len > 0xFFFF) |
| 627 | return -EINVAL; | 628 | return -EINVAL; |
| 628 | if (diff > skb_tailroom(e->skb)) { | 629 | if (diff > skb_tailroom(e->skb)) { |
| 629 | struct sk_buff *newskb; | 630 | err = pskb_expand_head(e->skb, 0, |
| 630 | 631 | diff - skb_tailroom(e->skb), | |
| 631 | newskb = skb_copy_expand(e->skb, | 632 | GFP_ATOMIC); |
| 632 | skb_headroom(e->skb), | 633 | if (err) { |
| 633 | diff, | ||
| 634 | GFP_ATOMIC); | ||
| 635 | if (newskb == NULL) { | ||
| 636 | printk(KERN_WARNING "nf_queue: OOM " | 634 | printk(KERN_WARNING "nf_queue: OOM " |
| 637 | "in mangle, dropping packet\n"); | 635 | "in mangle, dropping packet\n"); |
| 638 | return -ENOMEM; | 636 | return err; |
| 639 | } | 637 | } |
| 640 | if (e->skb->sk) | ||
| 641 | skb_set_owner_w(newskb, e->skb->sk); | ||
| 642 | kfree_skb(e->skb); | ||
| 643 | e->skb = newskb; | ||
| 644 | } | 638 | } |
| 645 | skb_put(e->skb, diff); | 639 | skb_put(e->skb, diff); |
| 646 | } | 640 | } |
| 647 | if (!skb_make_writable(&e->skb, data_len)) | 641 | if (!skb_make_writable(e->skb, data_len)) |
| 648 | return -ENOMEM; | 642 | return -ENOMEM; |
| 649 | skb_copy_to_linear_data(e->skb, data, data_len); | 643 | skb_copy_to_linear_data(e->skb, data, data_len); |
| 650 | e->skb->ip_summed = CHECKSUM_NONE; | 644 | e->skb->ip_summed = CHECKSUM_NONE; |
diff --git a/net/netfilter/xt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c index 07a1b9665005..77eeae658d42 100644 --- a/net/netfilter/xt_CLASSIFY.c +++ b/net/netfilter/xt_CLASSIFY.c | |||
| @@ -27,7 +27,7 @@ MODULE_ALIAS("ipt_CLASSIFY"); | |||
| 27 | MODULE_ALIAS("ip6t_CLASSIFY"); | 27 | MODULE_ALIAS("ip6t_CLASSIFY"); |
| 28 | 28 | ||
| 29 | static unsigned int | 29 | static unsigned int |
| 30 | target(struct sk_buff **pskb, | 30 | target(struct sk_buff *skb, |
| 31 | const struct net_device *in, | 31 | const struct net_device *in, |
| 32 | const struct net_device *out, | 32 | const struct net_device *out, |
| 33 | unsigned int hooknum, | 33 | unsigned int hooknum, |
| @@ -36,7 +36,7 @@ target(struct sk_buff **pskb, | |||
| 36 | { | 36 | { |
| 37 | const struct xt_classify_target_info *clinfo = targinfo; | 37 | const struct xt_classify_target_info *clinfo = targinfo; |
| 38 | 38 | ||
| 39 | (*pskb)->priority = clinfo->priority; | 39 | skb->priority = clinfo->priority; |
| 40 | return XT_CONTINUE; | 40 | return XT_CONTINUE; |
| 41 | } | 41 | } |
| 42 | 42 | ||
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c index 7043c2757e09..8cc324b159e9 100644 --- a/net/netfilter/xt_CONNMARK.c +++ b/net/netfilter/xt_CONNMARK.c | |||
| @@ -34,7 +34,7 @@ MODULE_ALIAS("ip6t_CONNMARK"); | |||
| 34 | #include <net/netfilter/nf_conntrack_ecache.h> | 34 | #include <net/netfilter/nf_conntrack_ecache.h> |
| 35 | 35 | ||
| 36 | static unsigned int | 36 | static unsigned int |
| 37 | target(struct sk_buff **pskb, | 37 | target(struct sk_buff *skb, |
| 38 | const struct net_device *in, | 38 | const struct net_device *in, |
| 39 | const struct net_device *out, | 39 | const struct net_device *out, |
| 40 | unsigned int hooknum, | 40 | unsigned int hooknum, |
| @@ -48,28 +48,28 @@ target(struct sk_buff **pskb, | |||
| 48 | u_int32_t mark; | 48 | u_int32_t mark; |
| 49 | u_int32_t newmark; | 49 | u_int32_t newmark; |
| 50 | 50 | ||
| 51 | ct = nf_ct_get(*pskb, &ctinfo); | 51 | ct = nf_ct_get(skb, &ctinfo); |
| 52 | if (ct) { | 52 | if (ct) { |
| 53 | switch(markinfo->mode) { | 53 | switch(markinfo->mode) { |
| 54 | case XT_CONNMARK_SET: | 54 | case XT_CONNMARK_SET: |
| 55 | newmark = (ct->mark & ~markinfo->mask) | markinfo->mark; | 55 | newmark = (ct->mark & ~markinfo->mask) | markinfo->mark; |
| 56 | if (newmark != ct->mark) { | 56 | if (newmark != ct->mark) { |
| 57 | ct->mark = newmark; | 57 | ct->mark = newmark; |
| 58 | nf_conntrack_event_cache(IPCT_MARK, *pskb); | 58 | nf_conntrack_event_cache(IPCT_MARK, skb); |
| 59 | } | 59 | } |
| 60 | break; | 60 | break; |
| 61 | case XT_CONNMARK_SAVE: | 61 | case XT_CONNMARK_SAVE: |
| 62 | newmark = (ct->mark & ~markinfo->mask) | | 62 | newmark = (ct->mark & ~markinfo->mask) | |
| 63 | ((*pskb)->mark & markinfo->mask); | 63 | (skb->mark & markinfo->mask); |
| 64 | if (ct->mark != newmark) { | 64 | if (ct->mark != newmark) { |
| 65 | ct->mark = newmark; | 65 | ct->mark = newmark; |
| 66 | nf_conntrack_event_cache(IPCT_MARK, *pskb); | 66 | nf_conntrack_event_cache(IPCT_MARK, skb); |
| 67 | } | 67 | } |
| 68 | break; | 68 | break; |
| 69 | case XT_CONNMARK_RESTORE: | 69 | case XT_CONNMARK_RESTORE: |
| 70 | mark = (*pskb)->mark; | 70 | mark = skb->mark; |
| 71 | diff = (ct->mark ^ mark) & markinfo->mask; | 71 | diff = (ct->mark ^ mark) & markinfo->mask; |
| 72 | (*pskb)->mark = mark ^ diff; | 72 | skb->mark = mark ^ diff; |
| 73 | break; | 73 | break; |
| 74 | } | 74 | } |
| 75 | } | 75 | } |
diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c index 63d73138c1b9..021b5c8d20e2 100644 --- a/net/netfilter/xt_CONNSECMARK.c +++ b/net/netfilter/xt_CONNSECMARK.c | |||
| @@ -61,12 +61,11 @@ static void secmark_restore(struct sk_buff *skb) | |||
| 61 | } | 61 | } |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | static unsigned int target(struct sk_buff **pskb, const struct net_device *in, | 64 | static unsigned int target(struct sk_buff *skb, const struct net_device *in, |
| 65 | const struct net_device *out, unsigned int hooknum, | 65 | const struct net_device *out, unsigned int hooknum, |
| 66 | const struct xt_target *target, | 66 | const struct xt_target *target, |
| 67 | const void *targinfo) | 67 | const void *targinfo) |
| 68 | { | 68 | { |
| 69 | struct sk_buff *skb = *pskb; | ||
| 70 | const struct xt_connsecmark_target_info *info = targinfo; | 69 | const struct xt_connsecmark_target_info *info = targinfo; |
| 71 | 70 | ||
| 72 | switch (info->mode) { | 71 | switch (info->mode) { |
diff --git a/net/netfilter/xt_DSCP.c b/net/netfilter/xt_DSCP.c index 798ab731009d..6322a933ab71 100644 --- a/net/netfilter/xt_DSCP.c +++ b/net/netfilter/xt_DSCP.c | |||
| @@ -25,7 +25,7 @@ MODULE_LICENSE("GPL"); | |||
| 25 | MODULE_ALIAS("ipt_DSCP"); | 25 | MODULE_ALIAS("ipt_DSCP"); |
| 26 | MODULE_ALIAS("ip6t_DSCP"); | 26 | MODULE_ALIAS("ip6t_DSCP"); |
| 27 | 27 | ||
| 28 | static unsigned int target(struct sk_buff **pskb, | 28 | static unsigned int target(struct sk_buff *skb, |
| 29 | const struct net_device *in, | 29 | const struct net_device *in, |
| 30 | const struct net_device *out, | 30 | const struct net_device *out, |
| 31 | unsigned int hooknum, | 31 | unsigned int hooknum, |
| @@ -33,20 +33,20 @@ static unsigned int target(struct sk_buff **pskb, | |||
| 33 | const void *targinfo) | 33 | const void *targinfo) |
| 34 | { | 34 | { |
| 35 | const struct xt_DSCP_info *dinfo = targinfo; | 35 | const struct xt_DSCP_info *dinfo = targinfo; |
| 36 | u_int8_t dscp = ipv4_get_dsfield(ip_hdr(*pskb)) >> XT_DSCP_SHIFT; | 36 | u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT; |
| 37 | 37 | ||
| 38 | if (dscp != dinfo->dscp) { | 38 | if (dscp != dinfo->dscp) { |
| 39 | if (!skb_make_writable(pskb, sizeof(struct iphdr))) | 39 | if (!skb_make_writable(skb, sizeof(struct iphdr))) |
| 40 | return NF_DROP; | 40 | return NF_DROP; |
| 41 | 41 | ||
| 42 | ipv4_change_dsfield(ip_hdr(*pskb), (__u8)(~XT_DSCP_MASK), | 42 | ipv4_change_dsfield(ip_hdr(skb), (__u8)(~XT_DSCP_MASK), |
| 43 | dinfo->dscp << XT_DSCP_SHIFT); | 43 | dinfo->dscp << XT_DSCP_SHIFT); |
| 44 | 44 | ||
| 45 | } | 45 | } |
| 46 | return XT_CONTINUE; | 46 | return XT_CONTINUE; |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | static unsigned int target6(struct sk_buff **pskb, | 49 | static unsigned int target6(struct sk_buff *skb, |
| 50 | const struct net_device *in, | 50 | const struct net_device *in, |
| 51 | const struct net_device *out, | 51 | const struct net_device *out, |
| 52 | unsigned int hooknum, | 52 | unsigned int hooknum, |
| @@ -54,13 +54,13 @@ static unsigned int target6(struct sk_buff **pskb, | |||
| 54 | const void *targinfo) | 54 | const void *targinfo) |
| 55 | { | 55 | { |
| 56 | const struct xt_DSCP_info *dinfo = targinfo; | 56 | const struct xt_DSCP_info *dinfo = targinfo; |
| 57 | u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(*pskb)) >> XT_DSCP_SHIFT; | 57 | u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT; |
| 58 | 58 | ||
| 59 | if (dscp != dinfo->dscp) { | 59 | if (dscp != dinfo->dscp) { |
| 60 | if (!skb_make_writable(pskb, sizeof(struct ipv6hdr))) | 60 | if (!skb_make_writable(skb, sizeof(struct ipv6hdr))) |
| 61 | return NF_DROP; | 61 | return NF_DROP; |
| 62 | 62 | ||
| 63 | ipv6_change_dsfield(ipv6_hdr(*pskb), (__u8)(~XT_DSCP_MASK), | 63 | ipv6_change_dsfield(ipv6_hdr(skb), (__u8)(~XT_DSCP_MASK), |
| 64 | dinfo->dscp << XT_DSCP_SHIFT); | 64 | dinfo->dscp << XT_DSCP_SHIFT); |
| 65 | } | 65 | } |
| 66 | return XT_CONTINUE; | 66 | return XT_CONTINUE; |
diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c index f30fe0baf7de..bc6503d77d75 100644 --- a/net/netfilter/xt_MARK.c +++ b/net/netfilter/xt_MARK.c | |||
| @@ -22,7 +22,7 @@ MODULE_ALIAS("ipt_MARK"); | |||
| 22 | MODULE_ALIAS("ip6t_MARK"); | 22 | MODULE_ALIAS("ip6t_MARK"); |
| 23 | 23 | ||
| 24 | static unsigned int | 24 | static unsigned int |
| 25 | target_v0(struct sk_buff **pskb, | 25 | target_v0(struct sk_buff *skb, |
| 26 | const struct net_device *in, | 26 | const struct net_device *in, |
| 27 | const struct net_device *out, | 27 | const struct net_device *out, |
| 28 | unsigned int hooknum, | 28 | unsigned int hooknum, |
| @@ -31,12 +31,12 @@ target_v0(struct sk_buff **pskb, | |||
| 31 | { | 31 | { |
| 32 | const struct xt_mark_target_info *markinfo = targinfo; | 32 | const struct xt_mark_target_info *markinfo = targinfo; |
| 33 | 33 | ||
| 34 | (*pskb)->mark = markinfo->mark; | 34 | skb->mark = markinfo->mark; |
| 35 | return XT_CONTINUE; | 35 | return XT_CONTINUE; |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | static unsigned int | 38 | static unsigned int |
| 39 | target_v1(struct sk_buff **pskb, | 39 | target_v1(struct sk_buff *skb, |
| 40 | const struct net_device *in, | 40 | const struct net_device *in, |
| 41 | const struct net_device *out, | 41 | const struct net_device *out, |
| 42 | unsigned int hooknum, | 42 | unsigned int hooknum, |
| @@ -52,15 +52,15 @@ target_v1(struct sk_buff **pskb, | |||
| 52 | break; | 52 | break; |
| 53 | 53 | ||
| 54 | case XT_MARK_AND: | 54 | case XT_MARK_AND: |
| 55 | mark = (*pskb)->mark & markinfo->mark; | 55 | mark = skb->mark & markinfo->mark; |
| 56 | break; | 56 | break; |
| 57 | 57 | ||
| 58 | case XT_MARK_OR: | 58 | case XT_MARK_OR: |
| 59 | mark = (*pskb)->mark | markinfo->mark; | 59 | mark = skb->mark | markinfo->mark; |
| 60 | break; | 60 | break; |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | (*pskb)->mark = mark; | 63 | skb->mark = mark; |
| 64 | return XT_CONTINUE; | 64 | return XT_CONTINUE; |
| 65 | } | 65 | } |
| 66 | 66 | ||
diff --git a/net/netfilter/xt_NFLOG.c b/net/netfilter/xt_NFLOG.c index d3594c7ccb26..9fb449ffbf8b 100644 --- a/net/netfilter/xt_NFLOG.c +++ b/net/netfilter/xt_NFLOG.c | |||
| @@ -20,7 +20,7 @@ MODULE_ALIAS("ipt_NFLOG"); | |||
| 20 | MODULE_ALIAS("ip6t_NFLOG"); | 20 | MODULE_ALIAS("ip6t_NFLOG"); |
| 21 | 21 | ||
| 22 | static unsigned int | 22 | static unsigned int |
| 23 | nflog_target(struct sk_buff **pskb, | 23 | nflog_target(struct sk_buff *skb, |
| 24 | const struct net_device *in, const struct net_device *out, | 24 | const struct net_device *in, const struct net_device *out, |
| 25 | unsigned int hooknum, const struct xt_target *target, | 25 | unsigned int hooknum, const struct xt_target *target, |
| 26 | const void *targinfo) | 26 | const void *targinfo) |
| @@ -33,7 +33,7 @@ nflog_target(struct sk_buff **pskb, | |||
| 33 | li.u.ulog.group = info->group; | 33 | li.u.ulog.group = info->group; |
| 34 | li.u.ulog.qthreshold = info->threshold; | 34 | li.u.ulog.qthreshold = info->threshold; |
| 35 | 35 | ||
| 36 | nf_log_packet(target->family, hooknum, *pskb, in, out, &li, | 36 | nf_log_packet(target->family, hooknum, skb, in, out, &li, |
| 37 | "%s", info->prefix); | 37 | "%s", info->prefix); |
| 38 | return XT_CONTINUE; | 38 | return XT_CONTINUE; |
| 39 | } | 39 | } |
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c index 13f59f3e8c38..c3984e9f766a 100644 --- a/net/netfilter/xt_NFQUEUE.c +++ b/net/netfilter/xt_NFQUEUE.c | |||
| @@ -24,7 +24,7 @@ MODULE_ALIAS("ip6t_NFQUEUE"); | |||
| 24 | MODULE_ALIAS("arpt_NFQUEUE"); | 24 | MODULE_ALIAS("arpt_NFQUEUE"); |
| 25 | 25 | ||
| 26 | static unsigned int | 26 | static unsigned int |
| 27 | target(struct sk_buff **pskb, | 27 | target(struct sk_buff *skb, |
| 28 | const struct net_device *in, | 28 | const struct net_device *in, |
| 29 | const struct net_device *out, | 29 | const struct net_device *out, |
| 30 | unsigned int hooknum, | 30 | unsigned int hooknum, |
diff --git a/net/netfilter/xt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c index fec1aefb1c32..4976ce186615 100644 --- a/net/netfilter/xt_NOTRACK.c +++ b/net/netfilter/xt_NOTRACK.c | |||
| @@ -12,7 +12,7 @@ MODULE_ALIAS("ipt_NOTRACK"); | |||
| 12 | MODULE_ALIAS("ip6t_NOTRACK"); | 12 | MODULE_ALIAS("ip6t_NOTRACK"); |
| 13 | 13 | ||
| 14 | static unsigned int | 14 | static unsigned int |
| 15 | target(struct sk_buff **pskb, | 15 | target(struct sk_buff *skb, |
| 16 | const struct net_device *in, | 16 | const struct net_device *in, |
| 17 | const struct net_device *out, | 17 | const struct net_device *out, |
| 18 | unsigned int hooknum, | 18 | unsigned int hooknum, |
| @@ -20,16 +20,16 @@ target(struct sk_buff **pskb, | |||
| 20 | const void *targinfo) | 20 | const void *targinfo) |
| 21 | { | 21 | { |
| 22 | /* Previously seen (loopback)? Ignore. */ | 22 | /* Previously seen (loopback)? Ignore. */ |
| 23 | if ((*pskb)->nfct != NULL) | 23 | if (skb->nfct != NULL) |
| 24 | return XT_CONTINUE; | 24 | return XT_CONTINUE; |
| 25 | 25 | ||
| 26 | /* Attach fake conntrack entry. | 26 | /* Attach fake conntrack entry. |
| 27 | If there is a real ct entry correspondig to this packet, | 27 | If there is a real ct entry correspondig to this packet, |
| 28 | it'll hang aroun till timing out. We don't deal with it | 28 | it'll hang aroun till timing out. We don't deal with it |
| 29 | for performance reasons. JK */ | 29 | for performance reasons. JK */ |
| 30 | (*pskb)->nfct = &nf_conntrack_untracked.ct_general; | 30 | skb->nfct = &nf_conntrack_untracked.ct_general; |
| 31 | (*pskb)->nfctinfo = IP_CT_NEW; | 31 | skb->nfctinfo = IP_CT_NEW; |
| 32 | nf_conntrack_get((*pskb)->nfct); | 32 | nf_conntrack_get(skb->nfct); |
| 33 | 33 | ||
| 34 | return XT_CONTINUE; | 34 | return XT_CONTINUE; |
| 35 | } | 35 | } |
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c index c83779a941a1..235806eb6ecd 100644 --- a/net/netfilter/xt_SECMARK.c +++ b/net/netfilter/xt_SECMARK.c | |||
| @@ -28,7 +28,7 @@ MODULE_ALIAS("ip6t_SECMARK"); | |||
| 28 | 28 | ||
| 29 | static u8 mode; | 29 | static u8 mode; |
| 30 | 30 | ||
| 31 | static unsigned int target(struct sk_buff **pskb, const struct net_device *in, | 31 | static unsigned int target(struct sk_buff *skb, const struct net_device *in, |
| 32 | const struct net_device *out, unsigned int hooknum, | 32 | const struct net_device *out, unsigned int hooknum, |
| 33 | const struct xt_target *target, | 33 | const struct xt_target *target, |
| 34 | const void *targinfo) | 34 | const void *targinfo) |
| @@ -47,7 +47,7 @@ static unsigned int target(struct sk_buff **pskb, const struct net_device *in, | |||
| 47 | BUG(); | 47 | BUG(); |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | (*pskb)->secmark = secmark; | 50 | skb->secmark = secmark; |
| 51 | return XT_CONTINUE; | 51 | return XT_CONTINUE; |
| 52 | } | 52 | } |
| 53 | 53 | ||
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index d40f7e4b1289..07435a602b11 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c | |||
| @@ -39,7 +39,7 @@ optlen(const u_int8_t *opt, unsigned int offset) | |||
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | static int | 41 | static int |
| 42 | tcpmss_mangle_packet(struct sk_buff **pskb, | 42 | tcpmss_mangle_packet(struct sk_buff *skb, |
| 43 | const struct xt_tcpmss_info *info, | 43 | const struct xt_tcpmss_info *info, |
| 44 | unsigned int tcphoff, | 44 | unsigned int tcphoff, |
| 45 | unsigned int minlen) | 45 | unsigned int minlen) |
| @@ -50,11 +50,11 @@ tcpmss_mangle_packet(struct sk_buff **pskb, | |||
| 50 | u16 newmss; | 50 | u16 newmss; |
| 51 | u8 *opt; | 51 | u8 *opt; |
| 52 | 52 | ||
| 53 | if (!skb_make_writable(pskb, (*pskb)->len)) | 53 | if (!skb_make_writable(skb, skb->len)) |
| 54 | return -1; | 54 | return -1; |
| 55 | 55 | ||
| 56 | tcplen = (*pskb)->len - tcphoff; | 56 | tcplen = skb->len - tcphoff; |
| 57 | tcph = (struct tcphdr *)(skb_network_header(*pskb) + tcphoff); | 57 | tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); |
| 58 | 58 | ||
| 59 | /* Since it passed flags test in tcp match, we know it is is | 59 | /* Since it passed flags test in tcp match, we know it is is |
| 60 | not a fragment, and has data >= tcp header length. SYN | 60 | not a fragment, and has data >= tcp header length. SYN |
| @@ -64,19 +64,19 @@ tcpmss_mangle_packet(struct sk_buff **pskb, | |||
| 64 | if (tcplen != tcph->doff*4) { | 64 | if (tcplen != tcph->doff*4) { |
| 65 | if (net_ratelimit()) | 65 | if (net_ratelimit()) |
| 66 | printk(KERN_ERR "xt_TCPMSS: bad length (%u bytes)\n", | 66 | printk(KERN_ERR "xt_TCPMSS: bad length (%u bytes)\n", |
| 67 | (*pskb)->len); | 67 | skb->len); |
| 68 | return -1; | 68 | return -1; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | if (info->mss == XT_TCPMSS_CLAMP_PMTU) { | 71 | if (info->mss == XT_TCPMSS_CLAMP_PMTU) { |
| 72 | if (dst_mtu((*pskb)->dst) <= minlen) { | 72 | if (dst_mtu(skb->dst) <= minlen) { |
| 73 | if (net_ratelimit()) | 73 | if (net_ratelimit()) |
| 74 | printk(KERN_ERR "xt_TCPMSS: " | 74 | printk(KERN_ERR "xt_TCPMSS: " |
| 75 | "unknown or invalid path-MTU (%u)\n", | 75 | "unknown or invalid path-MTU (%u)\n", |
| 76 | dst_mtu((*pskb)->dst)); | 76 | dst_mtu(skb->dst)); |
| 77 | return -1; | 77 | return -1; |
| 78 | } | 78 | } |
| 79 | newmss = dst_mtu((*pskb)->dst) - minlen; | 79 | newmss = dst_mtu(skb->dst) - minlen; |
| 80 | } else | 80 | } else |
| 81 | newmss = info->mss; | 81 | newmss = info->mss; |
| 82 | 82 | ||
| @@ -95,7 +95,7 @@ tcpmss_mangle_packet(struct sk_buff **pskb, | |||
| 95 | opt[i+2] = (newmss & 0xff00) >> 8; | 95 | opt[i+2] = (newmss & 0xff00) >> 8; |
| 96 | opt[i+3] = newmss & 0x00ff; | 96 | opt[i+3] = newmss & 0x00ff; |
| 97 | 97 | ||
| 98 | nf_proto_csum_replace2(&tcph->check, *pskb, | 98 | nf_proto_csum_replace2(&tcph->check, skb, |
| 99 | htons(oldmss), htons(newmss), 0); | 99 | htons(oldmss), htons(newmss), 0); |
| 100 | return 0; | 100 | return 0; |
| 101 | } | 101 | } |
| @@ -104,57 +104,53 @@ tcpmss_mangle_packet(struct sk_buff **pskb, | |||
| 104 | /* | 104 | /* |
| 105 | * MSS Option not found ?! add it.. | 105 | * MSS Option not found ?! add it.. |
| 106 | */ | 106 | */ |
| 107 | if (skb_tailroom((*pskb)) < TCPOLEN_MSS) { | 107 | if (skb_tailroom(skb) < TCPOLEN_MSS) { |
| 108 | struct sk_buff *newskb; | 108 | if (pskb_expand_head(skb, 0, |
| 109 | 109 | TCPOLEN_MSS - skb_tailroom(skb), | |
| 110 | newskb = skb_copy_expand(*pskb, skb_headroom(*pskb), | 110 | GFP_ATOMIC)) |
| 111 | TCPOLEN_MSS, GFP_ATOMIC); | ||
| 112 | if (!newskb) | ||
| 113 | return -1; | 111 | return -1; |
| 114 | kfree_skb(*pskb); | 112 | tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); |
| 115 | *pskb = newskb; | ||
| 116 | tcph = (struct tcphdr *)(skb_network_header(*pskb) + tcphoff); | ||
| 117 | } | 113 | } |
| 118 | 114 | ||
| 119 | skb_put((*pskb), TCPOLEN_MSS); | 115 | skb_put(skb, TCPOLEN_MSS); |
| 120 | 116 | ||
| 121 | opt = (u_int8_t *)tcph + sizeof(struct tcphdr); | 117 | opt = (u_int8_t *)tcph + sizeof(struct tcphdr); |
| 122 | memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr)); | 118 | memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr)); |
| 123 | 119 | ||
| 124 | nf_proto_csum_replace2(&tcph->check, *pskb, | 120 | nf_proto_csum_replace2(&tcph->check, skb, |
| 125 | htons(tcplen), htons(tcplen + TCPOLEN_MSS), 1); | 121 | htons(tcplen), htons(tcplen + TCPOLEN_MSS), 1); |
| 126 | opt[0] = TCPOPT_MSS; | 122 | opt[0] = TCPOPT_MSS; |
| 127 | opt[1] = TCPOLEN_MSS; | 123 | opt[1] = TCPOLEN_MSS; |
| 128 | opt[2] = (newmss & 0xff00) >> 8; | 124 | opt[2] = (newmss & 0xff00) >> 8; |
| 129 | opt[3] = newmss & 0x00ff; | 125 | opt[3] = newmss & 0x00ff; |
| 130 | 126 | ||
| 131 | nf_proto_csum_replace4(&tcph->check, *pskb, 0, *((__be32 *)opt), 0); | 127 | nf_proto_csum_replace4(&tcph->check, skb, 0, *((__be32 *)opt), 0); |
| 132 | 128 | ||
| 133 | oldval = ((__be16 *)tcph)[6]; | 129 | oldval = ((__be16 *)tcph)[6]; |
| 134 | tcph->doff += TCPOLEN_MSS/4; | 130 | tcph->doff += TCPOLEN_MSS/4; |
| 135 | nf_proto_csum_replace2(&tcph->check, *pskb, | 131 | nf_proto_csum_replace2(&tcph->check, skb, |
| 136 | oldval, ((__be16 *)tcph)[6], 0); | 132 | oldval, ((__be16 *)tcph)[6], 0); |
| 137 | return TCPOLEN_MSS; | 133 | return TCPOLEN_MSS; |
| 138 | } | 134 | } |
| 139 | 135 | ||
| 140 | static unsigned int | 136 | static unsigned int |
| 141 | xt_tcpmss_target4(struct sk_buff **pskb, | 137 | xt_tcpmss_target4(struct sk_buff *skb, |
| 142 | const struct net_device *in, | 138 | const struct net_device *in, |
| 143 | const struct net_device *out, | 139 | const struct net_device *out, |
| 144 | unsigned int hooknum, | 140 | unsigned int hooknum, |
| 145 | const struct xt_target *target, | 141 | const struct xt_target *target, |
| 146 | const void *targinfo) | 142 | const void *targinfo) |
| 147 | { | 143 | { |
| 148 | struct iphdr *iph = ip_hdr(*pskb); | 144 | struct iphdr *iph = ip_hdr(skb); |
| 149 | __be16 newlen; | 145 | __be16 newlen; |
| 150 | int ret; | 146 | int ret; |
| 151 | 147 | ||
| 152 | ret = tcpmss_mangle_packet(pskb, targinfo, iph->ihl * 4, | 148 | ret = tcpmss_mangle_packet(skb, targinfo, iph->ihl * 4, |
| 153 | sizeof(*iph) + sizeof(struct tcphdr)); | 149 | sizeof(*iph) + sizeof(struct tcphdr)); |
| 154 | if (ret < 0) | 150 | if (ret < 0) |
| 155 | return NF_DROP; | 151 | return NF_DROP; |
| 156 | if (ret > 0) { | 152 | if (ret > 0) { |
| 157 | iph = ip_hdr(*pskb); | 153 | iph = ip_hdr(skb); |
| 158 | newlen = htons(ntohs(iph->tot_len) + ret); | 154 | newlen = htons(ntohs(iph->tot_len) + ret); |
| 159 | nf_csum_replace2(&iph->check, iph->tot_len, newlen); | 155 | nf_csum_replace2(&iph->check, iph->tot_len, newlen); |
| 160 | iph->tot_len = newlen; | 156 | iph->tot_len = newlen; |
| @@ -164,30 +160,30 @@ xt_tcpmss_target4(struct sk_buff **pskb, | |||
| 164 | 160 | ||
| 165 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) | 161 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) |
| 166 | static unsigned int | 162 | static unsigned int |
| 167 | xt_tcpmss_target6(struct sk_buff **pskb, | 163 | xt_tcpmss_target6(struct sk_buff *skb, |
| 168 | const struct net_device *in, | 164 | const struct net_device *in, |
| 169 | const struct net_device *out, | 165 | const struct net_device *out, |
| 170 | unsigned int hooknum, | 166 | unsigned int hooknum, |
| 171 | const struct xt_target *target, | 167 | const struct xt_target *target, |
| 172 | const void *targinfo) | 168 | const void *targinfo) |
| 173 | { | 169 | { |
| 174 | struct ipv6hdr *ipv6h = ipv6_hdr(*pskb); | 170 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); |
| 175 | u8 nexthdr; | 171 | u8 nexthdr; |
| 176 | int tcphoff; | 172 | int tcphoff; |
| 177 | int ret; | 173 | int ret; |
| 178 | 174 | ||
| 179 | nexthdr = ipv6h->nexthdr; | 175 | nexthdr = ipv6h->nexthdr; |
| 180 | tcphoff = ipv6_skip_exthdr(*pskb, sizeof(*ipv6h), &nexthdr); | 176 | tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr); |
| 181 | if (tcphoff < 0) { | 177 | if (tcphoff < 0) { |
| 182 | WARN_ON(1); | 178 | WARN_ON(1); |
| 183 | return NF_DROP; | 179 | return NF_DROP; |
| 184 | } | 180 | } |
| 185 | ret = tcpmss_mangle_packet(pskb, targinfo, tcphoff, | 181 | ret = tcpmss_mangle_packet(skb, targinfo, tcphoff, |
| 186 | sizeof(*ipv6h) + sizeof(struct tcphdr)); | 182 | sizeof(*ipv6h) + sizeof(struct tcphdr)); |
| 187 | if (ret < 0) | 183 | if (ret < 0) |
| 188 | return NF_DROP; | 184 | return NF_DROP; |
| 189 | if (ret > 0) { | 185 | if (ret > 0) { |
| 190 | ipv6h = ipv6_hdr(*pskb); | 186 | ipv6h = ipv6_hdr(skb); |
| 191 | ipv6h->payload_len = htons(ntohs(ipv6h->payload_len) + ret); | 187 | ipv6h->payload_len = htons(ntohs(ipv6h->payload_len) + ret); |
| 192 | } | 188 | } |
| 193 | return XT_CONTINUE; | 189 | return XT_CONTINUE; |
diff --git a/net/netfilter/xt_TRACE.c b/net/netfilter/xt_TRACE.c index 4df2dedcc0b5..26c5d08ab2c2 100644 --- a/net/netfilter/xt_TRACE.c +++ b/net/netfilter/xt_TRACE.c | |||
| @@ -10,14 +10,14 @@ MODULE_ALIAS("ipt_TRACE"); | |||
| 10 | MODULE_ALIAS("ip6t_TRACE"); | 10 | MODULE_ALIAS("ip6t_TRACE"); |
| 11 | 11 | ||
| 12 | static unsigned int | 12 | static unsigned int |
| 13 | target(struct sk_buff **pskb, | 13 | target(struct sk_buff *skb, |
| 14 | const struct net_device *in, | 14 | const struct net_device *in, |
| 15 | const struct net_device *out, | 15 | const struct net_device *out, |
| 16 | unsigned int hooknum, | 16 | unsigned int hooknum, |
| 17 | const struct xt_target *target, | 17 | const struct xt_target *target, |
| 18 | const void *targinfo) | 18 | const void *targinfo) |
| 19 | { | 19 | { |
| 20 | (*pskb)->nf_trace = 1; | 20 | skb->nf_trace = 1; |
| 21 | return XT_CONTINUE; | 21 | return XT_CONTINUE; |
| 22 | } | 22 | } |
| 23 | 23 | ||
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index c776bcd9f825..98e313e5e594 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
| @@ -1378,6 +1378,8 @@ netlink_kernel_create(struct net *net, int unit, unsigned int groups, | |||
| 1378 | nl_table[unit].cb_mutex = cb_mutex; | 1378 | nl_table[unit].cb_mutex = cb_mutex; |
| 1379 | nl_table[unit].module = module; | 1379 | nl_table[unit].module = module; |
| 1380 | nl_table[unit].registered = 1; | 1380 | nl_table[unit].registered = 1; |
| 1381 | } else { | ||
| 1382 | kfree(listeners); | ||
| 1381 | } | 1383 | } |
| 1382 | netlink_table_ungrab(); | 1384 | netlink_table_ungrab(); |
| 1383 | 1385 | ||
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index 6b407ece953c..fa006e06ce33 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c | |||
| @@ -202,11 +202,7 @@ static int tcf_ipt(struct sk_buff *skb, struct tc_action *a, | |||
| 202 | /* yes, we have to worry about both in and out dev | 202 | /* yes, we have to worry about both in and out dev |
| 203 | worry later - danger - this API seems to have changed | 203 | worry later - danger - this API seems to have changed |
| 204 | from earlier kernels */ | 204 | from earlier kernels */ |
| 205 | 205 | ret = ipt->tcfi_t->u.kernel.target->target(skb, skb->dev, NULL, | |
| 206 | /* iptables targets take a double skb pointer in case the skb | ||
| 207 | * needs to be replaced. We don't own the skb, so this must not | ||
| 208 | * happen. The pskb_expand_head above should make sure of this */ | ||
| 209 | ret = ipt->tcfi_t->u.kernel.target->target(&skb, skb->dev, NULL, | ||
| 210 | ipt->tcfi_hook, | 206 | ipt->tcfi_hook, |
| 211 | ipt->tcfi_t->u.kernel.target, | 207 | ipt->tcfi_t->u.kernel.target, |
| 212 | ipt->tcfi_t->data); | 208 | ipt->tcfi_t->data); |
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c index 2d32fd27496e..3f8335e6ea2e 100644 --- a/net/sched/sch_ingress.c +++ b/net/sched/sch_ingress.c | |||
| @@ -205,20 +205,19 @@ static unsigned int ingress_drop(struct Qdisc *sch) | |||
| 205 | #ifndef CONFIG_NET_CLS_ACT | 205 | #ifndef CONFIG_NET_CLS_ACT |
| 206 | #ifdef CONFIG_NETFILTER | 206 | #ifdef CONFIG_NETFILTER |
| 207 | static unsigned int | 207 | static unsigned int |
| 208 | ing_hook(unsigned int hook, struct sk_buff **pskb, | 208 | ing_hook(unsigned int hook, struct sk_buff *skb, |
| 209 | const struct net_device *indev, | 209 | const struct net_device *indev, |
| 210 | const struct net_device *outdev, | 210 | const struct net_device *outdev, |
| 211 | int (*okfn)(struct sk_buff *)) | 211 | int (*okfn)(struct sk_buff *)) |
| 212 | { | 212 | { |
| 213 | 213 | ||
| 214 | struct Qdisc *q; | 214 | struct Qdisc *q; |
| 215 | struct sk_buff *skb = *pskb; | ||
| 216 | struct net_device *dev = skb->dev; | 215 | struct net_device *dev = skb->dev; |
| 217 | int fwres=NF_ACCEPT; | 216 | int fwres=NF_ACCEPT; |
| 218 | 217 | ||
| 219 | DPRINTK("ing_hook: skb %s dev=%s len=%u\n", | 218 | DPRINTK("ing_hook: skb %s dev=%s len=%u\n", |
| 220 | skb->sk ? "(owned)" : "(unowned)", | 219 | skb->sk ? "(owned)" : "(unowned)", |
| 221 | skb->dev ? (*pskb)->dev->name : "(no dev)", | 220 | skb->dev ? skb->dev->name : "(no dev)", |
| 222 | skb->len); | 221 | skb->len); |
| 223 | 222 | ||
| 224 | if (dev->qdisc_ingress) { | 223 | if (dev->qdisc_ingress) { |
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 9de3ddaa2768..eb4deaf58914 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
| @@ -954,9 +954,9 @@ static struct inet_protosw sctpv6_stream_protosw = { | |||
| 954 | .flags = SCTP_PROTOSW_FLAG, | 954 | .flags = SCTP_PROTOSW_FLAG, |
| 955 | }; | 955 | }; |
| 956 | 956 | ||
| 957 | static int sctp6_rcv(struct sk_buff **pskb) | 957 | static int sctp6_rcv(struct sk_buff *skb) |
| 958 | { | 958 | { |
| 959 | return sctp_rcv(*pskb) ? -1 : 0; | 959 | return sctp_rcv(skb) ? -1 : 0; |
| 960 | } | 960 | } |
| 961 | 961 | ||
| 962 | static struct inet6_protocol sctpv6_protocol = { | 962 | static struct inet6_protocol sctpv6_protocol = { |
diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile index 8ebfc4db7f51..5c69a725e530 100644 --- a/net/sunrpc/Makefile +++ b/net/sunrpc/Makefile | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | obj-$(CONFIG_SUNRPC) += sunrpc.o | 6 | obj-$(CONFIG_SUNRPC) += sunrpc.o |
| 7 | obj-$(CONFIG_SUNRPC_GSS) += auth_gss/ | 7 | obj-$(CONFIG_SUNRPC_GSS) += auth_gss/ |
| 8 | obj-$(CONFIG_SUNRPC_XPRT_RDMA) += xprtrdma/ | ||
| 8 | 9 | ||
| 9 | sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \ | 10 | sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \ |
| 10 | auth.o auth_null.o auth_unix.o \ | 11 | auth.o auth_null.o auth_unix.o \ |
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index 42b3220bed39..8bd074df27d3 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c | |||
| @@ -42,7 +42,7 @@ gss_krb5_remove_padding(struct xdr_buf *buf, int blocksize) | |||
| 42 | { | 42 | { |
| 43 | u8 *ptr; | 43 | u8 *ptr; |
| 44 | u8 pad; | 44 | u8 pad; |
| 45 | int len = buf->len; | 45 | size_t len = buf->len; |
| 46 | 46 | ||
| 47 | if (len <= buf->head[0].iov_len) { | 47 | if (len <= buf->head[0].iov_len) { |
| 48 | pad = *(u8 *)(buf->head[0].iov_base + len - 1); | 48 | pad = *(u8 *)(buf->head[0].iov_base + len - 1); |
| @@ -53,9 +53,9 @@ gss_krb5_remove_padding(struct xdr_buf *buf, int blocksize) | |||
| 53 | } else | 53 | } else |
| 54 | len -= buf->head[0].iov_len; | 54 | len -= buf->head[0].iov_len; |
| 55 | if (len <= buf->page_len) { | 55 | if (len <= buf->page_len) { |
| 56 | int last = (buf->page_base + len - 1) | 56 | unsigned int last = (buf->page_base + len - 1) |
| 57 | >>PAGE_CACHE_SHIFT; | 57 | >>PAGE_CACHE_SHIFT; |
| 58 | int offset = (buf->page_base + len - 1) | 58 | unsigned int offset = (buf->page_base + len - 1) |
| 59 | & (PAGE_CACHE_SIZE - 1); | 59 | & (PAGE_CACHE_SIZE - 1); |
| 60 | ptr = kmap_atomic(buf->pages[last], KM_USER0); | 60 | ptr = kmap_atomic(buf->pages[last], KM_USER0); |
| 61 | pad = *(ptr + offset); | 61 | pad = *(ptr + offset); |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 52429b1ffcc1..76be83ee4b04 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
| @@ -127,7 +127,14 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s | |||
| 127 | struct rpc_clnt *clnt = NULL; | 127 | struct rpc_clnt *clnt = NULL; |
| 128 | struct rpc_auth *auth; | 128 | struct rpc_auth *auth; |
| 129 | int err; | 129 | int err; |
| 130 | int len; | 130 | size_t len; |
| 131 | |||
| 132 | /* sanity check the name before trying to print it */ | ||
| 133 | err = -EINVAL; | ||
| 134 | len = strlen(servname); | ||
| 135 | if (len > RPC_MAXNETNAMELEN) | ||
| 136 | goto out_no_rpciod; | ||
| 137 | len++; | ||
| 131 | 138 | ||
| 132 | dprintk("RPC: creating %s client for %s (xprt %p)\n", | 139 | dprintk("RPC: creating %s client for %s (xprt %p)\n", |
| 133 | program->name, servname, xprt); | 140 | program->name, servname, xprt); |
| @@ -148,7 +155,6 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s | |||
| 148 | clnt->cl_parent = clnt; | 155 | clnt->cl_parent = clnt; |
| 149 | 156 | ||
| 150 | clnt->cl_server = clnt->cl_inline_name; | 157 | clnt->cl_server = clnt->cl_inline_name; |
| 151 | len = strlen(servname) + 1; | ||
| 152 | if (len > sizeof(clnt->cl_inline_name)) { | 158 | if (len > sizeof(clnt->cl_inline_name)) { |
| 153 | char *buf = kmalloc(len, GFP_KERNEL); | 159 | char *buf = kmalloc(len, GFP_KERNEL); |
| 154 | if (buf != 0) | 160 | if (buf != 0) |
| @@ -234,8 +240,8 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
| 234 | { | 240 | { |
| 235 | struct rpc_xprt *xprt; | 241 | struct rpc_xprt *xprt; |
| 236 | struct rpc_clnt *clnt; | 242 | struct rpc_clnt *clnt; |
| 237 | struct rpc_xprtsock_create xprtargs = { | 243 | struct xprt_create xprtargs = { |
| 238 | .proto = args->protocol, | 244 | .ident = args->protocol, |
| 239 | .srcaddr = args->saddress, | 245 | .srcaddr = args->saddress, |
| 240 | .dstaddr = args->address, | 246 | .dstaddr = args->address, |
| 241 | .addrlen = args->addrsize, | 247 | .addrlen = args->addrsize, |
| @@ -253,7 +259,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
| 253 | */ | 259 | */ |
| 254 | if (args->servername == NULL) { | 260 | if (args->servername == NULL) { |
| 255 | struct sockaddr_in *addr = | 261 | struct sockaddr_in *addr = |
| 256 | (struct sockaddr_in *) &args->address; | 262 | (struct sockaddr_in *) args->address; |
| 257 | snprintf(servername, sizeof(servername), NIPQUAD_FMT, | 263 | snprintf(servername, sizeof(servername), NIPQUAD_FMT, |
| 258 | NIPQUAD(addr->sin_addr.s_addr)); | 264 | NIPQUAD(addr->sin_addr.s_addr)); |
| 259 | args->servername = servername; | 265 | args->servername = servername; |
| @@ -269,9 +275,6 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
| 269 | if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT) | 275 | if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT) |
| 270 | xprt->resvport = 0; | 276 | xprt->resvport = 0; |
| 271 | 277 | ||
| 272 | dprintk("RPC: creating %s client for %s (xprt %p)\n", | ||
| 273 | args->program->name, args->servername, xprt); | ||
| 274 | |||
| 275 | clnt = rpc_new_client(xprt, args->servername, args->program, | 278 | clnt = rpc_new_client(xprt, args->servername, args->program, |
| 276 | args->version, args->authflavor); | 279 | args->version, args->authflavor); |
| 277 | if (IS_ERR(clnt)) | 280 | if (IS_ERR(clnt)) |
| @@ -439,7 +442,7 @@ rpc_release_client(struct rpc_clnt *clnt) | |||
| 439 | */ | 442 | */ |
| 440 | struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, | 443 | struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, |
| 441 | struct rpc_program *program, | 444 | struct rpc_program *program, |
| 442 | int vers) | 445 | u32 vers) |
| 443 | { | 446 | { |
| 444 | struct rpc_clnt *clnt; | 447 | struct rpc_clnt *clnt; |
| 445 | struct rpc_version *version; | 448 | struct rpc_version *version; |
| @@ -843,8 +846,7 @@ call_allocate(struct rpc_task *task) | |||
| 843 | dprintk("RPC: %5u rpc_buffer allocation failed\n", task->tk_pid); | 846 | dprintk("RPC: %5u rpc_buffer allocation failed\n", task->tk_pid); |
| 844 | 847 | ||
| 845 | if (RPC_IS_ASYNC(task) || !signalled()) { | 848 | if (RPC_IS_ASYNC(task) || !signalled()) { |
| 846 | xprt_release(task); | 849 | task->tk_action = call_allocate; |
| 847 | task->tk_action = call_reserve; | ||
| 848 | rpc_delay(task, HZ>>4); | 850 | rpc_delay(task, HZ>>4); |
| 849 | return; | 851 | return; |
| 850 | } | 852 | } |
| @@ -871,6 +873,7 @@ rpc_xdr_buf_init(struct xdr_buf *buf, void *start, size_t len) | |||
| 871 | buf->head[0].iov_len = len; | 873 | buf->head[0].iov_len = len; |
| 872 | buf->tail[0].iov_len = 0; | 874 | buf->tail[0].iov_len = 0; |
| 873 | buf->page_len = 0; | 875 | buf->page_len = 0; |
| 876 | buf->flags = 0; | ||
| 874 | buf->len = 0; | 877 | buf->len = 0; |
| 875 | buf->buflen = len; | 878 | buf->buflen = len; |
| 876 | } | 879 | } |
| @@ -937,7 +940,7 @@ call_bind(struct rpc_task *task) | |||
| 937 | static void | 940 | static void |
| 938 | call_bind_status(struct rpc_task *task) | 941 | call_bind_status(struct rpc_task *task) |
| 939 | { | 942 | { |
| 940 | int status = -EACCES; | 943 | int status = -EIO; |
| 941 | 944 | ||
| 942 | if (task->tk_status >= 0) { | 945 | if (task->tk_status >= 0) { |
| 943 | dprint_status(task); | 946 | dprint_status(task); |
| @@ -947,9 +950,20 @@ call_bind_status(struct rpc_task *task) | |||
| 947 | } | 950 | } |
| 948 | 951 | ||
| 949 | switch (task->tk_status) { | 952 | switch (task->tk_status) { |
| 953 | case -EAGAIN: | ||
| 954 | dprintk("RPC: %5u rpcbind waiting for another request " | ||
| 955 | "to finish\n", task->tk_pid); | ||
| 956 | /* avoid busy-waiting here -- could be a network outage. */ | ||
| 957 | rpc_delay(task, 5*HZ); | ||
| 958 | goto retry_timeout; | ||
| 950 | case -EACCES: | 959 | case -EACCES: |
| 951 | dprintk("RPC: %5u remote rpcbind: RPC program/version " | 960 | dprintk("RPC: %5u remote rpcbind: RPC program/version " |
| 952 | "unavailable\n", task->tk_pid); | 961 | "unavailable\n", task->tk_pid); |
| 962 | /* fail immediately if this is an RPC ping */ | ||
| 963 | if (task->tk_msg.rpc_proc->p_proc == 0) { | ||
| 964 | status = -EOPNOTSUPP; | ||
| 965 | break; | ||
| 966 | } | ||
| 953 | rpc_delay(task, 3*HZ); | 967 | rpc_delay(task, 3*HZ); |
| 954 | goto retry_timeout; | 968 | goto retry_timeout; |
| 955 | case -ETIMEDOUT: | 969 | case -ETIMEDOUT: |
| @@ -957,6 +971,7 @@ call_bind_status(struct rpc_task *task) | |||
| 957 | task->tk_pid); | 971 | task->tk_pid); |
| 958 | goto retry_timeout; | 972 | goto retry_timeout; |
| 959 | case -EPFNOSUPPORT: | 973 | case -EPFNOSUPPORT: |
| 974 | /* server doesn't support any rpcbind version we know of */ | ||
| 960 | dprintk("RPC: %5u remote rpcbind service unavailable\n", | 975 | dprintk("RPC: %5u remote rpcbind service unavailable\n", |
| 961 | task->tk_pid); | 976 | task->tk_pid); |
| 962 | break; | 977 | break; |
| @@ -969,7 +984,6 @@ call_bind_status(struct rpc_task *task) | |||
| 969 | default: | 984 | default: |
| 970 | dprintk("RPC: %5u unrecognized rpcbind error (%d)\n", | 985 | dprintk("RPC: %5u unrecognized rpcbind error (%d)\n", |
| 971 | task->tk_pid, -task->tk_status); | 986 | task->tk_pid, -task->tk_status); |
| 972 | status = -EIO; | ||
| 973 | } | 987 | } |
| 974 | 988 | ||
| 975 | rpc_exit(task, status); | 989 | rpc_exit(task, status); |
| @@ -1257,7 +1271,6 @@ call_refresh(struct rpc_task *task) | |||
| 1257 | { | 1271 | { |
| 1258 | dprint_status(task); | 1272 | dprint_status(task); |
| 1259 | 1273 | ||
| 1260 | xprt_release(task); /* Must do to obtain new XID */ | ||
| 1261 | task->tk_action = call_refreshresult; | 1274 | task->tk_action = call_refreshresult; |
| 1262 | task->tk_status = 0; | 1275 | task->tk_status = 0; |
| 1263 | task->tk_client->cl_stats->rpcauthrefresh++; | 1276 | task->tk_client->cl_stats->rpcauthrefresh++; |
| @@ -1375,6 +1388,8 @@ call_verify(struct rpc_task *task) | |||
| 1375 | dprintk("RPC: %5u %s: retry stale creds\n", | 1388 | dprintk("RPC: %5u %s: retry stale creds\n", |
| 1376 | task->tk_pid, __FUNCTION__); | 1389 | task->tk_pid, __FUNCTION__); |
| 1377 | rpcauth_invalcred(task); | 1390 | rpcauth_invalcred(task); |
| 1391 | /* Ensure we obtain a new XID! */ | ||
| 1392 | xprt_release(task); | ||
| 1378 | task->tk_action = call_refresh; | 1393 | task->tk_action = call_refresh; |
| 1379 | goto out_retry; | 1394 | goto out_retry; |
| 1380 | case RPC_AUTH_BADCRED: | 1395 | case RPC_AUTH_BADCRED: |
| @@ -1523,13 +1538,18 @@ void rpc_show_tasks(void) | |||
| 1523 | spin_lock(&clnt->cl_lock); | 1538 | spin_lock(&clnt->cl_lock); |
| 1524 | list_for_each_entry(t, &clnt->cl_tasks, tk_task) { | 1539 | list_for_each_entry(t, &clnt->cl_tasks, tk_task) { |
| 1525 | const char *rpc_waitq = "none"; | 1540 | const char *rpc_waitq = "none"; |
| 1541 | int proc; | ||
| 1542 | |||
| 1543 | if (t->tk_msg.rpc_proc) | ||
| 1544 | proc = t->tk_msg.rpc_proc->p_proc; | ||
| 1545 | else | ||
| 1546 | proc = -1; | ||
| 1526 | 1547 | ||
| 1527 | if (RPC_IS_QUEUED(t)) | 1548 | if (RPC_IS_QUEUED(t)) |
| 1528 | rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq); | 1549 | rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq); |
| 1529 | 1550 | ||
| 1530 | printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n", | 1551 | printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n", |
| 1531 | t->tk_pid, | 1552 | t->tk_pid, proc, |
| 1532 | (t->tk_msg.rpc_proc ? t->tk_msg.rpc_proc->p_proc : -1), | ||
| 1533 | t->tk_flags, t->tk_status, | 1553 | t->tk_flags, t->tk_status, |
| 1534 | t->tk_client, | 1554 | t->tk_client, |
| 1535 | (t->tk_client ? t->tk_client->cl_prog : 0), | 1555 | (t->tk_client ? t->tk_client->cl_prog : 0), |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 669e12a4ed18..c8433e8865aa 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
| @@ -14,7 +14,7 @@ | |||
| 14 | #include <linux/pagemap.h> | 14 | #include <linux/pagemap.h> |
| 15 | #include <linux/mount.h> | 15 | #include <linux/mount.h> |
| 16 | #include <linux/namei.h> | 16 | #include <linux/namei.h> |
| 17 | #include <linux/dnotify.h> | 17 | #include <linux/fsnotify.h> |
| 18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
| 19 | 19 | ||
| 20 | #include <asm/ioctls.h> | 20 | #include <asm/ioctls.h> |
| @@ -329,6 +329,7 @@ rpc_show_info(struct seq_file *m, void *v) | |||
| 329 | clnt->cl_prog, clnt->cl_vers); | 329 | clnt->cl_prog, clnt->cl_vers); |
| 330 | seq_printf(m, "address: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR)); | 330 | seq_printf(m, "address: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR)); |
| 331 | seq_printf(m, "protocol: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PROTO)); | 331 | seq_printf(m, "protocol: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PROTO)); |
| 332 | seq_printf(m, "port: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PORT)); | ||
| 332 | return 0; | 333 | return 0; |
| 333 | } | 334 | } |
| 334 | 335 | ||
| @@ -585,6 +586,7 @@ rpc_populate(struct dentry *parent, | |||
| 585 | if (S_ISDIR(mode)) | 586 | if (S_ISDIR(mode)) |
| 586 | inc_nlink(dir); | 587 | inc_nlink(dir); |
| 587 | d_add(dentry, inode); | 588 | d_add(dentry, inode); |
| 589 | fsnotify_create(dir, dentry); | ||
| 588 | } | 590 | } |
| 589 | mutex_unlock(&dir->i_mutex); | 591 | mutex_unlock(&dir->i_mutex); |
| 590 | return 0; | 592 | return 0; |
| @@ -606,7 +608,7 @@ __rpc_mkdir(struct inode *dir, struct dentry *dentry) | |||
| 606 | inode->i_ino = iunique(dir->i_sb, 100); | 608 | inode->i_ino = iunique(dir->i_sb, 100); |
| 607 | d_instantiate(dentry, inode); | 609 | d_instantiate(dentry, inode); |
| 608 | inc_nlink(dir); | 610 | inc_nlink(dir); |
| 609 | inode_dir_notify(dir, DN_CREATE); | 611 | fsnotify_mkdir(dir, dentry); |
| 610 | return 0; | 612 | return 0; |
| 611 | out_err: | 613 | out_err: |
| 612 | printk(KERN_WARNING "%s: %s failed to allocate inode for dentry %s\n", | 614 | printk(KERN_WARNING "%s: %s failed to allocate inode for dentry %s\n", |
| @@ -748,7 +750,7 @@ rpc_mkpipe(struct dentry *parent, const char *name, void *private, struct rpc_pi | |||
| 748 | rpci->flags = flags; | 750 | rpci->flags = flags; |
| 749 | rpci->ops = ops; | 751 | rpci->ops = ops; |
| 750 | rpci->nkern_readwriters = 1; | 752 | rpci->nkern_readwriters = 1; |
| 751 | inode_dir_notify(dir, DN_CREATE); | 753 | fsnotify_create(dir, dentry); |
| 752 | dget(dentry); | 754 | dget(dentry); |
| 753 | out: | 755 | out: |
| 754 | mutex_unlock(&dir->i_mutex); | 756 | mutex_unlock(&dir->i_mutex); |
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index d1740dbab991..a05493aedb68 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c | |||
| @@ -16,11 +16,14 @@ | |||
| 16 | 16 | ||
| 17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
| 18 | #include <linux/socket.h> | 18 | #include <linux/socket.h> |
| 19 | #include <linux/in.h> | ||
| 20 | #include <linux/in6.h> | ||
| 19 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
| 20 | #include <linux/errno.h> | 22 | #include <linux/errno.h> |
| 21 | 23 | ||
| 22 | #include <linux/sunrpc/clnt.h> | 24 | #include <linux/sunrpc/clnt.h> |
| 23 | #include <linux/sunrpc/sched.h> | 25 | #include <linux/sunrpc/sched.h> |
| 26 | #include <linux/sunrpc/xprtsock.h> | ||
| 24 | 27 | ||
| 25 | #ifdef RPC_DEBUG | 28 | #ifdef RPC_DEBUG |
| 26 | # define RPCDBG_FACILITY RPCDBG_BIND | 29 | # define RPCDBG_FACILITY RPCDBG_BIND |
| @@ -91,26 +94,6 @@ enum { | |||
| 91 | #define RPCB_MAXADDRLEN (128u) | 94 | #define RPCB_MAXADDRLEN (128u) |
| 92 | 95 | ||
| 93 | /* | 96 | /* |
| 94 | * r_netid | ||
| 95 | * | ||
| 96 | * Quoting RFC 3530, section 2.2: | ||
| 97 | * | ||
| 98 | * For TCP over IPv4 the value of r_netid is the string "tcp". For UDP | ||
| 99 | * over IPv4 the value of r_netid is the string "udp". | ||
| 100 | * | ||
| 101 | * ... | ||
| 102 | * | ||
| 103 | * For TCP over IPv6 the value of r_netid is the string "tcp6". For UDP | ||
| 104 | * over IPv6 the value of r_netid is the string "udp6". | ||
| 105 | */ | ||
| 106 | #define RPCB_NETID_UDP "\165\144\160" /* "udp" */ | ||
| 107 | #define RPCB_NETID_TCP "\164\143\160" /* "tcp" */ | ||
| 108 | #define RPCB_NETID_UDP6 "\165\144\160\066" /* "udp6" */ | ||
| 109 | #define RPCB_NETID_TCP6 "\164\143\160\066" /* "tcp6" */ | ||
| 110 | |||
| 111 | #define RPCB_MAXNETIDLEN (4u) | ||
| 112 | |||
| 113 | /* | ||
| 114 | * r_owner | 97 | * r_owner |
| 115 | * | 98 | * |
| 116 | * The "owner" is allowed to unset a service in the rpcbind database. | 99 | * The "owner" is allowed to unset a service in the rpcbind database. |
| @@ -120,7 +103,7 @@ enum { | |||
| 120 | #define RPCB_MAXOWNERLEN sizeof(RPCB_OWNER_STRING) | 103 | #define RPCB_MAXOWNERLEN sizeof(RPCB_OWNER_STRING) |
| 121 | 104 | ||
| 122 | static void rpcb_getport_done(struct rpc_task *, void *); | 105 | static void rpcb_getport_done(struct rpc_task *, void *); |
| 123 | extern struct rpc_program rpcb_program; | 106 | static struct rpc_program rpcb_program; |
| 124 | 107 | ||
| 125 | struct rpcbind_args { | 108 | struct rpcbind_args { |
| 126 | struct rpc_xprt * r_xprt; | 109 | struct rpc_xprt * r_xprt; |
| @@ -137,10 +120,13 @@ struct rpcbind_args { | |||
| 137 | static struct rpc_procinfo rpcb_procedures2[]; | 120 | static struct rpc_procinfo rpcb_procedures2[]; |
| 138 | static struct rpc_procinfo rpcb_procedures3[]; | 121 | static struct rpc_procinfo rpcb_procedures3[]; |
| 139 | 122 | ||
| 140 | static struct rpcb_info { | 123 | struct rpcb_info { |
| 141 | int rpc_vers; | 124 | int rpc_vers; |
| 142 | struct rpc_procinfo * rpc_proc; | 125 | struct rpc_procinfo * rpc_proc; |
| 143 | } rpcb_next_version[]; | 126 | }; |
| 127 | |||
| 128 | static struct rpcb_info rpcb_next_version[]; | ||
| 129 | static struct rpcb_info rpcb_next_version6[]; | ||
| 144 | 130 | ||
| 145 | static void rpcb_getport_prepare(struct rpc_task *task, void *calldata) | 131 | static void rpcb_getport_prepare(struct rpc_task *task, void *calldata) |
| 146 | { | 132 | { |
| @@ -190,7 +176,17 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr, | |||
| 190 | RPC_CLNT_CREATE_INTR), | 176 | RPC_CLNT_CREATE_INTR), |
| 191 | }; | 177 | }; |
| 192 | 178 | ||
| 193 | ((struct sockaddr_in *)srvaddr)->sin_port = htons(RPCBIND_PORT); | 179 | switch (srvaddr->sa_family) { |
| 180 | case AF_INET: | ||
| 181 | ((struct sockaddr_in *)srvaddr)->sin_port = htons(RPCBIND_PORT); | ||
| 182 | break; | ||
| 183 | case AF_INET6: | ||
| 184 | ((struct sockaddr_in6 *)srvaddr)->sin6_port = htons(RPCBIND_PORT); | ||
| 185 | break; | ||
| 186 | default: | ||
| 187 | return NULL; | ||
| 188 | } | ||
| 189 | |||
| 194 | if (!privileged) | 190 | if (!privileged) |
| 195 | args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; | 191 | args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; |
| 196 | return rpc_create(&args); | 192 | return rpc_create(&args); |
| @@ -234,7 +230,7 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay) | |||
| 234 | prog, vers, prot, port); | 230 | prog, vers, prot, port); |
| 235 | 231 | ||
| 236 | rpcb_clnt = rpcb_create("localhost", (struct sockaddr *) &sin, | 232 | rpcb_clnt = rpcb_create("localhost", (struct sockaddr *) &sin, |
| 237 | IPPROTO_UDP, 2, 1); | 233 | XPRT_TRANSPORT_UDP, 2, 1); |
| 238 | if (IS_ERR(rpcb_clnt)) | 234 | if (IS_ERR(rpcb_clnt)) |
| 239 | return PTR_ERR(rpcb_clnt); | 235 | return PTR_ERR(rpcb_clnt); |
| 240 | 236 | ||
| @@ -316,6 +312,7 @@ void rpcb_getport_async(struct rpc_task *task) | |||
| 316 | struct rpc_task *child; | 312 | struct rpc_task *child; |
| 317 | struct sockaddr addr; | 313 | struct sockaddr addr; |
| 318 | int status; | 314 | int status; |
| 315 | struct rpcb_info *info; | ||
| 319 | 316 | ||
| 320 | dprintk("RPC: %5u %s(%s, %u, %u, %d)\n", | 317 | dprintk("RPC: %5u %s(%s, %u, %u, %d)\n", |
| 321 | task->tk_pid, __FUNCTION__, | 318 | task->tk_pid, __FUNCTION__, |
| @@ -325,7 +322,7 @@ void rpcb_getport_async(struct rpc_task *task) | |||
| 325 | BUG_ON(clnt->cl_parent != clnt); | 322 | BUG_ON(clnt->cl_parent != clnt); |
| 326 | 323 | ||
| 327 | if (xprt_test_and_set_binding(xprt)) { | 324 | if (xprt_test_and_set_binding(xprt)) { |
| 328 | status = -EACCES; /* tell caller to check again */ | 325 | status = -EAGAIN; /* tell caller to check again */ |
| 329 | dprintk("RPC: %5u %s: waiting for another binder\n", | 326 | dprintk("RPC: %5u %s: waiting for another binder\n", |
| 330 | task->tk_pid, __FUNCTION__); | 327 | task->tk_pid, __FUNCTION__); |
| 331 | goto bailout_nowake; | 328 | goto bailout_nowake; |
| @@ -343,18 +340,43 @@ void rpcb_getport_async(struct rpc_task *task) | |||
| 343 | goto bailout_nofree; | 340 | goto bailout_nofree; |
| 344 | } | 341 | } |
| 345 | 342 | ||
| 346 | if (rpcb_next_version[xprt->bind_index].rpc_proc == NULL) { | 343 | rpc_peeraddr(clnt, (void *)&addr, sizeof(addr)); |
| 344 | |||
| 345 | /* Don't ever use rpcbind v2 for AF_INET6 requests */ | ||
| 346 | switch (addr.sa_family) { | ||
| 347 | case AF_INET: | ||
| 348 | info = rpcb_next_version; | ||
| 349 | break; | ||
| 350 | case AF_INET6: | ||
| 351 | info = rpcb_next_version6; | ||
| 352 | break; | ||
| 353 | default: | ||
| 354 | status = -EAFNOSUPPORT; | ||
| 355 | dprintk("RPC: %5u %s: bad address family\n", | ||
| 356 | task->tk_pid, __FUNCTION__); | ||
| 357 | goto bailout_nofree; | ||
| 358 | } | ||
| 359 | if (info[xprt->bind_index].rpc_proc == NULL) { | ||
| 347 | xprt->bind_index = 0; | 360 | xprt->bind_index = 0; |
| 348 | status = -EACCES; /* tell caller to try again later */ | 361 | status = -EPFNOSUPPORT; |
| 349 | dprintk("RPC: %5u %s: no more getport versions available\n", | 362 | dprintk("RPC: %5u %s: no more getport versions available\n", |
| 350 | task->tk_pid, __FUNCTION__); | 363 | task->tk_pid, __FUNCTION__); |
| 351 | goto bailout_nofree; | 364 | goto bailout_nofree; |
| 352 | } | 365 | } |
| 353 | bind_version = rpcb_next_version[xprt->bind_index].rpc_vers; | 366 | bind_version = info[xprt->bind_index].rpc_vers; |
| 354 | 367 | ||
| 355 | dprintk("RPC: %5u %s: trying rpcbind version %u\n", | 368 | dprintk("RPC: %5u %s: trying rpcbind version %u\n", |
| 356 | task->tk_pid, __FUNCTION__, bind_version); | 369 | task->tk_pid, __FUNCTION__, bind_version); |
| 357 | 370 | ||
| 371 | rpcb_clnt = rpcb_create(clnt->cl_server, &addr, xprt->prot, | ||
| 372 | bind_version, 0); | ||
| 373 | if (IS_ERR(rpcb_clnt)) { | ||
| 374 | status = PTR_ERR(rpcb_clnt); | ||
| 375 | dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n", | ||
| 376 | task->tk_pid, __FUNCTION__, PTR_ERR(rpcb_clnt)); | ||
| 377 | goto bailout_nofree; | ||
| 378 | } | ||
| 379 | |||
| 358 | map = kzalloc(sizeof(struct rpcbind_args), GFP_ATOMIC); | 380 | map = kzalloc(sizeof(struct rpcbind_args), GFP_ATOMIC); |
| 359 | if (!map) { | 381 | if (!map) { |
| 360 | status = -ENOMEM; | 382 | status = -ENOMEM; |
| @@ -367,28 +389,19 @@ void rpcb_getport_async(struct rpc_task *task) | |||
| 367 | map->r_prot = xprt->prot; | 389 | map->r_prot = xprt->prot; |
| 368 | map->r_port = 0; | 390 | map->r_port = 0; |
| 369 | map->r_xprt = xprt_get(xprt); | 391 | map->r_xprt = xprt_get(xprt); |
| 370 | map->r_netid = (xprt->prot == IPPROTO_TCP) ? RPCB_NETID_TCP : | 392 | map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); |
| 371 | RPCB_NETID_UDP; | 393 | memcpy(map->r_addr, |
| 372 | memcpy(&map->r_addr, rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR), | 394 | rpc_peeraddr2str(rpcb_clnt, RPC_DISPLAY_UNIVERSAL_ADDR), |
| 373 | sizeof(map->r_addr)); | 395 | sizeof(map->r_addr)); |
| 374 | map->r_owner = RPCB_OWNER_STRING; /* ignored for GETADDR */ | 396 | map->r_owner = RPCB_OWNER_STRING; /* ignored for GETADDR */ |
| 375 | 397 | ||
| 376 | rpc_peeraddr(clnt, (void *)&addr, sizeof(addr)); | ||
| 377 | rpcb_clnt = rpcb_create(clnt->cl_server, &addr, xprt->prot, bind_version, 0); | ||
| 378 | if (IS_ERR(rpcb_clnt)) { | ||
| 379 | status = PTR_ERR(rpcb_clnt); | ||
| 380 | dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n", | ||
| 381 | task->tk_pid, __FUNCTION__, PTR_ERR(rpcb_clnt)); | ||
| 382 | goto bailout; | ||
| 383 | } | ||
| 384 | |||
| 385 | child = rpc_run_task(rpcb_clnt, RPC_TASK_ASYNC, &rpcb_getport_ops, map); | 398 | child = rpc_run_task(rpcb_clnt, RPC_TASK_ASYNC, &rpcb_getport_ops, map); |
| 386 | rpc_release_client(rpcb_clnt); | 399 | rpc_release_client(rpcb_clnt); |
| 387 | if (IS_ERR(child)) { | 400 | if (IS_ERR(child)) { |
| 388 | status = -EIO; | 401 | status = -EIO; |
| 389 | dprintk("RPC: %5u %s: rpc_run_task failed\n", | 402 | dprintk("RPC: %5u %s: rpc_run_task failed\n", |
| 390 | task->tk_pid, __FUNCTION__); | 403 | task->tk_pid, __FUNCTION__); |
| 391 | goto bailout_nofree; | 404 | goto bailout; |
| 392 | } | 405 | } |
| 393 | rpc_put_task(child); | 406 | rpc_put_task(child); |
| 394 | 407 | ||
| @@ -403,6 +416,7 @@ bailout_nofree: | |||
| 403 | bailout_nowake: | 416 | bailout_nowake: |
| 404 | task->tk_status = status; | 417 | task->tk_status = status; |
| 405 | } | 418 | } |
| 419 | EXPORT_SYMBOL_GPL(rpcb_getport_async); | ||
| 406 | 420 | ||
| 407 | /* | 421 | /* |
| 408 | * Rpcbind child task calls this callback via tk_exit. | 422 | * Rpcbind child task calls this callback via tk_exit. |
| @@ -413,6 +427,10 @@ static void rpcb_getport_done(struct rpc_task *child, void *data) | |||
| 413 | struct rpc_xprt *xprt = map->r_xprt; | 427 | struct rpc_xprt *xprt = map->r_xprt; |
| 414 | int status = child->tk_status; | 428 | int status = child->tk_status; |
| 415 | 429 | ||
| 430 | /* Garbage reply: retry with a lesser rpcbind version */ | ||
| 431 | if (status == -EIO) | ||
| 432 | status = -EPROTONOSUPPORT; | ||
| 433 | |||
| 416 | /* rpcbind server doesn't support this rpcbind protocol version */ | 434 | /* rpcbind server doesn't support this rpcbind protocol version */ |
| 417 | if (status == -EPROTONOSUPPORT) | 435 | if (status == -EPROTONOSUPPORT) |
| 418 | xprt->bind_index++; | 436 | xprt->bind_index++; |
| @@ -490,16 +508,24 @@ static int rpcb_decode_getaddr(struct rpc_rqst *req, __be32 *p, | |||
| 490 | unsigned short *portp) | 508 | unsigned short *portp) |
| 491 | { | 509 | { |
| 492 | char *addr; | 510 | char *addr; |
| 493 | int addr_len, c, i, f, first, val; | 511 | u32 addr_len; |
| 512 | int c, i, f, first, val; | ||
| 494 | 513 | ||
| 495 | *portp = 0; | 514 | *portp = 0; |
| 496 | addr_len = (unsigned int) ntohl(*p++); | 515 | addr_len = ntohl(*p++); |
| 497 | if (addr_len > RPCB_MAXADDRLEN) /* sanity */ | 516 | |
| 498 | return -EINVAL; | 517 | /* |
| 499 | 518 | * Simple sanity check. The smallest possible universal | |
| 500 | dprintk("RPC: rpcb_decode_getaddr returned string: '%s'\n", | 519 | * address is an IPv4 address string containing 11 bytes. |
| 501 | (char *) p); | 520 | */ |
| 502 | 521 | if (addr_len < 11 || addr_len > RPCB_MAXADDRLEN) | |
| 522 | goto out_err; | ||
| 523 | |||
| 524 | /* | ||
| 525 | * Start at the end and walk backwards until the first dot | ||
| 526 | * is encountered. When the second dot is found, we have | ||
| 527 | * both parts of the port number. | ||
| 528 | */ | ||
| 503 | addr = (char *)p; | 529 | addr = (char *)p; |
| 504 | val = 0; | 530 | val = 0; |
| 505 | first = 1; | 531 | first = 1; |
| @@ -521,8 +547,19 @@ static int rpcb_decode_getaddr(struct rpc_rqst *req, __be32 *p, | |||
| 521 | } | 547 | } |
| 522 | } | 548 | } |
| 523 | 549 | ||
| 550 | /* | ||
| 551 | * Simple sanity check. If we never saw a dot in the reply, | ||
| 552 | * then this was probably just garbage. | ||
| 553 | */ | ||
| 554 | if (first) | ||
| 555 | goto out_err; | ||
| 556 | |||
| 524 | dprintk("RPC: rpcb_decode_getaddr port=%u\n", *portp); | 557 | dprintk("RPC: rpcb_decode_getaddr port=%u\n", *portp); |
| 525 | return 0; | 558 | return 0; |
| 559 | |||
| 560 | out_err: | ||
| 561 | dprintk("RPC: rpcbind server returned malformed reply\n"); | ||
| 562 | return -EIO; | ||
| 526 | } | 563 | } |
| 527 | 564 | ||
| 528 | #define RPCB_program_sz (1u) | 565 | #define RPCB_program_sz (1u) |
| @@ -531,7 +568,7 @@ static int rpcb_decode_getaddr(struct rpc_rqst *req, __be32 *p, | |||
| 531 | #define RPCB_port_sz (1u) | 568 | #define RPCB_port_sz (1u) |
| 532 | #define RPCB_boolean_sz (1u) | 569 | #define RPCB_boolean_sz (1u) |
| 533 | 570 | ||
| 534 | #define RPCB_netid_sz (1+XDR_QUADLEN(RPCB_MAXNETIDLEN)) | 571 | #define RPCB_netid_sz (1+XDR_QUADLEN(RPCBIND_MAXNETIDLEN)) |
| 535 | #define RPCB_addr_sz (1+XDR_QUADLEN(RPCB_MAXADDRLEN)) | 572 | #define RPCB_addr_sz (1+XDR_QUADLEN(RPCB_MAXADDRLEN)) |
| 536 | #define RPCB_ownerstring_sz (1+XDR_QUADLEN(RPCB_MAXOWNERLEN)) | 573 | #define RPCB_ownerstring_sz (1+XDR_QUADLEN(RPCB_MAXOWNERLEN)) |
| 537 | 574 | ||
| @@ -593,6 +630,14 @@ static struct rpcb_info rpcb_next_version[] = { | |||
| 593 | { 0, NULL }, | 630 | { 0, NULL }, |
| 594 | }; | 631 | }; |
| 595 | 632 | ||
| 633 | static struct rpcb_info rpcb_next_version6[] = { | ||
| 634 | #ifdef CONFIG_SUNRPC_BIND34 | ||
| 635 | { 4, &rpcb_procedures4[RPCBPROC_GETVERSADDR] }, | ||
| 636 | { 3, &rpcb_procedures3[RPCBPROC_GETADDR] }, | ||
| 637 | #endif | ||
| 638 | { 0, NULL }, | ||
| 639 | }; | ||
| 640 | |||
| 596 | static struct rpc_version rpcb_version2 = { | 641 | static struct rpc_version rpcb_version2 = { |
| 597 | .number = 2, | 642 | .number = 2, |
| 598 | .nrprocs = RPCB_HIGHPROC_2, | 643 | .nrprocs = RPCB_HIGHPROC_2, |
| @@ -621,7 +666,7 @@ static struct rpc_version *rpcb_version[] = { | |||
| 621 | 666 | ||
| 622 | static struct rpc_stat rpcb_stats; | 667 | static struct rpc_stat rpcb_stats; |
| 623 | 668 | ||
| 624 | struct rpc_program rpcb_program = { | 669 | static struct rpc_program rpcb_program = { |
| 625 | .name = "rpcbind", | 670 | .name = "rpcbind", |
| 626 | .number = RPCBIND_PROGRAM, | 671 | .number = RPCBIND_PROGRAM, |
| 627 | .nrvers = ARRAY_SIZE(rpcb_version), | 672 | .nrvers = ARRAY_SIZE(rpcb_version), |
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 954d7ec86c7e..3c773c53e12e 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
| @@ -777,6 +777,7 @@ void *rpc_malloc(struct rpc_task *task, size_t size) | |||
| 777 | task->tk_pid, size, buf); | 777 | task->tk_pid, size, buf); |
| 778 | return &buf->data; | 778 | return &buf->data; |
| 779 | } | 779 | } |
| 780 | EXPORT_SYMBOL_GPL(rpc_malloc); | ||
| 780 | 781 | ||
| 781 | /** | 782 | /** |
| 782 | * rpc_free - free buffer allocated via rpc_malloc | 783 | * rpc_free - free buffer allocated via rpc_malloc |
| @@ -802,6 +803,7 @@ void rpc_free(void *buffer) | |||
| 802 | else | 803 | else |
| 803 | kfree(buf); | 804 | kfree(buf); |
| 804 | } | 805 | } |
| 806 | EXPORT_SYMBOL_GPL(rpc_free); | ||
| 805 | 807 | ||
| 806 | /* | 808 | /* |
| 807 | * Creation and deletion of RPC task structures | 809 | * Creation and deletion of RPC task structures |
diff --git a/net/sunrpc/socklib.c b/net/sunrpc/socklib.c index 1d377d1ab7f4..97ac45f034d6 100644 --- a/net/sunrpc/socklib.c +++ b/net/sunrpc/socklib.c | |||
| @@ -34,6 +34,7 @@ size_t xdr_skb_read_bits(struct xdr_skb_reader *desc, void *to, size_t len) | |||
| 34 | desc->offset += len; | 34 | desc->offset += len; |
| 35 | return len; | 35 | return len; |
| 36 | } | 36 | } |
| 37 | EXPORT_SYMBOL_GPL(xdr_skb_read_bits); | ||
| 37 | 38 | ||
| 38 | /** | 39 | /** |
| 39 | * xdr_skb_read_and_csum_bits - copy and checksum from skb to buffer | 40 | * xdr_skb_read_and_csum_bits - copy and checksum from skb to buffer |
| @@ -137,6 +138,7 @@ copy_tail: | |||
| 137 | out: | 138 | out: |
| 138 | return copied; | 139 | return copied; |
| 139 | } | 140 | } |
| 141 | EXPORT_SYMBOL_GPL(xdr_partial_copy_from_skb); | ||
| 140 | 142 | ||
| 141 | /** | 143 | /** |
| 142 | * csum_partial_copy_to_xdr - checksum and copy data | 144 | * csum_partial_copy_to_xdr - checksum and copy data |
| @@ -179,3 +181,4 @@ no_checksum: | |||
| 179 | return -1; | 181 | return -1; |
| 180 | return 0; | 182 | return 0; |
| 181 | } | 183 | } |
| 184 | EXPORT_SYMBOL_GPL(csum_partial_copy_to_xdr); | ||
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index 384c4ad5ab86..33d89e842c85 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c | |||
| @@ -20,7 +20,7 @@ | |||
| 20 | #include <linux/sunrpc/auth.h> | 20 | #include <linux/sunrpc/auth.h> |
| 21 | #include <linux/workqueue.h> | 21 | #include <linux/workqueue.h> |
| 22 | #include <linux/sunrpc/rpc_pipe_fs.h> | 22 | #include <linux/sunrpc/rpc_pipe_fs.h> |
| 23 | 23 | #include <linux/sunrpc/xprtsock.h> | |
| 24 | 24 | ||
| 25 | /* RPC scheduler */ | 25 | /* RPC scheduler */ |
| 26 | EXPORT_SYMBOL(rpc_execute); | 26 | EXPORT_SYMBOL(rpc_execute); |
diff --git a/net/sunrpc/timer.c b/net/sunrpc/timer.c index 8142fdb8a930..31becbf09263 100644 --- a/net/sunrpc/timer.c +++ b/net/sunrpc/timer.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | 17 | ||
| 18 | #include <linux/types.h> | 18 | #include <linux/types.h> |
| 19 | #include <linux/unistd.h> | 19 | #include <linux/unistd.h> |
| 20 | #include <linux/module.h> | ||
| 20 | 21 | ||
| 21 | #include <linux/sunrpc/clnt.h> | 22 | #include <linux/sunrpc/clnt.h> |
| 22 | 23 | ||
| @@ -40,6 +41,7 @@ rpc_init_rtt(struct rpc_rtt *rt, unsigned long timeo) | |||
| 40 | rt->ntimeouts[i] = 0; | 41 | rt->ntimeouts[i] = 0; |
| 41 | } | 42 | } |
| 42 | } | 43 | } |
| 44 | EXPORT_SYMBOL_GPL(rpc_init_rtt); | ||
| 43 | 45 | ||
| 44 | /* | 46 | /* |
| 45 | * NB: When computing the smoothed RTT and standard deviation, | 47 | * NB: When computing the smoothed RTT and standard deviation, |
| @@ -75,6 +77,7 @@ rpc_update_rtt(struct rpc_rtt *rt, unsigned timer, long m) | |||
| 75 | if (*sdrtt < RPC_RTO_MIN) | 77 | if (*sdrtt < RPC_RTO_MIN) |
| 76 | *sdrtt = RPC_RTO_MIN; | 78 | *sdrtt = RPC_RTO_MIN; |
| 77 | } | 79 | } |
| 80 | EXPORT_SYMBOL_GPL(rpc_update_rtt); | ||
| 78 | 81 | ||
| 79 | /* | 82 | /* |
| 80 | * Estimate rto for an nfs rpc sent via. an unreliable datagram. | 83 | * Estimate rto for an nfs rpc sent via. an unreliable datagram. |
| @@ -103,3 +106,4 @@ rpc_calc_rto(struct rpc_rtt *rt, unsigned timer) | |||
| 103 | 106 | ||
| 104 | return res; | 107 | return res; |
| 105 | } | 108 | } |
| 109 | EXPORT_SYMBOL_GPL(rpc_calc_rto); | ||
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index c8c2edccad7e..282a9a2ec90c 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
| @@ -62,6 +62,9 @@ static inline void do_xprt_reserve(struct rpc_task *); | |||
| 62 | static void xprt_connect_status(struct rpc_task *task); | 62 | static void xprt_connect_status(struct rpc_task *task); |
| 63 | static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *); | 63 | static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *); |
| 64 | 64 | ||
| 65 | static spinlock_t xprt_list_lock = SPIN_LOCK_UNLOCKED; | ||
| 66 | static LIST_HEAD(xprt_list); | ||
| 67 | |||
| 65 | /* | 68 | /* |
| 66 | * The transport code maintains an estimate on the maximum number of out- | 69 | * The transport code maintains an estimate on the maximum number of out- |
| 67 | * standing RPC requests, using a smoothed version of the congestion | 70 | * standing RPC requests, using a smoothed version of the congestion |
| @@ -81,6 +84,78 @@ static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *); | |||
| 81 | #define RPCXPRT_CONGESTED(xprt) ((xprt)->cong >= (xprt)->cwnd) | 84 | #define RPCXPRT_CONGESTED(xprt) ((xprt)->cong >= (xprt)->cwnd) |
| 82 | 85 | ||
| 83 | /** | 86 | /** |
| 87 | * xprt_register_transport - register a transport implementation | ||
| 88 | * @transport: transport to register | ||
| 89 | * | ||
| 90 | * If a transport implementation is loaded as a kernel module, it can | ||
| 91 | * call this interface to make itself known to the RPC client. | ||
| 92 | * | ||
| 93 | * Returns: | ||
| 94 | * 0: transport successfully registered | ||
| 95 | * -EEXIST: transport already registered | ||
| 96 | * -EINVAL: transport module being unloaded | ||
| 97 | */ | ||
| 98 | int xprt_register_transport(struct xprt_class *transport) | ||
| 99 | { | ||
| 100 | struct xprt_class *t; | ||
| 101 | int result; | ||
| 102 | |||
| 103 | result = -EEXIST; | ||
| 104 | spin_lock(&xprt_list_lock); | ||
| 105 | list_for_each_entry(t, &xprt_list, list) { | ||
| 106 | /* don't register the same transport class twice */ | ||
| 107 | if (t->ident == transport->ident) | ||
| 108 | goto out; | ||
| 109 | } | ||
| 110 | |||
| 111 | result = -EINVAL; | ||
| 112 | if (try_module_get(THIS_MODULE)) { | ||
| 113 | list_add_tail(&transport->list, &xprt_list); | ||
| 114 | printk(KERN_INFO "RPC: Registered %s transport module.\n", | ||
| 115 | transport->name); | ||
| 116 | result = 0; | ||
| 117 | } | ||
| 118 | |||
| 119 | out: | ||
| 120 | spin_unlock(&xprt_list_lock); | ||
| 121 | return result; | ||
| 122 | } | ||
| 123 | EXPORT_SYMBOL_GPL(xprt_register_transport); | ||
| 124 | |||
| 125 | /** | ||
| 126 | * xprt_unregister_transport - unregister a transport implementation | ||
| 127 | * transport: transport to unregister | ||
| 128 | * | ||
| 129 | * Returns: | ||
| 130 | * 0: transport successfully unregistered | ||
| 131 | * -ENOENT: transport never registered | ||
| 132 | */ | ||
| 133 | int xprt_unregister_transport(struct xprt_class *transport) | ||
| 134 | { | ||
| 135 | struct xprt_class *t; | ||
| 136 | int result; | ||
| 137 | |||
| 138 | result = 0; | ||
| 139 | spin_lock(&xprt_list_lock); | ||
| 140 | list_for_each_entry(t, &xprt_list, list) { | ||
| 141 | if (t == transport) { | ||
| 142 | printk(KERN_INFO | ||
| 143 | "RPC: Unregistered %s transport module.\n", | ||
| 144 | transport->name); | ||
| 145 | list_del_init(&transport->list); | ||
| 146 | module_put(THIS_MODULE); | ||
| 147 | goto out; | ||
| 148 | } | ||
| 149 | } | ||
| 150 | result = -ENOENT; | ||
| 151 | |||
| 152 | out: | ||
| 153 | spin_unlock(&xprt_list_lock); | ||
| 154 | return result; | ||
| 155 | } | ||
| 156 | EXPORT_SYMBOL_GPL(xprt_unregister_transport); | ||
| 157 | |||
| 158 | /** | ||
| 84 | * xprt_reserve_xprt - serialize write access to transports | 159 | * xprt_reserve_xprt - serialize write access to transports |
| 85 | * @task: task that is requesting access to the transport | 160 | * @task: task that is requesting access to the transport |
| 86 | * | 161 | * |
| @@ -118,6 +193,7 @@ out_sleep: | |||
| 118 | rpc_sleep_on(&xprt->sending, task, NULL, NULL); | 193 | rpc_sleep_on(&xprt->sending, task, NULL, NULL); |
| 119 | return 0; | 194 | return 0; |
| 120 | } | 195 | } |
| 196 | EXPORT_SYMBOL_GPL(xprt_reserve_xprt); | ||
| 121 | 197 | ||
| 122 | static void xprt_clear_locked(struct rpc_xprt *xprt) | 198 | static void xprt_clear_locked(struct rpc_xprt *xprt) |
| 123 | { | 199 | { |
| @@ -167,6 +243,7 @@ out_sleep: | |||
| 167 | rpc_sleep_on(&xprt->sending, task, NULL, NULL); | 243 | rpc_sleep_on(&xprt->sending, task, NULL, NULL); |
| 168 | return 0; | 244 | return 0; |
| 169 | } | 245 | } |
| 246 | EXPORT_SYMBOL_GPL(xprt_reserve_xprt_cong); | ||
| 170 | 247 | ||
| 171 | static inline int xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task) | 248 | static inline int xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task) |
| 172 | { | 249 | { |
| @@ -246,6 +323,7 @@ void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task) | |||
| 246 | __xprt_lock_write_next(xprt); | 323 | __xprt_lock_write_next(xprt); |
| 247 | } | 324 | } |
| 248 | } | 325 | } |
| 326 | EXPORT_SYMBOL_GPL(xprt_release_xprt); | ||
| 249 | 327 | ||
| 250 | /** | 328 | /** |
| 251 | * xprt_release_xprt_cong - allow other requests to use a transport | 329 | * xprt_release_xprt_cong - allow other requests to use a transport |
| @@ -262,6 +340,7 @@ void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task) | |||
| 262 | __xprt_lock_write_next_cong(xprt); | 340 | __xprt_lock_write_next_cong(xprt); |
| 263 | } | 341 | } |
| 264 | } | 342 | } |
| 343 | EXPORT_SYMBOL_GPL(xprt_release_xprt_cong); | ||
| 265 | 344 | ||
| 266 | static inline void xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task) | 345 | static inline void xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task) |
| 267 | { | 346 | { |
| @@ -314,6 +393,7 @@ void xprt_release_rqst_cong(struct rpc_task *task) | |||
| 314 | { | 393 | { |
| 315 | __xprt_put_cong(task->tk_xprt, task->tk_rqstp); | 394 | __xprt_put_cong(task->tk_xprt, task->tk_rqstp); |
| 316 | } | 395 | } |
| 396 | EXPORT_SYMBOL_GPL(xprt_release_rqst_cong); | ||
| 317 | 397 | ||
| 318 | /** | 398 | /** |
| 319 | * xprt_adjust_cwnd - adjust transport congestion window | 399 | * xprt_adjust_cwnd - adjust transport congestion window |
| @@ -345,6 +425,7 @@ void xprt_adjust_cwnd(struct rpc_task *task, int result) | |||
| 345 | xprt->cwnd = cwnd; | 425 | xprt->cwnd = cwnd; |
| 346 | __xprt_put_cong(xprt, req); | 426 | __xprt_put_cong(xprt, req); |
| 347 | } | 427 | } |
| 428 | EXPORT_SYMBOL_GPL(xprt_adjust_cwnd); | ||
| 348 | 429 | ||
| 349 | /** | 430 | /** |
| 350 | * xprt_wake_pending_tasks - wake all tasks on a transport's pending queue | 431 | * xprt_wake_pending_tasks - wake all tasks on a transport's pending queue |
| @@ -359,6 +440,7 @@ void xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status) | |||
| 359 | else | 440 | else |
| 360 | rpc_wake_up(&xprt->pending); | 441 | rpc_wake_up(&xprt->pending); |
| 361 | } | 442 | } |
| 443 | EXPORT_SYMBOL_GPL(xprt_wake_pending_tasks); | ||
| 362 | 444 | ||
| 363 | /** | 445 | /** |
| 364 | * xprt_wait_for_buffer_space - wait for transport output buffer to clear | 446 | * xprt_wait_for_buffer_space - wait for transport output buffer to clear |
| @@ -373,6 +455,7 @@ void xprt_wait_for_buffer_space(struct rpc_task *task) | |||
| 373 | task->tk_timeout = req->rq_timeout; | 455 | task->tk_timeout = req->rq_timeout; |
| 374 | rpc_sleep_on(&xprt->pending, task, NULL, NULL); | 456 | rpc_sleep_on(&xprt->pending, task, NULL, NULL); |
| 375 | } | 457 | } |
| 458 | EXPORT_SYMBOL_GPL(xprt_wait_for_buffer_space); | ||
| 376 | 459 | ||
| 377 | /** | 460 | /** |
| 378 | * xprt_write_space - wake the task waiting for transport output buffer space | 461 | * xprt_write_space - wake the task waiting for transport output buffer space |
| @@ -393,6 +476,7 @@ void xprt_write_space(struct rpc_xprt *xprt) | |||
| 393 | } | 476 | } |
| 394 | spin_unlock_bh(&xprt->transport_lock); | 477 | spin_unlock_bh(&xprt->transport_lock); |
| 395 | } | 478 | } |
| 479 | EXPORT_SYMBOL_GPL(xprt_write_space); | ||
| 396 | 480 | ||
| 397 | /** | 481 | /** |
| 398 | * xprt_set_retrans_timeout_def - set a request's retransmit timeout | 482 | * xprt_set_retrans_timeout_def - set a request's retransmit timeout |
| @@ -406,6 +490,7 @@ void xprt_set_retrans_timeout_def(struct rpc_task *task) | |||
| 406 | { | 490 | { |
| 407 | task->tk_timeout = task->tk_rqstp->rq_timeout; | 491 | task->tk_timeout = task->tk_rqstp->rq_timeout; |
| 408 | } | 492 | } |
| 493 | EXPORT_SYMBOL_GPL(xprt_set_retrans_timeout_def); | ||
| 409 | 494 | ||
| 410 | /* | 495 | /* |
| 411 | * xprt_set_retrans_timeout_rtt - set a request's retransmit timeout | 496 | * xprt_set_retrans_timeout_rtt - set a request's retransmit timeout |
| @@ -425,6 +510,7 @@ void xprt_set_retrans_timeout_rtt(struct rpc_task *task) | |||
| 425 | if (task->tk_timeout > max_timeout || task->tk_timeout == 0) | 510 | if (task->tk_timeout > max_timeout || task->tk_timeout == 0) |
| 426 | task->tk_timeout = max_timeout; | 511 | task->tk_timeout = max_timeout; |
| 427 | } | 512 | } |
| 513 | EXPORT_SYMBOL_GPL(xprt_set_retrans_timeout_rtt); | ||
| 428 | 514 | ||
| 429 | static void xprt_reset_majortimeo(struct rpc_rqst *req) | 515 | static void xprt_reset_majortimeo(struct rpc_rqst *req) |
| 430 | { | 516 | { |
| @@ -500,6 +586,7 @@ void xprt_disconnect(struct rpc_xprt *xprt) | |||
| 500 | xprt_wake_pending_tasks(xprt, -ENOTCONN); | 586 | xprt_wake_pending_tasks(xprt, -ENOTCONN); |
| 501 | spin_unlock_bh(&xprt->transport_lock); | 587 | spin_unlock_bh(&xprt->transport_lock); |
| 502 | } | 588 | } |
| 589 | EXPORT_SYMBOL_GPL(xprt_disconnect); | ||
| 503 | 590 | ||
| 504 | static void | 591 | static void |
| 505 | xprt_init_autodisconnect(unsigned long data) | 592 | xprt_init_autodisconnect(unsigned long data) |
| @@ -610,6 +697,7 @@ struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, __be32 xid) | |||
| 610 | xprt->stat.bad_xids++; | 697 | xprt->stat.bad_xids++; |
| 611 | return NULL; | 698 | return NULL; |
| 612 | } | 699 | } |
| 700 | EXPORT_SYMBOL_GPL(xprt_lookup_rqst); | ||
| 613 | 701 | ||
| 614 | /** | 702 | /** |
| 615 | * xprt_update_rtt - update an RPC client's RTT state after receiving a reply | 703 | * xprt_update_rtt - update an RPC client's RTT state after receiving a reply |
| @@ -629,6 +717,7 @@ void xprt_update_rtt(struct rpc_task *task) | |||
| 629 | rpc_set_timeo(rtt, timer, req->rq_ntrans - 1); | 717 | rpc_set_timeo(rtt, timer, req->rq_ntrans - 1); |
| 630 | } | 718 | } |
| 631 | } | 719 | } |
| 720 | EXPORT_SYMBOL_GPL(xprt_update_rtt); | ||
| 632 | 721 | ||
| 633 | /** | 722 | /** |
| 634 | * xprt_complete_rqst - called when reply processing is complete | 723 | * xprt_complete_rqst - called when reply processing is complete |
| @@ -653,6 +742,7 @@ void xprt_complete_rqst(struct rpc_task *task, int copied) | |||
| 653 | req->rq_received = req->rq_private_buf.len = copied; | 742 | req->rq_received = req->rq_private_buf.len = copied; |
| 654 | rpc_wake_up_task(task); | 743 | rpc_wake_up_task(task); |
| 655 | } | 744 | } |
| 745 | EXPORT_SYMBOL_GPL(xprt_complete_rqst); | ||
| 656 | 746 | ||
| 657 | static void xprt_timer(struct rpc_task *task) | 747 | static void xprt_timer(struct rpc_task *task) |
| 658 | { | 748 | { |
| @@ -889,23 +979,25 @@ void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long i | |||
| 889 | * @args: rpc transport creation arguments | 979 | * @args: rpc transport creation arguments |
| 890 | * | 980 | * |
| 891 | */ | 981 | */ |
| 892 | struct rpc_xprt *xprt_create_transport(struct rpc_xprtsock_create *args) | 982 | struct rpc_xprt *xprt_create_transport(struct xprt_create *args) |
| 893 | { | 983 | { |
| 894 | struct rpc_xprt *xprt; | 984 | struct rpc_xprt *xprt; |
| 895 | struct rpc_rqst *req; | 985 | struct rpc_rqst *req; |
| 986 | struct xprt_class *t; | ||
| 896 | 987 | ||
| 897 | switch (args->proto) { | 988 | spin_lock(&xprt_list_lock); |
| 898 | case IPPROTO_UDP: | 989 | list_for_each_entry(t, &xprt_list, list) { |
| 899 | xprt = xs_setup_udp(args); | 990 | if (t->ident == args->ident) { |
| 900 | break; | 991 | spin_unlock(&xprt_list_lock); |
| 901 | case IPPROTO_TCP: | 992 | goto found; |
| 902 | xprt = xs_setup_tcp(args); | 993 | } |
| 903 | break; | ||
| 904 | default: | ||
| 905 | printk(KERN_ERR "RPC: unrecognized transport protocol: %d\n", | ||
| 906 | args->proto); | ||
| 907 | return ERR_PTR(-EIO); | ||
| 908 | } | 994 | } |
| 995 | spin_unlock(&xprt_list_lock); | ||
| 996 | printk(KERN_ERR "RPC: transport (%d) not supported\n", args->ident); | ||
| 997 | return ERR_PTR(-EIO); | ||
| 998 | |||
| 999 | found: | ||
| 1000 | xprt = t->setup(args); | ||
| 909 | if (IS_ERR(xprt)) { | 1001 | if (IS_ERR(xprt)) { |
| 910 | dprintk("RPC: xprt_create_transport: failed, %ld\n", | 1002 | dprintk("RPC: xprt_create_transport: failed, %ld\n", |
| 911 | -PTR_ERR(xprt)); | 1003 | -PTR_ERR(xprt)); |
diff --git a/net/sunrpc/xprtrdma/Makefile b/net/sunrpc/xprtrdma/Makefile new file mode 100644 index 000000000000..264f0feeb513 --- /dev/null +++ b/net/sunrpc/xprtrdma/Makefile | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | obj-$(CONFIG_SUNRPC_XPRT_RDMA) += xprtrdma.o | ||
| 2 | |||
| 3 | xprtrdma-y := transport.o rpc_rdma.o verbs.o | ||
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c new file mode 100644 index 000000000000..12db63580427 --- /dev/null +++ b/net/sunrpc/xprtrdma/rpc_rdma.c | |||
| @@ -0,0 +1,868 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved. | ||
| 3 | * | ||
| 4 | * This software is available to you under a choice of one of two | ||
| 5 | * licenses. You may choose to be licensed under the terms of the GNU | ||
| 6 | * General Public License (GPL) Version 2, available from the file | ||
| 7 | * COPYING in the main directory of this source tree, or the BSD-type | ||
| 8 | * license below: | ||
| 9 | * | ||
| 10 | * Redistribution and use in source and binary forms, with or without | ||
| 11 | * modification, are permitted provided that the following conditions | ||
| 12 | * are met: | ||
| 13 | * | ||
| 14 | * Redistributions of source code must retain the above copyright | ||
| 15 | * notice, this list of conditions and the following disclaimer. | ||
| 16 | * | ||
| 17 | * Redistributions in binary form must reproduce the above | ||
| 18 | * copyright notice, this list of conditions and the following | ||
| 19 | * disclaimer in the documentation and/or other materials provided | ||
| 20 | * with the distribution. | ||
| 21 | * | ||
| 22 | * Neither the name of the Network Appliance, Inc. nor the names of | ||
| 23 | * its contributors may be used to endorse or promote products | ||
| 24 | * derived from this software without specific prior written | ||
| 25 | * permission. | ||
| 26 | * | ||
| 27 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| 28 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| 29 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
| 30 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| 31 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
| 32 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
| 33 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
| 34 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
| 35 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 36 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
| 37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 38 | */ | ||
| 39 | |||
| 40 | /* | ||
| 41 | * rpc_rdma.c | ||
| 42 | * | ||
| 43 | * This file contains the guts of the RPC RDMA protocol, and | ||
| 44 | * does marshaling/unmarshaling, etc. It is also where interfacing | ||
| 45 | * to the Linux RPC framework lives. | ||
| 46 | */ | ||
| 47 | |||
| 48 | #include "xprt_rdma.h" | ||
| 49 | |||
| 50 | #include <linux/highmem.h> | ||
| 51 | |||
| 52 | #ifdef RPC_DEBUG | ||
| 53 | # define RPCDBG_FACILITY RPCDBG_TRANS | ||
| 54 | #endif | ||
| 55 | |||
| 56 | enum rpcrdma_chunktype { | ||
| 57 | rpcrdma_noch = 0, | ||
| 58 | rpcrdma_readch, | ||
| 59 | rpcrdma_areadch, | ||
| 60 | rpcrdma_writech, | ||
| 61 | rpcrdma_replych | ||
| 62 | }; | ||
| 63 | |||
| 64 | #ifdef RPC_DEBUG | ||
| 65 | static const char transfertypes[][12] = { | ||
| 66 | "pure inline", /* no chunks */ | ||
| 67 | " read chunk", /* some argument via rdma read */ | ||
| 68 | "*read chunk", /* entire request via rdma read */ | ||
| 69 | "write chunk", /* some result via rdma write */ | ||
| 70 | "reply chunk" /* entire reply via rdma write */ | ||
| 71 | }; | ||
| 72 | #endif | ||
| 73 | |||
| 74 | /* | ||
| 75 | * Chunk assembly from upper layer xdr_buf. | ||
| 76 | * | ||
| 77 | * Prepare the passed-in xdr_buf into representation as RPC/RDMA chunk | ||
| 78 | * elements. Segments are then coalesced when registered, if possible | ||
| 79 | * within the selected memreg mode. | ||
| 80 | * | ||
| 81 | * Note, this routine is never called if the connection's memory | ||
| 82 | * registration strategy is 0 (bounce buffers). | ||
| 83 | */ | ||
| 84 | |||
| 85 | static int | ||
| 86 | rpcrdma_convert_iovs(struct xdr_buf *xdrbuf, int pos, | ||
| 87 | enum rpcrdma_chunktype type, struct rpcrdma_mr_seg *seg, int nsegs) | ||
| 88 | { | ||
| 89 | int len, n = 0, p; | ||
| 90 | |||
| 91 | if (pos == 0 && xdrbuf->head[0].iov_len) { | ||
| 92 | seg[n].mr_page = NULL; | ||
| 93 | seg[n].mr_offset = xdrbuf->head[0].iov_base; | ||
| 94 | seg[n].mr_len = xdrbuf->head[0].iov_len; | ||
| 95 | pos += xdrbuf->head[0].iov_len; | ||
| 96 | ++n; | ||
| 97 | } | ||
| 98 | |||
| 99 | if (xdrbuf->page_len && (xdrbuf->pages[0] != NULL)) { | ||
| 100 | if (n == nsegs) | ||
| 101 | return 0; | ||
| 102 | seg[n].mr_page = xdrbuf->pages[0]; | ||
| 103 | seg[n].mr_offset = (void *)(unsigned long) xdrbuf->page_base; | ||
| 104 | seg[n].mr_len = min_t(u32, | ||
| 105 | PAGE_SIZE - xdrbuf->page_base, xdrbuf->page_len); | ||
| 106 | len = xdrbuf->page_len - seg[n].mr_len; | ||
| 107 | pos += len; | ||
| 108 | ++n; | ||
| 109 | p = 1; | ||
| 110 | while (len > 0) { | ||
| 111 | if (n == nsegs) | ||
| 112 | return 0; | ||
| 113 | seg[n].mr_page = xdrbuf->pages[p]; | ||
| 114 | seg[n].mr_offset = NULL; | ||
| 115 | seg[n].mr_len = min_t(u32, PAGE_SIZE, len); | ||
| 116 | len -= seg[n].mr_len; | ||
| 117 | ++n; | ||
| 118 | ++p; | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 122 | if (pos < xdrbuf->len && xdrbuf->tail[0].iov_len) { | ||
| 123 | if (n == nsegs) | ||
| 124 | return 0; | ||
| 125 | seg[n].mr_page = NULL; | ||
| 126 | seg[n].mr_offset = xdrbuf->tail[0].iov_base; | ||
| 127 | seg[n].mr_len = xdrbuf->tail[0].iov_len; | ||
| 128 | pos += xdrbuf->tail[0].iov_len; | ||
| 129 | ++n; | ||
| 130 | } | ||
| 131 | |||
| 132 | if (pos < xdrbuf->len) | ||
| 133 | dprintk("RPC: %s: marshaled only %d of %d\n", | ||
| 134 | __func__, pos, xdrbuf->len); | ||
| 135 | |||
| 136 | return n; | ||
| 137 | } | ||
| 138 | |||
| 139 | /* | ||
| 140 | * Create read/write chunk lists, and reply chunks, for RDMA | ||
| 141 | * | ||
| 142 | * Assume check against THRESHOLD has been done, and chunks are required. | ||
| 143 | * Assume only encoding one list entry for read|write chunks. The NFSv3 | ||
| 144 | * protocol is simple enough to allow this as it only has a single "bulk | ||
| 145 | * result" in each procedure - complicated NFSv4 COMPOUNDs are not. (The | ||
| 146 | * RDMA/Sessions NFSv4 proposal addresses this for future v4 revs.) | ||
| 147 | * | ||
| 148 | * When used for a single reply chunk (which is a special write | ||
| 149 | * chunk used for the entire reply, rather than just the data), it | ||
| 150 | * is used primarily for READDIR and READLINK which would otherwise | ||
| 151 | * be severely size-limited by a small rdma inline read max. The server | ||
| 152 | * response will come back as an RDMA Write, followed by a message | ||
| 153 | * of type RDMA_NOMSG carrying the xid and length. As a result, reply | ||
| 154 | * chunks do not provide data alignment, however they do not require | ||
| 155 | * "fixup" (moving the response to the upper layer buffer) either. | ||
| 156 | * | ||
| 157 | * Encoding key for single-list chunks (HLOO = Handle32 Length32 Offset64): | ||
| 158 | * | ||
| 159 | * Read chunklist (a linked list): | ||
| 160 | * N elements, position P (same P for all chunks of same arg!): | ||
| 161 | * 1 - PHLOO - 1 - PHLOO - ... - 1 - PHLOO - 0 | ||
| 162 | * | ||
| 163 | * Write chunklist (a list of (one) counted array): | ||
| 164 | * N elements: | ||
| 165 | * 1 - N - HLOO - HLOO - ... - HLOO - 0 | ||
| 166 | * | ||
| 167 | * Reply chunk (a counted array): | ||
| 168 | * N elements: | ||
| 169 | * 1 - N - HLOO - HLOO - ... - HLOO | ||
| 170 | */ | ||
| 171 | |||
| 172 | static unsigned int | ||
| 173 | rpcrdma_create_chunks(struct rpc_rqst *rqst, struct xdr_buf *target, | ||
| 174 | struct rpcrdma_msg *headerp, enum rpcrdma_chunktype type) | ||
| 175 | { | ||
| 176 | struct rpcrdma_req *req = rpcr_to_rdmar(rqst); | ||
| 177 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(rqst->rq_task->tk_xprt); | ||
| 178 | int nsegs, nchunks = 0; | ||
| 179 | int pos; | ||
| 180 | struct rpcrdma_mr_seg *seg = req->rl_segments; | ||
| 181 | struct rpcrdma_read_chunk *cur_rchunk = NULL; | ||
| 182 | struct rpcrdma_write_array *warray = NULL; | ||
| 183 | struct rpcrdma_write_chunk *cur_wchunk = NULL; | ||
| 184 | u32 *iptr = headerp->rm_body.rm_chunks; | ||
| 185 | |||
| 186 | if (type == rpcrdma_readch || type == rpcrdma_areadch) { | ||
| 187 | /* a read chunk - server will RDMA Read our memory */ | ||
| 188 | cur_rchunk = (struct rpcrdma_read_chunk *) iptr; | ||
| 189 | } else { | ||
| 190 | /* a write or reply chunk - server will RDMA Write our memory */ | ||
| 191 | *iptr++ = xdr_zero; /* encode a NULL read chunk list */ | ||
| 192 | if (type == rpcrdma_replych) | ||
| 193 | *iptr++ = xdr_zero; /* a NULL write chunk list */ | ||
| 194 | warray = (struct rpcrdma_write_array *) iptr; | ||
| 195 | cur_wchunk = (struct rpcrdma_write_chunk *) (warray + 1); | ||
| 196 | } | ||
| 197 | |||
| 198 | if (type == rpcrdma_replych || type == rpcrdma_areadch) | ||
| 199 | pos = 0; | ||
| 200 | else | ||
| 201 | pos = target->head[0].iov_len; | ||
| 202 | |||
| 203 | nsegs = rpcrdma_convert_iovs(target, pos, type, seg, RPCRDMA_MAX_SEGS); | ||
| 204 | if (nsegs == 0) | ||
| 205 | return 0; | ||
| 206 | |||
| 207 | do { | ||
| 208 | /* bind/register the memory, then build chunk from result. */ | ||
| 209 | int n = rpcrdma_register_external(seg, nsegs, | ||
| 210 | cur_wchunk != NULL, r_xprt); | ||
| 211 | if (n <= 0) | ||
| 212 | goto out; | ||
| 213 | if (cur_rchunk) { /* read */ | ||
| 214 | cur_rchunk->rc_discrim = xdr_one; | ||
| 215 | /* all read chunks have the same "position" */ | ||
| 216 | cur_rchunk->rc_position = htonl(pos); | ||
| 217 | cur_rchunk->rc_target.rs_handle = htonl(seg->mr_rkey); | ||
| 218 | cur_rchunk->rc_target.rs_length = htonl(seg->mr_len); | ||
| 219 | xdr_encode_hyper( | ||
| 220 | (u32 *)&cur_rchunk->rc_target.rs_offset, | ||
| 221 | seg->mr_base); | ||
| 222 | dprintk("RPC: %s: read chunk " | ||
| 223 | "elem %d@0x%llx:0x%x pos %d (%s)\n", __func__, | ||
| 224 | seg->mr_len, seg->mr_base, seg->mr_rkey, pos, | ||
| 225 | n < nsegs ? "more" : "last"); | ||
| 226 | cur_rchunk++; | ||
| 227 | r_xprt->rx_stats.read_chunk_count++; | ||
| 228 | } else { /* write/reply */ | ||
| 229 | cur_wchunk->wc_target.rs_handle = htonl(seg->mr_rkey); | ||
| 230 | cur_wchunk->wc_target.rs_length = htonl(seg->mr_len); | ||
| 231 | xdr_encode_hyper( | ||
| 232 | (u32 *)&cur_wchunk->wc_target.rs_offset, | ||
| 233 | seg->mr_base); | ||
| 234 | dprintk("RPC: %s: %s chunk " | ||
| 235 | "elem %d@0x%llx:0x%x (%s)\n", __func__, | ||
| 236 | (type == rpcrdma_replych) ? "reply" : "write", | ||
| 237 | seg->mr_len, seg->mr_base, seg->mr_rkey, | ||
| 238 | n < nsegs ? "more" : "last"); | ||
| 239 | cur_wchunk++; | ||
| 240 | if (type == rpcrdma_replych) | ||
| 241 | r_xprt->rx_stats.reply_chunk_count++; | ||
| 242 | else | ||
| 243 | r_xprt->rx_stats.write_chunk_count++; | ||
| 244 | r_xprt->rx_stats.total_rdma_request += seg->mr_len; | ||
| 245 | } | ||
| 246 | nchunks++; | ||
| 247 | seg += n; | ||
| 248 | nsegs -= n; | ||
| 249 | } while (nsegs); | ||
| 250 | |||
| 251 | /* success. all failures return above */ | ||
| 252 | req->rl_nchunks = nchunks; | ||
| 253 | |||
| 254 | BUG_ON(nchunks == 0); | ||
| 255 | |||
| 256 | /* | ||
| 257 | * finish off header. If write, marshal discrim and nchunks. | ||
| 258 | */ | ||
| 259 | if (cur_rchunk) { | ||
| 260 | iptr = (u32 *) cur_rchunk; | ||
| 261 | *iptr++ = xdr_zero; /* finish the read chunk list */ | ||
| 262 | *iptr++ = xdr_zero; /* encode a NULL write chunk list */ | ||
| 263 | *iptr++ = xdr_zero; /* encode a NULL reply chunk */ | ||
| 264 | } else { | ||
| 265 | warray->wc_discrim = xdr_one; | ||
| 266 | warray->wc_nchunks = htonl(nchunks); | ||
| 267 | iptr = (u32 *) cur_wchunk; | ||
| 268 | if (type == rpcrdma_writech) { | ||
| 269 | *iptr++ = xdr_zero; /* finish the write chunk list */ | ||
| 270 | *iptr++ = xdr_zero; /* encode a NULL reply chunk */ | ||
| 271 | } | ||
| 272 | } | ||
| 273 | |||
| 274 | /* | ||
| 275 | * Return header size. | ||
| 276 | */ | ||
| 277 | return (unsigned char *)iptr - (unsigned char *)headerp; | ||
| 278 | |||
| 279 | out: | ||
| 280 | for (pos = 0; nchunks--;) | ||
| 281 | pos += rpcrdma_deregister_external( | ||
| 282 | &req->rl_segments[pos], r_xprt, NULL); | ||
| 283 | return 0; | ||
| 284 | } | ||
| 285 | |||
| 286 | /* | ||
| 287 | * Copy write data inline. | ||
| 288 | * This function is used for "small" requests. Data which is passed | ||
| 289 | * to RPC via iovecs (or page list) is copied directly into the | ||
| 290 | * pre-registered memory buffer for this request. For small amounts | ||
| 291 | * of data, this is efficient. The cutoff value is tunable. | ||
| 292 | */ | ||
| 293 | static int | ||
| 294 | rpcrdma_inline_pullup(struct rpc_rqst *rqst, int pad) | ||
| 295 | { | ||
| 296 | int i, npages, curlen; | ||
| 297 | int copy_len; | ||
| 298 | unsigned char *srcp, *destp; | ||
| 299 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(rqst->rq_xprt); | ||
| 300 | |||
| 301 | destp = rqst->rq_svec[0].iov_base; | ||
| 302 | curlen = rqst->rq_svec[0].iov_len; | ||
| 303 | destp += curlen; | ||
| 304 | /* | ||
| 305 | * Do optional padding where it makes sense. Alignment of write | ||
| 306 | * payload can help the server, if our setting is accurate. | ||
| 307 | */ | ||
| 308 | pad -= (curlen + 36/*sizeof(struct rpcrdma_msg_padded)*/); | ||
| 309 | if (pad < 0 || rqst->rq_slen - curlen < RPCRDMA_INLINE_PAD_THRESH) | ||
| 310 | pad = 0; /* don't pad this request */ | ||
| 311 | |||
| 312 | dprintk("RPC: %s: pad %d destp 0x%p len %d hdrlen %d\n", | ||
| 313 | __func__, pad, destp, rqst->rq_slen, curlen); | ||
| 314 | |||
| 315 | copy_len = rqst->rq_snd_buf.page_len; | ||
| 316 | r_xprt->rx_stats.pullup_copy_count += copy_len; | ||
| 317 | npages = PAGE_ALIGN(rqst->rq_snd_buf.page_base+copy_len) >> PAGE_SHIFT; | ||
| 318 | for (i = 0; copy_len && i < npages; i++) { | ||
| 319 | if (i == 0) | ||
| 320 | curlen = PAGE_SIZE - rqst->rq_snd_buf.page_base; | ||
| 321 | else | ||
| 322 | curlen = PAGE_SIZE; | ||
| 323 | if (curlen > copy_len) | ||
| 324 | curlen = copy_len; | ||
| 325 | dprintk("RPC: %s: page %d destp 0x%p len %d curlen %d\n", | ||
| 326 | __func__, i, destp, copy_len, curlen); | ||
| 327 | srcp = kmap_atomic(rqst->rq_snd_buf.pages[i], | ||
| 328 | KM_SKB_SUNRPC_DATA); | ||
| 329 | if (i == 0) | ||
| 330 | memcpy(destp, srcp+rqst->rq_snd_buf.page_base, curlen); | ||
| 331 | else | ||
| 332 | memcpy(destp, srcp, curlen); | ||
| 333 | kunmap_atomic(srcp, KM_SKB_SUNRPC_DATA); | ||
| 334 | rqst->rq_svec[0].iov_len += curlen; | ||
| 335 | destp += curlen; | ||
| 336 | copy_len -= curlen; | ||
| 337 | } | ||
| 338 | if (rqst->rq_snd_buf.tail[0].iov_len) { | ||
| 339 | curlen = rqst->rq_snd_buf.tail[0].iov_len; | ||
| 340 | if (destp != rqst->rq_snd_buf.tail[0].iov_base) { | ||
| 341 | memcpy(destp, | ||
| 342 | rqst->rq_snd_buf.tail[0].iov_base, curlen); | ||
| 343 | r_xprt->rx_stats.pullup_copy_count += curlen; | ||
| 344 | } | ||
| 345 | dprintk("RPC: %s: tail destp 0x%p len %d curlen %d\n", | ||
| 346 | __func__, destp, copy_len, curlen); | ||
| 347 | rqst->rq_svec[0].iov_len += curlen; | ||
| 348 | } | ||
| 349 | /* header now contains entire send message */ | ||
| 350 | return pad; | ||
| 351 | } | ||
| 352 | |||
| 353 | /* | ||
| 354 | * Marshal a request: the primary job of this routine is to choose | ||
| 355 | * the transfer modes. See comments below. | ||
| 356 | * | ||
| 357 | * Uses multiple RDMA IOVs for a request: | ||
| 358 | * [0] -- RPC RDMA header, which uses memory from the *start* of the | ||
| 359 | * preregistered buffer that already holds the RPC data in | ||
| 360 | * its middle. | ||
| 361 | * [1] -- the RPC header/data, marshaled by RPC and the NFS protocol. | ||
| 362 | * [2] -- optional padding. | ||
| 363 | * [3] -- if padded, header only in [1] and data here. | ||
| 364 | */ | ||
| 365 | |||
| 366 | int | ||
| 367 | rpcrdma_marshal_req(struct rpc_rqst *rqst) | ||
| 368 | { | ||
| 369 | struct rpc_xprt *xprt = rqst->rq_task->tk_xprt; | ||
| 370 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); | ||
| 371 | struct rpcrdma_req *req = rpcr_to_rdmar(rqst); | ||
| 372 | char *base; | ||
| 373 | size_t hdrlen, rpclen, padlen; | ||
| 374 | enum rpcrdma_chunktype rtype, wtype; | ||
| 375 | struct rpcrdma_msg *headerp; | ||
| 376 | |||
| 377 | /* | ||
| 378 | * rpclen gets amount of data in first buffer, which is the | ||
| 379 | * pre-registered buffer. | ||
| 380 | */ | ||
| 381 | base = rqst->rq_svec[0].iov_base; | ||
| 382 | rpclen = rqst->rq_svec[0].iov_len; | ||
| 383 | |||
| 384 | /* build RDMA header in private area at front */ | ||
| 385 | headerp = (struct rpcrdma_msg *) req->rl_base; | ||
| 386 | /* don't htonl XID, it's already done in request */ | ||
| 387 | headerp->rm_xid = rqst->rq_xid; | ||
| 388 | headerp->rm_vers = xdr_one; | ||
| 389 | headerp->rm_credit = htonl(r_xprt->rx_buf.rb_max_requests); | ||
| 390 | headerp->rm_type = __constant_htonl(RDMA_MSG); | ||
| 391 | |||
| 392 | /* | ||
| 393 | * Chunks needed for results? | ||
| 394 | * | ||
| 395 | * o If the expected result is under the inline threshold, all ops | ||
| 396 | * return as inline (but see later). | ||
| 397 | * o Large non-read ops return as a single reply chunk. | ||
| 398 | * o Large read ops return data as write chunk(s), header as inline. | ||
| 399 | * | ||
| 400 | * Note: the NFS code sending down multiple result segments implies | ||
| 401 | * the op is one of read, readdir[plus], readlink or NFSv4 getacl. | ||
| 402 | */ | ||
| 403 | |||
| 404 | /* | ||
| 405 | * This code can handle read chunks, write chunks OR reply | ||
| 406 | * chunks -- only one type. If the request is too big to fit | ||
| 407 | * inline, then we will choose read chunks. If the request is | ||
| 408 | * a READ, then use write chunks to separate the file data | ||
| 409 | * into pages; otherwise use reply chunks. | ||
| 410 | */ | ||
| 411 | if (rqst->rq_rcv_buf.buflen <= RPCRDMA_INLINE_READ_THRESHOLD(rqst)) | ||
| 412 | wtype = rpcrdma_noch; | ||
| 413 | else if (rqst->rq_rcv_buf.page_len == 0) | ||
| 414 | wtype = rpcrdma_replych; | ||
| 415 | else if (rqst->rq_rcv_buf.flags & XDRBUF_READ) | ||
| 416 | wtype = rpcrdma_writech; | ||
| 417 | else | ||
| 418 | wtype = rpcrdma_replych; | ||
| 419 | |||
| 420 | /* | ||
| 421 | * Chunks needed for arguments? | ||
| 422 | * | ||
| 423 | * o If the total request is under the inline threshold, all ops | ||
| 424 | * are sent as inline. | ||
| 425 | * o Large non-write ops are sent with the entire message as a | ||
| 426 | * single read chunk (protocol 0-position special case). | ||
| 427 | * o Large write ops transmit data as read chunk(s), header as | ||
| 428 | * inline. | ||
| 429 | * | ||
| 430 | * Note: the NFS code sending down multiple argument segments | ||
| 431 | * implies the op is a write. | ||
| 432 | * TBD check NFSv4 setacl | ||
| 433 | */ | ||
| 434 | if (rqst->rq_snd_buf.len <= RPCRDMA_INLINE_WRITE_THRESHOLD(rqst)) | ||
| 435 | rtype = rpcrdma_noch; | ||
| 436 | else if (rqst->rq_snd_buf.page_len == 0) | ||
| 437 | rtype = rpcrdma_areadch; | ||
| 438 | else | ||
| 439 | rtype = rpcrdma_readch; | ||
| 440 | |||
| 441 | /* The following simplification is not true forever */ | ||
| 442 | if (rtype != rpcrdma_noch && wtype == rpcrdma_replych) | ||
| 443 | wtype = rpcrdma_noch; | ||
| 444 | BUG_ON(rtype != rpcrdma_noch && wtype != rpcrdma_noch); | ||
| 445 | |||
| 446 | if (r_xprt->rx_ia.ri_memreg_strategy == RPCRDMA_BOUNCEBUFFERS && | ||
| 447 | (rtype != rpcrdma_noch || wtype != rpcrdma_noch)) { | ||
| 448 | /* forced to "pure inline"? */ | ||
| 449 | dprintk("RPC: %s: too much data (%d/%d) for inline\n", | ||
| 450 | __func__, rqst->rq_rcv_buf.len, rqst->rq_snd_buf.len); | ||
| 451 | return -1; | ||
| 452 | } | ||
| 453 | |||
| 454 | hdrlen = 28; /*sizeof *headerp;*/ | ||
| 455 | padlen = 0; | ||
| 456 | |||
| 457 | /* | ||
| 458 | * Pull up any extra send data into the preregistered buffer. | ||
| 459 | * When padding is in use and applies to the transfer, insert | ||
| 460 | * it and change the message type. | ||
| 461 | */ | ||
| 462 | if (rtype == rpcrdma_noch) { | ||
| 463 | |||
| 464 | padlen = rpcrdma_inline_pullup(rqst, | ||
| 465 | RPCRDMA_INLINE_PAD_VALUE(rqst)); | ||
| 466 | |||
| 467 | if (padlen) { | ||
| 468 | headerp->rm_type = __constant_htonl(RDMA_MSGP); | ||
| 469 | headerp->rm_body.rm_padded.rm_align = | ||
| 470 | htonl(RPCRDMA_INLINE_PAD_VALUE(rqst)); | ||
| 471 | headerp->rm_body.rm_padded.rm_thresh = | ||
| 472 | __constant_htonl(RPCRDMA_INLINE_PAD_THRESH); | ||
| 473 | headerp->rm_body.rm_padded.rm_pempty[0] = xdr_zero; | ||
| 474 | headerp->rm_body.rm_padded.rm_pempty[1] = xdr_zero; | ||
| 475 | headerp->rm_body.rm_padded.rm_pempty[2] = xdr_zero; | ||
| 476 | hdrlen += 2 * sizeof(u32); /* extra words in padhdr */ | ||
| 477 | BUG_ON(wtype != rpcrdma_noch); | ||
| 478 | |||
| 479 | } else { | ||
| 480 | headerp->rm_body.rm_nochunks.rm_empty[0] = xdr_zero; | ||
| 481 | headerp->rm_body.rm_nochunks.rm_empty[1] = xdr_zero; | ||
| 482 | headerp->rm_body.rm_nochunks.rm_empty[2] = xdr_zero; | ||
| 483 | /* new length after pullup */ | ||
| 484 | rpclen = rqst->rq_svec[0].iov_len; | ||
| 485 | /* | ||
| 486 | * Currently we try to not actually use read inline. | ||
| 487 | * Reply chunks have the desirable property that | ||
| 488 | * they land, packed, directly in the target buffers | ||
| 489 | * without headers, so they require no fixup. The | ||
| 490 | * additional RDMA Write op sends the same amount | ||
| 491 | * of data, streams on-the-wire and adds no overhead | ||
| 492 | * on receive. Therefore, we request a reply chunk | ||
| 493 | * for non-writes wherever feasible and efficient. | ||
| 494 | */ | ||
| 495 | if (wtype == rpcrdma_noch && | ||
| 496 | r_xprt->rx_ia.ri_memreg_strategy > RPCRDMA_REGISTER) | ||
| 497 | wtype = rpcrdma_replych; | ||
| 498 | } | ||
| 499 | } | ||
| 500 | |||
| 501 | /* | ||
| 502 | * Marshal chunks. This routine will return the header length | ||
| 503 | * consumed by marshaling. | ||
| 504 | */ | ||
| 505 | if (rtype != rpcrdma_noch) { | ||
| 506 | hdrlen = rpcrdma_create_chunks(rqst, | ||
| 507 | &rqst->rq_snd_buf, headerp, rtype); | ||
| 508 | wtype = rtype; /* simplify dprintk */ | ||
| 509 | |||
| 510 | } else if (wtype != rpcrdma_noch) { | ||
| 511 | hdrlen = rpcrdma_create_chunks(rqst, | ||
| 512 | &rqst->rq_rcv_buf, headerp, wtype); | ||
| 513 | } | ||
| 514 | |||
| 515 | if (hdrlen == 0) | ||
| 516 | return -1; | ||
| 517 | |||
| 518 | dprintk("RPC: %s: %s: hdrlen %zd rpclen %zd padlen %zd\n" | ||
| 519 | " headerp 0x%p base 0x%p lkey 0x%x\n", | ||
| 520 | __func__, transfertypes[wtype], hdrlen, rpclen, padlen, | ||
| 521 | headerp, base, req->rl_iov.lkey); | ||
| 522 | |||
| 523 | /* | ||
| 524 | * initialize send_iov's - normally only two: rdma chunk header and | ||
| 525 | * single preregistered RPC header buffer, but if padding is present, | ||
| 526 | * then use a preregistered (and zeroed) pad buffer between the RPC | ||
| 527 | * header and any write data. In all non-rdma cases, any following | ||
| 528 | * data has been copied into the RPC header buffer. | ||
| 529 | */ | ||
| 530 | req->rl_send_iov[0].addr = req->rl_iov.addr; | ||
| 531 | req->rl_send_iov[0].length = hdrlen; | ||
| 532 | req->rl_send_iov[0].lkey = req->rl_iov.lkey; | ||
| 533 | |||
| 534 | req->rl_send_iov[1].addr = req->rl_iov.addr + (base - req->rl_base); | ||
| 535 | req->rl_send_iov[1].length = rpclen; | ||
| 536 | req->rl_send_iov[1].lkey = req->rl_iov.lkey; | ||
| 537 | |||
| 538 | req->rl_niovs = 2; | ||
| 539 | |||
| 540 | if (padlen) { | ||
| 541 | struct rpcrdma_ep *ep = &r_xprt->rx_ep; | ||
| 542 | |||
| 543 | req->rl_send_iov[2].addr = ep->rep_pad.addr; | ||
| 544 | req->rl_send_iov[2].length = padlen; | ||
| 545 | req->rl_send_iov[2].lkey = ep->rep_pad.lkey; | ||
| 546 | |||
| 547 | req->rl_send_iov[3].addr = req->rl_send_iov[1].addr + rpclen; | ||
| 548 | req->rl_send_iov[3].length = rqst->rq_slen - rpclen; | ||
| 549 | req->rl_send_iov[3].lkey = req->rl_iov.lkey; | ||
| 550 | |||
| 551 | req->rl_niovs = 4; | ||
| 552 | } | ||
| 553 | |||
| 554 | return 0; | ||
| 555 | } | ||
| 556 | |||
| 557 | /* | ||
| 558 | * Chase down a received write or reply chunklist to get length | ||
| 559 | * RDMA'd by server. See map at rpcrdma_create_chunks()! :-) | ||
| 560 | */ | ||
| 561 | static int | ||
| 562 | rpcrdma_count_chunks(struct rpcrdma_rep *rep, int max, int wrchunk, u32 **iptrp) | ||
| 563 | { | ||
| 564 | unsigned int i, total_len; | ||
| 565 | struct rpcrdma_write_chunk *cur_wchunk; | ||
| 566 | |||
| 567 | i = ntohl(**iptrp); /* get array count */ | ||
| 568 | if (i > max) | ||
| 569 | return -1; | ||
| 570 | cur_wchunk = (struct rpcrdma_write_chunk *) (*iptrp + 1); | ||
| 571 | total_len = 0; | ||
| 572 | while (i--) { | ||
| 573 | struct rpcrdma_segment *seg = &cur_wchunk->wc_target; | ||
| 574 | ifdebug(FACILITY) { | ||
| 575 | u64 off; | ||
| 576 | xdr_decode_hyper((u32 *)&seg->rs_offset, &off); | ||
| 577 | dprintk("RPC: %s: chunk %d@0x%llx:0x%x\n", | ||
| 578 | __func__, | ||
| 579 | ntohl(seg->rs_length), | ||
| 580 | off, | ||
| 581 | ntohl(seg->rs_handle)); | ||
| 582 | } | ||
| 583 | total_len += ntohl(seg->rs_length); | ||
| 584 | ++cur_wchunk; | ||
| 585 | } | ||
| 586 | /* check and adjust for properly terminated write chunk */ | ||
| 587 | if (wrchunk) { | ||
| 588 | u32 *w = (u32 *) cur_wchunk; | ||
| 589 | if (*w++ != xdr_zero) | ||
| 590 | return -1; | ||
| 591 | cur_wchunk = (struct rpcrdma_write_chunk *) w; | ||
| 592 | } | ||
| 593 | if ((char *) cur_wchunk > rep->rr_base + rep->rr_len) | ||
| 594 | return -1; | ||
| 595 | |||
| 596 | *iptrp = (u32 *) cur_wchunk; | ||
| 597 | return total_len; | ||
| 598 | } | ||
| 599 | |||
| 600 | /* | ||
| 601 | * Scatter inline received data back into provided iov's. | ||
| 602 | */ | ||
| 603 | static void | ||
| 604 | rpcrdma_inline_fixup(struct rpc_rqst *rqst, char *srcp, int copy_len) | ||
| 605 | { | ||
| 606 | int i, npages, curlen, olen; | ||
| 607 | char *destp; | ||
| 608 | |||
| 609 | curlen = rqst->rq_rcv_buf.head[0].iov_len; | ||
| 610 | if (curlen > copy_len) { /* write chunk header fixup */ | ||
| 611 | curlen = copy_len; | ||
| 612 | rqst->rq_rcv_buf.head[0].iov_len = curlen; | ||
| 613 | } | ||
| 614 | |||
| 615 | dprintk("RPC: %s: srcp 0x%p len %d hdrlen %d\n", | ||
| 616 | __func__, srcp, copy_len, curlen); | ||
| 617 | |||
| 618 | /* Shift pointer for first receive segment only */ | ||
| 619 | rqst->rq_rcv_buf.head[0].iov_base = srcp; | ||
| 620 | srcp += curlen; | ||
| 621 | copy_len -= curlen; | ||
| 622 | |||
| 623 | olen = copy_len; | ||
| 624 | i = 0; | ||
| 625 | rpcx_to_rdmax(rqst->rq_xprt)->rx_stats.fixup_copy_count += olen; | ||
| 626 | if (copy_len && rqst->rq_rcv_buf.page_len) { | ||
| 627 | npages = PAGE_ALIGN(rqst->rq_rcv_buf.page_base + | ||
| 628 | rqst->rq_rcv_buf.page_len) >> PAGE_SHIFT; | ||
| 629 | for (; i < npages; i++) { | ||
| 630 | if (i == 0) | ||
| 631 | curlen = PAGE_SIZE - rqst->rq_rcv_buf.page_base; | ||
| 632 | else | ||
| 633 | curlen = PAGE_SIZE; | ||
| 634 | if (curlen > copy_len) | ||
| 635 | curlen = copy_len; | ||
| 636 | dprintk("RPC: %s: page %d" | ||
| 637 | " srcp 0x%p len %d curlen %d\n", | ||
| 638 | __func__, i, srcp, copy_len, curlen); | ||
| 639 | destp = kmap_atomic(rqst->rq_rcv_buf.pages[i], | ||
| 640 | KM_SKB_SUNRPC_DATA); | ||
| 641 | if (i == 0) | ||
| 642 | memcpy(destp + rqst->rq_rcv_buf.page_base, | ||
| 643 | srcp, curlen); | ||
| 644 | else | ||
| 645 | memcpy(destp, srcp, curlen); | ||
| 646 | flush_dcache_page(rqst->rq_rcv_buf.pages[i]); | ||
| 647 | kunmap_atomic(destp, KM_SKB_SUNRPC_DATA); | ||
| 648 | srcp += curlen; | ||
| 649 | copy_len -= curlen; | ||
| 650 | if (copy_len == 0) | ||
| 651 | break; | ||
| 652 | } | ||
| 653 | rqst->rq_rcv_buf.page_len = olen - copy_len; | ||
| 654 | } else | ||
| 655 | rqst->rq_rcv_buf.page_len = 0; | ||
| 656 | |||
| 657 | if (copy_len && rqst->rq_rcv_buf.tail[0].iov_len) { | ||
| 658 | curlen = copy_len; | ||
| 659 | if (curlen > rqst->rq_rcv_buf.tail[0].iov_len) | ||
| 660 | curlen = rqst->rq_rcv_buf.tail[0].iov_len; | ||
| 661 | if (rqst->rq_rcv_buf.tail[0].iov_base != srcp) | ||
| 662 | memcpy(rqst->rq_rcv_buf.tail[0].iov_base, srcp, curlen); | ||
| 663 | dprintk("RPC: %s: tail srcp 0x%p len %d curlen %d\n", | ||
| 664 | __func__, srcp, copy_len, curlen); | ||
| 665 | rqst->rq_rcv_buf.tail[0].iov_len = curlen; | ||
| 666 | copy_len -= curlen; ++i; | ||
| 667 | } else | ||
| 668 | rqst->rq_rcv_buf.tail[0].iov_len = 0; | ||
| 669 | |||
| 670 | if (copy_len) | ||
| 671 | dprintk("RPC: %s: %d bytes in" | ||
| 672 | " %d extra segments (%d lost)\n", | ||
| 673 | __func__, olen, i, copy_len); | ||
| 674 | |||
| 675 | /* TBD avoid a warning from call_decode() */ | ||
| 676 | rqst->rq_private_buf = rqst->rq_rcv_buf; | ||
| 677 | } | ||
| 678 | |||
| 679 | /* | ||
| 680 | * This function is called when an async event is posted to | ||
| 681 | * the connection which changes the connection state. All it | ||
| 682 | * does at this point is mark the connection up/down, the rpc | ||
| 683 | * timers do the rest. | ||
| 684 | */ | ||
| 685 | void | ||
| 686 | rpcrdma_conn_func(struct rpcrdma_ep *ep) | ||
| 687 | { | ||
| 688 | struct rpc_xprt *xprt = ep->rep_xprt; | ||
| 689 | |||
| 690 | spin_lock_bh(&xprt->transport_lock); | ||
| 691 | if (ep->rep_connected > 0) { | ||
| 692 | if (!xprt_test_and_set_connected(xprt)) | ||
| 693 | xprt_wake_pending_tasks(xprt, 0); | ||
| 694 | } else { | ||
| 695 | if (xprt_test_and_clear_connected(xprt)) | ||
| 696 | xprt_wake_pending_tasks(xprt, ep->rep_connected); | ||
| 697 | } | ||
| 698 | spin_unlock_bh(&xprt->transport_lock); | ||
| 699 | } | ||
| 700 | |||
| 701 | /* | ||
| 702 | * This function is called when memory window unbind which we are waiting | ||
| 703 | * for completes. Just use rr_func (zeroed by upcall) to signal completion. | ||
| 704 | */ | ||
| 705 | static void | ||
| 706 | rpcrdma_unbind_func(struct rpcrdma_rep *rep) | ||
| 707 | { | ||
| 708 | wake_up(&rep->rr_unbind); | ||
| 709 | } | ||
| 710 | |||
| 711 | /* | ||
| 712 | * Called as a tasklet to do req/reply match and complete a request | ||
| 713 | * Errors must result in the RPC task either being awakened, or | ||
| 714 | * allowed to timeout, to discover the errors at that time. | ||
| 715 | */ | ||
| 716 | void | ||
| 717 | rpcrdma_reply_handler(struct rpcrdma_rep *rep) | ||
| 718 | { | ||
| 719 | struct rpcrdma_msg *headerp; | ||
| 720 | struct rpcrdma_req *req; | ||
| 721 | struct rpc_rqst *rqst; | ||
| 722 | struct rpc_xprt *xprt = rep->rr_xprt; | ||
| 723 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); | ||
| 724 | u32 *iptr; | ||
| 725 | int i, rdmalen, status; | ||
| 726 | |||
| 727 | /* Check status. If bad, signal disconnect and return rep to pool */ | ||
| 728 | if (rep->rr_len == ~0U) { | ||
| 729 | rpcrdma_recv_buffer_put(rep); | ||
| 730 | if (r_xprt->rx_ep.rep_connected == 1) { | ||
| 731 | r_xprt->rx_ep.rep_connected = -EIO; | ||
| 732 | rpcrdma_conn_func(&r_xprt->rx_ep); | ||
| 733 | } | ||
| 734 | return; | ||
| 735 | } | ||
| 736 | if (rep->rr_len < 28) { | ||
| 737 | dprintk("RPC: %s: short/invalid reply\n", __func__); | ||
| 738 | goto repost; | ||
| 739 | } | ||
| 740 | headerp = (struct rpcrdma_msg *) rep->rr_base; | ||
| 741 | if (headerp->rm_vers != xdr_one) { | ||
| 742 | dprintk("RPC: %s: invalid version %d\n", | ||
| 743 | __func__, ntohl(headerp->rm_vers)); | ||
| 744 | goto repost; | ||
| 745 | } | ||
| 746 | |||
| 747 | /* Get XID and try for a match. */ | ||
| 748 | spin_lock(&xprt->transport_lock); | ||
| 749 | rqst = xprt_lookup_rqst(xprt, headerp->rm_xid); | ||
| 750 | if (rqst == NULL) { | ||
| 751 | spin_unlock(&xprt->transport_lock); | ||
| 752 | dprintk("RPC: %s: reply 0x%p failed " | ||
| 753 | "to match any request xid 0x%08x len %d\n", | ||
| 754 | __func__, rep, headerp->rm_xid, rep->rr_len); | ||
| 755 | repost: | ||
| 756 | r_xprt->rx_stats.bad_reply_count++; | ||
| 757 | rep->rr_func = rpcrdma_reply_handler; | ||
| 758 | if (rpcrdma_ep_post_recv(&r_xprt->rx_ia, &r_xprt->rx_ep, rep)) | ||
| 759 | rpcrdma_recv_buffer_put(rep); | ||
| 760 | |||
| 761 | return; | ||
| 762 | } | ||
| 763 | |||
| 764 | /* get request object */ | ||
| 765 | req = rpcr_to_rdmar(rqst); | ||
| 766 | |||
| 767 | dprintk("RPC: %s: reply 0x%p completes request 0x%p\n" | ||
| 768 | " RPC request 0x%p xid 0x%08x\n", | ||
| 769 | __func__, rep, req, rqst, headerp->rm_xid); | ||
| 770 | |||
| 771 | BUG_ON(!req || req->rl_reply); | ||
| 772 | |||
| 773 | /* from here on, the reply is no longer an orphan */ | ||
| 774 | req->rl_reply = rep; | ||
| 775 | |||
| 776 | /* check for expected message types */ | ||
| 777 | /* The order of some of these tests is important. */ | ||
| 778 | switch (headerp->rm_type) { | ||
| 779 | case __constant_htonl(RDMA_MSG): | ||
| 780 | /* never expect read chunks */ | ||
| 781 | /* never expect reply chunks (two ways to check) */ | ||
| 782 | /* never expect write chunks without having offered RDMA */ | ||
| 783 | if (headerp->rm_body.rm_chunks[0] != xdr_zero || | ||
| 784 | (headerp->rm_body.rm_chunks[1] == xdr_zero && | ||
| 785 | headerp->rm_body.rm_chunks[2] != xdr_zero) || | ||
| 786 | (headerp->rm_body.rm_chunks[1] != xdr_zero && | ||
| 787 | req->rl_nchunks == 0)) | ||
| 788 | goto badheader; | ||
| 789 | if (headerp->rm_body.rm_chunks[1] != xdr_zero) { | ||
| 790 | /* count any expected write chunks in read reply */ | ||
| 791 | /* start at write chunk array count */ | ||
| 792 | iptr = &headerp->rm_body.rm_chunks[2]; | ||
| 793 | rdmalen = rpcrdma_count_chunks(rep, | ||
| 794 | req->rl_nchunks, 1, &iptr); | ||
| 795 | /* check for validity, and no reply chunk after */ | ||
| 796 | if (rdmalen < 0 || *iptr++ != xdr_zero) | ||
| 797 | goto badheader; | ||
| 798 | rep->rr_len -= | ||
| 799 | ((unsigned char *)iptr - (unsigned char *)headerp); | ||
| 800 | status = rep->rr_len + rdmalen; | ||
| 801 | r_xprt->rx_stats.total_rdma_reply += rdmalen; | ||
| 802 | } else { | ||
| 803 | /* else ordinary inline */ | ||
| 804 | iptr = (u32 *)((unsigned char *)headerp + 28); | ||
| 805 | rep->rr_len -= 28; /*sizeof *headerp;*/ | ||
| 806 | status = rep->rr_len; | ||
| 807 | } | ||
| 808 | /* Fix up the rpc results for upper layer */ | ||
| 809 | rpcrdma_inline_fixup(rqst, (char *)iptr, rep->rr_len); | ||
| 810 | break; | ||
| 811 | |||
| 812 | case __constant_htonl(RDMA_NOMSG): | ||
| 813 | /* never expect read or write chunks, always reply chunks */ | ||
| 814 | if (headerp->rm_body.rm_chunks[0] != xdr_zero || | ||
| 815 | headerp->rm_body.rm_chunks[1] != xdr_zero || | ||
| 816 | headerp->rm_body.rm_chunks[2] != xdr_one || | ||
| 817 | req->rl_nchunks == 0) | ||
| 818 | goto badheader; | ||
| 819 | iptr = (u32 *)((unsigned char *)headerp + 28); | ||
| 820 | rdmalen = rpcrdma_count_chunks(rep, req->rl_nchunks, 0, &iptr); | ||
| 821 | if (rdmalen < 0) | ||
| 822 | goto badheader; | ||
| 823 | r_xprt->rx_stats.total_rdma_reply += rdmalen; | ||
| 824 | /* Reply chunk buffer already is the reply vector - no fixup. */ | ||
| 825 | status = rdmalen; | ||
| 826 | break; | ||
| 827 | |||
| 828 | badheader: | ||
| 829 | default: | ||
| 830 | dprintk("%s: invalid rpcrdma reply header (type %d):" | ||
| 831 | " chunks[012] == %d %d %d" | ||
| 832 | " expected chunks <= %d\n", | ||
| 833 | __func__, ntohl(headerp->rm_type), | ||
| 834 | headerp->rm_body.rm_chunks[0], | ||
| 835 | headerp->rm_body.rm_chunks[1], | ||
| 836 | headerp->rm_body.rm_chunks[2], | ||
| 837 | req->rl_nchunks); | ||
| 838 | status = -EIO; | ||
| 839 | r_xprt->rx_stats.bad_reply_count++; | ||
| 840 | break; | ||
| 841 | } | ||
| 842 | |||
| 843 | /* If using mw bind, start the deregister process now. */ | ||
| 844 | /* (Note: if mr_free(), cannot perform it here, in tasklet context) */ | ||
| 845 | if (req->rl_nchunks) switch (r_xprt->rx_ia.ri_memreg_strategy) { | ||
| 846 | case RPCRDMA_MEMWINDOWS: | ||
| 847 | for (i = 0; req->rl_nchunks-- > 1;) | ||
| 848 | i += rpcrdma_deregister_external( | ||
| 849 | &req->rl_segments[i], r_xprt, NULL); | ||
| 850 | /* Optionally wait (not here) for unbinds to complete */ | ||
| 851 | rep->rr_func = rpcrdma_unbind_func; | ||
| 852 | (void) rpcrdma_deregister_external(&req->rl_segments[i], | ||
| 853 | r_xprt, rep); | ||
| 854 | break; | ||
| 855 | case RPCRDMA_MEMWINDOWS_ASYNC: | ||
| 856 | for (i = 0; req->rl_nchunks--;) | ||
| 857 | i += rpcrdma_deregister_external(&req->rl_segments[i], | ||
| 858 | r_xprt, NULL); | ||
| 859 | break; | ||
| 860 | default: | ||
| 861 | break; | ||
| 862 | } | ||
| 863 | |||
| 864 | dprintk("RPC: %s: xprt_complete_rqst(0x%p, 0x%p, %d)\n", | ||
| 865 | __func__, xprt, rqst, status); | ||
| 866 | xprt_complete_rqst(rqst->rq_task, status); | ||
| 867 | spin_unlock(&xprt->transport_lock); | ||
| 868 | } | ||
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c new file mode 100644 index 000000000000..dc55cc974c90 --- /dev/null +++ b/net/sunrpc/xprtrdma/transport.c | |||
| @@ -0,0 +1,800 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved. | ||
| 3 | * | ||
| 4 | * This software is available to you under a choice of one of two | ||
| 5 | * licenses. You may choose to be licensed under the terms of the GNU | ||
| 6 | * General Public License (GPL) Version 2, available from the file | ||
| 7 | * COPYING in the main directory of this source tree, or the BSD-type | ||
| 8 | * license below: | ||
| 9 | * | ||
| 10 | * Redistribution and use in source and binary forms, with or without | ||
| 11 | * modification, are permitted provided that the following conditions | ||
| 12 | * are met: | ||
| 13 | * | ||
| 14 | * Redistributions of source code must retain the above copyright | ||
| 15 | * notice, this list of conditions and the following disclaimer. | ||
| 16 | * | ||
| 17 | * Redistributions in binary form must reproduce the above | ||
| 18 | * copyright notice, this list of conditions and the following | ||
| 19 | * disclaimer in the documentation and/or other materials provided | ||
| 20 | * with the distribution. | ||
| 21 | * | ||
| 22 | * Neither the name of the Network Appliance, Inc. nor the names of | ||
| 23 | * its contributors may be used to endorse or promote products | ||
| 24 | * derived from this software without specific prior written | ||
| 25 | * permission. | ||
| 26 | * | ||
| 27 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| 28 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| 29 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
| 30 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| 31 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
| 32 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
| 33 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
| 34 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
| 35 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 36 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
| 37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 38 | */ | ||
| 39 | |||
| 40 | /* | ||
| 41 | * transport.c | ||
| 42 | * | ||
| 43 | * This file contains the top-level implementation of an RPC RDMA | ||
| 44 | * transport. | ||
| 45 | * | ||
| 46 | * Naming convention: functions beginning with xprt_ are part of the | ||
| 47 | * transport switch. All others are RPC RDMA internal. | ||
| 48 | */ | ||
| 49 | |||
| 50 | #include <linux/module.h> | ||
| 51 | #include <linux/init.h> | ||
| 52 | #include <linux/seq_file.h> | ||
| 53 | |||
| 54 | #include "xprt_rdma.h" | ||
| 55 | |||
| 56 | #ifdef RPC_DEBUG | ||
| 57 | # define RPCDBG_FACILITY RPCDBG_TRANS | ||
| 58 | #endif | ||
| 59 | |||
| 60 | MODULE_LICENSE("Dual BSD/GPL"); | ||
| 61 | |||
| 62 | MODULE_DESCRIPTION("RPC/RDMA Transport for Linux kernel NFS"); | ||
| 63 | MODULE_AUTHOR("Network Appliance, Inc."); | ||
| 64 | |||
| 65 | /* | ||
| 66 | * tunables | ||
| 67 | */ | ||
| 68 | |||
| 69 | static unsigned int xprt_rdma_slot_table_entries = RPCRDMA_DEF_SLOT_TABLE; | ||
| 70 | static unsigned int xprt_rdma_max_inline_read = RPCRDMA_DEF_INLINE; | ||
| 71 | static unsigned int xprt_rdma_max_inline_write = RPCRDMA_DEF_INLINE; | ||
| 72 | static unsigned int xprt_rdma_inline_write_padding; | ||
| 73 | #if !RPCRDMA_PERSISTENT_REGISTRATION | ||
| 74 | static unsigned int xprt_rdma_memreg_strategy = RPCRDMA_REGISTER; /* FMR? */ | ||
| 75 | #else | ||
| 76 | static unsigned int xprt_rdma_memreg_strategy = RPCRDMA_ALLPHYSICAL; | ||
| 77 | #endif | ||
| 78 | |||
| 79 | #ifdef RPC_DEBUG | ||
| 80 | |||
| 81 | static unsigned int min_slot_table_size = RPCRDMA_MIN_SLOT_TABLE; | ||
| 82 | static unsigned int max_slot_table_size = RPCRDMA_MAX_SLOT_TABLE; | ||
| 83 | static unsigned int zero; | ||
| 84 | static unsigned int max_padding = PAGE_SIZE; | ||
| 85 | static unsigned int min_memreg = RPCRDMA_BOUNCEBUFFERS; | ||
| 86 | static unsigned int max_memreg = RPCRDMA_LAST - 1; | ||
| 87 | |||
| 88 | static struct ctl_table_header *sunrpc_table_header; | ||
| 89 | |||
| 90 | static ctl_table xr_tunables_table[] = { | ||
| 91 | { | ||
| 92 | .ctl_name = CTL_SLOTTABLE_RDMA, | ||
| 93 | .procname = "rdma_slot_table_entries", | ||
| 94 | .data = &xprt_rdma_slot_table_entries, | ||
| 95 | .maxlen = sizeof(unsigned int), | ||
| 96 | .mode = 0644, | ||
| 97 | .proc_handler = &proc_dointvec_minmax, | ||
| 98 | .strategy = &sysctl_intvec, | ||
| 99 | .extra1 = &min_slot_table_size, | ||
| 100 | .extra2 = &max_slot_table_size | ||
| 101 | }, | ||
| 102 | { | ||
| 103 | .ctl_name = CTL_RDMA_MAXINLINEREAD, | ||
| 104 | .procname = "rdma_max_inline_read", | ||
| 105 | .data = &xprt_rdma_max_inline_read, | ||
| 106 | .maxlen = sizeof(unsigned int), | ||
| 107 | .mode = 0644, | ||
| 108 | .proc_handler = &proc_dointvec, | ||
| 109 | .strategy = &sysctl_intvec, | ||
| 110 | }, | ||
| 111 | { | ||
| 112 | .ctl_name = CTL_RDMA_MAXINLINEWRITE, | ||
| 113 | .procname = "rdma_max_inline_write", | ||
| 114 | .data = &xprt_rdma_max_inline_write, | ||
| 115 | .maxlen = sizeof(unsigned int), | ||
| 116 | .mode = 0644, | ||
| 117 | .proc_handler = &proc_dointvec, | ||
| 118 | .strategy = &sysctl_intvec, | ||
| 119 | }, | ||
| 120 | { | ||
| 121 | .ctl_name = CTL_RDMA_WRITEPADDING, | ||
| 122 | .procname = "rdma_inline_write_padding", | ||
| 123 | .data = &xprt_rdma_inline_write_padding, | ||
| 124 | .maxlen = sizeof(unsigned int), | ||
| 125 | .mode = 0644, | ||
| 126 | .proc_handler = &proc_dointvec_minmax, | ||
| 127 | .strategy = &sysctl_intvec, | ||
| 128 | .extra1 = &zero, | ||
| 129 | .extra2 = &max_padding, | ||
| 130 | }, | ||
| 131 | { | ||
| 132 | .ctl_name = CTL_RDMA_MEMREG, | ||
| 133 | .procname = "rdma_memreg_strategy", | ||
| 134 | .data = &xprt_rdma_memreg_strategy, | ||
| 135 | .maxlen = sizeof(unsigned int), | ||
| 136 | .mode = 0644, | ||
| 137 | .proc_handler = &proc_dointvec_minmax, | ||
| 138 | .strategy = &sysctl_intvec, | ||
| 139 | .extra1 = &min_memreg, | ||
| 140 | .extra2 = &max_memreg, | ||
| 141 | }, | ||
| 142 | { | ||
| 143 | .ctl_name = 0, | ||
| 144 | }, | ||
| 145 | }; | ||
| 146 | |||
| 147 | static ctl_table sunrpc_table[] = { | ||
| 148 | { | ||
| 149 | .ctl_name = CTL_SUNRPC, | ||
| 150 | .procname = "sunrpc", | ||
| 151 | .mode = 0555, | ||
| 152 | .child = xr_tunables_table | ||
| 153 | }, | ||
| 154 | { | ||
| 155 | .ctl_name = 0, | ||
| 156 | }, | ||
| 157 | }; | ||
| 158 | |||
| 159 | #endif | ||
| 160 | |||
| 161 | static struct rpc_xprt_ops xprt_rdma_procs; /* forward reference */ | ||
| 162 | |||
| 163 | static void | ||
| 164 | xprt_rdma_format_addresses(struct rpc_xprt *xprt) | ||
| 165 | { | ||
| 166 | struct sockaddr_in *addr = (struct sockaddr_in *) | ||
| 167 | &rpcx_to_rdmad(xprt).addr; | ||
| 168 | char *buf; | ||
| 169 | |||
| 170 | buf = kzalloc(20, GFP_KERNEL); | ||
| 171 | if (buf) | ||
| 172 | snprintf(buf, 20, NIPQUAD_FMT, NIPQUAD(addr->sin_addr.s_addr)); | ||
| 173 | xprt->address_strings[RPC_DISPLAY_ADDR] = buf; | ||
| 174 | |||
| 175 | buf = kzalloc(8, GFP_KERNEL); | ||
| 176 | if (buf) | ||
| 177 | snprintf(buf, 8, "%u", ntohs(addr->sin_port)); | ||
| 178 | xprt->address_strings[RPC_DISPLAY_PORT] = buf; | ||
| 179 | |||
| 180 | xprt->address_strings[RPC_DISPLAY_PROTO] = "rdma"; | ||
| 181 | |||
| 182 | buf = kzalloc(48, GFP_KERNEL); | ||
| 183 | if (buf) | ||
| 184 | snprintf(buf, 48, "addr="NIPQUAD_FMT" port=%u proto=%s", | ||
| 185 | NIPQUAD(addr->sin_addr.s_addr), | ||
| 186 | ntohs(addr->sin_port), "rdma"); | ||
| 187 | xprt->address_strings[RPC_DISPLAY_ALL] = buf; | ||
| 188 | |||
| 189 | buf = kzalloc(10, GFP_KERNEL); | ||
| 190 | if (buf) | ||
| 191 | snprintf(buf, 10, "%02x%02x%02x%02x", | ||
| 192 | NIPQUAD(addr->sin_addr.s_addr)); | ||
| 193 | xprt->address_strings[RPC_DISPLAY_HEX_ADDR] = buf; | ||
| 194 | |||
| 195 | buf = kzalloc(8, GFP_KERNEL); | ||
| 196 | if (buf) | ||
| 197 | snprintf(buf, 8, "%4hx", ntohs(addr->sin_port)); | ||
| 198 | xprt->address_strings[RPC_DISPLAY_HEX_PORT] = buf; | ||
| 199 | |||
| 200 | buf = kzalloc(30, GFP_KERNEL); | ||
| 201 | if (buf) | ||
| 202 | snprintf(buf, 30, NIPQUAD_FMT".%u.%u", | ||
| 203 | NIPQUAD(addr->sin_addr.s_addr), | ||
| 204 | ntohs(addr->sin_port) >> 8, | ||
| 205 | ntohs(addr->sin_port) & 0xff); | ||
| 206 | xprt->address_strings[RPC_DISPLAY_UNIVERSAL_ADDR] = buf; | ||
| 207 | |||
| 208 | /* netid */ | ||
| 209 | xprt->address_strings[RPC_DISPLAY_NETID] = "rdma"; | ||
| 210 | } | ||
| 211 | |||
| 212 | static void | ||
| 213 | xprt_rdma_free_addresses(struct rpc_xprt *xprt) | ||
| 214 | { | ||
| 215 | kfree(xprt->address_strings[RPC_DISPLAY_ADDR]); | ||
| 216 | kfree(xprt->address_strings[RPC_DISPLAY_PORT]); | ||
| 217 | kfree(xprt->address_strings[RPC_DISPLAY_ALL]); | ||
| 218 | kfree(xprt->address_strings[RPC_DISPLAY_HEX_ADDR]); | ||
| 219 | kfree(xprt->address_strings[RPC_DISPLAY_HEX_PORT]); | ||
| 220 | kfree(xprt->address_strings[RPC_DISPLAY_UNIVERSAL_ADDR]); | ||
| 221 | } | ||
| 222 | |||
| 223 | static void | ||
| 224 | xprt_rdma_connect_worker(struct work_struct *work) | ||
| 225 | { | ||
| 226 | struct rpcrdma_xprt *r_xprt = | ||
| 227 | container_of(work, struct rpcrdma_xprt, rdma_connect.work); | ||
| 228 | struct rpc_xprt *xprt = &r_xprt->xprt; | ||
| 229 | int rc = 0; | ||
| 230 | |||
| 231 | if (!xprt->shutdown) { | ||
| 232 | xprt_clear_connected(xprt); | ||
| 233 | |||
| 234 | dprintk("RPC: %s: %sconnect\n", __func__, | ||
| 235 | r_xprt->rx_ep.rep_connected != 0 ? "re" : ""); | ||
| 236 | rc = rpcrdma_ep_connect(&r_xprt->rx_ep, &r_xprt->rx_ia); | ||
| 237 | if (rc) | ||
| 238 | goto out; | ||
| 239 | } | ||
| 240 | goto out_clear; | ||
| 241 | |||
| 242 | out: | ||
| 243 | xprt_wake_pending_tasks(xprt, rc); | ||
| 244 | |||
| 245 | out_clear: | ||
| 246 | dprintk("RPC: %s: exit\n", __func__); | ||
| 247 | xprt_clear_connecting(xprt); | ||
| 248 | } | ||
| 249 | |||
| 250 | /* | ||
| 251 | * xprt_rdma_destroy | ||
| 252 | * | ||
| 253 | * Destroy the xprt. | ||
| 254 | * Free all memory associated with the object, including its own. | ||
| 255 | * NOTE: none of the *destroy methods free memory for their top-level | ||
| 256 | * objects, even though they may have allocated it (they do free | ||
| 257 | * private memory). It's up to the caller to handle it. In this | ||
| 258 | * case (RDMA transport), all structure memory is inlined with the | ||
| 259 | * struct rpcrdma_xprt. | ||
| 260 | */ | ||
| 261 | static void | ||
| 262 | xprt_rdma_destroy(struct rpc_xprt *xprt) | ||
| 263 | { | ||
| 264 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); | ||
| 265 | int rc; | ||
| 266 | |||
| 267 | dprintk("RPC: %s: called\n", __func__); | ||
| 268 | |||
| 269 | cancel_delayed_work(&r_xprt->rdma_connect); | ||
| 270 | flush_scheduled_work(); | ||
| 271 | |||
| 272 | xprt_clear_connected(xprt); | ||
| 273 | |||
| 274 | rpcrdma_buffer_destroy(&r_xprt->rx_buf); | ||
| 275 | rc = rpcrdma_ep_destroy(&r_xprt->rx_ep, &r_xprt->rx_ia); | ||
| 276 | if (rc) | ||
| 277 | dprintk("RPC: %s: rpcrdma_ep_destroy returned %i\n", | ||
| 278 | __func__, rc); | ||
| 279 | rpcrdma_ia_close(&r_xprt->rx_ia); | ||
| 280 | |||
| 281 | xprt_rdma_free_addresses(xprt); | ||
| 282 | |||
| 283 | kfree(xprt->slot); | ||
| 284 | xprt->slot = NULL; | ||
| 285 | kfree(xprt); | ||
| 286 | |||
| 287 | dprintk("RPC: %s: returning\n", __func__); | ||
| 288 | |||
| 289 | module_put(THIS_MODULE); | ||
| 290 | } | ||
| 291 | |||
| 292 | /** | ||
| 293 | * xprt_setup_rdma - Set up transport to use RDMA | ||
| 294 | * | ||
| 295 | * @args: rpc transport arguments | ||
| 296 | */ | ||
| 297 | static struct rpc_xprt * | ||
| 298 | xprt_setup_rdma(struct xprt_create *args) | ||
| 299 | { | ||
| 300 | struct rpcrdma_create_data_internal cdata; | ||
| 301 | struct rpc_xprt *xprt; | ||
| 302 | struct rpcrdma_xprt *new_xprt; | ||
| 303 | struct rpcrdma_ep *new_ep; | ||
| 304 | struct sockaddr_in *sin; | ||
| 305 | int rc; | ||
| 306 | |||
| 307 | if (args->addrlen > sizeof(xprt->addr)) { | ||
| 308 | dprintk("RPC: %s: address too large\n", __func__); | ||
| 309 | return ERR_PTR(-EBADF); | ||
| 310 | } | ||
| 311 | |||
| 312 | xprt = kzalloc(sizeof(struct rpcrdma_xprt), GFP_KERNEL); | ||
| 313 | if (xprt == NULL) { | ||
| 314 | dprintk("RPC: %s: couldn't allocate rpcrdma_xprt\n", | ||
| 315 | __func__); | ||
| 316 | return ERR_PTR(-ENOMEM); | ||
| 317 | } | ||
| 318 | |||
| 319 | xprt->max_reqs = xprt_rdma_slot_table_entries; | ||
| 320 | xprt->slot = kcalloc(xprt->max_reqs, | ||
| 321 | sizeof(struct rpc_rqst), GFP_KERNEL); | ||
| 322 | if (xprt->slot == NULL) { | ||
| 323 | kfree(xprt); | ||
| 324 | dprintk("RPC: %s: couldn't allocate %d slots\n", | ||
| 325 | __func__, xprt->max_reqs); | ||
| 326 | return ERR_PTR(-ENOMEM); | ||
| 327 | } | ||
| 328 | |||
| 329 | /* 60 second timeout, no retries */ | ||
| 330 | xprt_set_timeout(&xprt->timeout, 0, 60UL * HZ); | ||
| 331 | xprt->bind_timeout = (60U * HZ); | ||
| 332 | xprt->connect_timeout = (60U * HZ); | ||
| 333 | xprt->reestablish_timeout = (5U * HZ); | ||
| 334 | xprt->idle_timeout = (5U * 60 * HZ); | ||
| 335 | |||
| 336 | xprt->resvport = 0; /* privileged port not needed */ | ||
| 337 | xprt->tsh_size = 0; /* RPC-RDMA handles framing */ | ||
| 338 | xprt->max_payload = RPCRDMA_MAX_DATA_SEGS * PAGE_SIZE; | ||
| 339 | xprt->ops = &xprt_rdma_procs; | ||
| 340 | |||
| 341 | /* | ||
| 342 | * Set up RDMA-specific connect data. | ||
| 343 | */ | ||
| 344 | |||
| 345 | /* Put server RDMA address in local cdata */ | ||
| 346 | memcpy(&cdata.addr, args->dstaddr, args->addrlen); | ||
| 347 | |||
| 348 | /* Ensure xprt->addr holds valid server TCP (not RDMA) | ||
| 349 | * address, for any side protocols which peek at it */ | ||
| 350 | xprt->prot = IPPROTO_TCP; | ||
| 351 | xprt->addrlen = args->addrlen; | ||
| 352 | memcpy(&xprt->addr, &cdata.addr, xprt->addrlen); | ||
| 353 | |||
| 354 | sin = (struct sockaddr_in *)&cdata.addr; | ||
| 355 | if (ntohs(sin->sin_port) != 0) | ||
| 356 | xprt_set_bound(xprt); | ||
| 357 | |||
| 358 | dprintk("RPC: %s: %u.%u.%u.%u:%u\n", __func__, | ||
| 359 | NIPQUAD(sin->sin_addr.s_addr), ntohs(sin->sin_port)); | ||
| 360 | |||
| 361 | /* Set max requests */ | ||
| 362 | cdata.max_requests = xprt->max_reqs; | ||
| 363 | |||
| 364 | /* Set some length limits */ | ||
| 365 | cdata.rsize = RPCRDMA_MAX_SEGS * PAGE_SIZE; /* RDMA write max */ | ||
| 366 | cdata.wsize = RPCRDMA_MAX_SEGS * PAGE_SIZE; /* RDMA read max */ | ||
| 367 | |||
| 368 | cdata.inline_wsize = xprt_rdma_max_inline_write; | ||
| 369 | if (cdata.inline_wsize > cdata.wsize) | ||
| 370 | cdata.inline_wsize = cdata.wsize; | ||
| 371 | |||
| 372 | cdata.inline_rsize = xprt_rdma_max_inline_read; | ||
| 373 | if (cdata.inline_rsize > cdata.rsize) | ||
| 374 | cdata.inline_rsize = cdata.rsize; | ||
| 375 | |||
| 376 | cdata.padding = xprt_rdma_inline_write_padding; | ||
| 377 | |||
| 378 | /* | ||
| 379 | * Create new transport instance, which includes initialized | ||
| 380 | * o ia | ||
| 381 | * o endpoint | ||
| 382 | * o buffers | ||
| 383 | */ | ||
| 384 | |||
| 385 | new_xprt = rpcx_to_rdmax(xprt); | ||
| 386 | |||
| 387 | rc = rpcrdma_ia_open(new_xprt, (struct sockaddr *) &cdata.addr, | ||
| 388 | xprt_rdma_memreg_strategy); | ||
| 389 | if (rc) | ||
| 390 | goto out1; | ||
| 391 | |||
| 392 | /* | ||
| 393 | * initialize and create ep | ||
| 394 | */ | ||
| 395 | new_xprt->rx_data = cdata; | ||
| 396 | new_ep = &new_xprt->rx_ep; | ||
| 397 | new_ep->rep_remote_addr = cdata.addr; | ||
| 398 | |||
| 399 | rc = rpcrdma_ep_create(&new_xprt->rx_ep, | ||
| 400 | &new_xprt->rx_ia, &new_xprt->rx_data); | ||
| 401 | if (rc) | ||
| 402 | goto out2; | ||
| 403 | |||
| 404 | /* | ||
| 405 | * Allocate pre-registered send and receive buffers for headers and | ||
| 406 | * any inline data. Also specify any padding which will be provided | ||
| 407 | * from a preregistered zero buffer. | ||
| 408 | */ | ||
| 409 | rc = rpcrdma_buffer_create(&new_xprt->rx_buf, new_ep, &new_xprt->rx_ia, | ||
| 410 | &new_xprt->rx_data); | ||
| 411 | if (rc) | ||
| 412 | goto out3; | ||
| 413 | |||
| 414 | /* | ||
| 415 | * Register a callback for connection events. This is necessary because | ||
| 416 | * connection loss notification is async. We also catch connection loss | ||
| 417 | * when reaping receives. | ||
| 418 | */ | ||
| 419 | INIT_DELAYED_WORK(&new_xprt->rdma_connect, xprt_rdma_connect_worker); | ||
| 420 | new_ep->rep_func = rpcrdma_conn_func; | ||
| 421 | new_ep->rep_xprt = xprt; | ||
| 422 | |||
| 423 | xprt_rdma_format_addresses(xprt); | ||
| 424 | |||
| 425 | if (!try_module_get(THIS_MODULE)) | ||
| 426 | goto out4; | ||
| 427 | |||
| 428 | return xprt; | ||
| 429 | |||
| 430 | out4: | ||
| 431 | xprt_rdma_free_addresses(xprt); | ||
| 432 | rc = -EINVAL; | ||
| 433 | out3: | ||
| 434 | (void) rpcrdma_ep_destroy(new_ep, &new_xprt->rx_ia); | ||
| 435 | out2: | ||
| 436 | rpcrdma_ia_close(&new_xprt->rx_ia); | ||
| 437 | out1: | ||
| 438 | kfree(xprt->slot); | ||
| 439 | kfree(xprt); | ||
| 440 | return ERR_PTR(rc); | ||
| 441 | } | ||
| 442 | |||
| 443 | /* | ||
| 444 | * Close a connection, during shutdown or timeout/reconnect | ||
| 445 | */ | ||
| 446 | static void | ||
| 447 | xprt_rdma_close(struct rpc_xprt *xprt) | ||
| 448 | { | ||
| 449 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); | ||
| 450 | |||
| 451 | dprintk("RPC: %s: closing\n", __func__); | ||
| 452 | xprt_disconnect(xprt); | ||
| 453 | (void) rpcrdma_ep_disconnect(&r_xprt->rx_ep, &r_xprt->rx_ia); | ||
| 454 | } | ||
| 455 | |||
| 456 | static void | ||
| 457 | xprt_rdma_set_port(struct rpc_xprt *xprt, u16 port) | ||
| 458 | { | ||
| 459 | struct sockaddr_in *sap; | ||
| 460 | |||
| 461 | sap = (struct sockaddr_in *)&xprt->addr; | ||
| 462 | sap->sin_port = htons(port); | ||
| 463 | sap = (struct sockaddr_in *)&rpcx_to_rdmad(xprt).addr; | ||
| 464 | sap->sin_port = htons(port); | ||
| 465 | dprintk("RPC: %s: %u\n", __func__, port); | ||
| 466 | } | ||
| 467 | |||
| 468 | static void | ||
| 469 | xprt_rdma_connect(struct rpc_task *task) | ||
| 470 | { | ||
| 471 | struct rpc_xprt *xprt = (struct rpc_xprt *)task->tk_xprt; | ||
| 472 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); | ||
| 473 | |||
| 474 | if (!xprt_test_and_set_connecting(xprt)) { | ||
| 475 | if (r_xprt->rx_ep.rep_connected != 0) { | ||
| 476 | /* Reconnect */ | ||
| 477 | schedule_delayed_work(&r_xprt->rdma_connect, | ||
| 478 | xprt->reestablish_timeout); | ||
| 479 | } else { | ||
| 480 | schedule_delayed_work(&r_xprt->rdma_connect, 0); | ||
| 481 | if (!RPC_IS_ASYNC(task)) | ||
| 482 | flush_scheduled_work(); | ||
| 483 | } | ||
| 484 | } | ||
| 485 | } | ||
| 486 | |||
| 487 | static int | ||
| 488 | xprt_rdma_reserve_xprt(struct rpc_task *task) | ||
| 489 | { | ||
| 490 | struct rpc_xprt *xprt = task->tk_xprt; | ||
| 491 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); | ||
| 492 | int credits = atomic_read(&r_xprt->rx_buf.rb_credits); | ||
| 493 | |||
| 494 | /* == RPC_CWNDSCALE @ init, but *after* setup */ | ||
| 495 | if (r_xprt->rx_buf.rb_cwndscale == 0UL) { | ||
| 496 | r_xprt->rx_buf.rb_cwndscale = xprt->cwnd; | ||
| 497 | dprintk("RPC: %s: cwndscale %lu\n", __func__, | ||
| 498 | r_xprt->rx_buf.rb_cwndscale); | ||
| 499 | BUG_ON(r_xprt->rx_buf.rb_cwndscale <= 0); | ||
| 500 | } | ||
| 501 | xprt->cwnd = credits * r_xprt->rx_buf.rb_cwndscale; | ||
| 502 | return xprt_reserve_xprt_cong(task); | ||
| 503 | } | ||
| 504 | |||
| 505 | /* | ||
| 506 | * The RDMA allocate/free functions need the task structure as a place | ||
| 507 | * to hide the struct rpcrdma_req, which is necessary for the actual send/recv | ||
| 508 | * sequence. For this reason, the recv buffers are attached to send | ||
| 509 | * buffers for portions of the RPC. Note that the RPC layer allocates | ||
| 510 | * both send and receive buffers in the same call. We may register | ||
| 511 | * the receive buffer portion when using reply chunks. | ||
| 512 | */ | ||
| 513 | static void * | ||
| 514 | xprt_rdma_allocate(struct rpc_task *task, size_t size) | ||
| 515 | { | ||
| 516 | struct rpc_xprt *xprt = task->tk_xprt; | ||
| 517 | struct rpcrdma_req *req, *nreq; | ||
| 518 | |||
| 519 | req = rpcrdma_buffer_get(&rpcx_to_rdmax(xprt)->rx_buf); | ||
| 520 | BUG_ON(NULL == req); | ||
| 521 | |||
| 522 | if (size > req->rl_size) { | ||
| 523 | dprintk("RPC: %s: size %zd too large for buffer[%zd]: " | ||
| 524 | "prog %d vers %d proc %d\n", | ||
| 525 | __func__, size, req->rl_size, | ||
| 526 | task->tk_client->cl_prog, task->tk_client->cl_vers, | ||
| 527 | task->tk_msg.rpc_proc->p_proc); | ||
| 528 | /* | ||
| 529 | * Outgoing length shortage. Our inline write max must have | ||
| 530 | * been configured to perform direct i/o. | ||
| 531 | * | ||
| 532 | * This is therefore a large metadata operation, and the | ||
| 533 | * allocate call was made on the maximum possible message, | ||
| 534 | * e.g. containing long filename(s) or symlink data. In | ||
| 535 | * fact, while these metadata operations *might* carry | ||
| 536 | * large outgoing payloads, they rarely *do*. However, we | ||
| 537 | * have to commit to the request here, so reallocate and | ||
| 538 | * register it now. The data path will never require this | ||
| 539 | * reallocation. | ||
| 540 | * | ||
| 541 | * If the allocation or registration fails, the RPC framework | ||
| 542 | * will (doggedly) retry. | ||
| 543 | */ | ||
| 544 | if (rpcx_to_rdmax(xprt)->rx_ia.ri_memreg_strategy == | ||
| 545 | RPCRDMA_BOUNCEBUFFERS) { | ||
| 546 | /* forced to "pure inline" */ | ||
| 547 | dprintk("RPC: %s: too much data (%zd) for inline " | ||
| 548 | "(r/w max %d/%d)\n", __func__, size, | ||
| 549 | rpcx_to_rdmad(xprt).inline_rsize, | ||
| 550 | rpcx_to_rdmad(xprt).inline_wsize); | ||
| 551 | size = req->rl_size; | ||
| 552 | rpc_exit(task, -EIO); /* fail the operation */ | ||
| 553 | rpcx_to_rdmax(xprt)->rx_stats.failed_marshal_count++; | ||
| 554 | goto out; | ||
| 555 | } | ||
| 556 | if (task->tk_flags & RPC_TASK_SWAPPER) | ||
| 557 | nreq = kmalloc(sizeof *req + size, GFP_ATOMIC); | ||
| 558 | else | ||
| 559 | nreq = kmalloc(sizeof *req + size, GFP_NOFS); | ||
| 560 | if (nreq == NULL) | ||
| 561 | goto outfail; | ||
| 562 | |||
| 563 | if (rpcrdma_register_internal(&rpcx_to_rdmax(xprt)->rx_ia, | ||
| 564 | nreq->rl_base, size + sizeof(struct rpcrdma_req) | ||
| 565 | - offsetof(struct rpcrdma_req, rl_base), | ||
| 566 | &nreq->rl_handle, &nreq->rl_iov)) { | ||
| 567 | kfree(nreq); | ||
| 568 | goto outfail; | ||
| 569 | } | ||
| 570 | rpcx_to_rdmax(xprt)->rx_stats.hardway_register_count += size; | ||
| 571 | nreq->rl_size = size; | ||
| 572 | nreq->rl_niovs = 0; | ||
| 573 | nreq->rl_nchunks = 0; | ||
| 574 | nreq->rl_buffer = (struct rpcrdma_buffer *)req; | ||
| 575 | nreq->rl_reply = req->rl_reply; | ||
| 576 | memcpy(nreq->rl_segments, | ||
| 577 | req->rl_segments, sizeof nreq->rl_segments); | ||
| 578 | /* flag the swap with an unused field */ | ||
| 579 | nreq->rl_iov.length = 0; | ||
| 580 | req->rl_reply = NULL; | ||
| 581 | req = nreq; | ||
| 582 | } | ||
| 583 | dprintk("RPC: %s: size %zd, request 0x%p\n", __func__, size, req); | ||
| 584 | out: | ||
| 585 | return req->rl_xdr_buf; | ||
| 586 | |||
| 587 | outfail: | ||
| 588 | rpcrdma_buffer_put(req); | ||
| 589 | rpcx_to_rdmax(xprt)->rx_stats.failed_marshal_count++; | ||
| 590 | return NULL; | ||
| 591 | } | ||
| 592 | |||
| 593 | /* | ||
| 594 | * This function returns all RDMA resources to the pool. | ||
| 595 | */ | ||
| 596 | static void | ||
| 597 | xprt_rdma_free(void *buffer) | ||
| 598 | { | ||
| 599 | struct rpcrdma_req *req; | ||
| 600 | struct rpcrdma_xprt *r_xprt; | ||
| 601 | struct rpcrdma_rep *rep; | ||
| 602 | int i; | ||
| 603 | |||
| 604 | if (buffer == NULL) | ||
| 605 | return; | ||
| 606 | |||
| 607 | req = container_of(buffer, struct rpcrdma_req, rl_xdr_buf[0]); | ||
| 608 | r_xprt = container_of(req->rl_buffer, struct rpcrdma_xprt, rx_buf); | ||
| 609 | rep = req->rl_reply; | ||
| 610 | |||
| 611 | dprintk("RPC: %s: called on 0x%p%s\n", | ||
| 612 | __func__, rep, (rep && rep->rr_func) ? " (with waiter)" : ""); | ||
| 613 | |||
| 614 | /* | ||
| 615 | * Finish the deregistration. When using mw bind, this was | ||
| 616 | * begun in rpcrdma_reply_handler(). In all other modes, we | ||
| 617 | * do it here, in thread context. The process is considered | ||
| 618 | * complete when the rr_func vector becomes NULL - this | ||
| 619 | * was put in place during rpcrdma_reply_handler() - the wait | ||
| 620 | * call below will not block if the dereg is "done". If | ||
| 621 | * interrupted, our framework will clean up. | ||
| 622 | */ | ||
| 623 | for (i = 0; req->rl_nchunks;) { | ||
| 624 | --req->rl_nchunks; | ||
| 625 | i += rpcrdma_deregister_external( | ||
| 626 | &req->rl_segments[i], r_xprt, NULL); | ||
| 627 | } | ||
| 628 | |||
| 629 | if (rep && wait_event_interruptible(rep->rr_unbind, !rep->rr_func)) { | ||
| 630 | rep->rr_func = NULL; /* abandon the callback */ | ||
| 631 | req->rl_reply = NULL; | ||
| 632 | } | ||
| 633 | |||
| 634 | if (req->rl_iov.length == 0) { /* see allocate above */ | ||
| 635 | struct rpcrdma_req *oreq = (struct rpcrdma_req *)req->rl_buffer; | ||
| 636 | oreq->rl_reply = req->rl_reply; | ||
| 637 | (void) rpcrdma_deregister_internal(&r_xprt->rx_ia, | ||
| 638 | req->rl_handle, | ||
| 639 | &req->rl_iov); | ||
| 640 | kfree(req); | ||
| 641 | req = oreq; | ||
| 642 | } | ||
| 643 | |||
| 644 | /* Put back request+reply buffers */ | ||
| 645 | rpcrdma_buffer_put(req); | ||
| 646 | } | ||
| 647 | |||
| 648 | /* | ||
| 649 | * send_request invokes the meat of RPC RDMA. It must do the following: | ||
| 650 | * 1. Marshal the RPC request into an RPC RDMA request, which means | ||
| 651 | * putting a header in front of data, and creating IOVs for RDMA | ||
| 652 | * from those in the request. | ||
| 653 | * 2. In marshaling, detect opportunities for RDMA, and use them. | ||
| 654 | * 3. Post a recv message to set up asynch completion, then send | ||
| 655 | * the request (rpcrdma_ep_post). | ||
| 656 | * 4. No partial sends are possible in the RPC-RDMA protocol (as in UDP). | ||
| 657 | */ | ||
| 658 | |||
| 659 | static int | ||
| 660 | xprt_rdma_send_request(struct rpc_task *task) | ||
| 661 | { | ||
| 662 | struct rpc_rqst *rqst = task->tk_rqstp; | ||
| 663 | struct rpc_xprt *xprt = task->tk_xprt; | ||
| 664 | struct rpcrdma_req *req = rpcr_to_rdmar(rqst); | ||
| 665 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); | ||
| 666 | |||
| 667 | /* marshal the send itself */ | ||
| 668 | if (req->rl_niovs == 0 && rpcrdma_marshal_req(rqst) != 0) { | ||
| 669 | r_xprt->rx_stats.failed_marshal_count++; | ||
| 670 | dprintk("RPC: %s: rpcrdma_marshal_req failed\n", | ||
| 671 | __func__); | ||
| 672 | return -EIO; | ||
| 673 | } | ||
| 674 | |||
| 675 | if (req->rl_reply == NULL) /* e.g. reconnection */ | ||
| 676 | rpcrdma_recv_buffer_get(req); | ||
| 677 | |||
| 678 | if (req->rl_reply) { | ||
| 679 | req->rl_reply->rr_func = rpcrdma_reply_handler; | ||
| 680 | /* this need only be done once, but... */ | ||
| 681 | req->rl_reply->rr_xprt = xprt; | ||
| 682 | } | ||
| 683 | |||
| 684 | if (rpcrdma_ep_post(&r_xprt->rx_ia, &r_xprt->rx_ep, req)) { | ||
| 685 | xprt_disconnect(xprt); | ||
| 686 | return -ENOTCONN; /* implies disconnect */ | ||
| 687 | } | ||
| 688 | |||
| 689 | rqst->rq_bytes_sent = 0; | ||
| 690 | return 0; | ||
| 691 | } | ||
| 692 | |||
| 693 | static void xprt_rdma_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) | ||
| 694 | { | ||
| 695 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); | ||
| 696 | long idle_time = 0; | ||
| 697 | |||
| 698 | if (xprt_connected(xprt)) | ||
| 699 | idle_time = (long)(jiffies - xprt->last_used) / HZ; | ||
| 700 | |||
| 701 | seq_printf(seq, | ||
| 702 | "\txprt:\trdma %u %lu %lu %lu %ld %lu %lu %lu %Lu %Lu " | ||
| 703 | "%lu %lu %lu %Lu %Lu %Lu %Lu %lu %lu %lu\n", | ||
| 704 | |||
| 705 | 0, /* need a local port? */ | ||
| 706 | xprt->stat.bind_count, | ||
| 707 | xprt->stat.connect_count, | ||
| 708 | xprt->stat.connect_time, | ||
| 709 | idle_time, | ||
| 710 | xprt->stat.sends, | ||
| 711 | xprt->stat.recvs, | ||
| 712 | xprt->stat.bad_xids, | ||
| 713 | xprt->stat.req_u, | ||
| 714 | xprt->stat.bklog_u, | ||
| 715 | |||
| 716 | r_xprt->rx_stats.read_chunk_count, | ||
| 717 | r_xprt->rx_stats.write_chunk_count, | ||
| 718 | r_xprt->rx_stats.reply_chunk_count, | ||
| 719 | r_xprt->rx_stats.total_rdma_request, | ||
| 720 | r_xprt->rx_stats.total_rdma_reply, | ||
| 721 | r_xprt->rx_stats.pullup_copy_count, | ||
| 722 | r_xprt->rx_stats.fixup_copy_count, | ||
| 723 | r_xprt->rx_stats.hardway_register_count, | ||
| 724 | r_xprt->rx_stats.failed_marshal_count, | ||
| 725 | r_xprt->rx_stats.bad_reply_count); | ||
| 726 | } | ||
| 727 | |||
| 728 | /* | ||
| 729 | * Plumbing for rpc transport switch and kernel module | ||
| 730 | */ | ||
| 731 | |||
| 732 | static struct rpc_xprt_ops xprt_rdma_procs = { | ||
| 733 | .reserve_xprt = xprt_rdma_reserve_xprt, | ||
| 734 | .release_xprt = xprt_release_xprt_cong, /* sunrpc/xprt.c */ | ||
| 735 | .release_request = xprt_release_rqst_cong, /* ditto */ | ||
| 736 | .set_retrans_timeout = xprt_set_retrans_timeout_def, /* ditto */ | ||
| 737 | .rpcbind = rpcb_getport_async, /* sunrpc/rpcb_clnt.c */ | ||
| 738 | .set_port = xprt_rdma_set_port, | ||
| 739 | .connect = xprt_rdma_connect, | ||
| 740 | .buf_alloc = xprt_rdma_allocate, | ||
| 741 | .buf_free = xprt_rdma_free, | ||
| 742 | .send_request = xprt_rdma_send_request, | ||
| 743 | .close = xprt_rdma_close, | ||
| 744 | .destroy = xprt_rdma_destroy, | ||
| 745 | .print_stats = xprt_rdma_print_stats | ||
| 746 | }; | ||
| 747 | |||
| 748 | static struct xprt_class xprt_rdma = { | ||
| 749 | .list = LIST_HEAD_INIT(xprt_rdma.list), | ||
| 750 | .name = "rdma", | ||
| 751 | .owner = THIS_MODULE, | ||
| 752 | .ident = XPRT_TRANSPORT_RDMA, | ||
| 753 | .setup = xprt_setup_rdma, | ||
| 754 | }; | ||
| 755 | |||
| 756 | static void __exit xprt_rdma_cleanup(void) | ||
| 757 | { | ||
| 758 | int rc; | ||
| 759 | |||
| 760 | dprintk("RPCRDMA Module Removed, deregister RPC RDMA transport\n"); | ||
| 761 | #ifdef RPC_DEBUG | ||
| 762 | if (sunrpc_table_header) { | ||
| 763 | unregister_sysctl_table(sunrpc_table_header); | ||
| 764 | sunrpc_table_header = NULL; | ||
| 765 | } | ||
| 766 | #endif | ||
| 767 | rc = xprt_unregister_transport(&xprt_rdma); | ||
| 768 | if (rc) | ||
| 769 | dprintk("RPC: %s: xprt_unregister returned %i\n", | ||
| 770 | __func__, rc); | ||
| 771 | } | ||
| 772 | |||
| 773 | static int __init xprt_rdma_init(void) | ||
| 774 | { | ||
| 775 | int rc; | ||
| 776 | |||
| 777 | rc = xprt_register_transport(&xprt_rdma); | ||
| 778 | |||
| 779 | if (rc) | ||
| 780 | return rc; | ||
| 781 | |||
| 782 | dprintk(KERN_INFO "RPCRDMA Module Init, register RPC RDMA transport\n"); | ||
| 783 | |||
| 784 | dprintk(KERN_INFO "Defaults:\n"); | ||
| 785 | dprintk(KERN_INFO "\tSlots %d\n" | ||
| 786 | "\tMaxInlineRead %d\n\tMaxInlineWrite %d\n", | ||
| 787 | xprt_rdma_slot_table_entries, | ||
| 788 | xprt_rdma_max_inline_read, xprt_rdma_max_inline_write); | ||
| 789 | dprintk(KERN_INFO "\tPadding %d\n\tMemreg %d\n", | ||
| 790 | xprt_rdma_inline_write_padding, xprt_rdma_memreg_strategy); | ||
| 791 | |||
| 792 | #ifdef RPC_DEBUG | ||
| 793 | if (!sunrpc_table_header) | ||
| 794 | sunrpc_table_header = register_sysctl_table(sunrpc_table); | ||
| 795 | #endif | ||
| 796 | return 0; | ||
| 797 | } | ||
| 798 | |||
| 799 | module_init(xprt_rdma_init); | ||
| 800 | module_exit(xprt_rdma_cleanup); | ||
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c new file mode 100644 index 000000000000..9ec8ca4f6028 --- /dev/null +++ b/net/sunrpc/xprtrdma/verbs.c | |||
| @@ -0,0 +1,1626 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved. | ||
| 3 | * | ||
| 4 | * This software is available to you under a choice of one of two | ||
| 5 | * licenses. You may choose to be licensed under the terms of the GNU | ||
| 6 | * General Public License (GPL) Version 2, available from the file | ||
| 7 | * COPYING in the main directory of this source tree, or the BSD-type | ||
| 8 | * license below: | ||
| 9 | * | ||
| 10 | * Redistribution and use in source and binary forms, with or without | ||
| 11 | * modification, are permitted provided that the following conditions | ||
| 12 | * are met: | ||
| 13 | * | ||
| 14 | * Redistributions of source code must retain the above copyright | ||
| 15 | * notice, this list of conditions and the following disclaimer. | ||
| 16 | * | ||
| 17 | * Redistributions in binary form must reproduce the above | ||
| 18 | * copyright notice, this list of conditions and the following | ||
| 19 | * disclaimer in the documentation and/or other materials provided | ||
| 20 | * with the distribution. | ||
| 21 | * | ||
| 22 | * Neither the name of the Network Appliance, Inc. nor the names of | ||
| 23 | * its contributors may be used to endorse or promote products | ||
| 24 | * derived from this software without specific prior written | ||
| 25 | * permission. | ||
| 26 | * | ||
| 27 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| 28 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| 29 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
| 30 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| 31 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
| 32 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
| 33 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
| 34 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
| 35 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 36 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
| 37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 38 | */ | ||
| 39 | |||
| 40 | /* | ||
| 41 | * verbs.c | ||
| 42 | * | ||
| 43 | * Encapsulates the major functions managing: | ||
| 44 | * o adapters | ||
| 45 | * o endpoints | ||
| 46 | * o connections | ||
| 47 | * o buffer memory | ||
| 48 | */ | ||
| 49 | |||
| 50 | #include <linux/pci.h> /* for Tavor hack below */ | ||
| 51 | |||
| 52 | #include "xprt_rdma.h" | ||
| 53 | |||
| 54 | /* | ||
| 55 | * Globals/Macros | ||
| 56 | */ | ||
| 57 | |||
| 58 | #ifdef RPC_DEBUG | ||
| 59 | # define RPCDBG_FACILITY RPCDBG_TRANS | ||
| 60 | #endif | ||
| 61 | |||
| 62 | /* | ||
| 63 | * internal functions | ||
| 64 | */ | ||
| 65 | |||
| 66 | /* | ||
| 67 | * handle replies in tasklet context, using a single, global list | ||
| 68 | * rdma tasklet function -- just turn around and call the func | ||
| 69 | * for all replies on the list | ||
| 70 | */ | ||
| 71 | |||
| 72 | static DEFINE_SPINLOCK(rpcrdma_tk_lock_g); | ||
| 73 | static LIST_HEAD(rpcrdma_tasklets_g); | ||
| 74 | |||
| 75 | static void | ||
| 76 | rpcrdma_run_tasklet(unsigned long data) | ||
| 77 | { | ||
| 78 | struct rpcrdma_rep *rep; | ||
| 79 | void (*func)(struct rpcrdma_rep *); | ||
| 80 | unsigned long flags; | ||
| 81 | |||
| 82 | data = data; | ||
| 83 | spin_lock_irqsave(&rpcrdma_tk_lock_g, flags); | ||
| 84 | while (!list_empty(&rpcrdma_tasklets_g)) { | ||
| 85 | rep = list_entry(rpcrdma_tasklets_g.next, | ||
| 86 | struct rpcrdma_rep, rr_list); | ||
| 87 | list_del(&rep->rr_list); | ||
| 88 | func = rep->rr_func; | ||
| 89 | rep->rr_func = NULL; | ||
| 90 | spin_unlock_irqrestore(&rpcrdma_tk_lock_g, flags); | ||
| 91 | |||
| 92 | if (func) | ||
| 93 | func(rep); | ||
| 94 | else | ||
| 95 | rpcrdma_recv_buffer_put(rep); | ||
| 96 | |||
| 97 | spin_lock_irqsave(&rpcrdma_tk_lock_g, flags); | ||
| 98 | } | ||
| 99 | spin_unlock_irqrestore(&rpcrdma_tk_lock_g, flags); | ||
| 100 | } | ||
| 101 | |||
| 102 | static DECLARE_TASKLET(rpcrdma_tasklet_g, rpcrdma_run_tasklet, 0UL); | ||
| 103 | |||
| 104 | static inline void | ||
| 105 | rpcrdma_schedule_tasklet(struct rpcrdma_rep *rep) | ||
| 106 | { | ||
| 107 | unsigned long flags; | ||
| 108 | |||
| 109 | spin_lock_irqsave(&rpcrdma_tk_lock_g, flags); | ||
| 110 | list_add_tail(&rep->rr_list, &rpcrdma_tasklets_g); | ||
| 111 | spin_unlock_irqrestore(&rpcrdma_tk_lock_g, flags); | ||
| 112 | tasklet_schedule(&rpcrdma_tasklet_g); | ||
| 113 | } | ||
| 114 | |||
| 115 | static void | ||
| 116 | rpcrdma_qp_async_error_upcall(struct ib_event *event, void *context) | ||
| 117 | { | ||
| 118 | struct rpcrdma_ep *ep = context; | ||
| 119 | |||
| 120 | dprintk("RPC: %s: QP error %X on device %s ep %p\n", | ||
| 121 | __func__, event->event, event->device->name, context); | ||
| 122 | if (ep->rep_connected == 1) { | ||
| 123 | ep->rep_connected = -EIO; | ||
| 124 | ep->rep_func(ep); | ||
| 125 | wake_up_all(&ep->rep_connect_wait); | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | static void | ||
| 130 | rpcrdma_cq_async_error_upcall(struct ib_event *event, void *context) | ||
| 131 | { | ||
| 132 | struct rpcrdma_ep *ep = context; | ||
| 133 | |||
| 134 | dprintk("RPC: %s: CQ error %X on device %s ep %p\n", | ||
| 135 | __func__, event->event, event->device->name, context); | ||
| 136 | if (ep->rep_connected == 1) { | ||
| 137 | ep->rep_connected = -EIO; | ||
| 138 | ep->rep_func(ep); | ||
| 139 | wake_up_all(&ep->rep_connect_wait); | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 143 | static inline | ||
| 144 | void rpcrdma_event_process(struct ib_wc *wc) | ||
| 145 | { | ||
| 146 | struct rpcrdma_rep *rep = | ||
| 147 | (struct rpcrdma_rep *)(unsigned long) wc->wr_id; | ||
| 148 | |||
| 149 | dprintk("RPC: %s: event rep %p status %X opcode %X length %u\n", | ||
| 150 | __func__, rep, wc->status, wc->opcode, wc->byte_len); | ||
| 151 | |||
| 152 | if (!rep) /* send or bind completion that we don't care about */ | ||
| 153 | return; | ||
| 154 | |||
| 155 | if (IB_WC_SUCCESS != wc->status) { | ||
| 156 | dprintk("RPC: %s: %s WC status %X, connection lost\n", | ||
| 157 | __func__, (wc->opcode & IB_WC_RECV) ? "recv" : "send", | ||
| 158 | wc->status); | ||
| 159 | rep->rr_len = ~0U; | ||
| 160 | rpcrdma_schedule_tasklet(rep); | ||
| 161 | return; | ||
| 162 | } | ||
| 163 | |||
| 164 | switch (wc->opcode) { | ||
| 165 | case IB_WC_RECV: | ||
| 166 | rep->rr_len = wc->byte_len; | ||
| 167 | ib_dma_sync_single_for_cpu( | ||
| 168 | rdmab_to_ia(rep->rr_buffer)->ri_id->device, | ||
| 169 | rep->rr_iov.addr, rep->rr_len, DMA_FROM_DEVICE); | ||
| 170 | /* Keep (only) the most recent credits, after check validity */ | ||
| 171 | if (rep->rr_len >= 16) { | ||
| 172 | struct rpcrdma_msg *p = | ||
| 173 | (struct rpcrdma_msg *) rep->rr_base; | ||
| 174 | unsigned int credits = ntohl(p->rm_credit); | ||
| 175 | if (credits == 0) { | ||
| 176 | dprintk("RPC: %s: server" | ||
| 177 | " dropped credits to 0!\n", __func__); | ||
| 178 | /* don't deadlock */ | ||
| 179 | credits = 1; | ||
| 180 | } else if (credits > rep->rr_buffer->rb_max_requests) { | ||
| 181 | dprintk("RPC: %s: server" | ||
| 182 | " over-crediting: %d (%d)\n", | ||
| 183 | __func__, credits, | ||
| 184 | rep->rr_buffer->rb_max_requests); | ||
| 185 | credits = rep->rr_buffer->rb_max_requests; | ||
| 186 | } | ||
| 187 | atomic_set(&rep->rr_buffer->rb_credits, credits); | ||
| 188 | } | ||
| 189 | /* fall through */ | ||
| 190 | case IB_WC_BIND_MW: | ||
| 191 | rpcrdma_schedule_tasklet(rep); | ||
| 192 | break; | ||
| 193 | default: | ||
| 194 | dprintk("RPC: %s: unexpected WC event %X\n", | ||
| 195 | __func__, wc->opcode); | ||
| 196 | break; | ||
| 197 | } | ||
| 198 | } | ||
| 199 | |||
| 200 | static inline int | ||
| 201 | rpcrdma_cq_poll(struct ib_cq *cq) | ||
| 202 | { | ||
| 203 | struct ib_wc wc; | ||
| 204 | int rc; | ||
| 205 | |||
| 206 | for (;;) { | ||
| 207 | rc = ib_poll_cq(cq, 1, &wc); | ||
| 208 | if (rc < 0) { | ||
| 209 | dprintk("RPC: %s: ib_poll_cq failed %i\n", | ||
| 210 | __func__, rc); | ||
| 211 | return rc; | ||
| 212 | } | ||
| 213 | if (rc == 0) | ||
| 214 | break; | ||
| 215 | |||
| 216 | rpcrdma_event_process(&wc); | ||
| 217 | } | ||
| 218 | |||
| 219 | return 0; | ||
| 220 | } | ||
| 221 | |||
| 222 | /* | ||
| 223 | * rpcrdma_cq_event_upcall | ||
| 224 | * | ||
| 225 | * This upcall handles recv, send, bind and unbind events. | ||
| 226 | * It is reentrant but processes single events in order to maintain | ||
| 227 | * ordering of receives to keep server credits. | ||
| 228 | * | ||
| 229 | * It is the responsibility of the scheduled tasklet to return | ||
| 230 | * recv buffers to the pool. NOTE: this affects synchronization of | ||
| 231 | * connection shutdown. That is, the structures required for | ||
| 232 | * the completion of the reply handler must remain intact until | ||
| 233 | * all memory has been reclaimed. | ||
| 234 | * | ||
| 235 | * Note that send events are suppressed and do not result in an upcall. | ||
| 236 | */ | ||
| 237 | static void | ||
| 238 | rpcrdma_cq_event_upcall(struct ib_cq *cq, void *context) | ||
| 239 | { | ||
| 240 | int rc; | ||
| 241 | |||
| 242 | rc = rpcrdma_cq_poll(cq); | ||
| 243 | if (rc) | ||
| 244 | return; | ||
| 245 | |||
| 246 | rc = ib_req_notify_cq(cq, IB_CQ_NEXT_COMP); | ||
| 247 | if (rc) { | ||
| 248 | dprintk("RPC: %s: ib_req_notify_cq failed %i\n", | ||
| 249 | __func__, rc); | ||
| 250 | return; | ||
| 251 | } | ||
| 252 | |||
| 253 | rpcrdma_cq_poll(cq); | ||
| 254 | } | ||
| 255 | |||
| 256 | #ifdef RPC_DEBUG | ||
| 257 | static const char * const conn[] = { | ||
| 258 | "address resolved", | ||
| 259 | "address error", | ||
| 260 | "route resolved", | ||
| 261 | "route error", | ||
| 262 | "connect request", | ||
| 263 | "connect response", | ||
| 264 | "connect error", | ||
| 265 | "unreachable", | ||
| 266 | "rejected", | ||
| 267 | "established", | ||
| 268 | "disconnected", | ||
| 269 | "device removal" | ||
| 270 | }; | ||
| 271 | #endif | ||
| 272 | |||
| 273 | static int | ||
| 274 | rpcrdma_conn_upcall(struct rdma_cm_id *id, struct rdma_cm_event *event) | ||
| 275 | { | ||
| 276 | struct rpcrdma_xprt *xprt = id->context; | ||
| 277 | struct rpcrdma_ia *ia = &xprt->rx_ia; | ||
| 278 | struct rpcrdma_ep *ep = &xprt->rx_ep; | ||
| 279 | struct sockaddr_in *addr = (struct sockaddr_in *) &ep->rep_remote_addr; | ||
| 280 | struct ib_qp_attr attr; | ||
| 281 | struct ib_qp_init_attr iattr; | ||
| 282 | int connstate = 0; | ||
| 283 | |||
| 284 | switch (event->event) { | ||
| 285 | case RDMA_CM_EVENT_ADDR_RESOLVED: | ||
| 286 | case RDMA_CM_EVENT_ROUTE_RESOLVED: | ||
| 287 | complete(&ia->ri_done); | ||
| 288 | break; | ||
| 289 | case RDMA_CM_EVENT_ADDR_ERROR: | ||
| 290 | ia->ri_async_rc = -EHOSTUNREACH; | ||
| 291 | dprintk("RPC: %s: CM address resolution error, ep 0x%p\n", | ||
| 292 | __func__, ep); | ||
| 293 | complete(&ia->ri_done); | ||
| 294 | break; | ||
| 295 | case RDMA_CM_EVENT_ROUTE_ERROR: | ||
| 296 | ia->ri_async_rc = -ENETUNREACH; | ||
| 297 | dprintk("RPC: %s: CM route resolution error, ep 0x%p\n", | ||
| 298 | __func__, ep); | ||
| 299 | complete(&ia->ri_done); | ||
| 300 | break; | ||
| 301 | case RDMA_CM_EVENT_ESTABLISHED: | ||
| 302 | connstate = 1; | ||
| 303 | ib_query_qp(ia->ri_id->qp, &attr, | ||
| 304 | IB_QP_MAX_QP_RD_ATOMIC | IB_QP_MAX_DEST_RD_ATOMIC, | ||
| 305 | &iattr); | ||
| 306 | dprintk("RPC: %s: %d responder resources" | ||
| 307 | " (%d initiator)\n", | ||
| 308 | __func__, attr.max_dest_rd_atomic, attr.max_rd_atomic); | ||
| 309 | goto connected; | ||
| 310 | case RDMA_CM_EVENT_CONNECT_ERROR: | ||
| 311 | connstate = -ENOTCONN; | ||
| 312 | goto connected; | ||
| 313 | case RDMA_CM_EVENT_UNREACHABLE: | ||
| 314 | connstate = -ENETDOWN; | ||
| 315 | goto connected; | ||
| 316 | case RDMA_CM_EVENT_REJECTED: | ||
| 317 | connstate = -ECONNREFUSED; | ||
| 318 | goto connected; | ||
| 319 | case RDMA_CM_EVENT_DISCONNECTED: | ||
| 320 | connstate = -ECONNABORTED; | ||
| 321 | goto connected; | ||
| 322 | case RDMA_CM_EVENT_DEVICE_REMOVAL: | ||
| 323 | connstate = -ENODEV; | ||
| 324 | connected: | ||
| 325 | dprintk("RPC: %s: %s: %u.%u.%u.%u:%u" | ||
| 326 | " (ep 0x%p event 0x%x)\n", | ||
| 327 | __func__, | ||
| 328 | (event->event <= 11) ? conn[event->event] : | ||
| 329 | "unknown connection error", | ||
| 330 | NIPQUAD(addr->sin_addr.s_addr), | ||
| 331 | ntohs(addr->sin_port), | ||
| 332 | ep, event->event); | ||
| 333 | atomic_set(&rpcx_to_rdmax(ep->rep_xprt)->rx_buf.rb_credits, 1); | ||
| 334 | dprintk("RPC: %s: %sconnected\n", | ||
| 335 | __func__, connstate > 0 ? "" : "dis"); | ||
| 336 | ep->rep_connected = connstate; | ||
| 337 | ep->rep_func(ep); | ||
| 338 | wake_up_all(&ep->rep_connect_wait); | ||
| 339 | break; | ||
| 340 | default: | ||
| 341 | ia->ri_async_rc = -EINVAL; | ||
| 342 | dprintk("RPC: %s: unexpected CM event %X\n", | ||
| 343 | __func__, event->event); | ||
| 344 | complete(&ia->ri_done); | ||
| 345 | break; | ||
| 346 | } | ||
| 347 | |||
| 348 | return 0; | ||
| 349 | } | ||
| 350 | |||
| 351 | static struct rdma_cm_id * | ||
| 352 | rpcrdma_create_id(struct rpcrdma_xprt *xprt, | ||
| 353 | struct rpcrdma_ia *ia, struct sockaddr *addr) | ||
| 354 | { | ||
| 355 | struct rdma_cm_id *id; | ||
| 356 | int rc; | ||
| 357 | |||
| 358 | id = rdma_create_id(rpcrdma_conn_upcall, xprt, RDMA_PS_TCP); | ||
| 359 | if (IS_ERR(id)) { | ||
| 360 | rc = PTR_ERR(id); | ||
| 361 | dprintk("RPC: %s: rdma_create_id() failed %i\n", | ||
| 362 | __func__, rc); | ||
| 363 | return id; | ||
| 364 | } | ||
| 365 | |||
| 366 | ia->ri_async_rc = 0; | ||
| 367 | rc = rdma_resolve_addr(id, NULL, addr, RDMA_RESOLVE_TIMEOUT); | ||
| 368 | if (rc) { | ||
| 369 | dprintk("RPC: %s: rdma_resolve_addr() failed %i\n", | ||
| 370 | __func__, rc); | ||
| 371 | goto out; | ||
| 372 | } | ||
| 373 | wait_for_completion(&ia->ri_done); | ||
| 374 | rc = ia->ri_async_rc; | ||
| 375 | if (rc) | ||
| 376 | goto out; | ||
| 377 | |||
| 378 | ia->ri_async_rc = 0; | ||
| 379 | rc = rdma_resolve_route(id, RDMA_RESOLVE_TIMEOUT); | ||
| 380 | if (rc) { | ||
| 381 | dprintk("RPC: %s: rdma_resolve_route() failed %i\n", | ||
| 382 | __func__, rc); | ||
| 383 | goto out; | ||
| 384 | } | ||
| 385 | wait_for_completion(&ia->ri_done); | ||
| 386 | rc = ia->ri_async_rc; | ||
| 387 | if (rc) | ||
| 388 | goto out; | ||
| 389 | |||
| 390 | return id; | ||
| 391 | |||
| 392 | out: | ||
| 393 | rdma_destroy_id(id); | ||
| 394 | return ERR_PTR(rc); | ||
| 395 | } | ||
| 396 | |||
| 397 | /* | ||
| 398 | * Drain any cq, prior to teardown. | ||
| 399 | */ | ||
| 400 | static void | ||
| 401 | rpcrdma_clean_cq(struct ib_cq *cq) | ||
| 402 | { | ||
| 403 | struct ib_wc wc; | ||
| 404 | int count = 0; | ||
| 405 | |||
| 406 | while (1 == ib_poll_cq(cq, 1, &wc)) | ||
| 407 | ++count; | ||
| 408 | |||
| 409 | if (count) | ||
| 410 | dprintk("RPC: %s: flushed %d events (last 0x%x)\n", | ||
| 411 | __func__, count, wc.opcode); | ||
| 412 | } | ||
| 413 | |||
| 414 | /* | ||
| 415 | * Exported functions. | ||
| 416 | */ | ||
| 417 | |||
| 418 | /* | ||
| 419 | * Open and initialize an Interface Adapter. | ||
| 420 | * o initializes fields of struct rpcrdma_ia, including | ||
| 421 | * interface and provider attributes and protection zone. | ||
| 422 | */ | ||
| 423 | int | ||
| 424 | rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg) | ||
| 425 | { | ||
| 426 | int rc; | ||
| 427 | struct rpcrdma_ia *ia = &xprt->rx_ia; | ||
| 428 | |||
| 429 | init_completion(&ia->ri_done); | ||
| 430 | |||
| 431 | ia->ri_id = rpcrdma_create_id(xprt, ia, addr); | ||
| 432 | if (IS_ERR(ia->ri_id)) { | ||
| 433 | rc = PTR_ERR(ia->ri_id); | ||
| 434 | goto out1; | ||
| 435 | } | ||
| 436 | |||
| 437 | ia->ri_pd = ib_alloc_pd(ia->ri_id->device); | ||
| 438 | if (IS_ERR(ia->ri_pd)) { | ||
| 439 | rc = PTR_ERR(ia->ri_pd); | ||
| 440 | dprintk("RPC: %s: ib_alloc_pd() failed %i\n", | ||
| 441 | __func__, rc); | ||
| 442 | goto out2; | ||
| 443 | } | ||
| 444 | |||
| 445 | /* | ||
| 446 | * Optionally obtain an underlying physical identity mapping in | ||
| 447 | * order to do a memory window-based bind. This base registration | ||
| 448 | * is protected from remote access - that is enabled only by binding | ||
| 449 | * for the specific bytes targeted during each RPC operation, and | ||
| 450 | * revoked after the corresponding completion similar to a storage | ||
| 451 | * adapter. | ||
| 452 | */ | ||
| 453 | if (memreg > RPCRDMA_REGISTER) { | ||
| 454 | int mem_priv = IB_ACCESS_LOCAL_WRITE; | ||
| 455 | switch (memreg) { | ||
| 456 | #if RPCRDMA_PERSISTENT_REGISTRATION | ||
| 457 | case RPCRDMA_ALLPHYSICAL: | ||
| 458 | mem_priv |= IB_ACCESS_REMOTE_WRITE; | ||
| 459 | mem_priv |= IB_ACCESS_REMOTE_READ; | ||
| 460 | break; | ||
| 461 | #endif | ||
| 462 | case RPCRDMA_MEMWINDOWS_ASYNC: | ||
| 463 | case RPCRDMA_MEMWINDOWS: | ||
| 464 | mem_priv |= IB_ACCESS_MW_BIND; | ||
| 465 | break; | ||
| 466 | default: | ||
| 467 | break; | ||
| 468 | } | ||
| 469 | ia->ri_bind_mem = ib_get_dma_mr(ia->ri_pd, mem_priv); | ||
| 470 | if (IS_ERR(ia->ri_bind_mem)) { | ||
| 471 | printk(KERN_ALERT "%s: ib_get_dma_mr for " | ||
| 472 | "phys register failed with %lX\n\t" | ||
| 473 | "Will continue with degraded performance\n", | ||
| 474 | __func__, PTR_ERR(ia->ri_bind_mem)); | ||
| 475 | memreg = RPCRDMA_REGISTER; | ||
| 476 | ia->ri_bind_mem = NULL; | ||
| 477 | } | ||
| 478 | } | ||
| 479 | |||
| 480 | /* Else will do memory reg/dereg for each chunk */ | ||
| 481 | ia->ri_memreg_strategy = memreg; | ||
| 482 | |||
| 483 | return 0; | ||
| 484 | out2: | ||
| 485 | rdma_destroy_id(ia->ri_id); | ||
| 486 | out1: | ||
| 487 | return rc; | ||
| 488 | } | ||
| 489 | |||
| 490 | /* | ||
| 491 | * Clean up/close an IA. | ||
| 492 | * o if event handles and PD have been initialized, free them. | ||
| 493 | * o close the IA | ||
| 494 | */ | ||
| 495 | void | ||
| 496 | rpcrdma_ia_close(struct rpcrdma_ia *ia) | ||
| 497 | { | ||
| 498 | int rc; | ||
| 499 | |||
| 500 | dprintk("RPC: %s: entering\n", __func__); | ||
| 501 | if (ia->ri_bind_mem != NULL) { | ||
| 502 | rc = ib_dereg_mr(ia->ri_bind_mem); | ||
| 503 | dprintk("RPC: %s: ib_dereg_mr returned %i\n", | ||
| 504 | __func__, rc); | ||
| 505 | } | ||
| 506 | if (ia->ri_id != NULL && !IS_ERR(ia->ri_id) && ia->ri_id->qp) | ||
| 507 | rdma_destroy_qp(ia->ri_id); | ||
| 508 | if (ia->ri_pd != NULL && !IS_ERR(ia->ri_pd)) { | ||
| 509 | rc = ib_dealloc_pd(ia->ri_pd); | ||
| 510 | dprintk("RPC: %s: ib_dealloc_pd returned %i\n", | ||
| 511 | __func__, rc); | ||
| 512 | } | ||
| 513 | if (ia->ri_id != NULL && !IS_ERR(ia->ri_id)) | ||
| 514 | rdma_destroy_id(ia->ri_id); | ||
| 515 | } | ||
| 516 | |||
| 517 | /* | ||
| 518 | * Create unconnected endpoint. | ||
| 519 | */ | ||
| 520 | int | ||
| 521 | rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia, | ||
| 522 | struct rpcrdma_create_data_internal *cdata) | ||
| 523 | { | ||
| 524 | struct ib_device_attr devattr; | ||
| 525 | int rc; | ||
| 526 | |||
| 527 | rc = ib_query_device(ia->ri_id->device, &devattr); | ||
| 528 | if (rc) { | ||
| 529 | dprintk("RPC: %s: ib_query_device failed %d\n", | ||
| 530 | __func__, rc); | ||
| 531 | return rc; | ||
| 532 | } | ||
| 533 | |||
| 534 | /* check provider's send/recv wr limits */ | ||
| 535 | if (cdata->max_requests > devattr.max_qp_wr) | ||
| 536 | cdata->max_requests = devattr.max_qp_wr; | ||
| 537 | |||
| 538 | ep->rep_attr.event_handler = rpcrdma_qp_async_error_upcall; | ||
| 539 | ep->rep_attr.qp_context = ep; | ||
| 540 | /* send_cq and recv_cq initialized below */ | ||
| 541 | ep->rep_attr.srq = NULL; | ||
| 542 | ep->rep_attr.cap.max_send_wr = cdata->max_requests; | ||
| 543 | switch (ia->ri_memreg_strategy) { | ||
| 544 | case RPCRDMA_MEMWINDOWS_ASYNC: | ||
| 545 | case RPCRDMA_MEMWINDOWS: | ||
| 546 | /* Add room for mw_binds+unbinds - overkill! */ | ||
| 547 | ep->rep_attr.cap.max_send_wr++; | ||
| 548 | ep->rep_attr.cap.max_send_wr *= (2 * RPCRDMA_MAX_SEGS); | ||
| 549 | if (ep->rep_attr.cap.max_send_wr > devattr.max_qp_wr) | ||
| 550 | return -EINVAL; | ||
| 551 | break; | ||
| 552 | default: | ||
| 553 | break; | ||
| 554 | } | ||
| 555 | ep->rep_attr.cap.max_recv_wr = cdata->max_requests; | ||
| 556 | ep->rep_attr.cap.max_send_sge = (cdata->padding ? 4 : 2); | ||
| 557 | ep->rep_attr.cap.max_recv_sge = 1; | ||
| 558 | ep->rep_attr.cap.max_inline_data = 0; | ||
| 559 | ep->rep_attr.sq_sig_type = IB_SIGNAL_REQ_WR; | ||
| 560 | ep->rep_attr.qp_type = IB_QPT_RC; | ||
| 561 | ep->rep_attr.port_num = ~0; | ||
| 562 | |||
| 563 | dprintk("RPC: %s: requested max: dtos: send %d recv %d; " | ||
| 564 | "iovs: send %d recv %d\n", | ||
| 565 | __func__, | ||
| 566 | ep->rep_attr.cap.max_send_wr, | ||
| 567 | ep->rep_attr.cap.max_recv_wr, | ||
| 568 | ep->rep_attr.cap.max_send_sge, | ||
| 569 | ep->rep_attr.cap.max_recv_sge); | ||
| 570 | |||
| 571 | /* set trigger for requesting send completion */ | ||
| 572 | ep->rep_cqinit = ep->rep_attr.cap.max_send_wr/2 /* - 1*/; | ||
| 573 | switch (ia->ri_memreg_strategy) { | ||
| 574 | case RPCRDMA_MEMWINDOWS_ASYNC: | ||
| 575 | case RPCRDMA_MEMWINDOWS: | ||
| 576 | ep->rep_cqinit -= RPCRDMA_MAX_SEGS; | ||
| 577 | break; | ||
| 578 | default: | ||
| 579 | break; | ||
| 580 | } | ||
| 581 | if (ep->rep_cqinit <= 2) | ||
| 582 | ep->rep_cqinit = 0; | ||
| 583 | INIT_CQCOUNT(ep); | ||
| 584 | ep->rep_ia = ia; | ||
| 585 | init_waitqueue_head(&ep->rep_connect_wait); | ||
| 586 | |||
| 587 | /* | ||
| 588 | * Create a single cq for receive dto and mw_bind (only ever | ||
| 589 | * care about unbind, really). Send completions are suppressed. | ||
| 590 | * Use single threaded tasklet upcalls to maintain ordering. | ||
| 591 | */ | ||
| 592 | ep->rep_cq = ib_create_cq(ia->ri_id->device, rpcrdma_cq_event_upcall, | ||
| 593 | rpcrdma_cq_async_error_upcall, NULL, | ||
| 594 | ep->rep_attr.cap.max_recv_wr + | ||
| 595 | ep->rep_attr.cap.max_send_wr + 1, 0); | ||
| 596 | if (IS_ERR(ep->rep_cq)) { | ||
| 597 | rc = PTR_ERR(ep->rep_cq); | ||
| 598 | dprintk("RPC: %s: ib_create_cq failed: %i\n", | ||
| 599 | __func__, rc); | ||
| 600 | goto out1; | ||
| 601 | } | ||
| 602 | |||
| 603 | rc = ib_req_notify_cq(ep->rep_cq, IB_CQ_NEXT_COMP); | ||
| 604 | if (rc) { | ||
| 605 | dprintk("RPC: %s: ib_req_notify_cq failed: %i\n", | ||
| 606 | __func__, rc); | ||
| 607 | goto out2; | ||
| 608 | } | ||
| 609 | |||
| 610 | ep->rep_attr.send_cq = ep->rep_cq; | ||
| 611 | ep->rep_attr.recv_cq = ep->rep_cq; | ||
| 612 | |||
| 613 | /* Initialize cma parameters */ | ||
| 614 | |||
| 615 | /* RPC/RDMA does not use private data */ | ||
| 616 | ep->rep_remote_cma.private_data = NULL; | ||
| 617 | ep->rep_remote_cma.private_data_len = 0; | ||
| 618 | |||
| 619 | /* Client offers RDMA Read but does not initiate */ | ||
| 620 | switch (ia->ri_memreg_strategy) { | ||
| 621 | case RPCRDMA_BOUNCEBUFFERS: | ||
| 622 | ep->rep_remote_cma.responder_resources = 0; | ||
| 623 | break; | ||
| 624 | case RPCRDMA_MTHCAFMR: | ||
| 625 | case RPCRDMA_REGISTER: | ||
| 626 | ep->rep_remote_cma.responder_resources = cdata->max_requests * | ||
| 627 | (RPCRDMA_MAX_DATA_SEGS / 8); | ||
| 628 | break; | ||
| 629 | case RPCRDMA_MEMWINDOWS: | ||
| 630 | case RPCRDMA_MEMWINDOWS_ASYNC: | ||
| 631 | #if RPCRDMA_PERSISTENT_REGISTRATION | ||
| 632 | case RPCRDMA_ALLPHYSICAL: | ||
| 633 | #endif | ||
| 634 | ep->rep_remote_cma.responder_resources = cdata->max_requests * | ||
| 635 | (RPCRDMA_MAX_DATA_SEGS / 2); | ||
| 636 | break; | ||
| 637 | default: | ||
| 638 | break; | ||
| 639 | } | ||
| 640 | if (ep->rep_remote_cma.responder_resources > devattr.max_qp_rd_atom) | ||
| 641 | ep->rep_remote_cma.responder_resources = devattr.max_qp_rd_atom; | ||
| 642 | ep->rep_remote_cma.initiator_depth = 0; | ||
| 643 | |||
| 644 | ep->rep_remote_cma.retry_count = 7; | ||
| 645 | ep->rep_remote_cma.flow_control = 0; | ||
| 646 | ep->rep_remote_cma.rnr_retry_count = 0; | ||
| 647 | |||
| 648 | return 0; | ||
| 649 | |||
| 650 | out2: | ||
| 651 | if (ib_destroy_cq(ep->rep_cq)) | ||
| 652 | ; | ||
| 653 | out1: | ||
| 654 | return rc; | ||
| 655 | } | ||
| 656 | |||
| 657 | /* | ||
| 658 | * rpcrdma_ep_destroy | ||
| 659 | * | ||
| 660 | * Disconnect and destroy endpoint. After this, the only | ||
| 661 | * valid operations on the ep are to free it (if dynamically | ||
| 662 | * allocated) or re-create it. | ||
| 663 | * | ||
| 664 | * The caller's error handling must be sure to not leak the endpoint | ||
| 665 | * if this function fails. | ||
| 666 | */ | ||
| 667 | int | ||
| 668 | rpcrdma_ep_destroy(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia) | ||
| 669 | { | ||
| 670 | int rc; | ||
| 671 | |||
| 672 | dprintk("RPC: %s: entering, connected is %d\n", | ||
| 673 | __func__, ep->rep_connected); | ||
| 674 | |||
| 675 | if (ia->ri_id->qp) { | ||
| 676 | rc = rpcrdma_ep_disconnect(ep, ia); | ||
| 677 | if (rc) | ||
| 678 | dprintk("RPC: %s: rpcrdma_ep_disconnect" | ||
| 679 | " returned %i\n", __func__, rc); | ||
| 680 | } | ||
| 681 | |||
| 682 | ep->rep_func = NULL; | ||
| 683 | |||
| 684 | /* padding - could be done in rpcrdma_buffer_destroy... */ | ||
| 685 | if (ep->rep_pad_mr) { | ||
| 686 | rpcrdma_deregister_internal(ia, ep->rep_pad_mr, &ep->rep_pad); | ||
| 687 | ep->rep_pad_mr = NULL; | ||
| 688 | } | ||
| 689 | |||
| 690 | if (ia->ri_id->qp) { | ||
| 691 | rdma_destroy_qp(ia->ri_id); | ||
| 692 | ia->ri_id->qp = NULL; | ||
| 693 | } | ||
| 694 | |||
| 695 | rpcrdma_clean_cq(ep->rep_cq); | ||
| 696 | rc = ib_destroy_cq(ep->rep_cq); | ||
| 697 | if (rc) | ||
| 698 | dprintk("RPC: %s: ib_destroy_cq returned %i\n", | ||
| 699 | __func__, rc); | ||
| 700 | |||
| 701 | return rc; | ||
| 702 | } | ||
| 703 | |||
| 704 | /* | ||
| 705 | * Connect unconnected endpoint. | ||
| 706 | */ | ||
| 707 | int | ||
| 708 | rpcrdma_ep_connect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia) | ||
| 709 | { | ||
| 710 | struct rdma_cm_id *id; | ||
| 711 | int rc = 0; | ||
| 712 | int retry_count = 0; | ||
| 713 | int reconnect = (ep->rep_connected != 0); | ||
| 714 | |||
| 715 | if (reconnect) { | ||
| 716 | struct rpcrdma_xprt *xprt; | ||
| 717 | retry: | ||
| 718 | rc = rpcrdma_ep_disconnect(ep, ia); | ||
| 719 | if (rc && rc != -ENOTCONN) | ||
| 720 | dprintk("RPC: %s: rpcrdma_ep_disconnect" | ||
| 721 | " status %i\n", __func__, rc); | ||
| 722 | rpcrdma_clean_cq(ep->rep_cq); | ||
| 723 | |||
| 724 | xprt = container_of(ia, struct rpcrdma_xprt, rx_ia); | ||
| 725 | id = rpcrdma_create_id(xprt, ia, | ||
| 726 | (struct sockaddr *)&xprt->rx_data.addr); | ||
| 727 | if (IS_ERR(id)) { | ||
| 728 | rc = PTR_ERR(id); | ||
| 729 | goto out; | ||
| 730 | } | ||
| 731 | /* TEMP TEMP TEMP - fail if new device: | ||
| 732 | * Deregister/remarshal *all* requests! | ||
| 733 | * Close and recreate adapter, pd, etc! | ||
| 734 | * Re-determine all attributes still sane! | ||
| 735 | * More stuff I haven't thought of! | ||
| 736 | * Rrrgh! | ||
| 737 | */ | ||
| 738 | if (ia->ri_id->device != id->device) { | ||
| 739 | printk("RPC: %s: can't reconnect on " | ||
| 740 | "different device!\n", __func__); | ||
| 741 | rdma_destroy_id(id); | ||
| 742 | rc = -ENETDOWN; | ||
| 743 | goto out; | ||
| 744 | } | ||
| 745 | /* END TEMP */ | ||
| 746 | rdma_destroy_id(ia->ri_id); | ||
| 747 | ia->ri_id = id; | ||
| 748 | } | ||
| 749 | |||
| 750 | rc = rdma_create_qp(ia->ri_id, ia->ri_pd, &ep->rep_attr); | ||
| 751 | if (rc) { | ||
| 752 | dprintk("RPC: %s: rdma_create_qp failed %i\n", | ||
| 753 | __func__, rc); | ||
| 754 | goto out; | ||
| 755 | } | ||
| 756 | |||
| 757 | /* XXX Tavor device performs badly with 2K MTU! */ | ||
| 758 | if (strnicmp(ia->ri_id->device->dma_device->bus->name, "pci", 3) == 0) { | ||
| 759 | struct pci_dev *pcid = to_pci_dev(ia->ri_id->device->dma_device); | ||
| 760 | if (pcid->device == PCI_DEVICE_ID_MELLANOX_TAVOR && | ||
| 761 | (pcid->vendor == PCI_VENDOR_ID_MELLANOX || | ||
| 762 | pcid->vendor == PCI_VENDOR_ID_TOPSPIN)) { | ||
| 763 | struct ib_qp_attr attr = { | ||
| 764 | .path_mtu = IB_MTU_1024 | ||
| 765 | }; | ||
| 766 | rc = ib_modify_qp(ia->ri_id->qp, &attr, IB_QP_PATH_MTU); | ||
| 767 | } | ||
| 768 | } | ||
| 769 | |||
| 770 | /* Theoretically a client initiator_depth > 0 is not needed, | ||
| 771 | * but many peers fail to complete the connection unless they | ||
| 772 | * == responder_resources! */ | ||
| 773 | if (ep->rep_remote_cma.initiator_depth != | ||
| 774 | ep->rep_remote_cma.responder_resources) | ||
| 775 | ep->rep_remote_cma.initiator_depth = | ||
| 776 | ep->rep_remote_cma.responder_resources; | ||
| 777 | |||
| 778 | ep->rep_connected = 0; | ||
| 779 | |||
| 780 | rc = rdma_connect(ia->ri_id, &ep->rep_remote_cma); | ||
| 781 | if (rc) { | ||
| 782 | dprintk("RPC: %s: rdma_connect() failed with %i\n", | ||
| 783 | __func__, rc); | ||
| 784 | goto out; | ||
| 785 | } | ||
| 786 | |||
| 787 | if (reconnect) | ||
| 788 | return 0; | ||
| 789 | |||
| 790 | wait_event_interruptible(ep->rep_connect_wait, ep->rep_connected != 0); | ||
| 791 | |||
| 792 | /* | ||
| 793 | * Check state. A non-peer reject indicates no listener | ||
| 794 | * (ECONNREFUSED), which may be a transient state. All | ||
| 795 | * others indicate a transport condition which has already | ||
| 796 | * undergone a best-effort. | ||
| 797 | */ | ||
| 798 | if (ep->rep_connected == -ECONNREFUSED | ||
| 799 | && ++retry_count <= RDMA_CONNECT_RETRY_MAX) { | ||
| 800 | dprintk("RPC: %s: non-peer_reject, retry\n", __func__); | ||
| 801 | goto retry; | ||
| 802 | } | ||
| 803 | if (ep->rep_connected <= 0) { | ||
| 804 | /* Sometimes, the only way to reliably connect to remote | ||
| 805 | * CMs is to use same nonzero values for ORD and IRD. */ | ||
| 806 | ep->rep_remote_cma.initiator_depth = | ||
| 807 | ep->rep_remote_cma.responder_resources; | ||
| 808 | if (ep->rep_remote_cma.initiator_depth == 0) | ||
| 809 | ++ep->rep_remote_cma.initiator_depth; | ||
| 810 | if (ep->rep_remote_cma.responder_resources == 0) | ||
| 811 | ++ep->rep_remote_cma.responder_resources; | ||
| 812 | if (retry_count++ == 0) | ||
| 813 | goto retry; | ||
| 814 | rc = ep->rep_connected; | ||
| 815 | } else { | ||
| 816 | dprintk("RPC: %s: connected\n", __func__); | ||
| 817 | } | ||
| 818 | |||
| 819 | out: | ||
| 820 | if (rc) | ||
| 821 | ep->rep_connected = rc; | ||
| 822 | return rc; | ||
| 823 | } | ||
| 824 | |||
| 825 | /* | ||
| 826 | * rpcrdma_ep_disconnect | ||
| 827 | * | ||
| 828 | * This is separate from destroy to facilitate the ability | ||
| 829 | * to reconnect without recreating the endpoint. | ||
| 830 | * | ||
| 831 | * This call is not reentrant, and must not be made in parallel | ||
| 832 | * on the same endpoint. | ||
| 833 | */ | ||
| 834 | int | ||
| 835 | rpcrdma_ep_disconnect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia) | ||
| 836 | { | ||
| 837 | int rc; | ||
| 838 | |||
| 839 | rpcrdma_clean_cq(ep->rep_cq); | ||
| 840 | rc = rdma_disconnect(ia->ri_id); | ||
| 841 | if (!rc) { | ||
| 842 | /* returns without wait if not connected */ | ||
| 843 | wait_event_interruptible(ep->rep_connect_wait, | ||
| 844 | ep->rep_connected != 1); | ||
| 845 | dprintk("RPC: %s: after wait, %sconnected\n", __func__, | ||
| 846 | (ep->rep_connected == 1) ? "still " : "dis"); | ||
| 847 | } else { | ||
| 848 | dprintk("RPC: %s: rdma_disconnect %i\n", __func__, rc); | ||
| 849 | ep->rep_connected = rc; | ||
| 850 | } | ||
| 851 | return rc; | ||
| 852 | } | ||
| 853 | |||
| 854 | /* | ||
| 855 | * Initialize buffer memory | ||
| 856 | */ | ||
| 857 | int | ||
| 858 | rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep, | ||
| 859 | struct rpcrdma_ia *ia, struct rpcrdma_create_data_internal *cdata) | ||
| 860 | { | ||
| 861 | char *p; | ||
| 862 | size_t len; | ||
| 863 | int i, rc; | ||
| 864 | |||
| 865 | buf->rb_max_requests = cdata->max_requests; | ||
| 866 | spin_lock_init(&buf->rb_lock); | ||
| 867 | atomic_set(&buf->rb_credits, 1); | ||
| 868 | |||
| 869 | /* Need to allocate: | ||
| 870 | * 1. arrays for send and recv pointers | ||
| 871 | * 2. arrays of struct rpcrdma_req to fill in pointers | ||
| 872 | * 3. array of struct rpcrdma_rep for replies | ||
| 873 | * 4. padding, if any | ||
| 874 | * 5. mw's, if any | ||
| 875 | * Send/recv buffers in req/rep need to be registered | ||
| 876 | */ | ||
| 877 | |||
| 878 | len = buf->rb_max_requests * | ||
| 879 | (sizeof(struct rpcrdma_req *) + sizeof(struct rpcrdma_rep *)); | ||
| 880 | len += cdata->padding; | ||
| 881 | switch (ia->ri_memreg_strategy) { | ||
| 882 | case RPCRDMA_MTHCAFMR: | ||
| 883 | /* TBD we are perhaps overallocating here */ | ||
| 884 | len += (buf->rb_max_requests + 1) * RPCRDMA_MAX_SEGS * | ||
| 885 | sizeof(struct rpcrdma_mw); | ||
| 886 | break; | ||
| 887 | case RPCRDMA_MEMWINDOWS_ASYNC: | ||
| 888 | case RPCRDMA_MEMWINDOWS: | ||
| 889 | len += (buf->rb_max_requests + 1) * RPCRDMA_MAX_SEGS * | ||
| 890 | sizeof(struct rpcrdma_mw); | ||
| 891 | break; | ||
| 892 | default: | ||
| 893 | break; | ||
| 894 | } | ||
| 895 | |||
| 896 | /* allocate 1, 4 and 5 in one shot */ | ||
| 897 | p = kzalloc(len, GFP_KERNEL); | ||
| 898 | if (p == NULL) { | ||
| 899 | dprintk("RPC: %s: req_t/rep_t/pad kzalloc(%zd) failed\n", | ||
| 900 | __func__, len); | ||
| 901 | rc = -ENOMEM; | ||
| 902 | goto out; | ||
| 903 | } | ||
| 904 | buf->rb_pool = p; /* for freeing it later */ | ||
| 905 | |||
| 906 | buf->rb_send_bufs = (struct rpcrdma_req **) p; | ||
| 907 | p = (char *) &buf->rb_send_bufs[buf->rb_max_requests]; | ||
| 908 | buf->rb_recv_bufs = (struct rpcrdma_rep **) p; | ||
| 909 | p = (char *) &buf->rb_recv_bufs[buf->rb_max_requests]; | ||
| 910 | |||
| 911 | /* | ||
| 912 | * Register the zeroed pad buffer, if any. | ||
| 913 | */ | ||
| 914 | if (cdata->padding) { | ||
| 915 | rc = rpcrdma_register_internal(ia, p, cdata->padding, | ||
| 916 | &ep->rep_pad_mr, &ep->rep_pad); | ||
| 917 | if (rc) | ||
| 918 | goto out; | ||
| 919 | } | ||
| 920 | p += cdata->padding; | ||
| 921 | |||
| 922 | /* | ||
| 923 | * Allocate the fmr's, or mw's for mw_bind chunk registration. | ||
| 924 | * We "cycle" the mw's in order to minimize rkey reuse, | ||
| 925 | * and also reduce unbind-to-bind collision. | ||
| 926 | */ | ||
| 927 | INIT_LIST_HEAD(&buf->rb_mws); | ||
| 928 | switch (ia->ri_memreg_strategy) { | ||
| 929 | case RPCRDMA_MTHCAFMR: | ||
| 930 | { | ||
| 931 | struct rpcrdma_mw *r = (struct rpcrdma_mw *)p; | ||
| 932 | struct ib_fmr_attr fa = { | ||
| 933 | RPCRDMA_MAX_DATA_SEGS, 1, PAGE_SHIFT | ||
| 934 | }; | ||
| 935 | /* TBD we are perhaps overallocating here */ | ||
| 936 | for (i = (buf->rb_max_requests+1) * RPCRDMA_MAX_SEGS; i; i--) { | ||
| 937 | r->r.fmr = ib_alloc_fmr(ia->ri_pd, | ||
| 938 | IB_ACCESS_REMOTE_WRITE | IB_ACCESS_REMOTE_READ, | ||
| 939 | &fa); | ||
| 940 | if (IS_ERR(r->r.fmr)) { | ||
| 941 | rc = PTR_ERR(r->r.fmr); | ||
| 942 | dprintk("RPC: %s: ib_alloc_fmr" | ||
| 943 | " failed %i\n", __func__, rc); | ||
| 944 | goto out; | ||
| 945 | } | ||
| 946 | list_add(&r->mw_list, &buf->rb_mws); | ||
| 947 | ++r; | ||
| 948 | } | ||
| 949 | } | ||
| 950 | break; | ||
| 951 | case RPCRDMA_MEMWINDOWS_ASYNC: | ||
| 952 | case RPCRDMA_MEMWINDOWS: | ||
| 953 | { | ||
| 954 | struct rpcrdma_mw *r = (struct rpcrdma_mw *)p; | ||
| 955 | /* Allocate one extra request's worth, for full cycling */ | ||
| 956 | for (i = (buf->rb_max_requests+1) * RPCRDMA_MAX_SEGS; i; i--) { | ||
| 957 | r->r.mw = ib_alloc_mw(ia->ri_pd); | ||
| 958 | if (IS_ERR(r->r.mw)) { | ||
| 959 | rc = PTR_ERR(r->r.mw); | ||
| 960 | dprintk("RPC: %s: ib_alloc_mw" | ||
| 961 | " failed %i\n", __func__, rc); | ||
| 962 | goto out; | ||
| 963 | } | ||
| 964 | list_add(&r->mw_list, &buf->rb_mws); | ||
| 965 | ++r; | ||
| 966 | } | ||
| 967 | } | ||
| 968 | break; | ||
| 969 | default: | ||
| 970 | break; | ||
| 971 | } | ||
| 972 | |||
| 973 | /* | ||
| 974 | * Allocate/init the request/reply buffers. Doing this | ||
| 975 | * using kmalloc for now -- one for each buf. | ||
| 976 | */ | ||
| 977 | for (i = 0; i < buf->rb_max_requests; i++) { | ||
| 978 | struct rpcrdma_req *req; | ||
| 979 | struct rpcrdma_rep *rep; | ||
| 980 | |||
| 981 | len = cdata->inline_wsize + sizeof(struct rpcrdma_req); | ||
| 982 | /* RPC layer requests *double* size + 1K RPC_SLACK_SPACE! */ | ||
| 983 | /* Typical ~2400b, so rounding up saves work later */ | ||
| 984 | if (len < 4096) | ||
| 985 | len = 4096; | ||
| 986 | req = kmalloc(len, GFP_KERNEL); | ||
| 987 | if (req == NULL) { | ||
| 988 | dprintk("RPC: %s: request buffer %d alloc" | ||
| 989 | " failed\n", __func__, i); | ||
| 990 | rc = -ENOMEM; | ||
| 991 | goto out; | ||
| 992 | } | ||
| 993 | memset(req, 0, sizeof(struct rpcrdma_req)); | ||
| 994 | buf->rb_send_bufs[i] = req; | ||
| 995 | buf->rb_send_bufs[i]->rl_buffer = buf; | ||
| 996 | |||
| 997 | rc = rpcrdma_register_internal(ia, req->rl_base, | ||
| 998 | len - offsetof(struct rpcrdma_req, rl_base), | ||
| 999 | &buf->rb_send_bufs[i]->rl_handle, | ||
| 1000 | &buf->rb_send_bufs[i]->rl_iov); | ||
| 1001 | if (rc) | ||
| 1002 | goto out; | ||
| 1003 | |||
| 1004 | buf->rb_send_bufs[i]->rl_size = len-sizeof(struct rpcrdma_req); | ||
| 1005 | |||
| 1006 | len = cdata->inline_rsize + sizeof(struct rpcrdma_rep); | ||
| 1007 | rep = kmalloc(len, GFP_KERNEL); | ||
| 1008 | if (rep == NULL) { | ||
| 1009 | dprintk("RPC: %s: reply buffer %d alloc failed\n", | ||
| 1010 | __func__, i); | ||
| 1011 | rc = -ENOMEM; | ||
| 1012 | goto out; | ||
| 1013 | } | ||
| 1014 | memset(rep, 0, sizeof(struct rpcrdma_rep)); | ||
| 1015 | buf->rb_recv_bufs[i] = rep; | ||
| 1016 | buf->rb_recv_bufs[i]->rr_buffer = buf; | ||
| 1017 | init_waitqueue_head(&rep->rr_unbind); | ||
| 1018 | |||
| 1019 | rc = rpcrdma_register_internal(ia, rep->rr_base, | ||
| 1020 | len - offsetof(struct rpcrdma_rep, rr_base), | ||
| 1021 | &buf->rb_recv_bufs[i]->rr_handle, | ||
| 1022 | &buf->rb_recv_bufs[i]->rr_iov); | ||
| 1023 | if (rc) | ||
| 1024 | goto out; | ||
| 1025 | |||
| 1026 | } | ||
| 1027 | dprintk("RPC: %s: max_requests %d\n", | ||
| 1028 | __func__, buf->rb_max_requests); | ||
| 1029 | /* done */ | ||
| 1030 | return 0; | ||
| 1031 | out: | ||
| 1032 | rpcrdma_buffer_destroy(buf); | ||
| 1033 | return rc; | ||
| 1034 | } | ||
| 1035 | |||
| 1036 | /* | ||
| 1037 | * Unregister and destroy buffer memory. Need to deal with | ||
| 1038 | * partial initialization, so it's callable from failed create. | ||
| 1039 | * Must be called before destroying endpoint, as registrations | ||
| 1040 | * reference it. | ||
| 1041 | */ | ||
| 1042 | void | ||
| 1043 | rpcrdma_buffer_destroy(struct rpcrdma_buffer *buf) | ||
| 1044 | { | ||
| 1045 | int rc, i; | ||
| 1046 | struct rpcrdma_ia *ia = rdmab_to_ia(buf); | ||
| 1047 | |||
| 1048 | /* clean up in reverse order from create | ||
| 1049 | * 1. recv mr memory (mr free, then kfree) | ||
| 1050 | * 1a. bind mw memory | ||
| 1051 | * 2. send mr memory (mr free, then kfree) | ||
| 1052 | * 3. padding (if any) [moved to rpcrdma_ep_destroy] | ||
| 1053 | * 4. arrays | ||
| 1054 | */ | ||
| 1055 | dprintk("RPC: %s: entering\n", __func__); | ||
| 1056 | |||
| 1057 | for (i = 0; i < buf->rb_max_requests; i++) { | ||
| 1058 | if (buf->rb_recv_bufs && buf->rb_recv_bufs[i]) { | ||
| 1059 | rpcrdma_deregister_internal(ia, | ||
| 1060 | buf->rb_recv_bufs[i]->rr_handle, | ||
| 1061 | &buf->rb_recv_bufs[i]->rr_iov); | ||
| 1062 | kfree(buf->rb_recv_bufs[i]); | ||
| 1063 | } | ||
| 1064 | if (buf->rb_send_bufs && buf->rb_send_bufs[i]) { | ||
| 1065 | while (!list_empty(&buf->rb_mws)) { | ||
| 1066 | struct rpcrdma_mw *r; | ||
| 1067 | r = list_entry(buf->rb_mws.next, | ||
| 1068 | struct rpcrdma_mw, mw_list); | ||
| 1069 | list_del(&r->mw_list); | ||
| 1070 | switch (ia->ri_memreg_strategy) { | ||
| 1071 | case RPCRDMA_MTHCAFMR: | ||
| 1072 | rc = ib_dealloc_fmr(r->r.fmr); | ||
| 1073 | if (rc) | ||
| 1074 | dprintk("RPC: %s:" | ||
| 1075 | " ib_dealloc_fmr" | ||
| 1076 | " failed %i\n", | ||
| 1077 | __func__, rc); | ||
| 1078 | break; | ||
| 1079 | case RPCRDMA_MEMWINDOWS_ASYNC: | ||
| 1080 | case RPCRDMA_MEMWINDOWS: | ||
| 1081 | rc = ib_dealloc_mw(r->r.mw); | ||
| 1082 | if (rc) | ||
| 1083 | dprintk("RPC: %s:" | ||
| 1084 | " ib_dealloc_mw" | ||
| 1085 | " failed %i\n", | ||
| 1086 | __func__, rc); | ||
| 1087 | break; | ||
| 1088 | default: | ||
| 1089 | break; | ||
| 1090 | } | ||
| 1091 | } | ||
| 1092 | rpcrdma_deregister_internal(ia, | ||
| 1093 | buf->rb_send_bufs[i]->rl_handle, | ||
| 1094 | &buf->rb_send_bufs[i]->rl_iov); | ||
| 1095 | kfree(buf->rb_send_bufs[i]); | ||
| 1096 | } | ||
| 1097 | } | ||
| 1098 | |||
| 1099 | kfree(buf->rb_pool); | ||
| 1100 | } | ||
| 1101 | |||
| 1102 | /* | ||
| 1103 | * Get a set of request/reply buffers. | ||
| 1104 | * | ||
| 1105 | * Reply buffer (if needed) is attached to send buffer upon return. | ||
| 1106 | * Rule: | ||
| 1107 | * rb_send_index and rb_recv_index MUST always be pointing to the | ||
| 1108 | * *next* available buffer (non-NULL). They are incremented after | ||
| 1109 | * removing buffers, and decremented *before* returning them. | ||
| 1110 | */ | ||
| 1111 | struct rpcrdma_req * | ||
| 1112 | rpcrdma_buffer_get(struct rpcrdma_buffer *buffers) | ||
| 1113 | { | ||
| 1114 | struct rpcrdma_req *req; | ||
| 1115 | unsigned long flags; | ||
| 1116 | |||
| 1117 | spin_lock_irqsave(&buffers->rb_lock, flags); | ||
| 1118 | if (buffers->rb_send_index == buffers->rb_max_requests) { | ||
| 1119 | spin_unlock_irqrestore(&buffers->rb_lock, flags); | ||
| 1120 | dprintk("RPC: %s: out of request buffers\n", __func__); | ||
| 1121 | return ((struct rpcrdma_req *)NULL); | ||
| 1122 | } | ||
| 1123 | |||
| 1124 | req = buffers->rb_send_bufs[buffers->rb_send_index]; | ||
| 1125 | if (buffers->rb_send_index < buffers->rb_recv_index) { | ||
| 1126 | dprintk("RPC: %s: %d extra receives outstanding (ok)\n", | ||
| 1127 | __func__, | ||
| 1128 | buffers->rb_recv_index - buffers->rb_send_index); | ||
| 1129 | req->rl_reply = NULL; | ||
| 1130 | } else { | ||
| 1131 | req->rl_reply = buffers->rb_recv_bufs[buffers->rb_recv_index]; | ||
| 1132 | buffers->rb_recv_bufs[buffers->rb_recv_index++] = NULL; | ||
| 1133 | } | ||
| 1134 | buffers->rb_send_bufs[buffers->rb_send_index++] = NULL; | ||
| 1135 | if (!list_empty(&buffers->rb_mws)) { | ||
| 1136 | int i = RPCRDMA_MAX_SEGS - 1; | ||
| 1137 | do { | ||
| 1138 | struct rpcrdma_mw *r; | ||
| 1139 | r = list_entry(buffers->rb_mws.next, | ||
| 1140 | struct rpcrdma_mw, mw_list); | ||
| 1141 | list_del(&r->mw_list); | ||
| 1142 | req->rl_segments[i].mr_chunk.rl_mw = r; | ||
| 1143 | } while (--i >= 0); | ||
| 1144 | } | ||
| 1145 | spin_unlock_irqrestore(&buffers->rb_lock, flags); | ||
| 1146 | return req; | ||
| 1147 | } | ||
| 1148 | |||
| 1149 | /* | ||
| 1150 | * Put request/reply buffers back into pool. | ||
| 1151 | * Pre-decrement counter/array index. | ||
| 1152 | */ | ||
| 1153 | void | ||
| 1154 | rpcrdma_buffer_put(struct rpcrdma_req *req) | ||
| 1155 | { | ||
| 1156 | struct rpcrdma_buffer *buffers = req->rl_buffer; | ||
| 1157 | struct rpcrdma_ia *ia = rdmab_to_ia(buffers); | ||
| 1158 | int i; | ||
| 1159 | unsigned long flags; | ||
| 1160 | |||
| 1161 | BUG_ON(req->rl_nchunks != 0); | ||
| 1162 | spin_lock_irqsave(&buffers->rb_lock, flags); | ||
| 1163 | buffers->rb_send_bufs[--buffers->rb_send_index] = req; | ||
| 1164 | req->rl_niovs = 0; | ||
| 1165 | if (req->rl_reply) { | ||
| 1166 | buffers->rb_recv_bufs[--buffers->rb_recv_index] = req->rl_reply; | ||
| 1167 | init_waitqueue_head(&req->rl_reply->rr_unbind); | ||
| 1168 | req->rl_reply->rr_func = NULL; | ||
| 1169 | req->rl_reply = NULL; | ||
| 1170 | } | ||
| 1171 | switch (ia->ri_memreg_strategy) { | ||
| 1172 | case RPCRDMA_MTHCAFMR: | ||
| 1173 | case RPCRDMA_MEMWINDOWS_ASYNC: | ||
| 1174 | case RPCRDMA_MEMWINDOWS: | ||
| 1175 | /* | ||
| 1176 | * Cycle mw's back in reverse order, and "spin" them. | ||
| 1177 | * This delays and scrambles reuse as much as possible. | ||
| 1178 | */ | ||
| 1179 | i = 1; | ||
| 1180 | do { | ||
| 1181 | struct rpcrdma_mw **mw; | ||
| 1182 | mw = &req->rl_segments[i].mr_chunk.rl_mw; | ||
| 1183 | list_add_tail(&(*mw)->mw_list, &buffers->rb_mws); | ||
| 1184 | *mw = NULL; | ||
| 1185 | } while (++i < RPCRDMA_MAX_SEGS); | ||
| 1186 | list_add_tail(&req->rl_segments[0].mr_chunk.rl_mw->mw_list, | ||
| 1187 | &buffers->rb_mws); | ||
| 1188 | req->rl_segments[0].mr_chunk.rl_mw = NULL; | ||
| 1189 | break; | ||
| 1190 | default: | ||
| 1191 | break; | ||
| 1192 | } | ||
| 1193 | spin_unlock_irqrestore(&buffers->rb_lock, flags); | ||
| 1194 | } | ||
| 1195 | |||
| 1196 | /* | ||
| 1197 | * Recover reply buffers from pool. | ||
| 1198 | * This happens when recovering from error conditions. | ||
| 1199 | * Post-increment counter/array index. | ||
| 1200 | */ | ||
| 1201 | void | ||
| 1202 | rpcrdma_recv_buffer_get(struct rpcrdma_req *req) | ||
| 1203 | { | ||
| 1204 | struct rpcrdma_buffer *buffers = req->rl_buffer; | ||
| 1205 | unsigned long flags; | ||
| 1206 | |||
| 1207 | if (req->rl_iov.length == 0) /* special case xprt_rdma_allocate() */ | ||
| 1208 | buffers = ((struct rpcrdma_req *) buffers)->rl_buffer; | ||
| 1209 | spin_lock_irqsave(&buffers->rb_lock, flags); | ||
| 1210 | if (buffers->rb_recv_index < buffers->rb_max_requests) { | ||
| 1211 | req->rl_reply = buffers->rb_recv_bufs[buffers->rb_recv_index]; | ||
| 1212 | buffers->rb_recv_bufs[buffers->rb_recv_index++] = NULL; | ||
| 1213 | } | ||
| 1214 | spin_unlock_irqrestore(&buffers->rb_lock, flags); | ||
| 1215 | } | ||
| 1216 | |||
| 1217 | /* | ||
| 1218 | * Put reply buffers back into pool when not attached to | ||
| 1219 | * request. This happens in error conditions, and when | ||
| 1220 | * aborting unbinds. Pre-decrement counter/array index. | ||
| 1221 | */ | ||
| 1222 | void | ||
| 1223 | rpcrdma_recv_buffer_put(struct rpcrdma_rep *rep) | ||
| 1224 | { | ||
| 1225 | struct rpcrdma_buffer *buffers = rep->rr_buffer; | ||
| 1226 | unsigned long flags; | ||
| 1227 | |||
| 1228 | rep->rr_func = NULL; | ||
| 1229 | spin_lock_irqsave(&buffers->rb_lock, flags); | ||
| 1230 | buffers->rb_recv_bufs[--buffers->rb_recv_index] = rep; | ||
| 1231 | spin_unlock_irqrestore(&buffers->rb_lock, flags); | ||
| 1232 | } | ||
| 1233 | |||
| 1234 | /* | ||
| 1235 | * Wrappers for internal-use kmalloc memory registration, used by buffer code. | ||
| 1236 | */ | ||
| 1237 | |||
| 1238 | int | ||
| 1239 | rpcrdma_register_internal(struct rpcrdma_ia *ia, void *va, int len, | ||
| 1240 | struct ib_mr **mrp, struct ib_sge *iov) | ||
| 1241 | { | ||
| 1242 | struct ib_phys_buf ipb; | ||
| 1243 | struct ib_mr *mr; | ||
| 1244 | int rc; | ||
| 1245 | |||
| 1246 | /* | ||
| 1247 | * All memory passed here was kmalloc'ed, therefore phys-contiguous. | ||
| 1248 | */ | ||
| 1249 | iov->addr = ib_dma_map_single(ia->ri_id->device, | ||
| 1250 | va, len, DMA_BIDIRECTIONAL); | ||
| 1251 | iov->length = len; | ||
| 1252 | |||
| 1253 | if (ia->ri_bind_mem != NULL) { | ||
| 1254 | *mrp = NULL; | ||
| 1255 | iov->lkey = ia->ri_bind_mem->lkey; | ||
| 1256 | return 0; | ||
| 1257 | } | ||
| 1258 | |||
| 1259 | ipb.addr = iov->addr; | ||
| 1260 | ipb.size = iov->length; | ||
| 1261 | mr = ib_reg_phys_mr(ia->ri_pd, &ipb, 1, | ||
| 1262 | IB_ACCESS_LOCAL_WRITE, &iov->addr); | ||
| 1263 | |||
| 1264 | dprintk("RPC: %s: phys convert: 0x%llx " | ||
| 1265 | "registered 0x%llx length %d\n", | ||
| 1266 | __func__, ipb.addr, iov->addr, len); | ||
| 1267 | |||
| 1268 | if (IS_ERR(mr)) { | ||
| 1269 | *mrp = NULL; | ||
| 1270 | rc = PTR_ERR(mr); | ||
| 1271 | dprintk("RPC: %s: failed with %i\n", __func__, rc); | ||
| 1272 | } else { | ||
| 1273 | *mrp = mr; | ||
| 1274 | iov->lkey = mr->lkey; | ||
| 1275 | rc = 0; | ||
| 1276 | } | ||
| 1277 | |||
| 1278 | return rc; | ||
| 1279 | } | ||
| 1280 | |||
| 1281 | int | ||
| 1282 | rpcrdma_deregister_internal(struct rpcrdma_ia *ia, | ||
| 1283 | struct ib_mr *mr, struct ib_sge *iov) | ||
| 1284 | { | ||
| 1285 | int rc; | ||
| 1286 | |||
| 1287 | ib_dma_unmap_single(ia->ri_id->device, | ||
| 1288 | iov->addr, iov->length, DMA_BIDIRECTIONAL); | ||
| 1289 | |||
| 1290 | if (NULL == mr) | ||
| 1291 | return 0; | ||
| 1292 | |||
| 1293 | rc = ib_dereg_mr(mr); | ||
| 1294 | if (rc) | ||
| 1295 | dprintk("RPC: %s: ib_dereg_mr failed %i\n", __func__, rc); | ||
| 1296 | return rc; | ||
| 1297 | } | ||
| 1298 | |||
| 1299 | /* | ||
| 1300 | * Wrappers for chunk registration, shared by read/write chunk code. | ||
| 1301 | */ | ||
| 1302 | |||
| 1303 | static void | ||
| 1304 | rpcrdma_map_one(struct rpcrdma_ia *ia, struct rpcrdma_mr_seg *seg, int writing) | ||
| 1305 | { | ||
| 1306 | seg->mr_dir = writing ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | ||
| 1307 | seg->mr_dmalen = seg->mr_len; | ||
| 1308 | if (seg->mr_page) | ||
| 1309 | seg->mr_dma = ib_dma_map_page(ia->ri_id->device, | ||
| 1310 | seg->mr_page, offset_in_page(seg->mr_offset), | ||
| 1311 | seg->mr_dmalen, seg->mr_dir); | ||
| 1312 | else | ||
| 1313 | seg->mr_dma = ib_dma_map_single(ia->ri_id->device, | ||
| 1314 | seg->mr_offset, | ||
| 1315 | seg->mr_dmalen, seg->mr_dir); | ||
| 1316 | } | ||
| 1317 | |||
| 1318 | static void | ||
| 1319 | rpcrdma_unmap_one(struct rpcrdma_ia *ia, struct rpcrdma_mr_seg *seg) | ||
| 1320 | { | ||
| 1321 | if (seg->mr_page) | ||
| 1322 | ib_dma_unmap_page(ia->ri_id->device, | ||
| 1323 | seg->mr_dma, seg->mr_dmalen, seg->mr_dir); | ||
| 1324 | else | ||
| 1325 | ib_dma_unmap_single(ia->ri_id->device, | ||
| 1326 | seg->mr_dma, seg->mr_dmalen, seg->mr_dir); | ||
| 1327 | } | ||
| 1328 | |||
| 1329 | int | ||
| 1330 | rpcrdma_register_external(struct rpcrdma_mr_seg *seg, | ||
| 1331 | int nsegs, int writing, struct rpcrdma_xprt *r_xprt) | ||
| 1332 | { | ||
| 1333 | struct rpcrdma_ia *ia = &r_xprt->rx_ia; | ||
| 1334 | int mem_priv = (writing ? IB_ACCESS_REMOTE_WRITE : | ||
| 1335 | IB_ACCESS_REMOTE_READ); | ||
| 1336 | struct rpcrdma_mr_seg *seg1 = seg; | ||
| 1337 | int i; | ||
| 1338 | int rc = 0; | ||
| 1339 | |||
| 1340 | switch (ia->ri_memreg_strategy) { | ||
| 1341 | |||
| 1342 | #if RPCRDMA_PERSISTENT_REGISTRATION | ||
| 1343 | case RPCRDMA_ALLPHYSICAL: | ||
| 1344 | rpcrdma_map_one(ia, seg, writing); | ||
| 1345 | seg->mr_rkey = ia->ri_bind_mem->rkey; | ||
| 1346 | seg->mr_base = seg->mr_dma; | ||
| 1347 | seg->mr_nsegs = 1; | ||
| 1348 | nsegs = 1; | ||
| 1349 | break; | ||
| 1350 | #endif | ||
| 1351 | |||
| 1352 | /* Registration using fast memory registration */ | ||
| 1353 | case RPCRDMA_MTHCAFMR: | ||
| 1354 | { | ||
| 1355 | u64 physaddrs[RPCRDMA_MAX_DATA_SEGS]; | ||
| 1356 | int len, pageoff = offset_in_page(seg->mr_offset); | ||
| 1357 | seg1->mr_offset -= pageoff; /* start of page */ | ||
| 1358 | seg1->mr_len += pageoff; | ||
| 1359 | len = -pageoff; | ||
| 1360 | if (nsegs > RPCRDMA_MAX_DATA_SEGS) | ||
| 1361 | nsegs = RPCRDMA_MAX_DATA_SEGS; | ||
| 1362 | for (i = 0; i < nsegs;) { | ||
| 1363 | rpcrdma_map_one(ia, seg, writing); | ||
| 1364 | physaddrs[i] = seg->mr_dma; | ||
| 1365 | len += seg->mr_len; | ||
| 1366 | ++seg; | ||
| 1367 | ++i; | ||
| 1368 | /* Check for holes */ | ||
| 1369 | if ((i < nsegs && offset_in_page(seg->mr_offset)) || | ||
| 1370 | offset_in_page((seg-1)->mr_offset+(seg-1)->mr_len)) | ||
| 1371 | break; | ||
| 1372 | } | ||
| 1373 | nsegs = i; | ||
| 1374 | rc = ib_map_phys_fmr(seg1->mr_chunk.rl_mw->r.fmr, | ||
| 1375 | physaddrs, nsegs, seg1->mr_dma); | ||
| 1376 | if (rc) { | ||
| 1377 | dprintk("RPC: %s: failed ib_map_phys_fmr " | ||
| 1378 | "%u@0x%llx+%i (%d)... status %i\n", __func__, | ||
| 1379 | len, (unsigned long long)seg1->mr_dma, | ||
| 1380 | pageoff, nsegs, rc); | ||
| 1381 | while (nsegs--) | ||
| 1382 | rpcrdma_unmap_one(ia, --seg); | ||
| 1383 | } else { | ||
| 1384 | seg1->mr_rkey = seg1->mr_chunk.rl_mw->r.fmr->rkey; | ||
| 1385 | seg1->mr_base = seg1->mr_dma + pageoff; | ||
| 1386 | seg1->mr_nsegs = nsegs; | ||
| 1387 | seg1->mr_len = len; | ||
| 1388 | } | ||
| 1389 | } | ||
| 1390 | break; | ||
| 1391 | |||
| 1392 | /* Registration using memory windows */ | ||
| 1393 | case RPCRDMA_MEMWINDOWS_ASYNC: | ||
| 1394 | case RPCRDMA_MEMWINDOWS: | ||
| 1395 | { | ||
| 1396 | struct ib_mw_bind param; | ||
| 1397 | rpcrdma_map_one(ia, seg, writing); | ||
| 1398 | param.mr = ia->ri_bind_mem; | ||
| 1399 | param.wr_id = 0ULL; /* no send cookie */ | ||
| 1400 | param.addr = seg->mr_dma; | ||
| 1401 | param.length = seg->mr_len; | ||
| 1402 | param.send_flags = 0; | ||
| 1403 | param.mw_access_flags = mem_priv; | ||
| 1404 | |||
| 1405 | DECR_CQCOUNT(&r_xprt->rx_ep); | ||
| 1406 | rc = ib_bind_mw(ia->ri_id->qp, | ||
| 1407 | seg->mr_chunk.rl_mw->r.mw, ¶m); | ||
| 1408 | if (rc) { | ||
| 1409 | dprintk("RPC: %s: failed ib_bind_mw " | ||
| 1410 | "%u@0x%llx status %i\n", | ||
| 1411 | __func__, seg->mr_len, | ||
| 1412 | (unsigned long long)seg->mr_dma, rc); | ||
| 1413 | rpcrdma_unmap_one(ia, seg); | ||
| 1414 | } else { | ||
| 1415 | seg->mr_rkey = seg->mr_chunk.rl_mw->r.mw->rkey; | ||
| 1416 | seg->mr_base = param.addr; | ||
| 1417 | seg->mr_nsegs = 1; | ||
| 1418 | nsegs = 1; | ||
| 1419 | } | ||
| 1420 | } | ||
| 1421 | break; | ||
| 1422 | |||
| 1423 | /* Default registration each time */ | ||
| 1424 | default: | ||
| 1425 | { | ||
| 1426 | struct ib_phys_buf ipb[RPCRDMA_MAX_DATA_SEGS]; | ||
| 1427 | int len = 0; | ||
| 1428 | if (nsegs > RPCRDMA_MAX_DATA_SEGS) | ||
| 1429 | nsegs = RPCRDMA_MAX_DATA_SEGS; | ||
| 1430 | for (i = 0; i < nsegs;) { | ||
| 1431 | rpcrdma_map_one(ia, seg, writing); | ||
| 1432 | ipb[i].addr = seg->mr_dma; | ||
| 1433 | ipb[i].size = seg->mr_len; | ||
| 1434 | len += seg->mr_len; | ||
| 1435 | ++seg; | ||
| 1436 | ++i; | ||
| 1437 | /* Check for holes */ | ||
| 1438 | if ((i < nsegs && offset_in_page(seg->mr_offset)) || | ||
| 1439 | offset_in_page((seg-1)->mr_offset+(seg-1)->mr_len)) | ||
| 1440 | break; | ||
| 1441 | } | ||
| 1442 | nsegs = i; | ||
| 1443 | seg1->mr_base = seg1->mr_dma; | ||
| 1444 | seg1->mr_chunk.rl_mr = ib_reg_phys_mr(ia->ri_pd, | ||
| 1445 | ipb, nsegs, mem_priv, &seg1->mr_base); | ||
| 1446 | if (IS_ERR(seg1->mr_chunk.rl_mr)) { | ||
| 1447 | rc = PTR_ERR(seg1->mr_chunk.rl_mr); | ||
| 1448 | dprintk("RPC: %s: failed ib_reg_phys_mr " | ||
| 1449 | "%u@0x%llx (%d)... status %i\n", | ||
| 1450 | __func__, len, | ||
| 1451 | (unsigned long long)seg1->mr_dma, nsegs, rc); | ||
| 1452 | while (nsegs--) | ||
| 1453 | rpcrdma_unmap_one(ia, --seg); | ||
| 1454 | } else { | ||
| 1455 | seg1->mr_rkey = seg1->mr_chunk.rl_mr->rkey; | ||
| 1456 | seg1->mr_nsegs = nsegs; | ||
| 1457 | seg1->mr_len = len; | ||
| 1458 | } | ||
| 1459 | } | ||
| 1460 | break; | ||
| 1461 | } | ||
| 1462 | if (rc) | ||
| 1463 | return -1; | ||
| 1464 | |||
| 1465 | return nsegs; | ||
| 1466 | } | ||
| 1467 | |||
| 1468 | int | ||
| 1469 | rpcrdma_deregister_external(struct rpcrdma_mr_seg *seg, | ||
| 1470 | struct rpcrdma_xprt *r_xprt, void *r) | ||
| 1471 | { | ||
| 1472 | struct rpcrdma_ia *ia = &r_xprt->rx_ia; | ||
| 1473 | struct rpcrdma_mr_seg *seg1 = seg; | ||
| 1474 | int nsegs = seg->mr_nsegs, rc; | ||
| 1475 | |||
| 1476 | switch (ia->ri_memreg_strategy) { | ||
| 1477 | |||
| 1478 | #if RPCRDMA_PERSISTENT_REGISTRATION | ||
| 1479 | case RPCRDMA_ALLPHYSICAL: | ||
| 1480 | BUG_ON(nsegs != 1); | ||
| 1481 | rpcrdma_unmap_one(ia, seg); | ||
| 1482 | rc = 0; | ||
| 1483 | break; | ||
| 1484 | #endif | ||
| 1485 | |||
| 1486 | case RPCRDMA_MTHCAFMR: | ||
| 1487 | { | ||
| 1488 | LIST_HEAD(l); | ||
| 1489 | list_add(&seg->mr_chunk.rl_mw->r.fmr->list, &l); | ||
| 1490 | rc = ib_unmap_fmr(&l); | ||
| 1491 | while (seg1->mr_nsegs--) | ||
| 1492 | rpcrdma_unmap_one(ia, seg++); | ||
| 1493 | } | ||
| 1494 | if (rc) | ||
| 1495 | dprintk("RPC: %s: failed ib_unmap_fmr," | ||
| 1496 | " status %i\n", __func__, rc); | ||
| 1497 | break; | ||
| 1498 | |||
| 1499 | case RPCRDMA_MEMWINDOWS_ASYNC: | ||
| 1500 | case RPCRDMA_MEMWINDOWS: | ||
| 1501 | { | ||
| 1502 | struct ib_mw_bind param; | ||
| 1503 | BUG_ON(nsegs != 1); | ||
| 1504 | param.mr = ia->ri_bind_mem; | ||
| 1505 | param.addr = 0ULL; /* unbind */ | ||
| 1506 | param.length = 0; | ||
| 1507 | param.mw_access_flags = 0; | ||
| 1508 | if (r) { | ||
| 1509 | param.wr_id = (u64) (unsigned long) r; | ||
| 1510 | param.send_flags = IB_SEND_SIGNALED; | ||
| 1511 | INIT_CQCOUNT(&r_xprt->rx_ep); | ||
| 1512 | } else { | ||
| 1513 | param.wr_id = 0ULL; | ||
| 1514 | param.send_flags = 0; | ||
| 1515 | DECR_CQCOUNT(&r_xprt->rx_ep); | ||
| 1516 | } | ||
| 1517 | rc = ib_bind_mw(ia->ri_id->qp, | ||
| 1518 | seg->mr_chunk.rl_mw->r.mw, ¶m); | ||
| 1519 | rpcrdma_unmap_one(ia, seg); | ||
| 1520 | } | ||
| 1521 | if (rc) | ||
| 1522 | dprintk("RPC: %s: failed ib_(un)bind_mw," | ||
| 1523 | " status %i\n", __func__, rc); | ||
| 1524 | else | ||
| 1525 | r = NULL; /* will upcall on completion */ | ||
| 1526 | break; | ||
| 1527 | |||
| 1528 | default: | ||
| 1529 | rc = ib_dereg_mr(seg1->mr_chunk.rl_mr); | ||
| 1530 | seg1->mr_chunk.rl_mr = NULL; | ||
| 1531 | while (seg1->mr_nsegs--) | ||
| 1532 | rpcrdma_unmap_one(ia, seg++); | ||
| 1533 | if (rc) | ||
| 1534 | dprintk("RPC: %s: failed ib_dereg_mr," | ||
| 1535 | " status %i\n", __func__, rc); | ||
| 1536 | break; | ||
| 1537 | } | ||
| 1538 | if (r) { | ||
| 1539 | struct rpcrdma_rep *rep = r; | ||
| 1540 | void (*func)(struct rpcrdma_rep *) = rep->rr_func; | ||
| 1541 | rep->rr_func = NULL; | ||
| 1542 | func(rep); /* dereg done, callback now */ | ||
| 1543 | } | ||
| 1544 | return nsegs; | ||
| 1545 | } | ||
| 1546 | |||
| 1547 | /* | ||
| 1548 | * Prepost any receive buffer, then post send. | ||
| 1549 | * | ||
| 1550 | * Receive buffer is donated to hardware, reclaimed upon recv completion. | ||
| 1551 | */ | ||
| 1552 | int | ||
| 1553 | rpcrdma_ep_post(struct rpcrdma_ia *ia, | ||
| 1554 | struct rpcrdma_ep *ep, | ||
| 1555 | struct rpcrdma_req *req) | ||
| 1556 | { | ||
| 1557 | struct ib_send_wr send_wr, *send_wr_fail; | ||
| 1558 | struct rpcrdma_rep *rep = req->rl_reply; | ||
| 1559 | int rc; | ||
| 1560 | |||
| 1561 | if (rep) { | ||
| 1562 | rc = rpcrdma_ep_post_recv(ia, ep, rep); | ||
| 1563 | if (rc) | ||
| 1564 | goto out; | ||
| 1565 | req->rl_reply = NULL; | ||
| 1566 | } | ||
| 1567 | |||
| 1568 | send_wr.next = NULL; | ||
| 1569 | send_wr.wr_id = 0ULL; /* no send cookie */ | ||
| 1570 | send_wr.sg_list = req->rl_send_iov; | ||
| 1571 | send_wr.num_sge = req->rl_niovs; | ||
| 1572 | send_wr.opcode = IB_WR_SEND; | ||
| 1573 | send_wr.imm_data = 0; | ||
| 1574 | if (send_wr.num_sge == 4) /* no need to sync any pad (constant) */ | ||
| 1575 | ib_dma_sync_single_for_device(ia->ri_id->device, | ||
| 1576 | req->rl_send_iov[3].addr, req->rl_send_iov[3].length, | ||
| 1577 | DMA_TO_DEVICE); | ||
| 1578 | ib_dma_sync_single_for_device(ia->ri_id->device, | ||
| 1579 | req->rl_send_iov[1].addr, req->rl_send_iov[1].length, | ||
| 1580 | DMA_TO_DEVICE); | ||
| 1581 | ib_dma_sync_single_for_device(ia->ri_id->device, | ||
| 1582 | req->rl_send_iov[0].addr, req->rl_send_iov[0].length, | ||
| 1583 | DMA_TO_DEVICE); | ||
| 1584 | |||
| 1585 | if (DECR_CQCOUNT(ep) > 0) | ||
| 1586 | send_wr.send_flags = 0; | ||
| 1587 | else { /* Provider must take a send completion every now and then */ | ||
| 1588 | INIT_CQCOUNT(ep); | ||
| 1589 | send_wr.send_flags = IB_SEND_SIGNALED; | ||
| 1590 | } | ||
| 1591 | |||
| 1592 | rc = ib_post_send(ia->ri_id->qp, &send_wr, &send_wr_fail); | ||
| 1593 | if (rc) | ||
| 1594 | dprintk("RPC: %s: ib_post_send returned %i\n", __func__, | ||
| 1595 | rc); | ||
| 1596 | out: | ||
| 1597 | return rc; | ||
| 1598 | } | ||
| 1599 | |||
| 1600 | /* | ||
| 1601 | * (Re)post a receive buffer. | ||
| 1602 | */ | ||
| 1603 | int | ||
| 1604 | rpcrdma_ep_post_recv(struct rpcrdma_ia *ia, | ||
| 1605 | struct rpcrdma_ep *ep, | ||
| 1606 | struct rpcrdma_rep *rep) | ||
| 1607 | { | ||
| 1608 | struct ib_recv_wr recv_wr, *recv_wr_fail; | ||
| 1609 | int rc; | ||
| 1610 | |||
| 1611 | recv_wr.next = NULL; | ||
| 1612 | recv_wr.wr_id = (u64) (unsigned long) rep; | ||
| 1613 | recv_wr.sg_list = &rep->rr_iov; | ||
| 1614 | recv_wr.num_sge = 1; | ||
| 1615 | |||
| 1616 | ib_dma_sync_single_for_cpu(ia->ri_id->device, | ||
| 1617 | rep->rr_iov.addr, rep->rr_iov.length, DMA_BIDIRECTIONAL); | ||
| 1618 | |||
| 1619 | DECR_CQCOUNT(ep); | ||
| 1620 | rc = ib_post_recv(ia->ri_id->qp, &recv_wr, &recv_wr_fail); | ||
| 1621 | |||
| 1622 | if (rc) | ||
| 1623 | dprintk("RPC: %s: ib_post_recv returned %i\n", __func__, | ||
| 1624 | rc); | ||
| 1625 | return rc; | ||
| 1626 | } | ||
diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h new file mode 100644 index 000000000000..2427822f8bd4 --- /dev/null +++ b/net/sunrpc/xprtrdma/xprt_rdma.h | |||
| @@ -0,0 +1,330 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved. | ||
| 3 | * | ||
| 4 | * This software is available to you under a choice of one of two | ||
| 5 | * licenses. You may choose to be licensed under the terms of the GNU | ||
| 6 | * General Public License (GPL) Version 2, available from the file | ||
| 7 | * COPYING in the main directory of this source tree, or the BSD-type | ||
| 8 | * license below: | ||
| 9 | * | ||
| 10 | * Redistribution and use in source and binary forms, with or without | ||
| 11 | * modification, are permitted provided that the following conditions | ||
| 12 | * are met: | ||
| 13 | * | ||
| 14 | * Redistributions of source code must retain the above copyright | ||
| 15 | * notice, this list of conditions and the following disclaimer. | ||
| 16 | * | ||
| 17 | * Redistributions in binary form must reproduce the above | ||
| 18 | * copyright notice, this list of conditions and the following | ||
| 19 | * disclaimer in the documentation and/or other materials provided | ||
| 20 | * with the distribution. | ||
| 21 | * | ||
| 22 | * Neither the name of the Network Appliance, Inc. nor the names of | ||
| 23 | * its contributors may be used to endorse or promote products | ||
| 24 | * derived from this software without specific prior written | ||
| 25 | * permission. | ||
| 26 | * | ||
| 27 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| 28 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| 29 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
| 30 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| 31 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
| 32 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
| 33 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
| 34 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
| 35 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 36 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
| 37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 38 | */ | ||
| 39 | |||
| 40 | #ifndef _LINUX_SUNRPC_XPRT_RDMA_H | ||
| 41 | #define _LINUX_SUNRPC_XPRT_RDMA_H | ||
| 42 | |||
| 43 | #include <linux/wait.h> /* wait_queue_head_t, etc */ | ||
| 44 | #include <linux/spinlock.h> /* spinlock_t, etc */ | ||
| 45 | #include <asm/atomic.h> /* atomic_t, etc */ | ||
| 46 | |||
| 47 | #include <rdma/rdma_cm.h> /* RDMA connection api */ | ||
| 48 | #include <rdma/ib_verbs.h> /* RDMA verbs api */ | ||
| 49 | |||
| 50 | #include <linux/sunrpc/clnt.h> /* rpc_xprt */ | ||
| 51 | #include <linux/sunrpc/rpc_rdma.h> /* RPC/RDMA protocol */ | ||
| 52 | #include <linux/sunrpc/xprtrdma.h> /* xprt parameters */ | ||
| 53 | |||
| 54 | /* | ||
| 55 | * Interface Adapter -- one per transport instance | ||
| 56 | */ | ||
| 57 | struct rpcrdma_ia { | ||
| 58 | struct rdma_cm_id *ri_id; | ||
| 59 | struct ib_pd *ri_pd; | ||
| 60 | struct ib_mr *ri_bind_mem; | ||
| 61 | struct completion ri_done; | ||
| 62 | int ri_async_rc; | ||
| 63 | enum rpcrdma_memreg ri_memreg_strategy; | ||
| 64 | }; | ||
| 65 | |||
| 66 | /* | ||
| 67 | * RDMA Endpoint -- one per transport instance | ||
| 68 | */ | ||
| 69 | |||
| 70 | struct rpcrdma_ep { | ||
| 71 | atomic_t rep_cqcount; | ||
| 72 | int rep_cqinit; | ||
| 73 | int rep_connected; | ||
| 74 | struct rpcrdma_ia *rep_ia; | ||
| 75 | struct ib_cq *rep_cq; | ||
| 76 | struct ib_qp_init_attr rep_attr; | ||
| 77 | wait_queue_head_t rep_connect_wait; | ||
| 78 | struct ib_sge rep_pad; /* holds zeroed pad */ | ||
| 79 | struct ib_mr *rep_pad_mr; /* holds zeroed pad */ | ||
| 80 | void (*rep_func)(struct rpcrdma_ep *); | ||
| 81 | struct rpc_xprt *rep_xprt; /* for rep_func */ | ||
| 82 | struct rdma_conn_param rep_remote_cma; | ||
| 83 | struct sockaddr_storage rep_remote_addr; | ||
| 84 | }; | ||
| 85 | |||
| 86 | #define INIT_CQCOUNT(ep) atomic_set(&(ep)->rep_cqcount, (ep)->rep_cqinit) | ||
| 87 | #define DECR_CQCOUNT(ep) atomic_sub_return(1, &(ep)->rep_cqcount) | ||
| 88 | |||
| 89 | /* | ||
| 90 | * struct rpcrdma_rep -- this structure encapsulates state required to recv | ||
| 91 | * and complete a reply, asychronously. It needs several pieces of | ||
| 92 | * state: | ||
| 93 | * o recv buffer (posted to provider) | ||
| 94 | * o ib_sge (also donated to provider) | ||
| 95 | * o status of reply (length, success or not) | ||
| 96 | * o bookkeeping state to get run by tasklet (list, etc) | ||
| 97 | * | ||
| 98 | * These are allocated during initialization, per-transport instance; | ||
| 99 | * however, the tasklet execution list itself is global, as it should | ||
| 100 | * always be pretty short. | ||
| 101 | * | ||
| 102 | * N of these are associated with a transport instance, and stored in | ||
| 103 | * struct rpcrdma_buffer. N is the max number of outstanding requests. | ||
| 104 | */ | ||
| 105 | |||
| 106 | /* temporary static scatter/gather max */ | ||
| 107 | #define RPCRDMA_MAX_DATA_SEGS (8) /* max scatter/gather */ | ||
| 108 | #define RPCRDMA_MAX_SEGS (RPCRDMA_MAX_DATA_SEGS + 2) /* head+tail = 2 */ | ||
| 109 | #define MAX_RPCRDMAHDR (\ | ||
| 110 | /* max supported RPC/RDMA header */ \ | ||
| 111 | sizeof(struct rpcrdma_msg) + (2 * sizeof(u32)) + \ | ||
| 112 | (sizeof(struct rpcrdma_read_chunk) * RPCRDMA_MAX_SEGS) + sizeof(u32)) | ||
| 113 | |||
| 114 | struct rpcrdma_buffer; | ||
| 115 | |||
| 116 | struct rpcrdma_rep { | ||
| 117 | unsigned int rr_len; /* actual received reply length */ | ||
| 118 | struct rpcrdma_buffer *rr_buffer; /* home base for this structure */ | ||
| 119 | struct rpc_xprt *rr_xprt; /* needed for request/reply matching */ | ||
| 120 | void (*rr_func)(struct rpcrdma_rep *);/* called by tasklet in softint */ | ||
| 121 | struct list_head rr_list; /* tasklet list */ | ||
| 122 | wait_queue_head_t rr_unbind; /* optional unbind wait */ | ||
| 123 | struct ib_sge rr_iov; /* for posting */ | ||
| 124 | struct ib_mr *rr_handle; /* handle for mem in rr_iov */ | ||
| 125 | char rr_base[MAX_RPCRDMAHDR]; /* minimal inline receive buffer */ | ||
| 126 | }; | ||
| 127 | |||
| 128 | /* | ||
| 129 | * struct rpcrdma_req -- structure central to the request/reply sequence. | ||
| 130 | * | ||
| 131 | * N of these are associated with a transport instance, and stored in | ||
| 132 | * struct rpcrdma_buffer. N is the max number of outstanding requests. | ||
| 133 | * | ||
| 134 | * It includes pre-registered buffer memory for send AND recv. | ||
| 135 | * The recv buffer, however, is not owned by this structure, and | ||
| 136 | * is "donated" to the hardware when a recv is posted. When a | ||
| 137 | * reply is handled, the recv buffer used is given back to the | ||
| 138 | * struct rpcrdma_req associated with the request. | ||
| 139 | * | ||
| 140 | * In addition to the basic memory, this structure includes an array | ||
| 141 | * of iovs for send operations. The reason is that the iovs passed to | ||
| 142 | * ib_post_{send,recv} must not be modified until the work request | ||
| 143 | * completes. | ||
| 144 | * | ||
| 145 | * NOTES: | ||
| 146 | * o RPCRDMA_MAX_SEGS is the max number of addressible chunk elements we | ||
| 147 | * marshal. The number needed varies depending on the iov lists that | ||
| 148 | * are passed to us, the memory registration mode we are in, and if | ||
| 149 | * physical addressing is used, the layout. | ||
| 150 | */ | ||
| 151 | |||
| 152 | struct rpcrdma_mr_seg { /* chunk descriptors */ | ||
| 153 | union { /* chunk memory handles */ | ||
| 154 | struct ib_mr *rl_mr; /* if registered directly */ | ||
| 155 | struct rpcrdma_mw { /* if registered from region */ | ||
| 156 | union { | ||
| 157 | struct ib_mw *mw; | ||
| 158 | struct ib_fmr *fmr; | ||
| 159 | } r; | ||
| 160 | struct list_head mw_list; | ||
| 161 | } *rl_mw; | ||
| 162 | } mr_chunk; | ||
| 163 | u64 mr_base; /* registration result */ | ||
| 164 | u32 mr_rkey; /* registration result */ | ||
| 165 | u32 mr_len; /* length of chunk or segment */ | ||
| 166 | int mr_nsegs; /* number of segments in chunk or 0 */ | ||
| 167 | enum dma_data_direction mr_dir; /* segment mapping direction */ | ||
| 168 | dma_addr_t mr_dma; /* segment mapping address */ | ||
| 169 | size_t mr_dmalen; /* segment mapping length */ | ||
| 170 | struct page *mr_page; /* owning page, if any */ | ||
| 171 | char *mr_offset; /* kva if no page, else offset */ | ||
| 172 | }; | ||
| 173 | |||
| 174 | struct rpcrdma_req { | ||
| 175 | size_t rl_size; /* actual length of buffer */ | ||
| 176 | unsigned int rl_niovs; /* 0, 2 or 4 */ | ||
| 177 | unsigned int rl_nchunks; /* non-zero if chunks */ | ||
| 178 | struct rpcrdma_buffer *rl_buffer; /* home base for this structure */ | ||
| 179 | struct rpcrdma_rep *rl_reply;/* holder for reply buffer */ | ||
| 180 | struct rpcrdma_mr_seg rl_segments[RPCRDMA_MAX_SEGS];/* chunk segments */ | ||
| 181 | struct ib_sge rl_send_iov[4]; /* for active requests */ | ||
| 182 | struct ib_sge rl_iov; /* for posting */ | ||
| 183 | struct ib_mr *rl_handle; /* handle for mem in rl_iov */ | ||
| 184 | char rl_base[MAX_RPCRDMAHDR]; /* start of actual buffer */ | ||
| 185 | __u32 rl_xdr_buf[0]; /* start of returned rpc rq_buffer */ | ||
| 186 | }; | ||
| 187 | #define rpcr_to_rdmar(r) \ | ||
| 188 | container_of((r)->rq_buffer, struct rpcrdma_req, rl_xdr_buf[0]) | ||
| 189 | |||
| 190 | /* | ||
| 191 | * struct rpcrdma_buffer -- holds list/queue of pre-registered memory for | ||
| 192 | * inline requests/replies, and client/server credits. | ||
| 193 | * | ||
| 194 | * One of these is associated with a transport instance | ||
| 195 | */ | ||
| 196 | struct rpcrdma_buffer { | ||
| 197 | spinlock_t rb_lock; /* protects indexes */ | ||
| 198 | atomic_t rb_credits; /* most recent server credits */ | ||
| 199 | unsigned long rb_cwndscale; /* cached framework rpc_cwndscale */ | ||
| 200 | int rb_max_requests;/* client max requests */ | ||
| 201 | struct list_head rb_mws; /* optional memory windows/fmrs */ | ||
| 202 | int rb_send_index; | ||
| 203 | struct rpcrdma_req **rb_send_bufs; | ||
| 204 | int rb_recv_index; | ||
| 205 | struct rpcrdma_rep **rb_recv_bufs; | ||
| 206 | char *rb_pool; | ||
| 207 | }; | ||
| 208 | #define rdmab_to_ia(b) (&container_of((b), struct rpcrdma_xprt, rx_buf)->rx_ia) | ||
| 209 | |||
| 210 | /* | ||
| 211 | * Internal structure for transport instance creation. This | ||
| 212 | * exists primarily for modularity. | ||
| 213 | * | ||
| 214 | * This data should be set with mount options | ||
| 215 | */ | ||
| 216 | struct rpcrdma_create_data_internal { | ||
| 217 | struct sockaddr_storage addr; /* RDMA server address */ | ||
| 218 | unsigned int max_requests; /* max requests (slots) in flight */ | ||
| 219 | unsigned int rsize; /* mount rsize - max read hdr+data */ | ||
| 220 | unsigned int wsize; /* mount wsize - max write hdr+data */ | ||
| 221 | unsigned int inline_rsize; /* max non-rdma read data payload */ | ||
| 222 | unsigned int inline_wsize; /* max non-rdma write data payload */ | ||
| 223 | unsigned int padding; /* non-rdma write header padding */ | ||
| 224 | }; | ||
| 225 | |||
| 226 | #define RPCRDMA_INLINE_READ_THRESHOLD(rq) \ | ||
| 227 | (rpcx_to_rdmad(rq->rq_task->tk_xprt).inline_rsize) | ||
| 228 | |||
| 229 | #define RPCRDMA_INLINE_WRITE_THRESHOLD(rq)\ | ||
| 230 | (rpcx_to_rdmad(rq->rq_task->tk_xprt).inline_wsize) | ||
| 231 | |||
| 232 | #define RPCRDMA_INLINE_PAD_VALUE(rq)\ | ||
| 233 | rpcx_to_rdmad(rq->rq_task->tk_xprt).padding | ||
| 234 | |||
| 235 | /* | ||
| 236 | * Statistics for RPCRDMA | ||
| 237 | */ | ||
| 238 | struct rpcrdma_stats { | ||
| 239 | unsigned long read_chunk_count; | ||
| 240 | unsigned long write_chunk_count; | ||
| 241 | unsigned long reply_chunk_count; | ||
| 242 | |||
| 243 | unsigned long long total_rdma_request; | ||
| 244 | unsigned long long total_rdma_reply; | ||
| 245 | |||
| 246 | unsigned long long pullup_copy_count; | ||
| 247 | unsigned long long fixup_copy_count; | ||
| 248 | unsigned long hardway_register_count; | ||
| 249 | unsigned long failed_marshal_count; | ||
| 250 | unsigned long bad_reply_count; | ||
| 251 | }; | ||
| 252 | |||
| 253 | /* | ||
| 254 | * RPCRDMA transport -- encapsulates the structures above for | ||
| 255 | * integration with RPC. | ||
| 256 | * | ||
| 257 | * The contained structures are embedded, not pointers, | ||
| 258 | * for convenience. This structure need not be visible externally. | ||
| 259 | * | ||
| 260 | * It is allocated and initialized during mount, and released | ||
| 261 | * during unmount. | ||
| 262 | */ | ||
| 263 | struct rpcrdma_xprt { | ||
| 264 | struct rpc_xprt xprt; | ||
| 265 | struct rpcrdma_ia rx_ia; | ||
| 266 | struct rpcrdma_ep rx_ep; | ||
| 267 | struct rpcrdma_buffer rx_buf; | ||
| 268 | struct rpcrdma_create_data_internal rx_data; | ||
| 269 | struct delayed_work rdma_connect; | ||
| 270 | struct rpcrdma_stats rx_stats; | ||
| 271 | }; | ||
| 272 | |||
| 273 | #define rpcx_to_rdmax(x) container_of(x, struct rpcrdma_xprt, xprt) | ||
| 274 | #define rpcx_to_rdmad(x) (rpcx_to_rdmax(x)->rx_data) | ||
| 275 | |||
| 276 | /* | ||
| 277 | * Interface Adapter calls - xprtrdma/verbs.c | ||
| 278 | */ | ||
| 279 | int rpcrdma_ia_open(struct rpcrdma_xprt *, struct sockaddr *, int); | ||
| 280 | void rpcrdma_ia_close(struct rpcrdma_ia *); | ||
| 281 | |||
| 282 | /* | ||
| 283 | * Endpoint calls - xprtrdma/verbs.c | ||
| 284 | */ | ||
| 285 | int rpcrdma_ep_create(struct rpcrdma_ep *, struct rpcrdma_ia *, | ||
| 286 | struct rpcrdma_create_data_internal *); | ||
| 287 | int rpcrdma_ep_destroy(struct rpcrdma_ep *, struct rpcrdma_ia *); | ||
| 288 | int rpcrdma_ep_connect(struct rpcrdma_ep *, struct rpcrdma_ia *); | ||
| 289 | int rpcrdma_ep_disconnect(struct rpcrdma_ep *, struct rpcrdma_ia *); | ||
| 290 | |||
| 291 | int rpcrdma_ep_post(struct rpcrdma_ia *, struct rpcrdma_ep *, | ||
| 292 | struct rpcrdma_req *); | ||
| 293 | int rpcrdma_ep_post_recv(struct rpcrdma_ia *, struct rpcrdma_ep *, | ||
| 294 | struct rpcrdma_rep *); | ||
| 295 | |||
| 296 | /* | ||
| 297 | * Buffer calls - xprtrdma/verbs.c | ||
| 298 | */ | ||
| 299 | int rpcrdma_buffer_create(struct rpcrdma_buffer *, struct rpcrdma_ep *, | ||
| 300 | struct rpcrdma_ia *, | ||
| 301 | struct rpcrdma_create_data_internal *); | ||
| 302 | void rpcrdma_buffer_destroy(struct rpcrdma_buffer *); | ||
| 303 | |||
| 304 | struct rpcrdma_req *rpcrdma_buffer_get(struct rpcrdma_buffer *); | ||
| 305 | void rpcrdma_buffer_put(struct rpcrdma_req *); | ||
| 306 | void rpcrdma_recv_buffer_get(struct rpcrdma_req *); | ||
| 307 | void rpcrdma_recv_buffer_put(struct rpcrdma_rep *); | ||
| 308 | |||
| 309 | int rpcrdma_register_internal(struct rpcrdma_ia *, void *, int, | ||
| 310 | struct ib_mr **, struct ib_sge *); | ||
| 311 | int rpcrdma_deregister_internal(struct rpcrdma_ia *, | ||
| 312 | struct ib_mr *, struct ib_sge *); | ||
| 313 | |||
| 314 | int rpcrdma_register_external(struct rpcrdma_mr_seg *, | ||
| 315 | int, int, struct rpcrdma_xprt *); | ||
| 316 | int rpcrdma_deregister_external(struct rpcrdma_mr_seg *, | ||
| 317 | struct rpcrdma_xprt *, void *); | ||
| 318 | |||
| 319 | /* | ||
| 320 | * RPC/RDMA connection management calls - xprtrdma/rpc_rdma.c | ||
| 321 | */ | ||
| 322 | void rpcrdma_conn_func(struct rpcrdma_ep *); | ||
| 323 | void rpcrdma_reply_handler(struct rpcrdma_rep *); | ||
| 324 | |||
| 325 | /* | ||
| 326 | * RPC/RDMA protocol calls - xprtrdma/rpc_rdma.c | ||
| 327 | */ | ||
| 328 | int rpcrdma_marshal_req(struct rpc_rqst *); | ||
| 329 | |||
| 330 | #endif /* _LINUX_SUNRPC_XPRT_RDMA_H */ | ||
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 282efd447a61..02298f529dad 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
| @@ -13,10 +13,14 @@ | |||
| 13 | * (C) 1999 Trond Myklebust <trond.myklebust@fys.uio.no> | 13 | * (C) 1999 Trond Myklebust <trond.myklebust@fys.uio.no> |
| 14 | * | 14 | * |
| 15 | * IP socket transport implementation, (C) 2005 Chuck Lever <cel@netapp.com> | 15 | * IP socket transport implementation, (C) 2005 Chuck Lever <cel@netapp.com> |
| 16 | * | ||
| 17 | * IPv6 support contributed by Gilles Quillard, Bull Open Source, 2005. | ||
| 18 | * <gilles.quillard@bull.net> | ||
| 16 | */ | 19 | */ |
| 17 | 20 | ||
| 18 | #include <linux/types.h> | 21 | #include <linux/types.h> |
| 19 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
| 23 | #include <linux/module.h> | ||
| 20 | #include <linux/capability.h> | 24 | #include <linux/capability.h> |
| 21 | #include <linux/pagemap.h> | 25 | #include <linux/pagemap.h> |
| 22 | #include <linux/errno.h> | 26 | #include <linux/errno.h> |
| @@ -28,6 +32,7 @@ | |||
| 28 | #include <linux/tcp.h> | 32 | #include <linux/tcp.h> |
| 29 | #include <linux/sunrpc/clnt.h> | 33 | #include <linux/sunrpc/clnt.h> |
| 30 | #include <linux/sunrpc/sched.h> | 34 | #include <linux/sunrpc/sched.h> |
| 35 | #include <linux/sunrpc/xprtsock.h> | ||
| 31 | #include <linux/file.h> | 36 | #include <linux/file.h> |
| 32 | 37 | ||
| 33 | #include <net/sock.h> | 38 | #include <net/sock.h> |
| @@ -260,14 +265,29 @@ struct sock_xprt { | |||
| 260 | #define TCP_RCV_COPY_XID (1UL << 2) | 265 | #define TCP_RCV_COPY_XID (1UL << 2) |
| 261 | #define TCP_RCV_COPY_DATA (1UL << 3) | 266 | #define TCP_RCV_COPY_DATA (1UL << 3) |
| 262 | 267 | ||
| 263 | static void xs_format_peer_addresses(struct rpc_xprt *xprt) | 268 | static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt) |
| 269 | { | ||
| 270 | return (struct sockaddr *) &xprt->addr; | ||
| 271 | } | ||
| 272 | |||
| 273 | static inline struct sockaddr_in *xs_addr_in(struct rpc_xprt *xprt) | ||
| 264 | { | 274 | { |
| 265 | struct sockaddr_in *addr = (struct sockaddr_in *) &xprt->addr; | 275 | return (struct sockaddr_in *) &xprt->addr; |
| 276 | } | ||
| 277 | |||
| 278 | static inline struct sockaddr_in6 *xs_addr_in6(struct rpc_xprt *xprt) | ||
| 279 | { | ||
| 280 | return (struct sockaddr_in6 *) &xprt->addr; | ||
| 281 | } | ||
| 282 | |||
| 283 | static void xs_format_ipv4_peer_addresses(struct rpc_xprt *xprt) | ||
| 284 | { | ||
| 285 | struct sockaddr_in *addr = xs_addr_in(xprt); | ||
| 266 | char *buf; | 286 | char *buf; |
| 267 | 287 | ||
| 268 | buf = kzalloc(20, GFP_KERNEL); | 288 | buf = kzalloc(20, GFP_KERNEL); |
| 269 | if (buf) { | 289 | if (buf) { |
| 270 | snprintf(buf, 20, "%u.%u.%u.%u", | 290 | snprintf(buf, 20, NIPQUAD_FMT, |
| 271 | NIPQUAD(addr->sin_addr.s_addr)); | 291 | NIPQUAD(addr->sin_addr.s_addr)); |
| 272 | } | 292 | } |
| 273 | xprt->address_strings[RPC_DISPLAY_ADDR] = buf; | 293 | xprt->address_strings[RPC_DISPLAY_ADDR] = buf; |
| @@ -279,26 +299,123 @@ static void xs_format_peer_addresses(struct rpc_xprt *xprt) | |||
| 279 | } | 299 | } |
| 280 | xprt->address_strings[RPC_DISPLAY_PORT] = buf; | 300 | xprt->address_strings[RPC_DISPLAY_PORT] = buf; |
| 281 | 301 | ||
| 282 | if (xprt->prot == IPPROTO_UDP) | 302 | buf = kzalloc(8, GFP_KERNEL); |
| 283 | xprt->address_strings[RPC_DISPLAY_PROTO] = "udp"; | 303 | if (buf) { |
| 284 | else | 304 | if (xprt->prot == IPPROTO_UDP) |
| 285 | xprt->address_strings[RPC_DISPLAY_PROTO] = "tcp"; | 305 | snprintf(buf, 8, "udp"); |
| 306 | else | ||
| 307 | snprintf(buf, 8, "tcp"); | ||
| 308 | } | ||
| 309 | xprt->address_strings[RPC_DISPLAY_PROTO] = buf; | ||
| 286 | 310 | ||
| 287 | buf = kzalloc(48, GFP_KERNEL); | 311 | buf = kzalloc(48, GFP_KERNEL); |
| 288 | if (buf) { | 312 | if (buf) { |
| 289 | snprintf(buf, 48, "addr=%u.%u.%u.%u port=%u proto=%s", | 313 | snprintf(buf, 48, "addr="NIPQUAD_FMT" port=%u proto=%s", |
| 290 | NIPQUAD(addr->sin_addr.s_addr), | 314 | NIPQUAD(addr->sin_addr.s_addr), |
| 291 | ntohs(addr->sin_port), | 315 | ntohs(addr->sin_port), |
| 292 | xprt->prot == IPPROTO_UDP ? "udp" : "tcp"); | 316 | xprt->prot == IPPROTO_UDP ? "udp" : "tcp"); |
| 293 | } | 317 | } |
| 294 | xprt->address_strings[RPC_DISPLAY_ALL] = buf; | 318 | xprt->address_strings[RPC_DISPLAY_ALL] = buf; |
| 319 | |||
| 320 | buf = kzalloc(10, GFP_KERNEL); | ||
| 321 | if (buf) { | ||
| 322 | snprintf(buf, 10, "%02x%02x%02x%02x", | ||
| 323 | NIPQUAD(addr->sin_addr.s_addr)); | ||
| 324 | } | ||
| 325 | xprt->address_strings[RPC_DISPLAY_HEX_ADDR] = buf; | ||
| 326 | |||
| 327 | buf = kzalloc(8, GFP_KERNEL); | ||
| 328 | if (buf) { | ||
| 329 | snprintf(buf, 8, "%4hx", | ||
| 330 | ntohs(addr->sin_port)); | ||
| 331 | } | ||
| 332 | xprt->address_strings[RPC_DISPLAY_HEX_PORT] = buf; | ||
| 333 | |||
| 334 | buf = kzalloc(30, GFP_KERNEL); | ||
| 335 | if (buf) { | ||
| 336 | snprintf(buf, 30, NIPQUAD_FMT".%u.%u", | ||
| 337 | NIPQUAD(addr->sin_addr.s_addr), | ||
| 338 | ntohs(addr->sin_port) >> 8, | ||
| 339 | ntohs(addr->sin_port) & 0xff); | ||
| 340 | } | ||
| 341 | xprt->address_strings[RPC_DISPLAY_UNIVERSAL_ADDR] = buf; | ||
| 342 | |||
| 343 | xprt->address_strings[RPC_DISPLAY_NETID] = | ||
| 344 | kstrdup(xprt->prot == IPPROTO_UDP ? | ||
| 345 | RPCBIND_NETID_UDP : RPCBIND_NETID_TCP, GFP_KERNEL); | ||
| 346 | } | ||
| 347 | |||
| 348 | static void xs_format_ipv6_peer_addresses(struct rpc_xprt *xprt) | ||
| 349 | { | ||
| 350 | struct sockaddr_in6 *addr = xs_addr_in6(xprt); | ||
| 351 | char *buf; | ||
| 352 | |||
| 353 | buf = kzalloc(40, GFP_KERNEL); | ||
| 354 | if (buf) { | ||
| 355 | snprintf(buf, 40, NIP6_FMT, | ||
| 356 | NIP6(addr->sin6_addr)); | ||
| 357 | } | ||
| 358 | xprt->address_strings[RPC_DISPLAY_ADDR] = buf; | ||
| 359 | |||
| 360 | buf = kzalloc(8, GFP_KERNEL); | ||
| 361 | if (buf) { | ||
| 362 | snprintf(buf, 8, "%u", | ||
| 363 | ntohs(addr->sin6_port)); | ||
| 364 | } | ||
| 365 | xprt->address_strings[RPC_DISPLAY_PORT] = buf; | ||
| 366 | |||
| 367 | buf = kzalloc(8, GFP_KERNEL); | ||
| 368 | if (buf) { | ||
| 369 | if (xprt->prot == IPPROTO_UDP) | ||
| 370 | snprintf(buf, 8, "udp"); | ||
| 371 | else | ||
| 372 | snprintf(buf, 8, "tcp"); | ||
| 373 | } | ||
| 374 | xprt->address_strings[RPC_DISPLAY_PROTO] = buf; | ||
| 375 | |||
| 376 | buf = kzalloc(64, GFP_KERNEL); | ||
| 377 | if (buf) { | ||
| 378 | snprintf(buf, 64, "addr="NIP6_FMT" port=%u proto=%s", | ||
| 379 | NIP6(addr->sin6_addr), | ||
| 380 | ntohs(addr->sin6_port), | ||
| 381 | xprt->prot == IPPROTO_UDP ? "udp" : "tcp"); | ||
| 382 | } | ||
| 383 | xprt->address_strings[RPC_DISPLAY_ALL] = buf; | ||
| 384 | |||
| 385 | buf = kzalloc(36, GFP_KERNEL); | ||
| 386 | if (buf) { | ||
| 387 | snprintf(buf, 36, NIP6_SEQFMT, | ||
| 388 | NIP6(addr->sin6_addr)); | ||
| 389 | } | ||
| 390 | xprt->address_strings[RPC_DISPLAY_HEX_ADDR] = buf; | ||
| 391 | |||
| 392 | buf = kzalloc(8, GFP_KERNEL); | ||
| 393 | if (buf) { | ||
| 394 | snprintf(buf, 8, "%4hx", | ||
| 395 | ntohs(addr->sin6_port)); | ||
| 396 | } | ||
| 397 | xprt->address_strings[RPC_DISPLAY_HEX_PORT] = buf; | ||
| 398 | |||
| 399 | buf = kzalloc(50, GFP_KERNEL); | ||
| 400 | if (buf) { | ||
| 401 | snprintf(buf, 50, NIP6_FMT".%u.%u", | ||
| 402 | NIP6(addr->sin6_addr), | ||
| 403 | ntohs(addr->sin6_port) >> 8, | ||
| 404 | ntohs(addr->sin6_port) & 0xff); | ||
| 405 | } | ||
| 406 | xprt->address_strings[RPC_DISPLAY_UNIVERSAL_ADDR] = buf; | ||
| 407 | |||
| 408 | xprt->address_strings[RPC_DISPLAY_NETID] = | ||
| 409 | kstrdup(xprt->prot == IPPROTO_UDP ? | ||
| 410 | RPCBIND_NETID_UDP6 : RPCBIND_NETID_TCP6, GFP_KERNEL); | ||
| 295 | } | 411 | } |
| 296 | 412 | ||
| 297 | static void xs_free_peer_addresses(struct rpc_xprt *xprt) | 413 | static void xs_free_peer_addresses(struct rpc_xprt *xprt) |
| 298 | { | 414 | { |
| 299 | kfree(xprt->address_strings[RPC_DISPLAY_ADDR]); | 415 | int i; |
| 300 | kfree(xprt->address_strings[RPC_DISPLAY_PORT]); | 416 | |
| 301 | kfree(xprt->address_strings[RPC_DISPLAY_ALL]); | 417 | for (i = 0; i < RPC_DISPLAY_MAX; i++) |
| 418 | kfree(xprt->address_strings[i]); | ||
| 302 | } | 419 | } |
| 303 | 420 | ||
| 304 | #define XS_SENDMSG_FLAGS (MSG_DONTWAIT | MSG_NOSIGNAL) | 421 | #define XS_SENDMSG_FLAGS (MSG_DONTWAIT | MSG_NOSIGNAL) |
| @@ -463,19 +580,20 @@ static int xs_udp_send_request(struct rpc_task *task) | |||
| 463 | 580 | ||
| 464 | req->rq_xtime = jiffies; | 581 | req->rq_xtime = jiffies; |
| 465 | status = xs_sendpages(transport->sock, | 582 | status = xs_sendpages(transport->sock, |
| 466 | (struct sockaddr *) &xprt->addr, | 583 | xs_addr(xprt), |
| 467 | xprt->addrlen, xdr, | 584 | xprt->addrlen, xdr, |
| 468 | req->rq_bytes_sent); | 585 | req->rq_bytes_sent); |
| 469 | 586 | ||
| 470 | dprintk("RPC: xs_udp_send_request(%u) = %d\n", | 587 | dprintk("RPC: xs_udp_send_request(%u) = %d\n", |
| 471 | xdr->len - req->rq_bytes_sent, status); | 588 | xdr->len - req->rq_bytes_sent, status); |
| 472 | 589 | ||
| 473 | if (likely(status >= (int) req->rq_slen)) | 590 | if (status >= 0) { |
| 474 | return 0; | 591 | task->tk_bytes_sent += status; |
| 475 | 592 | if (status >= req->rq_slen) | |
| 476 | /* Still some bytes left; set up for a retry later. */ | 593 | return 0; |
| 477 | if (status > 0) | 594 | /* Still some bytes left; set up for a retry later. */ |
| 478 | status = -EAGAIN; | 595 | status = -EAGAIN; |
| 596 | } | ||
| 479 | 597 | ||
| 480 | switch (status) { | 598 | switch (status) { |
| 481 | case -ENETUNREACH: | 599 | case -ENETUNREACH: |
| @@ -523,7 +641,8 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
| 523 | struct rpc_xprt *xprt = req->rq_xprt; | 641 | struct rpc_xprt *xprt = req->rq_xprt; |
| 524 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | 642 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); |
| 525 | struct xdr_buf *xdr = &req->rq_snd_buf; | 643 | struct xdr_buf *xdr = &req->rq_snd_buf; |
| 526 | int status, retry = 0; | 644 | int status; |
| 645 | unsigned int retry = 0; | ||
| 527 | 646 | ||
| 528 | xs_encode_tcp_record_marker(&req->rq_snd_buf); | 647 | xs_encode_tcp_record_marker(&req->rq_snd_buf); |
| 529 | 648 | ||
| @@ -661,6 +780,7 @@ static void xs_destroy(struct rpc_xprt *xprt) | |||
| 661 | xs_free_peer_addresses(xprt); | 780 | xs_free_peer_addresses(xprt); |
| 662 | kfree(xprt->slot); | 781 | kfree(xprt->slot); |
| 663 | kfree(xprt); | 782 | kfree(xprt); |
| 783 | module_put(THIS_MODULE); | ||
| 664 | } | 784 | } |
| 665 | 785 | ||
| 666 | static inline struct rpc_xprt *xprt_from_sock(struct sock *sk) | 786 | static inline struct rpc_xprt *xprt_from_sock(struct sock *sk) |
| @@ -1139,14 +1259,23 @@ static unsigned short xs_get_random_port(void) | |||
| 1139 | */ | 1259 | */ |
| 1140 | static void xs_set_port(struct rpc_xprt *xprt, unsigned short port) | 1260 | static void xs_set_port(struct rpc_xprt *xprt, unsigned short port) |
| 1141 | { | 1261 | { |
| 1142 | struct sockaddr_in *sap = (struct sockaddr_in *) &xprt->addr; | 1262 | struct sockaddr *addr = xs_addr(xprt); |
| 1143 | 1263 | ||
| 1144 | dprintk("RPC: setting port for xprt %p to %u\n", xprt, port); | 1264 | dprintk("RPC: setting port for xprt %p to %u\n", xprt, port); |
| 1145 | 1265 | ||
| 1146 | sap->sin_port = htons(port); | 1266 | switch (addr->sa_family) { |
| 1267 | case AF_INET: | ||
| 1268 | ((struct sockaddr_in *)addr)->sin_port = htons(port); | ||
| 1269 | break; | ||
| 1270 | case AF_INET6: | ||
| 1271 | ((struct sockaddr_in6 *)addr)->sin6_port = htons(port); | ||
| 1272 | break; | ||
| 1273 | default: | ||
| 1274 | BUG(); | ||
| 1275 | } | ||
| 1147 | } | 1276 | } |
| 1148 | 1277 | ||
| 1149 | static int xs_bind(struct sock_xprt *transport, struct socket *sock) | 1278 | static int xs_bind4(struct sock_xprt *transport, struct socket *sock) |
| 1150 | { | 1279 | { |
| 1151 | struct sockaddr_in myaddr = { | 1280 | struct sockaddr_in myaddr = { |
| 1152 | .sin_family = AF_INET, | 1281 | .sin_family = AF_INET, |
| @@ -1174,8 +1303,42 @@ static int xs_bind(struct sock_xprt *transport, struct socket *sock) | |||
| 1174 | else | 1303 | else |
| 1175 | port--; | 1304 | port--; |
| 1176 | } while (err == -EADDRINUSE && port != transport->port); | 1305 | } while (err == -EADDRINUSE && port != transport->port); |
| 1177 | dprintk("RPC: xs_bind "NIPQUAD_FMT":%u: %s (%d)\n", | 1306 | dprintk("RPC: %s "NIPQUAD_FMT":%u: %s (%d)\n", |
| 1178 | NIPQUAD(myaddr.sin_addr), port, err ? "failed" : "ok", err); | 1307 | __FUNCTION__, NIPQUAD(myaddr.sin_addr), |
| 1308 | port, err ? "failed" : "ok", err); | ||
| 1309 | return err; | ||
| 1310 | } | ||
| 1311 | |||
| 1312 | static int xs_bind6(struct sock_xprt *transport, struct socket *sock) | ||
| 1313 | { | ||
| 1314 | struct sockaddr_in6 myaddr = { | ||
| 1315 | .sin6_family = AF_INET6, | ||
| 1316 | }; | ||
| 1317 | struct sockaddr_in6 *sa; | ||
| 1318 | int err; | ||
| 1319 | unsigned short port = transport->port; | ||
| 1320 | |||
| 1321 | if (!transport->xprt.resvport) | ||
| 1322 | port = 0; | ||
| 1323 | sa = (struct sockaddr_in6 *)&transport->addr; | ||
| 1324 | myaddr.sin6_addr = sa->sin6_addr; | ||
| 1325 | do { | ||
| 1326 | myaddr.sin6_port = htons(port); | ||
| 1327 | err = kernel_bind(sock, (struct sockaddr *) &myaddr, | ||
| 1328 | sizeof(myaddr)); | ||
| 1329 | if (!transport->xprt.resvport) | ||
| 1330 | break; | ||
| 1331 | if (err == 0) { | ||
| 1332 | transport->port = port; | ||
| 1333 | break; | ||
| 1334 | } | ||
| 1335 | if (port <= xprt_min_resvport) | ||
| 1336 | port = xprt_max_resvport; | ||
| 1337 | else | ||
| 1338 | port--; | ||
| 1339 | } while (err == -EADDRINUSE && port != transport->port); | ||
| 1340 | dprintk("RPC: xs_bind6 "NIP6_FMT":%u: %s (%d)\n", | ||
| 1341 | NIP6(myaddr.sin6_addr), port, err ? "failed" : "ok", err); | ||
| 1179 | return err; | 1342 | return err; |
| 1180 | } | 1343 | } |
| 1181 | 1344 | ||
| @@ -1183,38 +1346,69 @@ static int xs_bind(struct sock_xprt *transport, struct socket *sock) | |||
| 1183 | static struct lock_class_key xs_key[2]; | 1346 | static struct lock_class_key xs_key[2]; |
| 1184 | static struct lock_class_key xs_slock_key[2]; | 1347 | static struct lock_class_key xs_slock_key[2]; |
| 1185 | 1348 | ||
| 1186 | static inline void xs_reclassify_socket(struct socket *sock) | 1349 | static inline void xs_reclassify_socket4(struct socket *sock) |
| 1187 | { | 1350 | { |
| 1188 | struct sock *sk = sock->sk; | 1351 | struct sock *sk = sock->sk; |
| 1352 | |||
| 1189 | BUG_ON(sock_owned_by_user(sk)); | 1353 | BUG_ON(sock_owned_by_user(sk)); |
| 1190 | switch (sk->sk_family) { | 1354 | sock_lock_init_class_and_name(sk, "slock-AF_INET-RPC", |
| 1191 | case AF_INET: | 1355 | &xs_slock_key[0], "sk_lock-AF_INET-RPC", &xs_key[0]); |
| 1192 | sock_lock_init_class_and_name(sk, "slock-AF_INET-NFS", | 1356 | } |
| 1193 | &xs_slock_key[0], "sk_lock-AF_INET-NFS", &xs_key[0]); | ||
| 1194 | break; | ||
| 1195 | 1357 | ||
| 1196 | case AF_INET6: | 1358 | static inline void xs_reclassify_socket6(struct socket *sock) |
| 1197 | sock_lock_init_class_and_name(sk, "slock-AF_INET6-NFS", | 1359 | { |
| 1198 | &xs_slock_key[1], "sk_lock-AF_INET6-NFS", &xs_key[1]); | 1360 | struct sock *sk = sock->sk; |
| 1199 | break; | ||
| 1200 | 1361 | ||
| 1201 | default: | 1362 | BUG_ON(sock_owned_by_user(sk)); |
| 1202 | BUG(); | 1363 | sock_lock_init_class_and_name(sk, "slock-AF_INET6-RPC", |
| 1203 | } | 1364 | &xs_slock_key[1], "sk_lock-AF_INET6-RPC", &xs_key[1]); |
| 1204 | } | 1365 | } |
| 1205 | #else | 1366 | #else |
| 1206 | static inline void xs_reclassify_socket(struct socket *sock) | 1367 | static inline void xs_reclassify_socket4(struct socket *sock) |
| 1368 | { | ||
| 1369 | } | ||
| 1370 | |||
| 1371 | static inline void xs_reclassify_socket6(struct socket *sock) | ||
| 1207 | { | 1372 | { |
| 1208 | } | 1373 | } |
| 1209 | #endif | 1374 | #endif |
| 1210 | 1375 | ||
| 1376 | static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | ||
| 1377 | { | ||
| 1378 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | ||
| 1379 | |||
| 1380 | if (!transport->inet) { | ||
| 1381 | struct sock *sk = sock->sk; | ||
| 1382 | |||
| 1383 | write_lock_bh(&sk->sk_callback_lock); | ||
| 1384 | |||
| 1385 | sk->sk_user_data = xprt; | ||
| 1386 | transport->old_data_ready = sk->sk_data_ready; | ||
| 1387 | transport->old_state_change = sk->sk_state_change; | ||
| 1388 | transport->old_write_space = sk->sk_write_space; | ||
| 1389 | sk->sk_data_ready = xs_udp_data_ready; | ||
| 1390 | sk->sk_write_space = xs_udp_write_space; | ||
| 1391 | sk->sk_no_check = UDP_CSUM_NORCV; | ||
| 1392 | sk->sk_allocation = GFP_ATOMIC; | ||
| 1393 | |||
| 1394 | xprt_set_connected(xprt); | ||
| 1395 | |||
| 1396 | /* Reset to new socket */ | ||
| 1397 | transport->sock = sock; | ||
| 1398 | transport->inet = sk; | ||
| 1399 | |||
| 1400 | write_unlock_bh(&sk->sk_callback_lock); | ||
| 1401 | } | ||
| 1402 | xs_udp_do_set_buffer_size(xprt); | ||
| 1403 | } | ||
| 1404 | |||
| 1211 | /** | 1405 | /** |
| 1212 | * xs_udp_connect_worker - set up a UDP socket | 1406 | * xs_udp_connect_worker4 - set up a UDP socket |
| 1213 | * @work: RPC transport to connect | 1407 | * @work: RPC transport to connect |
| 1214 | * | 1408 | * |
| 1215 | * Invoked by a work queue tasklet. | 1409 | * Invoked by a work queue tasklet. |
| 1216 | */ | 1410 | */ |
| 1217 | static void xs_udp_connect_worker(struct work_struct *work) | 1411 | static void xs_udp_connect_worker4(struct work_struct *work) |
| 1218 | { | 1412 | { |
| 1219 | struct sock_xprt *transport = | 1413 | struct sock_xprt *transport = |
| 1220 | container_of(work, struct sock_xprt, connect_worker.work); | 1414 | container_of(work, struct sock_xprt, connect_worker.work); |
| @@ -1232,9 +1426,9 @@ static void xs_udp_connect_worker(struct work_struct *work) | |||
| 1232 | dprintk("RPC: can't create UDP transport socket (%d).\n", -err); | 1426 | dprintk("RPC: can't create UDP transport socket (%d).\n", -err); |
| 1233 | goto out; | 1427 | goto out; |
| 1234 | } | 1428 | } |
| 1235 | xs_reclassify_socket(sock); | 1429 | xs_reclassify_socket4(sock); |
| 1236 | 1430 | ||
| 1237 | if (xs_bind(transport, sock)) { | 1431 | if (xs_bind4(transport, sock)) { |
| 1238 | sock_release(sock); | 1432 | sock_release(sock); |
| 1239 | goto out; | 1433 | goto out; |
| 1240 | } | 1434 | } |
| @@ -1242,29 +1436,48 @@ static void xs_udp_connect_worker(struct work_struct *work) | |||
| 1242 | dprintk("RPC: worker connecting xprt %p to address: %s\n", | 1436 | dprintk("RPC: worker connecting xprt %p to address: %s\n", |
| 1243 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); | 1437 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); |
| 1244 | 1438 | ||
| 1245 | if (!transport->inet) { | 1439 | xs_udp_finish_connecting(xprt, sock); |
| 1246 | struct sock *sk = sock->sk; | 1440 | status = 0; |
| 1441 | out: | ||
| 1442 | xprt_wake_pending_tasks(xprt, status); | ||
| 1443 | xprt_clear_connecting(xprt); | ||
| 1444 | } | ||
| 1247 | 1445 | ||
| 1248 | write_lock_bh(&sk->sk_callback_lock); | 1446 | /** |
| 1447 | * xs_udp_connect_worker6 - set up a UDP socket | ||
| 1448 | * @work: RPC transport to connect | ||
| 1449 | * | ||
| 1450 | * Invoked by a work queue tasklet. | ||
| 1451 | */ | ||
| 1452 | static void xs_udp_connect_worker6(struct work_struct *work) | ||
| 1453 | { | ||
| 1454 | struct sock_xprt *transport = | ||
| 1455 | container_of(work, struct sock_xprt, connect_worker.work); | ||
| 1456 | struct rpc_xprt *xprt = &transport->xprt; | ||
| 1457 | struct socket *sock = transport->sock; | ||
| 1458 | int err, status = -EIO; | ||
| 1249 | 1459 | ||
| 1250 | sk->sk_user_data = xprt; | 1460 | if (xprt->shutdown || !xprt_bound(xprt)) |
| 1251 | transport->old_data_ready = sk->sk_data_ready; | 1461 | goto out; |
| 1252 | transport->old_state_change = sk->sk_state_change; | ||
| 1253 | transport->old_write_space = sk->sk_write_space; | ||
| 1254 | sk->sk_data_ready = xs_udp_data_ready; | ||
| 1255 | sk->sk_write_space = xs_udp_write_space; | ||
| 1256 | sk->sk_no_check = UDP_CSUM_NORCV; | ||
| 1257 | sk->sk_allocation = GFP_ATOMIC; | ||
| 1258 | 1462 | ||
| 1259 | xprt_set_connected(xprt); | 1463 | /* Start by resetting any existing state */ |
| 1464 | xs_close(xprt); | ||
| 1260 | 1465 | ||
| 1261 | /* Reset to new socket */ | 1466 | if ((err = sock_create_kern(PF_INET6, SOCK_DGRAM, IPPROTO_UDP, &sock)) < 0) { |
| 1262 | transport->sock = sock; | 1467 | dprintk("RPC: can't create UDP transport socket (%d).\n", -err); |
| 1263 | transport->inet = sk; | 1468 | goto out; |
| 1469 | } | ||
| 1470 | xs_reclassify_socket6(sock); | ||
| 1264 | 1471 | ||
| 1265 | write_unlock_bh(&sk->sk_callback_lock); | 1472 | if (xs_bind6(transport, sock) < 0) { |
| 1473 | sock_release(sock); | ||
| 1474 | goto out; | ||
| 1266 | } | 1475 | } |
| 1267 | xs_udp_do_set_buffer_size(xprt); | 1476 | |
| 1477 | dprintk("RPC: worker connecting xprt %p to address: %s\n", | ||
| 1478 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); | ||
| 1479 | |||
| 1480 | xs_udp_finish_connecting(xprt, sock); | ||
| 1268 | status = 0; | 1481 | status = 0; |
| 1269 | out: | 1482 | out: |
| 1270 | xprt_wake_pending_tasks(xprt, status); | 1483 | xprt_wake_pending_tasks(xprt, status); |
| @@ -1295,13 +1508,52 @@ static void xs_tcp_reuse_connection(struct rpc_xprt *xprt) | |||
| 1295 | result); | 1508 | result); |
| 1296 | } | 1509 | } |
| 1297 | 1510 | ||
| 1511 | static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | ||
| 1512 | { | ||
| 1513 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | ||
| 1514 | |||
| 1515 | if (!transport->inet) { | ||
| 1516 | struct sock *sk = sock->sk; | ||
| 1517 | |||
| 1518 | write_lock_bh(&sk->sk_callback_lock); | ||
| 1519 | |||
| 1520 | sk->sk_user_data = xprt; | ||
| 1521 | transport->old_data_ready = sk->sk_data_ready; | ||
| 1522 | transport->old_state_change = sk->sk_state_change; | ||
| 1523 | transport->old_write_space = sk->sk_write_space; | ||
| 1524 | sk->sk_data_ready = xs_tcp_data_ready; | ||
| 1525 | sk->sk_state_change = xs_tcp_state_change; | ||
| 1526 | sk->sk_write_space = xs_tcp_write_space; | ||
| 1527 | sk->sk_allocation = GFP_ATOMIC; | ||
| 1528 | |||
| 1529 | /* socket options */ | ||
| 1530 | sk->sk_userlocks |= SOCK_BINDPORT_LOCK; | ||
| 1531 | sock_reset_flag(sk, SOCK_LINGER); | ||
| 1532 | tcp_sk(sk)->linger2 = 0; | ||
| 1533 | tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF; | ||
| 1534 | |||
| 1535 | xprt_clear_connected(xprt); | ||
| 1536 | |||
| 1537 | /* Reset to new socket */ | ||
| 1538 | transport->sock = sock; | ||
| 1539 | transport->inet = sk; | ||
| 1540 | |||
| 1541 | write_unlock_bh(&sk->sk_callback_lock); | ||
| 1542 | } | ||
| 1543 | |||
| 1544 | /* Tell the socket layer to start connecting... */ | ||
| 1545 | xprt->stat.connect_count++; | ||
| 1546 | xprt->stat.connect_start = jiffies; | ||
| 1547 | return kernel_connect(sock, xs_addr(xprt), xprt->addrlen, O_NONBLOCK); | ||
| 1548 | } | ||
| 1549 | |||
| 1298 | /** | 1550 | /** |
| 1299 | * xs_tcp_connect_worker - connect a TCP socket to a remote endpoint | 1551 | * xs_tcp_connect_worker4 - connect a TCP socket to a remote endpoint |
| 1300 | * @work: RPC transport to connect | 1552 | * @work: RPC transport to connect |
| 1301 | * | 1553 | * |
| 1302 | * Invoked by a work queue tasklet. | 1554 | * Invoked by a work queue tasklet. |
| 1303 | */ | 1555 | */ |
| 1304 | static void xs_tcp_connect_worker(struct work_struct *work) | 1556 | static void xs_tcp_connect_worker4(struct work_struct *work) |
| 1305 | { | 1557 | { |
| 1306 | struct sock_xprt *transport = | 1558 | struct sock_xprt *transport = |
| 1307 | container_of(work, struct sock_xprt, connect_worker.work); | 1559 | container_of(work, struct sock_xprt, connect_worker.work); |
| @@ -1315,13 +1567,12 @@ static void xs_tcp_connect_worker(struct work_struct *work) | |||
| 1315 | if (!sock) { | 1567 | if (!sock) { |
| 1316 | /* start from scratch */ | 1568 | /* start from scratch */ |
| 1317 | if ((err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) { | 1569 | if ((err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) { |
| 1318 | dprintk("RPC: can't create TCP transport " | 1570 | dprintk("RPC: can't create TCP transport socket (%d).\n", -err); |
| 1319 | "socket (%d).\n", -err); | ||
| 1320 | goto out; | 1571 | goto out; |
| 1321 | } | 1572 | } |
| 1322 | xs_reclassify_socket(sock); | 1573 | xs_reclassify_socket4(sock); |
| 1323 | 1574 | ||
| 1324 | if (xs_bind(transport, sock)) { | 1575 | if (xs_bind4(transport, sock) < 0) { |
| 1325 | sock_release(sock); | 1576 | sock_release(sock); |
| 1326 | goto out; | 1577 | goto out; |
| 1327 | } | 1578 | } |
| @@ -1332,43 +1583,70 @@ static void xs_tcp_connect_worker(struct work_struct *work) | |||
| 1332 | dprintk("RPC: worker connecting xprt %p to address: %s\n", | 1583 | dprintk("RPC: worker connecting xprt %p to address: %s\n", |
| 1333 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); | 1584 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); |
| 1334 | 1585 | ||
| 1335 | if (!transport->inet) { | 1586 | status = xs_tcp_finish_connecting(xprt, sock); |
| 1336 | struct sock *sk = sock->sk; | 1587 | dprintk("RPC: %p connect status %d connected %d sock state %d\n", |
| 1337 | 1588 | xprt, -status, xprt_connected(xprt), | |
| 1338 | write_lock_bh(&sk->sk_callback_lock); | 1589 | sock->sk->sk_state); |
| 1590 | if (status < 0) { | ||
| 1591 | switch (status) { | ||
| 1592 | case -EINPROGRESS: | ||
| 1593 | case -EALREADY: | ||
| 1594 | goto out_clear; | ||
| 1595 | case -ECONNREFUSED: | ||
| 1596 | case -ECONNRESET: | ||
| 1597 | /* retry with existing socket, after a delay */ | ||
| 1598 | break; | ||
| 1599 | default: | ||
| 1600 | /* get rid of existing socket, and retry */ | ||
| 1601 | xs_close(xprt); | ||
| 1602 | break; | ||
| 1603 | } | ||
| 1604 | } | ||
| 1605 | out: | ||
| 1606 | xprt_wake_pending_tasks(xprt, status); | ||
| 1607 | out_clear: | ||
| 1608 | xprt_clear_connecting(xprt); | ||
| 1609 | } | ||
| 1339 | 1610 | ||
| 1340 | sk->sk_user_data = xprt; | 1611 | /** |
| 1341 | transport->old_data_ready = sk->sk_data_ready; | 1612 | * xs_tcp_connect_worker6 - connect a TCP socket to a remote endpoint |
| 1342 | transport->old_state_change = sk->sk_state_change; | 1613 | * @work: RPC transport to connect |
| 1343 | transport->old_write_space = sk->sk_write_space; | 1614 | * |
| 1344 | sk->sk_data_ready = xs_tcp_data_ready; | 1615 | * Invoked by a work queue tasklet. |
| 1345 | sk->sk_state_change = xs_tcp_state_change; | 1616 | */ |
| 1346 | sk->sk_write_space = xs_tcp_write_space; | 1617 | static void xs_tcp_connect_worker6(struct work_struct *work) |
| 1347 | sk->sk_allocation = GFP_ATOMIC; | 1618 | { |
| 1619 | struct sock_xprt *transport = | ||
| 1620 | container_of(work, struct sock_xprt, connect_worker.work); | ||
| 1621 | struct rpc_xprt *xprt = &transport->xprt; | ||
| 1622 | struct socket *sock = transport->sock; | ||
| 1623 | int err, status = -EIO; | ||
| 1348 | 1624 | ||
| 1349 | /* socket options */ | 1625 | if (xprt->shutdown || !xprt_bound(xprt)) |
| 1350 | sk->sk_userlocks |= SOCK_BINDPORT_LOCK; | 1626 | goto out; |
| 1351 | sock_reset_flag(sk, SOCK_LINGER); | ||
| 1352 | tcp_sk(sk)->linger2 = 0; | ||
| 1353 | tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF; | ||
| 1354 | 1627 | ||
| 1355 | xprt_clear_connected(xprt); | 1628 | if (!sock) { |
| 1629 | /* start from scratch */ | ||
| 1630 | if ((err = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) { | ||
| 1631 | dprintk("RPC: can't create TCP transport socket (%d).\n", -err); | ||
| 1632 | goto out; | ||
| 1633 | } | ||
| 1634 | xs_reclassify_socket6(sock); | ||
| 1356 | 1635 | ||
| 1357 | /* Reset to new socket */ | 1636 | if (xs_bind6(transport, sock) < 0) { |
| 1358 | transport->sock = sock; | 1637 | sock_release(sock); |
| 1359 | transport->inet = sk; | 1638 | goto out; |
| 1639 | } | ||
| 1640 | } else | ||
| 1641 | /* "close" the socket, preserving the local port */ | ||
| 1642 | xs_tcp_reuse_connection(xprt); | ||
| 1360 | 1643 | ||
| 1361 | write_unlock_bh(&sk->sk_callback_lock); | 1644 | dprintk("RPC: worker connecting xprt %p to address: %s\n", |
| 1362 | } | 1645 | xprt, xprt->address_strings[RPC_DISPLAY_ALL]); |
| 1363 | 1646 | ||
| 1364 | /* Tell the socket layer to start connecting... */ | 1647 | status = xs_tcp_finish_connecting(xprt, sock); |
| 1365 | xprt->stat.connect_count++; | ||
| 1366 | xprt->stat.connect_start = jiffies; | ||
| 1367 | status = kernel_connect(sock, (struct sockaddr *) &xprt->addr, | ||
| 1368 | xprt->addrlen, O_NONBLOCK); | ||
| 1369 | dprintk("RPC: %p connect status %d connected %d sock state %d\n", | 1648 | dprintk("RPC: %p connect status %d connected %d sock state %d\n", |
| 1370 | xprt, -status, xprt_connected(xprt), | 1649 | xprt, -status, xprt_connected(xprt), sock->sk->sk_state); |
| 1371 | sock->sk->sk_state); | ||
| 1372 | if (status < 0) { | 1650 | if (status < 0) { |
| 1373 | switch (status) { | 1651 | switch (status) { |
| 1374 | case -EINPROGRESS: | 1652 | case -EINPROGRESS: |
| @@ -1508,7 +1786,8 @@ static struct rpc_xprt_ops xs_tcp_ops = { | |||
| 1508 | .print_stats = xs_tcp_print_stats, | 1786 | .print_stats = xs_tcp_print_stats, |
| 1509 | }; | 1787 | }; |
| 1510 | 1788 | ||
| 1511 | static struct rpc_xprt *xs_setup_xprt(struct rpc_xprtsock_create *args, unsigned int slot_table_size) | 1789 | static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args, |
| 1790 | unsigned int slot_table_size) | ||
| 1512 | { | 1791 | { |
| 1513 | struct rpc_xprt *xprt; | 1792 | struct rpc_xprt *xprt; |
| 1514 | struct sock_xprt *new; | 1793 | struct sock_xprt *new; |
| @@ -1549,8 +1828,9 @@ static struct rpc_xprt *xs_setup_xprt(struct rpc_xprtsock_create *args, unsigned | |||
| 1549 | * @args: rpc transport creation arguments | 1828 | * @args: rpc transport creation arguments |
| 1550 | * | 1829 | * |
| 1551 | */ | 1830 | */ |
| 1552 | struct rpc_xprt *xs_setup_udp(struct rpc_xprtsock_create *args) | 1831 | struct rpc_xprt *xs_setup_udp(struct xprt_create *args) |
| 1553 | { | 1832 | { |
| 1833 | struct sockaddr *addr = args->dstaddr; | ||
| 1554 | struct rpc_xprt *xprt; | 1834 | struct rpc_xprt *xprt; |
| 1555 | struct sock_xprt *transport; | 1835 | struct sock_xprt *transport; |
| 1556 | 1836 | ||
| @@ -1559,15 +1839,11 @@ struct rpc_xprt *xs_setup_udp(struct rpc_xprtsock_create *args) | |||
| 1559 | return xprt; | 1839 | return xprt; |
| 1560 | transport = container_of(xprt, struct sock_xprt, xprt); | 1840 | transport = container_of(xprt, struct sock_xprt, xprt); |
| 1561 | 1841 | ||
| 1562 | if (ntohs(((struct sockaddr_in *)args->dstaddr)->sin_port) != 0) | ||
| 1563 | xprt_set_bound(xprt); | ||
| 1564 | |||
| 1565 | xprt->prot = IPPROTO_UDP; | 1842 | xprt->prot = IPPROTO_UDP; |
| 1566 | xprt->tsh_size = 0; | 1843 | xprt->tsh_size = 0; |
| 1567 | /* XXX: header size can vary due to auth type, IPv6, etc. */ | 1844 | /* XXX: header size can vary due to auth type, IPv6, etc. */ |
| 1568 | xprt->max_payload = (1U << 16) - (MAX_HEADER << 3); | 1845 | xprt->max_payload = (1U << 16) - (MAX_HEADER << 3); |
| 1569 | 1846 | ||
| 1570 | INIT_DELAYED_WORK(&transport->connect_worker, xs_udp_connect_worker); | ||
| 1571 | xprt->bind_timeout = XS_BIND_TO; | 1847 | xprt->bind_timeout = XS_BIND_TO; |
| 1572 | xprt->connect_timeout = XS_UDP_CONN_TO; | 1848 | xprt->connect_timeout = XS_UDP_CONN_TO; |
| 1573 | xprt->reestablish_timeout = XS_UDP_REEST_TO; | 1849 | xprt->reestablish_timeout = XS_UDP_REEST_TO; |
| @@ -1580,11 +1856,37 @@ struct rpc_xprt *xs_setup_udp(struct rpc_xprtsock_create *args) | |||
| 1580 | else | 1856 | else |
| 1581 | xprt_set_timeout(&xprt->timeout, 5, 5 * HZ); | 1857 | xprt_set_timeout(&xprt->timeout, 5, 5 * HZ); |
| 1582 | 1858 | ||
| 1583 | xs_format_peer_addresses(xprt); | 1859 | switch (addr->sa_family) { |
| 1860 | case AF_INET: | ||
| 1861 | if (((struct sockaddr_in *)addr)->sin_port != htons(0)) | ||
| 1862 | xprt_set_bound(xprt); | ||
| 1863 | |||
| 1864 | INIT_DELAYED_WORK(&transport->connect_worker, | ||
| 1865 | xs_udp_connect_worker4); | ||
| 1866 | xs_format_ipv4_peer_addresses(xprt); | ||
| 1867 | break; | ||
| 1868 | case AF_INET6: | ||
| 1869 | if (((struct sockaddr_in6 *)addr)->sin6_port != htons(0)) | ||
| 1870 | xprt_set_bound(xprt); | ||
| 1871 | |||
| 1872 | INIT_DELAYED_WORK(&transport->connect_worker, | ||
| 1873 | xs_udp_connect_worker6); | ||
| 1874 | xs_format_ipv6_peer_addresses(xprt); | ||
| 1875 | break; | ||
| 1876 | default: | ||
| 1877 | kfree(xprt); | ||
| 1878 | return ERR_PTR(-EAFNOSUPPORT); | ||
| 1879 | } | ||
| 1880 | |||
| 1584 | dprintk("RPC: set up transport to address %s\n", | 1881 | dprintk("RPC: set up transport to address %s\n", |
| 1585 | xprt->address_strings[RPC_DISPLAY_ALL]); | 1882 | xprt->address_strings[RPC_DISPLAY_ALL]); |
| 1586 | 1883 | ||
| 1587 | return xprt; | 1884 | if (try_module_get(THIS_MODULE)) |
| 1885 | return xprt; | ||
| 1886 | |||
| 1887 | kfree(xprt->slot); | ||
| 1888 | kfree(xprt); | ||
| 1889 | return ERR_PTR(-EINVAL); | ||
| 1588 | } | 1890 | } |
| 1589 | 1891 | ||
| 1590 | /** | 1892 | /** |
| @@ -1592,8 +1894,9 @@ struct rpc_xprt *xs_setup_udp(struct rpc_xprtsock_create *args) | |||
| 1592 | * @args: rpc transport creation arguments | 1894 | * @args: rpc transport creation arguments |
| 1593 | * | 1895 | * |
| 1594 | */ | 1896 | */ |
| 1595 | struct rpc_xprt *xs_setup_tcp(struct rpc_xprtsock_create *args) | 1897 | struct rpc_xprt *xs_setup_tcp(struct xprt_create *args) |
| 1596 | { | 1898 | { |
| 1899 | struct sockaddr *addr = args->dstaddr; | ||
| 1597 | struct rpc_xprt *xprt; | 1900 | struct rpc_xprt *xprt; |
| 1598 | struct sock_xprt *transport; | 1901 | struct sock_xprt *transport; |
| 1599 | 1902 | ||
| @@ -1602,14 +1905,10 @@ struct rpc_xprt *xs_setup_tcp(struct rpc_xprtsock_create *args) | |||
| 1602 | return xprt; | 1905 | return xprt; |
| 1603 | transport = container_of(xprt, struct sock_xprt, xprt); | 1906 | transport = container_of(xprt, struct sock_xprt, xprt); |
| 1604 | 1907 | ||
| 1605 | if (ntohs(((struct sockaddr_in *)args->dstaddr)->sin_port) != 0) | ||
| 1606 | xprt_set_bound(xprt); | ||
| 1607 | |||
| 1608 | xprt->prot = IPPROTO_TCP; | 1908 | xprt->prot = IPPROTO_TCP; |
| 1609 | xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32); | 1909 | xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32); |
| 1610 | xprt->max_payload = RPC_MAX_FRAGMENT_SIZE; | 1910 | xprt->max_payload = RPC_MAX_FRAGMENT_SIZE; |
| 1611 | 1911 | ||
| 1612 | INIT_DELAYED_WORK(&transport->connect_worker, xs_tcp_connect_worker); | ||
| 1613 | xprt->bind_timeout = XS_BIND_TO; | 1912 | xprt->bind_timeout = XS_BIND_TO; |
| 1614 | xprt->connect_timeout = XS_TCP_CONN_TO; | 1913 | xprt->connect_timeout = XS_TCP_CONN_TO; |
| 1615 | xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO; | 1914 | xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO; |
| @@ -1622,15 +1921,55 @@ struct rpc_xprt *xs_setup_tcp(struct rpc_xprtsock_create *args) | |||
| 1622 | else | 1921 | else |
| 1623 | xprt_set_timeout(&xprt->timeout, 2, 60 * HZ); | 1922 | xprt_set_timeout(&xprt->timeout, 2, 60 * HZ); |
| 1624 | 1923 | ||
| 1625 | xs_format_peer_addresses(xprt); | 1924 | switch (addr->sa_family) { |
| 1925 | case AF_INET: | ||
| 1926 | if (((struct sockaddr_in *)addr)->sin_port != htons(0)) | ||
| 1927 | xprt_set_bound(xprt); | ||
| 1928 | |||
| 1929 | INIT_DELAYED_WORK(&transport->connect_worker, xs_tcp_connect_worker4); | ||
| 1930 | xs_format_ipv4_peer_addresses(xprt); | ||
| 1931 | break; | ||
| 1932 | case AF_INET6: | ||
| 1933 | if (((struct sockaddr_in6 *)addr)->sin6_port != htons(0)) | ||
| 1934 | xprt_set_bound(xprt); | ||
| 1935 | |||
| 1936 | INIT_DELAYED_WORK(&transport->connect_worker, xs_tcp_connect_worker6); | ||
| 1937 | xs_format_ipv6_peer_addresses(xprt); | ||
| 1938 | break; | ||
| 1939 | default: | ||
| 1940 | kfree(xprt); | ||
| 1941 | return ERR_PTR(-EAFNOSUPPORT); | ||
| 1942 | } | ||
| 1943 | |||
| 1626 | dprintk("RPC: set up transport to address %s\n", | 1944 | dprintk("RPC: set up transport to address %s\n", |
| 1627 | xprt->address_strings[RPC_DISPLAY_ALL]); | 1945 | xprt->address_strings[RPC_DISPLAY_ALL]); |
| 1628 | 1946 | ||
| 1629 | return xprt; | 1947 | if (try_module_get(THIS_MODULE)) |
| 1948 | return xprt; | ||
| 1949 | |||
| 1950 | kfree(xprt->slot); | ||
| 1951 | kfree(xprt); | ||
| 1952 | return ERR_PTR(-EINVAL); | ||
| 1630 | } | 1953 | } |
| 1631 | 1954 | ||
| 1955 | static struct xprt_class xs_udp_transport = { | ||
| 1956 | .list = LIST_HEAD_INIT(xs_udp_transport.list), | ||
| 1957 | .name = "udp", | ||
| 1958 | .owner = THIS_MODULE, | ||
| 1959 | .ident = IPPROTO_UDP, | ||
| 1960 | .setup = xs_setup_udp, | ||
| 1961 | }; | ||
| 1962 | |||
| 1963 | static struct xprt_class xs_tcp_transport = { | ||
| 1964 | .list = LIST_HEAD_INIT(xs_tcp_transport.list), | ||
| 1965 | .name = "tcp", | ||
| 1966 | .owner = THIS_MODULE, | ||
| 1967 | .ident = IPPROTO_TCP, | ||
| 1968 | .setup = xs_setup_tcp, | ||
| 1969 | }; | ||
| 1970 | |||
| 1632 | /** | 1971 | /** |
| 1633 | * init_socket_xprt - set up xprtsock's sysctls | 1972 | * init_socket_xprt - set up xprtsock's sysctls, register with RPC client |
| 1634 | * | 1973 | * |
| 1635 | */ | 1974 | */ |
| 1636 | int init_socket_xprt(void) | 1975 | int init_socket_xprt(void) |
| @@ -1640,11 +1979,14 @@ int init_socket_xprt(void) | |||
| 1640 | sunrpc_table_header = register_sysctl_table(sunrpc_table); | 1979 | sunrpc_table_header = register_sysctl_table(sunrpc_table); |
| 1641 | #endif | 1980 | #endif |
| 1642 | 1981 | ||
| 1982 | xprt_register_transport(&xs_udp_transport); | ||
| 1983 | xprt_register_transport(&xs_tcp_transport); | ||
| 1984 | |||
| 1643 | return 0; | 1985 | return 0; |
| 1644 | } | 1986 | } |
| 1645 | 1987 | ||
| 1646 | /** | 1988 | /** |
| 1647 | * cleanup_socket_xprt - remove xprtsock's sysctls | 1989 | * cleanup_socket_xprt - remove xprtsock's sysctls, unregister |
| 1648 | * | 1990 | * |
| 1649 | */ | 1991 | */ |
| 1650 | void cleanup_socket_xprt(void) | 1992 | void cleanup_socket_xprt(void) |
| @@ -1655,4 +1997,7 @@ void cleanup_socket_xprt(void) | |||
| 1655 | sunrpc_table_header = NULL; | 1997 | sunrpc_table_header = NULL; |
| 1656 | } | 1998 | } |
| 1657 | #endif | 1999 | #endif |
| 2000 | |||
| 2001 | xprt_unregister_transport(&xs_udp_transport); | ||
| 2002 | xprt_unregister_transport(&xs_tcp_transport); | ||
| 1658 | } | 2003 | } |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 3c3fff33d1ce..cf76150e623e 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -3932,7 +3932,7 @@ out: | |||
| 3932 | } | 3932 | } |
| 3933 | 3933 | ||
| 3934 | static unsigned int selinux_ip_postroute_last(unsigned int hooknum, | 3934 | static unsigned int selinux_ip_postroute_last(unsigned int hooknum, |
| 3935 | struct sk_buff **pskb, | 3935 | struct sk_buff *skb, |
| 3936 | const struct net_device *in, | 3936 | const struct net_device *in, |
| 3937 | const struct net_device *out, | 3937 | const struct net_device *out, |
| 3938 | int (*okfn)(struct sk_buff *), | 3938 | int (*okfn)(struct sk_buff *), |
| @@ -3941,7 +3941,6 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum, | |||
| 3941 | char *addrp; | 3941 | char *addrp; |
| 3942 | int len, err = 0; | 3942 | int len, err = 0; |
| 3943 | struct sock *sk; | 3943 | struct sock *sk; |
| 3944 | struct sk_buff *skb = *pskb; | ||
| 3945 | struct avc_audit_data ad; | 3944 | struct avc_audit_data ad; |
| 3946 | struct net_device *dev = (struct net_device *)out; | 3945 | struct net_device *dev = (struct net_device *)out; |
| 3947 | struct sk_security_struct *sksec; | 3946 | struct sk_security_struct *sksec; |
| @@ -3977,23 +3976,23 @@ out: | |||
| 3977 | } | 3976 | } |
| 3978 | 3977 | ||
| 3979 | static unsigned int selinux_ipv4_postroute_last(unsigned int hooknum, | 3978 | static unsigned int selinux_ipv4_postroute_last(unsigned int hooknum, |
| 3980 | struct sk_buff **pskb, | 3979 | struct sk_buff *skb, |
| 3981 | const struct net_device *in, | 3980 | const struct net_device *in, |
| 3982 | const struct net_device *out, | 3981 | const struct net_device *out, |
| 3983 | int (*okfn)(struct sk_buff *)) | 3982 | int (*okfn)(struct sk_buff *)) |
| 3984 | { | 3983 | { |
| 3985 | return selinux_ip_postroute_last(hooknum, pskb, in, out, okfn, PF_INET); | 3984 | return selinux_ip_postroute_last(hooknum, skb, in, out, okfn, PF_INET); |
| 3986 | } | 3985 | } |
| 3987 | 3986 | ||
| 3988 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 3987 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
| 3989 | 3988 | ||
| 3990 | static unsigned int selinux_ipv6_postroute_last(unsigned int hooknum, | 3989 | static unsigned int selinux_ipv6_postroute_last(unsigned int hooknum, |
| 3991 | struct sk_buff **pskb, | 3990 | struct sk_buff *skb, |
| 3992 | const struct net_device *in, | 3991 | const struct net_device *in, |
| 3993 | const struct net_device *out, | 3992 | const struct net_device *out, |
| 3994 | int (*okfn)(struct sk_buff *)) | 3993 | int (*okfn)(struct sk_buff *)) |
| 3995 | { | 3994 | { |
| 3996 | return selinux_ip_postroute_last(hooknum, pskb, in, out, okfn, PF_INET6); | 3995 | return selinux_ip_postroute_last(hooknum, skb, in, out, okfn, PF_INET6); |
| 3997 | } | 3996 | } |
| 3998 | 3997 | ||
| 3999 | #endif /* IPV6 */ | 3998 | #endif /* IPV6 */ |
