diff options
author | Johannes Berg <johannes.berg@intel.com> | 2013-03-20 09:30:42 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-03-20 09:30:42 -0400 |
commit | fc8fed0eae4c2d1756ffd2f4f86c3e4357bebb08 (patch) | |
tree | 0b0d53c6976925edfb4f33d73fdfd3022f938b29 | |
parent | c451e6d4bd290db5290cfa7f9c4079386373645b (diff) | |
parent | 856a850afdd778fad7ded4240d333a8c3b05b136 (diff) |
Merge remote-tracking branch 'wireless-next/master' into iwlwifi-next
281 files changed, 10550 insertions, 3716 deletions
diff --git a/Documentation/device-mapper/dm-raid.txt b/Documentation/device-mapper/dm-raid.txt index 56fb62b09fc5..b428556197c9 100644 --- a/Documentation/device-mapper/dm-raid.txt +++ b/Documentation/device-mapper/dm-raid.txt | |||
@@ -30,6 +30,7 @@ The target is named "raid" and it accepts the following parameters: | |||
30 | raid10 Various RAID10 inspired algorithms chosen by additional params | 30 | raid10 Various RAID10 inspired algorithms chosen by additional params |
31 | - RAID10: Striped Mirrors (aka 'Striping on top of mirrors') | 31 | - RAID10: Striped Mirrors (aka 'Striping on top of mirrors') |
32 | - RAID1E: Integrated Adjacent Stripe Mirroring | 32 | - RAID1E: Integrated Adjacent Stripe Mirroring |
33 | - RAID1E: Integrated Offset Stripe Mirroring | ||
33 | - and other similar RAID10 variants | 34 | - and other similar RAID10 variants |
34 | 35 | ||
35 | Reference: Chapter 4 of | 36 | Reference: Chapter 4 of |
@@ -64,15 +65,15 @@ The target is named "raid" and it accepts the following parameters: | |||
64 | synchronisation state for each region. | 65 | synchronisation state for each region. |
65 | 66 | ||
66 | [raid10_copies <# copies>] | 67 | [raid10_copies <# copies>] |
67 | [raid10_format near] | 68 | [raid10_format <near|far|offset>] |
68 | These two options are used to alter the default layout of | 69 | These two options are used to alter the default layout of |
69 | a RAID10 configuration. The number of copies is can be | 70 | a RAID10 configuration. The number of copies is can be |
70 | specified, but the default is 2. There are other variations | 71 | specified, but the default is 2. There are also three |
71 | to how the copies are laid down - the default and only current | 72 | variations to how the copies are laid down - the default |
72 | option is "near". Near copies are what most people think of | 73 | is "near". Near copies are what most people think of with |
73 | with respect to mirroring. If these options are left | 74 | respect to mirroring. If these options are left unspecified, |
74 | unspecified, or 'raid10_copies 2' and/or 'raid10_format near' | 75 | or 'raid10_copies 2' and/or 'raid10_format near' are given, |
75 | are given, then the layouts for 2, 3 and 4 devices are: | 76 | then the layouts for 2, 3 and 4 devices are: |
76 | 2 drives 3 drives 4 drives | 77 | 2 drives 3 drives 4 drives |
77 | -------- ---------- -------------- | 78 | -------- ---------- -------------- |
78 | A1 A1 A1 A1 A2 A1 A1 A2 A2 | 79 | A1 A1 A1 A1 A2 A1 A1 A2 A2 |
@@ -85,6 +86,33 @@ The target is named "raid" and it accepts the following parameters: | |||
85 | 3-device layout is what might be called a 'RAID1E - Integrated | 86 | 3-device layout is what might be called a 'RAID1E - Integrated |
86 | Adjacent Stripe Mirroring'. | 87 | Adjacent Stripe Mirroring'. |
87 | 88 | ||
89 | If 'raid10_copies 2' and 'raid10_format far', then the layouts | ||
90 | for 2, 3 and 4 devices are: | ||
91 | 2 drives 3 drives 4 drives | ||
92 | -------- -------------- -------------------- | ||
93 | A1 A2 A1 A2 A3 A1 A2 A3 A4 | ||
94 | A3 A4 A4 A5 A6 A5 A6 A7 A8 | ||
95 | A5 A6 A7 A8 A9 A9 A10 A11 A12 | ||
96 | .. .. .. .. .. .. .. .. .. | ||
97 | A2 A1 A3 A1 A2 A2 A1 A4 A3 | ||
98 | A4 A3 A6 A4 A5 A6 A5 A8 A7 | ||
99 | A6 A5 A9 A7 A8 A10 A9 A12 A11 | ||
100 | .. .. .. .. .. .. .. .. .. | ||
101 | |||
102 | If 'raid10_copies 2' and 'raid10_format offset', then the | ||
103 | layouts for 2, 3 and 4 devices are: | ||
104 | 2 drives 3 drives 4 drives | ||
105 | -------- ------------ ----------------- | ||
106 | A1 A2 A1 A2 A3 A1 A2 A3 A4 | ||
107 | A2 A1 A3 A1 A2 A2 A1 A4 A3 | ||
108 | A3 A4 A4 A5 A6 A5 A6 A7 A8 | ||
109 | A4 A3 A6 A4 A5 A6 A5 A8 A7 | ||
110 | A5 A6 A7 A8 A9 A9 A10 A11 A12 | ||
111 | A6 A5 A9 A7 A8 A10 A9 A12 A11 | ||
112 | .. .. .. .. .. .. .. .. .. | ||
113 | Here we see layouts closely akin to 'RAID1E - Integrated | ||
114 | Offset Stripe Mirroring'. | ||
115 | |||
88 | <#raid_devs>: The number of devices composing the array. | 116 | <#raid_devs>: The number of devices composing the array. |
89 | Each device consists of two entries. The first is the device | 117 | Each device consists of two entries. The first is the device |
90 | containing the metadata (if any); the second is the one containing the | 118 | containing the metadata (if any); the second is the one containing the |
@@ -142,3 +170,5 @@ Version History | |||
142 | 1.3.0 Added support for RAID 10 | 170 | 1.3.0 Added support for RAID 10 |
143 | 1.3.1 Allow device replacement/rebuild for RAID 10 | 171 | 1.3.1 Allow device replacement/rebuild for RAID 10 |
144 | 1.3.2 Fix/improve redundancy checking for RAID10 | 172 | 1.3.2 Fix/improve redundancy checking for RAID10 |
173 | 1.4.0 Non-functional change. Removes arg from mapping function. | ||
174 | 1.4.1 Add RAID10 "far" and "offset" algorithm support. | ||
diff --git a/Documentation/networking/tuntap.txt b/Documentation/networking/tuntap.txt index c0aab985bad9..949d5dcdd9a3 100644 --- a/Documentation/networking/tuntap.txt +++ b/Documentation/networking/tuntap.txt | |||
@@ -105,6 +105,83 @@ Copyright (C) 1999-2000 Maxim Krasnyansky <max_mk@yahoo.com> | |||
105 | Proto [2 bytes] | 105 | Proto [2 bytes] |
106 | Raw protocol(IP, IPv6, etc) frame. | 106 | Raw protocol(IP, IPv6, etc) frame. |
107 | 107 | ||
108 | 3.3 Multiqueue tuntap interface: | ||
109 | |||
110 | From version 3.8, Linux supports multiqueue tuntap which can uses multiple | ||
111 | file descriptors (queues) to parallelize packets sending or receiving. The | ||
112 | device allocation is the same as before, and if user wants to create multiple | ||
113 | queues, TUNSETIFF with the same device name must be called many times with | ||
114 | IFF_MULTI_QUEUE flag. | ||
115 | |||
116 | char *dev should be the name of the device, queues is the number of queues to | ||
117 | be created, fds is used to store and return the file descriptors (queues) | ||
118 | created to the caller. Each file descriptor were served as the interface of a | ||
119 | queue which could be accessed by userspace. | ||
120 | |||
121 | #include <linux/if.h> | ||
122 | #include <linux/if_tun.h> | ||
123 | |||
124 | int tun_alloc_mq(char *dev, int queues, int *fds) | ||
125 | { | ||
126 | struct ifreq ifr; | ||
127 | int fd, err, i; | ||
128 | |||
129 | if (!dev) | ||
130 | return -1; | ||
131 | |||
132 | memset(&ifr, 0, sizeof(ifr)); | ||
133 | /* Flags: IFF_TUN - TUN device (no Ethernet headers) | ||
134 | * IFF_TAP - TAP device | ||
135 | * | ||
136 | * IFF_NO_PI - Do not provide packet information | ||
137 | * IFF_MULTI_QUEUE - Create a queue of multiqueue device | ||
138 | */ | ||
139 | ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_MULTI_QUEUE; | ||
140 | strcpy(ifr.ifr_name, dev); | ||
141 | |||
142 | for (i = 0; i < queues; i++) { | ||
143 | if ((fd = open("/dev/net/tun", O_RDWR)) < 0) | ||
144 | goto err; | ||
145 | err = ioctl(fd, TUNSETIFF, (void *)&ifr); | ||
146 | if (err) { | ||
147 | close(fd); | ||
148 | goto err; | ||
149 | } | ||
150 | fds[i] = fd; | ||
151 | } | ||
152 | |||
153 | return 0; | ||
154 | err: | ||
155 | for (--i; i >= 0; i--) | ||
156 | close(fds[i]); | ||
157 | return err; | ||
158 | } | ||
159 | |||
160 | A new ioctl(TUNSETQUEUE) were introduced to enable or disable a queue. When | ||
161 | calling it with IFF_DETACH_QUEUE flag, the queue were disabled. And when | ||
162 | calling it with IFF_ATTACH_QUEUE flag, the queue were enabled. The queue were | ||
163 | enabled by default after it was created through TUNSETIFF. | ||
164 | |||
165 | fd is the file descriptor (queue) that we want to enable or disable, when | ||
166 | enable is true we enable it, otherwise we disable it | ||
167 | |||
168 | #include <linux/if.h> | ||
169 | #include <linux/if_tun.h> | ||
170 | |||
171 | int tun_set_queue(int fd, int enable) | ||
172 | { | ||
173 | struct ifreq ifr; | ||
174 | |||
175 | memset(&ifr, 0, sizeof(ifr)); | ||
176 | |||
177 | if (enable) | ||
178 | ifr.ifr_flags = IFF_ATTACH_QUEUE; | ||
179 | else | ||
180 | ifr.ifr_flags = IFF_DETACH_QUEUE; | ||
181 | |||
182 | return ioctl(fd, TUNSETQUEUE, (void *)&ifr); | ||
183 | } | ||
184 | |||
108 | Universal TUN/TAP device driver Frequently Asked Question. | 185 | Universal TUN/TAP device driver Frequently Asked Question. |
109 | 186 | ||
110 | 1. What platforms are supported by TUN/TAP driver ? | 187 | 1. What platforms are supported by TUN/TAP driver ? |
diff --git a/MAINTAINERS b/MAINTAINERS index e95b1e944eb7..143507e7f6df 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -114,12 +114,6 @@ Maintainers List (try to look for most precise areas first) | |||
114 | 114 | ||
115 | ----------------------------------- | 115 | ----------------------------------- |
116 | 116 | ||
117 | 3C505 NETWORK DRIVER | ||
118 | M: Philip Blundell <philb@gnu.org> | ||
119 | L: netdev@vger.kernel.org | ||
120 | S: Maintained | ||
121 | F: drivers/net/ethernet/i825xx/3c505* | ||
122 | |||
123 | 3C59X NETWORK DRIVER | 117 | 3C59X NETWORK DRIVER |
124 | M: Steffen Klassert <klassert@mathematik.tu-chemnitz.de> | 118 | M: Steffen Klassert <klassert@mathematik.tu-chemnitz.de> |
125 | L: netdev@vger.kernel.org | 119 | L: netdev@vger.kernel.org |
@@ -2361,12 +2355,6 @@ W: http://www.arm.linux.org.uk/ | |||
2361 | S: Maintained | 2355 | S: Maintained |
2362 | F: drivers/video/cyber2000fb.* | 2356 | F: drivers/video/cyber2000fb.* |
2363 | 2357 | ||
2364 | CYCLADES 2X SYNC CARD DRIVER | ||
2365 | M: Arnaldo Carvalho de Melo <acme@ghostprotocols.net> | ||
2366 | W: http://oops.ghostprotocols.net:81/blog | ||
2367 | S: Maintained | ||
2368 | F: drivers/net/wan/cycx* | ||
2369 | |||
2370 | CYCLADES ASYNC MUX DRIVER | 2358 | CYCLADES ASYNC MUX DRIVER |
2371 | W: http://www.cyclades.com/ | 2359 | W: http://www.cyclades.com/ |
2372 | S: Orphan | 2360 | S: Orphan |
@@ -3067,12 +3055,6 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git | |||
3067 | F: drivers/video/s1d13xxxfb.c | 3055 | F: drivers/video/s1d13xxxfb.c |
3068 | F: include/video/s1d13xxxfb.h | 3056 | F: include/video/s1d13xxxfb.h |
3069 | 3057 | ||
3070 | ETHEREXPRESS-16 NETWORK DRIVER | ||
3071 | M: Philip Blundell <philb@gnu.org> | ||
3072 | L: netdev@vger.kernel.org | ||
3073 | S: Maintained | ||
3074 | F: drivers/net/ethernet/i825xx/eexpress.* | ||
3075 | |||
3076 | ETHERNET BRIDGE | 3058 | ETHERNET BRIDGE |
3077 | M: Stephen Hemminger <stephen@networkplumber.org> | 3059 | M: Stephen Hemminger <stephen@networkplumber.org> |
3078 | L: bridge@lists.linux-foundation.org | 3060 | L: bridge@lists.linux-foundation.org |
@@ -8504,7 +8486,7 @@ F: drivers/usb/gadget/*uvc*.c | |||
8504 | F: drivers/usb/gadget/webcam.c | 8486 | F: drivers/usb/gadget/webcam.c |
8505 | 8487 | ||
8506 | USB WIRELESS RNDIS DRIVER (rndis_wlan) | 8488 | USB WIRELESS RNDIS DRIVER (rndis_wlan) |
8507 | M: Jussi Kivilinna <jussi.kivilinna@mbnet.fi> | 8489 | M: Jussi Kivilinna <jussi.kivilinna@iki.fi> |
8508 | L: linux-wireless@vger.kernel.org | 8490 | L: linux-wireless@vger.kernel.org |
8509 | S: Maintained | 8491 | S: Maintained |
8510 | F: drivers/net/wireless/rndis_wlan.c | 8492 | F: drivers/net/wireless/rndis_wlan.c |
diff --git a/arch/powerpc/crypto/sha1-powerpc-asm.S b/arch/powerpc/crypto/sha1-powerpc-asm.S index a5f8264d2d3c..125e16520061 100644 --- a/arch/powerpc/crypto/sha1-powerpc-asm.S +++ b/arch/powerpc/crypto/sha1-powerpc-asm.S | |||
@@ -113,7 +113,7 @@ | |||
113 | STEPUP4((t)+16, fn) | 113 | STEPUP4((t)+16, fn) |
114 | 114 | ||
115 | _GLOBAL(powerpc_sha_transform) | 115 | _GLOBAL(powerpc_sha_transform) |
116 | PPC_STLU r1,-STACKFRAMESIZE(r1) | 116 | PPC_STLU r1,-INT_FRAME_SIZE(r1) |
117 | SAVE_8GPRS(14, r1) | 117 | SAVE_8GPRS(14, r1) |
118 | SAVE_10GPRS(22, r1) | 118 | SAVE_10GPRS(22, r1) |
119 | 119 | ||
@@ -175,5 +175,5 @@ _GLOBAL(powerpc_sha_transform) | |||
175 | 175 | ||
176 | REST_8GPRS(14, r1) | 176 | REST_8GPRS(14, r1) |
177 | REST_10GPRS(22, r1) | 177 | REST_10GPRS(22, r1) |
178 | addi r1,r1,STACKFRAMESIZE | 178 | addi r1,r1,INT_FRAME_SIZE |
179 | blr | 179 | blr |
diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h index ef918a2328bb..08bd299c75b1 100644 --- a/arch/powerpc/include/asm/bitops.h +++ b/arch/powerpc/include/asm/bitops.h | |||
@@ -52,8 +52,6 @@ | |||
52 | #define smp_mb__before_clear_bit() smp_mb() | 52 | #define smp_mb__before_clear_bit() smp_mb() |
53 | #define smp_mb__after_clear_bit() smp_mb() | 53 | #define smp_mb__after_clear_bit() smp_mb() |
54 | 54 | ||
55 | #define BITOP_LE_SWIZZLE ((BITS_PER_LONG-1) & ~0x7) | ||
56 | |||
57 | /* Macro for generating the ***_bits() functions */ | 55 | /* Macro for generating the ***_bits() functions */ |
58 | #define DEFINE_BITOP(fn, op, prefix, postfix) \ | 56 | #define DEFINE_BITOP(fn, op, prefix, postfix) \ |
59 | static __inline__ void fn(unsigned long mask, \ | 57 | static __inline__ void fn(unsigned long mask, \ |
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index e66586122030..c9c67fc888c9 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h | |||
@@ -266,7 +266,8 @@ | |||
266 | #define SPRN_HSRR0 0x13A /* Hypervisor Save/Restore 0 */ | 266 | #define SPRN_HSRR0 0x13A /* Hypervisor Save/Restore 0 */ |
267 | #define SPRN_HSRR1 0x13B /* Hypervisor Save/Restore 1 */ | 267 | #define SPRN_HSRR1 0x13B /* Hypervisor Save/Restore 1 */ |
268 | #define SPRN_FSCR 0x099 /* Facility Status & Control Register */ | 268 | #define SPRN_FSCR 0x099 /* Facility Status & Control Register */ |
269 | #define FSCR_TAR (1<<8) /* Enable Target Adress Register */ | 269 | #define FSCR_TAR (1 << (63-55)) /* Enable Target Address Register */ |
270 | #define FSCR_DSCR (1 << (63-61)) /* Enable Data Stream Control Register */ | ||
270 | #define SPRN_TAR 0x32f /* Target Address Register */ | 271 | #define SPRN_TAR 0x32f /* Target Address Register */ |
271 | #define SPRN_LPCR 0x13E /* LPAR Control Register */ | 272 | #define SPRN_LPCR 0x13E /* LPAR Control Register */ |
272 | #define LPCR_VPM0 (1ul << (63-0)) | 273 | #define LPCR_VPM0 (1ul << (63-0)) |
diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h index 535b6d8a41cc..ebbec52d21bd 100644 --- a/arch/powerpc/include/asm/systbl.h +++ b/arch/powerpc/include/asm/systbl.h | |||
@@ -358,3 +358,4 @@ SYSCALL_SPU(setns) | |||
358 | COMPAT_SYS(process_vm_readv) | 358 | COMPAT_SYS(process_vm_readv) |
359 | COMPAT_SYS(process_vm_writev) | 359 | COMPAT_SYS(process_vm_writev) |
360 | SYSCALL(finit_module) | 360 | SYSCALL(finit_module) |
361 | SYSCALL(ni_syscall) /* sys_kcmp */ | ||
diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h index f25b5c45c435..1487f0f12293 100644 --- a/arch/powerpc/include/asm/unistd.h +++ b/arch/powerpc/include/asm/unistd.h | |||
@@ -12,7 +12,7 @@ | |||
12 | #include <uapi/asm/unistd.h> | 12 | #include <uapi/asm/unistd.h> |
13 | 13 | ||
14 | 14 | ||
15 | #define __NR_syscalls 354 | 15 | #define __NR_syscalls 355 |
16 | 16 | ||
17 | #define __NR__exit __NR_exit | 17 | #define __NR__exit __NR_exit |
18 | #define NR_syscalls __NR_syscalls | 18 | #define NR_syscalls __NR_syscalls |
diff --git a/arch/powerpc/include/uapi/asm/unistd.h b/arch/powerpc/include/uapi/asm/unistd.h index 8c478c6c6b1e..74cb4d72d673 100644 --- a/arch/powerpc/include/uapi/asm/unistd.h +++ b/arch/powerpc/include/uapi/asm/unistd.h | |||
@@ -376,6 +376,7 @@ | |||
376 | #define __NR_process_vm_readv 351 | 376 | #define __NR_process_vm_readv 351 |
377 | #define __NR_process_vm_writev 352 | 377 | #define __NR_process_vm_writev 352 |
378 | #define __NR_finit_module 353 | 378 | #define __NR_finit_module 353 |
379 | #define __NR_kcmp 354 | ||
379 | 380 | ||
380 | 381 | ||
381 | #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */ | 382 | #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */ |
diff --git a/arch/powerpc/kernel/cpu_setup_power.S b/arch/powerpc/kernel/cpu_setup_power.S index d29facbf9a28..ea847abb0d0a 100644 --- a/arch/powerpc/kernel/cpu_setup_power.S +++ b/arch/powerpc/kernel/cpu_setup_power.S | |||
@@ -48,6 +48,7 @@ _GLOBAL(__restore_cpu_power7) | |||
48 | 48 | ||
49 | _GLOBAL(__setup_cpu_power8) | 49 | _GLOBAL(__setup_cpu_power8) |
50 | mflr r11 | 50 | mflr r11 |
51 | bl __init_FSCR | ||
51 | bl __init_hvmode_206 | 52 | bl __init_hvmode_206 |
52 | mtlr r11 | 53 | mtlr r11 |
53 | beqlr | 54 | beqlr |
@@ -56,13 +57,13 @@ _GLOBAL(__setup_cpu_power8) | |||
56 | mfspr r3,SPRN_LPCR | 57 | mfspr r3,SPRN_LPCR |
57 | oris r3, r3, LPCR_AIL_3@h | 58 | oris r3, r3, LPCR_AIL_3@h |
58 | bl __init_LPCR | 59 | bl __init_LPCR |
59 | bl __init_FSCR | ||
60 | bl __init_TLB | 60 | bl __init_TLB |
61 | mtlr r11 | 61 | mtlr r11 |
62 | blr | 62 | blr |
63 | 63 | ||
64 | _GLOBAL(__restore_cpu_power8) | 64 | _GLOBAL(__restore_cpu_power8) |
65 | mflr r11 | 65 | mflr r11 |
66 | bl __init_FSCR | ||
66 | mfmsr r3 | 67 | mfmsr r3 |
67 | rldicl. r0,r3,4,63 | 68 | rldicl. r0,r3,4,63 |
68 | beqlr | 69 | beqlr |
@@ -115,7 +116,7 @@ __init_LPCR: | |||
115 | 116 | ||
116 | __init_FSCR: | 117 | __init_FSCR: |
117 | mfspr r3,SPRN_FSCR | 118 | mfspr r3,SPRN_FSCR |
118 | ori r3,r3,FSCR_TAR | 119 | ori r3,r3,FSCR_TAR|FSCR_DSCR |
119 | mtspr SPRN_FSCR,r3 | 120 | mtspr SPRN_FSCR,r3 |
120 | blr | 121 | blr |
121 | 122 | ||
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index a8a5361fb70c..87ef8f5ee5bc 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
@@ -74,13 +74,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) \ | |||
74 | mflr r10 ; \ | 74 | mflr r10 ; \ |
75 | ld r12,PACAKBASE(r13) ; \ | 75 | ld r12,PACAKBASE(r13) ; \ |
76 | LOAD_HANDLER(r12, system_call_entry_direct) ; \ | 76 | LOAD_HANDLER(r12, system_call_entry_direct) ; \ |
77 | mtlr r12 ; \ | 77 | mtctr r12 ; \ |
78 | mfspr r12,SPRN_SRR1 ; \ | 78 | mfspr r12,SPRN_SRR1 ; \ |
79 | /* Re-use of r13... No spare regs to do this */ \ | 79 | /* Re-use of r13... No spare regs to do this */ \ |
80 | li r13,MSR_RI ; \ | 80 | li r13,MSR_RI ; \ |
81 | mtmsrd r13,1 ; \ | 81 | mtmsrd r13,1 ; \ |
82 | GET_PACA(r13) ; /* get r13 back */ \ | 82 | GET_PACA(r13) ; /* get r13 back */ \ |
83 | blr ; | 83 | bctr ; |
84 | #else | 84 | #else |
85 | /* We can branch directly */ | 85 | /* We can branch directly */ |
86 | #define SYSCALL_PSERIES_2_DIRECT \ | 86 | #define SYSCALL_PSERIES_2_DIRECT \ |
diff --git a/arch/powerpc/platforms/pseries/hvcserver.c b/arch/powerpc/platforms/pseries/hvcserver.c index fcf4b4cbeaf3..4557e91626c4 100644 --- a/arch/powerpc/platforms/pseries/hvcserver.c +++ b/arch/powerpc/platforms/pseries/hvcserver.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/list.h> | 23 | #include <linux/list.h> |
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/string.h> | ||
26 | 27 | ||
27 | #include <asm/hvcall.h> | 28 | #include <asm/hvcall.h> |
28 | #include <asm/hvcserver.h> | 29 | #include <asm/hvcserver.h> |
@@ -188,9 +189,9 @@ int hvcs_get_partner_info(uint32_t unit_address, struct list_head *head, | |||
188 | = (unsigned int)last_p_partition_ID; | 189 | = (unsigned int)last_p_partition_ID; |
189 | 190 | ||
190 | /* copy the Null-term char too */ | 191 | /* copy the Null-term char too */ |
191 | strncpy(&next_partner_info->location_code[0], | 192 | strlcpy(&next_partner_info->location_code[0], |
192 | (char *)&pi_buff[2], | 193 | (char *)&pi_buff[2], |
193 | strlen((char *)&pi_buff[2]) + 1); | 194 | sizeof(next_partner_info->location_code)); |
194 | 195 | ||
195 | list_add_tail(&(next_partner_info->node), head); | 196 | list_add_tail(&(next_partner_info->node), head); |
196 | next_partner_info = NULL; | 197 | next_partner_info = NULL; |
diff --git a/drivers/bcma/core.c b/drivers/bcma/core.c index 03bbe104338f..17b26ce7e051 100644 --- a/drivers/bcma/core.c +++ b/drivers/bcma/core.c | |||
@@ -104,7 +104,13 @@ void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status, bool on) | |||
104 | if (i) | 104 | if (i) |
105 | bcma_err(core->bus, "PLL enable timeout\n"); | 105 | bcma_err(core->bus, "PLL enable timeout\n"); |
106 | } else { | 106 | } else { |
107 | bcma_warn(core->bus, "Disabling PLL not supported yet!\n"); | 107 | /* |
108 | * Mask the PLL but don't wait for it to be disabled. PLL may be | ||
109 | * shared between cores and will be still up if there is another | ||
110 | * core using it. | ||
111 | */ | ||
112 | bcma_mask32(core, BCMA_CLKCTLST, ~req); | ||
113 | bcma_read32(core, BCMA_CLKCTLST); | ||
108 | } | 114 | } |
109 | } | 115 | } |
110 | EXPORT_SYMBOL_GPL(bcma_core_pll_ctl); | 116 | EXPORT_SYMBOL_GPL(bcma_core_pll_ctl); |
diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c index d3bde6cec927..30629a3d44cc 100644 --- a/drivers/bcma/driver_pci_host.c +++ b/drivers/bcma/driver_pci_host.c | |||
@@ -404,6 +404,8 @@ void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) | |||
404 | return; | 404 | return; |
405 | } | 405 | } |
406 | 406 | ||
407 | spin_lock_init(&pc_host->cfgspace_lock); | ||
408 | |||
407 | pc->host_controller = pc_host; | 409 | pc->host_controller = pc_host; |
408 | pc_host->pci_controller.io_resource = &pc_host->io_resource; | 410 | pc_host->pci_controller.io_resource = &pc_host->io_resource; |
409 | pc_host->pci_controller.mem_resource = &pc_host->mem_resource; | 411 | pc_host->pci_controller.mem_resource = &pc_host->mem_resource; |
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 9a6188add590..f72f52b4b1dd 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c | |||
@@ -120,6 +120,11 @@ static int bcma_register_cores(struct bcma_bus *bus) | |||
120 | continue; | 120 | continue; |
121 | } | 121 | } |
122 | 122 | ||
123 | /* Only first GMAC core on BCM4706 is connected and working */ | ||
124 | if (core->id.id == BCMA_CORE_4706_MAC_GBIT && | ||
125 | core->core_unit > 0) | ||
126 | continue; | ||
127 | |||
123 | core->dev.release = bcma_release_core_dev; | 128 | core->dev.release = bcma_release_core_dev; |
124 | core->dev.bus = &bcma_bus_type; | 129 | core->dev.bus = &bcma_bus_type; |
125 | dev_set_name(&core->dev, "bcma%d:%d", bus->num, dev_id); | 130 | dev_set_name(&core->dev, "bcma%d:%d", bus->num, dev_id); |
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index a8a41e07a221..b282af181b44 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c | |||
@@ -74,8 +74,10 @@ static struct usb_device_id ath3k_table[] = { | |||
74 | 74 | ||
75 | /* Atheros AR3012 with sflash firmware*/ | 75 | /* Atheros AR3012 with sflash firmware*/ |
76 | { USB_DEVICE(0x0CF3, 0x3004) }, | 76 | { USB_DEVICE(0x0CF3, 0x3004) }, |
77 | { USB_DEVICE(0x0CF3, 0x3008) }, | ||
77 | { USB_DEVICE(0x0CF3, 0x311D) }, | 78 | { USB_DEVICE(0x0CF3, 0x311D) }, |
78 | { USB_DEVICE(0x13d3, 0x3375) }, | 79 | { USB_DEVICE(0x13d3, 0x3375) }, |
80 | { USB_DEVICE(0x04CA, 0x3004) }, | ||
79 | { USB_DEVICE(0x04CA, 0x3005) }, | 81 | { USB_DEVICE(0x04CA, 0x3005) }, |
80 | { USB_DEVICE(0x04CA, 0x3006) }, | 82 | { USB_DEVICE(0x04CA, 0x3006) }, |
81 | { USB_DEVICE(0x04CA, 0x3008) }, | 83 | { USB_DEVICE(0x04CA, 0x3008) }, |
@@ -106,8 +108,10 @@ static struct usb_device_id ath3k_blist_tbl[] = { | |||
106 | 108 | ||
107 | /* Atheros AR3012 with sflash firmware*/ | 109 | /* Atheros AR3012 with sflash firmware*/ |
108 | { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, | 110 | { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, |
111 | { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, | ||
109 | { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, | 112 | { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, |
110 | { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, | 113 | { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, |
114 | { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, | ||
111 | { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, | 115 | { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, |
112 | { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, | 116 | { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, |
113 | { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, | 117 | { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, |
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 7e351e345476..e547851870e7 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c | |||
@@ -132,8 +132,10 @@ static struct usb_device_id blacklist_table[] = { | |||
132 | 132 | ||
133 | /* Atheros 3012 with sflash firmware */ | 133 | /* Atheros 3012 with sflash firmware */ |
134 | { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, | 134 | { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, |
135 | { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, | ||
135 | { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, | 136 | { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, |
136 | { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, | 137 | { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, |
138 | { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, | ||
137 | { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, | 139 | { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, |
138 | { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, | 140 | { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, |
139 | { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, | 141 | { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, |
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 1bafb40ec8a2..69ae5972713c 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/init.h> | 40 | #include <linux/init.h> |
41 | #include <linux/miscdevice.h> | 41 | #include <linux/miscdevice.h> |
42 | #include <linux/delay.h> | 42 | #include <linux/delay.h> |
43 | #include <linux/slab.h> | ||
43 | #include <asm/uaccess.h> | 44 | #include <asm/uaccess.h> |
44 | 45 | ||
45 | 46 | ||
@@ -52,8 +53,12 @@ static struct hwrng *current_rng; | |||
52 | static LIST_HEAD(rng_list); | 53 | static LIST_HEAD(rng_list); |
53 | static DEFINE_MUTEX(rng_mutex); | 54 | static DEFINE_MUTEX(rng_mutex); |
54 | static int data_avail; | 55 | static int data_avail; |
55 | static u8 rng_buffer[SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES] | 56 | static u8 *rng_buffer; |
56 | __cacheline_aligned; | 57 | |
58 | static size_t rng_buffer_size(void) | ||
59 | { | ||
60 | return SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES; | ||
61 | } | ||
57 | 62 | ||
58 | static inline int hwrng_init(struct hwrng *rng) | 63 | static inline int hwrng_init(struct hwrng *rng) |
59 | { | 64 | { |
@@ -116,7 +121,7 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf, | |||
116 | 121 | ||
117 | if (!data_avail) { | 122 | if (!data_avail) { |
118 | bytes_read = rng_get_data(current_rng, rng_buffer, | 123 | bytes_read = rng_get_data(current_rng, rng_buffer, |
119 | sizeof(rng_buffer), | 124 | rng_buffer_size(), |
120 | !(filp->f_flags & O_NONBLOCK)); | 125 | !(filp->f_flags & O_NONBLOCK)); |
121 | if (bytes_read < 0) { | 126 | if (bytes_read < 0) { |
122 | err = bytes_read; | 127 | err = bytes_read; |
@@ -307,6 +312,14 @@ int hwrng_register(struct hwrng *rng) | |||
307 | 312 | ||
308 | mutex_lock(&rng_mutex); | 313 | mutex_lock(&rng_mutex); |
309 | 314 | ||
315 | /* kmalloc makes this safe for virt_to_page() in virtio_rng.c */ | ||
316 | err = -ENOMEM; | ||
317 | if (!rng_buffer) { | ||
318 | rng_buffer = kmalloc(rng_buffer_size(), GFP_KERNEL); | ||
319 | if (!rng_buffer) | ||
320 | goto out_unlock; | ||
321 | } | ||
322 | |||
310 | /* Must not register two RNGs with the same name. */ | 323 | /* Must not register two RNGs with the same name. */ |
311 | err = -EEXIST; | 324 | err = -EEXIST; |
312 | list_for_each_entry(tmp, &rng_list, list) { | 325 | list_for_each_entry(tmp, &rng_list, list) { |
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c index fce2000eec31..1110478dd0fd 100644 --- a/drivers/connector/cn_proc.c +++ b/drivers/connector/cn_proc.c | |||
@@ -313,6 +313,12 @@ static void cn_proc_mcast_ctl(struct cn_msg *msg, | |||
313 | (task_active_pid_ns(current) != &init_pid_ns)) | 313 | (task_active_pid_ns(current) != &init_pid_ns)) |
314 | return; | 314 | return; |
315 | 315 | ||
316 | /* Can only change if privileged. */ | ||
317 | if (!capable(CAP_NET_ADMIN)) { | ||
318 | err = EPERM; | ||
319 | goto out; | ||
320 | } | ||
321 | |||
316 | mc_op = (enum proc_cn_mcast_op *)msg->data; | 322 | mc_op = (enum proc_cn_mcast_op *)msg->data; |
317 | switch (*mc_op) { | 323 | switch (*mc_op) { |
318 | case PROC_CN_MCAST_LISTEN: | 324 | case PROC_CN_MCAST_LISTEN: |
@@ -325,6 +331,8 @@ static void cn_proc_mcast_ctl(struct cn_msg *msg, | |||
325 | err = EINVAL; | 331 | err = EINVAL; |
326 | break; | 332 | break; |
327 | } | 333 | } |
334 | |||
335 | out: | ||
328 | cn_proc_ack(err, msg->seq, msg->ack); | 336 | cn_proc_ack(err, msg->seq, msg->ack); |
329 | } | 337 | } |
330 | 338 | ||
diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c index 6f2306db8591..f9dbd503fc40 100644 --- a/drivers/gpio/gpio-ich.c +++ b/drivers/gpio/gpio-ich.c | |||
@@ -128,9 +128,9 @@ static int ichx_read_bit(int reg, unsigned nr) | |||
128 | return data & (1 << bit) ? 1 : 0; | 128 | return data & (1 << bit) ? 1 : 0; |
129 | } | 129 | } |
130 | 130 | ||
131 | static int ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr) | 131 | static bool ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr) |
132 | { | 132 | { |
133 | return (ichx_priv.use_gpio & (1 << (nr / 32))) ? 0 : -ENXIO; | 133 | return ichx_priv.use_gpio & (1 << (nr / 32)); |
134 | } | 134 | } |
135 | 135 | ||
136 | static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) | 136 | static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) |
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index fff9786cdc64..c2534d62911c 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -88,13 +88,14 @@ static int gpiod_request(struct gpio_desc *desc, const char *label); | |||
88 | static void gpiod_free(struct gpio_desc *desc); | 88 | static void gpiod_free(struct gpio_desc *desc); |
89 | static int gpiod_direction_input(struct gpio_desc *desc); | 89 | static int gpiod_direction_input(struct gpio_desc *desc); |
90 | static int gpiod_direction_output(struct gpio_desc *desc, int value); | 90 | static int gpiod_direction_output(struct gpio_desc *desc, int value); |
91 | static int gpiod_get_direction(const struct gpio_desc *desc); | ||
91 | static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce); | 92 | static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce); |
92 | static int gpiod_get_value_cansleep(struct gpio_desc *desc); | 93 | static int gpiod_get_value_cansleep(const struct gpio_desc *desc); |
93 | static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value); | 94 | static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value); |
94 | static int gpiod_get_value(struct gpio_desc *desc); | 95 | static int gpiod_get_value(const struct gpio_desc *desc); |
95 | static void gpiod_set_value(struct gpio_desc *desc, int value); | 96 | static void gpiod_set_value(struct gpio_desc *desc, int value); |
96 | static int gpiod_cansleep(struct gpio_desc *desc); | 97 | static int gpiod_cansleep(const struct gpio_desc *desc); |
97 | static int gpiod_to_irq(struct gpio_desc *desc); | 98 | static int gpiod_to_irq(const struct gpio_desc *desc); |
98 | static int gpiod_export(struct gpio_desc *desc, bool direction_may_change); | 99 | static int gpiod_export(struct gpio_desc *desc, bool direction_may_change); |
99 | static int gpiod_export_link(struct device *dev, const char *name, | 100 | static int gpiod_export_link(struct device *dev, const char *name, |
100 | struct gpio_desc *desc); | 101 | struct gpio_desc *desc); |
@@ -171,12 +172,12 @@ static int gpio_ensure_requested(struct gpio_desc *desc) | |||
171 | return 0; | 172 | return 0; |
172 | } | 173 | } |
173 | 174 | ||
174 | /* caller holds gpio_lock *OR* gpio is marked as requested */ | 175 | static struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc) |
175 | static struct gpio_chip *gpiod_to_chip(struct gpio_desc *desc) | ||
176 | { | 176 | { |
177 | return desc->chip; | 177 | return desc ? desc->chip : NULL; |
178 | } | 178 | } |
179 | 179 | ||
180 | /* caller holds gpio_lock *OR* gpio is marked as requested */ | ||
180 | struct gpio_chip *gpio_to_chip(unsigned gpio) | 181 | struct gpio_chip *gpio_to_chip(unsigned gpio) |
181 | { | 182 | { |
182 | return gpiod_to_chip(gpio_to_desc(gpio)); | 183 | return gpiod_to_chip(gpio_to_desc(gpio)); |
@@ -207,7 +208,7 @@ static int gpiochip_find_base(int ngpio) | |||
207 | } | 208 | } |
208 | 209 | ||
209 | /* caller ensures gpio is valid and requested, chip->get_direction may sleep */ | 210 | /* caller ensures gpio is valid and requested, chip->get_direction may sleep */ |
210 | static int gpiod_get_direction(struct gpio_desc *desc) | 211 | static int gpiod_get_direction(const struct gpio_desc *desc) |
211 | { | 212 | { |
212 | struct gpio_chip *chip; | 213 | struct gpio_chip *chip; |
213 | unsigned offset; | 214 | unsigned offset; |
@@ -223,11 +224,13 @@ static int gpiod_get_direction(struct gpio_desc *desc) | |||
223 | if (status > 0) { | 224 | if (status > 0) { |
224 | /* GPIOF_DIR_IN, or other positive */ | 225 | /* GPIOF_DIR_IN, or other positive */ |
225 | status = 1; | 226 | status = 1; |
226 | clear_bit(FLAG_IS_OUT, &desc->flags); | 227 | /* FLAG_IS_OUT is just a cache of the result of get_direction(), |
228 | * so it does not affect constness per se */ | ||
229 | clear_bit(FLAG_IS_OUT, &((struct gpio_desc *)desc)->flags); | ||
227 | } | 230 | } |
228 | if (status == 0) { | 231 | if (status == 0) { |
229 | /* GPIOF_DIR_OUT */ | 232 | /* GPIOF_DIR_OUT */ |
230 | set_bit(FLAG_IS_OUT, &desc->flags); | 233 | set_bit(FLAG_IS_OUT, &((struct gpio_desc *)desc)->flags); |
231 | } | 234 | } |
232 | return status; | 235 | return status; |
233 | } | 236 | } |
@@ -263,7 +266,7 @@ static DEFINE_MUTEX(sysfs_lock); | |||
263 | static ssize_t gpio_direction_show(struct device *dev, | 266 | static ssize_t gpio_direction_show(struct device *dev, |
264 | struct device_attribute *attr, char *buf) | 267 | struct device_attribute *attr, char *buf) |
265 | { | 268 | { |
266 | struct gpio_desc *desc = dev_get_drvdata(dev); | 269 | const struct gpio_desc *desc = dev_get_drvdata(dev); |
267 | ssize_t status; | 270 | ssize_t status; |
268 | 271 | ||
269 | mutex_lock(&sysfs_lock); | 272 | mutex_lock(&sysfs_lock); |
@@ -654,6 +657,11 @@ static ssize_t export_store(struct class *class, | |||
654 | goto done; | 657 | goto done; |
655 | 658 | ||
656 | desc = gpio_to_desc(gpio); | 659 | desc = gpio_to_desc(gpio); |
660 | /* reject invalid GPIOs */ | ||
661 | if (!desc) { | ||
662 | pr_warn("%s: invalid GPIO %ld\n", __func__, gpio); | ||
663 | return -EINVAL; | ||
664 | } | ||
657 | 665 | ||
658 | /* No extra locking here; FLAG_SYSFS just signifies that the | 666 | /* No extra locking here; FLAG_SYSFS just signifies that the |
659 | * request and export were done by on behalf of userspace, so | 667 | * request and export were done by on behalf of userspace, so |
@@ -690,12 +698,14 @@ static ssize_t unexport_store(struct class *class, | |||
690 | if (status < 0) | 698 | if (status < 0) |
691 | goto done; | 699 | goto done; |
692 | 700 | ||
693 | status = -EINVAL; | ||
694 | |||
695 | desc = gpio_to_desc(gpio); | 701 | desc = gpio_to_desc(gpio); |
696 | /* reject bogus commands (gpio_unexport ignores them) */ | 702 | /* reject bogus commands (gpio_unexport ignores them) */ |
697 | if (!desc) | 703 | if (!desc) { |
698 | goto done; | 704 | pr_warn("%s: invalid GPIO %ld\n", __func__, gpio); |
705 | return -EINVAL; | ||
706 | } | ||
707 | |||
708 | status = -EINVAL; | ||
699 | 709 | ||
700 | /* No extra locking here; FLAG_SYSFS just signifies that the | 710 | /* No extra locking here; FLAG_SYSFS just signifies that the |
701 | * request and export were done by on behalf of userspace, so | 711 | * request and export were done by on behalf of userspace, so |
@@ -846,8 +856,10 @@ static int gpiod_export_link(struct device *dev, const char *name, | |||
846 | { | 856 | { |
847 | int status = -EINVAL; | 857 | int status = -EINVAL; |
848 | 858 | ||
849 | if (!desc) | 859 | if (!desc) { |
850 | goto done; | 860 | pr_warn("%s: invalid GPIO\n", __func__); |
861 | return -EINVAL; | ||
862 | } | ||
851 | 863 | ||
852 | mutex_lock(&sysfs_lock); | 864 | mutex_lock(&sysfs_lock); |
853 | 865 | ||
@@ -865,7 +877,6 @@ static int gpiod_export_link(struct device *dev, const char *name, | |||
865 | 877 | ||
866 | mutex_unlock(&sysfs_lock); | 878 | mutex_unlock(&sysfs_lock); |
867 | 879 | ||
868 | done: | ||
869 | if (status) | 880 | if (status) |
870 | pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), | 881 | pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), |
871 | status); | 882 | status); |
@@ -896,8 +907,10 @@ static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value) | |||
896 | struct device *dev = NULL; | 907 | struct device *dev = NULL; |
897 | int status = -EINVAL; | 908 | int status = -EINVAL; |
898 | 909 | ||
899 | if (!desc) | 910 | if (!desc) { |
900 | goto done; | 911 | pr_warn("%s: invalid GPIO\n", __func__); |
912 | return -EINVAL; | ||
913 | } | ||
901 | 914 | ||
902 | mutex_lock(&sysfs_lock); | 915 | mutex_lock(&sysfs_lock); |
903 | 916 | ||
@@ -914,7 +927,6 @@ static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value) | |||
914 | unlock: | 927 | unlock: |
915 | mutex_unlock(&sysfs_lock); | 928 | mutex_unlock(&sysfs_lock); |
916 | 929 | ||
917 | done: | ||
918 | if (status) | 930 | if (status) |
919 | pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), | 931 | pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), |
920 | status); | 932 | status); |
@@ -940,8 +952,8 @@ static void gpiod_unexport(struct gpio_desc *desc) | |||
940 | struct device *dev = NULL; | 952 | struct device *dev = NULL; |
941 | 953 | ||
942 | if (!desc) { | 954 | if (!desc) { |
943 | status = -EINVAL; | 955 | pr_warn("%s: invalid GPIO\n", __func__); |
944 | goto done; | 956 | return; |
945 | } | 957 | } |
946 | 958 | ||
947 | mutex_lock(&sysfs_lock); | 959 | mutex_lock(&sysfs_lock); |
@@ -962,7 +974,7 @@ static void gpiod_unexport(struct gpio_desc *desc) | |||
962 | device_unregister(dev); | 974 | device_unregister(dev); |
963 | put_device(dev); | 975 | put_device(dev); |
964 | } | 976 | } |
965 | done: | 977 | |
966 | if (status) | 978 | if (status) |
967 | pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), | 979 | pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), |
968 | status); | 980 | status); |
@@ -1384,12 +1396,13 @@ static int gpiod_request(struct gpio_desc *desc, const char *label) | |||
1384 | int status = -EPROBE_DEFER; | 1396 | int status = -EPROBE_DEFER; |
1385 | unsigned long flags; | 1397 | unsigned long flags; |
1386 | 1398 | ||
1387 | spin_lock_irqsave(&gpio_lock, flags); | ||
1388 | |||
1389 | if (!desc) { | 1399 | if (!desc) { |
1390 | status = -EINVAL; | 1400 | pr_warn("%s: invalid GPIO\n", __func__); |
1391 | goto done; | 1401 | return -EINVAL; |
1392 | } | 1402 | } |
1403 | |||
1404 | spin_lock_irqsave(&gpio_lock, flags); | ||
1405 | |||
1393 | chip = desc->chip; | 1406 | chip = desc->chip; |
1394 | if (chip == NULL) | 1407 | if (chip == NULL) |
1395 | goto done; | 1408 | goto done; |
@@ -1432,8 +1445,7 @@ static int gpiod_request(struct gpio_desc *desc, const char *label) | |||
1432 | done: | 1445 | done: |
1433 | if (status) | 1446 | if (status) |
1434 | pr_debug("_gpio_request: gpio-%d (%s) status %d\n", | 1447 | pr_debug("_gpio_request: gpio-%d (%s) status %d\n", |
1435 | desc ? desc_to_gpio(desc) : -1, | 1448 | desc_to_gpio(desc), label ? : "?", status); |
1436 | label ? : "?", status); | ||
1437 | spin_unlock_irqrestore(&gpio_lock, flags); | 1449 | spin_unlock_irqrestore(&gpio_lock, flags); |
1438 | return status; | 1450 | return status; |
1439 | } | 1451 | } |
@@ -1616,10 +1628,13 @@ static int gpiod_direction_input(struct gpio_desc *desc) | |||
1616 | int status = -EINVAL; | 1628 | int status = -EINVAL; |
1617 | int offset; | 1629 | int offset; |
1618 | 1630 | ||
1631 | if (!desc) { | ||
1632 | pr_warn("%s: invalid GPIO\n", __func__); | ||
1633 | return -EINVAL; | ||
1634 | } | ||
1635 | |||
1619 | spin_lock_irqsave(&gpio_lock, flags); | 1636 | spin_lock_irqsave(&gpio_lock, flags); |
1620 | 1637 | ||
1621 | if (!desc) | ||
1622 | goto fail; | ||
1623 | chip = desc->chip; | 1638 | chip = desc->chip; |
1624 | if (!chip || !chip->get || !chip->direction_input) | 1639 | if (!chip || !chip->get || !chip->direction_input) |
1625 | goto fail; | 1640 | goto fail; |
@@ -1655,13 +1670,9 @@ lose: | |||
1655 | return status; | 1670 | return status; |
1656 | fail: | 1671 | fail: |
1657 | spin_unlock_irqrestore(&gpio_lock, flags); | 1672 | spin_unlock_irqrestore(&gpio_lock, flags); |
1658 | if (status) { | 1673 | if (status) |
1659 | int gpio = -1; | 1674 | pr_debug("%s: gpio-%d status %d\n", __func__, |
1660 | if (desc) | 1675 | desc_to_gpio(desc), status); |
1661 | gpio = desc_to_gpio(desc); | ||
1662 | pr_debug("%s: gpio-%d status %d\n", | ||
1663 | __func__, gpio, status); | ||
1664 | } | ||
1665 | return status; | 1676 | return status; |
1666 | } | 1677 | } |
1667 | 1678 | ||
@@ -1678,6 +1689,11 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value) | |||
1678 | int status = -EINVAL; | 1689 | int status = -EINVAL; |
1679 | int offset; | 1690 | int offset; |
1680 | 1691 | ||
1692 | if (!desc) { | ||
1693 | pr_warn("%s: invalid GPIO\n", __func__); | ||
1694 | return -EINVAL; | ||
1695 | } | ||
1696 | |||
1681 | /* Open drain pin should not be driven to 1 */ | 1697 | /* Open drain pin should not be driven to 1 */ |
1682 | if (value && test_bit(FLAG_OPEN_DRAIN, &desc->flags)) | 1698 | if (value && test_bit(FLAG_OPEN_DRAIN, &desc->flags)) |
1683 | return gpiod_direction_input(desc); | 1699 | return gpiod_direction_input(desc); |
@@ -1688,8 +1704,6 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value) | |||
1688 | 1704 | ||
1689 | spin_lock_irqsave(&gpio_lock, flags); | 1705 | spin_lock_irqsave(&gpio_lock, flags); |
1690 | 1706 | ||
1691 | if (!desc) | ||
1692 | goto fail; | ||
1693 | chip = desc->chip; | 1707 | chip = desc->chip; |
1694 | if (!chip || !chip->set || !chip->direction_output) | 1708 | if (!chip || !chip->set || !chip->direction_output) |
1695 | goto fail; | 1709 | goto fail; |
@@ -1725,13 +1739,9 @@ lose: | |||
1725 | return status; | 1739 | return status; |
1726 | fail: | 1740 | fail: |
1727 | spin_unlock_irqrestore(&gpio_lock, flags); | 1741 | spin_unlock_irqrestore(&gpio_lock, flags); |
1728 | if (status) { | 1742 | if (status) |
1729 | int gpio = -1; | 1743 | pr_debug("%s: gpio-%d status %d\n", __func__, |
1730 | if (desc) | 1744 | desc_to_gpio(desc), status); |
1731 | gpio = desc_to_gpio(desc); | ||
1732 | pr_debug("%s: gpio-%d status %d\n", | ||
1733 | __func__, gpio, status); | ||
1734 | } | ||
1735 | return status; | 1745 | return status; |
1736 | } | 1746 | } |
1737 | 1747 | ||
@@ -1753,10 +1763,13 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) | |||
1753 | int status = -EINVAL; | 1763 | int status = -EINVAL; |
1754 | int offset; | 1764 | int offset; |
1755 | 1765 | ||
1766 | if (!desc) { | ||
1767 | pr_warn("%s: invalid GPIO\n", __func__); | ||
1768 | return -EINVAL; | ||
1769 | } | ||
1770 | |||
1756 | spin_lock_irqsave(&gpio_lock, flags); | 1771 | spin_lock_irqsave(&gpio_lock, flags); |
1757 | 1772 | ||
1758 | if (!desc) | ||
1759 | goto fail; | ||
1760 | chip = desc->chip; | 1773 | chip = desc->chip; |
1761 | if (!chip || !chip->set || !chip->set_debounce) | 1774 | if (!chip || !chip->set || !chip->set_debounce) |
1762 | goto fail; | 1775 | goto fail; |
@@ -1776,13 +1789,9 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) | |||
1776 | 1789 | ||
1777 | fail: | 1790 | fail: |
1778 | spin_unlock_irqrestore(&gpio_lock, flags); | 1791 | spin_unlock_irqrestore(&gpio_lock, flags); |
1779 | if (status) { | 1792 | if (status) |
1780 | int gpio = -1; | 1793 | pr_debug("%s: gpio-%d status %d\n", __func__, |
1781 | if (desc) | 1794 | desc_to_gpio(desc), status); |
1782 | gpio = desc_to_gpio(desc); | ||
1783 | pr_debug("%s: gpio-%d status %d\n", | ||
1784 | __func__, gpio, status); | ||
1785 | } | ||
1786 | 1795 | ||
1787 | return status; | 1796 | return status; |
1788 | } | 1797 | } |
@@ -1824,12 +1833,14 @@ EXPORT_SYMBOL_GPL(gpio_set_debounce); | |||
1824 | * It returns the zero or nonzero value provided by the associated | 1833 | * It returns the zero or nonzero value provided by the associated |
1825 | * gpio_chip.get() method; or zero if no such method is provided. | 1834 | * gpio_chip.get() method; or zero if no such method is provided. |
1826 | */ | 1835 | */ |
1827 | static int gpiod_get_value(struct gpio_desc *desc) | 1836 | static int gpiod_get_value(const struct gpio_desc *desc) |
1828 | { | 1837 | { |
1829 | struct gpio_chip *chip; | 1838 | struct gpio_chip *chip; |
1830 | int value; | 1839 | int value; |
1831 | int offset; | 1840 | int offset; |
1832 | 1841 | ||
1842 | if (!desc) | ||
1843 | return 0; | ||
1833 | chip = desc->chip; | 1844 | chip = desc->chip; |
1834 | offset = gpio_chip_hwgpio(desc); | 1845 | offset = gpio_chip_hwgpio(desc); |
1835 | /* Should be using gpio_get_value_cansleep() */ | 1846 | /* Should be using gpio_get_value_cansleep() */ |
@@ -1912,6 +1923,8 @@ static void gpiod_set_value(struct gpio_desc *desc, int value) | |||
1912 | { | 1923 | { |
1913 | struct gpio_chip *chip; | 1924 | struct gpio_chip *chip; |
1914 | 1925 | ||
1926 | if (!desc) | ||
1927 | return; | ||
1915 | chip = desc->chip; | 1928 | chip = desc->chip; |
1916 | /* Should be using gpio_set_value_cansleep() */ | 1929 | /* Should be using gpio_set_value_cansleep() */ |
1917 | WARN_ON(chip->can_sleep); | 1930 | WARN_ON(chip->can_sleep); |
@@ -1938,8 +1951,10 @@ EXPORT_SYMBOL_GPL(__gpio_set_value); | |||
1938 | * This is used directly or indirectly to implement gpio_cansleep(). It | 1951 | * This is used directly or indirectly to implement gpio_cansleep(). It |
1939 | * returns nonzero if access reading or writing the GPIO value can sleep. | 1952 | * returns nonzero if access reading or writing the GPIO value can sleep. |
1940 | */ | 1953 | */ |
1941 | static int gpiod_cansleep(struct gpio_desc *desc) | 1954 | static int gpiod_cansleep(const struct gpio_desc *desc) |
1942 | { | 1955 | { |
1956 | if (!desc) | ||
1957 | return 0; | ||
1943 | /* only call this on GPIOs that are valid! */ | 1958 | /* only call this on GPIOs that are valid! */ |
1944 | return desc->chip->can_sleep; | 1959 | return desc->chip->can_sleep; |
1945 | } | 1960 | } |
@@ -1959,11 +1974,13 @@ EXPORT_SYMBOL_GPL(__gpio_cansleep); | |||
1959 | * It returns the number of the IRQ signaled by this (input) GPIO, | 1974 | * It returns the number of the IRQ signaled by this (input) GPIO, |
1960 | * or a negative errno. | 1975 | * or a negative errno. |
1961 | */ | 1976 | */ |
1962 | static int gpiod_to_irq(struct gpio_desc *desc) | 1977 | static int gpiod_to_irq(const struct gpio_desc *desc) |
1963 | { | 1978 | { |
1964 | struct gpio_chip *chip; | 1979 | struct gpio_chip *chip; |
1965 | int offset; | 1980 | int offset; |
1966 | 1981 | ||
1982 | if (!desc) | ||
1983 | return -EINVAL; | ||
1967 | chip = desc->chip; | 1984 | chip = desc->chip; |
1968 | offset = gpio_chip_hwgpio(desc); | 1985 | offset = gpio_chip_hwgpio(desc); |
1969 | return chip->to_irq ? chip->to_irq(chip, offset) : -ENXIO; | 1986 | return chip->to_irq ? chip->to_irq(chip, offset) : -ENXIO; |
@@ -1980,13 +1997,15 @@ EXPORT_SYMBOL_GPL(__gpio_to_irq); | |||
1980 | * Common examples include ones connected to I2C or SPI chips. | 1997 | * Common examples include ones connected to I2C or SPI chips. |
1981 | */ | 1998 | */ |
1982 | 1999 | ||
1983 | static int gpiod_get_value_cansleep(struct gpio_desc *desc) | 2000 | static int gpiod_get_value_cansleep(const struct gpio_desc *desc) |
1984 | { | 2001 | { |
1985 | struct gpio_chip *chip; | 2002 | struct gpio_chip *chip; |
1986 | int value; | 2003 | int value; |
1987 | int offset; | 2004 | int offset; |
1988 | 2005 | ||
1989 | might_sleep_if(extra_checks); | 2006 | might_sleep_if(extra_checks); |
2007 | if (!desc) | ||
2008 | return 0; | ||
1990 | chip = desc->chip; | 2009 | chip = desc->chip; |
1991 | offset = gpio_chip_hwgpio(desc); | 2010 | offset = gpio_chip_hwgpio(desc); |
1992 | value = chip->get ? chip->get(chip, offset) : 0; | 2011 | value = chip->get ? chip->get(chip, offset) : 0; |
@@ -2005,6 +2024,8 @@ static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value) | |||
2005 | struct gpio_chip *chip; | 2024 | struct gpio_chip *chip; |
2006 | 2025 | ||
2007 | might_sleep_if(extra_checks); | 2026 | might_sleep_if(extra_checks); |
2027 | if (!desc) | ||
2028 | return; | ||
2008 | chip = desc->chip; | 2029 | chip = desc->chip; |
2009 | trace_gpio_value(desc_to_gpio(desc), 0, value); | 2030 | trace_gpio_value(desc_to_gpio(desc), 0, value); |
2010 | if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) | 2031 | if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) |
diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c index 017c67ea3f4c..ead0a4fb7448 100644 --- a/drivers/isdn/hisax/st5481_usb.c +++ b/drivers/isdn/hisax/st5481_usb.c | |||
@@ -294,13 +294,13 @@ int st5481_setup_usb(struct st5481_adapter *adapter) | |||
294 | // Allocate URBs and buffers for interrupt endpoint | 294 | // Allocate URBs and buffers for interrupt endpoint |
295 | urb = usb_alloc_urb(0, GFP_KERNEL); | 295 | urb = usb_alloc_urb(0, GFP_KERNEL); |
296 | if (!urb) { | 296 | if (!urb) { |
297 | return -ENOMEM; | 297 | goto err1; |
298 | } | 298 | } |
299 | intr->urb = urb; | 299 | intr->urb = urb; |
300 | 300 | ||
301 | buf = kmalloc(INT_PKT_SIZE, GFP_KERNEL); | 301 | buf = kmalloc(INT_PKT_SIZE, GFP_KERNEL); |
302 | if (!buf) { | 302 | if (!buf) { |
303 | return -ENOMEM; | 303 | goto err2; |
304 | } | 304 | } |
305 | 305 | ||
306 | endpoint = &altsetting->endpoint[EP_INT-1]; | 306 | endpoint = &altsetting->endpoint[EP_INT-1]; |
@@ -313,6 +313,14 @@ int st5481_setup_usb(struct st5481_adapter *adapter) | |||
313 | endpoint->desc.bInterval); | 313 | endpoint->desc.bInterval); |
314 | 314 | ||
315 | return 0; | 315 | return 0; |
316 | err2: | ||
317 | usb_free_urb(intr->urb); | ||
318 | intr->urb = NULL; | ||
319 | err1: | ||
320 | usb_free_urb(ctrl->urb); | ||
321 | ctrl->urb = NULL; | ||
322 | |||
323 | return -ENOMEM; | ||
316 | } | 324 | } |
317 | 325 | ||
318 | /* | 326 | /* |
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index e30b490055aa..4d8d90b4fe78 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig | |||
@@ -154,17 +154,6 @@ config MD_RAID456 | |||
154 | 154 | ||
155 | If unsure, say Y. | 155 | If unsure, say Y. |
156 | 156 | ||
157 | config MULTICORE_RAID456 | ||
158 | bool "RAID-4/RAID-5/RAID-6 Multicore processing (EXPERIMENTAL)" | ||
159 | depends on MD_RAID456 | ||
160 | depends on SMP | ||
161 | depends on EXPERIMENTAL | ||
162 | ---help--- | ||
163 | Enable the raid456 module to dispatch per-stripe raid operations to a | ||
164 | thread pool. | ||
165 | |||
166 | If unsure, say N. | ||
167 | |||
168 | config MD_MULTIPATH | 157 | config MD_MULTIPATH |
169 | tristate "Multipath I/O support" | 158 | tristate "Multipath I/O support" |
170 | depends on BLK_DEV_MD | 159 | depends on BLK_DEV_MD |
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index 9a01d1e4c783..311e3d35b272 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c | |||
@@ -91,15 +91,44 @@ static struct raid_type { | |||
91 | {"raid6_nc", "RAID6 (N continue)", 2, 4, 6, ALGORITHM_ROTATING_N_CONTINUE} | 91 | {"raid6_nc", "RAID6 (N continue)", 2, 4, 6, ALGORITHM_ROTATING_N_CONTINUE} |
92 | }; | 92 | }; |
93 | 93 | ||
94 | static char *raid10_md_layout_to_format(int layout) | ||
95 | { | ||
96 | /* | ||
97 | * Bit 16 and 17 stand for "offset" and "use_far_sets" | ||
98 | * Refer to MD's raid10.c for details | ||
99 | */ | ||
100 | if ((layout & 0x10000) && (layout & 0x20000)) | ||
101 | return "offset"; | ||
102 | |||
103 | if ((layout & 0xFF) > 1) | ||
104 | return "near"; | ||
105 | |||
106 | return "far"; | ||
107 | } | ||
108 | |||
94 | static unsigned raid10_md_layout_to_copies(int layout) | 109 | static unsigned raid10_md_layout_to_copies(int layout) |
95 | { | 110 | { |
96 | return layout & 0xFF; | 111 | if ((layout & 0xFF) > 1) |
112 | return layout & 0xFF; | ||
113 | return (layout >> 8) & 0xFF; | ||
97 | } | 114 | } |
98 | 115 | ||
99 | static int raid10_format_to_md_layout(char *format, unsigned copies) | 116 | static int raid10_format_to_md_layout(char *format, unsigned copies) |
100 | { | 117 | { |
101 | /* 1 "far" copy, and 'copies' "near" copies */ | 118 | unsigned n = 1, f = 1; |
102 | return (1 << 8) | (copies & 0xFF); | 119 | |
120 | if (!strcmp("near", format)) | ||
121 | n = copies; | ||
122 | else | ||
123 | f = copies; | ||
124 | |||
125 | if (!strcmp("offset", format)) | ||
126 | return 0x30000 | (f << 8) | n; | ||
127 | |||
128 | if (!strcmp("far", format)) | ||
129 | return 0x20000 | (f << 8) | n; | ||
130 | |||
131 | return (f << 8) | n; | ||
103 | } | 132 | } |
104 | 133 | ||
105 | static struct raid_type *get_raid_type(char *name) | 134 | static struct raid_type *get_raid_type(char *name) |
@@ -352,6 +381,7 @@ static int validate_raid_redundancy(struct raid_set *rs) | |||
352 | { | 381 | { |
353 | unsigned i, rebuild_cnt = 0; | 382 | unsigned i, rebuild_cnt = 0; |
354 | unsigned rebuilds_per_group, copies, d; | 383 | unsigned rebuilds_per_group, copies, d; |
384 | unsigned group_size, last_group_start; | ||
355 | 385 | ||
356 | for (i = 0; i < rs->md.raid_disks; i++) | 386 | for (i = 0; i < rs->md.raid_disks; i++) |
357 | if (!test_bit(In_sync, &rs->dev[i].rdev.flags) || | 387 | if (!test_bit(In_sync, &rs->dev[i].rdev.flags) || |
@@ -379,9 +409,6 @@ static int validate_raid_redundancy(struct raid_set *rs) | |||
379 | * as long as the failed devices occur in different mirror | 409 | * as long as the failed devices occur in different mirror |
380 | * groups (i.e. different stripes). | 410 | * groups (i.e. different stripes). |
381 | * | 411 | * |
382 | * Right now, we only allow for "near" copies. When other | ||
383 | * formats are added, we will have to check those too. | ||
384 | * | ||
385 | * When checking "near" format, make sure no adjacent devices | 412 | * When checking "near" format, make sure no adjacent devices |
386 | * have failed beyond what can be handled. In addition to the | 413 | * have failed beyond what can be handled. In addition to the |
387 | * simple case where the number of devices is a multiple of the | 414 | * simple case where the number of devices is a multiple of the |
@@ -391,14 +418,41 @@ static int validate_raid_redundancy(struct raid_set *rs) | |||
391 | * A A B B C | 418 | * A A B B C |
392 | * C D D E E | 419 | * C D D E E |
393 | */ | 420 | */ |
394 | for (i = 0; i < rs->md.raid_disks * copies; i++) { | 421 | if (!strcmp("near", raid10_md_layout_to_format(rs->md.layout))) { |
395 | if (!(i % copies)) | 422 | for (i = 0; i < rs->md.raid_disks * copies; i++) { |
423 | if (!(i % copies)) | ||
424 | rebuilds_per_group = 0; | ||
425 | d = i % rs->md.raid_disks; | ||
426 | if ((!rs->dev[d].rdev.sb_page || | ||
427 | !test_bit(In_sync, &rs->dev[d].rdev.flags)) && | ||
428 | (++rebuilds_per_group >= copies)) | ||
429 | goto too_many; | ||
430 | } | ||
431 | break; | ||
432 | } | ||
433 | |||
434 | /* | ||
435 | * When checking "far" and "offset" formats, we need to ensure | ||
436 | * that the device that holds its copy is not also dead or | ||
437 | * being rebuilt. (Note that "far" and "offset" formats only | ||
438 | * support two copies right now. These formats also only ever | ||
439 | * use the 'use_far_sets' variant.) | ||
440 | * | ||
441 | * This check is somewhat complicated by the need to account | ||
442 | * for arrays that are not a multiple of (far) copies. This | ||
443 | * results in the need to treat the last (potentially larger) | ||
444 | * set differently. | ||
445 | */ | ||
446 | group_size = (rs->md.raid_disks / copies); | ||
447 | last_group_start = (rs->md.raid_disks / group_size) - 1; | ||
448 | last_group_start *= group_size; | ||
449 | for (i = 0; i < rs->md.raid_disks; i++) { | ||
450 | if (!(i % copies) && !(i > last_group_start)) | ||
396 | rebuilds_per_group = 0; | 451 | rebuilds_per_group = 0; |
397 | d = i % rs->md.raid_disks; | 452 | if ((!rs->dev[i].rdev.sb_page || |
398 | if ((!rs->dev[d].rdev.sb_page || | 453 | !test_bit(In_sync, &rs->dev[i].rdev.flags)) && |
399 | !test_bit(In_sync, &rs->dev[d].rdev.flags)) && | ||
400 | (++rebuilds_per_group >= copies)) | 454 | (++rebuilds_per_group >= copies)) |
401 | goto too_many; | 455 | goto too_many; |
402 | } | 456 | } |
403 | break; | 457 | break; |
404 | default: | 458 | default: |
@@ -433,7 +487,7 @@ too_many: | |||
433 | * | 487 | * |
434 | * RAID10-only options: | 488 | * RAID10-only options: |
435 | * [raid10_copies <# copies>] Number of copies. (Default: 2) | 489 | * [raid10_copies <# copies>] Number of copies. (Default: 2) |
436 | * [raid10_format <near>] Layout algorithm. (Default: near) | 490 | * [raid10_format <near|far|offset>] Layout algorithm. (Default: near) |
437 | */ | 491 | */ |
438 | static int parse_raid_params(struct raid_set *rs, char **argv, | 492 | static int parse_raid_params(struct raid_set *rs, char **argv, |
439 | unsigned num_raid_params) | 493 | unsigned num_raid_params) |
@@ -520,7 +574,9 @@ static int parse_raid_params(struct raid_set *rs, char **argv, | |||
520 | rs->ti->error = "'raid10_format' is an invalid parameter for this RAID type"; | 574 | rs->ti->error = "'raid10_format' is an invalid parameter for this RAID type"; |
521 | return -EINVAL; | 575 | return -EINVAL; |
522 | } | 576 | } |
523 | if (strcmp("near", argv[i])) { | 577 | if (strcmp("near", argv[i]) && |
578 | strcmp("far", argv[i]) && | ||
579 | strcmp("offset", argv[i])) { | ||
524 | rs->ti->error = "Invalid 'raid10_format' value given"; | 580 | rs->ti->error = "Invalid 'raid10_format' value given"; |
525 | return -EINVAL; | 581 | return -EINVAL; |
526 | } | 582 | } |
@@ -644,6 +700,15 @@ static int parse_raid_params(struct raid_set *rs, char **argv, | |||
644 | return -EINVAL; | 700 | return -EINVAL; |
645 | } | 701 | } |
646 | 702 | ||
703 | /* | ||
704 | * If the format is not "near", we only support | ||
705 | * two copies at the moment. | ||
706 | */ | ||
707 | if (strcmp("near", raid10_format) && (raid10_copies > 2)) { | ||
708 | rs->ti->error = "Too many copies for given RAID10 format."; | ||
709 | return -EINVAL; | ||
710 | } | ||
711 | |||
647 | /* (Len * #mirrors) / #devices */ | 712 | /* (Len * #mirrors) / #devices */ |
648 | sectors_per_dev = rs->ti->len * raid10_copies; | 713 | sectors_per_dev = rs->ti->len * raid10_copies; |
649 | sector_div(sectors_per_dev, rs->md.raid_disks); | 714 | sector_div(sectors_per_dev, rs->md.raid_disks); |
@@ -854,17 +919,30 @@ static int super_init_validation(struct mddev *mddev, struct md_rdev *rdev) | |||
854 | /* | 919 | /* |
855 | * Reshaping is not currently allowed | 920 | * Reshaping is not currently allowed |
856 | */ | 921 | */ |
857 | if ((le32_to_cpu(sb->level) != mddev->level) || | 922 | if (le32_to_cpu(sb->level) != mddev->level) { |
858 | (le32_to_cpu(sb->layout) != mddev->layout) || | 923 | DMERR("Reshaping arrays not yet supported. (RAID level change)"); |
859 | (le32_to_cpu(sb->stripe_sectors) != mddev->chunk_sectors)) { | 924 | return -EINVAL; |
860 | DMERR("Reshaping arrays not yet supported."); | 925 | } |
926 | if (le32_to_cpu(sb->layout) != mddev->layout) { | ||
927 | DMERR("Reshaping arrays not yet supported. (RAID layout change)"); | ||
928 | DMERR(" 0x%X vs 0x%X", le32_to_cpu(sb->layout), mddev->layout); | ||
929 | DMERR(" Old layout: %s w/ %d copies", | ||
930 | raid10_md_layout_to_format(le32_to_cpu(sb->layout)), | ||
931 | raid10_md_layout_to_copies(le32_to_cpu(sb->layout))); | ||
932 | DMERR(" New layout: %s w/ %d copies", | ||
933 | raid10_md_layout_to_format(mddev->layout), | ||
934 | raid10_md_layout_to_copies(mddev->layout)); | ||
935 | return -EINVAL; | ||
936 | } | ||
937 | if (le32_to_cpu(sb->stripe_sectors) != mddev->chunk_sectors) { | ||
938 | DMERR("Reshaping arrays not yet supported. (stripe sectors change)"); | ||
861 | return -EINVAL; | 939 | return -EINVAL; |
862 | } | 940 | } |
863 | 941 | ||
864 | /* We can only change the number of devices in RAID1 right now */ | 942 | /* We can only change the number of devices in RAID1 right now */ |
865 | if ((rs->raid_type->level != 1) && | 943 | if ((rs->raid_type->level != 1) && |
866 | (le32_to_cpu(sb->num_devices) != mddev->raid_disks)) { | 944 | (le32_to_cpu(sb->num_devices) != mddev->raid_disks)) { |
867 | DMERR("Reshaping arrays not yet supported."); | 945 | DMERR("Reshaping arrays not yet supported. (device count change)"); |
868 | return -EINVAL; | 946 | return -EINVAL; |
869 | } | 947 | } |
870 | 948 | ||
@@ -1329,7 +1407,8 @@ static void raid_status(struct dm_target *ti, status_type_t type, | |||
1329 | raid10_md_layout_to_copies(rs->md.layout)); | 1407 | raid10_md_layout_to_copies(rs->md.layout)); |
1330 | 1408 | ||
1331 | if (rs->print_flags & DMPF_RAID10_FORMAT) | 1409 | if (rs->print_flags & DMPF_RAID10_FORMAT) |
1332 | DMEMIT(" raid10_format near"); | 1410 | DMEMIT(" raid10_format %s", |
1411 | raid10_md_layout_to_format(rs->md.layout)); | ||
1333 | 1412 | ||
1334 | DMEMIT(" %d", rs->md.raid_disks); | 1413 | DMEMIT(" %d", rs->md.raid_disks); |
1335 | for (i = 0; i < rs->md.raid_disks; i++) { | 1414 | for (i = 0; i < rs->md.raid_disks; i++) { |
@@ -1418,6 +1497,10 @@ static struct target_type raid_target = { | |||
1418 | 1497 | ||
1419 | static int __init dm_raid_init(void) | 1498 | static int __init dm_raid_init(void) |
1420 | { | 1499 | { |
1500 | DMINFO("Loading target version %u.%u.%u", | ||
1501 | raid_target.version[0], | ||
1502 | raid_target.version[1], | ||
1503 | raid_target.version[2]); | ||
1421 | return dm_register_target(&raid_target); | 1504 | return dm_register_target(&raid_target); |
1422 | } | 1505 | } |
1423 | 1506 | ||
diff --git a/drivers/md/md.c b/drivers/md/md.c index 3db3d1b271f7..fcb878f88796 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -307,6 +307,10 @@ static void md_make_request(struct request_queue *q, struct bio *bio) | |||
307 | bio_io_error(bio); | 307 | bio_io_error(bio); |
308 | return; | 308 | return; |
309 | } | 309 | } |
310 | if (mddev->ro == 1 && unlikely(rw == WRITE)) { | ||
311 | bio_endio(bio, bio_sectors(bio) == 0 ? 0 : -EROFS); | ||
312 | return; | ||
313 | } | ||
310 | smp_rmb(); /* Ensure implications of 'active' are visible */ | 314 | smp_rmb(); /* Ensure implications of 'active' are visible */ |
311 | rcu_read_lock(); | 315 | rcu_read_lock(); |
312 | if (mddev->suspended) { | 316 | if (mddev->suspended) { |
@@ -2994,6 +2998,9 @@ rdev_size_store(struct md_rdev *rdev, const char *buf, size_t len) | |||
2994 | } else if (!sectors) | 2998 | } else if (!sectors) |
2995 | sectors = (i_size_read(rdev->bdev->bd_inode) >> 9) - | 2999 | sectors = (i_size_read(rdev->bdev->bd_inode) >> 9) - |
2996 | rdev->data_offset; | 3000 | rdev->data_offset; |
3001 | if (!my_mddev->pers->resize) | ||
3002 | /* Cannot change size for RAID0 or Linear etc */ | ||
3003 | return -EINVAL; | ||
2997 | } | 3004 | } |
2998 | if (sectors < my_mddev->dev_sectors) | 3005 | if (sectors < my_mddev->dev_sectors) |
2999 | return -EINVAL; /* component must fit device */ | 3006 | return -EINVAL; /* component must fit device */ |
@@ -6525,7 +6532,17 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, | |||
6525 | mddev->ro = 0; | 6532 | mddev->ro = 0; |
6526 | sysfs_notify_dirent_safe(mddev->sysfs_state); | 6533 | sysfs_notify_dirent_safe(mddev->sysfs_state); |
6527 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | 6534 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); |
6528 | md_wakeup_thread(mddev->thread); | 6535 | /* mddev_unlock will wake thread */ |
6536 | /* If a device failed while we were read-only, we | ||
6537 | * need to make sure the metadata is updated now. | ||
6538 | */ | ||
6539 | if (test_bit(MD_CHANGE_DEVS, &mddev->flags)) { | ||
6540 | mddev_unlock(mddev); | ||
6541 | wait_event(mddev->sb_wait, | ||
6542 | !test_bit(MD_CHANGE_DEVS, &mddev->flags) && | ||
6543 | !test_bit(MD_CHANGE_PENDING, &mddev->flags)); | ||
6544 | mddev_lock(mddev); | ||
6545 | } | ||
6529 | } else { | 6546 | } else { |
6530 | err = -EROFS; | 6547 | err = -EROFS; |
6531 | goto abort_unlock; | 6548 | goto abort_unlock; |
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 24b359717a7e..0505452de8d6 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c | |||
@@ -175,7 +175,13 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf) | |||
175 | rdev1->new_raid_disk = j; | 175 | rdev1->new_raid_disk = j; |
176 | } | 176 | } |
177 | 177 | ||
178 | if (j < 0 || j >= mddev->raid_disks) { | 178 | if (j < 0) { |
179 | printk(KERN_ERR | ||
180 | "md/raid0:%s: remove inactive devices before converting to RAID0\n", | ||
181 | mdname(mddev)); | ||
182 | goto abort; | ||
183 | } | ||
184 | if (j >= mddev->raid_disks) { | ||
179 | printk(KERN_ERR "md/raid0:%s: bad disk number %d - " | 185 | printk(KERN_ERR "md/raid0:%s: bad disk number %d - " |
180 | "aborting!\n", mdname(mddev), j); | 186 | "aborting!\n", mdname(mddev), j); |
181 | goto abort; | 187 | goto abort; |
@@ -289,7 +295,7 @@ abort: | |||
289 | kfree(conf->strip_zone); | 295 | kfree(conf->strip_zone); |
290 | kfree(conf->devlist); | 296 | kfree(conf->devlist); |
291 | kfree(conf); | 297 | kfree(conf); |
292 | *private_conf = NULL; | 298 | *private_conf = ERR_PTR(err); |
293 | return err; | 299 | return err; |
294 | } | 300 | } |
295 | 301 | ||
@@ -411,7 +417,8 @@ static sector_t raid0_size(struct mddev *mddev, sector_t sectors, int raid_disks | |||
411 | "%s does not support generic reshape\n", __func__); | 417 | "%s does not support generic reshape\n", __func__); |
412 | 418 | ||
413 | rdev_for_each(rdev, mddev) | 419 | rdev_for_each(rdev, mddev) |
414 | array_sectors += rdev->sectors; | 420 | array_sectors += (rdev->sectors & |
421 | ~(sector_t)(mddev->chunk_sectors-1)); | ||
415 | 422 | ||
416 | return array_sectors; | 423 | return array_sectors; |
417 | } | 424 | } |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index d5bddfc4010e..fd86b372692d 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -967,6 +967,7 @@ static void raid1_unplug(struct blk_plug_cb *cb, bool from_schedule) | |||
967 | bio_list_merge(&conf->pending_bio_list, &plug->pending); | 967 | bio_list_merge(&conf->pending_bio_list, &plug->pending); |
968 | conf->pending_count += plug->pending_cnt; | 968 | conf->pending_count += plug->pending_cnt; |
969 | spin_unlock_irq(&conf->device_lock); | 969 | spin_unlock_irq(&conf->device_lock); |
970 | wake_up(&conf->wait_barrier); | ||
970 | md_wakeup_thread(mddev->thread); | 971 | md_wakeup_thread(mddev->thread); |
971 | kfree(plug); | 972 | kfree(plug); |
972 | return; | 973 | return; |
@@ -1000,6 +1001,7 @@ static void make_request(struct mddev *mddev, struct bio * bio) | |||
1000 | const unsigned long do_flush_fua = (bio->bi_rw & (REQ_FLUSH | REQ_FUA)); | 1001 | const unsigned long do_flush_fua = (bio->bi_rw & (REQ_FLUSH | REQ_FUA)); |
1001 | const unsigned long do_discard = (bio->bi_rw | 1002 | const unsigned long do_discard = (bio->bi_rw |
1002 | & (REQ_DISCARD | REQ_SECURE)); | 1003 | & (REQ_DISCARD | REQ_SECURE)); |
1004 | const unsigned long do_same = (bio->bi_rw & REQ_WRITE_SAME); | ||
1003 | struct md_rdev *blocked_rdev; | 1005 | struct md_rdev *blocked_rdev; |
1004 | struct blk_plug_cb *cb; | 1006 | struct blk_plug_cb *cb; |
1005 | struct raid1_plug_cb *plug = NULL; | 1007 | struct raid1_plug_cb *plug = NULL; |
@@ -1301,7 +1303,8 @@ read_again: | |||
1301 | conf->mirrors[i].rdev->data_offset); | 1303 | conf->mirrors[i].rdev->data_offset); |
1302 | mbio->bi_bdev = conf->mirrors[i].rdev->bdev; | 1304 | mbio->bi_bdev = conf->mirrors[i].rdev->bdev; |
1303 | mbio->bi_end_io = raid1_end_write_request; | 1305 | mbio->bi_end_io = raid1_end_write_request; |
1304 | mbio->bi_rw = WRITE | do_flush_fua | do_sync | do_discard; | 1306 | mbio->bi_rw = |
1307 | WRITE | do_flush_fua | do_sync | do_discard | do_same; | ||
1305 | mbio->bi_private = r1_bio; | 1308 | mbio->bi_private = r1_bio; |
1306 | 1309 | ||
1307 | atomic_inc(&r1_bio->remaining); | 1310 | atomic_inc(&r1_bio->remaining); |
@@ -2818,6 +2821,9 @@ static int run(struct mddev *mddev) | |||
2818 | if (IS_ERR(conf)) | 2821 | if (IS_ERR(conf)) |
2819 | return PTR_ERR(conf); | 2822 | return PTR_ERR(conf); |
2820 | 2823 | ||
2824 | if (mddev->queue) | ||
2825 | blk_queue_max_write_same_sectors(mddev->queue, | ||
2826 | mddev->chunk_sectors); | ||
2821 | rdev_for_each(rdev, mddev) { | 2827 | rdev_for_each(rdev, mddev) { |
2822 | if (!mddev->gendisk) | 2828 | if (!mddev->gendisk) |
2823 | continue; | 2829 | continue; |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 64d48249c03b..77b562d18a90 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -38,21 +38,36 @@ | |||
38 | * near_copies (stored in low byte of layout) | 38 | * near_copies (stored in low byte of layout) |
39 | * far_copies (stored in second byte of layout) | 39 | * far_copies (stored in second byte of layout) |
40 | * far_offset (stored in bit 16 of layout ) | 40 | * far_offset (stored in bit 16 of layout ) |
41 | * use_far_sets (stored in bit 17 of layout ) | ||
41 | * | 42 | * |
42 | * The data to be stored is divided into chunks using chunksize. | 43 | * The data to be stored is divided into chunks using chunksize. Each device |
43 | * Each device is divided into far_copies sections. | 44 | * is divided into far_copies sections. In each section, chunks are laid out |
44 | * In each section, chunks are laid out in a style similar to raid0, but | 45 | * in a style similar to raid0, but near_copies copies of each chunk is stored |
45 | * near_copies copies of each chunk is stored (each on a different drive). | 46 | * (each on a different drive). The starting device for each section is offset |
46 | * The starting device for each section is offset near_copies from the starting | 47 | * near_copies from the starting device of the previous section. Thus there |
47 | * device of the previous section. | 48 | * are (near_copies * far_copies) of each chunk, and each is on a different |
48 | * Thus they are (near_copies*far_copies) of each chunk, and each is on a different | 49 | * drive. near_copies and far_copies must be at least one, and their product |
49 | * drive. | 50 | * is at most raid_disks. |
50 | * near_copies and far_copies must be at least one, and their product is at most | ||
51 | * raid_disks. | ||
52 | * | 51 | * |
53 | * If far_offset is true, then the far_copies are handled a bit differently. | 52 | * If far_offset is true, then the far_copies are handled a bit differently. |
54 | * The copies are still in different stripes, but instead of be very far apart | 53 | * The copies are still in different stripes, but instead of being very far |
55 | * on disk, there are adjacent stripes. | 54 | * apart on disk, there are adjacent stripes. |
55 | * | ||
56 | * The far and offset algorithms are handled slightly differently if | ||
57 | * 'use_far_sets' is true. In this case, the array's devices are grouped into | ||
58 | * sets that are (near_copies * far_copies) in size. The far copied stripes | ||
59 | * are still shifted by 'near_copies' devices, but this shifting stays confined | ||
60 | * to the set rather than the entire array. This is done to improve the number | ||
61 | * of device combinations that can fail without causing the array to fail. | ||
62 | * Example 'far' algorithm w/o 'use_far_sets' (each letter represents a chunk | ||
63 | * on a device): | ||
64 | * A B C D A B C D E | ||
65 | * ... ... | ||
66 | * D A B C E A B C D | ||
67 | * Example 'far' algorithm w/ 'use_far_sets' enabled (sets illustrated w/ []'s): | ||
68 | * [A B] [C D] [A B] [C D E] | ||
69 | * |...| |...| |...| | ... | | ||
70 | * [B A] [D C] [B A] [E C D] | ||
56 | */ | 71 | */ |
57 | 72 | ||
58 | /* | 73 | /* |
@@ -535,6 +550,13 @@ static void __raid10_find_phys(struct geom *geo, struct r10bio *r10bio) | |||
535 | sector_t stripe; | 550 | sector_t stripe; |
536 | int dev; | 551 | int dev; |
537 | int slot = 0; | 552 | int slot = 0; |
553 | int last_far_set_start, last_far_set_size; | ||
554 | |||
555 | last_far_set_start = (geo->raid_disks / geo->far_set_size) - 1; | ||
556 | last_far_set_start *= geo->far_set_size; | ||
557 | |||
558 | last_far_set_size = geo->far_set_size; | ||
559 | last_far_set_size += (geo->raid_disks % geo->far_set_size); | ||
538 | 560 | ||
539 | /* now calculate first sector/dev */ | 561 | /* now calculate first sector/dev */ |
540 | chunk = r10bio->sector >> geo->chunk_shift; | 562 | chunk = r10bio->sector >> geo->chunk_shift; |
@@ -551,15 +573,25 @@ static void __raid10_find_phys(struct geom *geo, struct r10bio *r10bio) | |||
551 | /* and calculate all the others */ | 573 | /* and calculate all the others */ |
552 | for (n = 0; n < geo->near_copies; n++) { | 574 | for (n = 0; n < geo->near_copies; n++) { |
553 | int d = dev; | 575 | int d = dev; |
576 | int set; | ||
554 | sector_t s = sector; | 577 | sector_t s = sector; |
555 | r10bio->devs[slot].addr = sector; | ||
556 | r10bio->devs[slot].devnum = d; | 578 | r10bio->devs[slot].devnum = d; |
579 | r10bio->devs[slot].addr = s; | ||
557 | slot++; | 580 | slot++; |
558 | 581 | ||
559 | for (f = 1; f < geo->far_copies; f++) { | 582 | for (f = 1; f < geo->far_copies; f++) { |
583 | set = d / geo->far_set_size; | ||
560 | d += geo->near_copies; | 584 | d += geo->near_copies; |
561 | if (d >= geo->raid_disks) | 585 | |
562 | d -= geo->raid_disks; | 586 | if ((geo->raid_disks % geo->far_set_size) && |
587 | (d > last_far_set_start)) { | ||
588 | d -= last_far_set_start; | ||
589 | d %= last_far_set_size; | ||
590 | d += last_far_set_start; | ||
591 | } else { | ||
592 | d %= geo->far_set_size; | ||
593 | d += geo->far_set_size * set; | ||
594 | } | ||
563 | s += geo->stride; | 595 | s += geo->stride; |
564 | r10bio->devs[slot].devnum = d; | 596 | r10bio->devs[slot].devnum = d; |
565 | r10bio->devs[slot].addr = s; | 597 | r10bio->devs[slot].addr = s; |
@@ -595,6 +627,20 @@ static sector_t raid10_find_virt(struct r10conf *conf, sector_t sector, int dev) | |||
595 | * or recovery, so reshape isn't happening | 627 | * or recovery, so reshape isn't happening |
596 | */ | 628 | */ |
597 | struct geom *geo = &conf->geo; | 629 | struct geom *geo = &conf->geo; |
630 | int far_set_start = (dev / geo->far_set_size) * geo->far_set_size; | ||
631 | int far_set_size = geo->far_set_size; | ||
632 | int last_far_set_start; | ||
633 | |||
634 | if (geo->raid_disks % geo->far_set_size) { | ||
635 | last_far_set_start = (geo->raid_disks / geo->far_set_size) - 1; | ||
636 | last_far_set_start *= geo->far_set_size; | ||
637 | |||
638 | if (dev >= last_far_set_start) { | ||
639 | far_set_size = geo->far_set_size; | ||
640 | far_set_size += (geo->raid_disks % geo->far_set_size); | ||
641 | far_set_start = last_far_set_start; | ||
642 | } | ||
643 | } | ||
598 | 644 | ||
599 | offset = sector & geo->chunk_mask; | 645 | offset = sector & geo->chunk_mask; |
600 | if (geo->far_offset) { | 646 | if (geo->far_offset) { |
@@ -602,13 +648,13 @@ static sector_t raid10_find_virt(struct r10conf *conf, sector_t sector, int dev) | |||
602 | chunk = sector >> geo->chunk_shift; | 648 | chunk = sector >> geo->chunk_shift; |
603 | fc = sector_div(chunk, geo->far_copies); | 649 | fc = sector_div(chunk, geo->far_copies); |
604 | dev -= fc * geo->near_copies; | 650 | dev -= fc * geo->near_copies; |
605 | if (dev < 0) | 651 | if (dev < far_set_start) |
606 | dev += geo->raid_disks; | 652 | dev += far_set_size; |
607 | } else { | 653 | } else { |
608 | while (sector >= geo->stride) { | 654 | while (sector >= geo->stride) { |
609 | sector -= geo->stride; | 655 | sector -= geo->stride; |
610 | if (dev < geo->near_copies) | 656 | if (dev < (geo->near_copies + far_set_start)) |
611 | dev += geo->raid_disks - geo->near_copies; | 657 | dev += far_set_size - geo->near_copies; |
612 | else | 658 | else |
613 | dev -= geo->near_copies; | 659 | dev -= geo->near_copies; |
614 | } | 660 | } |
@@ -1073,6 +1119,7 @@ static void raid10_unplug(struct blk_plug_cb *cb, bool from_schedule) | |||
1073 | bio_list_merge(&conf->pending_bio_list, &plug->pending); | 1119 | bio_list_merge(&conf->pending_bio_list, &plug->pending); |
1074 | conf->pending_count += plug->pending_cnt; | 1120 | conf->pending_count += plug->pending_cnt; |
1075 | spin_unlock_irq(&conf->device_lock); | 1121 | spin_unlock_irq(&conf->device_lock); |
1122 | wake_up(&conf->wait_barrier); | ||
1076 | md_wakeup_thread(mddev->thread); | 1123 | md_wakeup_thread(mddev->thread); |
1077 | kfree(plug); | 1124 | kfree(plug); |
1078 | return; | 1125 | return; |
@@ -1105,6 +1152,7 @@ static void make_request(struct mddev *mddev, struct bio * bio) | |||
1105 | const unsigned long do_fua = (bio->bi_rw & REQ_FUA); | 1152 | const unsigned long do_fua = (bio->bi_rw & REQ_FUA); |
1106 | const unsigned long do_discard = (bio->bi_rw | 1153 | const unsigned long do_discard = (bio->bi_rw |
1107 | & (REQ_DISCARD | REQ_SECURE)); | 1154 | & (REQ_DISCARD | REQ_SECURE)); |
1155 | const unsigned long do_same = (bio->bi_rw & REQ_WRITE_SAME); | ||
1108 | unsigned long flags; | 1156 | unsigned long flags; |
1109 | struct md_rdev *blocked_rdev; | 1157 | struct md_rdev *blocked_rdev; |
1110 | struct blk_plug_cb *cb; | 1158 | struct blk_plug_cb *cb; |
@@ -1460,7 +1508,8 @@ retry_write: | |||
1460 | rdev)); | 1508 | rdev)); |
1461 | mbio->bi_bdev = rdev->bdev; | 1509 | mbio->bi_bdev = rdev->bdev; |
1462 | mbio->bi_end_io = raid10_end_write_request; | 1510 | mbio->bi_end_io = raid10_end_write_request; |
1463 | mbio->bi_rw = WRITE | do_sync | do_fua | do_discard; | 1511 | mbio->bi_rw = |
1512 | WRITE | do_sync | do_fua | do_discard | do_same; | ||
1464 | mbio->bi_private = r10_bio; | 1513 | mbio->bi_private = r10_bio; |
1465 | 1514 | ||
1466 | atomic_inc(&r10_bio->remaining); | 1515 | atomic_inc(&r10_bio->remaining); |
@@ -1502,7 +1551,8 @@ retry_write: | |||
1502 | r10_bio, rdev)); | 1551 | r10_bio, rdev)); |
1503 | mbio->bi_bdev = rdev->bdev; | 1552 | mbio->bi_bdev = rdev->bdev; |
1504 | mbio->bi_end_io = raid10_end_write_request; | 1553 | mbio->bi_end_io = raid10_end_write_request; |
1505 | mbio->bi_rw = WRITE | do_sync | do_fua | do_discard; | 1554 | mbio->bi_rw = |
1555 | WRITE | do_sync | do_fua | do_discard | do_same; | ||
1506 | mbio->bi_private = r10_bio; | 1556 | mbio->bi_private = r10_bio; |
1507 | 1557 | ||
1508 | atomic_inc(&r10_bio->remaining); | 1558 | atomic_inc(&r10_bio->remaining); |
@@ -3436,7 +3486,7 @@ static int setup_geo(struct geom *geo, struct mddev *mddev, enum geo_type new) | |||
3436 | disks = mddev->raid_disks + mddev->delta_disks; | 3486 | disks = mddev->raid_disks + mddev->delta_disks; |
3437 | break; | 3487 | break; |
3438 | } | 3488 | } |
3439 | if (layout >> 17) | 3489 | if (layout >> 18) |
3440 | return -1; | 3490 | return -1; |
3441 | if (chunk < (PAGE_SIZE >> 9) || | 3491 | if (chunk < (PAGE_SIZE >> 9) || |
3442 | !is_power_of_2(chunk)) | 3492 | !is_power_of_2(chunk)) |
@@ -3448,6 +3498,7 @@ static int setup_geo(struct geom *geo, struct mddev *mddev, enum geo_type new) | |||
3448 | geo->near_copies = nc; | 3498 | geo->near_copies = nc; |
3449 | geo->far_copies = fc; | 3499 | geo->far_copies = fc; |
3450 | geo->far_offset = fo; | 3500 | geo->far_offset = fo; |
3501 | geo->far_set_size = (layout & (1<<17)) ? disks / fc : disks; | ||
3451 | geo->chunk_mask = chunk - 1; | 3502 | geo->chunk_mask = chunk - 1; |
3452 | geo->chunk_shift = ffz(~chunk); | 3503 | geo->chunk_shift = ffz(~chunk); |
3453 | return nc*fc; | 3504 | return nc*fc; |
@@ -3569,6 +3620,8 @@ static int run(struct mddev *mddev) | |||
3569 | if (mddev->queue) { | 3620 | if (mddev->queue) { |
3570 | blk_queue_max_discard_sectors(mddev->queue, | 3621 | blk_queue_max_discard_sectors(mddev->queue, |
3571 | mddev->chunk_sectors); | 3622 | mddev->chunk_sectors); |
3623 | blk_queue_max_write_same_sectors(mddev->queue, | ||
3624 | mddev->chunk_sectors); | ||
3572 | blk_queue_io_min(mddev->queue, chunk_size); | 3625 | blk_queue_io_min(mddev->queue, chunk_size); |
3573 | if (conf->geo.raid_disks % conf->geo.near_copies) | 3626 | if (conf->geo.raid_disks % conf->geo.near_copies) |
3574 | blk_queue_io_opt(mddev->queue, chunk_size * conf->geo.raid_disks); | 3627 | blk_queue_io_opt(mddev->queue, chunk_size * conf->geo.raid_disks); |
diff --git a/drivers/md/raid10.h b/drivers/md/raid10.h index 1054cf602345..157d69e83ff4 100644 --- a/drivers/md/raid10.h +++ b/drivers/md/raid10.h | |||
@@ -33,6 +33,11 @@ struct r10conf { | |||
33 | * far_offset, in which case it is | 33 | * far_offset, in which case it is |
34 | * 1 stripe. | 34 | * 1 stripe. |
35 | */ | 35 | */ |
36 | int far_set_size; /* The number of devices in a set, | ||
37 | * where a 'set' are devices that | ||
38 | * contain far/offset copies of | ||
39 | * each other. | ||
40 | */ | ||
36 | int chunk_shift; /* shift from chunks to sectors */ | 41 | int chunk_shift; /* shift from chunks to sectors */ |
37 | sector_t chunk_mask; | 42 | sector_t chunk_mask; |
38 | } prev, geo; | 43 | } prev, geo; |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 5af2d2709081..3ee2912889e7 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -1403,7 +1403,7 @@ static void ops_run_check_pq(struct stripe_head *sh, struct raid5_percpu *percpu | |||
1403 | &sh->ops.zero_sum_result, percpu->spare_page, &submit); | 1403 | &sh->ops.zero_sum_result, percpu->spare_page, &submit); |
1404 | } | 1404 | } |
1405 | 1405 | ||
1406 | static void __raid_run_ops(struct stripe_head *sh, unsigned long ops_request) | 1406 | static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request) |
1407 | { | 1407 | { |
1408 | int overlap_clear = 0, i, disks = sh->disks; | 1408 | int overlap_clear = 0, i, disks = sh->disks; |
1409 | struct dma_async_tx_descriptor *tx = NULL; | 1409 | struct dma_async_tx_descriptor *tx = NULL; |
@@ -1468,36 +1468,6 @@ static void __raid_run_ops(struct stripe_head *sh, unsigned long ops_request) | |||
1468 | put_cpu(); | 1468 | put_cpu(); |
1469 | } | 1469 | } |
1470 | 1470 | ||
1471 | #ifdef CONFIG_MULTICORE_RAID456 | ||
1472 | static void async_run_ops(void *param, async_cookie_t cookie) | ||
1473 | { | ||
1474 | struct stripe_head *sh = param; | ||
1475 | unsigned long ops_request = sh->ops.request; | ||
1476 | |||
1477 | clear_bit_unlock(STRIPE_OPS_REQ_PENDING, &sh->state); | ||
1478 | wake_up(&sh->ops.wait_for_ops); | ||
1479 | |||
1480 | __raid_run_ops(sh, ops_request); | ||
1481 | release_stripe(sh); | ||
1482 | } | ||
1483 | |||
1484 | static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request) | ||
1485 | { | ||
1486 | /* since handle_stripe can be called outside of raid5d context | ||
1487 | * we need to ensure sh->ops.request is de-staged before another | ||
1488 | * request arrives | ||
1489 | */ | ||
1490 | wait_event(sh->ops.wait_for_ops, | ||
1491 | !test_and_set_bit_lock(STRIPE_OPS_REQ_PENDING, &sh->state)); | ||
1492 | sh->ops.request = ops_request; | ||
1493 | |||
1494 | atomic_inc(&sh->count); | ||
1495 | async_schedule(async_run_ops, sh); | ||
1496 | } | ||
1497 | #else | ||
1498 | #define raid_run_ops __raid_run_ops | ||
1499 | #endif | ||
1500 | |||
1501 | static int grow_one_stripe(struct r5conf *conf) | 1471 | static int grow_one_stripe(struct r5conf *conf) |
1502 | { | 1472 | { |
1503 | struct stripe_head *sh; | 1473 | struct stripe_head *sh; |
@@ -1506,9 +1476,6 @@ static int grow_one_stripe(struct r5conf *conf) | |||
1506 | return 0; | 1476 | return 0; |
1507 | 1477 | ||
1508 | sh->raid_conf = conf; | 1478 | sh->raid_conf = conf; |
1509 | #ifdef CONFIG_MULTICORE_RAID456 | ||
1510 | init_waitqueue_head(&sh->ops.wait_for_ops); | ||
1511 | #endif | ||
1512 | 1479 | ||
1513 | spin_lock_init(&sh->stripe_lock); | 1480 | spin_lock_init(&sh->stripe_lock); |
1514 | 1481 | ||
@@ -1627,9 +1594,6 @@ static int resize_stripes(struct r5conf *conf, int newsize) | |||
1627 | break; | 1594 | break; |
1628 | 1595 | ||
1629 | nsh->raid_conf = conf; | 1596 | nsh->raid_conf = conf; |
1630 | #ifdef CONFIG_MULTICORE_RAID456 | ||
1631 | init_waitqueue_head(&nsh->ops.wait_for_ops); | ||
1632 | #endif | ||
1633 | spin_lock_init(&nsh->stripe_lock); | 1597 | spin_lock_init(&nsh->stripe_lock); |
1634 | 1598 | ||
1635 | list_add(&nsh->lru, &newstripes); | 1599 | list_add(&nsh->lru, &newstripes); |
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 11d01d67b3f5..7bd068a6056a 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -1629,7 +1629,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1629 | 1629 | ||
1630 | /* If this is the first slave, then we need to set the master's hardware | 1630 | /* If this is the first slave, then we need to set the master's hardware |
1631 | * address to be the same as the slave's. */ | 1631 | * address to be the same as the slave's. */ |
1632 | if (bond->dev_addr_from_first) | 1632 | if (bond->slave_cnt == 0 && bond->dev_addr_from_first) |
1633 | bond_set_dev_addr(bond->dev, slave_dev); | 1633 | bond_set_dev_addr(bond->dev, slave_dev); |
1634 | 1634 | ||
1635 | new_slave = kzalloc(sizeof(struct slave), GFP_KERNEL); | 1635 | new_slave = kzalloc(sizeof(struct slave), GFP_KERNEL); |
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index 639049d7e92d..da5f4397f87c 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c | |||
@@ -301,12 +301,16 @@ static int bgmac_dma_rx_read(struct bgmac *bgmac, struct bgmac_dma_ring *ring, | |||
301 | bgmac_err(bgmac, "Found poisoned packet at slot %d, DMA issue!\n", | 301 | bgmac_err(bgmac, "Found poisoned packet at slot %d, DMA issue!\n", |
302 | ring->start); | 302 | ring->start); |
303 | } else { | 303 | } else { |
304 | /* Omit CRC. */ | ||
305 | len -= ETH_FCS_LEN; | ||
306 | |||
304 | new_skb = netdev_alloc_skb_ip_align(bgmac->net_dev, len); | 307 | new_skb = netdev_alloc_skb_ip_align(bgmac->net_dev, len); |
305 | if (new_skb) { | 308 | if (new_skb) { |
306 | skb_put(new_skb, len); | 309 | skb_put(new_skb, len); |
307 | skb_copy_from_linear_data_offset(skb, BGMAC_RX_FRAME_OFFSET, | 310 | skb_copy_from_linear_data_offset(skb, BGMAC_RX_FRAME_OFFSET, |
308 | new_skb->data, | 311 | new_skb->data, |
309 | len); | 312 | len); |
313 | skb_checksum_none_assert(skb); | ||
310 | new_skb->protocol = | 314 | new_skb->protocol = |
311 | eth_type_trans(new_skb, bgmac->net_dev); | 315 | eth_type_trans(new_skb, bgmac->net_dev); |
312 | netif_receive_skb(new_skb); | 316 | netif_receive_skb(new_skb); |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index ecac04a3687c..a923bc4d5a1f 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | |||
@@ -3142,7 +3142,7 @@ static inline __le16 bnx2x_csum_fix(unsigned char *t_header, u16 csum, s8 fix) | |||
3142 | tsum = ~csum_fold(csum_add((__force __wsum) csum, | 3142 | tsum = ~csum_fold(csum_add((__force __wsum) csum, |
3143 | csum_partial(t_header, -fix, 0))); | 3143 | csum_partial(t_header, -fix, 0))); |
3144 | 3144 | ||
3145 | return bswab16(csum); | 3145 | return bswab16(tsum); |
3146 | } | 3146 | } |
3147 | 3147 | ||
3148 | static inline u32 bnx2x_xmit_type(struct bnx2x *bp, struct sk_buff *skb) | 3148 | static inline u32 bnx2x_xmit_type(struct bnx2x *bp, struct sk_buff *skb) |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index 9a674b14b403..edfa67adf2f9 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | |||
@@ -281,6 +281,8 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
281 | cmd->lp_advertising |= ADVERTISED_2500baseX_Full; | 281 | cmd->lp_advertising |= ADVERTISED_2500baseX_Full; |
282 | if (status & LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE) | 282 | if (status & LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE) |
283 | cmd->lp_advertising |= ADVERTISED_10000baseT_Full; | 283 | cmd->lp_advertising |= ADVERTISED_10000baseT_Full; |
284 | if (status & LINK_STATUS_LINK_PARTNER_20GXFD_CAPABLE) | ||
285 | cmd->lp_advertising |= ADVERTISED_20000baseKR2_Full; | ||
284 | } | 286 | } |
285 | 287 | ||
286 | cmd->maxtxpkt = 0; | 288 | cmd->maxtxpkt = 0; |
@@ -463,6 +465,10 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
463 | ADVERTISED_10000baseKR_Full)) | 465 | ADVERTISED_10000baseKR_Full)) |
464 | bp->link_params.speed_cap_mask[cfg_idx] |= | 466 | bp->link_params.speed_cap_mask[cfg_idx] |= |
465 | PORT_HW_CFG_SPEED_CAPABILITY_D0_10G; | 467 | PORT_HW_CFG_SPEED_CAPABILITY_D0_10G; |
468 | |||
469 | if (cmd->advertising & ADVERTISED_20000baseKR2_Full) | ||
470 | bp->link_params.speed_cap_mask[cfg_idx] |= | ||
471 | PORT_HW_CFG_SPEED_CAPABILITY_D0_20G; | ||
466 | } | 472 | } |
467 | } else { /* forced speed */ | 473 | } else { /* forced speed */ |
468 | /* advertise the requested speed and duplex if supported */ | 474 | /* advertise the requested speed and duplex if supported */ |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 1663e0b6b5a0..31c5787970db 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | |||
@@ -10422,6 +10422,28 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy, | |||
10422 | MDIO_PMA_DEVAD, | 10422 | MDIO_PMA_DEVAD, |
10423 | MDIO_PMA_REG_8481_LED1_MASK, | 10423 | MDIO_PMA_REG_8481_LED1_MASK, |
10424 | 0x0); | 10424 | 0x0); |
10425 | if (phy->type == | ||
10426 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834) { | ||
10427 | /* Disable MI_INT interrupt before setting LED4 | ||
10428 | * source to constant off. | ||
10429 | */ | ||
10430 | if (REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + | ||
10431 | params->port*4) & | ||
10432 | NIG_MASK_MI_INT) { | ||
10433 | params->link_flags |= | ||
10434 | LINK_FLAGS_INT_DISABLED; | ||
10435 | |||
10436 | bnx2x_bits_dis( | ||
10437 | bp, | ||
10438 | NIG_REG_MASK_INTERRUPT_PORT0 + | ||
10439 | params->port*4, | ||
10440 | NIG_MASK_MI_INT); | ||
10441 | } | ||
10442 | bnx2x_cl45_write(bp, phy, | ||
10443 | MDIO_PMA_DEVAD, | ||
10444 | MDIO_PMA_REG_8481_SIGNAL_MASK, | ||
10445 | 0x0); | ||
10446 | } | ||
10425 | } | 10447 | } |
10426 | break; | 10448 | break; |
10427 | case LED_MODE_ON: | 10449 | case LED_MODE_ON: |
@@ -10468,6 +10490,28 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy, | |||
10468 | MDIO_PMA_DEVAD, | 10490 | MDIO_PMA_DEVAD, |
10469 | MDIO_PMA_REG_8481_LED1_MASK, | 10491 | MDIO_PMA_REG_8481_LED1_MASK, |
10470 | 0x20); | 10492 | 0x20); |
10493 | if (phy->type == | ||
10494 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834) { | ||
10495 | /* Disable MI_INT interrupt before setting LED4 | ||
10496 | * source to constant on. | ||
10497 | */ | ||
10498 | if (REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + | ||
10499 | params->port*4) & | ||
10500 | NIG_MASK_MI_INT) { | ||
10501 | params->link_flags |= | ||
10502 | LINK_FLAGS_INT_DISABLED; | ||
10503 | |||
10504 | bnx2x_bits_dis( | ||
10505 | bp, | ||
10506 | NIG_REG_MASK_INTERRUPT_PORT0 + | ||
10507 | params->port*4, | ||
10508 | NIG_MASK_MI_INT); | ||
10509 | } | ||
10510 | bnx2x_cl45_write(bp, phy, | ||
10511 | MDIO_PMA_DEVAD, | ||
10512 | MDIO_PMA_REG_8481_SIGNAL_MASK, | ||
10513 | 0x20); | ||
10514 | } | ||
10471 | } | 10515 | } |
10472 | break; | 10516 | break; |
10473 | 10517 | ||
@@ -10532,6 +10576,22 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy, | |||
10532 | MDIO_PMA_DEVAD, | 10576 | MDIO_PMA_DEVAD, |
10533 | MDIO_PMA_REG_8481_LINK_SIGNAL, | 10577 | MDIO_PMA_REG_8481_LINK_SIGNAL, |
10534 | val); | 10578 | val); |
10579 | if (phy->type == | ||
10580 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834) { | ||
10581 | /* Restore LED4 source to external link, | ||
10582 | * and re-enable interrupts. | ||
10583 | */ | ||
10584 | bnx2x_cl45_write(bp, phy, | ||
10585 | MDIO_PMA_DEVAD, | ||
10586 | MDIO_PMA_REG_8481_SIGNAL_MASK, | ||
10587 | 0x40); | ||
10588 | if (params->link_flags & | ||
10589 | LINK_FLAGS_INT_DISABLED) { | ||
10590 | bnx2x_link_int_enable(params); | ||
10591 | params->link_flags &= | ||
10592 | ~LINK_FLAGS_INT_DISABLED; | ||
10593 | } | ||
10594 | } | ||
10535 | } | 10595 | } |
10536 | break; | 10596 | break; |
10537 | } | 10597 | } |
@@ -11791,6 +11851,8 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port, | |||
11791 | phy->media_type = ETH_PHY_KR; | 11851 | phy->media_type = ETH_PHY_KR; |
11792 | phy->flags |= FLAGS_WC_DUAL_MODE; | 11852 | phy->flags |= FLAGS_WC_DUAL_MODE; |
11793 | phy->supported &= (SUPPORTED_20000baseKR2_Full | | 11853 | phy->supported &= (SUPPORTED_20000baseKR2_Full | |
11854 | SUPPORTED_10000baseT_Full | | ||
11855 | SUPPORTED_1000baseT_Full | | ||
11794 | SUPPORTED_Autoneg | | 11856 | SUPPORTED_Autoneg | |
11795 | SUPPORTED_FIBRE | | 11857 | SUPPORTED_FIBRE | |
11796 | SUPPORTED_Pause | | 11858 | SUPPORTED_Pause | |
@@ -13437,7 +13499,7 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars) | |||
13437 | struct bnx2x_phy *phy = ¶ms->phy[INT_PHY]; | 13499 | struct bnx2x_phy *phy = ¶ms->phy[INT_PHY]; |
13438 | bnx2x_set_aer_mmd(params, phy); | 13500 | bnx2x_set_aer_mmd(params, phy); |
13439 | if ((phy->supported & SUPPORTED_20000baseKR2_Full) && | 13501 | if ((phy->supported & SUPPORTED_20000baseKR2_Full) && |
13440 | (phy->speed_cap_mask & SPEED_20000)) | 13502 | (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)) |
13441 | bnx2x_check_kr2_wa(params, vars, phy); | 13503 | bnx2x_check_kr2_wa(params, vars, phy); |
13442 | bnx2x_check_over_curr(params, vars); | 13504 | bnx2x_check_over_curr(params, vars); |
13443 | if (vars->rx_tx_asic_rst) | 13505 | if (vars->rx_tx_asic_rst) |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h index d25c7d79787a..be5c195d03dd 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h | |||
@@ -307,7 +307,8 @@ struct link_params { | |||
307 | struct bnx2x *bp; | 307 | struct bnx2x *bp; |
308 | u16 req_fc_auto_adv; /* Should be set to TX / BOTH when | 308 | u16 req_fc_auto_adv; /* Should be set to TX / BOTH when |
309 | req_flow_ctrl is set to AUTO */ | 309 | req_flow_ctrl is set to AUTO */ |
310 | u16 rsrv1; | 310 | u16 link_flags; |
311 | #define LINK_FLAGS_INT_DISABLED (1<<0) | ||
311 | u32 lfa_base; | 312 | u32 lfa_base; |
312 | }; | 313 | }; |
313 | 314 | ||
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 28ceb8414185..29aff55f2eea 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h | |||
@@ -349,6 +349,7 @@ struct be_adapter { | |||
349 | struct pci_dev *pdev; | 349 | struct pci_dev *pdev; |
350 | struct net_device *netdev; | 350 | struct net_device *netdev; |
351 | 351 | ||
352 | u8 __iomem *csr; /* CSR BAR used only for BE2/3 */ | ||
352 | u8 __iomem *db; /* Door Bell */ | 353 | u8 __iomem *db; /* Door Bell */ |
353 | 354 | ||
354 | struct mutex mbox_lock; /* For serializing mbox cmds to BE card */ | 355 | struct mutex mbox_lock; /* For serializing mbox cmds to BE card */ |
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 071aea79d218..3c9b4f12e3e5 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c | |||
@@ -473,19 +473,17 @@ static int be_mbox_notify_wait(struct be_adapter *adapter) | |||
473 | return 0; | 473 | return 0; |
474 | } | 474 | } |
475 | 475 | ||
476 | static int be_POST_stage_get(struct be_adapter *adapter, u16 *stage) | 476 | static u16 be_POST_stage_get(struct be_adapter *adapter) |
477 | { | 477 | { |
478 | u32 sem; | 478 | u32 sem; |
479 | u32 reg = skyhawk_chip(adapter) ? SLIPORT_SEMAPHORE_OFFSET_SH : | ||
480 | SLIPORT_SEMAPHORE_OFFSET_BE; | ||
481 | 479 | ||
482 | pci_read_config_dword(adapter->pdev, reg, &sem); | 480 | if (BEx_chip(adapter)) |
483 | *stage = sem & POST_STAGE_MASK; | 481 | sem = ioread32(adapter->csr + SLIPORT_SEMAPHORE_OFFSET_BEx); |
484 | |||
485 | if ((sem >> POST_ERR_SHIFT) & POST_ERR_MASK) | ||
486 | return -1; | ||
487 | else | 482 | else |
488 | return 0; | 483 | pci_read_config_dword(adapter->pdev, |
484 | SLIPORT_SEMAPHORE_OFFSET_SH, &sem); | ||
485 | |||
486 | return sem & POST_STAGE_MASK; | ||
489 | } | 487 | } |
490 | 488 | ||
491 | int lancer_wait_ready(struct be_adapter *adapter) | 489 | int lancer_wait_ready(struct be_adapter *adapter) |
@@ -579,19 +577,17 @@ int be_fw_wait_ready(struct be_adapter *adapter) | |||
579 | } | 577 | } |
580 | 578 | ||
581 | do { | 579 | do { |
582 | status = be_POST_stage_get(adapter, &stage); | 580 | stage = be_POST_stage_get(adapter); |
583 | if (status) { | 581 | if (stage == POST_STAGE_ARMFW_RDY) |
584 | dev_err(dev, "POST error; stage=0x%x\n", stage); | ||
585 | return -1; | ||
586 | } else if (stage != POST_STAGE_ARMFW_RDY) { | ||
587 | if (msleep_interruptible(2000)) { | ||
588 | dev_err(dev, "Waiting for POST aborted\n"); | ||
589 | return -EINTR; | ||
590 | } | ||
591 | timeout += 2; | ||
592 | } else { | ||
593 | return 0; | 582 | return 0; |
583 | |||
584 | dev_info(dev, "Waiting for POST, %ds elapsed\n", | ||
585 | timeout); | ||
586 | if (msleep_interruptible(2000)) { | ||
587 | dev_err(dev, "Waiting for POST aborted\n"); | ||
588 | return -EINTR; | ||
594 | } | 589 | } |
590 | timeout += 2; | ||
595 | } while (timeout < 60); | 591 | } while (timeout < 60); |
596 | 592 | ||
597 | dev_err(dev, "POST timeout; stage=0x%x\n", stage); | 593 | dev_err(dev, "POST timeout; stage=0x%x\n", stage); |
diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h index 541d4530d5bf..62dc220695f7 100644 --- a/drivers/net/ethernet/emulex/benet/be_hw.h +++ b/drivers/net/ethernet/emulex/benet/be_hw.h | |||
@@ -32,8 +32,8 @@ | |||
32 | #define MPU_EP_CONTROL 0 | 32 | #define MPU_EP_CONTROL 0 |
33 | 33 | ||
34 | /********** MPU semphore: used for SH & BE *************/ | 34 | /********** MPU semphore: used for SH & BE *************/ |
35 | #define SLIPORT_SEMAPHORE_OFFSET_BE 0x7c | 35 | #define SLIPORT_SEMAPHORE_OFFSET_BEx 0xac /* CSR BAR offset */ |
36 | #define SLIPORT_SEMAPHORE_OFFSET_SH 0x94 | 36 | #define SLIPORT_SEMAPHORE_OFFSET_SH 0x94 /* PCI-CFG offset */ |
37 | #define POST_STAGE_MASK 0x0000FFFF | 37 | #define POST_STAGE_MASK 0x0000FFFF |
38 | #define POST_ERR_MASK 0x1 | 38 | #define POST_ERR_MASK 0x1 |
39 | #define POST_ERR_SHIFT 31 | 39 | #define POST_ERR_SHIFT 31 |
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 3860888ac711..08e54f3d288b 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c | |||
@@ -3688,6 +3688,8 @@ static void be_netdev_init(struct net_device *netdev) | |||
3688 | 3688 | ||
3689 | static void be_unmap_pci_bars(struct be_adapter *adapter) | 3689 | static void be_unmap_pci_bars(struct be_adapter *adapter) |
3690 | { | 3690 | { |
3691 | if (adapter->csr) | ||
3692 | pci_iounmap(adapter->pdev, adapter->csr); | ||
3691 | if (adapter->db) | 3693 | if (adapter->db) |
3692 | pci_iounmap(adapter->pdev, adapter->db); | 3694 | pci_iounmap(adapter->pdev, adapter->db); |
3693 | } | 3695 | } |
@@ -3721,6 +3723,12 @@ static int be_map_pci_bars(struct be_adapter *adapter) | |||
3721 | adapter->if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >> | 3723 | adapter->if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >> |
3722 | SLI_INTF_IF_TYPE_SHIFT; | 3724 | SLI_INTF_IF_TYPE_SHIFT; |
3723 | 3725 | ||
3726 | if (BEx_chip(adapter) && be_physfn(adapter)) { | ||
3727 | adapter->csr = pci_iomap(adapter->pdev, 2, 0); | ||
3728 | if (adapter->csr == NULL) | ||
3729 | return -ENOMEM; | ||
3730 | } | ||
3731 | |||
3724 | addr = pci_iomap(adapter->pdev, db_bar(adapter), 0); | 3732 | addr = pci_iomap(adapter->pdev, db_bar(adapter), 0); |
3725 | if (addr == NULL) | 3733 | if (addr == NULL) |
3726 | goto pci_map_err; | 3734 | goto pci_map_err; |
@@ -4329,6 +4337,8 @@ static pci_ers_result_t be_eeh_reset(struct pci_dev *pdev) | |||
4329 | pci_restore_state(pdev); | 4337 | pci_restore_state(pdev); |
4330 | 4338 | ||
4331 | /* Check if card is ok and fw is ready */ | 4339 | /* Check if card is ok and fw is ready */ |
4340 | dev_info(&adapter->pdev->dev, | ||
4341 | "Waiting for FW to be ready after EEH reset\n"); | ||
4332 | status = be_fw_wait_ready(adapter); | 4342 | status = be_fw_wait_ready(adapter); |
4333 | if (status) | 4343 | if (status) |
4334 | return PCI_ERS_RESULT_DISCONNECT; | 4344 | return PCI_ERS_RESULT_DISCONNECT; |
diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c index fccc3bf2141d..069a155d16ed 100644 --- a/drivers/net/ethernet/freescale/fec.c +++ b/drivers/net/ethernet/freescale/fec.c | |||
@@ -246,14 +246,13 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
246 | struct bufdesc *bdp; | 246 | struct bufdesc *bdp; |
247 | void *bufaddr; | 247 | void *bufaddr; |
248 | unsigned short status; | 248 | unsigned short status; |
249 | unsigned long flags; | 249 | unsigned int index; |
250 | 250 | ||
251 | if (!fep->link) { | 251 | if (!fep->link) { |
252 | /* Link is down or autonegotiation is in progress. */ | 252 | /* Link is down or autonegotiation is in progress. */ |
253 | return NETDEV_TX_BUSY; | 253 | return NETDEV_TX_BUSY; |
254 | } | 254 | } |
255 | 255 | ||
256 | spin_lock_irqsave(&fep->hw_lock, flags); | ||
257 | /* Fill in a Tx ring entry */ | 256 | /* Fill in a Tx ring entry */ |
258 | bdp = fep->cur_tx; | 257 | bdp = fep->cur_tx; |
259 | 258 | ||
@@ -264,7 +263,6 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
264 | * This should not happen, since ndev->tbusy should be set. | 263 | * This should not happen, since ndev->tbusy should be set. |
265 | */ | 264 | */ |
266 | printk("%s: tx queue full!.\n", ndev->name); | 265 | printk("%s: tx queue full!.\n", ndev->name); |
267 | spin_unlock_irqrestore(&fep->hw_lock, flags); | ||
268 | return NETDEV_TX_BUSY; | 266 | return NETDEV_TX_BUSY; |
269 | } | 267 | } |
270 | 268 | ||
@@ -280,13 +278,13 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
280 | * 4-byte boundaries. Use bounce buffers to copy data | 278 | * 4-byte boundaries. Use bounce buffers to copy data |
281 | * and get it aligned. Ugh. | 279 | * and get it aligned. Ugh. |
282 | */ | 280 | */ |
281 | if (fep->bufdesc_ex) | ||
282 | index = (struct bufdesc_ex *)bdp - | ||
283 | (struct bufdesc_ex *)fep->tx_bd_base; | ||
284 | else | ||
285 | index = bdp - fep->tx_bd_base; | ||
286 | |||
283 | if (((unsigned long) bufaddr) & FEC_ALIGNMENT) { | 287 | if (((unsigned long) bufaddr) & FEC_ALIGNMENT) { |
284 | unsigned int index; | ||
285 | if (fep->bufdesc_ex) | ||
286 | index = (struct bufdesc_ex *)bdp - | ||
287 | (struct bufdesc_ex *)fep->tx_bd_base; | ||
288 | else | ||
289 | index = bdp - fep->tx_bd_base; | ||
290 | memcpy(fep->tx_bounce[index], skb->data, skb->len); | 288 | memcpy(fep->tx_bounce[index], skb->data, skb->len); |
291 | bufaddr = fep->tx_bounce[index]; | 289 | bufaddr = fep->tx_bounce[index]; |
292 | } | 290 | } |
@@ -300,10 +298,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
300 | swap_buffer(bufaddr, skb->len); | 298 | swap_buffer(bufaddr, skb->len); |
301 | 299 | ||
302 | /* Save skb pointer */ | 300 | /* Save skb pointer */ |
303 | fep->tx_skbuff[fep->skb_cur] = skb; | 301 | fep->tx_skbuff[index] = skb; |
304 | |||
305 | ndev->stats.tx_bytes += skb->len; | ||
306 | fep->skb_cur = (fep->skb_cur+1) & TX_RING_MOD_MASK; | ||
307 | 302 | ||
308 | /* Push the data cache so the CPM does not get stale memory | 303 | /* Push the data cache so the CPM does not get stale memory |
309 | * data. | 304 | * data. |
@@ -331,26 +326,22 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
331 | ebdp->cbd_esc = BD_ENET_TX_INT; | 326 | ebdp->cbd_esc = BD_ENET_TX_INT; |
332 | } | 327 | } |
333 | } | 328 | } |
334 | /* Trigger transmission start */ | ||
335 | writel(0, fep->hwp + FEC_X_DES_ACTIVE); | ||
336 | |||
337 | /* If this was the last BD in the ring, start at the beginning again. */ | 329 | /* If this was the last BD in the ring, start at the beginning again. */ |
338 | if (status & BD_ENET_TX_WRAP) | 330 | if (status & BD_ENET_TX_WRAP) |
339 | bdp = fep->tx_bd_base; | 331 | bdp = fep->tx_bd_base; |
340 | else | 332 | else |
341 | bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex); | 333 | bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex); |
342 | 334 | ||
343 | if (bdp == fep->dirty_tx) { | 335 | fep->cur_tx = bdp; |
344 | fep->tx_full = 1; | 336 | |
337 | if (fep->cur_tx == fep->dirty_tx) | ||
345 | netif_stop_queue(ndev); | 338 | netif_stop_queue(ndev); |
346 | } | ||
347 | 339 | ||
348 | fep->cur_tx = bdp; | 340 | /* Trigger transmission start */ |
341 | writel(0, fep->hwp + FEC_X_DES_ACTIVE); | ||
349 | 342 | ||
350 | skb_tx_timestamp(skb); | 343 | skb_tx_timestamp(skb); |
351 | 344 | ||
352 | spin_unlock_irqrestore(&fep->hw_lock, flags); | ||
353 | |||
354 | return NETDEV_TX_OK; | 345 | return NETDEV_TX_OK; |
355 | } | 346 | } |
356 | 347 | ||
@@ -406,11 +397,8 @@ fec_restart(struct net_device *ndev, int duplex) | |||
406 | writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc) | 397 | writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc) |
407 | * RX_RING_SIZE, fep->hwp + FEC_X_DES_START); | 398 | * RX_RING_SIZE, fep->hwp + FEC_X_DES_START); |
408 | 399 | ||
409 | fep->dirty_tx = fep->cur_tx = fep->tx_bd_base; | ||
410 | fep->cur_rx = fep->rx_bd_base; | 400 | fep->cur_rx = fep->rx_bd_base; |
411 | 401 | ||
412 | /* Reset SKB transmit buffers. */ | ||
413 | fep->skb_cur = fep->skb_dirty = 0; | ||
414 | for (i = 0; i <= TX_RING_MOD_MASK; i++) { | 402 | for (i = 0; i <= TX_RING_MOD_MASK; i++) { |
415 | if (fep->tx_skbuff[i]) { | 403 | if (fep->tx_skbuff[i]) { |
416 | dev_kfree_skb_any(fep->tx_skbuff[i]); | 404 | dev_kfree_skb_any(fep->tx_skbuff[i]); |
@@ -573,20 +561,35 @@ fec_enet_tx(struct net_device *ndev) | |||
573 | struct bufdesc *bdp; | 561 | struct bufdesc *bdp; |
574 | unsigned short status; | 562 | unsigned short status; |
575 | struct sk_buff *skb; | 563 | struct sk_buff *skb; |
564 | int index = 0; | ||
576 | 565 | ||
577 | fep = netdev_priv(ndev); | 566 | fep = netdev_priv(ndev); |
578 | spin_lock(&fep->hw_lock); | ||
579 | bdp = fep->dirty_tx; | 567 | bdp = fep->dirty_tx; |
580 | 568 | ||
569 | /* get next bdp of dirty_tx */ | ||
570 | if (bdp->cbd_sc & BD_ENET_TX_WRAP) | ||
571 | bdp = fep->tx_bd_base; | ||
572 | else | ||
573 | bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex); | ||
574 | |||
581 | while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) { | 575 | while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) { |
582 | if (bdp == fep->cur_tx && fep->tx_full == 0) | 576 | |
577 | /* current queue is empty */ | ||
578 | if (bdp == fep->cur_tx) | ||
583 | break; | 579 | break; |
584 | 580 | ||
581 | if (fep->bufdesc_ex) | ||
582 | index = (struct bufdesc_ex *)bdp - | ||
583 | (struct bufdesc_ex *)fep->tx_bd_base; | ||
584 | else | ||
585 | index = bdp - fep->tx_bd_base; | ||
586 | |||
585 | dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, | 587 | dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, |
586 | FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE); | 588 | FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE); |
587 | bdp->cbd_bufaddr = 0; | 589 | bdp->cbd_bufaddr = 0; |
588 | 590 | ||
589 | skb = fep->tx_skbuff[fep->skb_dirty]; | 591 | skb = fep->tx_skbuff[index]; |
592 | |||
590 | /* Check for errors. */ | 593 | /* Check for errors. */ |
591 | if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC | | 594 | if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC | |
592 | BD_ENET_TX_RL | BD_ENET_TX_UN | | 595 | BD_ENET_TX_RL | BD_ENET_TX_UN | |
@@ -631,8 +634,9 @@ fec_enet_tx(struct net_device *ndev) | |||
631 | 634 | ||
632 | /* Free the sk buffer associated with this last transmit */ | 635 | /* Free the sk buffer associated with this last transmit */ |
633 | dev_kfree_skb_any(skb); | 636 | dev_kfree_skb_any(skb); |
634 | fep->tx_skbuff[fep->skb_dirty] = NULL; | 637 | fep->tx_skbuff[index] = NULL; |
635 | fep->skb_dirty = (fep->skb_dirty + 1) & TX_RING_MOD_MASK; | 638 | |
639 | fep->dirty_tx = bdp; | ||
636 | 640 | ||
637 | /* Update pointer to next buffer descriptor to be transmitted */ | 641 | /* Update pointer to next buffer descriptor to be transmitted */ |
638 | if (status & BD_ENET_TX_WRAP) | 642 | if (status & BD_ENET_TX_WRAP) |
@@ -642,14 +646,12 @@ fec_enet_tx(struct net_device *ndev) | |||
642 | 646 | ||
643 | /* Since we have freed up a buffer, the ring is no longer full | 647 | /* Since we have freed up a buffer, the ring is no longer full |
644 | */ | 648 | */ |
645 | if (fep->tx_full) { | 649 | if (fep->dirty_tx != fep->cur_tx) { |
646 | fep->tx_full = 0; | ||
647 | if (netif_queue_stopped(ndev)) | 650 | if (netif_queue_stopped(ndev)) |
648 | netif_wake_queue(ndev); | 651 | netif_wake_queue(ndev); |
649 | } | 652 | } |
650 | } | 653 | } |
651 | fep->dirty_tx = bdp; | 654 | return; |
652 | spin_unlock(&fep->hw_lock); | ||
653 | } | 655 | } |
654 | 656 | ||
655 | 657 | ||
@@ -816,7 +818,7 @@ fec_enet_interrupt(int irq, void *dev_id) | |||
816 | int_events = readl(fep->hwp + FEC_IEVENT); | 818 | int_events = readl(fep->hwp + FEC_IEVENT); |
817 | writel(int_events, fep->hwp + FEC_IEVENT); | 819 | writel(int_events, fep->hwp + FEC_IEVENT); |
818 | 820 | ||
819 | if (int_events & FEC_ENET_RXF) { | 821 | if (int_events & (FEC_ENET_RXF | FEC_ENET_TXF)) { |
820 | ret = IRQ_HANDLED; | 822 | ret = IRQ_HANDLED; |
821 | 823 | ||
822 | /* Disable the RX interrupt */ | 824 | /* Disable the RX interrupt */ |
@@ -827,15 +829,6 @@ fec_enet_interrupt(int irq, void *dev_id) | |||
827 | } | 829 | } |
828 | } | 830 | } |
829 | 831 | ||
830 | /* Transmit OK, or non-fatal error. Update the buffer | ||
831 | * descriptors. FEC handles all errors, we just discover | ||
832 | * them as part of the transmit process. | ||
833 | */ | ||
834 | if (int_events & FEC_ENET_TXF) { | ||
835 | ret = IRQ_HANDLED; | ||
836 | fec_enet_tx(ndev); | ||
837 | } | ||
838 | |||
839 | if (int_events & FEC_ENET_MII) { | 832 | if (int_events & FEC_ENET_MII) { |
840 | ret = IRQ_HANDLED; | 833 | ret = IRQ_HANDLED; |
841 | complete(&fep->mdio_done); | 834 | complete(&fep->mdio_done); |
@@ -851,6 +844,8 @@ static int fec_enet_rx_napi(struct napi_struct *napi, int budget) | |||
851 | int pkts = fec_enet_rx(ndev, budget); | 844 | int pkts = fec_enet_rx(ndev, budget); |
852 | struct fec_enet_private *fep = netdev_priv(ndev); | 845 | struct fec_enet_private *fep = netdev_priv(ndev); |
853 | 846 | ||
847 | fec_enet_tx(ndev); | ||
848 | |||
854 | if (pkts < budget) { | 849 | if (pkts < budget) { |
855 | napi_complete(napi); | 850 | napi_complete(napi); |
856 | writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK); | 851 | writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK); |
@@ -1646,6 +1641,7 @@ static int fec_enet_init(struct net_device *ndev) | |||
1646 | 1641 | ||
1647 | /* ...and the same for transmit */ | 1642 | /* ...and the same for transmit */ |
1648 | bdp = fep->tx_bd_base; | 1643 | bdp = fep->tx_bd_base; |
1644 | fep->cur_tx = bdp; | ||
1649 | for (i = 0; i < TX_RING_SIZE; i++) { | 1645 | for (i = 0; i < TX_RING_SIZE; i++) { |
1650 | 1646 | ||
1651 | /* Initialize the BD for every fragment in the page. */ | 1647 | /* Initialize the BD for every fragment in the page. */ |
@@ -1657,6 +1653,7 @@ static int fec_enet_init(struct net_device *ndev) | |||
1657 | /* Set the last buffer to wrap */ | 1653 | /* Set the last buffer to wrap */ |
1658 | bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex); | 1654 | bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex); |
1659 | bdp->cbd_sc |= BD_SC_WRAP; | 1655 | bdp->cbd_sc |= BD_SC_WRAP; |
1656 | fep->dirty_tx = bdp; | ||
1660 | 1657 | ||
1661 | fec_restart(ndev, 0); | 1658 | fec_restart(ndev, 0); |
1662 | 1659 | ||
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 01579b8e37c4..f5390071efd0 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h | |||
@@ -97,6 +97,13 @@ struct bufdesc { | |||
97 | unsigned short cbd_sc; /* Control and status info */ | 97 | unsigned short cbd_sc; /* Control and status info */ |
98 | unsigned long cbd_bufaddr; /* Buffer address */ | 98 | unsigned long cbd_bufaddr; /* Buffer address */ |
99 | }; | 99 | }; |
100 | #else | ||
101 | struct bufdesc { | ||
102 | unsigned short cbd_sc; /* Control and status info */ | ||
103 | unsigned short cbd_datlen; /* Data length */ | ||
104 | unsigned long cbd_bufaddr; /* Buffer address */ | ||
105 | }; | ||
106 | #endif | ||
100 | 107 | ||
101 | struct bufdesc_ex { | 108 | struct bufdesc_ex { |
102 | struct bufdesc desc; | 109 | struct bufdesc desc; |
@@ -107,14 +114,6 @@ struct bufdesc_ex { | |||
107 | unsigned short res0[4]; | 114 | unsigned short res0[4]; |
108 | }; | 115 | }; |
109 | 116 | ||
110 | #else | ||
111 | struct bufdesc { | ||
112 | unsigned short cbd_sc; /* Control and status info */ | ||
113 | unsigned short cbd_datlen; /* Data length */ | ||
114 | unsigned long cbd_bufaddr; /* Buffer address */ | ||
115 | }; | ||
116 | #endif | ||
117 | |||
118 | /* | 117 | /* |
119 | * The following definitions courtesy of commproc.h, which where | 118 | * The following definitions courtesy of commproc.h, which where |
120 | * Copyright (c) 1997 Dan Malek (dmalek@jlc.net). | 119 | * Copyright (c) 1997 Dan Malek (dmalek@jlc.net). |
@@ -214,8 +213,6 @@ struct fec_enet_private { | |||
214 | unsigned char *tx_bounce[TX_RING_SIZE]; | 213 | unsigned char *tx_bounce[TX_RING_SIZE]; |
215 | struct sk_buff *tx_skbuff[TX_RING_SIZE]; | 214 | struct sk_buff *tx_skbuff[TX_RING_SIZE]; |
216 | struct sk_buff *rx_skbuff[RX_RING_SIZE]; | 215 | struct sk_buff *rx_skbuff[RX_RING_SIZE]; |
217 | ushort skb_cur; | ||
218 | ushort skb_dirty; | ||
219 | 216 | ||
220 | /* CPM dual port RAM relative addresses */ | 217 | /* CPM dual port RAM relative addresses */ |
221 | dma_addr_t bd_dma; | 218 | dma_addr_t bd_dma; |
@@ -227,7 +224,6 @@ struct fec_enet_private { | |||
227 | /* The ring entries to be free()ed */ | 224 | /* The ring entries to be free()ed */ |
228 | struct bufdesc *dirty_tx; | 225 | struct bufdesc *dirty_tx; |
229 | 226 | ||
230 | uint tx_full; | ||
231 | /* hold while accessing the HW like ringbuffer for tx/rx but not MAC */ | 227 | /* hold while accessing the HW like ringbuffer for tx/rx but not MAC */ |
232 | spinlock_t hw_lock; | 228 | spinlock_t hw_lock; |
233 | 229 | ||
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c index dff7bff8b8e0..121a865c7fbd 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.c +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c | |||
@@ -782,6 +782,59 @@ release: | |||
782 | } | 782 | } |
783 | 783 | ||
784 | /** | 784 | /** |
785 | * e1000_k1_workaround_lpt_lp - K1 workaround on Lynxpoint-LP | ||
786 | * @hw: pointer to the HW structure | ||
787 | * @link: link up bool flag | ||
788 | * | ||
789 | * When K1 is enabled for 1Gbps, the MAC can miss 2 DMA completion indications | ||
790 | * preventing further DMA write requests. Workaround the issue by disabling | ||
791 | * the de-assertion of the clock request when in 1Gpbs mode. | ||
792 | **/ | ||
793 | static s32 e1000_k1_workaround_lpt_lp(struct e1000_hw *hw, bool link) | ||
794 | { | ||
795 | u32 fextnvm6 = er32(FEXTNVM6); | ||
796 | s32 ret_val = 0; | ||
797 | |||
798 | if (link && (er32(STATUS) & E1000_STATUS_SPEED_1000)) { | ||
799 | u16 kmrn_reg; | ||
800 | |||
801 | ret_val = hw->phy.ops.acquire(hw); | ||
802 | if (ret_val) | ||
803 | return ret_val; | ||
804 | |||
805 | ret_val = | ||
806 | e1000e_read_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG, | ||
807 | &kmrn_reg); | ||
808 | if (ret_val) | ||
809 | goto release; | ||
810 | |||
811 | ret_val = | ||
812 | e1000e_write_kmrn_reg_locked(hw, | ||
813 | E1000_KMRNCTRLSTA_K1_CONFIG, | ||
814 | kmrn_reg & | ||
815 | ~E1000_KMRNCTRLSTA_K1_ENABLE); | ||
816 | if (ret_val) | ||
817 | goto release; | ||
818 | |||
819 | usleep_range(10, 20); | ||
820 | |||
821 | ew32(FEXTNVM6, fextnvm6 | E1000_FEXTNVM6_REQ_PLL_CLK); | ||
822 | |||
823 | ret_val = | ||
824 | e1000e_write_kmrn_reg_locked(hw, | ||
825 | E1000_KMRNCTRLSTA_K1_CONFIG, | ||
826 | kmrn_reg); | ||
827 | release: | ||
828 | hw->phy.ops.release(hw); | ||
829 | } else { | ||
830 | /* clear FEXTNVM6 bit 8 on link down or 10/100 */ | ||
831 | ew32(FEXTNVM6, fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK); | ||
832 | } | ||
833 | |||
834 | return ret_val; | ||
835 | } | ||
836 | |||
837 | /** | ||
785 | * e1000_check_for_copper_link_ich8lan - Check for link (Copper) | 838 | * e1000_check_for_copper_link_ich8lan - Check for link (Copper) |
786 | * @hw: pointer to the HW structure | 839 | * @hw: pointer to the HW structure |
787 | * | 840 | * |
@@ -818,6 +871,14 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) | |||
818 | return ret_val; | 871 | return ret_val; |
819 | } | 872 | } |
820 | 873 | ||
874 | /* Work-around I218 hang issue */ | ||
875 | if ((hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPTLP_I218_LM) || | ||
876 | (hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPTLP_I218_V)) { | ||
877 | ret_val = e1000_k1_workaround_lpt_lp(hw, link); | ||
878 | if (ret_val) | ||
879 | return ret_val; | ||
880 | } | ||
881 | |||
821 | /* Clear link partner's EEE ability */ | 882 | /* Clear link partner's EEE ability */ |
822 | hw->dev_spec.ich8lan.eee_lp_ability = 0; | 883 | hw->dev_spec.ich8lan.eee_lp_ability = 0; |
823 | 884 | ||
@@ -3954,8 +4015,16 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw) | |||
3954 | 4015 | ||
3955 | phy_ctrl = er32(PHY_CTRL); | 4016 | phy_ctrl = er32(PHY_CTRL); |
3956 | phy_ctrl |= E1000_PHY_CTRL_GBE_DISABLE; | 4017 | phy_ctrl |= E1000_PHY_CTRL_GBE_DISABLE; |
4018 | |||
3957 | if (hw->phy.type == e1000_phy_i217) { | 4019 | if (hw->phy.type == e1000_phy_i217) { |
3958 | u16 phy_reg; | 4020 | u16 phy_reg, device_id = hw->adapter->pdev->device; |
4021 | |||
4022 | if ((device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) || | ||
4023 | (device_id == E1000_DEV_ID_PCH_LPTLP_I218_V)) { | ||
4024 | u32 fextnvm6 = er32(FEXTNVM6); | ||
4025 | |||
4026 | ew32(FEXTNVM6, fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK); | ||
4027 | } | ||
3959 | 4028 | ||
3960 | ret_val = hw->phy.ops.acquire(hw); | 4029 | ret_val = hw->phy.ops.acquire(hw); |
3961 | if (ret_val) | 4030 | if (ret_val) |
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.h b/drivers/net/ethernet/intel/e1000e/ich8lan.h index b6d3174d7d2d..8bf4655c2e17 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.h +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.h | |||
@@ -92,6 +92,8 @@ | |||
92 | #define E1000_FEXTNVM4_BEACON_DURATION_8USEC 0x7 | 92 | #define E1000_FEXTNVM4_BEACON_DURATION_8USEC 0x7 |
93 | #define E1000_FEXTNVM4_BEACON_DURATION_16USEC 0x3 | 93 | #define E1000_FEXTNVM4_BEACON_DURATION_16USEC 0x3 |
94 | 94 | ||
95 | #define E1000_FEXTNVM6_REQ_PLL_CLK 0x00000100 | ||
96 | |||
95 | #define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL | 97 | #define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL |
96 | 98 | ||
97 | #define E1000_ICH_RAR_ENTRIES 7 | 99 | #define E1000_ICH_RAR_ENTRIES 7 |
diff --git a/drivers/net/ethernet/intel/e1000e/regs.h b/drivers/net/ethernet/intel/e1000e/regs.h index 794fe1497666..a7e6a3e37257 100644 --- a/drivers/net/ethernet/intel/e1000e/regs.h +++ b/drivers/net/ethernet/intel/e1000e/regs.h | |||
@@ -42,6 +42,7 @@ | |||
42 | #define E1000_FEXTNVM 0x00028 /* Future Extended NVM - RW */ | 42 | #define E1000_FEXTNVM 0x00028 /* Future Extended NVM - RW */ |
43 | #define E1000_FEXTNVM3 0x0003C /* Future Extended NVM 3 - RW */ | 43 | #define E1000_FEXTNVM3 0x0003C /* Future Extended NVM 3 - RW */ |
44 | #define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */ | 44 | #define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */ |
45 | #define E1000_FEXTNVM6 0x00010 /* Future Extended NVM 6 - RW */ | ||
45 | #define E1000_FEXTNVM7 0x000E4 /* Future Extended NVM 7 - RW */ | 46 | #define E1000_FEXTNVM7 0x000E4 /* Future Extended NVM 7 - RW */ |
46 | #define E1000_FCT 0x00030 /* Flow Control Type - RW */ | 47 | #define E1000_FCT 0x00030 /* Flow Control Type - RW */ |
47 | #define E1000_VET 0x00038 /* VLAN Ether Type - RW */ | 48 | #define E1000_VET 0x00038 /* VLAN Ether Type - RW */ |
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c index 84e7e0909def..b64542acfa34 100644 --- a/drivers/net/ethernet/intel/igb/e1000_82575.c +++ b/drivers/net/ethernet/intel/igb/e1000_82575.c | |||
@@ -1361,11 +1361,16 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw) | |||
1361 | switch (hw->phy.type) { | 1361 | switch (hw->phy.type) { |
1362 | case e1000_phy_i210: | 1362 | case e1000_phy_i210: |
1363 | case e1000_phy_m88: | 1363 | case e1000_phy_m88: |
1364 | if (hw->phy.id == I347AT4_E_PHY_ID || | 1364 | switch (hw->phy.id) { |
1365 | hw->phy.id == M88E1112_E_PHY_ID) | 1365 | case I347AT4_E_PHY_ID: |
1366 | case M88E1112_E_PHY_ID: | ||
1367 | case I210_I_PHY_ID: | ||
1366 | ret_val = igb_copper_link_setup_m88_gen2(hw); | 1368 | ret_val = igb_copper_link_setup_m88_gen2(hw); |
1367 | else | 1369 | break; |
1370 | default: | ||
1368 | ret_val = igb_copper_link_setup_m88(hw); | 1371 | ret_val = igb_copper_link_setup_m88(hw); |
1372 | break; | ||
1373 | } | ||
1369 | break; | 1374 | break; |
1370 | case e1000_phy_igp_3: | 1375 | case e1000_phy_igp_3: |
1371 | ret_val = igb_copper_link_setup_igp(hw); | 1376 | ret_val = igb_copper_link_setup_igp(hw); |
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index d27edbc63923..25151401c2ab 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h | |||
@@ -447,7 +447,7 @@ struct igb_adapter { | |||
447 | #endif | 447 | #endif |
448 | struct i2c_algo_bit_data i2c_algo; | 448 | struct i2c_algo_bit_data i2c_algo; |
449 | struct i2c_adapter i2c_adap; | 449 | struct i2c_adapter i2c_adap; |
450 | struct igb_i2c_client_list *i2c_clients; | 450 | struct i2c_client *i2c_client; |
451 | }; | 451 | }; |
452 | 452 | ||
453 | #define IGB_FLAG_HAS_MSI (1 << 0) | 453 | #define IGB_FLAG_HAS_MSI (1 << 0) |
diff --git a/drivers/net/ethernet/intel/igb/igb_hwmon.c b/drivers/net/ethernet/intel/igb/igb_hwmon.c index 0a9b073d0b03..4623502054d5 100644 --- a/drivers/net/ethernet/intel/igb/igb_hwmon.c +++ b/drivers/net/ethernet/intel/igb/igb_hwmon.c | |||
@@ -39,6 +39,10 @@ | |||
39 | #include <linux/pci.h> | 39 | #include <linux/pci.h> |
40 | 40 | ||
41 | #ifdef CONFIG_IGB_HWMON | 41 | #ifdef CONFIG_IGB_HWMON |
42 | struct i2c_board_info i350_sensor_info = { | ||
43 | I2C_BOARD_INFO("i350bb", (0Xf8 >> 1)), | ||
44 | }; | ||
45 | |||
42 | /* hwmon callback functions */ | 46 | /* hwmon callback functions */ |
43 | static ssize_t igb_hwmon_show_location(struct device *dev, | 47 | static ssize_t igb_hwmon_show_location(struct device *dev, |
44 | struct device_attribute *attr, | 48 | struct device_attribute *attr, |
@@ -188,6 +192,7 @@ int igb_sysfs_init(struct igb_adapter *adapter) | |||
188 | unsigned int i; | 192 | unsigned int i; |
189 | int n_attrs; | 193 | int n_attrs; |
190 | int rc = 0; | 194 | int rc = 0; |
195 | struct i2c_client *client = NULL; | ||
191 | 196 | ||
192 | /* If this method isn't defined we don't support thermals */ | 197 | /* If this method isn't defined we don't support thermals */ |
193 | if (adapter->hw.mac.ops.init_thermal_sensor_thresh == NULL) | 198 | if (adapter->hw.mac.ops.init_thermal_sensor_thresh == NULL) |
@@ -198,6 +203,15 @@ int igb_sysfs_init(struct igb_adapter *adapter) | |||
198 | if (rc) | 203 | if (rc) |
199 | goto exit; | 204 | goto exit; |
200 | 205 | ||
206 | /* init i2c_client */ | ||
207 | client = i2c_new_device(&adapter->i2c_adap, &i350_sensor_info); | ||
208 | if (client == NULL) { | ||
209 | dev_info(&adapter->pdev->dev, | ||
210 | "Failed to create new i2c device..\n"); | ||
211 | goto exit; | ||
212 | } | ||
213 | adapter->i2c_client = client; | ||
214 | |||
201 | /* Allocation space for max attributes | 215 | /* Allocation space for max attributes |
202 | * max num sensors * values (loc, temp, max, caution) | 216 | * max num sensors * values (loc, temp, max, caution) |
203 | */ | 217 | */ |
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index ed79a1c53b59..4dbd62968c7a 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c | |||
@@ -1923,10 +1923,6 @@ void igb_set_fw_version(struct igb_adapter *adapter) | |||
1923 | return; | 1923 | return; |
1924 | } | 1924 | } |
1925 | 1925 | ||
1926 | static const struct i2c_board_info i350_sensor_info = { | ||
1927 | I2C_BOARD_INFO("i350bb", 0Xf8), | ||
1928 | }; | ||
1929 | |||
1930 | /* igb_init_i2c - Init I2C interface | 1926 | /* igb_init_i2c - Init I2C interface |
1931 | * @adapter: pointer to adapter structure | 1927 | * @adapter: pointer to adapter structure |
1932 | * | 1928 | * |
@@ -6227,13 +6223,6 @@ static struct sk_buff *igb_build_rx_buffer(struct igb_ring *rx_ring, | |||
6227 | /* If we spanned a buffer we have a huge mess so test for it */ | 6223 | /* If we spanned a buffer we have a huge mess so test for it */ |
6228 | BUG_ON(unlikely(!igb_test_staterr(rx_desc, E1000_RXD_STAT_EOP))); | 6224 | BUG_ON(unlikely(!igb_test_staterr(rx_desc, E1000_RXD_STAT_EOP))); |
6229 | 6225 | ||
6230 | /* Guarantee this function can be used by verifying buffer sizes */ | ||
6231 | BUILD_BUG_ON(SKB_WITH_OVERHEAD(IGB_RX_BUFSZ) < (NET_SKB_PAD + | ||
6232 | NET_IP_ALIGN + | ||
6233 | IGB_TS_HDR_LEN + | ||
6234 | ETH_FRAME_LEN + | ||
6235 | ETH_FCS_LEN)); | ||
6236 | |||
6237 | rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean]; | 6226 | rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean]; |
6238 | page = rx_buffer->page; | 6227 | page = rx_buffer->page; |
6239 | prefetchw(page); | 6228 | prefetchw(page); |
@@ -7724,67 +7713,6 @@ static void igb_init_dmac(struct igb_adapter *adapter, u32 pba) | |||
7724 | } | 7713 | } |
7725 | } | 7714 | } |
7726 | 7715 | ||
7727 | static DEFINE_SPINLOCK(i2c_clients_lock); | ||
7728 | |||
7729 | /* igb_get_i2c_client - returns matching client | ||
7730 | * in adapters's client list. | ||
7731 | * @adapter: adapter struct | ||
7732 | * @dev_addr: device address of i2c needed. | ||
7733 | */ | ||
7734 | static struct i2c_client * | ||
7735 | igb_get_i2c_client(struct igb_adapter *adapter, u8 dev_addr) | ||
7736 | { | ||
7737 | ulong flags; | ||
7738 | struct igb_i2c_client_list *client_list; | ||
7739 | struct i2c_client *client = NULL; | ||
7740 | struct i2c_board_info client_info = { | ||
7741 | I2C_BOARD_INFO("igb", 0x00), | ||
7742 | }; | ||
7743 | |||
7744 | spin_lock_irqsave(&i2c_clients_lock, flags); | ||
7745 | client_list = adapter->i2c_clients; | ||
7746 | |||
7747 | /* See if we already have an i2c_client */ | ||
7748 | while (client_list) { | ||
7749 | if (client_list->client->addr == (dev_addr >> 1)) { | ||
7750 | client = client_list->client; | ||
7751 | goto exit; | ||
7752 | } else { | ||
7753 | client_list = client_list->next; | ||
7754 | } | ||
7755 | } | ||
7756 | |||
7757 | /* no client_list found, create a new one */ | ||
7758 | client_list = kzalloc(sizeof(*client_list), GFP_ATOMIC); | ||
7759 | if (client_list == NULL) | ||
7760 | goto exit; | ||
7761 | |||
7762 | /* dev_addr passed to us is left-shifted by 1 bit | ||
7763 | * i2c_new_device call expects it to be flush to the right. | ||
7764 | */ | ||
7765 | client_info.addr = dev_addr >> 1; | ||
7766 | client_info.platform_data = adapter; | ||
7767 | client_list->client = i2c_new_device(&adapter->i2c_adap, &client_info); | ||
7768 | if (client_list->client == NULL) { | ||
7769 | dev_info(&adapter->pdev->dev, | ||
7770 | "Failed to create new i2c device..\n"); | ||
7771 | goto err_no_client; | ||
7772 | } | ||
7773 | |||
7774 | /* insert new client at head of list */ | ||
7775 | client_list->next = adapter->i2c_clients; | ||
7776 | adapter->i2c_clients = client_list; | ||
7777 | |||
7778 | client = client_list->client; | ||
7779 | goto exit; | ||
7780 | |||
7781 | err_no_client: | ||
7782 | kfree(client_list); | ||
7783 | exit: | ||
7784 | spin_unlock_irqrestore(&i2c_clients_lock, flags); | ||
7785 | return client; | ||
7786 | } | ||
7787 | |||
7788 | /* igb_read_i2c_byte - Reads 8 bit word over I2C | 7716 | /* igb_read_i2c_byte - Reads 8 bit word over I2C |
7789 | * @hw: pointer to hardware structure | 7717 | * @hw: pointer to hardware structure |
7790 | * @byte_offset: byte offset to read | 7718 | * @byte_offset: byte offset to read |
@@ -7798,7 +7726,7 @@ s32 igb_read_i2c_byte(struct e1000_hw *hw, u8 byte_offset, | |||
7798 | u8 dev_addr, u8 *data) | 7726 | u8 dev_addr, u8 *data) |
7799 | { | 7727 | { |
7800 | struct igb_adapter *adapter = container_of(hw, struct igb_adapter, hw); | 7728 | struct igb_adapter *adapter = container_of(hw, struct igb_adapter, hw); |
7801 | struct i2c_client *this_client = igb_get_i2c_client(adapter, dev_addr); | 7729 | struct i2c_client *this_client = adapter->i2c_client; |
7802 | s32 status; | 7730 | s32 status; |
7803 | u16 swfw_mask = 0; | 7731 | u16 swfw_mask = 0; |
7804 | 7732 | ||
@@ -7835,7 +7763,7 @@ s32 igb_write_i2c_byte(struct e1000_hw *hw, u8 byte_offset, | |||
7835 | u8 dev_addr, u8 data) | 7763 | u8 dev_addr, u8 data) |
7836 | { | 7764 | { |
7837 | struct igb_adapter *adapter = container_of(hw, struct igb_adapter, hw); | 7765 | struct igb_adapter *adapter = container_of(hw, struct igb_adapter, hw); |
7838 | struct i2c_client *this_client = igb_get_i2c_client(adapter, dev_addr); | 7766 | struct i2c_client *this_client = adapter->i2c_client; |
7839 | s32 status; | 7767 | s32 status; |
7840 | u16 swfw_mask = E1000_SWFW_PHY0_SM; | 7768 | u16 swfw_mask = E1000_SWFW_PHY0_SM; |
7841 | 7769 | ||
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 8900398ba103..28fb50a1e9c3 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c | |||
@@ -4765,8 +4765,10 @@ static void rtl_hw_start_8168bb(struct rtl8169_private *tp) | |||
4765 | 4765 | ||
4766 | RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); | 4766 | RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); |
4767 | 4767 | ||
4768 | rtl_tx_performance_tweak(pdev, | 4768 | if (tp->dev->mtu <= ETH_DATA_LEN) { |
4769 | (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); | 4769 | rtl_tx_performance_tweak(pdev, (0x5 << MAX_READ_REQUEST_SHIFT) | |
4770 | PCI_EXP_DEVCTL_NOSNOOP_EN); | ||
4771 | } | ||
4770 | } | 4772 | } |
4771 | 4773 | ||
4772 | static void rtl_hw_start_8168bef(struct rtl8169_private *tp) | 4774 | static void rtl_hw_start_8168bef(struct rtl8169_private *tp) |
@@ -4789,7 +4791,8 @@ static void __rtl_hw_start_8168cp(struct rtl8169_private *tp) | |||
4789 | 4791 | ||
4790 | RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); | 4792 | RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); |
4791 | 4793 | ||
4792 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | 4794 | if (tp->dev->mtu <= ETH_DATA_LEN) |
4795 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | ||
4793 | 4796 | ||
4794 | rtl_disable_clock_request(pdev); | 4797 | rtl_disable_clock_request(pdev); |
4795 | 4798 | ||
@@ -4822,7 +4825,8 @@ static void rtl_hw_start_8168cp_2(struct rtl8169_private *tp) | |||
4822 | 4825 | ||
4823 | RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); | 4826 | RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); |
4824 | 4827 | ||
4825 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | 4828 | if (tp->dev->mtu <= ETH_DATA_LEN) |
4829 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | ||
4826 | 4830 | ||
4827 | RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); | 4831 | RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); |
4828 | } | 4832 | } |
@@ -4841,7 +4845,8 @@ static void rtl_hw_start_8168cp_3(struct rtl8169_private *tp) | |||
4841 | 4845 | ||
4842 | RTL_W8(MaxTxPacketSize, TxPacketMax); | 4846 | RTL_W8(MaxTxPacketSize, TxPacketMax); |
4843 | 4847 | ||
4844 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | 4848 | if (tp->dev->mtu <= ETH_DATA_LEN) |
4849 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | ||
4845 | 4850 | ||
4846 | RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); | 4851 | RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); |
4847 | } | 4852 | } |
@@ -4901,7 +4906,8 @@ static void rtl_hw_start_8168d(struct rtl8169_private *tp) | |||
4901 | 4906 | ||
4902 | RTL_W8(MaxTxPacketSize, TxPacketMax); | 4907 | RTL_W8(MaxTxPacketSize, TxPacketMax); |
4903 | 4908 | ||
4904 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | 4909 | if (tp->dev->mtu <= ETH_DATA_LEN) |
4910 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | ||
4905 | 4911 | ||
4906 | RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); | 4912 | RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); |
4907 | } | 4913 | } |
@@ -4913,7 +4919,8 @@ static void rtl_hw_start_8168dp(struct rtl8169_private *tp) | |||
4913 | 4919 | ||
4914 | rtl_csi_access_enable_1(tp); | 4920 | rtl_csi_access_enable_1(tp); |
4915 | 4921 | ||
4916 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | 4922 | if (tp->dev->mtu <= ETH_DATA_LEN) |
4923 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | ||
4917 | 4924 | ||
4918 | RTL_W8(MaxTxPacketSize, TxPacketMax); | 4925 | RTL_W8(MaxTxPacketSize, TxPacketMax); |
4919 | 4926 | ||
@@ -4972,7 +4979,8 @@ static void rtl_hw_start_8168e_1(struct rtl8169_private *tp) | |||
4972 | 4979 | ||
4973 | rtl_ephy_init(tp, e_info_8168e_1, ARRAY_SIZE(e_info_8168e_1)); | 4980 | rtl_ephy_init(tp, e_info_8168e_1, ARRAY_SIZE(e_info_8168e_1)); |
4974 | 4981 | ||
4975 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | 4982 | if (tp->dev->mtu <= ETH_DATA_LEN) |
4983 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | ||
4976 | 4984 | ||
4977 | RTL_W8(MaxTxPacketSize, TxPacketMax); | 4985 | RTL_W8(MaxTxPacketSize, TxPacketMax); |
4978 | 4986 | ||
@@ -4998,7 +5006,8 @@ static void rtl_hw_start_8168e_2(struct rtl8169_private *tp) | |||
4998 | 5006 | ||
4999 | rtl_ephy_init(tp, e_info_8168e_2, ARRAY_SIZE(e_info_8168e_2)); | 5007 | rtl_ephy_init(tp, e_info_8168e_2, ARRAY_SIZE(e_info_8168e_2)); |
5000 | 5008 | ||
5001 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | 5009 | if (tp->dev->mtu <= ETH_DATA_LEN) |
5010 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | ||
5002 | 5011 | ||
5003 | rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); | 5012 | rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); |
5004 | rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); | 5013 | rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); |
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index bf57b3cb16ab..0bc00991d310 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c | |||
@@ -779,6 +779,7 @@ efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries) | |||
779 | tx_queue->txd.entries); | 779 | tx_queue->txd.entries); |
780 | } | 780 | } |
781 | 781 | ||
782 | efx_device_detach_sync(efx); | ||
782 | efx_stop_all(efx); | 783 | efx_stop_all(efx); |
783 | efx_stop_interrupts(efx, true); | 784 | efx_stop_interrupts(efx, true); |
784 | 785 | ||
@@ -832,6 +833,7 @@ out: | |||
832 | 833 | ||
833 | efx_start_interrupts(efx, true); | 834 | efx_start_interrupts(efx, true); |
834 | efx_start_all(efx); | 835 | efx_start_all(efx); |
836 | netif_device_attach(efx->net_dev); | ||
835 | return rc; | 837 | return rc; |
836 | 838 | ||
837 | rollback: | 839 | rollback: |
@@ -1641,8 +1643,12 @@ static void efx_stop_all(struct efx_nic *efx) | |||
1641 | /* Flush efx_mac_work(), refill_workqueue, monitor_work */ | 1643 | /* Flush efx_mac_work(), refill_workqueue, monitor_work */ |
1642 | efx_flush_all(efx); | 1644 | efx_flush_all(efx); |
1643 | 1645 | ||
1644 | /* Stop the kernel transmit interface late, so the watchdog | 1646 | /* Stop the kernel transmit interface. This is only valid if |
1645 | * timer isn't ticking over the flush */ | 1647 | * the device is stopped or detached; otherwise the watchdog |
1648 | * may fire immediately. | ||
1649 | */ | ||
1650 | WARN_ON(netif_running(efx->net_dev) && | ||
1651 | netif_device_present(efx->net_dev)); | ||
1646 | netif_tx_disable(efx->net_dev); | 1652 | netif_tx_disable(efx->net_dev); |
1647 | 1653 | ||
1648 | efx_stop_datapath(efx); | 1654 | efx_stop_datapath(efx); |
@@ -1963,16 +1969,18 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu) | |||
1963 | if (new_mtu > EFX_MAX_MTU) | 1969 | if (new_mtu > EFX_MAX_MTU) |
1964 | return -EINVAL; | 1970 | return -EINVAL; |
1965 | 1971 | ||
1966 | efx_stop_all(efx); | ||
1967 | |||
1968 | netif_dbg(efx, drv, efx->net_dev, "changing MTU to %d\n", new_mtu); | 1972 | netif_dbg(efx, drv, efx->net_dev, "changing MTU to %d\n", new_mtu); |
1969 | 1973 | ||
1974 | efx_device_detach_sync(efx); | ||
1975 | efx_stop_all(efx); | ||
1976 | |||
1970 | mutex_lock(&efx->mac_lock); | 1977 | mutex_lock(&efx->mac_lock); |
1971 | net_dev->mtu = new_mtu; | 1978 | net_dev->mtu = new_mtu; |
1972 | efx->type->reconfigure_mac(efx); | 1979 | efx->type->reconfigure_mac(efx); |
1973 | mutex_unlock(&efx->mac_lock); | 1980 | mutex_unlock(&efx->mac_lock); |
1974 | 1981 | ||
1975 | efx_start_all(efx); | 1982 | efx_start_all(efx); |
1983 | netif_device_attach(efx->net_dev); | ||
1976 | return 0; | 1984 | return 0; |
1977 | } | 1985 | } |
1978 | 1986 | ||
diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h index 50247dfe8f57..d2f790df6dcb 100644 --- a/drivers/net/ethernet/sfc/efx.h +++ b/drivers/net/ethernet/sfc/efx.h | |||
@@ -171,9 +171,9 @@ static inline void efx_device_detach_sync(struct efx_nic *efx) | |||
171 | * TX scheduler is stopped when we're done and before | 171 | * TX scheduler is stopped when we're done and before |
172 | * netif_device_present() becomes false. | 172 | * netif_device_present() becomes false. |
173 | */ | 173 | */ |
174 | netif_tx_lock(dev); | 174 | netif_tx_lock_bh(dev); |
175 | netif_device_detach(dev); | 175 | netif_device_detach(dev); |
176 | netif_tx_unlock(dev); | 176 | netif_tx_unlock_bh(dev); |
177 | } | 177 | } |
178 | 178 | ||
179 | #endif /* EFX_EFX_H */ | 179 | #endif /* EFX_EFX_H */ |
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 2d756c1d7142..0a90abd2421b 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h | |||
@@ -210,6 +210,7 @@ struct efx_tx_queue { | |||
210 | * Will be %NULL if the buffer slot is currently free. | 210 | * Will be %NULL if the buffer slot is currently free. |
211 | * @page: The associated page buffer. Valif iff @flags & %EFX_RX_BUF_PAGE. | 211 | * @page: The associated page buffer. Valif iff @flags & %EFX_RX_BUF_PAGE. |
212 | * Will be %NULL if the buffer slot is currently free. | 212 | * Will be %NULL if the buffer slot is currently free. |
213 | * @page_offset: Offset within page. Valid iff @flags & %EFX_RX_BUF_PAGE. | ||
213 | * @len: Buffer length, in bytes. | 214 | * @len: Buffer length, in bytes. |
214 | * @flags: Flags for buffer and packet state. | 215 | * @flags: Flags for buffer and packet state. |
215 | */ | 216 | */ |
@@ -219,7 +220,8 @@ struct efx_rx_buffer { | |||
219 | struct sk_buff *skb; | 220 | struct sk_buff *skb; |
220 | struct page *page; | 221 | struct page *page; |
221 | } u; | 222 | } u; |
222 | unsigned int len; | 223 | u16 page_offset; |
224 | u16 len; | ||
223 | u16 flags; | 225 | u16 flags; |
224 | }; | 226 | }; |
225 | #define EFX_RX_BUF_PAGE 0x0001 | 227 | #define EFX_RX_BUF_PAGE 0x0001 |
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index d780a0d096b4..bb579a6128c8 100644 --- a/drivers/net/ethernet/sfc/rx.c +++ b/drivers/net/ethernet/sfc/rx.c | |||
@@ -90,11 +90,7 @@ static unsigned int rx_refill_threshold; | |||
90 | static inline unsigned int efx_rx_buf_offset(struct efx_nic *efx, | 90 | static inline unsigned int efx_rx_buf_offset(struct efx_nic *efx, |
91 | struct efx_rx_buffer *buf) | 91 | struct efx_rx_buffer *buf) |
92 | { | 92 | { |
93 | /* Offset is always within one page, so we don't need to consider | 93 | return buf->page_offset + efx->type->rx_buffer_hash_size; |
94 | * the page order. | ||
95 | */ | ||
96 | return ((unsigned int) buf->dma_addr & (PAGE_SIZE - 1)) + | ||
97 | efx->type->rx_buffer_hash_size; | ||
98 | } | 94 | } |
99 | static inline unsigned int efx_rx_buf_size(struct efx_nic *efx) | 95 | static inline unsigned int efx_rx_buf_size(struct efx_nic *efx) |
100 | { | 96 | { |
@@ -187,6 +183,7 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) | |||
187 | struct efx_nic *efx = rx_queue->efx; | 183 | struct efx_nic *efx = rx_queue->efx; |
188 | struct efx_rx_buffer *rx_buf; | 184 | struct efx_rx_buffer *rx_buf; |
189 | struct page *page; | 185 | struct page *page; |
186 | unsigned int page_offset; | ||
190 | struct efx_rx_page_state *state; | 187 | struct efx_rx_page_state *state; |
191 | dma_addr_t dma_addr; | 188 | dma_addr_t dma_addr; |
192 | unsigned index, count; | 189 | unsigned index, count; |
@@ -211,12 +208,14 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) | |||
211 | state->dma_addr = dma_addr; | 208 | state->dma_addr = dma_addr; |
212 | 209 | ||
213 | dma_addr += sizeof(struct efx_rx_page_state); | 210 | dma_addr += sizeof(struct efx_rx_page_state); |
211 | page_offset = sizeof(struct efx_rx_page_state); | ||
214 | 212 | ||
215 | split: | 213 | split: |
216 | index = rx_queue->added_count & rx_queue->ptr_mask; | 214 | index = rx_queue->added_count & rx_queue->ptr_mask; |
217 | rx_buf = efx_rx_buffer(rx_queue, index); | 215 | rx_buf = efx_rx_buffer(rx_queue, index); |
218 | rx_buf->dma_addr = dma_addr + EFX_PAGE_IP_ALIGN; | 216 | rx_buf->dma_addr = dma_addr + EFX_PAGE_IP_ALIGN; |
219 | rx_buf->u.page = page; | 217 | rx_buf->u.page = page; |
218 | rx_buf->page_offset = page_offset + EFX_PAGE_IP_ALIGN; | ||
220 | rx_buf->len = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN; | 219 | rx_buf->len = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN; |
221 | rx_buf->flags = EFX_RX_BUF_PAGE; | 220 | rx_buf->flags = EFX_RX_BUF_PAGE; |
222 | ++rx_queue->added_count; | 221 | ++rx_queue->added_count; |
@@ -227,6 +226,7 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) | |||
227 | /* Use the second half of the page */ | 226 | /* Use the second half of the page */ |
228 | get_page(page); | 227 | get_page(page); |
229 | dma_addr += (PAGE_SIZE >> 1); | 228 | dma_addr += (PAGE_SIZE >> 1); |
229 | page_offset += (PAGE_SIZE >> 1); | ||
230 | ++count; | 230 | ++count; |
231 | goto split; | 231 | goto split; |
232 | } | 232 | } |
@@ -236,7 +236,8 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) | |||
236 | } | 236 | } |
237 | 237 | ||
238 | static void efx_unmap_rx_buffer(struct efx_nic *efx, | 238 | static void efx_unmap_rx_buffer(struct efx_nic *efx, |
239 | struct efx_rx_buffer *rx_buf) | 239 | struct efx_rx_buffer *rx_buf, |
240 | unsigned int used_len) | ||
240 | { | 241 | { |
241 | if ((rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.page) { | 242 | if ((rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.page) { |
242 | struct efx_rx_page_state *state; | 243 | struct efx_rx_page_state *state; |
@@ -247,6 +248,10 @@ static void efx_unmap_rx_buffer(struct efx_nic *efx, | |||
247 | state->dma_addr, | 248 | state->dma_addr, |
248 | efx_rx_buf_size(efx), | 249 | efx_rx_buf_size(efx), |
249 | DMA_FROM_DEVICE); | 250 | DMA_FROM_DEVICE); |
251 | } else if (used_len) { | ||
252 | dma_sync_single_for_cpu(&efx->pci_dev->dev, | ||
253 | rx_buf->dma_addr, used_len, | ||
254 | DMA_FROM_DEVICE); | ||
250 | } | 255 | } |
251 | } else if (!(rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.skb) { | 256 | } else if (!(rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.skb) { |
252 | dma_unmap_single(&efx->pci_dev->dev, rx_buf->dma_addr, | 257 | dma_unmap_single(&efx->pci_dev->dev, rx_buf->dma_addr, |
@@ -269,7 +274,7 @@ static void efx_free_rx_buffer(struct efx_nic *efx, | |||
269 | static void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue, | 274 | static void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue, |
270 | struct efx_rx_buffer *rx_buf) | 275 | struct efx_rx_buffer *rx_buf) |
271 | { | 276 | { |
272 | efx_unmap_rx_buffer(rx_queue->efx, rx_buf); | 277 | efx_unmap_rx_buffer(rx_queue->efx, rx_buf, 0); |
273 | efx_free_rx_buffer(rx_queue->efx, rx_buf); | 278 | efx_free_rx_buffer(rx_queue->efx, rx_buf); |
274 | } | 279 | } |
275 | 280 | ||
@@ -535,10 +540,10 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index, | |||
535 | goto out; | 540 | goto out; |
536 | } | 541 | } |
537 | 542 | ||
538 | /* Release card resources - assumes all RX buffers consumed in-order | 543 | /* Release and/or sync DMA mapping - assumes all RX buffers |
539 | * per RX queue | 544 | * consumed in-order per RX queue |
540 | */ | 545 | */ |
541 | efx_unmap_rx_buffer(efx, rx_buf); | 546 | efx_unmap_rx_buffer(efx, rx_buf, len); |
542 | 547 | ||
543 | /* Prefetch nice and early so data will (hopefully) be in cache by | 548 | /* Prefetch nice and early so data will (hopefully) be in cache by |
544 | * the time we look at it. | 549 | * the time we look at it. |
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 7e93df6585e7..01ffbc486982 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c | |||
@@ -731,7 +731,7 @@ static inline void cpsw_add_default_vlan(struct cpsw_priv *priv) | |||
731 | 731 | ||
732 | writel(vlan, &priv->host_port_regs->port_vlan); | 732 | writel(vlan, &priv->host_port_regs->port_vlan); |
733 | 733 | ||
734 | for (i = 0; i < 2; i++) | 734 | for (i = 0; i < priv->data.slaves; i++) |
735 | slave_write(priv->slaves + i, vlan, reg); | 735 | slave_write(priv->slaves + i, vlan, reg); |
736 | 736 | ||
737 | cpsw_ale_add_vlan(priv->ale, vlan, ALE_ALL_PORTS << port, | 737 | cpsw_ale_add_vlan(priv->ale, vlan, ALE_ALL_PORTS << port, |
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 29934446436a..abf7b6153d00 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c | |||
@@ -257,8 +257,7 @@ static struct phy_driver ksphy_driver[] = { | |||
257 | .phy_id = PHY_ID_KSZ9021, | 257 | .phy_id = PHY_ID_KSZ9021, |
258 | .phy_id_mask = 0x000ffffe, | 258 | .phy_id_mask = 0x000ffffe, |
259 | .name = "Micrel KSZ9021 Gigabit PHY", | 259 | .name = "Micrel KSZ9021 Gigabit PHY", |
260 | .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause | 260 | .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause), |
261 | | SUPPORTED_Asym_Pause), | ||
262 | .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, | 261 | .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, |
263 | .config_init = kszphy_config_init, | 262 | .config_init = kszphy_config_init, |
264 | .config_aneg = genphy_config_aneg, | 263 | .config_aneg = genphy_config_aneg, |
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 9930f9999561..3657b4a29124 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c | |||
@@ -44,13 +44,13 @@ MODULE_LICENSE("GPL"); | |||
44 | 44 | ||
45 | void phy_device_free(struct phy_device *phydev) | 45 | void phy_device_free(struct phy_device *phydev) |
46 | { | 46 | { |
47 | kfree(phydev); | 47 | put_device(&phydev->dev); |
48 | } | 48 | } |
49 | EXPORT_SYMBOL(phy_device_free); | 49 | EXPORT_SYMBOL(phy_device_free); |
50 | 50 | ||
51 | static void phy_device_release(struct device *dev) | 51 | static void phy_device_release(struct device *dev) |
52 | { | 52 | { |
53 | phy_device_free(to_phy_device(dev)); | 53 | kfree(to_phy_device(dev)); |
54 | } | 54 | } |
55 | 55 | ||
56 | static struct phy_driver genphy_driver; | 56 | static struct phy_driver genphy_driver; |
@@ -201,6 +201,8 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id, | |||
201 | there's no driver _already_ loaded. */ | 201 | there's no driver _already_ loaded. */ |
202 | request_module(MDIO_MODULE_PREFIX MDIO_ID_FMT, MDIO_ID_ARGS(phy_id)); | 202 | request_module(MDIO_MODULE_PREFIX MDIO_ID_FMT, MDIO_ID_ARGS(phy_id)); |
203 | 203 | ||
204 | device_initialize(&dev->dev); | ||
205 | |||
204 | return dev; | 206 | return dev; |
205 | } | 207 | } |
206 | EXPORT_SYMBOL(phy_device_create); | 208 | EXPORT_SYMBOL(phy_device_create); |
@@ -363,9 +365,9 @@ int phy_device_register(struct phy_device *phydev) | |||
363 | /* Run all of the fixups for this PHY */ | 365 | /* Run all of the fixups for this PHY */ |
364 | phy_scan_fixups(phydev); | 366 | phy_scan_fixups(phydev); |
365 | 367 | ||
366 | err = device_register(&phydev->dev); | 368 | err = device_add(&phydev->dev); |
367 | if (err) { | 369 | if (err) { |
368 | pr_err("phy %d failed to register\n", phydev->addr); | 370 | pr_err("PHY %d failed to add\n", phydev->addr); |
369 | goto out; | 371 | goto out; |
370 | } | 372 | } |
371 | 373 | ||
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index da92ed3797aa..3b6e9b83342d 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig | |||
@@ -156,6 +156,24 @@ config USB_NET_AX8817X | |||
156 | This driver creates an interface named "ethX", where X depends on | 156 | This driver creates an interface named "ethX", where X depends on |
157 | what other networking devices you have in use. | 157 | what other networking devices you have in use. |
158 | 158 | ||
159 | config USB_NET_AX88179_178A | ||
160 | tristate "ASIX AX88179/178A USB 3.0/2.0 to Gigabit Ethernet" | ||
161 | depends on USB_USBNET | ||
162 | select CRC32 | ||
163 | select PHYLIB | ||
164 | default y | ||
165 | help | ||
166 | This option adds support for ASIX AX88179 based USB 3.0/2.0 | ||
167 | to Gigabit Ethernet adapters. | ||
168 | |||
169 | This driver should work with at least the following devices: | ||
170 | * ASIX AX88179 | ||
171 | * ASIX AX88178A | ||
172 | * Sitcomm LN-032 | ||
173 | |||
174 | This driver creates an interface named "ethX", where X depends on | ||
175 | what other networking devices you have in use. | ||
176 | |||
159 | config USB_NET_CDCETHER | 177 | config USB_NET_CDCETHER |
160 | tristate "CDC Ethernet support (smart devices such as cable modems)" | 178 | tristate "CDC Ethernet support (smart devices such as cable modems)" |
161 | depends on USB_USBNET | 179 | depends on USB_USBNET |
diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index 478691326f37..119b06c9aa16 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile | |||
@@ -9,6 +9,7 @@ obj-$(CONFIG_USB_RTL8150) += rtl8150.o | |||
9 | obj-$(CONFIG_USB_HSO) += hso.o | 9 | obj-$(CONFIG_USB_HSO) += hso.o |
10 | obj-$(CONFIG_USB_NET_AX8817X) += asix.o | 10 | obj-$(CONFIG_USB_NET_AX8817X) += asix.o |
11 | asix-y := asix_devices.o asix_common.o ax88172a.o | 11 | asix-y := asix_devices.o asix_common.o ax88172a.o |
12 | obj-$(CONFIG_USB_NET_AX88179_178A) += ax88179_178a.o | ||
12 | obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o | 13 | obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o |
13 | obj-$(CONFIG_USB_NET_CDC_EEM) += cdc_eem.o | 14 | obj-$(CONFIG_USB_NET_CDC_EEM) += cdc_eem.o |
14 | obj-$(CONFIG_USB_NET_DM9601) += dm9601.o | 15 | obj-$(CONFIG_USB_NET_DM9601) += dm9601.o |
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c index 2205dbc8d32f..709753469099 100644 --- a/drivers/net/usb/asix_devices.c +++ b/drivers/net/usb/asix_devices.c | |||
@@ -924,6 +924,29 @@ static const struct driver_info ax88178_info = { | |||
924 | .tx_fixup = asix_tx_fixup, | 924 | .tx_fixup = asix_tx_fixup, |
925 | }; | 925 | }; |
926 | 926 | ||
927 | /* | ||
928 | * USBLINK 20F9 "USB 2.0 LAN" USB ethernet adapter, typically found in | ||
929 | * no-name packaging. | ||
930 | * USB device strings are: | ||
931 | * 1: Manufacturer: USBLINK | ||
932 | * 2: Product: HG20F9 USB2.0 | ||
933 | * 3: Serial: 000003 | ||
934 | * Appears to be compatible with Asix 88772B. | ||
935 | */ | ||
936 | static const struct driver_info hg20f9_info = { | ||
937 | .description = "HG20F9 USB 2.0 Ethernet", | ||
938 | .bind = ax88772_bind, | ||
939 | .unbind = ax88772_unbind, | ||
940 | .status = asix_status, | ||
941 | .link_reset = ax88772_link_reset, | ||
942 | .reset = ax88772_reset, | ||
943 | .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | | ||
944 | FLAG_MULTI_PACKET, | ||
945 | .rx_fixup = asix_rx_fixup_common, | ||
946 | .tx_fixup = asix_tx_fixup, | ||
947 | .data = FLAG_EEPROM_MAC, | ||
948 | }; | ||
949 | |||
927 | extern const struct driver_info ax88172a_info; | 950 | extern const struct driver_info ax88172a_info; |
928 | 951 | ||
929 | static const struct usb_device_id products [] = { | 952 | static const struct usb_device_id products [] = { |
@@ -1063,6 +1086,14 @@ static const struct usb_device_id products [] = { | |||
1063 | /* ASIX 88172a demo board */ | 1086 | /* ASIX 88172a demo board */ |
1064 | USB_DEVICE(0x0b95, 0x172a), | 1087 | USB_DEVICE(0x0b95, 0x172a), |
1065 | .driver_info = (unsigned long) &ax88172a_info, | 1088 | .driver_info = (unsigned long) &ax88172a_info, |
1089 | }, { | ||
1090 | /* | ||
1091 | * USBLINK HG20F9 "USB 2.0 LAN" | ||
1092 | * Appears to have gazumped Linksys's manufacturer ID but | ||
1093 | * doesn't (yet) conflict with any known Linksys product. | ||
1094 | */ | ||
1095 | USB_DEVICE(0x066b, 0x20f9), | ||
1096 | .driver_info = (unsigned long) &hg20f9_info, | ||
1066 | }, | 1097 | }, |
1067 | { }, // END | 1098 | { }, // END |
1068 | }; | 1099 | }; |
diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c new file mode 100644 index 000000000000..71c27d8d214f --- /dev/null +++ b/drivers/net/usb/ax88179_178a.c | |||
@@ -0,0 +1,1448 @@ | |||
1 | /* | ||
2 | * ASIX AX88179/178A USB 3.0/2.0 to Gigabit Ethernet Devices | ||
3 | * | ||
4 | * Copyright (C) 2011-2013 ASIX | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version 2 | ||
9 | * of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/etherdevice.h> | ||
23 | #include <linux/mii.h> | ||
24 | #include <linux/usb.h> | ||
25 | #include <linux/crc32.h> | ||
26 | #include <linux/usb/usbnet.h> | ||
27 | |||
28 | #define AX88179_PHY_ID 0x03 | ||
29 | #define AX_EEPROM_LEN 0x100 | ||
30 | #define AX88179_EEPROM_MAGIC 0x17900b95 | ||
31 | #define AX_MCAST_FLTSIZE 8 | ||
32 | #define AX_MAX_MCAST 64 | ||
33 | #define AX_INT_PPLS_LINK ((u32)BIT(16)) | ||
34 | #define AX_RXHDR_L4_TYPE_MASK 0x1c | ||
35 | #define AX_RXHDR_L4_TYPE_UDP 4 | ||
36 | #define AX_RXHDR_L4_TYPE_TCP 16 | ||
37 | #define AX_RXHDR_L3CSUM_ERR 2 | ||
38 | #define AX_RXHDR_L4CSUM_ERR 1 | ||
39 | #define AX_RXHDR_CRC_ERR ((u32)BIT(31)) | ||
40 | #define AX_RXHDR_DROP_ERR ((u32)BIT(30)) | ||
41 | #define AX_ACCESS_MAC 0x01 | ||
42 | #define AX_ACCESS_PHY 0x02 | ||
43 | #define AX_ACCESS_EEPROM 0x04 | ||
44 | #define AX_ACCESS_EFUS 0x05 | ||
45 | #define AX_PAUSE_WATERLVL_HIGH 0x54 | ||
46 | #define AX_PAUSE_WATERLVL_LOW 0x55 | ||
47 | |||
48 | #define PHYSICAL_LINK_STATUS 0x02 | ||
49 | #define AX_USB_SS 0x04 | ||
50 | #define AX_USB_HS 0x02 | ||
51 | |||
52 | #define GENERAL_STATUS 0x03 | ||
53 | /* Check AX88179 version. UA1:Bit2 = 0, UA2:Bit2 = 1 */ | ||
54 | #define AX_SECLD 0x04 | ||
55 | |||
56 | #define AX_SROM_ADDR 0x07 | ||
57 | #define AX_SROM_CMD 0x0a | ||
58 | #define EEP_RD 0x04 | ||
59 | #define EEP_BUSY 0x10 | ||
60 | |||
61 | #define AX_SROM_DATA_LOW 0x08 | ||
62 | #define AX_SROM_DATA_HIGH 0x09 | ||
63 | |||
64 | #define AX_RX_CTL 0x0b | ||
65 | #define AX_RX_CTL_DROPCRCERR 0x0100 | ||
66 | #define AX_RX_CTL_IPE 0x0200 | ||
67 | #define AX_RX_CTL_START 0x0080 | ||
68 | #define AX_RX_CTL_AP 0x0020 | ||
69 | #define AX_RX_CTL_AM 0x0010 | ||
70 | #define AX_RX_CTL_AB 0x0008 | ||
71 | #define AX_RX_CTL_AMALL 0x0002 | ||
72 | #define AX_RX_CTL_PRO 0x0001 | ||
73 | #define AX_RX_CTL_STOP 0x0000 | ||
74 | |||
75 | #define AX_NODE_ID 0x10 | ||
76 | #define AX_MULFLTARY 0x16 | ||
77 | |||
78 | #define AX_MEDIUM_STATUS_MODE 0x22 | ||
79 | #define AX_MEDIUM_GIGAMODE 0x01 | ||
80 | #define AX_MEDIUM_FULL_DUPLEX 0x02 | ||
81 | #define AX_MEDIUM_ALWAYS_ONE 0x04 | ||
82 | #define AX_MEDIUM_EN_125MHZ 0x08 | ||
83 | #define AX_MEDIUM_RXFLOW_CTRLEN 0x10 | ||
84 | #define AX_MEDIUM_TXFLOW_CTRLEN 0x20 | ||
85 | #define AX_MEDIUM_RECEIVE_EN 0x100 | ||
86 | #define AX_MEDIUM_PS 0x200 | ||
87 | #define AX_MEDIUM_JUMBO_EN 0x8040 | ||
88 | |||
89 | #define AX_MONITOR_MOD 0x24 | ||
90 | #define AX_MONITOR_MODE_RWLC 0x02 | ||
91 | #define AX_MONITOR_MODE_RWMP 0x04 | ||
92 | #define AX_MONITOR_MODE_PMEPOL 0x20 | ||
93 | #define AX_MONITOR_MODE_PMETYPE 0x40 | ||
94 | |||
95 | #define AX_GPIO_CTRL 0x25 | ||
96 | #define AX_GPIO_CTRL_GPIO3EN 0x80 | ||
97 | #define AX_GPIO_CTRL_GPIO2EN 0x40 | ||
98 | #define AX_GPIO_CTRL_GPIO1EN 0x20 | ||
99 | |||
100 | #define AX_PHYPWR_RSTCTL 0x26 | ||
101 | #define AX_PHYPWR_RSTCTL_BZ 0x0010 | ||
102 | #define AX_PHYPWR_RSTCTL_IPRL 0x0020 | ||
103 | #define AX_PHYPWR_RSTCTL_AT 0x1000 | ||
104 | |||
105 | #define AX_RX_BULKIN_QCTRL 0x2e | ||
106 | #define AX_CLK_SELECT 0x33 | ||
107 | #define AX_CLK_SELECT_BCS 0x01 | ||
108 | #define AX_CLK_SELECT_ACS 0x02 | ||
109 | #define AX_CLK_SELECT_ULR 0x08 | ||
110 | |||
111 | #define AX_RXCOE_CTL 0x34 | ||
112 | #define AX_RXCOE_IP 0x01 | ||
113 | #define AX_RXCOE_TCP 0x02 | ||
114 | #define AX_RXCOE_UDP 0x04 | ||
115 | #define AX_RXCOE_TCPV6 0x20 | ||
116 | #define AX_RXCOE_UDPV6 0x40 | ||
117 | |||
118 | #define AX_TXCOE_CTL 0x35 | ||
119 | #define AX_TXCOE_IP 0x01 | ||
120 | #define AX_TXCOE_TCP 0x02 | ||
121 | #define AX_TXCOE_UDP 0x04 | ||
122 | #define AX_TXCOE_TCPV6 0x20 | ||
123 | #define AX_TXCOE_UDPV6 0x40 | ||
124 | |||
125 | #define AX_LEDCTRL 0x73 | ||
126 | |||
127 | #define GMII_PHY_PHYSR 0x11 | ||
128 | #define GMII_PHY_PHYSR_SMASK 0xc000 | ||
129 | #define GMII_PHY_PHYSR_GIGA 0x8000 | ||
130 | #define GMII_PHY_PHYSR_100 0x4000 | ||
131 | #define GMII_PHY_PHYSR_FULL 0x2000 | ||
132 | #define GMII_PHY_PHYSR_LINK 0x400 | ||
133 | |||
134 | #define GMII_LED_ACT 0x1a | ||
135 | #define GMII_LED_ACTIVE_MASK 0xff8f | ||
136 | #define GMII_LED0_ACTIVE BIT(4) | ||
137 | #define GMII_LED1_ACTIVE BIT(5) | ||
138 | #define GMII_LED2_ACTIVE BIT(6) | ||
139 | |||
140 | #define GMII_LED_LINK 0x1c | ||
141 | #define GMII_LED_LINK_MASK 0xf888 | ||
142 | #define GMII_LED0_LINK_10 BIT(0) | ||
143 | #define GMII_LED0_LINK_100 BIT(1) | ||
144 | #define GMII_LED0_LINK_1000 BIT(2) | ||
145 | #define GMII_LED1_LINK_10 BIT(4) | ||
146 | #define GMII_LED1_LINK_100 BIT(5) | ||
147 | #define GMII_LED1_LINK_1000 BIT(6) | ||
148 | #define GMII_LED2_LINK_10 BIT(8) | ||
149 | #define GMII_LED2_LINK_100 BIT(9) | ||
150 | #define GMII_LED2_LINK_1000 BIT(10) | ||
151 | #define LED0_ACTIVE BIT(0) | ||
152 | #define LED0_LINK_10 BIT(1) | ||
153 | #define LED0_LINK_100 BIT(2) | ||
154 | #define LED0_LINK_1000 BIT(3) | ||
155 | #define LED0_FD BIT(4) | ||
156 | #define LED0_USB3_MASK 0x001f | ||
157 | #define LED1_ACTIVE BIT(5) | ||
158 | #define LED1_LINK_10 BIT(6) | ||
159 | #define LED1_LINK_100 BIT(7) | ||
160 | #define LED1_LINK_1000 BIT(8) | ||
161 | #define LED1_FD BIT(9) | ||
162 | #define LED1_USB3_MASK 0x03e0 | ||
163 | #define LED2_ACTIVE BIT(10) | ||
164 | #define LED2_LINK_1000 BIT(13) | ||
165 | #define LED2_LINK_100 BIT(12) | ||
166 | #define LED2_LINK_10 BIT(11) | ||
167 | #define LED2_FD BIT(14) | ||
168 | #define LED_VALID BIT(15) | ||
169 | #define LED2_USB3_MASK 0x7c00 | ||
170 | |||
171 | #define GMII_PHYPAGE 0x1e | ||
172 | #define GMII_PHY_PAGE_SELECT 0x1f | ||
173 | #define GMII_PHY_PGSEL_EXT 0x0007 | ||
174 | #define GMII_PHY_PGSEL_PAGE0 0x0000 | ||
175 | |||
176 | struct ax88179_data { | ||
177 | u16 rxctl; | ||
178 | u16 reserved; | ||
179 | }; | ||
180 | |||
181 | struct ax88179_int_data { | ||
182 | __le32 intdata1; | ||
183 | __le32 intdata2; | ||
184 | }; | ||
185 | |||
186 | static const struct { | ||
187 | unsigned char ctrl, timer_l, timer_h, size, ifg; | ||
188 | } AX88179_BULKIN_SIZE[] = { | ||
189 | {7, 0x4f, 0, 0x12, 0xff}, | ||
190 | {7, 0x20, 3, 0x16, 0xff}, | ||
191 | {7, 0xae, 7, 0x18, 0xff}, | ||
192 | {7, 0xcc, 0x4c, 0x18, 8}, | ||
193 | }; | ||
194 | |||
195 | static int __ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, | ||
196 | u16 size, void *data, int in_pm) | ||
197 | { | ||
198 | int ret; | ||
199 | int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16); | ||
200 | |||
201 | BUG_ON(!dev); | ||
202 | |||
203 | if (!in_pm) | ||
204 | fn = usbnet_read_cmd; | ||
205 | else | ||
206 | fn = usbnet_read_cmd_nopm; | ||
207 | |||
208 | ret = fn(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
209 | value, index, data, size); | ||
210 | |||
211 | if (unlikely(ret < 0)) | ||
212 | netdev_warn(dev->net, "Failed to read reg index 0x%04x: %d\n", | ||
213 | index, ret); | ||
214 | |||
215 | return ret; | ||
216 | } | ||
217 | |||
218 | static int __ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, | ||
219 | u16 size, void *data, int in_pm) | ||
220 | { | ||
221 | int ret; | ||
222 | int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16); | ||
223 | |||
224 | BUG_ON(!dev); | ||
225 | |||
226 | if (!in_pm) | ||
227 | fn = usbnet_write_cmd; | ||
228 | else | ||
229 | fn = usbnet_write_cmd_nopm; | ||
230 | |||
231 | ret = fn(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
232 | value, index, data, size); | ||
233 | |||
234 | if (unlikely(ret < 0)) | ||
235 | netdev_warn(dev->net, "Failed to write reg index 0x%04x: %d\n", | ||
236 | index, ret); | ||
237 | |||
238 | return ret; | ||
239 | } | ||
240 | |||
241 | static void ax88179_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, | ||
242 | u16 index, u16 size, void *data) | ||
243 | { | ||
244 | u16 buf; | ||
245 | |||
246 | if (2 == size) { | ||
247 | buf = *((u16 *)data); | ||
248 | cpu_to_le16s(&buf); | ||
249 | usbnet_write_cmd_async(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | | ||
250 | USB_RECIP_DEVICE, value, index, &buf, | ||
251 | size); | ||
252 | } else { | ||
253 | usbnet_write_cmd_async(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | | ||
254 | USB_RECIP_DEVICE, value, index, data, | ||
255 | size); | ||
256 | } | ||
257 | } | ||
258 | |||
259 | static int ax88179_read_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, | ||
260 | u16 index, u16 size, void *data) | ||
261 | { | ||
262 | int ret; | ||
263 | |||
264 | if (2 == size) { | ||
265 | u16 buf; | ||
266 | ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 1); | ||
267 | le16_to_cpus(&buf); | ||
268 | *((u16 *)data) = buf; | ||
269 | } else if (4 == size) { | ||
270 | u32 buf; | ||
271 | ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 1); | ||
272 | le32_to_cpus(&buf); | ||
273 | *((u32 *)data) = buf; | ||
274 | } else { | ||
275 | ret = __ax88179_read_cmd(dev, cmd, value, index, size, data, 1); | ||
276 | } | ||
277 | |||
278 | return ret; | ||
279 | } | ||
280 | |||
281 | static int ax88179_write_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, | ||
282 | u16 index, u16 size, void *data) | ||
283 | { | ||
284 | int ret; | ||
285 | |||
286 | if (2 == size) { | ||
287 | u16 buf; | ||
288 | buf = *((u16 *)data); | ||
289 | cpu_to_le16s(&buf); | ||
290 | ret = __ax88179_write_cmd(dev, cmd, value, index, | ||
291 | size, &buf, 1); | ||
292 | } else { | ||
293 | ret = __ax88179_write_cmd(dev, cmd, value, index, | ||
294 | size, data, 1); | ||
295 | } | ||
296 | |||
297 | return ret; | ||
298 | } | ||
299 | |||
300 | static int ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, | ||
301 | u16 size, void *data) | ||
302 | { | ||
303 | int ret; | ||
304 | |||
305 | if (2 == size) { | ||
306 | u16 buf; | ||
307 | ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 0); | ||
308 | le16_to_cpus(&buf); | ||
309 | *((u16 *)data) = buf; | ||
310 | } else if (4 == size) { | ||
311 | u32 buf; | ||
312 | ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 0); | ||
313 | le32_to_cpus(&buf); | ||
314 | *((u32 *)data) = buf; | ||
315 | } else { | ||
316 | ret = __ax88179_read_cmd(dev, cmd, value, index, size, data, 0); | ||
317 | } | ||
318 | |||
319 | return ret; | ||
320 | } | ||
321 | |||
322 | static int ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, | ||
323 | u16 size, void *data) | ||
324 | { | ||
325 | int ret; | ||
326 | |||
327 | if (2 == size) { | ||
328 | u16 buf; | ||
329 | buf = *((u16 *)data); | ||
330 | cpu_to_le16s(&buf); | ||
331 | ret = __ax88179_write_cmd(dev, cmd, value, index, | ||
332 | size, &buf, 0); | ||
333 | } else { | ||
334 | ret = __ax88179_write_cmd(dev, cmd, value, index, | ||
335 | size, data, 0); | ||
336 | } | ||
337 | |||
338 | return ret; | ||
339 | } | ||
340 | |||
341 | static void ax88179_status(struct usbnet *dev, struct urb *urb) | ||
342 | { | ||
343 | struct ax88179_int_data *event; | ||
344 | u32 link; | ||
345 | |||
346 | if (urb->actual_length < 8) | ||
347 | return; | ||
348 | |||
349 | event = urb->transfer_buffer; | ||
350 | le32_to_cpus((void *)&event->intdata1); | ||
351 | |||
352 | link = (((__force u32)event->intdata1) & AX_INT_PPLS_LINK) >> 16; | ||
353 | |||
354 | if (netif_carrier_ok(dev->net) != link) { | ||
355 | if (link) | ||
356 | usbnet_defer_kevent(dev, EVENT_LINK_RESET); | ||
357 | else | ||
358 | netif_carrier_off(dev->net); | ||
359 | |||
360 | netdev_info(dev->net, "ax88179 - Link status is: %d\n", link); | ||
361 | } | ||
362 | } | ||
363 | |||
364 | static int ax88179_mdio_read(struct net_device *netdev, int phy_id, int loc) | ||
365 | { | ||
366 | struct usbnet *dev = netdev_priv(netdev); | ||
367 | u16 res; | ||
368 | |||
369 | ax88179_read_cmd(dev, AX_ACCESS_PHY, phy_id, (__u16)loc, 2, &res); | ||
370 | return res; | ||
371 | } | ||
372 | |||
373 | static void ax88179_mdio_write(struct net_device *netdev, int phy_id, int loc, | ||
374 | int val) | ||
375 | { | ||
376 | struct usbnet *dev = netdev_priv(netdev); | ||
377 | u16 res = (u16) val; | ||
378 | |||
379 | ax88179_write_cmd(dev, AX_ACCESS_PHY, phy_id, (__u16)loc, 2, &res); | ||
380 | } | ||
381 | |||
382 | static int ax88179_suspend(struct usb_interface *intf, pm_message_t message) | ||
383 | { | ||
384 | struct usbnet *dev = usb_get_intfdata(intf); | ||
385 | u16 tmp16; | ||
386 | u8 tmp8; | ||
387 | |||
388 | usbnet_suspend(intf, message); | ||
389 | |||
390 | /* Disable RX path */ | ||
391 | ax88179_read_cmd_nopm(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, | ||
392 | 2, 2, &tmp16); | ||
393 | tmp16 &= ~AX_MEDIUM_RECEIVE_EN; | ||
394 | ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, | ||
395 | 2, 2, &tmp16); | ||
396 | |||
397 | /* Force bulk-in zero length */ | ||
398 | ax88179_read_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, | ||
399 | 2, 2, &tmp16); | ||
400 | |||
401 | tmp16 |= AX_PHYPWR_RSTCTL_BZ | AX_PHYPWR_RSTCTL_IPRL; | ||
402 | ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, | ||
403 | 2, 2, &tmp16); | ||
404 | |||
405 | /* change clock */ | ||
406 | tmp8 = 0; | ||
407 | ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); | ||
408 | |||
409 | /* Configure RX control register => stop operation */ | ||
410 | tmp16 = AX_RX_CTL_STOP; | ||
411 | ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16); | ||
412 | |||
413 | return 0; | ||
414 | } | ||
415 | |||
416 | /* This function is used to enable the autodetach function. */ | ||
417 | /* This function is determined by offset 0x43 of EEPROM */ | ||
418 | static int ax88179_auto_detach(struct usbnet *dev, int in_pm) | ||
419 | { | ||
420 | u16 tmp16; | ||
421 | u8 tmp8; | ||
422 | int (*fnr)(struct usbnet *, u8, u16, u16, u16, void *); | ||
423 | int (*fnw)(struct usbnet *, u8, u16, u16, u16, void *); | ||
424 | |||
425 | if (!in_pm) { | ||
426 | fnr = ax88179_read_cmd; | ||
427 | fnw = ax88179_write_cmd; | ||
428 | } else { | ||
429 | fnr = ax88179_read_cmd_nopm; | ||
430 | fnw = ax88179_write_cmd_nopm; | ||
431 | } | ||
432 | |||
433 | if (fnr(dev, AX_ACCESS_EEPROM, 0x43, 1, 2, &tmp16) < 0) | ||
434 | return 0; | ||
435 | |||
436 | if ((tmp16 == 0xFFFF) || (!(tmp16 & 0x0100))) | ||
437 | return 0; | ||
438 | |||
439 | /* Enable Auto Detach bit */ | ||
440 | tmp8 = 0; | ||
441 | fnr(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); | ||
442 | tmp8 |= AX_CLK_SELECT_ULR; | ||
443 | fnw(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); | ||
444 | |||
445 | fnr(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16); | ||
446 | tmp16 |= AX_PHYPWR_RSTCTL_AT; | ||
447 | fnw(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16); | ||
448 | |||
449 | return 0; | ||
450 | } | ||
451 | |||
452 | static int ax88179_resume(struct usb_interface *intf) | ||
453 | { | ||
454 | struct usbnet *dev = usb_get_intfdata(intf); | ||
455 | u16 tmp16; | ||
456 | u8 tmp8; | ||
457 | |||
458 | netif_carrier_off(dev->net); | ||
459 | |||
460 | /* Power up ethernet PHY */ | ||
461 | tmp16 = 0; | ||
462 | ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, | ||
463 | 2, 2, &tmp16); | ||
464 | udelay(1000); | ||
465 | |||
466 | tmp16 = AX_PHYPWR_RSTCTL_IPRL; | ||
467 | ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, | ||
468 | 2, 2, &tmp16); | ||
469 | msleep(200); | ||
470 | |||
471 | /* Ethernet PHY Auto Detach*/ | ||
472 | ax88179_auto_detach(dev, 1); | ||
473 | |||
474 | /* Enable clock */ | ||
475 | ax88179_read_cmd_nopm(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); | ||
476 | tmp8 |= AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS; | ||
477 | ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); | ||
478 | msleep(100); | ||
479 | |||
480 | /* Configure RX control register => start operation */ | ||
481 | tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START | | ||
482 | AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB; | ||
483 | ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16); | ||
484 | |||
485 | return usbnet_resume(intf); | ||
486 | } | ||
487 | |||
488 | static void | ||
489 | ax88179_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) | ||
490 | { | ||
491 | struct usbnet *dev = netdev_priv(net); | ||
492 | u8 opt; | ||
493 | |||
494 | if (ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, | ||
495 | 1, 1, &opt) < 0) { | ||
496 | wolinfo->supported = 0; | ||
497 | wolinfo->wolopts = 0; | ||
498 | return; | ||
499 | } | ||
500 | |||
501 | wolinfo->supported = WAKE_PHY | WAKE_MAGIC; | ||
502 | wolinfo->wolopts = 0; | ||
503 | if (opt & AX_MONITOR_MODE_RWLC) | ||
504 | wolinfo->wolopts |= WAKE_PHY; | ||
505 | if (opt & AX_MONITOR_MODE_RWMP) | ||
506 | wolinfo->wolopts |= WAKE_MAGIC; | ||
507 | } | ||
508 | |||
509 | static int | ||
510 | ax88179_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) | ||
511 | { | ||
512 | struct usbnet *dev = netdev_priv(net); | ||
513 | u8 opt = 0; | ||
514 | |||
515 | if (wolinfo->wolopts & WAKE_PHY) | ||
516 | opt |= AX_MONITOR_MODE_RWLC; | ||
517 | if (wolinfo->wolopts & WAKE_MAGIC) | ||
518 | opt |= AX_MONITOR_MODE_RWMP; | ||
519 | |||
520 | if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, | ||
521 | 1, 1, &opt) < 0) | ||
522 | return -EINVAL; | ||
523 | |||
524 | return 0; | ||
525 | } | ||
526 | |||
527 | static int ax88179_get_eeprom_len(struct net_device *net) | ||
528 | { | ||
529 | return AX_EEPROM_LEN; | ||
530 | } | ||
531 | |||
532 | static int | ||
533 | ax88179_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom, | ||
534 | u8 *data) | ||
535 | { | ||
536 | struct usbnet *dev = netdev_priv(net); | ||
537 | u16 *eeprom_buff; | ||
538 | int first_word, last_word; | ||
539 | int i, ret; | ||
540 | |||
541 | if (eeprom->len == 0) | ||
542 | return -EINVAL; | ||
543 | |||
544 | eeprom->magic = AX88179_EEPROM_MAGIC; | ||
545 | |||
546 | first_word = eeprom->offset >> 1; | ||
547 | last_word = (eeprom->offset + eeprom->len - 1) >> 1; | ||
548 | eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1), | ||
549 | GFP_KERNEL); | ||
550 | if (!eeprom_buff) | ||
551 | return -ENOMEM; | ||
552 | |||
553 | /* ax88179/178A returns 2 bytes from eeprom on read */ | ||
554 | for (i = first_word; i <= last_word; i++) { | ||
555 | ret = __ax88179_read_cmd(dev, AX_ACCESS_EEPROM, i, 1, 2, | ||
556 | &eeprom_buff[i - first_word], | ||
557 | 0); | ||
558 | if (ret < 0) { | ||
559 | kfree(eeprom_buff); | ||
560 | return -EIO; | ||
561 | } | ||
562 | } | ||
563 | |||
564 | memcpy(data, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len); | ||
565 | kfree(eeprom_buff); | ||
566 | return 0; | ||
567 | } | ||
568 | |||
569 | static int ax88179_get_settings(struct net_device *net, struct ethtool_cmd *cmd) | ||
570 | { | ||
571 | struct usbnet *dev = netdev_priv(net); | ||
572 | return mii_ethtool_gset(&dev->mii, cmd); | ||
573 | } | ||
574 | |||
575 | static int ax88179_set_settings(struct net_device *net, struct ethtool_cmd *cmd) | ||
576 | { | ||
577 | struct usbnet *dev = netdev_priv(net); | ||
578 | return mii_ethtool_sset(&dev->mii, cmd); | ||
579 | } | ||
580 | |||
581 | |||
582 | static int ax88179_ioctl(struct net_device *net, struct ifreq *rq, int cmd) | ||
583 | { | ||
584 | struct usbnet *dev = netdev_priv(net); | ||
585 | return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); | ||
586 | } | ||
587 | |||
588 | static const struct ethtool_ops ax88179_ethtool_ops = { | ||
589 | .get_link = ethtool_op_get_link, | ||
590 | .get_msglevel = usbnet_get_msglevel, | ||
591 | .set_msglevel = usbnet_set_msglevel, | ||
592 | .get_wol = ax88179_get_wol, | ||
593 | .set_wol = ax88179_set_wol, | ||
594 | .get_eeprom_len = ax88179_get_eeprom_len, | ||
595 | .get_eeprom = ax88179_get_eeprom, | ||
596 | .get_settings = ax88179_get_settings, | ||
597 | .set_settings = ax88179_set_settings, | ||
598 | .nway_reset = usbnet_nway_reset, | ||
599 | }; | ||
600 | |||
601 | static void ax88179_set_multicast(struct net_device *net) | ||
602 | { | ||
603 | struct usbnet *dev = netdev_priv(net); | ||
604 | struct ax88179_data *data = (struct ax88179_data *)dev->data; | ||
605 | u8 *m_filter = ((u8 *)dev->data) + 12; | ||
606 | |||
607 | data->rxctl = (AX_RX_CTL_START | AX_RX_CTL_AB | AX_RX_CTL_IPE); | ||
608 | |||
609 | if (net->flags & IFF_PROMISC) { | ||
610 | data->rxctl |= AX_RX_CTL_PRO; | ||
611 | } else if (net->flags & IFF_ALLMULTI || | ||
612 | netdev_mc_count(net) > AX_MAX_MCAST) { | ||
613 | data->rxctl |= AX_RX_CTL_AMALL; | ||
614 | } else if (netdev_mc_empty(net)) { | ||
615 | /* just broadcast and directed */ | ||
616 | } else { | ||
617 | /* We use the 20 byte dev->data for our 8 byte filter buffer | ||
618 | * to avoid allocating memory that is tricky to free later | ||
619 | */ | ||
620 | u32 crc_bits; | ||
621 | struct netdev_hw_addr *ha; | ||
622 | |||
623 | memset(m_filter, 0, AX_MCAST_FLTSIZE); | ||
624 | |||
625 | netdev_for_each_mc_addr(ha, net) { | ||
626 | crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26; | ||
627 | *(m_filter + (crc_bits >> 3)) |= (1 << (crc_bits & 7)); | ||
628 | } | ||
629 | |||
630 | ax88179_write_cmd_async(dev, AX_ACCESS_MAC, AX_MULFLTARY, | ||
631 | AX_MCAST_FLTSIZE, AX_MCAST_FLTSIZE, | ||
632 | m_filter); | ||
633 | |||
634 | data->rxctl |= AX_RX_CTL_AM; | ||
635 | } | ||
636 | |||
637 | ax88179_write_cmd_async(dev, AX_ACCESS_MAC, AX_RX_CTL, | ||
638 | 2, 2, &data->rxctl); | ||
639 | } | ||
640 | |||
641 | static int | ||
642 | ax88179_set_features(struct net_device *net, netdev_features_t features) | ||
643 | { | ||
644 | u8 tmp; | ||
645 | struct usbnet *dev = netdev_priv(net); | ||
646 | netdev_features_t changed = net->features ^ features; | ||
647 | |||
648 | if (changed & NETIF_F_IP_CSUM) { | ||
649 | ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); | ||
650 | tmp ^= AX_TXCOE_TCP | AX_TXCOE_UDP; | ||
651 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); | ||
652 | } | ||
653 | |||
654 | if (changed & NETIF_F_IPV6_CSUM) { | ||
655 | ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); | ||
656 | tmp ^= AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6; | ||
657 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); | ||
658 | } | ||
659 | |||
660 | if (changed & NETIF_F_RXCSUM) { | ||
661 | ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, &tmp); | ||
662 | tmp ^= AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | | ||
663 | AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6; | ||
664 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, &tmp); | ||
665 | } | ||
666 | |||
667 | return 0; | ||
668 | } | ||
669 | |||
670 | static int ax88179_change_mtu(struct net_device *net, int new_mtu) | ||
671 | { | ||
672 | struct usbnet *dev = netdev_priv(net); | ||
673 | u16 tmp16; | ||
674 | |||
675 | if (new_mtu <= 0 || new_mtu > 4088) | ||
676 | return -EINVAL; | ||
677 | |||
678 | net->mtu = new_mtu; | ||
679 | dev->hard_mtu = net->mtu + net->hard_header_len; | ||
680 | |||
681 | if (net->mtu > 1500) { | ||
682 | ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, | ||
683 | 2, 2, &tmp16); | ||
684 | tmp16 |= AX_MEDIUM_JUMBO_EN; | ||
685 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, | ||
686 | 2, 2, &tmp16); | ||
687 | } else { | ||
688 | ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, | ||
689 | 2, 2, &tmp16); | ||
690 | tmp16 &= ~AX_MEDIUM_JUMBO_EN; | ||
691 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, | ||
692 | 2, 2, &tmp16); | ||
693 | } | ||
694 | |||
695 | return 0; | ||
696 | } | ||
697 | |||
698 | static int ax88179_set_mac_addr(struct net_device *net, void *p) | ||
699 | { | ||
700 | struct usbnet *dev = netdev_priv(net); | ||
701 | struct sockaddr *addr = p; | ||
702 | |||
703 | if (netif_running(net)) | ||
704 | return -EBUSY; | ||
705 | if (!is_valid_ether_addr(addr->sa_data)) | ||
706 | return -EADDRNOTAVAIL; | ||
707 | |||
708 | memcpy(net->dev_addr, addr->sa_data, ETH_ALEN); | ||
709 | |||
710 | /* Set the MAC address */ | ||
711 | return ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, | ||
712 | ETH_ALEN, net->dev_addr); | ||
713 | } | ||
714 | |||
715 | static const struct net_device_ops ax88179_netdev_ops = { | ||
716 | .ndo_open = usbnet_open, | ||
717 | .ndo_stop = usbnet_stop, | ||
718 | .ndo_start_xmit = usbnet_start_xmit, | ||
719 | .ndo_tx_timeout = usbnet_tx_timeout, | ||
720 | .ndo_change_mtu = ax88179_change_mtu, | ||
721 | .ndo_set_mac_address = ax88179_set_mac_addr, | ||
722 | .ndo_validate_addr = eth_validate_addr, | ||
723 | .ndo_do_ioctl = ax88179_ioctl, | ||
724 | .ndo_set_rx_mode = ax88179_set_multicast, | ||
725 | .ndo_set_features = ax88179_set_features, | ||
726 | }; | ||
727 | |||
728 | static int ax88179_check_eeprom(struct usbnet *dev) | ||
729 | { | ||
730 | u8 i, buf, eeprom[20]; | ||
731 | u16 csum, delay = HZ / 10; | ||
732 | unsigned long jtimeout; | ||
733 | |||
734 | /* Read EEPROM content */ | ||
735 | for (i = 0; i < 6; i++) { | ||
736 | buf = i; | ||
737 | if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_ADDR, | ||
738 | 1, 1, &buf) < 0) | ||
739 | return -EINVAL; | ||
740 | |||
741 | buf = EEP_RD; | ||
742 | if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD, | ||
743 | 1, 1, &buf) < 0) | ||
744 | return -EINVAL; | ||
745 | |||
746 | jtimeout = jiffies + delay; | ||
747 | do { | ||
748 | ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD, | ||
749 | 1, 1, &buf); | ||
750 | |||
751 | if (time_after(jiffies, jtimeout)) | ||
752 | return -EINVAL; | ||
753 | |||
754 | } while (buf & EEP_BUSY); | ||
755 | |||
756 | __ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_DATA_LOW, | ||
757 | 2, 2, &eeprom[i * 2], 0); | ||
758 | |||
759 | if ((i == 0) && (eeprom[0] == 0xFF)) | ||
760 | return -EINVAL; | ||
761 | } | ||
762 | |||
763 | csum = eeprom[6] + eeprom[7] + eeprom[8] + eeprom[9]; | ||
764 | csum = (csum >> 8) + (csum & 0xff); | ||
765 | if ((csum + eeprom[10]) != 0xff) | ||
766 | return -EINVAL; | ||
767 | |||
768 | return 0; | ||
769 | } | ||
770 | |||
771 | static int ax88179_check_efuse(struct usbnet *dev, u16 *ledmode) | ||
772 | { | ||
773 | u8 i; | ||
774 | u8 efuse[64]; | ||
775 | u16 csum = 0; | ||
776 | |||
777 | if (ax88179_read_cmd(dev, AX_ACCESS_EFUS, 0, 64, 64, efuse) < 0) | ||
778 | return -EINVAL; | ||
779 | |||
780 | if (*efuse == 0xFF) | ||
781 | return -EINVAL; | ||
782 | |||
783 | for (i = 0; i < 64; i++) | ||
784 | csum = csum + efuse[i]; | ||
785 | |||
786 | while (csum > 255) | ||
787 | csum = (csum & 0x00FF) + ((csum >> 8) & 0x00FF); | ||
788 | |||
789 | if (csum != 0xFF) | ||
790 | return -EINVAL; | ||
791 | |||
792 | *ledmode = (efuse[51] << 8) | efuse[52]; | ||
793 | |||
794 | return 0; | ||
795 | } | ||
796 | |||
797 | static int ax88179_convert_old_led(struct usbnet *dev, u16 *ledvalue) | ||
798 | { | ||
799 | u16 led; | ||
800 | |||
801 | /* Loaded the old eFuse LED Mode */ | ||
802 | if (ax88179_read_cmd(dev, AX_ACCESS_EEPROM, 0x3C, 1, 2, &led) < 0) | ||
803 | return -EINVAL; | ||
804 | |||
805 | led >>= 8; | ||
806 | switch (led) { | ||
807 | case 0xFF: | ||
808 | led = LED0_ACTIVE | LED1_LINK_10 | LED1_LINK_100 | | ||
809 | LED1_LINK_1000 | LED2_ACTIVE | LED2_LINK_10 | | ||
810 | LED2_LINK_100 | LED2_LINK_1000 | LED_VALID; | ||
811 | break; | ||
812 | case 0xFE: | ||
813 | led = LED0_ACTIVE | LED1_LINK_1000 | LED2_LINK_100 | LED_VALID; | ||
814 | break; | ||
815 | case 0xFD: | ||
816 | led = LED0_ACTIVE | LED1_LINK_1000 | LED2_LINK_100 | | ||
817 | LED2_LINK_10 | LED_VALID; | ||
818 | break; | ||
819 | case 0xFC: | ||
820 | led = LED0_ACTIVE | LED1_ACTIVE | LED1_LINK_1000 | LED2_ACTIVE | | ||
821 | LED2_LINK_100 | LED2_LINK_10 | LED_VALID; | ||
822 | break; | ||
823 | default: | ||
824 | led = LED0_ACTIVE | LED1_LINK_10 | LED1_LINK_100 | | ||
825 | LED1_LINK_1000 | LED2_ACTIVE | LED2_LINK_10 | | ||
826 | LED2_LINK_100 | LED2_LINK_1000 | LED_VALID; | ||
827 | break; | ||
828 | } | ||
829 | |||
830 | *ledvalue = led; | ||
831 | |||
832 | return 0; | ||
833 | } | ||
834 | |||
835 | static int ax88179_led_setting(struct usbnet *dev) | ||
836 | { | ||
837 | u8 ledfd, value = 0; | ||
838 | u16 tmp, ledact, ledlink, ledvalue = 0, delay = HZ / 10; | ||
839 | unsigned long jtimeout; | ||
840 | |||
841 | /* Check AX88179 version. UA1 or UA2*/ | ||
842 | ax88179_read_cmd(dev, AX_ACCESS_MAC, GENERAL_STATUS, 1, 1, &value); | ||
843 | |||
844 | if (!(value & AX_SECLD)) { /* UA1 */ | ||
845 | value = AX_GPIO_CTRL_GPIO3EN | AX_GPIO_CTRL_GPIO2EN | | ||
846 | AX_GPIO_CTRL_GPIO1EN; | ||
847 | if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_GPIO_CTRL, | ||
848 | 1, 1, &value) < 0) | ||
849 | return -EINVAL; | ||
850 | } | ||
851 | |||
852 | /* Check EEPROM */ | ||
853 | if (!ax88179_check_eeprom(dev)) { | ||
854 | value = 0x42; | ||
855 | if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_ADDR, | ||
856 | 1, 1, &value) < 0) | ||
857 | return -EINVAL; | ||
858 | |||
859 | value = EEP_RD; | ||
860 | if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD, | ||
861 | 1, 1, &value) < 0) | ||
862 | return -EINVAL; | ||
863 | |||
864 | jtimeout = jiffies + delay; | ||
865 | do { | ||
866 | ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD, | ||
867 | 1, 1, &value); | ||
868 | |||
869 | if (time_after(jiffies, jtimeout)) | ||
870 | return -EINVAL; | ||
871 | |||
872 | } while (value & EEP_BUSY); | ||
873 | |||
874 | ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_DATA_HIGH, | ||
875 | 1, 1, &value); | ||
876 | ledvalue = (value << 8); | ||
877 | |||
878 | ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_DATA_LOW, | ||
879 | 1, 1, &value); | ||
880 | ledvalue |= value; | ||
881 | |||
882 | /* load internal ROM for defaule setting */ | ||
883 | if ((ledvalue == 0xFFFF) || ((ledvalue & LED_VALID) == 0)) | ||
884 | ax88179_convert_old_led(dev, &ledvalue); | ||
885 | |||
886 | } else if (!ax88179_check_efuse(dev, &ledvalue)) { | ||
887 | if ((ledvalue == 0xFFFF) || ((ledvalue & LED_VALID) == 0)) | ||
888 | ax88179_convert_old_led(dev, &ledvalue); | ||
889 | } else { | ||
890 | ax88179_convert_old_led(dev, &ledvalue); | ||
891 | } | ||
892 | |||
893 | tmp = GMII_PHY_PGSEL_EXT; | ||
894 | ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, | ||
895 | GMII_PHY_PAGE_SELECT, 2, &tmp); | ||
896 | |||
897 | tmp = 0x2c; | ||
898 | ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, | ||
899 | GMII_PHYPAGE, 2, &tmp); | ||
900 | |||
901 | ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, | ||
902 | GMII_LED_ACT, 2, &ledact); | ||
903 | |||
904 | ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, | ||
905 | GMII_LED_LINK, 2, &ledlink); | ||
906 | |||
907 | ledact &= GMII_LED_ACTIVE_MASK; | ||
908 | ledlink &= GMII_LED_LINK_MASK; | ||
909 | |||
910 | if (ledvalue & LED0_ACTIVE) | ||
911 | ledact |= GMII_LED0_ACTIVE; | ||
912 | |||
913 | if (ledvalue & LED1_ACTIVE) | ||
914 | ledact |= GMII_LED1_ACTIVE; | ||
915 | |||
916 | if (ledvalue & LED2_ACTIVE) | ||
917 | ledact |= GMII_LED2_ACTIVE; | ||
918 | |||
919 | if (ledvalue & LED0_LINK_10) | ||
920 | ledlink |= GMII_LED0_LINK_10; | ||
921 | |||
922 | if (ledvalue & LED1_LINK_10) | ||
923 | ledlink |= GMII_LED1_LINK_10; | ||
924 | |||
925 | if (ledvalue & LED2_LINK_10) | ||
926 | ledlink |= GMII_LED2_LINK_10; | ||
927 | |||
928 | if (ledvalue & LED0_LINK_100) | ||
929 | ledlink |= GMII_LED0_LINK_100; | ||
930 | |||
931 | if (ledvalue & LED1_LINK_100) | ||
932 | ledlink |= GMII_LED1_LINK_100; | ||
933 | |||
934 | if (ledvalue & LED2_LINK_100) | ||
935 | ledlink |= GMII_LED2_LINK_100; | ||
936 | |||
937 | if (ledvalue & LED0_LINK_1000) | ||
938 | ledlink |= GMII_LED0_LINK_1000; | ||
939 | |||
940 | if (ledvalue & LED1_LINK_1000) | ||
941 | ledlink |= GMII_LED1_LINK_1000; | ||
942 | |||
943 | if (ledvalue & LED2_LINK_1000) | ||
944 | ledlink |= GMII_LED2_LINK_1000; | ||
945 | |||
946 | tmp = ledact; | ||
947 | ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, | ||
948 | GMII_LED_ACT, 2, &tmp); | ||
949 | |||
950 | tmp = ledlink; | ||
951 | ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, | ||
952 | GMII_LED_LINK, 2, &tmp); | ||
953 | |||
954 | tmp = GMII_PHY_PGSEL_PAGE0; | ||
955 | ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, | ||
956 | GMII_PHY_PAGE_SELECT, 2, &tmp); | ||
957 | |||
958 | /* LED full duplex setting */ | ||
959 | ledfd = 0; | ||
960 | if (ledvalue & LED0_FD) | ||
961 | ledfd |= 0x01; | ||
962 | else if ((ledvalue & LED0_USB3_MASK) == 0) | ||
963 | ledfd |= 0x02; | ||
964 | |||
965 | if (ledvalue & LED1_FD) | ||
966 | ledfd |= 0x04; | ||
967 | else if ((ledvalue & LED1_USB3_MASK) == 0) | ||
968 | ledfd |= 0x08; | ||
969 | |||
970 | if (ledvalue & LED2_FD) | ||
971 | ledfd |= 0x10; | ||
972 | else if ((ledvalue & LED2_USB3_MASK) == 0) | ||
973 | ledfd |= 0x20; | ||
974 | |||
975 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_LEDCTRL, 1, 1, &ledfd); | ||
976 | |||
977 | return 0; | ||
978 | } | ||
979 | |||
980 | static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf) | ||
981 | { | ||
982 | u8 buf[5]; | ||
983 | u16 *tmp16; | ||
984 | u8 *tmp; | ||
985 | struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data; | ||
986 | |||
987 | usbnet_get_endpoints(dev, intf); | ||
988 | |||
989 | tmp16 = (u16 *)buf; | ||
990 | tmp = (u8 *)buf; | ||
991 | |||
992 | memset(ax179_data, 0, sizeof(*ax179_data)); | ||
993 | |||
994 | /* Power up ethernet PHY */ | ||
995 | *tmp16 = 0; | ||
996 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16); | ||
997 | *tmp16 = AX_PHYPWR_RSTCTL_IPRL; | ||
998 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16); | ||
999 | msleep(200); | ||
1000 | |||
1001 | *tmp = AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS; | ||
1002 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, tmp); | ||
1003 | msleep(100); | ||
1004 | |||
1005 | ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, | ||
1006 | ETH_ALEN, dev->net->dev_addr); | ||
1007 | memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN); | ||
1008 | |||
1009 | /* RX bulk configuration */ | ||
1010 | memcpy(tmp, &AX88179_BULKIN_SIZE[0], 5); | ||
1011 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL, 5, 5, tmp); | ||
1012 | |||
1013 | dev->rx_urb_size = 1024 * 20; | ||
1014 | |||
1015 | *tmp = 0x34; | ||
1016 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_LOW, 1, 1, tmp); | ||
1017 | |||
1018 | *tmp = 0x52; | ||
1019 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_HIGH, | ||
1020 | 1, 1, tmp); | ||
1021 | |||
1022 | dev->net->netdev_ops = &ax88179_netdev_ops; | ||
1023 | dev->net->ethtool_ops = &ax88179_ethtool_ops; | ||
1024 | dev->net->needed_headroom = 8; | ||
1025 | |||
1026 | /* Initialize MII structure */ | ||
1027 | dev->mii.dev = dev->net; | ||
1028 | dev->mii.mdio_read = ax88179_mdio_read; | ||
1029 | dev->mii.mdio_write = ax88179_mdio_write; | ||
1030 | dev->mii.phy_id_mask = 0xff; | ||
1031 | dev->mii.reg_num_mask = 0xff; | ||
1032 | dev->mii.phy_id = 0x03; | ||
1033 | dev->mii.supports_gmii = 1; | ||
1034 | |||
1035 | dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | | ||
1036 | NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO; | ||
1037 | |||
1038 | dev->net->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | | ||
1039 | NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO; | ||
1040 | |||
1041 | /* Enable checksum offload */ | ||
1042 | *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | | ||
1043 | AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6; | ||
1044 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, tmp); | ||
1045 | |||
1046 | *tmp = AX_TXCOE_IP | AX_TXCOE_TCP | AX_TXCOE_UDP | | ||
1047 | AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6; | ||
1048 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, tmp); | ||
1049 | |||
1050 | /* Configure RX control register => start operation */ | ||
1051 | *tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START | | ||
1052 | AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB; | ||
1053 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, tmp16); | ||
1054 | |||
1055 | *tmp = AX_MONITOR_MODE_PMETYPE | AX_MONITOR_MODE_PMEPOL | | ||
1056 | AX_MONITOR_MODE_RWMP; | ||
1057 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, 1, 1, tmp); | ||
1058 | |||
1059 | /* Configure default medium type => giga */ | ||
1060 | *tmp16 = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN | | ||
1061 | AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_ALWAYS_ONE | | ||
1062 | AX_MEDIUM_FULL_DUPLEX | AX_MEDIUM_GIGAMODE; | ||
1063 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, | ||
1064 | 2, 2, tmp16); | ||
1065 | |||
1066 | ax88179_led_setting(dev); | ||
1067 | |||
1068 | /* Restart autoneg */ | ||
1069 | mii_nway_restart(&dev->mii); | ||
1070 | |||
1071 | netif_carrier_off(dev->net); | ||
1072 | |||
1073 | return 0; | ||
1074 | } | ||
1075 | |||
1076 | static void ax88179_unbind(struct usbnet *dev, struct usb_interface *intf) | ||
1077 | { | ||
1078 | u16 tmp16; | ||
1079 | |||
1080 | /* Configure RX control register => stop operation */ | ||
1081 | tmp16 = AX_RX_CTL_STOP; | ||
1082 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16); | ||
1083 | |||
1084 | tmp16 = 0; | ||
1085 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp16); | ||
1086 | |||
1087 | /* Power down ethernet PHY */ | ||
1088 | tmp16 = 0; | ||
1089 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16); | ||
1090 | } | ||
1091 | |||
1092 | static void | ||
1093 | ax88179_rx_checksum(struct sk_buff *skb, u32 *pkt_hdr) | ||
1094 | { | ||
1095 | skb->ip_summed = CHECKSUM_NONE; | ||
1096 | |||
1097 | /* checksum error bit is set */ | ||
1098 | if ((*pkt_hdr & AX_RXHDR_L3CSUM_ERR) || | ||
1099 | (*pkt_hdr & AX_RXHDR_L4CSUM_ERR)) | ||
1100 | return; | ||
1101 | |||
1102 | /* It must be a TCP or UDP packet with a valid checksum */ | ||
1103 | if (((*pkt_hdr & AX_RXHDR_L4_TYPE_MASK) == AX_RXHDR_L4_TYPE_TCP) || | ||
1104 | ((*pkt_hdr & AX_RXHDR_L4_TYPE_MASK) == AX_RXHDR_L4_TYPE_UDP)) | ||
1105 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
1106 | } | ||
1107 | |||
1108 | static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | ||
1109 | { | ||
1110 | struct sk_buff *ax_skb; | ||
1111 | int pkt_cnt; | ||
1112 | u32 rx_hdr; | ||
1113 | u16 hdr_off; | ||
1114 | u32 *pkt_hdr; | ||
1115 | |||
1116 | skb_trim(skb, skb->len - 4); | ||
1117 | memcpy(&rx_hdr, skb_tail_pointer(skb), 4); | ||
1118 | le32_to_cpus(&rx_hdr); | ||
1119 | |||
1120 | pkt_cnt = (u16)rx_hdr; | ||
1121 | hdr_off = (u16)(rx_hdr >> 16); | ||
1122 | pkt_hdr = (u32 *)(skb->data + hdr_off); | ||
1123 | |||
1124 | while (pkt_cnt--) { | ||
1125 | u16 pkt_len; | ||
1126 | |||
1127 | le32_to_cpus(pkt_hdr); | ||
1128 | pkt_len = (*pkt_hdr >> 16) & 0x1fff; | ||
1129 | |||
1130 | /* Check CRC or runt packet */ | ||
1131 | if ((*pkt_hdr & AX_RXHDR_CRC_ERR) || | ||
1132 | (*pkt_hdr & AX_RXHDR_DROP_ERR)) { | ||
1133 | skb_pull(skb, (pkt_len + 7) & 0xFFF8); | ||
1134 | pkt_hdr++; | ||
1135 | continue; | ||
1136 | } | ||
1137 | |||
1138 | if (pkt_cnt == 0) { | ||
1139 | /* Skip IP alignment psudo header */ | ||
1140 | skb_pull(skb, 2); | ||
1141 | skb->len = pkt_len; | ||
1142 | skb_set_tail_pointer(skb, pkt_len); | ||
1143 | skb->truesize = pkt_len + sizeof(struct sk_buff); | ||
1144 | ax88179_rx_checksum(skb, pkt_hdr); | ||
1145 | return 1; | ||
1146 | } | ||
1147 | |||
1148 | ax_skb = skb_clone(skb, GFP_ATOMIC); | ||
1149 | if (ax_skb) { | ||
1150 | ax_skb->len = pkt_len; | ||
1151 | ax_skb->data = skb->data + 2; | ||
1152 | skb_set_tail_pointer(ax_skb, pkt_len); | ||
1153 | ax_skb->truesize = pkt_len + sizeof(struct sk_buff); | ||
1154 | ax88179_rx_checksum(ax_skb, pkt_hdr); | ||
1155 | usbnet_skb_return(dev, ax_skb); | ||
1156 | } else { | ||
1157 | return 0; | ||
1158 | } | ||
1159 | |||
1160 | skb_pull(skb, (pkt_len + 7) & 0xFFF8); | ||
1161 | pkt_hdr++; | ||
1162 | } | ||
1163 | return 1; | ||
1164 | } | ||
1165 | |||
1166 | static struct sk_buff * | ||
1167 | ax88179_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) | ||
1168 | { | ||
1169 | u32 tx_hdr1, tx_hdr2; | ||
1170 | int frame_size = dev->maxpacket; | ||
1171 | int mss = skb_shinfo(skb)->gso_size; | ||
1172 | int headroom; | ||
1173 | int tailroom; | ||
1174 | |||
1175 | tx_hdr1 = skb->len; | ||
1176 | tx_hdr2 = mss; | ||
1177 | if (((skb->len + 8) % frame_size) == 0) | ||
1178 | tx_hdr2 |= 0x80008000; /* Enable padding */ | ||
1179 | |||
1180 | skb_linearize(skb); | ||
1181 | headroom = skb_headroom(skb); | ||
1182 | tailroom = skb_tailroom(skb); | ||
1183 | |||
1184 | if (!skb_header_cloned(skb) && | ||
1185 | !skb_cloned(skb) && | ||
1186 | (headroom + tailroom) >= 8) { | ||
1187 | if (headroom < 8) { | ||
1188 | skb->data = memmove(skb->head + 8, skb->data, skb->len); | ||
1189 | skb_set_tail_pointer(skb, skb->len); | ||
1190 | } | ||
1191 | } else { | ||
1192 | struct sk_buff *skb2; | ||
1193 | |||
1194 | skb2 = skb_copy_expand(skb, 8, 0, flags); | ||
1195 | dev_kfree_skb_any(skb); | ||
1196 | skb = skb2; | ||
1197 | if (!skb) | ||
1198 | return NULL; | ||
1199 | } | ||
1200 | |||
1201 | skb_push(skb, 4); | ||
1202 | cpu_to_le32s(&tx_hdr2); | ||
1203 | skb_copy_to_linear_data(skb, &tx_hdr2, 4); | ||
1204 | |||
1205 | skb_push(skb, 4); | ||
1206 | cpu_to_le32s(&tx_hdr1); | ||
1207 | skb_copy_to_linear_data(skb, &tx_hdr1, 4); | ||
1208 | |||
1209 | return skb; | ||
1210 | } | ||
1211 | |||
1212 | static int ax88179_link_reset(struct usbnet *dev) | ||
1213 | { | ||
1214 | struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data; | ||
1215 | u8 tmp[5], link_sts; | ||
1216 | u16 mode, tmp16, delay = HZ / 10; | ||
1217 | u32 tmp32 = 0x40000000; | ||
1218 | unsigned long jtimeout; | ||
1219 | |||
1220 | jtimeout = jiffies + delay; | ||
1221 | while (tmp32 & 0x40000000) { | ||
1222 | mode = 0; | ||
1223 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &mode); | ||
1224 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, | ||
1225 | &ax179_data->rxctl); | ||
1226 | |||
1227 | /*link up, check the usb device control TX FIFO full or empty*/ | ||
1228 | ax88179_read_cmd(dev, 0x81, 0x8c, 0, 4, &tmp32); | ||
1229 | |||
1230 | if (time_after(jiffies, jtimeout)) | ||
1231 | return 0; | ||
1232 | } | ||
1233 | |||
1234 | mode = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN | | ||
1235 | AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_ALWAYS_ONE; | ||
1236 | |||
1237 | ax88179_read_cmd(dev, AX_ACCESS_MAC, PHYSICAL_LINK_STATUS, | ||
1238 | 1, 1, &link_sts); | ||
1239 | |||
1240 | ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, | ||
1241 | GMII_PHY_PHYSR, 2, &tmp16); | ||
1242 | |||
1243 | if (!(tmp16 & GMII_PHY_PHYSR_LINK)) { | ||
1244 | return 0; | ||
1245 | } else if (GMII_PHY_PHYSR_GIGA == (tmp16 & GMII_PHY_PHYSR_SMASK)) { | ||
1246 | mode |= AX_MEDIUM_GIGAMODE | AX_MEDIUM_EN_125MHZ; | ||
1247 | if (dev->net->mtu > 1500) | ||
1248 | mode |= AX_MEDIUM_JUMBO_EN; | ||
1249 | |||
1250 | if (link_sts & AX_USB_SS) | ||
1251 | memcpy(tmp, &AX88179_BULKIN_SIZE[0], 5); | ||
1252 | else if (link_sts & AX_USB_HS) | ||
1253 | memcpy(tmp, &AX88179_BULKIN_SIZE[1], 5); | ||
1254 | else | ||
1255 | memcpy(tmp, &AX88179_BULKIN_SIZE[3], 5); | ||
1256 | } else if (GMII_PHY_PHYSR_100 == (tmp16 & GMII_PHY_PHYSR_SMASK)) { | ||
1257 | mode |= AX_MEDIUM_PS; | ||
1258 | |||
1259 | if (link_sts & (AX_USB_SS | AX_USB_HS)) | ||
1260 | memcpy(tmp, &AX88179_BULKIN_SIZE[2], 5); | ||
1261 | else | ||
1262 | memcpy(tmp, &AX88179_BULKIN_SIZE[3], 5); | ||
1263 | } else { | ||
1264 | memcpy(tmp, &AX88179_BULKIN_SIZE[3], 5); | ||
1265 | } | ||
1266 | |||
1267 | /* RX bulk configuration */ | ||
1268 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL, 5, 5, tmp); | ||
1269 | |||
1270 | dev->rx_urb_size = (1024 * (tmp[3] + 2)); | ||
1271 | |||
1272 | if (tmp16 & GMII_PHY_PHYSR_FULL) | ||
1273 | mode |= AX_MEDIUM_FULL_DUPLEX; | ||
1274 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, | ||
1275 | 2, 2, &mode); | ||
1276 | |||
1277 | netif_carrier_on(dev->net); | ||
1278 | |||
1279 | return 0; | ||
1280 | } | ||
1281 | |||
1282 | static int ax88179_reset(struct usbnet *dev) | ||
1283 | { | ||
1284 | u8 buf[5]; | ||
1285 | u16 *tmp16; | ||
1286 | u8 *tmp; | ||
1287 | |||
1288 | tmp16 = (u16 *)buf; | ||
1289 | tmp = (u8 *)buf; | ||
1290 | |||
1291 | /* Power up ethernet PHY */ | ||
1292 | *tmp16 = 0; | ||
1293 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16); | ||
1294 | |||
1295 | *tmp16 = AX_PHYPWR_RSTCTL_IPRL; | ||
1296 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16); | ||
1297 | msleep(200); | ||
1298 | |||
1299 | *tmp = AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS; | ||
1300 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, tmp); | ||
1301 | msleep(100); | ||
1302 | |||
1303 | /* Ethernet PHY Auto Detach*/ | ||
1304 | ax88179_auto_detach(dev, 0); | ||
1305 | |||
1306 | ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, ETH_ALEN, | ||
1307 | dev->net->dev_addr); | ||
1308 | memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN); | ||
1309 | |||
1310 | /* RX bulk configuration */ | ||
1311 | memcpy(tmp, &AX88179_BULKIN_SIZE[0], 5); | ||
1312 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL, 5, 5, tmp); | ||
1313 | |||
1314 | dev->rx_urb_size = 1024 * 20; | ||
1315 | |||
1316 | *tmp = 0x34; | ||
1317 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_LOW, 1, 1, tmp); | ||
1318 | |||
1319 | *tmp = 0x52; | ||
1320 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_HIGH, | ||
1321 | 1, 1, tmp); | ||
1322 | |||
1323 | dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | | ||
1324 | NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO; | ||
1325 | |||
1326 | dev->net->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | | ||
1327 | NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO; | ||
1328 | |||
1329 | /* Enable checksum offload */ | ||
1330 | *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | | ||
1331 | AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6; | ||
1332 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, tmp); | ||
1333 | |||
1334 | *tmp = AX_TXCOE_IP | AX_TXCOE_TCP | AX_TXCOE_UDP | | ||
1335 | AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6; | ||
1336 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, tmp); | ||
1337 | |||
1338 | /* Configure RX control register => start operation */ | ||
1339 | *tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START | | ||
1340 | AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB; | ||
1341 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, tmp16); | ||
1342 | |||
1343 | *tmp = AX_MONITOR_MODE_PMETYPE | AX_MONITOR_MODE_PMEPOL | | ||
1344 | AX_MONITOR_MODE_RWMP; | ||
1345 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, 1, 1, tmp); | ||
1346 | |||
1347 | /* Configure default medium type => giga */ | ||
1348 | *tmp16 = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN | | ||
1349 | AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_ALWAYS_ONE | | ||
1350 | AX_MEDIUM_FULL_DUPLEX | AX_MEDIUM_GIGAMODE; | ||
1351 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, | ||
1352 | 2, 2, tmp16); | ||
1353 | |||
1354 | ax88179_led_setting(dev); | ||
1355 | |||
1356 | /* Restart autoneg */ | ||
1357 | mii_nway_restart(&dev->mii); | ||
1358 | |||
1359 | netif_carrier_off(dev->net); | ||
1360 | |||
1361 | return 0; | ||
1362 | } | ||
1363 | |||
1364 | static int ax88179_stop(struct usbnet *dev) | ||
1365 | { | ||
1366 | u16 tmp16; | ||
1367 | |||
1368 | ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, | ||
1369 | 2, 2, &tmp16); | ||
1370 | tmp16 &= ~AX_MEDIUM_RECEIVE_EN; | ||
1371 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, | ||
1372 | 2, 2, &tmp16); | ||
1373 | |||
1374 | return 0; | ||
1375 | } | ||
1376 | |||
1377 | static const struct driver_info ax88179_info = { | ||
1378 | .description = "ASIX AX88179 USB 3.0 Gigibit Ethernet", | ||
1379 | .bind = ax88179_bind, | ||
1380 | .unbind = ax88179_unbind, | ||
1381 | .status = ax88179_status, | ||
1382 | .link_reset = ax88179_link_reset, | ||
1383 | .reset = ax88179_reset, | ||
1384 | .stop = ax88179_stop, | ||
1385 | .flags = FLAG_ETHER | FLAG_FRAMING_AX, | ||
1386 | .rx_fixup = ax88179_rx_fixup, | ||
1387 | .tx_fixup = ax88179_tx_fixup, | ||
1388 | }; | ||
1389 | |||
1390 | static const struct driver_info ax88178a_info = { | ||
1391 | .description = "ASIX AX88178A USB 2.0 Gigibit Ethernet", | ||
1392 | .bind = ax88179_bind, | ||
1393 | .unbind = ax88179_unbind, | ||
1394 | .status = ax88179_status, | ||
1395 | .link_reset = ax88179_link_reset, | ||
1396 | .reset = ax88179_reset, | ||
1397 | .stop = ax88179_stop, | ||
1398 | .flags = FLAG_ETHER | FLAG_FRAMING_AX, | ||
1399 | .rx_fixup = ax88179_rx_fixup, | ||
1400 | .tx_fixup = ax88179_tx_fixup, | ||
1401 | }; | ||
1402 | |||
1403 | static const struct driver_info sitecom_info = { | ||
1404 | .description = "Sitecom USB 3.0 to Gigabit Adapter", | ||
1405 | .bind = ax88179_bind, | ||
1406 | .unbind = ax88179_unbind, | ||
1407 | .status = ax88179_status, | ||
1408 | .link_reset = ax88179_link_reset, | ||
1409 | .reset = ax88179_reset, | ||
1410 | .stop = ax88179_stop, | ||
1411 | .flags = FLAG_ETHER | FLAG_FRAMING_AX, | ||
1412 | .rx_fixup = ax88179_rx_fixup, | ||
1413 | .tx_fixup = ax88179_tx_fixup, | ||
1414 | }; | ||
1415 | |||
1416 | static const struct usb_device_id products[] = { | ||
1417 | { | ||
1418 | /* ASIX AX88179 10/100/1000 */ | ||
1419 | USB_DEVICE(0x0b95, 0x1790), | ||
1420 | .driver_info = (unsigned long)&ax88179_info, | ||
1421 | }, { | ||
1422 | /* ASIX AX88178A 10/100/1000 */ | ||
1423 | USB_DEVICE(0x0b95, 0x178a), | ||
1424 | .driver_info = (unsigned long)&ax88178a_info, | ||
1425 | }, { | ||
1426 | /* Sitecom USB 3.0 to Gigabit Adapter */ | ||
1427 | USB_DEVICE(0x0df6, 0x0072), | ||
1428 | .driver_info = (unsigned long) &sitecom_info, | ||
1429 | }, | ||
1430 | { }, | ||
1431 | }; | ||
1432 | MODULE_DEVICE_TABLE(usb, products); | ||
1433 | |||
1434 | static struct usb_driver ax88179_178a_driver = { | ||
1435 | .name = "ax88179_178a", | ||
1436 | .id_table = products, | ||
1437 | .probe = usbnet_probe, | ||
1438 | .suspend = ax88179_suspend, | ||
1439 | .resume = ax88179_resume, | ||
1440 | .disconnect = usbnet_disconnect, | ||
1441 | .supports_autosuspend = 1, | ||
1442 | .disable_hub_initiated_lpm = 1, | ||
1443 | }; | ||
1444 | |||
1445 | module_usb_driver(ax88179_178a_driver); | ||
1446 | |||
1447 | MODULE_DESCRIPTION("ASIX AX88179/178A based USB 3.0/2.0 Gigabit Ethernet Devices"); | ||
1448 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 4a8c25a22294..61b74a2b89ac 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c | |||
@@ -1213,6 +1213,14 @@ static const struct usb_device_id cdc_devs[] = { | |||
1213 | .driver_info = (unsigned long) &wwan_info, | 1213 | .driver_info = (unsigned long) &wwan_info, |
1214 | }, | 1214 | }, |
1215 | 1215 | ||
1216 | /* tag Huawei devices as wwan */ | ||
1217 | { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, | ||
1218 | USB_CLASS_COMM, | ||
1219 | USB_CDC_SUBCLASS_NCM, | ||
1220 | USB_CDC_PROTO_NONE), | ||
1221 | .driver_info = (unsigned long)&wwan_info, | ||
1222 | }, | ||
1223 | |||
1216 | /* Huawei NCM devices disguised as vendor specific */ | 1224 | /* Huawei NCM devices disguised as vendor specific */ |
1217 | { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x16), | 1225 | { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x16), |
1218 | .driver_info = (unsigned long)&wwan_info, | 1226 | .driver_info = (unsigned long)&wwan_info, |
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index f10e58ac9c1b..c3e3d2929ee3 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c | |||
@@ -961,6 +961,8 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) | |||
961 | iph->ttl = ttl ? : ip4_dst_hoplimit(&rt->dst); | 961 | iph->ttl = ttl ? : ip4_dst_hoplimit(&rt->dst); |
962 | tunnel_ip_select_ident(skb, old_iph, &rt->dst); | 962 | tunnel_ip_select_ident(skb, old_iph, &rt->dst); |
963 | 963 | ||
964 | nf_reset(skb); | ||
965 | |||
964 | vxlan_set_owner(dev, skb); | 966 | vxlan_set_owner(dev, skb); |
965 | 967 | ||
966 | /* See iptunnel_xmit() */ | 968 | /* See iptunnel_xmit() */ |
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 3150def17193..2d691b8b95b9 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -1523,7 +1523,8 @@ int ath5k_hw_dma_stop(struct ath5k_hw *ah); | |||
1523 | /* EEPROM access functions */ | 1523 | /* EEPROM access functions */ |
1524 | int ath5k_eeprom_init(struct ath5k_hw *ah); | 1524 | int ath5k_eeprom_init(struct ath5k_hw *ah); |
1525 | void ath5k_eeprom_detach(struct ath5k_hw *ah); | 1525 | void ath5k_eeprom_detach(struct ath5k_hw *ah); |
1526 | 1526 | int ath5k_eeprom_mode_from_channel(struct ath5k_hw *ah, | |
1527 | struct ieee80211_channel *channel); | ||
1527 | 1528 | ||
1528 | /* Protocol Control Unit Functions */ | 1529 | /* Protocol Control Unit Functions */ |
1529 | /* Helpers */ | 1530 | /* Helpers */ |
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index b7e0258887e7..94d34ee02265 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c | |||
@@ -1779,7 +1779,8 @@ ath5k_eeprom_detach(struct ath5k_hw *ah) | |||
1779 | } | 1779 | } |
1780 | 1780 | ||
1781 | int | 1781 | int |
1782 | ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel) | 1782 | ath5k_eeprom_mode_from_channel(struct ath5k_hw *ah, |
1783 | struct ieee80211_channel *channel) | ||
1783 | { | 1784 | { |
1784 | switch (channel->hw_value) { | 1785 | switch (channel->hw_value) { |
1785 | case AR5K_MODE_11A: | 1786 | case AR5K_MODE_11A: |
@@ -1789,6 +1790,7 @@ ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel) | |||
1789 | case AR5K_MODE_11B: | 1790 | case AR5K_MODE_11B: |
1790 | return AR5K_EEPROM_MODE_11B; | 1791 | return AR5K_EEPROM_MODE_11B; |
1791 | default: | 1792 | default: |
1792 | return -1; | 1793 | ATH5K_WARN(ah, "channel is not A/B/G!"); |
1794 | return AR5K_EEPROM_MODE_11A; | ||
1793 | } | 1795 | } |
1794 | } | 1796 | } |
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h index 94a9bbea6874..693296ee9693 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.h +++ b/drivers/net/wireless/ath/ath5k/eeprom.h | |||
@@ -493,6 +493,3 @@ struct ath5k_eeprom_info { | |||
493 | /* Antenna raw switch tables */ | 493 | /* Antenna raw switch tables */ |
494 | u32 ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; | 494 | u32 ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; |
495 | }; | 495 | }; |
496 | |||
497 | int | ||
498 | ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel); | ||
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index a78afa98c650..d6bc7cb61bfb 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c | |||
@@ -1612,11 +1612,7 @@ ath5k_hw_update_noise_floor(struct ath5k_hw *ah) | |||
1612 | 1612 | ||
1613 | ah->ah_cal_mask |= AR5K_CALIBRATION_NF; | 1613 | ah->ah_cal_mask |= AR5K_CALIBRATION_NF; |
1614 | 1614 | ||
1615 | ee_mode = ath5k_eeprom_mode_from_channel(ah->ah_current_channel); | 1615 | ee_mode = ath5k_eeprom_mode_from_channel(ah, ah->ah_current_channel); |
1616 | if (WARN_ON(ee_mode < 0)) { | ||
1617 | ah->ah_cal_mask &= ~AR5K_CALIBRATION_NF; | ||
1618 | return; | ||
1619 | } | ||
1620 | 1616 | ||
1621 | /* completed NF calibration, test threshold */ | 1617 | /* completed NF calibration, test threshold */ |
1622 | nf = ath5k_hw_read_measured_noise_floor(ah); | 1618 | nf = ath5k_hw_read_measured_noise_floor(ah); |
@@ -2317,12 +2313,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) | |||
2317 | 2313 | ||
2318 | def_ant = ah->ah_def_ant; | 2314 | def_ant = ah->ah_def_ant; |
2319 | 2315 | ||
2320 | ee_mode = ath5k_eeprom_mode_from_channel(channel); | 2316 | ee_mode = ath5k_eeprom_mode_from_channel(ah, channel); |
2321 | if (ee_mode < 0) { | ||
2322 | ATH5K_ERR(ah, | ||
2323 | "invalid channel: %d\n", channel->center_freq); | ||
2324 | return; | ||
2325 | } | ||
2326 | 2317 | ||
2327 | switch (ant_mode) { | 2318 | switch (ant_mode) { |
2328 | case AR5K_ANTMODE_DEFAULT: | 2319 | case AR5K_ANTMODE_DEFAULT: |
@@ -3622,12 +3613,7 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
3622 | return -EINVAL; | 3613 | return -EINVAL; |
3623 | } | 3614 | } |
3624 | 3615 | ||
3625 | ee_mode = ath5k_eeprom_mode_from_channel(channel); | 3616 | ee_mode = ath5k_eeprom_mode_from_channel(ah, channel); |
3626 | if (ee_mode < 0) { | ||
3627 | ATH5K_ERR(ah, | ||
3628 | "invalid channel: %d\n", channel->center_freq); | ||
3629 | return -EINVAL; | ||
3630 | } | ||
3631 | 3617 | ||
3632 | /* Initialize TX power table */ | 3618 | /* Initialize TX power table */ |
3633 | switch (ah->ah_radio) { | 3619 | switch (ah->ah_radio) { |
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index e2d8b2cf19eb..a3399c4f13a9 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c | |||
@@ -984,9 +984,7 @@ ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, | |||
984 | if (ah->ah_version == AR5K_AR5210) | 984 | if (ah->ah_version == AR5K_AR5210) |
985 | return; | 985 | return; |
986 | 986 | ||
987 | ee_mode = ath5k_eeprom_mode_from_channel(channel); | 987 | ee_mode = ath5k_eeprom_mode_from_channel(ah, channel); |
988 | if (WARN_ON(ee_mode < 0)) | ||
989 | return; | ||
990 | 988 | ||
991 | /* Adjust power delta for channel 14 */ | 989 | /* Adjust power delta for channel 14 */ |
992 | if (channel->center_freq == 2484) | 990 | if (channel->center_freq == 2484) |
diff --git a/drivers/net/wireless/ath/ath6kl/Kconfig b/drivers/net/wireless/ath/ath6kl/Kconfig index 630c83db056e..e39e5860a2e9 100644 --- a/drivers/net/wireless/ath/ath6kl/Kconfig +++ b/drivers/net/wireless/ath/ath6kl/Kconfig | |||
@@ -30,6 +30,15 @@ config ATH6KL_DEBUG | |||
30 | ---help--- | 30 | ---help--- |
31 | Enables debug support | 31 | Enables debug support |
32 | 32 | ||
33 | config ATH6KL_TRACING | ||
34 | bool "Atheros ath6kl tracing support" | ||
35 | depends on ATH6KL | ||
36 | depends on EVENT_TRACING | ||
37 | ---help--- | ||
38 | Select this to ath6kl use tracing infrastructure. | ||
39 | |||
40 | If unsure, say Y to make it easier to debug problems. | ||
41 | |||
33 | config ATH6KL_REGDOMAIN | 42 | config ATH6KL_REGDOMAIN |
34 | bool "Atheros ath6kl regdomain support" | 43 | bool "Atheros ath6kl regdomain support" |
35 | depends on ATH6KL | 44 | depends on ATH6KL |
diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile index cab0ec0d5380..dc2b3b46781e 100644 --- a/drivers/net/wireless/ath/ath6kl/Makefile +++ b/drivers/net/wireless/ath/ath6kl/Makefile | |||
@@ -35,10 +35,15 @@ ath6kl_core-y += txrx.o | |||
35 | ath6kl_core-y += wmi.o | 35 | ath6kl_core-y += wmi.o |
36 | ath6kl_core-y += core.o | 36 | ath6kl_core-y += core.o |
37 | ath6kl_core-y += recovery.o | 37 | ath6kl_core-y += recovery.o |
38 | |||
38 | ath6kl_core-$(CONFIG_NL80211_TESTMODE) += testmode.o | 39 | ath6kl_core-$(CONFIG_NL80211_TESTMODE) += testmode.o |
40 | ath6kl_core-$(CONFIG_ATH6KL_TRACING) += trace.o | ||
39 | 41 | ||
40 | obj-$(CONFIG_ATH6KL_SDIO) += ath6kl_sdio.o | 42 | obj-$(CONFIG_ATH6KL_SDIO) += ath6kl_sdio.o |
41 | ath6kl_sdio-y += sdio.o | 43 | ath6kl_sdio-y += sdio.o |
42 | 44 | ||
43 | obj-$(CONFIG_ATH6KL_USB) += ath6kl_usb.o | 45 | obj-$(CONFIG_ATH6KL_USB) += ath6kl_usb.o |
44 | ath6kl_usb-y += usb.o | 46 | ath6kl_usb-y += usb.o |
47 | |||
48 | # for tracing framework to find trace.h | ||
49 | CFLAGS_trace.o := -I$(src) | ||
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 752ffc4f4166..5c9736a94e54 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -402,7 +402,7 @@ static bool ath6kl_is_valid_iftype(struct ath6kl *ar, enum nl80211_iftype type, | |||
402 | if (type == NL80211_IFTYPE_STATION || | 402 | if (type == NL80211_IFTYPE_STATION || |
403 | type == NL80211_IFTYPE_AP || type == NL80211_IFTYPE_ADHOC) { | 403 | type == NL80211_IFTYPE_AP || type == NL80211_IFTYPE_ADHOC) { |
404 | for (i = 0; i < ar->vif_max; i++) { | 404 | for (i = 0; i < ar->vif_max; i++) { |
405 | if ((ar->avail_idx_map >> i) & BIT(0)) { | 405 | if ((ar->avail_idx_map) & BIT(i)) { |
406 | *if_idx = i; | 406 | *if_idx = i; |
407 | return true; | 407 | return true; |
408 | } | 408 | } |
@@ -412,7 +412,7 @@ static bool ath6kl_is_valid_iftype(struct ath6kl *ar, enum nl80211_iftype type, | |||
412 | if (type == NL80211_IFTYPE_P2P_CLIENT || | 412 | if (type == NL80211_IFTYPE_P2P_CLIENT || |
413 | type == NL80211_IFTYPE_P2P_GO) { | 413 | type == NL80211_IFTYPE_P2P_GO) { |
414 | for (i = ar->max_norm_iface; i < ar->vif_max; i++) { | 414 | for (i = ar->max_norm_iface; i < ar->vif_max; i++) { |
415 | if ((ar->avail_idx_map >> i) & BIT(0)) { | 415 | if ((ar->avail_idx_map) & BIT(i)) { |
416 | *if_idx = i; | 416 | *if_idx = i; |
417 | return true; | 417 | return true; |
418 | } | 418 | } |
@@ -1535,7 +1535,9 @@ static int ath6kl_cfg80211_del_iface(struct wiphy *wiphy, | |||
1535 | 1535 | ||
1536 | ath6kl_cfg80211_vif_stop(vif, test_bit(WMI_READY, &ar->flag)); | 1536 | ath6kl_cfg80211_vif_stop(vif, test_bit(WMI_READY, &ar->flag)); |
1537 | 1537 | ||
1538 | rtnl_lock(); | ||
1538 | ath6kl_cfg80211_vif_cleanup(vif); | 1539 | ath6kl_cfg80211_vif_cleanup(vif); |
1540 | rtnl_unlock(); | ||
1539 | 1541 | ||
1540 | return 0; | 1542 | return 0; |
1541 | } | 1543 | } |
@@ -2990,13 +2992,15 @@ static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev, | |||
2990 | { | 2992 | { |
2991 | struct ath6kl *ar = ath6kl_priv(dev); | 2993 | struct ath6kl *ar = ath6kl_priv(dev); |
2992 | struct ath6kl_vif *vif = netdev_priv(dev); | 2994 | struct ath6kl_vif *vif = netdev_priv(dev); |
2995 | int err; | ||
2993 | 2996 | ||
2994 | if (vif->nw_type != AP_NETWORK) | 2997 | if (vif->nw_type != AP_NETWORK) |
2995 | return -EOPNOTSUPP; | 2998 | return -EOPNOTSUPP; |
2996 | 2999 | ||
2997 | /* Use this only for authorizing/unauthorizing a station */ | 3000 | err = cfg80211_check_station_change(wiphy, params, |
2998 | if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))) | 3001 | CFG80211_STA_AP_MLME_CLIENT); |
2999 | return -EOPNOTSUPP; | 3002 | if (err) |
3003 | return err; | ||
3000 | 3004 | ||
3001 | if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) | 3005 | if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) |
3002 | return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx, | 3006 | return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx, |
@@ -3659,7 +3663,6 @@ struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name, | |||
3659 | vif->sme_state = SME_DISCONNECTED; | 3663 | vif->sme_state = SME_DISCONNECTED; |
3660 | set_bit(WLAN_ENABLED, &vif->flags); | 3664 | set_bit(WLAN_ENABLED, &vif->flags); |
3661 | ar->wlan_pwr_state = WLAN_POWER_STATE_ON; | 3665 | ar->wlan_pwr_state = WLAN_POWER_STATE_ON; |
3662 | set_bit(NETDEV_REGISTERED, &vif->flags); | ||
3663 | 3666 | ||
3664 | if (type == NL80211_IFTYPE_ADHOC) | 3667 | if (type == NL80211_IFTYPE_ADHOC) |
3665 | ar->ibss_if_active = true; | 3668 | ar->ibss_if_active = true; |
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 61b2f98b4e77..26b0f92424e1 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h | |||
@@ -560,7 +560,6 @@ enum ath6kl_vif_state { | |||
560 | WMM_ENABLED, | 560 | WMM_ENABLED, |
561 | NETQ_STOPPED, | 561 | NETQ_STOPPED, |
562 | DTIM_EXPIRED, | 562 | DTIM_EXPIRED, |
563 | NETDEV_REGISTERED, | ||
564 | CLEAR_BSSFILTER_ON_BEACON, | 563 | CLEAR_BSSFILTER_ON_BEACON, |
565 | DTIM_PERIOD_AVAIL, | 564 | DTIM_PERIOD_AVAIL, |
566 | WLAN_ENABLED, | 565 | WLAN_ENABLED, |
@@ -936,8 +935,6 @@ void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid, u16 seq_no, | |||
936 | u8 win_sz); | 935 | u8 win_sz); |
937 | void ath6kl_wakeup_event(void *dev); | 936 | void ath6kl_wakeup_event(void *dev); |
938 | 937 | ||
939 | void ath6kl_reset_device(struct ath6kl *ar, u32 target_type, | ||
940 | bool wait_fot_compltn, bool cold_reset); | ||
941 | void ath6kl_init_control_info(struct ath6kl_vif *vif); | 938 | void ath6kl_init_control_info(struct ath6kl_vif *vif); |
942 | struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar); | 939 | struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar); |
943 | void ath6kl_cfg80211_vif_stop(struct ath6kl_vif *vif, bool wmi_ready); | 940 | void ath6kl_cfg80211_vif_stop(struct ath6kl_vif *vif, bool wmi_ready); |
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index 15cfe30e54fd..fe38b836cb26 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c | |||
@@ -56,6 +56,60 @@ int ath6kl_printk(const char *level, const char *fmt, ...) | |||
56 | } | 56 | } |
57 | EXPORT_SYMBOL(ath6kl_printk); | 57 | EXPORT_SYMBOL(ath6kl_printk); |
58 | 58 | ||
59 | int ath6kl_info(const char *fmt, ...) | ||
60 | { | ||
61 | struct va_format vaf = { | ||
62 | .fmt = fmt, | ||
63 | }; | ||
64 | va_list args; | ||
65 | int ret; | ||
66 | |||
67 | va_start(args, fmt); | ||
68 | vaf.va = &args; | ||
69 | ret = ath6kl_printk(KERN_INFO, "%pV", &vaf); | ||
70 | trace_ath6kl_log_info(&vaf); | ||
71 | va_end(args); | ||
72 | |||
73 | return ret; | ||
74 | } | ||
75 | EXPORT_SYMBOL(ath6kl_info); | ||
76 | |||
77 | int ath6kl_err(const char *fmt, ...) | ||
78 | { | ||
79 | struct va_format vaf = { | ||
80 | .fmt = fmt, | ||
81 | }; | ||
82 | va_list args; | ||
83 | int ret; | ||
84 | |||
85 | va_start(args, fmt); | ||
86 | vaf.va = &args; | ||
87 | ret = ath6kl_printk(KERN_ERR, "%pV", &vaf); | ||
88 | trace_ath6kl_log_err(&vaf); | ||
89 | va_end(args); | ||
90 | |||
91 | return ret; | ||
92 | } | ||
93 | EXPORT_SYMBOL(ath6kl_err); | ||
94 | |||
95 | int ath6kl_warn(const char *fmt, ...) | ||
96 | { | ||
97 | struct va_format vaf = { | ||
98 | .fmt = fmt, | ||
99 | }; | ||
100 | va_list args; | ||
101 | int ret; | ||
102 | |||
103 | va_start(args, fmt); | ||
104 | vaf.va = &args; | ||
105 | ret = ath6kl_printk(KERN_WARNING, "%pV", &vaf); | ||
106 | trace_ath6kl_log_warn(&vaf); | ||
107 | va_end(args); | ||
108 | |||
109 | return ret; | ||
110 | } | ||
111 | EXPORT_SYMBOL(ath6kl_warn); | ||
112 | |||
59 | #ifdef CONFIG_ATH6KL_DEBUG | 113 | #ifdef CONFIG_ATH6KL_DEBUG |
60 | 114 | ||
61 | void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...) | 115 | void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...) |
@@ -63,15 +117,15 @@ void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...) | |||
63 | struct va_format vaf; | 117 | struct va_format vaf; |
64 | va_list args; | 118 | va_list args; |
65 | 119 | ||
66 | if (!(debug_mask & mask)) | ||
67 | return; | ||
68 | |||
69 | va_start(args, fmt); | 120 | va_start(args, fmt); |
70 | 121 | ||
71 | vaf.fmt = fmt; | 122 | vaf.fmt = fmt; |
72 | vaf.va = &args; | 123 | vaf.va = &args; |
73 | 124 | ||
74 | ath6kl_printk(KERN_DEBUG, "%pV", &vaf); | 125 | if (debug_mask & mask) |
126 | ath6kl_printk(KERN_DEBUG, "%pV", &vaf); | ||
127 | |||
128 | trace_ath6kl_log_dbg(mask, &vaf); | ||
75 | 129 | ||
76 | va_end(args); | 130 | va_end(args); |
77 | } | 131 | } |
@@ -87,6 +141,10 @@ void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, | |||
87 | 141 | ||
88 | print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len); | 142 | print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len); |
89 | } | 143 | } |
144 | |||
145 | /* tracing code doesn't like null strings :/ */ | ||
146 | trace_ath6kl_log_dbg_dump(msg ? msg : "", prefix ? prefix : "", | ||
147 | buf, len); | ||
90 | } | 148 | } |
91 | EXPORT_SYMBOL(ath6kl_dbg_dump); | 149 | EXPORT_SYMBOL(ath6kl_dbg_dump); |
92 | 150 | ||
@@ -1752,8 +1810,10 @@ int ath6kl_debug_init_fs(struct ath6kl *ar) | |||
1752 | debugfs_create_file("tgt_stats", S_IRUSR, ar->debugfs_phy, ar, | 1810 | debugfs_create_file("tgt_stats", S_IRUSR, ar->debugfs_phy, ar, |
1753 | &fops_tgt_stats); | 1811 | &fops_tgt_stats); |
1754 | 1812 | ||
1755 | debugfs_create_file("credit_dist_stats", S_IRUSR, ar->debugfs_phy, ar, | 1813 | if (ar->hif_type == ATH6KL_HIF_TYPE_SDIO) |
1756 | &fops_credit_dist_stats); | 1814 | debugfs_create_file("credit_dist_stats", S_IRUSR, |
1815 | ar->debugfs_phy, ar, | ||
1816 | &fops_credit_dist_stats); | ||
1757 | 1817 | ||
1758 | debugfs_create_file("endpoint_stats", S_IRUSR | S_IWUSR, | 1818 | debugfs_create_file("endpoint_stats", S_IRUSR | S_IWUSR, |
1759 | ar->debugfs_phy, ar, &fops_endpoint_stats); | 1819 | ar->debugfs_phy, ar, &fops_endpoint_stats); |
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h index f97cd4ead543..74369de00fb5 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.h +++ b/drivers/net/wireless/ath/ath6kl/debug.h | |||
@@ -19,6 +19,7 @@ | |||
19 | #define DEBUG_H | 19 | #define DEBUG_H |
20 | 20 | ||
21 | #include "hif.h" | 21 | #include "hif.h" |
22 | #include "trace.h" | ||
22 | 23 | ||
23 | enum ATH6K_DEBUG_MASK { | 24 | enum ATH6K_DEBUG_MASK { |
24 | ATH6KL_DBG_CREDIT = BIT(0), | 25 | ATH6KL_DBG_CREDIT = BIT(0), |
@@ -51,13 +52,9 @@ enum ATH6K_DEBUG_MASK { | |||
51 | extern unsigned int debug_mask; | 52 | extern unsigned int debug_mask; |
52 | extern __printf(2, 3) | 53 | extern __printf(2, 3) |
53 | int ath6kl_printk(const char *level, const char *fmt, ...); | 54 | int ath6kl_printk(const char *level, const char *fmt, ...); |
54 | 55 | extern __printf(1, 2) int ath6kl_info(const char *fmt, ...); | |
55 | #define ath6kl_info(fmt, ...) \ | 56 | extern __printf(1, 2) int ath6kl_err(const char *fmt, ...); |
56 | ath6kl_printk(KERN_INFO, fmt, ##__VA_ARGS__) | 57 | extern __printf(1, 2) int ath6kl_warn(const char *fmt, ...); |
57 | #define ath6kl_err(fmt, ...) \ | ||
58 | ath6kl_printk(KERN_ERR, fmt, ##__VA_ARGS__) | ||
59 | #define ath6kl_warn(fmt, ...) \ | ||
60 | ath6kl_printk(KERN_WARNING, fmt, ##__VA_ARGS__) | ||
61 | 58 | ||
62 | enum ath6kl_war { | 59 | enum ath6kl_war { |
63 | ATH6KL_WAR_INVALID_RATE, | 60 | ATH6KL_WAR_INVALID_RATE, |
diff --git a/drivers/net/wireless/ath/ath6kl/hif.c b/drivers/net/wireless/ath/ath6kl/hif.c index a6b614421fa4..fea7709b5dda 100644 --- a/drivers/net/wireless/ath/ath6kl/hif.c +++ b/drivers/net/wireless/ath/ath6kl/hif.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include "target.h" | 22 | #include "target.h" |
23 | #include "hif-ops.h" | 23 | #include "hif-ops.h" |
24 | #include "debug.h" | 24 | #include "debug.h" |
25 | #include "trace.h" | ||
25 | 26 | ||
26 | #define MAILBOX_FOR_BLOCK_SIZE 1 | 27 | #define MAILBOX_FOR_BLOCK_SIZE 1 |
27 | 28 | ||
@@ -436,6 +437,8 @@ static int proc_pending_irqs(struct ath6kl_device *dev, bool *done) | |||
436 | 437 | ||
437 | ath6kl_dump_registers(dev, &dev->irq_proc_reg, | 438 | ath6kl_dump_registers(dev, &dev->irq_proc_reg, |
438 | &dev->irq_en_reg); | 439 | &dev->irq_en_reg); |
440 | trace_ath6kl_sdio_irq(&dev->irq_en_reg, | ||
441 | sizeof(dev->irq_en_reg)); | ||
439 | 442 | ||
440 | /* Update only those registers that are enabled */ | 443 | /* Update only those registers that are enabled */ |
441 | host_int_status = dev->irq_proc_reg.host_int_status & | 444 | host_int_status = dev->irq_proc_reg.host_int_status & |
diff --git a/drivers/net/wireless/ath/ath6kl/htc_mbox.c b/drivers/net/wireless/ath/ath6kl/htc_mbox.c index fbb78dfe078f..65e5b719093d 100644 --- a/drivers/net/wireless/ath/ath6kl/htc_mbox.c +++ b/drivers/net/wireless/ath/ath6kl/htc_mbox.c | |||
@@ -19,6 +19,8 @@ | |||
19 | #include "hif.h" | 19 | #include "hif.h" |
20 | #include "debug.h" | 20 | #include "debug.h" |
21 | #include "hif-ops.h" | 21 | #include "hif-ops.h" |
22 | #include "trace.h" | ||
23 | |||
22 | #include <asm/unaligned.h> | 24 | #include <asm/unaligned.h> |
23 | 25 | ||
24 | #define CALC_TXRX_PADDED_LEN(dev, len) (__ALIGN_MASK((len), (dev)->block_mask)) | 26 | #define CALC_TXRX_PADDED_LEN(dev, len) (__ALIGN_MASK((len), (dev)->block_mask)) |
@@ -537,6 +539,8 @@ static int ath6kl_htc_tx_issue(struct htc_target *target, | |||
537 | packet->buf, padded_len, | 539 | packet->buf, padded_len, |
538 | HIF_WR_ASYNC_BLOCK_INC, packet); | 540 | HIF_WR_ASYNC_BLOCK_INC, packet); |
539 | 541 | ||
542 | trace_ath6kl_htc_tx(status, packet->endpoint, packet->buf, send_len); | ||
543 | |||
540 | return status; | 544 | return status; |
541 | } | 545 | } |
542 | 546 | ||
@@ -757,7 +761,8 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint, | |||
757 | { | 761 | { |
758 | struct htc_target *target = endpoint->target; | 762 | struct htc_target *target = endpoint->target; |
759 | struct hif_scatter_req *scat_req = NULL; | 763 | struct hif_scatter_req *scat_req = NULL; |
760 | int n_scat, n_sent_bundle = 0, tot_pkts_bundle = 0; | 764 | int n_scat, n_sent_bundle = 0, tot_pkts_bundle = 0, i; |
765 | struct htc_packet *packet; | ||
761 | int status; | 766 | int status; |
762 | u32 txb_mask; | 767 | u32 txb_mask; |
763 | u8 ac = WMM_NUM_AC; | 768 | u8 ac = WMM_NUM_AC; |
@@ -832,6 +837,13 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint, | |||
832 | ath6kl_dbg(ATH6KL_DBG_HTC, | 837 | ath6kl_dbg(ATH6KL_DBG_HTC, |
833 | "htc tx scatter bytes %d entries %d\n", | 838 | "htc tx scatter bytes %d entries %d\n", |
834 | scat_req->len, scat_req->scat_entries); | 839 | scat_req->len, scat_req->scat_entries); |
840 | |||
841 | for (i = 0; i < scat_req->scat_entries; i++) { | ||
842 | packet = scat_req->scat_list[i].packet; | ||
843 | trace_ath6kl_htc_tx(packet->status, packet->endpoint, | ||
844 | packet->buf, packet->act_len); | ||
845 | } | ||
846 | |||
835 | ath6kl_hif_submit_scat_req(target->dev, scat_req, false); | 847 | ath6kl_hif_submit_scat_req(target->dev, scat_req, false); |
836 | 848 | ||
837 | if (status) | 849 | if (status) |
@@ -1903,6 +1915,7 @@ static void ath6kl_htc_rx_complete(struct htc_endpoint *endpoint, | |||
1903 | ath6kl_dbg(ATH6KL_DBG_HTC, | 1915 | ath6kl_dbg(ATH6KL_DBG_HTC, |
1904 | "htc rx complete ep %d packet 0x%p\n", | 1916 | "htc rx complete ep %d packet 0x%p\n", |
1905 | endpoint->eid, packet); | 1917 | endpoint->eid, packet); |
1918 | |||
1906 | endpoint->ep_cb.rx(endpoint->target, packet); | 1919 | endpoint->ep_cb.rx(endpoint->target, packet); |
1907 | } | 1920 | } |
1908 | 1921 | ||
@@ -2011,6 +2024,9 @@ static int ath6kl_htc_rx_process_packets(struct htc_target *target, | |||
2011 | list_for_each_entry_safe(packet, tmp_pkt, comp_pktq, list) { | 2024 | list_for_each_entry_safe(packet, tmp_pkt, comp_pktq, list) { |
2012 | ep = &target->endpoint[packet->endpoint]; | 2025 | ep = &target->endpoint[packet->endpoint]; |
2013 | 2026 | ||
2027 | trace_ath6kl_htc_rx(packet->status, packet->endpoint, | ||
2028 | packet->buf, packet->act_len); | ||
2029 | |||
2014 | /* process header for each of the recv packet */ | 2030 | /* process header for each of the recv packet */ |
2015 | status = ath6kl_htc_rx_process_hdr(target, packet, lk_ahds, | 2031 | status = ath6kl_htc_rx_process_hdr(target, packet, lk_ahds, |
2016 | n_lk_ahd); | 2032 | n_lk_ahd); |
@@ -2291,6 +2307,9 @@ static struct htc_packet *htc_wait_for_ctrl_msg(struct htc_target *target) | |||
2291 | if (ath6kl_htc_rx_packet(target, packet, packet->act_len)) | 2307 | if (ath6kl_htc_rx_packet(target, packet, packet->act_len)) |
2292 | goto fail_ctrl_rx; | 2308 | goto fail_ctrl_rx; |
2293 | 2309 | ||
2310 | trace_ath6kl_htc_rx(packet->status, packet->endpoint, | ||
2311 | packet->buf, packet->act_len); | ||
2312 | |||
2294 | /* process receive header */ | 2313 | /* process receive header */ |
2295 | packet->status = ath6kl_htc_rx_process_hdr(target, packet, NULL, NULL); | 2314 | packet->status = ath6kl_htc_rx_process_hdr(target, packet, NULL, NULL); |
2296 | 2315 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/htc_pipe.c b/drivers/net/wireless/ath/ath6kl/htc_pipe.c index 281390178e3d..67aa924ed8b3 100644 --- a/drivers/net/wireless/ath/ath6kl/htc_pipe.c +++ b/drivers/net/wireless/ath/ath6kl/htc_pipe.c | |||
@@ -988,8 +988,6 @@ static int ath6kl_htc_pipe_rx_complete(struct ath6kl *ar, struct sk_buff *skb, | |||
988 | 988 | ||
989 | htc_hdr = (struct htc_frame_hdr *) netdata; | 989 | htc_hdr = (struct htc_frame_hdr *) netdata; |
990 | 990 | ||
991 | ep = &target->endpoint[htc_hdr->eid]; | ||
992 | |||
993 | if (htc_hdr->eid >= ENDPOINT_MAX) { | 991 | if (htc_hdr->eid >= ENDPOINT_MAX) { |
994 | ath6kl_dbg(ATH6KL_DBG_HTC, | 992 | ath6kl_dbg(ATH6KL_DBG_HTC, |
995 | "HTC Rx: invalid EndpointID=%d\n", | 993 | "HTC Rx: invalid EndpointID=%d\n", |
@@ -997,6 +995,7 @@ static int ath6kl_htc_pipe_rx_complete(struct ath6kl *ar, struct sk_buff *skb, | |||
997 | status = -EINVAL; | 995 | status = -EINVAL; |
998 | goto free_skb; | 996 | goto free_skb; |
999 | } | 997 | } |
998 | ep = &target->endpoint[htc_hdr->eid]; | ||
1000 | 999 | ||
1001 | payload_len = le16_to_cpu(get_unaligned(&htc_hdr->payld_len)); | 1000 | payload_len = le16_to_cpu(get_unaligned(&htc_hdr->payld_len)); |
1002 | 1001 | ||
@@ -1168,8 +1167,8 @@ static int htc_wait_recv_ctrl_message(struct htc_target *target) | |||
1168 | } | 1167 | } |
1169 | 1168 | ||
1170 | if (count <= 0) { | 1169 | if (count <= 0) { |
1171 | ath6kl_dbg(ATH6KL_DBG_HTC, "%s: Timeout!\n", __func__); | 1170 | ath6kl_warn("htc pipe control receive timeout!\n"); |
1172 | return -ECOMM; | 1171 | return -ETIMEDOUT; |
1173 | } | 1172 | } |
1174 | 1173 | ||
1175 | return 0; | 1174 | return 0; |
@@ -1582,16 +1581,16 @@ static int ath6kl_htc_pipe_wait_target(struct htc_target *target) | |||
1582 | return status; | 1581 | return status; |
1583 | 1582 | ||
1584 | if (target->pipe.ctrl_response_len < sizeof(*ready_msg)) { | 1583 | if (target->pipe.ctrl_response_len < sizeof(*ready_msg)) { |
1585 | ath6kl_dbg(ATH6KL_DBG_HTC, "invalid htc ready msg len:%d!\n", | 1584 | ath6kl_warn("invalid htc pipe ready msg len: %d\n", |
1586 | target->pipe.ctrl_response_len); | 1585 | target->pipe.ctrl_response_len); |
1587 | return -ECOMM; | 1586 | return -ECOMM; |
1588 | } | 1587 | } |
1589 | 1588 | ||
1590 | ready_msg = (struct htc_ready_ext_msg *) target->pipe.ctrl_response_buf; | 1589 | ready_msg = (struct htc_ready_ext_msg *) target->pipe.ctrl_response_buf; |
1591 | 1590 | ||
1592 | if (ready_msg->ver2_0_info.msg_id != cpu_to_le16(HTC_MSG_READY_ID)) { | 1591 | if (ready_msg->ver2_0_info.msg_id != cpu_to_le16(HTC_MSG_READY_ID)) { |
1593 | ath6kl_dbg(ATH6KL_DBG_HTC, "invalid htc ready msg : 0x%X !\n", | 1592 | ath6kl_warn("invalid htc pipe ready msg: 0x%x\n", |
1594 | ready_msg->ver2_0_info.msg_id); | 1593 | ready_msg->ver2_0_info.msg_id); |
1595 | return -ECOMM; | 1594 | return -ECOMM; |
1596 | } | 1595 | } |
1597 | 1596 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 5d434cf88f35..40ffee6184fd 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c | |||
@@ -201,8 +201,8 @@ struct sk_buff *ath6kl_buf_alloc(int size) | |||
201 | u16 reserved; | 201 | u16 reserved; |
202 | 202 | ||
203 | /* Add chacheline space at front and back of buffer */ | 203 | /* Add chacheline space at front and back of buffer */ |
204 | reserved = (2 * L1_CACHE_BYTES) + ATH6KL_DATA_OFFSET + | 204 | reserved = roundup((2 * L1_CACHE_BYTES) + ATH6KL_DATA_OFFSET + |
205 | sizeof(struct htc_packet) + ATH6KL_HTC_ALIGN_BYTES; | 205 | sizeof(struct htc_packet) + ATH6KL_HTC_ALIGN_BYTES, 4); |
206 | skb = dev_alloc_skb(size + reserved); | 206 | skb = dev_alloc_skb(size + reserved); |
207 | 207 | ||
208 | if (skb) | 208 | if (skb) |
@@ -1549,10 +1549,89 @@ static const char *ath6kl_init_get_hif_name(enum ath6kl_hif_type type) | |||
1549 | return NULL; | 1549 | return NULL; |
1550 | } | 1550 | } |
1551 | 1551 | ||
1552 | |||
1553 | static const struct fw_capa_str_map { | ||
1554 | int id; | ||
1555 | const char *name; | ||
1556 | } fw_capa_map[] = { | ||
1557 | { ATH6KL_FW_CAPABILITY_HOST_P2P, "host-p2p" }, | ||
1558 | { ATH6KL_FW_CAPABILITY_SCHED_SCAN, "sched-scan" }, | ||
1559 | { ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX, "sta-p2pdev-duplex" }, | ||
1560 | { ATH6KL_FW_CAPABILITY_INACTIVITY_TIMEOUT, "inactivity-timeout" }, | ||
1561 | { ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE, "rsn-cap-override" }, | ||
1562 | { ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER, "wow-mc-filter" }, | ||
1563 | { ATH6KL_FW_CAPABILITY_BMISS_ENHANCE, "bmiss-enhance" }, | ||
1564 | { ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST, "sscan-match-list" }, | ||
1565 | { ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD, "rssi-scan-thold" }, | ||
1566 | { ATH6KL_FW_CAPABILITY_CUSTOM_MAC_ADDR, "custom-mac-addr" }, | ||
1567 | { ATH6KL_FW_CAPABILITY_TX_ERR_NOTIFY, "tx-err-notify" }, | ||
1568 | { ATH6KL_FW_CAPABILITY_REGDOMAIN, "regdomain" }, | ||
1569 | { ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2, "sched-scan-v2" }, | ||
1570 | { ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL, "hb-poll" }, | ||
1571 | }; | ||
1572 | |||
1573 | static const char *ath6kl_init_get_fw_capa_name(unsigned int id) | ||
1574 | { | ||
1575 | int i; | ||
1576 | |||
1577 | for (i = 0; i < ARRAY_SIZE(fw_capa_map); i++) { | ||
1578 | if (fw_capa_map[i].id == id) | ||
1579 | return fw_capa_map[i].name; | ||
1580 | } | ||
1581 | |||
1582 | return "<unknown>"; | ||
1583 | } | ||
1584 | |||
1585 | static void ath6kl_init_get_fwcaps(struct ath6kl *ar, char *buf, size_t buf_len) | ||
1586 | { | ||
1587 | u8 *data = (u8 *) ar->fw_capabilities; | ||
1588 | size_t trunc_len, len = 0; | ||
1589 | int i, index, bit; | ||
1590 | char *trunc = "..."; | ||
1591 | |||
1592 | for (i = 0; i < ATH6KL_FW_CAPABILITY_MAX; i++) { | ||
1593 | index = i / 8; | ||
1594 | bit = i % 8; | ||
1595 | |||
1596 | if (index >= sizeof(ar->fw_capabilities) * 4) | ||
1597 | break; | ||
1598 | |||
1599 | if (buf_len - len < 4) { | ||
1600 | ath6kl_warn("firmware capability buffer too small!\n"); | ||
1601 | |||
1602 | /* add "..." to the end of string */ | ||
1603 | trunc_len = strlen(trunc) + 1; | ||
1604 | strncpy(buf + buf_len - trunc_len, trunc, trunc_len); | ||
1605 | |||
1606 | return; | ||
1607 | } | ||
1608 | |||
1609 | if (data[index] & (1 << bit)) { | ||
1610 | len += scnprintf(buf + len, buf_len - len, "%s,", | ||
1611 | ath6kl_init_get_fw_capa_name(i)); | ||
1612 | } | ||
1613 | } | ||
1614 | |||
1615 | /* overwrite the last comma */ | ||
1616 | if (len > 0) | ||
1617 | len--; | ||
1618 | |||
1619 | buf[len] = '\0'; | ||
1620 | } | ||
1621 | |||
1622 | static int ath6kl_init_hw_reset(struct ath6kl *ar) | ||
1623 | { | ||
1624 | ath6kl_dbg(ATH6KL_DBG_BOOT, "cold resetting the device"); | ||
1625 | |||
1626 | return ath6kl_diag_write32(ar, RESET_CONTROL_ADDRESS, | ||
1627 | cpu_to_le32(RESET_CONTROL_COLD_RST)); | ||
1628 | } | ||
1629 | |||
1552 | static int __ath6kl_init_hw_start(struct ath6kl *ar) | 1630 | static int __ath6kl_init_hw_start(struct ath6kl *ar) |
1553 | { | 1631 | { |
1554 | long timeleft; | 1632 | long timeleft; |
1555 | int ret, i; | 1633 | int ret, i; |
1634 | char buf[200]; | ||
1556 | 1635 | ||
1557 | ath6kl_dbg(ATH6KL_DBG_BOOT, "hw start\n"); | 1636 | ath6kl_dbg(ATH6KL_DBG_BOOT, "hw start\n"); |
1558 | 1637 | ||
@@ -1569,24 +1648,35 @@ static int __ath6kl_init_hw_start(struct ath6kl *ar) | |||
1569 | goto err_power_off; | 1648 | goto err_power_off; |
1570 | 1649 | ||
1571 | /* Do we need to finish the BMI phase */ | 1650 | /* Do we need to finish the BMI phase */ |
1572 | /* FIXME: return error from ath6kl_bmi_done() */ | 1651 | ret = ath6kl_bmi_done(ar); |
1573 | if (ath6kl_bmi_done(ar)) { | 1652 | if (ret) |
1574 | ret = -EIO; | ||
1575 | goto err_power_off; | 1653 | goto err_power_off; |
1576 | } | ||
1577 | 1654 | ||
1578 | /* | 1655 | /* |
1579 | * The reason we have to wait for the target here is that the | 1656 | * The reason we have to wait for the target here is that the |
1580 | * driver layer has to init BMI in order to set the host block | 1657 | * driver layer has to init BMI in order to set the host block |
1581 | * size. | 1658 | * size. |
1582 | */ | 1659 | */ |
1583 | if (ath6kl_htc_wait_target(ar->htc_target)) { | 1660 | ret = ath6kl_htc_wait_target(ar->htc_target); |
1584 | ret = -EIO; | 1661 | |
1662 | if (ret == -ETIMEDOUT) { | ||
1663 | /* | ||
1664 | * Most likely USB target is in odd state after reboot and | ||
1665 | * needs a reset. A cold reset makes the whole device | ||
1666 | * disappear from USB bus and initialisation starts from | ||
1667 | * beginning. | ||
1668 | */ | ||
1669 | ath6kl_warn("htc wait target timed out, resetting device\n"); | ||
1670 | ath6kl_init_hw_reset(ar); | ||
1671 | goto err_power_off; | ||
1672 | } else if (ret) { | ||
1673 | ath6kl_err("htc wait target failed: %d\n", ret); | ||
1585 | goto err_power_off; | 1674 | goto err_power_off; |
1586 | } | 1675 | } |
1587 | 1676 | ||
1588 | if (ath6kl_init_service_ep(ar)) { | 1677 | ret = ath6kl_init_service_ep(ar); |
1589 | ret = -EIO; | 1678 | if (ret) { |
1679 | ath6kl_err("Endpoint service initilisation failed: %d\n", ret); | ||
1590 | goto err_cleanup_scatter; | 1680 | goto err_cleanup_scatter; |
1591 | } | 1681 | } |
1592 | 1682 | ||
@@ -1617,6 +1707,8 @@ static int __ath6kl_init_hw_start(struct ath6kl *ar) | |||
1617 | ar->wiphy->fw_version, | 1707 | ar->wiphy->fw_version, |
1618 | ar->fw_api, | 1708 | ar->fw_api, |
1619 | test_bit(TESTMODE, &ar->flag) ? " testmode" : ""); | 1709 | test_bit(TESTMODE, &ar->flag) ? " testmode" : ""); |
1710 | ath6kl_init_get_fwcaps(ar, buf, sizeof(buf)); | ||
1711 | ath6kl_info("firmware supports: %s\n", buf); | ||
1620 | } | 1712 | } |
1621 | 1713 | ||
1622 | if (ar->version.abi_ver != ATH6KL_ABI_VERSION) { | 1714 | if (ar->version.abi_ver != ATH6KL_ABI_VERSION) { |
@@ -1765,9 +1857,7 @@ void ath6kl_stop_txrx(struct ath6kl *ar) | |||
1765 | * Try to reset the device if we can. The driver may have been | 1857 | * Try to reset the device if we can. The driver may have been |
1766 | * configure NOT to reset the target during a debug session. | 1858 | * configure NOT to reset the target during a debug session. |
1767 | */ | 1859 | */ |
1768 | ath6kl_dbg(ATH6KL_DBG_TRC, | 1860 | ath6kl_init_hw_reset(ar); |
1769 | "attempting to reset target on instance destroy\n"); | ||
1770 | ath6kl_reset_device(ar, ar->target_type, true, true); | ||
1771 | 1861 | ||
1772 | up(&ar->sem); | 1862 | up(&ar->sem); |
1773 | } | 1863 | } |
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index bd50b6b7b492..d4fcfcad57d0 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c | |||
@@ -345,39 +345,6 @@ out: | |||
345 | return ret; | 345 | return ret; |
346 | } | 346 | } |
347 | 347 | ||
348 | /* FIXME: move to a better place, target.h? */ | ||
349 | #define AR6003_RESET_CONTROL_ADDRESS 0x00004000 | ||
350 | #define AR6004_RESET_CONTROL_ADDRESS 0x00004000 | ||
351 | |||
352 | void ath6kl_reset_device(struct ath6kl *ar, u32 target_type, | ||
353 | bool wait_fot_compltn, bool cold_reset) | ||
354 | { | ||
355 | int status = 0; | ||
356 | u32 address; | ||
357 | __le32 data; | ||
358 | |||
359 | if (target_type != TARGET_TYPE_AR6003 && | ||
360 | target_type != TARGET_TYPE_AR6004) | ||
361 | return; | ||
362 | |||
363 | data = cold_reset ? cpu_to_le32(RESET_CONTROL_COLD_RST) : | ||
364 | cpu_to_le32(RESET_CONTROL_MBOX_RST); | ||
365 | |||
366 | switch (target_type) { | ||
367 | case TARGET_TYPE_AR6003: | ||
368 | address = AR6003_RESET_CONTROL_ADDRESS; | ||
369 | break; | ||
370 | case TARGET_TYPE_AR6004: | ||
371 | address = AR6004_RESET_CONTROL_ADDRESS; | ||
372 | break; | ||
373 | } | ||
374 | |||
375 | status = ath6kl_diag_write32(ar, address, data); | ||
376 | |||
377 | if (status) | ||
378 | ath6kl_err("failed to reset target\n"); | ||
379 | } | ||
380 | |||
381 | static void ath6kl_install_static_wep_keys(struct ath6kl_vif *vif) | 348 | static void ath6kl_install_static_wep_keys(struct ath6kl_vif *vif) |
382 | { | 349 | { |
383 | u8 index; | 350 | u8 index; |
@@ -1327,9 +1294,11 @@ void init_netdev(struct net_device *dev) | |||
1327 | dev->watchdog_timeo = ATH6KL_TX_TIMEOUT; | 1294 | dev->watchdog_timeo = ATH6KL_TX_TIMEOUT; |
1328 | 1295 | ||
1329 | dev->needed_headroom = ETH_HLEN; | 1296 | dev->needed_headroom = ETH_HLEN; |
1330 | dev->needed_headroom += sizeof(struct ath6kl_llc_snap_hdr) + | 1297 | dev->needed_headroom += roundup(sizeof(struct ath6kl_llc_snap_hdr) + |
1331 | sizeof(struct wmi_data_hdr) + HTC_HDR_LENGTH | 1298 | sizeof(struct wmi_data_hdr) + |
1332 | + WMI_MAX_TX_META_SZ + ATH6KL_HTC_ALIGN_BYTES; | 1299 | HTC_HDR_LENGTH + |
1300 | WMI_MAX_TX_META_SZ + | ||
1301 | ATH6KL_HTC_ALIGN_BYTES, 4); | ||
1333 | 1302 | ||
1334 | dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM; | 1303 | dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM; |
1335 | 1304 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index d111980d44c0..fb141454c6d2 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "target.h" | 28 | #include "target.h" |
29 | #include "debug.h" | 29 | #include "debug.h" |
30 | #include "cfg80211.h" | 30 | #include "cfg80211.h" |
31 | #include "trace.h" | ||
31 | 32 | ||
32 | struct ath6kl_sdio { | 33 | struct ath6kl_sdio { |
33 | struct sdio_func *func; | 34 | struct sdio_func *func; |
@@ -179,6 +180,8 @@ static int ath6kl_sdio_io(struct sdio_func *func, u32 request, u32 addr, | |||
179 | request & HIF_FIXED_ADDRESS ? " (fixed)" : "", buf, len); | 180 | request & HIF_FIXED_ADDRESS ? " (fixed)" : "", buf, len); |
180 | ath6kl_dbg_dump(ATH6KL_DBG_SDIO_DUMP, NULL, "sdio ", buf, len); | 181 | ath6kl_dbg_dump(ATH6KL_DBG_SDIO_DUMP, NULL, "sdio ", buf, len); |
181 | 182 | ||
183 | trace_ath6kl_sdio(addr, request, buf, len); | ||
184 | |||
182 | return ret; | 185 | return ret; |
183 | } | 186 | } |
184 | 187 | ||
@@ -309,6 +312,13 @@ static int ath6kl_sdio_scat_rw(struct ath6kl_sdio *ar_sdio, | |||
309 | sdio_claim_host(ar_sdio->func); | 312 | sdio_claim_host(ar_sdio->func); |
310 | 313 | ||
311 | mmc_set_data_timeout(&data, ar_sdio->func->card); | 314 | mmc_set_data_timeout(&data, ar_sdio->func->card); |
315 | |||
316 | trace_ath6kl_sdio_scat(scat_req->addr, | ||
317 | scat_req->req, | ||
318 | scat_req->len, | ||
319 | scat_req->scat_entries, | ||
320 | scat_req->scat_list); | ||
321 | |||
312 | /* synchronous call to process request */ | 322 | /* synchronous call to process request */ |
313 | mmc_wait_for_req(ar_sdio->func->card->host, &mmc_req); | 323 | mmc_wait_for_req(ar_sdio->func->card->host, &mmc_req); |
314 | 324 | ||
@@ -1123,10 +1133,12 @@ static int ath6kl_sdio_bmi_write(struct ath6kl *ar, u8 *buf, u32 len) | |||
1123 | 1133 | ||
1124 | ret = ath6kl_sdio_read_write_sync(ar, addr, buf, len, | 1134 | ret = ath6kl_sdio_read_write_sync(ar, addr, buf, len, |
1125 | HIF_WR_SYNC_BYTE_INC); | 1135 | HIF_WR_SYNC_BYTE_INC); |
1126 | if (ret) | 1136 | if (ret) { |
1127 | ath6kl_err("unable to send the bmi data to the device\n"); | 1137 | ath6kl_err("unable to send the bmi data to the device\n"); |
1138 | return ret; | ||
1139 | } | ||
1128 | 1140 | ||
1129 | return ret; | 1141 | return 0; |
1130 | } | 1142 | } |
1131 | 1143 | ||
1132 | static int ath6kl_sdio_bmi_read(struct ath6kl *ar, u8 *buf, u32 len) | 1144 | static int ath6kl_sdio_bmi_read(struct ath6kl *ar, u8 *buf, u32 len) |
diff --git a/drivers/net/wireless/ath/ath6kl/target.h b/drivers/net/wireless/ath/ath6kl/target.h index a98c12ba70c1..a580a629a0da 100644 --- a/drivers/net/wireless/ath/ath6kl/target.h +++ b/drivers/net/wireless/ath/ath6kl/target.h | |||
@@ -25,7 +25,7 @@ | |||
25 | #define AR6004_BOARD_DATA_SZ 6144 | 25 | #define AR6004_BOARD_DATA_SZ 6144 |
26 | #define AR6004_BOARD_EXT_DATA_SZ 0 | 26 | #define AR6004_BOARD_EXT_DATA_SZ 0 |
27 | 27 | ||
28 | #define RESET_CONTROL_ADDRESS 0x00000000 | 28 | #define RESET_CONTROL_ADDRESS 0x00004000 |
29 | #define RESET_CONTROL_COLD_RST 0x00000100 | 29 | #define RESET_CONTROL_COLD_RST 0x00000100 |
30 | #define RESET_CONTROL_MBOX_RST 0x00000004 | 30 | #define RESET_CONTROL_MBOX_RST 0x00000004 |
31 | 31 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/trace.c b/drivers/net/wireless/ath/ath6kl/trace.c new file mode 100644 index 000000000000..e7d64b1285cb --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/trace.c | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | |||
19 | #define CREATE_TRACE_POINTS | ||
20 | #include "trace.h" | ||
21 | |||
22 | EXPORT_TRACEPOINT_SYMBOL(ath6kl_sdio); | ||
23 | EXPORT_TRACEPOINT_SYMBOL(ath6kl_sdio_scat); | ||
diff --git a/drivers/net/wireless/ath/ath6kl/trace.h b/drivers/net/wireless/ath/ath6kl/trace.h new file mode 100644 index 000000000000..6af6fa038312 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/trace.h | |||
@@ -0,0 +1,332 @@ | |||
1 | #if !defined(_ATH6KL_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) | ||
2 | |||
3 | #include <net/cfg80211.h> | ||
4 | #include <linux/skbuff.h> | ||
5 | #include <linux/tracepoint.h> | ||
6 | #include "wmi.h" | ||
7 | #include "hif.h" | ||
8 | |||
9 | #if !defined(_ATH6KL_TRACE_H) | ||
10 | static inline unsigned int ath6kl_get_wmi_id(void *buf, size_t buf_len) | ||
11 | { | ||
12 | struct wmi_cmd_hdr *hdr = buf; | ||
13 | |||
14 | if (buf_len < sizeof(*hdr)) | ||
15 | return 0; | ||
16 | |||
17 | return le16_to_cpu(hdr->cmd_id); | ||
18 | } | ||
19 | #endif /* __ATH6KL_TRACE_H */ | ||
20 | |||
21 | #define _ATH6KL_TRACE_H | ||
22 | |||
23 | /* create empty functions when tracing is disabled */ | ||
24 | #if !defined(CONFIG_ATH6KL_TRACING) | ||
25 | #undef TRACE_EVENT | ||
26 | #define TRACE_EVENT(name, proto, ...) \ | ||
27 | static inline void trace_ ## name(proto) {} | ||
28 | #undef DECLARE_EVENT_CLASS | ||
29 | #define DECLARE_EVENT_CLASS(...) | ||
30 | #undef DEFINE_EVENT | ||
31 | #define DEFINE_EVENT(evt_class, name, proto, ...) \ | ||
32 | static inline void trace_ ## name(proto) {} | ||
33 | #endif /* !CONFIG_ATH6KL_TRACING || __CHECKER__ */ | ||
34 | |||
35 | #undef TRACE_SYSTEM | ||
36 | #define TRACE_SYSTEM ath6kl | ||
37 | |||
38 | TRACE_EVENT(ath6kl_wmi_cmd, | ||
39 | TP_PROTO(void *buf, size_t buf_len), | ||
40 | |||
41 | TP_ARGS(buf, buf_len), | ||
42 | |||
43 | TP_STRUCT__entry( | ||
44 | __field(unsigned int, id) | ||
45 | __field(size_t, buf_len) | ||
46 | __dynamic_array(u8, buf, buf_len) | ||
47 | ), | ||
48 | |||
49 | TP_fast_assign( | ||
50 | __entry->id = ath6kl_get_wmi_id(buf, buf_len); | ||
51 | __entry->buf_len = buf_len; | ||
52 | memcpy(__get_dynamic_array(buf), buf, buf_len); | ||
53 | ), | ||
54 | |||
55 | TP_printk( | ||
56 | "id %d len %d", | ||
57 | __entry->id, __entry->buf_len | ||
58 | ) | ||
59 | ); | ||
60 | |||
61 | TRACE_EVENT(ath6kl_wmi_event, | ||
62 | TP_PROTO(void *buf, size_t buf_len), | ||
63 | |||
64 | TP_ARGS(buf, buf_len), | ||
65 | |||
66 | TP_STRUCT__entry( | ||
67 | __field(unsigned int, id) | ||
68 | __field(size_t, buf_len) | ||
69 | __dynamic_array(u8, buf, buf_len) | ||
70 | ), | ||
71 | |||
72 | TP_fast_assign( | ||
73 | __entry->id = ath6kl_get_wmi_id(buf, buf_len); | ||
74 | __entry->buf_len = buf_len; | ||
75 | memcpy(__get_dynamic_array(buf), buf, buf_len); | ||
76 | ), | ||
77 | |||
78 | TP_printk( | ||
79 | "id %d len %d", | ||
80 | __entry->id, __entry->buf_len | ||
81 | ) | ||
82 | ); | ||
83 | |||
84 | TRACE_EVENT(ath6kl_sdio, | ||
85 | TP_PROTO(unsigned int addr, int flags, | ||
86 | void *buf, size_t buf_len), | ||
87 | |||
88 | TP_ARGS(addr, flags, buf, buf_len), | ||
89 | |||
90 | TP_STRUCT__entry( | ||
91 | __field(unsigned int, tx) | ||
92 | __field(unsigned int, addr) | ||
93 | __field(int, flags) | ||
94 | __field(size_t, buf_len) | ||
95 | __dynamic_array(u8, buf, buf_len) | ||
96 | ), | ||
97 | |||
98 | TP_fast_assign( | ||
99 | __entry->addr = addr; | ||
100 | __entry->flags = flags; | ||
101 | __entry->buf_len = buf_len; | ||
102 | memcpy(__get_dynamic_array(buf), buf, buf_len); | ||
103 | |||
104 | if (flags & HIF_WRITE) | ||
105 | __entry->tx = 1; | ||
106 | else | ||
107 | __entry->tx = 0; | ||
108 | ), | ||
109 | |||
110 | TP_printk( | ||
111 | "%s addr 0x%x flags 0x%x len %d\n", | ||
112 | __entry->tx ? "tx" : "rx", | ||
113 | __entry->addr, | ||
114 | __entry->flags, | ||
115 | __entry->buf_len | ||
116 | ) | ||
117 | ); | ||
118 | |||
119 | TRACE_EVENT(ath6kl_sdio_scat, | ||
120 | TP_PROTO(unsigned int addr, int flags, unsigned int total_len, | ||
121 | unsigned int entries, struct hif_scatter_item *list), | ||
122 | |||
123 | TP_ARGS(addr, flags, total_len, entries, list), | ||
124 | |||
125 | TP_STRUCT__entry( | ||
126 | __field(unsigned int, tx) | ||
127 | __field(unsigned int, addr) | ||
128 | __field(int, flags) | ||
129 | __field(unsigned int, entries) | ||
130 | __field(size_t, total_len) | ||
131 | __dynamic_array(unsigned int, len_array, entries) | ||
132 | __dynamic_array(u8, data, total_len) | ||
133 | ), | ||
134 | |||
135 | TP_fast_assign( | ||
136 | unsigned int *len_array; | ||
137 | int i, offset = 0; | ||
138 | size_t len; | ||
139 | |||
140 | __entry->addr = addr; | ||
141 | __entry->flags = flags; | ||
142 | __entry->entries = entries; | ||
143 | __entry->total_len = total_len; | ||
144 | |||
145 | if (flags & HIF_WRITE) | ||
146 | __entry->tx = 1; | ||
147 | else | ||
148 | __entry->tx = 0; | ||
149 | |||
150 | len_array = __get_dynamic_array(len_array); | ||
151 | |||
152 | for (i = 0; i < entries; i++) { | ||
153 | len = list[i].len; | ||
154 | |||
155 | memcpy((u8 *) __get_dynamic_array(data) + offset, | ||
156 | list[i].buf, len); | ||
157 | |||
158 | len_array[i] = len; | ||
159 | offset += len; | ||
160 | } | ||
161 | ), | ||
162 | |||
163 | TP_printk( | ||
164 | "%s addr 0x%x flags 0x%x entries %d total_len %d\n", | ||
165 | __entry->tx ? "tx" : "rx", | ||
166 | __entry->addr, | ||
167 | __entry->flags, | ||
168 | __entry->entries, | ||
169 | __entry->total_len | ||
170 | ) | ||
171 | ); | ||
172 | |||
173 | TRACE_EVENT(ath6kl_sdio_irq, | ||
174 | TP_PROTO(void *buf, size_t buf_len), | ||
175 | |||
176 | TP_ARGS(buf, buf_len), | ||
177 | |||
178 | TP_STRUCT__entry( | ||
179 | __field(size_t, buf_len) | ||
180 | __dynamic_array(u8, buf, buf_len) | ||
181 | ), | ||
182 | |||
183 | TP_fast_assign( | ||
184 | __entry->buf_len = buf_len; | ||
185 | memcpy(__get_dynamic_array(buf), buf, buf_len); | ||
186 | ), | ||
187 | |||
188 | TP_printk( | ||
189 | "irq len %d\n", __entry->buf_len | ||
190 | ) | ||
191 | ); | ||
192 | |||
193 | TRACE_EVENT(ath6kl_htc_rx, | ||
194 | TP_PROTO(int status, int endpoint, void *buf, | ||
195 | size_t buf_len), | ||
196 | |||
197 | TP_ARGS(status, endpoint, buf, buf_len), | ||
198 | |||
199 | TP_STRUCT__entry( | ||
200 | __field(int, status) | ||
201 | __field(int, endpoint) | ||
202 | __field(size_t, buf_len) | ||
203 | __dynamic_array(u8, buf, buf_len) | ||
204 | ), | ||
205 | |||
206 | TP_fast_assign( | ||
207 | __entry->status = status; | ||
208 | __entry->endpoint = endpoint; | ||
209 | __entry->buf_len = buf_len; | ||
210 | memcpy(__get_dynamic_array(buf), buf, buf_len); | ||
211 | ), | ||
212 | |||
213 | TP_printk( | ||
214 | "status %d endpoint %d len %d\n", | ||
215 | __entry->status, | ||
216 | __entry->endpoint, | ||
217 | __entry->buf_len | ||
218 | ) | ||
219 | ); | ||
220 | |||
221 | TRACE_EVENT(ath6kl_htc_tx, | ||
222 | TP_PROTO(int status, int endpoint, void *buf, | ||
223 | size_t buf_len), | ||
224 | |||
225 | TP_ARGS(status, endpoint, buf, buf_len), | ||
226 | |||
227 | TP_STRUCT__entry( | ||
228 | __field(int, status) | ||
229 | __field(int, endpoint) | ||
230 | __field(size_t, buf_len) | ||
231 | __dynamic_array(u8, buf, buf_len) | ||
232 | ), | ||
233 | |||
234 | TP_fast_assign( | ||
235 | __entry->status = status; | ||
236 | __entry->endpoint = endpoint; | ||
237 | __entry->buf_len = buf_len; | ||
238 | memcpy(__get_dynamic_array(buf), buf, buf_len); | ||
239 | ), | ||
240 | |||
241 | TP_printk( | ||
242 | "status %d endpoint %d len %d\n", | ||
243 | __entry->status, | ||
244 | __entry->endpoint, | ||
245 | __entry->buf_len | ||
246 | ) | ||
247 | ); | ||
248 | |||
249 | #define ATH6KL_MSG_MAX 200 | ||
250 | |||
251 | DECLARE_EVENT_CLASS(ath6kl_log_event, | ||
252 | TP_PROTO(struct va_format *vaf), | ||
253 | TP_ARGS(vaf), | ||
254 | TP_STRUCT__entry( | ||
255 | __dynamic_array(char, msg, ATH6KL_MSG_MAX) | ||
256 | ), | ||
257 | TP_fast_assign( | ||
258 | WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg), | ||
259 | ATH6KL_MSG_MAX, | ||
260 | vaf->fmt, | ||
261 | *vaf->va) >= ATH6KL_MSG_MAX); | ||
262 | ), | ||
263 | TP_printk("%s", __get_str(msg)) | ||
264 | ); | ||
265 | |||
266 | DEFINE_EVENT(ath6kl_log_event, ath6kl_log_err, | ||
267 | TP_PROTO(struct va_format *vaf), | ||
268 | TP_ARGS(vaf) | ||
269 | ); | ||
270 | |||
271 | DEFINE_EVENT(ath6kl_log_event, ath6kl_log_warn, | ||
272 | TP_PROTO(struct va_format *vaf), | ||
273 | TP_ARGS(vaf) | ||
274 | ); | ||
275 | |||
276 | DEFINE_EVENT(ath6kl_log_event, ath6kl_log_info, | ||
277 | TP_PROTO(struct va_format *vaf), | ||
278 | TP_ARGS(vaf) | ||
279 | ); | ||
280 | |||
281 | TRACE_EVENT(ath6kl_log_dbg, | ||
282 | TP_PROTO(unsigned int level, struct va_format *vaf), | ||
283 | TP_ARGS(level, vaf), | ||
284 | TP_STRUCT__entry( | ||
285 | __field(unsigned int, level) | ||
286 | __dynamic_array(char, msg, ATH6KL_MSG_MAX) | ||
287 | ), | ||
288 | TP_fast_assign( | ||
289 | __entry->level = level; | ||
290 | WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg), | ||
291 | ATH6KL_MSG_MAX, | ||
292 | vaf->fmt, | ||
293 | *vaf->va) >= ATH6KL_MSG_MAX); | ||
294 | ), | ||
295 | TP_printk("%s", __get_str(msg)) | ||
296 | ); | ||
297 | |||
298 | TRACE_EVENT(ath6kl_log_dbg_dump, | ||
299 | TP_PROTO(const char *msg, const char *prefix, | ||
300 | const void *buf, size_t buf_len), | ||
301 | |||
302 | TP_ARGS(msg, prefix, buf, buf_len), | ||
303 | |||
304 | TP_STRUCT__entry( | ||
305 | __string(msg, msg) | ||
306 | __string(prefix, prefix) | ||
307 | __field(size_t, buf_len) | ||
308 | __dynamic_array(u8, buf, buf_len) | ||
309 | ), | ||
310 | |||
311 | TP_fast_assign( | ||
312 | __assign_str(msg, msg); | ||
313 | __assign_str(prefix, prefix); | ||
314 | __entry->buf_len = buf_len; | ||
315 | memcpy(__get_dynamic_array(buf), buf, buf_len); | ||
316 | ), | ||
317 | |||
318 | TP_printk( | ||
319 | "%s/%s\n", __get_str(prefix), __get_str(msg) | ||
320 | ) | ||
321 | ); | ||
322 | |||
323 | #endif /* _ ATH6KL_TRACE_H || TRACE_HEADER_MULTI_READ*/ | ||
324 | |||
325 | /* we don't want to use include/trace/events */ | ||
326 | #undef TRACE_INCLUDE_PATH | ||
327 | #define TRACE_INCLUDE_PATH . | ||
328 | #undef TRACE_INCLUDE_FILE | ||
329 | #define TRACE_INCLUDE_FILE trace | ||
330 | |||
331 | /* This part must be outside protection */ | ||
332 | #include <trace/define_trace.h> | ||
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index 78b369286579..ebb24045a8ae 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include "core.h" | 20 | #include "core.h" |
21 | #include "debug.h" | 21 | #include "debug.h" |
22 | #include "htc-ops.h" | 22 | #include "htc-ops.h" |
23 | #include "trace.h" | ||
23 | 24 | ||
24 | /* | 25 | /* |
25 | * tid - tid_mux0..tid_mux3 | 26 | * tid - tid_mux0..tid_mux3 |
@@ -288,6 +289,8 @@ int ath6kl_control_tx(void *devt, struct sk_buff *skb, | |||
288 | int status = 0; | 289 | int status = 0; |
289 | struct ath6kl_cookie *cookie = NULL; | 290 | struct ath6kl_cookie *cookie = NULL; |
290 | 291 | ||
292 | trace_ath6kl_wmi_cmd(skb->data, skb->len); | ||
293 | |||
291 | if (WARN_ON_ONCE(ar->state == ATH6KL_STATE_WOW)) { | 294 | if (WARN_ON_ONCE(ar->state == ATH6KL_STATE_WOW)) { |
292 | dev_kfree_skb(skb); | 295 | dev_kfree_skb(skb); |
293 | return -EACCES; | 296 | return -EACCES; |
@@ -1324,7 +1327,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) | |||
1324 | __func__, ar, ept, skb, packet->buf, | 1327 | __func__, ar, ept, skb, packet->buf, |
1325 | packet->act_len, status); | 1328 | packet->act_len, status); |
1326 | 1329 | ||
1327 | if (status || !(skb->data + HTC_HDR_LENGTH)) { | 1330 | if (status || packet->act_len < HTC_HDR_LENGTH) { |
1328 | dev_kfree_skb(skb); | 1331 | dev_kfree_skb(skb); |
1329 | return; | 1332 | return; |
1330 | } | 1333 | } |
diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c index 5fcd342762de..bed0d337712d 100644 --- a/drivers/net/wireless/ath/ath6kl/usb.c +++ b/drivers/net/wireless/ath/ath6kl/usb.c | |||
@@ -856,11 +856,9 @@ static int ath6kl_usb_submit_ctrl_out(struct ath6kl_usb *ar_usb, | |||
856 | int ret; | 856 | int ret; |
857 | 857 | ||
858 | if (size > 0) { | 858 | if (size > 0) { |
859 | buf = kmalloc(size, GFP_KERNEL); | 859 | buf = kmemdup(data, size, GFP_KERNEL); |
860 | if (buf == NULL) | 860 | if (buf == NULL) |
861 | return -ENOMEM; | 861 | return -ENOMEM; |
862 | |||
863 | memcpy(buf, data, size); | ||
864 | } | 862 | } |
865 | 863 | ||
866 | /* note: if successful returns number of bytes transfered */ | 864 | /* note: if successful returns number of bytes transfered */ |
@@ -872,8 +870,9 @@ static int ath6kl_usb_submit_ctrl_out(struct ath6kl_usb *ar_usb, | |||
872 | size, 1000); | 870 | size, 1000); |
873 | 871 | ||
874 | if (ret < 0) { | 872 | if (ret < 0) { |
875 | ath6kl_dbg(ATH6KL_DBG_USB, "%s failed,result = %d\n", | 873 | ath6kl_warn("Failed to submit usb control message: %d\n", ret); |
876 | __func__, ret); | 874 | kfree(buf); |
875 | return ret; | ||
877 | } | 876 | } |
878 | 877 | ||
879 | kfree(buf); | 878 | kfree(buf); |
@@ -903,8 +902,9 @@ static int ath6kl_usb_submit_ctrl_in(struct ath6kl_usb *ar_usb, | |||
903 | size, 2 * HZ); | 902 | size, 2 * HZ); |
904 | 903 | ||
905 | if (ret < 0) { | 904 | if (ret < 0) { |
906 | ath6kl_dbg(ATH6KL_DBG_USB, "%s failed,result = %d\n", | 905 | ath6kl_warn("Failed to read usb control message: %d\n", ret); |
907 | __func__, ret); | 906 | kfree(buf); |
907 | return ret; | ||
908 | } | 908 | } |
909 | 909 | ||
910 | memcpy((u8 *) data, buf, size); | 910 | memcpy((u8 *) data, buf, size); |
@@ -961,8 +961,10 @@ static int ath6kl_usb_diag_read32(struct ath6kl *ar, u32 address, u32 *data) | |||
961 | ATH6KL_USB_CONTROL_REQ_DIAG_RESP, | 961 | ATH6KL_USB_CONTROL_REQ_DIAG_RESP, |
962 | ar_usb->diag_resp_buffer, &resp_len); | 962 | ar_usb->diag_resp_buffer, &resp_len); |
963 | 963 | ||
964 | if (ret) | 964 | if (ret) { |
965 | ath6kl_warn("diag read32 failed: %d\n", ret); | ||
965 | return ret; | 966 | return ret; |
967 | } | ||
966 | 968 | ||
967 | resp = (struct ath6kl_usb_ctrl_diag_resp_read *) | 969 | resp = (struct ath6kl_usb_ctrl_diag_resp_read *) |
968 | ar_usb->diag_resp_buffer; | 970 | ar_usb->diag_resp_buffer; |
@@ -976,6 +978,7 @@ static int ath6kl_usb_diag_write32(struct ath6kl *ar, u32 address, __le32 data) | |||
976 | { | 978 | { |
977 | struct ath6kl_usb *ar_usb = ar->hif_priv; | 979 | struct ath6kl_usb *ar_usb = ar->hif_priv; |
978 | struct ath6kl_usb_ctrl_diag_cmd_write *cmd; | 980 | struct ath6kl_usb_ctrl_diag_cmd_write *cmd; |
981 | int ret; | ||
979 | 982 | ||
980 | cmd = (struct ath6kl_usb_ctrl_diag_cmd_write *) ar_usb->diag_cmd_buffer; | 983 | cmd = (struct ath6kl_usb_ctrl_diag_cmd_write *) ar_usb->diag_cmd_buffer; |
981 | 984 | ||
@@ -984,12 +987,17 @@ static int ath6kl_usb_diag_write32(struct ath6kl *ar, u32 address, __le32 data) | |||
984 | cmd->address = cpu_to_le32(address); | 987 | cmd->address = cpu_to_le32(address); |
985 | cmd->value = data; | 988 | cmd->value = data; |
986 | 989 | ||
987 | return ath6kl_usb_ctrl_msg_exchange(ar_usb, | 990 | ret = ath6kl_usb_ctrl_msg_exchange(ar_usb, |
988 | ATH6KL_USB_CONTROL_REQ_DIAG_CMD, | 991 | ATH6KL_USB_CONTROL_REQ_DIAG_CMD, |
989 | (u8 *) cmd, | 992 | (u8 *) cmd, |
990 | sizeof(*cmd), | 993 | sizeof(*cmd), |
991 | 0, NULL, NULL); | 994 | 0, NULL, NULL); |
995 | if (ret) { | ||
996 | ath6kl_warn("diag_write32 failed: %d\n", ret); | ||
997 | return ret; | ||
998 | } | ||
992 | 999 | ||
1000 | return 0; | ||
993 | } | 1001 | } |
994 | 1002 | ||
995 | static int ath6kl_usb_bmi_read(struct ath6kl *ar, u8 *buf, u32 len) | 1003 | static int ath6kl_usb_bmi_read(struct ath6kl *ar, u8 *buf, u32 len) |
@@ -1001,7 +1009,7 @@ static int ath6kl_usb_bmi_read(struct ath6kl *ar, u8 *buf, u32 len) | |||
1001 | ret = ath6kl_usb_submit_ctrl_in(ar_usb, | 1009 | ret = ath6kl_usb_submit_ctrl_in(ar_usb, |
1002 | ATH6KL_USB_CONTROL_REQ_RECV_BMI_RESP, | 1010 | ATH6KL_USB_CONTROL_REQ_RECV_BMI_RESP, |
1003 | 0, 0, buf, len); | 1011 | 0, 0, buf, len); |
1004 | if (ret != 0) { | 1012 | if (ret) { |
1005 | ath6kl_err("Unable to read the bmi data from the device: %d\n", | 1013 | ath6kl_err("Unable to read the bmi data from the device: %d\n", |
1006 | ret); | 1014 | ret); |
1007 | return ret; | 1015 | return ret; |
@@ -1019,7 +1027,7 @@ static int ath6kl_usb_bmi_write(struct ath6kl *ar, u8 *buf, u32 len) | |||
1019 | ret = ath6kl_usb_submit_ctrl_out(ar_usb, | 1027 | ret = ath6kl_usb_submit_ctrl_out(ar_usb, |
1020 | ATH6KL_USB_CONTROL_REQ_SEND_BMI_CMD, | 1028 | ATH6KL_USB_CONTROL_REQ_SEND_BMI_CMD, |
1021 | 0, 0, buf, len); | 1029 | 0, 0, buf, len); |
1022 | if (ret != 0) { | 1030 | if (ret) { |
1023 | ath6kl_err("unable to send the bmi data to the device: %d\n", | 1031 | ath6kl_err("unable to send the bmi data to the device: %d\n", |
1024 | ret); | 1032 | ret); |
1025 | return ret; | 1033 | return ret; |
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index d76b5bd81a0d..87aefb4c4c23 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include "core.h" | 20 | #include "core.h" |
21 | #include "debug.h" | 21 | #include "debug.h" |
22 | #include "testmode.h" | 22 | #include "testmode.h" |
23 | #include "trace.h" | ||
23 | #include "../regd.h" | 24 | #include "../regd.h" |
24 | #include "../regd_common.h" | 25 | #include "../regd_common.h" |
25 | 26 | ||
@@ -2028,6 +2029,9 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx, | |||
2028 | if (!sband) | 2029 | if (!sband) |
2029 | continue; | 2030 | continue; |
2030 | 2031 | ||
2032 | if (WARN_ON(band >= ATH6KL_NUM_BANDS)) | ||
2033 | break; | ||
2034 | |||
2031 | ratemask = rates[band]; | 2035 | ratemask = rates[band]; |
2032 | supp_rates = sc->supp_rates[band].rates; | 2036 | supp_rates = sc->supp_rates[band].rates; |
2033 | num_rates = 0; | 2037 | num_rates = 0; |
@@ -4086,6 +4090,8 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb) | |||
4086 | return -EINVAL; | 4090 | return -EINVAL; |
4087 | } | 4091 | } |
4088 | 4092 | ||
4093 | trace_ath6kl_wmi_event(skb->data, skb->len); | ||
4094 | |||
4089 | return ath6kl_wmi_proc_events(wmi, skb); | 4095 | return ath6kl_wmi_proc_events(wmi, skb); |
4090 | } | 4096 | } |
4091 | 4097 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 881e989ea470..e6b92ff265fd 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -3606,6 +3606,12 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) | |||
3606 | value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz); | 3606 | value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz); |
3607 | REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value); | 3607 | REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value); |
3608 | 3608 | ||
3609 | if ((AR_SREV_9462(ah)) && (ah->rxchainmask == 0x2)) { | ||
3610 | value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz); | ||
3611 | REG_RMW_FIELD(ah, switch_chain_reg[0], | ||
3612 | AR_SWITCH_TABLE_ALL, value); | ||
3613 | } | ||
3614 | |||
3609 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { | 3615 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { |
3610 | if ((ah->rxchainmask & BIT(chain)) || | 3616 | if ((ah->rxchainmask & BIT(chain)) || |
3611 | (ah->txchainmask & BIT(chain))) { | 3617 | (ah->txchainmask & BIT(chain))) { |
@@ -3772,6 +3778,17 @@ static void ar9003_hw_atten_apply(struct ath_hw *ah, struct ath9k_channel *chan) | |||
3772 | AR_PHY_EXT_ATTEN_CTL_2, | 3778 | AR_PHY_EXT_ATTEN_CTL_2, |
3773 | }; | 3779 | }; |
3774 | 3780 | ||
3781 | if ((AR_SREV_9462(ah)) && (ah->rxchainmask == 0x2)) { | ||
3782 | value = ar9003_hw_atten_chain_get(ah, 1, chan); | ||
3783 | REG_RMW_FIELD(ah, ext_atten_reg[0], | ||
3784 | AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value); | ||
3785 | |||
3786 | value = ar9003_hw_atten_chain_get_margin(ah, 1, chan); | ||
3787 | REG_RMW_FIELD(ah, ext_atten_reg[0], | ||
3788 | AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, | ||
3789 | value); | ||
3790 | } | ||
3791 | |||
3775 | /* Test value. if 0 then attenuation is unused. Don't load anything. */ | 3792 | /* Test value. if 0 then attenuation is unused. Don't load anything. */ |
3776 | for (i = 0; i < 3; i++) { | 3793 | for (i = 0; i < 3; i++) { |
3777 | if (ah->txchainmask & BIT(i)) { | 3794 | if (ah->txchainmask & BIT(i)) { |
diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h index ccc42a71b436..999ab08c34e6 100644 --- a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h | |||
@@ -37,28 +37,28 @@ static const u32 ar9462_pciephy_clkreq_enable_L1_2p0[][2] = { | |||
37 | /* Addr allmodes */ | 37 | /* Addr allmodes */ |
38 | {0x00018c00, 0x18253ede}, | 38 | {0x00018c00, 0x18253ede}, |
39 | {0x00018c04, 0x000801d8}, | 39 | {0x00018c04, 0x000801d8}, |
40 | {0x00018c08, 0x0003580c}, | 40 | {0x00018c08, 0x0003780c}, |
41 | }; | 41 | }; |
42 | 42 | ||
43 | static const u32 ar9462_2p0_baseband_postamble[][5] = { | 43 | static const u32 ar9462_2p0_baseband_postamble[][5] = { |
44 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 44 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
45 | {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a800d}, | 45 | {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a800d}, |
46 | {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a01ae}, | 46 | {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a01ae}, |
47 | {0x00009824, 0x5ac640de, 0x5ac640d0, 0x5ac640d0, 0x63c640da}, | 47 | {0x00009824, 0x63c640de, 0x5ac640d0, 0x5ac640d0, 0x63c640da}, |
48 | {0x00009828, 0x0796be89, 0x0696b081, 0x0696b881, 0x09143e81}, | 48 | {0x00009828, 0x0796be89, 0x0696b081, 0x0696b881, 0x09143e81}, |
49 | {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, | 49 | {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, |
50 | {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, | 50 | {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, |
51 | {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, | 51 | {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, |
52 | {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0}, | 52 | {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a2}, |
53 | {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020}, | 53 | {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020}, |
54 | {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000d8}, | 54 | {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000d8}, |
55 | {0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec86d2e}, | 55 | {0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec86d2e}, |
56 | {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3376605e, 0x32395d5e}, | 56 | {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3236605e, 0x32365a5e}, |
57 | {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 57 | {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
58 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, | 58 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, |
59 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, | 59 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, |
60 | {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, | 60 | {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, |
61 | {0x00009e3c, 0xcf946222, 0xcf946222, 0xcfd5c782, 0xcfd5c282}, | 61 | {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282}, |
62 | {0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27}, | 62 | {0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27}, |
63 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, | 63 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, |
64 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, | 64 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, |
@@ -82,9 +82,9 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = { | |||
82 | {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982}, | 82 | {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982}, |
83 | {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, | 83 | {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, |
84 | {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 84 | {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
85 | {0x0000a3a4, 0x00000010, 0x00000010, 0x00000000, 0x00000000}, | 85 | {0x0000a3a4, 0x00000050, 0x00000050, 0x00000000, 0x00000000}, |
86 | {0x0000a3a8, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa}, | 86 | {0x0000a3a8, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa}, |
87 | {0x0000a3ac, 0xaaaaaa00, 0xaaaaaa30, 0xaaaaaa00, 0xaaaaaa00}, | 87 | {0x0000a3ac, 0xaaaaaa00, 0xaa30aa30, 0xaaaaaa00, 0xaaaaaa00}, |
88 | {0x0000a41c, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce}, | 88 | {0x0000a41c, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce}, |
89 | {0x0000a420, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce}, | 89 | {0x0000a420, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce}, |
90 | {0x0000a424, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce}, | 90 | {0x0000a424, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce}, |
@@ -363,14 +363,14 @@ static const u32 ar9462_pciephy_clkreq_disable_L1_2p0[][2] = { | |||
363 | /* Addr allmodes */ | 363 | /* Addr allmodes */ |
364 | {0x00018c00, 0x18213ede}, | 364 | {0x00018c00, 0x18213ede}, |
365 | {0x00018c04, 0x000801d8}, | 365 | {0x00018c04, 0x000801d8}, |
366 | {0x00018c08, 0x0003580c}, | 366 | {0x00018c08, 0x0003780c}, |
367 | }; | 367 | }; |
368 | 368 | ||
369 | static const u32 ar9462_pciephy_pll_on_clkreq_disable_L1_2p0[][2] = { | 369 | static const u32 ar9462_pciephy_pll_on_clkreq_disable_L1_2p0[][2] = { |
370 | /* Addr allmodes */ | 370 | /* Addr allmodes */ |
371 | {0x00018c00, 0x18212ede}, | 371 | {0x00018c00, 0x18212ede}, |
372 | {0x00018c04, 0x000801d8}, | 372 | {0x00018c04, 0x000801d8}, |
373 | {0x00018c08, 0x0003580c}, | 373 | {0x00018c08, 0x0003780c}, |
374 | }; | 374 | }; |
375 | 375 | ||
376 | static const u32 ar9462_2p0_radio_postamble_sys2ant[][5] = { | 376 | static const u32 ar9462_2p0_radio_postamble_sys2ant[][5] = { |
@@ -775,7 +775,7 @@ static const u32 ar9462_2p0_baseband_core[][2] = { | |||
775 | {0x00009fc0, 0x803e4788}, | 775 | {0x00009fc0, 0x803e4788}, |
776 | {0x00009fc4, 0x0001efb5}, | 776 | {0x00009fc4, 0x0001efb5}, |
777 | {0x00009fcc, 0x40000014}, | 777 | {0x00009fcc, 0x40000014}, |
778 | {0x00009fd0, 0x01193b93}, | 778 | {0x00009fd0, 0x0a193b93}, |
779 | {0x0000a20c, 0x00000000}, | 779 | {0x0000a20c, 0x00000000}, |
780 | {0x0000a220, 0x00000000}, | 780 | {0x0000a220, 0x00000000}, |
781 | {0x0000a224, 0x00000000}, | 781 | {0x0000a224, 0x00000000}, |
@@ -850,7 +850,7 @@ static const u32 ar9462_2p0_baseband_core[][2] = { | |||
850 | {0x0000a7cc, 0x00000000}, | 850 | {0x0000a7cc, 0x00000000}, |
851 | {0x0000a7d0, 0x00000000}, | 851 | {0x0000a7d0, 0x00000000}, |
852 | {0x0000a7d4, 0x00000004}, | 852 | {0x0000a7d4, 0x00000004}, |
853 | {0x0000a7dc, 0x00000001}, | 853 | {0x0000a7dc, 0x00000000}, |
854 | {0x0000a7f0, 0x80000000}, | 854 | {0x0000a7f0, 0x80000000}, |
855 | {0x0000a8d0, 0x004b6a8e}, | 855 | {0x0000a8d0, 0x004b6a8e}, |
856 | {0x0000a8d4, 0x00000820}, | 856 | {0x0000a8d4, 0x00000820}, |
@@ -886,7 +886,7 @@ static const u32 ar9462_modes_high_ob_db_tx_gain_table_2p0[][5] = { | |||
886 | {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, | 886 | {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, |
887 | {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, | 887 | {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, |
888 | {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | 888 | {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, |
889 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | 889 | {0x0000a410, 0x000050da, 0x000050da, 0x000050de, 0x000050de}, |
890 | {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 890 | {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
891 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, | 891 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, |
892 | {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, | 892 | {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, |
@@ -906,20 +906,20 @@ static const u32 ar9462_modes_high_ob_db_tx_gain_table_2p0[][5] = { | |||
906 | {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640}, | 906 | {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640}, |
907 | {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660}, | 907 | {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660}, |
908 | {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861}, | 908 | {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861}, |
909 | {0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81}, | 909 | {0x0000a548, 0x55025eb3, 0x55025eb3, 0x3e001a81, 0x3e001a81}, |
910 | {0x0000a54c, 0x59025eb6, 0x59025eb6, 0x42001a83, 0x42001a83}, | 910 | {0x0000a54c, 0x58025ef3, 0x58025ef3, 0x42001a83, 0x42001a83}, |
911 | {0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x44001c84, 0x44001c84}, | 911 | {0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x44001a84, 0x44001a84}, |
912 | {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3}, | 912 | {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3}, |
913 | {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5}, | 913 | {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5}, |
914 | {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9}, | 914 | {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9}, |
915 | {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb}, | 915 | {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb}, |
916 | {0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 916 | {0x0000a564, 0x751ffff6, 0x751ffff6, 0x56001eec, 0x56001eec}, |
917 | {0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 917 | {0x0000a568, 0x751ffff6, 0x751ffff6, 0x58001ef0, 0x58001ef0}, |
918 | {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 918 | {0x0000a56c, 0x751ffff6, 0x751ffff6, 0x5a001ef4, 0x5a001ef4}, |
919 | {0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 919 | {0x0000a570, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6}, |
920 | {0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 920 | {0x0000a574, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6}, |
921 | {0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 921 | {0x0000a578, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6}, |
922 | {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 922 | {0x0000a57c, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6}, |
923 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 923 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
924 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 924 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
925 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 925 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
@@ -1053,7 +1053,6 @@ static const u32 ar9462_2p0_mac_core[][2] = { | |||
1053 | {0x00008044, 0x00000000}, | 1053 | {0x00008044, 0x00000000}, |
1054 | {0x00008048, 0x00000000}, | 1054 | {0x00008048, 0x00000000}, |
1055 | {0x0000804c, 0xffffffff}, | 1055 | {0x0000804c, 0xffffffff}, |
1056 | {0x00008050, 0xffffffff}, | ||
1057 | {0x00008054, 0x00000000}, | 1056 | {0x00008054, 0x00000000}, |
1058 | {0x00008058, 0x00000000}, | 1057 | {0x00008058, 0x00000000}, |
1059 | {0x0000805c, 0x000fc78f}, | 1058 | {0x0000805c, 0x000fc78f}, |
@@ -1117,9 +1116,9 @@ static const u32 ar9462_2p0_mac_core[][2] = { | |||
1117 | {0x000081f8, 0x00000000}, | 1116 | {0x000081f8, 0x00000000}, |
1118 | {0x000081fc, 0x00000000}, | 1117 | {0x000081fc, 0x00000000}, |
1119 | {0x00008240, 0x00100000}, | 1118 | {0x00008240, 0x00100000}, |
1120 | {0x00008244, 0x0010f424}, | 1119 | {0x00008244, 0x0010f400}, |
1121 | {0x00008248, 0x00000800}, | 1120 | {0x00008248, 0x00000800}, |
1122 | {0x0000824c, 0x0001e848}, | 1121 | {0x0000824c, 0x0001e800}, |
1123 | {0x00008250, 0x00000000}, | 1122 | {0x00008250, 0x00000000}, |
1124 | {0x00008254, 0x00000000}, | 1123 | {0x00008254, 0x00000000}, |
1125 | {0x00008258, 0x00000000}, | 1124 | {0x00008258, 0x00000000}, |
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 1e8508530e98..7bdd726c7a8f 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
@@ -369,7 +369,6 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
369 | struct ieee80211_channel *c = chan->chan; | 369 | struct ieee80211_channel *c = chan->chan; |
370 | struct ath9k_hw_cal_data *caldata = ah->caldata; | 370 | struct ath9k_hw_cal_data *caldata = ah->caldata; |
371 | 371 | ||
372 | chan->channelFlags &= (~CHANNEL_CW_INT); | ||
373 | if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { | 372 | if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { |
374 | ath_dbg(common, CALIBRATE, | 373 | ath_dbg(common, CALIBRATE, |
375 | "NF did not complete in calibration window\n"); | 374 | "NF did not complete in calibration window\n"); |
@@ -384,7 +383,6 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
384 | ath_dbg(common, CALIBRATE, | 383 | ath_dbg(common, CALIBRATE, |
385 | "noise floor failed detected; detected %d, threshold %d\n", | 384 | "noise floor failed detected; detected %d, threshold %d\n", |
386 | nf, nfThresh); | 385 | nf, nfThresh); |
387 | chan->channelFlags |= CHANNEL_CW_INT; | ||
388 | } | 386 | } |
389 | 387 | ||
390 | if (!caldata) { | 388 | if (!caldata) { |
@@ -410,7 +408,7 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, | |||
410 | int i, j; | 408 | int i, j; |
411 | 409 | ||
412 | ah->caldata->channel = chan->channel; | 410 | ah->caldata->channel = chan->channel; |
413 | ah->caldata->channelFlags = chan->channelFlags & ~CHANNEL_CW_INT; | 411 | ah->caldata->channelFlags = chan->channelFlags; |
414 | ah->caldata->chanmode = chan->chanmode; | 412 | ah->caldata->chanmode = chan->chanmode; |
415 | h = ah->caldata->nfCalHist; | 413 | h = ah->caldata->nfCalHist; |
416 | default_nf = ath9k_hw_get_default_nf(ah, chan); | 414 | default_nf = ath9k_hw_get_default_nf(ah, chan); |
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index 5f845beeb18b..6102476a65de 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h | |||
@@ -27,7 +27,7 @@ | |||
27 | #define WME_MAX_BA WME_BA_BMP_SIZE | 27 | #define WME_MAX_BA WME_BA_BMP_SIZE |
28 | #define ATH_TID_MAX_BUFS (2 * WME_MAX_BA) | 28 | #define ATH_TID_MAX_BUFS (2 * WME_MAX_BA) |
29 | 29 | ||
30 | #define ATH_RSSI_DUMMY_MARKER 0x127 | 30 | #define ATH_RSSI_DUMMY_MARKER 127 |
31 | #define ATH_RSSI_LPF_LEN 10 | 31 | #define ATH_RSSI_LPF_LEN 10 |
32 | #define RSSI_LPF_THRESHOLD -20 | 32 | #define RSSI_LPF_THRESHOLD -20 |
33 | #define ATH_RSSI_EP_MULTIPLIER (1<<7) | 33 | #define ATH_RSSI_EP_MULTIPLIER (1<<7) |
@@ -40,7 +40,7 @@ | |||
40 | x = ATH_LPF_RSSI((x), ATH_RSSI_IN((y)), ATH_RSSI_LPF_LEN); \ | 40 | x = ATH_LPF_RSSI((x), ATH_RSSI_IN((y)), ATH_RSSI_LPF_LEN); \ |
41 | } while (0) | 41 | } while (0) |
42 | #define ATH_EP_RND(x, mul) \ | 42 | #define ATH_EP_RND(x, mul) \ |
43 | ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) | 43 | (((x) + ((mul)/2)) / (mul)) |
44 | 44 | ||
45 | int ath9k_cmn_padpos(__le16 frame_control); | 45 | int ath9k_cmn_padpos(__le16 frame_control); |
46 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); | 46 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 3714b971d18e..67a2a4b3b883 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -537,6 +537,7 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | |||
537 | PR("AMPDUs Completed:", a_completed); | 537 | PR("AMPDUs Completed:", a_completed); |
538 | PR("AMPDUs Retried: ", a_retries); | 538 | PR("AMPDUs Retried: ", a_retries); |
539 | PR("AMPDUs XRetried: ", a_xretries); | 539 | PR("AMPDUs XRetried: ", a_xretries); |
540 | PR("TXERR Filtered: ", txerr_filtered); | ||
540 | PR("FIFO Underrun: ", fifo_underrun); | 541 | PR("FIFO Underrun: ", fifo_underrun); |
541 | PR("TXOP Exceeded: ", xtxop); | 542 | PR("TXOP Exceeded: ", xtxop); |
542 | PR("TXTIMER Expiry: ", timer_exp); | 543 | PR("TXTIMER Expiry: ", timer_exp); |
@@ -756,6 +757,8 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, | |||
756 | TX_STAT_INC(qnum, completed); | 757 | TX_STAT_INC(qnum, completed); |
757 | } | 758 | } |
758 | 759 | ||
760 | if (ts->ts_status & ATH9K_TXERR_FILT) | ||
761 | TX_STAT_INC(qnum, txerr_filtered); | ||
759 | if (ts->ts_status & ATH9K_TXERR_FIFO) | 762 | if (ts->ts_status & ATH9K_TXERR_FIFO) |
760 | TX_STAT_INC(qnum, fifo_underrun); | 763 | TX_STAT_INC(qnum, fifo_underrun); |
761 | if (ts->ts_status & ATH9K_TXERR_XTXOP) | 764 | if (ts->ts_status & ATH9K_TXERR_XTXOP) |
@@ -1909,6 +1912,7 @@ static const char ath9k_gstrings_stats[][ETH_GSTRING_LEN] = { | |||
1909 | AMKSTR(d_tx_desc_cfg_err), | 1912 | AMKSTR(d_tx_desc_cfg_err), |
1910 | AMKSTR(d_tx_data_underrun), | 1913 | AMKSTR(d_tx_data_underrun), |
1911 | AMKSTR(d_tx_delim_underrun), | 1914 | AMKSTR(d_tx_delim_underrun), |
1915 | "d_rx_crc_err", | ||
1912 | "d_rx_decrypt_crc_err", | 1916 | "d_rx_decrypt_crc_err", |
1913 | "d_rx_phy_err", | 1917 | "d_rx_phy_err", |
1914 | "d_rx_mic_err", | 1918 | "d_rx_mic_err", |
@@ -1989,6 +1993,7 @@ void ath9k_get_et_stats(struct ieee80211_hw *hw, | |||
1989 | AWDATA(data_underrun); | 1993 | AWDATA(data_underrun); |
1990 | AWDATA(delim_underrun); | 1994 | AWDATA(delim_underrun); |
1991 | 1995 | ||
1996 | AWDATA_RX(crc_err); | ||
1992 | AWDATA_RX(decrypt_crc_err); | 1997 | AWDATA_RX(decrypt_crc_err); |
1993 | AWDATA_RX(phy_err); | 1998 | AWDATA_RX(phy_err); |
1994 | AWDATA_RX(mic_err); | 1999 | AWDATA_RX(mic_err); |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 410d6d8f1aa7..794a7ec83a24 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -142,6 +142,7 @@ struct ath_interrupt_stats { | |||
142 | * @a_completed: Total AMPDUs completed | 142 | * @a_completed: Total AMPDUs completed |
143 | * @a_retries: No. of AMPDUs retried (SW) | 143 | * @a_retries: No. of AMPDUs retried (SW) |
144 | * @a_xretries: No. of AMPDUs dropped due to xretries | 144 | * @a_xretries: No. of AMPDUs dropped due to xretries |
145 | * @txerr_filtered: No. of frames with TXERR_FILT flag set. | ||
145 | * @fifo_underrun: FIFO underrun occurrences | 146 | * @fifo_underrun: FIFO underrun occurrences |
146 | Valid only for: | 147 | Valid only for: |
147 | - non-aggregate condition. | 148 | - non-aggregate condition. |
@@ -168,6 +169,7 @@ struct ath_tx_stats { | |||
168 | u32 a_completed; | 169 | u32 a_completed; |
169 | u32 a_retries; | 170 | u32 a_retries; |
170 | u32 a_xretries; | 171 | u32 a_xretries; |
172 | u32 txerr_filtered; | ||
171 | u32 fifo_underrun; | 173 | u32 fifo_underrun; |
172 | u32 xtxop; | 174 | u32 xtxop; |
173 | u32 timer_exp; | 175 | u32 timer_exp; |
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 96bfb18078fa..d3b099d7898b 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/firmware.h> | 22 | #include <linux/firmware.h> |
23 | #include <linux/skbuff.h> | 23 | #include <linux/skbuff.h> |
24 | #include <linux/netdevice.h> | 24 | #include <linux/netdevice.h> |
25 | #include <linux/etherdevice.h> | ||
25 | #include <linux/leds.h> | 26 | #include <linux/leds.h> |
26 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
27 | #include <net/mac80211.h> | 28 | #include <net/mac80211.h> |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 3ad1fd05c5e7..bd8251c1c749 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | |||
@@ -1067,15 +1067,19 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, | |||
1067 | 1067 | ||
1068 | last_rssi = priv->rx.last_rssi; | 1068 | last_rssi = priv->rx.last_rssi; |
1069 | 1069 | ||
1070 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) | 1070 | if (ieee80211_is_beacon(hdr->frame_control) && |
1071 | rxbuf->rxstatus.rs_rssi = ATH_EP_RND(last_rssi, | 1071 | !is_zero_ether_addr(common->curbssid) && |
1072 | ATH_RSSI_EP_MULTIPLIER); | 1072 | ether_addr_equal(hdr->addr3, common->curbssid)) { |
1073 | s8 rssi = rxbuf->rxstatus.rs_rssi; | ||
1073 | 1074 | ||
1074 | if (rxbuf->rxstatus.rs_rssi < 0) | 1075 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) |
1075 | rxbuf->rxstatus.rs_rssi = 0; | 1076 | rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER); |
1076 | 1077 | ||
1077 | if (ieee80211_is_beacon(fc)) | 1078 | if (rssi < 0) |
1078 | priv->ah->stats.avgbrssi = rxbuf->rxstatus.rs_rssi; | 1079 | rssi = 0; |
1080 | |||
1081 | priv->ah->stats.avgbrssi = rssi; | ||
1082 | } | ||
1079 | 1083 | ||
1080 | rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp); | 1084 | rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp); |
1081 | rx_status->band = hw->conf.channel->band; | 1085 | rx_status->band = hw->conf.channel->band; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 2a2ae403e0e5..4fa2bb167050 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -1463,7 +1463,9 @@ static bool ath9k_hw_chip_reset(struct ath_hw *ah, | |||
1463 | reset_type = ATH9K_RESET_POWER_ON; | 1463 | reset_type = ATH9K_RESET_POWER_ON; |
1464 | else | 1464 | else |
1465 | reset_type = ATH9K_RESET_COLD; | 1465 | reset_type = ATH9K_RESET_COLD; |
1466 | } | 1466 | } else if (ah->chip_fullsleep || REG_READ(ah, AR_Q_TXE) || |
1467 | (REG_READ(ah, AR_CR) & AR_CR_RXE)) | ||
1468 | reset_type = ATH9K_RESET_COLD; | ||
1467 | 1469 | ||
1468 | if (!ath9k_hw_set_reset_reg(ah, reset_type)) | 1470 | if (!ath9k_hw_set_reset_reg(ah, reset_type)) |
1469 | return false; | 1471 | return false; |
@@ -1667,6 +1669,104 @@ bool ath9k_hw_check_alive(struct ath_hw *ah) | |||
1667 | } | 1669 | } |
1668 | EXPORT_SYMBOL(ath9k_hw_check_alive); | 1670 | EXPORT_SYMBOL(ath9k_hw_check_alive); |
1669 | 1671 | ||
1672 | static void ath9k_hw_init_mfp(struct ath_hw *ah) | ||
1673 | { | ||
1674 | /* Setup MFP options for CCMP */ | ||
1675 | if (AR_SREV_9280_20_OR_LATER(ah)) { | ||
1676 | /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt | ||
1677 | * frames when constructing CCMP AAD. */ | ||
1678 | REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT, | ||
1679 | 0xc7ff); | ||
1680 | ah->sw_mgmt_crypto = false; | ||
1681 | } else if (AR_SREV_9160_10_OR_LATER(ah)) { | ||
1682 | /* Disable hardware crypto for management frames */ | ||
1683 | REG_CLR_BIT(ah, AR_PCU_MISC_MODE2, | ||
1684 | AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE); | ||
1685 | REG_SET_BIT(ah, AR_PCU_MISC_MODE2, | ||
1686 | AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT); | ||
1687 | ah->sw_mgmt_crypto = true; | ||
1688 | } else { | ||
1689 | ah->sw_mgmt_crypto = true; | ||
1690 | } | ||
1691 | } | ||
1692 | |||
1693 | static void ath9k_hw_reset_opmode(struct ath_hw *ah, | ||
1694 | u32 macStaId1, u32 saveDefAntenna) | ||
1695 | { | ||
1696 | struct ath_common *common = ath9k_hw_common(ah); | ||
1697 | |||
1698 | ENABLE_REGWRITE_BUFFER(ah); | ||
1699 | |||
1700 | REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr)); | ||
1701 | REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4) | ||
1702 | | macStaId1 | ||
1703 | | AR_STA_ID1_RTS_USE_DEF | ||
1704 | | (ah->config.ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0) | ||
1705 | | ah->sta_id1_defaults); | ||
1706 | ath_hw_setbssidmask(common); | ||
1707 | REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); | ||
1708 | ath9k_hw_write_associd(ah); | ||
1709 | REG_WRITE(ah, AR_ISR, ~0); | ||
1710 | REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); | ||
1711 | |||
1712 | REGWRITE_BUFFER_FLUSH(ah); | ||
1713 | |||
1714 | ath9k_hw_set_operating_mode(ah, ah->opmode); | ||
1715 | } | ||
1716 | |||
1717 | static void ath9k_hw_init_queues(struct ath_hw *ah) | ||
1718 | { | ||
1719 | int i; | ||
1720 | |||
1721 | ENABLE_REGWRITE_BUFFER(ah); | ||
1722 | |||
1723 | for (i = 0; i < AR_NUM_DCU; i++) | ||
1724 | REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); | ||
1725 | |||
1726 | REGWRITE_BUFFER_FLUSH(ah); | ||
1727 | |||
1728 | ah->intr_txqs = 0; | ||
1729 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||
1730 | ath9k_hw_resettxqueue(ah, i); | ||
1731 | } | ||
1732 | |||
1733 | /* | ||
1734 | * For big endian systems turn on swapping for descriptors | ||
1735 | */ | ||
1736 | static void ath9k_hw_init_desc(struct ath_hw *ah) | ||
1737 | { | ||
1738 | struct ath_common *common = ath9k_hw_common(ah); | ||
1739 | |||
1740 | if (AR_SREV_9100(ah)) { | ||
1741 | u32 mask; | ||
1742 | mask = REG_READ(ah, AR_CFG); | ||
1743 | if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) { | ||
1744 | ath_dbg(common, RESET, "CFG Byte Swap Set 0x%x\n", | ||
1745 | mask); | ||
1746 | } else { | ||
1747 | mask = INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB; | ||
1748 | REG_WRITE(ah, AR_CFG, mask); | ||
1749 | ath_dbg(common, RESET, "Setting CFG 0x%x\n", | ||
1750 | REG_READ(ah, AR_CFG)); | ||
1751 | } | ||
1752 | } else { | ||
1753 | if (common->bus_ops->ath_bus_type == ATH_USB) { | ||
1754 | /* Configure AR9271 target WLAN */ | ||
1755 | if (AR_SREV_9271(ah)) | ||
1756 | REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB); | ||
1757 | else | ||
1758 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); | ||
1759 | } | ||
1760 | #ifdef __BIG_ENDIAN | ||
1761 | else if (AR_SREV_9330(ah) || AR_SREV_9340(ah) || | ||
1762 | AR_SREV_9550(ah)) | ||
1763 | REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0); | ||
1764 | else | ||
1765 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); | ||
1766 | #endif | ||
1767 | } | ||
1768 | } | ||
1769 | |||
1670 | /* | 1770 | /* |
1671 | * Fast channel change: | 1771 | * Fast channel change: |
1672 | * (Change synthesizer based on channel freq without resetting chip) | 1772 | * (Change synthesizer based on channel freq without resetting chip) |
@@ -1744,7 +1844,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1744 | u32 saveDefAntenna; | 1844 | u32 saveDefAntenna; |
1745 | u32 macStaId1; | 1845 | u32 macStaId1; |
1746 | u64 tsf = 0; | 1846 | u64 tsf = 0; |
1747 | int i, r; | 1847 | int r; |
1748 | bool start_mci_reset = false; | 1848 | bool start_mci_reset = false; |
1749 | bool save_fullsleep = ah->chip_fullsleep; | 1849 | bool save_fullsleep = ah->chip_fullsleep; |
1750 | 1850 | ||
@@ -1761,10 +1861,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1761 | ath9k_hw_getnf(ah, ah->curchan); | 1861 | ath9k_hw_getnf(ah, ah->curchan); |
1762 | 1862 | ||
1763 | ah->caldata = caldata; | 1863 | ah->caldata = caldata; |
1764 | if (caldata && | 1864 | if (caldata && (chan->channel != caldata->channel || |
1765 | (chan->channel != caldata->channel || | 1865 | chan->channelFlags != caldata->channelFlags)) { |
1766 | (chan->channelFlags & ~CHANNEL_CW_INT) != | ||
1767 | (caldata->channelFlags & ~CHANNEL_CW_INT))) { | ||
1768 | /* Operating channel changed, reset channel calibration data */ | 1866 | /* Operating channel changed, reset channel calibration data */ |
1769 | memset(caldata, 0, sizeof(*caldata)); | 1867 | memset(caldata, 0, sizeof(*caldata)); |
1770 | ath9k_init_nfcal_hist_buffer(ah, chan); | 1868 | ath9k_init_nfcal_hist_buffer(ah, chan); |
@@ -1851,22 +1949,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1851 | ath9k_hw_settsf64(ah, tsf); | 1949 | ath9k_hw_settsf64(ah, tsf); |
1852 | } | 1950 | } |
1853 | 1951 | ||
1854 | /* Setup MFP options for CCMP */ | 1952 | ath9k_hw_init_mfp(ah); |
1855 | if (AR_SREV_9280_20_OR_LATER(ah)) { | ||
1856 | /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt | ||
1857 | * frames when constructing CCMP AAD. */ | ||
1858 | REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT, | ||
1859 | 0xc7ff); | ||
1860 | ah->sw_mgmt_crypto = false; | ||
1861 | } else if (AR_SREV_9160_10_OR_LATER(ah)) { | ||
1862 | /* Disable hardware crypto for management frames */ | ||
1863 | REG_CLR_BIT(ah, AR_PCU_MISC_MODE2, | ||
1864 | AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE); | ||
1865 | REG_SET_BIT(ah, AR_PCU_MISC_MODE2, | ||
1866 | AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT); | ||
1867 | ah->sw_mgmt_crypto = true; | ||
1868 | } else | ||
1869 | ah->sw_mgmt_crypto = true; | ||
1870 | 1953 | ||
1871 | if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) | 1954 | if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) |
1872 | ath9k_hw_set_delta_slope(ah, chan); | 1955 | ath9k_hw_set_delta_slope(ah, chan); |
@@ -1874,24 +1957,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1874 | ath9k_hw_spur_mitigate_freq(ah, chan); | 1957 | ath9k_hw_spur_mitigate_freq(ah, chan); |
1875 | ah->eep_ops->set_board_values(ah, chan); | 1958 | ah->eep_ops->set_board_values(ah, chan); |
1876 | 1959 | ||
1877 | ENABLE_REGWRITE_BUFFER(ah); | 1960 | ath9k_hw_reset_opmode(ah, macStaId1, saveDefAntenna); |
1878 | |||
1879 | REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr)); | ||
1880 | REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4) | ||
1881 | | macStaId1 | ||
1882 | | AR_STA_ID1_RTS_USE_DEF | ||
1883 | | (ah->config. | ||
1884 | ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0) | ||
1885 | | ah->sta_id1_defaults); | ||
1886 | ath_hw_setbssidmask(common); | ||
1887 | REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); | ||
1888 | ath9k_hw_write_associd(ah); | ||
1889 | REG_WRITE(ah, AR_ISR, ~0); | ||
1890 | REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); | ||
1891 | |||
1892 | REGWRITE_BUFFER_FLUSH(ah); | ||
1893 | |||
1894 | ath9k_hw_set_operating_mode(ah, ah->opmode); | ||
1895 | 1961 | ||
1896 | r = ath9k_hw_rf_set_freq(ah, chan); | 1962 | r = ath9k_hw_rf_set_freq(ah, chan); |
1897 | if (r) | 1963 | if (r) |
@@ -1899,17 +1965,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1899 | 1965 | ||
1900 | ath9k_hw_set_clockrate(ah); | 1966 | ath9k_hw_set_clockrate(ah); |
1901 | 1967 | ||
1902 | ENABLE_REGWRITE_BUFFER(ah); | 1968 | ath9k_hw_init_queues(ah); |
1903 | |||
1904 | for (i = 0; i < AR_NUM_DCU; i++) | ||
1905 | REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); | ||
1906 | |||
1907 | REGWRITE_BUFFER_FLUSH(ah); | ||
1908 | |||
1909 | ah->intr_txqs = 0; | ||
1910 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||
1911 | ath9k_hw_resettxqueue(ah, i); | ||
1912 | |||
1913 | ath9k_hw_init_interrupt_masks(ah, ah->opmode); | 1969 | ath9k_hw_init_interrupt_masks(ah, ah->opmode); |
1914 | ath9k_hw_ani_cache_ini_regs(ah); | 1970 | ath9k_hw_ani_cache_ini_regs(ah); |
1915 | ath9k_hw_init_qos(ah); | 1971 | ath9k_hw_init_qos(ah); |
@@ -1964,38 +2020,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1964 | 2020 | ||
1965 | REGWRITE_BUFFER_FLUSH(ah); | 2021 | REGWRITE_BUFFER_FLUSH(ah); |
1966 | 2022 | ||
1967 | /* | 2023 | ath9k_hw_init_desc(ah); |
1968 | * For big endian systems turn on swapping for descriptors | ||
1969 | */ | ||
1970 | if (AR_SREV_9100(ah)) { | ||
1971 | u32 mask; | ||
1972 | mask = REG_READ(ah, AR_CFG); | ||
1973 | if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) { | ||
1974 | ath_dbg(common, RESET, "CFG Byte Swap Set 0x%x\n", | ||
1975 | mask); | ||
1976 | } else { | ||
1977 | mask = | ||
1978 | INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB; | ||
1979 | REG_WRITE(ah, AR_CFG, mask); | ||
1980 | ath_dbg(common, RESET, "Setting CFG 0x%x\n", | ||
1981 | REG_READ(ah, AR_CFG)); | ||
1982 | } | ||
1983 | } else { | ||
1984 | if (common->bus_ops->ath_bus_type == ATH_USB) { | ||
1985 | /* Configure AR9271 target WLAN */ | ||
1986 | if (AR_SREV_9271(ah)) | ||
1987 | REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB); | ||
1988 | else | ||
1989 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); | ||
1990 | } | ||
1991 | #ifdef __BIG_ENDIAN | ||
1992 | else if (AR_SREV_9330(ah) || AR_SREV_9340(ah) || | ||
1993 | AR_SREV_9550(ah)) | ||
1994 | REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0); | ||
1995 | else | ||
1996 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); | ||
1997 | #endif | ||
1998 | } | ||
1999 | 2024 | ||
2000 | if (ath9k_hw_btcoex_is_enabled(ah)) | 2025 | if (ath9k_hw_btcoex_is_enabled(ah)) |
2001 | ath9k_hw_btcoex_enable(ah); | 2026 | ath9k_hw_btcoex_enable(ah); |
@@ -2008,7 +2033,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
2008 | 2033 | ||
2009 | if (AR_SREV_9300_20_OR_LATER(ah)) { | 2034 | if (AR_SREV_9300_20_OR_LATER(ah)) { |
2010 | ar9003_hw_bb_watchdog_config(ah); | 2035 | ar9003_hw_bb_watchdog_config(ah); |
2011 | |||
2012 | ar9003_hw_disable_phy_restart(ah); | 2036 | ar9003_hw_disable_phy_restart(ah); |
2013 | } | 2037 | } |
2014 | 2038 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 784e81ccb903..30e62d92d46d 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -363,7 +363,6 @@ enum ath9k_int { | |||
363 | ATH9K_INT_NOCARD = 0xffffffff | 363 | ATH9K_INT_NOCARD = 0xffffffff |
364 | }; | 364 | }; |
365 | 365 | ||
366 | #define CHANNEL_CW_INT 0x00002 | ||
367 | #define CHANNEL_CCK 0x00020 | 366 | #define CHANNEL_CCK 0x00020 |
368 | #define CHANNEL_OFDM 0x00040 | 367 | #define CHANNEL_OFDM 0x00040 |
369 | #define CHANNEL_2GHZ 0x00080 | 368 | #define CHANNEL_2GHZ 0x00080 |
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c index 9c0b150d5b8e..c61cafa2665b 100644 --- a/drivers/net/wireless/ath/carl9170/tx.c +++ b/drivers/net/wireless/ath/carl9170/tx.c | |||
@@ -387,8 +387,7 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar, | |||
387 | u8 tid; | 387 | u8 tid; |
388 | 388 | ||
389 | if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) || | 389 | if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) || |
390 | txinfo->flags & IEEE80211_TX_CTL_INJECTED || | 390 | txinfo->flags & IEEE80211_TX_CTL_INJECTED) |
391 | (!(super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_AGGR)))) | ||
392 | return; | 391 | return; |
393 | 392 | ||
394 | rcu_read_lock(); | 393 | rcu_read_lock(); |
@@ -981,30 +980,6 @@ static int carl9170_tx_prepare(struct ar9170 *ar, | |||
981 | 980 | ||
982 | SET_VAL(CARL9170_TX_SUPER_AMPDU_FACTOR, | 981 | SET_VAL(CARL9170_TX_SUPER_AMPDU_FACTOR, |
983 | txc->s.ampdu_settings, factor); | 982 | txc->s.ampdu_settings, factor); |
984 | |||
985 | for (i = 0; i < CARL9170_TX_MAX_RATES; i++) { | ||
986 | txrate = &info->control.rates[i]; | ||
987 | if (txrate->idx >= 0) { | ||
988 | txc->s.ri[i] = | ||
989 | CARL9170_TX_SUPER_RI_AMPDU; | ||
990 | |||
991 | if (WARN_ON(!(txrate->flags & | ||
992 | IEEE80211_TX_RC_MCS))) { | ||
993 | /* | ||
994 | * Not sure if it's even possible | ||
995 | * to aggregate non-ht rates with | ||
996 | * this HW. | ||
997 | */ | ||
998 | goto err_out; | ||
999 | } | ||
1000 | continue; | ||
1001 | } | ||
1002 | |||
1003 | txrate->idx = 0; | ||
1004 | txrate->count = ar->hw->max_rate_tries; | ||
1005 | } | ||
1006 | |||
1007 | mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR); | ||
1008 | } | 983 | } |
1009 | 984 | ||
1010 | /* | 985 | /* |
@@ -1012,11 +987,31 @@ static int carl9170_tx_prepare(struct ar9170 *ar, | |||
1012 | * taken from mac_control. For all fallback rate, the firmware | 987 | * taken from mac_control. For all fallback rate, the firmware |
1013 | * updates the mac_control flags from the rate info field. | 988 | * updates the mac_control flags from the rate info field. |
1014 | */ | 989 | */ |
1015 | for (i = 1; i < CARL9170_TX_MAX_RATES; i++) { | 990 | for (i = 0; i < CARL9170_TX_MAX_RATES; i++) { |
991 | __le32 phy_set; | ||
1016 | txrate = &info->control.rates[i]; | 992 | txrate = &info->control.rates[i]; |
1017 | if (txrate->idx < 0) | 993 | if (txrate->idx < 0) |
1018 | break; | 994 | break; |
1019 | 995 | ||
996 | phy_set = carl9170_tx_physet(ar, info, txrate); | ||
997 | if (i == 0) { | ||
998 | /* first rate - part of the hw's frame header */ | ||
999 | txc->f.phy_control = phy_set; | ||
1000 | |||
1001 | if (ampdu && txrate->flags & IEEE80211_TX_RC_MCS) | ||
1002 | mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR); | ||
1003 | if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) | ||
1004 | mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); | ||
1005 | else if (carl9170_tx_cts_check(ar, txrate)) | ||
1006 | mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); | ||
1007 | |||
1008 | } else { | ||
1009 | /* fallback rates are stored in the firmware's | ||
1010 | * retry rate set array. | ||
1011 | */ | ||
1012 | txc->s.rr[i - 1] = phy_set; | ||
1013 | } | ||
1014 | |||
1020 | SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[i], | 1015 | SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[i], |
1021 | txrate->count); | 1016 | txrate->count); |
1022 | 1017 | ||
@@ -1027,21 +1022,13 @@ static int carl9170_tx_prepare(struct ar9170 *ar, | |||
1027 | txc->s.ri[i] |= (AR9170_TX_MAC_PROT_CTS << | 1022 | txc->s.ri[i] |= (AR9170_TX_MAC_PROT_CTS << |
1028 | CARL9170_TX_SUPER_RI_ERP_PROT_S); | 1023 | CARL9170_TX_SUPER_RI_ERP_PROT_S); |
1029 | 1024 | ||
1030 | txc->s.rr[i - 1] = carl9170_tx_physet(ar, info, txrate); | 1025 | if (ampdu && (txrate->flags & IEEE80211_TX_RC_MCS)) |
1026 | txc->s.ri[i] |= CARL9170_TX_SUPER_RI_AMPDU; | ||
1031 | } | 1027 | } |
1032 | 1028 | ||
1033 | txrate = &info->control.rates[0]; | ||
1034 | SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[0], txrate->count); | ||
1035 | |||
1036 | if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) | ||
1037 | mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); | ||
1038 | else if (carl9170_tx_cts_check(ar, txrate)) | ||
1039 | mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); | ||
1040 | |||
1041 | txc->s.len = cpu_to_le16(skb->len); | 1029 | txc->s.len = cpu_to_le16(skb->len); |
1042 | txc->f.length = cpu_to_le16(len + FCS_LEN); | 1030 | txc->f.length = cpu_to_le16(len + FCS_LEN); |
1043 | txc->f.mac_control = mac_tmp; | 1031 | txc->f.mac_control = mac_tmp; |
1044 | txc->f.phy_control = carl9170_tx_physet(ar, info, txrate); | ||
1045 | 1032 | ||
1046 | arinfo = (void *)info->rate_driver_data; | 1033 | arinfo = (void *)info->rate_driver_data; |
1047 | arinfo->timeout = jiffies; | 1034 | arinfo->timeout = jiffies; |
@@ -1381,9 +1368,9 @@ static void carl9170_tx(struct ar9170 *ar) | |||
1381 | } | 1368 | } |
1382 | 1369 | ||
1383 | static bool carl9170_tx_ampdu_queue(struct ar9170 *ar, | 1370 | static bool carl9170_tx_ampdu_queue(struct ar9170 *ar, |
1384 | struct ieee80211_sta *sta, struct sk_buff *skb) | 1371 | struct ieee80211_sta *sta, struct sk_buff *skb, |
1372 | struct ieee80211_tx_info *txinfo) | ||
1385 | { | 1373 | { |
1386 | struct _carl9170_tx_superframe *super = (void *) skb->data; | ||
1387 | struct carl9170_sta_info *sta_info; | 1374 | struct carl9170_sta_info *sta_info; |
1388 | struct carl9170_sta_tid *agg; | 1375 | struct carl9170_sta_tid *agg; |
1389 | struct sk_buff *iter; | 1376 | struct sk_buff *iter; |
@@ -1450,7 +1437,7 @@ err_unlock: | |||
1450 | 1437 | ||
1451 | err_unlock_rcu: | 1438 | err_unlock_rcu: |
1452 | rcu_read_unlock(); | 1439 | rcu_read_unlock(); |
1453 | super->f.mac_control &= ~cpu_to_le16(AR9170_TX_MAC_AGGR); | 1440 | txinfo->flags &= ~IEEE80211_TX_CTL_AMPDU; |
1454 | carl9170_tx_status(ar, skb, false); | 1441 | carl9170_tx_status(ar, skb, false); |
1455 | ar->tx_dropped++; | 1442 | ar->tx_dropped++; |
1456 | return false; | 1443 | return false; |
@@ -1492,7 +1479,7 @@ void carl9170_op_tx(struct ieee80211_hw *hw, | |||
1492 | * sta == NULL checks are redundant in this | 1479 | * sta == NULL checks are redundant in this |
1493 | * special case. | 1480 | * special case. |
1494 | */ | 1481 | */ |
1495 | run = carl9170_tx_ampdu_queue(ar, sta, skb); | 1482 | run = carl9170_tx_ampdu_queue(ar, sta, skb, info); |
1496 | if (run) | 1483 | if (run) |
1497 | carl9170_tx_ampdu(ar); | 1484 | carl9170_tx_ampdu(ar); |
1498 | 1485 | ||
diff --git a/drivers/net/wireless/ath/wil6210/Makefile b/drivers/net/wireless/ath/wil6210/Makefile index 9396dc9fe3c5..d288eea0a26a 100644 --- a/drivers/net/wireless/ath/wil6210/Makefile +++ b/drivers/net/wireless/ath/wil6210/Makefile | |||
@@ -9,5 +9,7 @@ wil6210-objs += wmi.o | |||
9 | wil6210-objs += interrupt.o | 9 | wil6210-objs += interrupt.o |
10 | wil6210-objs += txrx.o | 10 | wil6210-objs += txrx.o |
11 | 11 | ||
12 | subdir-ccflags-y += -Werror | 12 | ifeq (, $(findstring -W,$(EXTRA_CFLAGS))) |
13 | subdir-ccflags-y += -Werror | ||
14 | endif | ||
13 | subdir-ccflags-y += -D__CHECK_ENDIAN__ | 15 | subdir-ccflags-y += -D__CHECK_ENDIAN__ |
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 9ecc1968262c..c5d4a87abaaf 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c | |||
@@ -14,16 +14,6 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/netdevice.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/etherdevice.h> | ||
21 | #include <linux/wireless.h> | ||
22 | #include <linux/ieee80211.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/version.h> | ||
25 | #include <net/cfg80211.h> | ||
26 | |||
27 | #include "wil6210.h" | 17 | #include "wil6210.h" |
28 | #include "wmi.h" | 18 | #include "wmi.h" |
29 | 19 | ||
@@ -292,7 +282,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, | |||
292 | 282 | ||
293 | /* WMI_CONNECT_CMD */ | 283 | /* WMI_CONNECT_CMD */ |
294 | memset(&conn, 0, sizeof(conn)); | 284 | memset(&conn, 0, sizeof(conn)); |
295 | switch (bss->capability & 0x03) { | 285 | switch (bss->capability & WLAN_CAPABILITY_DMG_TYPE_MASK) { |
296 | case WLAN_CAPABILITY_DMG_TYPE_AP: | 286 | case WLAN_CAPABILITY_DMG_TYPE_AP: |
297 | conn.network_type = WMI_NETTYPE_INFRA; | 287 | conn.network_type = WMI_NETTYPE_INFRA; |
298 | break; | 288 | break; |
@@ -437,17 +427,18 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, | |||
437 | if (rc) | 427 | if (rc) |
438 | return rc; | 428 | return rc; |
439 | 429 | ||
440 | rc = wmi_set_channel(wil, channel->hw_value); | ||
441 | if (rc) | ||
442 | return rc; | ||
443 | |||
444 | /* MAC address - pre-requisite for other commands */ | 430 | /* MAC address - pre-requisite for other commands */ |
445 | wmi_set_mac_address(wil, ndev->dev_addr); | 431 | wmi_set_mac_address(wil, ndev->dev_addr); |
446 | 432 | ||
447 | /* IE's */ | 433 | /* IE's */ |
448 | /* bcon 'head IE's are not relevant for 60g band */ | 434 | /* bcon 'head IE's are not relevant for 60g band */ |
449 | wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->beacon_ies_len, | 435 | /* |
450 | bcon->beacon_ies); | 436 | * FW do not form regular beacon, so bcon IE's are not set |
437 | * For the DMG bcon, when it will be supported, bcon IE's will | ||
438 | * be reused; add something like: | ||
439 | * wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->beacon_ies_len, | ||
440 | * bcon->beacon_ies); | ||
441 | */ | ||
451 | wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, bcon->proberesp_ies_len, | 442 | wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, bcon->proberesp_ies_len, |
452 | bcon->proberesp_ies); | 443 | bcon->proberesp_ies); |
453 | wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, bcon->assocresp_ies_len, | 444 | wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, bcon->assocresp_ies_len, |
@@ -455,7 +446,8 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, | |||
455 | 446 | ||
456 | wil->secure_pcp = info->privacy; | 447 | wil->secure_pcp = info->privacy; |
457 | 448 | ||
458 | rc = wmi_set_bcon(wil, info->beacon_interval, wmi_nettype); | 449 | rc = wmi_pcp_start(wil, info->beacon_interval, wmi_nettype, |
450 | channel->hw_value); | ||
459 | if (rc) | 451 | if (rc) |
460 | return rc; | 452 | return rc; |
461 | 453 | ||
@@ -472,11 +464,8 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy, | |||
472 | { | 464 | { |
473 | int rc = 0; | 465 | int rc = 0; |
474 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 466 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
475 | struct wireless_dev *wdev = ndev->ieee80211_ptr; | ||
476 | u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); | ||
477 | 467 | ||
478 | /* To stop beaconing, set BI to 0 */ | 468 | rc = wmi_pcp_stop(wil); |
479 | rc = wmi_set_bcon(wil, 0, wmi_nettype); | ||
480 | 469 | ||
481 | return rc; | 470 | return rc; |
482 | } | 471 | } |
diff --git a/drivers/net/wireless/ath/wil6210/dbg_hexdump.h b/drivers/net/wireless/ath/wil6210/dbg_hexdump.h deleted file mode 100644 index e5712f026c47..000000000000 --- a/drivers/net/wireless/ath/wil6210/dbg_hexdump.h +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | #ifndef WIL_DBG_HEXDUMP_H_ | ||
2 | #define WIL_DBG_HEXDUMP_H_ | ||
3 | |||
4 | #include <linux/printk.h> | ||
5 | #include <linux/dynamic_debug.h> | ||
6 | |||
7 | #if defined(CONFIG_DYNAMIC_DEBUG) | ||
8 | #define wil_print_hex_dump_debug(prefix_str, prefix_type, rowsize, \ | ||
9 | groupsize, buf, len, ascii) \ | ||
10 | dynamic_hex_dump(prefix_str, prefix_type, rowsize, \ | ||
11 | groupsize, buf, len, ascii) | ||
12 | |||
13 | #else /* defined(CONFIG_DYNAMIC_DEBUG) */ | ||
14 | #define wil_print_hex_dump_debug(prefix_str, prefix_type, rowsize, \ | ||
15 | groupsize, buf, len, ascii) \ | ||
16 | print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, rowsize, \ | ||
17 | groupsize, buf, len, ascii) | ||
18 | #endif /* defined(CONFIG_DYNAMIC_DEBUG) */ | ||
19 | |||
20 | #endif /* WIL_DBG_HEXDUMP_H_ */ | ||
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 65fc9683bfd8..4be07f5e22b9 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c | |||
@@ -312,14 +312,6 @@ static const struct file_operations fops_memread = { | |||
312 | .llseek = seq_lseek, | 312 | .llseek = seq_lseek, |
313 | }; | 313 | }; |
314 | 314 | ||
315 | static int wil_default_open(struct inode *inode, struct file *file) | ||
316 | { | ||
317 | if (inode->i_private) | ||
318 | file->private_data = inode->i_private; | ||
319 | |||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, | 315 | static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, |
324 | size_t count, loff_t *ppos) | 316 | size_t count, loff_t *ppos) |
325 | { | 317 | { |
@@ -361,7 +353,7 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, | |||
361 | 353 | ||
362 | static const struct file_operations fops_ioblob = { | 354 | static const struct file_operations fops_ioblob = { |
363 | .read = wil_read_file_ioblob, | 355 | .read = wil_read_file_ioblob, |
364 | .open = wil_default_open, | 356 | .open = simple_open, |
365 | .llseek = default_llseek, | 357 | .llseek = default_llseek, |
366 | }; | 358 | }; |
367 | 359 | ||
@@ -396,7 +388,7 @@ static ssize_t wil_write_file_reset(struct file *file, const char __user *buf, | |||
396 | 388 | ||
397 | static const struct file_operations fops_reset = { | 389 | static const struct file_operations fops_reset = { |
398 | .write = wil_write_file_reset, | 390 | .write = wil_write_file_reset, |
399 | .open = wil_default_open, | 391 | .open = simple_open, |
400 | }; | 392 | }; |
401 | /*---------Tx descriptor------------*/ | 393 | /*---------Tx descriptor------------*/ |
402 | 394 | ||
@@ -526,7 +518,50 @@ static ssize_t wil_write_file_ssid(struct file *file, const char __user *buf, | |||
526 | static const struct file_operations fops_ssid = { | 518 | static const struct file_operations fops_ssid = { |
527 | .read = wil_read_file_ssid, | 519 | .read = wil_read_file_ssid, |
528 | .write = wil_write_file_ssid, | 520 | .write = wil_write_file_ssid, |
529 | .open = wil_default_open, | 521 | .open = simple_open, |
522 | }; | ||
523 | |||
524 | /*---------temp------------*/ | ||
525 | static void print_temp(struct seq_file *s, const char *prefix, u32 t) | ||
526 | { | ||
527 | switch (t) { | ||
528 | case 0: | ||
529 | case ~(u32)0: | ||
530 | seq_printf(s, "%s N/A\n", prefix); | ||
531 | break; | ||
532 | default: | ||
533 | seq_printf(s, "%s %d.%03d\n", prefix, t / 1000, t % 1000); | ||
534 | break; | ||
535 | } | ||
536 | } | ||
537 | |||
538 | static int wil_temp_debugfs_show(struct seq_file *s, void *data) | ||
539 | { | ||
540 | struct wil6210_priv *wil = s->private; | ||
541 | u32 t_m, t_r; | ||
542 | |||
543 | int rc = wmi_get_temperature(wil, &t_m, &t_r); | ||
544 | if (rc) { | ||
545 | seq_printf(s, "Failed\n"); | ||
546 | return 0; | ||
547 | } | ||
548 | |||
549 | print_temp(s, "MAC temperature :", t_m); | ||
550 | print_temp(s, "Radio temperature :", t_r); | ||
551 | |||
552 | return 0; | ||
553 | } | ||
554 | |||
555 | static int wil_temp_seq_open(struct inode *inode, struct file *file) | ||
556 | { | ||
557 | return single_open(file, wil_temp_debugfs_show, inode->i_private); | ||
558 | } | ||
559 | |||
560 | static const struct file_operations fops_temp = { | ||
561 | .open = wil_temp_seq_open, | ||
562 | .release = single_release, | ||
563 | .read = seq_read, | ||
564 | .llseek = seq_lseek, | ||
530 | }; | 565 | }; |
531 | 566 | ||
532 | /*----------------*/ | 567 | /*----------------*/ |
@@ -563,6 +598,7 @@ int wil6210_debugfs_init(struct wil6210_priv *wil) | |||
563 | debugfs_create_file("mem_val", S_IRUGO, dbg, wil, &fops_memread); | 598 | debugfs_create_file("mem_val", S_IRUGO, dbg, wil, &fops_memread); |
564 | 599 | ||
565 | debugfs_create_file("reset", S_IWUSR, dbg, wil, &fops_reset); | 600 | debugfs_create_file("reset", S_IWUSR, dbg, wil, &fops_reset); |
601 | debugfs_create_file("temp", S_IRUGO, dbg, wil, &fops_temp); | ||
566 | 602 | ||
567 | wil->rgf_blob.data = (void * __force)wil->csr + 0; | 603 | wil->rgf_blob.data = (void * __force)wil->csr + 0; |
568 | wil->rgf_blob.size = 0xa000; | 604 | wil->rgf_blob.size = 0xa000; |
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index dc97e7b2609c..e3c1e7684f9c 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c | |||
@@ -240,6 +240,15 @@ static void wil_notify_fw_error(struct wil6210_priv *wil) | |||
240 | kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); | 240 | kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); |
241 | } | 241 | } |
242 | 242 | ||
243 | static void wil_cache_mbox_regs(struct wil6210_priv *wil) | ||
244 | { | ||
245 | /* make shadow copy of registers that should not change on run time */ | ||
246 | wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX, | ||
247 | sizeof(struct wil6210_mbox_ctl)); | ||
248 | wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx); | ||
249 | wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx); | ||
250 | } | ||
251 | |||
243 | static irqreturn_t wil6210_irq_misc(int irq, void *cookie) | 252 | static irqreturn_t wil6210_irq_misc(int irq, void *cookie) |
244 | { | 253 | { |
245 | struct wil6210_priv *wil = cookie; | 254 | struct wil6210_priv *wil = cookie; |
@@ -257,14 +266,19 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) | |||
257 | wil6210_mask_irq_misc(wil); | 266 | wil6210_mask_irq_misc(wil); |
258 | 267 | ||
259 | if (isr & ISR_MISC_FW_ERROR) { | 268 | if (isr & ISR_MISC_FW_ERROR) { |
260 | wil_dbg_irq(wil, "IRQ: Firmware error\n"); | 269 | wil_err(wil, "Firmware error detected\n"); |
261 | clear_bit(wil_status_fwready, &wil->status); | 270 | clear_bit(wil_status_fwready, &wil->status); |
262 | wil_notify_fw_error(wil); | 271 | /* |
263 | isr &= ~ISR_MISC_FW_ERROR; | 272 | * do not clear @isr here - we do 2-nd part in thread |
273 | * there, user space get notified, and it should be done | ||
274 | * in non-atomic context | ||
275 | */ | ||
264 | } | 276 | } |
265 | 277 | ||
266 | if (isr & ISR_MISC_FW_READY) { | 278 | if (isr & ISR_MISC_FW_READY) { |
267 | wil_dbg_irq(wil, "IRQ: FW ready\n"); | 279 | wil_dbg_irq(wil, "IRQ: FW ready\n"); |
280 | wil_cache_mbox_regs(wil); | ||
281 | set_bit(wil_status_reset_done, &wil->status); | ||
268 | /** | 282 | /** |
269 | * Actual FW ready indicated by the | 283 | * Actual FW ready indicated by the |
270 | * WMI_FW_READY_EVENTID | 284 | * WMI_FW_READY_EVENTID |
@@ -289,6 +303,11 @@ static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie) | |||
289 | 303 | ||
290 | wil_dbg_irq(wil, "Thread ISR MISC 0x%08x\n", isr); | 304 | wil_dbg_irq(wil, "Thread ISR MISC 0x%08x\n", isr); |
291 | 305 | ||
306 | if (isr & ISR_MISC_FW_ERROR) { | ||
307 | wil_notify_fw_error(wil); | ||
308 | isr &= ~ISR_MISC_FW_ERROR; | ||
309 | } | ||
310 | |||
292 | if (isr & ISR_MISC_MBOX_EVT) { | 311 | if (isr & ISR_MISC_MBOX_EVT) { |
293 | wil_dbg_irq(wil, "MBOX event\n"); | 312 | wil_dbg_irq(wil, "MBOX event\n"); |
294 | wmi_recv_cmd(wil); | 313 | wmi_recv_cmd(wil); |
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 761c389586d4..a0478e2f6868 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c | |||
@@ -14,12 +14,6 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/netdevice.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/ieee80211.h> | ||
21 | #include <linux/wireless.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/moduleparam.h> | 17 | #include <linux/moduleparam.h> |
24 | #include <linux/if_arp.h> | 18 | #include <linux/if_arp.h> |
25 | 19 | ||
@@ -109,13 +103,24 @@ static void wil_connect_timer_fn(ulong x) | |||
109 | schedule_work(&wil->disconnect_worker); | 103 | schedule_work(&wil->disconnect_worker); |
110 | } | 104 | } |
111 | 105 | ||
112 | static void wil_cache_mbox_regs(struct wil6210_priv *wil) | 106 | static void wil_connect_worker(struct work_struct *work) |
113 | { | 107 | { |
114 | /* make shadow copy of registers that should not change on run time */ | 108 | int rc; |
115 | wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX, | 109 | struct wil6210_priv *wil = container_of(work, struct wil6210_priv, |
116 | sizeof(struct wil6210_mbox_ctl)); | 110 | connect_worker); |
117 | wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx); | 111 | int cid = wil->pending_connect_cid; |
118 | wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx); | 112 | |
113 | if (cid < 0) { | ||
114 | wil_err(wil, "No connection pending\n"); | ||
115 | return; | ||
116 | } | ||
117 | |||
118 | wil_dbg_wmi(wil, "Configure for connection CID %d\n", cid); | ||
119 | |||
120 | rc = wil_vring_init_tx(wil, 0, WIL6210_TX_RING_SIZE, cid, 0); | ||
121 | wil->pending_connect_cid = -1; | ||
122 | if (rc == 0) | ||
123 | wil_link_on(wil); | ||
119 | } | 124 | } |
120 | 125 | ||
121 | int wil_priv_init(struct wil6210_priv *wil) | 126 | int wil_priv_init(struct wil6210_priv *wil) |
@@ -130,7 +135,7 @@ int wil_priv_init(struct wil6210_priv *wil) | |||
130 | wil->pending_connect_cid = -1; | 135 | wil->pending_connect_cid = -1; |
131 | setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil); | 136 | setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil); |
132 | 137 | ||
133 | INIT_WORK(&wil->wmi_connect_worker, wmi_connect_worker); | 138 | INIT_WORK(&wil->connect_worker, wil_connect_worker); |
134 | INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker); | 139 | INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker); |
135 | INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); | 140 | INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); |
136 | 141 | ||
@@ -147,8 +152,6 @@ int wil_priv_init(struct wil6210_priv *wil) | |||
147 | return -EAGAIN; | 152 | return -EAGAIN; |
148 | } | 153 | } |
149 | 154 | ||
150 | wil_cache_mbox_regs(wil); | ||
151 | |||
152 | return 0; | 155 | return 0; |
153 | } | 156 | } |
154 | 157 | ||
@@ -185,15 +188,11 @@ static void wil_target_reset(struct wil6210_priv *wil) | |||
185 | W(RGF_USER_MAC_CPU_0, BIT(1)); /* mac_cpu_man_rst */ | 188 | W(RGF_USER_MAC_CPU_0, BIT(1)); /* mac_cpu_man_rst */ |
186 | W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */ | 189 | W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */ |
187 | 190 | ||
188 | msleep(100); | ||
189 | |||
190 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000); | 191 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000); |
191 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F); | 192 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F); |
192 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000170); | 193 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000170); |
193 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FC00); | 194 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FC00); |
194 | 195 | ||
195 | msleep(100); | ||
196 | |||
197 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0); | 196 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0); |
198 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0); | 197 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0); |
199 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0); | 198 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0); |
@@ -203,12 +202,6 @@ static void wil_target_reset(struct wil6210_priv *wil) | |||
203 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080); | 202 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080); |
204 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); | 203 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); |
205 | 204 | ||
206 | msleep(2000); | ||
207 | |||
208 | W(RGF_USER_USER_CPU_0, BIT(0)); /* user_cpu_man_de_rst */ | ||
209 | |||
210 | msleep(2000); | ||
211 | |||
212 | wil_dbg_misc(wil, "Reset completed\n"); | 205 | wil_dbg_misc(wil, "Reset completed\n"); |
213 | 206 | ||
214 | #undef W | 207 | #undef W |
@@ -265,8 +258,6 @@ int wil_reset(struct wil6210_priv *wil) | |||
265 | wil->pending_connect_cid = -1; | 258 | wil->pending_connect_cid = -1; |
266 | INIT_COMPLETION(wil->wmi_ready); | 259 | INIT_COMPLETION(wil->wmi_ready); |
267 | 260 | ||
268 | wil_cache_mbox_regs(wil); | ||
269 | |||
270 | /* TODO: release MAC reset */ | 261 | /* TODO: release MAC reset */ |
271 | wil6210_enable_irq(wil); | 262 | wil6210_enable_irq(wil); |
272 | 263 | ||
@@ -352,9 +343,9 @@ static int __wil_up(struct wil6210_priv *wil) | |||
352 | wil_err(wil, "SSID not set\n"); | 343 | wil_err(wil, "SSID not set\n"); |
353 | return -EINVAL; | 344 | return -EINVAL; |
354 | } | 345 | } |
355 | wmi_set_ssid(wil, wdev->ssid_len, wdev->ssid); | 346 | rc = wmi_set_ssid(wil, wdev->ssid_len, wdev->ssid); |
356 | if (channel) | 347 | if (rc) |
357 | wmi_set_channel(wil, channel->hw_value); | 348 | return rc; |
358 | break; | 349 | break; |
359 | default: | 350 | default: |
360 | break; | 351 | break; |
@@ -364,9 +355,12 @@ static int __wil_up(struct wil6210_priv *wil) | |||
364 | wmi_set_mac_address(wil, ndev->dev_addr); | 355 | wmi_set_mac_address(wil, ndev->dev_addr); |
365 | 356 | ||
366 | /* Set up beaconing if required. */ | 357 | /* Set up beaconing if required. */ |
367 | rc = wmi_set_bcon(wil, bi, wmi_nettype); | 358 | if (bi > 0) { |
368 | if (rc) | 359 | rc = wmi_pcp_start(wil, bi, wmi_nettype, |
369 | return rc; | 360 | (channel ? channel->hw_value : 0)); |
361 | if (rc) | ||
362 | return rc; | ||
363 | } | ||
370 | 364 | ||
371 | /* Rx VRING. After MAC and beacon */ | 365 | /* Rx VRING. After MAC and beacon */ |
372 | wil_rx_init(wil); | 366 | wil_rx_init(wil); |
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index 8ce2e33dce20..098a8ec6b841 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c | |||
@@ -14,10 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/netdevice.h> | ||
19 | #include <linux/etherdevice.h> | 17 | #include <linux/etherdevice.h> |
20 | #include <linux/slab.h> | ||
21 | 18 | ||
22 | #include "wil6210.h" | 19 | #include "wil6210.h" |
23 | 20 | ||
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c index 81c35c6e3832..eb1dc7ad80fb 100644 --- a/drivers/net/wireless/ath/wil6210/pcie_bus.c +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c | |||
@@ -14,10 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/module.h> | 17 | #include <linux/module.h> |
19 | #include <linux/slab.h> | ||
20 | #include <linux/netdevice.h> | ||
21 | #include <linux/debugfs.h> | 18 | #include <linux/debugfs.h> |
22 | #include <linux/pci.h> | 19 | #include <linux/pci.h> |
23 | #include <linux/moduleparam.h> | 20 | #include <linux/moduleparam.h> |
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index d1315b442375..1bfa736cc1f2 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c | |||
@@ -14,10 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/netdevice.h> | ||
19 | #include <linux/etherdevice.h> | 17 | #include <linux/etherdevice.h> |
20 | #include <linux/hardirq.h> | ||
21 | #include <net/ieee80211_radiotap.h> | 18 | #include <net/ieee80211_radiotap.h> |
22 | #include <linux/if_arp.h> | 19 | #include <linux/if_arp.h> |
23 | #include <linux/moduleparam.h> | 20 | #include <linux/moduleparam.h> |
@@ -560,7 +557,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | |||
560 | if (rc) | 557 | if (rc) |
561 | goto out_free; | 558 | goto out_free; |
562 | 559 | ||
563 | if (reply.cmd.status != WMI_VRING_CFG_SUCCESS) { | 560 | if (reply.cmd.status != WMI_FW_STATUS_SUCCESS) { |
564 | wil_err(wil, "Tx config failed, status 0x%02x\n", | 561 | wil_err(wil, "Tx config failed, status 0x%02x\n", |
565 | reply.cmd.status); | 562 | reply.cmd.status); |
566 | rc = -EINVAL; | 563 | rc = -EINVAL; |
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index aea961ff8f08..8f76ecd8a7e5 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h | |||
@@ -21,8 +21,6 @@ | |||
21 | #include <linux/wireless.h> | 21 | #include <linux/wireless.h> |
22 | #include <net/cfg80211.h> | 22 | #include <net/cfg80211.h> |
23 | 23 | ||
24 | #include "dbg_hexdump.h" | ||
25 | |||
26 | #define WIL_NAME "wil6210" | 24 | #define WIL_NAME "wil6210" |
27 | 25 | ||
28 | /** | 26 | /** |
@@ -188,6 +186,7 @@ enum { /* for wil6210_priv.status */ | |||
188 | wil_status_fwready = 0, | 186 | wil_status_fwready = 0, |
189 | wil_status_fwconnected, | 187 | wil_status_fwconnected, |
190 | wil_status_dontscan, | 188 | wil_status_dontscan, |
189 | wil_status_reset_done, | ||
191 | wil_status_irqen, /* FIXME: interrupts enabled - for debug */ | 190 | wil_status_irqen, /* FIXME: interrupts enabled - for debug */ |
192 | }; | 191 | }; |
193 | 192 | ||
@@ -210,6 +209,8 @@ struct wil6210_priv { | |||
210 | struct wireless_dev *wdev; | 209 | struct wireless_dev *wdev; |
211 | void __iomem *csr; | 210 | void __iomem *csr; |
212 | ulong status; | 211 | ulong status; |
212 | u32 fw_version; | ||
213 | u8 n_mids; /* number of additional MIDs as reported by FW */ | ||
213 | /* profile */ | 214 | /* profile */ |
214 | u32 monitor_flags; | 215 | u32 monitor_flags; |
215 | u32 secure_pcp; /* create secure PCP? */ | 216 | u32 secure_pcp; /* create secure PCP? */ |
@@ -227,7 +228,7 @@ struct wil6210_priv { | |||
227 | struct workqueue_struct *wmi_wq; /* for deferred calls */ | 228 | struct workqueue_struct *wmi_wq; /* for deferred calls */ |
228 | struct work_struct wmi_event_worker; | 229 | struct work_struct wmi_event_worker; |
229 | struct workqueue_struct *wmi_wq_conn; /* for connect worker */ | 230 | struct workqueue_struct *wmi_wq_conn; /* for connect worker */ |
230 | struct work_struct wmi_connect_worker; | 231 | struct work_struct connect_worker; |
231 | struct work_struct disconnect_worker; | 232 | struct work_struct disconnect_worker; |
232 | struct timer_list connect_timer; | 233 | struct timer_list connect_timer; |
233 | int pending_connect_cid; | 234 | int pending_connect_cid; |
@@ -277,13 +278,13 @@ struct wil6210_priv { | |||
277 | 278 | ||
278 | #define wil_hex_dump_txrx(prefix_str, prefix_type, rowsize, \ | 279 | #define wil_hex_dump_txrx(prefix_str, prefix_type, rowsize, \ |
279 | groupsize, buf, len, ascii) \ | 280 | groupsize, buf, len, ascii) \ |
280 | wil_print_hex_dump_debug("DBG[TXRX]" prefix_str,\ | 281 | print_hex_dump_debug("DBG[TXRX]" prefix_str,\ |
281 | prefix_type, rowsize, \ | 282 | prefix_type, rowsize, \ |
282 | groupsize, buf, len, ascii) | 283 | groupsize, buf, len, ascii) |
283 | 284 | ||
284 | #define wil_hex_dump_wmi(prefix_str, prefix_type, rowsize, \ | 285 | #define wil_hex_dump_wmi(prefix_str, prefix_type, rowsize, \ |
285 | groupsize, buf, len, ascii) \ | 286 | groupsize, buf, len, ascii) \ |
286 | wil_print_hex_dump_debug("DBG[ WMI]" prefix_str,\ | 287 | print_hex_dump_debug("DBG[ WMI]" prefix_str,\ |
287 | prefix_type, rowsize, \ | 288 | prefix_type, rowsize, \ |
288 | groupsize, buf, len, ascii) | 289 | groupsize, buf, len, ascii) |
289 | 290 | ||
@@ -313,7 +314,6 @@ int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len); | |||
313 | void wmi_recv_cmd(struct wil6210_priv *wil); | 314 | void wmi_recv_cmd(struct wil6210_priv *wil); |
314 | int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, | 315 | int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, |
315 | u16 reply_id, void *reply, u8 reply_size, int to_msec); | 316 | u16 reply_id, void *reply, u8 reply_size, int to_msec); |
316 | void wmi_connect_worker(struct work_struct *work); | ||
317 | void wmi_event_worker(struct work_struct *work); | 317 | void wmi_event_worker(struct work_struct *work); |
318 | void wmi_event_flush(struct wil6210_priv *wil); | 318 | void wmi_event_flush(struct wil6210_priv *wil); |
319 | int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid); | 319 | int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid); |
@@ -328,6 +328,8 @@ int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index, | |||
328 | int wmi_echo(struct wil6210_priv *wil); | 328 | int wmi_echo(struct wil6210_priv *wil); |
329 | int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie); | 329 | int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie); |
330 | int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring); | 330 | int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring); |
331 | int wmi_p2p_cfg(struct wil6210_priv *wil, int channel); | ||
332 | int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r); | ||
331 | 333 | ||
332 | int wil6210_init_irq(struct wil6210_priv *wil, int irq); | 334 | int wil6210_init_irq(struct wil6210_priv *wil, int irq); |
333 | void wil6210_fini_irq(struct wil6210_priv *wil, int irq); | 335 | void wil6210_fini_irq(struct wil6210_priv *wil, int irq); |
@@ -341,7 +343,8 @@ struct wireless_dev *wil_cfg80211_init(struct device *dev); | |||
341 | void wil_wdev_free(struct wil6210_priv *wil); | 343 | void wil_wdev_free(struct wil6210_priv *wil); |
342 | 344 | ||
343 | int wmi_set_mac_address(struct wil6210_priv *wil, void *addr); | 345 | int wmi_set_mac_address(struct wil6210_priv *wil, void *addr); |
344 | int wmi_set_bcon(struct wil6210_priv *wil, int bi, u8 wmi_nettype); | 346 | int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan); |
347 | int wmi_pcp_stop(struct wil6210_priv *wil); | ||
345 | void wil6210_disconnect(struct wil6210_priv *wil, void *bssid); | 348 | void wil6210_disconnect(struct wil6210_priv *wil, void *bssid); |
346 | 349 | ||
347 | int wil_rx_init(struct wil6210_priv *wil); | 350 | int wil_rx_init(struct wil6210_priv *wil); |
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 0bb3b76b4b58..45b04e383f9a 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c | |||
@@ -14,9 +14,6 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/pci.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/list.h> | ||
20 | #include <linux/etherdevice.h> | 17 | #include <linux/etherdevice.h> |
21 | #include <linux/if_arp.h> | 18 | #include <linux/if_arp.h> |
22 | 19 | ||
@@ -272,16 +269,18 @@ static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len) | |||
272 | struct net_device *ndev = wil_to_ndev(wil); | 269 | struct net_device *ndev = wil_to_ndev(wil); |
273 | struct wireless_dev *wdev = wil->wdev; | 270 | struct wireless_dev *wdev = wil->wdev; |
274 | struct wmi_ready_event *evt = d; | 271 | struct wmi_ready_event *evt = d; |
275 | u32 ver = le32_to_cpu(evt->sw_version); | 272 | wil->fw_version = le32_to_cpu(evt->sw_version); |
273 | wil->n_mids = evt->numof_additional_mids; | ||
276 | 274 | ||
277 | wil_dbg_wmi(wil, "FW ver. %d; MAC %pM\n", ver, evt->mac); | 275 | wil_dbg_wmi(wil, "FW ver. %d; MAC %pM; %d MID's\n", wil->fw_version, |
276 | evt->mac, wil->n_mids); | ||
278 | 277 | ||
279 | if (!is_valid_ether_addr(ndev->dev_addr)) { | 278 | if (!is_valid_ether_addr(ndev->dev_addr)) { |
280 | memcpy(ndev->dev_addr, evt->mac, ETH_ALEN); | 279 | memcpy(ndev->dev_addr, evt->mac, ETH_ALEN); |
281 | memcpy(ndev->perm_addr, evt->mac, ETH_ALEN); | 280 | memcpy(ndev->perm_addr, evt->mac, ETH_ALEN); |
282 | } | 281 | } |
283 | snprintf(wdev->wiphy->fw_version, sizeof(wdev->wiphy->fw_version), | 282 | snprintf(wdev->wiphy->fw_version, sizeof(wdev->wiphy->fw_version), |
284 | "%d", ver); | 283 | "%d", wil->fw_version); |
285 | } | 284 | } |
286 | 285 | ||
287 | static void wmi_evt_fw_ready(struct wil6210_priv *wil, int id, void *d, | 286 | static void wmi_evt_fw_ready(struct wil6210_priv *wil, int id, void *d, |
@@ -324,17 +323,9 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) | |||
324 | 323 | ||
325 | if (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)) { | 324 | if (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)) { |
326 | struct cfg80211_bss *bss; | 325 | struct cfg80211_bss *bss; |
327 | u64 tsf = le64_to_cpu(rx_mgmt_frame->u.beacon.timestamp); | 326 | |
328 | u16 cap = le16_to_cpu(rx_mgmt_frame->u.beacon.capab_info); | 327 | bss = cfg80211_inform_bss_frame(wiphy, channel, rx_mgmt_frame, |
329 | u16 bi = le16_to_cpu(rx_mgmt_frame->u.beacon.beacon_int); | 328 | d_len, signal, GFP_KERNEL); |
330 | const u8 *ie_buf = rx_mgmt_frame->u.beacon.variable; | ||
331 | size_t ie_len = d_len - offsetof(struct ieee80211_mgmt, | ||
332 | u.beacon.variable); | ||
333 | wil_dbg_wmi(wil, "Capability info : 0x%04x\n", cap); | ||
334 | |||
335 | bss = cfg80211_inform_bss(wiphy, channel, rx_mgmt_frame->bssid, | ||
336 | tsf, cap, bi, ie_buf, ie_len, | ||
337 | signal, GFP_KERNEL); | ||
338 | if (bss) { | 329 | if (bss) { |
339 | wil_dbg_wmi(wil, "Added BSS %pM\n", | 330 | wil_dbg_wmi(wil, "Added BSS %pM\n", |
340 | rx_mgmt_frame->bssid); | 331 | rx_mgmt_frame->bssid); |
@@ -342,6 +333,9 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) | |||
342 | } else { | 333 | } else { |
343 | wil_err(wil, "cfg80211_inform_bss() failed\n"); | 334 | wil_err(wil, "cfg80211_inform_bss() failed\n"); |
344 | } | 335 | } |
336 | } else { | ||
337 | cfg80211_rx_mgmt(wil->wdev, freq, signal, | ||
338 | (void *)rx_mgmt_frame, d_len, GFP_KERNEL); | ||
345 | } | 339 | } |
346 | } | 340 | } |
347 | 341 | ||
@@ -443,7 +437,7 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) | |||
443 | memcpy(wil->dst_addr[0], evt->bssid, ETH_ALEN); | 437 | memcpy(wil->dst_addr[0], evt->bssid, ETH_ALEN); |
444 | 438 | ||
445 | wil->pending_connect_cid = evt->cid; | 439 | wil->pending_connect_cid = evt->cid; |
446 | queue_work(wil->wmi_wq_conn, &wil->wmi_connect_worker); | 440 | queue_work(wil->wmi_wq_conn, &wil->connect_worker); |
447 | } | 441 | } |
448 | 442 | ||
449 | static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, | 443 | static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, |
@@ -528,6 +522,37 @@ static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id, | |||
528 | } | 522 | } |
529 | } | 523 | } |
530 | 524 | ||
525 | static void wmi_evt_linkup(struct wil6210_priv *wil, int id, void *d, int len) | ||
526 | { | ||
527 | struct net_device *ndev = wil_to_ndev(wil); | ||
528 | struct wmi_data_port_open_event *evt = d; | ||
529 | |||
530 | wil_dbg_wmi(wil, "Link UP for CID %d\n", evt->cid); | ||
531 | |||
532 | netif_carrier_on(ndev); | ||
533 | } | ||
534 | |||
535 | static void wmi_evt_linkdown(struct wil6210_priv *wil, int id, void *d, int len) | ||
536 | { | ||
537 | struct net_device *ndev = wil_to_ndev(wil); | ||
538 | struct wmi_wbe_link_down_event *evt = d; | ||
539 | |||
540 | wil_dbg_wmi(wil, "Link DOWN for CID %d, reason %d\n", | ||
541 | evt->cid, le32_to_cpu(evt->reason)); | ||
542 | |||
543 | netif_carrier_off(ndev); | ||
544 | } | ||
545 | |||
546 | static void wmi_evt_ba_status(struct wil6210_priv *wil, int id, void *d, | ||
547 | int len) | ||
548 | { | ||
549 | struct wmi_vring_ba_status_event *evt = d; | ||
550 | |||
551 | wil_dbg_wmi(wil, "BACK[%d] %s {%d} timeout %d\n", | ||
552 | evt->ringid, evt->status ? "N/A" : "OK", evt->agg_wsize, | ||
553 | __le16_to_cpu(evt->ba_timeout)); | ||
554 | } | ||
555 | |||
531 | static const struct { | 556 | static const struct { |
532 | int eventid; | 557 | int eventid; |
533 | void (*handler)(struct wil6210_priv *wil, int eventid, | 558 | void (*handler)(struct wil6210_priv *wil, int eventid, |
@@ -541,6 +566,9 @@ static const struct { | |||
541 | {WMI_DISCONNECT_EVENTID, wmi_evt_disconnect}, | 566 | {WMI_DISCONNECT_EVENTID, wmi_evt_disconnect}, |
542 | {WMI_NOTIFY_REQ_DONE_EVENTID, wmi_evt_notify}, | 567 | {WMI_NOTIFY_REQ_DONE_EVENTID, wmi_evt_notify}, |
543 | {WMI_EAPOL_RX_EVENTID, wmi_evt_eapol_rx}, | 568 | {WMI_EAPOL_RX_EVENTID, wmi_evt_eapol_rx}, |
569 | {WMI_DATA_PORT_OPEN_EVENTID, wmi_evt_linkup}, | ||
570 | {WMI_WBE_LINKDOWN_EVENTID, wmi_evt_linkdown}, | ||
571 | {WMI_BA_STATUS_EVENTID, wmi_evt_ba_status}, | ||
544 | }; | 572 | }; |
545 | 573 | ||
546 | /* | 574 | /* |
@@ -559,6 +587,11 @@ void wmi_recv_cmd(struct wil6210_priv *wil) | |||
559 | void __iomem *src; | 587 | void __iomem *src; |
560 | ulong flags; | 588 | ulong flags; |
561 | 589 | ||
590 | if (!test_bit(wil_status_reset_done, &wil->status)) { | ||
591 | wil_err(wil, "Reset not completed\n"); | ||
592 | return; | ||
593 | } | ||
594 | |||
562 | for (;;) { | 595 | for (;;) { |
563 | u16 len; | 596 | u16 len; |
564 | 597 | ||
@@ -683,18 +716,39 @@ int wmi_set_mac_address(struct wil6210_priv *wil, void *addr) | |||
683 | return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd)); | 716 | return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd)); |
684 | } | 717 | } |
685 | 718 | ||
686 | int wmi_set_bcon(struct wil6210_priv *wil, int bi, u8 wmi_nettype) | 719 | int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan) |
687 | { | 720 | { |
688 | struct wmi_bcon_ctrl_cmd cmd = { | 721 | int rc; |
722 | |||
723 | struct wmi_pcp_start_cmd cmd = { | ||
689 | .bcon_interval = cpu_to_le16(bi), | 724 | .bcon_interval = cpu_to_le16(bi), |
690 | .network_type = wmi_nettype, | 725 | .network_type = wmi_nettype, |
691 | .disable_sec_offload = 1, | 726 | .disable_sec_offload = 1, |
727 | .channel = chan, | ||
692 | }; | 728 | }; |
729 | struct { | ||
730 | struct wil6210_mbox_hdr_wmi wmi; | ||
731 | struct wmi_pcp_started_event evt; | ||
732 | } __packed reply; | ||
693 | 733 | ||
694 | if (!wil->secure_pcp) | 734 | if (!wil->secure_pcp) |
695 | cmd.disable_sec = 1; | 735 | cmd.disable_sec = 1; |
696 | 736 | ||
697 | return wmi_send(wil, WMI_BCON_CTRL_CMDID, &cmd, sizeof(cmd)); | 737 | rc = wmi_call(wil, WMI_PCP_START_CMDID, &cmd, sizeof(cmd), |
738 | WMI_PCP_STARTED_EVENTID, &reply, sizeof(reply), 100); | ||
739 | if (rc) | ||
740 | return rc; | ||
741 | |||
742 | if (reply.evt.status != WMI_FW_STATUS_SUCCESS) | ||
743 | rc = -EINVAL; | ||
744 | |||
745 | return rc; | ||
746 | } | ||
747 | |||
748 | int wmi_pcp_stop(struct wil6210_priv *wil) | ||
749 | { | ||
750 | return wmi_call(wil, WMI_PCP_STOP_CMDID, NULL, 0, | ||
751 | WMI_PCP_STOPPED_EVENTID, NULL, 0, 20); | ||
698 | } | 752 | } |
699 | 753 | ||
700 | int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid) | 754 | int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid) |
@@ -765,6 +819,16 @@ int wmi_get_channel(struct wil6210_priv *wil, int *channel) | |||
765 | return 0; | 819 | return 0; |
766 | } | 820 | } |
767 | 821 | ||
822 | int wmi_p2p_cfg(struct wil6210_priv *wil, int channel) | ||
823 | { | ||
824 | struct wmi_p2p_cfg_cmd cmd = { | ||
825 | .discovery_mode = WMI_DISCOVERY_MODE_NON_OFFLOAD, | ||
826 | .channel = channel - 1, | ||
827 | }; | ||
828 | |||
829 | return wmi_send(wil, WMI_P2P_CFG_CMDID, &cmd, sizeof(cmd)); | ||
830 | } | ||
831 | |||
768 | int wmi_tx_eapol(struct wil6210_priv *wil, struct sk_buff *skb) | 832 | int wmi_tx_eapol(struct wil6210_priv *wil, struct sk_buff *skb) |
769 | { | 833 | { |
770 | struct wmi_eapol_tx_cmd *cmd; | 834 | struct wmi_eapol_tx_cmd *cmd; |
@@ -843,7 +907,7 @@ int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie) | |||
843 | /* BUG: FW API define ieLen as u8. Will fix FW */ | 907 | /* BUG: FW API define ieLen as u8. Will fix FW */ |
844 | cmd->ie_len = cpu_to_le16(ie_len); | 908 | cmd->ie_len = cpu_to_le16(ie_len); |
845 | memcpy(cmd->ie_info, ie, ie_len); | 909 | memcpy(cmd->ie_info, ie, ie_len); |
846 | rc = wmi_send(wil, WMI_SET_APPIE_CMDID, &cmd, len); | 910 | rc = wmi_send(wil, WMI_SET_APPIE_CMDID, cmd, len); |
847 | kfree(cmd); | 911 | kfree(cmd); |
848 | 912 | ||
849 | return rc; | 913 | return rc; |
@@ -898,6 +962,31 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring) | |||
898 | return rc; | 962 | return rc; |
899 | } | 963 | } |
900 | 964 | ||
965 | int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r) | ||
966 | { | ||
967 | int rc; | ||
968 | struct wmi_temp_sense_cmd cmd = { | ||
969 | .measure_marlon_m_en = cpu_to_le32(!!t_m), | ||
970 | .measure_marlon_r_en = cpu_to_le32(!!t_r), | ||
971 | }; | ||
972 | struct { | ||
973 | struct wil6210_mbox_hdr_wmi wmi; | ||
974 | struct wmi_temp_sense_done_event evt; | ||
975 | } __packed reply; | ||
976 | |||
977 | rc = wmi_call(wil, WMI_TEMP_SENSE_CMDID, &cmd, sizeof(cmd), | ||
978 | WMI_TEMP_SENSE_DONE_EVENTID, &reply, sizeof(reply), 100); | ||
979 | if (rc) | ||
980 | return rc; | ||
981 | |||
982 | if (t_m) | ||
983 | *t_m = le32_to_cpu(reply.evt.marlon_m_t1000); | ||
984 | if (t_r) | ||
985 | *t_r = le32_to_cpu(reply.evt.marlon_r_t1000); | ||
986 | |||
987 | return 0; | ||
988 | } | ||
989 | |||
901 | void wmi_event_flush(struct wil6210_priv *wil) | 990 | void wmi_event_flush(struct wil6210_priv *wil) |
902 | { | 991 | { |
903 | struct pending_wmi_event *evt, *t; | 992 | struct pending_wmi_event *evt, *t; |
@@ -997,24 +1086,3 @@ void wmi_event_worker(struct work_struct *work) | |||
997 | kfree(evt); | 1086 | kfree(evt); |
998 | } | 1087 | } |
999 | } | 1088 | } |
1000 | |||
1001 | void wmi_connect_worker(struct work_struct *work) | ||
1002 | { | ||
1003 | int rc; | ||
1004 | struct wil6210_priv *wil = container_of(work, struct wil6210_priv, | ||
1005 | wmi_connect_worker); | ||
1006 | |||
1007 | if (wil->pending_connect_cid < 0) { | ||
1008 | wil_err(wil, "No connection pending\n"); | ||
1009 | return; | ||
1010 | } | ||
1011 | |||
1012 | wil_dbg_wmi(wil, "Configure for connection CID %d\n", | ||
1013 | wil->pending_connect_cid); | ||
1014 | |||
1015 | rc = wil_vring_init_tx(wil, 0, WIL6210_TX_RING_SIZE, | ||
1016 | wil->pending_connect_cid, 0); | ||
1017 | wil->pending_connect_cid = -1; | ||
1018 | if (rc == 0) | ||
1019 | wil_link_on(wil); | ||
1020 | } | ||
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h index 3bbf87572b07..50b8528394f4 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.h +++ b/drivers/net/wireless/ath/wil6210/wmi.h | |||
@@ -36,6 +36,7 @@ | |||
36 | enum wmi_command_id { | 36 | enum wmi_command_id { |
37 | WMI_CONNECT_CMDID = 0x0001, | 37 | WMI_CONNECT_CMDID = 0x0001, |
38 | WMI_DISCONNECT_CMDID = 0x0003, | 38 | WMI_DISCONNECT_CMDID = 0x0003, |
39 | WMI_DISCONNECT_STA_CMDID = 0x0004, | ||
39 | WMI_START_SCAN_CMDID = 0x0007, | 40 | WMI_START_SCAN_CMDID = 0x0007, |
40 | WMI_SET_BSS_FILTER_CMDID = 0x0009, | 41 | WMI_SET_BSS_FILTER_CMDID = 0x0009, |
41 | WMI_SET_PROBED_SSID_CMDID = 0x000a, | 42 | WMI_SET_PROBED_SSID_CMDID = 0x000a, |
@@ -44,7 +45,6 @@ enum wmi_command_id { | |||
44 | WMI_ADD_CIPHER_KEY_CMDID = 0x0016, | 45 | WMI_ADD_CIPHER_KEY_CMDID = 0x0016, |
45 | WMI_DELETE_CIPHER_KEY_CMDID = 0x0017, | 46 | WMI_DELETE_CIPHER_KEY_CMDID = 0x0017, |
46 | WMI_SET_APPIE_CMDID = 0x003f, | 47 | WMI_SET_APPIE_CMDID = 0x003f, |
47 | WMI_GET_APPIE_CMDID = 0x0040, | ||
48 | WMI_SET_WSC_STATUS_CMDID = 0x0041, | 48 | WMI_SET_WSC_STATUS_CMDID = 0x0041, |
49 | WMI_PXMT_RANGE_CFG_CMDID = 0x0042, | 49 | WMI_PXMT_RANGE_CFG_CMDID = 0x0042, |
50 | WMI_PXMT_SNR2_RANGE_CFG_CMDID = 0x0043, | 50 | WMI_PXMT_SNR2_RANGE_CFG_CMDID = 0x0043, |
@@ -55,11 +55,11 @@ enum wmi_command_id { | |||
55 | WMI_DEEP_ECHO_CMDID = 0x0804, | 55 | WMI_DEEP_ECHO_CMDID = 0x0804, |
56 | WMI_CONFIG_MAC_CMDID = 0x0805, | 56 | WMI_CONFIG_MAC_CMDID = 0x0805, |
57 | WMI_CONFIG_PHY_DEBUG_CMDID = 0x0806, | 57 | WMI_CONFIG_PHY_DEBUG_CMDID = 0x0806, |
58 | WMI_ADD_STATION_CMDID = 0x0807, | ||
59 | WMI_ADD_DEBUG_TX_PCKT_CMDID = 0x0808, | 58 | WMI_ADD_DEBUG_TX_PCKT_CMDID = 0x0808, |
60 | WMI_PHY_GET_STATISTICS_CMDID = 0x0809, | 59 | WMI_PHY_GET_STATISTICS_CMDID = 0x0809, |
61 | WMI_FS_TUNE_CMDID = 0x080a, | 60 | WMI_FS_TUNE_CMDID = 0x080a, |
62 | WMI_CORR_MEASURE_CMDID = 0x080b, | 61 | WMI_CORR_MEASURE_CMDID = 0x080b, |
62 | WMI_READ_RSSI_CMDID = 0x080c, | ||
63 | WMI_TEMP_SENSE_CMDID = 0x080e, | 63 | WMI_TEMP_SENSE_CMDID = 0x080e, |
64 | WMI_DC_CALIB_CMDID = 0x080f, | 64 | WMI_DC_CALIB_CMDID = 0x080f, |
65 | WMI_SEND_TONE_CMDID = 0x0810, | 65 | WMI_SEND_TONE_CMDID = 0x0810, |
@@ -75,9 +75,9 @@ enum wmi_command_id { | |||
75 | MAC_IO_STATIC_PARAMS_CMDID = 0x081b, | 75 | MAC_IO_STATIC_PARAMS_CMDID = 0x081b, |
76 | MAC_IO_DYNAMIC_PARAMS_CMDID = 0x081c, | 76 | MAC_IO_DYNAMIC_PARAMS_CMDID = 0x081c, |
77 | WMI_SILENT_RSSI_CALIB_CMDID = 0x081d, | 77 | WMI_SILENT_RSSI_CALIB_CMDID = 0x081d, |
78 | WMI_RF_RX_TEST_CMDID = 0x081e, | ||
78 | WMI_CFG_RX_CHAIN_CMDID = 0x0820, | 79 | WMI_CFG_RX_CHAIN_CMDID = 0x0820, |
79 | WMI_VRING_CFG_CMDID = 0x0821, | 80 | WMI_VRING_CFG_CMDID = 0x0821, |
80 | WMI_RX_ON_CMDID = 0x0822, | ||
81 | WMI_VRING_BA_EN_CMDID = 0x0823, | 81 | WMI_VRING_BA_EN_CMDID = 0x0823, |
82 | WMI_VRING_BA_DIS_CMDID = 0x0824, | 82 | WMI_VRING_BA_DIS_CMDID = 0x0824, |
83 | WMI_RCP_ADDBA_RESP_CMDID = 0x0825, | 83 | WMI_RCP_ADDBA_RESP_CMDID = 0x0825, |
@@ -87,7 +87,6 @@ enum wmi_command_id { | |||
87 | WMI_SET_PCP_CHANNEL_CMDID = 0x0829, | 87 | WMI_SET_PCP_CHANNEL_CMDID = 0x0829, |
88 | WMI_GET_PCP_CHANNEL_CMDID = 0x082a, | 88 | WMI_GET_PCP_CHANNEL_CMDID = 0x082a, |
89 | WMI_SW_TX_REQ_CMDID = 0x082b, | 89 | WMI_SW_TX_REQ_CMDID = 0x082b, |
90 | WMI_RX_OFF_CMDID = 0x082c, | ||
91 | WMI_READ_MAC_RXQ_CMDID = 0x0830, | 90 | WMI_READ_MAC_RXQ_CMDID = 0x0830, |
92 | WMI_READ_MAC_TXQ_CMDID = 0x0831, | 91 | WMI_READ_MAC_TXQ_CMDID = 0x0831, |
93 | WMI_WRITE_MAC_RXQ_CMDID = 0x0832, | 92 | WMI_WRITE_MAC_RXQ_CMDID = 0x0832, |
@@ -112,6 +111,18 @@ enum wmi_command_id { | |||
112 | WMI_FLASH_READ_CMDID = 0x0902, | 111 | WMI_FLASH_READ_CMDID = 0x0902, |
113 | WMI_FLASH_WRITE_CMDID = 0x0903, | 112 | WMI_FLASH_WRITE_CMDID = 0x0903, |
114 | WMI_SECURITY_UNIT_TEST_CMDID = 0x0904, | 113 | WMI_SECURITY_UNIT_TEST_CMDID = 0x0904, |
114 | /*P2P*/ | ||
115 | WMI_P2P_CFG_CMDID = 0x0910, | ||
116 | WMI_PORT_ALLOCATE_CMDID = 0x0911, | ||
117 | WMI_PORT_DELETE_CMDID = 0x0912, | ||
118 | WMI_POWER_MGMT_CFG_CMDID = 0x0913, | ||
119 | WMI_START_LISTEN_CMDID = 0x0914, | ||
120 | WMI_START_SEARCH_CMDID = 0x0915, | ||
121 | WMI_DISCOVERY_START_CMDID = 0x0916, | ||
122 | WMI_DISCOVERY_STOP_CMDID = 0x0917, | ||
123 | WMI_PCP_START_CMDID = 0x0918, | ||
124 | WMI_PCP_STOP_CMDID = 0x0919, | ||
125 | WMI_GET_PCP_FACTOR_CMDID = 0x091b, | ||
115 | 126 | ||
116 | WMI_SET_MAC_ADDRESS_CMDID = 0xf003, | 127 | WMI_SET_MAC_ADDRESS_CMDID = 0xf003, |
117 | WMI_ABORT_SCAN_CMDID = 0xf007, | 128 | WMI_ABORT_SCAN_CMDID = 0xf007, |
@@ -132,18 +143,6 @@ enum wmi_command_id { | |||
132 | */ | 143 | */ |
133 | 144 | ||
134 | /* | 145 | /* |
135 | * Frame Types | ||
136 | */ | ||
137 | enum wmi_mgmt_frame_type { | ||
138 | WMI_FRAME_BEACON = 0, | ||
139 | WMI_FRAME_PROBE_REQ = 1, | ||
140 | WMI_FRAME_PROBE_RESP = 2, | ||
141 | WMI_FRAME_ASSOC_REQ = 3, | ||
142 | WMI_FRAME_ASSOC_RESP = 4, | ||
143 | WMI_NUM_MGMT_FRAME, | ||
144 | }; | ||
145 | |||
146 | /* | ||
147 | * WMI_CONNECT_CMDID | 146 | * WMI_CONNECT_CMDID |
148 | */ | 147 | */ |
149 | enum wmi_network_type { | 148 | enum wmi_network_type { |
@@ -184,7 +183,7 @@ enum wmi_crypto_type { | |||
184 | enum wmi_connect_ctrl_flag_bits { | 183 | enum wmi_connect_ctrl_flag_bits { |
185 | WMI_CONNECT_ASSOC_POLICY_USER = 0x0001, | 184 | WMI_CONNECT_ASSOC_POLICY_USER = 0x0001, |
186 | WMI_CONNECT_SEND_REASSOC = 0x0002, | 185 | WMI_CONNECT_SEND_REASSOC = 0x0002, |
187 | WMI_CONNECT_IGNORE_WPAx_GROUP_CIPHER = 0x0004, | 186 | WMI_CONNECT_IGNORE_WPA_GROUP_CIPHER = 0x0004, |
188 | WMI_CONNECT_PROFILE_MATCH_DONE = 0x0008, | 187 | WMI_CONNECT_PROFILE_MATCH_DONE = 0x0008, |
189 | WMI_CONNECT_IGNORE_AAC_BEACON = 0x0010, | 188 | WMI_CONNECT_IGNORE_AAC_BEACON = 0x0010, |
190 | WMI_CONNECT_CSA_FOLLOW_BSS = 0x0020, | 189 | WMI_CONNECT_CSA_FOLLOW_BSS = 0x0020, |
@@ -212,6 +211,13 @@ struct wmi_connect_cmd { | |||
212 | u8 reserved1[2]; | 211 | u8 reserved1[2]; |
213 | } __packed; | 212 | } __packed; |
214 | 213 | ||
214 | /* | ||
215 | * WMI_DISCONNECT_STA_CMDID | ||
216 | */ | ||
217 | struct wmi_disconnect_sta_cmd { | ||
218 | u8 dst_mac[WMI_MAC_LEN]; | ||
219 | __le16 disconnect_reason; | ||
220 | } __packed; | ||
215 | 221 | ||
216 | /* | 222 | /* |
217 | * WMI_RECONNECT_CMDID | 223 | * WMI_RECONNECT_CMDID |
@@ -289,10 +295,12 @@ struct wmi_delete_cipher_key_cmd { | |||
289 | enum wmi_scan_type { | 295 | enum wmi_scan_type { |
290 | WMI_LONG_SCAN = 0, | 296 | WMI_LONG_SCAN = 0, |
291 | WMI_SHORT_SCAN = 1, | 297 | WMI_SHORT_SCAN = 1, |
298 | WMI_PBC_SCAN = 2, | ||
292 | }; | 299 | }; |
293 | 300 | ||
294 | struct wmi_start_scan_cmd { | 301 | struct wmi_start_scan_cmd { |
295 | u8 reserved[8]; | 302 | u8 reserved[8]; |
303 | |||
296 | __le32 home_dwell_time; /* Max duration in the home channel(ms) */ | 304 | __le32 home_dwell_time; /* Max duration in the home channel(ms) */ |
297 | __le32 force_scan_interval; /* Time interval between scans (ms)*/ | 305 | __le32 force_scan_interval; /* Time interval between scans (ms)*/ |
298 | u8 scan_type; /* wmi_scan_type */ | 306 | u8 scan_type; /* wmi_scan_type */ |
@@ -309,7 +317,7 @@ struct wmi_start_scan_cmd { | |||
309 | /* | 317 | /* |
310 | * WMI_SET_PROBED_SSID_CMDID | 318 | * WMI_SET_PROBED_SSID_CMDID |
311 | */ | 319 | */ |
312 | #define MAX_PROBED_SSID_INDEX (15) | 320 | #define MAX_PROBED_SSID_INDEX (3) |
313 | 321 | ||
314 | enum wmi_ssid_flag { | 322 | enum wmi_ssid_flag { |
315 | WMI_SSID_FLAG_DISABLE = 0, /* disables entry */ | 323 | WMI_SSID_FLAG_DISABLE = 0, /* disables entry */ |
@@ -328,6 +336,20 @@ struct wmi_probed_ssid_cmd { | |||
328 | * WMI_SET_APPIE_CMDID | 336 | * WMI_SET_APPIE_CMDID |
329 | * Add Application specified IE to a management frame | 337 | * Add Application specified IE to a management frame |
330 | */ | 338 | */ |
339 | #define WMI_MAX_IE_LEN (1024) | ||
340 | |||
341 | /* | ||
342 | * Frame Types | ||
343 | */ | ||
344 | enum wmi_mgmt_frame_type { | ||
345 | WMI_FRAME_BEACON = 0, | ||
346 | WMI_FRAME_PROBE_REQ = 1, | ||
347 | WMI_FRAME_PROBE_RESP = 2, | ||
348 | WMI_FRAME_ASSOC_REQ = 3, | ||
349 | WMI_FRAME_ASSOC_RESP = 4, | ||
350 | WMI_NUM_MGMT_FRAME, | ||
351 | }; | ||
352 | |||
331 | struct wmi_set_appie_cmd { | 353 | struct wmi_set_appie_cmd { |
332 | u8 mgmt_frm_type; /* enum wmi_mgmt_frame_type */ | 354 | u8 mgmt_frm_type; /* enum wmi_mgmt_frame_type */ |
333 | u8 reserved; | 355 | u8 reserved; |
@@ -335,13 +357,18 @@ struct wmi_set_appie_cmd { | |||
335 | u8 ie_info[0]; | 357 | u8 ie_info[0]; |
336 | } __packed; | 358 | } __packed; |
337 | 359 | ||
338 | #define WMI_MAX_IE_LEN (1024) | ||
339 | 360 | ||
361 | /* | ||
362 | * WMI_PXMT_RANGE_CFG_CMDID | ||
363 | */ | ||
340 | struct wmi_pxmt_range_cfg_cmd { | 364 | struct wmi_pxmt_range_cfg_cmd { |
341 | u8 dst_mac[WMI_MAC_LEN]; | 365 | u8 dst_mac[WMI_MAC_LEN]; |
342 | __le16 range; | 366 | __le16 range; |
343 | } __packed; | 367 | } __packed; |
344 | 368 | ||
369 | /* | ||
370 | * WMI_PXMT_SNR2_RANGE_CFG_CMDID | ||
371 | */ | ||
345 | struct wmi_pxmt_snr2_range_cfg_cmd { | 372 | struct wmi_pxmt_snr2_range_cfg_cmd { |
346 | s8 snr2range_arr[WMI_PROX_RANGE_NUM-1]; | 373 | s8 snr2range_arr[WMI_PROX_RANGE_NUM-1]; |
347 | } __packed; | 374 | } __packed; |
@@ -359,6 +386,23 @@ struct wmi_rf_mgmt_cmd { | |||
359 | __le32 rf_mgmt_type; | 386 | __le32 rf_mgmt_type; |
360 | } __packed; | 387 | } __packed; |
361 | 388 | ||
389 | |||
390 | /* | ||
391 | * WMI_RF_RX_TEST_CMDID | ||
392 | */ | ||
393 | struct wmi_rf_rx_test_cmd { | ||
394 | __le32 sector; | ||
395 | } __packed; | ||
396 | |||
397 | /* | ||
398 | * WMI_CORR_MEASURE_CMDID | ||
399 | */ | ||
400 | struct wmi_corr_measure_cmd { | ||
401 | s32 freq_mhz; | ||
402 | __le32 length_samples; | ||
403 | __le32 iterations; | ||
404 | } __packed; | ||
405 | |||
362 | /* | 406 | /* |
363 | * WMI_SET_SSID_CMDID | 407 | * WMI_SET_SSID_CMDID |
364 | */ | 408 | */ |
@@ -388,6 +432,74 @@ struct wmi_bcon_ctrl_cmd { | |||
388 | u8 disable_sec; | 432 | u8 disable_sec; |
389 | } __packed; | 433 | } __packed; |
390 | 434 | ||
435 | |||
436 | /******* P2P ***********/ | ||
437 | |||
438 | /* | ||
439 | * WMI_PORT_ALLOCATE_CMDID | ||
440 | */ | ||
441 | enum wmi_port_role { | ||
442 | WMI_PORT_STA = 0, | ||
443 | WMI_PORT_PCP = 1, | ||
444 | WMI_PORT_AP = 2, | ||
445 | WMI_PORT_P2P_DEV = 3, | ||
446 | WMI_PORT_P2P_CLIENT = 4, | ||
447 | WMI_PORT_P2P_GO = 5, | ||
448 | }; | ||
449 | |||
450 | struct wmi_port_allocate_cmd { | ||
451 | u8 mac[WMI_MAC_LEN]; | ||
452 | u8 port_role; | ||
453 | u8 midid; | ||
454 | } __packed; | ||
455 | |||
456 | /* | ||
457 | * WMI_PORT_DELETE_CMDID | ||
458 | */ | ||
459 | struct wmi_delete_port_cmd { | ||
460 | u8 mid; | ||
461 | u8 reserved[3]; | ||
462 | } __packed; | ||
463 | |||
464 | /* | ||
465 | * WMI_P2P_CFG_CMDID | ||
466 | */ | ||
467 | enum wmi_discovery_mode { | ||
468 | WMI_DISCOVERY_MODE_NON_OFFLOAD = 0, | ||
469 | WMI_DISCOVERY_MODE_OFFLOAD = 1, | ||
470 | }; | ||
471 | |||
472 | struct wmi_p2p_cfg_cmd { | ||
473 | u8 discovery_mode; /* wmi_discovery_mode */ | ||
474 | u8 channel; | ||
475 | __le16 bcon_interval; /* base to listen/search duration calculation */ | ||
476 | } __packed; | ||
477 | |||
478 | /* | ||
479 | * WMI_POWER_MGMT_CFG_CMDID | ||
480 | */ | ||
481 | enum wmi_power_source_type { | ||
482 | WMI_POWER_SOURCE_BATTERY = 0, | ||
483 | WMI_POWER_SOURCE_OTHER = 1, | ||
484 | }; | ||
485 | |||
486 | struct wmi_power_mgmt_cfg_cmd { | ||
487 | u8 power_source; /* wmi_power_source_type */ | ||
488 | u8 reserved[3]; | ||
489 | } __packed; | ||
490 | |||
491 | /* | ||
492 | * WMI_PCP_START_CMDID | ||
493 | */ | ||
494 | struct wmi_pcp_start_cmd { | ||
495 | __le16 bcon_interval; | ||
496 | u8 reserved0[10]; | ||
497 | u8 network_type; | ||
498 | u8 channel; | ||
499 | u8 disable_sec_offload; | ||
500 | u8 disable_sec; | ||
501 | } __packed; | ||
502 | |||
391 | /* | 503 | /* |
392 | * WMI_SW_TX_REQ_CMDID | 504 | * WMI_SW_TX_REQ_CMDID |
393 | */ | 505 | */ |
@@ -435,16 +547,17 @@ enum wmi_vring_cfg_schd_params_priority { | |||
435 | WMI_SCH_PRIO_HIGH = 1, | 547 | WMI_SCH_PRIO_HIGH = 1, |
436 | }; | 548 | }; |
437 | 549 | ||
550 | #define CIDXTID_CID_POS (0) | ||
551 | #define CIDXTID_CID_LEN (4) | ||
552 | #define CIDXTID_CID_MSK (0xF) | ||
553 | #define CIDXTID_TID_POS (4) | ||
554 | #define CIDXTID_TID_LEN (4) | ||
555 | #define CIDXTID_TID_MSK (0xF0) | ||
556 | |||
438 | struct wmi_vring_cfg { | 557 | struct wmi_vring_cfg { |
439 | struct wmi_sw_ring_cfg tx_sw_ring; | 558 | struct wmi_sw_ring_cfg tx_sw_ring; |
440 | u8 ringid; /* 0-23 vrings */ | 559 | u8 ringid; /* 0-23 vrings */ |
441 | 560 | ||
442 | #define CIDXTID_CID_POS (0) | ||
443 | #define CIDXTID_CID_LEN (4) | ||
444 | #define CIDXTID_CID_MSK (0xF) | ||
445 | #define CIDXTID_TID_POS (4) | ||
446 | #define CIDXTID_TID_LEN (4) | ||
447 | #define CIDXTID_TID_MSK (0xF0) | ||
448 | u8 cidxtid; | 561 | u8 cidxtid; |
449 | 562 | ||
450 | u8 encap_trans_type; | 563 | u8 encap_trans_type; |
@@ -501,8 +614,14 @@ struct wmi_vring_ba_dis_cmd { | |||
501 | */ | 614 | */ |
502 | struct wmi_notify_req_cmd { | 615 | struct wmi_notify_req_cmd { |
503 | u8 cid; | 616 | u8 cid; |
504 | u8 reserved[3]; | 617 | u8 year; |
618 | u8 month; | ||
619 | u8 day; | ||
505 | __le32 interval_usec; | 620 | __le32 interval_usec; |
621 | u8 hour; | ||
622 | u8 minute; | ||
623 | u8 second; | ||
624 | u8 miliseconds; | ||
506 | } __packed; | 625 | } __packed; |
507 | 626 | ||
508 | /* | 627 | /* |
@@ -548,6 +667,11 @@ enum wmi_cfg_rx_chain_cmd_nwifi_ds_trans_type { | |||
548 | WMI_NWIFI_RX_TRANS_MODE_PBSS2STA = 2, | 667 | WMI_NWIFI_RX_TRANS_MODE_PBSS2STA = 2, |
549 | }; | 668 | }; |
550 | 669 | ||
670 | enum wmi_cfg_rx_chain_cmd_reorder_type { | ||
671 | WMI_RX_HW_REORDER = 0, | ||
672 | WMI_RX_SW_REORDER = 1, | ||
673 | }; | ||
674 | |||
551 | struct wmi_cfg_rx_chain_cmd { | 675 | struct wmi_cfg_rx_chain_cmd { |
552 | __le32 action; | 676 | __le32 action; |
553 | struct wmi_sw_ring_cfg rx_sw_ring; | 677 | struct wmi_sw_ring_cfg rx_sw_ring; |
@@ -596,7 +720,8 @@ struct wmi_cfg_rx_chain_cmd { | |||
596 | __le16 wb_thrsh; | 720 | __le16 wb_thrsh; |
597 | __le32 itr_value; | 721 | __le32 itr_value; |
598 | __le16 host_thrsh; | 722 | __le16 host_thrsh; |
599 | u8 reserved[2]; | 723 | u8 reorder_type; |
724 | u8 reserved; | ||
600 | struct wmi_sniffer_cfg sniffer_cfg; | 725 | struct wmi_sniffer_cfg sniffer_cfg; |
601 | } __packed; | 726 | } __packed; |
602 | 727 | ||
@@ -604,15 +729,7 @@ struct wmi_cfg_rx_chain_cmd { | |||
604 | * WMI_RCP_ADDBA_RESP_CMDID | 729 | * WMI_RCP_ADDBA_RESP_CMDID |
605 | */ | 730 | */ |
606 | struct wmi_rcp_addba_resp_cmd { | 731 | struct wmi_rcp_addba_resp_cmd { |
607 | |||
608 | #define CIDXTID_CID_POS (0) | ||
609 | #define CIDXTID_CID_LEN (4) | ||
610 | #define CIDXTID_CID_MSK (0xF) | ||
611 | #define CIDXTID_TID_POS (4) | ||
612 | #define CIDXTID_TID_LEN (4) | ||
613 | #define CIDXTID_TID_MSK (0xF0) | ||
614 | u8 cidxtid; | 732 | u8 cidxtid; |
615 | |||
616 | u8 dialog_token; | 733 | u8 dialog_token; |
617 | __le16 status_code; | 734 | __le16 status_code; |
618 | __le16 ba_param_set; /* ieee80211_ba_parameterset field to send */ | 735 | __le16 ba_param_set; /* ieee80211_ba_parameterset field to send */ |
@@ -623,15 +740,7 @@ struct wmi_rcp_addba_resp_cmd { | |||
623 | * WMI_RCP_DELBA_CMDID | 740 | * WMI_RCP_DELBA_CMDID |
624 | */ | 741 | */ |
625 | struct wmi_rcp_delba_cmd { | 742 | struct wmi_rcp_delba_cmd { |
626 | |||
627 | #define CIDXTID_CID_POS (0) | ||
628 | #define CIDXTID_CID_LEN (4) | ||
629 | #define CIDXTID_CID_MSK (0xF) | ||
630 | #define CIDXTID_TID_POS (4) | ||
631 | #define CIDXTID_TID_LEN (4) | ||
632 | #define CIDXTID_TID_MSK (0xF0) | ||
633 | u8 cidxtid; | 743 | u8 cidxtid; |
634 | |||
635 | u8 reserved; | 744 | u8 reserved; |
636 | __le16 reason; | 745 | __le16 reason; |
637 | } __packed; | 746 | } __packed; |
@@ -640,15 +749,7 @@ struct wmi_rcp_delba_cmd { | |||
640 | * WMI_RCP_ADDBA_REQ_CMDID | 749 | * WMI_RCP_ADDBA_REQ_CMDID |
641 | */ | 750 | */ |
642 | struct wmi_rcp_addba_req_cmd { | 751 | struct wmi_rcp_addba_req_cmd { |
643 | |||
644 | #define CIDXTID_CID_POS (0) | ||
645 | #define CIDXTID_CID_LEN (4) | ||
646 | #define CIDXTID_CID_MSK (0xF) | ||
647 | #define CIDXTID_TID_POS (4) | ||
648 | #define CIDXTID_TID_LEN (4) | ||
649 | #define CIDXTID_TID_MSK (0xF0) | ||
650 | u8 cidxtid; | 752 | u8 cidxtid; |
651 | |||
652 | u8 dialog_token; | 753 | u8 dialog_token; |
653 | /* ieee80211_ba_parameterset field as it received */ | 754 | /* ieee80211_ba_parameterset field as it received */ |
654 | __le16 ba_param_set; | 755 | __le16 ba_param_set; |
@@ -665,7 +766,6 @@ struct wmi_set_mac_address_cmd { | |||
665 | u8 reserved[2]; | 766 | u8 reserved[2]; |
666 | } __packed; | 767 | } __packed; |
667 | 768 | ||
668 | |||
669 | /* | 769 | /* |
670 | * WMI_EAPOL_TX_CMDID | 770 | * WMI_EAPOL_TX_CMDID |
671 | */ | 771 | */ |
@@ -692,6 +792,17 @@ struct wmi_echo_cmd { | |||
692 | } __packed; | 792 | } __packed; |
693 | 793 | ||
694 | /* | 794 | /* |
795 | * WMI_TEMP_SENSE_CMDID | ||
796 | * | ||
797 | * Measure MAC and radio temperatures | ||
798 | */ | ||
799 | struct wmi_temp_sense_cmd { | ||
800 | __le32 measure_marlon_m_en; | ||
801 | __le32 measure_marlon_r_en; | ||
802 | } __packed; | ||
803 | |||
804 | |||
805 | /* | ||
695 | * WMI Events | 806 | * WMI Events |
696 | */ | 807 | */ |
697 | 808 | ||
@@ -699,7 +810,6 @@ struct wmi_echo_cmd { | |||
699 | * List of Events (target to host) | 810 | * List of Events (target to host) |
700 | */ | 811 | */ |
701 | enum wmi_event_id { | 812 | enum wmi_event_id { |
702 | WMI_IMM_RSP_EVENTID = 0x0000, | ||
703 | WMI_READY_EVENTID = 0x1001, | 813 | WMI_READY_EVENTID = 0x1001, |
704 | WMI_CONNECT_EVENTID = 0x1002, | 814 | WMI_CONNECT_EVENTID = 0x1002, |
705 | WMI_DISCONNECT_EVENTID = 0x1003, | 815 | WMI_DISCONNECT_EVENTID = 0x1003, |
@@ -709,13 +819,9 @@ enum wmi_event_id { | |||
709 | WMI_FW_READY_EVENTID = 0x1801, | 819 | WMI_FW_READY_EVENTID = 0x1801, |
710 | WMI_EXIT_FAST_MEM_ACC_MODE_EVENTID = 0x0200, | 820 | WMI_EXIT_FAST_MEM_ACC_MODE_EVENTID = 0x0200, |
711 | WMI_ECHO_RSP_EVENTID = 0x1803, | 821 | WMI_ECHO_RSP_EVENTID = 0x1803, |
712 | WMI_CONFIG_MAC_DONE_EVENTID = 0x1805, | ||
713 | WMI_CONFIG_PHY_DEBUG_DONE_EVENTID = 0x1806, | ||
714 | WMI_ADD_STATION_DONE_EVENTID = 0x1807, | ||
715 | WMI_ADD_DEBUG_TX_PCKT_DONE_EVENTID = 0x1808, | ||
716 | WMI_PHY_GET_STATISTICS_EVENTID = 0x1809, | ||
717 | WMI_FS_TUNE_DONE_EVENTID = 0x180a, | 822 | WMI_FS_TUNE_DONE_EVENTID = 0x180a, |
718 | WMI_CORR_MEASURE_DONE_EVENTID = 0x180b, | 823 | WMI_CORR_MEASURE_EVENTID = 0x180b, |
824 | WMI_READ_RSSI_EVENTID = 0x180c, | ||
719 | WMI_TEMP_SENSE_DONE_EVENTID = 0x180e, | 825 | WMI_TEMP_SENSE_DONE_EVENTID = 0x180e, |
720 | WMI_DC_CALIB_DONE_EVENTID = 0x180f, | 826 | WMI_DC_CALIB_DONE_EVENTID = 0x180f, |
721 | WMI_IQ_TX_CALIB_DONE_EVENTID = 0x1811, | 827 | WMI_IQ_TX_CALIB_DONE_EVENTID = 0x1811, |
@@ -727,10 +833,9 @@ enum wmi_event_id { | |||
727 | WMI_MARLON_R_WRITE_DONE_EVENTID = 0x1819, | 833 | WMI_MARLON_R_WRITE_DONE_EVENTID = 0x1819, |
728 | WMI_MARLON_R_TXRX_SEL_DONE_EVENTID = 0x181a, | 834 | WMI_MARLON_R_TXRX_SEL_DONE_EVENTID = 0x181a, |
729 | WMI_SILENT_RSSI_CALIB_DONE_EVENTID = 0x181d, | 835 | WMI_SILENT_RSSI_CALIB_DONE_EVENTID = 0x181d, |
730 | 836 | WMI_RF_RX_TEST_DONE_EVENTID = 0x181e, | |
731 | WMI_CFG_RX_CHAIN_DONE_EVENTID = 0x1820, | 837 | WMI_CFG_RX_CHAIN_DONE_EVENTID = 0x1820, |
732 | WMI_VRING_CFG_DONE_EVENTID = 0x1821, | 838 | WMI_VRING_CFG_DONE_EVENTID = 0x1821, |
733 | WMI_RX_ON_DONE_EVENTID = 0x1822, | ||
734 | WMI_BA_STATUS_EVENTID = 0x1823, | 839 | WMI_BA_STATUS_EVENTID = 0x1823, |
735 | WMI_RCP_ADDBA_REQ_EVENTID = 0x1824, | 840 | WMI_RCP_ADDBA_REQ_EVENTID = 0x1824, |
736 | WMI_ADDBA_RESP_SENT_EVENTID = 0x1825, | 841 | WMI_ADDBA_RESP_SENT_EVENTID = 0x1825, |
@@ -738,7 +843,6 @@ enum wmi_event_id { | |||
738 | WMI_GET_SSID_EVENTID = 0x1828, | 843 | WMI_GET_SSID_EVENTID = 0x1828, |
739 | WMI_GET_PCP_CHANNEL_EVENTID = 0x182a, | 844 | WMI_GET_PCP_CHANNEL_EVENTID = 0x182a, |
740 | WMI_SW_TX_COMPLETE_EVENTID = 0x182b, | 845 | WMI_SW_TX_COMPLETE_EVENTID = 0x182b, |
741 | WMI_RX_OFF_DONE_EVENTID = 0x182c, | ||
742 | 846 | ||
743 | WMI_READ_MAC_RXQ_EVENTID = 0x1830, | 847 | WMI_READ_MAC_RXQ_EVENTID = 0x1830, |
744 | WMI_READ_MAC_TXQ_EVENTID = 0x1831, | 848 | WMI_READ_MAC_TXQ_EVENTID = 0x1831, |
@@ -765,7 +869,16 @@ enum wmi_event_id { | |||
765 | WMI_UNIT_TEST_EVENTID = 0x1900, | 869 | WMI_UNIT_TEST_EVENTID = 0x1900, |
766 | WMI_FLASH_READ_DONE_EVENTID = 0x1902, | 870 | WMI_FLASH_READ_DONE_EVENTID = 0x1902, |
767 | WMI_FLASH_WRITE_DONE_EVENTID = 0x1903, | 871 | WMI_FLASH_WRITE_DONE_EVENTID = 0x1903, |
768 | 872 | /*P2P*/ | |
873 | WMI_PORT_ALLOCATED_EVENTID = 0x1911, | ||
874 | WMI_PORT_DELETED_EVENTID = 0x1912, | ||
875 | WMI_LISTEN_STARTED_EVENTID = 0x1914, | ||
876 | WMI_SEARCH_STARTED_EVENTID = 0x1915, | ||
877 | WMI_DISCOVERY_STARTED_EVENTID = 0x1916, | ||
878 | WMI_DISCOVERY_STOPPED_EVENTID = 0x1917, | ||
879 | WMI_PCP_STARTED_EVENTID = 0x1918, | ||
880 | WMI_PCP_STOPPED_EVENTID = 0x1919, | ||
881 | WMI_PCP_FACTOR_EVENTID = 0x191a, | ||
769 | WMI_SET_CHANNEL_EVENTID = 0x9000, | 882 | WMI_SET_CHANNEL_EVENTID = 0x9000, |
770 | WMI_ASSOC_REQ_EVENTID = 0x9001, | 883 | WMI_ASSOC_REQ_EVENTID = 0x9001, |
771 | WMI_EAPOL_RX_EVENTID = 0x9002, | 884 | WMI_EAPOL_RX_EVENTID = 0x9002, |
@@ -777,6 +890,12 @@ enum wmi_event_id { | |||
777 | * Events data structures | 890 | * Events data structures |
778 | */ | 891 | */ |
779 | 892 | ||
893 | |||
894 | enum wmi_fw_status { | ||
895 | WMI_FW_STATUS_SUCCESS, | ||
896 | WMI_FW_STATUS_FAILURE, | ||
897 | }; | ||
898 | |||
780 | /* | 899 | /* |
781 | * WMI_RF_MGMT_STATUS_EVENTID | 900 | * WMI_RF_MGMT_STATUS_EVENTID |
782 | */ | 901 | */ |
@@ -857,7 +976,7 @@ struct wmi_ready_event { | |||
857 | __le32 abi_version; | 976 | __le32 abi_version; |
858 | u8 mac[WMI_MAC_LEN]; | 977 | u8 mac[WMI_MAC_LEN]; |
859 | u8 phy_capability; /* enum wmi_phy_capability */ | 978 | u8 phy_capability; /* enum wmi_phy_capability */ |
860 | u8 reserved; | 979 | u8 numof_additional_mids; |
861 | } __packed; | 980 | } __packed; |
862 | 981 | ||
863 | /* | 982 | /* |
@@ -876,6 +995,8 @@ struct wmi_notify_req_done_event { | |||
876 | __le16 other_rx_sector; | 995 | __le16 other_rx_sector; |
877 | __le16 other_tx_sector; | 996 | __le16 other_tx_sector; |
878 | __le16 range; | 997 | __le16 range; |
998 | u8 sqi; | ||
999 | u8 reserved[3]; | ||
879 | } __packed; | 1000 | } __packed; |
880 | 1001 | ||
881 | /* | 1002 | /* |
@@ -951,27 +1072,15 @@ struct wmi_vring_ba_status_event { | |||
951 | * WMI_DELBA_EVENTID | 1072 | * WMI_DELBA_EVENTID |
952 | */ | 1073 | */ |
953 | struct wmi_delba_event { | 1074 | struct wmi_delba_event { |
954 | |||
955 | #define CIDXTID_CID_POS (0) | ||
956 | #define CIDXTID_CID_LEN (4) | ||
957 | #define CIDXTID_CID_MSK (0xF) | ||
958 | #define CIDXTID_TID_POS (4) | ||
959 | #define CIDXTID_TID_LEN (4) | ||
960 | #define CIDXTID_TID_MSK (0xF0) | ||
961 | u8 cidxtid; | 1075 | u8 cidxtid; |
962 | |||
963 | u8 from_initiator; | 1076 | u8 from_initiator; |
964 | __le16 reason; | 1077 | __le16 reason; |
965 | } __packed; | 1078 | } __packed; |
966 | 1079 | ||
1080 | |||
967 | /* | 1081 | /* |
968 | * WMI_VRING_CFG_DONE_EVENTID | 1082 | * WMI_VRING_CFG_DONE_EVENTID |
969 | */ | 1083 | */ |
970 | enum wmi_vring_cfg_done_event_status { | ||
971 | WMI_VRING_CFG_SUCCESS = 0, | ||
972 | WMI_VRING_CFG_FAILURE = 1, | ||
973 | }; | ||
974 | |||
975 | struct wmi_vring_cfg_done_event { | 1084 | struct wmi_vring_cfg_done_event { |
976 | u8 ringid; | 1085 | u8 ringid; |
977 | u8 status; | 1086 | u8 status; |
@@ -982,21 +1091,8 @@ struct wmi_vring_cfg_done_event { | |||
982 | /* | 1091 | /* |
983 | * WMI_ADDBA_RESP_SENT_EVENTID | 1092 | * WMI_ADDBA_RESP_SENT_EVENTID |
984 | */ | 1093 | */ |
985 | enum wmi_rcp_addba_resp_sent_event_status { | ||
986 | WMI_ADDBA_SUCCESS = 0, | ||
987 | WMI_ADDBA_FAIL = 1, | ||
988 | }; | ||
989 | |||
990 | struct wmi_rcp_addba_resp_sent_event { | 1094 | struct wmi_rcp_addba_resp_sent_event { |
991 | |||
992 | #define CIDXTID_CID_POS (0) | ||
993 | #define CIDXTID_CID_LEN (4) | ||
994 | #define CIDXTID_CID_MSK (0xF) | ||
995 | #define CIDXTID_TID_POS (4) | ||
996 | #define CIDXTID_TID_LEN (4) | ||
997 | #define CIDXTID_TID_MSK (0xF0) | ||
998 | u8 cidxtid; | 1095 | u8 cidxtid; |
999 | |||
1000 | u8 reserved; | 1096 | u8 reserved; |
1001 | __le16 status; | 1097 | __le16 status; |
1002 | } __packed; | 1098 | } __packed; |
@@ -1005,15 +1101,7 @@ struct wmi_rcp_addba_resp_sent_event { | |||
1005 | * WMI_RCP_ADDBA_REQ_EVENTID | 1101 | * WMI_RCP_ADDBA_REQ_EVENTID |
1006 | */ | 1102 | */ |
1007 | struct wmi_rcp_addba_req_event { | 1103 | struct wmi_rcp_addba_req_event { |
1008 | |||
1009 | #define CIDXTID_CID_POS (0) | ||
1010 | #define CIDXTID_CID_LEN (4) | ||
1011 | #define CIDXTID_CID_MSK (0xF) | ||
1012 | #define CIDXTID_TID_POS (4) | ||
1013 | #define CIDXTID_TID_LEN (4) | ||
1014 | #define CIDXTID_TID_MSK (0xF0) | ||
1015 | u8 cidxtid; | 1104 | u8 cidxtid; |
1016 | |||
1017 | u8 dialog_token; | 1105 | u8 dialog_token; |
1018 | __le16 ba_param_set; /* ieee80211_ba_parameterset as it received */ | 1106 | __le16 ba_param_set; /* ieee80211_ba_parameterset as it received */ |
1019 | __le16 ba_timeout; | 1107 | __le16 ba_timeout; |
@@ -1055,6 +1143,7 @@ struct wmi_data_port_open_event { | |||
1055 | u8 reserved[3]; | 1143 | u8 reserved[3]; |
1056 | } __packed; | 1144 | } __packed; |
1057 | 1145 | ||
1146 | |||
1058 | /* | 1147 | /* |
1059 | * WMI_GET_PCP_CHANNEL_EVENTID | 1148 | * WMI_GET_PCP_CHANNEL_EVENTID |
1060 | */ | 1149 | */ |
@@ -1063,6 +1152,54 @@ struct wmi_get_pcp_channel_event { | |||
1063 | u8 reserved[3]; | 1152 | u8 reserved[3]; |
1064 | } __packed; | 1153 | } __packed; |
1065 | 1154 | ||
1155 | |||
1156 | /* | ||
1157 | * WMI_PORT_ALLOCATED_EVENTID | ||
1158 | */ | ||
1159 | struct wmi_port_allocated_event { | ||
1160 | u8 status; /* wmi_fw_status */ | ||
1161 | u8 reserved[3]; | ||
1162 | } __packed; | ||
1163 | |||
1164 | /* | ||
1165 | * WMI_PORT_DELETED_EVENTID | ||
1166 | */ | ||
1167 | struct wmi_port_deleted_event { | ||
1168 | u8 status; /* wmi_fw_status */ | ||
1169 | u8 reserved[3]; | ||
1170 | } __packed; | ||
1171 | |||
1172 | /* | ||
1173 | * WMI_LISTEN_STARTED_EVENTID | ||
1174 | */ | ||
1175 | struct wmi_listen_started_event { | ||
1176 | u8 status; /* wmi_fw_status */ | ||
1177 | u8 reserved[3]; | ||
1178 | } __packed; | ||
1179 | |||
1180 | /* | ||
1181 | * WMI_SEARCH_STARTED_EVENTID | ||
1182 | */ | ||
1183 | struct wmi_search_started_event { | ||
1184 | u8 status; /* wmi_fw_status */ | ||
1185 | u8 reserved[3]; | ||
1186 | } __packed; | ||
1187 | |||
1188 | /* | ||
1189 | * WMI_PCP_STARTED_EVENTID | ||
1190 | */ | ||
1191 | struct wmi_pcp_started_event { | ||
1192 | u8 status; /* wmi_fw_status */ | ||
1193 | u8 reserved[3]; | ||
1194 | } __packed; | ||
1195 | |||
1196 | /* | ||
1197 | * WMI_PCP_FACTOR_EVENTID | ||
1198 | */ | ||
1199 | struct wmi_pcp_factor_event { | ||
1200 | __le32 pcp_factor; | ||
1201 | } __packed; | ||
1202 | |||
1066 | /* | 1203 | /* |
1067 | * WMI_SW_TX_COMPLETE_EVENTID | 1204 | * WMI_SW_TX_COMPLETE_EVENTID |
1068 | */ | 1205 | */ |
@@ -1078,6 +1215,23 @@ struct wmi_sw_tx_complete_event { | |||
1078 | } __packed; | 1215 | } __packed; |
1079 | 1216 | ||
1080 | /* | 1217 | /* |
1218 | * WMI_CORR_MEASURE_EVENTID | ||
1219 | */ | ||
1220 | struct wmi_corr_measure_event { | ||
1221 | s32 i; | ||
1222 | s32 q; | ||
1223 | s32 image_i; | ||
1224 | s32 image_q; | ||
1225 | } __packed; | ||
1226 | |||
1227 | /* | ||
1228 | * WMI_READ_RSSI_EVENTID | ||
1229 | */ | ||
1230 | struct wmi_read_rssi_event { | ||
1231 | __le32 ina_rssi_adc_dbm; | ||
1232 | } __packed; | ||
1233 | |||
1234 | /* | ||
1081 | * WMI_GET_SSID_EVENTID | 1235 | * WMI_GET_SSID_EVENTID |
1082 | */ | 1236 | */ |
1083 | struct wmi_get_ssid_event { | 1237 | struct wmi_get_ssid_event { |
@@ -1091,7 +1245,8 @@ struct wmi_get_ssid_event { | |||
1091 | struct wmi_rx_mgmt_info { | 1245 | struct wmi_rx_mgmt_info { |
1092 | u8 mcs; | 1246 | u8 mcs; |
1093 | s8 snr; | 1247 | s8 snr; |
1094 | __le16 range; | 1248 | u8 range; |
1249 | u8 sqi; | ||
1095 | __le16 stype; | 1250 | __le16 stype; |
1096 | __le16 status; | 1251 | __le16 status; |
1097 | __le32 len; | 1252 | __le32 len; |
@@ -1113,4 +1268,14 @@ struct wmi_echo_event { | |||
1113 | __le32 echoed_value; | 1268 | __le32 echoed_value; |
1114 | } __packed; | 1269 | } __packed; |
1115 | 1270 | ||
1271 | /* | ||
1272 | * WMI_TEMP_SENSE_DONE_EVENTID | ||
1273 | * | ||
1274 | * Measure MAC and radio temperatures | ||
1275 | */ | ||
1276 | struct wmi_temp_sense_done_event { | ||
1277 | __le32 marlon_m_t1000; | ||
1278 | __le32 marlon_r_t1000; | ||
1279 | } __packed; | ||
1280 | |||
1116 | #endif /* __WILOCITY_WMI_H__ */ | 1281 | #endif /* __WILOCITY_WMI_H__ */ |
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 287c6b670a36..078e6f3477a9 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig | |||
@@ -131,7 +131,7 @@ config B43_PHY_LP | |||
131 | 131 | ||
132 | config B43_PHY_HT | 132 | config B43_PHY_HT |
133 | bool "Support for HT-PHY (high throughput) devices" | 133 | bool "Support for HT-PHY (high throughput) devices" |
134 | depends on B43 | 134 | depends on B43 && B43_BCMA |
135 | ---help--- | 135 | ---help--- |
136 | Support for the HT-PHY. | 136 | Support for the HT-PHY. |
137 | 137 | ||
@@ -166,8 +166,8 @@ config B43_DEBUG | |||
166 | Broadcom 43xx debugging. | 166 | Broadcom 43xx debugging. |
167 | 167 | ||
168 | This adds additional runtime sanity checks and statistics to the driver. | 168 | This adds additional runtime sanity checks and statistics to the driver. |
169 | These checks and statistics might me expensive and hurt runtime performance | 169 | These checks and statistics might be expensive and hurt the runtime |
170 | of your system. | 170 | performance of your system. |
171 | This also adds the b43 debugfs interface. | 171 | This also adds the b43 debugfs interface. |
172 | 172 | ||
173 | Do not enable this, unless you are debugging the driver. | 173 | Do not enable this, unless you are debugging the driver. |
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 10e288d470e7..fe4a77ee05c9 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
@@ -473,6 +473,12 @@ enum { | |||
473 | #define B43_MACCMD_CCA 0x00000008 /* Clear channel assessment */ | 473 | #define B43_MACCMD_CCA 0x00000008 /* Clear channel assessment */ |
474 | #define B43_MACCMD_BGNOISE 0x00000010 /* Background noise */ | 474 | #define B43_MACCMD_BGNOISE 0x00000010 /* Background noise */ |
475 | 475 | ||
476 | /* See BCMA_CLKCTLST_EXTRESREQ and BCMA_CLKCTLST_EXTRESST */ | ||
477 | #define B43_BCMA_CLKCTLST_80211_PLL_REQ 0x00000100 | ||
478 | #define B43_BCMA_CLKCTLST_PHY_PLL_REQ 0x00000200 | ||
479 | #define B43_BCMA_CLKCTLST_80211_PLL_ST 0x01000000 | ||
480 | #define B43_BCMA_CLKCTLST_PHY_PLL_ST 0x02000000 | ||
481 | |||
476 | /* BCMA 802.11 core specific IO Control (BCMA_IOCTL) flags */ | 482 | /* BCMA 802.11 core specific IO Control (BCMA_IOCTL) flags */ |
477 | #define B43_BCMA_IOCTL_PHY_CLKEN 0x00000004 /* PHY Clock Enable */ | 483 | #define B43_BCMA_IOCTL_PHY_CLKEN 0x00000004 /* PHY Clock Enable */ |
478 | #define B43_BCMA_IOCTL_PHY_RESET 0x00000008 /* PHY Reset */ | 484 | #define B43_BCMA_IOCTL_PHY_RESET 0x00000008 /* PHY Reset */ |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 05682736e466..c4d0cc582555 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -1189,10 +1189,15 @@ static void b43_bcma_phy_reset(struct b43_wldev *dev) | |||
1189 | 1189 | ||
1190 | static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode) | 1190 | static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode) |
1191 | { | 1191 | { |
1192 | u32 req = B43_BCMA_CLKCTLST_80211_PLL_REQ | | ||
1193 | B43_BCMA_CLKCTLST_PHY_PLL_REQ; | ||
1194 | u32 status = B43_BCMA_CLKCTLST_80211_PLL_ST | | ||
1195 | B43_BCMA_CLKCTLST_PHY_PLL_ST; | ||
1196 | |||
1192 | b43_device_enable(dev, B43_BCMA_IOCTL_PHY_CLKEN); | 1197 | b43_device_enable(dev, B43_BCMA_IOCTL_PHY_CLKEN); |
1193 | bcma_core_set_clockmode(dev->dev->bdev, BCMA_CLKMODE_FAST); | 1198 | bcma_core_set_clockmode(dev->dev->bdev, BCMA_CLKMODE_FAST); |
1194 | b43_bcma_phy_reset(dev); | 1199 | b43_bcma_phy_reset(dev); |
1195 | bcma_core_pll_ctl(dev->dev->bdev, 0x300, 0x3000000, true); | 1200 | bcma_core_pll_ctl(dev->dev->bdev, req, status, true); |
1196 | } | 1201 | } |
1197 | #endif | 1202 | #endif |
1198 | 1203 | ||
diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c index 7416c5e9154d..b8667706fc27 100644 --- a/drivers/net/wireless/b43/phy_ht.c +++ b/drivers/net/wireless/b43/phy_ht.c | |||
@@ -154,9 +154,84 @@ static void b43_radio_2059_init(struct b43_wldev *dev) | |||
154 | } | 154 | } |
155 | 155 | ||
156 | /************************************************** | 156 | /************************************************** |
157 | * RF | ||
158 | **************************************************/ | ||
159 | |||
160 | static void b43_phy_ht_force_rf_sequence(struct b43_wldev *dev, u16 rf_seq) | ||
161 | { | ||
162 | u8 i; | ||
163 | |||
164 | u16 save_seq_mode = b43_phy_read(dev, B43_PHY_HT_RF_SEQ_MODE); | ||
165 | b43_phy_set(dev, B43_PHY_HT_RF_SEQ_MODE, 0x3); | ||
166 | |||
167 | b43_phy_set(dev, B43_PHY_HT_RF_SEQ_TRIG, rf_seq); | ||
168 | for (i = 0; i < 200; i++) { | ||
169 | if (!(b43_phy_read(dev, B43_PHY_HT_RF_SEQ_STATUS) & rf_seq)) { | ||
170 | i = 0; | ||
171 | break; | ||
172 | } | ||
173 | msleep(1); | ||
174 | } | ||
175 | if (i) | ||
176 | b43err(dev->wl, "Forcing RF sequence timeout\n"); | ||
177 | |||
178 | b43_phy_write(dev, B43_PHY_HT_RF_SEQ_MODE, save_seq_mode); | ||
179 | } | ||
180 | |||
181 | static void b43_phy_ht_pa_override(struct b43_wldev *dev, bool enable) | ||
182 | { | ||
183 | struct b43_phy_ht *htphy = dev->phy.ht; | ||
184 | static const u16 regs[3] = { B43_PHY_HT_RF_CTL_INT_C1, | ||
185 | B43_PHY_HT_RF_CTL_INT_C2, | ||
186 | B43_PHY_HT_RF_CTL_INT_C3 }; | ||
187 | int i; | ||
188 | |||
189 | if (enable) { | ||
190 | for (i = 0; i < 3; i++) | ||
191 | b43_phy_write(dev, regs[i], htphy->rf_ctl_int_save[i]); | ||
192 | } else { | ||
193 | for (i = 0; i < 3; i++) | ||
194 | htphy->rf_ctl_int_save[i] = b43_phy_read(dev, regs[i]); | ||
195 | /* TODO: Does 5GHz band use different value (not 0x0400)? */ | ||
196 | for (i = 0; i < 3; i++) | ||
197 | b43_phy_write(dev, regs[i], 0x0400); | ||
198 | } | ||
199 | } | ||
200 | |||
201 | /************************************************** | ||
157 | * Various PHY ops | 202 | * Various PHY ops |
158 | **************************************************/ | 203 | **************************************************/ |
159 | 204 | ||
205 | static u16 b43_phy_ht_classifier(struct b43_wldev *dev, u16 mask, u16 val) | ||
206 | { | ||
207 | u16 tmp; | ||
208 | u16 allowed = B43_PHY_HT_CLASS_CTL_CCK_EN | | ||
209 | B43_PHY_HT_CLASS_CTL_OFDM_EN | | ||
210 | B43_PHY_HT_CLASS_CTL_WAITED_EN; | ||
211 | |||
212 | tmp = b43_phy_read(dev, B43_PHY_HT_CLASS_CTL); | ||
213 | tmp &= allowed; | ||
214 | tmp &= ~mask; | ||
215 | tmp |= (val & mask); | ||
216 | b43_phy_maskset(dev, B43_PHY_HT_CLASS_CTL, ~allowed, tmp); | ||
217 | |||
218 | return tmp; | ||
219 | } | ||
220 | |||
221 | static void b43_phy_ht_reset_cca(struct b43_wldev *dev) | ||
222 | { | ||
223 | u16 bbcfg; | ||
224 | |||
225 | b43_phy_force_clock(dev, true); | ||
226 | bbcfg = b43_phy_read(dev, B43_PHY_HT_BBCFG); | ||
227 | b43_phy_write(dev, B43_PHY_HT_BBCFG, bbcfg | B43_PHY_HT_BBCFG_RSTCCA); | ||
228 | udelay(1); | ||
229 | b43_phy_write(dev, B43_PHY_HT_BBCFG, bbcfg & ~B43_PHY_HT_BBCFG_RSTCCA); | ||
230 | b43_phy_force_clock(dev, false); | ||
231 | |||
232 | b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RST2RX); | ||
233 | } | ||
234 | |||
160 | static void b43_phy_ht_zero_extg(struct b43_wldev *dev) | 235 | static void b43_phy_ht_zero_extg(struct b43_wldev *dev) |
161 | { | 236 | { |
162 | u8 i, j; | 237 | u8 i, j; |
@@ -176,10 +251,10 @@ static void b43_phy_ht_afe_unk1(struct b43_wldev *dev) | |||
176 | { | 251 | { |
177 | u8 i; | 252 | u8 i; |
178 | 253 | ||
179 | const u16 ctl_regs[3][2] = { | 254 | static const u16 ctl_regs[3][2] = { |
180 | { B43_PHY_HT_AFE_CTL1, B43_PHY_HT_AFE_CTL2 }, | 255 | { B43_PHY_HT_AFE_C1_OVER, B43_PHY_HT_AFE_C1 }, |
181 | { B43_PHY_HT_AFE_CTL3, B43_PHY_HT_AFE_CTL4 }, | 256 | { B43_PHY_HT_AFE_C2_OVER, B43_PHY_HT_AFE_C2 }, |
182 | { B43_PHY_HT_AFE_CTL5, B43_PHY_HT_AFE_CTL6}, | 257 | { B43_PHY_HT_AFE_C3_OVER, B43_PHY_HT_AFE_C3}, |
183 | }; | 258 | }; |
184 | 259 | ||
185 | for (i = 0; i < 3; i++) { | 260 | for (i = 0; i < 3; i++) { |
@@ -193,27 +268,6 @@ static void b43_phy_ht_afe_unk1(struct b43_wldev *dev) | |||
193 | } | 268 | } |
194 | } | 269 | } |
195 | 270 | ||
196 | static void b43_phy_ht_force_rf_sequence(struct b43_wldev *dev, u16 rf_seq) | ||
197 | { | ||
198 | u8 i; | ||
199 | |||
200 | u16 save_seq_mode = b43_phy_read(dev, B43_PHY_HT_RF_SEQ_MODE); | ||
201 | b43_phy_set(dev, B43_PHY_HT_RF_SEQ_MODE, 0x3); | ||
202 | |||
203 | b43_phy_set(dev, B43_PHY_HT_RF_SEQ_TRIG, rf_seq); | ||
204 | for (i = 0; i < 200; i++) { | ||
205 | if (!(b43_phy_read(dev, B43_PHY_HT_RF_SEQ_STATUS) & rf_seq)) { | ||
206 | i = 0; | ||
207 | break; | ||
208 | } | ||
209 | msleep(1); | ||
210 | } | ||
211 | if (i) | ||
212 | b43err(dev->wl, "Forcing RF sequence timeout\n"); | ||
213 | |||
214 | b43_phy_write(dev, B43_PHY_HT_RF_SEQ_MODE, save_seq_mode); | ||
215 | } | ||
216 | |||
217 | static void b43_phy_ht_read_clip_detection(struct b43_wldev *dev, u16 *clip_st) | 271 | static void b43_phy_ht_read_clip_detection(struct b43_wldev *dev, u16 *clip_st) |
218 | { | 272 | { |
219 | clip_st[0] = b43_phy_read(dev, B43_PHY_HT_C1_CLIP1THRES); | 273 | clip_st[0] = b43_phy_read(dev, B43_PHY_HT_C1_CLIP1THRES); |
@@ -240,15 +294,426 @@ static void b43_phy_ht_bphy_init(struct b43_wldev *dev) | |||
240 | } | 294 | } |
241 | 295 | ||
242 | /************************************************** | 296 | /************************************************** |
297 | * Samples | ||
298 | **************************************************/ | ||
299 | |||
300 | static void b43_phy_ht_stop_playback(struct b43_wldev *dev) | ||
301 | { | ||
302 | struct b43_phy_ht *phy_ht = dev->phy.ht; | ||
303 | u16 tmp; | ||
304 | int i; | ||
305 | |||
306 | tmp = b43_phy_read(dev, B43_PHY_HT_SAMP_STAT); | ||
307 | if (tmp & 0x1) | ||
308 | b43_phy_set(dev, B43_PHY_HT_SAMP_CMD, B43_PHY_HT_SAMP_CMD_STOP); | ||
309 | else if (tmp & 0x2) | ||
310 | b43_phy_mask(dev, B43_PHY_HT_IQLOCAL_CMDGCTL, 0x7FFF); | ||
311 | |||
312 | b43_phy_mask(dev, B43_PHY_HT_SAMP_CMD, ~0x0004); | ||
313 | |||
314 | for (i = 0; i < 3; i++) { | ||
315 | if (phy_ht->bb_mult_save[i] >= 0) { | ||
316 | b43_httab_write(dev, B43_HTTAB16(13, 0x63 + i * 4), | ||
317 | phy_ht->bb_mult_save[i]); | ||
318 | b43_httab_write(dev, B43_HTTAB16(13, 0x67 + i * 4), | ||
319 | phy_ht->bb_mult_save[i]); | ||
320 | } | ||
321 | } | ||
322 | } | ||
323 | |||
324 | static u16 b43_phy_ht_load_samples(struct b43_wldev *dev) | ||
325 | { | ||
326 | int i; | ||
327 | u16 len = 20 << 3; | ||
328 | |||
329 | b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, 0x4400); | ||
330 | |||
331 | for (i = 0; i < len; i++) { | ||
332 | b43_phy_write(dev, B43_PHY_HT_TABLE_DATAHI, 0); | ||
333 | b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, 0); | ||
334 | } | ||
335 | |||
336 | return len; | ||
337 | } | ||
338 | |||
339 | static void b43_phy_ht_run_samples(struct b43_wldev *dev, u16 samps, u16 loops, | ||
340 | u16 wait) | ||
341 | { | ||
342 | struct b43_phy_ht *phy_ht = dev->phy.ht; | ||
343 | u16 save_seq_mode; | ||
344 | int i; | ||
345 | |||
346 | for (i = 0; i < 3; i++) { | ||
347 | if (phy_ht->bb_mult_save[i] < 0) | ||
348 | phy_ht->bb_mult_save[i] = b43_httab_read(dev, B43_HTTAB16(13, 0x63 + i * 4)); | ||
349 | } | ||
350 | |||
351 | b43_phy_write(dev, B43_PHY_HT_SAMP_DEP_CNT, samps - 1); | ||
352 | if (loops != 0xFFFF) | ||
353 | loops--; | ||
354 | b43_phy_write(dev, B43_PHY_HT_SAMP_LOOP_CNT, loops); | ||
355 | b43_phy_write(dev, B43_PHY_HT_SAMP_WAIT_CNT, wait); | ||
356 | |||
357 | save_seq_mode = b43_phy_read(dev, B43_PHY_HT_RF_SEQ_MODE); | ||
358 | b43_phy_set(dev, B43_PHY_HT_RF_SEQ_MODE, | ||
359 | B43_PHY_HT_RF_SEQ_MODE_CA_OVER); | ||
360 | |||
361 | /* TODO: find out mask bits! Do we need more function arguments? */ | ||
362 | b43_phy_mask(dev, B43_PHY_HT_SAMP_CMD, ~0); | ||
363 | b43_phy_mask(dev, B43_PHY_HT_SAMP_CMD, ~0); | ||
364 | b43_phy_mask(dev, B43_PHY_HT_IQLOCAL_CMDGCTL, ~0); | ||
365 | b43_phy_set(dev, B43_PHY_HT_SAMP_CMD, 0x1); | ||
366 | |||
367 | for (i = 0; i < 100; i++) { | ||
368 | if (!(b43_phy_read(dev, B43_PHY_HT_RF_SEQ_STATUS) & 1)) { | ||
369 | i = 0; | ||
370 | break; | ||
371 | } | ||
372 | udelay(10); | ||
373 | } | ||
374 | if (i) | ||
375 | b43err(dev->wl, "run samples timeout\n"); | ||
376 | |||
377 | b43_phy_write(dev, B43_PHY_HT_RF_SEQ_MODE, save_seq_mode); | ||
378 | } | ||
379 | |||
380 | static void b43_phy_ht_tx_tone(struct b43_wldev *dev) | ||
381 | { | ||
382 | u16 samp; | ||
383 | |||
384 | samp = b43_phy_ht_load_samples(dev); | ||
385 | b43_phy_ht_run_samples(dev, samp, 0xFFFF, 0); | ||
386 | } | ||
387 | |||
388 | /************************************************** | ||
389 | * RSSI | ||
390 | **************************************************/ | ||
391 | |||
392 | static void b43_phy_ht_rssi_select(struct b43_wldev *dev, u8 core_sel, | ||
393 | u8 rssi_type) | ||
394 | { | ||
395 | static const u16 ctl_regs[3][2] = { | ||
396 | { B43_PHY_HT_AFE_C1, B43_PHY_HT_AFE_C1_OVER, }, | ||
397 | { B43_PHY_HT_AFE_C2, B43_PHY_HT_AFE_C2_OVER, }, | ||
398 | { B43_PHY_HT_AFE_C3, B43_PHY_HT_AFE_C3_OVER, }, | ||
399 | }; | ||
400 | static const u16 radio_r[] = { R2059_SYN, R2059_TXRX0, R2059_RXRX1, }; | ||
401 | int core; | ||
402 | |||
403 | if (core_sel == 0) { | ||
404 | b43err(dev->wl, "RSSI selection for core off not implemented yet\n"); | ||
405 | } else { | ||
406 | for (core = 0; core < 3; core++) { | ||
407 | /* Check if caller requested a one specific core */ | ||
408 | if ((core_sel == 1 && core != 0) || | ||
409 | (core_sel == 2 && core != 1) || | ||
410 | (core_sel == 3 && core != 2)) | ||
411 | continue; | ||
412 | |||
413 | switch (rssi_type) { | ||
414 | case 4: | ||
415 | b43_phy_set(dev, ctl_regs[core][0], 0x3 << 8); | ||
416 | b43_phy_set(dev, ctl_regs[core][0], 0x3 << 10); | ||
417 | b43_phy_set(dev, ctl_regs[core][1], 0x1 << 9); | ||
418 | b43_phy_set(dev, ctl_regs[core][1], 0x1 << 10); | ||
419 | |||
420 | b43_radio_set(dev, R2059_RXRX1 | 0xbf, 0x1); | ||
421 | b43_radio_write(dev, radio_r[core] | 0x159, | ||
422 | 0x11); | ||
423 | break; | ||
424 | default: | ||
425 | b43err(dev->wl, "RSSI selection for type %d not implemented yet\n", | ||
426 | rssi_type); | ||
427 | } | ||
428 | } | ||
429 | } | ||
430 | } | ||
431 | |||
432 | static void b43_phy_ht_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf, | ||
433 | u8 nsamp) | ||
434 | { | ||
435 | u16 phy_regs_values[12]; | ||
436 | static const u16 phy_regs_to_save[] = { | ||
437 | B43_PHY_HT_AFE_C1, B43_PHY_HT_AFE_C1_OVER, | ||
438 | 0x848, 0x841, | ||
439 | B43_PHY_HT_AFE_C2, B43_PHY_HT_AFE_C2_OVER, | ||
440 | 0x868, 0x861, | ||
441 | B43_PHY_HT_AFE_C3, B43_PHY_HT_AFE_C3_OVER, | ||
442 | 0x888, 0x881, | ||
443 | }; | ||
444 | u16 tmp[3]; | ||
445 | int i; | ||
446 | |||
447 | for (i = 0; i < 12; i++) | ||
448 | phy_regs_values[i] = b43_phy_read(dev, phy_regs_to_save[i]); | ||
449 | |||
450 | b43_phy_ht_rssi_select(dev, 5, type); | ||
451 | |||
452 | for (i = 0; i < 6; i++) | ||
453 | buf[i] = 0; | ||
454 | |||
455 | for (i = 0; i < nsamp; i++) { | ||
456 | tmp[0] = b43_phy_read(dev, B43_PHY_HT_RSSI_C1); | ||
457 | tmp[1] = b43_phy_read(dev, B43_PHY_HT_RSSI_C2); | ||
458 | tmp[2] = b43_phy_read(dev, B43_PHY_HT_RSSI_C3); | ||
459 | |||
460 | buf[0] += ((s8)((tmp[0] & 0x3F) << 2)) >> 2; | ||
461 | buf[1] += ((s8)(((tmp[0] >> 8) & 0x3F) << 2)) >> 2; | ||
462 | buf[2] += ((s8)((tmp[1] & 0x3F) << 2)) >> 2; | ||
463 | buf[3] += ((s8)(((tmp[1] >> 8) & 0x3F) << 2)) >> 2; | ||
464 | buf[4] += ((s8)((tmp[2] & 0x3F) << 2)) >> 2; | ||
465 | buf[5] += ((s8)(((tmp[2] >> 8) & 0x3F) << 2)) >> 2; | ||
466 | } | ||
467 | |||
468 | for (i = 0; i < 12; i++) | ||
469 | b43_phy_write(dev, phy_regs_to_save[i], phy_regs_values[i]); | ||
470 | } | ||
471 | |||
472 | /************************************************** | ||
473 | * Tx/Rx | ||
474 | **************************************************/ | ||
475 | |||
476 | static void b43_phy_ht_tx_power_fix(struct b43_wldev *dev) | ||
477 | { | ||
478 | int i; | ||
479 | |||
480 | for (i = 0; i < 3; i++) { | ||
481 | u16 mask; | ||
482 | u32 tmp = b43_httab_read(dev, B43_HTTAB32(26, 0xE8)); | ||
483 | |||
484 | if (0) /* FIXME */ | ||
485 | mask = 0x2 << (i * 4); | ||
486 | else | ||
487 | mask = 0; | ||
488 | b43_phy_mask(dev, B43_PHY_EXTG(0x108), mask); | ||
489 | |||
490 | b43_httab_write(dev, B43_HTTAB16(7, 0x110 + i), tmp >> 16); | ||
491 | b43_httab_write(dev, B43_HTTAB8(13, 0x63 + (i * 4)), | ||
492 | tmp & 0xFF); | ||
493 | b43_httab_write(dev, B43_HTTAB8(13, 0x73 + (i * 4)), | ||
494 | tmp & 0xFF); | ||
495 | } | ||
496 | } | ||
497 | |||
498 | static void b43_phy_ht_tx_power_ctl(struct b43_wldev *dev, bool enable) | ||
499 | { | ||
500 | struct b43_phy_ht *phy_ht = dev->phy.ht; | ||
501 | u16 en_bits = B43_PHY_HT_TXPCTL_CMD_C1_COEFF | | ||
502 | B43_PHY_HT_TXPCTL_CMD_C1_HWPCTLEN | | ||
503 | B43_PHY_HT_TXPCTL_CMD_C1_PCTLEN; | ||
504 | static const u16 cmd_regs[3] = { B43_PHY_HT_TXPCTL_CMD_C1, | ||
505 | B43_PHY_HT_TXPCTL_CMD_C2, | ||
506 | B43_PHY_HT_TXPCTL_CMD_C3 }; | ||
507 | int i; | ||
508 | |||
509 | if (!enable) { | ||
510 | if (b43_phy_read(dev, B43_PHY_HT_TXPCTL_CMD_C1) & en_bits) { | ||
511 | /* We disable enabled TX pwr ctl, save it's state */ | ||
512 | /* | ||
513 | * TODO: find the registers. On N-PHY they were 0x1ed | ||
514 | * and 0x1ee, we need 3 such a registers for HT-PHY | ||
515 | */ | ||
516 | } | ||
517 | b43_phy_mask(dev, B43_PHY_HT_TXPCTL_CMD_C1, ~en_bits); | ||
518 | } else { | ||
519 | b43_phy_set(dev, B43_PHY_HT_TXPCTL_CMD_C1, en_bits); | ||
520 | |||
521 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { | ||
522 | for (i = 0; i < 3; i++) | ||
523 | b43_phy_write(dev, cmd_regs[i], 0x32); | ||
524 | } | ||
525 | |||
526 | for (i = 0; i < 3; i++) | ||
527 | if (phy_ht->tx_pwr_idx[i] <= | ||
528 | B43_PHY_HT_TXPCTL_CMD_C1_INIT) | ||
529 | b43_phy_write(dev, cmd_regs[i], | ||
530 | phy_ht->tx_pwr_idx[i]); | ||
531 | } | ||
532 | |||
533 | phy_ht->tx_pwr_ctl = enable; | ||
534 | } | ||
535 | |||
536 | static void b43_phy_ht_tx_power_ctl_idle_tssi(struct b43_wldev *dev) | ||
537 | { | ||
538 | struct b43_phy_ht *phy_ht = dev->phy.ht; | ||
539 | s32 rssi_buf[6]; | ||
540 | |||
541 | /* TODO */ | ||
542 | |||
543 | b43_phy_ht_tx_tone(dev); | ||
544 | udelay(20); | ||
545 | b43_phy_ht_poll_rssi(dev, 4, rssi_buf, 1); | ||
546 | b43_phy_ht_stop_playback(dev); | ||
547 | b43_phy_ht_reset_cca(dev); | ||
548 | |||
549 | phy_ht->idle_tssi[0] = rssi_buf[0] & 0xff; | ||
550 | phy_ht->idle_tssi[1] = rssi_buf[2] & 0xff; | ||
551 | phy_ht->idle_tssi[2] = rssi_buf[4] & 0xff; | ||
552 | |||
553 | /* TODO */ | ||
554 | } | ||
555 | |||
556 | static void b43_phy_ht_tx_power_ctl_setup(struct b43_wldev *dev) | ||
557 | { | ||
558 | struct b43_phy_ht *phy_ht = dev->phy.ht; | ||
559 | struct ssb_sprom *sprom = dev->dev->bus_sprom; | ||
560 | |||
561 | u8 *idle = phy_ht->idle_tssi; | ||
562 | u8 target[3]; | ||
563 | s16 a1[3], b0[3], b1[3]; | ||
564 | |||
565 | u16 freq = dev->phy.channel_freq; | ||
566 | int i, c; | ||
567 | |||
568 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | ||
569 | for (c = 0; c < 3; c++) { | ||
570 | target[c] = sprom->core_pwr_info[c].maxpwr_2g; | ||
571 | a1[c] = sprom->core_pwr_info[c].pa_2g[0]; | ||
572 | b0[c] = sprom->core_pwr_info[c].pa_2g[1]; | ||
573 | b1[c] = sprom->core_pwr_info[c].pa_2g[2]; | ||
574 | } | ||
575 | } else if (freq >= 4900 && freq < 5100) { | ||
576 | for (c = 0; c < 3; c++) { | ||
577 | target[c] = sprom->core_pwr_info[c].maxpwr_5gl; | ||
578 | a1[c] = sprom->core_pwr_info[c].pa_5gl[0]; | ||
579 | b0[c] = sprom->core_pwr_info[c].pa_5gl[1]; | ||
580 | b1[c] = sprom->core_pwr_info[c].pa_5gl[2]; | ||
581 | } | ||
582 | } else if (freq >= 5100 && freq < 5500) { | ||
583 | for (c = 0; c < 3; c++) { | ||
584 | target[c] = sprom->core_pwr_info[c].maxpwr_5g; | ||
585 | a1[c] = sprom->core_pwr_info[c].pa_5g[0]; | ||
586 | b0[c] = sprom->core_pwr_info[c].pa_5g[1]; | ||
587 | b1[c] = sprom->core_pwr_info[c].pa_5g[2]; | ||
588 | } | ||
589 | } else if (freq >= 5500) { | ||
590 | for (c = 0; c < 3; c++) { | ||
591 | target[c] = sprom->core_pwr_info[c].maxpwr_5gh; | ||
592 | a1[c] = sprom->core_pwr_info[c].pa_5gh[0]; | ||
593 | b0[c] = sprom->core_pwr_info[c].pa_5gh[1]; | ||
594 | b1[c] = sprom->core_pwr_info[c].pa_5gh[2]; | ||
595 | } | ||
596 | } else { | ||
597 | target[0] = target[1] = target[2] = 52; | ||
598 | a1[0] = a1[1] = a1[2] = -424; | ||
599 | b0[0] = b0[1] = b0[2] = 5612; | ||
600 | b1[0] = b1[1] = b1[2] = -1393; | ||
601 | } | ||
602 | |||
603 | b43_phy_set(dev, B43_PHY_HT_TSSIMODE, B43_PHY_HT_TSSIMODE_EN); | ||
604 | b43_phy_mask(dev, B43_PHY_HT_TXPCTL_CMD_C1, | ||
605 | ~B43_PHY_HT_TXPCTL_CMD_C1_PCTLEN & 0xFFFF); | ||
606 | |||
607 | /* TODO: Does it depend on sprom->fem.ghz2.tssipos? */ | ||
608 | b43_phy_set(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI, 0x4000); | ||
609 | |||
610 | b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1, | ||
611 | ~B43_PHY_HT_TXPCTL_CMD_C1_INIT, 0x19); | ||
612 | b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C2, | ||
613 | ~B43_PHY_HT_TXPCTL_CMD_C2_INIT, 0x19); | ||
614 | b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C3, | ||
615 | ~B43_PHY_HT_TXPCTL_CMD_C3_INIT, 0x19); | ||
616 | |||
617 | b43_phy_set(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI, | ||
618 | B43_PHY_HT_TXPCTL_IDLE_TSSI_BINF); | ||
619 | |||
620 | b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI, | ||
621 | ~B43_PHY_HT_TXPCTL_IDLE_TSSI_C1, | ||
622 | idle[0] << B43_PHY_HT_TXPCTL_IDLE_TSSI_C1_SHIFT); | ||
623 | b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI, | ||
624 | ~B43_PHY_HT_TXPCTL_IDLE_TSSI_C2, | ||
625 | idle[1] << B43_PHY_HT_TXPCTL_IDLE_TSSI_C2_SHIFT); | ||
626 | b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI2, | ||
627 | ~B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3, | ||
628 | idle[2] << B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3_SHIFT); | ||
629 | |||
630 | b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_N, ~B43_PHY_HT_TXPCTL_N_TSSID, | ||
631 | 0xf0); | ||
632 | b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_N, ~B43_PHY_HT_TXPCTL_N_NPTIL2, | ||
633 | 0x3 << B43_PHY_HT_TXPCTL_N_NPTIL2_SHIFT); | ||
634 | #if 0 | ||
635 | /* TODO: what to mask/set? */ | ||
636 | b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1, 0x800, 0) | ||
637 | b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1, 0x400, 0) | ||
638 | #endif | ||
639 | |||
640 | b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR, | ||
641 | ~B43_PHY_HT_TXPCTL_TARG_PWR_C1, | ||
642 | target[0] << B43_PHY_HT_TXPCTL_TARG_PWR_C1_SHIFT); | ||
643 | b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR, | ||
644 | ~B43_PHY_HT_TXPCTL_TARG_PWR_C2 & 0xFFFF, | ||
645 | target[1] << B43_PHY_HT_TXPCTL_TARG_PWR_C2_SHIFT); | ||
646 | b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR2, | ||
647 | ~B43_PHY_HT_TXPCTL_TARG_PWR2_C3, | ||
648 | target[2] << B43_PHY_HT_TXPCTL_TARG_PWR2_C3_SHIFT); | ||
649 | |||
650 | for (c = 0; c < 3; c++) { | ||
651 | s32 num, den, pwr; | ||
652 | u32 regval[64]; | ||
653 | |||
654 | for (i = 0; i < 64; i++) { | ||
655 | num = 8 * (16 * b0[c] + b1[c] * i); | ||
656 | den = 32768 + a1[c] * i; | ||
657 | pwr = max((4 * num + den / 2) / den, -8); | ||
658 | regval[i] = pwr; | ||
659 | } | ||
660 | b43_httab_write_bulk(dev, B43_HTTAB16(26 + c, 0), 64, regval); | ||
661 | } | ||
662 | } | ||
663 | |||
664 | /************************************************** | ||
243 | * Channel switching ops. | 665 | * Channel switching ops. |
244 | **************************************************/ | 666 | **************************************************/ |
245 | 667 | ||
668 | static void b43_phy_ht_spur_avoid(struct b43_wldev *dev, | ||
669 | struct ieee80211_channel *new_channel) | ||
670 | { | ||
671 | struct bcma_device *core = dev->dev->bdev; | ||
672 | int spuravoid = 0; | ||
673 | u16 tmp; | ||
674 | |||
675 | /* Check for 13 and 14 is just a guess, we don't have enough logs. */ | ||
676 | if (new_channel->hw_value == 13 || new_channel->hw_value == 14) | ||
677 | spuravoid = 1; | ||
678 | bcma_core_pll_ctl(core, B43_BCMA_CLKCTLST_PHY_PLL_REQ, 0, false); | ||
679 | bcma_pmu_spuravoid_pllupdate(&core->bus->drv_cc, spuravoid); | ||
680 | bcma_core_pll_ctl(core, | ||
681 | B43_BCMA_CLKCTLST_80211_PLL_REQ | | ||
682 | B43_BCMA_CLKCTLST_PHY_PLL_REQ, | ||
683 | B43_BCMA_CLKCTLST_80211_PLL_ST | | ||
684 | B43_BCMA_CLKCTLST_PHY_PLL_ST, false); | ||
685 | |||
686 | /* Values has been taken from wlc_bmac_switch_macfreq comments */ | ||
687 | switch (spuravoid) { | ||
688 | case 2: /* 126MHz */ | ||
689 | tmp = 0x2082; | ||
690 | break; | ||
691 | case 1: /* 123MHz */ | ||
692 | tmp = 0x5341; | ||
693 | break; | ||
694 | default: /* 120MHz */ | ||
695 | tmp = 0x8889; | ||
696 | } | ||
697 | |||
698 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, tmp); | ||
699 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8); | ||
700 | |||
701 | /* TODO: reset PLL */ | ||
702 | |||
703 | if (spuravoid) | ||
704 | b43_phy_set(dev, B43_PHY_HT_BBCFG, B43_PHY_HT_BBCFG_RSTRX); | ||
705 | else | ||
706 | b43_phy_mask(dev, B43_PHY_HT_BBCFG, | ||
707 | ~B43_PHY_HT_BBCFG_RSTRX & 0xFFFF); | ||
708 | |||
709 | b43_phy_ht_reset_cca(dev); | ||
710 | } | ||
711 | |||
246 | static void b43_phy_ht_channel_setup(struct b43_wldev *dev, | 712 | static void b43_phy_ht_channel_setup(struct b43_wldev *dev, |
247 | const struct b43_phy_ht_channeltab_e_phy *e, | 713 | const struct b43_phy_ht_channeltab_e_phy *e, |
248 | struct ieee80211_channel *new_channel) | 714 | struct ieee80211_channel *new_channel) |
249 | { | 715 | { |
250 | bool old_band_5ghz; | 716 | bool old_band_5ghz; |
251 | u8 i; | ||
252 | 717 | ||
253 | old_band_5ghz = b43_phy_read(dev, B43_PHY_HT_BANDCTL) & 0; /* FIXME */ | 718 | old_band_5ghz = b43_phy_read(dev, B43_PHY_HT_BANDCTL) & 0; /* FIXME */ |
254 | if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) { | 719 | if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) { |
@@ -264,25 +729,20 @@ static void b43_phy_ht_channel_setup(struct b43_wldev *dev, | |||
264 | b43_phy_write(dev, B43_PHY_HT_BW5, e->bw5); | 729 | b43_phy_write(dev, B43_PHY_HT_BW5, e->bw5); |
265 | b43_phy_write(dev, B43_PHY_HT_BW6, e->bw6); | 730 | b43_phy_write(dev, B43_PHY_HT_BW6, e->bw6); |
266 | 731 | ||
267 | /* TODO: some ops on PHY regs 0x0B0 and 0xC0A */ | 732 | if (new_channel->hw_value == 14) { |
733 | b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_OFDM_EN, 0); | ||
734 | b43_phy_set(dev, B43_PHY_HT_TEST, 0x0800); | ||
735 | } else { | ||
736 | b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_OFDM_EN, | ||
737 | B43_PHY_HT_CLASS_CTL_OFDM_EN); | ||
738 | if (new_channel->band == IEEE80211_BAND_2GHZ) | ||
739 | b43_phy_mask(dev, B43_PHY_HT_TEST, ~0x840); | ||
740 | } | ||
268 | 741 | ||
269 | /* TODO: separated function? */ | 742 | if (1) /* TODO: On N it's for early devices only, what about HT? */ |
270 | for (i = 0; i < 3; i++) { | 743 | b43_phy_ht_tx_power_fix(dev); |
271 | u16 mask; | ||
272 | u32 tmp = b43_httab_read(dev, B43_HTTAB32(26, 0xE8)); | ||
273 | 744 | ||
274 | if (0) /* FIXME */ | 745 | b43_phy_ht_spur_avoid(dev, new_channel); |
275 | mask = 0x2 << (i * 4); | ||
276 | else | ||
277 | mask = 0; | ||
278 | b43_phy_mask(dev, B43_PHY_EXTG(0x108), mask); | ||
279 | |||
280 | b43_httab_write(dev, B43_HTTAB16(7, 0x110 + i), tmp >> 16); | ||
281 | b43_httab_write(dev, B43_HTTAB8(13, 0x63 + (i * 4)), | ||
282 | tmp & 0xFF); | ||
283 | b43_httab_write(dev, B43_HTTAB8(13, 0x73 + (i * 4)), | ||
284 | tmp & 0xFF); | ||
285 | } | ||
286 | 746 | ||
287 | b43_phy_write(dev, 0x017e, 0x3830); | 747 | b43_phy_write(dev, 0x017e, 0x3830); |
288 | } | 748 | } |
@@ -337,14 +797,29 @@ static void b43_phy_ht_op_prepare_structs(struct b43_wldev *dev) | |||
337 | { | 797 | { |
338 | struct b43_phy *phy = &dev->phy; | 798 | struct b43_phy *phy = &dev->phy; |
339 | struct b43_phy_ht *phy_ht = phy->ht; | 799 | struct b43_phy_ht *phy_ht = phy->ht; |
800 | int i; | ||
340 | 801 | ||
341 | memset(phy_ht, 0, sizeof(*phy_ht)); | 802 | memset(phy_ht, 0, sizeof(*phy_ht)); |
803 | |||
804 | phy_ht->tx_pwr_ctl = true; | ||
805 | for (i = 0; i < 3; i++) | ||
806 | phy_ht->tx_pwr_idx[i] = B43_PHY_HT_TXPCTL_CMD_C1_INIT + 1; | ||
807 | |||
808 | for (i = 0; i < 3; i++) | ||
809 | phy_ht->bb_mult_save[i] = -1; | ||
342 | } | 810 | } |
343 | 811 | ||
344 | static int b43_phy_ht_op_init(struct b43_wldev *dev) | 812 | static int b43_phy_ht_op_init(struct b43_wldev *dev) |
345 | { | 813 | { |
814 | struct b43_phy_ht *phy_ht = dev->phy.ht; | ||
346 | u16 tmp; | 815 | u16 tmp; |
347 | u16 clip_state[3]; | 816 | u16 clip_state[3]; |
817 | bool saved_tx_pwr_ctl; | ||
818 | |||
819 | if (dev->dev->bus_type != B43_BUS_BCMA) { | ||
820 | b43err(dev->wl, "HT-PHY is supported only on BCMA bus!\n"); | ||
821 | return -EOPNOTSUPP; | ||
822 | } | ||
348 | 823 | ||
349 | b43_phy_ht_tables_init(dev); | 824 | b43_phy_ht_tables_init(dev); |
350 | 825 | ||
@@ -357,9 +832,9 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev) | |||
357 | 832 | ||
358 | b43_phy_mask(dev, B43_PHY_EXTG(0), ~0x3); | 833 | b43_phy_mask(dev, B43_PHY_EXTG(0), ~0x3); |
359 | 834 | ||
360 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0); | 835 | b43_phy_write(dev, B43_PHY_HT_AFE_C1_OVER, 0); |
361 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0); | 836 | b43_phy_write(dev, B43_PHY_HT_AFE_C2_OVER, 0); |
362 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL5, 0); | 837 | b43_phy_write(dev, B43_PHY_HT_AFE_C3_OVER, 0); |
363 | 838 | ||
364 | b43_phy_write(dev, B43_PHY_EXTG(0x103), 0x20); | 839 | b43_phy_write(dev, B43_PHY_EXTG(0x103), 0x20); |
365 | b43_phy_write(dev, B43_PHY_EXTG(0x101), 0x20); | 840 | b43_phy_write(dev, B43_PHY_EXTG(0x101), 0x20); |
@@ -371,8 +846,11 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev) | |||
371 | if (0) /* TODO: condition */ | 846 | if (0) /* TODO: condition */ |
372 | ; /* TODO: PHY op on reg 0x217 */ | 847 | ; /* TODO: PHY op on reg 0x217 */ |
373 | 848 | ||
374 | b43_phy_read(dev, 0xb0); /* TODO: what for? */ | 849 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) |
375 | b43_phy_set(dev, 0xb0, 0x1); | 850 | b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_CCK_EN, 0); |
851 | else | ||
852 | b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_CCK_EN, | ||
853 | B43_PHY_HT_CLASS_CTL_CCK_EN); | ||
376 | 854 | ||
377 | b43_phy_set(dev, 0xb1, 0x91); | 855 | b43_phy_set(dev, 0xb1, 0x91); |
378 | b43_phy_write(dev, 0x32f, 0x0003); | 856 | b43_phy_write(dev, 0x32f, 0x0003); |
@@ -448,12 +926,13 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev) | |||
448 | 926 | ||
449 | b43_mac_phy_clock_set(dev, true); | 927 | b43_mac_phy_clock_set(dev, true); |
450 | 928 | ||
929 | b43_phy_ht_pa_override(dev, false); | ||
451 | b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RX2TX); | 930 | b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RX2TX); |
452 | b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RST2RX); | 931 | b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RST2RX); |
453 | 932 | b43_phy_ht_pa_override(dev, true); | |
454 | /* TODO: PHY op on reg 0xb0 */ | ||
455 | 933 | ||
456 | /* TODO: Should we restore it? Or store it in global PHY info? */ | 934 | /* TODO: Should we restore it? Or store it in global PHY info? */ |
935 | b43_phy_ht_classifier(dev, 0, 0); | ||
457 | b43_phy_ht_read_clip_detection(dev, clip_state); | 936 | b43_phy_ht_read_clip_detection(dev, clip_state); |
458 | 937 | ||
459 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | 938 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) |
@@ -462,6 +941,13 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev) | |||
462 | b43_httab_write_bulk(dev, B43_HTTAB32(0x1a, 0xc0), | 941 | b43_httab_write_bulk(dev, B43_HTTAB32(0x1a, 0xc0), |
463 | B43_HTTAB_1A_C0_LATE_SIZE, b43_httab_0x1a_0xc0_late); | 942 | B43_HTTAB_1A_C0_LATE_SIZE, b43_httab_0x1a_0xc0_late); |
464 | 943 | ||
944 | saved_tx_pwr_ctl = phy_ht->tx_pwr_ctl; | ||
945 | b43_phy_ht_tx_power_fix(dev); | ||
946 | b43_phy_ht_tx_power_ctl(dev, false); | ||
947 | b43_phy_ht_tx_power_ctl_idle_tssi(dev); | ||
948 | b43_phy_ht_tx_power_ctl_setup(dev); | ||
949 | b43_phy_ht_tx_power_ctl(dev, saved_tx_pwr_ctl); | ||
950 | |||
465 | return 0; | 951 | return 0; |
466 | } | 952 | } |
467 | 953 | ||
@@ -506,19 +992,19 @@ static void b43_phy_ht_op_software_rfkill(struct b43_wldev *dev, | |||
506 | static void b43_phy_ht_op_switch_analog(struct b43_wldev *dev, bool on) | 992 | static void b43_phy_ht_op_switch_analog(struct b43_wldev *dev, bool on) |
507 | { | 993 | { |
508 | if (on) { | 994 | if (on) { |
509 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL2, 0x00cd); | 995 | b43_phy_write(dev, B43_PHY_HT_AFE_C1, 0x00cd); |
510 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0x0000); | 996 | b43_phy_write(dev, B43_PHY_HT_AFE_C1_OVER, 0x0000); |
511 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL4, 0x00cd); | 997 | b43_phy_write(dev, B43_PHY_HT_AFE_C2, 0x00cd); |
512 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0x0000); | 998 | b43_phy_write(dev, B43_PHY_HT_AFE_C2_OVER, 0x0000); |
513 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL6, 0x00cd); | 999 | b43_phy_write(dev, B43_PHY_HT_AFE_C3, 0x00cd); |
514 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL5, 0x0000); | 1000 | b43_phy_write(dev, B43_PHY_HT_AFE_C3_OVER, 0x0000); |
515 | } else { | 1001 | } else { |
516 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0x07ff); | 1002 | b43_phy_write(dev, B43_PHY_HT_AFE_C1_OVER, 0x07ff); |
517 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL2, 0x00fd); | 1003 | b43_phy_write(dev, B43_PHY_HT_AFE_C1, 0x00fd); |
518 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0x07ff); | 1004 | b43_phy_write(dev, B43_PHY_HT_AFE_C2_OVER, 0x07ff); |
519 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL4, 0x00fd); | 1005 | b43_phy_write(dev, B43_PHY_HT_AFE_C2, 0x00fd); |
520 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL5, 0x07ff); | 1006 | b43_phy_write(dev, B43_PHY_HT_AFE_C3_OVER, 0x07ff); |
521 | b43_phy_write(dev, B43_PHY_HT_AFE_CTL6, 0x00fd); | 1007 | b43_phy_write(dev, B43_PHY_HT_AFE_C3, 0x00fd); |
522 | } | 1008 | } |
523 | } | 1009 | } |
524 | 1010 | ||
diff --git a/drivers/net/wireless/b43/phy_ht.h b/drivers/net/wireless/b43/phy_ht.h index 6544c4293b34..9b2408efb224 100644 --- a/drivers/net/wireless/b43/phy_ht.h +++ b/drivers/net/wireless/b43/phy_ht.h | |||
@@ -12,18 +12,60 @@ | |||
12 | #define B43_PHY_HT_TABLE_ADDR 0x072 /* Table address */ | 12 | #define B43_PHY_HT_TABLE_ADDR 0x072 /* Table address */ |
13 | #define B43_PHY_HT_TABLE_DATALO 0x073 /* Table data low */ | 13 | #define B43_PHY_HT_TABLE_DATALO 0x073 /* Table data low */ |
14 | #define B43_PHY_HT_TABLE_DATAHI 0x074 /* Table data high */ | 14 | #define B43_PHY_HT_TABLE_DATAHI 0x074 /* Table data high */ |
15 | #define B43_PHY_HT_CLASS_CTL 0x0B0 /* Classifier control */ | ||
16 | #define B43_PHY_HT_CLASS_CTL_CCK_EN 0x0001 /* CCK enable */ | ||
17 | #define B43_PHY_HT_CLASS_CTL_OFDM_EN 0x0002 /* OFDM enable */ | ||
18 | #define B43_PHY_HT_CLASS_CTL_WAITED_EN 0x0004 /* Waited enable */ | ||
19 | #define B43_PHY_HT_IQLOCAL_CMDGCTL 0x0C2 /* I/Q LO cal command G control */ | ||
20 | #define B43_PHY_HT_SAMP_CMD 0x0C3 /* Sample command */ | ||
21 | #define B43_PHY_HT_SAMP_CMD_STOP 0x0002 /* Stop */ | ||
22 | #define B43_PHY_HT_SAMP_LOOP_CNT 0x0C4 /* Sample loop count */ | ||
23 | #define B43_PHY_HT_SAMP_WAIT_CNT 0x0C5 /* Sample wait count */ | ||
24 | #define B43_PHY_HT_SAMP_DEP_CNT 0x0C6 /* Sample depth count */ | ||
25 | #define B43_PHY_HT_SAMP_STAT 0x0C7 /* Sample status */ | ||
26 | #define B43_PHY_HT_TSSIMODE 0x122 /* TSSI mode */ | ||
27 | #define B43_PHY_HT_TSSIMODE_EN 0x0001 /* TSSI enable */ | ||
28 | #define B43_PHY_HT_TSSIMODE_PDEN 0x0002 /* Power det enable */ | ||
15 | #define B43_PHY_HT_BW1 0x1CE | 29 | #define B43_PHY_HT_BW1 0x1CE |
16 | #define B43_PHY_HT_BW2 0x1CF | 30 | #define B43_PHY_HT_BW2 0x1CF |
17 | #define B43_PHY_HT_BW3 0x1D0 | 31 | #define B43_PHY_HT_BW3 0x1D0 |
18 | #define B43_PHY_HT_BW4 0x1D1 | 32 | #define B43_PHY_HT_BW4 0x1D1 |
19 | #define B43_PHY_HT_BW5 0x1D2 | 33 | #define B43_PHY_HT_BW5 0x1D2 |
20 | #define B43_PHY_HT_BW6 0x1D3 | 34 | #define B43_PHY_HT_BW6 0x1D3 |
35 | #define B43_PHY_HT_TXPCTL_CMD_C1 0x1E7 /* TX power control command */ | ||
36 | #define B43_PHY_HT_TXPCTL_CMD_C1_INIT 0x007F /* Init */ | ||
37 | #define B43_PHY_HT_TXPCTL_CMD_C1_COEFF 0x2000 /* Power control coefficients */ | ||
38 | #define B43_PHY_HT_TXPCTL_CMD_C1_HWPCTLEN 0x4000 /* Hardware TX power control enable */ | ||
39 | #define B43_PHY_HT_TXPCTL_CMD_C1_PCTLEN 0x8000 /* TX power control enable */ | ||
40 | #define B43_PHY_HT_TXPCTL_N 0x1E8 /* TX power control N num */ | ||
41 | #define B43_PHY_HT_TXPCTL_N_TSSID 0x00FF /* N TSSI delay */ | ||
42 | #define B43_PHY_HT_TXPCTL_N_TSSID_SHIFT 0 | ||
43 | #define B43_PHY_HT_TXPCTL_N_NPTIL2 0x0700 /* N PT integer log2 */ | ||
44 | #define B43_PHY_HT_TXPCTL_N_NPTIL2_SHIFT 8 | ||
45 | #define B43_PHY_HT_TXPCTL_IDLE_TSSI 0x1E9 /* TX power control idle TSSI */ | ||
46 | #define B43_PHY_HT_TXPCTL_IDLE_TSSI_C1 0x003F | ||
47 | #define B43_PHY_HT_TXPCTL_IDLE_TSSI_C1_SHIFT 0 | ||
48 | #define B43_PHY_HT_TXPCTL_IDLE_TSSI_C2 0x3F00 | ||
49 | #define B43_PHY_HT_TXPCTL_IDLE_TSSI_C2_SHIFT 8 | ||
50 | #define B43_PHY_HT_TXPCTL_IDLE_TSSI_BINF 0x8000 /* Raw TSSI offset bin format */ | ||
51 | #define B43_PHY_HT_TXPCTL_TARG_PWR 0x1EA /* TX power control target power */ | ||
52 | #define B43_PHY_HT_TXPCTL_TARG_PWR_C1 0x00FF /* Power 0 */ | ||
53 | #define B43_PHY_HT_TXPCTL_TARG_PWR_C1_SHIFT 0 | ||
54 | #define B43_PHY_HT_TXPCTL_TARG_PWR_C2 0xFF00 /* Power 1 */ | ||
55 | #define B43_PHY_HT_TXPCTL_TARG_PWR_C2_SHIFT 8 | ||
56 | #define B43_PHY_HT_TXPCTL_CMD_C2 0x222 | ||
57 | #define B43_PHY_HT_TXPCTL_CMD_C2_INIT 0x007F | ||
58 | #define B43_PHY_HT_RSSI_C1 0x219 | ||
59 | #define B43_PHY_HT_RSSI_C2 0x21A | ||
60 | #define B43_PHY_HT_RSSI_C3 0x21B | ||
21 | 61 | ||
22 | #define B43_PHY_HT_C1_CLIP1THRES B43_PHY_OFDM(0x00E) | 62 | #define B43_PHY_HT_C1_CLIP1THRES B43_PHY_OFDM(0x00E) |
23 | #define B43_PHY_HT_C2_CLIP1THRES B43_PHY_OFDM(0x04E) | 63 | #define B43_PHY_HT_C2_CLIP1THRES B43_PHY_OFDM(0x04E) |
24 | #define B43_PHY_HT_C3_CLIP1THRES B43_PHY_OFDM(0x08E) | 64 | #define B43_PHY_HT_C3_CLIP1THRES B43_PHY_OFDM(0x08E) |
25 | 65 | ||
26 | #define B43_PHY_HT_RF_SEQ_MODE B43_PHY_EXTG(0x000) | 66 | #define B43_PHY_HT_RF_SEQ_MODE B43_PHY_EXTG(0x000) |
67 | #define B43_PHY_HT_RF_SEQ_MODE_CA_OVER 0x0001 /* Core active override */ | ||
68 | #define B43_PHY_HT_RF_SEQ_MODE_TR_OVER 0x0002 /* Trigger override */ | ||
27 | #define B43_PHY_HT_RF_SEQ_TRIG B43_PHY_EXTG(0x003) | 69 | #define B43_PHY_HT_RF_SEQ_TRIG B43_PHY_EXTG(0x003) |
28 | #define B43_PHY_HT_RF_SEQ_TRIG_RX2TX 0x0001 /* RX2TX */ | 70 | #define B43_PHY_HT_RF_SEQ_TRIG_RX2TX 0x0001 /* RX2TX */ |
29 | #define B43_PHY_HT_RF_SEQ_TRIG_TX2RX 0x0002 /* TX2RX */ | 71 | #define B43_PHY_HT_RF_SEQ_TRIG_TX2RX 0x0002 /* TX2RX */ |
@@ -36,12 +78,27 @@ | |||
36 | 78 | ||
37 | #define B43_PHY_HT_RF_CTL1 B43_PHY_EXTG(0x010) | 79 | #define B43_PHY_HT_RF_CTL1 B43_PHY_EXTG(0x010) |
38 | 80 | ||
39 | #define B43_PHY_HT_AFE_CTL1 B43_PHY_EXTG(0x110) | 81 | #define B43_PHY_HT_RF_CTL_INT_C1 B43_PHY_EXTG(0x04c) |
40 | #define B43_PHY_HT_AFE_CTL2 B43_PHY_EXTG(0x111) | 82 | #define B43_PHY_HT_RF_CTL_INT_C2 B43_PHY_EXTG(0x06c) |
41 | #define B43_PHY_HT_AFE_CTL3 B43_PHY_EXTG(0x114) | 83 | #define B43_PHY_HT_RF_CTL_INT_C3 B43_PHY_EXTG(0x08c) |
42 | #define B43_PHY_HT_AFE_CTL4 B43_PHY_EXTG(0x115) | 84 | |
43 | #define B43_PHY_HT_AFE_CTL5 B43_PHY_EXTG(0x118) | 85 | #define B43_PHY_HT_AFE_C1_OVER B43_PHY_EXTG(0x110) |
44 | #define B43_PHY_HT_AFE_CTL6 B43_PHY_EXTG(0x119) | 86 | #define B43_PHY_HT_AFE_C1 B43_PHY_EXTG(0x111) |
87 | #define B43_PHY_HT_AFE_C2_OVER B43_PHY_EXTG(0x114) | ||
88 | #define B43_PHY_HT_AFE_C2 B43_PHY_EXTG(0x115) | ||
89 | #define B43_PHY_HT_AFE_C3_OVER B43_PHY_EXTG(0x118) | ||
90 | #define B43_PHY_HT_AFE_C3 B43_PHY_EXTG(0x119) | ||
91 | |||
92 | #define B43_PHY_HT_TXPCTL_CMD_C3 B43_PHY_EXTG(0x164) | ||
93 | #define B43_PHY_HT_TXPCTL_CMD_C3_INIT 0x007F | ||
94 | #define B43_PHY_HT_TXPCTL_IDLE_TSSI2 B43_PHY_EXTG(0x165) /* TX power control idle TSSI */ | ||
95 | #define B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3 0x003F | ||
96 | #define B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3_SHIFT 0 | ||
97 | #define B43_PHY_HT_TXPCTL_TARG_PWR2 B43_PHY_EXTG(0x166) /* TX power control target power */ | ||
98 | #define B43_PHY_HT_TXPCTL_TARG_PWR2_C3 0x00FF | ||
99 | #define B43_PHY_HT_TXPCTL_TARG_PWR2_C3_SHIFT 0 | ||
100 | |||
101 | #define B43_PHY_HT_TEST B43_PHY_N_BMODE(0x00A) | ||
45 | 102 | ||
46 | 103 | ||
47 | /* Values for PHY registers used on channel switching */ | 104 | /* Values for PHY registers used on channel switching */ |
@@ -56,6 +113,14 @@ struct b43_phy_ht_channeltab_e_phy { | |||
56 | 113 | ||
57 | 114 | ||
58 | struct b43_phy_ht { | 115 | struct b43_phy_ht { |
116 | u16 rf_ctl_int_save[3]; | ||
117 | |||
118 | bool tx_pwr_ctl; | ||
119 | u8 tx_pwr_idx[3]; | ||
120 | |||
121 | s32 bb_mult_save[3]; | ||
122 | |||
123 | u8 idle_tssi[3]; | ||
59 | }; | 124 | }; |
60 | 125 | ||
61 | 126 | ||
diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig index 1d92d874ebb6..747e9317dabd 100644 --- a/drivers/net/wireless/brcm80211/Kconfig +++ b/drivers/net/wireless/brcm80211/Kconfig | |||
@@ -12,8 +12,9 @@ config BRCMSMAC | |||
12 | select CORDIC | 12 | select CORDIC |
13 | ---help--- | 13 | ---help--- |
14 | This module adds support for PCIe wireless adapters based on Broadcom | 14 | This module adds support for PCIe wireless adapters based on Broadcom |
15 | IEEE802.11n SoftMAC chipsets. If you choose to build a module, it'll | 15 | IEEE802.11n SoftMAC chipsets. It also has WLAN led support, which will |
16 | be called brcmsmac.ko. | 16 | be available if you select BCMA_DRIVER_GPIO. If you choose to build a |
17 | module, the driver will be called brcmsmac.ko. | ||
17 | 18 | ||
18 | config BRCMFMAC | 19 | config BRCMFMAC |
19 | tristate "Broadcom IEEE802.11n embedded FullMAC WLAN driver" | 20 | tristate "Broadcom IEEE802.11n embedded FullMAC WLAN driver" |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile index 756e19fc2795..598c8e2f8d2b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile +++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile | |||
@@ -26,6 +26,7 @@ brcmfmac-objs += \ | |||
26 | wl_cfg80211.o \ | 26 | wl_cfg80211.o \ |
27 | fwil.o \ | 27 | fwil.o \ |
28 | fweh.o \ | 28 | fweh.o \ |
29 | fwsignal.o \ | ||
29 | p2p.o \ | 30 | p2p.o \ |
30 | dhd_cdc.o \ | 31 | dhd_cdc.o \ |
31 | dhd_common.o \ | 32 | dhd_common.o \ |
@@ -39,3 +40,5 @@ brcmfmac-$(CONFIG_BRCMFMAC_USB) += \ | |||
39 | usb.o | 40 | usb.o |
40 | brcmfmac-$(CONFIG_BRCMDBG) += \ | 41 | brcmfmac-$(CONFIG_BRCMDBG) += \ |
41 | dhd_dbg.o | 42 | dhd_dbg.o |
43 | brcmfmac-$(CONFIG_BRCM_TRACING) += \ | ||
44 | tracepoint.o | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index ef6f23be6d32..c7fa20846b32 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h | |||
@@ -501,6 +501,7 @@ struct brcmf_dcmd { | |||
501 | /* Forward decls for struct brcmf_pub (see below) */ | 501 | /* Forward decls for struct brcmf_pub (see below) */ |
502 | struct brcmf_proto; /* device communication protocol info */ | 502 | struct brcmf_proto; /* device communication protocol info */ |
503 | struct brcmf_cfg80211_dev; /* cfg80211 device info */ | 503 | struct brcmf_cfg80211_dev; /* cfg80211 device info */ |
504 | struct brcmf_fws_info; /* firmware signalling info */ | ||
504 | 505 | ||
505 | /* Common structure for module and instance linkage */ | 506 | /* Common structure for module and instance linkage */ |
506 | struct brcmf_pub { | 507 | struct brcmf_pub { |
@@ -527,6 +528,10 @@ struct brcmf_pub { | |||
527 | unsigned char proto_buf[BRCMF_DCMD_MAXLEN]; | 528 | unsigned char proto_buf[BRCMF_DCMD_MAXLEN]; |
528 | 529 | ||
529 | struct brcmf_fweh_info fweh; | 530 | struct brcmf_fweh_info fweh; |
531 | |||
532 | bool fw_signals; | ||
533 | struct brcmf_fws_info *fws; | ||
534 | spinlock_t fws_spinlock; | ||
530 | #ifdef DEBUG | 535 | #ifdef DEBUG |
531 | struct dentry *dbgfs_dir; | 536 | struct dentry *dbgfs_dir; |
532 | #endif | 537 | #endif |
@@ -582,7 +587,7 @@ extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, | |||
582 | void *buf, uint len); | 587 | void *buf, uint len); |
583 | 588 | ||
584 | /* Remove any protocol-specific data header. */ | 589 | /* Remove any protocol-specific data header. */ |
585 | extern int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx, | 590 | extern int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, |
586 | struct sk_buff *rxp); | 591 | struct sk_buff *rxp); |
587 | 592 | ||
588 | extern int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked); | 593 | extern int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h index ad25c3408b59..883ef9063e8a 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h | |||
@@ -134,7 +134,7 @@ extern void brcmf_dev_reset(struct device *dev); | |||
134 | /* Indication from bus module to change flow-control state */ | 134 | /* Indication from bus module to change flow-control state */ |
135 | extern void brcmf_txflowblock(struct device *dev, bool state); | 135 | extern void brcmf_txflowblock(struct device *dev, bool state); |
136 | 136 | ||
137 | /* Notify tx completion */ | 137 | /* Notify the bus has transferred the tx packet to firmware */ |
138 | extern void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, | 138 | extern void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, |
139 | bool success); | 139 | bool success); |
140 | 140 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c index a2354d951dd7..e224bcb90024 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "dhd.h" | 28 | #include "dhd.h" |
29 | #include "dhd_proto.h" | 29 | #include "dhd_proto.h" |
30 | #include "dhd_bus.h" | 30 | #include "dhd_bus.h" |
31 | #include "fwsignal.h" | ||
31 | #include "dhd_dbg.h" | 32 | #include "dhd_dbg.h" |
32 | 33 | ||
33 | struct brcmf_proto_cdc_dcmd { | 34 | struct brcmf_proto_cdc_dcmd { |
@@ -71,13 +72,26 @@ struct brcmf_proto_cdc_dcmd { | |||
71 | ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \ | 72 | ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \ |
72 | ((idx) << BDC_FLAG2_IF_SHIFT))) | 73 | ((idx) << BDC_FLAG2_IF_SHIFT))) |
73 | 74 | ||
75 | /** | ||
76 | * struct brcmf_proto_bdc_header - BDC header format | ||
77 | * | ||
78 | * @flags: flags contain protocol and checksum info. | ||
79 | * @priority: 802.1d priority and USB flow control info (bit 4:7). | ||
80 | * @flags2: additional flags containing dongle interface index. | ||
81 | * @data_offset: start of packet data. header is following by firmware signals. | ||
82 | */ | ||
74 | struct brcmf_proto_bdc_header { | 83 | struct brcmf_proto_bdc_header { |
75 | u8 flags; | 84 | u8 flags; |
76 | u8 priority; /* 802.1d Priority, 4:7 flow control info for usb */ | 85 | u8 priority; |
77 | u8 flags2; | 86 | u8 flags2; |
78 | u8 data_offset; | 87 | u8 data_offset; |
79 | }; | 88 | }; |
80 | 89 | ||
90 | /* | ||
91 | * maximum length of firmware signal data between | ||
92 | * the BDC header and packet data in the tx path. | ||
93 | */ | ||
94 | #define BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES 12 | ||
81 | 95 | ||
82 | #define RETRIES 2 /* # of retries to retrieve matching dcmd response */ | 96 | #define RETRIES 2 /* # of retries to retrieve matching dcmd response */ |
83 | #define BUS_HEADER_LEN (16+64) /* Must be atleast SDPCM_RESERVE | 97 | #define BUS_HEADER_LEN (16+64) /* Must be atleast SDPCM_RESERVE |
@@ -258,7 +272,7 @@ static void pkt_set_sum_good(struct sk_buff *skb, bool x) | |||
258 | skb->ip_summed = (x ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE); | 272 | skb->ip_summed = (x ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE); |
259 | } | 273 | } |
260 | 274 | ||
261 | void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, | 275 | void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, u8 offset, |
262 | struct sk_buff *pktbuf) | 276 | struct sk_buff *pktbuf) |
263 | { | 277 | { |
264 | struct brcmf_proto_bdc_header *h; | 278 | struct brcmf_proto_bdc_header *h; |
@@ -266,7 +280,6 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, | |||
266 | brcmf_dbg(CDC, "Enter\n"); | 280 | brcmf_dbg(CDC, "Enter\n"); |
267 | 281 | ||
268 | /* Push BDC header used to convey priority for buses that don't */ | 282 | /* Push BDC header used to convey priority for buses that don't */ |
269 | |||
270 | skb_push(pktbuf, BDC_HEADER_LEN); | 283 | skb_push(pktbuf, BDC_HEADER_LEN); |
271 | 284 | ||
272 | h = (struct brcmf_proto_bdc_header *)(pktbuf->data); | 285 | h = (struct brcmf_proto_bdc_header *)(pktbuf->data); |
@@ -277,11 +290,11 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, | |||
277 | 290 | ||
278 | h->priority = (pktbuf->priority & BDC_PRIORITY_MASK); | 291 | h->priority = (pktbuf->priority & BDC_PRIORITY_MASK); |
279 | h->flags2 = 0; | 292 | h->flags2 = 0; |
280 | h->data_offset = 0; | 293 | h->data_offset = offset; |
281 | BDC_SET_IF_IDX(h, ifidx); | 294 | BDC_SET_IF_IDX(h, ifidx); |
282 | } | 295 | } |
283 | 296 | ||
284 | int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx, | 297 | int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, |
285 | struct sk_buff *pktbuf) | 298 | struct sk_buff *pktbuf) |
286 | { | 299 | { |
287 | struct brcmf_proto_bdc_header *h; | 300 | struct brcmf_proto_bdc_header *h; |
@@ -328,7 +341,10 @@ int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx, | |||
328 | pktbuf->priority = h->priority & BDC_PRIORITY_MASK; | 341 | pktbuf->priority = h->priority & BDC_PRIORITY_MASK; |
329 | 342 | ||
330 | skb_pull(pktbuf, BDC_HEADER_LEN); | 343 | skb_pull(pktbuf, BDC_HEADER_LEN); |
331 | skb_pull(pktbuf, h->data_offset << 2); | 344 | if (do_fws) |
345 | brcmf_fws_hdrpull(drvr, *ifidx, h->data_offset << 2, pktbuf); | ||
346 | else | ||
347 | skb_pull(pktbuf, h->data_offset << 2); | ||
332 | 348 | ||
333 | if (pktbuf->len == 0) | 349 | if (pktbuf->len == 0) |
334 | return -ENODATA; | 350 | return -ENODATA; |
@@ -350,7 +366,7 @@ int brcmf_proto_attach(struct brcmf_pub *drvr) | |||
350 | } | 366 | } |
351 | 367 | ||
352 | drvr->prot = cdc; | 368 | drvr->prot = cdc; |
353 | drvr->hdrlen += BDC_HEADER_LEN; | 369 | drvr->hdrlen += BDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES; |
354 | drvr->bus_if->maxctl = BRCMF_DCMD_MAXLEN + | 370 | drvr->bus_if->maxctl = BRCMF_DCMD_MAXLEN + |
355 | sizeof(struct brcmf_proto_cdc_dcmd) + ROUND_UP_MARGIN; | 371 | sizeof(struct brcmf_proto_cdc_dcmd) + ROUND_UP_MARGIN; |
356 | return 0; | 372 | return 0; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index 4544342a0428..be0787cab24f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "dhd_proto.h" | 24 | #include "dhd_proto.h" |
25 | #include "dhd_dbg.h" | 25 | #include "dhd_dbg.h" |
26 | #include "fwil.h" | 26 | #include "fwil.h" |
27 | #include "tracepoint.h" | ||
27 | 28 | ||
28 | #define PKTFILTER_BUF_SIZE 128 | 29 | #define PKTFILTER_BUF_SIZE 128 |
29 | #define BRCMF_ARPOL_MODE 0xb /* agent|snoop|peer_autoreply */ | 30 | #define BRCMF_ARPOL_MODE 0xb /* agent|snoop|peer_autoreply */ |
@@ -373,3 +374,35 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) | |||
373 | done: | 374 | done: |
374 | return err; | 375 | return err; |
375 | } | 376 | } |
377 | |||
378 | #ifdef CONFIG_BRCM_TRACING | ||
379 | void __brcmf_err(const char *func, const char *fmt, ...) | ||
380 | { | ||
381 | struct va_format vaf = { | ||
382 | .fmt = fmt, | ||
383 | }; | ||
384 | va_list args; | ||
385 | |||
386 | va_start(args, fmt); | ||
387 | vaf.va = &args; | ||
388 | pr_err("%s: %pV", func, &vaf); | ||
389 | trace_brcmf_err(func, &vaf); | ||
390 | va_end(args); | ||
391 | } | ||
392 | #endif | ||
393 | #if defined(CONFIG_BRCM_TRACING) || defined(CONFIG_BRCMDBG) | ||
394 | void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...) | ||
395 | { | ||
396 | struct va_format vaf = { | ||
397 | .fmt = fmt, | ||
398 | }; | ||
399 | va_list args; | ||
400 | |||
401 | va_start(args, fmt); | ||
402 | vaf.va = &args; | ||
403 | if (brcmf_msg_level & level) | ||
404 | pr_debug("%s %pV", func, &vaf); | ||
405 | trace_brcmf_dbg(level, func, &vaf); | ||
406 | va_end(args); | ||
407 | } | ||
408 | #endif | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c index 57671eddf79d..ac792499b46a 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include "dhd.h" | 22 | #include "dhd.h" |
23 | #include "dhd_bus.h" | 23 | #include "dhd_bus.h" |
24 | #include "dhd_dbg.h" | 24 | #include "dhd_dbg.h" |
25 | #include "tracepoint.h" | ||
25 | 26 | ||
26 | static struct dentry *root_folder; | 27 | static struct dentry *root_folder; |
27 | 28 | ||
@@ -123,3 +124,44 @@ void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr, | |||
123 | debugfs_create_file("counters", S_IRUGO, dentry, | 124 | debugfs_create_file("counters", S_IRUGO, dentry, |
124 | sdcnt, &brcmf_debugfs_sdio_counter_ops); | 125 | sdcnt, &brcmf_debugfs_sdio_counter_ops); |
125 | } | 126 | } |
127 | |||
128 | static | ||
129 | ssize_t brcmf_debugfs_fws_stats_read(struct file *f, char __user *data, | ||
130 | size_t count, loff_t *ppos) | ||
131 | { | ||
132 | struct brcmf_fws_stats *fwstats = f->private_data; | ||
133 | char buf[100]; | ||
134 | int res; | ||
135 | |||
136 | /* only allow read from start */ | ||
137 | if (*ppos > 0) | ||
138 | return 0; | ||
139 | |||
140 | res = scnprintf(buf, sizeof(buf), | ||
141 | "header_pulls: %u\n" | ||
142 | "header_only_pkt: %u\n" | ||
143 | "tlv_parse_failed: %u\n" | ||
144 | "tlv_invalid_type: %u\n", | ||
145 | fwstats->header_pulls, | ||
146 | fwstats->header_only_pkt, | ||
147 | fwstats->tlv_parse_failed, | ||
148 | fwstats->tlv_invalid_type); | ||
149 | |||
150 | return simple_read_from_buffer(data, count, ppos, buf, res); | ||
151 | } | ||
152 | |||
153 | static const struct file_operations brcmf_debugfs_fws_stats_ops = { | ||
154 | .owner = THIS_MODULE, | ||
155 | .open = simple_open, | ||
156 | .read = brcmf_debugfs_fws_stats_read | ||
157 | }; | ||
158 | |||
159 | void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr, | ||
160 | struct brcmf_fws_stats *stats) | ||
161 | { | ||
162 | struct dentry *dentry = drvr->dbgfs_dir; | ||
163 | |||
164 | if (!IS_ERR_OR_NULL(dentry)) | ||
165 | debugfs_create_file("fws_stats", S_IRUGO, dentry, | ||
166 | stats, &brcmf_debugfs_fws_stats_ops); | ||
167 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h index bc013cbe06f6..4bc646bde16f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h | |||
@@ -43,6 +43,7 @@ | |||
43 | * debugging is not selected. When debugging the driver error | 43 | * debugging is not selected. When debugging the driver error |
44 | * messages are as important as other tracing or even more so. | 44 | * messages are as important as other tracing or even more so. |
45 | */ | 45 | */ |
46 | #ifndef CONFIG_BRCM_TRACING | ||
46 | #ifdef CONFIG_BRCMDBG | 47 | #ifdef CONFIG_BRCMDBG |
47 | #define brcmf_err(fmt, ...) pr_err("%s: " fmt, __func__, ##__VA_ARGS__) | 48 | #define brcmf_err(fmt, ...) pr_err("%s: " fmt, __func__, ##__VA_ARGS__) |
48 | #else | 49 | #else |
@@ -52,15 +53,21 @@ | |||
52 | pr_err("%s: " fmt, __func__, ##__VA_ARGS__); \ | 53 | pr_err("%s: " fmt, __func__, ##__VA_ARGS__); \ |
53 | } while (0) | 54 | } while (0) |
54 | #endif | 55 | #endif |
56 | #else | ||
57 | __printf(2, 3) | ||
58 | void __brcmf_err(const char *func, const char *fmt, ...); | ||
59 | #define brcmf_err(fmt, ...) \ | ||
60 | __brcmf_err(__func__, fmt, ##__VA_ARGS__) | ||
61 | #endif | ||
55 | 62 | ||
56 | #if defined(DEBUG) | 63 | #if defined(DEBUG) || defined(CONFIG_BRCM_TRACING) |
57 | 64 | __printf(3, 4) | |
65 | void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...); | ||
58 | #define brcmf_dbg(level, fmt, ...) \ | 66 | #define brcmf_dbg(level, fmt, ...) \ |
59 | do { \ | 67 | do { \ |
60 | if (brcmf_msg_level & BRCMF_##level##_VAL) \ | 68 | __brcmf_dbg(BRCMF_##level##_VAL, __func__, \ |
61 | pr_debug("%s: " fmt, __func__, ##__VA_ARGS__); \ | 69 | fmt, ##__VA_ARGS__); \ |
62 | } while (0) | 70 | } while (0) |
63 | |||
64 | #define BRCMF_DATA_ON() (brcmf_msg_level & BRCMF_DATA_VAL) | 71 | #define BRCMF_DATA_ON() (brcmf_msg_level & BRCMF_DATA_VAL) |
65 | #define BRCMF_CTL_ON() (brcmf_msg_level & BRCMF_CTL_VAL) | 72 | #define BRCMF_CTL_ON() (brcmf_msg_level & BRCMF_CTL_VAL) |
66 | #define BRCMF_HDRS_ON() (brcmf_msg_level & BRCMF_HDRS_VAL) | 73 | #define BRCMF_HDRS_ON() (brcmf_msg_level & BRCMF_HDRS_VAL) |
@@ -69,7 +76,7 @@ do { \ | |||
69 | #define BRCMF_EVENT_ON() (brcmf_msg_level & BRCMF_EVENT_VAL) | 76 | #define BRCMF_EVENT_ON() (brcmf_msg_level & BRCMF_EVENT_VAL) |
70 | #define BRCMF_FIL_ON() (brcmf_msg_level & BRCMF_FIL_VAL) | 77 | #define BRCMF_FIL_ON() (brcmf_msg_level & BRCMF_FIL_VAL) |
71 | 78 | ||
72 | #else /* (defined DEBUG) || (defined DEBUG) */ | 79 | #else /* defined(DEBUG) || defined(CONFIG_BRCM_TRACING) */ |
73 | 80 | ||
74 | #define brcmf_dbg(level, fmt, ...) no_printk(fmt, ##__VA_ARGS__) | 81 | #define brcmf_dbg(level, fmt, ...) no_printk(fmt, ##__VA_ARGS__) |
75 | 82 | ||
@@ -81,7 +88,7 @@ do { \ | |||
81 | #define BRCMF_EVENT_ON() 0 | 88 | #define BRCMF_EVENT_ON() 0 |
82 | #define BRCMF_FIL_ON() 0 | 89 | #define BRCMF_FIL_ON() 0 |
83 | 90 | ||
84 | #endif /* defined(DEBUG) */ | 91 | #endif /* defined(DEBUG) || defined(CONFIG_BRCM_TRACING) */ |
85 | 92 | ||
86 | #define brcmf_dbg_hex_dump(test, data, len, fmt, ...) \ | 93 | #define brcmf_dbg_hex_dump(test, data, len, fmt, ...) \ |
87 | do { \ | 94 | do { \ |
@@ -125,6 +132,13 @@ struct brcmf_sdio_count { | |||
125 | ulong rx_readahead_cnt; /* packets where header read-ahead was used */ | 132 | ulong rx_readahead_cnt; /* packets where header read-ahead was used */ |
126 | }; | 133 | }; |
127 | 134 | ||
135 | struct brcmf_fws_stats { | ||
136 | u32 tlv_parse_failed; | ||
137 | u32 tlv_invalid_type; | ||
138 | u32 header_only_pkt; | ||
139 | u32 header_pulls; | ||
140 | }; | ||
141 | |||
128 | struct brcmf_pub; | 142 | struct brcmf_pub; |
129 | #ifdef DEBUG | 143 | #ifdef DEBUG |
130 | void brcmf_debugfs_init(void); | 144 | void brcmf_debugfs_init(void); |
@@ -134,6 +148,8 @@ void brcmf_debugfs_detach(struct brcmf_pub *drvr); | |||
134 | struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr); | 148 | struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr); |
135 | void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr, | 149 | void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr, |
136 | struct brcmf_sdio_count *sdcnt); | 150 | struct brcmf_sdio_count *sdcnt); |
151 | void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr, | ||
152 | struct brcmf_fws_stats *stats); | ||
137 | #else | 153 | #else |
138 | static inline void brcmf_debugfs_init(void) | 154 | static inline void brcmf_debugfs_init(void) |
139 | { | 155 | { |
@@ -148,6 +164,10 @@ static inline int brcmf_debugfs_attach(struct brcmf_pub *drvr) | |||
148 | static inline void brcmf_debugfs_detach(struct brcmf_pub *drvr) | 164 | static inline void brcmf_debugfs_detach(struct brcmf_pub *drvr) |
149 | { | 165 | { |
150 | } | 166 | } |
167 | static inline void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr, | ||
168 | struct brcmf_fws_stats *stats) | ||
169 | { | ||
170 | } | ||
151 | #endif | 171 | #endif |
152 | 172 | ||
153 | #endif /* _BRCMF_DBG_H_ */ | 173 | #endif /* _BRCMF_DBG_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index c06cea88df0d..fa5a2af04d46 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | |||
@@ -30,17 +30,18 @@ | |||
30 | #include "p2p.h" | 30 | #include "p2p.h" |
31 | #include "wl_cfg80211.h" | 31 | #include "wl_cfg80211.h" |
32 | #include "fwil.h" | 32 | #include "fwil.h" |
33 | #include "fwsignal.h" | ||
33 | 34 | ||
34 | MODULE_AUTHOR("Broadcom Corporation"); | 35 | MODULE_AUTHOR("Broadcom Corporation"); |
35 | MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver."); | 36 | MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver."); |
36 | MODULE_SUPPORTED_DEVICE("Broadcom 802.11 WLAN fullmac cards"); | ||
37 | MODULE_LICENSE("Dual BSD/GPL"); | 37 | MODULE_LICENSE("Dual BSD/GPL"); |
38 | 38 | ||
39 | #define MAX_WAIT_FOR_8021X_TX 50 /* msecs */ | 39 | #define MAX_WAIT_FOR_8021X_TX 50 /* msecs */ |
40 | 40 | ||
41 | /* Error bits */ | 41 | /* Error bits */ |
42 | int brcmf_msg_level; | 42 | int brcmf_msg_level; |
43 | module_param(brcmf_msg_level, int, 0); | 43 | module_param_named(debug, brcmf_msg_level, int, S_IRUSR | S_IWUSR); |
44 | MODULE_PARM_DESC(debug, "level of debug output"); | ||
44 | 45 | ||
45 | /* P2P0 enable */ | 46 | /* P2P0 enable */ |
46 | static int brcmf_p2p_enable; | 47 | static int brcmf_p2p_enable; |
@@ -230,7 +231,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, | |||
230 | atomic_inc(&ifp->pend_8021x_cnt); | 231 | atomic_inc(&ifp->pend_8021x_cnt); |
231 | 232 | ||
232 | /* If the protocol uses a data header, apply it */ | 233 | /* If the protocol uses a data header, apply it */ |
233 | brcmf_proto_hdrpush(drvr, ifp->ifidx, skb); | 234 | brcmf_proto_hdrpush(drvr, ifp->ifidx, 0, skb); |
234 | 235 | ||
235 | /* Use bus module to send data frame */ | 236 | /* Use bus module to send data frame */ |
236 | ret = brcmf_bus_txdata(drvr->bus_if, skb); | 237 | ret = brcmf_bus_txdata(drvr->bus_if, skb); |
@@ -283,7 +284,7 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list) | |||
283 | skb_unlink(skb, skb_list); | 284 | skb_unlink(skb, skb_list); |
284 | 285 | ||
285 | /* process and remove protocol-specific header */ | 286 | /* process and remove protocol-specific header */ |
286 | ret = brcmf_proto_hdrpull(drvr, &ifidx, skb); | 287 | ret = brcmf_proto_hdrpull(drvr, drvr->fw_signals, &ifidx, skb); |
287 | ifp = drvr->iflist[ifidx]; | 288 | ifp = drvr->iflist[ifidx]; |
288 | 289 | ||
289 | if (ret || !ifp || !ifp->ndev) { | 290 | if (ret || !ifp || !ifp->ndev) { |
@@ -357,23 +358,29 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success) | |||
357 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 358 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
358 | struct brcmf_pub *drvr = bus_if->drvr; | 359 | struct brcmf_pub *drvr = bus_if->drvr; |
359 | struct brcmf_if *ifp; | 360 | struct brcmf_if *ifp; |
361 | int res; | ||
360 | 362 | ||
361 | brcmf_proto_hdrpull(drvr, &ifidx, txp); | 363 | res = brcmf_proto_hdrpull(drvr, false, &ifidx, txp); |
362 | 364 | ||
363 | ifp = drvr->iflist[ifidx]; | 365 | ifp = drvr->iflist[ifidx]; |
364 | if (!ifp) | 366 | if (!ifp) |
365 | return; | 367 | goto done; |
366 | 368 | ||
367 | eh = (struct ethhdr *)(txp->data); | 369 | if (res == 0) { |
368 | type = ntohs(eh->h_proto); | 370 | eh = (struct ethhdr *)(txp->data); |
371 | type = ntohs(eh->h_proto); | ||
369 | 372 | ||
370 | if (type == ETH_P_PAE) { | 373 | if (type == ETH_P_PAE) { |
371 | atomic_dec(&ifp->pend_8021x_cnt); | 374 | atomic_dec(&ifp->pend_8021x_cnt); |
372 | if (waitqueue_active(&ifp->pend_8021x_wait)) | 375 | if (waitqueue_active(&ifp->pend_8021x_wait)) |
373 | wake_up(&ifp->pend_8021x_wait); | 376 | wake_up(&ifp->pend_8021x_wait); |
377 | } | ||
374 | } | 378 | } |
375 | if (!success) | 379 | if (!success) |
376 | ifp->stats.tx_errors++; | 380 | ifp->stats.tx_errors++; |
381 | |||
382 | done: | ||
383 | brcmu_pkt_buf_free_skb(txp); | ||
377 | } | 384 | } |
378 | 385 | ||
379 | static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev) | 386 | static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev) |
@@ -873,6 +880,9 @@ int brcmf_bus_start(struct device *dev) | |||
873 | if (ret < 0) | 880 | if (ret < 0) |
874 | goto fail; | 881 | goto fail; |
875 | 882 | ||
883 | drvr->fw_signals = true; | ||
884 | (void)brcmf_fws_init(drvr); | ||
885 | |||
876 | drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev); | 886 | drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev); |
877 | if (drvr->config == NULL) { | 887 | if (drvr->config == NULL) { |
878 | ret = -ENOMEM; | 888 | ret = -ENOMEM; |
@@ -889,6 +899,8 @@ fail: | |||
889 | brcmf_err("failed: %d\n", ret); | 899 | brcmf_err("failed: %d\n", ret); |
890 | if (drvr->config) | 900 | if (drvr->config) |
891 | brcmf_cfg80211_detach(drvr->config); | 901 | brcmf_cfg80211_detach(drvr->config); |
902 | if (drvr->fws) | ||
903 | brcmf_fws_deinit(drvr); | ||
892 | free_netdev(ifp->ndev); | 904 | free_netdev(ifp->ndev); |
893 | drvr->iflist[0] = NULL; | 905 | drvr->iflist[0] = NULL; |
894 | if (p2p_ifp) { | 906 | if (p2p_ifp) { |
@@ -952,6 +964,9 @@ void brcmf_detach(struct device *dev) | |||
952 | if (drvr->prot) | 964 | if (drvr->prot) |
953 | brcmf_proto_detach(drvr); | 965 | brcmf_proto_detach(drvr); |
954 | 966 | ||
967 | if (drvr->fws) | ||
968 | brcmf_fws_deinit(drvr); | ||
969 | |||
955 | brcmf_debugfs_detach(drvr); | 970 | brcmf_debugfs_detach(drvr); |
956 | bus_if->drvr = NULL; | 971 | bus_if->drvr = NULL; |
957 | kfree(drvr); | 972 | kfree(drvr); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h index 48fa70302192..ef9179883748 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h | |||
@@ -33,7 +33,7 @@ extern void brcmf_proto_stop(struct brcmf_pub *drvr); | |||
33 | /* Add any protocol-specific data header. | 33 | /* Add any protocol-specific data header. |
34 | * Caller must reserve prot_hdrlen prepend space. | 34 | * Caller must reserve prot_hdrlen prepend space. |
35 | */ | 35 | */ |
36 | extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx, | 36 | extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx, u8 offset, |
37 | struct sk_buff *txp); | 37 | struct sk_buff *txp); |
38 | 38 | ||
39 | /* Sets dongle media info (drv_version, mac address). */ | 39 | /* Sets dongle media info (drv_version, mac address). */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 4469321c0eb3..9a2edd3f0a5c 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
@@ -1546,7 +1546,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1546 | struct sk_buff_head pktlist; /* needed for bus interface */ | 1546 | struct sk_buff_head pktlist; /* needed for bus interface */ |
1547 | u16 pad; /* Number of pad bytes to read */ | 1547 | u16 pad; /* Number of pad bytes to read */ |
1548 | uint rxleft = 0; /* Remaining number of frames allowed */ | 1548 | uint rxleft = 0; /* Remaining number of frames allowed */ |
1549 | int sdret; /* Return code from calls */ | 1549 | int ret; /* Return code from calls */ |
1550 | uint rxcount = 0; /* Total frames read */ | 1550 | uint rxcount = 0; /* Total frames read */ |
1551 | struct brcmf_sdio_read *rd = &bus->cur_read, rd_new; | 1551 | struct brcmf_sdio_read *rd = &bus->cur_read, rd_new; |
1552 | u8 head_read = 0; | 1552 | u8 head_read = 0; |
@@ -1577,15 +1577,15 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1577 | /* read header first for unknow frame length */ | 1577 | /* read header first for unknow frame length */ |
1578 | sdio_claim_host(bus->sdiodev->func[1]); | 1578 | sdio_claim_host(bus->sdiodev->func[1]); |
1579 | if (!rd->len) { | 1579 | if (!rd->len) { |
1580 | sdret = brcmf_sdcard_recv_buf(bus->sdiodev, | 1580 | ret = brcmf_sdcard_recv_buf(bus->sdiodev, |
1581 | bus->sdiodev->sbwad, | 1581 | bus->sdiodev->sbwad, |
1582 | SDIO_FUNC_2, F2SYNC, | 1582 | SDIO_FUNC_2, F2SYNC, |
1583 | bus->rxhdr, | 1583 | bus->rxhdr, |
1584 | BRCMF_FIRSTREAD); | 1584 | BRCMF_FIRSTREAD); |
1585 | bus->sdcnt.f2rxhdrs++; | 1585 | bus->sdcnt.f2rxhdrs++; |
1586 | if (sdret < 0) { | 1586 | if (ret < 0) { |
1587 | brcmf_err("RXHEADER FAILED: %d\n", | 1587 | brcmf_err("RXHEADER FAILED: %d\n", |
1588 | sdret); | 1588 | ret); |
1589 | bus->sdcnt.rx_hdrfail++; | 1589 | bus->sdcnt.rx_hdrfail++; |
1590 | brcmf_sdbrcm_rxfail(bus, true, true); | 1590 | brcmf_sdbrcm_rxfail(bus, true, true); |
1591 | sdio_release_host(bus->sdiodev->func[1]); | 1591 | sdio_release_host(bus->sdiodev->func[1]); |
@@ -1637,14 +1637,14 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1637 | skb_pull(pkt, head_read); | 1637 | skb_pull(pkt, head_read); |
1638 | pkt_align(pkt, rd->len_left, BRCMF_SDALIGN); | 1638 | pkt_align(pkt, rd->len_left, BRCMF_SDALIGN); |
1639 | 1639 | ||
1640 | sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, | 1640 | ret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, |
1641 | SDIO_FUNC_2, F2SYNC, pkt); | 1641 | SDIO_FUNC_2, F2SYNC, pkt); |
1642 | bus->sdcnt.f2rxdata++; | 1642 | bus->sdcnt.f2rxdata++; |
1643 | sdio_release_host(bus->sdiodev->func[1]); | 1643 | sdio_release_host(bus->sdiodev->func[1]); |
1644 | 1644 | ||
1645 | if (sdret < 0) { | 1645 | if (ret < 0) { |
1646 | brcmf_err("read %d bytes from channel %d failed: %d\n", | 1646 | brcmf_err("read %d bytes from channel %d failed: %d\n", |
1647 | rd->len, rd->channel, sdret); | 1647 | rd->len, rd->channel, ret); |
1648 | brcmu_pkt_buf_free_skb(pkt); | 1648 | brcmu_pkt_buf_free_skb(pkt); |
1649 | sdio_claim_host(bus->sdiodev->func[1]); | 1649 | sdio_claim_host(bus->sdiodev->func[1]); |
1650 | brcmf_sdbrcm_rxfail(bus, true, | 1650 | brcmf_sdbrcm_rxfail(bus, true, |
@@ -1775,7 +1775,7 @@ brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus) | |||
1775 | /* Writes a HW/SW header into the packet and sends it. */ | 1775 | /* Writes a HW/SW header into the packet and sends it. */ |
1776 | /* Assumes: (a) header space already there, (b) caller holds lock */ | 1776 | /* Assumes: (a) header space already there, (b) caller holds lock */ |
1777 | static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, | 1777 | static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, |
1778 | uint chan, bool free_pkt) | 1778 | uint chan) |
1779 | { | 1779 | { |
1780 | int ret; | 1780 | int ret; |
1781 | u8 *frame; | 1781 | u8 *frame; |
@@ -1805,10 +1805,7 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, | |||
1805 | 1805 | ||
1806 | pkt_align(new, pkt->len, BRCMF_SDALIGN); | 1806 | pkt_align(new, pkt->len, BRCMF_SDALIGN); |
1807 | memcpy(new->data, pkt->data, pkt->len); | 1807 | memcpy(new->data, pkt->data, pkt->len); |
1808 | if (free_pkt) | 1808 | brcmu_pkt_buf_free_skb(pkt); |
1809 | brcmu_pkt_buf_free_skb(pkt); | ||
1810 | /* free the pkt if canned one is not used */ | ||
1811 | free_pkt = true; | ||
1812 | pkt = new; | 1809 | pkt = new; |
1813 | frame = (u8 *) (pkt->data); | 1810 | frame = (u8 *) (pkt->data); |
1814 | /* precondition: (frame % BRCMF_SDALIGN) == 0) */ | 1811 | /* precondition: (frame % BRCMF_SDALIGN) == 0) */ |
@@ -1901,10 +1898,6 @@ done: | |||
1901 | /* restore pkt buffer pointer before calling tx complete routine */ | 1898 | /* restore pkt buffer pointer before calling tx complete routine */ |
1902 | skb_pull(pkt, SDPCM_HDRLEN + pad); | 1899 | skb_pull(pkt, SDPCM_HDRLEN + pad); |
1903 | brcmf_txcomplete(bus->sdiodev->dev, pkt, ret != 0); | 1900 | brcmf_txcomplete(bus->sdiodev->dev, pkt, ret != 0); |
1904 | |||
1905 | if (free_pkt) | ||
1906 | brcmu_pkt_buf_free_skb(pkt); | ||
1907 | |||
1908 | return ret; | 1901 | return ret; |
1909 | } | 1902 | } |
1910 | 1903 | ||
@@ -1932,7 +1925,7 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes) | |||
1932 | spin_unlock_bh(&bus->txqlock); | 1925 | spin_unlock_bh(&bus->txqlock); |
1933 | datalen = pkt->len - SDPCM_HDRLEN; | 1926 | datalen = pkt->len - SDPCM_HDRLEN; |
1934 | 1927 | ||
1935 | ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true); | 1928 | ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL); |
1936 | 1929 | ||
1937 | /* In poll mode, need to check for other events */ | 1930 | /* In poll mode, need to check for other events */ |
1938 | if (!bus->intr && cnt) { | 1931 | if (!bus->intr && cnt) { |
@@ -2343,7 +2336,6 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) | |||
2343 | if (!brcmf_c_prec_enq(bus->sdiodev->dev, &bus->txq, pkt, prec)) { | 2336 | if (!brcmf_c_prec_enq(bus->sdiodev->dev, &bus->txq, pkt, prec)) { |
2344 | skb_pull(pkt, SDPCM_HDRLEN); | 2337 | skb_pull(pkt, SDPCM_HDRLEN); |
2345 | brcmf_txcomplete(bus->sdiodev->dev, pkt, false); | 2338 | brcmf_txcomplete(bus->sdiodev->dev, pkt, false); |
2346 | brcmu_pkt_buf_free_skb(pkt); | ||
2347 | brcmf_err("out of bus->txq !!!\n"); | 2339 | brcmf_err("out of bus->txq !!!\n"); |
2348 | ret = -ENOSR; | 2340 | ret = -ENOSR; |
2349 | } else { | 2341 | } else { |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c new file mode 100644 index 000000000000..071d55f9cd4d --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | |||
@@ -0,0 +1,382 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Broadcom Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | #include <linux/types.h> | ||
17 | #include <linux/if_ether.h> | ||
18 | #include <linux/spinlock.h> | ||
19 | #include <linux/skbuff.h> | ||
20 | #include <linux/netdevice.h> | ||
21 | #include <linux/err.h> | ||
22 | #include <uapi/linux/nl80211.h> | ||
23 | |||
24 | #include <brcmu_utils.h> | ||
25 | #include <brcmu_wifi.h> | ||
26 | #include "dhd.h" | ||
27 | #include "dhd_dbg.h" | ||
28 | #include "fwil.h" | ||
29 | #include "fweh.h" | ||
30 | #include "fwsignal.h" | ||
31 | |||
32 | /** | ||
33 | * DOC: Firmware Signalling | ||
34 | * | ||
35 | * Firmware can send signals to host and vice versa, which are passed in the | ||
36 | * data packets using TLV based header. This signalling layer is on top of the | ||
37 | * BDC bus protocol layer. | ||
38 | */ | ||
39 | |||
40 | /* | ||
41 | * single definition for firmware-driver flow control tlv's. | ||
42 | * | ||
43 | * each tlv is specified by BRCMF_FWS_TLV_DEF(name, ID, length). | ||
44 | * A length value 0 indicates variable length tlv. | ||
45 | */ | ||
46 | #define BRCMF_FWS_TLV_DEFLIST \ | ||
47 | BRCMF_FWS_TLV_DEF(MAC_OPEN, 1, 1) \ | ||
48 | BRCMF_FWS_TLV_DEF(MAC_CLOSE, 2, 1) \ | ||
49 | BRCMF_FWS_TLV_DEF(MAC_REQUEST_CREDIT, 3, 2) \ | ||
50 | BRCMF_FWS_TLV_DEF(TXSTATUS, 4, 4) \ | ||
51 | BRCMF_FWS_TLV_DEF(PKTTAG, 5, 4) \ | ||
52 | BRCMF_FWS_TLV_DEF(MACDESC_ADD, 6, 8) \ | ||
53 | BRCMF_FWS_TLV_DEF(MACDESC_DEL, 7, 8) \ | ||
54 | BRCMF_FWS_TLV_DEF(RSSI, 8, 1) \ | ||
55 | BRCMF_FWS_TLV_DEF(INTERFACE_OPEN, 9, 1) \ | ||
56 | BRCMF_FWS_TLV_DEF(INTERFACE_CLOSE, 10, 1) \ | ||
57 | BRCMF_FWS_TLV_DEF(FIFO_CREDITBACK, 11, 8) \ | ||
58 | BRCMF_FWS_TLV_DEF(PENDING_TRAFFIC_BMP, 12, 2) \ | ||
59 | BRCMF_FWS_TLV_DEF(MAC_REQUEST_PACKET, 13, 3) \ | ||
60 | BRCMF_FWS_TLV_DEF(HOST_REORDER_RXPKTS, 14, 10) \ | ||
61 | BRCMF_FWS_TLV_DEF(TRANS_ID, 18, 6) \ | ||
62 | BRCMF_FWS_TLV_DEF(COMP_TXSTATUS, 19, 1) \ | ||
63 | BRCMF_FWS_TLV_DEF(FILLER, 255, 0) | ||
64 | |||
65 | /** | ||
66 | * enum brcmf_fws_tlv_type - definition of tlv identifiers. | ||
67 | */ | ||
68 | #define BRCMF_FWS_TLV_DEF(name, id, len) \ | ||
69 | BRCMF_FWS_TYPE_ ## name = id, | ||
70 | enum brcmf_fws_tlv_type { | ||
71 | BRCMF_FWS_TLV_DEFLIST | ||
72 | BRCMF_FWS_TYPE_INVALID | ||
73 | }; | ||
74 | #undef BRCMF_FWS_TLV_DEF | ||
75 | |||
76 | /** | ||
77 | * enum brcmf_fws_tlv_len - length values for tlvs. | ||
78 | */ | ||
79 | #define BRCMF_FWS_TLV_DEF(name, id, len) \ | ||
80 | BRCMF_FWS_TYPE_ ## name ## _LEN = len, | ||
81 | enum brcmf_fws_tlv_len { | ||
82 | BRCMF_FWS_TLV_DEFLIST | ||
83 | }; | ||
84 | #undef BRCMF_FWS_TLV_DEF | ||
85 | |||
86 | #ifdef DEBUG | ||
87 | /** | ||
88 | * brcmf_fws_tlv_names - array of tlv names. | ||
89 | */ | ||
90 | #define BRCMF_FWS_TLV_DEF(name, id, len) \ | ||
91 | { id, #name }, | ||
92 | static struct { | ||
93 | enum brcmf_fws_tlv_type id; | ||
94 | const char *name; | ||
95 | } brcmf_fws_tlv_names[] = { | ||
96 | BRCMF_FWS_TLV_DEFLIST | ||
97 | }; | ||
98 | #undef BRCMF_FWS_TLV_DEF | ||
99 | |||
100 | static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id) | ||
101 | { | ||
102 | int i; | ||
103 | |||
104 | for (i = 0; i < ARRAY_SIZE(brcmf_fws_tlv_names); i++) | ||
105 | if (brcmf_fws_tlv_names[i].id == id) | ||
106 | return brcmf_fws_tlv_names[i].name; | ||
107 | |||
108 | return "INVALID"; | ||
109 | } | ||
110 | #else | ||
111 | static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id) | ||
112 | { | ||
113 | return "NODEBUG"; | ||
114 | } | ||
115 | #endif /* DEBUG */ | ||
116 | |||
117 | /** | ||
118 | * flags used to enable tlv signalling from firmware. | ||
119 | */ | ||
120 | #define BRCMF_FWS_FLAGS_RSSI_SIGNALS 0x0001 | ||
121 | #define BRCMF_FWS_FLAGS_XONXOFF_SIGNALS 0x0002 | ||
122 | #define BRCMF_FWS_FLAGS_CREDIT_STATUS_SIGNALS 0x0004 | ||
123 | #define BRCMF_FWS_FLAGS_HOST_PROPTXSTATUS_ACTIVE 0x0008 | ||
124 | #define BRCMF_FWS_FLAGS_PSQ_GENERATIONFSM_ENABLE 0x0010 | ||
125 | #define BRCMF_FWS_FLAGS_PSQ_ZERO_BUFFER_ENABLE 0x0020 | ||
126 | #define BRCMF_FWS_FLAGS_HOST_RXREORDER_ACTIVE 0x0040 | ||
127 | |||
128 | #define BRCMF_FWS_HANGER_MAXITEMS 1024 | ||
129 | #define BRCMF_FWS_HANGER_ITEM_STATE_FREE 1 | ||
130 | #define BRCMF_FWS_HANGER_ITEM_STATE_INUSE 2 | ||
131 | #define BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED 3 | ||
132 | |||
133 | #define BRCMF_FWS_STATE_OPEN 1 | ||
134 | #define BRCMF_FWS_STATE_CLOSE 2 | ||
135 | |||
136 | #define BRCMF_FWS_FCMODE_NONE 0 | ||
137 | #define BRCMF_FWS_FCMODE_IMPLIED_CREDIT 1 | ||
138 | #define BRCMF_FWS_FCMODE_EXPLICIT_CREDIT 2 | ||
139 | |||
140 | #define BRCMF_FWS_MAC_DESC_TABLE_SIZE 32 | ||
141 | #define BRCMF_FWS_MAX_IFNUM 16 | ||
142 | #define BRCMF_FWS_MAC_DESC_ID_INVALID 0xff | ||
143 | |||
144 | #define BRCMF_FWS_HOSTIF_FLOWSTATE_OFF 0 | ||
145 | #define BRCMF_FWS_HOSTIF_FLOWSTATE_ON 1 | ||
146 | |||
147 | /** | ||
148 | * FWFC packet identifier | ||
149 | * | ||
150 | * 32-bit packet identifier used in PKTTAG tlv from host to dongle. | ||
151 | * | ||
152 | * - Generated at the host (e.g. dhd) | ||
153 | * - Seen as a generic sequence number by wlc except the flags field | ||
154 | * | ||
155 | * Generation : b[31] => generation number for this packet [host->fw] | ||
156 | * OR, current generation number [fw->host] | ||
157 | * Flags : b[30:27] => command, status flags | ||
158 | * FIFO-AC : b[26:24] => AC-FIFO id | ||
159 | * h-slot : b[23:8] => hanger-slot | ||
160 | * freerun : b[7:0] => A free running counter | ||
161 | */ | ||
162 | #define BRCMF_FWS_PKTTAG_GENERATION_MASK 0x80000000 | ||
163 | #define BRCMF_FWS_PKTTAG_GENERATION_SHIFT 31 | ||
164 | #define BRCMF_FWS_PKTTAG_FLAGS_MASK 0x78000000 | ||
165 | #define BRCMF_FWS_PKTTAG_FLAGS_SHIFT 27 | ||
166 | #define BRCMF_FWS_PKTTAG_FIFO_MASK 0x07000000 | ||
167 | #define BRCMF_FWS_PKTTAG_FIFO_SHIFT 24 | ||
168 | #define BRCMF_FWS_PKTTAG_HSLOT_MASK 0x00ffff00 | ||
169 | #define BRCMF_FWS_PKTTAG_HSLOT_SHIFT 8 | ||
170 | #define BRCMF_FWS_PKTTAG_FREERUN_MASK 0x000000ff | ||
171 | #define BRCMF_FWS_PKTTAG_FREERUN_SHIFT 0 | ||
172 | |||
173 | #define brcmf_fws_pkttag_set_field(var, field, value) \ | ||
174 | brcmu_maskset32((var), BRCMF_FWS_PKTTAG_ ## field ## _MASK, \ | ||
175 | BRCMF_FWS_PKTTAG_ ## field ## _SHIFT, (value)) | ||
176 | #define brcmf_fws_pkttag_get_field(var, field) \ | ||
177 | brcmu_maskget32((var), BRCMF_FWS_PKTTAG_ ## field ## _MASK, \ | ||
178 | BRCMF_FWS_PKTTAG_ ## field ## _SHIFT) | ||
179 | |||
180 | struct brcmf_fws_info { | ||
181 | struct brcmf_pub *drvr; | ||
182 | struct brcmf_fws_stats stats; | ||
183 | }; | ||
184 | |||
185 | static int brcmf_fws_rssi_indicate(struct brcmf_fws_info *fws, s8 rssi) | ||
186 | { | ||
187 | brcmf_dbg(CTL, "rssi %d\n", rssi); | ||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data) | ||
192 | { | ||
193 | __le32 timestamp; | ||
194 | |||
195 | memcpy(×tamp, &data[2], sizeof(timestamp)); | ||
196 | brcmf_dbg(INFO, "received: seq %d, timestamp %d\n", data[1], | ||
197 | le32_to_cpu(timestamp)); | ||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | /* using macro so sparse checking does not complain | ||
202 | * about locking imbalance. | ||
203 | */ | ||
204 | #define brcmf_fws_lock(drvr, flags) \ | ||
205 | do { \ | ||
206 | flags = 0; \ | ||
207 | spin_lock_irqsave(&((drvr)->fws_spinlock), (flags)); \ | ||
208 | } while (0) | ||
209 | |||
210 | /* using macro so sparse checking does not complain | ||
211 | * about locking imbalance. | ||
212 | */ | ||
213 | #define brcmf_fws_unlock(drvr, flags) \ | ||
214 | spin_unlock_irqrestore(&((drvr)->fws_spinlock), (flags)) | ||
215 | |||
216 | int brcmf_fws_init(struct brcmf_pub *drvr) | ||
217 | { | ||
218 | u32 tlv; | ||
219 | int rc; | ||
220 | |||
221 | /* enable rssi signals */ | ||
222 | tlv = drvr->fw_signals ? BRCMF_FWS_FLAGS_RSSI_SIGNALS : 0; | ||
223 | |||
224 | spin_lock_init(&drvr->fws_spinlock); | ||
225 | |||
226 | drvr->fws = kzalloc(sizeof(*(drvr->fws)), GFP_KERNEL); | ||
227 | if (!drvr->fws) { | ||
228 | rc = -ENOMEM; | ||
229 | goto fail; | ||
230 | } | ||
231 | |||
232 | /* enable proptxtstatus signaling by default */ | ||
233 | rc = brcmf_fil_iovar_int_set(drvr->iflist[0], "tlv", tlv); | ||
234 | if (rc < 0) { | ||
235 | brcmf_err("failed to set bdcv2 tlv signaling\n"); | ||
236 | goto fail; | ||
237 | } | ||
238 | /* set linkage back */ | ||
239 | drvr->fws->drvr = drvr; | ||
240 | |||
241 | /* create debugfs file for statistics */ | ||
242 | brcmf_debugfs_create_fws_stats(drvr, &drvr->fws->stats); | ||
243 | |||
244 | /* TODO: remove upon feature delivery */ | ||
245 | brcmf_err("%s bdcv2 tlv signaling [%x]\n", | ||
246 | drvr->fw_signals ? "enabled" : "disabled", tlv); | ||
247 | return 0; | ||
248 | |||
249 | fail: | ||
250 | /* disable flow control entirely */ | ||
251 | drvr->fw_signals = false; | ||
252 | brcmf_fws_deinit(drvr); | ||
253 | return rc; | ||
254 | } | ||
255 | |||
256 | void brcmf_fws_deinit(struct brcmf_pub *drvr) | ||
257 | { | ||
258 | /* free top structure */ | ||
259 | kfree(drvr->fws); | ||
260 | drvr->fws = NULL; | ||
261 | } | ||
262 | |||
263 | int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, | ||
264 | struct sk_buff *skb) | ||
265 | { | ||
266 | struct brcmf_fws_info *fws = drvr->fws; | ||
267 | ulong flags; | ||
268 | u8 *signal_data; | ||
269 | s16 data_len; | ||
270 | u8 type; | ||
271 | u8 len; | ||
272 | u8 *data; | ||
273 | |||
274 | brcmf_dbg(TRACE, "enter: ifidx %d, skblen %u, sig %d\n", | ||
275 | ifidx, skb->len, signal_len); | ||
276 | |||
277 | WARN_ON(signal_len > skb->len); | ||
278 | |||
279 | /* if flow control disabled, skip to packet data and leave */ | ||
280 | if (!signal_len || !drvr->fw_signals) { | ||
281 | skb_pull(skb, signal_len); | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | /* lock during tlv parsing */ | ||
286 | brcmf_fws_lock(drvr, flags); | ||
287 | |||
288 | fws->stats.header_pulls++; | ||
289 | data_len = signal_len; | ||
290 | signal_data = skb->data; | ||
291 | |||
292 | while (data_len > 0) { | ||
293 | /* extract tlv info */ | ||
294 | type = signal_data[0]; | ||
295 | |||
296 | /* FILLER type is actually not a TLV, but | ||
297 | * a single byte that can be skipped. | ||
298 | */ | ||
299 | if (type == BRCMF_FWS_TYPE_FILLER) { | ||
300 | signal_data += 1; | ||
301 | data_len -= 1; | ||
302 | continue; | ||
303 | } | ||
304 | len = signal_data[1]; | ||
305 | data = signal_data + 2; | ||
306 | |||
307 | /* abort parsing when length invalid */ | ||
308 | if (data_len < len + 2) | ||
309 | break; | ||
310 | |||
311 | brcmf_dbg(INFO, "tlv type=%d (%s), len=%d\n", type, | ||
312 | brcmf_fws_get_tlv_name(type), len); | ||
313 | switch (type) { | ||
314 | case BRCMF_FWS_TYPE_MAC_OPEN: | ||
315 | case BRCMF_FWS_TYPE_MAC_CLOSE: | ||
316 | WARN_ON(len != BRCMF_FWS_TYPE_MAC_OPEN_LEN); | ||
317 | break; | ||
318 | case BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT: | ||
319 | WARN_ON(len != BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT_LEN); | ||
320 | break; | ||
321 | case BRCMF_FWS_TYPE_TXSTATUS: | ||
322 | WARN_ON(len != BRCMF_FWS_TYPE_TXSTATUS_LEN); | ||
323 | break; | ||
324 | case BRCMF_FWS_TYPE_PKTTAG: | ||
325 | WARN_ON(len != BRCMF_FWS_TYPE_PKTTAG_LEN); | ||
326 | break; | ||
327 | case BRCMF_FWS_TYPE_MACDESC_ADD: | ||
328 | case BRCMF_FWS_TYPE_MACDESC_DEL: | ||
329 | WARN_ON(len != BRCMF_FWS_TYPE_MACDESC_ADD_LEN); | ||
330 | break; | ||
331 | case BRCMF_FWS_TYPE_RSSI: | ||
332 | WARN_ON(len != BRCMF_FWS_TYPE_RSSI_LEN); | ||
333 | brcmf_fws_rssi_indicate(fws, *(s8 *)data); | ||
334 | break; | ||
335 | case BRCMF_FWS_TYPE_INTERFACE_OPEN: | ||
336 | case BRCMF_FWS_TYPE_INTERFACE_CLOSE: | ||
337 | WARN_ON(len != BRCMF_FWS_TYPE_INTERFACE_OPEN_LEN); | ||
338 | break; | ||
339 | case BRCMF_FWS_TYPE_FIFO_CREDITBACK: | ||
340 | WARN_ON(len != BRCMF_FWS_TYPE_FIFO_CREDITBACK_LEN); | ||
341 | break; | ||
342 | case BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP: | ||
343 | WARN_ON(len != BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN); | ||
344 | break; | ||
345 | case BRCMF_FWS_TYPE_MAC_REQUEST_PACKET: | ||
346 | WARN_ON(len != BRCMF_FWS_TYPE_MAC_REQUEST_PACKET_LEN); | ||
347 | break; | ||
348 | case BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS: | ||
349 | WARN_ON(len != BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS_LEN); | ||
350 | break; | ||
351 | case BRCMF_FWS_TYPE_TRANS_ID: | ||
352 | WARN_ON(len != BRCMF_FWS_TYPE_TRANS_ID_LEN); | ||
353 | brcmf_fws_dbg_seqnum_check(fws, data); | ||
354 | break; | ||
355 | case BRCMF_FWS_TYPE_COMP_TXSTATUS: | ||
356 | WARN_ON(len != BRCMF_FWS_TYPE_COMP_TXSTATUS_LEN); | ||
357 | break; | ||
358 | default: | ||
359 | fws->stats.tlv_invalid_type++; | ||
360 | break; | ||
361 | } | ||
362 | |||
363 | signal_data += len + 2; | ||
364 | data_len -= len + 2; | ||
365 | } | ||
366 | |||
367 | if (data_len != 0) | ||
368 | fws->stats.tlv_parse_failed++; | ||
369 | |||
370 | /* signalling processing result does | ||
371 | * not affect the actual ethernet packet. | ||
372 | */ | ||
373 | skb_pull(skb, signal_len); | ||
374 | |||
375 | /* this may be a signal-only packet | ||
376 | */ | ||
377 | if (skb->len == 0) | ||
378 | fws->stats.header_only_pkt++; | ||
379 | |||
380 | brcmf_fws_unlock(drvr, flags); | ||
381 | return 0; | ||
382 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h new file mode 100644 index 000000000000..e728eea72bb4 --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Broadcom Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | |||
18 | #ifndef FWSIGNAL_H_ | ||
19 | #define FWSIGNAL_H_ | ||
20 | |||
21 | int brcmf_fws_init(struct brcmf_pub *drvr); | ||
22 | void brcmf_fws_deinit(struct brcmf_pub *drvr); | ||
23 | int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, | ||
24 | struct sk_buff *skb); | ||
25 | #endif /* FWSIGNAL_H_ */ | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c new file mode 100644 index 000000000000..b505db48c60d --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Broadcom Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> /* bug in tracepoint.h, it should include this */ | ||
18 | |||
19 | #ifndef __CHECKER__ | ||
20 | #define CREATE_TRACE_POINTS | ||
21 | #include "tracepoint.h" | ||
22 | #endif | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h new file mode 100644 index 000000000000..35efc7a67644 --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h | |||
@@ -0,0 +1,87 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Broadcom Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | #if !defined(BRCMF_TRACEPOINT_H_) || defined(TRACE_HEADER_MULTI_READ) | ||
17 | #define BRCMF_TRACEPOINT_H_ | ||
18 | |||
19 | #include <linux/types.h> | ||
20 | #include <linux/tracepoint.h> | ||
21 | |||
22 | #ifndef CONFIG_BRCM_TRACING | ||
23 | |||
24 | #undef TRACE_EVENT | ||
25 | #define TRACE_EVENT(name, proto, ...) \ | ||
26 | static inline void trace_ ## name(proto) {} | ||
27 | |||
28 | #undef DECLARE_EVENT_CLASS | ||
29 | #define DECLARE_EVENT_CLASS(...) | ||
30 | |||
31 | #undef DEFINE_EVENT | ||
32 | #define DEFINE_EVENT(evt_class, name, proto, ...) \ | ||
33 | static inline void trace_ ## name(proto) {} | ||
34 | |||
35 | #endif /* CONFIG_BRCM_TRACING */ | ||
36 | |||
37 | #undef TRACE_SYSTEM | ||
38 | #define TRACE_SYSTEM brcmfmac | ||
39 | |||
40 | #define MAX_MSG_LEN 100 | ||
41 | |||
42 | TRACE_EVENT(brcmf_err, | ||
43 | TP_PROTO(const char *func, struct va_format *vaf), | ||
44 | TP_ARGS(func, vaf), | ||
45 | TP_STRUCT__entry( | ||
46 | __string(func, func) | ||
47 | __dynamic_array(char, msg, MAX_MSG_LEN) | ||
48 | ), | ||
49 | TP_fast_assign( | ||
50 | __assign_str(func, func); | ||
51 | WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg), | ||
52 | MAX_MSG_LEN, vaf->fmt, | ||
53 | *vaf->va) >= MAX_MSG_LEN); | ||
54 | ), | ||
55 | TP_printk("%s: %s", __get_str(func), __get_str(msg)) | ||
56 | ); | ||
57 | |||
58 | TRACE_EVENT(brcmf_dbg, | ||
59 | TP_PROTO(u32 level, const char *func, struct va_format *vaf), | ||
60 | TP_ARGS(level, func, vaf), | ||
61 | TP_STRUCT__entry( | ||
62 | __field(u32, level) | ||
63 | __string(func, func) | ||
64 | __dynamic_array(char, msg, MAX_MSG_LEN) | ||
65 | ), | ||
66 | TP_fast_assign( | ||
67 | __entry->level = level; | ||
68 | __assign_str(func, func); | ||
69 | WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg), | ||
70 | MAX_MSG_LEN, vaf->fmt, | ||
71 | *vaf->va) >= MAX_MSG_LEN); | ||
72 | ), | ||
73 | TP_printk("%s: %s", __get_str(func), __get_str(msg)) | ||
74 | ); | ||
75 | |||
76 | #ifdef CONFIG_BRCM_TRACING | ||
77 | |||
78 | #undef TRACE_INCLUDE_PATH | ||
79 | #define TRACE_INCLUDE_PATH . | ||
80 | #undef TRACE_INCLUDE_FILE | ||
81 | #define TRACE_INCLUDE_FILE tracepoint | ||
82 | |||
83 | #include <trace/define_trace.h> | ||
84 | |||
85 | #endif /* CONFIG_BRCM_TRACING */ | ||
86 | |||
87 | #endif /* BRCMF_TRACEPOINT_H_ */ | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index 42289e9ea886..01aed7ad6bec 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c | |||
@@ -112,11 +112,6 @@ struct brcmf_usbdev_info { | |||
112 | static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo, | 112 | static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo, |
113 | struct brcmf_usbreq *req); | 113 | struct brcmf_usbreq *req); |
114 | 114 | ||
115 | MODULE_AUTHOR("Broadcom Corporation"); | ||
116 | MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN fullmac usb driver."); | ||
117 | MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac usb cards"); | ||
118 | MODULE_LICENSE("Dual BSD/GPL"); | ||
119 | |||
120 | static struct brcmf_usbdev *brcmf_usb_get_buspub(struct device *dev) | 115 | static struct brcmf_usbdev *brcmf_usb_get_buspub(struct device *dev) |
121 | { | 116 | { |
122 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 117 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
@@ -422,8 +417,6 @@ static void brcmf_usb_tx_complete(struct urb *urb) | |||
422 | brcmf_usb_del_fromq(devinfo, req); | 417 | brcmf_usb_del_fromq(devinfo, req); |
423 | 418 | ||
424 | brcmf_txcomplete(devinfo->dev, req->skb, urb->status == 0); | 419 | brcmf_txcomplete(devinfo->dev, req->skb, urb->status == 0); |
425 | |||
426 | brcmu_pkt_buf_free_skb(req->skb); | ||
427 | req->skb = NULL; | 420 | req->skb = NULL; |
428 | brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req, &devinfo->tx_freecount); | 421 | brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req, &devinfo->tx_freecount); |
429 | if (devinfo->tx_freecount > devinfo->tx_high_watermark && | 422 | if (devinfo->tx_freecount > devinfo->tx_high_watermark && |
@@ -577,15 +570,17 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb) | |||
577 | int ret; | 570 | int ret; |
578 | 571 | ||
579 | brcmf_dbg(USB, "Enter, skb=%p\n", skb); | 572 | brcmf_dbg(USB, "Enter, skb=%p\n", skb); |
580 | if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) | 573 | if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) { |
581 | return -EIO; | 574 | ret = -EIO; |
575 | goto fail; | ||
576 | } | ||
582 | 577 | ||
583 | req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq, | 578 | req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq, |
584 | &devinfo->tx_freecount); | 579 | &devinfo->tx_freecount); |
585 | if (!req) { | 580 | if (!req) { |
586 | brcmu_pkt_buf_free_skb(skb); | ||
587 | brcmf_err("no req to send\n"); | 581 | brcmf_err("no req to send\n"); |
588 | return -ENOMEM; | 582 | ret = -ENOMEM; |
583 | goto fail; | ||
589 | } | 584 | } |
590 | 585 | ||
591 | req->skb = skb; | 586 | req->skb = skb; |
@@ -598,18 +593,21 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb) | |||
598 | if (ret) { | 593 | if (ret) { |
599 | brcmf_err("brcmf_usb_tx usb_submit_urb FAILED\n"); | 594 | brcmf_err("brcmf_usb_tx usb_submit_urb FAILED\n"); |
600 | brcmf_usb_del_fromq(devinfo, req); | 595 | brcmf_usb_del_fromq(devinfo, req); |
601 | brcmu_pkt_buf_free_skb(req->skb); | ||
602 | req->skb = NULL; | 596 | req->skb = NULL; |
603 | brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req, | 597 | brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req, |
604 | &devinfo->tx_freecount); | 598 | &devinfo->tx_freecount); |
605 | } else { | 599 | goto fail; |
606 | if (devinfo->tx_freecount < devinfo->tx_low_watermark && | ||
607 | !devinfo->tx_flowblock) { | ||
608 | brcmf_txflowblock(dev, true); | ||
609 | devinfo->tx_flowblock = true; | ||
610 | } | ||
611 | } | 600 | } |
612 | 601 | ||
602 | if (devinfo->tx_freecount < devinfo->tx_low_watermark && | ||
603 | !devinfo->tx_flowblock) { | ||
604 | brcmf_txflowblock(dev, true); | ||
605 | devinfo->tx_flowblock = true; | ||
606 | } | ||
607 | return 0; | ||
608 | |||
609 | fail: | ||
610 | brcmf_txcomplete(dev, skb, false); | ||
613 | return ret; | 611 | return ret; |
614 | } | 612 | } |
615 | 613 | ||
@@ -1485,6 +1483,7 @@ static struct usb_device_id brcmf_usb_devid_table[] = { | |||
1485 | { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_BCMFW) }, | 1483 | { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_BCMFW) }, |
1486 | { } | 1484 | { } |
1487 | }; | 1485 | }; |
1486 | |||
1488 | MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table); | 1487 | MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table); |
1489 | MODULE_FIRMWARE(BRCMF_USB_43143_FW_NAME); | 1488 | MODULE_FIRMWARE(BRCMF_USB_43143_FW_NAME); |
1490 | MODULE_FIRMWARE(BRCMF_USB_43236_FW_NAME); | 1489 | MODULE_FIRMWARE(BRCMF_USB_43236_FW_NAME); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 2af9c0f0798d..804473fc5c5e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | |||
@@ -3052,16 +3052,16 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, | |||
3052 | int i; | 3052 | int i; |
3053 | int ret = 0; | 3053 | int ret = 0; |
3054 | 3054 | ||
3055 | brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n", | 3055 | brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n", |
3056 | request->n_match_sets, request->n_ssids); | 3056 | request->n_match_sets, request->n_ssids); |
3057 | if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { | 3057 | if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { |
3058 | brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status); | 3058 | brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status); |
3059 | return -EAGAIN; | 3059 | return -EAGAIN; |
3060 | } | 3060 | } |
3061 | 3061 | ||
3062 | if (!request || !request->n_ssids || !request->n_match_sets) { | 3062 | if (!request->n_ssids || !request->n_match_sets) { |
3063 | brcmf_err("Invalid sched scan req!! n_ssids:%d\n", | 3063 | brcmf_err("Invalid sched scan req!! n_ssids:%d\n", |
3064 | request ? request->n_ssids : 0); | 3064 | request->n_ssids); |
3065 | return -EINVAL; | 3065 | return -EINVAL; |
3066 | } | 3066 | } |
3067 | 3067 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/Makefile b/drivers/net/wireless/brcm80211/brcmsmac/Makefile index d3d4151c3eda..cba19d839b77 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/Makefile +++ b/drivers/net/wireless/brcm80211/brcmsmac/Makefile | |||
@@ -43,6 +43,10 @@ BRCMSMAC_OFILES := \ | |||
43 | brcms_trace_events.o \ | 43 | brcms_trace_events.o \ |
44 | debug.o | 44 | debug.o |
45 | 45 | ||
46 | ifdef CONFIG_BCMA_DRIVER_GPIO | ||
47 | BRCMSMAC_OFILES += led.o | ||
48 | endif | ||
49 | |||
46 | MODULEPFX := brcmsmac | 50 | MODULEPFX := brcmsmac |
47 | 51 | ||
48 | obj-$(CONFIG_BRCMSMAC) += $(MODULEPFX).o | 52 | obj-$(CONFIG_BRCMSMAC) += $(MODULEPFX).o |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/led.c b/drivers/net/wireless/brcm80211/brcmsmac/led.c new file mode 100644 index 000000000000..74b17cecb189 --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmsmac/led.c | |||
@@ -0,0 +1,126 @@ | |||
1 | #include <net/mac80211.h> | ||
2 | #include <linux/bcma/bcma_driver_chipcommon.h> | ||
3 | #include <linux/gpio.h> | ||
4 | |||
5 | #include "mac80211_if.h" | ||
6 | #include "pub.h" | ||
7 | #include "main.h" | ||
8 | #include "led.h" | ||
9 | |||
10 | /* number of leds */ | ||
11 | #define BRCMS_LED_NO 4 | ||
12 | /* behavior mask */ | ||
13 | #define BRCMS_LED_BEH_MASK 0x7f | ||
14 | /* activelow (polarity) bit */ | ||
15 | #define BRCMS_LED_AL_MASK 0x80 | ||
16 | /* radio enabled */ | ||
17 | #define BRCMS_LED_RADIO 3 | ||
18 | |||
19 | static void brcms_radio_led_ctrl(struct brcms_info *wl, bool state) | ||
20 | { | ||
21 | if (wl->radio_led.gpio == -1) | ||
22 | return; | ||
23 | |||
24 | if (wl->radio_led.active_low) | ||
25 | state = !state; | ||
26 | |||
27 | if (state) | ||
28 | gpio_set_value(wl->radio_led.gpio, 1); | ||
29 | else | ||
30 | gpio_set_value(wl->radio_led.gpio, 0); | ||
31 | } | ||
32 | |||
33 | |||
34 | /* Callback from the LED subsystem. */ | ||
35 | static void brcms_led_brightness_set(struct led_classdev *led_dev, | ||
36 | enum led_brightness brightness) | ||
37 | { | ||
38 | struct brcms_info *wl = container_of(led_dev, | ||
39 | struct brcms_info, led_dev); | ||
40 | brcms_radio_led_ctrl(wl, brightness); | ||
41 | } | ||
42 | |||
43 | void brcms_led_unregister(struct brcms_info *wl) | ||
44 | { | ||
45 | if (wl->led_dev.dev) | ||
46 | led_classdev_unregister(&wl->led_dev); | ||
47 | if (wl->radio_led.gpio != -1) | ||
48 | gpio_free(wl->radio_led.gpio); | ||
49 | } | ||
50 | |||
51 | int brcms_led_register(struct brcms_info *wl) | ||
52 | { | ||
53 | int i, err; | ||
54 | struct brcms_led *radio_led = &wl->radio_led; | ||
55 | /* get CC core */ | ||
56 | struct bcma_drv_cc *cc_drv = &wl->wlc->hw->d11core->bus->drv_cc; | ||
57 | struct gpio_chip *bcma_gpio = &cc_drv->gpio; | ||
58 | struct ssb_sprom *sprom = &wl->wlc->hw->d11core->bus->sprom; | ||
59 | u8 *leds[] = { &sprom->gpio0, | ||
60 | &sprom->gpio1, | ||
61 | &sprom->gpio2, | ||
62 | &sprom->gpio3 }; | ||
63 | unsigned gpio = -1; | ||
64 | bool active_low = false; | ||
65 | |||
66 | /* none by default */ | ||
67 | radio_led->gpio = -1; | ||
68 | radio_led->active_low = false; | ||
69 | |||
70 | if (!bcma_gpio || !gpio_is_valid(bcma_gpio->base)) | ||
71 | return -ENODEV; | ||
72 | |||
73 | /* find radio enabled LED */ | ||
74 | for (i = 0; i < BRCMS_LED_NO; i++) { | ||
75 | u8 led = *leds[i]; | ||
76 | if ((led & BRCMS_LED_BEH_MASK) == BRCMS_LED_RADIO) { | ||
77 | gpio = bcma_gpio->base + i; | ||
78 | if (led & BRCMS_LED_AL_MASK) | ||
79 | active_low = true; | ||
80 | break; | ||
81 | } | ||
82 | } | ||
83 | |||
84 | if (gpio == -1 || !gpio_is_valid(gpio)) | ||
85 | return -ENODEV; | ||
86 | |||
87 | /* request and configure LED gpio */ | ||
88 | err = gpio_request_one(gpio, | ||
89 | active_low ? GPIOF_OUT_INIT_HIGH | ||
90 | : GPIOF_OUT_INIT_LOW, | ||
91 | "radio on"); | ||
92 | if (err) { | ||
93 | wiphy_err(wl->wiphy, "requesting led gpio %d failed (err: %d)\n", | ||
94 | gpio, err); | ||
95 | return err; | ||
96 | } | ||
97 | err = gpio_direction_output(gpio, 1); | ||
98 | if (err) { | ||
99 | wiphy_err(wl->wiphy, "cannot set led gpio %d to output (err: %d)\n", | ||
100 | gpio, err); | ||
101 | return err; | ||
102 | } | ||
103 | |||
104 | snprintf(wl->radio_led.name, sizeof(wl->radio_led.name), | ||
105 | "brcmsmac-%s:radio", wiphy_name(wl->wiphy)); | ||
106 | |||
107 | wl->led_dev.name = wl->radio_led.name; | ||
108 | wl->led_dev.default_trigger = | ||
109 | ieee80211_get_radio_led_name(wl->pub->ieee_hw); | ||
110 | wl->led_dev.brightness_set = brcms_led_brightness_set; | ||
111 | err = led_classdev_register(wiphy_dev(wl->wiphy), &wl->led_dev); | ||
112 | |||
113 | if (err) { | ||
114 | wiphy_err(wl->wiphy, "cannot register led device: %s (err: %d)\n", | ||
115 | wl->radio_led.name, err); | ||
116 | return err; | ||
117 | } | ||
118 | |||
119 | wiphy_info(wl->wiphy, "registered radio enabled led device: %s gpio: %d\n", | ||
120 | wl->radio_led.name, | ||
121 | gpio); | ||
122 | radio_led->gpio = gpio; | ||
123 | radio_led->active_low = active_low; | ||
124 | |||
125 | return 0; | ||
126 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/led.h b/drivers/net/wireless/brcm80211/brcmsmac/led.h new file mode 100644 index 000000000000..17a0b1f5dbcf --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmsmac/led.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Broadcom Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef _BRCM_LED_H_ | ||
18 | #define _BRCM_LED_H_ | ||
19 | struct brcms_led { | ||
20 | char name[32]; | ||
21 | unsigned gpio; | ||
22 | bool active_low; | ||
23 | }; | ||
24 | |||
25 | #ifdef CONFIG_BCMA_DRIVER_GPIO | ||
26 | void brcms_led_unregister(struct brcms_info *wl); | ||
27 | int brcms_led_register(struct brcms_info *wl); | ||
28 | #else | ||
29 | static inline void brcms_led_unregister(struct brcms_info *wl) {}; | ||
30 | static inline int brcms_led_register(struct brcms_info *wl) | ||
31 | { | ||
32 | return -ENOTSUPP; | ||
33 | }; | ||
34 | #endif | ||
35 | |||
36 | #endif /* _BRCM_LED_H_ */ | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index c6451c61407a..c70cf7b654cd 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include "mac80211_if.h" | 34 | #include "mac80211_if.h" |
35 | #include "main.h" | 35 | #include "main.h" |
36 | #include "debug.h" | 36 | #include "debug.h" |
37 | #include "led.h" | ||
37 | 38 | ||
38 | #define N_TX_QUEUES 4 /* #tx queues on mac80211<->driver interface */ | 39 | #define N_TX_QUEUES 4 /* #tx queues on mac80211<->driver interface */ |
39 | #define BRCMS_FLUSH_TIMEOUT 500 /* msec */ | 40 | #define BRCMS_FLUSH_TIMEOUT 500 /* msec */ |
@@ -904,6 +905,7 @@ static void brcms_remove(struct bcma_device *pdev) | |||
904 | struct brcms_info *wl = hw->priv; | 905 | struct brcms_info *wl = hw->priv; |
905 | 906 | ||
906 | if (wl->wlc) { | 907 | if (wl->wlc) { |
908 | brcms_led_unregister(wl); | ||
907 | wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false); | 909 | wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false); |
908 | wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); | 910 | wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); |
909 | ieee80211_unregister_hw(hw); | 911 | ieee80211_unregister_hw(hw); |
@@ -1151,6 +1153,8 @@ static int brcms_bcma_probe(struct bcma_device *pdev) | |||
1151 | pr_err("%s: brcms_attach failed!\n", __func__); | 1153 | pr_err("%s: brcms_attach failed!\n", __func__); |
1152 | return -ENODEV; | 1154 | return -ENODEV; |
1153 | } | 1155 | } |
1156 | brcms_led_register(wl); | ||
1157 | |||
1154 | return 0; | 1158 | return 0; |
1155 | } | 1159 | } |
1156 | 1160 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h index 947ccacf43e6..4090032e81a2 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h | |||
@@ -20,8 +20,10 @@ | |||
20 | #include <linux/timer.h> | 20 | #include <linux/timer.h> |
21 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
22 | #include <linux/workqueue.h> | 22 | #include <linux/workqueue.h> |
23 | #include <linux/leds.h> | ||
23 | 24 | ||
24 | #include "ucode_loader.h" | 25 | #include "ucode_loader.h" |
26 | #include "led.h" | ||
25 | /* | 27 | /* |
26 | * Starting index for 5G rates in the | 28 | * Starting index for 5G rates in the |
27 | * legacy rate table. | 29 | * legacy rate table. |
@@ -81,6 +83,8 @@ struct brcms_info { | |||
81 | struct wiphy *wiphy; | 83 | struct wiphy *wiphy; |
82 | struct brcms_ucode ucode; | 84 | struct brcms_ucode ucode; |
83 | bool mute_tx; | 85 | bool mute_tx; |
86 | struct brcms_led radio_led; | ||
87 | struct led_classdev led_dev; | ||
84 | }; | 88 | }; |
85 | 89 | ||
86 | /* misc callbacks */ | 90 | /* misc callbacks */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index 8ef02dca8f8c..0c8e998bfb1e 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c | |||
@@ -7810,9 +7810,14 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx) | |||
7810 | 7810 | ||
7811 | /* read the ucode version if we have not yet done so */ | 7811 | /* read the ucode version if we have not yet done so */ |
7812 | if (wlc->ucode_rev == 0) { | 7812 | if (wlc->ucode_rev == 0) { |
7813 | wlc->ucode_rev = | 7813 | u16 rev; |
7814 | brcms_b_read_shm(wlc->hw, M_BOM_REV_MAJOR) << NBITS(u16); | 7814 | u16 patch; |
7815 | wlc->ucode_rev |= brcms_b_read_shm(wlc->hw, M_BOM_REV_MINOR); | 7815 | |
7816 | rev = brcms_b_read_shm(wlc->hw, M_BOM_REV_MAJOR); | ||
7817 | patch = brcms_b_read_shm(wlc->hw, M_BOM_REV_MINOR); | ||
7818 | wlc->ucode_rev = (rev << NBITS(u16)) | patch; | ||
7819 | snprintf(wlc->wiphy->fw_version, | ||
7820 | sizeof(wlc->wiphy->fw_version), "%u.%u", rev, patch); | ||
7816 | } | 7821 | } |
7817 | 7822 | ||
7818 | /* ..now really unleash hell (allow the MAC out of suspend) */ | 7823 | /* ..now really unleash hell (allow the MAC out of suspend) */ |
diff --git a/drivers/net/wireless/brcm80211/brcmutil/utils.c b/drivers/net/wireless/brcm80211/brcmutil/utils.c index 3e6405e06ac0..bf5e50fc21ba 100644 --- a/drivers/net/wireless/brcm80211/brcmutil/utils.c +++ b/drivers/net/wireless/brcm80211/brcmutil/utils.c | |||
@@ -116,6 +116,31 @@ struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec) | |||
116 | } | 116 | } |
117 | EXPORT_SYMBOL(brcmu_pktq_pdeq); | 117 | EXPORT_SYMBOL(brcmu_pktq_pdeq); |
118 | 118 | ||
119 | /* | ||
120 | * precedence based dequeue with match function. Passing a NULL pointer | ||
121 | * for the match function parameter is considered to be a wildcard so | ||
122 | * any packet on the queue is returned. In that case it is no different | ||
123 | * from brcmu_pktq_pdeq() above. | ||
124 | */ | ||
125 | struct sk_buff *brcmu_pktq_pdeq_match(struct pktq *pq, int prec, | ||
126 | bool (*match_fn)(struct sk_buff *skb, | ||
127 | void *arg), void *arg) | ||
128 | { | ||
129 | struct sk_buff_head *q; | ||
130 | struct sk_buff *p, *next; | ||
131 | |||
132 | q = &pq->q[prec].skblist; | ||
133 | skb_queue_walk_safe(q, p, next) { | ||
134 | if (match_fn == NULL || match_fn(p, arg)) { | ||
135 | skb_unlink(p, q); | ||
136 | pq->len--; | ||
137 | return p; | ||
138 | } | ||
139 | } | ||
140 | return NULL; | ||
141 | } | ||
142 | EXPORT_SYMBOL(brcmu_pktq_pdeq_match); | ||
143 | |||
119 | struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec) | 144 | struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec) |
120 | { | 145 | { |
121 | struct sk_buff_head *q; | 146 | struct sk_buff_head *q; |
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_utils.h b/drivers/net/wireless/brcm80211/include/brcmu_utils.h index 477b92ad3d62..898cacb8d01d 100644 --- a/drivers/net/wireless/brcm80211/include/brcmu_utils.h +++ b/drivers/net/wireless/brcm80211/include/brcmu_utils.h | |||
@@ -120,6 +120,10 @@ extern struct sk_buff *brcmu_pktq_penq_head(struct pktq *pq, int prec, | |||
120 | struct sk_buff *p); | 120 | struct sk_buff *p); |
121 | extern struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec); | 121 | extern struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec); |
122 | extern struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec); | 122 | extern struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec); |
123 | extern struct sk_buff *brcmu_pktq_pdeq_match(struct pktq *pq, int prec, | ||
124 | bool (*match_fn)(struct sk_buff *p, | ||
125 | void *arg), | ||
126 | void *arg); | ||
123 | 127 | ||
124 | /* packet primitives */ | 128 | /* packet primitives */ |
125 | extern struct sk_buff *brcmu_pkt_buf_get_skb(uint len); | 129 | extern struct sk_buff *brcmu_pkt_buf_get_skb(uint len); |
@@ -173,6 +177,29 @@ extern void brcmu_pktq_flush(struct pktq *pq, bool dir, | |||
173 | /* ip address */ | 177 | /* ip address */ |
174 | struct ipv4_addr; | 178 | struct ipv4_addr; |
175 | 179 | ||
180 | /* | ||
181 | * bitfield macros using masking and shift | ||
182 | * | ||
183 | * remark: the mask parameter should be a shifted mask. | ||
184 | */ | ||
185 | static inline void brcmu_maskset32(u32 *var, u32 mask, u8 shift, u32 value) | ||
186 | { | ||
187 | value = (value << shift) & mask; | ||
188 | *var = (*var & ~mask) | value; | ||
189 | } | ||
190 | static inline u32 brcmu_maskget32(u32 var, u32 mask, u8 shift) | ||
191 | { | ||
192 | return (var & mask) >> shift; | ||
193 | } | ||
194 | static inline void brcmu_maskset16(u16 *var, u16 mask, u8 shift, u16 value) | ||
195 | { | ||
196 | value = (value << shift) & mask; | ||
197 | *var = (*var & ~mask) | value; | ||
198 | } | ||
199 | static inline u16 brcmu_maskget16(u16 var, u16 mask, u8 shift) | ||
200 | { | ||
201 | return (var & mask) >> shift; | ||
202 | } | ||
176 | 203 | ||
177 | /* externs */ | 204 | /* externs */ |
178 | /* format/print */ | 205 | /* format/print */ |
diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index 3630a41df50d..df5a57c74808 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c | |||
@@ -3475,7 +3475,7 @@ static struct attribute_group il3945_attribute_group = { | |||
3475 | .attrs = il3945_sysfs_entries, | 3475 | .attrs = il3945_sysfs_entries, |
3476 | }; | 3476 | }; |
3477 | 3477 | ||
3478 | struct ieee80211_ops il3945_mac_ops = { | 3478 | static struct ieee80211_ops il3945_mac_ops __read_mostly = { |
3479 | .tx = il3945_mac_tx, | 3479 | .tx = il3945_mac_tx, |
3480 | .start = il3945_mac_start, | 3480 | .start = il3945_mac_start, |
3481 | .stop = il3945_mac_stop, | 3481 | .stop = il3945_mac_stop, |
diff --git a/drivers/net/wireless/iwlegacy/3945.h b/drivers/net/wireless/iwlegacy/3945.h index 1d45075e0d5b..9a8703def0ba 100644 --- a/drivers/net/wireless/iwlegacy/3945.h +++ b/drivers/net/wireless/iwlegacy/3945.h | |||
@@ -150,10 +150,6 @@ struct il3945_frame { | |||
150 | struct list_head list; | 150 | struct list_head list; |
151 | }; | 151 | }; |
152 | 152 | ||
153 | #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) | ||
154 | #define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) | ||
155 | #define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) | ||
156 | |||
157 | #define SUP_RATE_11A_MAX_NUM_CHANNELS 8 | 153 | #define SUP_RATE_11A_MAX_NUM_CHANNELS 8 |
158 | #define SUP_RATE_11B_MAX_NUM_CHANNELS 4 | 154 | #define SUP_RATE_11B_MAX_NUM_CHANNELS 4 |
159 | #define SUP_RATE_11G_MAX_NUM_CHANNELS 12 | 155 | #define SUP_RATE_11G_MAX_NUM_CHANNELS 12 |
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 7941eb3a0166..5bc995a48519 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c | |||
@@ -612,7 +612,7 @@ il4965_pass_packet_to_mac80211(struct il_priv *il, struct ieee80211_hdr *hdr, | |||
612 | 612 | ||
613 | /* Called for N_RX (legacy ABG frames), or | 613 | /* Called for N_RX (legacy ABG frames), or |
614 | * N_RX_MPDU (HT high-throughput N frames). */ | 614 | * N_RX_MPDU (HT high-throughput N frames). */ |
615 | void | 615 | static void |
616 | il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb) | 616 | il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb) |
617 | { | 617 | { |
618 | struct ieee80211_hdr *header; | 618 | struct ieee80211_hdr *header; |
@@ -744,7 +744,7 @@ il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb) | |||
744 | 744 | ||
745 | /* Cache phy data (Rx signal strength, etc) for HT frame (N_RX_PHY). | 745 | /* Cache phy data (Rx signal strength, etc) for HT frame (N_RX_PHY). |
746 | * This will be used later in il_hdl_rx() for N_RX_MPDU. */ | 746 | * This will be used later in il_hdl_rx() for N_RX_MPDU. */ |
747 | void | 747 | static void |
748 | il4965_hdl_rx_phy(struct il_priv *il, struct il_rx_buf *rxb) | 748 | il4965_hdl_rx_phy(struct il_priv *il, struct il_rx_buf *rxb) |
749 | { | 749 | { |
750 | struct il_rx_pkt *pkt = rxb_addr(rxb); | 750 | struct il_rx_pkt *pkt = rxb_addr(rxb); |
@@ -1250,7 +1250,7 @@ il4965_dump_fh(struct il_priv *il, char **buf, bool display) | |||
1250 | return 0; | 1250 | return 0; |
1251 | } | 1251 | } |
1252 | 1252 | ||
1253 | void | 1253 | static void |
1254 | il4965_hdl_missed_beacon(struct il_priv *il, struct il_rx_buf *rxb) | 1254 | il4965_hdl_missed_beacon(struct il_priv *il, struct il_rx_buf *rxb) |
1255 | { | 1255 | { |
1256 | struct il_rx_pkt *pkt = rxb_addr(rxb); | 1256 | struct il_rx_pkt *pkt = rxb_addr(rxb); |
@@ -1357,7 +1357,7 @@ il4965_accumulative_stats(struct il_priv *il, __le32 * stats) | |||
1357 | } | 1357 | } |
1358 | #endif | 1358 | #endif |
1359 | 1359 | ||
1360 | void | 1360 | static void |
1361 | il4965_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb) | 1361 | il4965_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb) |
1362 | { | 1362 | { |
1363 | const int recalib_seconds = 60; | 1363 | const int recalib_seconds = 60; |
@@ -1399,7 +1399,7 @@ il4965_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb) | |||
1399 | il4965_temperature_calib(il); | 1399 | il4965_temperature_calib(il); |
1400 | } | 1400 | } |
1401 | 1401 | ||
1402 | void | 1402 | static void |
1403 | il4965_hdl_c_stats(struct il_priv *il, struct il_rx_buf *rxb) | 1403 | il4965_hdl_c_stats(struct il_priv *il, struct il_rx_buf *rxb) |
1404 | { | 1404 | { |
1405 | struct il_rx_pkt *pkt = rxb_addr(rxb); | 1405 | struct il_rx_pkt *pkt = rxb_addr(rxb); |
@@ -2050,7 +2050,7 @@ il4965_txq_ctx_reset(struct il_priv *il) | |||
2050 | il_tx_queue_reset(il, txq_id); | 2050 | il_tx_queue_reset(il, txq_id); |
2051 | } | 2051 | } |
2052 | 2052 | ||
2053 | void | 2053 | static void |
2054 | il4965_txq_ctx_unmap(struct il_priv *il) | 2054 | il4965_txq_ctx_unmap(struct il_priv *il) |
2055 | { | 2055 | { |
2056 | int txq_id; | 2056 | int txq_id; |
@@ -2258,7 +2258,7 @@ il4965_tx_agg_start(struct il_priv *il, struct ieee80211_vif *vif, | |||
2258 | 2258 | ||
2259 | spin_lock_irqsave(&il->sta_lock, flags); | 2259 | spin_lock_irqsave(&il->sta_lock, flags); |
2260 | tid_data = &il->stations[sta_id].tid[tid]; | 2260 | tid_data = &il->stations[sta_id].tid[tid]; |
2261 | *ssn = SEQ_TO_SN(tid_data->seq_number); | 2261 | *ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); |
2262 | tid_data->agg.txq_id = txq_id; | 2262 | tid_data->agg.txq_id = txq_id; |
2263 | il_set_swq_id(&il->txq[txq_id], il4965_get_ac_from_tid(tid), txq_id); | 2263 | il_set_swq_id(&il->txq[txq_id], il4965_get_ac_from_tid(tid), txq_id); |
2264 | spin_unlock_irqrestore(&il->sta_lock, flags); | 2264 | spin_unlock_irqrestore(&il->sta_lock, flags); |
@@ -2408,7 +2408,7 @@ il4965_txq_check_empty(struct il_priv *il, int sta_id, u8 tid, int txq_id) | |||
2408 | /* aggregated HW queue */ | 2408 | /* aggregated HW queue */ |
2409 | if (txq_id == tid_data->agg.txq_id && | 2409 | if (txq_id == tid_data->agg.txq_id && |
2410 | q->read_ptr == q->write_ptr) { | 2410 | q->read_ptr == q->write_ptr) { |
2411 | u16 ssn = SEQ_TO_SN(tid_data->seq_number); | 2411 | u16 ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); |
2412 | int tx_fifo = il4965_get_fifo_from_tid(tid); | 2412 | int tx_fifo = il4965_get_fifo_from_tid(tid); |
2413 | D_HT("HW queue empty: continue DELBA flow\n"); | 2413 | D_HT("HW queue empty: continue DELBA flow\n"); |
2414 | il4965_txq_agg_disable(il, txq_id, ssn, tx_fifo); | 2414 | il4965_txq_agg_disable(il, txq_id, ssn, tx_fifo); |
@@ -2627,7 +2627,8 @@ il4965_get_ra_sta_id(struct il_priv *il, struct ieee80211_hdr *hdr) | |||
2627 | static inline u32 | 2627 | static inline u32 |
2628 | il4965_get_scd_ssn(struct il4965_tx_resp *tx_resp) | 2628 | il4965_get_scd_ssn(struct il4965_tx_resp *tx_resp) |
2629 | { | 2629 | { |
2630 | return le32_to_cpup(&tx_resp->u.status + tx_resp->frame_count) & MAX_SN; | 2630 | return le32_to_cpup(&tx_resp->u.status + |
2631 | tx_resp->frame_count) & IEEE80211_MAX_SN; | ||
2631 | } | 2632 | } |
2632 | 2633 | ||
2633 | static inline u32 | 2634 | static inline u32 |
@@ -2717,15 +2718,15 @@ il4965_tx_status_reply_tx(struct il_priv *il, struct il_ht_agg *agg, | |||
2717 | hdr = (struct ieee80211_hdr *) skb->data; | 2718 | hdr = (struct ieee80211_hdr *) skb->data; |
2718 | 2719 | ||
2719 | sc = le16_to_cpu(hdr->seq_ctrl); | 2720 | sc = le16_to_cpu(hdr->seq_ctrl); |
2720 | if (idx != (SEQ_TO_SN(sc) & 0xff)) { | 2721 | if (idx != (IEEE80211_SEQ_TO_SN(sc) & 0xff)) { |
2721 | IL_ERR("BUG_ON idx doesn't match seq control" | 2722 | IL_ERR("BUG_ON idx doesn't match seq control" |
2722 | " idx=%d, seq_idx=%d, seq=%d\n", idx, | 2723 | " idx=%d, seq_idx=%d, seq=%d\n", idx, |
2723 | SEQ_TO_SN(sc), hdr->seq_ctrl); | 2724 | IEEE80211_SEQ_TO_SN(sc), hdr->seq_ctrl); |
2724 | return -1; | 2725 | return -1; |
2725 | } | 2726 | } |
2726 | 2727 | ||
2727 | D_TX_REPLY("AGG Frame i=%d idx %d seq=%d\n", i, idx, | 2728 | D_TX_REPLY("AGG Frame i=%d idx %d seq=%d\n", i, idx, |
2728 | SEQ_TO_SN(sc)); | 2729 | IEEE80211_SEQ_TO_SN(sc)); |
2729 | 2730 | ||
2730 | sh = idx - start; | 2731 | sh = idx - start; |
2731 | if (sh > 64) { | 2732 | if (sh > 64) { |
@@ -2895,7 +2896,7 @@ il4965_hwrate_to_tx_control(struct il_priv *il, u32 rate_n_flags, | |||
2895 | * Handles block-acknowledge notification from device, which reports success | 2896 | * Handles block-acknowledge notification from device, which reports success |
2896 | * of frames sent via aggregation. | 2897 | * of frames sent via aggregation. |
2897 | */ | 2898 | */ |
2898 | void | 2899 | static void |
2899 | il4965_hdl_compressed_ba(struct il_priv *il, struct il_rx_buf *rxb) | 2900 | il4965_hdl_compressed_ba(struct il_priv *il, struct il_rx_buf *rxb) |
2900 | { | 2901 | { |
2901 | struct il_rx_pkt *pkt = rxb_addr(rxb); | 2902 | struct il_rx_pkt *pkt = rxb_addr(rxb); |
@@ -6316,7 +6317,7 @@ il4965_tx_queue_set_status(struct il_priv *il, struct il_tx_queue *txq, | |||
6316 | scd_retry ? "BA" : "AC", txq_id, tx_fifo_id); | 6317 | scd_retry ? "BA" : "AC", txq_id, tx_fifo_id); |
6317 | } | 6318 | } |
6318 | 6319 | ||
6319 | const struct ieee80211_ops il4965_mac_ops = { | 6320 | static const struct ieee80211_ops il4965_mac_ops = { |
6320 | .tx = il4965_mac_tx, | 6321 | .tx = il4965_mac_tx, |
6321 | .start = il4965_mac_start, | 6322 | .start = il4965_mac_start, |
6322 | .stop = il4965_mac_stop, | 6323 | .stop = il4965_mac_stop, |
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index e006ea831320..bc465da40476 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c | |||
@@ -1122,7 +1122,7 @@ il_set_power(struct il_priv *il, struct il_powertable_cmd *cmd) | |||
1122 | sizeof(struct il_powertable_cmd), cmd); | 1122 | sizeof(struct il_powertable_cmd), cmd); |
1123 | } | 1123 | } |
1124 | 1124 | ||
1125 | int | 1125 | static int |
1126 | il_power_set_mode(struct il_priv *il, struct il_powertable_cmd *cmd, bool force) | 1126 | il_power_set_mode(struct il_priv *il, struct il_powertable_cmd *cmd, bool force) |
1127 | { | 1127 | { |
1128 | int ret; | 1128 | int ret; |
diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index 96f2025d936e..73bd3ef316c8 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h | |||
@@ -541,10 +541,6 @@ struct il_frame { | |||
541 | struct list_head list; | 541 | struct list_head list; |
542 | }; | 542 | }; |
543 | 543 | ||
544 | #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) | ||
545 | #define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) | ||
546 | #define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) | ||
547 | |||
548 | enum { | 544 | enum { |
549 | CMD_SYNC = 0, | 545 | CMD_SYNC = 0, |
550 | CMD_SIZE_NORMAL = 0, | 546 | CMD_SIZE_NORMAL = 0, |
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index 323e4a33fcac..c7cd2dffa5cd 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c | |||
@@ -1137,7 +1137,8 @@ done: | |||
1137 | static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw, | 1137 | static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw, |
1138 | struct ieee80211_vif *vif, | 1138 | struct ieee80211_vif *vif, |
1139 | struct ieee80211_channel *channel, | 1139 | struct ieee80211_channel *channel, |
1140 | int duration) | 1140 | int duration, |
1141 | enum ieee80211_roc_type type) | ||
1141 | { | 1142 | { |
1142 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1143 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1143 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN]; | 1144 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN]; |
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index 303403b86b75..cc1e0c1a6f48 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c | |||
@@ -418,7 +418,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, | |||
418 | " Tx flags = 0x%08x, agg.state = %d", | 418 | " Tx flags = 0x%08x, agg.state = %d", |
419 | info->flags, tid_data->agg.state); | 419 | info->flags, tid_data->agg.state); |
420 | IWL_ERR(priv, "sta_id = %d, tid = %d seq_num = %d", | 420 | IWL_ERR(priv, "sta_id = %d, tid = %d seq_num = %d", |
421 | sta_id, tid, SEQ_TO_SN(tid_data->seq_number)); | 421 | sta_id, tid, |
422 | IEEE80211_SEQ_TO_SN(tid_data->seq_number)); | ||
422 | goto drop_unlock_sta; | 423 | goto drop_unlock_sta; |
423 | } | 424 | } |
424 | 425 | ||
@@ -569,7 +570,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
569 | return 0; | 570 | return 0; |
570 | } | 571 | } |
571 | 572 | ||
572 | tid_data->agg.ssn = SEQ_TO_SN(tid_data->seq_number); | 573 | tid_data->agg.ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); |
573 | 574 | ||
574 | /* There are still packets for this RA / TID in the HW */ | 575 | /* There are still packets for this RA / TID in the HW */ |
575 | if (!test_bit(txq_id, priv->agg_q_alloc)) { | 576 | if (!test_bit(txq_id, priv->agg_q_alloc)) { |
@@ -651,7 +652,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
651 | 652 | ||
652 | spin_lock_bh(&priv->sta_lock); | 653 | spin_lock_bh(&priv->sta_lock); |
653 | tid_data = &priv->tid_data[sta_id][tid]; | 654 | tid_data = &priv->tid_data[sta_id][tid]; |
654 | tid_data->agg.ssn = SEQ_TO_SN(tid_data->seq_number); | 655 | tid_data->agg.ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); |
655 | tid_data->agg.txq_id = txq_id; | 656 | tid_data->agg.txq_id = txq_id; |
656 | 657 | ||
657 | *ssn = tid_data->agg.ssn; | 658 | *ssn = tid_data->agg.ssn; |
@@ -911,7 +912,7 @@ static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status) | |||
911 | static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp) | 912 | static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp) |
912 | { | 913 | { |
913 | return le32_to_cpup((__le32 *)&tx_resp->status + | 914 | return le32_to_cpup((__le32 *)&tx_resp->status + |
914 | tx_resp->frame_count) & MAX_SN; | 915 | tx_resp->frame_count) & IEEE80211_MAX_SN; |
915 | } | 916 | } |
916 | 917 | ||
917 | static void iwl_rx_reply_tx_agg(struct iwl_priv *priv, | 918 | static void iwl_rx_reply_tx_agg(struct iwl_priv *priv, |
@@ -1148,7 +1149,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
1148 | 1149 | ||
1149 | if (tx_resp->frame_count == 1) { | 1150 | if (tx_resp->frame_count == 1) { |
1150 | u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl); | 1151 | u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl); |
1151 | next_reclaimed = SEQ_TO_SN(next_reclaimed + 0x10); | 1152 | next_reclaimed = IEEE80211_SEQ_TO_SN(next_reclaimed + 0x10); |
1152 | 1153 | ||
1153 | if (is_agg) { | 1154 | if (is_agg) { |
1154 | /* If this is an aggregation queue, we can rely on the | 1155 | /* If this is an aggregation queue, we can rely on the |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 205aab851e5f..7f9c254292a8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -114,9 +114,6 @@ | |||
114 | * completely agnostic to these differences. | 114 | * completely agnostic to these differences. |
115 | * The transport does provide helper functionnality (i.e. SYNC / ASYNC mode), | 115 | * The transport does provide helper functionnality (i.e. SYNC / ASYNC mode), |
116 | */ | 116 | */ |
117 | #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) | ||
118 | #define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) | ||
119 | #define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) | ||
120 | #define SEQ_TO_QUEUE(s) (((s) >> 8) & 0x1f) | 117 | #define SEQ_TO_QUEUE(s) (((s) >> 8) & 0x1f) |
121 | #define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8) | 118 | #define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8) |
122 | #define SEQ_TO_INDEX(s) ((s) & 0xff) | 119 | #define SEQ_TO_INDEX(s) ((s) & 0xff) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index ccbeaed60943..de4e0e476f4e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -1139,7 +1139,8 @@ static void iwl_mvm_mac_update_tkip_key(struct ieee80211_hw *hw, | |||
1139 | static int iwl_mvm_roc(struct ieee80211_hw *hw, | 1139 | static int iwl_mvm_roc(struct ieee80211_hw *hw, |
1140 | struct ieee80211_vif *vif, | 1140 | struct ieee80211_vif *vif, |
1141 | struct ieee80211_channel *channel, | 1141 | struct ieee80211_channel *channel, |
1142 | int duration) | 1142 | int duration, |
1143 | enum ieee80211_roc_type type) | ||
1143 | { | 1144 | { |
1144 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 1145 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
1145 | struct cfg80211_chan_def chandef; | 1146 | struct cfg80211_chan_def chandef; |
@@ -1150,8 +1151,8 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, | |||
1150 | return -EINVAL; | 1151 | return -EINVAL; |
1151 | } | 1152 | } |
1152 | 1153 | ||
1153 | IWL_DEBUG_MAC80211(mvm, "enter (%d, %d)\n", channel->hw_value, | 1154 | IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value, |
1154 | duration); | 1155 | duration, type); |
1155 | 1156 | ||
1156 | mutex_lock(&mvm->mutex); | 1157 | mutex_lock(&mvm->mutex); |
1157 | 1158 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 4872ec23b371..4d872d69577f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
@@ -733,7 +733,7 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
733 | 733 | ||
734 | spin_lock_bh(&mvmsta->lock); | 734 | spin_lock_bh(&mvmsta->lock); |
735 | tid_data = &mvmsta->tid_data[tid]; | 735 | tid_data = &mvmsta->tid_data[tid]; |
736 | tid_data->ssn = SEQ_TO_SN(tid_data->seq_number); | 736 | tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); |
737 | tid_data->txq_id = txq_id; | 737 | tid_data->txq_id = txq_id; |
738 | *ssn = tid_data->ssn; | 738 | *ssn = tid_data->ssn; |
739 | 739 | ||
@@ -836,7 +836,7 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
836 | 836 | ||
837 | switch (tid_data->state) { | 837 | switch (tid_data->state) { |
838 | case IWL_AGG_ON: | 838 | case IWL_AGG_ON: |
839 | tid_data->ssn = SEQ_TO_SN(tid_data->seq_number); | 839 | tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); |
840 | 840 | ||
841 | IWL_DEBUG_TX_QUEUES(mvm, | 841 | IWL_DEBUG_TX_QUEUES(mvm, |
842 | "ssn = %d, next_recl = %d\n", | 842 | "ssn = %d, next_recl = %d\n", |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index ccff2e5f71a6..0acc0bff43c7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c | |||
@@ -637,7 +637,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
637 | next_reclaimed = ssn; | 637 | next_reclaimed = ssn; |
638 | } else { | 638 | } else { |
639 | /* The next packet to be reclaimed is the one after this one */ | 639 | /* The next packet to be reclaimed is the one after this one */ |
640 | next_reclaimed = SEQ_TO_SN(seq_ctl + 0x10); | 640 | next_reclaimed = IEEE80211_SEQ_TO_SN(seq_ctl + 0x10); |
641 | } | 641 | } |
642 | 642 | ||
643 | IWL_DEBUG_TX_REPLY(mvm, | 643 | IWL_DEBUG_TX_REPLY(mvm, |
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index b29034d9c963..a4508c2fa92b 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
@@ -1612,7 +1612,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
1612 | * Check here that the packets are in the right place on the ring. | 1612 | * Check here that the packets are in the right place on the ring. |
1613 | */ | 1613 | */ |
1614 | #ifdef CONFIG_IWLWIFI_DEBUG | 1614 | #ifdef CONFIG_IWLWIFI_DEBUG |
1615 | wifi_seq = SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); | 1615 | wifi_seq = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); |
1616 | WARN_ONCE((iwl_read_prph(trans, SCD_AGGR_SEL) & BIT(txq_id)) && | 1616 | WARN_ONCE((iwl_read_prph(trans, SCD_AGGR_SEL) & BIT(txq_id)) && |
1617 | ((wifi_seq & 0xff) != q->write_ptr), | 1617 | ((wifi_seq & 0xff) != q->write_ptr), |
1618 | "Q: %d WiFi Seq %d tfdNum %d", | 1618 | "Q: %d WiFi Seq %d tfdNum %d", |
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 739309e70d8b..45578335e420 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c | |||
@@ -825,6 +825,11 @@ static void if_sdio_finish_power_on(struct if_sdio_card *card) | |||
825 | 825 | ||
826 | sdio_release_host(func); | 826 | sdio_release_host(func); |
827 | 827 | ||
828 | /* Set fw_ready before queuing any commands so that | ||
829 | * lbs_thread won't block from sending them to firmware. | ||
830 | */ | ||
831 | priv->fw_ready = 1; | ||
832 | |||
828 | /* | 833 | /* |
829 | * FUNC_INIT is required for SD8688 WLAN/BT multiple functions | 834 | * FUNC_INIT is required for SD8688 WLAN/BT multiple functions |
830 | */ | 835 | */ |
@@ -839,7 +844,6 @@ static void if_sdio_finish_power_on(struct if_sdio_card *card) | |||
839 | netdev_alert(priv->dev, "CMD_FUNC_INIT cmd failed\n"); | 844 | netdev_alert(priv->dev, "CMD_FUNC_INIT cmd failed\n"); |
840 | } | 845 | } |
841 | 846 | ||
842 | priv->fw_ready = 1; | ||
843 | wake_up(&card->pwron_waitq); | 847 | wake_up(&card->pwron_waitq); |
844 | 848 | ||
845 | if (!card->started) { | 849 | if (!card->started) { |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index cffdf4fbf161..7490c4fc7177 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -1535,7 +1535,8 @@ static void hw_roc_done(struct work_struct *work) | |||
1535 | static int mac80211_hwsim_roc(struct ieee80211_hw *hw, | 1535 | static int mac80211_hwsim_roc(struct ieee80211_hw *hw, |
1536 | struct ieee80211_vif *vif, | 1536 | struct ieee80211_vif *vif, |
1537 | struct ieee80211_channel *chan, | 1537 | struct ieee80211_channel *chan, |
1538 | int duration) | 1538 | int duration, |
1539 | enum ieee80211_roc_type type) | ||
1539 | { | 1540 | { |
1540 | struct mac80211_hwsim_data *hwsim = hw->priv; | 1541 | struct mac80211_hwsim_data *hwsim = hw->priv; |
1541 | 1542 | ||
diff --git a/drivers/net/wireless/mwifiex/Makefile b/drivers/net/wireless/mwifiex/Makefile index 97b245cbafd8..ecf28464367f 100644 --- a/drivers/net/wireless/mwifiex/Makefile +++ b/drivers/net/wireless/mwifiex/Makefile | |||
@@ -39,6 +39,7 @@ mwifiex-y += sta_tx.o | |||
39 | mwifiex-y += sta_rx.o | 39 | mwifiex-y += sta_rx.o |
40 | mwifiex-y += uap_txrx.o | 40 | mwifiex-y += uap_txrx.o |
41 | mwifiex-y += cfg80211.o | 41 | mwifiex-y += cfg80211.o |
42 | mwifiex-y += ethtool.o | ||
42 | mwifiex-$(CONFIG_DEBUG_FS) += debugfs.o | 43 | mwifiex-$(CONFIG_DEBUG_FS) += debugfs.o |
43 | obj-$(CONFIG_MWIFIEX) += mwifiex.o | 44 | obj-$(CONFIG_MWIFIEX) += mwifiex.o |
44 | 45 | ||
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index a44023a7bd57..dbf5b1289516 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -1932,66 +1932,10 @@ static void mwifiex_setup_vht_caps(struct ieee80211_sta_vht_cap *vht_info, | |||
1932 | struct mwifiex_private *priv) | 1932 | struct mwifiex_private *priv) |
1933 | { | 1933 | { |
1934 | struct mwifiex_adapter *adapter = priv->adapter; | 1934 | struct mwifiex_adapter *adapter = priv->adapter; |
1935 | u32 vht_cap = 0, cap = adapter->hw_dot_11ac_dev_cap; | ||
1936 | 1935 | ||
1937 | vht_info->vht_supported = true; | 1936 | vht_info->vht_supported = true; |
1938 | 1937 | ||
1939 | switch (GET_VHTCAP_MAXMPDULEN(cap)) { | 1938 | vht_info->cap = adapter->hw_dot_11ac_dev_cap; |
1940 | case 0x00: | ||
1941 | vht_cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895; | ||
1942 | break; | ||
1943 | case 0x01: | ||
1944 | vht_cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991; | ||
1945 | break; | ||
1946 | case 0x10: | ||
1947 | vht_cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454; | ||
1948 | break; | ||
1949 | default: | ||
1950 | dev_err(adapter->dev, "unsupported MAX MPDU len\n"); | ||
1951 | break; | ||
1952 | } | ||
1953 | |||
1954 | if (ISSUPP_11ACVHTHTCVHT(cap)) | ||
1955 | vht_cap |= IEEE80211_VHT_CAP_HTC_VHT; | ||
1956 | |||
1957 | if (ISSUPP_11ACVHTTXOPPS(cap)) | ||
1958 | vht_cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS; | ||
1959 | |||
1960 | if (ISSUPP_11ACMURXBEAMFORMEE(cap)) | ||
1961 | vht_cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE; | ||
1962 | |||
1963 | if (ISSUPP_11ACMUTXBEAMFORMEE(cap)) | ||
1964 | vht_cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE; | ||
1965 | |||
1966 | if (ISSUPP_11ACSUBEAMFORMER(cap)) | ||
1967 | vht_cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE; | ||
1968 | |||
1969 | if (ISSUPP_11ACSUBEAMFORMEE(cap)) | ||
1970 | vht_cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; | ||
1971 | |||
1972 | if (ISSUPP_11ACRXSTBC(cap)) | ||
1973 | vht_cap |= IEEE80211_VHT_CAP_RXSTBC_1; | ||
1974 | |||
1975 | if (ISSUPP_11ACTXSTBC(cap)) | ||
1976 | vht_cap |= IEEE80211_VHT_CAP_TXSTBC; | ||
1977 | |||
1978 | if (ISSUPP_11ACSGI160(cap)) | ||
1979 | vht_cap |= IEEE80211_VHT_CAP_SHORT_GI_160; | ||
1980 | |||
1981 | if (ISSUPP_11ACSGI80(cap)) | ||
1982 | vht_cap |= IEEE80211_VHT_CAP_SHORT_GI_80; | ||
1983 | |||
1984 | if (ISSUPP_11ACLDPC(cap)) | ||
1985 | vht_cap |= IEEE80211_VHT_CAP_RXLDPC; | ||
1986 | |||
1987 | if (ISSUPP_11ACBW8080(cap)) | ||
1988 | vht_cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; | ||
1989 | |||
1990 | if (ISSUPP_11ACBW160(cap)) | ||
1991 | vht_cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; | ||
1992 | |||
1993 | vht_info->cap = vht_cap; | ||
1994 | |||
1995 | /* Update MCS support for VHT */ | 1939 | /* Update MCS support for VHT */ |
1996 | vht_info->vht_mcs.rx_mcs_map = cpu_to_le16( | 1940 | vht_info->vht_mcs.rx_mcs_map = cpu_to_le16( |
1997 | adapter->hw_dot_11ac_mcs_support & 0xFFFF); | 1941 | adapter->hw_dot_11ac_mcs_support & 0xFFFF); |
@@ -2235,6 +2179,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
2235 | dev->flags |= IFF_BROADCAST | IFF_MULTICAST; | 2179 | dev->flags |= IFF_BROADCAST | IFF_MULTICAST; |
2236 | dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT; | 2180 | dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT; |
2237 | dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN; | 2181 | dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN; |
2182 | dev->ethtool_ops = &mwifiex_ethtool_ops; | ||
2238 | 2183 | ||
2239 | mdev_priv = netdev_priv(dev); | 2184 | mdev_priv = netdev_priv(dev); |
2240 | *((unsigned long *) mdev_priv) = (unsigned long) priv; | 2185 | *((unsigned long *) mdev_priv) = (unsigned long) priv; |
@@ -2293,6 +2238,152 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
2293 | } | 2238 | } |
2294 | EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf); | 2239 | EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf); |
2295 | 2240 | ||
2241 | #ifdef CONFIG_PM | ||
2242 | static bool | ||
2243 | mwifiex_is_pattern_supported(struct cfg80211_wowlan_trig_pkt_pattern *pat, | ||
2244 | s8 *byte_seq) | ||
2245 | { | ||
2246 | int j, k, valid_byte_cnt = 0; | ||
2247 | bool dont_care_byte = false; | ||
2248 | |||
2249 | for (j = 0; j < DIV_ROUND_UP(pat->pattern_len, 8); j++) { | ||
2250 | for (k = 0; k < 8; k++) { | ||
2251 | if (pat->mask[j] & 1 << k) { | ||
2252 | memcpy(byte_seq + valid_byte_cnt, | ||
2253 | &pat->pattern[j * 8 + k], 1); | ||
2254 | valid_byte_cnt++; | ||
2255 | if (dont_care_byte) | ||
2256 | return false; | ||
2257 | } else { | ||
2258 | if (valid_byte_cnt) | ||
2259 | dont_care_byte = true; | ||
2260 | } | ||
2261 | |||
2262 | if (valid_byte_cnt > MAX_BYTESEQ) | ||
2263 | return false; | ||
2264 | } | ||
2265 | } | ||
2266 | |||
2267 | byte_seq[MAX_BYTESEQ] = valid_byte_cnt; | ||
2268 | |||
2269 | return true; | ||
2270 | } | ||
2271 | |||
2272 | static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, | ||
2273 | struct cfg80211_wowlan *wowlan) | ||
2274 | { | ||
2275 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); | ||
2276 | struct mwifiex_ds_mef_cfg mef_cfg; | ||
2277 | struct mwifiex_mef_entry *mef_entry; | ||
2278 | int i, filt_num = 0, ret; | ||
2279 | bool first_pat = true; | ||
2280 | u8 byte_seq[MAX_BYTESEQ + 1]; | ||
2281 | const u8 ipv4_mc_mac[] = {0x33, 0x33}; | ||
2282 | const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e}; | ||
2283 | struct mwifiex_private *priv = | ||
2284 | mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); | ||
2285 | |||
2286 | if (!wowlan) { | ||
2287 | dev_warn(adapter->dev, "None of the WOWLAN triggers enabled\n"); | ||
2288 | return 0; | ||
2289 | } | ||
2290 | |||
2291 | if (!priv->media_connected) { | ||
2292 | dev_warn(adapter->dev, | ||
2293 | "Can not configure WOWLAN in disconnected state\n"); | ||
2294 | return 0; | ||
2295 | } | ||
2296 | |||
2297 | mef_entry = kzalloc(sizeof(*mef_entry), GFP_KERNEL); | ||
2298 | if (!mef_entry) | ||
2299 | return -ENOMEM; | ||
2300 | |||
2301 | memset(&mef_cfg, 0, sizeof(mef_cfg)); | ||
2302 | mef_cfg.num_entries = 1; | ||
2303 | mef_cfg.mef_entry = mef_entry; | ||
2304 | mef_entry->mode = MEF_MODE_HOST_SLEEP; | ||
2305 | mef_entry->action = MEF_ACTION_ALLOW_AND_WAKEUP_HOST; | ||
2306 | |||
2307 | for (i = 0; i < wowlan->n_patterns; i++) { | ||
2308 | memset(byte_seq, 0, sizeof(byte_seq)); | ||
2309 | if (!mwifiex_is_pattern_supported(&wowlan->patterns[i], | ||
2310 | byte_seq)) { | ||
2311 | wiphy_err(wiphy, "Pattern not supported\n"); | ||
2312 | kfree(mef_entry); | ||
2313 | return -EOPNOTSUPP; | ||
2314 | } | ||
2315 | |||
2316 | if (!wowlan->patterns[i].pkt_offset) { | ||
2317 | if (!(byte_seq[0] & 0x01) && | ||
2318 | (byte_seq[MAX_BYTESEQ] == 1)) { | ||
2319 | mef_cfg.criteria |= MWIFIEX_CRITERIA_UNICAST; | ||
2320 | continue; | ||
2321 | } else if (is_broadcast_ether_addr(byte_seq)) { | ||
2322 | mef_cfg.criteria |= MWIFIEX_CRITERIA_BROADCAST; | ||
2323 | continue; | ||
2324 | } else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) && | ||
2325 | (byte_seq[MAX_BYTESEQ] == 2)) || | ||
2326 | (!memcmp(byte_seq, ipv6_mc_mac, 3) && | ||
2327 | (byte_seq[MAX_BYTESEQ] == 3))) { | ||
2328 | mef_cfg.criteria |= MWIFIEX_CRITERIA_MULTICAST; | ||
2329 | continue; | ||
2330 | } | ||
2331 | } | ||
2332 | |||
2333 | mef_entry->filter[filt_num].repeat = 1; | ||
2334 | mef_entry->filter[filt_num].offset = | ||
2335 | wowlan->patterns[i].pkt_offset; | ||
2336 | memcpy(mef_entry->filter[filt_num].byte_seq, byte_seq, | ||
2337 | sizeof(byte_seq)); | ||
2338 | mef_entry->filter[filt_num].filt_type = TYPE_EQ; | ||
2339 | |||
2340 | if (first_pat) | ||
2341 | first_pat = false; | ||
2342 | else | ||
2343 | mef_entry->filter[filt_num].filt_action = TYPE_AND; | ||
2344 | |||
2345 | filt_num++; | ||
2346 | } | ||
2347 | |||
2348 | if (wowlan->magic_pkt) { | ||
2349 | mef_cfg.criteria |= MWIFIEX_CRITERIA_UNICAST; | ||
2350 | mef_entry->filter[filt_num].repeat = 16; | ||
2351 | memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr, | ||
2352 | ETH_ALEN); | ||
2353 | mef_entry->filter[filt_num].byte_seq[MAX_BYTESEQ] = ETH_ALEN; | ||
2354 | mef_entry->filter[filt_num].offset = 14; | ||
2355 | mef_entry->filter[filt_num].filt_type = TYPE_EQ; | ||
2356 | if (filt_num) | ||
2357 | mef_entry->filter[filt_num].filt_action = TYPE_OR; | ||
2358 | } | ||
2359 | |||
2360 | if (!mef_cfg.criteria) | ||
2361 | mef_cfg.criteria = MWIFIEX_CRITERIA_BROADCAST | | ||
2362 | MWIFIEX_CRITERIA_UNICAST | | ||
2363 | MWIFIEX_CRITERIA_MULTICAST; | ||
2364 | |||
2365 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_MEF_CFG, | ||
2366 | HostCmd_ACT_GEN_SET, 0, | ||
2367 | &mef_cfg); | ||
2368 | |||
2369 | kfree(mef_entry); | ||
2370 | return ret; | ||
2371 | } | ||
2372 | |||
2373 | static int mwifiex_cfg80211_resume(struct wiphy *wiphy) | ||
2374 | { | ||
2375 | return 0; | ||
2376 | } | ||
2377 | |||
2378 | static void mwifiex_cfg80211_set_wakeup(struct wiphy *wiphy, | ||
2379 | bool enabled) | ||
2380 | { | ||
2381 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); | ||
2382 | |||
2383 | device_set_wakeup_enable(adapter->dev, enabled); | ||
2384 | } | ||
2385 | #endif | ||
2386 | |||
2296 | /* station cfg80211 operations */ | 2387 | /* station cfg80211 operations */ |
2297 | static struct cfg80211_ops mwifiex_cfg80211_ops = { | 2388 | static struct cfg80211_ops mwifiex_cfg80211_ops = { |
2298 | .add_virtual_intf = mwifiex_add_virtual_intf, | 2389 | .add_virtual_intf = mwifiex_add_virtual_intf, |
@@ -2321,6 +2412,11 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { | |||
2321 | .change_beacon = mwifiex_cfg80211_change_beacon, | 2412 | .change_beacon = mwifiex_cfg80211_change_beacon, |
2322 | .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config, | 2413 | .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config, |
2323 | .set_antenna = mwifiex_cfg80211_set_antenna, | 2414 | .set_antenna = mwifiex_cfg80211_set_antenna, |
2415 | #ifdef CONFIG_PM | ||
2416 | .suspend = mwifiex_cfg80211_suspend, | ||
2417 | .resume = mwifiex_cfg80211_resume, | ||
2418 | .set_wakeup = mwifiex_cfg80211_set_wakeup, | ||
2419 | #endif | ||
2324 | }; | 2420 | }; |
2325 | 2421 | ||
2326 | /* | 2422 | /* |
@@ -2379,6 +2475,14 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) | |||
2379 | 2475 | ||
2380 | wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom); | 2476 | wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom); |
2381 | 2477 | ||
2478 | #ifdef CONFIG_PM | ||
2479 | wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT; | ||
2480 | wiphy->wowlan.n_patterns = MWIFIEX_MAX_FILTERS; | ||
2481 | wiphy->wowlan.pattern_min_len = 1; | ||
2482 | wiphy->wowlan.pattern_max_len = MWIFIEX_MAX_PATTERN_LEN; | ||
2483 | wiphy->wowlan.max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN; | ||
2484 | #endif | ||
2485 | |||
2382 | wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | | 2486 | wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | |
2383 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | | 2487 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | |
2384 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; | 2488 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; |
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 20a6c5555873..d19a88c47a4d 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c | |||
@@ -1139,7 +1139,7 @@ int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv, | |||
1139 | phs_cfg->params.hs_config.gpio, | 1139 | phs_cfg->params.hs_config.gpio, |
1140 | phs_cfg->params.hs_config.gap); | 1140 | phs_cfg->params.hs_config.gap); |
1141 | } | 1141 | } |
1142 | if (conditions != HOST_SLEEP_CFG_CANCEL) { | 1142 | if (conditions != HS_CFG_CANCEL) { |
1143 | adapter->is_hs_configured = true; | 1143 | adapter->is_hs_configured = true; |
1144 | if (adapter->iface_type == MWIFIEX_USB || | 1144 | if (adapter->iface_type == MWIFIEX_USB || |
1145 | adapter->iface_type == MWIFIEX_PCIE) | 1145 | adapter->iface_type == MWIFIEX_PCIE) |
diff --git a/drivers/net/wireless/mwifiex/ethtool.c b/drivers/net/wireless/mwifiex/ethtool.c new file mode 100644 index 000000000000..bfb39908b2c6 --- /dev/null +++ b/drivers/net/wireless/mwifiex/ethtool.c | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * Marvell Wireless LAN device driver: ethtool | ||
3 | * | ||
4 | * Copyright (C) 2013, Marvell International Ltd. | ||
5 | * | ||
6 | * This software file (the "File") is distributed by Marvell International | ||
7 | * Ltd. under the terms of the GNU General Public License Version 2, June 1991 | ||
8 | * (the "License"). You may use, redistribute and/or modify this File in | ||
9 | * accordance with the terms and conditions of the License, a copy of which | ||
10 | * is available by writing to the Free Software Foundation, Inc., | ||
11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the | ||
12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. | ||
13 | * | ||
14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE | ||
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE | ||
16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about | ||
17 | * this warranty disclaimer. | ||
18 | */ | ||
19 | |||
20 | #include "main.h" | ||
21 | |||
22 | static void mwifiex_ethtool_get_wol(struct net_device *dev, | ||
23 | struct ethtool_wolinfo *wol) | ||
24 | { | ||
25 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | ||
26 | u32 conditions = le32_to_cpu(priv->adapter->hs_cfg.conditions); | ||
27 | |||
28 | wol->supported = WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY; | ||
29 | |||
30 | if (conditions == HS_CFG_COND_DEF) | ||
31 | return; | ||
32 | |||
33 | if (conditions & HS_CFG_COND_UNICAST_DATA) | ||
34 | wol->wolopts |= WAKE_UCAST; | ||
35 | if (conditions & HS_CFG_COND_MULTICAST_DATA) | ||
36 | wol->wolopts |= WAKE_MCAST; | ||
37 | if (conditions & HS_CFG_COND_BROADCAST_DATA) | ||
38 | wol->wolopts |= WAKE_BCAST; | ||
39 | if (conditions & HS_CFG_COND_MAC_EVENT) | ||
40 | wol->wolopts |= WAKE_PHY; | ||
41 | } | ||
42 | |||
43 | static int mwifiex_ethtool_set_wol(struct net_device *dev, | ||
44 | struct ethtool_wolinfo *wol) | ||
45 | { | ||
46 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | ||
47 | u32 conditions = 0; | ||
48 | |||
49 | if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY)) | ||
50 | return -EOPNOTSUPP; | ||
51 | |||
52 | if (wol->wolopts & WAKE_UCAST) | ||
53 | conditions |= HS_CFG_COND_UNICAST_DATA; | ||
54 | if (wol->wolopts & WAKE_MCAST) | ||
55 | conditions |= HS_CFG_COND_MULTICAST_DATA; | ||
56 | if (wol->wolopts & WAKE_BCAST) | ||
57 | conditions |= HS_CFG_COND_BROADCAST_DATA; | ||
58 | if (wol->wolopts & WAKE_PHY) | ||
59 | conditions |= HS_CFG_COND_MAC_EVENT; | ||
60 | if (wol->wolopts == 0) | ||
61 | conditions |= HS_CFG_COND_DEF; | ||
62 | priv->adapter->hs_cfg.conditions = cpu_to_le32(conditions); | ||
63 | |||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | const struct ethtool_ops mwifiex_ethtool_ops = { | ||
68 | .get_wol = mwifiex_ethtool_get_wol, | ||
69 | .set_wol = mwifiex_ethtool_set_wol, | ||
70 | }; | ||
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 25acb0682c56..57c5defe1f9d 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
@@ -230,40 +230,12 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
230 | 230 | ||
231 | #define ISSUPP_11ACENABLED(fw_cap_info) (fw_cap_info & (BIT(13)|BIT(14))) | 231 | #define ISSUPP_11ACENABLED(fw_cap_info) (fw_cap_info & (BIT(13)|BIT(14))) |
232 | 232 | ||
233 | #define GET_VHTCAP_MAXMPDULEN(vht_cap_info) (vht_cap_info & 0x3) | ||
234 | #define GET_VHTCAP_CHWDSET(vht_cap_info) ((vht_cap_info >> 2) & 0x3) | 233 | #define GET_VHTCAP_CHWDSET(vht_cap_info) ((vht_cap_info >> 2) & 0x3) |
235 | #define GET_VHTNSSMCS(mcs_mapset, nss) ((mcs_mapset >> (2 * (nss - 1))) & 0x3) | 234 | #define GET_VHTNSSMCS(mcs_mapset, nss) ((mcs_mapset >> (2 * (nss - 1))) & 0x3) |
236 | #define SET_VHTNSSMCS(mcs_mapset, nss, value) (mcs_mapset |= (value & 0x3) << \ | 235 | #define SET_VHTNSSMCS(mcs_mapset, nss, value) (mcs_mapset |= (value & 0x3) << \ |
237 | (2 * (nss - 1))) | 236 | (2 * (nss - 1))) |
238 | #define NO_NSS_SUPPORT 0x3 | 237 | #define NO_NSS_SUPPORT 0x3 |
239 | 238 | ||
240 | /* HW_SPEC: HTC-VHT supported */ | ||
241 | #define ISSUPP_11ACVHTHTCVHT(Dot11acDevCap) (Dot11acDevCap & BIT(22)) | ||
242 | /* HW_SPEC: VHT TXOP PS support */ | ||
243 | #define ISSUPP_11ACVHTTXOPPS(Dot11acDevCap) (Dot11acDevCap & BIT(21)) | ||
244 | /* HW_SPEC: MU RX beamformee support */ | ||
245 | #define ISSUPP_11ACMURXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & BIT(20)) | ||
246 | /* HW_SPEC: MU TX beamformee support */ | ||
247 | #define ISSUPP_11ACMUTXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & BIT(19)) | ||
248 | /* HW_SPEC: SU Beamformee support */ | ||
249 | #define ISSUPP_11ACSUBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & BIT(10)) | ||
250 | /* HW_SPEC: SU Beamformer support */ | ||
251 | #define ISSUPP_11ACSUBEAMFORMER(Dot11acDevCap) (Dot11acDevCap & BIT(9)) | ||
252 | /* HW_SPEC: Rx STBC support */ | ||
253 | #define ISSUPP_11ACRXSTBC(Dot11acDevCap) (Dot11acDevCap & BIT(8)) | ||
254 | /* HW_SPEC: Tx STBC support */ | ||
255 | #define ISSUPP_11ACTXSTBC(Dot11acDevCap) (Dot11acDevCap & BIT(7)) | ||
256 | /* HW_SPEC: Short GI support for 160MHz BW */ | ||
257 | #define ISSUPP_11ACSGI160(Dot11acDevCap) (Dot11acDevCap & BIT(6)) | ||
258 | /* HW_SPEC: Short GI support for 80MHz BW */ | ||
259 | #define ISSUPP_11ACSGI80(Dot11acDevCap) (Dot11acDevCap & BIT(5)) | ||
260 | /* HW_SPEC: LDPC coding support */ | ||
261 | #define ISSUPP_11ACLDPC(Dot11acDevCap) (Dot11acDevCap & BIT(4)) | ||
262 | /* HW_SPEC: Channel BW 20/40/80/160/80+80 MHz support */ | ||
263 | #define ISSUPP_11ACBW8080(Dot11acDevCap) (Dot11acDevCap & BIT(3)) | ||
264 | /* HW_SPEC: Channel BW 20/40/80/160 MHz support */ | ||
265 | #define ISSUPP_11ACBW160(Dot11acDevCap) (Dot11acDevCap & BIT(2)) | ||
266 | |||
267 | #define GET_DEVTXMCSMAP(dev_mcs_map) (dev_mcs_map >> 16) | 239 | #define GET_DEVTXMCSMAP(dev_mcs_map) (dev_mcs_map >> 16) |
268 | #define GET_DEVRXMCSMAP(dev_mcs_map) (dev_mcs_map & 0xFFFF) | 240 | #define GET_DEVRXMCSMAP(dev_mcs_map) (dev_mcs_map & 0xFFFF) |
269 | 241 | ||
@@ -300,6 +272,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
300 | #define HostCmd_CMD_802_11_TX_RATE_QUERY 0x007f | 272 | #define HostCmd_CMD_802_11_TX_RATE_QUERY 0x007f |
301 | #define HostCmd_CMD_802_11_IBSS_COALESCING_STATUS 0x0083 | 273 | #define HostCmd_CMD_802_11_IBSS_COALESCING_STATUS 0x0083 |
302 | #define HostCmd_CMD_VERSION_EXT 0x0097 | 274 | #define HostCmd_CMD_VERSION_EXT 0x0097 |
275 | #define HostCmd_CMD_MEF_CFG 0x009a | ||
303 | #define HostCmd_CMD_RSSI_INFO 0x00a4 | 276 | #define HostCmd_CMD_RSSI_INFO 0x00a4 |
304 | #define HostCmd_CMD_FUNC_INIT 0x00a9 | 277 | #define HostCmd_CMD_FUNC_INIT 0x00a9 |
305 | #define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa | 278 | #define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa |
@@ -376,10 +349,14 @@ enum P2P_MODES { | |||
376 | #define HostCmd_SCAN_RADIO_TYPE_BG 0 | 349 | #define HostCmd_SCAN_RADIO_TYPE_BG 0 |
377 | #define HostCmd_SCAN_RADIO_TYPE_A 1 | 350 | #define HostCmd_SCAN_RADIO_TYPE_A 1 |
378 | 351 | ||
379 | #define HOST_SLEEP_CFG_CANCEL 0xffffffff | 352 | #define HS_CFG_CANCEL 0xffffffff |
380 | #define HOST_SLEEP_CFG_COND_DEF 0x00000000 | 353 | #define HS_CFG_COND_DEF 0x00000000 |
381 | #define HOST_SLEEP_CFG_GPIO_DEF 0xff | 354 | #define HS_CFG_GPIO_DEF 0xff |
382 | #define HOST_SLEEP_CFG_GAP_DEF 0 | 355 | #define HS_CFG_GAP_DEF 0 |
356 | #define HS_CFG_COND_BROADCAST_DATA 0x00000001 | ||
357 | #define HS_CFG_COND_UNICAST_DATA 0x00000002 | ||
358 | #define HS_CFG_COND_MAC_EVENT 0x00000004 | ||
359 | #define HS_CFG_COND_MULTICAST_DATA 0x00000008 | ||
383 | 360 | ||
384 | #define MWIFIEX_TIMEOUT_FOR_AP_RESP 0xfffc | 361 | #define MWIFIEX_TIMEOUT_FOR_AP_RESP 0xfffc |
385 | #define MWIFIEX_STATUS_CODE_AUTH_TIMEOUT 2 | 362 | #define MWIFIEX_STATUS_CODE_AUTH_TIMEOUT 2 |
@@ -469,6 +446,23 @@ enum P2P_MODES { | |||
469 | #define EVENT_GET_BSS_TYPE(event_cause) \ | 446 | #define EVENT_GET_BSS_TYPE(event_cause) \ |
470 | (((event_cause) >> 24) & 0x00ff) | 447 | (((event_cause) >> 24) & 0x00ff) |
471 | 448 | ||
449 | #define MWIFIEX_MAX_PATTERN_LEN 20 | ||
450 | #define MWIFIEX_MAX_OFFSET_LEN 50 | ||
451 | #define STACK_NBYTES 100 | ||
452 | #define TYPE_DNUM 1 | ||
453 | #define TYPE_BYTESEQ 2 | ||
454 | #define MAX_OPERAND 0x40 | ||
455 | #define TYPE_EQ (MAX_OPERAND+1) | ||
456 | #define TYPE_EQ_DNUM (MAX_OPERAND+2) | ||
457 | #define TYPE_EQ_BIT (MAX_OPERAND+3) | ||
458 | #define TYPE_AND (MAX_OPERAND+4) | ||
459 | #define TYPE_OR (MAX_OPERAND+5) | ||
460 | #define MEF_MODE_HOST_SLEEP 1 | ||
461 | #define MEF_ACTION_ALLOW_AND_WAKEUP_HOST 3 | ||
462 | #define MWIFIEX_CRITERIA_BROADCAST BIT(0) | ||
463 | #define MWIFIEX_CRITERIA_UNICAST BIT(1) | ||
464 | #define MWIFIEX_CRITERIA_MULTICAST BIT(3) | ||
465 | |||
472 | struct mwifiex_ie_types_header { | 466 | struct mwifiex_ie_types_header { |
473 | __le16 type; | 467 | __le16 type; |
474 | __le16 len; | 468 | __le16 len; |
@@ -1499,6 +1493,19 @@ struct host_cmd_ds_802_11_ibss_status { | |||
1499 | __le16 use_g_rate_protect; | 1493 | __le16 use_g_rate_protect; |
1500 | } __packed; | 1494 | } __packed; |
1501 | 1495 | ||
1496 | struct mwifiex_fw_mef_entry { | ||
1497 | u8 mode; | ||
1498 | u8 action; | ||
1499 | __le16 exprsize; | ||
1500 | u8 expr[0]; | ||
1501 | } __packed; | ||
1502 | |||
1503 | struct host_cmd_ds_mef_cfg { | ||
1504 | __le32 criteria; | ||
1505 | __le16 num_entries; | ||
1506 | struct mwifiex_fw_mef_entry mef_entry[0]; | ||
1507 | } __packed; | ||
1508 | |||
1502 | #define CONNECTION_TYPE_INFRA 0 | 1509 | #define CONNECTION_TYPE_INFRA 0 |
1503 | #define CONNECTION_TYPE_ADHOC 1 | 1510 | #define CONNECTION_TYPE_ADHOC 1 |
1504 | #define CONNECTION_TYPE_AP 2 | 1511 | #define CONNECTION_TYPE_AP 2 |
@@ -1603,6 +1610,7 @@ struct host_cmd_ds_command { | |||
1603 | struct host_cmd_ds_remain_on_chan roc_cfg; | 1610 | struct host_cmd_ds_remain_on_chan roc_cfg; |
1604 | struct host_cmd_ds_p2p_mode_cfg mode_cfg; | 1611 | struct host_cmd_ds_p2p_mode_cfg mode_cfg; |
1605 | struct host_cmd_ds_802_11_ibss_status ibss_coalescing; | 1612 | struct host_cmd_ds_802_11_ibss_status ibss_coalescing; |
1613 | struct host_cmd_ds_mef_cfg mef_cfg; | ||
1606 | struct host_cmd_ds_mac_reg_access mac_reg; | 1614 | struct host_cmd_ds_mac_reg_access mac_reg; |
1607 | struct host_cmd_ds_bbp_reg_access bbp_reg; | 1615 | struct host_cmd_ds_bbp_reg_access bbp_reg; |
1608 | struct host_cmd_ds_rf_reg_access rf_reg; | 1616 | struct host_cmd_ds_rf_reg_access rf_reg; |
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index e38aa9b3663d..cab3434d0d52 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c | |||
@@ -318,9 +318,9 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) | |||
318 | adapter->curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; | 318 | adapter->curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; |
319 | 319 | ||
320 | adapter->is_hs_configured = false; | 320 | adapter->is_hs_configured = false; |
321 | adapter->hs_cfg.conditions = cpu_to_le32(HOST_SLEEP_CFG_COND_DEF); | 321 | adapter->hs_cfg.conditions = cpu_to_le32(HS_CFG_COND_DEF); |
322 | adapter->hs_cfg.gpio = HOST_SLEEP_CFG_GPIO_DEF; | 322 | adapter->hs_cfg.gpio = HS_CFG_GPIO_DEF; |
323 | adapter->hs_cfg.gap = HOST_SLEEP_CFG_GAP_DEF; | 323 | adapter->hs_cfg.gap = HS_CFG_GAP_DEF; |
324 | adapter->hs_activated = false; | 324 | adapter->hs_activated = false; |
325 | 325 | ||
326 | memset(adapter->event_body, 0, sizeof(adapter->event_body)); | 326 | memset(adapter->event_body, 0, sizeof(adapter->event_body)); |
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index d85e6eb1f58a..91d522c746ed 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h | |||
@@ -354,6 +354,29 @@ struct mwifiex_ds_misc_subsc_evt { | |||
354 | struct subsc_evt_cfg bcn_h_rssi_cfg; | 354 | struct subsc_evt_cfg bcn_h_rssi_cfg; |
355 | }; | 355 | }; |
356 | 356 | ||
357 | #define MAX_BYTESEQ 6 /* non-adjustable */ | ||
358 | #define MWIFIEX_MAX_FILTERS 10 | ||
359 | |||
360 | struct mwifiex_mef_filter { | ||
361 | u16 repeat; | ||
362 | u16 offset; | ||
363 | s8 byte_seq[MAX_BYTESEQ + 1]; | ||
364 | u8 filt_type; | ||
365 | u8 filt_action; | ||
366 | }; | ||
367 | |||
368 | struct mwifiex_mef_entry { | ||
369 | u8 mode; | ||
370 | u8 action; | ||
371 | struct mwifiex_mef_filter filter[MWIFIEX_MAX_FILTERS]; | ||
372 | }; | ||
373 | |||
374 | struct mwifiex_ds_mef_cfg { | ||
375 | u32 criteria; | ||
376 | u16 num_entries; | ||
377 | struct mwifiex_mef_entry *mef_entry; | ||
378 | }; | ||
379 | |||
357 | #define MWIFIEX_MAX_VSIE_LEN (256) | 380 | #define MWIFIEX_MAX_VSIE_LEN (256) |
358 | #define MWIFIEX_MAX_VSIE_NUM (8) | 381 | #define MWIFIEX_MAX_VSIE_NUM (8) |
359 | #define MWIFIEX_VSIE_MASK_CLEAR 0x00 | 382 | #define MWIFIEX_VSIE_MASK_CLEAR 0x00 |
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 246aa62a4817..2fe0ceba4400 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c | |||
@@ -1117,10 +1117,9 @@ mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv, | |||
1117 | adhoc_join->bss_descriptor.bssid, | 1117 | adhoc_join->bss_descriptor.bssid, |
1118 | adhoc_join->bss_descriptor.ssid); | 1118 | adhoc_join->bss_descriptor.ssid); |
1119 | 1119 | ||
1120 | for (i = 0; bss_desc->supported_rates[i] && | 1120 | for (i = 0; i < MWIFIEX_SUPPORTED_RATES && |
1121 | i < MWIFIEX_SUPPORTED_RATES; | 1121 | bss_desc->supported_rates[i]; i++) |
1122 | i++) | 1122 | ; |
1123 | ; | ||
1124 | rates_size = i; | 1123 | rates_size = i; |
1125 | 1124 | ||
1126 | /* Copy Data Rates from the Rates recorded in scan response */ | 1125 | /* Copy Data Rates from the Rates recorded in scan response */ |
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 9c802ede9c3b..121443a0f2a1 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
@@ -588,10 +588,19 @@ mwifiex_tx_timeout(struct net_device *dev) | |||
588 | { | 588 | { |
589 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 589 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
590 | 590 | ||
591 | dev_err(priv->adapter->dev, "%lu : Tx timeout, bss_type-num = %d-%d\n", | ||
592 | jiffies, priv->bss_type, priv->bss_num); | ||
593 | mwifiex_set_trans_start(dev); | ||
594 | priv->num_tx_timeout++; | 591 | priv->num_tx_timeout++; |
592 | priv->tx_timeout_cnt++; | ||
593 | dev_err(priv->adapter->dev, | ||
594 | "%lu : Tx timeout(#%d), bss_type-num = %d-%d\n", | ||
595 | jiffies, priv->tx_timeout_cnt, priv->bss_type, priv->bss_num); | ||
596 | mwifiex_set_trans_start(dev); | ||
597 | |||
598 | if (priv->tx_timeout_cnt > TX_TIMEOUT_THRESHOLD && | ||
599 | priv->adapter->if_ops.card_reset) { | ||
600 | dev_err(priv->adapter->dev, | ||
601 | "tx_timeout_cnt exceeds threshold. Triggering card reset!\n"); | ||
602 | priv->adapter->if_ops.card_reset(priv->adapter); | ||
603 | } | ||
595 | } | 604 | } |
596 | 605 | ||
597 | /* | 606 | /* |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 553adfb0aa81..920657587fff 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -130,6 +130,9 @@ enum { | |||
130 | #define MWIFIEX_USB_TYPE_DATA 0xBEADC0DE | 130 | #define MWIFIEX_USB_TYPE_DATA 0xBEADC0DE |
131 | #define MWIFIEX_USB_TYPE_EVENT 0xBEEFFACE | 131 | #define MWIFIEX_USB_TYPE_EVENT 0xBEEFFACE |
132 | 132 | ||
133 | /* Threshold for tx_timeout_cnt before we trigger a card reset */ | ||
134 | #define TX_TIMEOUT_THRESHOLD 6 | ||
135 | |||
133 | struct mwifiex_dbg { | 136 | struct mwifiex_dbg { |
134 | u32 num_cmd_host_to_card_failure; | 137 | u32 num_cmd_host_to_card_failure; |
135 | u32 num_cmd_sleep_cfm_host_to_card_failure; | 138 | u32 num_cmd_sleep_cfm_host_to_card_failure; |
@@ -394,6 +397,8 @@ struct mwifiex_private { | |||
394 | u8 curr_addr[ETH_ALEN]; | 397 | u8 curr_addr[ETH_ALEN]; |
395 | u8 media_connected; | 398 | u8 media_connected; |
396 | u32 num_tx_timeout; | 399 | u32 num_tx_timeout; |
400 | /* track consecutive timeout */ | ||
401 | u8 tx_timeout_cnt; | ||
397 | struct net_device *netdev; | 402 | struct net_device *netdev; |
398 | struct net_device_stats stats; | 403 | struct net_device_stats stats; |
399 | u16 curr_pkt_filter; | 404 | u16 curr_pkt_filter; |
@@ -1098,11 +1103,15 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev); | |||
1098 | 1103 | ||
1099 | void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config); | 1104 | void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config); |
1100 | 1105 | ||
1106 | int mwifiex_add_wowlan_magic_pkt_filter(struct mwifiex_adapter *adapter); | ||
1107 | |||
1101 | int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, | 1108 | int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, |
1102 | struct cfg80211_beacon_data *data); | 1109 | struct cfg80211_beacon_data *data); |
1103 | int mwifiex_del_mgmt_ies(struct mwifiex_private *priv); | 1110 | int mwifiex_del_mgmt_ies(struct mwifiex_private *priv); |
1104 | u8 *mwifiex_11d_code_2_region(u8 code); | 1111 | u8 *mwifiex_11d_code_2_region(u8 code); |
1105 | 1112 | ||
1113 | extern const struct ethtool_ops mwifiex_ethtool_ops; | ||
1114 | |||
1106 | #ifdef CONFIG_DEBUG_FS | 1115 | #ifdef CONFIG_DEBUG_FS |
1107 | void mwifiex_debugfs_init(void); | 1116 | void mwifiex_debugfs_init(void); |
1108 | void mwifiex_debugfs_remove(void); | 1117 | void mwifiex_debugfs_remove(void); |
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 35c79722c361..6283294398bf 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c | |||
@@ -36,8 +36,6 @@ static u8 user_rmmod; | |||
36 | static struct mwifiex_if_ops pcie_ops; | 36 | static struct mwifiex_if_ops pcie_ops; |
37 | 37 | ||
38 | static struct semaphore add_remove_card_sem; | 38 | static struct semaphore add_remove_card_sem; |
39 | static int mwifiex_pcie_enable_host_int(struct mwifiex_adapter *adapter); | ||
40 | static int mwifiex_pcie_resume(struct pci_dev *pdev); | ||
41 | 39 | ||
42 | static int | 40 | static int |
43 | mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb, | 41 | mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb, |
@@ -78,6 +76,82 @@ static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter) | |||
78 | return false; | 76 | return false; |
79 | } | 77 | } |
80 | 78 | ||
79 | #ifdef CONFIG_PM | ||
80 | /* | ||
81 | * Kernel needs to suspend all functions separately. Therefore all | ||
82 | * registered functions must have drivers with suspend and resume | ||
83 | * methods. Failing that the kernel simply removes the whole card. | ||
84 | * | ||
85 | * If already not suspended, this function allocates and sends a host | ||
86 | * sleep activate request to the firmware and turns off the traffic. | ||
87 | */ | ||
88 | static int mwifiex_pcie_suspend(struct pci_dev *pdev, pm_message_t state) | ||
89 | { | ||
90 | struct mwifiex_adapter *adapter; | ||
91 | struct pcie_service_card *card; | ||
92 | int hs_actived; | ||
93 | |||
94 | if (pdev) { | ||
95 | card = (struct pcie_service_card *) pci_get_drvdata(pdev); | ||
96 | if (!card || !card->adapter) { | ||
97 | pr_err("Card or adapter structure is not valid\n"); | ||
98 | return 0; | ||
99 | } | ||
100 | } else { | ||
101 | pr_err("PCIE device is not specified\n"); | ||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | adapter = card->adapter; | ||
106 | |||
107 | hs_actived = mwifiex_enable_hs(adapter); | ||
108 | |||
109 | /* Indicate device suspended */ | ||
110 | adapter->is_suspended = true; | ||
111 | |||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | /* | ||
116 | * Kernel needs to suspend all functions separately. Therefore all | ||
117 | * registered functions must have drivers with suspend and resume | ||
118 | * methods. Failing that the kernel simply removes the whole card. | ||
119 | * | ||
120 | * If already not resumed, this function turns on the traffic and | ||
121 | * sends a host sleep cancel request to the firmware. | ||
122 | */ | ||
123 | static int mwifiex_pcie_resume(struct pci_dev *pdev) | ||
124 | { | ||
125 | struct mwifiex_adapter *adapter; | ||
126 | struct pcie_service_card *card; | ||
127 | |||
128 | if (pdev) { | ||
129 | card = (struct pcie_service_card *) pci_get_drvdata(pdev); | ||
130 | if (!card || !card->adapter) { | ||
131 | pr_err("Card or adapter structure is not valid\n"); | ||
132 | return 0; | ||
133 | } | ||
134 | } else { | ||
135 | pr_err("PCIE device is not specified\n"); | ||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | adapter = card->adapter; | ||
140 | |||
141 | if (!adapter->is_suspended) { | ||
142 | dev_warn(adapter->dev, "Device already resumed\n"); | ||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | adapter->is_suspended = false; | ||
147 | |||
148 | mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), | ||
149 | MWIFIEX_ASYNC_CMD); | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | #endif | ||
154 | |||
81 | /* | 155 | /* |
82 | * This function probes an mwifiex device and registers it. It allocates | 156 | * This function probes an mwifiex device and registers it. It allocates |
83 | * the card structure, enables PCIE function number and initiates the | 157 | * the card structure, enables PCIE function number and initiates the |
@@ -159,80 +233,6 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev) | |||
159 | kfree(card); | 233 | kfree(card); |
160 | } | 234 | } |
161 | 235 | ||
162 | /* | ||
163 | * Kernel needs to suspend all functions separately. Therefore all | ||
164 | * registered functions must have drivers with suspend and resume | ||
165 | * methods. Failing that the kernel simply removes the whole card. | ||
166 | * | ||
167 | * If already not suspended, this function allocates and sends a host | ||
168 | * sleep activate request to the firmware and turns off the traffic. | ||
169 | */ | ||
170 | static int mwifiex_pcie_suspend(struct pci_dev *pdev, pm_message_t state) | ||
171 | { | ||
172 | struct mwifiex_adapter *adapter; | ||
173 | struct pcie_service_card *card; | ||
174 | int hs_actived; | ||
175 | |||
176 | if (pdev) { | ||
177 | card = (struct pcie_service_card *) pci_get_drvdata(pdev); | ||
178 | if (!card || !card->adapter) { | ||
179 | pr_err("Card or adapter structure is not valid\n"); | ||
180 | return 0; | ||
181 | } | ||
182 | } else { | ||
183 | pr_err("PCIE device is not specified\n"); | ||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | adapter = card->adapter; | ||
188 | |||
189 | hs_actived = mwifiex_enable_hs(adapter); | ||
190 | |||
191 | /* Indicate device suspended */ | ||
192 | adapter->is_suspended = true; | ||
193 | |||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | /* | ||
198 | * Kernel needs to suspend all functions separately. Therefore all | ||
199 | * registered functions must have drivers with suspend and resume | ||
200 | * methods. Failing that the kernel simply removes the whole card. | ||
201 | * | ||
202 | * If already not resumed, this function turns on the traffic and | ||
203 | * sends a host sleep cancel request to the firmware. | ||
204 | */ | ||
205 | static int mwifiex_pcie_resume(struct pci_dev *pdev) | ||
206 | { | ||
207 | struct mwifiex_adapter *adapter; | ||
208 | struct pcie_service_card *card; | ||
209 | |||
210 | if (pdev) { | ||
211 | card = (struct pcie_service_card *) pci_get_drvdata(pdev); | ||
212 | if (!card || !card->adapter) { | ||
213 | pr_err("Card or adapter structure is not valid\n"); | ||
214 | return 0; | ||
215 | } | ||
216 | } else { | ||
217 | pr_err("PCIE device is not specified\n"); | ||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | adapter = card->adapter; | ||
222 | |||
223 | if (!adapter->is_suspended) { | ||
224 | dev_warn(adapter->dev, "Device already resumed\n"); | ||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | adapter->is_suspended = false; | ||
229 | |||
230 | mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), | ||
231 | MWIFIEX_ASYNC_CMD); | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static DEFINE_PCI_DEVICE_TABLE(mwifiex_ids) = { | 236 | static DEFINE_PCI_DEVICE_TABLE(mwifiex_ids) = { |
237 | { | 237 | { |
238 | PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8766P, | 238 | PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8766P, |
@@ -302,7 +302,7 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) | |||
302 | i++; | 302 | i++; |
303 | usleep_range(10, 20); | 303 | usleep_range(10, 20); |
304 | /* 50ms max wait */ | 304 | /* 50ms max wait */ |
305 | if (i == 50000) | 305 | if (i == 5000) |
306 | break; | 306 | break; |
307 | } | 307 | } |
308 | 308 | ||
@@ -1030,8 +1030,8 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb, | |||
1030 | u32 wrindx, num_tx_buffs, rx_val; | 1030 | u32 wrindx, num_tx_buffs, rx_val; |
1031 | int ret; | 1031 | int ret; |
1032 | dma_addr_t buf_pa; | 1032 | dma_addr_t buf_pa; |
1033 | struct mwifiex_pcie_buf_desc *desc; | 1033 | struct mwifiex_pcie_buf_desc *desc = NULL; |
1034 | struct mwifiex_pfu_buf_desc *desc2; | 1034 | struct mwifiex_pfu_buf_desc *desc2 = NULL; |
1035 | __le16 *tmp; | 1035 | __le16 *tmp; |
1036 | 1036 | ||
1037 | if (!(skb->data && skb->len)) { | 1037 | if (!(skb->data && skb->len)) { |
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index c55c5bb93134..a2ae690a0a67 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c | |||
@@ -334,7 +334,7 @@ mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv, | |||
334 | cmd->command = cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH); | 334 | cmd->command = cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH); |
335 | 335 | ||
336 | if (!hs_activate && | 336 | if (!hs_activate && |
337 | (hscfg_param->conditions != cpu_to_le32(HOST_SLEEP_CFG_CANCEL)) && | 337 | (hscfg_param->conditions != cpu_to_le32(HS_CFG_CANCEL)) && |
338 | ((adapter->arp_filter_size > 0) && | 338 | ((adapter->arp_filter_size > 0) && |
339 | (adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) { | 339 | (adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) { |
340 | dev_dbg(adapter->dev, | 340 | dev_dbg(adapter->dev, |
@@ -1059,6 +1059,80 @@ mwifiex_cmd_802_11_subsc_evt(struct mwifiex_private *priv, | |||
1059 | return 0; | 1059 | return 0; |
1060 | } | 1060 | } |
1061 | 1061 | ||
1062 | static int | ||
1063 | mwifiex_cmd_append_rpn_expression(struct mwifiex_private *priv, | ||
1064 | struct mwifiex_mef_entry *mef_entry, | ||
1065 | u8 **buffer) | ||
1066 | { | ||
1067 | struct mwifiex_mef_filter *filter = mef_entry->filter; | ||
1068 | int i, byte_len; | ||
1069 | u8 *stack_ptr = *buffer; | ||
1070 | |||
1071 | for (i = 0; i < MWIFIEX_MAX_FILTERS; i++) { | ||
1072 | filter = &mef_entry->filter[i]; | ||
1073 | if (!filter->filt_type) | ||
1074 | break; | ||
1075 | *(__le32 *)stack_ptr = cpu_to_le32((u32)filter->repeat); | ||
1076 | stack_ptr += 4; | ||
1077 | *stack_ptr = TYPE_DNUM; | ||
1078 | stack_ptr += 1; | ||
1079 | |||
1080 | byte_len = filter->byte_seq[MAX_BYTESEQ]; | ||
1081 | memcpy(stack_ptr, filter->byte_seq, byte_len); | ||
1082 | stack_ptr += byte_len; | ||
1083 | *stack_ptr = byte_len; | ||
1084 | stack_ptr += 1; | ||
1085 | *stack_ptr = TYPE_BYTESEQ; | ||
1086 | stack_ptr += 1; | ||
1087 | |||
1088 | *(__le32 *)stack_ptr = cpu_to_le32((u32)filter->offset); | ||
1089 | stack_ptr += 4; | ||
1090 | *stack_ptr = TYPE_DNUM; | ||
1091 | stack_ptr += 1; | ||
1092 | |||
1093 | *stack_ptr = filter->filt_type; | ||
1094 | stack_ptr += 1; | ||
1095 | |||
1096 | if (filter->filt_action) { | ||
1097 | *stack_ptr = filter->filt_action; | ||
1098 | stack_ptr += 1; | ||
1099 | } | ||
1100 | |||
1101 | if (stack_ptr - *buffer > STACK_NBYTES) | ||
1102 | return -1; | ||
1103 | } | ||
1104 | |||
1105 | *buffer = stack_ptr; | ||
1106 | return 0; | ||
1107 | } | ||
1108 | |||
1109 | static int | ||
1110 | mwifiex_cmd_mef_cfg(struct mwifiex_private *priv, | ||
1111 | struct host_cmd_ds_command *cmd, | ||
1112 | struct mwifiex_ds_mef_cfg *mef) | ||
1113 | { | ||
1114 | struct host_cmd_ds_mef_cfg *mef_cfg = &cmd->params.mef_cfg; | ||
1115 | u8 *pos = (u8 *)mef_cfg; | ||
1116 | |||
1117 | cmd->command = cpu_to_le16(HostCmd_CMD_MEF_CFG); | ||
1118 | |||
1119 | mef_cfg->criteria = cpu_to_le32(mef->criteria); | ||
1120 | mef_cfg->num_entries = cpu_to_le16(mef->num_entries); | ||
1121 | pos += sizeof(*mef_cfg); | ||
1122 | mef_cfg->mef_entry->mode = mef->mef_entry->mode; | ||
1123 | mef_cfg->mef_entry->action = mef->mef_entry->action; | ||
1124 | pos += sizeof(*(mef_cfg->mef_entry)); | ||
1125 | |||
1126 | if (mwifiex_cmd_append_rpn_expression(priv, mef->mef_entry, &pos)) | ||
1127 | return -1; | ||
1128 | |||
1129 | mef_cfg->mef_entry->exprsize = | ||
1130 | cpu_to_le16(pos - mef_cfg->mef_entry->expr); | ||
1131 | cmd->size = cpu_to_le16((u16) (pos - (u8 *)mef_cfg) + S_DS_GEN); | ||
1132 | |||
1133 | return 0; | ||
1134 | } | ||
1135 | |||
1062 | /* | 1136 | /* |
1063 | * This function prepares the commands before sending them to the firmware. | 1137 | * This function prepares the commands before sending them to the firmware. |
1064 | * | 1138 | * |
@@ -1273,6 +1347,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, | |||
1273 | case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: | 1347 | case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: |
1274 | ret = mwifiex_cmd_802_11_subsc_evt(priv, cmd_ptr, data_buf); | 1348 | ret = mwifiex_cmd_802_11_subsc_evt(priv, cmd_ptr, data_buf); |
1275 | break; | 1349 | break; |
1350 | case HostCmd_CMD_MEF_CFG: | ||
1351 | ret = mwifiex_cmd_mef_cfg(priv, cmd_ptr, data_buf); | ||
1352 | break; | ||
1276 | default: | 1353 | default: |
1277 | dev_err(priv->adapter->dev, | 1354 | dev_err(priv->adapter->dev, |
1278 | "PREP_CMD: unknown cmd- %#x\n", cmd_no); | 1355 | "PREP_CMD: unknown cmd- %#x\n", cmd_no); |
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 4669f8d9389f..80b9f2238001 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c | |||
@@ -976,6 +976,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, | |||
976 | case HostCmd_CMD_UAP_BSS_STOP: | 976 | case HostCmd_CMD_UAP_BSS_STOP: |
977 | priv->bss_started = 0; | 977 | priv->bss_started = 0; |
978 | break; | 978 | break; |
979 | case HostCmd_CMD_MEF_CFG: | ||
980 | break; | ||
979 | default: | 981 | default: |
980 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", | 982 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", |
981 | resp->command); | 983 | resp->command); |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 9f33c92c90f5..76d31deb7b1b 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -388,7 +388,7 @@ static int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action, | |||
388 | break; | 388 | break; |
389 | } | 389 | } |
390 | if (hs_cfg->is_invoke_hostcmd) { | 390 | if (hs_cfg->is_invoke_hostcmd) { |
391 | if (hs_cfg->conditions == HOST_SLEEP_CFG_CANCEL) { | 391 | if (hs_cfg->conditions == HS_CFG_CANCEL) { |
392 | if (!adapter->is_hs_configured) | 392 | if (!adapter->is_hs_configured) |
393 | /* Already cancelled */ | 393 | /* Already cancelled */ |
394 | break; | 394 | break; |
@@ -403,8 +403,8 @@ static int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action, | |||
403 | adapter->hs_cfg.gpio = (u8)hs_cfg->gpio; | 403 | adapter->hs_cfg.gpio = (u8)hs_cfg->gpio; |
404 | if (hs_cfg->gap) | 404 | if (hs_cfg->gap) |
405 | adapter->hs_cfg.gap = (u8)hs_cfg->gap; | 405 | adapter->hs_cfg.gap = (u8)hs_cfg->gap; |
406 | } else if (adapter->hs_cfg.conditions | 406 | } else if (adapter->hs_cfg.conditions == |
407 | == cpu_to_le32(HOST_SLEEP_CFG_CANCEL)) { | 407 | cpu_to_le32(HS_CFG_CANCEL)) { |
408 | /* Return failure if no parameters for HS | 408 | /* Return failure if no parameters for HS |
409 | enable */ | 409 | enable */ |
410 | status = -1; | 410 | status = -1; |
@@ -420,7 +420,7 @@ static int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action, | |||
420 | HostCmd_CMD_802_11_HS_CFG_ENH, | 420 | HostCmd_CMD_802_11_HS_CFG_ENH, |
421 | HostCmd_ACT_GEN_SET, 0, | 421 | HostCmd_ACT_GEN_SET, 0, |
422 | &adapter->hs_cfg); | 422 | &adapter->hs_cfg); |
423 | if (hs_cfg->conditions == HOST_SLEEP_CFG_CANCEL) | 423 | if (hs_cfg->conditions == HS_CFG_CANCEL) |
424 | /* Restore previous condition */ | 424 | /* Restore previous condition */ |
425 | adapter->hs_cfg.conditions = | 425 | adapter->hs_cfg.conditions = |
426 | cpu_to_le32(prev_cond); | 426 | cpu_to_le32(prev_cond); |
@@ -454,7 +454,7 @@ int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type) | |||
454 | { | 454 | { |
455 | struct mwifiex_ds_hs_cfg hscfg; | 455 | struct mwifiex_ds_hs_cfg hscfg; |
456 | 456 | ||
457 | hscfg.conditions = HOST_SLEEP_CFG_CANCEL; | 457 | hscfg.conditions = HS_CFG_CANCEL; |
458 | hscfg.is_invoke_hostcmd = true; | 458 | hscfg.is_invoke_hostcmd = true; |
459 | 459 | ||
460 | return mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET, | 460 | return mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET, |
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index 296faec14365..8f923d0d2ba6 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c | |||
@@ -169,6 +169,8 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, | |||
169 | if (!status) { | 169 | if (!status) { |
170 | priv->stats.tx_packets++; | 170 | priv->stats.tx_packets++; |
171 | priv->stats.tx_bytes += skb->len; | 171 | priv->stats.tx_bytes += skb->len; |
172 | if (priv->tx_timeout_cnt) | ||
173 | priv->tx_timeout_cnt = 0; | ||
172 | } else { | 174 | } else { |
173 | priv->stats.tx_errors++; | 175 | priv->stats.tx_errors++; |
174 | } | 176 | } |
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c index 21553976b550..54667e65ca47 100644 --- a/drivers/net/wireless/mwifiex/util.c +++ b/drivers/net/wireless/mwifiex/util.c | |||
@@ -195,7 +195,7 @@ int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb) | |||
195 | skb->protocol = eth_type_trans(skb, priv->netdev); | 195 | skb->protocol = eth_type_trans(skb, priv->netdev); |
196 | skb->ip_summed = CHECKSUM_NONE; | 196 | skb->ip_summed = CHECKSUM_NONE; |
197 | 197 | ||
198 | /* This is required only in case of 11n and USB as we alloc | 198 | /* This is required only in case of 11n and USB/PCIE as we alloc |
199 | * a buffer of 4K only if its 11N (to be able to receive 4K | 199 | * a buffer of 4K only if its 11N (to be able to receive 4K |
200 | * AMSDU packets). In case of SD we allocate buffers based | 200 | * AMSDU packets). In case of SD we allocate buffers based |
201 | * on the size of packet and hence this is not needed. | 201 | * on the size of packet and hence this is not needed. |
@@ -212,7 +212,8 @@ int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb) | |||
212 | * fragments. Currently we fail the Filesndl-ht.scr script | 212 | * fragments. Currently we fail the Filesndl-ht.scr script |
213 | * for UDP, hence this fix | 213 | * for UDP, hence this fix |
214 | */ | 214 | */ |
215 | if ((priv->adapter->iface_type == MWIFIEX_USB) && | 215 | if ((priv->adapter->iface_type == MWIFIEX_USB || |
216 | priv->adapter->iface_type == MWIFIEX_PCIE) && | ||
216 | (skb->truesize > MWIFIEX_RX_DATA_BUF_SIZE)) | 217 | (skb->truesize > MWIFIEX_RX_DATA_BUF_SIZE)) |
217 | skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE); | 218 | skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE); |
218 | 219 | ||
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 091d9a64080a..0640e7d7f0c2 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -232,6 +232,7 @@ struct mwl8k_priv { | |||
232 | u16 num_mcaddrs; | 232 | u16 num_mcaddrs; |
233 | u8 hw_rev; | 233 | u8 hw_rev; |
234 | u32 fw_rev; | 234 | u32 fw_rev; |
235 | u32 caps; | ||
235 | 236 | ||
236 | /* | 237 | /* |
237 | * Running count of TX packets in flight, to avoid | 238 | * Running count of TX packets in flight, to avoid |
@@ -284,6 +285,7 @@ struct mwl8k_priv { | |||
284 | unsigned fw_state; | 285 | unsigned fw_state; |
285 | char *fw_pref; | 286 | char *fw_pref; |
286 | char *fw_alt; | 287 | char *fw_alt; |
288 | bool is_8764; | ||
287 | struct completion firmware_loading_complete; | 289 | struct completion firmware_loading_complete; |
288 | 290 | ||
289 | /* bitmap of running BSSes */ | 291 | /* bitmap of running BSSes */ |
@@ -600,13 +602,18 @@ mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length) | |||
600 | loops = 1000; | 602 | loops = 1000; |
601 | do { | 603 | do { |
602 | u32 int_code; | 604 | u32 int_code; |
603 | 605 | if (priv->is_8764) { | |
604 | int_code = ioread32(regs + MWL8K_HIU_INT_CODE); | 606 | int_code = ioread32(regs + |
605 | if (int_code == MWL8K_INT_CODE_CMD_FINISHED) { | 607 | MWL8K_HIU_H2A_INTERRUPT_STATUS); |
606 | iowrite32(0, regs + MWL8K_HIU_INT_CODE); | 608 | if (int_code == 0) |
607 | break; | 609 | break; |
610 | } else { | ||
611 | int_code = ioread32(regs + MWL8K_HIU_INT_CODE); | ||
612 | if (int_code == MWL8K_INT_CODE_CMD_FINISHED) { | ||
613 | iowrite32(0, regs + MWL8K_HIU_INT_CODE); | ||
614 | break; | ||
615 | } | ||
608 | } | 616 | } |
609 | |||
610 | cond_resched(); | 617 | cond_resched(); |
611 | udelay(1); | 618 | udelay(1); |
612 | } while (--loops); | 619 | } while (--loops); |
@@ -724,7 +731,7 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw) | |||
724 | int rc; | 731 | int rc; |
725 | int loops; | 732 | int loops; |
726 | 733 | ||
727 | if (!memcmp(fw->data, "\x01\x00\x00\x00", 4)) { | 734 | if (!memcmp(fw->data, "\x01\x00\x00\x00", 4) && !priv->is_8764) { |
728 | const struct firmware *helper = priv->fw_helper; | 735 | const struct firmware *helper = priv->fw_helper; |
729 | 736 | ||
730 | if (helper == NULL) { | 737 | if (helper == NULL) { |
@@ -743,7 +750,10 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw) | |||
743 | 750 | ||
744 | rc = mwl8k_feed_fw_image(priv, fw->data, fw->size); | 751 | rc = mwl8k_feed_fw_image(priv, fw->data, fw->size); |
745 | } else { | 752 | } else { |
746 | rc = mwl8k_load_fw_image(priv, fw->data, fw->size); | 753 | if (priv->is_8764) |
754 | rc = mwl8k_feed_fw_image(priv, fw->data, fw->size); | ||
755 | else | ||
756 | rc = mwl8k_load_fw_image(priv, fw->data, fw->size); | ||
747 | } | 757 | } |
748 | 758 | ||
749 | if (rc) { | 759 | if (rc) { |
@@ -908,9 +918,9 @@ static void mwl8k_encapsulate_tx_frame(struct mwl8k_priv *priv, | |||
908 | } | 918 | } |
909 | 919 | ||
910 | /* | 920 | /* |
911 | * Packet reception for 88w8366 AP firmware. | 921 | * Packet reception for 88w8366/88w8764 AP firmware. |
912 | */ | 922 | */ |
913 | struct mwl8k_rxd_8366_ap { | 923 | struct mwl8k_rxd_ap { |
914 | __le16 pkt_len; | 924 | __le16 pkt_len; |
915 | __u8 sq2; | 925 | __u8 sq2; |
916 | __u8 rate; | 926 | __u8 rate; |
@@ -928,30 +938,30 @@ struct mwl8k_rxd_8366_ap { | |||
928 | __u8 rx_ctrl; | 938 | __u8 rx_ctrl; |
929 | } __packed; | 939 | } __packed; |
930 | 940 | ||
931 | #define MWL8K_8366_AP_RATE_INFO_MCS_FORMAT 0x80 | 941 | #define MWL8K_AP_RATE_INFO_MCS_FORMAT 0x80 |
932 | #define MWL8K_8366_AP_RATE_INFO_40MHZ 0x40 | 942 | #define MWL8K_AP_RATE_INFO_40MHZ 0x40 |
933 | #define MWL8K_8366_AP_RATE_INFO_RATEID(x) ((x) & 0x3f) | 943 | #define MWL8K_AP_RATE_INFO_RATEID(x) ((x) & 0x3f) |
934 | 944 | ||
935 | #define MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST 0x80 | 945 | #define MWL8K_AP_RX_CTRL_OWNED_BY_HOST 0x80 |
936 | 946 | ||
937 | /* 8366 AP rx_status bits */ | 947 | /* 8366/8764 AP rx_status bits */ |
938 | #define MWL8K_8366_AP_RXSTAT_DECRYPT_ERR_MASK 0x80 | 948 | #define MWL8K_AP_RXSTAT_DECRYPT_ERR_MASK 0x80 |
939 | #define MWL8K_8366_AP_RXSTAT_GENERAL_DECRYPT_ERR 0xFF | 949 | #define MWL8K_AP_RXSTAT_GENERAL_DECRYPT_ERR 0xFF |
940 | #define MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR 0x02 | 950 | #define MWL8K_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR 0x02 |
941 | #define MWL8K_8366_AP_RXSTAT_WEP_DECRYPT_ICV_ERR 0x04 | 951 | #define MWL8K_AP_RXSTAT_WEP_DECRYPT_ICV_ERR 0x04 |
942 | #define MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_ICV_ERR 0x08 | 952 | #define MWL8K_AP_RXSTAT_TKIP_DECRYPT_ICV_ERR 0x08 |
943 | 953 | ||
944 | static void mwl8k_rxd_8366_ap_init(void *_rxd, dma_addr_t next_dma_addr) | 954 | static void mwl8k_rxd_ap_init(void *_rxd, dma_addr_t next_dma_addr) |
945 | { | 955 | { |
946 | struct mwl8k_rxd_8366_ap *rxd = _rxd; | 956 | struct mwl8k_rxd_ap *rxd = _rxd; |
947 | 957 | ||
948 | rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr); | 958 | rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr); |
949 | rxd->rx_ctrl = MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST; | 959 | rxd->rx_ctrl = MWL8K_AP_RX_CTRL_OWNED_BY_HOST; |
950 | } | 960 | } |
951 | 961 | ||
952 | static void mwl8k_rxd_8366_ap_refill(void *_rxd, dma_addr_t addr, int len) | 962 | static void mwl8k_rxd_ap_refill(void *_rxd, dma_addr_t addr, int len) |
953 | { | 963 | { |
954 | struct mwl8k_rxd_8366_ap *rxd = _rxd; | 964 | struct mwl8k_rxd_ap *rxd = _rxd; |
955 | 965 | ||
956 | rxd->pkt_len = cpu_to_le16(len); | 966 | rxd->pkt_len = cpu_to_le16(len); |
957 | rxd->pkt_phys_addr = cpu_to_le32(addr); | 967 | rxd->pkt_phys_addr = cpu_to_le32(addr); |
@@ -960,12 +970,12 @@ static void mwl8k_rxd_8366_ap_refill(void *_rxd, dma_addr_t addr, int len) | |||
960 | } | 970 | } |
961 | 971 | ||
962 | static int | 972 | static int |
963 | mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status, | 973 | mwl8k_rxd_ap_process(void *_rxd, struct ieee80211_rx_status *status, |
964 | __le16 *qos, s8 *noise) | 974 | __le16 *qos, s8 *noise) |
965 | { | 975 | { |
966 | struct mwl8k_rxd_8366_ap *rxd = _rxd; | 976 | struct mwl8k_rxd_ap *rxd = _rxd; |
967 | 977 | ||
968 | if (!(rxd->rx_ctrl & MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST)) | 978 | if (!(rxd->rx_ctrl & MWL8K_AP_RX_CTRL_OWNED_BY_HOST)) |
969 | return -1; | 979 | return -1; |
970 | rmb(); | 980 | rmb(); |
971 | 981 | ||
@@ -974,11 +984,11 @@ mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status, | |||
974 | status->signal = -rxd->rssi; | 984 | status->signal = -rxd->rssi; |
975 | *noise = -rxd->noise_floor; | 985 | *noise = -rxd->noise_floor; |
976 | 986 | ||
977 | if (rxd->rate & MWL8K_8366_AP_RATE_INFO_MCS_FORMAT) { | 987 | if (rxd->rate & MWL8K_AP_RATE_INFO_MCS_FORMAT) { |
978 | status->flag |= RX_FLAG_HT; | 988 | status->flag |= RX_FLAG_HT; |
979 | if (rxd->rate & MWL8K_8366_AP_RATE_INFO_40MHZ) | 989 | if (rxd->rate & MWL8K_AP_RATE_INFO_40MHZ) |
980 | status->flag |= RX_FLAG_40MHZ; | 990 | status->flag |= RX_FLAG_40MHZ; |
981 | status->rate_idx = MWL8K_8366_AP_RATE_INFO_RATEID(rxd->rate); | 991 | status->rate_idx = MWL8K_AP_RATE_INFO_RATEID(rxd->rate); |
982 | } else { | 992 | } else { |
983 | int i; | 993 | int i; |
984 | 994 | ||
@@ -1002,19 +1012,19 @@ mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status, | |||
1002 | 1012 | ||
1003 | *qos = rxd->qos_control; | 1013 | *qos = rxd->qos_control; |
1004 | 1014 | ||
1005 | if ((rxd->rx_status != MWL8K_8366_AP_RXSTAT_GENERAL_DECRYPT_ERR) && | 1015 | if ((rxd->rx_status != MWL8K_AP_RXSTAT_GENERAL_DECRYPT_ERR) && |
1006 | (rxd->rx_status & MWL8K_8366_AP_RXSTAT_DECRYPT_ERR_MASK) && | 1016 | (rxd->rx_status & MWL8K_AP_RXSTAT_DECRYPT_ERR_MASK) && |
1007 | (rxd->rx_status & MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR)) | 1017 | (rxd->rx_status & MWL8K_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR)) |
1008 | status->flag |= RX_FLAG_MMIC_ERROR; | 1018 | status->flag |= RX_FLAG_MMIC_ERROR; |
1009 | 1019 | ||
1010 | return le16_to_cpu(rxd->pkt_len); | 1020 | return le16_to_cpu(rxd->pkt_len); |
1011 | } | 1021 | } |
1012 | 1022 | ||
1013 | static struct rxd_ops rxd_8366_ap_ops = { | 1023 | static struct rxd_ops rxd_ap_ops = { |
1014 | .rxd_size = sizeof(struct mwl8k_rxd_8366_ap), | 1024 | .rxd_size = sizeof(struct mwl8k_rxd_ap), |
1015 | .rxd_init = mwl8k_rxd_8366_ap_init, | 1025 | .rxd_init = mwl8k_rxd_ap_init, |
1016 | .rxd_refill = mwl8k_rxd_8366_ap_refill, | 1026 | .rxd_refill = mwl8k_rxd_ap_refill, |
1017 | .rxd_process = mwl8k_rxd_8366_ap_process, | 1027 | .rxd_process = mwl8k_rxd_ap_process, |
1018 | }; | 1028 | }; |
1019 | 1029 | ||
1020 | /* | 1030 | /* |
@@ -2401,6 +2411,9 @@ mwl8k_set_caps(struct ieee80211_hw *hw, u32 caps) | |||
2401 | { | 2411 | { |
2402 | struct mwl8k_priv *priv = hw->priv; | 2412 | struct mwl8k_priv *priv = hw->priv; |
2403 | 2413 | ||
2414 | if (priv->caps) | ||
2415 | return; | ||
2416 | |||
2404 | if ((caps & MWL8K_CAP_2GHZ4) || !(caps & MWL8K_CAP_BAND_MASK)) { | 2417 | if ((caps & MWL8K_CAP_2GHZ4) || !(caps & MWL8K_CAP_BAND_MASK)) { |
2405 | mwl8k_setup_2ghz_band(hw); | 2418 | mwl8k_setup_2ghz_band(hw); |
2406 | if (caps & MWL8K_CAP_MIMO) | 2419 | if (caps & MWL8K_CAP_MIMO) |
@@ -2412,6 +2425,8 @@ mwl8k_set_caps(struct ieee80211_hw *hw, u32 caps) | |||
2412 | if (caps & MWL8K_CAP_MIMO) | 2425 | if (caps & MWL8K_CAP_MIMO) |
2413 | mwl8k_set_ht_caps(hw, &priv->band_50, caps); | 2426 | mwl8k_set_ht_caps(hw, &priv->band_50, caps); |
2414 | } | 2427 | } |
2428 | |||
2429 | priv->caps = caps; | ||
2415 | } | 2430 | } |
2416 | 2431 | ||
2417 | static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) | 2432 | static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) |
@@ -5429,12 +5444,17 @@ enum { | |||
5429 | MWL8363 = 0, | 5444 | MWL8363 = 0, |
5430 | MWL8687, | 5445 | MWL8687, |
5431 | MWL8366, | 5446 | MWL8366, |
5447 | MWL8764, | ||
5432 | }; | 5448 | }; |
5433 | 5449 | ||
5434 | #define MWL8K_8366_AP_FW_API 3 | 5450 | #define MWL8K_8366_AP_FW_API 3 |
5435 | #define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw" | 5451 | #define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw" |
5436 | #define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api) | 5452 | #define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api) |
5437 | 5453 | ||
5454 | #define MWL8K_8764_AP_FW_API 1 | ||
5455 | #define _MWL8K_8764_AP_FW(api) "mwl8k/fmimage_8764_ap-" #api ".fw" | ||
5456 | #define MWL8K_8764_AP_FW(api) _MWL8K_8764_AP_FW(api) | ||
5457 | |||
5438 | static struct mwl8k_device_info mwl8k_info_tbl[] = { | 5458 | static struct mwl8k_device_info mwl8k_info_tbl[] = { |
5439 | [MWL8363] = { | 5459 | [MWL8363] = { |
5440 | .part_name = "88w8363", | 5460 | .part_name = "88w8363", |
@@ -5452,7 +5472,13 @@ static struct mwl8k_device_info mwl8k_info_tbl[] = { | |||
5452 | .fw_image_sta = "mwl8k/fmimage_8366.fw", | 5472 | .fw_image_sta = "mwl8k/fmimage_8366.fw", |
5453 | .fw_image_ap = MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API), | 5473 | .fw_image_ap = MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API), |
5454 | .fw_api_ap = MWL8K_8366_AP_FW_API, | 5474 | .fw_api_ap = MWL8K_8366_AP_FW_API, |
5455 | .ap_rxd_ops = &rxd_8366_ap_ops, | 5475 | .ap_rxd_ops = &rxd_ap_ops, |
5476 | }, | ||
5477 | [MWL8764] = { | ||
5478 | .part_name = "88w8764", | ||
5479 | .fw_image_ap = MWL8K_8764_AP_FW(MWL8K_8764_AP_FW_API), | ||
5480 | .fw_api_ap = MWL8K_8764_AP_FW_API, | ||
5481 | .ap_rxd_ops = &rxd_ap_ops, | ||
5456 | }, | 5482 | }, |
5457 | }; | 5483 | }; |
5458 | 5484 | ||
@@ -5474,6 +5500,7 @@ static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = { | |||
5474 | { PCI_VDEVICE(MARVELL, 0x2a41), .driver_data = MWL8366, }, | 5500 | { PCI_VDEVICE(MARVELL, 0x2a41), .driver_data = MWL8366, }, |
5475 | { PCI_VDEVICE(MARVELL, 0x2a42), .driver_data = MWL8366, }, | 5501 | { PCI_VDEVICE(MARVELL, 0x2a42), .driver_data = MWL8366, }, |
5476 | { PCI_VDEVICE(MARVELL, 0x2a43), .driver_data = MWL8366, }, | 5502 | { PCI_VDEVICE(MARVELL, 0x2a43), .driver_data = MWL8366, }, |
5503 | { PCI_VDEVICE(MARVELL, 0x2b36), .driver_data = MWL8764, }, | ||
5477 | { }, | 5504 | { }, |
5478 | }; | 5505 | }; |
5479 | MODULE_DEVICE_TABLE(pci, mwl8k_pci_id_table); | 5506 | MODULE_DEVICE_TABLE(pci, mwl8k_pci_id_table); |
@@ -5995,6 +6022,8 @@ static int mwl8k_probe(struct pci_dev *pdev, | |||
5995 | priv->pdev = pdev; | 6022 | priv->pdev = pdev; |
5996 | priv->device_info = &mwl8k_info_tbl[id->driver_data]; | 6023 | priv->device_info = &mwl8k_info_tbl[id->driver_data]; |
5997 | 6024 | ||
6025 | if (id->driver_data == MWL8764) | ||
6026 | priv->is_8764 = true; | ||
5998 | 6027 | ||
5999 | priv->sram = pci_iomap(pdev, 0, 0x10000); | 6028 | priv->sram = pci_iomap(pdev, 0, 0x10000); |
6000 | if (priv->sram == NULL) { | 6029 | if (priv->sram == NULL) { |
diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c index 7744f42de1ea..1f9cb55c3360 100644 --- a/drivers/net/wireless/orinoco/orinoco_usb.c +++ b/drivers/net/wireless/orinoco/orinoco_usb.c | |||
@@ -1584,7 +1584,7 @@ static int ezusb_probe(struct usb_interface *interface, | |||
1584 | struct ezusb_priv *upriv = NULL; | 1584 | struct ezusb_priv *upriv = NULL; |
1585 | struct usb_interface_descriptor *iface_desc; | 1585 | struct usb_interface_descriptor *iface_desc; |
1586 | struct usb_endpoint_descriptor *ep; | 1586 | struct usb_endpoint_descriptor *ep; |
1587 | const struct firmware *fw_entry; | 1587 | const struct firmware *fw_entry = NULL; |
1588 | int retval = 0; | 1588 | int retval = 0; |
1589 | int i; | 1589 | int i; |
1590 | 1590 | ||
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 3109c0db66e1..4775b5d172d5 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c | |||
@@ -144,7 +144,7 @@ static int psm; | |||
144 | static char *essid; | 144 | static char *essid; |
145 | 145 | ||
146 | /* Default to encapsulation unless translation requested */ | 146 | /* Default to encapsulation unless translation requested */ |
147 | static int translate = 1; | 147 | static bool translate = 1; |
148 | 148 | ||
149 | static int country = USA; | 149 | static int country = USA; |
150 | 150 | ||
@@ -178,7 +178,7 @@ module_param(hop_dwell, int, 0); | |||
178 | module_param(beacon_period, int, 0); | 178 | module_param(beacon_period, int, 0); |
179 | module_param(psm, int, 0); | 179 | module_param(psm, int, 0); |
180 | module_param(essid, charp, 0); | 180 | module_param(essid, charp, 0); |
181 | module_param(translate, int, 0); | 181 | module_param(translate, bool, 0); |
182 | module_param(country, int, 0); | 182 | module_param(country, int, 0); |
183 | module_param(sniffer, int, 0); | 183 | module_param(sniffer, int, 0); |
184 | module_param(bc, int, 0); | 184 | module_param(bc, int, 0); |
@@ -1353,7 +1353,7 @@ static int ray_get_range(struct net_device *dev, struct iw_request_info *info, | |||
1353 | static int ray_set_framing(struct net_device *dev, struct iw_request_info *info, | 1353 | static int ray_set_framing(struct net_device *dev, struct iw_request_info *info, |
1354 | union iwreq_data *wrqu, char *extra) | 1354 | union iwreq_data *wrqu, char *extra) |
1355 | { | 1355 | { |
1356 | translate = *(extra); /* Set framing mode */ | 1356 | translate = !!*(extra); /* Set framing mode */ |
1357 | 1357 | ||
1358 | return 0; | 1358 | return 0; |
1359 | } | 1359 | } |
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 525fd7521dff..8169a85c4498 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Driver for RNDIS based wireless USB devices. | 2 | * Driver for RNDIS based wireless USB devices. |
3 | * | 3 | * |
4 | * Copyright (C) 2007 by Bjorge Dijkstra <bjd@jooz.net> | 4 | * Copyright (C) 2007 by Bjorge Dijkstra <bjd@jooz.net> |
5 | * Copyright (C) 2008-2009 by Jussi Kivilinna <jussi.kivilinna@mbnet.fi> | 5 | * Copyright (C) 2008-2009 by Jussi Kivilinna <jussi.kivilinna@iki.fi> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 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 | 8 | * it under the terms of the GNU General Public License as published by |
@@ -2839,8 +2839,7 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) | |||
2839 | } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) | 2839 | } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) |
2840 | cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL); | 2840 | cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL); |
2841 | 2841 | ||
2842 | if (info != NULL) | 2842 | kfree(info); |
2843 | kfree(info); | ||
2844 | 2843 | ||
2845 | priv->connected = true; | 2844 | priv->connected = true; |
2846 | memcpy(priv->bssid, bssid, ETH_ALEN); | 2845 | memcpy(priv->bssid, bssid, ETH_ALEN); |
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 44d6ead43341..ffe61d53e3fe 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig | |||
@@ -55,10 +55,10 @@ config RT61PCI | |||
55 | 55 | ||
56 | config RT2800PCI | 56 | config RT2800PCI |
57 | tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support" | 57 | tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support" |
58 | depends on PCI || RALINK_RT288X || RALINK_RT305X | 58 | depends on PCI || SOC_RT288X || SOC_RT305X |
59 | select RT2800_LIB | 59 | select RT2800_LIB |
60 | select RT2X00_LIB_PCI if PCI | 60 | select RT2X00_LIB_PCI if PCI |
61 | select RT2X00_LIB_SOC if RALINK_RT288X || RALINK_RT305X | 61 | select RT2X00_LIB_SOC if SOC_RT288X || SOC_RT305X |
62 | select RT2X00_LIB_FIRMWARE | 62 | select RT2X00_LIB_FIRMWARE |
63 | select RT2X00_LIB_CRYPTO | 63 | select RT2X00_LIB_CRYPTO |
64 | select CRC_CCITT | 64 | select CRC_CCITT |
@@ -169,6 +169,13 @@ config RT2800USB_RT53XX | |||
169 | rt2800usb driver. | 169 | rt2800usb driver. |
170 | Supported chips: RT5370 | 170 | Supported chips: RT5370 |
171 | 171 | ||
172 | config RT2800USB_RT55XX | ||
173 | bool "rt2800usb - Include support for rt55xx devices (EXPERIMENTAL)" | ||
174 | ---help--- | ||
175 | This adds support for rt55xx wireless chipset family to the | ||
176 | rt2800usb driver. | ||
177 | Supported chips: RT5572 | ||
178 | |||
172 | config RT2800USB_UNKNOWN | 179 | config RT2800USB_UNKNOWN |
173 | bool "rt2800usb - Include support for unknown (USB) devices" | 180 | bool "rt2800usb - Include support for unknown (USB) devices" |
174 | default n | 181 | default n |
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 4db1088a847f..a7630d5ec892 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h | |||
@@ -51,6 +51,7 @@ | |||
51 | * RF3320 2.4G 1T1R(RT3350/RT3370/RT3390) | 51 | * RF3320 2.4G 1T1R(RT3350/RT3370/RT3390) |
52 | * RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392) | 52 | * RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392) |
53 | * RF3053 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662) | 53 | * RF3053 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662) |
54 | * RF5592 2.4G/5G 2T2R | ||
54 | * RF5360 2.4G 1T1R | 55 | * RF5360 2.4G 1T1R |
55 | * RF5370 2.4G 1T1R | 56 | * RF5370 2.4G 1T1R |
56 | * RF5390 2.4G 1T1R | 57 | * RF5390 2.4G 1T1R |
@@ -68,6 +69,7 @@ | |||
68 | #define RF3320 0x000b | 69 | #define RF3320 0x000b |
69 | #define RF3322 0x000c | 70 | #define RF3322 0x000c |
70 | #define RF3053 0x000d | 71 | #define RF3053 0x000d |
72 | #define RF5592 0x000f | ||
71 | #define RF3290 0x3290 | 73 | #define RF3290 0x3290 |
72 | #define RF5360 0x5360 | 74 | #define RF5360 0x5360 |
73 | #define RF5370 0x5370 | 75 | #define RF5370 0x5370 |
@@ -88,11 +90,8 @@ | |||
88 | #define REV_RT3390E 0x0211 | 90 | #define REV_RT3390E 0x0211 |
89 | #define REV_RT5390F 0x0502 | 91 | #define REV_RT5390F 0x0502 |
90 | #define REV_RT5390R 0x1502 | 92 | #define REV_RT5390R 0x1502 |
93 | #define REV_RT5592C 0x0221 | ||
91 | 94 | ||
92 | /* | ||
93 | * Signal information. | ||
94 | * Default offset is required for RSSI <-> dBm conversion. | ||
95 | */ | ||
96 | #define DEFAULT_RSSI_OFFSET 120 | 95 | #define DEFAULT_RSSI_OFFSET 120 |
97 | 96 | ||
98 | /* | 97 | /* |
@@ -690,6 +689,12 @@ | |||
690 | #define GPIO_SWITCH_7 FIELD32(0x00000080) | 689 | #define GPIO_SWITCH_7 FIELD32(0x00000080) |
691 | 690 | ||
692 | /* | 691 | /* |
692 | * FIXME: where the DEBUG_INDEX name come from? | ||
693 | */ | ||
694 | #define MAC_DEBUG_INDEX 0x05e8 | ||
695 | #define MAC_DEBUG_INDEX_XTAL FIELD32(0x80000000) | ||
696 | |||
697 | /* | ||
693 | * MAC Control/Status Registers(CSR). | 698 | * MAC Control/Status Registers(CSR). |
694 | * Some values are set in TU, whereas 1 TU == 1024 us. | 699 | * Some values are set in TU, whereas 1 TU == 1024 us. |
695 | */ | 700 | */ |
@@ -1934,6 +1939,9 @@ struct mac_iveiv_entry { | |||
1934 | #define BBP4_BANDWIDTH FIELD8(0x18) | 1939 | #define BBP4_BANDWIDTH FIELD8(0x18) |
1935 | #define BBP4_MAC_IF_CTRL FIELD8(0x40) | 1940 | #define BBP4_MAC_IF_CTRL FIELD8(0x40) |
1936 | 1941 | ||
1942 | /* BBP27 */ | ||
1943 | #define BBP27_RX_CHAIN_SEL FIELD8(0x60) | ||
1944 | |||
1937 | /* | 1945 | /* |
1938 | * BBP 47: Bandwidth | 1946 | * BBP 47: Bandwidth |
1939 | */ | 1947 | */ |
@@ -1948,6 +1956,20 @@ struct mac_iveiv_entry { | |||
1948 | #define BBP49_UPDATE_FLAG FIELD8(0x01) | 1956 | #define BBP49_UPDATE_FLAG FIELD8(0x01) |
1949 | 1957 | ||
1950 | /* | 1958 | /* |
1959 | * BBP 105: | ||
1960 | * - bit0: detect SIG on primary channel only (on 40MHz bandwidth) | ||
1961 | * - bit1: FEQ (Feed Forward Compensation) for independend streams | ||
1962 | * - bit2: MLD (Maximum Likehood Detection) for 2 streams (reserved on single | ||
1963 | * stream) | ||
1964 | * - bit4: channel estimation updates based on remodulation of | ||
1965 | * L-SIG and HT-SIG symbols | ||
1966 | */ | ||
1967 | #define BBP105_DETECT_SIG_ON_PRIMARY FIELD8(0x01) | ||
1968 | #define BBP105_FEQ FIELD8(0x02) | ||
1969 | #define BBP105_MLD FIELD8(0x04) | ||
1970 | #define BBP105_SIG_REMODULATION FIELD8(0x08) | ||
1971 | |||
1972 | /* | ||
1951 | * BBP 109 | 1973 | * BBP 109 |
1952 | */ | 1974 | */ |
1953 | #define BBP109_TX0_POWER FIELD8(0x0f) | 1975 | #define BBP109_TX0_POWER FIELD8(0x0f) |
@@ -1967,6 +1989,11 @@ struct mac_iveiv_entry { | |||
1967 | #define BBP152_RX_DEFAULT_ANT FIELD8(0x80) | 1989 | #define BBP152_RX_DEFAULT_ANT FIELD8(0x80) |
1968 | 1990 | ||
1969 | /* | 1991 | /* |
1992 | * BBP 254: unknown | ||
1993 | */ | ||
1994 | #define BBP254_BIT7 FIELD8(0x80) | ||
1995 | |||
1996 | /* | ||
1970 | * RFCSR registers | 1997 | * RFCSR registers |
1971 | * The wordsize of the RFCSR is 8 bits. | 1998 | * The wordsize of the RFCSR is 8 bits. |
1972 | */ | 1999 | */ |
@@ -2022,9 +2049,18 @@ struct mac_iveiv_entry { | |||
2022 | #define RFCSR7_BITS67 FIELD8(0xc0) | 2049 | #define RFCSR7_BITS67 FIELD8(0xc0) |
2023 | 2050 | ||
2024 | /* | 2051 | /* |
2052 | * RFCSR 9: | ||
2053 | */ | ||
2054 | #define RFCSR9_K FIELD8(0x0f) | ||
2055 | #define RFCSR9_N FIELD8(0x10) | ||
2056 | #define RFCSR9_UNKNOWN FIELD8(0x60) | ||
2057 | #define RFCSR9_MOD FIELD8(0x80) | ||
2058 | |||
2059 | /* | ||
2025 | * RFCSR 11: | 2060 | * RFCSR 11: |
2026 | */ | 2061 | */ |
2027 | #define RFCSR11_R FIELD8(0x03) | 2062 | #define RFCSR11_R FIELD8(0x03) |
2063 | #define RFCSR11_MOD FIELD8(0xc0) | ||
2028 | 2064 | ||
2029 | /* | 2065 | /* |
2030 | * RFCSR 12: | 2066 | * RFCSR 12: |
@@ -2130,11 +2166,13 @@ struct mac_iveiv_entry { | |||
2130 | * RFCSR 49: | 2166 | * RFCSR 49: |
2131 | */ | 2167 | */ |
2132 | #define RFCSR49_TX FIELD8(0x3f) | 2168 | #define RFCSR49_TX FIELD8(0x3f) |
2169 | #define RFCSR49_EP FIELD8(0xc0) | ||
2133 | 2170 | ||
2134 | /* | 2171 | /* |
2135 | * RFCSR 50: | 2172 | * RFCSR 50: |
2136 | */ | 2173 | */ |
2137 | #define RFCSR50_TX FIELD8(0x3f) | 2174 | #define RFCSR50_TX FIELD8(0x3f) |
2175 | #define RFCSR50_EP FIELD8(0xc0) | ||
2138 | 2176 | ||
2139 | /* | 2177 | /* |
2140 | * RF registers | 2178 | * RF registers |
@@ -2497,6 +2535,61 @@ struct mac_iveiv_entry { | |||
2497 | #define EEPROM_BBP_REG_ID FIELD16(0xff00) | 2535 | #define EEPROM_BBP_REG_ID FIELD16(0xff00) |
2498 | 2536 | ||
2499 | /* | 2537 | /* |
2538 | * EEPROM IQ Calibration, unlike other entries those are byte addresses. | ||
2539 | */ | ||
2540 | |||
2541 | #define EEPROM_IQ_GAIN_CAL_TX0_2G 0x130 | ||
2542 | #define EEPROM_IQ_PHASE_CAL_TX0_2G 0x131 | ||
2543 | #define EEPROM_IQ_GROUPDELAY_CAL_TX0_2G 0x132 | ||
2544 | #define EEPROM_IQ_GAIN_CAL_TX1_2G 0x133 | ||
2545 | #define EEPROM_IQ_PHASE_CAL_TX1_2G 0x134 | ||
2546 | #define EEPROM_IQ_GROUPDELAY_CAL_TX1_2G 0x135 | ||
2547 | #define EEPROM_IQ_GAIN_CAL_RX0_2G 0x136 | ||
2548 | #define EEPROM_IQ_PHASE_CAL_RX0_2G 0x137 | ||
2549 | #define EEPROM_IQ_GROUPDELAY_CAL_RX0_2G 0x138 | ||
2550 | #define EEPROM_IQ_GAIN_CAL_RX1_2G 0x139 | ||
2551 | #define EEPROM_IQ_PHASE_CAL_RX1_2G 0x13A | ||
2552 | #define EEPROM_IQ_GROUPDELAY_CAL_RX1_2G 0x13B | ||
2553 | #define EEPROM_RF_IQ_COMPENSATION_CONTROL 0x13C | ||
2554 | #define EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CONTROL 0x13D | ||
2555 | #define EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5G 0x144 | ||
2556 | #define EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5G 0x145 | ||
2557 | #define EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5G 0X146 | ||
2558 | #define EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5G 0x147 | ||
2559 | #define EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5G 0x148 | ||
2560 | #define EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5G 0x149 | ||
2561 | #define EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5G 0x14A | ||
2562 | #define EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5G 0x14B | ||
2563 | #define EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5G 0X14C | ||
2564 | #define EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5G 0x14D | ||
2565 | #define EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5G 0x14E | ||
2566 | #define EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5G 0x14F | ||
2567 | #define EEPROM_IQ_GROUPDELAY_CAL_TX0_CH36_TO_CH64_5G 0x150 | ||
2568 | #define EEPROM_IQ_GROUPDELAY_CAL_TX1_CH36_TO_CH64_5G 0x151 | ||
2569 | #define EEPROM_IQ_GROUPDELAY_CAL_TX0_CH100_TO_CH138_5G 0x152 | ||
2570 | #define EEPROM_IQ_GROUPDELAY_CAL_TX1_CH100_TO_CH138_5G 0x153 | ||
2571 | #define EEPROM_IQ_GROUPDELAY_CAL_TX0_CH140_TO_CH165_5G 0x154 | ||
2572 | #define EEPROM_IQ_GROUPDELAY_CAL_TX1_CH140_TO_CH165_5G 0x155 | ||
2573 | #define EEPROM_IQ_GAIN_CAL_RX0_CH36_TO_CH64_5G 0x156 | ||
2574 | #define EEPROM_IQ_PHASE_CAL_RX0_CH36_TO_CH64_5G 0x157 | ||
2575 | #define EEPROM_IQ_GAIN_CAL_RX0_CH100_TO_CH138_5G 0X158 | ||
2576 | #define EEPROM_IQ_PHASE_CAL_RX0_CH100_TO_CH138_5G 0x159 | ||
2577 | #define EEPROM_IQ_GAIN_CAL_RX0_CH140_TO_CH165_5G 0x15A | ||
2578 | #define EEPROM_IQ_PHASE_CAL_RX0_CH140_TO_CH165_5G 0x15B | ||
2579 | #define EEPROM_IQ_GAIN_CAL_RX1_CH36_TO_CH64_5G 0x15C | ||
2580 | #define EEPROM_IQ_PHASE_CAL_RX1_CH36_TO_CH64_5G 0x15D | ||
2581 | #define EEPROM_IQ_GAIN_CAL_RX1_CH100_TO_CH138_5G 0X15E | ||
2582 | #define EEPROM_IQ_PHASE_CAL_RX1_CH100_TO_CH138_5G 0x15F | ||
2583 | #define EEPROM_IQ_GAIN_CAL_RX1_CH140_TO_CH165_5G 0x160 | ||
2584 | #define EEPROM_IQ_PHASE_CAL_RX1_CH140_TO_CH165_5G 0x161 | ||
2585 | #define EEPROM_IQ_GROUPDELAY_CAL_RX0_CH36_TO_CH64_5G 0x162 | ||
2586 | #define EEPROM_IQ_GROUPDELAY_CAL_RX1_CH36_TO_CH64_5G 0x163 | ||
2587 | #define EEPROM_IQ_GROUPDELAY_CAL_RX0_CH100_TO_CH138_5G 0x164 | ||
2588 | #define EEPROM_IQ_GROUPDELAY_CAL_RX1_CH100_TO_CH138_5G 0x165 | ||
2589 | #define EEPROM_IQ_GROUPDELAY_CAL_RX0_CH140_TO_CH165_5G 0x166 | ||
2590 | #define EEPROM_IQ_GROUPDELAY_CAL_RX1_CH140_TO_CH165_5G 0x167 | ||
2591 | |||
2592 | /* | ||
2500 | * MCU mailbox commands. | 2593 | * MCU mailbox commands. |
2501 | * MCU_SLEEP - go to power-save mode. | 2594 | * MCU_SLEEP - go to power-save mode. |
2502 | * arg1: 1: save as much power as possible, 0: save less power. | 2595 | * arg1: 1: save as much power as possible, 0: save less power. |
@@ -2535,6 +2628,8 @@ struct mac_iveiv_entry { | |||
2535 | #define TXWI_DESC_SIZE (4 * sizeof(__le32)) | 2628 | #define TXWI_DESC_SIZE (4 * sizeof(__le32)) |
2536 | #define RXWI_DESC_SIZE (4 * sizeof(__le32)) | 2629 | #define RXWI_DESC_SIZE (4 * sizeof(__le32)) |
2537 | 2630 | ||
2631 | #define TXWI_DESC_SIZE_5592 (5 * sizeof(__le32)) | ||
2632 | #define RXWI_DESC_SIZE_5592 (6 * sizeof(__le32)) | ||
2538 | /* | 2633 | /* |
2539 | * TX WI structure | 2634 | * TX WI structure |
2540 | */ | 2635 | */ |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index a658b4bc7da2..f08a0424fe4d 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -527,8 +527,10 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
527 | */ | 527 | */ |
528 | rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); | 528 | rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); |
529 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); | 529 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); |
530 | if (rt2x00_is_usb(rt2x00dev)) | 530 | if (rt2x00_is_usb(rt2x00dev)) { |
531 | rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0); | 531 | rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0); |
532 | rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); | ||
533 | } | ||
532 | msleep(1); | 534 | msleep(1); |
533 | 535 | ||
534 | return 0; | 536 | return 0; |
@@ -674,11 +676,6 @@ void rt2800_process_rxwi(struct queue_entry *entry, | |||
674 | * Convert descriptor AGC value to RSSI value. | 676 | * Convert descriptor AGC value to RSSI value. |
675 | */ | 677 | */ |
676 | rxdesc->rssi = rt2800_agc_to_rssi(entry->queue->rt2x00dev, word); | 678 | rxdesc->rssi = rt2800_agc_to_rssi(entry->queue->rt2x00dev, word); |
677 | |||
678 | /* | ||
679 | * Remove RXWI descriptor from start of buffer. | ||
680 | */ | ||
681 | skb_pull(entry->skb, RXWI_DESC_SIZE); | ||
682 | } | 679 | } |
683 | EXPORT_SYMBOL_GPL(rt2800_process_rxwi); | 680 | EXPORT_SYMBOL_GPL(rt2800_process_rxwi); |
684 | 681 | ||
@@ -1988,8 +1985,21 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, | |||
1988 | } | 1985 | } |
1989 | 1986 | ||
1990 | #define POWER_BOUND 0x27 | 1987 | #define POWER_BOUND 0x27 |
1988 | #define POWER_BOUND_5G 0x2b | ||
1991 | #define FREQ_OFFSET_BOUND 0x5f | 1989 | #define FREQ_OFFSET_BOUND 0x5f |
1992 | 1990 | ||
1991 | static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev) | ||
1992 | { | ||
1993 | u8 rfcsr; | ||
1994 | |||
1995 | rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); | ||
1996 | if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND) | ||
1997 | rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND); | ||
1998 | else | ||
1999 | rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset); | ||
2000 | rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); | ||
2001 | } | ||
2002 | |||
1993 | static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev, | 2003 | static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev, |
1994 | struct ieee80211_conf *conf, | 2004 | struct ieee80211_conf *conf, |
1995 | struct rf_channel *rf, | 2005 | struct rf_channel *rf, |
@@ -2010,12 +2020,7 @@ static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev, | |||
2010 | rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1); | 2020 | rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1); |
2011 | rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); | 2021 | rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); |
2012 | 2022 | ||
2013 | rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); | 2023 | rt2800_adjust_freq_offset(rt2x00dev); |
2014 | if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND) | ||
2015 | rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND); | ||
2016 | else | ||
2017 | rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset); | ||
2018 | rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); | ||
2019 | 2024 | ||
2020 | if (rf->channel <= 14) { | 2025 | if (rf->channel <= 14) { |
2021 | if (rf->channel == 6) | 2026 | if (rf->channel == 6) |
@@ -2056,13 +2061,7 @@ static void rt2800_config_channel_rf3322(struct rt2x00_dev *rt2x00dev, | |||
2056 | else | 2061 | else |
2057 | rt2800_rfcsr_write(rt2x00dev, 48, info->default_power2); | 2062 | rt2800_rfcsr_write(rt2x00dev, 48, info->default_power2); |
2058 | 2063 | ||
2059 | rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); | 2064 | rt2800_adjust_freq_offset(rt2x00dev); |
2060 | if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND) | ||
2061 | rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND); | ||
2062 | else | ||
2063 | rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset); | ||
2064 | |||
2065 | rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); | ||
2066 | 2065 | ||
2067 | rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); | 2066 | rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); |
2068 | rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); | 2067 | rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); |
@@ -2127,12 +2126,7 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, | |||
2127 | rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1); | 2126 | rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1); |
2128 | rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); | 2127 | rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); |
2129 | 2128 | ||
2130 | rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); | 2129 | rt2800_adjust_freq_offset(rt2x00dev); |
2131 | if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND) | ||
2132 | rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND); | ||
2133 | else | ||
2134 | rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset); | ||
2135 | rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); | ||
2136 | 2130 | ||
2137 | if (rf->channel <= 14) { | 2131 | if (rf->channel <= 14) { |
2138 | int idx = rf->channel-1; | 2132 | int idx = rf->channel-1; |
@@ -2184,6 +2178,382 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, | |||
2184 | } | 2178 | } |
2185 | } | 2179 | } |
2186 | 2180 | ||
2181 | static void rt2800_config_channel_rf55xx(struct rt2x00_dev *rt2x00dev, | ||
2182 | struct ieee80211_conf *conf, | ||
2183 | struct rf_channel *rf, | ||
2184 | struct channel_info *info) | ||
2185 | { | ||
2186 | u8 rfcsr, ep_reg; | ||
2187 | u32 reg; | ||
2188 | int power_bound; | ||
2189 | |||
2190 | /* TODO */ | ||
2191 | const bool is_11b = false; | ||
2192 | const bool is_type_ep = false; | ||
2193 | |||
2194 | rt2800_register_read(rt2x00dev, LDO_CFG0, ®); | ||
2195 | rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, | ||
2196 | (rf->channel > 14 || conf_is_ht40(conf)) ? 5 : 0); | ||
2197 | rt2800_register_write(rt2x00dev, LDO_CFG0, reg); | ||
2198 | |||
2199 | /* Order of values on rf_channel entry: N, K, mod, R */ | ||
2200 | rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1 & 0xff); | ||
2201 | |||
2202 | rt2800_rfcsr_read(rt2x00dev, 9, &rfcsr); | ||
2203 | rt2x00_set_field8(&rfcsr, RFCSR9_K, rf->rf2 & 0xf); | ||
2204 | rt2x00_set_field8(&rfcsr, RFCSR9_N, (rf->rf1 & 0x100) >> 8); | ||
2205 | rt2x00_set_field8(&rfcsr, RFCSR9_MOD, ((rf->rf3 - 8) & 0x4) >> 2); | ||
2206 | rt2800_rfcsr_write(rt2x00dev, 9, rfcsr); | ||
2207 | |||
2208 | rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr); | ||
2209 | rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf4 - 1); | ||
2210 | rt2x00_set_field8(&rfcsr, RFCSR11_MOD, (rf->rf3 - 8) & 0x3); | ||
2211 | rt2800_rfcsr_write(rt2x00dev, 11, rfcsr); | ||
2212 | |||
2213 | if (rf->channel <= 14) { | ||
2214 | rt2800_rfcsr_write(rt2x00dev, 10, 0x90); | ||
2215 | /* FIXME: RF11 owerwrite ? */ | ||
2216 | rt2800_rfcsr_write(rt2x00dev, 11, 0x4A); | ||
2217 | rt2800_rfcsr_write(rt2x00dev, 12, 0x52); | ||
2218 | rt2800_rfcsr_write(rt2x00dev, 13, 0x42); | ||
2219 | rt2800_rfcsr_write(rt2x00dev, 22, 0x40); | ||
2220 | rt2800_rfcsr_write(rt2x00dev, 24, 0x4A); | ||
2221 | rt2800_rfcsr_write(rt2x00dev, 25, 0x80); | ||
2222 | rt2800_rfcsr_write(rt2x00dev, 27, 0x42); | ||
2223 | rt2800_rfcsr_write(rt2x00dev, 36, 0x80); | ||
2224 | rt2800_rfcsr_write(rt2x00dev, 37, 0x08); | ||
2225 | rt2800_rfcsr_write(rt2x00dev, 38, 0x89); | ||
2226 | rt2800_rfcsr_write(rt2x00dev, 39, 0x1B); | ||
2227 | rt2800_rfcsr_write(rt2x00dev, 40, 0x0D); | ||
2228 | rt2800_rfcsr_write(rt2x00dev, 41, 0x9B); | ||
2229 | rt2800_rfcsr_write(rt2x00dev, 42, 0xD5); | ||
2230 | rt2800_rfcsr_write(rt2x00dev, 43, 0x72); | ||
2231 | rt2800_rfcsr_write(rt2x00dev, 44, 0x0E); | ||
2232 | rt2800_rfcsr_write(rt2x00dev, 45, 0xA2); | ||
2233 | rt2800_rfcsr_write(rt2x00dev, 46, 0x6B); | ||
2234 | rt2800_rfcsr_write(rt2x00dev, 48, 0x10); | ||
2235 | rt2800_rfcsr_write(rt2x00dev, 51, 0x3E); | ||
2236 | rt2800_rfcsr_write(rt2x00dev, 52, 0x48); | ||
2237 | rt2800_rfcsr_write(rt2x00dev, 54, 0x38); | ||
2238 | rt2800_rfcsr_write(rt2x00dev, 56, 0xA1); | ||
2239 | rt2800_rfcsr_write(rt2x00dev, 57, 0x00); | ||
2240 | rt2800_rfcsr_write(rt2x00dev, 58, 0x39); | ||
2241 | rt2800_rfcsr_write(rt2x00dev, 60, 0x45); | ||
2242 | rt2800_rfcsr_write(rt2x00dev, 61, 0x91); | ||
2243 | rt2800_rfcsr_write(rt2x00dev, 62, 0x39); | ||
2244 | |||
2245 | /* TODO RF27 <- tssi */ | ||
2246 | |||
2247 | rfcsr = rf->channel <= 10 ? 0x07 : 0x06; | ||
2248 | rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); | ||
2249 | rt2800_rfcsr_write(rt2x00dev, 59, rfcsr); | ||
2250 | |||
2251 | if (is_11b) { | ||
2252 | /* CCK */ | ||
2253 | rt2800_rfcsr_write(rt2x00dev, 31, 0xF8); | ||
2254 | rt2800_rfcsr_write(rt2x00dev, 32, 0xC0); | ||
2255 | if (is_type_ep) | ||
2256 | rt2800_rfcsr_write(rt2x00dev, 55, 0x06); | ||
2257 | else | ||
2258 | rt2800_rfcsr_write(rt2x00dev, 55, 0x47); | ||
2259 | } else { | ||
2260 | /* OFDM */ | ||
2261 | if (is_type_ep) | ||
2262 | rt2800_rfcsr_write(rt2x00dev, 55, 0x03); | ||
2263 | else | ||
2264 | rt2800_rfcsr_write(rt2x00dev, 55, 0x43); | ||
2265 | } | ||
2266 | |||
2267 | power_bound = POWER_BOUND; | ||
2268 | ep_reg = 0x2; | ||
2269 | } else { | ||
2270 | rt2800_rfcsr_write(rt2x00dev, 10, 0x97); | ||
2271 | /* FIMXE: RF11 overwrite */ | ||
2272 | rt2800_rfcsr_write(rt2x00dev, 11, 0x40); | ||
2273 | rt2800_rfcsr_write(rt2x00dev, 25, 0xBF); | ||
2274 | rt2800_rfcsr_write(rt2x00dev, 27, 0x42); | ||
2275 | rt2800_rfcsr_write(rt2x00dev, 36, 0x00); | ||
2276 | rt2800_rfcsr_write(rt2x00dev, 37, 0x04); | ||
2277 | rt2800_rfcsr_write(rt2x00dev, 38, 0x85); | ||
2278 | rt2800_rfcsr_write(rt2x00dev, 40, 0x42); | ||
2279 | rt2800_rfcsr_write(rt2x00dev, 41, 0xBB); | ||
2280 | rt2800_rfcsr_write(rt2x00dev, 42, 0xD7); | ||
2281 | rt2800_rfcsr_write(rt2x00dev, 45, 0x41); | ||
2282 | rt2800_rfcsr_write(rt2x00dev, 48, 0x00); | ||
2283 | rt2800_rfcsr_write(rt2x00dev, 57, 0x77); | ||
2284 | rt2800_rfcsr_write(rt2x00dev, 60, 0x05); | ||
2285 | rt2800_rfcsr_write(rt2x00dev, 61, 0x01); | ||
2286 | |||
2287 | /* TODO RF27 <- tssi */ | ||
2288 | |||
2289 | if (rf->channel >= 36 && rf->channel <= 64) { | ||
2290 | |||
2291 | rt2800_rfcsr_write(rt2x00dev, 12, 0x2E); | ||
2292 | rt2800_rfcsr_write(rt2x00dev, 13, 0x22); | ||
2293 | rt2800_rfcsr_write(rt2x00dev, 22, 0x60); | ||
2294 | rt2800_rfcsr_write(rt2x00dev, 23, 0x7F); | ||
2295 | if (rf->channel <= 50) | ||
2296 | rt2800_rfcsr_write(rt2x00dev, 24, 0x09); | ||
2297 | else if (rf->channel >= 52) | ||
2298 | rt2800_rfcsr_write(rt2x00dev, 24, 0x07); | ||
2299 | rt2800_rfcsr_write(rt2x00dev, 39, 0x1C); | ||
2300 | rt2800_rfcsr_write(rt2x00dev, 43, 0x5B); | ||
2301 | rt2800_rfcsr_write(rt2x00dev, 44, 0X40); | ||
2302 | rt2800_rfcsr_write(rt2x00dev, 46, 0X00); | ||
2303 | rt2800_rfcsr_write(rt2x00dev, 51, 0xFE); | ||
2304 | rt2800_rfcsr_write(rt2x00dev, 52, 0x0C); | ||
2305 | rt2800_rfcsr_write(rt2x00dev, 54, 0xF8); | ||
2306 | if (rf->channel <= 50) { | ||
2307 | rt2800_rfcsr_write(rt2x00dev, 55, 0x06), | ||
2308 | rt2800_rfcsr_write(rt2x00dev, 56, 0xD3); | ||
2309 | } else if (rf->channel >= 52) { | ||
2310 | rt2800_rfcsr_write(rt2x00dev, 55, 0x04); | ||
2311 | rt2800_rfcsr_write(rt2x00dev, 56, 0xBB); | ||
2312 | } | ||
2313 | |||
2314 | rt2800_rfcsr_write(rt2x00dev, 58, 0x15); | ||
2315 | rt2800_rfcsr_write(rt2x00dev, 59, 0x7F); | ||
2316 | rt2800_rfcsr_write(rt2x00dev, 62, 0x15); | ||
2317 | |||
2318 | } else if (rf->channel >= 100 && rf->channel <= 165) { | ||
2319 | |||
2320 | rt2800_rfcsr_write(rt2x00dev, 12, 0x0E); | ||
2321 | rt2800_rfcsr_write(rt2x00dev, 13, 0x42); | ||
2322 | rt2800_rfcsr_write(rt2x00dev, 22, 0x40); | ||
2323 | if (rf->channel <= 153) { | ||
2324 | rt2800_rfcsr_write(rt2x00dev, 23, 0x3C); | ||
2325 | rt2800_rfcsr_write(rt2x00dev, 24, 0x06); | ||
2326 | } else if (rf->channel >= 155) { | ||
2327 | rt2800_rfcsr_write(rt2x00dev, 23, 0x38); | ||
2328 | rt2800_rfcsr_write(rt2x00dev, 24, 0x05); | ||
2329 | } | ||
2330 | if (rf->channel <= 138) { | ||
2331 | rt2800_rfcsr_write(rt2x00dev, 39, 0x1A); | ||
2332 | rt2800_rfcsr_write(rt2x00dev, 43, 0x3B); | ||
2333 | rt2800_rfcsr_write(rt2x00dev, 44, 0x20); | ||
2334 | rt2800_rfcsr_write(rt2x00dev, 46, 0x18); | ||
2335 | } else if (rf->channel >= 140) { | ||
2336 | rt2800_rfcsr_write(rt2x00dev, 39, 0x18); | ||
2337 | rt2800_rfcsr_write(rt2x00dev, 43, 0x1B); | ||
2338 | rt2800_rfcsr_write(rt2x00dev, 44, 0x10); | ||
2339 | rt2800_rfcsr_write(rt2x00dev, 46, 0X08); | ||
2340 | } | ||
2341 | if (rf->channel <= 124) | ||
2342 | rt2800_rfcsr_write(rt2x00dev, 51, 0xFC); | ||
2343 | else if (rf->channel >= 126) | ||
2344 | rt2800_rfcsr_write(rt2x00dev, 51, 0xEC); | ||
2345 | if (rf->channel <= 138) | ||
2346 | rt2800_rfcsr_write(rt2x00dev, 52, 0x06); | ||
2347 | else if (rf->channel >= 140) | ||
2348 | rt2800_rfcsr_write(rt2x00dev, 52, 0x06); | ||
2349 | rt2800_rfcsr_write(rt2x00dev, 54, 0xEB); | ||
2350 | if (rf->channel <= 138) | ||
2351 | rt2800_rfcsr_write(rt2x00dev, 55, 0x01); | ||
2352 | else if (rf->channel >= 140) | ||
2353 | rt2800_rfcsr_write(rt2x00dev, 55, 0x00); | ||
2354 | if (rf->channel <= 128) | ||
2355 | rt2800_rfcsr_write(rt2x00dev, 56, 0xBB); | ||
2356 | else if (rf->channel >= 130) | ||
2357 | rt2800_rfcsr_write(rt2x00dev, 56, 0xAB); | ||
2358 | if (rf->channel <= 116) | ||
2359 | rt2800_rfcsr_write(rt2x00dev, 58, 0x1D); | ||
2360 | else if (rf->channel >= 118) | ||
2361 | rt2800_rfcsr_write(rt2x00dev, 58, 0x15); | ||
2362 | if (rf->channel <= 138) | ||
2363 | rt2800_rfcsr_write(rt2x00dev, 59, 0x3F); | ||
2364 | else if (rf->channel >= 140) | ||
2365 | rt2800_rfcsr_write(rt2x00dev, 59, 0x7C); | ||
2366 | if (rf->channel <= 116) | ||
2367 | rt2800_rfcsr_write(rt2x00dev, 62, 0x1D); | ||
2368 | else if (rf->channel >= 118) | ||
2369 | rt2800_rfcsr_write(rt2x00dev, 62, 0x15); | ||
2370 | } | ||
2371 | |||
2372 | power_bound = POWER_BOUND_5G; | ||
2373 | ep_reg = 0x3; | ||
2374 | } | ||
2375 | |||
2376 | rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr); | ||
2377 | if (info->default_power1 > power_bound) | ||
2378 | rt2x00_set_field8(&rfcsr, RFCSR49_TX, power_bound); | ||
2379 | else | ||
2380 | rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1); | ||
2381 | if (is_type_ep) | ||
2382 | rt2x00_set_field8(&rfcsr, RFCSR49_EP, ep_reg); | ||
2383 | rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); | ||
2384 | |||
2385 | rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr); | ||
2386 | if (info->default_power1 > power_bound) | ||
2387 | rt2x00_set_field8(&rfcsr, RFCSR50_TX, power_bound); | ||
2388 | else | ||
2389 | rt2x00_set_field8(&rfcsr, RFCSR50_TX, info->default_power2); | ||
2390 | if (is_type_ep) | ||
2391 | rt2x00_set_field8(&rfcsr, RFCSR50_EP, ep_reg); | ||
2392 | rt2800_rfcsr_write(rt2x00dev, 50, rfcsr); | ||
2393 | |||
2394 | rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); | ||
2395 | rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); | ||
2396 | rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1); | ||
2397 | |||
2398 | rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, | ||
2399 | rt2x00dev->default_ant.tx_chain_num >= 1); | ||
2400 | rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, | ||
2401 | rt2x00dev->default_ant.tx_chain_num == 2); | ||
2402 | rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0); | ||
2403 | |||
2404 | rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, | ||
2405 | rt2x00dev->default_ant.rx_chain_num >= 1); | ||
2406 | rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, | ||
2407 | rt2x00dev->default_ant.rx_chain_num == 2); | ||
2408 | rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); | ||
2409 | |||
2410 | rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); | ||
2411 | rt2800_rfcsr_write(rt2x00dev, 6, 0xe4); | ||
2412 | |||
2413 | if (conf_is_ht40(conf)) | ||
2414 | rt2800_rfcsr_write(rt2x00dev, 30, 0x16); | ||
2415 | else | ||
2416 | rt2800_rfcsr_write(rt2x00dev, 30, 0x10); | ||
2417 | |||
2418 | if (!is_11b) { | ||
2419 | rt2800_rfcsr_write(rt2x00dev, 31, 0x80); | ||
2420 | rt2800_rfcsr_write(rt2x00dev, 32, 0x80); | ||
2421 | } | ||
2422 | |||
2423 | /* TODO proper frequency adjustment */ | ||
2424 | rt2800_adjust_freq_offset(rt2x00dev); | ||
2425 | |||
2426 | /* TODO merge with others */ | ||
2427 | rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); | ||
2428 | rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1); | ||
2429 | rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); | ||
2430 | |||
2431 | /* BBP settings */ | ||
2432 | rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); | ||
2433 | rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); | ||
2434 | rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); | ||
2435 | |||
2436 | rt2800_bbp_write(rt2x00dev, 79, (rf->channel <= 14) ? 0x1C : 0x18); | ||
2437 | rt2800_bbp_write(rt2x00dev, 80, (rf->channel <= 14) ? 0x0E : 0x08); | ||
2438 | rt2800_bbp_write(rt2x00dev, 81, (rf->channel <= 14) ? 0x3A : 0x38); | ||
2439 | rt2800_bbp_write(rt2x00dev, 82, (rf->channel <= 14) ? 0x62 : 0x92); | ||
2440 | |||
2441 | /* GLRT band configuration */ | ||
2442 | rt2800_bbp_write(rt2x00dev, 195, 128); | ||
2443 | rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0xE0 : 0xF0); | ||
2444 | rt2800_bbp_write(rt2x00dev, 195, 129); | ||
2445 | rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x1F : 0x1E); | ||
2446 | rt2800_bbp_write(rt2x00dev, 195, 130); | ||
2447 | rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x38 : 0x28); | ||
2448 | rt2800_bbp_write(rt2x00dev, 195, 131); | ||
2449 | rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x32 : 0x20); | ||
2450 | rt2800_bbp_write(rt2x00dev, 195, 133); | ||
2451 | rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x28 : 0x7F); | ||
2452 | rt2800_bbp_write(rt2x00dev, 195, 124); | ||
2453 | rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x19 : 0x7F); | ||
2454 | } | ||
2455 | |||
2456 | static void rt2800_bbp_write_with_rx_chain(struct rt2x00_dev *rt2x00dev, | ||
2457 | const unsigned int word, | ||
2458 | const u8 value) | ||
2459 | { | ||
2460 | u8 chain, reg; | ||
2461 | |||
2462 | for (chain = 0; chain < rt2x00dev->default_ant.rx_chain_num; chain++) { | ||
2463 | rt2800_bbp_read(rt2x00dev, 27, ®); | ||
2464 | rt2x00_set_field8(®, BBP27_RX_CHAIN_SEL, chain); | ||
2465 | rt2800_bbp_write(rt2x00dev, 27, reg); | ||
2466 | |||
2467 | rt2800_bbp_write(rt2x00dev, word, value); | ||
2468 | } | ||
2469 | } | ||
2470 | |||
2471 | static void rt2800_iq_calibrate(struct rt2x00_dev *rt2x00dev, int channel) | ||
2472 | { | ||
2473 | u8 cal; | ||
2474 | |||
2475 | /* TX0 IQ Gain */ | ||
2476 | rt2800_bbp_write(rt2x00dev, 158, 0x2c); | ||
2477 | if (channel <= 14) | ||
2478 | cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_GAIN_CAL_TX0_2G); | ||
2479 | else if (channel >= 36 && channel <= 64) | ||
2480 | cal = rt2x00_eeprom_byte(rt2x00dev, | ||
2481 | EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5G); | ||
2482 | else if (channel >= 100 && channel <= 138) | ||
2483 | cal = rt2x00_eeprom_byte(rt2x00dev, | ||
2484 | EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5G); | ||
2485 | else if (channel >= 140 && channel <= 165) | ||
2486 | cal = rt2x00_eeprom_byte(rt2x00dev, | ||
2487 | EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5G); | ||
2488 | else | ||
2489 | cal = 0; | ||
2490 | rt2800_bbp_write(rt2x00dev, 159, cal); | ||
2491 | |||
2492 | /* TX0 IQ Phase */ | ||
2493 | rt2800_bbp_write(rt2x00dev, 158, 0x2d); | ||
2494 | if (channel <= 14) | ||
2495 | cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_PHASE_CAL_TX0_2G); | ||
2496 | else if (channel >= 36 && channel <= 64) | ||
2497 | cal = rt2x00_eeprom_byte(rt2x00dev, | ||
2498 | EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5G); | ||
2499 | else if (channel >= 100 && channel <= 138) | ||
2500 | cal = rt2x00_eeprom_byte(rt2x00dev, | ||
2501 | EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5G); | ||
2502 | else if (channel >= 140 && channel <= 165) | ||
2503 | cal = rt2x00_eeprom_byte(rt2x00dev, | ||
2504 | EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5G); | ||
2505 | else | ||
2506 | cal = 0; | ||
2507 | rt2800_bbp_write(rt2x00dev, 159, cal); | ||
2508 | |||
2509 | /* TX1 IQ Gain */ | ||
2510 | rt2800_bbp_write(rt2x00dev, 158, 0x4a); | ||
2511 | if (channel <= 14) | ||
2512 | cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_GAIN_CAL_TX1_2G); | ||
2513 | else if (channel >= 36 && channel <= 64) | ||
2514 | cal = rt2x00_eeprom_byte(rt2x00dev, | ||
2515 | EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5G); | ||
2516 | else if (channel >= 100 && channel <= 138) | ||
2517 | cal = rt2x00_eeprom_byte(rt2x00dev, | ||
2518 | EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5G); | ||
2519 | else if (channel >= 140 && channel <= 165) | ||
2520 | cal = rt2x00_eeprom_byte(rt2x00dev, | ||
2521 | EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5G); | ||
2522 | else | ||
2523 | cal = 0; | ||
2524 | rt2800_bbp_write(rt2x00dev, 159, cal); | ||
2525 | |||
2526 | /* TX1 IQ Phase */ | ||
2527 | rt2800_bbp_write(rt2x00dev, 158, 0x4b); | ||
2528 | if (channel <= 14) | ||
2529 | cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_PHASE_CAL_TX1_2G); | ||
2530 | else if (channel >= 36 && channel <= 64) | ||
2531 | cal = rt2x00_eeprom_byte(rt2x00dev, | ||
2532 | EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5G); | ||
2533 | else if (channel >= 100 && channel <= 138) | ||
2534 | cal = rt2x00_eeprom_byte(rt2x00dev, | ||
2535 | EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5G); | ||
2536 | else if (channel >= 140 && channel <= 165) | ||
2537 | cal = rt2x00_eeprom_byte(rt2x00dev, | ||
2538 | EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5G); | ||
2539 | else | ||
2540 | cal = 0; | ||
2541 | rt2800_bbp_write(rt2x00dev, 159, cal); | ||
2542 | |||
2543 | /* FIXME: possible RX0, RX1 callibration ? */ | ||
2544 | |||
2545 | /* RF IQ compensation control */ | ||
2546 | rt2800_bbp_write(rt2x00dev, 158, 0x04); | ||
2547 | cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_RF_IQ_COMPENSATION_CONTROL); | ||
2548 | rt2800_bbp_write(rt2x00dev, 159, cal != 0xff ? cal : 0); | ||
2549 | |||
2550 | /* RF IQ imbalance compensation control */ | ||
2551 | rt2800_bbp_write(rt2x00dev, 158, 0x03); | ||
2552 | cal = rt2x00_eeprom_byte(rt2x00dev, | ||
2553 | EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CONTROL); | ||
2554 | rt2800_bbp_write(rt2x00dev, 159, cal != 0xff ? cal : 0); | ||
2555 | } | ||
2556 | |||
2187 | static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | 2557 | static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, |
2188 | struct ieee80211_conf *conf, | 2558 | struct ieee80211_conf *conf, |
2189 | struct rf_channel *rf, | 2559 | struct rf_channel *rf, |
@@ -2225,6 +2595,9 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
2225 | case RF5392: | 2595 | case RF5392: |
2226 | rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info); | 2596 | rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info); |
2227 | break; | 2597 | break; |
2598 | case RF5592: | ||
2599 | rt2800_config_channel_rf55xx(rt2x00dev, conf, rf, info); | ||
2600 | break; | ||
2228 | default: | 2601 | default: |
2229 | rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info); | 2602 | rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info); |
2230 | } | 2603 | } |
@@ -2326,6 +2699,17 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
2326 | if (rt2x00_rt(rt2x00dev, RT3572)) | 2699 | if (rt2x00_rt(rt2x00dev, RT3572)) |
2327 | rt2800_rfcsr_write(rt2x00dev, 8, 0x80); | 2700 | rt2800_rfcsr_write(rt2x00dev, 8, 0x80); |
2328 | 2701 | ||
2702 | if (rt2x00_rt(rt2x00dev, RT5592)) { | ||
2703 | rt2800_bbp_write(rt2x00dev, 195, 141); | ||
2704 | rt2800_bbp_write(rt2x00dev, 196, conf_is_ht40(conf) ? 0x10 : 0x1a); | ||
2705 | |||
2706 | /* AGC init */ | ||
2707 | reg = (rf->channel <= 14 ? 0x1c : 0x24) + 2 * rt2x00dev->lna_gain; | ||
2708 | rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg); | ||
2709 | |||
2710 | rt2800_iq_calibrate(rt2x00dev, rf->channel); | ||
2711 | } | ||
2712 | |||
2329 | rt2800_bbp_read(rt2x00dev, 4, &bbp); | 2713 | rt2800_bbp_read(rt2x00dev, 4, &bbp); |
2330 | rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf)); | 2714 | rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf)); |
2331 | rt2800_bbp_write(rt2x00dev, 4, bbp); | 2715 | rt2800_bbp_write(rt2x00dev, 4, bbp); |
@@ -2938,13 +3322,16 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) | |||
2938 | rt2x00_rt(rt2x00dev, RT3390) || | 3322 | rt2x00_rt(rt2x00dev, RT3390) || |
2939 | rt2x00_rt(rt2x00dev, RT3572) || | 3323 | rt2x00_rt(rt2x00dev, RT3572) || |
2940 | rt2x00_rt(rt2x00dev, RT5390) || | 3324 | rt2x00_rt(rt2x00dev, RT5390) || |
2941 | rt2x00_rt(rt2x00dev, RT5392)) | 3325 | rt2x00_rt(rt2x00dev, RT5392) || |
3326 | rt2x00_rt(rt2x00dev, RT5592)) | ||
2942 | vgc = 0x1c + (2 * rt2x00dev->lna_gain); | 3327 | vgc = 0x1c + (2 * rt2x00dev->lna_gain); |
2943 | else | 3328 | else |
2944 | vgc = 0x2e + rt2x00dev->lna_gain; | 3329 | vgc = 0x2e + rt2x00dev->lna_gain; |
2945 | } else { /* 5GHZ band */ | 3330 | } else { /* 5GHZ band */ |
2946 | if (rt2x00_rt(rt2x00dev, RT3572)) | 3331 | if (rt2x00_rt(rt2x00dev, RT3572)) |
2947 | vgc = 0x22 + (rt2x00dev->lna_gain * 5) / 3; | 3332 | vgc = 0x22 + (rt2x00dev->lna_gain * 5) / 3; |
3333 | else if (rt2x00_rt(rt2x00dev, RT5592)) | ||
3334 | vgc = 0x24 + (2 * rt2x00dev->lna_gain); | ||
2948 | else { | 3335 | else { |
2949 | if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) | 3336 | if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) |
2950 | vgc = 0x32 + (rt2x00dev->lna_gain * 5) / 3; | 3337 | vgc = 0x32 + (rt2x00dev->lna_gain * 5) / 3; |
@@ -2960,7 +3347,11 @@ static inline void rt2800_set_vgc(struct rt2x00_dev *rt2x00dev, | |||
2960 | struct link_qual *qual, u8 vgc_level) | 3347 | struct link_qual *qual, u8 vgc_level) |
2961 | { | 3348 | { |
2962 | if (qual->vgc_level != vgc_level) { | 3349 | if (qual->vgc_level != vgc_level) { |
2963 | rt2800_bbp_write(rt2x00dev, 66, vgc_level); | 3350 | if (rt2x00_rt(rt2x00dev, RT5592)) { |
3351 | rt2800_bbp_write(rt2x00dev, 83, qual->rssi > -65 ? 0x4a : 0x7a); | ||
3352 | rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, vgc_level); | ||
3353 | } else | ||
3354 | rt2800_bbp_write(rt2x00dev, 66, vgc_level); | ||
2964 | qual->vgc_level = vgc_level; | 3355 | qual->vgc_level = vgc_level; |
2965 | qual->vgc_level_reg = vgc_level; | 3356 | qual->vgc_level_reg = vgc_level; |
2966 | } | 3357 | } |
@@ -2975,15 +3366,23 @@ EXPORT_SYMBOL_GPL(rt2800_reset_tuner); | |||
2975 | void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, | 3366 | void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, |
2976 | const u32 count) | 3367 | const u32 count) |
2977 | { | 3368 | { |
3369 | u8 vgc; | ||
3370 | |||
2978 | if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) | 3371 | if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) |
2979 | return; | 3372 | return; |
2980 | |||
2981 | /* | 3373 | /* |
2982 | * When RSSI is better then -80 increase VGC level with 0x10 | 3374 | * When RSSI is better then -80 increase VGC level with 0x10, except |
3375 | * for rt5592 chip. | ||
2983 | */ | 3376 | */ |
2984 | rt2800_set_vgc(rt2x00dev, qual, | 3377 | |
2985 | rt2800_get_default_vgc(rt2x00dev) + | 3378 | vgc = rt2800_get_default_vgc(rt2x00dev); |
2986 | ((qual->rssi > -80) * 0x10)); | 3379 | |
3380 | if (rt2x00_rt(rt2x00dev, RT5592) && qual->rssi > -65) | ||
3381 | vgc += 0x20; | ||
3382 | else if (qual->rssi > -80) | ||
3383 | vgc += 0x10; | ||
3384 | |||
3385 | rt2800_set_vgc(rt2x00dev, qual, vgc); | ||
2987 | } | 3386 | } |
2988 | EXPORT_SYMBOL_GPL(rt2800_link_tuner); | 3387 | EXPORT_SYMBOL_GPL(rt2800_link_tuner); |
2989 | 3388 | ||
@@ -3122,7 +3521,8 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
3122 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); | 3521 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); |
3123 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); | 3522 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); |
3124 | } else if (rt2x00_rt(rt2x00dev, RT5390) || | 3523 | } else if (rt2x00_rt(rt2x00dev, RT5390) || |
3125 | rt2x00_rt(rt2x00dev, RT5392)) { | 3524 | rt2x00_rt(rt2x00dev, RT5392) || |
3525 | rt2x00_rt(rt2x00dev, RT5592)) { | ||
3126 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); | 3526 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); |
3127 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); | 3527 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); |
3128 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); | 3528 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); |
@@ -3302,7 +3702,8 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
3302 | rt2x00_set_field32(®, TXOP_CTRL_CFG_EXT_CWMIN, 0); | 3702 | rt2x00_set_field32(®, TXOP_CTRL_CFG_EXT_CWMIN, 0); |
3303 | rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, reg); | 3703 | rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, reg); |
3304 | 3704 | ||
3305 | rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, 0x00000002); | 3705 | reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002; |
3706 | rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg); | ||
3306 | 3707 | ||
3307 | rt2800_register_read(rt2x00dev, TX_RTS_CFG, ®); | 3708 | rt2800_register_read(rt2x00dev, TX_RTS_CFG, ®); |
3308 | rt2x00_set_field32(®, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32); | 3709 | rt2x00_set_field32(®, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32); |
@@ -3487,6 +3888,136 @@ static int rt2800_wait_bbp_ready(struct rt2x00_dev *rt2x00dev) | |||
3487 | return -EACCES; | 3888 | return -EACCES; |
3488 | } | 3889 | } |
3489 | 3890 | ||
3891 | static void rt2800_bbp4_mac_if_ctrl(struct rt2x00_dev *rt2x00dev) | ||
3892 | { | ||
3893 | u8 value; | ||
3894 | |||
3895 | rt2800_bbp_read(rt2x00dev, 4, &value); | ||
3896 | rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1); | ||
3897 | rt2800_bbp_write(rt2x00dev, 4, value); | ||
3898 | } | ||
3899 | |||
3900 | static void rt2800_init_freq_calibration(struct rt2x00_dev *rt2x00dev) | ||
3901 | { | ||
3902 | rt2800_bbp_write(rt2x00dev, 142, 1); | ||
3903 | rt2800_bbp_write(rt2x00dev, 143, 57); | ||
3904 | } | ||
3905 | |||
3906 | static void rt2800_init_bbp_5592_glrt(struct rt2x00_dev *rt2x00dev) | ||
3907 | { | ||
3908 | const u8 glrt_table[] = { | ||
3909 | 0xE0, 0x1F, 0X38, 0x32, 0x08, 0x28, 0x19, 0x0A, 0xFF, 0x00, /* 128 ~ 137 */ | ||
3910 | 0x16, 0x10, 0x10, 0x0B, 0x36, 0x2C, 0x26, 0x24, 0x42, 0x36, /* 138 ~ 147 */ | ||
3911 | 0x30, 0x2D, 0x4C, 0x46, 0x3D, 0x40, 0x3E, 0x42, 0x3D, 0x40, /* 148 ~ 157 */ | ||
3912 | 0X3C, 0x34, 0x2C, 0x2F, 0x3C, 0x35, 0x2E, 0x2A, 0x49, 0x41, /* 158 ~ 167 */ | ||
3913 | 0x36, 0x31, 0x30, 0x30, 0x0E, 0x0D, 0x28, 0x21, 0x1C, 0x16, /* 168 ~ 177 */ | ||
3914 | 0x50, 0x4A, 0x43, 0x40, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, /* 178 ~ 187 */ | ||
3915 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 188 ~ 197 */ | ||
3916 | 0x00, 0x00, 0x7D, 0x14, 0x32, 0x2C, 0x36, 0x4C, 0x43, 0x2C, /* 198 ~ 207 */ | ||
3917 | 0x2E, 0x36, 0x30, 0x6E, /* 208 ~ 211 */ | ||
3918 | }; | ||
3919 | int i; | ||
3920 | |||
3921 | for (i = 0; i < ARRAY_SIZE(glrt_table); i++) { | ||
3922 | rt2800_bbp_write(rt2x00dev, 195, 128 + i); | ||
3923 | rt2800_bbp_write(rt2x00dev, 196, glrt_table[i]); | ||
3924 | } | ||
3925 | }; | ||
3926 | |||
3927 | static void rt2800_init_bbb_early(struct rt2x00_dev *rt2x00dev) | ||
3928 | { | ||
3929 | rt2800_bbp_write(rt2x00dev, 65, 0x2C); | ||
3930 | rt2800_bbp_write(rt2x00dev, 66, 0x38); | ||
3931 | rt2800_bbp_write(rt2x00dev, 68, 0x0B); | ||
3932 | rt2800_bbp_write(rt2x00dev, 69, 0x12); | ||
3933 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); | ||
3934 | rt2800_bbp_write(rt2x00dev, 73, 0x10); | ||
3935 | rt2800_bbp_write(rt2x00dev, 81, 0x37); | ||
3936 | rt2800_bbp_write(rt2x00dev, 82, 0x62); | ||
3937 | rt2800_bbp_write(rt2x00dev, 83, 0x6A); | ||
3938 | rt2800_bbp_write(rt2x00dev, 84, 0x99); | ||
3939 | rt2800_bbp_write(rt2x00dev, 86, 0x00); | ||
3940 | rt2800_bbp_write(rt2x00dev, 91, 0x04); | ||
3941 | rt2800_bbp_write(rt2x00dev, 92, 0x00); | ||
3942 | rt2800_bbp_write(rt2x00dev, 103, 0x00); | ||
3943 | rt2800_bbp_write(rt2x00dev, 105, 0x05); | ||
3944 | rt2800_bbp_write(rt2x00dev, 106, 0x35); | ||
3945 | } | ||
3946 | |||
3947 | static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) | ||
3948 | { | ||
3949 | int ant, div_mode; | ||
3950 | u16 eeprom; | ||
3951 | u8 value; | ||
3952 | |||
3953 | rt2800_init_bbb_early(rt2x00dev); | ||
3954 | |||
3955 | rt2800_bbp_read(rt2x00dev, 105, &value); | ||
3956 | rt2x00_set_field8(&value, BBP105_MLD, | ||
3957 | rt2x00dev->default_ant.rx_chain_num == 2); | ||
3958 | rt2800_bbp_write(rt2x00dev, 105, value); | ||
3959 | |||
3960 | rt2800_bbp4_mac_if_ctrl(rt2x00dev); | ||
3961 | |||
3962 | rt2800_bbp_write(rt2x00dev, 20, 0x06); | ||
3963 | rt2800_bbp_write(rt2x00dev, 31, 0x08); | ||
3964 | rt2800_bbp_write(rt2x00dev, 65, 0x2C); | ||
3965 | rt2800_bbp_write(rt2x00dev, 68, 0xDD); | ||
3966 | rt2800_bbp_write(rt2x00dev, 69, 0x1A); | ||
3967 | rt2800_bbp_write(rt2x00dev, 70, 0x05); | ||
3968 | rt2800_bbp_write(rt2x00dev, 73, 0x13); | ||
3969 | rt2800_bbp_write(rt2x00dev, 74, 0x0F); | ||
3970 | rt2800_bbp_write(rt2x00dev, 75, 0x4F); | ||
3971 | rt2800_bbp_write(rt2x00dev, 76, 0x28); | ||
3972 | rt2800_bbp_write(rt2x00dev, 77, 0x59); | ||
3973 | rt2800_bbp_write(rt2x00dev, 84, 0x9A); | ||
3974 | rt2800_bbp_write(rt2x00dev, 86, 0x38); | ||
3975 | rt2800_bbp_write(rt2x00dev, 88, 0x90); | ||
3976 | rt2800_bbp_write(rt2x00dev, 91, 0x04); | ||
3977 | rt2800_bbp_write(rt2x00dev, 92, 0x02); | ||
3978 | rt2800_bbp_write(rt2x00dev, 95, 0x9a); | ||
3979 | rt2800_bbp_write(rt2x00dev, 98, 0x12); | ||
3980 | rt2800_bbp_write(rt2x00dev, 103, 0xC0); | ||
3981 | rt2800_bbp_write(rt2x00dev, 104, 0x92); | ||
3982 | /* FIXME BBP105 owerwrite */ | ||
3983 | rt2800_bbp_write(rt2x00dev, 105, 0x3C); | ||
3984 | rt2800_bbp_write(rt2x00dev, 106, 0x35); | ||
3985 | rt2800_bbp_write(rt2x00dev, 128, 0x12); | ||
3986 | rt2800_bbp_write(rt2x00dev, 134, 0xD0); | ||
3987 | rt2800_bbp_write(rt2x00dev, 135, 0xF6); | ||
3988 | rt2800_bbp_write(rt2x00dev, 137, 0x0F); | ||
3989 | |||
3990 | /* Initialize GLRT (Generalized Likehood Radio Test) */ | ||
3991 | rt2800_init_bbp_5592_glrt(rt2x00dev); | ||
3992 | |||
3993 | rt2800_bbp4_mac_if_ctrl(rt2x00dev); | ||
3994 | |||
3995 | rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); | ||
3996 | div_mode = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_ANT_DIVERSITY); | ||
3997 | ant = (div_mode == 3) ? 1 : 0; | ||
3998 | rt2800_bbp_read(rt2x00dev, 152, &value); | ||
3999 | if (ant == 0) { | ||
4000 | /* Main antenna */ | ||
4001 | rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 1); | ||
4002 | } else { | ||
4003 | /* Auxiliary antenna */ | ||
4004 | rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 0); | ||
4005 | } | ||
4006 | rt2800_bbp_write(rt2x00dev, 152, value); | ||
4007 | |||
4008 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C)) { | ||
4009 | rt2800_bbp_read(rt2x00dev, 254, &value); | ||
4010 | rt2x00_set_field8(&value, BBP254_BIT7, 1); | ||
4011 | rt2800_bbp_write(rt2x00dev, 254, value); | ||
4012 | } | ||
4013 | |||
4014 | rt2800_init_freq_calibration(rt2x00dev); | ||
4015 | |||
4016 | rt2800_bbp_write(rt2x00dev, 84, 0x19); | ||
4017 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C)) | ||
4018 | rt2800_bbp_write(rt2x00dev, 103, 0xc0); | ||
4019 | } | ||
4020 | |||
3490 | static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) | 4021 | static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) |
3491 | { | 4022 | { |
3492 | unsigned int i; | 4023 | unsigned int i; |
@@ -3498,6 +4029,11 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
3498 | rt2800_wait_bbp_ready(rt2x00dev))) | 4029 | rt2800_wait_bbp_ready(rt2x00dev))) |
3499 | return -EACCES; | 4030 | return -EACCES; |
3500 | 4031 | ||
4032 | if (rt2x00_rt(rt2x00dev, RT5592)) { | ||
4033 | rt2800_init_bbp_5592(rt2x00dev); | ||
4034 | return 0; | ||
4035 | } | ||
4036 | |||
3501 | if (rt2x00_rt(rt2x00dev, RT3352)) { | 4037 | if (rt2x00_rt(rt2x00dev, RT3352)) { |
3502 | rt2800_bbp_write(rt2x00dev, 3, 0x00); | 4038 | rt2800_bbp_write(rt2x00dev, 3, 0x00); |
3503 | rt2800_bbp_write(rt2x00dev, 4, 0x50); | 4039 | rt2800_bbp_write(rt2x00dev, 4, 0x50); |
@@ -3505,11 +4041,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
3505 | 4041 | ||
3506 | if (rt2x00_rt(rt2x00dev, RT3290) || | 4042 | if (rt2x00_rt(rt2x00dev, RT3290) || |
3507 | rt2x00_rt(rt2x00dev, RT5390) || | 4043 | rt2x00_rt(rt2x00dev, RT5390) || |
3508 | rt2x00_rt(rt2x00dev, RT5392)) { | 4044 | rt2x00_rt(rt2x00dev, RT5392)) |
3509 | rt2800_bbp_read(rt2x00dev, 4, &value); | 4045 | rt2800_bbp4_mac_if_ctrl(rt2x00dev); |
3510 | rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1); | ||
3511 | rt2800_bbp_write(rt2x00dev, 4, value); | ||
3512 | } | ||
3513 | 4046 | ||
3514 | if (rt2800_is_305x_soc(rt2x00dev) || | 4047 | if (rt2800_is_305x_soc(rt2x00dev) || |
3515 | rt2x00_rt(rt2x00dev, RT3290) || | 4048 | rt2x00_rt(rt2x00dev, RT3290) || |
@@ -3783,9 +4316,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
3783 | rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 0); | 4316 | rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 0); |
3784 | rt2800_bbp_write(rt2x00dev, 152, value); | 4317 | rt2800_bbp_write(rt2x00dev, 152, value); |
3785 | 4318 | ||
3786 | /* Init frequency calibration */ | 4319 | rt2800_init_freq_calibration(rt2x00dev); |
3787 | rt2800_bbp_write(rt2x00dev, 142, 1); | ||
3788 | rt2800_bbp_write(rt2x00dev, 143, 57); | ||
3789 | } | 4320 | } |
3790 | 4321 | ||
3791 | for (i = 0; i < EEPROM_BBP_SIZE; i++) { | 4322 | for (i = 0; i < EEPROM_BBP_SIZE; i++) { |
@@ -4259,6 +4790,69 @@ static void rt2800_init_rfcsr_5392(struct rt2x00_dev *rt2x00dev) | |||
4259 | rt2800_rfcsr_write(rt2x00dev, 63, 0x07); | 4790 | rt2800_rfcsr_write(rt2x00dev, 63, 0x07); |
4260 | } | 4791 | } |
4261 | 4792 | ||
4793 | static void rt2800_init_rfcsr_5592(struct rt2x00_dev *rt2x00dev) | ||
4794 | { | ||
4795 | u8 reg; | ||
4796 | u16 eeprom; | ||
4797 | |||
4798 | rt2800_rfcsr_write(rt2x00dev, 1, 0x3F); | ||
4799 | rt2800_rfcsr_write(rt2x00dev, 3, 0x08); | ||
4800 | rt2800_rfcsr_write(rt2x00dev, 3, 0x08); | ||
4801 | rt2800_rfcsr_write(rt2x00dev, 5, 0x10); | ||
4802 | rt2800_rfcsr_write(rt2x00dev, 6, 0xE4); | ||
4803 | rt2800_rfcsr_write(rt2x00dev, 7, 0x00); | ||
4804 | rt2800_rfcsr_write(rt2x00dev, 14, 0x00); | ||
4805 | rt2800_rfcsr_write(rt2x00dev, 15, 0x00); | ||
4806 | rt2800_rfcsr_write(rt2x00dev, 16, 0x00); | ||
4807 | rt2800_rfcsr_write(rt2x00dev, 18, 0x03); | ||
4808 | rt2800_rfcsr_write(rt2x00dev, 19, 0x4D); | ||
4809 | rt2800_rfcsr_write(rt2x00dev, 20, 0x10); | ||
4810 | rt2800_rfcsr_write(rt2x00dev, 21, 0x8D); | ||
4811 | rt2800_rfcsr_write(rt2x00dev, 26, 0x82); | ||
4812 | rt2800_rfcsr_write(rt2x00dev, 28, 0x00); | ||
4813 | rt2800_rfcsr_write(rt2x00dev, 29, 0x10); | ||
4814 | rt2800_rfcsr_write(rt2x00dev, 33, 0xC0); | ||
4815 | rt2800_rfcsr_write(rt2x00dev, 34, 0x07); | ||
4816 | rt2800_rfcsr_write(rt2x00dev, 35, 0x12); | ||
4817 | rt2800_rfcsr_write(rt2x00dev, 47, 0x0C); | ||
4818 | rt2800_rfcsr_write(rt2x00dev, 53, 0x22); | ||
4819 | rt2800_rfcsr_write(rt2x00dev, 63, 0x07); | ||
4820 | |||
4821 | rt2800_rfcsr_write(rt2x00dev, 2, 0x80); | ||
4822 | msleep(1); | ||
4823 | |||
4824 | rt2800_adjust_freq_offset(rt2x00dev); | ||
4825 | |||
4826 | rt2800_bbp_read(rt2x00dev, 138, ®); | ||
4827 | |||
4828 | /* Turn off unused DAC1 and ADC1 to reduce power consumption */ | ||
4829 | rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); | ||
4830 | if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1) | ||
4831 | rt2x00_set_field8(®, BBP138_RX_ADC1, 0); | ||
4832 | if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1) | ||
4833 | rt2x00_set_field8(®, BBP138_TX_DAC1, 1); | ||
4834 | |||
4835 | rt2800_bbp_write(rt2x00dev, 138, reg); | ||
4836 | |||
4837 | /* Enable DC filter */ | ||
4838 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C)) | ||
4839 | rt2800_bbp_write(rt2x00dev, 103, 0xc0); | ||
4840 | |||
4841 | rt2800_rfcsr_read(rt2x00dev, 38, ®); | ||
4842 | rt2x00_set_field8(®, RFCSR38_RX_LO1_EN, 0); | ||
4843 | rt2800_rfcsr_write(rt2x00dev, 38, reg); | ||
4844 | |||
4845 | rt2800_rfcsr_read(rt2x00dev, 39, ®); | ||
4846 | rt2x00_set_field8(®, RFCSR39_RX_LO2_EN, 0); | ||
4847 | rt2800_rfcsr_write(rt2x00dev, 39, reg); | ||
4848 | |||
4849 | rt2800_bbp4_mac_if_ctrl(rt2x00dev); | ||
4850 | |||
4851 | rt2800_rfcsr_read(rt2x00dev, 30, ®); | ||
4852 | rt2x00_set_field8(®, RFCSR30_RX_VCM, 2); | ||
4853 | rt2800_rfcsr_write(rt2x00dev, 30, reg); | ||
4854 | } | ||
4855 | |||
4262 | static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | 4856 | static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) |
4263 | { | 4857 | { |
4264 | struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; | 4858 | struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; |
@@ -4276,6 +4870,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
4276 | !rt2x00_rt(rt2x00dev, RT3572) && | 4870 | !rt2x00_rt(rt2x00dev, RT3572) && |
4277 | !rt2x00_rt(rt2x00dev, RT5390) && | 4871 | !rt2x00_rt(rt2x00dev, RT5390) && |
4278 | !rt2x00_rt(rt2x00dev, RT5392) && | 4872 | !rt2x00_rt(rt2x00dev, RT5392) && |
4873 | !rt2x00_rt(rt2x00dev, RT5392) && | ||
4874 | !rt2x00_rt(rt2x00dev, RT5592) && | ||
4279 | !rt2800_is_305x_soc(rt2x00dev)) | 4875 | !rt2800_is_305x_soc(rt2x00dev)) |
4280 | return 0; | 4876 | return 0; |
4281 | 4877 | ||
@@ -4330,6 +4926,9 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
4330 | case RT5392: | 4926 | case RT5392: |
4331 | rt2800_init_rfcsr_5392(rt2x00dev); | 4927 | rt2800_init_rfcsr_5392(rt2x00dev); |
4332 | break; | 4928 | break; |
4929 | case RT5592: | ||
4930 | rt2800_init_rfcsr_5592(rt2x00dev); | ||
4931 | return 0; | ||
4333 | } | 4932 | } |
4334 | 4933 | ||
4335 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) { | 4934 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) { |
@@ -4427,7 +5026,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
4427 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) || | 5026 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) || |
4428 | rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || | 5027 | rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || |
4429 | rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || | 5028 | rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || |
4430 | rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) | 5029 | rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E) || |
5030 | rt2x00_rt_rev_lt(rt2x00dev, RT5592, REV_RT5592C)) | ||
4431 | rt2800_rfcsr_write(rt2x00dev, 27, 0x03); | 5031 | rt2800_rfcsr_write(rt2x00dev, 27, 0x03); |
4432 | 5032 | ||
4433 | rt2800_register_read(rt2x00dev, OPT_14_CSR, ®); | 5033 | rt2800_register_read(rt2x00dev, OPT_14_CSR, ®); |
@@ -4451,7 +5051,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
4451 | rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); | 5051 | rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); |
4452 | } | 5052 | } |
4453 | 5053 | ||
4454 | if (rt2x00_rt(rt2x00dev, RT3090)) { | 5054 | if (rt2x00_rt(rt2x00dev, RT3090) || |
5055 | rt2x00_rt(rt2x00dev, RT5592)) { | ||
4455 | rt2800_bbp_read(rt2x00dev, 138, &bbp); | 5056 | rt2800_bbp_read(rt2x00dev, 138, &bbp); |
4456 | 5057 | ||
4457 | /* Turn off unused DAC1 and ADC1 to reduce power consumption */ | 5058 | /* Turn off unused DAC1 and ADC1 to reduce power consumption */ |
@@ -4507,7 +5108,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
4507 | } | 5108 | } |
4508 | 5109 | ||
4509 | if (rt2x00_rt(rt2x00dev, RT5390) || | 5110 | if (rt2x00_rt(rt2x00dev, RT5390) || |
4510 | rt2x00_rt(rt2x00dev, RT5392)) { | 5111 | rt2x00_rt(rt2x00dev, RT5392) || |
5112 | rt2x00_rt(rt2x00dev, RT5592)) { | ||
4511 | rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr); | 5113 | rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr); |
4512 | rt2x00_set_field8(&rfcsr, RFCSR38_RX_LO1_EN, 0); | 5114 | rt2x00_set_field8(&rfcsr, RFCSR38_RX_LO1_EN, 0); |
4513 | rt2800_rfcsr_write(rt2x00dev, 38, rfcsr); | 5115 | rt2800_rfcsr_write(rt2x00dev, 38, rfcsr); |
@@ -4533,15 +5135,23 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev) | |||
4533 | * Initialize all registers. | 5135 | * Initialize all registers. |
4534 | */ | 5136 | */ |
4535 | if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) || | 5137 | if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) || |
4536 | rt2800_init_registers(rt2x00dev) || | 5138 | rt2800_init_registers(rt2x00dev))) |
4537 | rt2800_init_bbp(rt2x00dev) || | ||
4538 | rt2800_init_rfcsr(rt2x00dev))) | ||
4539 | return -EIO; | 5139 | return -EIO; |
4540 | 5140 | ||
4541 | /* | 5141 | /* |
4542 | * Send signal to firmware during boot time. | 5142 | * Send signal to firmware during boot time. |
4543 | */ | 5143 | */ |
4544 | rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); | 5144 | rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); |
5145 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); | ||
5146 | if (rt2x00_is_usb(rt2x00dev)) { | ||
5147 | rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0); | ||
5148 | rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); | ||
5149 | } | ||
5150 | msleep(1); | ||
5151 | |||
5152 | if (unlikely(rt2800_init_bbp(rt2x00dev) || | ||
5153 | rt2800_init_rfcsr(rt2x00dev))) | ||
5154 | return -EIO; | ||
4545 | 5155 | ||
4546 | if (rt2x00_is_usb(rt2x00dev) && | 5156 | if (rt2x00_is_usb(rt2x00dev) && |
4547 | (rt2x00_rt(rt2x00dev, RT3070) || | 5157 | (rt2x00_rt(rt2x00dev, RT3070) || |
@@ -4863,6 +5473,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
4863 | case RT3572: | 5473 | case RT3572: |
4864 | case RT5390: | 5474 | case RT5390: |
4865 | case RT5392: | 5475 | case RT5392: |
5476 | case RT5592: | ||
4866 | break; | 5477 | break; |
4867 | default: | 5478 | default: |
4868 | ERROR(rt2x00dev, "Invalid RT chipset 0x%04x detected.\n", rt2x00dev->chip.rt); | 5479 | ERROR(rt2x00dev, "Invalid RT chipset 0x%04x detected.\n", rt2x00dev->chip.rt); |
@@ -4887,6 +5498,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
4887 | case RF5372: | 5498 | case RF5372: |
4888 | case RF5390: | 5499 | case RF5390: |
4889 | case RF5392: | 5500 | case RF5392: |
5501 | case RF5592: | ||
4890 | break; | 5502 | break; |
4891 | default: | 5503 | default: |
4892 | ERROR(rt2x00dev, "Invalid RF chipset 0x%04x detected.\n", | 5504 | ERROR(rt2x00dev, "Invalid RF chipset 0x%04x detected.\n", |
@@ -5122,6 +5734,138 @@ static const struct rf_channel rf_vals_3x[] = { | |||
5122 | {173, 0x61, 0, 9}, | 5734 | {173, 0x61, 0, 9}, |
5123 | }; | 5735 | }; |
5124 | 5736 | ||
5737 | static const struct rf_channel rf_vals_5592_xtal20[] = { | ||
5738 | /* Channel, N, K, mod, R */ | ||
5739 | {1, 482, 4, 10, 3}, | ||
5740 | {2, 483, 4, 10, 3}, | ||
5741 | {3, 484, 4, 10, 3}, | ||
5742 | {4, 485, 4, 10, 3}, | ||
5743 | {5, 486, 4, 10, 3}, | ||
5744 | {6, 487, 4, 10, 3}, | ||
5745 | {7, 488, 4, 10, 3}, | ||
5746 | {8, 489, 4, 10, 3}, | ||
5747 | {9, 490, 4, 10, 3}, | ||
5748 | {10, 491, 4, 10, 3}, | ||
5749 | {11, 492, 4, 10, 3}, | ||
5750 | {12, 493, 4, 10, 3}, | ||
5751 | {13, 494, 4, 10, 3}, | ||
5752 | {14, 496, 8, 10, 3}, | ||
5753 | {36, 172, 8, 12, 1}, | ||
5754 | {38, 173, 0, 12, 1}, | ||
5755 | {40, 173, 4, 12, 1}, | ||
5756 | {42, 173, 8, 12, 1}, | ||
5757 | {44, 174, 0, 12, 1}, | ||
5758 | {46, 174, 4, 12, 1}, | ||
5759 | {48, 174, 8, 12, 1}, | ||
5760 | {50, 175, 0, 12, 1}, | ||
5761 | {52, 175, 4, 12, 1}, | ||
5762 | {54, 175, 8, 12, 1}, | ||
5763 | {56, 176, 0, 12, 1}, | ||
5764 | {58, 176, 4, 12, 1}, | ||
5765 | {60, 176, 8, 12, 1}, | ||
5766 | {62, 177, 0, 12, 1}, | ||
5767 | {64, 177, 4, 12, 1}, | ||
5768 | {100, 183, 4, 12, 1}, | ||
5769 | {102, 183, 8, 12, 1}, | ||
5770 | {104, 184, 0, 12, 1}, | ||
5771 | {106, 184, 4, 12, 1}, | ||
5772 | {108, 184, 8, 12, 1}, | ||
5773 | {110, 185, 0, 12, 1}, | ||
5774 | {112, 185, 4, 12, 1}, | ||
5775 | {114, 185, 8, 12, 1}, | ||
5776 | {116, 186, 0, 12, 1}, | ||
5777 | {118, 186, 4, 12, 1}, | ||
5778 | {120, 186, 8, 12, 1}, | ||
5779 | {122, 187, 0, 12, 1}, | ||
5780 | {124, 187, 4, 12, 1}, | ||
5781 | {126, 187, 8, 12, 1}, | ||
5782 | {128, 188, 0, 12, 1}, | ||
5783 | {130, 188, 4, 12, 1}, | ||
5784 | {132, 188, 8, 12, 1}, | ||
5785 | {134, 189, 0, 12, 1}, | ||
5786 | {136, 189, 4, 12, 1}, | ||
5787 | {138, 189, 8, 12, 1}, | ||
5788 | {140, 190, 0, 12, 1}, | ||
5789 | {149, 191, 6, 12, 1}, | ||
5790 | {151, 191, 10, 12, 1}, | ||
5791 | {153, 192, 2, 12, 1}, | ||
5792 | {155, 192, 6, 12, 1}, | ||
5793 | {157, 192, 10, 12, 1}, | ||
5794 | {159, 193, 2, 12, 1}, | ||
5795 | {161, 193, 6, 12, 1}, | ||
5796 | {165, 194, 2, 12, 1}, | ||
5797 | {184, 164, 0, 12, 1}, | ||
5798 | {188, 164, 4, 12, 1}, | ||
5799 | {192, 165, 8, 12, 1}, | ||
5800 | {196, 166, 0, 12, 1}, | ||
5801 | }; | ||
5802 | |||
5803 | static const struct rf_channel rf_vals_5592_xtal40[] = { | ||
5804 | /* Channel, N, K, mod, R */ | ||
5805 | {1, 241, 2, 10, 3}, | ||
5806 | {2, 241, 7, 10, 3}, | ||
5807 | {3, 242, 2, 10, 3}, | ||
5808 | {4, 242, 7, 10, 3}, | ||
5809 | {5, 243, 2, 10, 3}, | ||
5810 | {6, 243, 7, 10, 3}, | ||
5811 | {7, 244, 2, 10, 3}, | ||
5812 | {8, 244, 7, 10, 3}, | ||
5813 | {9, 245, 2, 10, 3}, | ||
5814 | {10, 245, 7, 10, 3}, | ||
5815 | {11, 246, 2, 10, 3}, | ||
5816 | {12, 246, 7, 10, 3}, | ||
5817 | {13, 247, 2, 10, 3}, | ||
5818 | {14, 248, 4, 10, 3}, | ||
5819 | {36, 86, 4, 12, 1}, | ||
5820 | {38, 86, 6, 12, 1}, | ||
5821 | {40, 86, 8, 12, 1}, | ||
5822 | {42, 86, 10, 12, 1}, | ||
5823 | {44, 87, 0, 12, 1}, | ||
5824 | {46, 87, 2, 12, 1}, | ||
5825 | {48, 87, 4, 12, 1}, | ||
5826 | {50, 87, 6, 12, 1}, | ||
5827 | {52, 87, 8, 12, 1}, | ||
5828 | {54, 87, 10, 12, 1}, | ||
5829 | {56, 88, 0, 12, 1}, | ||
5830 | {58, 88, 2, 12, 1}, | ||
5831 | {60, 88, 4, 12, 1}, | ||
5832 | {62, 88, 6, 12, 1}, | ||
5833 | {64, 88, 8, 12, 1}, | ||
5834 | {100, 91, 8, 12, 1}, | ||
5835 | {102, 91, 10, 12, 1}, | ||
5836 | {104, 92, 0, 12, 1}, | ||
5837 | {106, 92, 2, 12, 1}, | ||
5838 | {108, 92, 4, 12, 1}, | ||
5839 | {110, 92, 6, 12, 1}, | ||
5840 | {112, 92, 8, 12, 1}, | ||
5841 | {114, 92, 10, 12, 1}, | ||
5842 | {116, 93, 0, 12, 1}, | ||
5843 | {118, 93, 2, 12, 1}, | ||
5844 | {120, 93, 4, 12, 1}, | ||
5845 | {122, 93, 6, 12, 1}, | ||
5846 | {124, 93, 8, 12, 1}, | ||
5847 | {126, 93, 10, 12, 1}, | ||
5848 | {128, 94, 0, 12, 1}, | ||
5849 | {130, 94, 2, 12, 1}, | ||
5850 | {132, 94, 4, 12, 1}, | ||
5851 | {134, 94, 6, 12, 1}, | ||
5852 | {136, 94, 8, 12, 1}, | ||
5853 | {138, 94, 10, 12, 1}, | ||
5854 | {140, 95, 0, 12, 1}, | ||
5855 | {149, 95, 9, 12, 1}, | ||
5856 | {151, 95, 11, 12, 1}, | ||
5857 | {153, 96, 1, 12, 1}, | ||
5858 | {155, 96, 3, 12, 1}, | ||
5859 | {157, 96, 5, 12, 1}, | ||
5860 | {159, 96, 7, 12, 1}, | ||
5861 | {161, 96, 9, 12, 1}, | ||
5862 | {165, 97, 1, 12, 1}, | ||
5863 | {184, 82, 0, 12, 1}, | ||
5864 | {188, 82, 4, 12, 1}, | ||
5865 | {192, 82, 8, 12, 1}, | ||
5866 | {196, 83, 0, 12, 1}, | ||
5867 | }; | ||
5868 | |||
5125 | static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | 5869 | static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) |
5126 | { | 5870 | { |
5127 | struct hw_mode_spec *spec = &rt2x00dev->spec; | 5871 | struct hw_mode_spec *spec = &rt2x00dev->spec; |
@@ -5130,6 +5874,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
5130 | char *default_power2; | 5874 | char *default_power2; |
5131 | unsigned int i; | 5875 | unsigned int i; |
5132 | u16 eeprom; | 5876 | u16 eeprom; |
5877 | u32 reg; | ||
5133 | 5878 | ||
5134 | /* | 5879 | /* |
5135 | * Disable powersaving as default on PCI devices. | 5880 | * Disable powersaving as default on PCI devices. |
@@ -5211,8 +5956,22 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
5211 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 5956 | spec->supported_bands |= SUPPORT_BAND_5GHZ; |
5212 | spec->num_channels = ARRAY_SIZE(rf_vals_3x); | 5957 | spec->num_channels = ARRAY_SIZE(rf_vals_3x); |
5213 | spec->channels = rf_vals_3x; | 5958 | spec->channels = rf_vals_3x; |
5959 | } else if (rt2x00_rf(rt2x00dev, RF5592)) { | ||
5960 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | ||
5961 | |||
5962 | rt2800_register_read(rt2x00dev, MAC_DEBUG_INDEX, ®); | ||
5963 | if (rt2x00_get_field32(reg, MAC_DEBUG_INDEX_XTAL)) { | ||
5964 | spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal40); | ||
5965 | spec->channels = rf_vals_5592_xtal40; | ||
5966 | } else { | ||
5967 | spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal20); | ||
5968 | spec->channels = rf_vals_5592_xtal20; | ||
5969 | } | ||
5214 | } | 5970 | } |
5215 | 5971 | ||
5972 | if (WARN_ON_ONCE(!spec->channels)) | ||
5973 | return -ENODEV; | ||
5974 | |||
5216 | /* | 5975 | /* |
5217 | * Initialize HT information. | 5976 | * Initialize HT information. |
5218 | */ | 5977 | */ |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 48a01aa21f1c..f732ded8f1ba 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -89,7 +89,7 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) | |||
89 | rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); | 89 | rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); |
90 | } | 90 | } |
91 | 91 | ||
92 | #if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) | 92 | #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X) |
93 | static int rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) | 93 | static int rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) |
94 | { | 94 | { |
95 | void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE); | 95 | void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE); |
@@ -107,7 +107,7 @@ static inline int rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) | |||
107 | { | 107 | { |
108 | return -ENOMEM; | 108 | return -ENOMEM; |
109 | } | 109 | } |
110 | #endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */ | 110 | #endif /* CONFIG_SOC_RT288X || CONFIG_SOC_RT305X */ |
111 | 111 | ||
112 | #ifdef CONFIG_PCI | 112 | #ifdef CONFIG_PCI |
113 | static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) | 113 | static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) |
@@ -729,6 +729,11 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, | |||
729 | * Process the RXWI structure that is at the start of the buffer. | 729 | * Process the RXWI structure that is at the start of the buffer. |
730 | */ | 730 | */ |
731 | rt2800_process_rxwi(entry, rxdesc); | 731 | rt2800_process_rxwi(entry, rxdesc); |
732 | |||
733 | /* | ||
734 | * Remove RXWI descriptor from start of buffer. | ||
735 | */ | ||
736 | skb_pull(entry->skb, RXWI_DESC_SIZE); | ||
732 | } | 737 | } |
733 | 738 | ||
734 | /* | 739 | /* |
@@ -742,10 +747,90 @@ static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev) | |||
742 | rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); | 747 | rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); |
743 | } | 748 | } |
744 | 749 | ||
750 | static bool rt2800pci_txdone_entry_check(struct queue_entry *entry, u32 status) | ||
751 | { | ||
752 | __le32 *txwi; | ||
753 | u32 word; | ||
754 | int wcid, tx_wcid; | ||
755 | |||
756 | wcid = rt2x00_get_field32(status, TX_STA_FIFO_WCID); | ||
757 | |||
758 | txwi = rt2800_drv_get_txwi(entry); | ||
759 | rt2x00_desc_read(txwi, 1, &word); | ||
760 | tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); | ||
761 | |||
762 | return (tx_wcid == wcid); | ||
763 | } | ||
764 | |||
765 | static bool rt2800pci_txdone_find_entry(struct queue_entry *entry, void *data) | ||
766 | { | ||
767 | u32 status = *(u32 *)data; | ||
768 | |||
769 | /* | ||
770 | * rt2800pci hardware might reorder frames when exchanging traffic | ||
771 | * with multiple BA enabled STAs. | ||
772 | * | ||
773 | * For example, a tx queue | ||
774 | * [ STA1 | STA2 | STA1 | STA2 ] | ||
775 | * can result in tx status reports | ||
776 | * [ STA1 | STA1 | STA2 | STA2 ] | ||
777 | * when the hw decides to aggregate the frames for STA1 into one AMPDU. | ||
778 | * | ||
779 | * To mitigate this effect, associate the tx status to the first frame | ||
780 | * in the tx queue with a matching wcid. | ||
781 | */ | ||
782 | if (rt2800pci_txdone_entry_check(entry, status) && | ||
783 | !test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) { | ||
784 | /* | ||
785 | * Got a matching frame, associate the tx status with | ||
786 | * the frame | ||
787 | */ | ||
788 | entry->status = status; | ||
789 | set_bit(ENTRY_DATA_STATUS_SET, &entry->flags); | ||
790 | return true; | ||
791 | } | ||
792 | |||
793 | /* Check the next frame */ | ||
794 | return false; | ||
795 | } | ||
796 | |||
797 | static bool rt2800pci_txdone_match_first(struct queue_entry *entry, void *data) | ||
798 | { | ||
799 | u32 status = *(u32 *)data; | ||
800 | |||
801 | /* | ||
802 | * Find the first frame without tx status and assign this status to it | ||
803 | * regardless if it matches or not. | ||
804 | */ | ||
805 | if (!test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) { | ||
806 | /* | ||
807 | * Got a matching frame, associate the tx status with | ||
808 | * the frame | ||
809 | */ | ||
810 | entry->status = status; | ||
811 | set_bit(ENTRY_DATA_STATUS_SET, &entry->flags); | ||
812 | return true; | ||
813 | } | ||
814 | |||
815 | /* Check the next frame */ | ||
816 | return false; | ||
817 | } | ||
818 | static bool rt2800pci_txdone_release_entries(struct queue_entry *entry, | ||
819 | void *data) | ||
820 | { | ||
821 | if (test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) { | ||
822 | rt2800_txdone_entry(entry, entry->status, | ||
823 | rt2800pci_get_txwi(entry)); | ||
824 | return false; | ||
825 | } | ||
826 | |||
827 | /* No more frames to release */ | ||
828 | return true; | ||
829 | } | ||
830 | |||
745 | static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) | 831 | static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) |
746 | { | 832 | { |
747 | struct data_queue *queue; | 833 | struct data_queue *queue; |
748 | struct queue_entry *entry; | ||
749 | u32 status; | 834 | u32 status; |
750 | u8 qid; | 835 | u8 qid; |
751 | int max_tx_done = 16; | 836 | int max_tx_done = 16; |
@@ -783,8 +868,33 @@ static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
783 | break; | 868 | break; |
784 | } | 869 | } |
785 | 870 | ||
786 | entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | 871 | /* |
787 | rt2800_txdone_entry(entry, status, rt2800pci_get_txwi(entry)); | 872 | * Let's associate this tx status with the first |
873 | * matching frame. | ||
874 | */ | ||
875 | if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, | ||
876 | Q_INDEX, &status, | ||
877 | rt2800pci_txdone_find_entry)) { | ||
878 | /* | ||
879 | * We cannot match the tx status to any frame, so just | ||
880 | * use the first one. | ||
881 | */ | ||
882 | if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, | ||
883 | Q_INDEX, &status, | ||
884 | rt2800pci_txdone_match_first)) { | ||
885 | WARNING(rt2x00dev, "No frame found for TX " | ||
886 | "status on queue %u, dropping\n", | ||
887 | qid); | ||
888 | break; | ||
889 | } | ||
890 | } | ||
891 | |||
892 | /* | ||
893 | * Release all frames with a valid tx status. | ||
894 | */ | ||
895 | rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, | ||
896 | Q_INDEX, NULL, | ||
897 | rt2800pci_txdone_release_entries); | ||
788 | 898 | ||
789 | if (--max_tx_done == 0) | 899 | if (--max_tx_done == 0) |
790 | break; | 900 | break; |
@@ -1177,7 +1287,7 @@ MODULE_DEVICE_TABLE(pci, rt2800pci_device_table); | |||
1177 | #endif /* CONFIG_PCI */ | 1287 | #endif /* CONFIG_PCI */ |
1178 | MODULE_LICENSE("GPL"); | 1288 | MODULE_LICENSE("GPL"); |
1179 | 1289 | ||
1180 | #if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) | 1290 | #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X) |
1181 | static int rt2800soc_probe(struct platform_device *pdev) | 1291 | static int rt2800soc_probe(struct platform_device *pdev) |
1182 | { | 1292 | { |
1183 | return rt2x00soc_probe(pdev, &rt2800pci_ops); | 1293 | return rt2x00soc_probe(pdev, &rt2800pci_ops); |
@@ -1194,7 +1304,7 @@ static struct platform_driver rt2800soc_driver = { | |||
1194 | .suspend = rt2x00soc_suspend, | 1304 | .suspend = rt2x00soc_suspend, |
1195 | .resume = rt2x00soc_resume, | 1305 | .resume = rt2x00soc_resume, |
1196 | }; | 1306 | }; |
1197 | #endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */ | 1307 | #endif /* CONFIG_SOC_RT288X || CONFIG_SOC_RT305X */ |
1198 | 1308 | ||
1199 | #ifdef CONFIG_PCI | 1309 | #ifdef CONFIG_PCI |
1200 | static int rt2800pci_probe(struct pci_dev *pci_dev, | 1310 | static int rt2800pci_probe(struct pci_dev *pci_dev, |
@@ -1217,7 +1327,7 @@ static int __init rt2800pci_init(void) | |||
1217 | { | 1327 | { |
1218 | int ret = 0; | 1328 | int ret = 0; |
1219 | 1329 | ||
1220 | #if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) | 1330 | #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X) |
1221 | ret = platform_driver_register(&rt2800soc_driver); | 1331 | ret = platform_driver_register(&rt2800soc_driver); |
1222 | if (ret) | 1332 | if (ret) |
1223 | return ret; | 1333 | return ret; |
@@ -1225,7 +1335,7 @@ static int __init rt2800pci_init(void) | |||
1225 | #ifdef CONFIG_PCI | 1335 | #ifdef CONFIG_PCI |
1226 | ret = pci_register_driver(&rt2800pci_driver); | 1336 | ret = pci_register_driver(&rt2800pci_driver); |
1227 | if (ret) { | 1337 | if (ret) { |
1228 | #if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) | 1338 | #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X) |
1229 | platform_driver_unregister(&rt2800soc_driver); | 1339 | platform_driver_unregister(&rt2800soc_driver); |
1230 | #endif | 1340 | #endif |
1231 | return ret; | 1341 | return ret; |
@@ -1240,7 +1350,7 @@ static void __exit rt2800pci_exit(void) | |||
1240 | #ifdef CONFIG_PCI | 1350 | #ifdef CONFIG_PCI |
1241 | pci_unregister_driver(&rt2800pci_driver); | 1351 | pci_unregister_driver(&rt2800pci_driver); |
1242 | #endif | 1352 | #endif |
1243 | #if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) | 1353 | #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X) |
1244 | platform_driver_unregister(&rt2800soc_driver); | 1354 | platform_driver_unregister(&rt2800soc_driver); |
1245 | #endif | 1355 | #endif |
1246 | } | 1356 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 098613ed93fb..f32282009146 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -485,7 +485,7 @@ static void rt2800usb_write_tx_desc(struct queue_entry *entry, | |||
485 | */ | 485 | */ |
486 | skbdesc->flags |= SKBDESC_DESC_IN_SKB; | 486 | skbdesc->flags |= SKBDESC_DESC_IN_SKB; |
487 | skbdesc->desc = txi; | 487 | skbdesc->desc = txi; |
488 | skbdesc->desc_len = TXINFO_DESC_SIZE + TXWI_DESC_SIZE; | 488 | skbdesc->desc_len = entry->queue->desc_size; |
489 | } | 489 | } |
490 | 490 | ||
491 | /* | 491 | /* |
@@ -730,6 +730,11 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, | |||
730 | * Process the RXWI structure. | 730 | * Process the RXWI structure. |
731 | */ | 731 | */ |
732 | rt2800_process_rxwi(entry, rxdesc); | 732 | rt2800_process_rxwi(entry, rxdesc); |
733 | |||
734 | /* | ||
735 | * Remove RXWI descriptor from start of buffer. | ||
736 | */ | ||
737 | skb_pull(entry->skb, entry->queue->desc_size - RXINFO_DESC_SIZE); | ||
733 | } | 738 | } |
734 | 739 | ||
735 | /* | 740 | /* |
@@ -890,6 +895,47 @@ static const struct rt2x00_ops rt2800usb_ops = { | |||
890 | #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ | 895 | #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ |
891 | }; | 896 | }; |
892 | 897 | ||
898 | static const struct data_queue_desc rt2800usb_queue_rx_5592 = { | ||
899 | .entry_num = 128, | ||
900 | .data_size = AGGREGATION_SIZE, | ||
901 | .desc_size = RXINFO_DESC_SIZE + RXWI_DESC_SIZE_5592, | ||
902 | .priv_size = sizeof(struct queue_entry_priv_usb), | ||
903 | }; | ||
904 | |||
905 | static const struct data_queue_desc rt2800usb_queue_tx_5592 = { | ||
906 | .entry_num = 16, | ||
907 | .data_size = AGGREGATION_SIZE, | ||
908 | .desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE_5592, | ||
909 | .priv_size = sizeof(struct queue_entry_priv_usb), | ||
910 | }; | ||
911 | |||
912 | static const struct data_queue_desc rt2800usb_queue_bcn_5592 = { | ||
913 | .entry_num = 8, | ||
914 | .data_size = MGMT_FRAME_SIZE, | ||
915 | .desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE_5592, | ||
916 | .priv_size = sizeof(struct queue_entry_priv_usb), | ||
917 | }; | ||
918 | |||
919 | |||
920 | static const struct rt2x00_ops rt2800usb_ops_5592 = { | ||
921 | .name = KBUILD_MODNAME, | ||
922 | .drv_data_size = sizeof(struct rt2800_drv_data), | ||
923 | .max_ap_intf = 8, | ||
924 | .eeprom_size = EEPROM_SIZE, | ||
925 | .rf_size = RF_SIZE, | ||
926 | .tx_queues = NUM_TX_QUEUES, | ||
927 | .extra_tx_headroom = TXINFO_DESC_SIZE + TXWI_DESC_SIZE_5592, | ||
928 | .rx = &rt2800usb_queue_rx_5592, | ||
929 | .tx = &rt2800usb_queue_tx_5592, | ||
930 | .bcn = &rt2800usb_queue_bcn_5592, | ||
931 | .lib = &rt2800usb_rt2x00_ops, | ||
932 | .drv = &rt2800usb_rt2800_ops, | ||
933 | .hw = &rt2800usb_mac80211_ops, | ||
934 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS | ||
935 | .debugfs = &rt2800_rt2x00debug, | ||
936 | #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ | ||
937 | }; | ||
938 | |||
893 | /* | 939 | /* |
894 | * rt2800usb module information. | 940 | * rt2800usb module information. |
895 | */ | 941 | */ |
@@ -1200,6 +1246,18 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
1200 | { USB_DEVICE(0x148f, 0x5370) }, | 1246 | { USB_DEVICE(0x148f, 0x5370) }, |
1201 | { USB_DEVICE(0x148f, 0x5372) }, | 1247 | { USB_DEVICE(0x148f, 0x5372) }, |
1202 | #endif | 1248 | #endif |
1249 | #ifdef CONFIG_RT2800USB_RT55XX | ||
1250 | /* Arcadyan */ | ||
1251 | { USB_DEVICE(0x043e, 0x7a32), .driver_info = 5592 }, | ||
1252 | /* AVM GmbH */ | ||
1253 | { USB_DEVICE(0x057c, 0x8501), .driver_info = 5592 }, | ||
1254 | /* D-Link DWA-160-B2 */ | ||
1255 | { USB_DEVICE(0x2001, 0x3c1a), .driver_info = 5592 }, | ||
1256 | /* Proware */ | ||
1257 | { USB_DEVICE(0x043e, 0x7a13), .driver_info = 5592 }, | ||
1258 | /* Ralink */ | ||
1259 | { USB_DEVICE(0x148f, 0x5572), .driver_info = 5592 }, | ||
1260 | #endif | ||
1203 | #ifdef CONFIG_RT2800USB_UNKNOWN | 1261 | #ifdef CONFIG_RT2800USB_UNKNOWN |
1204 | /* | 1262 | /* |
1205 | * Unclear what kind of devices these are (they aren't supported by the | 1263 | * Unclear what kind of devices these are (they aren't supported by the |
@@ -1303,6 +1361,9 @@ MODULE_LICENSE("GPL"); | |||
1303 | static int rt2800usb_probe(struct usb_interface *usb_intf, | 1361 | static int rt2800usb_probe(struct usb_interface *usb_intf, |
1304 | const struct usb_device_id *id) | 1362 | const struct usb_device_id *id) |
1305 | { | 1363 | { |
1364 | if (id->driver_info == 5592) | ||
1365 | return rt2x00usb_probe(usb_intf, &rt2800usb_ops_5592); | ||
1366 | |||
1306 | return rt2x00usb_probe(usb_intf, &rt2800usb_ops); | 1367 | return rt2x00usb_probe(usb_intf, &rt2800usb_ops); |
1307 | } | 1368 | } |
1308 | 1369 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 086abb403a4f..51922cc179de 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -193,6 +193,7 @@ struct rt2x00_chip { | |||
193 | #define RT3883 0x3883 /* WSOC */ | 193 | #define RT3883 0x3883 /* WSOC */ |
194 | #define RT5390 0x5390 /* 2.4GHz */ | 194 | #define RT5390 0x5390 /* 2.4GHz */ |
195 | #define RT5392 0x5392 /* 2.4GHz */ | 195 | #define RT5392 0x5392 /* 2.4GHz */ |
196 | #define RT5592 0x5592 | ||
196 | 197 | ||
197 | u16 rf; | 198 | u16 rf; |
198 | u16 rev; | 199 | u16 rev; |
@@ -1064,8 +1065,7 @@ static inline void rt2x00_rf_write(struct rt2x00_dev *rt2x00dev, | |||
1064 | } | 1065 | } |
1065 | 1066 | ||
1066 | /* | 1067 | /* |
1067 | * Generic EEPROM access. | 1068 | * Generic EEPROM access. The EEPROM is being accessed by word or byte index. |
1068 | * The EEPROM is being accessed by word index. | ||
1069 | */ | 1069 | */ |
1070 | static inline void *rt2x00_eeprom_addr(struct rt2x00_dev *rt2x00dev, | 1070 | static inline void *rt2x00_eeprom_addr(struct rt2x00_dev *rt2x00dev, |
1071 | const unsigned int word) | 1071 | const unsigned int word) |
@@ -1085,6 +1085,12 @@ static inline void rt2x00_eeprom_write(struct rt2x00_dev *rt2x00dev, | |||
1085 | rt2x00dev->eeprom[word] = cpu_to_le16(data); | 1085 | rt2x00dev->eeprom[word] = cpu_to_le16(data); |
1086 | } | 1086 | } |
1087 | 1087 | ||
1088 | static inline u8 rt2x00_eeprom_byte(struct rt2x00_dev *rt2x00dev, | ||
1089 | const unsigned int byte) | ||
1090 | { | ||
1091 | return *(((u8 *)rt2x00dev->eeprom) + byte); | ||
1092 | } | ||
1093 | |||
1088 | /* | 1094 | /* |
1089 | * Chipset handlers | 1095 | * Chipset handlers |
1090 | */ | 1096 | */ |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 1031db66474a..189744db65e0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -1236,8 +1236,10 @@ static inline void rt2x00lib_set_if_combinations(struct rt2x00_dev *rt2x00dev) | |||
1236 | */ | 1236 | */ |
1237 | if_limit = &rt2x00dev->if_limits_ap; | 1237 | if_limit = &rt2x00dev->if_limits_ap; |
1238 | if_limit->max = rt2x00dev->ops->max_ap_intf; | 1238 | if_limit->max = rt2x00dev->ops->max_ap_intf; |
1239 | if_limit->types = BIT(NL80211_IFTYPE_AP) | | 1239 | if_limit->types = BIT(NL80211_IFTYPE_AP); |
1240 | BIT(NL80211_IFTYPE_MESH_POINT); | 1240 | #ifdef CONFIG_MAC80211_MESH |
1241 | if_limit->types |= BIT(NL80211_IFTYPE_MESH_POINT); | ||
1242 | #endif | ||
1241 | 1243 | ||
1242 | /* | 1244 | /* |
1243 | * Build up AP interface combinations structure. | 1245 | * Build up AP interface combinations structure. |
@@ -1309,7 +1311,9 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) | |||
1309 | rt2x00dev->hw->wiphy->interface_modes |= | 1311 | rt2x00dev->hw->wiphy->interface_modes |= |
1310 | BIT(NL80211_IFTYPE_ADHOC) | | 1312 | BIT(NL80211_IFTYPE_ADHOC) | |
1311 | BIT(NL80211_IFTYPE_AP) | | 1313 | BIT(NL80211_IFTYPE_AP) | |
1314 | #ifdef CONFIG_MAC80211_MESH | ||
1312 | BIT(NL80211_IFTYPE_MESH_POINT) | | 1315 | BIT(NL80211_IFTYPE_MESH_POINT) | |
1316 | #endif | ||
1313 | BIT(NL80211_IFTYPE_WDS); | 1317 | BIT(NL80211_IFTYPE_WDS); |
1314 | 1318 | ||
1315 | rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | 1319 | rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index a0c8caef3b0a..b1c673ecada1 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c | |||
@@ -52,8 +52,8 @@ int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev, | |||
52 | udelay(REGISTER_BUSY_DELAY); | 52 | udelay(REGISTER_BUSY_DELAY); |
53 | } | 53 | } |
54 | 54 | ||
55 | ERROR(rt2x00dev, "Indirect register access failed: " | 55 | printk_once(KERN_ERR "%s() Indirect register access failed: " |
56 | "offset=0x%.08x, value=0x%.08x\n", offset, *reg); | 56 | "offset=0x%.08x, value=0x%.08x\n", __func__, offset, *reg); |
57 | *reg = ~0; | 57 | *reg = ~0; |
58 | 58 | ||
59 | return 0; | 59 | return 0; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 4d91795dc6a2..952a0490eb17 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -832,7 +832,9 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, | |||
832 | bool rt2x00queue_for_each_entry(struct data_queue *queue, | 832 | bool rt2x00queue_for_each_entry(struct data_queue *queue, |
833 | enum queue_index start, | 833 | enum queue_index start, |
834 | enum queue_index end, | 834 | enum queue_index end, |
835 | bool (*fn)(struct queue_entry *entry)) | 835 | void *data, |
836 | bool (*fn)(struct queue_entry *entry, | ||
837 | void *data)) | ||
836 | { | 838 | { |
837 | unsigned long irqflags; | 839 | unsigned long irqflags; |
838 | unsigned int index_start; | 840 | unsigned int index_start; |
@@ -863,17 +865,17 @@ bool rt2x00queue_for_each_entry(struct data_queue *queue, | |||
863 | */ | 865 | */ |
864 | if (index_start < index_end) { | 866 | if (index_start < index_end) { |
865 | for (i = index_start; i < index_end; i++) { | 867 | for (i = index_start; i < index_end; i++) { |
866 | if (fn(&queue->entries[i])) | 868 | if (fn(&queue->entries[i], data)) |
867 | return true; | 869 | return true; |
868 | } | 870 | } |
869 | } else { | 871 | } else { |
870 | for (i = index_start; i < queue->limit; i++) { | 872 | for (i = index_start; i < queue->limit; i++) { |
871 | if (fn(&queue->entries[i])) | 873 | if (fn(&queue->entries[i], data)) |
872 | return true; | 874 | return true; |
873 | } | 875 | } |
874 | 876 | ||
875 | for (i = 0; i < index_end; i++) { | 877 | for (i = 0; i < index_end; i++) { |
876 | if (fn(&queue->entries[i])) | 878 | if (fn(&queue->entries[i], data)) |
877 | return true; | 879 | return true; |
878 | } | 880 | } |
879 | } | 881 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 9b8c10a86dee..3d0137193da0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h | |||
@@ -359,6 +359,7 @@ enum queue_entry_flags { | |||
359 | ENTRY_DATA_PENDING, | 359 | ENTRY_DATA_PENDING, |
360 | ENTRY_DATA_IO_FAILED, | 360 | ENTRY_DATA_IO_FAILED, |
361 | ENTRY_DATA_STATUS_PENDING, | 361 | ENTRY_DATA_STATUS_PENDING, |
362 | ENTRY_DATA_STATUS_SET, | ||
362 | }; | 363 | }; |
363 | 364 | ||
364 | /** | 365 | /** |
@@ -372,6 +373,7 @@ enum queue_entry_flags { | |||
372 | * @entry_idx: The entry index number. | 373 | * @entry_idx: The entry index number. |
373 | * @priv_data: Private data belonging to this queue entry. The pointer | 374 | * @priv_data: Private data belonging to this queue entry. The pointer |
374 | * points to data specific to a particular driver and queue type. | 375 | * points to data specific to a particular driver and queue type. |
376 | * @status: Device specific status | ||
375 | */ | 377 | */ |
376 | struct queue_entry { | 378 | struct queue_entry { |
377 | unsigned long flags; | 379 | unsigned long flags; |
@@ -383,6 +385,8 @@ struct queue_entry { | |||
383 | 385 | ||
384 | unsigned int entry_idx; | 386 | unsigned int entry_idx; |
385 | 387 | ||
388 | u32 status; | ||
389 | |||
386 | void *priv_data; | 390 | void *priv_data; |
387 | }; | 391 | }; |
388 | 392 | ||
@@ -584,6 +588,7 @@ struct data_queue_desc { | |||
584 | * @queue: Pointer to @data_queue | 588 | * @queue: Pointer to @data_queue |
585 | * @start: &enum queue_index Pointer to start index | 589 | * @start: &enum queue_index Pointer to start index |
586 | * @end: &enum queue_index Pointer to end index | 590 | * @end: &enum queue_index Pointer to end index |
591 | * @data: Data to pass to the callback function | ||
587 | * @fn: The function to call for each &struct queue_entry | 592 | * @fn: The function to call for each &struct queue_entry |
588 | * | 593 | * |
589 | * This will walk through all entries in the queue, in chronological | 594 | * This will walk through all entries in the queue, in chronological |
@@ -596,7 +601,9 @@ struct data_queue_desc { | |||
596 | bool rt2x00queue_for_each_entry(struct data_queue *queue, | 601 | bool rt2x00queue_for_each_entry(struct data_queue *queue, |
597 | enum queue_index start, | 602 | enum queue_index start, |
598 | enum queue_index end, | 603 | enum queue_index end, |
599 | bool (*fn)(struct queue_entry *entry)); | 604 | void *data, |
605 | bool (*fn)(struct queue_entry *entry, | ||
606 | void *data)); | ||
600 | 607 | ||
601 | /** | 608 | /** |
602 | * rt2x00queue_empty - Check if the queue is empty. | 609 | * rt2x00queue_empty - Check if the queue is empty. |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 40ea80725a96..5e50d4ff9d21 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -285,7 +285,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) | |||
285 | queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); | 285 | queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); |
286 | } | 286 | } |
287 | 287 | ||
288 | static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry) | 288 | static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void *data) |
289 | { | 289 | { |
290 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 290 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
291 | struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); | 291 | struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); |
@@ -390,7 +390,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) | |||
390 | queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work); | 390 | queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work); |
391 | } | 391 | } |
392 | 392 | ||
393 | static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry) | 393 | static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void *data) |
394 | { | 394 | { |
395 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 395 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
396 | struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); | 396 | struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); |
@@ -427,12 +427,18 @@ void rt2x00usb_kick_queue(struct data_queue *queue) | |||
427 | case QID_AC_BE: | 427 | case QID_AC_BE: |
428 | case QID_AC_BK: | 428 | case QID_AC_BK: |
429 | if (!rt2x00queue_empty(queue)) | 429 | if (!rt2x00queue_empty(queue)) |
430 | rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, | 430 | rt2x00queue_for_each_entry(queue, |
431 | Q_INDEX_DONE, | ||
432 | Q_INDEX, | ||
433 | NULL, | ||
431 | rt2x00usb_kick_tx_entry); | 434 | rt2x00usb_kick_tx_entry); |
432 | break; | 435 | break; |
433 | case QID_RX: | 436 | case QID_RX: |
434 | if (!rt2x00queue_full(queue)) | 437 | if (!rt2x00queue_full(queue)) |
435 | rt2x00queue_for_each_entry(queue, Q_INDEX, Q_INDEX_DONE, | 438 | rt2x00queue_for_each_entry(queue, |
439 | Q_INDEX, | ||
440 | Q_INDEX_DONE, | ||
441 | NULL, | ||
436 | rt2x00usb_kick_rx_entry); | 442 | rt2x00usb_kick_rx_entry); |
437 | break; | 443 | break; |
438 | default: | 444 | default: |
@@ -441,7 +447,7 @@ void rt2x00usb_kick_queue(struct data_queue *queue) | |||
441 | } | 447 | } |
442 | EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue); | 448 | EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue); |
443 | 449 | ||
444 | static bool rt2x00usb_flush_entry(struct queue_entry *entry) | 450 | static bool rt2x00usb_flush_entry(struct queue_entry *entry, void *data) |
445 | { | 451 | { |
446 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 452 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
447 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; | 453 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; |
@@ -468,7 +474,7 @@ void rt2x00usb_flush_queue(struct data_queue *queue, bool drop) | |||
468 | unsigned int i; | 474 | unsigned int i; |
469 | 475 | ||
470 | if (drop) | 476 | if (drop) |
471 | rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, | 477 | rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL, |
472 | rt2x00usb_flush_entry); | 478 | rt2x00usb_flush_entry); |
473 | 479 | ||
474 | /* | 480 | /* |
@@ -559,7 +565,7 @@ void rt2x00usb_clear_entry(struct queue_entry *entry) | |||
559 | entry->flags = 0; | 565 | entry->flags = 0; |
560 | 566 | ||
561 | if (entry->queue->qid == QID_RX) | 567 | if (entry->queue->qid == QID_RX) |
562 | rt2x00usb_kick_rx_entry(entry); | 568 | rt2x00usb_kick_rx_entry(entry, NULL); |
563 | } | 569 | } |
564 | EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); | 570 | EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); |
565 | 571 | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index b1ccff474c79..c08d0f4c5f3d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c | |||
@@ -1377,74 +1377,57 @@ void rtl92cu_card_disable(struct ieee80211_hw *hw) | |||
1377 | 1377 | ||
1378 | void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) | 1378 | void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) |
1379 | { | 1379 | { |
1380 | /* dummy routine needed for callback from rtl_op_configure_filter() */ | ||
1381 | } | ||
1382 | |||
1383 | /*========================================================================== */ | ||
1384 | |||
1385 | static void _rtl92cu_set_check_bssid(struct ieee80211_hw *hw, | ||
1386 | enum nl80211_iftype type) | ||
1387 | { | ||
1388 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1380 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1389 | u32 reg_rcr = rtl_read_dword(rtlpriv, REG_RCR); | ||
1390 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); | 1381 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); |
1391 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | 1382 | u32 reg_rcr = rtl_read_dword(rtlpriv, REG_RCR); |
1392 | u8 filterout_non_associated_bssid = false; | ||
1393 | 1383 | ||
1394 | switch (type) { | 1384 | if (rtlpriv->psc.rfpwr_state != ERFON) |
1395 | case NL80211_IFTYPE_ADHOC: | 1385 | return; |
1396 | case NL80211_IFTYPE_STATION: | 1386 | |
1397 | filterout_non_associated_bssid = true; | 1387 | if (check_bssid) { |
1398 | break; | 1388 | u8 tmp; |
1399 | case NL80211_IFTYPE_UNSPECIFIED: | ||
1400 | case NL80211_IFTYPE_AP: | ||
1401 | default: | ||
1402 | break; | ||
1403 | } | ||
1404 | if (filterout_non_associated_bssid) { | ||
1405 | if (IS_NORMAL_CHIP(rtlhal->version)) { | 1389 | if (IS_NORMAL_CHIP(rtlhal->version)) { |
1406 | switch (rtlphy->current_io_type) { | 1390 | reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); |
1407 | case IO_CMD_RESUME_DM_BY_SCAN: | 1391 | tmp = BIT(4); |
1408 | reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); | ||
1409 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
1410 | HW_VAR_RCR, (u8 *)(®_rcr)); | ||
1411 | /* enable update TSF */ | ||
1412 | _rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(4)); | ||
1413 | break; | ||
1414 | case IO_CMD_PAUSE_DM_BY_SCAN: | ||
1415 | reg_rcr &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN); | ||
1416 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
1417 | HW_VAR_RCR, (u8 *)(®_rcr)); | ||
1418 | /* disable update TSF */ | ||
1419 | _rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0); | ||
1420 | break; | ||
1421 | } | ||
1422 | } else { | 1392 | } else { |
1423 | reg_rcr |= (RCR_CBSSID); | 1393 | reg_rcr |= RCR_CBSSID; |
1424 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, | 1394 | tmp = BIT(4) | BIT(5); |
1425 | (u8 *)(®_rcr)); | ||
1426 | _rtl92cu_set_bcn_ctrl_reg(hw, 0, (BIT(4)|BIT(5))); | ||
1427 | } | 1395 | } |
1428 | } else if (filterout_non_associated_bssid == false) { | 1396 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, |
1397 | (u8 *) (®_rcr)); | ||
1398 | _rtl92cu_set_bcn_ctrl_reg(hw, 0, tmp); | ||
1399 | } else { | ||
1400 | u8 tmp; | ||
1429 | if (IS_NORMAL_CHIP(rtlhal->version)) { | 1401 | if (IS_NORMAL_CHIP(rtlhal->version)) { |
1430 | reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); | 1402 | reg_rcr &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN); |
1431 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, | 1403 | tmp = BIT(4); |
1432 | (u8 *)(®_rcr)); | ||
1433 | _rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0); | ||
1434 | } else { | 1404 | } else { |
1435 | reg_rcr &= (~RCR_CBSSID); | 1405 | reg_rcr &= ~RCR_CBSSID; |
1436 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, | 1406 | tmp = BIT(4) | BIT(5); |
1437 | (u8 *)(®_rcr)); | ||
1438 | _rtl92cu_set_bcn_ctrl_reg(hw, (BIT(4)|BIT(5)), 0); | ||
1439 | } | 1407 | } |
1408 | reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); | ||
1409 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
1410 | HW_VAR_RCR, (u8 *) (®_rcr)); | ||
1411 | _rtl92cu_set_bcn_ctrl_reg(hw, tmp, 0); | ||
1440 | } | 1412 | } |
1441 | } | 1413 | } |
1442 | 1414 | ||
1415 | /*========================================================================== */ | ||
1416 | |||
1443 | int rtl92cu_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) | 1417 | int rtl92cu_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) |
1444 | { | 1418 | { |
1419 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1420 | |||
1445 | if (_rtl92cu_set_media_status(hw, type)) | 1421 | if (_rtl92cu_set_media_status(hw, type)) |
1446 | return -EOPNOTSUPP; | 1422 | return -EOPNOTSUPP; |
1447 | _rtl92cu_set_check_bssid(hw, type); | 1423 | |
1424 | if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { | ||
1425 | if (type != NL80211_IFTYPE_AP) | ||
1426 | rtl92cu_set_check_bssid(hw, true); | ||
1427 | } else { | ||
1428 | rtl92cu_set_check_bssid(hw, false); | ||
1429 | } | ||
1430 | |||
1448 | return 0; | 1431 | return 0; |
1449 | } | 1432 | } |
1450 | 1433 | ||
@@ -2058,8 +2041,6 @@ void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw, | |||
2058 | (shortgi_rate << 4) | (shortgi_rate); | 2041 | (shortgi_rate << 4) | (shortgi_rate); |
2059 | } | 2042 | } |
2060 | rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value); | 2043 | rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value); |
2061 | RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, "%x\n", | ||
2062 | rtl_read_dword(rtlpriv, REG_ARFR0)); | ||
2063 | } | 2044 | } |
2064 | 2045 | ||
2065 | void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level) | 2046 | void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level) |
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index 156b52732f3d..b5c80b5d57ef 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c | |||
@@ -224,10 +224,9 @@ static void _usb_writeN_sync(struct rtl_priv *rtlpriv, u32 addr, void *data, | |||
224 | u8 *buffer; | 224 | u8 *buffer; |
225 | 225 | ||
226 | wvalue = (u16)(addr & 0x0000ffff); | 226 | wvalue = (u16)(addr & 0x0000ffff); |
227 | buffer = kmalloc(len, GFP_ATOMIC); | 227 | buffer = kmemdup(data, len, GFP_ATOMIC); |
228 | if (!buffer) | 228 | if (!buffer) |
229 | return; | 229 | return; |
230 | memcpy(buffer, data, len); | ||
231 | usb_control_msg(udev, pipe, request, reqtype, wvalue, | 230 | usb_control_msg(udev, pipe, request, reqtype, wvalue, |
232 | index, buffer, len, 50); | 231 | index, buffer, len, 50); |
233 | 232 | ||
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index f13258a8d995..c3eff32acf6c 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h | |||
@@ -2127,9 +2127,6 @@ value to host byte ordering.*/ | |||
2127 | #define WLAN_FC_GET_TYPE(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) | 2127 | #define WLAN_FC_GET_TYPE(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) |
2128 | #define WLAN_FC_GET_STYPE(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) | 2128 | #define WLAN_FC_GET_STYPE(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) |
2129 | #define WLAN_FC_MORE_DATA(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_MOREDATA) | 2129 | #define WLAN_FC_MORE_DATA(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_MOREDATA) |
2130 | #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) | ||
2131 | #define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) | ||
2132 | #define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) | ||
2133 | 2130 | ||
2134 | #define RT_RF_OFF_LEVL_ASPM BIT(0) /*PCI ASPM */ | 2131 | #define RT_RF_OFF_LEVL_ASPM BIT(0) /*PCI ASPM */ |
2135 | #define RT_RF_OFF_LEVL_CLK_REQ BIT(1) /*PCI clock request */ | 2132 | #define RT_RF_OFF_LEVL_CLK_REQ BIT(1) /*PCI clock request */ |
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 2c2ff3e1f849..d7e306333f6c 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
@@ -4956,7 +4956,8 @@ static void wlcore_op_flush(struct ieee80211_hw *hw, bool drop) | |||
4956 | static int wlcore_op_remain_on_channel(struct ieee80211_hw *hw, | 4956 | static int wlcore_op_remain_on_channel(struct ieee80211_hw *hw, |
4957 | struct ieee80211_vif *vif, | 4957 | struct ieee80211_vif *vif, |
4958 | struct ieee80211_channel *chan, | 4958 | struct ieee80211_channel *chan, |
4959 | int duration) | 4959 | int duration, |
4960 | enum ieee80211_roc_type type) | ||
4960 | { | 4961 | { |
4961 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | 4962 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); |
4962 | struct wl1271 *wl = hw->priv; | 4963 | struct wl1271 *wl = hw->priv; |
diff --git a/drivers/nfc/microread/mei.c b/drivers/nfc/microread/mei.c index eef38cfd812e..13bde92b1e29 100644 --- a/drivers/nfc/microread/mei.c +++ b/drivers/nfc/microread/mei.c | |||
@@ -48,7 +48,7 @@ struct mei_nfc_hdr { | |||
48 | #define MEI_NFC_MAX_READ (MEI_NFC_HEADER_SIZE + MEI_NFC_MAX_HCI_PAYLOAD) | 48 | #define MEI_NFC_MAX_READ (MEI_NFC_HEADER_SIZE + MEI_NFC_MAX_HCI_PAYLOAD) |
49 | 49 | ||
50 | struct microread_mei_phy { | 50 | struct microread_mei_phy { |
51 | struct mei_device *mei_device; | 51 | struct mei_device *device; |
52 | struct nfc_hci_dev *hdev; | 52 | struct nfc_hci_dev *hdev; |
53 | 53 | ||
54 | int powered; | 54 | int powered; |
diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c index 71098a7b5fed..7cb7d2c8fd86 100644 --- a/drivers/ssb/driver_chipcommon.c +++ b/drivers/ssb/driver_chipcommon.c | |||
@@ -354,7 +354,7 @@ void ssb_chipcommon_init(struct ssb_chipcommon *cc) | |||
354 | 354 | ||
355 | if (cc->dev->id.revision >= 11) | 355 | if (cc->dev->id.revision >= 11) |
356 | cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT); | 356 | cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT); |
357 | ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status); | 357 | ssb_dbg("chipcommon status is 0x%x\n", cc->status); |
358 | 358 | ||
359 | if (cc->dev->id.revision >= 20) { | 359 | if (cc->dev->id.revision >= 20) { |
360 | chipco_write32(cc, SSB_CHIPCO_GPIOPULLUP, 0); | 360 | chipco_write32(cc, SSB_CHIPCO_GPIOPULLUP, 0); |
diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c index 4c0f6d883dd3..791da2c0d8f6 100644 --- a/drivers/ssb/driver_chipcommon_pmu.c +++ b/drivers/ssb/driver_chipcommon_pmu.c | |||
@@ -110,8 +110,8 @@ static void ssb_pmu0_pllinit_r0(struct ssb_chipcommon *cc, | |||
110 | return; | 110 | return; |
111 | } | 111 | } |
112 | 112 | ||
113 | ssb_printk(KERN_INFO PFX "Programming PLL to %u.%03u MHz\n", | 113 | ssb_info("Programming PLL to %u.%03u MHz\n", |
114 | (crystalfreq / 1000), (crystalfreq % 1000)); | 114 | crystalfreq / 1000, crystalfreq % 1000); |
115 | 115 | ||
116 | /* First turn the PLL off. */ | 116 | /* First turn the PLL off. */ |
117 | switch (bus->chip_id) { | 117 | switch (bus->chip_id) { |
@@ -138,7 +138,7 @@ static void ssb_pmu0_pllinit_r0(struct ssb_chipcommon *cc, | |||
138 | } | 138 | } |
139 | tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); | 139 | tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); |
140 | if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT) | 140 | if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT) |
141 | ssb_printk(KERN_EMERG PFX "Failed to turn the PLL off!\n"); | 141 | ssb_emerg("Failed to turn the PLL off!\n"); |
142 | 142 | ||
143 | /* Set PDIV in PLL control 0. */ | 143 | /* Set PDIV in PLL control 0. */ |
144 | pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL0); | 144 | pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL0); |
@@ -249,8 +249,8 @@ static void ssb_pmu1_pllinit_r0(struct ssb_chipcommon *cc, | |||
249 | return; | 249 | return; |
250 | } | 250 | } |
251 | 251 | ||
252 | ssb_printk(KERN_INFO PFX "Programming PLL to %u.%03u MHz\n", | 252 | ssb_info("Programming PLL to %u.%03u MHz\n", |
253 | (crystalfreq / 1000), (crystalfreq % 1000)); | 253 | crystalfreq / 1000, crystalfreq % 1000); |
254 | 254 | ||
255 | /* First turn the PLL off. */ | 255 | /* First turn the PLL off. */ |
256 | switch (bus->chip_id) { | 256 | switch (bus->chip_id) { |
@@ -275,7 +275,7 @@ static void ssb_pmu1_pllinit_r0(struct ssb_chipcommon *cc, | |||
275 | } | 275 | } |
276 | tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); | 276 | tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); |
277 | if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT) | 277 | if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT) |
278 | ssb_printk(KERN_EMERG PFX "Failed to turn the PLL off!\n"); | 278 | ssb_emerg("Failed to turn the PLL off!\n"); |
279 | 279 | ||
280 | /* Set p1div and p2div. */ | 280 | /* Set p1div and p2div. */ |
281 | pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL0); | 281 | pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL0); |
@@ -349,9 +349,8 @@ static void ssb_pmu_pll_init(struct ssb_chipcommon *cc) | |||
349 | case 43222: | 349 | case 43222: |
350 | break; | 350 | break; |
351 | default: | 351 | default: |
352 | ssb_printk(KERN_ERR PFX | 352 | ssb_err("ERROR: PLL init unknown for device %04X\n", |
353 | "ERROR: PLL init unknown for device %04X\n", | 353 | bus->chip_id); |
354 | bus->chip_id); | ||
355 | } | 354 | } |
356 | } | 355 | } |
357 | 356 | ||
@@ -472,9 +471,8 @@ static void ssb_pmu_resources_init(struct ssb_chipcommon *cc) | |||
472 | max_msk = 0xFFFFF; | 471 | max_msk = 0xFFFFF; |
473 | break; | 472 | break; |
474 | default: | 473 | default: |
475 | ssb_printk(KERN_ERR PFX | 474 | ssb_err("ERROR: PMU resource config unknown for device %04X\n", |
476 | "ERROR: PMU resource config unknown for device %04X\n", | 475 | bus->chip_id); |
477 | bus->chip_id); | ||
478 | } | 476 | } |
479 | 477 | ||
480 | if (updown_tab) { | 478 | if (updown_tab) { |
@@ -526,8 +524,8 @@ void ssb_pmu_init(struct ssb_chipcommon *cc) | |||
526 | pmucap = chipco_read32(cc, SSB_CHIPCO_PMU_CAP); | 524 | pmucap = chipco_read32(cc, SSB_CHIPCO_PMU_CAP); |
527 | cc->pmu.rev = (pmucap & SSB_CHIPCO_PMU_CAP_REVISION); | 525 | cc->pmu.rev = (pmucap & SSB_CHIPCO_PMU_CAP_REVISION); |
528 | 526 | ||
529 | ssb_dprintk(KERN_DEBUG PFX "Found rev %u PMU (capabilities 0x%08X)\n", | 527 | ssb_dbg("Found rev %u PMU (capabilities 0x%08X)\n", |
530 | cc->pmu.rev, pmucap); | 528 | cc->pmu.rev, pmucap); |
531 | 529 | ||
532 | if (cc->pmu.rev == 1) | 530 | if (cc->pmu.rev == 1) |
533 | chipco_mask32(cc, SSB_CHIPCO_PMU_CTL, | 531 | chipco_mask32(cc, SSB_CHIPCO_PMU_CTL, |
@@ -638,9 +636,8 @@ u32 ssb_pmu_get_alp_clock(struct ssb_chipcommon *cc) | |||
638 | case 0x5354: | 636 | case 0x5354: |
639 | ssb_pmu_get_alp_clock_clk0(cc); | 637 | ssb_pmu_get_alp_clock_clk0(cc); |
640 | default: | 638 | default: |
641 | ssb_printk(KERN_ERR PFX | 639 | ssb_err("ERROR: PMU alp clock unknown for device %04X\n", |
642 | "ERROR: PMU alp clock unknown for device %04X\n", | 640 | bus->chip_id); |
643 | bus->chip_id); | ||
644 | return 0; | 641 | return 0; |
645 | } | 642 | } |
646 | } | 643 | } |
@@ -654,9 +651,8 @@ u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc) | |||
654 | /* 5354 chip uses a non programmable PLL of frequency 240MHz */ | 651 | /* 5354 chip uses a non programmable PLL of frequency 240MHz */ |
655 | return 240000000; | 652 | return 240000000; |
656 | default: | 653 | default: |
657 | ssb_printk(KERN_ERR PFX | 654 | ssb_err("ERROR: PMU cpu clock unknown for device %04X\n", |
658 | "ERROR: PMU cpu clock unknown for device %04X\n", | 655 | bus->chip_id); |
659 | bus->chip_id); | ||
660 | return 0; | 656 | return 0; |
661 | } | 657 | } |
662 | } | 658 | } |
@@ -669,9 +665,8 @@ u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc) | |||
669 | case 0x5354: | 665 | case 0x5354: |
670 | return 120000000; | 666 | return 120000000; |
671 | default: | 667 | default: |
672 | ssb_printk(KERN_ERR PFX | 668 | ssb_err("ERROR: PMU controlclock unknown for device %04X\n", |
673 | "ERROR: PMU controlclock unknown for device %04X\n", | 669 | bus->chip_id); |
674 | bus->chip_id); | ||
675 | return 0; | 670 | return 0; |
676 | } | 671 | } |
677 | } | 672 | } |
diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c index 33b37dac40bd..fa385a368a56 100644 --- a/drivers/ssb/driver_mipscore.c +++ b/drivers/ssb/driver_mipscore.c | |||
@@ -167,21 +167,22 @@ static void set_irq(struct ssb_device *dev, unsigned int irq) | |||
167 | irqflag |= (ipsflag & ~ipsflag_irq_mask[irq]); | 167 | irqflag |= (ipsflag & ~ipsflag_irq_mask[irq]); |
168 | ssb_write32(mdev, SSB_IPSFLAG, irqflag); | 168 | ssb_write32(mdev, SSB_IPSFLAG, irqflag); |
169 | } | 169 | } |
170 | ssb_dprintk(KERN_INFO PFX | 170 | ssb_dbg("set_irq: core 0x%04x, irq %d => %d\n", |
171 | "set_irq: core 0x%04x, irq %d => %d\n", | 171 | dev->id.coreid, oldirq+2, irq+2); |
172 | dev->id.coreid, oldirq+2, irq+2); | ||
173 | } | 172 | } |
174 | 173 | ||
175 | static void print_irq(struct ssb_device *dev, unsigned int irq) | 174 | static void print_irq(struct ssb_device *dev, unsigned int irq) |
176 | { | 175 | { |
177 | int i; | ||
178 | static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"}; | 176 | static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"}; |
179 | ssb_dprintk(KERN_INFO PFX | 177 | ssb_dbg("core 0x%04x, irq : %s%s %s%s %s%s %s%s %s%s %s%s %s%s\n", |
180 | "core 0x%04x, irq :", dev->id.coreid); | 178 | dev->id.coreid, |
181 | for (i = 0; i <= 6; i++) { | 179 | irq_name[0], irq == 0 ? "*" : " ", |
182 | ssb_dprintk(" %s%s", irq_name[i], i==irq?"*":" "); | 180 | irq_name[1], irq == 1 ? "*" : " ", |
183 | } | 181 | irq_name[2], irq == 2 ? "*" : " ", |
184 | ssb_dprintk("\n"); | 182 | irq_name[3], irq == 3 ? "*" : " ", |
183 | irq_name[4], irq == 4 ? "*" : " ", | ||
184 | irq_name[5], irq == 5 ? "*" : " ", | ||
185 | irq_name[6], irq == 6 ? "*" : " "); | ||
185 | } | 186 | } |
186 | 187 | ||
187 | static void dump_irq(struct ssb_bus *bus) | 188 | static void dump_irq(struct ssb_bus *bus) |
@@ -286,7 +287,7 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore) | |||
286 | if (!mcore->dev) | 287 | if (!mcore->dev) |
287 | return; /* We don't have a MIPS core */ | 288 | return; /* We don't have a MIPS core */ |
288 | 289 | ||
289 | ssb_dprintk(KERN_INFO PFX "Initializing MIPS core...\n"); | 290 | ssb_dbg("Initializing MIPS core...\n"); |
290 | 291 | ||
291 | bus = mcore->dev->bus; | 292 | bus = mcore->dev->bus; |
292 | hz = ssb_clockspeed(bus); | 293 | hz = ssb_clockspeed(bus); |
@@ -334,7 +335,7 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore) | |||
334 | break; | 335 | break; |
335 | } | 336 | } |
336 | } | 337 | } |
337 | ssb_dprintk(KERN_INFO PFX "after irq reconfiguration\n"); | 338 | ssb_dbg("after irq reconfiguration\n"); |
338 | dump_irq(bus); | 339 | dump_irq(bus); |
339 | 340 | ||
340 | ssb_mips_serial_init(mcore); | 341 | ssb_mips_serial_init(mcore); |
diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index 59801d23d7ec..d75b72ba2672 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c | |||
@@ -263,8 +263,7 @@ int ssb_pcicore_plat_dev_init(struct pci_dev *d) | |||
263 | return -ENODEV; | 263 | return -ENODEV; |
264 | } | 264 | } |
265 | 265 | ||
266 | ssb_printk(KERN_INFO "PCI: Fixing up device %s\n", | 266 | ssb_info("PCI: Fixing up device %s\n", pci_name(d)); |
267 | pci_name(d)); | ||
268 | 267 | ||
269 | /* Fix up interrupt lines */ | 268 | /* Fix up interrupt lines */ |
270 | d->irq = ssb_mips_irq(extpci_core->dev) + 2; | 269 | d->irq = ssb_mips_irq(extpci_core->dev) + 2; |
@@ -285,12 +284,12 @@ static void ssb_pcicore_fixup_pcibridge(struct pci_dev *dev) | |||
285 | if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0) | 284 | if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0) |
286 | return; | 285 | return; |
287 | 286 | ||
288 | ssb_printk(KERN_INFO "PCI: Fixing up bridge %s\n", pci_name(dev)); | 287 | ssb_info("PCI: Fixing up bridge %s\n", pci_name(dev)); |
289 | 288 | ||
290 | /* Enable PCI bridge bus mastering and memory space */ | 289 | /* Enable PCI bridge bus mastering and memory space */ |
291 | pci_set_master(dev); | 290 | pci_set_master(dev); |
292 | if (pcibios_enable_device(dev, ~0) < 0) { | 291 | if (pcibios_enable_device(dev, ~0) < 0) { |
293 | ssb_printk(KERN_ERR "PCI: SSB bridge enable failed\n"); | 292 | ssb_err("PCI: SSB bridge enable failed\n"); |
294 | return; | 293 | return; |
295 | } | 294 | } |
296 | 295 | ||
@@ -299,8 +298,8 @@ static void ssb_pcicore_fixup_pcibridge(struct pci_dev *dev) | |||
299 | 298 | ||
300 | /* Make sure our latency is high enough to handle the devices behind us */ | 299 | /* Make sure our latency is high enough to handle the devices behind us */ |
301 | lat = 168; | 300 | lat = 168; |
302 | ssb_printk(KERN_INFO "PCI: Fixing latency timer of device %s to %u\n", | 301 | ssb_info("PCI: Fixing latency timer of device %s to %u\n", |
303 | pci_name(dev), lat); | 302 | pci_name(dev), lat); |
304 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); | 303 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); |
305 | } | 304 | } |
306 | DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_pcicore_fixup_pcibridge); | 305 | DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_pcicore_fixup_pcibridge); |
@@ -323,7 +322,7 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc) | |||
323 | return; | 322 | return; |
324 | extpci_core = pc; | 323 | extpci_core = pc; |
325 | 324 | ||
326 | ssb_dprintk(KERN_INFO PFX "PCIcore in host mode found\n"); | 325 | ssb_dbg("PCIcore in host mode found\n"); |
327 | /* Reset devices on the external PCI bus */ | 326 | /* Reset devices on the external PCI bus */ |
328 | val = SSB_PCICORE_CTL_RST_OE; | 327 | val = SSB_PCICORE_CTL_RST_OE; |
329 | val |= SSB_PCICORE_CTL_CLK_OE; | 328 | val |= SSB_PCICORE_CTL_CLK_OE; |
@@ -338,7 +337,7 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc) | |||
338 | udelay(1); /* Assertion time demanded by the PCI standard */ | 337 | udelay(1); /* Assertion time demanded by the PCI standard */ |
339 | 338 | ||
340 | if (pc->dev->bus->has_cardbus_slot) { | 339 | if (pc->dev->bus->has_cardbus_slot) { |
341 | ssb_dprintk(KERN_INFO PFX "CardBus slot detected\n"); | 340 | ssb_dbg("CardBus slot detected\n"); |
342 | pc->cardbusmode = 1; | 341 | pc->cardbusmode = 1; |
343 | /* GPIO 1 resets the bridge */ | 342 | /* GPIO 1 resets the bridge */ |
344 | ssb_gpio_out(pc->dev->bus, 1, 1); | 343 | ssb_gpio_out(pc->dev->bus, 1, 1); |
diff --git a/drivers/ssb/embedded.c b/drivers/ssb/embedded.c index bb18d76f9f2c..55e101115038 100644 --- a/drivers/ssb/embedded.c +++ b/drivers/ssb/embedded.c | |||
@@ -57,9 +57,8 @@ int ssb_watchdog_register(struct ssb_bus *bus) | |||
57 | bus->busnumber, &wdt, | 57 | bus->busnumber, &wdt, |
58 | sizeof(wdt)); | 58 | sizeof(wdt)); |
59 | if (IS_ERR(pdev)) { | 59 | if (IS_ERR(pdev)) { |
60 | ssb_dprintk(KERN_INFO PFX | 60 | ssb_dbg("can not register watchdog device, err: %li\n", |
61 | "can not register watchdog device, err: %li\n", | 61 | PTR_ERR(pdev)); |
62 | PTR_ERR(pdev)); | ||
63 | return PTR_ERR(pdev); | 62 | return PTR_ERR(pdev); |
64 | } | 63 | } |
65 | 64 | ||
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 3b645b8a261f..812775a4bfb6 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c | |||
@@ -275,8 +275,8 @@ int ssb_devices_thaw(struct ssb_freeze_context *ctx) | |||
275 | 275 | ||
276 | err = sdrv->probe(sdev, &sdev->id); | 276 | err = sdrv->probe(sdev, &sdev->id); |
277 | if (err) { | 277 | if (err) { |
278 | ssb_printk(KERN_ERR PFX "Failed to thaw device %s\n", | 278 | ssb_err("Failed to thaw device %s\n", |
279 | dev_name(sdev->dev)); | 279 | dev_name(sdev->dev)); |
280 | result = err; | 280 | result = err; |
281 | } | 281 | } |
282 | ssb_device_put(sdev); | 282 | ssb_device_put(sdev); |
@@ -447,10 +447,9 @@ void ssb_bus_unregister(struct ssb_bus *bus) | |||
447 | 447 | ||
448 | err = ssb_gpio_unregister(bus); | 448 | err = ssb_gpio_unregister(bus); |
449 | if (err == -EBUSY) | 449 | if (err == -EBUSY) |
450 | ssb_dprintk(KERN_ERR PFX "Some GPIOs are still in use.\n"); | 450 | ssb_dbg("Some GPIOs are still in use\n"); |
451 | else if (err) | 451 | else if (err) |
452 | ssb_dprintk(KERN_ERR PFX | 452 | ssb_dbg("Can not unregister GPIO driver: %i\n", err); |
453 | "Can not unregister GPIO driver: %i\n", err); | ||
454 | 453 | ||
455 | ssb_buses_lock(); | 454 | ssb_buses_lock(); |
456 | ssb_devices_unregister(bus); | 455 | ssb_devices_unregister(bus); |
@@ -497,8 +496,7 @@ static int ssb_devices_register(struct ssb_bus *bus) | |||
497 | 496 | ||
498 | devwrap = kzalloc(sizeof(*devwrap), GFP_KERNEL); | 497 | devwrap = kzalloc(sizeof(*devwrap), GFP_KERNEL); |
499 | if (!devwrap) { | 498 | if (!devwrap) { |
500 | ssb_printk(KERN_ERR PFX | 499 | ssb_err("Could not allocate device\n"); |
501 | "Could not allocate device\n"); | ||
502 | err = -ENOMEM; | 500 | err = -ENOMEM; |
503 | goto error; | 501 | goto error; |
504 | } | 502 | } |
@@ -537,9 +535,7 @@ static int ssb_devices_register(struct ssb_bus *bus) | |||
537 | sdev->dev = dev; | 535 | sdev->dev = dev; |
538 | err = device_register(dev); | 536 | err = device_register(dev); |
539 | if (err) { | 537 | if (err) { |
540 | ssb_printk(KERN_ERR PFX | 538 | ssb_err("Could not register %s\n", dev_name(dev)); |
541 | "Could not register %s\n", | ||
542 | dev_name(dev)); | ||
543 | /* Set dev to NULL to not unregister | 539 | /* Set dev to NULL to not unregister |
544 | * dev on error unwinding. */ | 540 | * dev on error unwinding. */ |
545 | sdev->dev = NULL; | 541 | sdev->dev = NULL; |
@@ -825,10 +821,9 @@ static int ssb_bus_register(struct ssb_bus *bus, | |||
825 | ssb_mipscore_init(&bus->mipscore); | 821 | ssb_mipscore_init(&bus->mipscore); |
826 | err = ssb_gpio_init(bus); | 822 | err = ssb_gpio_init(bus); |
827 | if (err == -ENOTSUPP) | 823 | if (err == -ENOTSUPP) |
828 | ssb_dprintk(KERN_DEBUG PFX "GPIO driver not activated\n"); | 824 | ssb_dbg("GPIO driver not activated\n"); |
829 | else if (err) | 825 | else if (err) |
830 | ssb_dprintk(KERN_ERR PFX | 826 | ssb_dbg("Error registering GPIO driver: %i\n", err); |
831 | "Error registering GPIO driver: %i\n", err); | ||
832 | err = ssb_fetch_invariants(bus, get_invariants); | 827 | err = ssb_fetch_invariants(bus, get_invariants); |
833 | if (err) { | 828 | if (err) { |
834 | ssb_bus_may_powerdown(bus); | 829 | ssb_bus_may_powerdown(bus); |
@@ -878,11 +873,11 @@ int ssb_bus_pcibus_register(struct ssb_bus *bus, struct pci_dev *host_pci) | |||
878 | 873 | ||
879 | err = ssb_bus_register(bus, ssb_pci_get_invariants, 0); | 874 | err = ssb_bus_register(bus, ssb_pci_get_invariants, 0); |
880 | if (!err) { | 875 | if (!err) { |
881 | ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on " | 876 | ssb_info("Sonics Silicon Backplane found on PCI device %s\n", |
882 | "PCI device %s\n", dev_name(&host_pci->dev)); | 877 | dev_name(&host_pci->dev)); |
883 | } else { | 878 | } else { |
884 | ssb_printk(KERN_ERR PFX "Failed to register PCI version" | 879 | ssb_err("Failed to register PCI version of SSB with error %d\n", |
885 | " of SSB with error %d\n", err); | 880 | err); |
886 | } | 881 | } |
887 | 882 | ||
888 | return err; | 883 | return err; |
@@ -903,8 +898,8 @@ int ssb_bus_pcmciabus_register(struct ssb_bus *bus, | |||
903 | 898 | ||
904 | err = ssb_bus_register(bus, ssb_pcmcia_get_invariants, baseaddr); | 899 | err = ssb_bus_register(bus, ssb_pcmcia_get_invariants, baseaddr); |
905 | if (!err) { | 900 | if (!err) { |
906 | ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on " | 901 | ssb_info("Sonics Silicon Backplane found on PCMCIA device %s\n", |
907 | "PCMCIA device %s\n", pcmcia_dev->devname); | 902 | pcmcia_dev->devname); |
908 | } | 903 | } |
909 | 904 | ||
910 | return err; | 905 | return err; |
@@ -925,8 +920,8 @@ int ssb_bus_sdiobus_register(struct ssb_bus *bus, struct sdio_func *func, | |||
925 | 920 | ||
926 | err = ssb_bus_register(bus, ssb_sdio_get_invariants, ~0); | 921 | err = ssb_bus_register(bus, ssb_sdio_get_invariants, ~0); |
927 | if (!err) { | 922 | if (!err) { |
928 | ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on " | 923 | ssb_info("Sonics Silicon Backplane found on SDIO device %s\n", |
929 | "SDIO device %s\n", sdio_func_id(func)); | 924 | sdio_func_id(func)); |
930 | } | 925 | } |
931 | 926 | ||
932 | return err; | 927 | return err; |
@@ -944,8 +939,8 @@ int ssb_bus_ssbbus_register(struct ssb_bus *bus, unsigned long baseaddr, | |||
944 | 939 | ||
945 | err = ssb_bus_register(bus, get_invariants, baseaddr); | 940 | err = ssb_bus_register(bus, get_invariants, baseaddr); |
946 | if (!err) { | 941 | if (!err) { |
947 | ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found at " | 942 | ssb_info("Sonics Silicon Backplane found at address 0x%08lX\n", |
948 | "address 0x%08lX\n", baseaddr); | 943 | baseaddr); |
949 | } | 944 | } |
950 | 945 | ||
951 | return err; | 946 | return err; |
@@ -1339,7 +1334,7 @@ out: | |||
1339 | #endif | 1334 | #endif |
1340 | return err; | 1335 | return err; |
1341 | error: | 1336 | error: |
1342 | ssb_printk(KERN_ERR PFX "Bus powerdown failed\n"); | 1337 | ssb_err("Bus powerdown failed\n"); |
1343 | goto out; | 1338 | goto out; |
1344 | } | 1339 | } |
1345 | EXPORT_SYMBOL(ssb_bus_may_powerdown); | 1340 | EXPORT_SYMBOL(ssb_bus_may_powerdown); |
@@ -1362,7 +1357,7 @@ int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl) | |||
1362 | 1357 | ||
1363 | return 0; | 1358 | return 0; |
1364 | error: | 1359 | error: |
1365 | ssb_printk(KERN_ERR PFX "Bus powerup failed\n"); | 1360 | ssb_err("Bus powerup failed\n"); |
1366 | return err; | 1361 | return err; |
1367 | } | 1362 | } |
1368 | EXPORT_SYMBOL(ssb_bus_powerup); | 1363 | EXPORT_SYMBOL(ssb_bus_powerup); |
@@ -1470,15 +1465,13 @@ static int __init ssb_modinit(void) | |||
1470 | 1465 | ||
1471 | err = b43_pci_ssb_bridge_init(); | 1466 | err = b43_pci_ssb_bridge_init(); |
1472 | if (err) { | 1467 | if (err) { |
1473 | ssb_printk(KERN_ERR "Broadcom 43xx PCI-SSB-bridge " | 1468 | ssb_err("Broadcom 43xx PCI-SSB-bridge initialization failed\n"); |
1474 | "initialization failed\n"); | ||
1475 | /* don't fail SSB init because of this */ | 1469 | /* don't fail SSB init because of this */ |
1476 | err = 0; | 1470 | err = 0; |
1477 | } | 1471 | } |
1478 | err = ssb_gige_init(); | 1472 | err = ssb_gige_init(); |
1479 | if (err) { | 1473 | if (err) { |
1480 | ssb_printk(KERN_ERR "SSB Broadcom Gigabit Ethernet " | 1474 | ssb_err("SSB Broadcom Gigabit Ethernet driver initialization failed\n"); |
1481 | "driver initialization failed\n"); | ||
1482 | /* don't fail SSB init because of this */ | 1475 | /* don't fail SSB init because of this */ |
1483 | err = 0; | 1476 | err = 0; |
1484 | } | 1477 | } |
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c index e9d94968f394..63ff69f9d3eb 100644 --- a/drivers/ssb/pci.c +++ b/drivers/ssb/pci.c | |||
@@ -56,7 +56,7 @@ int ssb_pci_switch_coreidx(struct ssb_bus *bus, u8 coreidx) | |||
56 | } | 56 | } |
57 | return 0; | 57 | return 0; |
58 | error: | 58 | error: |
59 | ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx); | 59 | ssb_err("Failed to switch to core %u\n", coreidx); |
60 | return -ENODEV; | 60 | return -ENODEV; |
61 | } | 61 | } |
62 | 62 | ||
@@ -67,10 +67,9 @@ int ssb_pci_switch_core(struct ssb_bus *bus, | |||
67 | unsigned long flags; | 67 | unsigned long flags; |
68 | 68 | ||
69 | #if SSB_VERBOSE_PCICORESWITCH_DEBUG | 69 | #if SSB_VERBOSE_PCICORESWITCH_DEBUG |
70 | ssb_printk(KERN_INFO PFX | 70 | ssb_info("Switching to %s core, index %d\n", |
71 | "Switching to %s core, index %d\n", | 71 | ssb_core_name(dev->id.coreid), |
72 | ssb_core_name(dev->id.coreid), | 72 | dev->core_index); |
73 | dev->core_index); | ||
74 | #endif | 73 | #endif |
75 | 74 | ||
76 | spin_lock_irqsave(&bus->bar_lock, flags); | 75 | spin_lock_irqsave(&bus->bar_lock, flags); |
@@ -231,6 +230,15 @@ static inline u8 ssb_crc8(u8 crc, u8 data) | |||
231 | return t[crc ^ data]; | 230 | return t[crc ^ data]; |
232 | } | 231 | } |
233 | 232 | ||
233 | static void sprom_get_mac(char *mac, const u16 *in) | ||
234 | { | ||
235 | int i; | ||
236 | for (i = 0; i < 3; i++) { | ||
237 | *mac++ = in[i] >> 8; | ||
238 | *mac++ = in[i]; | ||
239 | } | ||
240 | } | ||
241 | |||
234 | static u8 ssb_sprom_crc(const u16 *sprom, u16 size) | 242 | static u8 ssb_sprom_crc(const u16 *sprom, u16 size) |
235 | { | 243 | { |
236 | int word; | 244 | int word; |
@@ -278,7 +286,7 @@ static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom) | |||
278 | u32 spromctl; | 286 | u32 spromctl; |
279 | u16 size = bus->sprom_size; | 287 | u16 size = bus->sprom_size; |
280 | 288 | ||
281 | ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n"); | 289 | ssb_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n"); |
282 | err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl); | 290 | err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl); |
283 | if (err) | 291 | if (err) |
284 | goto err_ctlreg; | 292 | goto err_ctlreg; |
@@ -286,17 +294,17 @@ static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom) | |||
286 | err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl); | 294 | err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl); |
287 | if (err) | 295 | if (err) |
288 | goto err_ctlreg; | 296 | goto err_ctlreg; |
289 | ssb_printk(KERN_NOTICE PFX "[ 0%%"); | 297 | ssb_notice("[ 0%%"); |
290 | msleep(500); | 298 | msleep(500); |
291 | for (i = 0; i < size; i++) { | 299 | for (i = 0; i < size; i++) { |
292 | if (i == size / 4) | 300 | if (i == size / 4) |
293 | ssb_printk("25%%"); | 301 | ssb_cont("25%%"); |
294 | else if (i == size / 2) | 302 | else if (i == size / 2) |
295 | ssb_printk("50%%"); | 303 | ssb_cont("50%%"); |
296 | else if (i == (size * 3) / 4) | 304 | else if (i == (size * 3) / 4) |
297 | ssb_printk("75%%"); | 305 | ssb_cont("75%%"); |
298 | else if (i % 2) | 306 | else if (i % 2) |
299 | ssb_printk("."); | 307 | ssb_cont("."); |
300 | writew(sprom[i], bus->mmio + bus->sprom_offset + (i * 2)); | 308 | writew(sprom[i], bus->mmio + bus->sprom_offset + (i * 2)); |
301 | mmiowb(); | 309 | mmiowb(); |
302 | msleep(20); | 310 | msleep(20); |
@@ -309,12 +317,12 @@ static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom) | |||
309 | if (err) | 317 | if (err) |
310 | goto err_ctlreg; | 318 | goto err_ctlreg; |
311 | msleep(500); | 319 | msleep(500); |
312 | ssb_printk("100%% ]\n"); | 320 | ssb_cont("100%% ]\n"); |
313 | ssb_printk(KERN_NOTICE PFX "SPROM written.\n"); | 321 | ssb_notice("SPROM written\n"); |
314 | 322 | ||
315 | return 0; | 323 | return 0; |
316 | err_ctlreg: | 324 | err_ctlreg: |
317 | ssb_printk(KERN_ERR PFX "Could not access SPROM control register.\n"); | 325 | ssb_err("Could not access SPROM control register.\n"); |
318 | return err; | 326 | return err; |
319 | } | 327 | } |
320 | 328 | ||
@@ -341,8 +349,6 @@ static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in, | |||
341 | 349 | ||
342 | static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) | 350 | static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) |
343 | { | 351 | { |
344 | int i; | ||
345 | u16 v; | ||
346 | u16 loc[3]; | 352 | u16 loc[3]; |
347 | 353 | ||
348 | if (out->revision == 3) /* rev 3 moved MAC */ | 354 | if (out->revision == 3) /* rev 3 moved MAC */ |
@@ -352,19 +358,10 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) | |||
352 | loc[1] = SSB_SPROM1_ET0MAC; | 358 | loc[1] = SSB_SPROM1_ET0MAC; |
353 | loc[2] = SSB_SPROM1_ET1MAC; | 359 | loc[2] = SSB_SPROM1_ET1MAC; |
354 | } | 360 | } |
355 | for (i = 0; i < 3; i++) { | 361 | sprom_get_mac(out->il0mac, &in[SPOFF(loc[0])]); |
356 | v = in[SPOFF(loc[0]) + i]; | ||
357 | *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); | ||
358 | } | ||
359 | if (out->revision < 3) { /* only rev 1-2 have et0, et1 */ | 362 | if (out->revision < 3) { /* only rev 1-2 have et0, et1 */ |
360 | for (i = 0; i < 3; i++) { | 363 | sprom_get_mac(out->et0mac, &in[SPOFF(loc[1])]); |
361 | v = in[SPOFF(loc[1]) + i]; | 364 | sprom_get_mac(out->et1mac, &in[SPOFF(loc[2])]); |
362 | *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v); | ||
363 | } | ||
364 | for (i = 0; i < 3; i++) { | ||
365 | v = in[SPOFF(loc[2]) + i]; | ||
366 | *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v); | ||
367 | } | ||
368 | } | 365 | } |
369 | SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0); | 366 | SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0); |
370 | SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A, | 367 | SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A, |
@@ -454,19 +451,15 @@ static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in) | |||
454 | 451 | ||
455 | static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) | 452 | static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) |
456 | { | 453 | { |
457 | int i; | ||
458 | u16 v; | ||
459 | u16 il0mac_offset; | 454 | u16 il0mac_offset; |
460 | 455 | ||
461 | if (out->revision == 4) | 456 | if (out->revision == 4) |
462 | il0mac_offset = SSB_SPROM4_IL0MAC; | 457 | il0mac_offset = SSB_SPROM4_IL0MAC; |
463 | else | 458 | else |
464 | il0mac_offset = SSB_SPROM5_IL0MAC; | 459 | il0mac_offset = SSB_SPROM5_IL0MAC; |
465 | /* extract the MAC address */ | 460 | |
466 | for (i = 0; i < 3; i++) { | 461 | sprom_get_mac(out->il0mac, &in[SPOFF(il0mac_offset)]); |
467 | v = in[SPOFF(il0mac_offset) + i]; | 462 | |
468 | *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); | ||
469 | } | ||
470 | SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0); | 463 | SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0); |
471 | SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A, | 464 | SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A, |
472 | SSB_SPROM4_ETHPHY_ET1A_SHIFT); | 465 | SSB_SPROM4_ETHPHY_ET1A_SHIFT); |
@@ -530,7 +523,7 @@ static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) | |||
530 | static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) | 523 | static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) |
531 | { | 524 | { |
532 | int i; | 525 | int i; |
533 | u16 v, o; | 526 | u16 o; |
534 | u16 pwr_info_offset[] = { | 527 | u16 pwr_info_offset[] = { |
535 | SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1, | 528 | SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1, |
536 | SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3 | 529 | SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3 |
@@ -539,10 +532,8 @@ static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) | |||
539 | ARRAY_SIZE(out->core_pwr_info)); | 532 | ARRAY_SIZE(out->core_pwr_info)); |
540 | 533 | ||
541 | /* extract the MAC address */ | 534 | /* extract the MAC address */ |
542 | for (i = 0; i < 3; i++) { | 535 | sprom_get_mac(out->il0mac, &in[SPOFF(SSB_SPROM8_IL0MAC)]); |
543 | v = in[SPOFF(SSB_SPROM8_IL0MAC) + i]; | 536 | |
544 | *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); | ||
545 | } | ||
546 | SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0); | 537 | SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0); |
547 | SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8); | 538 | SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8); |
548 | SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0); | 539 | SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0); |
@@ -743,7 +734,7 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, | |||
743 | memset(out, 0, sizeof(*out)); | 734 | memset(out, 0, sizeof(*out)); |
744 | 735 | ||
745 | out->revision = in[size - 1] & 0x00FF; | 736 | out->revision = in[size - 1] & 0x00FF; |
746 | ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision); | 737 | ssb_dbg("SPROM revision %d detected\n", out->revision); |
747 | memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */ | 738 | memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */ |
748 | memset(out->et1mac, 0xFF, 6); | 739 | memset(out->et1mac, 0xFF, 6); |
749 | 740 | ||
@@ -752,7 +743,7 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, | |||
752 | * number stored in the SPROM. | 743 | * number stored in the SPROM. |
753 | * Always extract r1. */ | 744 | * Always extract r1. */ |
754 | out->revision = 1; | 745 | out->revision = 1; |
755 | ssb_dprintk(KERN_DEBUG PFX "SPROM treated as revision %d\n", out->revision); | 746 | ssb_dbg("SPROM treated as revision %d\n", out->revision); |
756 | } | 747 | } |
757 | 748 | ||
758 | switch (out->revision) { | 749 | switch (out->revision) { |
@@ -769,9 +760,8 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, | |||
769 | sprom_extract_r8(out, in); | 760 | sprom_extract_r8(out, in); |
770 | break; | 761 | break; |
771 | default: | 762 | default: |
772 | ssb_printk(KERN_WARNING PFX "Unsupported SPROM" | 763 | ssb_warn("Unsupported SPROM revision %d detected. Will extract v1\n", |
773 | " revision %d detected. Will extract" | 764 | out->revision); |
774 | " v1\n", out->revision); | ||
775 | out->revision = 1; | 765 | out->revision = 1; |
776 | sprom_extract_r123(out, in); | 766 | sprom_extract_r123(out, in); |
777 | } | 767 | } |
@@ -791,7 +781,7 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, | |||
791 | u16 *buf; | 781 | u16 *buf; |
792 | 782 | ||
793 | if (!ssb_is_sprom_available(bus)) { | 783 | if (!ssb_is_sprom_available(bus)) { |
794 | ssb_printk(KERN_ERR PFX "No SPROM available!\n"); | 784 | ssb_err("No SPROM available!\n"); |
795 | return -ENODEV; | 785 | return -ENODEV; |
796 | } | 786 | } |
797 | if (bus->chipco.dev) { /* can be unavailable! */ | 787 | if (bus->chipco.dev) { /* can be unavailable! */ |
@@ -810,7 +800,7 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, | |||
810 | } else { | 800 | } else { |
811 | bus->sprom_offset = SSB_SPROM_BASE1; | 801 | bus->sprom_offset = SSB_SPROM_BASE1; |
812 | } | 802 | } |
813 | ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset); | 803 | ssb_dbg("SPROM offset is 0x%x\n", bus->sprom_offset); |
814 | 804 | ||
815 | buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL); | 805 | buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL); |
816 | if (!buf) | 806 | if (!buf) |
@@ -835,18 +825,15 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, | |||
835 | * available for this device in some other storage */ | 825 | * available for this device in some other storage */ |
836 | err = ssb_fill_sprom_with_fallback(bus, sprom); | 826 | err = ssb_fill_sprom_with_fallback(bus, sprom); |
837 | if (err) { | 827 | if (err) { |
838 | ssb_printk(KERN_WARNING PFX "WARNING: Using" | 828 | ssb_warn("WARNING: Using fallback SPROM failed (err %d)\n", |
839 | " fallback SPROM failed (err %d)\n", | 829 | err); |
840 | err); | ||
841 | } else { | 830 | } else { |
842 | ssb_dprintk(KERN_DEBUG PFX "Using SPROM" | 831 | ssb_dbg("Using SPROM revision %d provided by platform\n", |
843 | " revision %d provided by" | 832 | sprom->revision); |
844 | " platform.\n", sprom->revision); | ||
845 | err = 0; | 833 | err = 0; |
846 | goto out_free; | 834 | goto out_free; |
847 | } | 835 | } |
848 | ssb_printk(KERN_WARNING PFX "WARNING: Invalid" | 836 | ssb_warn("WARNING: Invalid SPROM CRC (corrupt SPROM)\n"); |
849 | " SPROM CRC (corrupt SPROM)\n"); | ||
850 | } | 837 | } |
851 | } | 838 | } |
852 | err = sprom_extract(bus, sprom, buf, bus->sprom_size); | 839 | err = sprom_extract(bus, sprom, buf, bus->sprom_size); |
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c index fbafed5b729b..b413e0187087 100644 --- a/drivers/ssb/pcmcia.c +++ b/drivers/ssb/pcmcia.c | |||
@@ -143,7 +143,7 @@ int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus, | |||
143 | 143 | ||
144 | return 0; | 144 | return 0; |
145 | error: | 145 | error: |
146 | ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx); | 146 | ssb_err("Failed to switch to core %u\n", coreidx); |
147 | return err; | 147 | return err; |
148 | } | 148 | } |
149 | 149 | ||
@@ -153,10 +153,9 @@ int ssb_pcmcia_switch_core(struct ssb_bus *bus, | |||
153 | int err; | 153 | int err; |
154 | 154 | ||
155 | #if SSB_VERBOSE_PCMCIACORESWITCH_DEBUG | 155 | #if SSB_VERBOSE_PCMCIACORESWITCH_DEBUG |
156 | ssb_printk(KERN_INFO PFX | 156 | ssb_info("Switching to %s core, index %d\n", |
157 | "Switching to %s core, index %d\n", | 157 | ssb_core_name(dev->id.coreid), |
158 | ssb_core_name(dev->id.coreid), | 158 | dev->core_index); |
159 | dev->core_index); | ||
160 | #endif | 159 | #endif |
161 | 160 | ||
162 | err = ssb_pcmcia_switch_coreidx(bus, dev->core_index); | 161 | err = ssb_pcmcia_switch_coreidx(bus, dev->core_index); |
@@ -192,7 +191,7 @@ int ssb_pcmcia_switch_segment(struct ssb_bus *bus, u8 seg) | |||
192 | 191 | ||
193 | return 0; | 192 | return 0; |
194 | error: | 193 | error: |
195 | ssb_printk(KERN_ERR PFX "Failed to switch pcmcia segment\n"); | 194 | ssb_err("Failed to switch pcmcia segment\n"); |
196 | return err; | 195 | return err; |
197 | } | 196 | } |
198 | 197 | ||
@@ -549,44 +548,39 @@ static int ssb_pcmcia_sprom_write_all(struct ssb_bus *bus, const u16 *sprom) | |||
549 | bool failed = 0; | 548 | bool failed = 0; |
550 | size_t size = SSB_PCMCIA_SPROM_SIZE; | 549 | size_t size = SSB_PCMCIA_SPROM_SIZE; |
551 | 550 | ||
552 | ssb_printk(KERN_NOTICE PFX | 551 | ssb_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n"); |
553 | "Writing SPROM. Do NOT turn off the power! " | ||
554 | "Please stand by...\n"); | ||
555 | err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEEN); | 552 | err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEEN); |
556 | if (err) { | 553 | if (err) { |
557 | ssb_printk(KERN_NOTICE PFX | 554 | ssb_notice("Could not enable SPROM write access\n"); |
558 | "Could not enable SPROM write access.\n"); | ||
559 | return -EBUSY; | 555 | return -EBUSY; |
560 | } | 556 | } |
561 | ssb_printk(KERN_NOTICE PFX "[ 0%%"); | 557 | ssb_notice("[ 0%%"); |
562 | msleep(500); | 558 | msleep(500); |
563 | for (i = 0; i < size; i++) { | 559 | for (i = 0; i < size; i++) { |
564 | if (i == size / 4) | 560 | if (i == size / 4) |
565 | ssb_printk("25%%"); | 561 | ssb_cont("25%%"); |
566 | else if (i == size / 2) | 562 | else if (i == size / 2) |
567 | ssb_printk("50%%"); | 563 | ssb_cont("50%%"); |
568 | else if (i == (size * 3) / 4) | 564 | else if (i == (size * 3) / 4) |
569 | ssb_printk("75%%"); | 565 | ssb_cont("75%%"); |
570 | else if (i % 2) | 566 | else if (i % 2) |
571 | ssb_printk("."); | 567 | ssb_cont("."); |
572 | err = ssb_pcmcia_sprom_write(bus, i, sprom[i]); | 568 | err = ssb_pcmcia_sprom_write(bus, i, sprom[i]); |
573 | if (err) { | 569 | if (err) { |
574 | ssb_printk(KERN_NOTICE PFX | 570 | ssb_notice("Failed to write to SPROM\n"); |
575 | "Failed to write to SPROM.\n"); | ||
576 | failed = 1; | 571 | failed = 1; |
577 | break; | 572 | break; |
578 | } | 573 | } |
579 | } | 574 | } |
580 | err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS); | 575 | err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS); |
581 | if (err) { | 576 | if (err) { |
582 | ssb_printk(KERN_NOTICE PFX | 577 | ssb_notice("Could not disable SPROM write access\n"); |
583 | "Could not disable SPROM write access.\n"); | ||
584 | failed = 1; | 578 | failed = 1; |
585 | } | 579 | } |
586 | msleep(500); | 580 | msleep(500); |
587 | if (!failed) { | 581 | if (!failed) { |
588 | ssb_printk("100%% ]\n"); | 582 | ssb_cont("100%% ]\n"); |
589 | ssb_printk(KERN_NOTICE PFX "SPROM written.\n"); | 583 | ssb_notice("SPROM written\n"); |
590 | } | 584 | } |
591 | 585 | ||
592 | return failed ? -EBUSY : 0; | 586 | return failed ? -EBUSY : 0; |
@@ -700,7 +694,7 @@ static int ssb_pcmcia_do_get_invariants(struct pcmcia_device *p_dev, | |||
700 | return -ENOSPC; /* continue with next entry */ | 694 | return -ENOSPC; /* continue with next entry */ |
701 | 695 | ||
702 | error: | 696 | error: |
703 | ssb_printk(KERN_ERR PFX | 697 | ssb_err( |
704 | "PCMCIA: Failed to fetch device invariants: %s\n", | 698 | "PCMCIA: Failed to fetch device invariants: %s\n", |
705 | error_description); | 699 | error_description); |
706 | return -ENODEV; | 700 | return -ENODEV; |
@@ -722,7 +716,7 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus, | |||
722 | res = pcmcia_loop_tuple(bus->host_pcmcia, CISTPL_FUNCE, | 716 | res = pcmcia_loop_tuple(bus->host_pcmcia, CISTPL_FUNCE, |
723 | ssb_pcmcia_get_mac, sprom); | 717 | ssb_pcmcia_get_mac, sprom); |
724 | if (res != 0) { | 718 | if (res != 0) { |
725 | ssb_printk(KERN_ERR PFX | 719 | ssb_err( |
726 | "PCMCIA: Failed to fetch MAC address\n"); | 720 | "PCMCIA: Failed to fetch MAC address\n"); |
727 | return -ENODEV; | 721 | return -ENODEV; |
728 | } | 722 | } |
@@ -733,7 +727,7 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus, | |||
733 | if ((res == 0) || (res == -ENOSPC)) | 727 | if ((res == 0) || (res == -ENOSPC)) |
734 | return 0; | 728 | return 0; |
735 | 729 | ||
736 | ssb_printk(KERN_ERR PFX | 730 | ssb_err( |
737 | "PCMCIA: Failed to fetch device invariants\n"); | 731 | "PCMCIA: Failed to fetch device invariants\n"); |
738 | return -ENODEV; | 732 | return -ENODEV; |
739 | } | 733 | } |
@@ -843,6 +837,6 @@ int ssb_pcmcia_init(struct ssb_bus *bus) | |||
843 | 837 | ||
844 | return 0; | 838 | return 0; |
845 | error: | 839 | error: |
846 | ssb_printk(KERN_ERR PFX "Failed to initialize PCMCIA host device\n"); | 840 | ssb_err("Failed to initialize PCMCIA host device\n"); |
847 | return err; | 841 | return err; |
848 | } | 842 | } |
diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c index ab4627cf1114..b9429df583eb 100644 --- a/drivers/ssb/scan.c +++ b/drivers/ssb/scan.c | |||
@@ -125,8 +125,7 @@ static u16 pcidev_to_chipid(struct pci_dev *pci_dev) | |||
125 | chipid_fallback = 0x4401; | 125 | chipid_fallback = 0x4401; |
126 | break; | 126 | break; |
127 | default: | 127 | default: |
128 | ssb_printk(KERN_ERR PFX | 128 | ssb_err("PCI-ID not in fallback list\n"); |
129 | "PCI-ID not in fallback list\n"); | ||
130 | } | 129 | } |
131 | 130 | ||
132 | return chipid_fallback; | 131 | return chipid_fallback; |
@@ -152,8 +151,7 @@ static u8 chipid_to_nrcores(u16 chipid) | |||
152 | case 0x4704: | 151 | case 0x4704: |
153 | return 9; | 152 | return 9; |
154 | default: | 153 | default: |
155 | ssb_printk(KERN_ERR PFX | 154 | ssb_err("CHIPID not in nrcores fallback list\n"); |
156 | "CHIPID not in nrcores fallback list\n"); | ||
157 | } | 155 | } |
158 | 156 | ||
159 | return 1; | 157 | return 1; |
@@ -320,15 +318,13 @@ int ssb_bus_scan(struct ssb_bus *bus, | |||
320 | bus->chip_package = 0; | 318 | bus->chip_package = 0; |
321 | } | 319 | } |
322 | } | 320 | } |
323 | ssb_printk(KERN_INFO PFX "Found chip with id 0x%04X, rev 0x%02X and " | 321 | ssb_info("Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n", |
324 | "package 0x%02X\n", bus->chip_id, bus->chip_rev, | 322 | bus->chip_id, bus->chip_rev, bus->chip_package); |
325 | bus->chip_package); | ||
326 | if (!bus->nr_devices) | 323 | if (!bus->nr_devices) |
327 | bus->nr_devices = chipid_to_nrcores(bus->chip_id); | 324 | bus->nr_devices = chipid_to_nrcores(bus->chip_id); |
328 | if (bus->nr_devices > ARRAY_SIZE(bus->devices)) { | 325 | if (bus->nr_devices > ARRAY_SIZE(bus->devices)) { |
329 | ssb_printk(KERN_ERR PFX | 326 | ssb_err("More than %d ssb cores found (%d)\n", |
330 | "More than %d ssb cores found (%d)\n", | 327 | SSB_MAX_NR_CORES, bus->nr_devices); |
331 | SSB_MAX_NR_CORES, bus->nr_devices); | ||
332 | goto err_unmap; | 328 | goto err_unmap; |
333 | } | 329 | } |
334 | if (bus->bustype == SSB_BUSTYPE_SSB) { | 330 | if (bus->bustype == SSB_BUSTYPE_SSB) { |
@@ -370,8 +366,7 @@ int ssb_bus_scan(struct ssb_bus *bus, | |||
370 | nr_80211_cores++; | 366 | nr_80211_cores++; |
371 | if (nr_80211_cores > 1) { | 367 | if (nr_80211_cores > 1) { |
372 | if (!we_support_multiple_80211_cores(bus)) { | 368 | if (!we_support_multiple_80211_cores(bus)) { |
373 | ssb_dprintk(KERN_INFO PFX "Ignoring additional " | 369 | ssb_dbg("Ignoring additional 802.11 core\n"); |
374 | "802.11 core\n"); | ||
375 | continue; | 370 | continue; |
376 | } | 371 | } |
377 | } | 372 | } |
@@ -379,8 +374,7 @@ int ssb_bus_scan(struct ssb_bus *bus, | |||
379 | case SSB_DEV_EXTIF: | 374 | case SSB_DEV_EXTIF: |
380 | #ifdef CONFIG_SSB_DRIVER_EXTIF | 375 | #ifdef CONFIG_SSB_DRIVER_EXTIF |
381 | if (bus->extif.dev) { | 376 | if (bus->extif.dev) { |
382 | ssb_printk(KERN_WARNING PFX | 377 | ssb_warn("WARNING: Multiple EXTIFs found\n"); |
383 | "WARNING: Multiple EXTIFs found\n"); | ||
384 | break; | 378 | break; |
385 | } | 379 | } |
386 | bus->extif.dev = dev; | 380 | bus->extif.dev = dev; |
@@ -388,8 +382,7 @@ int ssb_bus_scan(struct ssb_bus *bus, | |||
388 | break; | 382 | break; |
389 | case SSB_DEV_CHIPCOMMON: | 383 | case SSB_DEV_CHIPCOMMON: |
390 | if (bus->chipco.dev) { | 384 | if (bus->chipco.dev) { |
391 | ssb_printk(KERN_WARNING PFX | 385 | ssb_warn("WARNING: Multiple ChipCommon found\n"); |
392 | "WARNING: Multiple ChipCommon found\n"); | ||
393 | break; | 386 | break; |
394 | } | 387 | } |
395 | bus->chipco.dev = dev; | 388 | bus->chipco.dev = dev; |
@@ -398,8 +391,7 @@ int ssb_bus_scan(struct ssb_bus *bus, | |||
398 | case SSB_DEV_MIPS_3302: | 391 | case SSB_DEV_MIPS_3302: |
399 | #ifdef CONFIG_SSB_DRIVER_MIPS | 392 | #ifdef CONFIG_SSB_DRIVER_MIPS |
400 | if (bus->mipscore.dev) { | 393 | if (bus->mipscore.dev) { |
401 | ssb_printk(KERN_WARNING PFX | 394 | ssb_warn("WARNING: Multiple MIPS cores found\n"); |
402 | "WARNING: Multiple MIPS cores found\n"); | ||
403 | break; | 395 | break; |
404 | } | 396 | } |
405 | bus->mipscore.dev = dev; | 397 | bus->mipscore.dev = dev; |
@@ -420,8 +412,7 @@ int ssb_bus_scan(struct ssb_bus *bus, | |||
420 | } | 412 | } |
421 | } | 413 | } |
422 | if (bus->pcicore.dev) { | 414 | if (bus->pcicore.dev) { |
423 | ssb_printk(KERN_WARNING PFX | 415 | ssb_warn("WARNING: Multiple PCI(E) cores found\n"); |
424 | "WARNING: Multiple PCI(E) cores found\n"); | ||
425 | break; | 416 | break; |
426 | } | 417 | } |
427 | bus->pcicore.dev = dev; | 418 | bus->pcicore.dev = dev; |
diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c index 80d366fcf8d3..a3b23644b0fb 100644 --- a/drivers/ssb/sprom.c +++ b/drivers/ssb/sprom.c | |||
@@ -127,13 +127,13 @@ ssize_t ssb_attr_sprom_store(struct ssb_bus *bus, | |||
127 | goto out_kfree; | 127 | goto out_kfree; |
128 | err = ssb_devices_freeze(bus, &freeze); | 128 | err = ssb_devices_freeze(bus, &freeze); |
129 | if (err) { | 129 | if (err) { |
130 | ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n"); | 130 | ssb_err("SPROM write: Could not freeze all devices\n"); |
131 | goto out_unlock; | 131 | goto out_unlock; |
132 | } | 132 | } |
133 | res = sprom_write(bus, sprom); | 133 | res = sprom_write(bus, sprom); |
134 | err = ssb_devices_thaw(&freeze); | 134 | err = ssb_devices_thaw(&freeze); |
135 | if (err) | 135 | if (err) |
136 | ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n"); | 136 | ssb_err("SPROM write: Could not thaw all devices\n"); |
137 | out_unlock: | 137 | out_unlock: |
138 | mutex_unlock(&bus->sprom_mutex); | 138 | mutex_unlock(&bus->sprom_mutex); |
139 | out_kfree: | 139 | out_kfree: |
diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h index 466171b77f68..4671f17f09af 100644 --- a/drivers/ssb/ssb_private.h +++ b/drivers/ssb/ssb_private.h | |||
@@ -9,16 +9,27 @@ | |||
9 | #define PFX "ssb: " | 9 | #define PFX "ssb: " |
10 | 10 | ||
11 | #ifdef CONFIG_SSB_SILENT | 11 | #ifdef CONFIG_SSB_SILENT |
12 | # define ssb_printk(fmt, x...) do { /* nothing */ } while (0) | 12 | # define ssb_printk(fmt, ...) \ |
13 | do { if (0) printk(fmt, ##__VA_ARGS__); } while (0) | ||
13 | #else | 14 | #else |
14 | # define ssb_printk printk | 15 | # define ssb_printk(fmt, ...) \ |
16 | printk(fmt, ##__VA_ARGS__) | ||
15 | #endif /* CONFIG_SSB_SILENT */ | 17 | #endif /* CONFIG_SSB_SILENT */ |
16 | 18 | ||
19 | #define ssb_emerg(fmt, ...) ssb_printk(KERN_EMERG PFX fmt, ##__VA_ARGS__) | ||
20 | #define ssb_err(fmt, ...) ssb_printk(KERN_ERR PFX fmt, ##__VA_ARGS__) | ||
21 | #define ssb_warn(fmt, ...) ssb_printk(KERN_WARNING PFX fmt, ##__VA_ARGS__) | ||
22 | #define ssb_notice(fmt, ...) ssb_printk(KERN_NOTICE PFX fmt, ##__VA_ARGS__) | ||
23 | #define ssb_info(fmt, ...) ssb_printk(KERN_INFO PFX fmt, ##__VA_ARGS__) | ||
24 | #define ssb_cont(fmt, ...) ssb_printk(KERN_CONT fmt, ##__VA_ARGS__) | ||
25 | |||
17 | /* dprintk: Debugging printk; vanishes for non-debug compilation */ | 26 | /* dprintk: Debugging printk; vanishes for non-debug compilation */ |
18 | #ifdef CONFIG_SSB_DEBUG | 27 | #ifdef CONFIG_SSB_DEBUG |
19 | # define ssb_dprintk(fmt, x...) ssb_printk(fmt , ##x) | 28 | # define ssb_dbg(fmt, ...) \ |
29 | ssb_printk(KERN_DEBUG PFX fmt, ##__VA_ARGS__) | ||
20 | #else | 30 | #else |
21 | # define ssb_dprintk(fmt, x...) do { /* nothing */ } while (0) | 31 | # define ssb_dbg(fmt, ...) \ |
32 | do { if (0) printk(KERN_DEBUG PFX fmt, ##__VA_ARGS__); } while (0) | ||
22 | #endif | 33 | #endif |
23 | 34 | ||
24 | #ifdef CONFIG_SSB_DEBUG | 35 | #ifdef CONFIG_SSB_DEBUG |
diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c index 1956593ee89d..81e939e90c4c 100644 --- a/drivers/tty/hvc/hvcs.c +++ b/drivers/tty/hvc/hvcs.c | |||
@@ -881,17 +881,12 @@ static struct vio_driver hvcs_vio_driver = { | |||
881 | /* Only called from hvcs_get_pi please */ | 881 | /* Only called from hvcs_get_pi please */ |
882 | static void hvcs_set_pi(struct hvcs_partner_info *pi, struct hvcs_struct *hvcsd) | 882 | static void hvcs_set_pi(struct hvcs_partner_info *pi, struct hvcs_struct *hvcsd) |
883 | { | 883 | { |
884 | int clclength; | ||
885 | |||
886 | hvcsd->p_unit_address = pi->unit_address; | 884 | hvcsd->p_unit_address = pi->unit_address; |
887 | hvcsd->p_partition_ID = pi->partition_ID; | 885 | hvcsd->p_partition_ID = pi->partition_ID; |
888 | clclength = strlen(&pi->location_code[0]); | ||
889 | if (clclength > HVCS_CLC_LENGTH) | ||
890 | clclength = HVCS_CLC_LENGTH; | ||
891 | 886 | ||
892 | /* copy the null-term char too */ | 887 | /* copy the null-term char too */ |
893 | strncpy(&hvcsd->p_location_code[0], | 888 | strlcpy(&hvcsd->p_location_code[0], |
894 | &pi->location_code[0], clclength + 1); | 889 | &pi->location_code[0], sizeof(hvcsd->p_location_code)); |
895 | } | 890 | } |
896 | 891 | ||
897 | /* | 892 | /* |
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h index 29eb805ea4a6..c1d6555d2567 100644 --- a/include/linux/hardirq.h +++ b/include/linux/hardirq.h | |||
@@ -118,10 +118,8 @@ | |||
118 | 118 | ||
119 | #ifdef CONFIG_PREEMPT_COUNT | 119 | #ifdef CONFIG_PREEMPT_COUNT |
120 | # define preemptible() (preempt_count() == 0 && !irqs_disabled()) | 120 | # define preemptible() (preempt_count() == 0 && !irqs_disabled()) |
121 | # define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1) | ||
122 | #else | 121 | #else |
123 | # define preemptible() 0 | 122 | # define preemptible() 0 |
124 | # define IRQ_EXIT_OFFSET HARDIRQ_OFFSET | ||
125 | #endif | 123 | #endif |
126 | 124 | ||
127 | #if defined(CONFIG_SMP) || defined(CONFIG_GENERIC_HARDIRQS) | 125 | #if defined(CONFIG_SMP) || defined(CONFIG_GENERIC_HARDIRQS) |
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 7e24fe0cfbcd..4cf0c9e4dd99 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
@@ -113,6 +113,34 @@ | |||
113 | #define IEEE80211_CTL_EXT_SSW_FBACK 0x9000 | 113 | #define IEEE80211_CTL_EXT_SSW_FBACK 0x9000 |
114 | #define IEEE80211_CTL_EXT_SSW_ACK 0xa000 | 114 | #define IEEE80211_CTL_EXT_SSW_ACK 0xa000 |
115 | 115 | ||
116 | |||
117 | #define IEEE80211_SN_MASK ((IEEE80211_SCTL_SEQ) >> 4) | ||
118 | #define IEEE80211_MAX_SN IEEE80211_SN_MASK | ||
119 | #define IEEE80211_SN_MODULO (IEEE80211_MAX_SN + 1) | ||
120 | |||
121 | static inline int ieee80211_sn_less(u16 sn1, u16 sn2) | ||
122 | { | ||
123 | return ((sn1 - sn2) & IEEE80211_SN_MASK) > (IEEE80211_SN_MODULO >> 1); | ||
124 | } | ||
125 | |||
126 | static inline u16 ieee80211_sn_add(u16 sn1, u16 sn2) | ||
127 | { | ||
128 | return (sn1 + sn2) & IEEE80211_SN_MASK; | ||
129 | } | ||
130 | |||
131 | static inline u16 ieee80211_sn_inc(u16 sn) | ||
132 | { | ||
133 | return ieee80211_sn_add(sn, 1); | ||
134 | } | ||
135 | |||
136 | static inline u16 ieee80211_sn_sub(u16 sn1, u16 sn2) | ||
137 | { | ||
138 | return (sn1 - sn2) & IEEE80211_SN_MASK; | ||
139 | } | ||
140 | |||
141 | #define IEEE80211_SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) | ||
142 | #define IEEE80211_SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) | ||
143 | |||
116 | /* miscellaneous IEEE 802.11 constants */ | 144 | /* miscellaneous IEEE 802.11 constants */ |
117 | #define IEEE80211_MAX_FRAG_THRESHOLD 2352 | 145 | #define IEEE80211_MAX_FRAG_THRESHOLD 2352 |
118 | #define IEEE80211_MAX_RTS_THRESHOLD 2353 | 146 | #define IEEE80211_MAX_RTS_THRESHOLD 2353 |
@@ -185,7 +213,7 @@ struct ieee80211_hdr { | |||
185 | u8 addr3[6]; | 213 | u8 addr3[6]; |
186 | __le16 seq_ctrl; | 214 | __le16 seq_ctrl; |
187 | u8 addr4[6]; | 215 | u8 addr4[6]; |
188 | } __packed; | 216 | } __packed __aligned(2); |
189 | 217 | ||
190 | struct ieee80211_hdr_3addr { | 218 | struct ieee80211_hdr_3addr { |
191 | __le16 frame_control; | 219 | __le16 frame_control; |
@@ -194,7 +222,7 @@ struct ieee80211_hdr_3addr { | |||
194 | u8 addr2[6]; | 222 | u8 addr2[6]; |
195 | u8 addr3[6]; | 223 | u8 addr3[6]; |
196 | __le16 seq_ctrl; | 224 | __le16 seq_ctrl; |
197 | } __packed; | 225 | } __packed __aligned(2); |
198 | 226 | ||
199 | struct ieee80211_qos_hdr { | 227 | struct ieee80211_qos_hdr { |
200 | __le16 frame_control; | 228 | __le16 frame_control; |
@@ -204,7 +232,7 @@ struct ieee80211_qos_hdr { | |||
204 | u8 addr3[6]; | 232 | u8 addr3[6]; |
205 | __le16 seq_ctrl; | 233 | __le16 seq_ctrl; |
206 | __le16 qos_ctrl; | 234 | __le16 qos_ctrl; |
207 | } __packed; | 235 | } __packed __aligned(2); |
208 | 236 | ||
209 | /** | 237 | /** |
210 | * ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set | 238 | * ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set |
@@ -581,7 +609,7 @@ struct ieee80211s_hdr { | |||
581 | __le32 seqnum; | 609 | __le32 seqnum; |
582 | u8 eaddr1[6]; | 610 | u8 eaddr1[6]; |
583 | u8 eaddr2[6]; | 611 | u8 eaddr2[6]; |
584 | } __packed; | 612 | } __packed __aligned(2); |
585 | 613 | ||
586 | /* Mesh flags */ | 614 | /* Mesh flags */ |
587 | #define MESH_FLAGS_AE_A4 0x1 | 615 | #define MESH_FLAGS_AE_A4 0x1 |
@@ -875,7 +903,7 @@ struct ieee80211_mgmt { | |||
875 | } u; | 903 | } u; |
876 | } __packed action; | 904 | } __packed action; |
877 | } u; | 905 | } u; |
878 | } __packed; | 906 | } __packed __aligned(2); |
879 | 907 | ||
880 | /* Supported Rates value encodings in 802.11n-2009 7.3.2.2 */ | 908 | /* Supported Rates value encodings in 802.11n-2009 7.3.2.2 */ |
881 | #define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127 | 909 | #define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127 |
@@ -906,20 +934,20 @@ struct ieee80211_rts { | |||
906 | __le16 duration; | 934 | __le16 duration; |
907 | u8 ra[6]; | 935 | u8 ra[6]; |
908 | u8 ta[6]; | 936 | u8 ta[6]; |
909 | } __packed; | 937 | } __packed __aligned(2); |
910 | 938 | ||
911 | struct ieee80211_cts { | 939 | struct ieee80211_cts { |
912 | __le16 frame_control; | 940 | __le16 frame_control; |
913 | __le16 duration; | 941 | __le16 duration; |
914 | u8 ra[6]; | 942 | u8 ra[6]; |
915 | } __packed; | 943 | } __packed __aligned(2); |
916 | 944 | ||
917 | struct ieee80211_pspoll { | 945 | struct ieee80211_pspoll { |
918 | __le16 frame_control; | 946 | __le16 frame_control; |
919 | __le16 aid; | 947 | __le16 aid; |
920 | u8 bssid[6]; | 948 | u8 bssid[6]; |
921 | u8 ta[6]; | 949 | u8 ta[6]; |
922 | } __packed; | 950 | } __packed __aligned(2); |
923 | 951 | ||
924 | /* TDLS */ | 952 | /* TDLS */ |
925 | 953 | ||
@@ -1290,11 +1318,6 @@ struct ieee80211_vht_operation { | |||
1290 | } __packed; | 1318 | } __packed; |
1291 | 1319 | ||
1292 | 1320 | ||
1293 | #define IEEE80211_VHT_MCS_ZERO_TO_SEVEN_SUPPORT 0 | ||
1294 | #define IEEE80211_VHT_MCS_ZERO_TO_EIGHT_SUPPORT 1 | ||
1295 | #define IEEE80211_VHT_MCS_ZERO_TO_NINE_SUPPORT 2 | ||
1296 | #define IEEE80211_VHT_MCS_NOT_SUPPORTED 3 | ||
1297 | |||
1298 | /* 802.11ac VHT Capabilities */ | 1321 | /* 802.11ac VHT Capabilities */ |
1299 | #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000 | 1322 | #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000 |
1300 | #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001 | 1323 | #define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001 |
@@ -1310,10 +1333,11 @@ struct ieee80211_vht_operation { | |||
1310 | #define IEEE80211_VHT_CAP_RXSTBC_2 0x00000200 | 1333 | #define IEEE80211_VHT_CAP_RXSTBC_2 0x00000200 |
1311 | #define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300 | 1334 | #define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300 |
1312 | #define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400 | 1335 | #define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400 |
1336 | #define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700 | ||
1313 | #define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800 | 1337 | #define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800 |
1314 | #define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000 | 1338 | #define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000 |
1315 | #define IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX 0x00006000 | 1339 | #define IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX 0x00006000 |
1316 | #define IEEE80211_VHT_CAP_SOUNDING_DIMENTION_MAX 0x00030000 | 1340 | #define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX 0x00030000 |
1317 | #define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000 | 1341 | #define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000 |
1318 | #define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000 | 1342 | #define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000 |
1319 | #define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000 | 1343 | #define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000 |
diff --git a/include/linux/netfilter/ipset/ip_set_ahash.h b/include/linux/netfilter/ipset/ip_set_ahash.h index ef9acd3c8450..01d25e6fc792 100644 --- a/include/linux/netfilter/ipset/ip_set_ahash.h +++ b/include/linux/netfilter/ipset/ip_set_ahash.h | |||
@@ -854,6 +854,8 @@ type_pf_tresize(struct ip_set *set, bool retried) | |||
854 | retry: | 854 | retry: |
855 | ret = 0; | 855 | ret = 0; |
856 | htable_bits++; | 856 | htable_bits++; |
857 | pr_debug("attempt to resize set %s from %u to %u, t %p\n", | ||
858 | set->name, orig->htable_bits, htable_bits, orig); | ||
857 | if (!htable_bits) { | 859 | if (!htable_bits) { |
858 | /* In case we have plenty of memory :-) */ | 860 | /* In case we have plenty of memory :-) */ |
859 | pr_warning("Cannot increase the hashsize of set %s further\n", | 861 | pr_warning("Cannot increase the hashsize of set %s further\n", |
@@ -873,7 +875,7 @@ retry: | |||
873 | data = ahash_tdata(n, j); | 875 | data = ahash_tdata(n, j); |
874 | m = hbucket(t, HKEY(data, h->initval, htable_bits)); | 876 | m = hbucket(t, HKEY(data, h->initval, htable_bits)); |
875 | ret = type_pf_elem_tadd(m, data, AHASH_MAX(h), 0, | 877 | ret = type_pf_elem_tadd(m, data, AHASH_MAX(h), 0, |
876 | type_pf_data_timeout(data)); | 878 | ip_set_timeout_get(type_pf_data_timeout(data))); |
877 | if (ret < 0) { | 879 | if (ret < 0) { |
878 | read_unlock_bh(&set->lock); | 880 | read_unlock_bh(&set->lock); |
879 | ahash_destroy(t); | 881 | ahash_destroy(t); |
diff --git a/include/linux/smpboot.h b/include/linux/smpboot.h index c65dee059913..13e929679550 100644 --- a/include/linux/smpboot.h +++ b/include/linux/smpboot.h | |||
@@ -24,6 +24,9 @@ struct smpboot_thread_data; | |||
24 | * parked (cpu offline) | 24 | * parked (cpu offline) |
25 | * @unpark: Optional unpark function, called when the thread is | 25 | * @unpark: Optional unpark function, called when the thread is |
26 | * unparked (cpu online) | 26 | * unparked (cpu online) |
27 | * @pre_unpark: Optional unpark function, called before the thread is | ||
28 | * unparked (cpu online). This is not guaranteed to be | ||
29 | * called on the target cpu of the thread. Careful! | ||
27 | * @selfparking: Thread is not parked by the park function. | 30 | * @selfparking: Thread is not parked by the park function. |
28 | * @thread_comm: The base name of the thread | 31 | * @thread_comm: The base name of the thread |
29 | */ | 32 | */ |
@@ -37,6 +40,7 @@ struct smp_hotplug_thread { | |||
37 | void (*cleanup)(unsigned int cpu, bool online); | 40 | void (*cleanup)(unsigned int cpu, bool online); |
38 | void (*park)(unsigned int cpu); | 41 | void (*park)(unsigned int cpu); |
39 | void (*unpark)(unsigned int cpu); | 42 | void (*unpark)(unsigned int cpu); |
43 | void (*pre_unpark)(unsigned int cpu); | ||
40 | bool selfparking; | 44 | bool selfparking; |
41 | const char *thread_comm; | 45 | const char *thread_comm; |
42 | }; | 46 | }; |
diff --git a/include/linux/socket.h b/include/linux/socket.h index 2b9f74b0ffea..428c37a1f95c 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h | |||
@@ -298,6 +298,7 @@ struct ucred { | |||
298 | #define SOL_IUCV 277 | 298 | #define SOL_IUCV 277 |
299 | #define SOL_CAIF 278 | 299 | #define SOL_CAIF 278 |
300 | #define SOL_ALG 279 | 300 | #define SOL_ALG 279 |
301 | #define SOL_NFC 280 | ||
301 | 302 | ||
302 | /* IPX options */ | 303 | /* IPX options */ |
303 | #define IPX_TYPE 1 | 304 | #define IPX_TYPE 1 |
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index 22958d68ecfe..8b1322296fed 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h | |||
@@ -26,9 +26,9 @@ struct ssb_sprom_core_pwr_info { | |||
26 | 26 | ||
27 | struct ssb_sprom { | 27 | struct ssb_sprom { |
28 | u8 revision; | 28 | u8 revision; |
29 | u8 il0mac[6]; /* MAC address for 802.11b/g */ | 29 | u8 il0mac[6] __aligned(sizeof(u16)); /* MAC address for 802.11b/g */ |
30 | u8 et0mac[6]; /* MAC address for Ethernet */ | 30 | u8 et0mac[6] __aligned(sizeof(u16)); /* MAC address for Ethernet */ |
31 | u8 et1mac[6]; /* MAC address for 802.11a */ | 31 | u8 et1mac[6] __aligned(sizeof(u16)); /* MAC address for 802.11a */ |
32 | u8 et0phyaddr; /* MII address for enet0 */ | 32 | u8 et0phyaddr; /* MII address for enet0 */ |
33 | u8 et1phyaddr; /* MII address for enet1 */ | 33 | u8 et1phyaddr; /* MII address for enet1 */ |
34 | u8 et0mdcport; /* MDIO for enet0 */ | 34 | u8 et0mdcport; /* MDIO for enet0 */ |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index d581c6de5d64..bdba9b619064 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -611,22 +611,10 @@ struct cfg80211_ap_settings { | |||
611 | }; | 611 | }; |
612 | 612 | ||
613 | /** | 613 | /** |
614 | * enum plink_action - actions to perform in mesh peers | ||
615 | * | ||
616 | * @PLINK_ACTION_INVALID: action 0 is reserved | ||
617 | * @PLINK_ACTION_OPEN: start mesh peer link establishment | ||
618 | * @PLINK_ACTION_BLOCK: block traffic from this mesh peer | ||
619 | */ | ||
620 | enum plink_actions { | ||
621 | PLINK_ACTION_INVALID, | ||
622 | PLINK_ACTION_OPEN, | ||
623 | PLINK_ACTION_BLOCK, | ||
624 | }; | ||
625 | |||
626 | /** | ||
627 | * enum station_parameters_apply_mask - station parameter values to apply | 614 | * enum station_parameters_apply_mask - station parameter values to apply |
628 | * @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp) | 615 | * @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp) |
629 | * @STATION_PARAM_APPLY_CAPABILITY: apply new capability | 616 | * @STATION_PARAM_APPLY_CAPABILITY: apply new capability |
617 | * @STATION_PARAM_APPLY_PLINK_STATE: apply new plink state | ||
630 | * | 618 | * |
631 | * Not all station parameters have in-band "no change" signalling, | 619 | * Not all station parameters have in-band "no change" signalling, |
632 | * for those that don't these flags will are used. | 620 | * for those that don't these flags will are used. |
@@ -634,6 +622,7 @@ enum plink_actions { | |||
634 | enum station_parameters_apply_mask { | 622 | enum station_parameters_apply_mask { |
635 | STATION_PARAM_APPLY_UAPSD = BIT(0), | 623 | STATION_PARAM_APPLY_UAPSD = BIT(0), |
636 | STATION_PARAM_APPLY_CAPABILITY = BIT(1), | 624 | STATION_PARAM_APPLY_CAPABILITY = BIT(1), |
625 | STATION_PARAM_APPLY_PLINK_STATE = BIT(2), | ||
637 | }; | 626 | }; |
638 | 627 | ||
639 | /** | 628 | /** |
@@ -669,7 +658,7 @@ enum station_parameters_apply_mask { | |||
669 | * @ext_capab_len: number of extended capabilities | 658 | * @ext_capab_len: number of extended capabilities |
670 | */ | 659 | */ |
671 | struct station_parameters { | 660 | struct station_parameters { |
672 | u8 *supported_rates; | 661 | const u8 *supported_rates; |
673 | struct net_device *vlan; | 662 | struct net_device *vlan; |
674 | u32 sta_flags_mask, sta_flags_set; | 663 | u32 sta_flags_mask, sta_flags_set; |
675 | u32 sta_modify_mask; | 664 | u32 sta_modify_mask; |
@@ -678,17 +667,60 @@ struct station_parameters { | |||
678 | u8 supported_rates_len; | 667 | u8 supported_rates_len; |
679 | u8 plink_action; | 668 | u8 plink_action; |
680 | u8 plink_state; | 669 | u8 plink_state; |
681 | struct ieee80211_ht_cap *ht_capa; | 670 | const struct ieee80211_ht_cap *ht_capa; |
682 | struct ieee80211_vht_cap *vht_capa; | 671 | const struct ieee80211_vht_cap *vht_capa; |
683 | u8 uapsd_queues; | 672 | u8 uapsd_queues; |
684 | u8 max_sp; | 673 | u8 max_sp; |
685 | enum nl80211_mesh_power_mode local_pm; | 674 | enum nl80211_mesh_power_mode local_pm; |
686 | u16 capability; | 675 | u16 capability; |
687 | u8 *ext_capab; | 676 | const u8 *ext_capab; |
688 | u8 ext_capab_len; | 677 | u8 ext_capab_len; |
689 | }; | 678 | }; |
690 | 679 | ||
691 | /** | 680 | /** |
681 | * enum cfg80211_station_type - the type of station being modified | ||
682 | * @CFG80211_STA_AP_CLIENT: client of an AP interface | ||
683 | * @CFG80211_STA_AP_MLME_CLIENT: client of an AP interface that has | ||
684 | * the AP MLME in the device | ||
685 | * @CFG80211_STA_AP_STA: AP station on managed interface | ||
686 | * @CFG80211_STA_IBSS: IBSS station | ||
687 | * @CFG80211_STA_TDLS_PEER_SETUP: TDLS peer on managed interface (dummy entry | ||
688 | * while TDLS setup is in progress, it moves out of this state when | ||
689 | * being marked authorized; use this only if TDLS with external setup is | ||
690 | * supported/used) | ||
691 | * @CFG80211_STA_TDLS_PEER_ACTIVE: TDLS peer on managed interface (active | ||
692 | * entry that is operating, has been marked authorized by userspace) | ||
693 | * @CFG80211_STA_MESH_PEER_KERNEL: peer on mesh interface (kernel managed) | ||
694 | * @CFG80211_STA_MESH_PEER_USER: peer on mesh interface (user managed) | ||
695 | */ | ||
696 | enum cfg80211_station_type { | ||
697 | CFG80211_STA_AP_CLIENT, | ||
698 | CFG80211_STA_AP_MLME_CLIENT, | ||
699 | CFG80211_STA_AP_STA, | ||
700 | CFG80211_STA_IBSS, | ||
701 | CFG80211_STA_TDLS_PEER_SETUP, | ||
702 | CFG80211_STA_TDLS_PEER_ACTIVE, | ||
703 | CFG80211_STA_MESH_PEER_KERNEL, | ||
704 | CFG80211_STA_MESH_PEER_USER, | ||
705 | }; | ||
706 | |||
707 | /** | ||
708 | * cfg80211_check_station_change - validate parameter changes | ||
709 | * @wiphy: the wiphy this operates on | ||
710 | * @params: the new parameters for a station | ||
711 | * @statype: the type of station being modified | ||
712 | * | ||
713 | * Utility function for the @change_station driver method. Call this function | ||
714 | * with the appropriate station type looking up the station (and checking that | ||
715 | * it exists). It will verify whether the station change is acceptable, and if | ||
716 | * not will return an error code. Note that it may modify the parameters for | ||
717 | * backward compatibility reasons, so don't use them before calling this. | ||
718 | */ | ||
719 | int cfg80211_check_station_change(struct wiphy *wiphy, | ||
720 | struct station_parameters *params, | ||
721 | enum cfg80211_station_type statype); | ||
722 | |||
723 | /** | ||
692 | * enum station_info_flags - station information flags | 724 | * enum station_info_flags - station information flags |
693 | * | 725 | * |
694 | * Used by the driver to indicate which info in &struct station_info | 726 | * Used by the driver to indicate which info in &struct station_info |
@@ -1119,6 +1151,7 @@ struct mesh_config { | |||
1119 | * @ie_len: length of vendor information elements | 1151 | * @ie_len: length of vendor information elements |
1120 | * @is_authenticated: this mesh requires authentication | 1152 | * @is_authenticated: this mesh requires authentication |
1121 | * @is_secure: this mesh uses security | 1153 | * @is_secure: this mesh uses security |
1154 | * @user_mpm: userspace handles all MPM functions | ||
1122 | * @dtim_period: DTIM period to use | 1155 | * @dtim_period: DTIM period to use |
1123 | * @beacon_interval: beacon interval to use | 1156 | * @beacon_interval: beacon interval to use |
1124 | * @mcast_rate: multicat rate for Mesh Node [6Mbps is the default for 802.11a] | 1157 | * @mcast_rate: multicat rate for Mesh Node [6Mbps is the default for 802.11a] |
@@ -1136,6 +1169,7 @@ struct mesh_setup { | |||
1136 | u8 ie_len; | 1169 | u8 ie_len; |
1137 | bool is_authenticated; | 1170 | bool is_authenticated; |
1138 | bool is_secure; | 1171 | bool is_secure; |
1172 | bool user_mpm; | ||
1139 | u8 dtim_period; | 1173 | u8 dtim_period; |
1140 | u16 beacon_interval; | 1174 | u16 beacon_interval; |
1141 | int mcast_rate[IEEE80211_NUM_BANDS]; | 1175 | int mcast_rate[IEEE80211_NUM_BANDS]; |
@@ -1398,9 +1432,11 @@ struct cfg80211_auth_request { | |||
1398 | * enum cfg80211_assoc_req_flags - Over-ride default behaviour in association. | 1432 | * enum cfg80211_assoc_req_flags - Over-ride default behaviour in association. |
1399 | * | 1433 | * |
1400 | * @ASSOC_REQ_DISABLE_HT: Disable HT (802.11n) | 1434 | * @ASSOC_REQ_DISABLE_HT: Disable HT (802.11n) |
1435 | * @ASSOC_REQ_DISABLE_VHT: Disable VHT | ||
1401 | */ | 1436 | */ |
1402 | enum cfg80211_assoc_req_flags { | 1437 | enum cfg80211_assoc_req_flags { |
1403 | ASSOC_REQ_DISABLE_HT = BIT(0), | 1438 | ASSOC_REQ_DISABLE_HT = BIT(0), |
1439 | ASSOC_REQ_DISABLE_VHT = BIT(1), | ||
1404 | }; | 1440 | }; |
1405 | 1441 | ||
1406 | /** | 1442 | /** |
@@ -1422,6 +1458,8 @@ enum cfg80211_assoc_req_flags { | |||
1422 | * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask | 1458 | * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask |
1423 | * will be used in ht_capa. Un-supported values will be ignored. | 1459 | * will be used in ht_capa. Un-supported values will be ignored. |
1424 | * @ht_capa_mask: The bits of ht_capa which are to be used. | 1460 | * @ht_capa_mask: The bits of ht_capa which are to be used. |
1461 | * @vht_capa: VHT capability override | ||
1462 | * @vht_capa_mask: VHT capability mask indicating which fields to use | ||
1425 | */ | 1463 | */ |
1426 | struct cfg80211_assoc_request { | 1464 | struct cfg80211_assoc_request { |
1427 | struct cfg80211_bss *bss; | 1465 | struct cfg80211_bss *bss; |
@@ -1432,6 +1470,7 @@ struct cfg80211_assoc_request { | |||
1432 | u32 flags; | 1470 | u32 flags; |
1433 | struct ieee80211_ht_cap ht_capa; | 1471 | struct ieee80211_ht_cap ht_capa; |
1434 | struct ieee80211_ht_cap ht_capa_mask; | 1472 | struct ieee80211_ht_cap ht_capa_mask; |
1473 | struct ieee80211_vht_cap vht_capa, vht_capa_mask; | ||
1435 | }; | 1474 | }; |
1436 | 1475 | ||
1437 | /** | 1476 | /** |
@@ -1542,6 +1581,8 @@ struct cfg80211_ibss_params { | |||
1542 | * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask | 1581 | * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask |
1543 | * will be used in ht_capa. Un-supported values will be ignored. | 1582 | * will be used in ht_capa. Un-supported values will be ignored. |
1544 | * @ht_capa_mask: The bits of ht_capa which are to be used. | 1583 | * @ht_capa_mask: The bits of ht_capa which are to be used. |
1584 | * @vht_capa: VHT Capability overrides | ||
1585 | * @vht_capa_mask: The bits of vht_capa which are to be used. | ||
1545 | */ | 1586 | */ |
1546 | struct cfg80211_connect_params { | 1587 | struct cfg80211_connect_params { |
1547 | struct ieee80211_channel *channel; | 1588 | struct ieee80211_channel *channel; |
@@ -1560,6 +1601,8 @@ struct cfg80211_connect_params { | |||
1560 | int bg_scan_period; | 1601 | int bg_scan_period; |
1561 | struct ieee80211_ht_cap ht_capa; | 1602 | struct ieee80211_ht_cap ht_capa; |
1562 | struct ieee80211_ht_cap ht_capa_mask; | 1603 | struct ieee80211_ht_cap ht_capa_mask; |
1604 | struct ieee80211_vht_cap vht_capa; | ||
1605 | struct ieee80211_vht_cap vht_capa_mask; | ||
1563 | }; | 1606 | }; |
1564 | 1607 | ||
1565 | /** | 1608 | /** |
@@ -1722,6 +1765,21 @@ struct cfg80211_gtk_rekey_data { | |||
1722 | }; | 1765 | }; |
1723 | 1766 | ||
1724 | /** | 1767 | /** |
1768 | * struct cfg80211_update_ft_ies_params - FT IE Information | ||
1769 | * | ||
1770 | * This structure provides information needed to update the fast transition IE | ||
1771 | * | ||
1772 | * @md: The Mobility Domain ID, 2 Octet value | ||
1773 | * @ie: Fast Transition IEs | ||
1774 | * @ie_len: Length of ft_ie in octets | ||
1775 | */ | ||
1776 | struct cfg80211_update_ft_ies_params { | ||
1777 | u16 md; | ||
1778 | const u8 *ie; | ||
1779 | size_t ie_len; | ||
1780 | }; | ||
1781 | |||
1782 | /** | ||
1725 | * struct cfg80211_ops - backend description for wireless configuration | 1783 | * struct cfg80211_ops - backend description for wireless configuration |
1726 | * | 1784 | * |
1727 | * This struct is registered by fullmac card drivers and/or wireless stacks | 1785 | * This struct is registered by fullmac card drivers and/or wireless stacks |
@@ -1781,9 +1839,8 @@ struct cfg80211_gtk_rekey_data { | |||
1781 | * @change_station: Modify a given station. Note that flags changes are not much | 1839 | * @change_station: Modify a given station. Note that flags changes are not much |
1782 | * validated in cfg80211, in particular the auth/assoc/authorized flags | 1840 | * validated in cfg80211, in particular the auth/assoc/authorized flags |
1783 | * might come to the driver in invalid combinations -- make sure to check | 1841 | * might come to the driver in invalid combinations -- make sure to check |
1784 | * them, also against the existing state! Also, supported_rates changes are | 1842 | * them, also against the existing state! Drivers must call |
1785 | * not checked in station mode -- drivers need to reject (or ignore) them | 1843 | * cfg80211_check_station_change() to validate the information. |
1786 | * for anything but TDLS peers. | ||
1787 | * @get_station: get station information for the station identified by @mac | 1844 | * @get_station: get station information for the station identified by @mac |
1788 | * @dump_station: dump station callback -- resume dump at index @idx | 1845 | * @dump_station: dump station callback -- resume dump at index @idx |
1789 | * | 1846 | * |
@@ -2168,6 +2225,8 @@ struct cfg80211_ops { | |||
2168 | int (*start_radar_detection)(struct wiphy *wiphy, | 2225 | int (*start_radar_detection)(struct wiphy *wiphy, |
2169 | struct net_device *dev, | 2226 | struct net_device *dev, |
2170 | struct cfg80211_chan_def *chandef); | 2227 | struct cfg80211_chan_def *chandef); |
2228 | int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev, | ||
2229 | struct cfg80211_update_ft_ies_params *ftie); | ||
2171 | }; | 2230 | }; |
2172 | 2231 | ||
2173 | /* | 2232 | /* |
@@ -2485,6 +2544,8 @@ struct wiphy_wowlan_support { | |||
2485 | * @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features. | 2544 | * @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features. |
2486 | * @ht_capa_mod_mask: Specify what ht_cap values can be over-ridden. | 2545 | * @ht_capa_mod_mask: Specify what ht_cap values can be over-ridden. |
2487 | * If null, then none can be over-ridden. | 2546 | * If null, then none can be over-ridden. |
2547 | * @vht_capa_mod_mask: Specify what VHT capabilities can be over-ridden. | ||
2548 | * If null, then none can be over-ridden. | ||
2488 | * | 2549 | * |
2489 | * @max_acl_mac_addrs: Maximum number of MAC addresses that the device | 2550 | * @max_acl_mac_addrs: Maximum number of MAC addresses that the device |
2490 | * supports for ACL. | 2551 | * supports for ACL. |
@@ -2593,6 +2654,7 @@ struct wiphy { | |||
2593 | struct dentry *debugfsdir; | 2654 | struct dentry *debugfsdir; |
2594 | 2655 | ||
2595 | const struct ieee80211_ht_cap *ht_capa_mod_mask; | 2656 | const struct ieee80211_ht_cap *ht_capa_mod_mask; |
2657 | const struct ieee80211_vht_cap *vht_capa_mod_mask; | ||
2596 | 2658 | ||
2597 | #ifdef CONFIG_NET_NS | 2659 | #ifdef CONFIG_NET_NS |
2598 | /* the network namespace this phy lives in currently */ | 2660 | /* the network namespace this phy lives in currently */ |
@@ -4002,6 +4064,30 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate); | |||
4002 | void cfg80211_unregister_wdev(struct wireless_dev *wdev); | 4064 | void cfg80211_unregister_wdev(struct wireless_dev *wdev); |
4003 | 4065 | ||
4004 | /** | 4066 | /** |
4067 | * struct cfg80211_ft_event - FT Information Elements | ||
4068 | * @ies: FT IEs | ||
4069 | * @ies_len: length of the FT IE in bytes | ||
4070 | * @target_ap: target AP's MAC address | ||
4071 | * @ric_ies: RIC IE | ||
4072 | * @ric_ies_len: length of the RIC IE in bytes | ||
4073 | */ | ||
4074 | struct cfg80211_ft_event_params { | ||
4075 | const u8 *ies; | ||
4076 | size_t ies_len; | ||
4077 | const u8 *target_ap; | ||
4078 | const u8 *ric_ies; | ||
4079 | size_t ric_ies_len; | ||
4080 | }; | ||
4081 | |||
4082 | /** | ||
4083 | * cfg80211_ft_event - notify userspace about FT IE and RIC IE | ||
4084 | * @netdev: network device | ||
4085 | * @ft_event: IE information | ||
4086 | */ | ||
4087 | void cfg80211_ft_event(struct net_device *netdev, | ||
4088 | struct cfg80211_ft_event_params *ft_event); | ||
4089 | |||
4090 | /** | ||
4005 | * cfg80211_get_p2p_attr - find and copy a P2P attribute from IE buffer | 4091 | * cfg80211_get_p2p_attr - find and copy a P2P attribute from IE buffer |
4006 | * @ies: the input IE buffer | 4092 | * @ies: the input IE buffer |
4007 | * @len: the input length | 4093 | * @len: the input length |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index f7eba1300d82..cdd7cea1fd4c 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -1101,8 +1101,6 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif) | |||
1101 | * These flags are used for communication about keys between the driver | 1101 | * These flags are used for communication about keys between the driver |
1102 | * and mac80211, with the @flags parameter of &struct ieee80211_key_conf. | 1102 | * and mac80211, with the @flags parameter of &struct ieee80211_key_conf. |
1103 | * | 1103 | * |
1104 | * @IEEE80211_KEY_FLAG_WMM_STA: Set by mac80211, this flag indicates | ||
1105 | * that the STA this key will be used with could be using QoS. | ||
1106 | * @IEEE80211_KEY_FLAG_GENERATE_IV: This flag should be set by the | 1104 | * @IEEE80211_KEY_FLAG_GENERATE_IV: This flag should be set by the |
1107 | * driver to indicate that it requires IV generation for this | 1105 | * driver to indicate that it requires IV generation for this |
1108 | * particular key. | 1106 | * particular key. |
@@ -1127,7 +1125,6 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif) | |||
1127 | * %IEEE80211_KEY_FLAG_SW_MGMT_TX flag to encrypt such frames in SW. | 1125 | * %IEEE80211_KEY_FLAG_SW_MGMT_TX flag to encrypt such frames in SW. |
1128 | */ | 1126 | */ |
1129 | enum ieee80211_key_flags { | 1127 | enum ieee80211_key_flags { |
1130 | IEEE80211_KEY_FLAG_WMM_STA = 1<<0, | ||
1131 | IEEE80211_KEY_FLAG_GENERATE_IV = 1<<1, | 1128 | IEEE80211_KEY_FLAG_GENERATE_IV = 1<<1, |
1132 | IEEE80211_KEY_FLAG_GENERATE_MMIC= 1<<2, | 1129 | IEEE80211_KEY_FLAG_GENERATE_MMIC= 1<<2, |
1133 | IEEE80211_KEY_FLAG_PAIRWISE = 1<<3, | 1130 | IEEE80211_KEY_FLAG_PAIRWISE = 1<<3, |
@@ -1231,9 +1228,8 @@ enum ieee80211_sta_rx_bandwidth { | |||
1231 | * @addr: MAC address | 1228 | * @addr: MAC address |
1232 | * @aid: AID we assigned to the station if we're an AP | 1229 | * @aid: AID we assigned to the station if we're an AP |
1233 | * @supp_rates: Bitmap of supported rates (per band) | 1230 | * @supp_rates: Bitmap of supported rates (per band) |
1234 | * @ht_cap: HT capabilities of this STA; restricted to our own TX capabilities | 1231 | * @ht_cap: HT capabilities of this STA; restricted to our own capabilities |
1235 | * @vht_cap: VHT capabilities of this STA; Not restricting any capabilities | 1232 | * @vht_cap: VHT capabilities of this STA; restricted to our own capabilities |
1236 | * of remote STA. Taking as is. | ||
1237 | * @wme: indicates whether the STA supports WME. Only valid during AP-mode. | 1233 | * @wme: indicates whether the STA supports WME. Only valid during AP-mode. |
1238 | * @drv_priv: data area for driver use, will always be aligned to | 1234 | * @drv_priv: data area for driver use, will always be aligned to |
1239 | * sizeof(void *), size is determined in hw information. | 1235 | * sizeof(void *), size is determined in hw information. |
@@ -2135,6 +2131,24 @@ enum ieee80211_rate_control_changed { | |||
2135 | }; | 2131 | }; |
2136 | 2132 | ||
2137 | /** | 2133 | /** |
2134 | * enum ieee80211_roc_type - remain on channel type | ||
2135 | * | ||
2136 | * With the support for multi channel contexts and multi channel operations, | ||
2137 | * remain on channel operations might be limited/deferred/aborted by other | ||
2138 | * flows/operations which have higher priority (and vise versa). | ||
2139 | * Specifying the ROC type can be used by devices to prioritize the ROC | ||
2140 | * operations compared to other operations/flows. | ||
2141 | * | ||
2142 | * @IEEE80211_ROC_TYPE_NORMAL: There are no special requirements for this ROC. | ||
2143 | * @IEEE80211_ROC_TYPE_MGMT_TX: The remain on channel request is required | ||
2144 | * for sending managment frames offchannel. | ||
2145 | */ | ||
2146 | enum ieee80211_roc_type { | ||
2147 | IEEE80211_ROC_TYPE_NORMAL = 0, | ||
2148 | IEEE80211_ROC_TYPE_MGMT_TX, | ||
2149 | }; | ||
2150 | |||
2151 | /** | ||
2138 | * struct ieee80211_ops - callbacks from mac80211 to the driver | 2152 | * struct ieee80211_ops - callbacks from mac80211 to the driver |
2139 | * | 2153 | * |
2140 | * This structure contains various callbacks that the driver may | 2154 | * This structure contains various callbacks that the driver may |
@@ -2687,7 +2701,8 @@ struct ieee80211_ops { | |||
2687 | int (*remain_on_channel)(struct ieee80211_hw *hw, | 2701 | int (*remain_on_channel)(struct ieee80211_hw *hw, |
2688 | struct ieee80211_vif *vif, | 2702 | struct ieee80211_vif *vif, |
2689 | struct ieee80211_channel *chan, | 2703 | struct ieee80211_channel *chan, |
2690 | int duration); | 2704 | int duration, |
2705 | enum ieee80211_roc_type type); | ||
2691 | int (*cancel_remain_on_channel)(struct ieee80211_hw *hw); | 2706 | int (*cancel_remain_on_channel)(struct ieee80211_hw *hw); |
2692 | int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx); | 2707 | int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx); |
2693 | void (*get_ringparam)(struct ieee80211_hw *hw, | 2708 | void (*get_ringparam)(struct ieee80211_hw *hw, |
diff --git a/include/net/tcp.h b/include/net/tcp.h index 23f2e98d4b65..cf0694d4ad60 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -1045,6 +1045,10 @@ static inline bool tcp_prequeue(struct sock *sk, struct sk_buff *skb) | |||
1045 | if (sysctl_tcp_low_latency || !tp->ucopy.task) | 1045 | if (sysctl_tcp_low_latency || !tp->ucopy.task) |
1046 | return false; | 1046 | return false; |
1047 | 1047 | ||
1048 | if (skb->len <= tcp_hdrlen(skb) && | ||
1049 | skb_queue_len(&tp->ucopy.prequeue) == 0) | ||
1050 | return false; | ||
1051 | |||
1048 | __skb_queue_tail(&tp->ucopy.prequeue, skb); | 1052 | __skb_queue_tail(&tp->ucopy.prequeue, skb); |
1049 | tp->ucopy.memory += skb->truesize; | 1053 | tp->ucopy.memory += skb->truesize; |
1050 | if (tp->ucopy.memory > sk->sk_rcvbuf) { | 1054 | if (tp->ucopy.memory > sk->sk_rcvbuf) { |
diff --git a/include/uapi/linux/nfc.h b/include/uapi/linux/nfc.h index 7969f46f1bb3..7440bc81a04b 100644 --- a/include/uapi/linux/nfc.h +++ b/include/uapi/linux/nfc.h | |||
@@ -90,6 +90,8 @@ enum nfc_commands { | |||
90 | NFC_CMD_LLC_SET_PARAMS, | 90 | NFC_CMD_LLC_SET_PARAMS, |
91 | NFC_CMD_ENABLE_SE, | 91 | NFC_CMD_ENABLE_SE, |
92 | NFC_CMD_DISABLE_SE, | 92 | NFC_CMD_DISABLE_SE, |
93 | NFC_CMD_LLC_SDREQ, | ||
94 | NFC_EVENT_LLC_SDRES, | ||
93 | /* private: internal use only */ | 95 | /* private: internal use only */ |
94 | __NFC_CMD_AFTER_LAST | 96 | __NFC_CMD_AFTER_LAST |
95 | }; | 97 | }; |
@@ -140,11 +142,21 @@ enum nfc_attrs { | |||
140 | NFC_ATTR_LLC_PARAM_RW, | 142 | NFC_ATTR_LLC_PARAM_RW, |
141 | NFC_ATTR_LLC_PARAM_MIUX, | 143 | NFC_ATTR_LLC_PARAM_MIUX, |
142 | NFC_ATTR_SE, | 144 | NFC_ATTR_SE, |
145 | NFC_ATTR_LLC_SDP, | ||
143 | /* private: internal use only */ | 146 | /* private: internal use only */ |
144 | __NFC_ATTR_AFTER_LAST | 147 | __NFC_ATTR_AFTER_LAST |
145 | }; | 148 | }; |
146 | #define NFC_ATTR_MAX (__NFC_ATTR_AFTER_LAST - 1) | 149 | #define NFC_ATTR_MAX (__NFC_ATTR_AFTER_LAST - 1) |
147 | 150 | ||
151 | enum nfc_sdp_attr { | ||
152 | NFC_SDP_ATTR_UNSPEC, | ||
153 | NFC_SDP_ATTR_URI, | ||
154 | NFC_SDP_ATTR_SAP, | ||
155 | /* private: internal use only */ | ||
156 | __NFC_SDP_ATTR_AFTER_LAST | ||
157 | }; | ||
158 | #define NFC_SDP_ATTR_MAX (__NFC_SDP_ATTR_AFTER_LAST - 1) | ||
159 | |||
148 | #define NFC_DEVICE_NAME_MAXSIZE 8 | 160 | #define NFC_DEVICE_NAME_MAXSIZE 8 |
149 | #define NFC_NFCID1_MAXSIZE 10 | 161 | #define NFC_NFCID1_MAXSIZE 10 |
150 | #define NFC_SENSB_RES_MAXSIZE 12 | 162 | #define NFC_SENSB_RES_MAXSIZE 12 |
@@ -220,4 +232,8 @@ struct sockaddr_nfc_llcp { | |||
220 | #define NFC_LLCP_DIRECTION_RX 0x00 | 232 | #define NFC_LLCP_DIRECTION_RX 0x00 |
221 | #define NFC_LLCP_DIRECTION_TX 0x01 | 233 | #define NFC_LLCP_DIRECTION_TX 0x01 |
222 | 234 | ||
235 | /* socket option names */ | ||
236 | #define NFC_LLCP_RW 0 | ||
237 | #define NFC_LLCP_MIUX 1 | ||
238 | |||
223 | #endif /*__LINUX_NFC_H */ | 239 | #endif /*__LINUX_NFC_H */ |
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index c46bb016f4e4..79da8710448e 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h | |||
@@ -36,7 +36,21 @@ | |||
36 | * The station is still assumed to belong to the AP interface it was added | 36 | * The station is still assumed to belong to the AP interface it was added |
37 | * to. | 37 | * to. |
38 | * | 38 | * |
39 | * TODO: need more info? | 39 | * Station handling varies per interface type and depending on the driver's |
40 | * capabilities. | ||
41 | * | ||
42 | * For drivers supporting TDLS with external setup (WIPHY_FLAG_SUPPORTS_TDLS | ||
43 | * and WIPHY_FLAG_TDLS_EXTERNAL_SETUP), the station lifetime is as follows: | ||
44 | * - a setup station entry is added, not yet authorized, without any rate | ||
45 | * or capability information, this just exists to avoid race conditions | ||
46 | * - when the TDLS setup is done, a single NL80211_CMD_SET_STATION is valid | ||
47 | * to add rate and capability information to the station and at the same | ||
48 | * time mark it authorized. | ||
49 | * - %NL80211_TDLS_ENABLE_LINK is then used | ||
50 | * - after this, the only valid operation is to remove it by tearing down | ||
51 | * the TDLS link (%NL80211_TDLS_DISABLE_LINK) | ||
52 | * | ||
53 | * TODO: need more info for other interface types | ||
40 | */ | 54 | */ |
41 | 55 | ||
42 | /** | 56 | /** |
@@ -499,9 +513,11 @@ | |||
499 | * @NL80211_CMD_NEW_PEER_CANDIDATE: Notification on the reception of a | 513 | * @NL80211_CMD_NEW_PEER_CANDIDATE: Notification on the reception of a |
500 | * beacon or probe response from a compatible mesh peer. This is only | 514 | * beacon or probe response from a compatible mesh peer. This is only |
501 | * sent while no station information (sta_info) exists for the new peer | 515 | * sent while no station information (sta_info) exists for the new peer |
502 | * candidate and when @NL80211_MESH_SETUP_USERSPACE_AUTH is set. On | 516 | * candidate and when @NL80211_MESH_SETUP_USERSPACE_AUTH, |
503 | * reception of this notification, userspace may decide to create a new | 517 | * @NL80211_MESH_SETUP_USERSPACE_AMPE, or |
504 | * station (@NL80211_CMD_NEW_STATION). To stop this notification from | 518 | * @NL80211_MESH_SETUP_USERSPACE_MPM is set. On reception of this |
519 | * notification, userspace may decide to create a new station | ||
520 | * (@NL80211_CMD_NEW_STATION). To stop this notification from | ||
505 | * reoccurring, the userspace authentication daemon may want to create the | 521 | * reoccurring, the userspace authentication daemon may want to create the |
506 | * new station with the AUTHENTICATED flag unset and maybe change it later | 522 | * new station with the AUTHENTICATED flag unset and maybe change it later |
507 | * depending on the authentication result. | 523 | * depending on the authentication result. |
@@ -611,6 +627,18 @@ | |||
611 | * %NL80211_ATTR_RADAR_EVENT is used to inform about the type of the | 627 | * %NL80211_ATTR_RADAR_EVENT is used to inform about the type of the |
612 | * event. | 628 | * event. |
613 | * | 629 | * |
630 | * @NL80211_CMD_GET_PROTOCOL_FEATURES: Get global nl80211 protocol features, | ||
631 | * i.e. features for the nl80211 protocol rather than device features. | ||
632 | * Returns the features in the %NL80211_ATTR_PROTOCOL_FEATURES bitmap. | ||
633 | * | ||
634 | * @NL80211_CMD_UPDATE_FT_IES: Pass down the most up-to-date Fast Transition | ||
635 | * Information Element to the WLAN driver | ||
636 | * | ||
637 | * @NL80211_CMD_FT_EVENT: Send a Fast transition event from the WLAN driver | ||
638 | * to the supplicant. This will carry the target AP's MAC address along | ||
639 | * with the relevant Information Elements. This event is used to report | ||
640 | * received FT IEs (MDIE, FTIE, RSN IE, TIE, RICIE). | ||
641 | * | ||
614 | * @NL80211_CMD_MAX: highest used command number | 642 | * @NL80211_CMD_MAX: highest used command number |
615 | * @__NL80211_CMD_AFTER_LAST: internal use | 643 | * @__NL80211_CMD_AFTER_LAST: internal use |
616 | */ | 644 | */ |
@@ -765,6 +793,11 @@ enum nl80211_commands { | |||
765 | 793 | ||
766 | NL80211_CMD_RADAR_DETECT, | 794 | NL80211_CMD_RADAR_DETECT, |
767 | 795 | ||
796 | NL80211_CMD_GET_PROTOCOL_FEATURES, | ||
797 | |||
798 | NL80211_CMD_UPDATE_FT_IES, | ||
799 | NL80211_CMD_FT_EVENT, | ||
800 | |||
768 | /* add new commands above here */ | 801 | /* add new commands above here */ |
769 | 802 | ||
770 | /* used to define NL80211_CMD_MAX below */ | 803 | /* used to define NL80211_CMD_MAX below */ |
@@ -884,7 +917,8 @@ enum nl80211_commands { | |||
884 | * consisting of a nested array. | 917 | * consisting of a nested array. |
885 | * | 918 | * |
886 | * @NL80211_ATTR_MESH_ID: mesh id (1-32 bytes). | 919 | * @NL80211_ATTR_MESH_ID: mesh id (1-32 bytes). |
887 | * @NL80211_ATTR_STA_PLINK_ACTION: action to perform on the mesh peer link. | 920 | * @NL80211_ATTR_STA_PLINK_ACTION: action to perform on the mesh peer link |
921 | * (see &enum nl80211_plink_action). | ||
888 | * @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path. | 922 | * @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path. |
889 | * @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path | 923 | * @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path |
890 | * info given for %NL80211_CMD_GET_MPATH, nested attribute described at | 924 | * info given for %NL80211_CMD_GET_MPATH, nested attribute described at |
@@ -1167,10 +1201,10 @@ enum nl80211_commands { | |||
1167 | * @NL80211_ATTR_SUPPORT_MESH_AUTH: Currently, this means the underlying driver | 1201 | * @NL80211_ATTR_SUPPORT_MESH_AUTH: Currently, this means the underlying driver |
1168 | * allows auth frames in a mesh to be passed to userspace for processing via | 1202 | * allows auth frames in a mesh to be passed to userspace for processing via |
1169 | * the @NL80211_MESH_SETUP_USERSPACE_AUTH flag. | 1203 | * the @NL80211_MESH_SETUP_USERSPACE_AUTH flag. |
1170 | * @NL80211_ATTR_STA_PLINK_STATE: The state of a mesh peer link as | 1204 | * @NL80211_ATTR_STA_PLINK_STATE: The state of a mesh peer link as defined in |
1171 | * defined in &enum nl80211_plink_state. Used when userspace is | 1205 | * &enum nl80211_plink_state. Used when userspace is driving the peer link |
1172 | * driving the peer link management state machine. | 1206 | * management state machine. @NL80211_MESH_SETUP_USERSPACE_AMPE or |
1173 | * @NL80211_MESH_SETUP_USERSPACE_AMPE must be enabled. | 1207 | * @NL80211_MESH_SETUP_USERSPACE_MPM must be enabled. |
1174 | * | 1208 | * |
1175 | * @NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED: indicates, as part of the wiphy | 1209 | * @NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED: indicates, as part of the wiphy |
1176 | * capabilities, the supported WoWLAN triggers | 1210 | * capabilities, the supported WoWLAN triggers |
@@ -1368,6 +1402,18 @@ enum nl80211_commands { | |||
1368 | * advertised to the driver, e.g., to enable TDLS off channel operations | 1402 | * advertised to the driver, e.g., to enable TDLS off channel operations |
1369 | * and PU-APSD. | 1403 | * and PU-APSD. |
1370 | * | 1404 | * |
1405 | * @NL80211_ATTR_PROTOCOL_FEATURES: global nl80211 feature flags, see | ||
1406 | * &enum nl80211_protocol_features, the attribute is a u32. | ||
1407 | * | ||
1408 | * @NL80211_ATTR_SPLIT_WIPHY_DUMP: flag attribute, userspace supports | ||
1409 | * receiving the data for a single wiphy split across multiple | ||
1410 | * messages, given with wiphy dump message | ||
1411 | * | ||
1412 | * @NL80211_ATTR_MDID: Mobility Domain Identifier | ||
1413 | * | ||
1414 | * @NL80211_ATTR_IE_RIC: Resource Information Container Information | ||
1415 | * Element | ||
1416 | * | ||
1371 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 1417 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
1372 | * @__NL80211_ATTR_AFTER_LAST: internal use | 1418 | * @__NL80211_ATTR_AFTER_LAST: internal use |
1373 | */ | 1419 | */ |
@@ -1654,6 +1700,15 @@ enum nl80211_attrs { | |||
1654 | NL80211_ATTR_STA_CAPABILITY, | 1700 | NL80211_ATTR_STA_CAPABILITY, |
1655 | NL80211_ATTR_STA_EXT_CAPABILITY, | 1701 | NL80211_ATTR_STA_EXT_CAPABILITY, |
1656 | 1702 | ||
1703 | NL80211_ATTR_PROTOCOL_FEATURES, | ||
1704 | NL80211_ATTR_SPLIT_WIPHY_DUMP, | ||
1705 | |||
1706 | NL80211_ATTR_DISABLE_VHT, | ||
1707 | NL80211_ATTR_VHT_CAPABILITY_MASK, | ||
1708 | |||
1709 | NL80211_ATTR_MDID, | ||
1710 | NL80211_ATTR_IE_RIC, | ||
1711 | |||
1657 | /* add attributes here, update the policy in nl80211.c */ | 1712 | /* add attributes here, update the policy in nl80211.c */ |
1658 | 1713 | ||
1659 | __NL80211_ATTR_AFTER_LAST, | 1714 | __NL80211_ATTR_AFTER_LAST, |
@@ -2412,8 +2467,10 @@ enum nl80211_mesh_power_mode { | |||
2412 | * @NL80211_MESHCONF_TTL: specifies the value of TTL field set at a source mesh | 2467 | * @NL80211_MESHCONF_TTL: specifies the value of TTL field set at a source mesh |
2413 | * point. | 2468 | * point. |
2414 | * | 2469 | * |
2415 | * @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically | 2470 | * @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically open |
2416 | * open peer links when we detect compatible mesh peers. | 2471 | * peer links when we detect compatible mesh peers. Disabled if |
2472 | * @NL80211_MESH_SETUP_USERSPACE_MPM or @NL80211_MESH_SETUP_USERSPACE_AMPE are | ||
2473 | * set. | ||
2417 | * | 2474 | * |
2418 | * @NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES: the number of action frames | 2475 | * @NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES: the number of action frames |
2419 | * containing a PREQ that an MP can send to a particular destination (path | 2476 | * containing a PREQ that an MP can send to a particular destination (path |
@@ -2559,6 +2616,9 @@ enum nl80211_meshconf_params { | |||
2559 | * vendor specific synchronization method or disable it to use the default | 2616 | * vendor specific synchronization method or disable it to use the default |
2560 | * neighbor offset synchronization | 2617 | * neighbor offset synchronization |
2561 | * | 2618 | * |
2619 | * @NL80211_MESH_SETUP_USERSPACE_MPM: Enable this option if userspace will | ||
2620 | * implement an MPM which handles peer allocation and state. | ||
2621 | * | ||
2562 | * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number | 2622 | * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number |
2563 | * | 2623 | * |
2564 | * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use | 2624 | * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use |
@@ -2571,6 +2631,7 @@ enum nl80211_mesh_setup_params { | |||
2571 | NL80211_MESH_SETUP_USERSPACE_AUTH, | 2631 | NL80211_MESH_SETUP_USERSPACE_AUTH, |
2572 | NL80211_MESH_SETUP_USERSPACE_AMPE, | 2632 | NL80211_MESH_SETUP_USERSPACE_AMPE, |
2573 | NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC, | 2633 | NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC, |
2634 | NL80211_MESH_SETUP_USERSPACE_MPM, | ||
2574 | 2635 | ||
2575 | /* keep last */ | 2636 | /* keep last */ |
2576 | __NL80211_MESH_SETUP_ATTR_AFTER_LAST, | 2637 | __NL80211_MESH_SETUP_ATTR_AFTER_LAST, |
@@ -3307,6 +3368,23 @@ enum nl80211_plink_state { | |||
3307 | MAX_NL80211_PLINK_STATES = NUM_NL80211_PLINK_STATES - 1 | 3368 | MAX_NL80211_PLINK_STATES = NUM_NL80211_PLINK_STATES - 1 |
3308 | }; | 3369 | }; |
3309 | 3370 | ||
3371 | /** | ||
3372 | * enum nl80211_plink_action - actions to perform in mesh peers | ||
3373 | * | ||
3374 | * @NL80211_PLINK_ACTION_NO_ACTION: perform no action | ||
3375 | * @NL80211_PLINK_ACTION_OPEN: start mesh peer link establishment | ||
3376 | * @NL80211_PLINK_ACTION_BLOCK: block traffic from this mesh peer | ||
3377 | * @NUM_NL80211_PLINK_ACTIONS: number of possible actions | ||
3378 | */ | ||
3379 | enum plink_actions { | ||
3380 | NL80211_PLINK_ACTION_NO_ACTION, | ||
3381 | NL80211_PLINK_ACTION_OPEN, | ||
3382 | NL80211_PLINK_ACTION_BLOCK, | ||
3383 | |||
3384 | NUM_NL80211_PLINK_ACTIONS, | ||
3385 | }; | ||
3386 | |||
3387 | |||
3310 | #define NL80211_KCK_LEN 16 | 3388 | #define NL80211_KCK_LEN 16 |
3311 | #define NL80211_KEK_LEN 16 | 3389 | #define NL80211_KEK_LEN 16 |
3312 | #define NL80211_REPLAY_CTR_LEN 8 | 3390 | #define NL80211_REPLAY_CTR_LEN 8 |
@@ -3456,6 +3534,10 @@ enum nl80211_ap_sme_features { | |||
3456 | * stations the authenticated/associated bits have to be set in the mask. | 3534 | * stations the authenticated/associated bits have to be set in the mask. |
3457 | * @NL80211_FEATURE_ADVERTISE_CHAN_LIMITS: cfg80211 advertises channel limits | 3535 | * @NL80211_FEATURE_ADVERTISE_CHAN_LIMITS: cfg80211 advertises channel limits |
3458 | * (HT40, VHT 80/160 MHz) if this flag is set | 3536 | * (HT40, VHT 80/160 MHz) if this flag is set |
3537 | * @NL80211_FEATURE_USERSPACE_MPM: This driver supports a userspace Mesh | ||
3538 | * Peering Management entity which may be implemented by registering for | ||
3539 | * beacons or NL80211_CMD_NEW_PEER_CANDIDATE events. The mesh beacon is | ||
3540 | * still generated by the driver. | ||
3459 | */ | 3541 | */ |
3460 | enum nl80211_feature_flags { | 3542 | enum nl80211_feature_flags { |
3461 | NL80211_FEATURE_SK_TX_STATUS = 1 << 0, | 3543 | NL80211_FEATURE_SK_TX_STATUS = 1 << 0, |
@@ -3474,6 +3556,7 @@ enum nl80211_feature_flags { | |||
3474 | /* bit 13 is reserved */ | 3556 | /* bit 13 is reserved */ |
3475 | NL80211_FEATURE_ADVERTISE_CHAN_LIMITS = 1 << 14, | 3557 | NL80211_FEATURE_ADVERTISE_CHAN_LIMITS = 1 << 14, |
3476 | NL80211_FEATURE_FULL_AP_CLIENT_STATE = 1 << 15, | 3558 | NL80211_FEATURE_FULL_AP_CLIENT_STATE = 1 << 15, |
3559 | NL80211_FEATURE_USERSPACE_MPM = 1 << 16, | ||
3477 | }; | 3560 | }; |
3478 | 3561 | ||
3479 | /** | 3562 | /** |
@@ -3587,4 +3670,16 @@ enum nl80211_dfs_state { | |||
3587 | NL80211_DFS_AVAILABLE, | 3670 | NL80211_DFS_AVAILABLE, |
3588 | }; | 3671 | }; |
3589 | 3672 | ||
3673 | /** | ||
3674 | * enum enum nl80211_protocol_features - nl80211 protocol features | ||
3675 | * @NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP: nl80211 supports splitting | ||
3676 | * wiphy dumps (if requested by the application with the attribute | ||
3677 | * %NL80211_ATTR_SPLIT_WIPHY_DUMP. Also supported is filtering the | ||
3678 | * wiphy dump by %NL80211_ATTR_WIPHY, %NL80211_ATTR_IFINDEX or | ||
3679 | * %NL80211_ATTR_WDEV. | ||
3680 | */ | ||
3681 | enum nl80211_protocol_features { | ||
3682 | NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP = 1 << 0, | ||
3683 | }; | ||
3684 | |||
3590 | #endif /* __LINUX_NL80211_H */ | 3685 | #endif /* __LINUX_NL80211_H */ |
diff --git a/kernel/smpboot.c b/kernel/smpboot.c index b9bde5727829..25d3d8b6e4e1 100644 --- a/kernel/smpboot.c +++ b/kernel/smpboot.c | |||
@@ -209,6 +209,8 @@ static void smpboot_unpark_thread(struct smp_hotplug_thread *ht, unsigned int cp | |||
209 | { | 209 | { |
210 | struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu); | 210 | struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu); |
211 | 211 | ||
212 | if (ht->pre_unpark) | ||
213 | ht->pre_unpark(cpu); | ||
212 | kthread_unpark(tsk); | 214 | kthread_unpark(tsk); |
213 | } | 215 | } |
214 | 216 | ||
diff --git a/kernel/softirq.c b/kernel/softirq.c index b4d252fd195b..14d7758074aa 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c | |||
@@ -323,18 +323,10 @@ void irq_enter(void) | |||
323 | 323 | ||
324 | static inline void invoke_softirq(void) | 324 | static inline void invoke_softirq(void) |
325 | { | 325 | { |
326 | if (!force_irqthreads) { | 326 | if (!force_irqthreads) |
327 | #ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED | ||
328 | __do_softirq(); | 327 | __do_softirq(); |
329 | #else | 328 | else |
330 | do_softirq(); | ||
331 | #endif | ||
332 | } else { | ||
333 | __local_bh_disable((unsigned long)__builtin_return_address(0), | ||
334 | SOFTIRQ_OFFSET); | ||
335 | wakeup_softirqd(); | 329 | wakeup_softirqd(); |
336 | __local_bh_enable(SOFTIRQ_OFFSET); | ||
337 | } | ||
338 | } | 330 | } |
339 | 331 | ||
340 | /* | 332 | /* |
@@ -342,9 +334,15 @@ static inline void invoke_softirq(void) | |||
342 | */ | 334 | */ |
343 | void irq_exit(void) | 335 | void irq_exit(void) |
344 | { | 336 | { |
337 | #ifndef __ARCH_IRQ_EXIT_IRQS_DISABLED | ||
338 | local_irq_disable(); | ||
339 | #else | ||
340 | WARN_ON_ONCE(!irqs_disabled()); | ||
341 | #endif | ||
342 | |||
345 | account_irq_exit_time(current); | 343 | account_irq_exit_time(current); |
346 | trace_hardirq_exit(); | 344 | trace_hardirq_exit(); |
347 | sub_preempt_count(IRQ_EXIT_OFFSET); | 345 | sub_preempt_count(HARDIRQ_OFFSET); |
348 | if (!in_interrupt() && local_softirq_pending()) | 346 | if (!in_interrupt() && local_softirq_pending()) |
349 | invoke_softirq(); | 347 | invoke_softirq(); |
350 | 348 | ||
@@ -354,7 +352,6 @@ void irq_exit(void) | |||
354 | tick_nohz_irq_exit(); | 352 | tick_nohz_irq_exit(); |
355 | #endif | 353 | #endif |
356 | rcu_irq_exit(); | 354 | rcu_irq_exit(); |
357 | sched_preempt_enable_no_resched(); | ||
358 | } | 355 | } |
359 | 356 | ||
360 | /* | 357 | /* |
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index 95d178c62d5a..c09f2955ae30 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c | |||
@@ -336,7 +336,7 @@ static struct smp_hotplug_thread cpu_stop_threads = { | |||
336 | .create = cpu_stop_create, | 336 | .create = cpu_stop_create, |
337 | .setup = cpu_stop_unpark, | 337 | .setup = cpu_stop_unpark, |
338 | .park = cpu_stop_park, | 338 | .park = cpu_stop_park, |
339 | .unpark = cpu_stop_unpark, | 339 | .pre_unpark = cpu_stop_unpark, |
340 | .selfparking = true, | 340 | .selfparking = true, |
341 | }; | 341 | }; |
342 | 342 | ||
diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c index 1ae1d9cb278d..21760f008974 100644 --- a/net/caif/caif_dev.c +++ b/net/caif/caif_dev.c | |||
@@ -118,7 +118,7 @@ static struct caif_device_entry *caif_get(struct net_device *dev) | |||
118 | return NULL; | 118 | return NULL; |
119 | } | 119 | } |
120 | 120 | ||
121 | void caif_flow_cb(struct sk_buff *skb) | 121 | static void caif_flow_cb(struct sk_buff *skb) |
122 | { | 122 | { |
123 | struct caif_device_entry *caifd; | 123 | struct caif_device_entry *caifd; |
124 | void (*dtor)(struct sk_buff *skb) = NULL; | 124 | void (*dtor)(struct sk_buff *skb) = NULL; |
diff --git a/net/caif/caif_usb.c b/net/caif/caif_usb.c index 3ebc8cbc91ff..ef8ebaa993cf 100644 --- a/net/caif/caif_usb.c +++ b/net/caif/caif_usb.c | |||
@@ -81,8 +81,8 @@ static void cfusbl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | |||
81 | layr->up->ctrlcmd(layr->up, ctrl, layr->id); | 81 | layr->up->ctrlcmd(layr->up, ctrl, layr->id); |
82 | } | 82 | } |
83 | 83 | ||
84 | struct cflayer *cfusbl_create(int phyid, u8 ethaddr[ETH_ALEN], | 84 | static struct cflayer *cfusbl_create(int phyid, u8 ethaddr[ETH_ALEN], |
85 | u8 braddr[ETH_ALEN]) | 85 | u8 braddr[ETH_ALEN]) |
86 | { | 86 | { |
87 | struct cfusbl *this = kmalloc(sizeof(struct cfusbl), GFP_ATOMIC); | 87 | struct cfusbl *this = kmalloc(sizeof(struct cfusbl), GFP_ATOMIC); |
88 | 88 | ||
diff --git a/net/core/dev.c b/net/core/dev.c index a06a7a58dd11..8f152f904f70 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -4103,7 +4103,7 @@ static void net_rx_action(struct softirq_action *h) | |||
4103 | * Allow this to run for 2 jiffies since which will allow | 4103 | * Allow this to run for 2 jiffies since which will allow |
4104 | * an average latency of 1.5/HZ. | 4104 | * an average latency of 1.5/HZ. |
4105 | */ | 4105 | */ |
4106 | if (unlikely(budget <= 0 || time_after(jiffies, time_limit))) | 4106 | if (unlikely(budget <= 0 || time_after_eq(jiffies, time_limit))) |
4107 | goto softnet_break; | 4107 | goto softnet_break; |
4108 | 4108 | ||
4109 | local_irq_enable(); | 4109 | local_irq_enable(); |
@@ -4780,7 +4780,7 @@ EXPORT_SYMBOL(dev_set_mac_address); | |||
4780 | /** | 4780 | /** |
4781 | * dev_change_carrier - Change device carrier | 4781 | * dev_change_carrier - Change device carrier |
4782 | * @dev: device | 4782 | * @dev: device |
4783 | * @new_carries: new value | 4783 | * @new_carrier: new value |
4784 | * | 4784 | * |
4785 | * Change device carrier | 4785 | * Change device carrier |
4786 | */ | 4786 | */ |
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 87abd3e2bd32..2bdf802e28e2 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c | |||
@@ -228,9 +228,11 @@ static int ip_local_deliver_finish(struct sk_buff *skb) | |||
228 | icmp_send(skb, ICMP_DEST_UNREACH, | 228 | icmp_send(skb, ICMP_DEST_UNREACH, |
229 | ICMP_PROT_UNREACH, 0); | 229 | ICMP_PROT_UNREACH, 0); |
230 | } | 230 | } |
231 | } else | 231 | kfree_skb(skb); |
232 | } else { | ||
232 | IP_INC_STATS_BH(net, IPSTATS_MIB_INDELIVERS); | 233 | IP_INC_STATS_BH(net, IPSTATS_MIB_INDELIVERS); |
233 | kfree_skb(skb); | 234 | consume_skb(skb); |
235 | } | ||
234 | } | 236 | } |
235 | } | 237 | } |
236 | out: | 238 | out: |
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index f6289bf6f332..310a3647c83d 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c | |||
@@ -423,7 +423,7 @@ int ip_options_compile(struct net *net, | |||
423 | put_unaligned_be32(midtime, timeptr); | 423 | put_unaligned_be32(midtime, timeptr); |
424 | opt->is_changed = 1; | 424 | opt->is_changed = 1; |
425 | } | 425 | } |
426 | } else { | 426 | } else if ((optptr[3]&0xF) != IPOPT_TS_PRESPEC) { |
427 | unsigned int overflow = optptr[3]>>4; | 427 | unsigned int overflow = optptr[3]>>4; |
428 | if (overflow == 15) { | 428 | if (overflow == 15) { |
429 | pp_ptr = optptr + 3; | 429 | pp_ptr = optptr + 3; |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index a759e19496d2..0d9bdacce99f 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -5485,6 +5485,9 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, | |||
5485 | if (tcp_checksum_complete_user(sk, skb)) | 5485 | if (tcp_checksum_complete_user(sk, skb)) |
5486 | goto csum_error; | 5486 | goto csum_error; |
5487 | 5487 | ||
5488 | if ((int)skb->truesize > sk->sk_forward_alloc) | ||
5489 | goto step5; | ||
5490 | |||
5488 | /* Predicted packet is in window by definition. | 5491 | /* Predicted packet is in window by definition. |
5489 | * seq == rcv_nxt and rcv_wup <= rcv_nxt. | 5492 | * seq == rcv_nxt and rcv_wup <= rcv_nxt. |
5490 | * Hence, check seq<=rcv_wup reduces to: | 5493 | * Hence, check seq<=rcv_wup reduces to: |
@@ -5496,9 +5499,6 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, | |||
5496 | 5499 | ||
5497 | tcp_rcv_rtt_measure_ts(sk, skb); | 5500 | tcp_rcv_rtt_measure_ts(sk, skb); |
5498 | 5501 | ||
5499 | if ((int)skb->truesize > sk->sk_forward_alloc) | ||
5500 | goto step5; | ||
5501 | |||
5502 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPHPHITS); | 5502 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPHPHITS); |
5503 | 5503 | ||
5504 | /* Bulk data transfer: receiver */ | 5504 | /* Bulk data transfer: receiver */ |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 5b10414e619e..b1876e52091e 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -241,9 +241,11 @@ resubmit: | |||
241 | icmpv6_send(skb, ICMPV6_PARAMPROB, | 241 | icmpv6_send(skb, ICMPV6_PARAMPROB, |
242 | ICMPV6_UNK_NEXTHDR, nhoff); | 242 | ICMPV6_UNK_NEXTHDR, nhoff); |
243 | } | 243 | } |
244 | } else | 244 | kfree_skb(skb); |
245 | } else { | ||
245 | IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDELIVERS); | 246 | IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDELIVERS); |
246 | kfree_skb(skb); | 247 | consume_skb(skb); |
248 | } | ||
247 | } | 249 | } |
248 | rcu_read_unlock(); | 250 | rcu_read_unlock(); |
249 | return 0; | 251 | return 0; |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 928266569689..e5fe0041adfa 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -1915,7 +1915,8 @@ void rt6_purge_dflt_routers(struct net *net) | |||
1915 | restart: | 1915 | restart: |
1916 | read_lock_bh(&table->tb6_lock); | 1916 | read_lock_bh(&table->tb6_lock); |
1917 | for (rt = table->tb6_root.leaf; rt; rt = rt->dst.rt6_next) { | 1917 | for (rt = table->tb6_root.leaf; rt; rt = rt->dst.rt6_next) { |
1918 | if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) { | 1918 | if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF) && |
1919 | (!rt->rt6i_idev || rt->rt6i_idev->cnf.accept_ra != 2)) { | ||
1919 | dst_hold(&rt->dst); | 1920 | dst_hold(&rt->dst); |
1920 | read_unlock_bh(&table->tb6_lock); | 1921 | read_unlock_bh(&table->tb6_lock); |
1921 | ip6_del_rt(rt); | 1922 | ip6_del_rt(rt); |
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index 9a5fd3c3e530..362ba47968e4 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c | |||
@@ -280,7 +280,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, | |||
280 | struct tty_port *port = &self->port; | 280 | struct tty_port *port = &self->port; |
281 | DECLARE_WAITQUEUE(wait, current); | 281 | DECLARE_WAITQUEUE(wait, current); |
282 | int retval; | 282 | int retval; |
283 | int do_clocal = 0, extra_count = 0; | 283 | int do_clocal = 0; |
284 | unsigned long flags; | 284 | unsigned long flags; |
285 | 285 | ||
286 | IRDA_DEBUG(2, "%s()\n", __func__ ); | 286 | IRDA_DEBUG(2, "%s()\n", __func__ ); |
@@ -289,8 +289,15 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, | |||
289 | * If non-blocking mode is set, or the port is not enabled, | 289 | * If non-blocking mode is set, or the port is not enabled, |
290 | * then make the check up front and then exit. | 290 | * then make the check up front and then exit. |
291 | */ | 291 | */ |
292 | if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ | 292 | if (test_bit(TTY_IO_ERROR, &tty->flags)) { |
293 | /* nonblock mode is set or port is not enabled */ | 293 | port->flags |= ASYNC_NORMAL_ACTIVE; |
294 | return 0; | ||
295 | } | ||
296 | |||
297 | if (filp->f_flags & O_NONBLOCK) { | ||
298 | /* nonblock mode is set */ | ||
299 | if (tty->termios.c_cflag & CBAUD) | ||
300 | tty_port_raise_dtr_rts(port); | ||
294 | port->flags |= ASYNC_NORMAL_ACTIVE; | 301 | port->flags |= ASYNC_NORMAL_ACTIVE; |
295 | IRDA_DEBUG(1, "%s(), O_NONBLOCK requested!\n", __func__ ); | 302 | IRDA_DEBUG(1, "%s(), O_NONBLOCK requested!\n", __func__ ); |
296 | return 0; | 303 | return 0; |
@@ -315,18 +322,16 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, | |||
315 | __FILE__, __LINE__, tty->driver->name, port->count); | 322 | __FILE__, __LINE__, tty->driver->name, port->count); |
316 | 323 | ||
317 | spin_lock_irqsave(&port->lock, flags); | 324 | spin_lock_irqsave(&port->lock, flags); |
318 | if (!tty_hung_up_p(filp)) { | 325 | if (!tty_hung_up_p(filp)) |
319 | extra_count = 1; | ||
320 | port->count--; | 326 | port->count--; |
321 | } | ||
322 | spin_unlock_irqrestore(&port->lock, flags); | ||
323 | port->blocked_open++; | 327 | port->blocked_open++; |
328 | spin_unlock_irqrestore(&port->lock, flags); | ||
324 | 329 | ||
325 | while (1) { | 330 | while (1) { |
326 | if (tty->termios.c_cflag & CBAUD) | 331 | if (tty->termios.c_cflag & CBAUD) |
327 | tty_port_raise_dtr_rts(port); | 332 | tty_port_raise_dtr_rts(port); |
328 | 333 | ||
329 | current->state = TASK_INTERRUPTIBLE; | 334 | set_current_state(TASK_INTERRUPTIBLE); |
330 | 335 | ||
331 | if (tty_hung_up_p(filp) || | 336 | if (tty_hung_up_p(filp) || |
332 | !test_bit(ASYNCB_INITIALIZED, &port->flags)) { | 337 | !test_bit(ASYNCB_INITIALIZED, &port->flags)) { |
@@ -361,13 +366,11 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, | |||
361 | __set_current_state(TASK_RUNNING); | 366 | __set_current_state(TASK_RUNNING); |
362 | remove_wait_queue(&port->open_wait, &wait); | 367 | remove_wait_queue(&port->open_wait, &wait); |
363 | 368 | ||
364 | if (extra_count) { | 369 | spin_lock_irqsave(&port->lock, flags); |
365 | /* ++ is not atomic, so this should be protected - Jean II */ | 370 | if (!tty_hung_up_p(filp)) |
366 | spin_lock_irqsave(&port->lock, flags); | ||
367 | port->count++; | 371 | port->count++; |
368 | spin_unlock_irqrestore(&port->lock, flags); | ||
369 | } | ||
370 | port->blocked_open--; | 372 | port->blocked_open--; |
373 | spin_unlock_irqrestore(&port->lock, flags); | ||
371 | 374 | ||
372 | IRDA_DEBUG(1, "%s(%d):block_til_ready after blocking on %s open_count=%d\n", | 375 | IRDA_DEBUG(1, "%s(%d):block_til_ready after blocking on %s open_count=%d\n", |
373 | __FILE__, __LINE__, tty->driver->name, port->count); | 376 | __FILE__, __LINE__, tty->driver->name, port->count); |
diff --git a/net/irda/iriap.c b/net/irda/iriap.c index e71e85ba2bf1..29340a9a6fb9 100644 --- a/net/irda/iriap.c +++ b/net/irda/iriap.c | |||
@@ -495,8 +495,11 @@ static void iriap_getvaluebyclass_confirm(struct iriap_cb *self, | |||
495 | /* case CS_ISO_8859_9: */ | 495 | /* case CS_ISO_8859_9: */ |
496 | /* case CS_UNICODE: */ | 496 | /* case CS_UNICODE: */ |
497 | default: | 497 | default: |
498 | IRDA_DEBUG(0, "%s(), charset %s, not supported\n", | 498 | IRDA_DEBUG(0, "%s(), charset [%d] %s, not supported\n", |
499 | __func__, ias_charset_types[charset]); | 499 | __func__, charset, |
500 | charset < ARRAY_SIZE(ias_charset_types) ? | ||
501 | ias_charset_types[charset] : | ||
502 | "(unknown)"); | ||
500 | 503 | ||
501 | /* Aborting, close connection! */ | 504 | /* Aborting, close connection! */ |
502 | iriap_disconnect_request(self); | 505 | iriap_disconnect_request(self); |
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 3f4e3afc191a..6a53371dba1f 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c | |||
@@ -355,6 +355,7 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh | |||
355 | l2tp_xmit_skb(session, skb, session->hdr_len); | 355 | l2tp_xmit_skb(session, skb, session->hdr_len); |
356 | 356 | ||
357 | sock_put(ps->tunnel_sock); | 357 | sock_put(ps->tunnel_sock); |
358 | sock_put(sk); | ||
358 | 359 | ||
359 | return error; | 360 | return error; |
360 | 361 | ||
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 09d96a8f6c2c..1d1ddabd89ca 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -254,7 +254,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | |||
254 | goto out_unlock; | 254 | goto out_unlock; |
255 | } | 255 | } |
256 | 256 | ||
257 | __ieee80211_key_free(key); | 257 | __ieee80211_key_free(key, true); |
258 | 258 | ||
259 | ret = 0; | 259 | ret = 0; |
260 | out_unlock: | 260 | out_unlock: |
@@ -1035,9 +1035,12 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
1035 | sta_info_flush_defer(vlan); | 1035 | sta_info_flush_defer(vlan); |
1036 | sta_info_flush_defer(sdata); | 1036 | sta_info_flush_defer(sdata); |
1037 | rcu_barrier(); | 1037 | rcu_barrier(); |
1038 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | 1038 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) { |
1039 | sta_info_flush_cleanup(vlan); | 1039 | sta_info_flush_cleanup(vlan); |
1040 | ieee80211_free_keys(vlan); | ||
1041 | } | ||
1040 | sta_info_flush_cleanup(sdata); | 1042 | sta_info_flush_cleanup(sdata); |
1043 | ieee80211_free_keys(sdata); | ||
1041 | 1044 | ||
1042 | sdata->vif.bss_conf.enable_beacon = false; | 1045 | sdata->vif.bss_conf.enable_beacon = false; |
1043 | clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); | 1046 | clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); |
@@ -1177,6 +1180,18 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1177 | mask |= BIT(NL80211_STA_FLAG_ASSOCIATED); | 1180 | mask |= BIT(NL80211_STA_FLAG_ASSOCIATED); |
1178 | if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) | 1181 | if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) |
1179 | set |= BIT(NL80211_STA_FLAG_ASSOCIATED); | 1182 | set |= BIT(NL80211_STA_FLAG_ASSOCIATED); |
1183 | } else if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { | ||
1184 | /* | ||
1185 | * TDLS -- everything follows authorized, but | ||
1186 | * only becoming authorized is possible, not | ||
1187 | * going back | ||
1188 | */ | ||
1189 | if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) { | ||
1190 | set |= BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
1191 | BIT(NL80211_STA_FLAG_ASSOCIATED); | ||
1192 | mask |= BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
1193 | BIT(NL80211_STA_FLAG_ASSOCIATED); | ||
1194 | } | ||
1180 | } | 1195 | } |
1181 | 1196 | ||
1182 | ret = sta_apply_auth_flags(local, sta, mask, set); | 1197 | ret = sta_apply_auth_flags(local, sta, mask, set); |
@@ -1261,7 +1276,8 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1261 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 1276 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
1262 | #ifdef CONFIG_MAC80211_MESH | 1277 | #ifdef CONFIG_MAC80211_MESH |
1263 | u32 changed = 0; | 1278 | u32 changed = 0; |
1264 | if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED) { | 1279 | |
1280 | if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE) { | ||
1265 | switch (params->plink_state) { | 1281 | switch (params->plink_state) { |
1266 | case NL80211_PLINK_ESTAB: | 1282 | case NL80211_PLINK_ESTAB: |
1267 | if (sta->plink_state != NL80211_PLINK_ESTAB) | 1283 | if (sta->plink_state != NL80211_PLINK_ESTAB) |
@@ -1292,15 +1308,18 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1292 | /* nothing */ | 1308 | /* nothing */ |
1293 | break; | 1309 | break; |
1294 | } | 1310 | } |
1295 | } else { | 1311 | } |
1296 | switch (params->plink_action) { | 1312 | |
1297 | case PLINK_ACTION_OPEN: | 1313 | switch (params->plink_action) { |
1298 | changed |= mesh_plink_open(sta); | 1314 | case NL80211_PLINK_ACTION_NO_ACTION: |
1299 | break; | 1315 | /* nothing */ |
1300 | case PLINK_ACTION_BLOCK: | 1316 | break; |
1301 | changed |= mesh_plink_block(sta); | 1317 | case NL80211_PLINK_ACTION_OPEN: |
1302 | break; | 1318 | changed |= mesh_plink_open(sta); |
1303 | } | 1319 | break; |
1320 | case NL80211_PLINK_ACTION_BLOCK: | ||
1321 | changed |= mesh_plink_block(sta); | ||
1322 | break; | ||
1304 | } | 1323 | } |
1305 | 1324 | ||
1306 | if (params->local_pm) | 1325 | if (params->local_pm) |
@@ -1346,8 +1365,10 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
1346 | * defaults -- if userspace wants something else we'll | 1365 | * defaults -- if userspace wants something else we'll |
1347 | * change it accordingly in sta_apply_parameters() | 1366 | * change it accordingly in sta_apply_parameters() |
1348 | */ | 1367 | */ |
1349 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); | 1368 | if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) { |
1350 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); | 1369 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); |
1370 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); | ||
1371 | } | ||
1351 | 1372 | ||
1352 | err = sta_apply_parameters(local, sta, params); | 1373 | err = sta_apply_parameters(local, sta, params); |
1353 | if (err) { | 1374 | if (err) { |
@@ -1356,8 +1377,8 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
1356 | } | 1377 | } |
1357 | 1378 | ||
1358 | /* | 1379 | /* |
1359 | * for TDLS, rate control should be initialized only when supported | 1380 | * for TDLS, rate control should be initialized only when |
1360 | * rates are known. | 1381 | * rates are known and station is marked authorized |
1361 | */ | 1382 | */ |
1362 | if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) | 1383 | if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) |
1363 | rate_control_rate_init(sta); | 1384 | rate_control_rate_init(sta); |
@@ -1394,50 +1415,67 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, | |||
1394 | } | 1415 | } |
1395 | 1416 | ||
1396 | static int ieee80211_change_station(struct wiphy *wiphy, | 1417 | static int ieee80211_change_station(struct wiphy *wiphy, |
1397 | struct net_device *dev, | 1418 | struct net_device *dev, u8 *mac, |
1398 | u8 *mac, | ||
1399 | struct station_parameters *params) | 1419 | struct station_parameters *params) |
1400 | { | 1420 | { |
1401 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1421 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1402 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1422 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1403 | struct sta_info *sta; | 1423 | struct sta_info *sta; |
1404 | struct ieee80211_sub_if_data *vlansdata; | 1424 | struct ieee80211_sub_if_data *vlansdata; |
1425 | enum cfg80211_station_type statype; | ||
1405 | int err; | 1426 | int err; |
1406 | 1427 | ||
1407 | mutex_lock(&local->sta_mtx); | 1428 | mutex_lock(&local->sta_mtx); |
1408 | 1429 | ||
1409 | sta = sta_info_get_bss(sdata, mac); | 1430 | sta = sta_info_get_bss(sdata, mac); |
1410 | if (!sta) { | 1431 | if (!sta) { |
1411 | mutex_unlock(&local->sta_mtx); | 1432 | err = -ENOENT; |
1412 | return -ENOENT; | 1433 | goto out_err; |
1413 | } | 1434 | } |
1414 | 1435 | ||
1415 | /* in station mode, some updates are only valid with TDLS */ | 1436 | switch (sdata->vif.type) { |
1416 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 1437 | case NL80211_IFTYPE_MESH_POINT: |
1417 | (params->supported_rates || params->ht_capa || params->vht_capa || | 1438 | if (sdata->u.mesh.user_mpm) |
1418 | params->sta_modify_mask || | 1439 | statype = CFG80211_STA_MESH_PEER_USER; |
1419 | (params->sta_flags_mask & BIT(NL80211_STA_FLAG_WME))) && | 1440 | else |
1420 | !test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { | 1441 | statype = CFG80211_STA_MESH_PEER_KERNEL; |
1421 | mutex_unlock(&local->sta_mtx); | 1442 | break; |
1422 | return -EINVAL; | 1443 | case NL80211_IFTYPE_ADHOC: |
1444 | statype = CFG80211_STA_IBSS; | ||
1445 | break; | ||
1446 | case NL80211_IFTYPE_STATION: | ||
1447 | if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { | ||
1448 | statype = CFG80211_STA_AP_STA; | ||
1449 | break; | ||
1450 | } | ||
1451 | if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) | ||
1452 | statype = CFG80211_STA_TDLS_PEER_ACTIVE; | ||
1453 | else | ||
1454 | statype = CFG80211_STA_TDLS_PEER_SETUP; | ||
1455 | break; | ||
1456 | case NL80211_IFTYPE_AP: | ||
1457 | case NL80211_IFTYPE_AP_VLAN: | ||
1458 | statype = CFG80211_STA_AP_CLIENT; | ||
1459 | break; | ||
1460 | default: | ||
1461 | err = -EOPNOTSUPP; | ||
1462 | goto out_err; | ||
1423 | } | 1463 | } |
1424 | 1464 | ||
1465 | err = cfg80211_check_station_change(wiphy, params, statype); | ||
1466 | if (err) | ||
1467 | goto out_err; | ||
1468 | |||
1425 | if (params->vlan && params->vlan != sta->sdata->dev) { | 1469 | if (params->vlan && params->vlan != sta->sdata->dev) { |
1426 | bool prev_4addr = false; | 1470 | bool prev_4addr = false; |
1427 | bool new_4addr = false; | 1471 | bool new_4addr = false; |
1428 | 1472 | ||
1429 | vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); | 1473 | vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); |
1430 | 1474 | ||
1431 | if (vlansdata->vif.type != NL80211_IFTYPE_AP_VLAN && | ||
1432 | vlansdata->vif.type != NL80211_IFTYPE_AP) { | ||
1433 | mutex_unlock(&local->sta_mtx); | ||
1434 | return -EINVAL; | ||
1435 | } | ||
1436 | |||
1437 | if (params->vlan->ieee80211_ptr->use_4addr) { | 1475 | if (params->vlan->ieee80211_ptr->use_4addr) { |
1438 | if (vlansdata->u.vlan.sta) { | 1476 | if (vlansdata->u.vlan.sta) { |
1439 | mutex_unlock(&local->sta_mtx); | 1477 | err = -EBUSY; |
1440 | return -EBUSY; | 1478 | goto out_err; |
1441 | } | 1479 | } |
1442 | 1480 | ||
1443 | rcu_assign_pointer(vlansdata->u.vlan.sta, sta); | 1481 | rcu_assign_pointer(vlansdata->u.vlan.sta, sta); |
@@ -1464,12 +1502,12 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
1464 | } | 1502 | } |
1465 | 1503 | ||
1466 | err = sta_apply_parameters(local, sta, params); | 1504 | err = sta_apply_parameters(local, sta, params); |
1467 | if (err) { | 1505 | if (err) |
1468 | mutex_unlock(&local->sta_mtx); | 1506 | goto out_err; |
1469 | return err; | ||
1470 | } | ||
1471 | 1507 | ||
1472 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) && params->supported_rates) | 1508 | /* When peer becomes authorized, init rate control as well */ |
1509 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) && | ||
1510 | test_sta_flag(sta, WLAN_STA_AUTHORIZED)) | ||
1473 | rate_control_rate_init(sta); | 1511 | rate_control_rate_init(sta); |
1474 | 1512 | ||
1475 | mutex_unlock(&local->sta_mtx); | 1513 | mutex_unlock(&local->sta_mtx); |
@@ -1479,7 +1517,11 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
1479 | ieee80211_recalc_ps(local, -1); | 1517 | ieee80211_recalc_ps(local, -1); |
1480 | ieee80211_recalc_ps_vif(sdata); | 1518 | ieee80211_recalc_ps_vif(sdata); |
1481 | } | 1519 | } |
1520 | |||
1482 | return 0; | 1521 | return 0; |
1522 | out_err: | ||
1523 | mutex_unlock(&local->sta_mtx); | ||
1524 | return err; | ||
1483 | } | 1525 | } |
1484 | 1526 | ||
1485 | #ifdef CONFIG_MAC80211_MESH | 1527 | #ifdef CONFIG_MAC80211_MESH |
@@ -1687,6 +1729,7 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, | |||
1687 | ifmsh->mesh_sp_id = setup->sync_method; | 1729 | ifmsh->mesh_sp_id = setup->sync_method; |
1688 | ifmsh->mesh_pp_id = setup->path_sel_proto; | 1730 | ifmsh->mesh_pp_id = setup->path_sel_proto; |
1689 | ifmsh->mesh_pm_id = setup->path_metric; | 1731 | ifmsh->mesh_pm_id = setup->path_metric; |
1732 | ifmsh->user_mpm = setup->user_mpm; | ||
1690 | ifmsh->security = IEEE80211_MESH_SEC_NONE; | 1733 | ifmsh->security = IEEE80211_MESH_SEC_NONE; |
1691 | if (setup->is_authenticated) | 1734 | if (setup->is_authenticated) |
1692 | ifmsh->security |= IEEE80211_MESH_SEC_AUTHED; | 1735 | ifmsh->security |= IEEE80211_MESH_SEC_AUTHED; |
@@ -1730,8 +1773,11 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, | |||
1730 | conf->dot11MeshTTL = nconf->dot11MeshTTL; | 1773 | conf->dot11MeshTTL = nconf->dot11MeshTTL; |
1731 | if (_chg_mesh_attr(NL80211_MESHCONF_ELEMENT_TTL, mask)) | 1774 | if (_chg_mesh_attr(NL80211_MESHCONF_ELEMENT_TTL, mask)) |
1732 | conf->element_ttl = nconf->element_ttl; | 1775 | conf->element_ttl = nconf->element_ttl; |
1733 | if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) | 1776 | if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) { |
1777 | if (ifmsh->user_mpm) | ||
1778 | return -EBUSY; | ||
1734 | conf->auto_open_plinks = nconf->auto_open_plinks; | 1779 | conf->auto_open_plinks = nconf->auto_open_plinks; |
1780 | } | ||
1735 | if (_chg_mesh_attr(NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, mask)) | 1781 | if (_chg_mesh_attr(NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, mask)) |
1736 | conf->dot11MeshNbrOffsetMaxNeighbor = | 1782 | conf->dot11MeshNbrOffsetMaxNeighbor = |
1737 | nconf->dot11MeshNbrOffsetMaxNeighbor; | 1783 | nconf->dot11MeshNbrOffsetMaxNeighbor; |
@@ -2371,7 +2417,8 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2371 | struct ieee80211_sub_if_data *sdata, | 2417 | struct ieee80211_sub_if_data *sdata, |
2372 | struct ieee80211_channel *channel, | 2418 | struct ieee80211_channel *channel, |
2373 | unsigned int duration, u64 *cookie, | 2419 | unsigned int duration, u64 *cookie, |
2374 | struct sk_buff *txskb) | 2420 | struct sk_buff *txskb, |
2421 | enum ieee80211_roc_type type) | ||
2375 | { | 2422 | { |
2376 | struct ieee80211_roc_work *roc, *tmp; | 2423 | struct ieee80211_roc_work *roc, *tmp; |
2377 | bool queued = false; | 2424 | bool queued = false; |
@@ -2390,6 +2437,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2390 | roc->duration = duration; | 2437 | roc->duration = duration; |
2391 | roc->req_duration = duration; | 2438 | roc->req_duration = duration; |
2392 | roc->frame = txskb; | 2439 | roc->frame = txskb; |
2440 | roc->type = type; | ||
2393 | roc->mgmt_tx_cookie = (unsigned long)txskb; | 2441 | roc->mgmt_tx_cookie = (unsigned long)txskb; |
2394 | roc->sdata = sdata; | 2442 | roc->sdata = sdata; |
2395 | INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work); | 2443 | INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work); |
@@ -2420,7 +2468,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2420 | if (!duration) | 2468 | if (!duration) |
2421 | duration = 10; | 2469 | duration = 10; |
2422 | 2470 | ||
2423 | ret = drv_remain_on_channel(local, sdata, channel, duration); | 2471 | ret = drv_remain_on_channel(local, sdata, channel, duration, type); |
2424 | if (ret) { | 2472 | if (ret) { |
2425 | kfree(roc); | 2473 | kfree(roc); |
2426 | return ret; | 2474 | return ret; |
@@ -2439,10 +2487,13 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2439 | * | 2487 | * |
2440 | * If it hasn't started yet, just increase the duration | 2488 | * If it hasn't started yet, just increase the duration |
2441 | * and add the new one to the list of dependents. | 2489 | * and add the new one to the list of dependents. |
2490 | * If the type of the new ROC has higher priority, modify the | ||
2491 | * type of the previous one to match that of the new one. | ||
2442 | */ | 2492 | */ |
2443 | if (!tmp->started) { | 2493 | if (!tmp->started) { |
2444 | list_add_tail(&roc->list, &tmp->dependents); | 2494 | list_add_tail(&roc->list, &tmp->dependents); |
2445 | tmp->duration = max(tmp->duration, roc->duration); | 2495 | tmp->duration = max(tmp->duration, roc->duration); |
2496 | tmp->type = max(tmp->type, roc->type); | ||
2446 | queued = true; | 2497 | queued = true; |
2447 | break; | 2498 | break; |
2448 | } | 2499 | } |
@@ -2454,16 +2505,18 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2454 | /* | 2505 | /* |
2455 | * In the offloaded ROC case, if it hasn't begun, add | 2506 | * In the offloaded ROC case, if it hasn't begun, add |
2456 | * this new one to the dependent list to be handled | 2507 | * this new one to the dependent list to be handled |
2457 | * when the the master one begins. If it has begun, | 2508 | * when the master one begins. If it has begun, |
2458 | * check that there's still a minimum time left and | 2509 | * check that there's still a minimum time left and |
2459 | * if so, start this one, transmitting the frame, but | 2510 | * if so, start this one, transmitting the frame, but |
2460 | * add it to the list directly after this one with a | 2511 | * add it to the list directly after this one with |
2461 | * a reduced time so we'll ask the driver to execute | 2512 | * a reduced time so we'll ask the driver to execute |
2462 | * it right after finishing the previous one, in the | 2513 | * it right after finishing the previous one, in the |
2463 | * hope that it'll also be executed right afterwards, | 2514 | * hope that it'll also be executed right afterwards, |
2464 | * effectively extending the old one. | 2515 | * effectively extending the old one. |
2465 | * If there's no minimum time left, just add it to the | 2516 | * If there's no minimum time left, just add it to the |
2466 | * normal list. | 2517 | * normal list. |
2518 | * TODO: the ROC type is ignored here, assuming that it | ||
2519 | * is better to immediately use the current ROC. | ||
2467 | */ | 2520 | */ |
2468 | if (!tmp->hw_begun) { | 2521 | if (!tmp->hw_begun) { |
2469 | list_add_tail(&roc->list, &tmp->dependents); | 2522 | list_add_tail(&roc->list, &tmp->dependents); |
@@ -2557,7 +2610,8 @@ static int ieee80211_remain_on_channel(struct wiphy *wiphy, | |||
2557 | 2610 | ||
2558 | mutex_lock(&local->mtx); | 2611 | mutex_lock(&local->mtx); |
2559 | ret = ieee80211_start_roc_work(local, sdata, chan, | 2612 | ret = ieee80211_start_roc_work(local, sdata, chan, |
2560 | duration, cookie, NULL); | 2613 | duration, cookie, NULL, |
2614 | IEEE80211_ROC_TYPE_NORMAL); | ||
2561 | mutex_unlock(&local->mtx); | 2615 | mutex_unlock(&local->mtx); |
2562 | 2616 | ||
2563 | return ret; | 2617 | return ret; |
@@ -2790,7 +2844,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
2790 | 2844 | ||
2791 | /* This will handle all kinds of coalescing and immediate TX */ | 2845 | /* This will handle all kinds of coalescing and immediate TX */ |
2792 | ret = ieee80211_start_roc_work(local, sdata, chan, | 2846 | ret = ieee80211_start_roc_work(local, sdata, chan, |
2793 | wait, cookie, skb); | 2847 | wait, cookie, skb, |
2848 | IEEE80211_ROC_TYPE_MGMT_TX); | ||
2794 | if (ret) | 2849 | if (ret) |
2795 | kfree_skb(skb); | 2850 | kfree_skb(skb); |
2796 | out_unlock: | 2851 | out_unlock: |
@@ -3285,6 +3340,7 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy, | |||
3285 | struct cfg80211_chan_def *chandef) | 3340 | struct cfg80211_chan_def *chandef) |
3286 | { | 3341 | { |
3287 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); | 3342 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); |
3343 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
3288 | struct ieee80211_chanctx_conf *chanctx_conf; | 3344 | struct ieee80211_chanctx_conf *chanctx_conf; |
3289 | int ret = -ENODATA; | 3345 | int ret = -ENODATA; |
3290 | 3346 | ||
@@ -3293,6 +3349,16 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy, | |||
3293 | if (chanctx_conf) { | 3349 | if (chanctx_conf) { |
3294 | *chandef = chanctx_conf->def; | 3350 | *chandef = chanctx_conf->def; |
3295 | ret = 0; | 3351 | ret = 0; |
3352 | } else if (local->open_count > 0 && | ||
3353 | local->open_count == local->monitors && | ||
3354 | sdata->vif.type == NL80211_IFTYPE_MONITOR) { | ||
3355 | if (local->use_chanctx) | ||
3356 | *chandef = local->monitor_chandef; | ||
3357 | else | ||
3358 | cfg80211_chandef_create(chandef, | ||
3359 | local->_oper_channel, | ||
3360 | local->_oper_channel_type); | ||
3361 | ret = 0; | ||
3296 | } | 3362 | } |
3297 | rcu_read_unlock(); | 3363 | rcu_read_unlock(); |
3298 | 3364 | ||
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index c7591f73dbc3..4f841fe559df 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -325,6 +325,36 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, | |||
325 | } | 325 | } |
326 | STA_OPS(ht_capa); | 326 | STA_OPS(ht_capa); |
327 | 327 | ||
328 | static ssize_t sta_vht_capa_read(struct file *file, char __user *userbuf, | ||
329 | size_t count, loff_t *ppos) | ||
330 | { | ||
331 | char buf[128], *p = buf; | ||
332 | struct sta_info *sta = file->private_data; | ||
333 | struct ieee80211_sta_vht_cap *vhtc = &sta->sta.vht_cap; | ||
334 | |||
335 | p += scnprintf(p, sizeof(buf) + buf - p, "VHT %ssupported\n", | ||
336 | vhtc->vht_supported ? "" : "not "); | ||
337 | if (vhtc->vht_supported) { | ||
338 | p += scnprintf(p, sizeof(buf)+buf-p, "cap: %#.8x\n", vhtc->cap); | ||
339 | |||
340 | p += scnprintf(p, sizeof(buf)+buf-p, "RX MCS: %.4x\n", | ||
341 | le16_to_cpu(vhtc->vht_mcs.rx_mcs_map)); | ||
342 | if (vhtc->vht_mcs.rx_highest) | ||
343 | p += scnprintf(p, sizeof(buf)+buf-p, | ||
344 | "MCS RX highest: %d Mbps\n", | ||
345 | le16_to_cpu(vhtc->vht_mcs.rx_highest)); | ||
346 | p += scnprintf(p, sizeof(buf)+buf-p, "TX MCS: %.4x\n", | ||
347 | le16_to_cpu(vhtc->vht_mcs.tx_mcs_map)); | ||
348 | if (vhtc->vht_mcs.tx_highest) | ||
349 | p += scnprintf(p, sizeof(buf)+buf-p, | ||
350 | "MCS TX highest: %d Mbps\n", | ||
351 | le16_to_cpu(vhtc->vht_mcs.tx_highest)); | ||
352 | } | ||
353 | |||
354 | return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); | ||
355 | } | ||
356 | STA_OPS(vht_capa); | ||
357 | |||
328 | static ssize_t sta_current_tx_rate_read(struct file *file, char __user *userbuf, | 358 | static ssize_t sta_current_tx_rate_read(struct file *file, char __user *userbuf, |
329 | size_t count, loff_t *ppos) | 359 | size_t count, loff_t *ppos) |
330 | { | 360 | { |
@@ -405,6 +435,7 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) | |||
405 | DEBUGFS_ADD(dev); | 435 | DEBUGFS_ADD(dev); |
406 | DEBUGFS_ADD(last_signal); | 436 | DEBUGFS_ADD(last_signal); |
407 | DEBUGFS_ADD(ht_capa); | 437 | DEBUGFS_ADD(ht_capa); |
438 | DEBUGFS_ADD(vht_capa); | ||
408 | DEBUGFS_ADD(last_ack_signal); | 439 | DEBUGFS_ADD(last_ack_signal); |
409 | DEBUGFS_ADD(current_tx_rate); | 440 | DEBUGFS_ADD(current_tx_rate); |
410 | DEBUGFS_ADD(last_rx_rate); | 441 | DEBUGFS_ADD(last_rx_rate); |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index ee56d0779d8b..832acea4a5cb 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -787,15 +787,16 @@ static inline int drv_get_antenna(struct ieee80211_local *local, | |||
787 | static inline int drv_remain_on_channel(struct ieee80211_local *local, | 787 | static inline int drv_remain_on_channel(struct ieee80211_local *local, |
788 | struct ieee80211_sub_if_data *sdata, | 788 | struct ieee80211_sub_if_data *sdata, |
789 | struct ieee80211_channel *chan, | 789 | struct ieee80211_channel *chan, |
790 | unsigned int duration) | 790 | unsigned int duration, |
791 | enum ieee80211_roc_type type) | ||
791 | { | 792 | { |
792 | int ret; | 793 | int ret; |
793 | 794 | ||
794 | might_sleep(); | 795 | might_sleep(); |
795 | 796 | ||
796 | trace_drv_remain_on_channel(local, sdata, chan, duration); | 797 | trace_drv_remain_on_channel(local, sdata, chan, duration, type); |
797 | ret = local->ops->remain_on_channel(&local->hw, &sdata->vif, | 798 | ret = local->ops->remain_on_channel(&local->hw, &sdata->vif, |
798 | chan, duration); | 799 | chan, duration, type); |
799 | trace_drv_return_int(local, ret); | 800 | trace_drv_return_int(local, ret); |
800 | 801 | ||
801 | return ret; | 802 | return ret; |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 0db25d4bb223..af8cee06e4f3 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -40,13 +40,6 @@ void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, | |||
40 | if (!ht_cap->ht_supported) | 40 | if (!ht_cap->ht_supported) |
41 | return; | 41 | return; |
42 | 42 | ||
43 | if (sdata->vif.type != NL80211_IFTYPE_STATION) { | ||
44 | /* AP interfaces call this code when adding new stations, | ||
45 | * so just silently ignore non station interfaces. | ||
46 | */ | ||
47 | return; | ||
48 | } | ||
49 | |||
50 | /* NOTE: If you add more over-rides here, update register_hw | 43 | /* NOTE: If you add more over-rides here, update register_hw |
51 | * ht_capa_mod_msk logic in main.c as well. | 44 | * ht_capa_mod_msk logic in main.c as well. |
52 | * And, if this method can ever change ht_cap.ht_supported, fix | 45 | * And, if this method can ever change ht_cap.ht_supported, fix |
@@ -97,7 +90,7 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, | |||
97 | const struct ieee80211_ht_cap *ht_cap_ie, | 90 | const struct ieee80211_ht_cap *ht_cap_ie, |
98 | struct sta_info *sta) | 91 | struct sta_info *sta) |
99 | { | 92 | { |
100 | struct ieee80211_sta_ht_cap ht_cap; | 93 | struct ieee80211_sta_ht_cap ht_cap, own_cap; |
101 | u8 ampdu_info, tx_mcs_set_cap; | 94 | u8 ampdu_info, tx_mcs_set_cap; |
102 | int i, max_tx_streams; | 95 | int i, max_tx_streams; |
103 | bool changed; | 96 | bool changed; |
@@ -111,6 +104,18 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, | |||
111 | 104 | ||
112 | ht_cap.ht_supported = true; | 105 | ht_cap.ht_supported = true; |
113 | 106 | ||
107 | own_cap = sband->ht_cap; | ||
108 | |||
109 | /* | ||
110 | * If user has specified capability over-rides, take care | ||
111 | * of that if the station we're setting up is the AP that | ||
112 | * we advertised a restricted capability set to. Override | ||
113 | * our own capabilities and then use those below. | ||
114 | */ | ||
115 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | ||
116 | !test_sta_flag(sta, WLAN_STA_TDLS_PEER)) | ||
117 | ieee80211_apply_htcap_overrides(sdata, &own_cap); | ||
118 | |||
114 | /* | 119 | /* |
115 | * The bits listed in this expression should be | 120 | * The bits listed in this expression should be |
116 | * the same for the peer and us, if the station | 121 | * the same for the peer and us, if the station |
@@ -118,21 +123,20 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, | |||
118 | * we mask them out. | 123 | * we mask them out. |
119 | */ | 124 | */ |
120 | ht_cap.cap = le16_to_cpu(ht_cap_ie->cap_info) & | 125 | ht_cap.cap = le16_to_cpu(ht_cap_ie->cap_info) & |
121 | (sband->ht_cap.cap | | 126 | (own_cap.cap | ~(IEEE80211_HT_CAP_LDPC_CODING | |
122 | ~(IEEE80211_HT_CAP_LDPC_CODING | | 127 | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | |
123 | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | | 128 | IEEE80211_HT_CAP_GRN_FLD | |
124 | IEEE80211_HT_CAP_GRN_FLD | | 129 | IEEE80211_HT_CAP_SGI_20 | |
125 | IEEE80211_HT_CAP_SGI_20 | | 130 | IEEE80211_HT_CAP_SGI_40 | |
126 | IEEE80211_HT_CAP_SGI_40 | | 131 | IEEE80211_HT_CAP_DSSSCCK40)); |
127 | IEEE80211_HT_CAP_DSSSCCK40)); | ||
128 | 132 | ||
129 | /* | 133 | /* |
130 | * The STBC bits are asymmetric -- if we don't have | 134 | * The STBC bits are asymmetric -- if we don't have |
131 | * TX then mask out the peer's RX and vice versa. | 135 | * TX then mask out the peer's RX and vice versa. |
132 | */ | 136 | */ |
133 | if (!(sband->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC)) | 137 | if (!(own_cap.cap & IEEE80211_HT_CAP_TX_STBC)) |
134 | ht_cap.cap &= ~IEEE80211_HT_CAP_RX_STBC; | 138 | ht_cap.cap &= ~IEEE80211_HT_CAP_RX_STBC; |
135 | if (!(sband->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC)) | 139 | if (!(own_cap.cap & IEEE80211_HT_CAP_RX_STBC)) |
136 | ht_cap.cap &= ~IEEE80211_HT_CAP_TX_STBC; | 140 | ht_cap.cap &= ~IEEE80211_HT_CAP_TX_STBC; |
137 | 141 | ||
138 | ampdu_info = ht_cap_ie->ampdu_params_info; | 142 | ampdu_info = ht_cap_ie->ampdu_params_info; |
@@ -142,7 +146,7 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, | |||
142 | (ampdu_info & IEEE80211_HT_AMPDU_PARM_DENSITY) >> 2; | 146 | (ampdu_info & IEEE80211_HT_AMPDU_PARM_DENSITY) >> 2; |
143 | 147 | ||
144 | /* own MCS TX capabilities */ | 148 | /* own MCS TX capabilities */ |
145 | tx_mcs_set_cap = sband->ht_cap.mcs.tx_params; | 149 | tx_mcs_set_cap = own_cap.mcs.tx_params; |
146 | 150 | ||
147 | /* Copy peer MCS TX capabilities, the driver might need them. */ | 151 | /* Copy peer MCS TX capabilities, the driver might need them. */ |
148 | ht_cap.mcs.tx_params = ht_cap_ie->mcs.tx_params; | 152 | ht_cap.mcs.tx_params = ht_cap_ie->mcs.tx_params; |
@@ -168,26 +172,20 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, | |||
168 | */ | 172 | */ |
169 | for (i = 0; i < max_tx_streams; i++) | 173 | for (i = 0; i < max_tx_streams; i++) |
170 | ht_cap.mcs.rx_mask[i] = | 174 | ht_cap.mcs.rx_mask[i] = |
171 | sband->ht_cap.mcs.rx_mask[i] & ht_cap_ie->mcs.rx_mask[i]; | 175 | own_cap.mcs.rx_mask[i] & ht_cap_ie->mcs.rx_mask[i]; |
172 | 176 | ||
173 | if (tx_mcs_set_cap & IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION) | 177 | if (tx_mcs_set_cap & IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION) |
174 | for (i = IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE; | 178 | for (i = IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE; |
175 | i < IEEE80211_HT_MCS_MASK_LEN; i++) | 179 | i < IEEE80211_HT_MCS_MASK_LEN; i++) |
176 | ht_cap.mcs.rx_mask[i] = | 180 | ht_cap.mcs.rx_mask[i] = |
177 | sband->ht_cap.mcs.rx_mask[i] & | 181 | own_cap.mcs.rx_mask[i] & |
178 | ht_cap_ie->mcs.rx_mask[i]; | 182 | ht_cap_ie->mcs.rx_mask[i]; |
179 | 183 | ||
180 | /* handle MCS rate 32 too */ | 184 | /* handle MCS rate 32 too */ |
181 | if (sband->ht_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1) | 185 | if (own_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1) |
182 | ht_cap.mcs.rx_mask[32/8] |= 1; | 186 | ht_cap.mcs.rx_mask[32/8] |= 1; |
183 | 187 | ||
184 | apply: | 188 | apply: |
185 | /* | ||
186 | * If user has specified capability over-rides, take care | ||
187 | * of that here. | ||
188 | */ | ||
189 | ieee80211_apply_htcap_overrides(sdata, &ht_cap); | ||
190 | |||
191 | changed = memcmp(&sta->sta.ht_cap, &ht_cap, sizeof(ht_cap)); | 189 | changed = memcmp(&sta->sta.ht_cap, &ht_cap, sizeof(ht_cap)); |
192 | 190 | ||
193 | memcpy(&sta->sta.ht_cap, &ht_cap, sizeof(ht_cap)); | 191 | memcpy(&sta->sta.ht_cap, &ht_cap, sizeof(ht_cap)); |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 40b71dfcc79d..539d4a11b47b 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -985,36 +985,9 @@ static void ieee80211_ibss_timer(unsigned long data) | |||
985 | { | 985 | { |
986 | struct ieee80211_sub_if_data *sdata = | 986 | struct ieee80211_sub_if_data *sdata = |
987 | (struct ieee80211_sub_if_data *) data; | 987 | (struct ieee80211_sub_if_data *) data; |
988 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | ||
989 | struct ieee80211_local *local = sdata->local; | ||
990 | |||
991 | if (local->quiescing) { | ||
992 | ifibss->timer_running = true; | ||
993 | return; | ||
994 | } | ||
995 | |||
996 | ieee80211_queue_work(&local->hw, &sdata->work); | ||
997 | } | ||
998 | |||
999 | #ifdef CONFIG_PM | ||
1000 | void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata) | ||
1001 | { | ||
1002 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | ||
1003 | 988 | ||
1004 | if (del_timer_sync(&ifibss->timer)) | 989 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); |
1005 | ifibss->timer_running = true; | ||
1006 | } | ||
1007 | |||
1008 | void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata) | ||
1009 | { | ||
1010 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | ||
1011 | |||
1012 | if (ifibss->timer_running) { | ||
1013 | add_timer(&ifibss->timer); | ||
1014 | ifibss->timer_running = false; | ||
1015 | } | ||
1016 | } | 990 | } |
1017 | #endif | ||
1018 | 991 | ||
1019 | void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata) | 992 | void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata) |
1020 | { | 993 | { |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 388580a1bada..f4433f081e77 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -315,6 +315,7 @@ struct ieee80211_roc_work { | |||
315 | u32 duration, req_duration; | 315 | u32 duration, req_duration; |
316 | struct sk_buff *frame; | 316 | struct sk_buff *frame; |
317 | u64 cookie, mgmt_tx_cookie; | 317 | u64 cookie, mgmt_tx_cookie; |
318 | enum ieee80211_roc_type type; | ||
318 | }; | 319 | }; |
319 | 320 | ||
320 | /* flags used in struct ieee80211_if_managed.flags */ | 321 | /* flags used in struct ieee80211_if_managed.flags */ |
@@ -400,7 +401,6 @@ struct ieee80211_if_managed { | |||
400 | 401 | ||
401 | u16 aid; | 402 | u16 aid; |
402 | 403 | ||
403 | unsigned long timers_running; /* used for quiesce/restart */ | ||
404 | bool powersave; /* powersave requested for this iface */ | 404 | bool powersave; /* powersave requested for this iface */ |
405 | bool broken_ap; /* AP is broken -- turn off powersave */ | 405 | bool broken_ap; /* AP is broken -- turn off powersave */ |
406 | u8 dtim_period; | 406 | u8 dtim_period; |
@@ -479,6 +479,8 @@ struct ieee80211_if_managed { | |||
479 | 479 | ||
480 | struct ieee80211_ht_cap ht_capa; /* configured ht-cap over-rides */ | 480 | struct ieee80211_ht_cap ht_capa; /* configured ht-cap over-rides */ |
481 | struct ieee80211_ht_cap ht_capa_mask; /* Valid parts of ht_capa */ | 481 | struct ieee80211_ht_cap ht_capa_mask; /* Valid parts of ht_capa */ |
482 | struct ieee80211_vht_cap vht_capa; /* configured VHT overrides */ | ||
483 | struct ieee80211_vht_cap vht_capa_mask; /* Valid parts of vht_capa */ | ||
482 | }; | 484 | }; |
483 | 485 | ||
484 | struct ieee80211_if_ibss { | 486 | struct ieee80211_if_ibss { |
@@ -490,8 +492,6 @@ struct ieee80211_if_ibss { | |||
490 | 492 | ||
491 | u32 basic_rates; | 493 | u32 basic_rates; |
492 | 494 | ||
493 | bool timer_running; | ||
494 | |||
495 | bool fixed_bssid; | 495 | bool fixed_bssid; |
496 | bool fixed_channel; | 496 | bool fixed_channel; |
497 | bool privacy; | 497 | bool privacy; |
@@ -543,8 +543,6 @@ struct ieee80211_if_mesh { | |||
543 | struct timer_list mesh_path_timer; | 543 | struct timer_list mesh_path_timer; |
544 | struct timer_list mesh_path_root_timer; | 544 | struct timer_list mesh_path_root_timer; |
545 | 545 | ||
546 | unsigned long timers_running; | ||
547 | |||
548 | unsigned long wrkq_flags; | 546 | unsigned long wrkq_flags; |
549 | 547 | ||
550 | u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; | 548 | u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; |
@@ -590,6 +588,7 @@ struct ieee80211_if_mesh { | |||
590 | IEEE80211_MESH_SEC_AUTHED = 0x1, | 588 | IEEE80211_MESH_SEC_AUTHED = 0x1, |
591 | IEEE80211_MESH_SEC_SECURED = 0x2, | 589 | IEEE80211_MESH_SEC_SECURED = 0x2, |
592 | } security; | 590 | } security; |
591 | bool user_mpm; | ||
593 | /* Extensible Synchronization Framework */ | 592 | /* Extensible Synchronization Framework */ |
594 | const struct ieee80211_mesh_sync_ops *sync_ops; | 593 | const struct ieee80211_mesh_sync_ops *sync_ops; |
595 | s64 sync_offset_clockdrift_max; | 594 | s64 sync_offset_clockdrift_max; |
@@ -682,6 +681,8 @@ struct ieee80211_sub_if_data { | |||
682 | 681 | ||
683 | /* count for keys needing tailroom space allocation */ | 682 | /* count for keys needing tailroom space allocation */ |
684 | int crypto_tx_tailroom_needed_cnt; | 683 | int crypto_tx_tailroom_needed_cnt; |
684 | int crypto_tx_tailroom_pending_dec; | ||
685 | struct delayed_work dec_tailroom_needed_wk; | ||
685 | 686 | ||
686 | struct net_device *dev; | 687 | struct net_device *dev; |
687 | struct ieee80211_local *local; | 688 | struct ieee80211_local *local; |
@@ -765,10 +766,6 @@ struct ieee80211_sub_if_data { | |||
765 | } debugfs; | 766 | } debugfs; |
766 | #endif | 767 | #endif |
767 | 768 | ||
768 | #ifdef CONFIG_PM | ||
769 | struct ieee80211_bss_conf suspend_bss_conf; | ||
770 | #endif | ||
771 | |||
772 | /* must be last, dynamically sized area in this! */ | 769 | /* must be last, dynamically sized area in this! */ |
773 | struct ieee80211_vif vif; | 770 | struct ieee80211_vif vif; |
774 | }; | 771 | }; |
@@ -1136,11 +1133,6 @@ struct ieee80211_local { | |||
1136 | 1133 | ||
1137 | struct ieee80211_sub_if_data __rcu *p2p_sdata; | 1134 | struct ieee80211_sub_if_data __rcu *p2p_sdata; |
1138 | 1135 | ||
1139 | /* dummy netdev for use w/ NAPI */ | ||
1140 | struct net_device napi_dev; | ||
1141 | |||
1142 | struct napi_struct napi; | ||
1143 | |||
1144 | /* virtual monitor interface */ | 1136 | /* virtual monitor interface */ |
1145 | struct ieee80211_sub_if_data __rcu *monitor_sdata; | 1137 | struct ieee80211_sub_if_data __rcu *monitor_sdata; |
1146 | struct cfg80211_chan_def monitor_chandef; | 1138 | struct cfg80211_chan_def monitor_chandef; |
@@ -1283,8 +1275,6 @@ void | |||
1283 | ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | 1275 | ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, |
1284 | const struct ieee80211_channel_sw_ie *sw_elem, | 1276 | const struct ieee80211_channel_sw_ie *sw_elem, |
1285 | struct ieee80211_bss *bss, u64 timestamp); | 1277 | struct ieee80211_bss *bss, u64 timestamp); |
1286 | void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata); | ||
1287 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); | ||
1288 | void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata); | 1278 | void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata); |
1289 | void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | 1279 | void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, |
1290 | struct sk_buff *skb); | 1280 | struct sk_buff *skb); |
@@ -1302,8 +1292,6 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, | |||
1302 | int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | 1292 | int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, |
1303 | struct cfg80211_ibss_params *params); | 1293 | struct cfg80211_ibss_params *params); |
1304 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); | 1294 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); |
1305 | void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata); | ||
1306 | void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata); | ||
1307 | void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata); | 1295 | void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata); |
1308 | void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | 1296 | void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, |
1309 | struct sk_buff *skb); | 1297 | struct sk_buff *skb); |
@@ -1441,6 +1429,8 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta); | |||
1441 | void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | 1429 | void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, |
1442 | struct sta_info *sta, u8 opmode, | 1430 | struct sta_info *sta, u8 opmode, |
1443 | enum ieee80211_band band, bool nss_only); | 1431 | enum ieee80211_band band, bool nss_only); |
1432 | void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata, | ||
1433 | struct ieee80211_sta_vht_cap *vht_cap); | ||
1444 | 1434 | ||
1445 | /* Spectrum management */ | 1435 | /* Spectrum management */ |
1446 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, | 1436 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 2c059e54e885..d85282f64405 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -107,7 +107,7 @@ void ieee80211_recalc_idle(struct ieee80211_local *local) | |||
107 | 107 | ||
108 | lockdep_assert_held(&local->mtx); | 108 | lockdep_assert_held(&local->mtx); |
109 | 109 | ||
110 | active = !list_empty(&local->chanctx_list); | 110 | active = !list_empty(&local->chanctx_list) || local->monitors; |
111 | 111 | ||
112 | if (!local->ops->remain_on_channel) { | 112 | if (!local->ops->remain_on_channel) { |
113 | list_for_each_entry(roc, &local->roc_list, list) { | 113 | list_for_each_entry(roc, &local->roc_list, list) { |
@@ -485,8 +485,6 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) | |||
485 | res = drv_start(local); | 485 | res = drv_start(local); |
486 | if (res) | 486 | if (res) |
487 | goto err_del_bss; | 487 | goto err_del_bss; |
488 | if (local->ops->napi_poll) | ||
489 | napi_enable(&local->napi); | ||
490 | /* we're brought up, everything changes */ | 488 | /* we're brought up, everything changes */ |
491 | hw_reconf_flags = ~0; | 489 | hw_reconf_flags = ~0; |
492 | ieee80211_led_radio(local, true); | 490 | ieee80211_led_radio(local, true); |
@@ -541,6 +539,9 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) | |||
541 | 539 | ||
542 | ieee80211_adjust_monitor_flags(sdata, 1); | 540 | ieee80211_adjust_monitor_flags(sdata, 1); |
543 | ieee80211_configure_filter(local); | 541 | ieee80211_configure_filter(local); |
542 | mutex_lock(&local->mtx); | ||
543 | ieee80211_recalc_idle(local); | ||
544 | mutex_unlock(&local->mtx); | ||
544 | 545 | ||
545 | netif_carrier_on(dev); | 546 | netif_carrier_on(dev); |
546 | break; | 547 | break; |
@@ -812,6 +813,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
812 | 813 | ||
813 | ieee80211_adjust_monitor_flags(sdata, -1); | 814 | ieee80211_adjust_monitor_flags(sdata, -1); |
814 | ieee80211_configure_filter(local); | 815 | ieee80211_configure_filter(local); |
816 | mutex_lock(&local->mtx); | ||
817 | ieee80211_recalc_idle(local); | ||
818 | mutex_unlock(&local->mtx); | ||
815 | break; | 819 | break; |
816 | case NL80211_IFTYPE_P2P_DEVICE: | 820 | case NL80211_IFTYPE_P2P_DEVICE: |
817 | /* relies on synchronize_rcu() below */ | 821 | /* relies on synchronize_rcu() below */ |
@@ -832,14 +836,16 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
832 | rcu_barrier(); | 836 | rcu_barrier(); |
833 | sta_info_flush_cleanup(sdata); | 837 | sta_info_flush_cleanup(sdata); |
834 | 838 | ||
835 | skb_queue_purge(&sdata->skb_queue); | ||
836 | |||
837 | /* | 839 | /* |
838 | * Free all remaining keys, there shouldn't be any, | 840 | * Free all remaining keys, there shouldn't be any, |
839 | * except maybe group keys in AP more or WDS? | 841 | * except maybe in WDS mode? |
840 | */ | 842 | */ |
841 | ieee80211_free_keys(sdata); | 843 | ieee80211_free_keys(sdata); |
842 | 844 | ||
845 | /* fall through */ | ||
846 | case NL80211_IFTYPE_AP: | ||
847 | skb_queue_purge(&sdata->skb_queue); | ||
848 | |||
843 | drv_remove_interface_debugfs(local, sdata); | 849 | drv_remove_interface_debugfs(local, sdata); |
844 | 850 | ||
845 | if (going_down) | 851 | if (going_down) |
@@ -851,8 +857,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
851 | ieee80211_recalc_ps(local, -1); | 857 | ieee80211_recalc_ps(local, -1); |
852 | 858 | ||
853 | if (local->open_count == 0) { | 859 | if (local->open_count == 0) { |
854 | if (local->ops->napi_poll) | ||
855 | napi_disable(&local->napi); | ||
856 | ieee80211_clear_tx_pending(local); | 860 | ieee80211_clear_tx_pending(local); |
857 | ieee80211_stop_device(local); | 861 | ieee80211_stop_device(local); |
858 | 862 | ||
@@ -1541,6 +1545,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1541 | INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk); | 1545 | INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk); |
1542 | INIT_DELAYED_WORK(&sdata->dfs_cac_timer_work, | 1546 | INIT_DELAYED_WORK(&sdata->dfs_cac_timer_work, |
1543 | ieee80211_dfs_cac_timer_work); | 1547 | ieee80211_dfs_cac_timer_work); |
1548 | INIT_DELAYED_WORK(&sdata->dec_tailroom_needed_wk, | ||
1549 | ieee80211_delayed_tailroom_dec); | ||
1544 | 1550 | ||
1545 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { | 1551 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { |
1546 | struct ieee80211_supported_band *sband; | 1552 | struct ieee80211_supported_band *sband; |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index ef252eb58c36..99e9f6ae6a54 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -397,7 +397,8 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, | |||
397 | return key; | 397 | return key; |
398 | } | 398 | } |
399 | 399 | ||
400 | static void __ieee80211_key_destroy(struct ieee80211_key *key) | 400 | static void __ieee80211_key_destroy(struct ieee80211_key *key, |
401 | bool delay_tailroom) | ||
401 | { | 402 | { |
402 | if (!key) | 403 | if (!key) |
403 | return; | 404 | return; |
@@ -416,8 +417,18 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key) | |||
416 | if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) | 417 | if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) |
417 | ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); | 418 | ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); |
418 | if (key->local) { | 419 | if (key->local) { |
420 | struct ieee80211_sub_if_data *sdata = key->sdata; | ||
421 | |||
419 | ieee80211_debugfs_key_remove(key); | 422 | ieee80211_debugfs_key_remove(key); |
420 | key->sdata->crypto_tx_tailroom_needed_cnt--; | 423 | |
424 | if (delay_tailroom) { | ||
425 | /* see ieee80211_delayed_tailroom_dec */ | ||
426 | sdata->crypto_tx_tailroom_pending_dec++; | ||
427 | schedule_delayed_work(&sdata->dec_tailroom_needed_wk, | ||
428 | HZ/2); | ||
429 | } else { | ||
430 | sdata->crypto_tx_tailroom_needed_cnt--; | ||
431 | } | ||
421 | } | 432 | } |
422 | 433 | ||
423 | kfree(key); | 434 | kfree(key); |
@@ -440,32 +451,6 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
440 | key->sdata = sdata; | 451 | key->sdata = sdata; |
441 | key->sta = sta; | 452 | key->sta = sta; |
442 | 453 | ||
443 | if (sta) { | ||
444 | /* | ||
445 | * some hardware cannot handle TKIP with QoS, so | ||
446 | * we indicate whether QoS could be in use. | ||
447 | */ | ||
448 | if (test_sta_flag(sta, WLAN_STA_WME)) | ||
449 | key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA; | ||
450 | } else { | ||
451 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
452 | struct sta_info *ap; | ||
453 | |||
454 | /* | ||
455 | * We're getting a sta pointer in, so must be under | ||
456 | * appropriate locking for sta_info_get(). | ||
457 | */ | ||
458 | |||
459 | /* same here, the AP could be using QoS */ | ||
460 | ap = sta_info_get(key->sdata, key->sdata->u.mgd.bssid); | ||
461 | if (ap) { | ||
462 | if (test_sta_flag(ap, WLAN_STA_WME)) | ||
463 | key->conf.flags |= | ||
464 | IEEE80211_KEY_FLAG_WMM_STA; | ||
465 | } | ||
466 | } | ||
467 | } | ||
468 | |||
469 | mutex_lock(&sdata->local->key_mtx); | 454 | mutex_lock(&sdata->local->key_mtx); |
470 | 455 | ||
471 | if (sta && pairwise) | 456 | if (sta && pairwise) |
@@ -478,7 +463,7 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
478 | increment_tailroom_need_count(sdata); | 463 | increment_tailroom_need_count(sdata); |
479 | 464 | ||
480 | __ieee80211_key_replace(sdata, sta, pairwise, old_key, key); | 465 | __ieee80211_key_replace(sdata, sta, pairwise, old_key, key); |
481 | __ieee80211_key_destroy(old_key); | 466 | __ieee80211_key_destroy(old_key, true); |
482 | 467 | ||
483 | ieee80211_debugfs_key_add(key); | 468 | ieee80211_debugfs_key_add(key); |
484 | 469 | ||
@@ -489,7 +474,7 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
489 | return ret; | 474 | return ret; |
490 | } | 475 | } |
491 | 476 | ||
492 | void __ieee80211_key_free(struct ieee80211_key *key) | 477 | void __ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom) |
493 | { | 478 | { |
494 | if (!key) | 479 | if (!key) |
495 | return; | 480 | return; |
@@ -501,14 +486,14 @@ void __ieee80211_key_free(struct ieee80211_key *key) | |||
501 | __ieee80211_key_replace(key->sdata, key->sta, | 486 | __ieee80211_key_replace(key->sdata, key->sta, |
502 | key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, | 487 | key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, |
503 | key, NULL); | 488 | key, NULL); |
504 | __ieee80211_key_destroy(key); | 489 | __ieee80211_key_destroy(key, delay_tailroom); |
505 | } | 490 | } |
506 | 491 | ||
507 | void ieee80211_key_free(struct ieee80211_local *local, | 492 | void ieee80211_key_free(struct ieee80211_local *local, |
508 | struct ieee80211_key *key) | 493 | struct ieee80211_key *key) |
509 | { | 494 | { |
510 | mutex_lock(&local->key_mtx); | 495 | mutex_lock(&local->key_mtx); |
511 | __ieee80211_key_free(key); | 496 | __ieee80211_key_free(key, true); |
512 | mutex_unlock(&local->key_mtx); | 497 | mutex_unlock(&local->key_mtx); |
513 | } | 498 | } |
514 | 499 | ||
@@ -566,36 +551,60 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw, | |||
566 | } | 551 | } |
567 | EXPORT_SYMBOL(ieee80211_iter_keys); | 552 | EXPORT_SYMBOL(ieee80211_iter_keys); |
568 | 553 | ||
569 | void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata) | ||
570 | { | ||
571 | struct ieee80211_key *key; | ||
572 | |||
573 | ASSERT_RTNL(); | ||
574 | |||
575 | mutex_lock(&sdata->local->key_mtx); | ||
576 | |||
577 | list_for_each_entry(key, &sdata->key_list, list) | ||
578 | ieee80211_key_disable_hw_accel(key); | ||
579 | |||
580 | mutex_unlock(&sdata->local->key_mtx); | ||
581 | } | ||
582 | |||
583 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) | 554 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) |
584 | { | 555 | { |
585 | struct ieee80211_key *key, *tmp; | 556 | struct ieee80211_key *key, *tmp; |
586 | 557 | ||
558 | cancel_delayed_work_sync(&sdata->dec_tailroom_needed_wk); | ||
559 | |||
587 | mutex_lock(&sdata->local->key_mtx); | 560 | mutex_lock(&sdata->local->key_mtx); |
588 | 561 | ||
562 | sdata->crypto_tx_tailroom_needed_cnt -= | ||
563 | sdata->crypto_tx_tailroom_pending_dec; | ||
564 | sdata->crypto_tx_tailroom_pending_dec = 0; | ||
565 | |||
589 | ieee80211_debugfs_key_remove_mgmt_default(sdata); | 566 | ieee80211_debugfs_key_remove_mgmt_default(sdata); |
590 | 567 | ||
591 | list_for_each_entry_safe(key, tmp, &sdata->key_list, list) | 568 | list_for_each_entry_safe(key, tmp, &sdata->key_list, list) |
592 | __ieee80211_key_free(key); | 569 | __ieee80211_key_free(key, false); |
593 | 570 | ||
594 | ieee80211_debugfs_key_update_default(sdata); | 571 | ieee80211_debugfs_key_update_default(sdata); |
595 | 572 | ||
573 | WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt || | ||
574 | sdata->crypto_tx_tailroom_pending_dec); | ||
575 | |||
596 | mutex_unlock(&sdata->local->key_mtx); | 576 | mutex_unlock(&sdata->local->key_mtx); |
597 | } | 577 | } |
598 | 578 | ||
579 | void ieee80211_delayed_tailroom_dec(struct work_struct *wk) | ||
580 | { | ||
581 | struct ieee80211_sub_if_data *sdata; | ||
582 | |||
583 | sdata = container_of(wk, struct ieee80211_sub_if_data, | ||
584 | dec_tailroom_needed_wk.work); | ||
585 | |||
586 | /* | ||
587 | * The reason for the delayed tailroom needed decrementing is to | ||
588 | * make roaming faster: during roaming, all keys are first deleted | ||
589 | * and then new keys are installed. The first new key causes the | ||
590 | * crypto_tx_tailroom_needed_cnt to go from 0 to 1, which invokes | ||
591 | * the cost of synchronize_net() (which can be slow). Avoid this | ||
592 | * by deferring the crypto_tx_tailroom_needed_cnt decrementing on | ||
593 | * key removal for a while, so if we roam the value is larger than | ||
594 | * zero and no 0->1 transition happens. | ||
595 | * | ||
596 | * The cost is that if the AP switching was from an AP with keys | ||
597 | * to one without, we still allocate tailroom while it would no | ||
598 | * longer be needed. However, in the typical (fast) roaming case | ||
599 | * within an ESS this usually won't happen. | ||
600 | */ | ||
601 | |||
602 | mutex_lock(&sdata->local->key_mtx); | ||
603 | sdata->crypto_tx_tailroom_needed_cnt -= | ||
604 | sdata->crypto_tx_tailroom_pending_dec; | ||
605 | sdata->crypto_tx_tailroom_pending_dec = 0; | ||
606 | mutex_unlock(&sdata->local->key_mtx); | ||
607 | } | ||
599 | 608 | ||
600 | void ieee80211_gtk_rekey_notify(struct ieee80211_vif *vif, const u8 *bssid, | 609 | void ieee80211_gtk_rekey_notify(struct ieee80211_vif *vif, const u8 *bssid, |
601 | const u8 *replay_ctr, gfp_t gfp) | 610 | const u8 *replay_ctr, gfp_t gfp) |
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 382dc44ed330..2a682d81cee9 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -134,7 +134,7 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, | |||
134 | int __must_check ieee80211_key_link(struct ieee80211_key *key, | 134 | int __must_check ieee80211_key_link(struct ieee80211_key *key, |
135 | struct ieee80211_sub_if_data *sdata, | 135 | struct ieee80211_sub_if_data *sdata, |
136 | struct sta_info *sta); | 136 | struct sta_info *sta); |
137 | void __ieee80211_key_free(struct ieee80211_key *key); | 137 | void __ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom); |
138 | void ieee80211_key_free(struct ieee80211_local *local, | 138 | void ieee80211_key_free(struct ieee80211_local *local, |
139 | struct ieee80211_key *key); | 139 | struct ieee80211_key *key); |
140 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, | 140 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, |
@@ -143,9 +143,10 @@ void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, | |||
143 | int idx); | 143 | int idx); |
144 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); | 144 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); |
145 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); | 145 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); |
146 | void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata); | ||
147 | 146 | ||
148 | #define key_mtx_dereference(local, ref) \ | 147 | #define key_mtx_dereference(local, ref) \ |
149 | rcu_dereference_protected(ref, lockdep_is_held(&((local)->key_mtx))) | 148 | rcu_dereference_protected(ref, lockdep_is_held(&((local)->key_mtx))) |
150 | 149 | ||
150 | void ieee80211_delayed_tailroom_dec(struct work_struct *wk); | ||
151 | |||
151 | #endif /* IEEE80211_KEY_H */ | 152 | #endif /* IEEE80211_KEY_H */ |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 1a8591b77a13..5a53aa5ede80 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -399,30 +399,6 @@ static int ieee80211_ifa6_changed(struct notifier_block *nb, | |||
399 | } | 399 | } |
400 | #endif | 400 | #endif |
401 | 401 | ||
402 | static int ieee80211_napi_poll(struct napi_struct *napi, int budget) | ||
403 | { | ||
404 | struct ieee80211_local *local = | ||
405 | container_of(napi, struct ieee80211_local, napi); | ||
406 | |||
407 | return local->ops->napi_poll(&local->hw, budget); | ||
408 | } | ||
409 | |||
410 | void ieee80211_napi_schedule(struct ieee80211_hw *hw) | ||
411 | { | ||
412 | struct ieee80211_local *local = hw_to_local(hw); | ||
413 | |||
414 | napi_schedule(&local->napi); | ||
415 | } | ||
416 | EXPORT_SYMBOL(ieee80211_napi_schedule); | ||
417 | |||
418 | void ieee80211_napi_complete(struct ieee80211_hw *hw) | ||
419 | { | ||
420 | struct ieee80211_local *local = hw_to_local(hw); | ||
421 | |||
422 | napi_complete(&local->napi); | ||
423 | } | ||
424 | EXPORT_SYMBOL(ieee80211_napi_complete); | ||
425 | |||
426 | /* There isn't a lot of sense in it, but you can transmit anything you like */ | 402 | /* There isn't a lot of sense in it, but you can transmit anything you like */ |
427 | static const struct ieee80211_txrx_stypes | 403 | static const struct ieee80211_txrx_stypes |
428 | ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { | 404 | ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { |
@@ -501,6 +477,27 @@ static const struct ieee80211_ht_cap mac80211_ht_capa_mod_mask = { | |||
501 | }, | 477 | }, |
502 | }; | 478 | }; |
503 | 479 | ||
480 | static const struct ieee80211_vht_cap mac80211_vht_capa_mod_mask = { | ||
481 | .vht_cap_info = | ||
482 | cpu_to_le32(IEEE80211_VHT_CAP_RXLDPC | | ||
483 | IEEE80211_VHT_CAP_SHORT_GI_80 | | ||
484 | IEEE80211_VHT_CAP_SHORT_GI_160 | | ||
485 | IEEE80211_VHT_CAP_RXSTBC_1 | | ||
486 | IEEE80211_VHT_CAP_RXSTBC_2 | | ||
487 | IEEE80211_VHT_CAP_RXSTBC_3 | | ||
488 | IEEE80211_VHT_CAP_RXSTBC_4 | | ||
489 | IEEE80211_VHT_CAP_TXSTBC | | ||
490 | IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | | ||
491 | IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | | ||
492 | IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN | | ||
493 | IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | | ||
494 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK), | ||
495 | .supp_mcs = { | ||
496 | .rx_mcs_map = cpu_to_le16(~0), | ||
497 | .tx_mcs_map = cpu_to_le16(~0), | ||
498 | }, | ||
499 | }; | ||
500 | |||
504 | static const u8 extended_capabilities[] = { | 501 | static const u8 extended_capabilities[] = { |
505 | 0, 0, 0, 0, 0, 0, 0, | 502 | 0, 0, 0, 0, 0, 0, 0, |
506 | WLAN_EXT_CAPA8_OPMODE_NOTIF, | 503 | WLAN_EXT_CAPA8_OPMODE_NOTIF, |
@@ -572,7 +569,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
572 | wiphy->features |= NL80211_FEATURE_SK_TX_STATUS | | 569 | wiphy->features |= NL80211_FEATURE_SK_TX_STATUS | |
573 | NL80211_FEATURE_SAE | | 570 | NL80211_FEATURE_SAE | |
574 | NL80211_FEATURE_HT_IBSS | | 571 | NL80211_FEATURE_HT_IBSS | |
575 | NL80211_FEATURE_VIF_TXPOWER; | 572 | NL80211_FEATURE_VIF_TXPOWER | |
573 | NL80211_FEATURE_USERSPACE_MPM; | ||
576 | 574 | ||
577 | if (!ops->hw_scan) | 575 | if (!ops->hw_scan) |
578 | wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN | | 576 | wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN | |
@@ -609,6 +607,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
609 | IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; | 607 | IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; |
610 | local->user_power_level = IEEE80211_UNSET_POWER_LEVEL; | 608 | local->user_power_level = IEEE80211_UNSET_POWER_LEVEL; |
611 | wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask; | 609 | wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask; |
610 | wiphy->vht_capa_mod_mask = &mac80211_vht_capa_mod_mask; | ||
612 | 611 | ||
613 | INIT_LIST_HEAD(&local->interfaces); | 612 | INIT_LIST_HEAD(&local->interfaces); |
614 | 613 | ||
@@ -664,9 +663,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
664 | skb_queue_head_init(&local->skb_queue); | 663 | skb_queue_head_init(&local->skb_queue); |
665 | skb_queue_head_init(&local->skb_queue_unreliable); | 664 | skb_queue_head_init(&local->skb_queue_unreliable); |
666 | 665 | ||
667 | /* init dummy netdev for use w/ NAPI */ | ||
668 | init_dummy_netdev(&local->napi_dev); | ||
669 | |||
670 | ieee80211_led_names(local); | 666 | ieee80211_led_names(local); |
671 | 667 | ||
672 | ieee80211_roc_setup(local); | 668 | ieee80211_roc_setup(local); |
@@ -1021,9 +1017,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1021 | goto fail_ifa6; | 1017 | goto fail_ifa6; |
1022 | #endif | 1018 | #endif |
1023 | 1019 | ||
1024 | netif_napi_add(&local->napi_dev, &local->napi, ieee80211_napi_poll, | ||
1025 | local->hw.napi_weight); | ||
1026 | |||
1027 | return 0; | 1020 | return 0; |
1028 | 1021 | ||
1029 | #if IS_ENABLED(CONFIG_IPV6) | 1022 | #if IS_ENABLED(CONFIG_IPV6) |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 29ce2aa87e7b..5ac017f3fcd2 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -13,10 +13,6 @@ | |||
13 | #include "ieee80211_i.h" | 13 | #include "ieee80211_i.h" |
14 | #include "mesh.h" | 14 | #include "mesh.h" |
15 | 15 | ||
16 | #define TMR_RUNNING_HK 0 | ||
17 | #define TMR_RUNNING_MP 1 | ||
18 | #define TMR_RUNNING_MPR 2 | ||
19 | |||
20 | static int mesh_allocated; | 16 | static int mesh_allocated; |
21 | static struct kmem_cache *rm_cache; | 17 | static struct kmem_cache *rm_cache; |
22 | 18 | ||
@@ -50,11 +46,6 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data) | |||
50 | 46 | ||
51 | set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); | 47 | set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); |
52 | 48 | ||
53 | if (local->quiescing) { | ||
54 | set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); | ||
55 | return; | ||
56 | } | ||
57 | |||
58 | ieee80211_queue_work(&local->hw, &sdata->work); | 49 | ieee80211_queue_work(&local->hw, &sdata->work); |
59 | } | 50 | } |
60 | 51 | ||
@@ -165,7 +156,7 @@ void mesh_sta_cleanup(struct sta_info *sta) | |||
165 | * an update. | 156 | * an update. |
166 | */ | 157 | */ |
167 | changed = mesh_accept_plinks_update(sdata); | 158 | changed = mesh_accept_plinks_update(sdata); |
168 | if (sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) { | 159 | if (!sdata->u.mesh.user_mpm) { |
169 | changed |= mesh_plink_deactivate(sta); | 160 | changed |= mesh_plink_deactivate(sta); |
170 | del_timer_sync(&sta->plink_timer); | 161 | del_timer_sync(&sta->plink_timer); |
171 | } | 162 | } |
@@ -479,15 +470,8 @@ static void ieee80211_mesh_path_timer(unsigned long data) | |||
479 | { | 470 | { |
480 | struct ieee80211_sub_if_data *sdata = | 471 | struct ieee80211_sub_if_data *sdata = |
481 | (struct ieee80211_sub_if_data *) data; | 472 | (struct ieee80211_sub_if_data *) data; |
482 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
483 | struct ieee80211_local *local = sdata->local; | ||
484 | |||
485 | if (local->quiescing) { | ||
486 | set_bit(TMR_RUNNING_MP, &ifmsh->timers_running); | ||
487 | return; | ||
488 | } | ||
489 | 473 | ||
490 | ieee80211_queue_work(&local->hw, &sdata->work); | 474 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); |
491 | } | 475 | } |
492 | 476 | ||
493 | static void ieee80211_mesh_path_root_timer(unsigned long data) | 477 | static void ieee80211_mesh_path_root_timer(unsigned long data) |
@@ -495,16 +479,10 @@ static void ieee80211_mesh_path_root_timer(unsigned long data) | |||
495 | struct ieee80211_sub_if_data *sdata = | 479 | struct ieee80211_sub_if_data *sdata = |
496 | (struct ieee80211_sub_if_data *) data; | 480 | (struct ieee80211_sub_if_data *) data; |
497 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 481 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
498 | struct ieee80211_local *local = sdata->local; | ||
499 | 482 | ||
500 | set_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags); | 483 | set_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags); |
501 | 484 | ||
502 | if (local->quiescing) { | 485 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); |
503 | set_bit(TMR_RUNNING_MPR, &ifmsh->timers_running); | ||
504 | return; | ||
505 | } | ||
506 | |||
507 | ieee80211_queue_work(&local->hw, &sdata->work); | ||
508 | } | 486 | } |
509 | 487 | ||
510 | void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh) | 488 | void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh) |
@@ -622,35 +600,6 @@ static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata) | |||
622 | round_jiffies(TU_TO_EXP_TIME(interval))); | 600 | round_jiffies(TU_TO_EXP_TIME(interval))); |
623 | } | 601 | } |
624 | 602 | ||
625 | #ifdef CONFIG_PM | ||
626 | void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) | ||
627 | { | ||
628 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
629 | |||
630 | /* use atomic bitops in case all timers fire at the same time */ | ||
631 | |||
632 | if (del_timer_sync(&ifmsh->housekeeping_timer)) | ||
633 | set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); | ||
634 | if (del_timer_sync(&ifmsh->mesh_path_timer)) | ||
635 | set_bit(TMR_RUNNING_MP, &ifmsh->timers_running); | ||
636 | if (del_timer_sync(&ifmsh->mesh_path_root_timer)) | ||
637 | set_bit(TMR_RUNNING_MPR, &ifmsh->timers_running); | ||
638 | } | ||
639 | |||
640 | void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata) | ||
641 | { | ||
642 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
643 | |||
644 | if (test_and_clear_bit(TMR_RUNNING_HK, &ifmsh->timers_running)) | ||
645 | add_timer(&ifmsh->housekeeping_timer); | ||
646 | if (test_and_clear_bit(TMR_RUNNING_MP, &ifmsh->timers_running)) | ||
647 | add_timer(&ifmsh->mesh_path_timer); | ||
648 | if (test_and_clear_bit(TMR_RUNNING_MPR, &ifmsh->timers_running)) | ||
649 | add_timer(&ifmsh->mesh_path_root_timer); | ||
650 | ieee80211_mesh_root_setup(ifmsh); | ||
651 | } | ||
652 | #endif | ||
653 | |||
654 | static int | 603 | static int |
655 | ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) | 604 | ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) |
656 | { | 605 | { |
@@ -871,8 +820,6 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) | |||
871 | local->fif_other_bss--; | 820 | local->fif_other_bss--; |
872 | atomic_dec(&local->iff_allmultis); | 821 | atomic_dec(&local->iff_allmultis); |
873 | ieee80211_configure_filter(local); | 822 | ieee80211_configure_filter(local); |
874 | |||
875 | sdata->u.mesh.timers_running = 0; | ||
876 | } | 823 | } |
877 | 824 | ||
878 | static void | 825 | static void |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 336c88a16687..6ffabbe99c46 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -313,8 +313,6 @@ void mesh_path_timer(unsigned long data); | |||
313 | void mesh_path_flush_by_nexthop(struct sta_info *sta); | 313 | void mesh_path_flush_by_nexthop(struct sta_info *sta); |
314 | void mesh_path_discard_frame(struct ieee80211_sub_if_data *sdata, | 314 | void mesh_path_discard_frame(struct ieee80211_sub_if_data *sdata, |
315 | struct sk_buff *skb); | 315 | struct sk_buff *skb); |
316 | void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata); | ||
317 | void mesh_path_restart(struct ieee80211_sub_if_data *sdata); | ||
318 | void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata); | 316 | void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata); |
319 | 317 | ||
320 | bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt); | 318 | bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt); |
@@ -359,22 +357,12 @@ static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) | |||
359 | 357 | ||
360 | void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local); | 358 | void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local); |
361 | 359 | ||
362 | void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata); | ||
363 | void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata); | ||
364 | void mesh_plink_quiesce(struct sta_info *sta); | ||
365 | void mesh_plink_restart(struct sta_info *sta); | ||
366 | void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata); | 360 | void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata); |
367 | void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata); | 361 | void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata); |
368 | void ieee80211s_stop(void); | 362 | void ieee80211s_stop(void); |
369 | #else | 363 | #else |
370 | static inline void | 364 | static inline void |
371 | ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {} | 365 | ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {} |
372 | static inline void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) | ||
373 | {} | ||
374 | static inline void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata) | ||
375 | {} | ||
376 | static inline void mesh_plink_quiesce(struct sta_info *sta) {} | ||
377 | static inline void mesh_plink_restart(struct sta_info *sta) {} | ||
378 | static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) | 366 | static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) |
379 | { return false; } | 367 | { return false; } |
380 | static inline void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) | 368 | static inline void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 07d396d57079..937e06fe8f2a 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -420,7 +420,6 @@ __mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *hw_addr) | |||
420 | return NULL; | 420 | return NULL; |
421 | 421 | ||
422 | sta->plink_state = NL80211_PLINK_LISTEN; | 422 | sta->plink_state = NL80211_PLINK_LISTEN; |
423 | init_timer(&sta->plink_timer); | ||
424 | 423 | ||
425 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); | 424 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); |
426 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); | 425 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); |
@@ -437,8 +436,9 @@ mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *addr, | |||
437 | { | 436 | { |
438 | struct sta_info *sta = NULL; | 437 | struct sta_info *sta = NULL; |
439 | 438 | ||
440 | /* Userspace handles peer allocation when security is enabled */ | 439 | /* Userspace handles station allocation */ |
441 | if (sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED) | 440 | if (sdata->u.mesh.user_mpm || |
441 | sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED) | ||
442 | cfg80211_notify_new_peer_candidate(sdata->dev, addr, | 442 | cfg80211_notify_new_peer_candidate(sdata->dev, addr, |
443 | elems->ie_start, | 443 | elems->ie_start, |
444 | elems->total_len, | 444 | elems->total_len, |
@@ -534,10 +534,8 @@ static void mesh_plink_timer(unsigned long data) | |||
534 | */ | 534 | */ |
535 | sta = (struct sta_info *) data; | 535 | sta = (struct sta_info *) data; |
536 | 536 | ||
537 | if (sta->sdata->local->quiescing) { | 537 | if (sta->sdata->local->quiescing) |
538 | sta->plink_timer_was_running = true; | ||
539 | return; | 538 | return; |
540 | } | ||
541 | 539 | ||
542 | spin_lock_bh(&sta->lock); | 540 | spin_lock_bh(&sta->lock); |
543 | if (sta->ignore_plink_timer) { | 541 | if (sta->ignore_plink_timer) { |
@@ -598,29 +596,6 @@ static void mesh_plink_timer(unsigned long data) | |||
598 | } | 596 | } |
599 | } | 597 | } |
600 | 598 | ||
601 | #ifdef CONFIG_PM | ||
602 | void mesh_plink_quiesce(struct sta_info *sta) | ||
603 | { | ||
604 | if (!ieee80211_vif_is_mesh(&sta->sdata->vif)) | ||
605 | return; | ||
606 | |||
607 | /* no kernel mesh sta timers have been initialized */ | ||
608 | if (sta->sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE) | ||
609 | return; | ||
610 | |||
611 | if (del_timer_sync(&sta->plink_timer)) | ||
612 | sta->plink_timer_was_running = true; | ||
613 | } | ||
614 | |||
615 | void mesh_plink_restart(struct sta_info *sta) | ||
616 | { | ||
617 | if (sta->plink_timer_was_running) { | ||
618 | add_timer(&sta->plink_timer); | ||
619 | sta->plink_timer_was_running = false; | ||
620 | } | ||
621 | } | ||
622 | #endif | ||
623 | |||
624 | static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout) | 599 | static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout) |
625 | { | 600 | { |
626 | sta->plink_timer.expires = jiffies + (HZ * timeout / 1000); | 601 | sta->plink_timer.expires = jiffies + (HZ * timeout / 1000); |
@@ -695,6 +670,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, | |||
695 | if (len < IEEE80211_MIN_ACTION_SIZE + 3) | 670 | if (len < IEEE80211_MIN_ACTION_SIZE + 3) |
696 | return; | 671 | return; |
697 | 672 | ||
673 | if (sdata->u.mesh.user_mpm) | ||
674 | /* userspace must register for these */ | ||
675 | return; | ||
676 | |||
698 | if (is_multicast_ether_addr(mgmt->da)) { | 677 | if (is_multicast_ether_addr(mgmt->da)) { |
699 | mpl_dbg(sdata, | 678 | mpl_dbg(sdata, |
700 | "Mesh plink: ignore frame from multicast address\n"); | 679 | "Mesh plink: ignore frame from multicast address\n"); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 9f6464f3e05f..fdc06e381c10 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -87,9 +87,6 @@ MODULE_PARM_DESC(probe_wait_ms, | |||
87 | */ | 87 | */ |
88 | #define IEEE80211_SIGNAL_AVE_MIN_COUNT 4 | 88 | #define IEEE80211_SIGNAL_AVE_MIN_COUNT 4 |
89 | 89 | ||
90 | #define TMR_RUNNING_TIMER 0 | ||
91 | #define TMR_RUNNING_CHANSW 1 | ||
92 | |||
93 | /* | 90 | /* |
94 | * All cfg80211 functions have to be called outside a locked | 91 | * All cfg80211 functions have to be called outside a locked |
95 | * section so that they can acquire a lock themselves... This | 92 | * section so that they can acquire a lock themselves... This |
@@ -609,6 +606,7 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata, | |||
609 | BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap)); | 606 | BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap)); |
610 | 607 | ||
611 | memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap)); | 608 | memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap)); |
609 | ieee80211_apply_vhtcap_overrides(sdata, &vht_cap); | ||
612 | 610 | ||
613 | /* determine capability flags */ | 611 | /* determine capability flags */ |
614 | cap = vht_cap.cap; | 612 | cap = vht_cap.cap; |
@@ -647,6 +645,9 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata, | |||
647 | our_mcs = (le16_to_cpu(vht_cap.vht_mcs.rx_mcs_map) & | 645 | our_mcs = (le16_to_cpu(vht_cap.vht_mcs.rx_mcs_map) & |
648 | mask) >> shift; | 646 | mask) >> shift; |
649 | 647 | ||
648 | if (our_mcs == IEEE80211_VHT_MCS_NOT_SUPPORTED) | ||
649 | continue; | ||
650 | |||
650 | switch (ap_mcs) { | 651 | switch (ap_mcs) { |
651 | default: | 652 | default: |
652 | if (our_mcs <= ap_mcs) | 653 | if (our_mcs <= ap_mcs) |
@@ -1035,14 +1036,8 @@ static void ieee80211_chswitch_timer(unsigned long data) | |||
1035 | { | 1036 | { |
1036 | struct ieee80211_sub_if_data *sdata = | 1037 | struct ieee80211_sub_if_data *sdata = |
1037 | (struct ieee80211_sub_if_data *) data; | 1038 | (struct ieee80211_sub_if_data *) data; |
1038 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
1039 | 1039 | ||
1040 | if (sdata->local->quiescing) { | 1040 | ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.chswitch_work); |
1041 | set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running); | ||
1042 | return; | ||
1043 | } | ||
1044 | |||
1045 | ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work); | ||
1046 | } | 1041 | } |
1047 | 1042 | ||
1048 | void | 1043 | void |
@@ -1799,9 +1794,11 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1799 | sdata->vif.bss_conf.p2p_ctwindow = 0; | 1794 | sdata->vif.bss_conf.p2p_ctwindow = 0; |
1800 | sdata->vif.bss_conf.p2p_oppps = false; | 1795 | sdata->vif.bss_conf.p2p_oppps = false; |
1801 | 1796 | ||
1802 | /* on the next assoc, re-program HT parameters */ | 1797 | /* on the next assoc, re-program HT/VHT parameters */ |
1803 | memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); | 1798 | memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); |
1804 | memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask)); | 1799 | memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask)); |
1800 | memset(&ifmgd->vht_capa, 0, sizeof(ifmgd->vht_capa)); | ||
1801 | memset(&ifmgd->vht_capa_mask, 0, sizeof(ifmgd->vht_capa_mask)); | ||
1805 | 1802 | ||
1806 | sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL; | 1803 | sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL; |
1807 | 1804 | ||
@@ -1827,8 +1824,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1827 | del_timer_sync(&sdata->u.mgd.timer); | 1824 | del_timer_sync(&sdata->u.mgd.timer); |
1828 | del_timer_sync(&sdata->u.mgd.chswitch_timer); | 1825 | del_timer_sync(&sdata->u.mgd.chswitch_timer); |
1829 | 1826 | ||
1830 | sdata->u.mgd.timers_running = 0; | ||
1831 | |||
1832 | sdata->vif.bss_conf.dtim_period = 0; | 1827 | sdata->vif.bss_conf.dtim_period = 0; |
1833 | 1828 | ||
1834 | ifmgd->flags = 0; | 1829 | ifmgd->flags = 0; |
@@ -3137,15 +3132,8 @@ static void ieee80211_sta_timer(unsigned long data) | |||
3137 | { | 3132 | { |
3138 | struct ieee80211_sub_if_data *sdata = | 3133 | struct ieee80211_sub_if_data *sdata = |
3139 | (struct ieee80211_sub_if_data *) data; | 3134 | (struct ieee80211_sub_if_data *) data; |
3140 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
3141 | struct ieee80211_local *local = sdata->local; | ||
3142 | |||
3143 | if (local->quiescing) { | ||
3144 | set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); | ||
3145 | return; | ||
3146 | } | ||
3147 | 3135 | ||
3148 | ieee80211_queue_work(&local->hw, &sdata->work); | 3136 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); |
3149 | } | 3137 | } |
3150 | 3138 | ||
3151 | static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, | 3139 | static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, |
@@ -3497,68 +3485,6 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) | |||
3497 | } | 3485 | } |
3498 | } | 3486 | } |
3499 | 3487 | ||
3500 | #ifdef CONFIG_PM | ||
3501 | void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata) | ||
3502 | { | ||
3503 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
3504 | |||
3505 | /* | ||
3506 | * we need to use atomic bitops for the running bits | ||
3507 | * only because both timers might fire at the same | ||
3508 | * time -- the code here is properly synchronised. | ||
3509 | */ | ||
3510 | |||
3511 | cancel_work_sync(&ifmgd->request_smps_work); | ||
3512 | |||
3513 | cancel_work_sync(&ifmgd->monitor_work); | ||
3514 | cancel_work_sync(&ifmgd->beacon_connection_loss_work); | ||
3515 | cancel_work_sync(&ifmgd->csa_connection_drop_work); | ||
3516 | if (del_timer_sync(&ifmgd->timer)) | ||
3517 | set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); | ||
3518 | |||
3519 | cancel_work_sync(&ifmgd->chswitch_work); | ||
3520 | if (del_timer_sync(&ifmgd->chswitch_timer)) | ||
3521 | set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running); | ||
3522 | |||
3523 | /* these will just be re-established on connection */ | ||
3524 | del_timer_sync(&ifmgd->conn_mon_timer); | ||
3525 | del_timer_sync(&ifmgd->bcn_mon_timer); | ||
3526 | } | ||
3527 | |||
3528 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) | ||
3529 | { | ||
3530 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
3531 | |||
3532 | mutex_lock(&ifmgd->mtx); | ||
3533 | if (!ifmgd->associated) { | ||
3534 | mutex_unlock(&ifmgd->mtx); | ||
3535 | return; | ||
3536 | } | ||
3537 | |||
3538 | if (sdata->flags & IEEE80211_SDATA_DISCONNECT_RESUME) { | ||
3539 | sdata->flags &= ~IEEE80211_SDATA_DISCONNECT_RESUME; | ||
3540 | mlme_dbg(sdata, "driver requested disconnect after resume\n"); | ||
3541 | ieee80211_sta_connection_lost(sdata, | ||
3542 | ifmgd->associated->bssid, | ||
3543 | WLAN_REASON_UNSPECIFIED, | ||
3544 | true); | ||
3545 | mutex_unlock(&ifmgd->mtx); | ||
3546 | return; | ||
3547 | } | ||
3548 | mutex_unlock(&ifmgd->mtx); | ||
3549 | |||
3550 | if (test_and_clear_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running)) | ||
3551 | add_timer(&ifmgd->timer); | ||
3552 | if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running)) | ||
3553 | add_timer(&ifmgd->chswitch_timer); | ||
3554 | ieee80211_sta_reset_beacon_monitor(sdata); | ||
3555 | |||
3556 | mutex_lock(&sdata->local->mtx); | ||
3557 | ieee80211_restart_sta_timer(sdata); | ||
3558 | mutex_unlock(&sdata->local->mtx); | ||
3559 | } | ||
3560 | #endif | ||
3561 | |||
3562 | /* interface setup */ | 3488 | /* interface setup */ |
3563 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | 3489 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) |
3564 | { | 3490 | { |
@@ -4064,6 +3990,9 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
4064 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; | 3990 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; |
4065 | } | 3991 | } |
4066 | 3992 | ||
3993 | if (req->flags & ASSOC_REQ_DISABLE_VHT) | ||
3994 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; | ||
3995 | |||
4067 | /* Also disable HT if we don't support it or the AP doesn't use WMM */ | 3996 | /* Also disable HT if we don't support it or the AP doesn't use WMM */ |
4068 | sband = local->hw.wiphy->bands[req->bss->channel->band]; | 3997 | sband = local->hw.wiphy->bands[req->bss->channel->band]; |
4069 | if (!sband->ht_cap.ht_supported || | 3998 | if (!sband->ht_cap.ht_supported || |
@@ -4087,6 +4016,10 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
4087 | memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask, | 4016 | memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask, |
4088 | sizeof(ifmgd->ht_capa_mask)); | 4017 | sizeof(ifmgd->ht_capa_mask)); |
4089 | 4018 | ||
4019 | memcpy(&ifmgd->vht_capa, &req->vht_capa, sizeof(ifmgd->vht_capa)); | ||
4020 | memcpy(&ifmgd->vht_capa_mask, &req->vht_capa_mask, | ||
4021 | sizeof(ifmgd->vht_capa_mask)); | ||
4022 | |||
4090 | if (req->ie && req->ie_len) { | 4023 | if (req->ie && req->ie_len) { |
4091 | memcpy(assoc_data->ie, req->ie, req->ie_len); | 4024 | memcpy(assoc_data->ie, req->ie, req->ie_len); |
4092 | assoc_data->ie_len = req->ie_len; | 4025 | assoc_data->ie_len = req->ie_len; |
@@ -4315,6 +4248,17 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata) | |||
4315 | { | 4248 | { |
4316 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 4249 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
4317 | 4250 | ||
4251 | /* | ||
4252 | * Make sure some work items will not run after this, | ||
4253 | * they will not do anything but might not have been | ||
4254 | * cancelled when disconnecting. | ||
4255 | */ | ||
4256 | cancel_work_sync(&ifmgd->monitor_work); | ||
4257 | cancel_work_sync(&ifmgd->beacon_connection_loss_work); | ||
4258 | cancel_work_sync(&ifmgd->request_smps_work); | ||
4259 | cancel_work_sync(&ifmgd->csa_connection_drop_work); | ||
4260 | cancel_work_sync(&ifmgd->chswitch_work); | ||
4261 | |||
4318 | mutex_lock(&ifmgd->mtx); | 4262 | mutex_lock(&ifmgd->mtx); |
4319 | if (ifmgd->assoc_data) | 4263 | if (ifmgd->assoc_data) |
4320 | ieee80211_destroy_assoc_data(sdata, false); | 4264 | ieee80211_destroy_assoc_data(sdata, false); |
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index cc79b4a2e821..db547fceaeb9 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -277,7 +277,7 @@ void ieee80211_start_next_roc(struct ieee80211_local *local) | |||
277 | duration = 10; | 277 | duration = 10; |
278 | 278 | ||
279 | ret = drv_remain_on_channel(local, roc->sdata, roc->chan, | 279 | ret = drv_remain_on_channel(local, roc->sdata, roc->chan, |
280 | duration); | 280 | duration, roc->type); |
281 | 281 | ||
282 | roc->started = true; | 282 | roc->started = true; |
283 | 283 | ||
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index d0275f34bf70..b471a67f224d 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -6,32 +6,11 @@ | |||
6 | #include "driver-ops.h" | 6 | #include "driver-ops.h" |
7 | #include "led.h" | 7 | #include "led.h" |
8 | 8 | ||
9 | /* return value indicates whether the driver should be further notified */ | ||
10 | static void ieee80211_quiesce(struct ieee80211_sub_if_data *sdata) | ||
11 | { | ||
12 | switch (sdata->vif.type) { | ||
13 | case NL80211_IFTYPE_STATION: | ||
14 | ieee80211_sta_quiesce(sdata); | ||
15 | break; | ||
16 | case NL80211_IFTYPE_ADHOC: | ||
17 | ieee80211_ibss_quiesce(sdata); | ||
18 | break; | ||
19 | case NL80211_IFTYPE_MESH_POINT: | ||
20 | ieee80211_mesh_quiesce(sdata); | ||
21 | break; | ||
22 | default: | ||
23 | break; | ||
24 | } | ||
25 | |||
26 | cancel_work_sync(&sdata->work); | ||
27 | } | ||
28 | |||
29 | int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | 9 | int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) |
30 | { | 10 | { |
31 | struct ieee80211_local *local = hw_to_local(hw); | 11 | struct ieee80211_local *local = hw_to_local(hw); |
32 | struct ieee80211_sub_if_data *sdata; | 12 | struct ieee80211_sub_if_data *sdata; |
33 | struct sta_info *sta; | 13 | struct sta_info *sta; |
34 | struct ieee80211_chanctx *ctx; | ||
35 | 14 | ||
36 | if (!local->open_count) | 15 | if (!local->open_count) |
37 | goto suspend; | 16 | goto suspend; |
@@ -93,19 +72,12 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
93 | return err; | 72 | return err; |
94 | } else if (err > 0) { | 73 | } else if (err > 0) { |
95 | WARN_ON(err != 1); | 74 | WARN_ON(err != 1); |
96 | local->wowlan = false; | 75 | return err; |
97 | } else { | 76 | } else { |
98 | list_for_each_entry(sdata, &local->interfaces, list) | ||
99 | if (ieee80211_sdata_running(sdata)) | ||
100 | ieee80211_quiesce(sdata); | ||
101 | goto suspend; | 77 | goto suspend; |
102 | } | 78 | } |
103 | } | 79 | } |
104 | 80 | ||
105 | /* disable keys */ | ||
106 | list_for_each_entry(sdata, &local->interfaces, list) | ||
107 | ieee80211_disable_keys(sdata); | ||
108 | |||
109 | /* tear down aggregation sessions and remove STAs */ | 81 | /* tear down aggregation sessions and remove STAs */ |
110 | mutex_lock(&local->sta_mtx); | 82 | mutex_lock(&local->sta_mtx); |
111 | list_for_each_entry(sta, &local->sta_list, list) { | 83 | list_for_each_entry(sta, &local->sta_list, list) { |
@@ -117,100 +89,25 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
117 | WARN_ON(drv_sta_state(local, sta->sdata, sta, | 89 | WARN_ON(drv_sta_state(local, sta->sdata, sta, |
118 | state, state - 1)); | 90 | state, state - 1)); |
119 | } | 91 | } |
120 | |||
121 | mesh_plink_quiesce(sta); | ||
122 | } | 92 | } |
123 | mutex_unlock(&local->sta_mtx); | 93 | mutex_unlock(&local->sta_mtx); |
124 | 94 | ||
125 | /* remove all interfaces */ | 95 | /* remove all interfaces */ |
126 | list_for_each_entry(sdata, &local->interfaces, list) { | 96 | list_for_each_entry(sdata, &local->interfaces, list) { |
127 | static u8 zero_addr[ETH_ALEN] = {}; | ||
128 | u32 changed = 0; | ||
129 | |||
130 | if (!ieee80211_sdata_running(sdata)) | 97 | if (!ieee80211_sdata_running(sdata)) |
131 | continue; | 98 | continue; |
132 | |||
133 | switch (sdata->vif.type) { | ||
134 | case NL80211_IFTYPE_AP_VLAN: | ||
135 | case NL80211_IFTYPE_MONITOR: | ||
136 | /* skip these */ | ||
137 | continue; | ||
138 | case NL80211_IFTYPE_STATION: | ||
139 | if (sdata->vif.bss_conf.assoc) | ||
140 | changed = BSS_CHANGED_ASSOC | | ||
141 | BSS_CHANGED_BSSID | | ||
142 | BSS_CHANGED_IDLE; | ||
143 | break; | ||
144 | case NL80211_IFTYPE_AP: | ||
145 | case NL80211_IFTYPE_ADHOC: | ||
146 | case NL80211_IFTYPE_MESH_POINT: | ||
147 | if (sdata->vif.bss_conf.enable_beacon) | ||
148 | changed = BSS_CHANGED_BEACON_ENABLED; | ||
149 | break; | ||
150 | default: | ||
151 | break; | ||
152 | } | ||
153 | |||
154 | ieee80211_quiesce(sdata); | ||
155 | |||
156 | sdata->suspend_bss_conf = sdata->vif.bss_conf; | ||
157 | memset(&sdata->vif.bss_conf, 0, sizeof(sdata->vif.bss_conf)); | ||
158 | sdata->vif.bss_conf.idle = true; | ||
159 | if (sdata->suspend_bss_conf.bssid) | ||
160 | sdata->vif.bss_conf.bssid = zero_addr; | ||
161 | |||
162 | /* disable beaconing or remove association */ | ||
163 | ieee80211_bss_info_change_notify(sdata, changed); | ||
164 | |||
165 | if (sdata->vif.type == NL80211_IFTYPE_AP && | ||
166 | rcu_access_pointer(sdata->u.ap.beacon)) | ||
167 | drv_stop_ap(local, sdata); | ||
168 | |||
169 | if (local->use_chanctx) { | ||
170 | struct ieee80211_chanctx_conf *conf; | ||
171 | |||
172 | mutex_lock(&local->chanctx_mtx); | ||
173 | conf = rcu_dereference_protected( | ||
174 | sdata->vif.chanctx_conf, | ||
175 | lockdep_is_held(&local->chanctx_mtx)); | ||
176 | if (conf) { | ||
177 | ctx = container_of(conf, | ||
178 | struct ieee80211_chanctx, | ||
179 | conf); | ||
180 | drv_unassign_vif_chanctx(local, sdata, ctx); | ||
181 | } | ||
182 | |||
183 | mutex_unlock(&local->chanctx_mtx); | ||
184 | } | ||
185 | drv_remove_interface(local, sdata); | 99 | drv_remove_interface(local, sdata); |
186 | } | 100 | } |
187 | 101 | ||
188 | sdata = rtnl_dereference(local->monitor_sdata); | 102 | sdata = rtnl_dereference(local->monitor_sdata); |
189 | if (sdata) { | 103 | if (sdata) |
190 | if (local->use_chanctx) { | ||
191 | struct ieee80211_chanctx_conf *conf; | ||
192 | |||
193 | mutex_lock(&local->chanctx_mtx); | ||
194 | conf = rcu_dereference_protected( | ||
195 | sdata->vif.chanctx_conf, | ||
196 | lockdep_is_held(&local->chanctx_mtx)); | ||
197 | if (conf) { | ||
198 | ctx = container_of(conf, | ||
199 | struct ieee80211_chanctx, | ||
200 | conf); | ||
201 | drv_unassign_vif_chanctx(local, sdata, ctx); | ||
202 | } | ||
203 | |||
204 | mutex_unlock(&local->chanctx_mtx); | ||
205 | } | ||
206 | |||
207 | drv_remove_interface(local, sdata); | 104 | drv_remove_interface(local, sdata); |
208 | } | ||
209 | 105 | ||
210 | mutex_lock(&local->chanctx_mtx); | 106 | /* |
211 | list_for_each_entry(ctx, &local->chanctx_list, list) | 107 | * We disconnected on all interfaces before suspend, all channel |
212 | drv_remove_chanctx(local, ctx); | 108 | * contexts should be released. |
213 | mutex_unlock(&local->chanctx_mtx); | 109 | */ |
110 | WARN_ON(!list_empty(&local->chanctx_list)); | ||
214 | 111 | ||
215 | /* stop hardware - this must stop RX */ | 112 | /* stop hardware - this must stop RX */ |
216 | if (local->open_count) | 113 | if (local->open_count) |
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index eea45a2c7c35..1c36c9b4fa4a 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c | |||
@@ -55,7 +55,6 @@ | |||
55 | #include "rate.h" | 55 | #include "rate.h" |
56 | #include "rc80211_minstrel.h" | 56 | #include "rc80211_minstrel.h" |
57 | 57 | ||
58 | #define SAMPLE_COLUMNS 10 | ||
59 | #define SAMPLE_TBL(_mi, _idx, _col) \ | 58 | #define SAMPLE_TBL(_mi, _idx, _col) \ |
60 | _mi->sample_table[(_idx * SAMPLE_COLUMNS) + _col] | 59 | _mi->sample_table[(_idx * SAMPLE_COLUMNS) + _col] |
61 | 60 | ||
@@ -70,16 +69,31 @@ rix_to_ndx(struct minstrel_sta_info *mi, int rix) | |||
70 | return i; | 69 | return i; |
71 | } | 70 | } |
72 | 71 | ||
72 | /* find & sort topmost throughput rates */ | ||
73 | static inline void | ||
74 | minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list) | ||
75 | { | ||
76 | int j = MAX_THR_RATES; | ||
77 | |||
78 | while (j > 0 && mi->r[i].cur_tp > mi->r[tp_list[j - 1]].cur_tp) | ||
79 | j--; | ||
80 | if (j < MAX_THR_RATES - 1) | ||
81 | memmove(&tp_list[j + 1], &tp_list[j], MAX_THR_RATES - (j + 1)); | ||
82 | if (j < MAX_THR_RATES) | ||
83 | tp_list[j] = i; | ||
84 | } | ||
85 | |||
73 | static void | 86 | static void |
74 | minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) | 87 | minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) |
75 | { | 88 | { |
76 | u32 max_tp = 0, index_max_tp = 0, index_max_tp2 = 0; | 89 | u8 tmp_tp_rate[MAX_THR_RATES]; |
77 | u32 max_prob = 0, index_max_prob = 0; | 90 | u8 tmp_prob_rate = 0; |
78 | u32 usecs; | 91 | u32 usecs; |
79 | u32 p; | ||
80 | int i; | 92 | int i; |
81 | 93 | ||
82 | mi->stats_update = jiffies; | 94 | for (i=0; i < MAX_THR_RATES; i++) |
95 | tmp_tp_rate[i] = 0; | ||
96 | |||
83 | for (i = 0; i < mi->n_rates; i++) { | 97 | for (i = 0; i < mi->n_rates; i++) { |
84 | struct minstrel_rate *mr = &mi->r[i]; | 98 | struct minstrel_rate *mr = &mi->r[i]; |
85 | 99 | ||
@@ -87,27 +101,32 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) | |||
87 | if (!usecs) | 101 | if (!usecs) |
88 | usecs = 1000000; | 102 | usecs = 1000000; |
89 | 103 | ||
90 | /* To avoid rounding issues, probabilities scale from 0 (0%) | 104 | if (unlikely(mr->attempts > 0)) { |
91 | * to 18000 (100%) */ | 105 | mr->sample_skipped = 0; |
92 | if (mr->attempts) { | 106 | mr->cur_prob = MINSTREL_FRAC(mr->success, mr->attempts); |
93 | p = (mr->success * 18000) / mr->attempts; | ||
94 | mr->succ_hist += mr->success; | 107 | mr->succ_hist += mr->success; |
95 | mr->att_hist += mr->attempts; | 108 | mr->att_hist += mr->attempts; |
96 | mr->cur_prob = p; | 109 | mr->probability = minstrel_ewma(mr->probability, |
97 | p = ((p * (100 - mp->ewma_level)) + (mr->probability * | 110 | mr->cur_prob, |
98 | mp->ewma_level)) / 100; | 111 | EWMA_LEVEL); |
99 | mr->probability = p; | 112 | } else |
100 | mr->cur_tp = p * (1000000 / usecs); | 113 | mr->sample_skipped++; |
101 | } | ||
102 | 114 | ||
103 | mr->last_success = mr->success; | 115 | mr->last_success = mr->success; |
104 | mr->last_attempts = mr->attempts; | 116 | mr->last_attempts = mr->attempts; |
105 | mr->success = 0; | 117 | mr->success = 0; |
106 | mr->attempts = 0; | 118 | mr->attempts = 0; |
107 | 119 | ||
120 | /* Update throughput per rate, reset thr. below 10% success */ | ||
121 | if (mr->probability < MINSTREL_FRAC(10, 100)) | ||
122 | mr->cur_tp = 0; | ||
123 | else | ||
124 | mr->cur_tp = mr->probability * (1000000 / usecs); | ||
125 | |||
108 | /* Sample less often below the 10% chance of success. | 126 | /* Sample less often below the 10% chance of success. |
109 | * Sample less often above the 95% chance of success. */ | 127 | * Sample less often above the 95% chance of success. */ |
110 | if ((mr->probability > 17100) || (mr->probability < 1800)) { | 128 | if (mr->probability > MINSTREL_FRAC(95, 100) || |
129 | mr->probability < MINSTREL_FRAC(10, 100)) { | ||
111 | mr->adjusted_retry_count = mr->retry_count >> 1; | 130 | mr->adjusted_retry_count = mr->retry_count >> 1; |
112 | if (mr->adjusted_retry_count > 2) | 131 | if (mr->adjusted_retry_count > 2) |
113 | mr->adjusted_retry_count = 2; | 132 | mr->adjusted_retry_count = 2; |
@@ -118,35 +137,30 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) | |||
118 | } | 137 | } |
119 | if (!mr->adjusted_retry_count) | 138 | if (!mr->adjusted_retry_count) |
120 | mr->adjusted_retry_count = 2; | 139 | mr->adjusted_retry_count = 2; |
121 | } | ||
122 | 140 | ||
123 | for (i = 0; i < mi->n_rates; i++) { | 141 | minstrel_sort_best_tp_rates(mi, i, tmp_tp_rate); |
124 | struct minstrel_rate *mr = &mi->r[i]; | 142 | |
125 | if (max_tp < mr->cur_tp) { | 143 | /* To determine the most robust rate (max_prob_rate) used at |
126 | index_max_tp = i; | 144 | * 3rd mmr stage we distinct between two cases: |
127 | max_tp = mr->cur_tp; | 145 | * (1) if any success probabilitiy >= 95%, out of those rates |
128 | } | 146 | * choose the maximum throughput rate as max_prob_rate |
129 | if (max_prob < mr->probability) { | 147 | * (2) if all success probabilities < 95%, the rate with |
130 | index_max_prob = i; | 148 | * highest success probability is choosen as max_prob_rate */ |
131 | max_prob = mr->probability; | 149 | if (mr->probability >= MINSTREL_FRAC(95,100)) { |
150 | if (mr->cur_tp >= mi->r[tmp_prob_rate].cur_tp) | ||
151 | tmp_prob_rate = i; | ||
152 | } else { | ||
153 | if (mr->probability >= mi->r[tmp_prob_rate].probability) | ||
154 | tmp_prob_rate = i; | ||
132 | } | 155 | } |
133 | } | 156 | } |
134 | 157 | ||
135 | max_tp = 0; | 158 | /* Assign the new rate set */ |
136 | for (i = 0; i < mi->n_rates; i++) { | 159 | memcpy(mi->max_tp_rate, tmp_tp_rate, sizeof(mi->max_tp_rate)); |
137 | struct minstrel_rate *mr = &mi->r[i]; | 160 | mi->max_prob_rate = tmp_prob_rate; |
138 | |||
139 | if (i == index_max_tp) | ||
140 | continue; | ||
141 | 161 | ||
142 | if (max_tp < mr->cur_tp) { | 162 | /* Reset update timer */ |
143 | index_max_tp2 = i; | 163 | mi->stats_update = jiffies; |
144 | max_tp = mr->cur_tp; | ||
145 | } | ||
146 | } | ||
147 | mi->max_tp_rate = index_max_tp; | ||
148 | mi->max_tp_rate2 = index_max_tp2; | ||
149 | mi->max_prob_rate = index_max_prob; | ||
150 | } | 164 | } |
151 | 165 | ||
152 | static void | 166 | static void |
@@ -207,10 +221,10 @@ static int | |||
207 | minstrel_get_next_sample(struct minstrel_sta_info *mi) | 221 | minstrel_get_next_sample(struct minstrel_sta_info *mi) |
208 | { | 222 | { |
209 | unsigned int sample_ndx; | 223 | unsigned int sample_ndx; |
210 | sample_ndx = SAMPLE_TBL(mi, mi->sample_idx, mi->sample_column); | 224 | sample_ndx = SAMPLE_TBL(mi, mi->sample_row, mi->sample_column); |
211 | mi->sample_idx++; | 225 | mi->sample_row++; |
212 | if ((int) mi->sample_idx > (mi->n_rates - 2)) { | 226 | if ((int) mi->sample_row >= mi->n_rates) { |
213 | mi->sample_idx = 0; | 227 | mi->sample_row = 0; |
214 | mi->sample_column++; | 228 | mi->sample_column++; |
215 | if (mi->sample_column >= SAMPLE_COLUMNS) | 229 | if (mi->sample_column >= SAMPLE_COLUMNS) |
216 | mi->sample_column = 0; | 230 | mi->sample_column = 0; |
@@ -228,31 +242,37 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, | |||
228 | struct minstrel_priv *mp = priv; | 242 | struct minstrel_priv *mp = priv; |
229 | struct ieee80211_tx_rate *ar = info->control.rates; | 243 | struct ieee80211_tx_rate *ar = info->control.rates; |
230 | unsigned int ndx, sample_ndx = 0; | 244 | unsigned int ndx, sample_ndx = 0; |
231 | bool mrr; | 245 | bool mrr_capable; |
232 | bool sample_slower = false; | 246 | bool indirect_rate_sampling = false; |
233 | bool sample = false; | 247 | bool rate_sampling = false; |
234 | int i, delta; | 248 | int i, delta; |
235 | int mrr_ndx[3]; | 249 | int mrr_ndx[3]; |
236 | int sample_rate; | 250 | int sampling_ratio; |
237 | 251 | ||
252 | /* management/no-ack frames do not use rate control */ | ||
238 | if (rate_control_send_low(sta, priv_sta, txrc)) | 253 | if (rate_control_send_low(sta, priv_sta, txrc)) |
239 | return; | 254 | return; |
240 | 255 | ||
241 | mrr = mp->has_mrr && !txrc->rts && !txrc->bss_conf->use_cts_prot; | 256 | /* check multi-rate-retry capabilities & adjust lookaround_rate */ |
242 | 257 | mrr_capable = mp->has_mrr && | |
243 | ndx = mi->max_tp_rate; | 258 | !txrc->rts && |
244 | 259 | !txrc->bss_conf->use_cts_prot; | |
245 | if (mrr) | 260 | if (mrr_capable) |
246 | sample_rate = mp->lookaround_rate_mrr; | 261 | sampling_ratio = mp->lookaround_rate_mrr; |
247 | else | 262 | else |
248 | sample_rate = mp->lookaround_rate; | 263 | sampling_ratio = mp->lookaround_rate; |
264 | |||
265 | /* init rateindex [ndx] with max throughput rate */ | ||
266 | ndx = mi->max_tp_rate[0]; | ||
249 | 267 | ||
268 | /* increase sum packet counter */ | ||
250 | mi->packet_count++; | 269 | mi->packet_count++; |
251 | delta = (mi->packet_count * sample_rate / 100) - | 270 | |
271 | delta = (mi->packet_count * sampling_ratio / 100) - | ||
252 | (mi->sample_count + mi->sample_deferred / 2); | 272 | (mi->sample_count + mi->sample_deferred / 2); |
253 | 273 | ||
254 | /* delta > 0: sampling required */ | 274 | /* delta > 0: sampling required */ |
255 | if ((delta > 0) && (mrr || !mi->prev_sample)) { | 275 | if ((delta > 0) && (mrr_capable || !mi->prev_sample)) { |
256 | struct minstrel_rate *msr; | 276 | struct minstrel_rate *msr; |
257 | if (mi->packet_count >= 10000) { | 277 | if (mi->packet_count >= 10000) { |
258 | mi->sample_deferred = 0; | 278 | mi->sample_deferred = 0; |
@@ -271,21 +291,28 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, | |||
271 | mi->sample_count += (delta - mi->n_rates * 2); | 291 | mi->sample_count += (delta - mi->n_rates * 2); |
272 | } | 292 | } |
273 | 293 | ||
294 | /* get next random rate sample */ | ||
274 | sample_ndx = minstrel_get_next_sample(mi); | 295 | sample_ndx = minstrel_get_next_sample(mi); |
275 | msr = &mi->r[sample_ndx]; | 296 | msr = &mi->r[sample_ndx]; |
276 | sample = true; | 297 | rate_sampling = true; |
277 | sample_slower = mrr && (msr->perfect_tx_time > | 298 | |
278 | mi->r[ndx].perfect_tx_time); | 299 | /* Decide if direct ( 1st mrr stage) or indirect (2nd mrr stage) |
279 | 300 | * rate sampling method should be used. | |
280 | if (!sample_slower) { | 301 | * Respect such rates that are not sampled for 20 interations. |
302 | */ | ||
303 | if (mrr_capable && | ||
304 | msr->perfect_tx_time > mi->r[ndx].perfect_tx_time && | ||
305 | msr->sample_skipped < 20) | ||
306 | indirect_rate_sampling = true; | ||
307 | |||
308 | if (!indirect_rate_sampling) { | ||
281 | if (msr->sample_limit != 0) { | 309 | if (msr->sample_limit != 0) { |
282 | ndx = sample_ndx; | 310 | ndx = sample_ndx; |
283 | mi->sample_count++; | 311 | mi->sample_count++; |
284 | if (msr->sample_limit > 0) | 312 | if (msr->sample_limit > 0) |
285 | msr->sample_limit--; | 313 | msr->sample_limit--; |
286 | } else { | 314 | } else |
287 | sample = false; | 315 | rate_sampling = false; |
288 | } | ||
289 | } else { | 316 | } else { |
290 | /* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark | 317 | /* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark |
291 | * packets that have the sampling rate deferred to the | 318 | * packets that have the sampling rate deferred to the |
@@ -297,34 +324,39 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, | |||
297 | mi->sample_deferred++; | 324 | mi->sample_deferred++; |
298 | } | 325 | } |
299 | } | 326 | } |
300 | mi->prev_sample = sample; | 327 | mi->prev_sample = rate_sampling; |
301 | 328 | ||
302 | /* If we're not using MRR and the sampling rate already | 329 | /* If we're not using MRR and the sampling rate already |
303 | * has a probability of >95%, we shouldn't be attempting | 330 | * has a probability of >95%, we shouldn't be attempting |
304 | * to use it, as this only wastes precious airtime */ | 331 | * to use it, as this only wastes precious airtime */ |
305 | if (!mrr && sample && (mi->r[ndx].probability > 17100)) | 332 | if (!mrr_capable && rate_sampling && |
306 | ndx = mi->max_tp_rate; | 333 | (mi->r[ndx].probability > MINSTREL_FRAC(95, 100))) |
334 | ndx = mi->max_tp_rate[0]; | ||
307 | 335 | ||
336 | /* mrr setup for 1st stage */ | ||
308 | ar[0].idx = mi->r[ndx].rix; | 337 | ar[0].idx = mi->r[ndx].rix; |
309 | ar[0].count = minstrel_get_retry_count(&mi->r[ndx], info); | 338 | ar[0].count = minstrel_get_retry_count(&mi->r[ndx], info); |
310 | 339 | ||
311 | if (!mrr) { | 340 | /* non mrr setup for 2nd stage */ |
312 | if (!sample) | 341 | if (!mrr_capable) { |
342 | if (!rate_sampling) | ||
313 | ar[0].count = mp->max_retry; | 343 | ar[0].count = mp->max_retry; |
314 | ar[1].idx = mi->lowest_rix; | 344 | ar[1].idx = mi->lowest_rix; |
315 | ar[1].count = mp->max_retry; | 345 | ar[1].count = mp->max_retry; |
316 | return; | 346 | return; |
317 | } | 347 | } |
318 | 348 | ||
319 | /* MRR setup */ | 349 | /* mrr setup for 2nd stage */ |
320 | if (sample) { | 350 | if (rate_sampling) { |
321 | if (sample_slower) | 351 | if (indirect_rate_sampling) |
322 | mrr_ndx[0] = sample_ndx; | 352 | mrr_ndx[0] = sample_ndx; |
323 | else | 353 | else |
324 | mrr_ndx[0] = mi->max_tp_rate; | 354 | mrr_ndx[0] = mi->max_tp_rate[0]; |
325 | } else { | 355 | } else { |
326 | mrr_ndx[0] = mi->max_tp_rate2; | 356 | mrr_ndx[0] = mi->max_tp_rate[1]; |
327 | } | 357 | } |
358 | |||
359 | /* mrr setup for 3rd & 4th stage */ | ||
328 | mrr_ndx[1] = mi->max_prob_rate; | 360 | mrr_ndx[1] = mi->max_prob_rate; |
329 | mrr_ndx[2] = 0; | 361 | mrr_ndx[2] = 0; |
330 | for (i = 1; i < 4; i++) { | 362 | for (i = 1; i < 4; i++) { |
@@ -351,26 +383,21 @@ static void | |||
351 | init_sample_table(struct minstrel_sta_info *mi) | 383 | init_sample_table(struct minstrel_sta_info *mi) |
352 | { | 384 | { |
353 | unsigned int i, col, new_idx; | 385 | unsigned int i, col, new_idx; |
354 | unsigned int n_srates = mi->n_rates - 1; | ||
355 | u8 rnd[8]; | 386 | u8 rnd[8]; |
356 | 387 | ||
357 | mi->sample_column = 0; | 388 | mi->sample_column = 0; |
358 | mi->sample_idx = 0; | 389 | mi->sample_row = 0; |
359 | memset(mi->sample_table, 0, SAMPLE_COLUMNS * mi->n_rates); | 390 | memset(mi->sample_table, 0xff, SAMPLE_COLUMNS * mi->n_rates); |
360 | 391 | ||
361 | for (col = 0; col < SAMPLE_COLUMNS; col++) { | 392 | for (col = 0; col < SAMPLE_COLUMNS; col++) { |
362 | for (i = 0; i < n_srates; i++) { | 393 | for (i = 0; i < mi->n_rates; i++) { |
363 | get_random_bytes(rnd, sizeof(rnd)); | 394 | get_random_bytes(rnd, sizeof(rnd)); |
364 | new_idx = (i + rnd[i & 7]) % n_srates; | 395 | new_idx = (i + rnd[i & 7]) % mi->n_rates; |
365 | 396 | ||
366 | while (SAMPLE_TBL(mi, new_idx, col) != 0) | 397 | while (SAMPLE_TBL(mi, new_idx, col) != 0xff) |
367 | new_idx = (new_idx + 1) % n_srates; | 398 | new_idx = (new_idx + 1) % mi->n_rates; |
368 | 399 | ||
369 | /* Don't sample the slowest rate (i.e. slowest base | 400 | SAMPLE_TBL(mi, new_idx, col) = i; |
370 | * rate). We must presume that the slowest rate works | ||
371 | * fine, or else other management frames will also be | ||
372 | * failing and the link will break */ | ||
373 | SAMPLE_TBL(mi, new_idx, col) = i + 1; | ||
374 | } | 401 | } |
375 | } | 402 | } |
376 | } | 403 | } |
@@ -542,9 +569,6 @@ minstrel_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) | |||
542 | mp->lookaround_rate = 5; | 569 | mp->lookaround_rate = 5; |
543 | mp->lookaround_rate_mrr = 10; | 570 | mp->lookaround_rate_mrr = 10; |
544 | 571 | ||
545 | /* moving average weight for EWMA */ | ||
546 | mp->ewma_level = 75; | ||
547 | |||
548 | /* maximum time that the hw is allowed to stay in one MRR segment */ | 572 | /* maximum time that the hw is allowed to stay in one MRR segment */ |
549 | mp->segment_size = 6000; | 573 | mp->segment_size = 6000; |
550 | 574 | ||
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h index 5ecf757817f2..85ebf42cb46d 100644 --- a/net/mac80211/rc80211_minstrel.h +++ b/net/mac80211/rc80211_minstrel.h | |||
@@ -9,6 +9,28 @@ | |||
9 | #ifndef __RC_MINSTREL_H | 9 | #ifndef __RC_MINSTREL_H |
10 | #define __RC_MINSTREL_H | 10 | #define __RC_MINSTREL_H |
11 | 11 | ||
12 | #define EWMA_LEVEL 75 /* ewma weighting factor [%] */ | ||
13 | #define SAMPLE_COLUMNS 10 /* number of columns in sample table */ | ||
14 | |||
15 | |||
16 | /* scaled fraction values */ | ||
17 | #define MINSTREL_SCALE 16 | ||
18 | #define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div) | ||
19 | #define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE) | ||
20 | |||
21 | /* number of highest throughput rates to consider*/ | ||
22 | #define MAX_THR_RATES 4 | ||
23 | |||
24 | /* | ||
25 | * Perform EWMA (Exponentially Weighted Moving Average) calculation | ||
26 | */ | ||
27 | static inline int | ||
28 | minstrel_ewma(int old, int new, int weight) | ||
29 | { | ||
30 | return (new * (100 - weight) + old * weight) / 100; | ||
31 | } | ||
32 | |||
33 | |||
12 | struct minstrel_rate { | 34 | struct minstrel_rate { |
13 | int bitrate; | 35 | int bitrate; |
14 | int rix; | 36 | int rix; |
@@ -26,6 +48,7 @@ struct minstrel_rate { | |||
26 | u32 attempts; | 48 | u32 attempts; |
27 | u32 last_attempts; | 49 | u32 last_attempts; |
28 | u32 last_success; | 50 | u32 last_success; |
51 | u8 sample_skipped; | ||
29 | 52 | ||
30 | /* parts per thousand */ | 53 | /* parts per thousand */ |
31 | u32 cur_prob; | 54 | u32 cur_prob; |
@@ -45,14 +68,13 @@ struct minstrel_sta_info { | |||
45 | 68 | ||
46 | unsigned int lowest_rix; | 69 | unsigned int lowest_rix; |
47 | 70 | ||
48 | unsigned int max_tp_rate; | 71 | u8 max_tp_rate[MAX_THR_RATES]; |
49 | unsigned int max_tp_rate2; | 72 | u8 max_prob_rate; |
50 | unsigned int max_prob_rate; | ||
51 | unsigned int packet_count; | 73 | unsigned int packet_count; |
52 | unsigned int sample_count; | 74 | unsigned int sample_count; |
53 | int sample_deferred; | 75 | int sample_deferred; |
54 | 76 | ||
55 | unsigned int sample_idx; | 77 | unsigned int sample_row; |
56 | unsigned int sample_column; | 78 | unsigned int sample_column; |
57 | 79 | ||
58 | int n_rates; | 80 | int n_rates; |
@@ -73,7 +95,6 @@ struct minstrel_priv { | |||
73 | unsigned int cw_min; | 95 | unsigned int cw_min; |
74 | unsigned int cw_max; | 96 | unsigned int cw_max; |
75 | unsigned int max_retry; | 97 | unsigned int max_retry; |
76 | unsigned int ewma_level; | ||
77 | unsigned int segment_size; | 98 | unsigned int segment_size; |
78 | unsigned int update_interval; | 99 | unsigned int update_interval; |
79 | unsigned int lookaround_rate; | 100 | unsigned int lookaround_rate; |
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c index d5a56226e675..d1048348d399 100644 --- a/net/mac80211/rc80211_minstrel_debugfs.c +++ b/net/mac80211/rc80211_minstrel_debugfs.c | |||
@@ -73,15 +73,17 @@ minstrel_stats_open(struct inode *inode, struct file *file) | |||
73 | for (i = 0; i < mi->n_rates; i++) { | 73 | for (i = 0; i < mi->n_rates; i++) { |
74 | struct minstrel_rate *mr = &mi->r[i]; | 74 | struct minstrel_rate *mr = &mi->r[i]; |
75 | 75 | ||
76 | *(p++) = (i == mi->max_tp_rate) ? 'T' : ' '; | 76 | *(p++) = (i == mi->max_tp_rate[0]) ? 'A' : ' '; |
77 | *(p++) = (i == mi->max_tp_rate2) ? 't' : ' '; | 77 | *(p++) = (i == mi->max_tp_rate[1]) ? 'B' : ' '; |
78 | *(p++) = (i == mi->max_tp_rate[2]) ? 'C' : ' '; | ||
79 | *(p++) = (i == mi->max_tp_rate[3]) ? 'D' : ' '; | ||
78 | *(p++) = (i == mi->max_prob_rate) ? 'P' : ' '; | 80 | *(p++) = (i == mi->max_prob_rate) ? 'P' : ' '; |
79 | p += sprintf(p, "%3u%s", mr->bitrate / 2, | 81 | p += sprintf(p, "%3u%s", mr->bitrate / 2, |
80 | (mr->bitrate & 1 ? ".5" : " ")); | 82 | (mr->bitrate & 1 ? ".5" : " ")); |
81 | 83 | ||
82 | tp = mr->cur_tp / ((18000 << 10) / 96); | 84 | tp = MINSTREL_TRUNC(mr->cur_tp / 10); |
83 | prob = mr->cur_prob / 18; | 85 | prob = MINSTREL_TRUNC(mr->cur_prob * 1000); |
84 | eprob = mr->probability / 18; | 86 | eprob = MINSTREL_TRUNC(mr->probability * 1000); |
85 | 87 | ||
86 | p += sprintf(p, " %6u.%1u %6u.%1u %6u.%1u " | 88 | p += sprintf(p, " %6u.%1u %6u.%1u %6u.%1u " |
87 | "%3u(%3u) %8llu %8llu\n", | 89 | "%3u(%3u) %8llu %8llu\n", |
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 3af141c69712..749552bdcfe1 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -17,8 +17,6 @@ | |||
17 | #include "rc80211_minstrel_ht.h" | 17 | #include "rc80211_minstrel_ht.h" |
18 | 18 | ||
19 | #define AVG_PKT_SIZE 1200 | 19 | #define AVG_PKT_SIZE 1200 |
20 | #define SAMPLE_COLUMNS 10 | ||
21 | #define EWMA_LEVEL 75 | ||
22 | 20 | ||
23 | /* Number of bits for an average sized packet */ | 21 | /* Number of bits for an average sized packet */ |
24 | #define MCS_NBITS (AVG_PKT_SIZE << 3) | 22 | #define MCS_NBITS (AVG_PKT_SIZE << 3) |
@@ -26,11 +24,11 @@ | |||
26 | /* Number of symbols for a packet with (bps) bits per symbol */ | 24 | /* Number of symbols for a packet with (bps) bits per symbol */ |
27 | #define MCS_NSYMS(bps) ((MCS_NBITS + (bps) - 1) / (bps)) | 25 | #define MCS_NSYMS(bps) ((MCS_NBITS + (bps) - 1) / (bps)) |
28 | 26 | ||
29 | /* Transmission time for a packet containing (syms) symbols */ | 27 | /* Transmission time (nanoseconds) for a packet containing (syms) symbols */ |
30 | #define MCS_SYMBOL_TIME(sgi, syms) \ | 28 | #define MCS_SYMBOL_TIME(sgi, syms) \ |
31 | (sgi ? \ | 29 | (sgi ? \ |
32 | ((syms) * 18 + 4) / 5 : /* syms * 3.6 us */ \ | 30 | ((syms) * 18000 + 4000) / 5 : /* syms * 3.6 us */ \ |
33 | (syms) << 2 /* syms * 4 us */ \ | 31 | ((syms) * 1000) << 2 /* syms * 4 us */ \ |
34 | ) | 32 | ) |
35 | 33 | ||
36 | /* Transmit duration for the raw data part of an average sized packet */ | 34 | /* Transmit duration for the raw data part of an average sized packet */ |
@@ -64,9 +62,9 @@ | |||
64 | } | 62 | } |
65 | 63 | ||
66 | #define CCK_DURATION(_bitrate, _short, _len) \ | 64 | #define CCK_DURATION(_bitrate, _short, _len) \ |
67 | (10 /* SIFS */ + \ | 65 | (1000 * (10 /* SIFS */ + \ |
68 | (_short ? 72 + 24 : 144 + 48 ) + \ | 66 | (_short ? 72 + 24 : 144 + 48 ) + \ |
69 | (8 * (_len + 4) * 10) / (_bitrate)) | 67 | (8 * (_len + 4) * 10) / (_bitrate))) |
70 | 68 | ||
71 | #define CCK_ACK_DURATION(_bitrate, _short) \ | 69 | #define CCK_ACK_DURATION(_bitrate, _short) \ |
72 | (CCK_DURATION((_bitrate > 10 ? 20 : 10), false, 60) + \ | 70 | (CCK_DURATION((_bitrate > 10 ? 20 : 10), false, 60) + \ |
@@ -129,15 +127,6 @@ const struct mcs_group minstrel_mcs_groups[] = { | |||
129 | static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES]; | 127 | static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES]; |
130 | 128 | ||
131 | /* | 129 | /* |
132 | * Perform EWMA (Exponentially Weighted Moving Average) calculation | ||
133 | */ | ||
134 | static int | ||
135 | minstrel_ewma(int old, int new, int weight) | ||
136 | { | ||
137 | return (new * (100 - weight) + old * weight) / 100; | ||
138 | } | ||
139 | |||
140 | /* | ||
141 | * Look up an MCS group index based on mac80211 rate information | 130 | * Look up an MCS group index based on mac80211 rate information |
142 | */ | 131 | */ |
143 | static int | 132 | static int |
@@ -211,7 +200,8 @@ static void | |||
211 | minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate) | 200 | minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate) |
212 | { | 201 | { |
213 | struct minstrel_rate_stats *mr; | 202 | struct minstrel_rate_stats *mr; |
214 | unsigned int usecs = 0; | 203 | unsigned int nsecs = 0; |
204 | unsigned int tp; | ||
215 | 205 | ||
216 | mr = &mi->groups[group].rates[rate]; | 206 | mr = &mi->groups[group].rates[rate]; |
217 | 207 | ||
@@ -221,10 +211,12 @@ minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate) | |||
221 | } | 211 | } |
222 | 212 | ||
223 | if (group != MINSTREL_CCK_GROUP) | 213 | if (group != MINSTREL_CCK_GROUP) |
224 | usecs = mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len); | 214 | nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len); |
225 | 215 | ||
226 | usecs += minstrel_mcs_groups[group].duration[rate]; | 216 | nsecs += minstrel_mcs_groups[group].duration[rate]; |
227 | mr->cur_tp = MINSTREL_TRUNC((1000000 / usecs) * mr->probability); | 217 | tp = 1000000 * ((mr->probability * 1000) / nsecs); |
218 | |||
219 | mr->cur_tp = MINSTREL_TRUNC(tp); | ||
228 | } | 220 | } |
229 | 221 | ||
230 | /* | 222 | /* |
@@ -308,8 +300,8 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
308 | } | 300 | } |
309 | } | 301 | } |
310 | 302 | ||
311 | /* try to sample up to half of the available rates during each interval */ | 303 | /* try to sample all available rates during each interval */ |
312 | mi->sample_count *= 4; | 304 | mi->sample_count *= 8; |
313 | 305 | ||
314 | cur_prob = 0; | 306 | cur_prob = 0; |
315 | cur_prob_tp = 0; | 307 | cur_prob_tp = 0; |
@@ -320,20 +312,13 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
320 | if (!mg->supported) | 312 | if (!mg->supported) |
321 | continue; | 313 | continue; |
322 | 314 | ||
323 | mr = minstrel_get_ratestats(mi, mg->max_prob_rate); | ||
324 | if (cur_prob_tp < mr->cur_tp && | ||
325 | minstrel_mcs_groups[group].streams == 1) { | ||
326 | mi->max_prob_rate = mg->max_prob_rate; | ||
327 | cur_prob = mr->cur_prob; | ||
328 | cur_prob_tp = mr->cur_tp; | ||
329 | } | ||
330 | |||
331 | mr = minstrel_get_ratestats(mi, mg->max_tp_rate); | 315 | mr = minstrel_get_ratestats(mi, mg->max_tp_rate); |
332 | if (cur_tp < mr->cur_tp) { | 316 | if (cur_tp < mr->cur_tp) { |
333 | mi->max_tp_rate2 = mi->max_tp_rate; | 317 | mi->max_tp_rate2 = mi->max_tp_rate; |
334 | cur_tp2 = cur_tp; | 318 | cur_tp2 = cur_tp; |
335 | mi->max_tp_rate = mg->max_tp_rate; | 319 | mi->max_tp_rate = mg->max_tp_rate; |
336 | cur_tp = mr->cur_tp; | 320 | cur_tp = mr->cur_tp; |
321 | mi->max_prob_streams = minstrel_mcs_groups[group].streams - 1; | ||
337 | } | 322 | } |
338 | 323 | ||
339 | mr = minstrel_get_ratestats(mi, mg->max_tp_rate2); | 324 | mr = minstrel_get_ratestats(mi, mg->max_tp_rate2); |
@@ -343,6 +328,23 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
343 | } | 328 | } |
344 | } | 329 | } |
345 | 330 | ||
331 | if (mi->max_prob_streams < 1) | ||
332 | mi->max_prob_streams = 1; | ||
333 | |||
334 | for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) { | ||
335 | mg = &mi->groups[group]; | ||
336 | if (!mg->supported) | ||
337 | continue; | ||
338 | mr = minstrel_get_ratestats(mi, mg->max_prob_rate); | ||
339 | if (cur_prob_tp < mr->cur_tp && | ||
340 | minstrel_mcs_groups[group].streams <= mi->max_prob_streams) { | ||
341 | mi->max_prob_rate = mg->max_prob_rate; | ||
342 | cur_prob = mr->cur_prob; | ||
343 | cur_prob_tp = mr->cur_tp; | ||
344 | } | ||
345 | } | ||
346 | |||
347 | |||
346 | mi->stats_update = jiffies; | 348 | mi->stats_update = jiffies; |
347 | } | 349 | } |
348 | 350 | ||
@@ -467,7 +469,7 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
467 | 469 | ||
468 | if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) { | 470 | if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) { |
469 | mi->sample_wait = 16 + 2 * MINSTREL_TRUNC(mi->avg_ampdu_len); | 471 | mi->sample_wait = 16 + 2 * MINSTREL_TRUNC(mi->avg_ampdu_len); |
470 | mi->sample_tries = 2; | 472 | mi->sample_tries = 1; |
471 | mi->sample_count--; | 473 | mi->sample_count--; |
472 | } | 474 | } |
473 | 475 | ||
@@ -536,7 +538,7 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, | |||
536 | mr->retry_updated = true; | 538 | mr->retry_updated = true; |
537 | 539 | ||
538 | group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; | 540 | group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; |
539 | tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len; | 541 | tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len / 1000; |
540 | 542 | ||
541 | /* Contention time for first 2 tries */ | 543 | /* Contention time for first 2 tries */ |
542 | ctime = (t_slot * cw) >> 1; | 544 | ctime = (t_slot * cw) >> 1; |
@@ -616,6 +618,7 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
616 | { | 618 | { |
617 | struct minstrel_rate_stats *mr; | 619 | struct minstrel_rate_stats *mr; |
618 | struct minstrel_mcs_group_data *mg; | 620 | struct minstrel_mcs_group_data *mg; |
621 | unsigned int sample_dur, sample_group; | ||
619 | int sample_idx = 0; | 622 | int sample_idx = 0; |
620 | 623 | ||
621 | if (mi->sample_wait > 0) { | 624 | if (mi->sample_wait > 0) { |
@@ -626,11 +629,11 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
626 | if (!mi->sample_tries) | 629 | if (!mi->sample_tries) |
627 | return -1; | 630 | return -1; |
628 | 631 | ||
629 | mi->sample_tries--; | ||
630 | mg = &mi->groups[mi->sample_group]; | 632 | mg = &mi->groups[mi->sample_group]; |
631 | sample_idx = sample_table[mg->column][mg->index]; | 633 | sample_idx = sample_table[mg->column][mg->index]; |
632 | mr = &mg->rates[sample_idx]; | 634 | mr = &mg->rates[sample_idx]; |
633 | sample_idx += mi->sample_group * MCS_GROUP_RATES; | 635 | sample_group = mi->sample_group; |
636 | sample_idx += sample_group * MCS_GROUP_RATES; | ||
634 | minstrel_next_sample_idx(mi); | 637 | minstrel_next_sample_idx(mi); |
635 | 638 | ||
636 | /* | 639 | /* |
@@ -651,14 +654,18 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
651 | * Make sure that lower rates get sampled only occasionally, | 654 | * Make sure that lower rates get sampled only occasionally, |
652 | * if the link is working perfectly. | 655 | * if the link is working perfectly. |
653 | */ | 656 | */ |
654 | if (minstrel_get_duration(sample_idx) > | 657 | sample_dur = minstrel_get_duration(sample_idx); |
655 | minstrel_get_duration(mi->max_tp_rate)) { | 658 | if (sample_dur >= minstrel_get_duration(mi->max_tp_rate2) && |
659 | (mi->max_prob_streams < | ||
660 | minstrel_mcs_groups[sample_group].streams || | ||
661 | sample_dur >= minstrel_get_duration(mi->max_prob_rate))) { | ||
656 | if (mr->sample_skipped < 20) | 662 | if (mr->sample_skipped < 20) |
657 | return -1; | 663 | return -1; |
658 | 664 | ||
659 | if (mi->sample_slow++ > 2) | 665 | if (mi->sample_slow++ > 2) |
660 | return -1; | 666 | return -1; |
661 | } | 667 | } |
668 | mi->sample_tries--; | ||
662 | 669 | ||
663 | return sample_idx; | 670 | return sample_idx; |
664 | } | 671 | } |
diff --git a/net/mac80211/rc80211_minstrel_ht.h b/net/mac80211/rc80211_minstrel_ht.h index 302dbd52180d..9b16e9de9923 100644 --- a/net/mac80211/rc80211_minstrel_ht.h +++ b/net/mac80211/rc80211_minstrel_ht.h | |||
@@ -16,11 +16,6 @@ | |||
16 | #define MINSTREL_MAX_STREAMS 3 | 16 | #define MINSTREL_MAX_STREAMS 3 |
17 | #define MINSTREL_STREAM_GROUPS 4 | 17 | #define MINSTREL_STREAM_GROUPS 4 |
18 | 18 | ||
19 | /* scaled fraction values */ | ||
20 | #define MINSTREL_SCALE 16 | ||
21 | #define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div) | ||
22 | #define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE) | ||
23 | |||
24 | #define MCS_GROUP_RATES 8 | 19 | #define MCS_GROUP_RATES 8 |
25 | 20 | ||
26 | struct mcs_group { | 21 | struct mcs_group { |
@@ -85,6 +80,7 @@ struct minstrel_ht_sta { | |||
85 | 80 | ||
86 | /* best probability rate */ | 81 | /* best probability rate */ |
87 | unsigned int max_prob_rate; | 82 | unsigned int max_prob_rate; |
83 | unsigned int max_prob_streams; | ||
88 | 84 | ||
89 | /* time of last status update */ | 85 | /* time of last status update */ |
90 | unsigned long stats_update; | 86 | unsigned long stats_update; |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index bb73ed2d20b9..5b4492af4e85 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -648,24 +648,6 @@ static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | |||
648 | return RX_CONTINUE; | 648 | return RX_CONTINUE; |
649 | } | 649 | } |
650 | 650 | ||
651 | #define SEQ_MODULO 0x1000 | ||
652 | #define SEQ_MASK 0xfff | ||
653 | |||
654 | static inline int seq_less(u16 sq1, u16 sq2) | ||
655 | { | ||
656 | return ((sq1 - sq2) & SEQ_MASK) > (SEQ_MODULO >> 1); | ||
657 | } | ||
658 | |||
659 | static inline u16 seq_inc(u16 sq) | ||
660 | { | ||
661 | return (sq + 1) & SEQ_MASK; | ||
662 | } | ||
663 | |||
664 | static inline u16 seq_sub(u16 sq1, u16 sq2) | ||
665 | { | ||
666 | return (sq1 - sq2) & SEQ_MASK; | ||
667 | } | ||
668 | |||
669 | static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata, | 651 | static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata, |
670 | struct tid_ampdu_rx *tid_agg_rx, | 652 | struct tid_ampdu_rx *tid_agg_rx, |
671 | int index, | 653 | int index, |
@@ -687,7 +669,7 @@ static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata, | |||
687 | __skb_queue_tail(frames, skb); | 669 | __skb_queue_tail(frames, skb); |
688 | 670 | ||
689 | no_frame: | 671 | no_frame: |
690 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); | 672 | tid_agg_rx->head_seq_num = ieee80211_sn_inc(tid_agg_rx->head_seq_num); |
691 | } | 673 | } |
692 | 674 | ||
693 | static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata, | 675 | static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata, |
@@ -699,8 +681,9 @@ static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata | |||
699 | 681 | ||
700 | lockdep_assert_held(&tid_agg_rx->reorder_lock); | 682 | lockdep_assert_held(&tid_agg_rx->reorder_lock); |
701 | 683 | ||
702 | while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) { | 684 | while (ieee80211_sn_less(tid_agg_rx->head_seq_num, head_seq_num)) { |
703 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | 685 | index = ieee80211_sn_sub(tid_agg_rx->head_seq_num, |
686 | tid_agg_rx->ssn) % | ||
704 | tid_agg_rx->buf_size; | 687 | tid_agg_rx->buf_size; |
705 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, | 688 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, |
706 | frames); | 689 | frames); |
@@ -727,8 +710,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, | |||
727 | lockdep_assert_held(&tid_agg_rx->reorder_lock); | 710 | lockdep_assert_held(&tid_agg_rx->reorder_lock); |
728 | 711 | ||
729 | /* release the buffer until next missing frame */ | 712 | /* release the buffer until next missing frame */ |
730 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | 713 | index = ieee80211_sn_sub(tid_agg_rx->head_seq_num, |
731 | tid_agg_rx->buf_size; | 714 | tid_agg_rx->ssn) % tid_agg_rx->buf_size; |
732 | if (!tid_agg_rx->reorder_buf[index] && | 715 | if (!tid_agg_rx->reorder_buf[index] && |
733 | tid_agg_rx->stored_mpdu_num) { | 716 | tid_agg_rx->stored_mpdu_num) { |
734 | /* | 717 | /* |
@@ -756,19 +739,22 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, | |||
756 | * Increment the head seq# also for the skipped slots. | 739 | * Increment the head seq# also for the skipped slots. |
757 | */ | 740 | */ |
758 | tid_agg_rx->head_seq_num = | 741 | tid_agg_rx->head_seq_num = |
759 | (tid_agg_rx->head_seq_num + skipped) & SEQ_MASK; | 742 | (tid_agg_rx->head_seq_num + |
743 | skipped) & IEEE80211_SN_MASK; | ||
760 | skipped = 0; | 744 | skipped = 0; |
761 | } | 745 | } |
762 | } else while (tid_agg_rx->reorder_buf[index]) { | 746 | } else while (tid_agg_rx->reorder_buf[index]) { |
763 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, | 747 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, |
764 | frames); | 748 | frames); |
765 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | 749 | index = ieee80211_sn_sub(tid_agg_rx->head_seq_num, |
750 | tid_agg_rx->ssn) % | ||
766 | tid_agg_rx->buf_size; | 751 | tid_agg_rx->buf_size; |
767 | } | 752 | } |
768 | 753 | ||
769 | if (tid_agg_rx->stored_mpdu_num) { | 754 | if (tid_agg_rx->stored_mpdu_num) { |
770 | j = index = seq_sub(tid_agg_rx->head_seq_num, | 755 | j = index = ieee80211_sn_sub(tid_agg_rx->head_seq_num, |
771 | tid_agg_rx->ssn) % tid_agg_rx->buf_size; | 756 | tid_agg_rx->ssn) % |
757 | tid_agg_rx->buf_size; | ||
772 | 758 | ||
773 | for (; j != (index - 1) % tid_agg_rx->buf_size; | 759 | for (; j != (index - 1) % tid_agg_rx->buf_size; |
774 | j = (j + 1) % tid_agg_rx->buf_size) { | 760 | j = (j + 1) % tid_agg_rx->buf_size) { |
@@ -809,7 +795,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata | |||
809 | head_seq_num = tid_agg_rx->head_seq_num; | 795 | head_seq_num = tid_agg_rx->head_seq_num; |
810 | 796 | ||
811 | /* frame with out of date sequence number */ | 797 | /* frame with out of date sequence number */ |
812 | if (seq_less(mpdu_seq_num, head_seq_num)) { | 798 | if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) { |
813 | dev_kfree_skb(skb); | 799 | dev_kfree_skb(skb); |
814 | goto out; | 800 | goto out; |
815 | } | 801 | } |
@@ -818,8 +804,9 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata | |||
818 | * If frame the sequence number exceeds our buffering window | 804 | * If frame the sequence number exceeds our buffering window |
819 | * size release some previous frames to make room for this one. | 805 | * size release some previous frames to make room for this one. |
820 | */ | 806 | */ |
821 | if (!seq_less(mpdu_seq_num, head_seq_num + buf_size)) { | 807 | if (!ieee80211_sn_less(mpdu_seq_num, head_seq_num + buf_size)) { |
822 | head_seq_num = seq_inc(seq_sub(mpdu_seq_num, buf_size)); | 808 | head_seq_num = ieee80211_sn_inc( |
809 | ieee80211_sn_sub(mpdu_seq_num, buf_size)); | ||
823 | /* release stored frames up to new head to stack */ | 810 | /* release stored frames up to new head to stack */ |
824 | ieee80211_release_reorder_frames(sdata, tid_agg_rx, | 811 | ieee80211_release_reorder_frames(sdata, tid_agg_rx, |
825 | head_seq_num, frames); | 812 | head_seq_num, frames); |
@@ -827,7 +814,8 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata | |||
827 | 814 | ||
828 | /* Now the new frame is always in the range of the reordering buffer */ | 815 | /* Now the new frame is always in the range of the reordering buffer */ |
829 | 816 | ||
830 | index = seq_sub(mpdu_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size; | 817 | index = ieee80211_sn_sub(mpdu_seq_num, |
818 | tid_agg_rx->ssn) % tid_agg_rx->buf_size; | ||
831 | 819 | ||
832 | /* check if we already stored this frame */ | 820 | /* check if we already stored this frame */ |
833 | if (tid_agg_rx->reorder_buf[index]) { | 821 | if (tid_agg_rx->reorder_buf[index]) { |
@@ -843,7 +831,8 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata | |||
843 | */ | 831 | */ |
844 | if (mpdu_seq_num == tid_agg_rx->head_seq_num && | 832 | if (mpdu_seq_num == tid_agg_rx->head_seq_num && |
845 | tid_agg_rx->stored_mpdu_num == 0) { | 833 | tid_agg_rx->stored_mpdu_num == 0) { |
846 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); | 834 | tid_agg_rx->head_seq_num = |
835 | ieee80211_sn_inc(tid_agg_rx->head_seq_num); | ||
847 | ret = false; | 836 | ret = false; |
848 | goto out; | 837 | goto out; |
849 | } | 838 | } |
@@ -1894,8 +1883,10 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
1894 | * 'align' will only take the values 0 or 2 here | 1883 | * 'align' will only take the values 0 or 2 here |
1895 | * since all frames are required to be aligned | 1884 | * since all frames are required to be aligned |
1896 | * to 2-byte boundaries when being passed to | 1885 | * to 2-byte boundaries when being passed to |
1897 | * mac80211. That also explains the __skb_push() | 1886 | * mac80211; the code here works just as well if |
1898 | * below. | 1887 | * that isn't true, but mac80211 assumes it can |
1888 | * access fields as 2-byte aligned (e.g. for | ||
1889 | * compare_ether_addr) | ||
1899 | */ | 1890 | */ |
1900 | align = ((unsigned long)(skb->data + sizeof(struct ethhdr))) & 3; | 1891 | align = ((unsigned long)(skb->data + sizeof(struct ethhdr))) & 3; |
1901 | if (align) { | 1892 | if (align) { |
@@ -2552,7 +2543,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2552 | case WLAN_SP_MESH_PEERING_CONFIRM: | 2543 | case WLAN_SP_MESH_PEERING_CONFIRM: |
2553 | if (!ieee80211_vif_is_mesh(&sdata->vif)) | 2544 | if (!ieee80211_vif_is_mesh(&sdata->vif)) |
2554 | goto invalid; | 2545 | goto invalid; |
2555 | if (sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE) | 2546 | if (sdata->u.mesh.user_mpm) |
2556 | /* userspace handles this frame */ | 2547 | /* userspace handles this frame */ |
2557 | break; | 2548 | break; |
2558 | goto queue; | 2549 | goto queue; |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index a79ce820cb50..3644ad79688a 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -342,6 +342,11 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
342 | INIT_WORK(&sta->drv_unblock_wk, sta_unblock); | 342 | INIT_WORK(&sta->drv_unblock_wk, sta_unblock); |
343 | INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); | 343 | INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); |
344 | mutex_init(&sta->ampdu_mlme.mtx); | 344 | mutex_init(&sta->ampdu_mlme.mtx); |
345 | #ifdef CONFIG_MAC80211_MESH | ||
346 | if (ieee80211_vif_is_mesh(&sdata->vif) && | ||
347 | !sdata->u.mesh.user_mpm) | ||
348 | init_timer(&sta->plink_timer); | ||
349 | #endif | ||
345 | 350 | ||
346 | memcpy(sta->sta.addr, addr, ETH_ALEN); | 351 | memcpy(sta->sta.addr, addr, ETH_ALEN); |
347 | sta->local = local; | 352 | sta->local = local; |
@@ -794,9 +799,11 @@ int __must_check __sta_info_destroy(struct sta_info *sta) | |||
794 | 799 | ||
795 | mutex_lock(&local->key_mtx); | 800 | mutex_lock(&local->key_mtx); |
796 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) | 801 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) |
797 | __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i])); | 802 | __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i]), |
803 | true); | ||
798 | if (sta->ptk) | 804 | if (sta->ptk) |
799 | __ieee80211_key_free(key_mtx_dereference(local, sta->ptk)); | 805 | __ieee80211_key_free(key_mtx_dereference(local, sta->ptk), |
806 | true); | ||
800 | mutex_unlock(&local->key_mtx); | 807 | mutex_unlock(&local->key_mtx); |
801 | 808 | ||
802 | sta->dead = true; | 809 | sta->dead = true; |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 4947341a2a82..e5868c32d1a3 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -281,7 +281,6 @@ struct sta_ampdu_mlme { | |||
281 | * @plink_state: peer link state | 281 | * @plink_state: peer link state |
282 | * @plink_timeout: timeout of peer link | 282 | * @plink_timeout: timeout of peer link |
283 | * @plink_timer: peer link watch timer | 283 | * @plink_timer: peer link watch timer |
284 | * @plink_timer_was_running: used by suspend/resume to restore timers | ||
285 | * @t_offset: timing offset relative to this host | 284 | * @t_offset: timing offset relative to this host |
286 | * @t_offset_setpoint: reference timing offset of this sta to be used when | 285 | * @t_offset_setpoint: reference timing offset of this sta to be used when |
287 | * calculating clockdrift | 286 | * calculating clockdrift |
@@ -379,7 +378,6 @@ struct sta_info { | |||
379 | __le16 reason; | 378 | __le16 reason; |
380 | u8 plink_retries; | 379 | u8 plink_retries; |
381 | bool ignore_plink_timer; | 380 | bool ignore_plink_timer; |
382 | bool plink_timer_was_running; | ||
383 | enum nl80211_plink_state plink_state; | 381 | enum nl80211_plink_state plink_state; |
384 | u32 plink_timeout; | 382 | u32 plink_timeout; |
385 | struct timer_list plink_timer; | 383 | struct timer_list plink_timer; |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 3d7cd2a0582f..e7db2b804e0c 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -1042,15 +1042,17 @@ TRACE_EVENT(drv_remain_on_channel, | |||
1042 | TP_PROTO(struct ieee80211_local *local, | 1042 | TP_PROTO(struct ieee80211_local *local, |
1043 | struct ieee80211_sub_if_data *sdata, | 1043 | struct ieee80211_sub_if_data *sdata, |
1044 | struct ieee80211_channel *chan, | 1044 | struct ieee80211_channel *chan, |
1045 | unsigned int duration), | 1045 | unsigned int duration, |
1046 | enum ieee80211_roc_type type), | ||
1046 | 1047 | ||
1047 | TP_ARGS(local, sdata, chan, duration), | 1048 | TP_ARGS(local, sdata, chan, duration, type), |
1048 | 1049 | ||
1049 | TP_STRUCT__entry( | 1050 | TP_STRUCT__entry( |
1050 | LOCAL_ENTRY | 1051 | LOCAL_ENTRY |
1051 | VIF_ENTRY | 1052 | VIF_ENTRY |
1052 | __field(int, center_freq) | 1053 | __field(int, center_freq) |
1053 | __field(unsigned int, duration) | 1054 | __field(unsigned int, duration) |
1055 | __field(u32, type) | ||
1054 | ), | 1056 | ), |
1055 | 1057 | ||
1056 | TP_fast_assign( | 1058 | TP_fast_assign( |
@@ -1058,12 +1060,13 @@ TRACE_EVENT(drv_remain_on_channel, | |||
1058 | VIF_ASSIGN; | 1060 | VIF_ASSIGN; |
1059 | __entry->center_freq = chan->center_freq; | 1061 | __entry->center_freq = chan->center_freq; |
1060 | __entry->duration = duration; | 1062 | __entry->duration = duration; |
1063 | __entry->type = type; | ||
1061 | ), | 1064 | ), |
1062 | 1065 | ||
1063 | TP_printk( | 1066 | TP_printk( |
1064 | LOCAL_PR_FMT VIF_PR_FMT " freq:%dMHz duration:%dms", | 1067 | LOCAL_PR_FMT VIF_PR_FMT " freq:%dMHz duration:%dms type=%d", |
1065 | LOCAL_PR_ARG, VIF_PR_ARG, | 1068 | LOCAL_PR_ARG, VIF_PR_ARG, |
1066 | __entry->center_freq, __entry->duration | 1069 | __entry->center_freq, __entry->duration, __entry->type |
1067 | ) | 1070 | ) |
1068 | ); | 1071 | ); |
1069 | 1072 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index de8548bf0a7f..8914d2d2881a 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1231,34 +1231,40 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local, | |||
1231 | if (local->queue_stop_reasons[q] || | 1231 | if (local->queue_stop_reasons[q] || |
1232 | (!txpending && !skb_queue_empty(&local->pending[q]))) { | 1232 | (!txpending && !skb_queue_empty(&local->pending[q]))) { |
1233 | if (unlikely(info->flags & | 1233 | if (unlikely(info->flags & |
1234 | IEEE80211_TX_INTFL_OFFCHAN_TX_OK && | 1234 | IEEE80211_TX_INTFL_OFFCHAN_TX_OK)) { |
1235 | local->queue_stop_reasons[q] & | 1235 | if (local->queue_stop_reasons[q] & |
1236 | ~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL))) { | 1236 | ~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL)) { |
1237 | /* | ||
1238 | * Drop off-channel frames if queues | ||
1239 | * are stopped for any reason other | ||
1240 | * than off-channel operation. Never | ||
1241 | * queue them. | ||
1242 | */ | ||
1243 | spin_unlock_irqrestore( | ||
1244 | &local->queue_stop_reason_lock, | ||
1245 | flags); | ||
1246 | ieee80211_purge_tx_queue(&local->hw, | ||
1247 | skbs); | ||
1248 | return true; | ||
1249 | } | ||
1250 | } else { | ||
1251 | |||
1237 | /* | 1252 | /* |
1238 | * Drop off-channel frames if queues are stopped | 1253 | * Since queue is stopped, queue up frames for |
1239 | * for any reason other than off-channel | 1254 | * later transmission from the tx-pending |
1240 | * operation. Never queue them. | 1255 | * tasklet when the queue is woken again. |
1241 | */ | 1256 | */ |
1242 | spin_unlock_irqrestore( | 1257 | if (txpending) |
1243 | &local->queue_stop_reason_lock, flags); | 1258 | skb_queue_splice_init(skbs, |
1244 | ieee80211_purge_tx_queue(&local->hw, skbs); | 1259 | &local->pending[q]); |
1245 | return true; | 1260 | else |
1261 | skb_queue_splice_tail_init(skbs, | ||
1262 | &local->pending[q]); | ||
1263 | |||
1264 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, | ||
1265 | flags); | ||
1266 | return false; | ||
1246 | } | 1267 | } |
1247 | |||
1248 | /* | ||
1249 | * Since queue is stopped, queue up frames for later | ||
1250 | * transmission from the tx-pending tasklet when the | ||
1251 | * queue is woken again. | ||
1252 | */ | ||
1253 | if (txpending) | ||
1254 | skb_queue_splice_init(skbs, &local->pending[q]); | ||
1255 | else | ||
1256 | skb_queue_splice_tail_init(skbs, | ||
1257 | &local->pending[q]); | ||
1258 | |||
1259 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, | ||
1260 | flags); | ||
1261 | return false; | ||
1262 | } | 1268 | } |
1263 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 1269 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
1264 | 1270 | ||
@@ -1844,9 +1850,24 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1844 | } | 1850 | } |
1845 | 1851 | ||
1846 | if (!is_multicast_ether_addr(skb->data)) { | 1852 | if (!is_multicast_ether_addr(skb->data)) { |
1853 | struct sta_info *next_hop; | ||
1854 | bool mpp_lookup = true; | ||
1855 | |||
1847 | mpath = mesh_path_lookup(sdata, skb->data); | 1856 | mpath = mesh_path_lookup(sdata, skb->data); |
1848 | if (!mpath) | 1857 | if (mpath) { |
1858 | mpp_lookup = false; | ||
1859 | next_hop = rcu_dereference(mpath->next_hop); | ||
1860 | if (!next_hop || | ||
1861 | !(mpath->flags & (MESH_PATH_ACTIVE | | ||
1862 | MESH_PATH_RESOLVING))) | ||
1863 | mpp_lookup = true; | ||
1864 | } | ||
1865 | |||
1866 | if (mpp_lookup) | ||
1849 | mppath = mpp_path_lookup(sdata, skb->data); | 1867 | mppath = mpp_path_lookup(sdata, skb->data); |
1868 | |||
1869 | if (mppath && mpath) | ||
1870 | mesh_path_del(mpath->sdata, mpath->dst); | ||
1850 | } | 1871 | } |
1851 | 1872 | ||
1852 | /* | 1873 | /* |
@@ -2350,9 +2371,9 @@ static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, | |||
2350 | if (local->tim_in_locked_section) { | 2371 | if (local->tim_in_locked_section) { |
2351 | __ieee80211_beacon_add_tim(sdata, ps, skb); | 2372 | __ieee80211_beacon_add_tim(sdata, ps, skb); |
2352 | } else { | 2373 | } else { |
2353 | spin_lock(&local->tim_lock); | 2374 | spin_lock_bh(&local->tim_lock); |
2354 | __ieee80211_beacon_add_tim(sdata, ps, skb); | 2375 | __ieee80211_beacon_add_tim(sdata, ps, skb); |
2355 | spin_unlock(&local->tim_lock); | 2376 | spin_unlock_bh(&local->tim_lock); |
2356 | } | 2377 | } |
2357 | 2378 | ||
2358 | return 0; | 2379 | return 0; |
@@ -2724,7 +2745,8 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2724 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | 2745 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); |
2725 | } | 2746 | } |
2726 | 2747 | ||
2727 | sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev); | 2748 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
2749 | sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev); | ||
2728 | if (!ieee80211_tx_prepare(sdata, &tx, skb)) | 2750 | if (!ieee80211_tx_prepare(sdata, &tx, skb)) |
2729 | break; | 2751 | break; |
2730 | dev_kfree_skb_any(skb); | 2752 | dev_kfree_skb_any(skb); |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 0f38f43ac62e..b7a856e3281b 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1357,6 +1357,25 @@ void ieee80211_stop_device(struct ieee80211_local *local) | |||
1357 | drv_stop(local); | 1357 | drv_stop(local); |
1358 | } | 1358 | } |
1359 | 1359 | ||
1360 | static void ieee80211_assign_chanctx(struct ieee80211_local *local, | ||
1361 | struct ieee80211_sub_if_data *sdata) | ||
1362 | { | ||
1363 | struct ieee80211_chanctx_conf *conf; | ||
1364 | struct ieee80211_chanctx *ctx; | ||
1365 | |||
1366 | if (!local->use_chanctx) | ||
1367 | return; | ||
1368 | |||
1369 | mutex_lock(&local->chanctx_mtx); | ||
1370 | conf = rcu_dereference_protected(sdata->vif.chanctx_conf, | ||
1371 | lockdep_is_held(&local->chanctx_mtx)); | ||
1372 | if (conf) { | ||
1373 | ctx = container_of(conf, struct ieee80211_chanctx, conf); | ||
1374 | drv_assign_vif_chanctx(local, sdata, ctx); | ||
1375 | } | ||
1376 | mutex_unlock(&local->chanctx_mtx); | ||
1377 | } | ||
1378 | |||
1360 | int ieee80211_reconfig(struct ieee80211_local *local) | 1379 | int ieee80211_reconfig(struct ieee80211_local *local) |
1361 | { | 1380 | { |
1362 | struct ieee80211_hw *hw = &local->hw; | 1381 | struct ieee80211_hw *hw = &local->hw; |
@@ -1445,36 +1464,14 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1445 | } | 1464 | } |
1446 | 1465 | ||
1447 | list_for_each_entry(sdata, &local->interfaces, list) { | 1466 | list_for_each_entry(sdata, &local->interfaces, list) { |
1448 | struct ieee80211_chanctx_conf *ctx_conf; | ||
1449 | |||
1450 | if (!ieee80211_sdata_running(sdata)) | 1467 | if (!ieee80211_sdata_running(sdata)) |
1451 | continue; | 1468 | continue; |
1452 | 1469 | ieee80211_assign_chanctx(local, sdata); | |
1453 | mutex_lock(&local->chanctx_mtx); | ||
1454 | ctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf, | ||
1455 | lockdep_is_held(&local->chanctx_mtx)); | ||
1456 | if (ctx_conf) { | ||
1457 | ctx = container_of(ctx_conf, struct ieee80211_chanctx, | ||
1458 | conf); | ||
1459 | drv_assign_vif_chanctx(local, sdata, ctx); | ||
1460 | } | ||
1461 | mutex_unlock(&local->chanctx_mtx); | ||
1462 | } | 1470 | } |
1463 | 1471 | ||
1464 | sdata = rtnl_dereference(local->monitor_sdata); | 1472 | sdata = rtnl_dereference(local->monitor_sdata); |
1465 | if (sdata && local->use_chanctx && ieee80211_sdata_running(sdata)) { | 1473 | if (sdata && ieee80211_sdata_running(sdata)) |
1466 | struct ieee80211_chanctx_conf *ctx_conf; | 1474 | ieee80211_assign_chanctx(local, sdata); |
1467 | |||
1468 | mutex_lock(&local->chanctx_mtx); | ||
1469 | ctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf, | ||
1470 | lockdep_is_held(&local->chanctx_mtx)); | ||
1471 | if (ctx_conf) { | ||
1472 | ctx = container_of(ctx_conf, struct ieee80211_chanctx, | ||
1473 | conf); | ||
1474 | drv_assign_vif_chanctx(local, sdata, ctx); | ||
1475 | } | ||
1476 | mutex_unlock(&local->chanctx_mtx); | ||
1477 | } | ||
1478 | 1475 | ||
1479 | /* add STAs back */ | 1476 | /* add STAs back */ |
1480 | mutex_lock(&local->sta_mtx); | 1477 | mutex_lock(&local->sta_mtx); |
@@ -1534,11 +1531,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1534 | BSS_CHANGED_IDLE | | 1531 | BSS_CHANGED_IDLE | |
1535 | BSS_CHANGED_TXPOWER; | 1532 | BSS_CHANGED_TXPOWER; |
1536 | 1533 | ||
1537 | #ifdef CONFIG_PM | ||
1538 | if (local->resuming && !reconfig_due_to_wowlan) | ||
1539 | sdata->vif.bss_conf = sdata->suspend_bss_conf; | ||
1540 | #endif | ||
1541 | |||
1542 | switch (sdata->vif.type) { | 1534 | switch (sdata->vif.type) { |
1543 | case NL80211_IFTYPE_STATION: | 1535 | case NL80211_IFTYPE_STATION: |
1544 | changed |= BSS_CHANGED_ASSOC | | 1536 | changed |= BSS_CHANGED_ASSOC | |
@@ -1678,28 +1670,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1678 | mb(); | 1670 | mb(); |
1679 | local->resuming = false; | 1671 | local->resuming = false; |
1680 | 1672 | ||
1681 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
1682 | switch(sdata->vif.type) { | ||
1683 | case NL80211_IFTYPE_STATION: | ||
1684 | ieee80211_sta_restart(sdata); | ||
1685 | break; | ||
1686 | case NL80211_IFTYPE_ADHOC: | ||
1687 | ieee80211_ibss_restart(sdata); | ||
1688 | break; | ||
1689 | case NL80211_IFTYPE_MESH_POINT: | ||
1690 | ieee80211_mesh_restart(sdata); | ||
1691 | break; | ||
1692 | default: | ||
1693 | break; | ||
1694 | } | ||
1695 | } | ||
1696 | |||
1697 | mod_timer(&local->sta_cleanup, jiffies + 1); | 1673 | mod_timer(&local->sta_cleanup, jiffies + 1); |
1698 | |||
1699 | mutex_lock(&local->sta_mtx); | ||
1700 | list_for_each_entry(sta, &local->sta_list, list) | ||
1701 | mesh_plink_restart(sta); | ||
1702 | mutex_unlock(&local->sta_mtx); | ||
1703 | #else | 1674 | #else |
1704 | WARN_ON(1); | 1675 | WARN_ON(1); |
1705 | #endif | 1676 | #endif |
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index a2c2258bc84e..171344d4eb7c 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c | |||
@@ -13,6 +13,104 @@ | |||
13 | #include "rate.h" | 13 | #include "rate.h" |
14 | 14 | ||
15 | 15 | ||
16 | static void __check_vhtcap_disable(struct ieee80211_sub_if_data *sdata, | ||
17 | struct ieee80211_sta_vht_cap *vht_cap, | ||
18 | u32 flag) | ||
19 | { | ||
20 | __le32 le_flag = cpu_to_le32(flag); | ||
21 | |||
22 | if (sdata->u.mgd.vht_capa_mask.vht_cap_info & le_flag && | ||
23 | !(sdata->u.mgd.vht_capa.vht_cap_info & le_flag)) | ||
24 | vht_cap->cap &= ~flag; | ||
25 | } | ||
26 | |||
27 | void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata, | ||
28 | struct ieee80211_sta_vht_cap *vht_cap) | ||
29 | { | ||
30 | int i; | ||
31 | u16 rxmcs_mask, rxmcs_cap, rxmcs_n, txmcs_mask, txmcs_cap, txmcs_n; | ||
32 | |||
33 | if (!vht_cap->vht_supported) | ||
34 | return; | ||
35 | |||
36 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
37 | return; | ||
38 | |||
39 | __check_vhtcap_disable(sdata, vht_cap, | ||
40 | IEEE80211_VHT_CAP_RXLDPC); | ||
41 | __check_vhtcap_disable(sdata, vht_cap, | ||
42 | IEEE80211_VHT_CAP_SHORT_GI_80); | ||
43 | __check_vhtcap_disable(sdata, vht_cap, | ||
44 | IEEE80211_VHT_CAP_SHORT_GI_160); | ||
45 | __check_vhtcap_disable(sdata, vht_cap, | ||
46 | IEEE80211_VHT_CAP_TXSTBC); | ||
47 | __check_vhtcap_disable(sdata, vht_cap, | ||
48 | IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE); | ||
49 | __check_vhtcap_disable(sdata, vht_cap, | ||
50 | IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE); | ||
51 | __check_vhtcap_disable(sdata, vht_cap, | ||
52 | IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN); | ||
53 | __check_vhtcap_disable(sdata, vht_cap, | ||
54 | IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN); | ||
55 | |||
56 | /* Allow user to decrease AMPDU length exponent */ | ||
57 | if (sdata->u.mgd.vht_capa_mask.vht_cap_info & | ||
58 | cpu_to_le32(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK)) { | ||
59 | u32 cap, n; | ||
60 | |||
61 | n = le32_to_cpu(sdata->u.mgd.vht_capa.vht_cap_info) & | ||
62 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; | ||
63 | n >>= IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; | ||
64 | cap = vht_cap->cap & IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; | ||
65 | cap >>= IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; | ||
66 | |||
67 | if (n < cap) { | ||
68 | vht_cap->cap &= | ||
69 | ~IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; | ||
70 | vht_cap->cap |= | ||
71 | n << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; | ||
72 | } | ||
73 | } | ||
74 | |||
75 | /* Allow the user to decrease MCSes */ | ||
76 | rxmcs_mask = | ||
77 | le16_to_cpu(sdata->u.mgd.vht_capa_mask.supp_mcs.rx_mcs_map); | ||
78 | rxmcs_n = le16_to_cpu(sdata->u.mgd.vht_capa.supp_mcs.rx_mcs_map); | ||
79 | rxmcs_n &= rxmcs_mask; | ||
80 | rxmcs_cap = le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map); | ||
81 | |||
82 | txmcs_mask = | ||
83 | le16_to_cpu(sdata->u.mgd.vht_capa_mask.supp_mcs.tx_mcs_map); | ||
84 | txmcs_n = le16_to_cpu(sdata->u.mgd.vht_capa.supp_mcs.tx_mcs_map); | ||
85 | txmcs_n &= txmcs_mask; | ||
86 | txmcs_cap = le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map); | ||
87 | for (i = 0; i < 8; i++) { | ||
88 | u8 m, n, c; | ||
89 | |||
90 | m = (rxmcs_mask >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED; | ||
91 | n = (rxmcs_n >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED; | ||
92 | c = (rxmcs_cap >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED; | ||
93 | |||
94 | if (m && ((c != IEEE80211_VHT_MCS_NOT_SUPPORTED && n < c) || | ||
95 | n == IEEE80211_VHT_MCS_NOT_SUPPORTED)) { | ||
96 | rxmcs_cap &= ~(3 << 2*i); | ||
97 | rxmcs_cap |= (rxmcs_n & (3 << 2*i)); | ||
98 | } | ||
99 | |||
100 | m = (txmcs_mask >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED; | ||
101 | n = (txmcs_n >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED; | ||
102 | c = (txmcs_cap >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED; | ||
103 | |||
104 | if (m && ((c != IEEE80211_VHT_MCS_NOT_SUPPORTED && n < c) || | ||
105 | n == IEEE80211_VHT_MCS_NOT_SUPPORTED)) { | ||
106 | txmcs_cap &= ~(3 << 2*i); | ||
107 | txmcs_cap |= (txmcs_n & (3 << 2*i)); | ||
108 | } | ||
109 | } | ||
110 | vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(rxmcs_cap); | ||
111 | vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(txmcs_cap); | ||
112 | } | ||
113 | |||
16 | void | 114 | void |
17 | ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, | 115 | ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, |
18 | struct ieee80211_supported_band *sband, | 116 | struct ieee80211_supported_band *sband, |
@@ -20,6 +118,8 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, | |||
20 | struct sta_info *sta) | 118 | struct sta_info *sta) |
21 | { | 119 | { |
22 | struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.vht_cap; | 120 | struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.vht_cap; |
121 | struct ieee80211_sta_vht_cap own_cap; | ||
122 | u32 cap_info, i; | ||
23 | 123 | ||
24 | memset(vht_cap, 0, sizeof(*vht_cap)); | 124 | memset(vht_cap, 0, sizeof(*vht_cap)); |
25 | 125 | ||
@@ -35,12 +135,122 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, | |||
35 | 135 | ||
36 | vht_cap->vht_supported = true; | 136 | vht_cap->vht_supported = true; |
37 | 137 | ||
38 | vht_cap->cap = le32_to_cpu(vht_cap_ie->vht_cap_info); | 138 | own_cap = sband->vht_cap; |
139 | /* | ||
140 | * If user has specified capability overrides, take care | ||
141 | * of that if the station we're setting up is the AP that | ||
142 | * we advertised a restricted capability set to. Override | ||
143 | * our own capabilities and then use those below. | ||
144 | */ | ||
145 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | ||
146 | !test_sta_flag(sta, WLAN_STA_TDLS_PEER)) | ||
147 | ieee80211_apply_vhtcap_overrides(sdata, &own_cap); | ||
148 | |||
149 | /* take some capabilities as-is */ | ||
150 | cap_info = le32_to_cpu(vht_cap_ie->vht_cap_info); | ||
151 | vht_cap->cap = cap_info; | ||
152 | vht_cap->cap &= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 | | ||
153 | IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 | | ||
154 | IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | | ||
155 | IEEE80211_VHT_CAP_RXLDPC | | ||
156 | IEEE80211_VHT_CAP_VHT_TXOP_PS | | ||
157 | IEEE80211_VHT_CAP_HTC_VHT | | ||
158 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | | ||
159 | IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB | | ||
160 | IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB | | ||
161 | IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | | ||
162 | IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN; | ||
163 | |||
164 | /* and some based on our own capabilities */ | ||
165 | switch (own_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) { | ||
166 | case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ: | ||
167 | vht_cap->cap |= cap_info & | ||
168 | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; | ||
169 | break; | ||
170 | case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ: | ||
171 | vht_cap->cap |= cap_info & | ||
172 | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK; | ||
173 | break; | ||
174 | default: | ||
175 | /* nothing */ | ||
176 | break; | ||
177 | } | ||
178 | |||
179 | /* symmetric capabilities */ | ||
180 | vht_cap->cap |= cap_info & own_cap.cap & | ||
181 | (IEEE80211_VHT_CAP_SHORT_GI_80 | | ||
182 | IEEE80211_VHT_CAP_SHORT_GI_160); | ||
183 | |||
184 | /* remaining ones */ | ||
185 | if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) { | ||
186 | vht_cap->cap |= cap_info & | ||
187 | (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | | ||
188 | IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX | | ||
189 | IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX); | ||
190 | } | ||
191 | |||
192 | if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) | ||
193 | vht_cap->cap |= cap_info & | ||
194 | IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; | ||
195 | |||
196 | if (own_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) | ||
197 | vht_cap->cap |= cap_info & | ||
198 | IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE; | ||
199 | |||
200 | if (own_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) | ||
201 | vht_cap->cap |= cap_info & | ||
202 | IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE; | ||
203 | |||
204 | if (own_cap.cap & IEEE80211_VHT_CAP_TXSTBC) | ||
205 | vht_cap->cap |= cap_info & IEEE80211_VHT_CAP_RXSTBC_MASK; | ||
206 | |||
207 | if (own_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK) | ||
208 | vht_cap->cap |= cap_info & IEEE80211_VHT_CAP_TXSTBC; | ||
39 | 209 | ||
40 | /* Copy peer MCS info, the driver might need them. */ | 210 | /* Copy peer MCS info, the driver might need them. */ |
41 | memcpy(&vht_cap->vht_mcs, &vht_cap_ie->supp_mcs, | 211 | memcpy(&vht_cap->vht_mcs, &vht_cap_ie->supp_mcs, |
42 | sizeof(struct ieee80211_vht_mcs_info)); | 212 | sizeof(struct ieee80211_vht_mcs_info)); |
43 | 213 | ||
214 | /* but also restrict MCSes */ | ||
215 | for (i = 0; i < 8; i++) { | ||
216 | u16 own_rx, own_tx, peer_rx, peer_tx; | ||
217 | |||
218 | own_rx = le16_to_cpu(own_cap.vht_mcs.rx_mcs_map); | ||
219 | own_rx = (own_rx >> i * 2) & IEEE80211_VHT_MCS_NOT_SUPPORTED; | ||
220 | |||
221 | own_tx = le16_to_cpu(own_cap.vht_mcs.tx_mcs_map); | ||
222 | own_tx = (own_tx >> i * 2) & IEEE80211_VHT_MCS_NOT_SUPPORTED; | ||
223 | |||
224 | peer_rx = le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map); | ||
225 | peer_rx = (peer_rx >> i * 2) & IEEE80211_VHT_MCS_NOT_SUPPORTED; | ||
226 | |||
227 | peer_tx = le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map); | ||
228 | peer_tx = (peer_tx >> i * 2) & IEEE80211_VHT_MCS_NOT_SUPPORTED; | ||
229 | |||
230 | if (peer_tx != IEEE80211_VHT_MCS_NOT_SUPPORTED) { | ||
231 | if (own_rx == IEEE80211_VHT_MCS_NOT_SUPPORTED) | ||
232 | peer_tx = IEEE80211_VHT_MCS_NOT_SUPPORTED; | ||
233 | else if (own_rx < peer_tx) | ||
234 | peer_tx = own_rx; | ||
235 | } | ||
236 | |||
237 | if (peer_rx != IEEE80211_VHT_MCS_NOT_SUPPORTED) { | ||
238 | if (own_tx == IEEE80211_VHT_MCS_NOT_SUPPORTED) | ||
239 | peer_rx = IEEE80211_VHT_MCS_NOT_SUPPORTED; | ||
240 | else if (own_tx < peer_rx) | ||
241 | peer_rx = own_tx; | ||
242 | } | ||
243 | |||
244 | vht_cap->vht_mcs.rx_mcs_map &= | ||
245 | ~cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << i * 2); | ||
246 | vht_cap->vht_mcs.rx_mcs_map |= cpu_to_le16(peer_rx << i * 2); | ||
247 | |||
248 | vht_cap->vht_mcs.tx_mcs_map &= | ||
249 | ~cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << i * 2); | ||
250 | vht_cap->vht_mcs.tx_mcs_map |= cpu_to_le16(peer_tx << i * 2); | ||
251 | } | ||
252 | |||
253 | /* finally set up the bandwidth */ | ||
44 | switch (vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) { | 254 | switch (vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) { |
45 | case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ: | 255 | case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ: |
46 | case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ: | 256 | case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ: |
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index f82b2e606cfd..1ba9dbc0e107 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c | |||
@@ -1470,7 +1470,8 @@ ip_set_utest(struct sock *ctnl, struct sk_buff *skb, | |||
1470 | if (ret == -EAGAIN) | 1470 | if (ret == -EAGAIN) |
1471 | ret = 1; | 1471 | ret = 1; |
1472 | 1472 | ||
1473 | return ret < 0 ? ret : ret > 0 ? 0 : -IPSET_ERR_EXIST; | 1473 | return (ret < 0 && ret != -ENOTEMPTY) ? ret : |
1474 | ret > 0 ? 0 : -IPSET_ERR_EXIST; | ||
1474 | } | 1475 | } |
1475 | 1476 | ||
1476 | /* Get headed data of a set */ | 1477 | /* Get headed data of a set */ |
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c index c6bc3bd95052..b75a9b3f9e89 100644 --- a/net/nfc/llcp/commands.c +++ b/net/nfc/llcp/commands.c | |||
@@ -117,6 +117,88 @@ u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length) | |||
117 | return tlv; | 117 | return tlv; |
118 | } | 118 | } |
119 | 119 | ||
120 | struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdres_tlv(u8 tid, u8 sap) | ||
121 | { | ||
122 | struct nfc_llcp_sdp_tlv *sdres; | ||
123 | u8 value[2]; | ||
124 | |||
125 | sdres = kzalloc(sizeof(struct nfc_llcp_sdp_tlv), GFP_KERNEL); | ||
126 | if (sdres == NULL) | ||
127 | return NULL; | ||
128 | |||
129 | value[0] = tid; | ||
130 | value[1] = sap; | ||
131 | |||
132 | sdres->tlv = nfc_llcp_build_tlv(LLCP_TLV_SDRES, value, 2, | ||
133 | &sdres->tlv_len); | ||
134 | if (sdres->tlv == NULL) { | ||
135 | kfree(sdres); | ||
136 | return NULL; | ||
137 | } | ||
138 | |||
139 | sdres->tid = tid; | ||
140 | sdres->sap = sap; | ||
141 | |||
142 | INIT_HLIST_NODE(&sdres->node); | ||
143 | |||
144 | return sdres; | ||
145 | } | ||
146 | |||
147 | struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdreq_tlv(u8 tid, char *uri, | ||
148 | size_t uri_len) | ||
149 | { | ||
150 | struct nfc_llcp_sdp_tlv *sdreq; | ||
151 | |||
152 | pr_debug("uri: %s, len: %zu\n", uri, uri_len); | ||
153 | |||
154 | sdreq = kzalloc(sizeof(struct nfc_llcp_sdp_tlv), GFP_KERNEL); | ||
155 | if (sdreq == NULL) | ||
156 | return NULL; | ||
157 | |||
158 | sdreq->tlv_len = uri_len + 3; | ||
159 | |||
160 | if (uri[uri_len - 1] == 0) | ||
161 | sdreq->tlv_len--; | ||
162 | |||
163 | sdreq->tlv = kzalloc(sdreq->tlv_len + 1, GFP_KERNEL); | ||
164 | if (sdreq->tlv == NULL) { | ||
165 | kfree(sdreq); | ||
166 | return NULL; | ||
167 | } | ||
168 | |||
169 | sdreq->tlv[0] = LLCP_TLV_SDREQ; | ||
170 | sdreq->tlv[1] = sdreq->tlv_len - 2; | ||
171 | sdreq->tlv[2] = tid; | ||
172 | |||
173 | sdreq->tid = tid; | ||
174 | sdreq->uri = sdreq->tlv + 3; | ||
175 | memcpy(sdreq->uri, uri, uri_len); | ||
176 | |||
177 | sdreq->time = jiffies; | ||
178 | |||
179 | INIT_HLIST_NODE(&sdreq->node); | ||
180 | |||
181 | return sdreq; | ||
182 | } | ||
183 | |||
184 | void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp) | ||
185 | { | ||
186 | kfree(sdp->tlv); | ||
187 | kfree(sdp); | ||
188 | } | ||
189 | |||
190 | void nfc_llcp_free_sdp_tlv_list(struct hlist_head *head) | ||
191 | { | ||
192 | struct nfc_llcp_sdp_tlv *sdp; | ||
193 | struct hlist_node *n; | ||
194 | |||
195 | hlist_for_each_entry_safe(sdp, n, head, node) { | ||
196 | hlist_del(&sdp->node); | ||
197 | |||
198 | nfc_llcp_free_sdp_tlv(sdp); | ||
199 | } | ||
200 | } | ||
201 | |||
120 | int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local, | 202 | int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local, |
121 | u8 *tlv_array, u16 tlv_array_len) | 203 | u8 *tlv_array, u16 tlv_array_len) |
122 | { | 204 | { |
@@ -184,10 +266,10 @@ int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock, | |||
184 | 266 | ||
185 | switch (type) { | 267 | switch (type) { |
186 | case LLCP_TLV_MIUX: | 268 | case LLCP_TLV_MIUX: |
187 | sock->miu = llcp_tlv_miux(tlv) + 128; | 269 | sock->remote_miu = llcp_tlv_miux(tlv) + 128; |
188 | break; | 270 | break; |
189 | case LLCP_TLV_RW: | 271 | case LLCP_TLV_RW: |
190 | sock->rw = llcp_tlv_rw(tlv); | 272 | sock->remote_rw = llcp_tlv_rw(tlv); |
191 | break; | 273 | break; |
192 | case LLCP_TLV_SN: | 274 | case LLCP_TLV_SN: |
193 | break; | 275 | break; |
@@ -200,7 +282,8 @@ int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock, | |||
200 | tlv += length + 2; | 282 | tlv += length + 2; |
201 | } | 283 | } |
202 | 284 | ||
203 | pr_debug("sock %p rw %d miu %d\n", sock, sock->rw, sock->miu); | 285 | pr_debug("sock %p rw %d miu %d\n", sock, |
286 | sock->remote_rw, sock->remote_miu); | ||
204 | 287 | ||
205 | return 0; | 288 | return 0; |
206 | } | 289 | } |
@@ -318,9 +401,9 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock) | |||
318 | struct sk_buff *skb; | 401 | struct sk_buff *skb; |
319 | u8 *service_name_tlv = NULL, service_name_tlv_length; | 402 | u8 *service_name_tlv = NULL, service_name_tlv_length; |
320 | u8 *miux_tlv = NULL, miux_tlv_length; | 403 | u8 *miux_tlv = NULL, miux_tlv_length; |
321 | u8 *rw_tlv = NULL, rw_tlv_length; | 404 | u8 *rw_tlv = NULL, rw_tlv_length, rw; |
322 | int err; | 405 | int err; |
323 | u16 size = 0; | 406 | u16 size = 0, miux; |
324 | 407 | ||
325 | pr_debug("Sending CONNECT\n"); | 408 | pr_debug("Sending CONNECT\n"); |
326 | 409 | ||
@@ -336,11 +419,15 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock) | |||
336 | size += service_name_tlv_length; | 419 | size += service_name_tlv_length; |
337 | } | 420 | } |
338 | 421 | ||
339 | miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0, | 422 | /* If the socket parameters are not set, use the local ones */ |
423 | miux = sock->miux > LLCP_MAX_MIUX ? local->miux : sock->miux; | ||
424 | rw = sock->rw > LLCP_MAX_RW ? local->rw : sock->rw; | ||
425 | |||
426 | miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0, | ||
340 | &miux_tlv_length); | 427 | &miux_tlv_length); |
341 | size += miux_tlv_length; | 428 | size += miux_tlv_length; |
342 | 429 | ||
343 | rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &local->rw, 0, &rw_tlv_length); | 430 | rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length); |
344 | size += rw_tlv_length; | 431 | size += rw_tlv_length; |
345 | 432 | ||
346 | pr_debug("SKB size %d SN length %zu\n", size, sock->service_name_len); | 433 | pr_debug("SKB size %d SN length %zu\n", size, sock->service_name_len); |
@@ -377,9 +464,9 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock) | |||
377 | struct nfc_llcp_local *local; | 464 | struct nfc_llcp_local *local; |
378 | struct sk_buff *skb; | 465 | struct sk_buff *skb; |
379 | u8 *miux_tlv = NULL, miux_tlv_length; | 466 | u8 *miux_tlv = NULL, miux_tlv_length; |
380 | u8 *rw_tlv = NULL, rw_tlv_length; | 467 | u8 *rw_tlv = NULL, rw_tlv_length, rw; |
381 | int err; | 468 | int err; |
382 | u16 size = 0; | 469 | u16 size = 0, miux; |
383 | 470 | ||
384 | pr_debug("Sending CC\n"); | 471 | pr_debug("Sending CC\n"); |
385 | 472 | ||
@@ -387,11 +474,15 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock) | |||
387 | if (local == NULL) | 474 | if (local == NULL) |
388 | return -ENODEV; | 475 | return -ENODEV; |
389 | 476 | ||
390 | miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0, | 477 | /* If the socket parameters are not set, use the local ones */ |
478 | miux = sock->miux > LLCP_MAX_MIUX ? local->miux : sock->miux; | ||
479 | rw = sock->rw > LLCP_MAX_RW ? local->rw : sock->rw; | ||
480 | |||
481 | miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0, | ||
391 | &miux_tlv_length); | 482 | &miux_tlv_length); |
392 | size += miux_tlv_length; | 483 | size += miux_tlv_length; |
393 | 484 | ||
394 | rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &local->rw, 0, &rw_tlv_length); | 485 | rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length); |
395 | size += rw_tlv_length; | 486 | size += rw_tlv_length; |
396 | 487 | ||
397 | skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, size); | 488 | skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, size); |
@@ -416,48 +507,90 @@ error_tlv: | |||
416 | return err; | 507 | return err; |
417 | } | 508 | } |
418 | 509 | ||
419 | int nfc_llcp_send_snl(struct nfc_llcp_local *local, u8 tid, u8 sap) | 510 | static struct sk_buff *nfc_llcp_allocate_snl(struct nfc_llcp_local *local, |
511 | size_t tlv_length) | ||
420 | { | 512 | { |
421 | struct sk_buff *skb; | 513 | struct sk_buff *skb; |
422 | struct nfc_dev *dev; | 514 | struct nfc_dev *dev; |
423 | u8 *sdres_tlv = NULL, sdres_tlv_length, sdres[2]; | ||
424 | u16 size = 0; | 515 | u16 size = 0; |
425 | 516 | ||
426 | pr_debug("Sending SNL tid 0x%x sap 0x%x\n", tid, sap); | ||
427 | |||
428 | if (local == NULL) | 517 | if (local == NULL) |
429 | return -ENODEV; | 518 | return ERR_PTR(-ENODEV); |
430 | 519 | ||
431 | dev = local->dev; | 520 | dev = local->dev; |
432 | if (dev == NULL) | 521 | if (dev == NULL) |
433 | return -ENODEV; | 522 | return ERR_PTR(-ENODEV); |
434 | |||
435 | sdres[0] = tid; | ||
436 | sdres[1] = sap; | ||
437 | sdres_tlv = nfc_llcp_build_tlv(LLCP_TLV_SDRES, sdres, 0, | ||
438 | &sdres_tlv_length); | ||
439 | if (sdres_tlv == NULL) | ||
440 | return -ENOMEM; | ||
441 | 523 | ||
442 | size += LLCP_HEADER_SIZE; | 524 | size += LLCP_HEADER_SIZE; |
443 | size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE; | 525 | size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE; |
444 | size += sdres_tlv_length; | 526 | size += tlv_length; |
445 | 527 | ||
446 | skb = alloc_skb(size, GFP_KERNEL); | 528 | skb = alloc_skb(size, GFP_KERNEL); |
447 | if (skb == NULL) { | 529 | if (skb == NULL) |
448 | kfree(sdres_tlv); | 530 | return ERR_PTR(-ENOMEM); |
449 | return -ENOMEM; | ||
450 | } | ||
451 | 531 | ||
452 | skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE); | 532 | skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE); |
453 | 533 | ||
454 | skb = llcp_add_header(skb, LLCP_SAP_SDP, LLCP_SAP_SDP, LLCP_PDU_SNL); | 534 | skb = llcp_add_header(skb, LLCP_SAP_SDP, LLCP_SAP_SDP, LLCP_PDU_SNL); |
455 | 535 | ||
456 | memcpy(skb_put(skb, sdres_tlv_length), sdres_tlv, sdres_tlv_length); | 536 | return skb; |
537 | } | ||
538 | |||
539 | int nfc_llcp_send_snl_sdres(struct nfc_llcp_local *local, | ||
540 | struct hlist_head *tlv_list, size_t tlvs_len) | ||
541 | { | ||
542 | struct nfc_llcp_sdp_tlv *sdp; | ||
543 | struct hlist_node *n; | ||
544 | struct sk_buff *skb; | ||
545 | |||
546 | skb = nfc_llcp_allocate_snl(local, tlvs_len); | ||
547 | if (IS_ERR(skb)) | ||
548 | return PTR_ERR(skb); | ||
549 | |||
550 | hlist_for_each_entry_safe(sdp, n, tlv_list, node) { | ||
551 | memcpy(skb_put(skb, sdp->tlv_len), sdp->tlv, sdp->tlv_len); | ||
552 | |||
553 | hlist_del(&sdp->node); | ||
554 | |||
555 | nfc_llcp_free_sdp_tlv(sdp); | ||
556 | } | ||
457 | 557 | ||
458 | skb_queue_tail(&local->tx_queue, skb); | 558 | skb_queue_tail(&local->tx_queue, skb); |
459 | 559 | ||
460 | kfree(sdres_tlv); | 560 | return 0; |
561 | } | ||
562 | |||
563 | int nfc_llcp_send_snl_sdreq(struct nfc_llcp_local *local, | ||
564 | struct hlist_head *tlv_list, size_t tlvs_len) | ||
565 | { | ||
566 | struct nfc_llcp_sdp_tlv *sdreq; | ||
567 | struct hlist_node *n; | ||
568 | struct sk_buff *skb; | ||
569 | |||
570 | skb = nfc_llcp_allocate_snl(local, tlvs_len); | ||
571 | if (IS_ERR(skb)) | ||
572 | return PTR_ERR(skb); | ||
573 | |||
574 | mutex_lock(&local->sdreq_lock); | ||
575 | |||
576 | if (hlist_empty(&local->pending_sdreqs)) | ||
577 | mod_timer(&local->sdreq_timer, | ||
578 | jiffies + msecs_to_jiffies(3 * local->remote_lto)); | ||
579 | |||
580 | hlist_for_each_entry_safe(sdreq, n, tlv_list, node) { | ||
581 | pr_debug("tid %d for %s\n", sdreq->tid, sdreq->uri); | ||
582 | |||
583 | memcpy(skb_put(skb, sdreq->tlv_len), sdreq->tlv, | ||
584 | sdreq->tlv_len); | ||
585 | |||
586 | hlist_del(&sdreq->node); | ||
587 | |||
588 | hlist_add_head(&sdreq->node, &local->pending_sdreqs); | ||
589 | } | ||
590 | |||
591 | mutex_unlock(&local->sdreq_lock); | ||
592 | |||
593 | skb_queue_tail(&local->tx_queue, skb); | ||
461 | 594 | ||
462 | return 0; | 595 | return 0; |
463 | } | 596 | } |
@@ -532,8 +665,8 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | |||
532 | 665 | ||
533 | /* Remote is ready but has not acknowledged our frames */ | 666 | /* Remote is ready but has not acknowledged our frames */ |
534 | if((sock->remote_ready && | 667 | if((sock->remote_ready && |
535 | skb_queue_len(&sock->tx_pending_queue) >= sock->rw && | 668 | skb_queue_len(&sock->tx_pending_queue) >= sock->remote_rw && |
536 | skb_queue_len(&sock->tx_queue) >= 2 * sock->rw)) { | 669 | skb_queue_len(&sock->tx_queue) >= 2 * sock->remote_rw)) { |
537 | pr_err("Pending queue is full %d frames\n", | 670 | pr_err("Pending queue is full %d frames\n", |
538 | skb_queue_len(&sock->tx_pending_queue)); | 671 | skb_queue_len(&sock->tx_pending_queue)); |
539 | return -ENOBUFS; | 672 | return -ENOBUFS; |
@@ -541,7 +674,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | |||
541 | 674 | ||
542 | /* Remote is not ready and we've been queueing enough frames */ | 675 | /* Remote is not ready and we've been queueing enough frames */ |
543 | if ((!sock->remote_ready && | 676 | if ((!sock->remote_ready && |
544 | skb_queue_len(&sock->tx_queue) >= 2 * sock->rw)) { | 677 | skb_queue_len(&sock->tx_queue) >= 2 * sock->remote_rw)) { |
545 | pr_err("Tx queue is full %d frames\n", | 678 | pr_err("Tx queue is full %d frames\n", |
546 | skb_queue_len(&sock->tx_queue)); | 679 | skb_queue_len(&sock->tx_queue)); |
547 | return -ENOBUFS; | 680 | return -ENOBUFS; |
@@ -561,7 +694,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | |||
561 | 694 | ||
562 | while (remaining_len > 0) { | 695 | while (remaining_len > 0) { |
563 | 696 | ||
564 | frag_len = min_t(size_t, sock->miu, remaining_len); | 697 | frag_len = min_t(size_t, sock->remote_miu, remaining_len); |
565 | 698 | ||
566 | pr_debug("Fragment %zd bytes remaining %zd", | 699 | pr_debug("Fragment %zd bytes remaining %zd", |
567 | frag_len, remaining_len); | 700 | frag_len, remaining_len); |
@@ -621,7 +754,7 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap, | |||
621 | 754 | ||
622 | while (remaining_len > 0) { | 755 | while (remaining_len > 0) { |
623 | 756 | ||
624 | frag_len = min_t(size_t, sock->miu, remaining_len); | 757 | frag_len = min_t(size_t, sock->remote_miu, remaining_len); |
625 | 758 | ||
626 | pr_debug("Fragment %zd bytes remaining %zd", | 759 | pr_debug("Fragment %zd bytes remaining %zd", |
627 | frag_len, remaining_len); | 760 | frag_len, remaining_len); |
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index 7f8266dd14cb..bb67b98b9797 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c | |||
@@ -68,7 +68,8 @@ static void nfc_llcp_socket_purge(struct nfc_llcp_sock *sock) | |||
68 | } | 68 | } |
69 | } | 69 | } |
70 | 70 | ||
71 | static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) | 71 | static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen, |
72 | int err) | ||
72 | { | 73 | { |
73 | struct sock *sk; | 74 | struct sock *sk; |
74 | struct hlist_node *tmp; | 75 | struct hlist_node *tmp; |
@@ -100,7 +101,10 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) | |||
100 | 101 | ||
101 | nfc_llcp_accept_unlink(accept_sk); | 102 | nfc_llcp_accept_unlink(accept_sk); |
102 | 103 | ||
104 | if (err) | ||
105 | accept_sk->sk_err = err; | ||
103 | accept_sk->sk_state = LLCP_CLOSED; | 106 | accept_sk->sk_state = LLCP_CLOSED; |
107 | accept_sk->sk_state_change(sk); | ||
104 | 108 | ||
105 | bh_unlock_sock(accept_sk); | 109 | bh_unlock_sock(accept_sk); |
106 | 110 | ||
@@ -123,7 +127,10 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) | |||
123 | continue; | 127 | continue; |
124 | } | 128 | } |
125 | 129 | ||
130 | if (err) | ||
131 | sk->sk_err = err; | ||
126 | sk->sk_state = LLCP_CLOSED; | 132 | sk->sk_state = LLCP_CLOSED; |
133 | sk->sk_state_change(sk); | ||
127 | 134 | ||
128 | bh_unlock_sock(sk); | 135 | bh_unlock_sock(sk); |
129 | 136 | ||
@@ -133,6 +140,36 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) | |||
133 | } | 140 | } |
134 | 141 | ||
135 | write_unlock(&local->sockets.lock); | 142 | write_unlock(&local->sockets.lock); |
143 | |||
144 | /* | ||
145 | * If we want to keep the listening sockets alive, | ||
146 | * we don't touch the RAW ones. | ||
147 | */ | ||
148 | if (listen == true) | ||
149 | return; | ||
150 | |||
151 | write_lock(&local->raw_sockets.lock); | ||
152 | |||
153 | sk_for_each_safe(sk, tmp, &local->raw_sockets.head) { | ||
154 | llcp_sock = nfc_llcp_sock(sk); | ||
155 | |||
156 | bh_lock_sock(sk); | ||
157 | |||
158 | nfc_llcp_socket_purge(llcp_sock); | ||
159 | |||
160 | if (err) | ||
161 | sk->sk_err = err; | ||
162 | sk->sk_state = LLCP_CLOSED; | ||
163 | sk->sk_state_change(sk); | ||
164 | |||
165 | bh_unlock_sock(sk); | ||
166 | |||
167 | sock_orphan(sk); | ||
168 | |||
169 | sk_del_node_init(sk); | ||
170 | } | ||
171 | |||
172 | write_unlock(&local->raw_sockets.lock); | ||
136 | } | 173 | } |
137 | 174 | ||
138 | struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) | 175 | struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) |
@@ -142,20 +179,28 @@ struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) | |||
142 | return local; | 179 | return local; |
143 | } | 180 | } |
144 | 181 | ||
145 | static void local_release(struct kref *ref) | 182 | static void local_cleanup(struct nfc_llcp_local *local, bool listen) |
146 | { | 183 | { |
147 | struct nfc_llcp_local *local; | 184 | nfc_llcp_socket_release(local, listen, ENXIO); |
148 | |||
149 | local = container_of(ref, struct nfc_llcp_local, ref); | ||
150 | |||
151 | list_del(&local->list); | ||
152 | nfc_llcp_socket_release(local, false); | ||
153 | del_timer_sync(&local->link_timer); | 185 | del_timer_sync(&local->link_timer); |
154 | skb_queue_purge(&local->tx_queue); | 186 | skb_queue_purge(&local->tx_queue); |
155 | cancel_work_sync(&local->tx_work); | 187 | cancel_work_sync(&local->tx_work); |
156 | cancel_work_sync(&local->rx_work); | 188 | cancel_work_sync(&local->rx_work); |
157 | cancel_work_sync(&local->timeout_work); | 189 | cancel_work_sync(&local->timeout_work); |
158 | kfree_skb(local->rx_pending); | 190 | kfree_skb(local->rx_pending); |
191 | del_timer_sync(&local->sdreq_timer); | ||
192 | cancel_work_sync(&local->sdreq_timeout_work); | ||
193 | nfc_llcp_free_sdp_tlv_list(&local->pending_sdreqs); | ||
194 | } | ||
195 | |||
196 | static void local_release(struct kref *ref) | ||
197 | { | ||
198 | struct nfc_llcp_local *local; | ||
199 | |||
200 | local = container_of(ref, struct nfc_llcp_local, ref); | ||
201 | |||
202 | list_del(&local->list); | ||
203 | local_cleanup(local, false); | ||
159 | kfree(local); | 204 | kfree(local); |
160 | } | 205 | } |
161 | 206 | ||
@@ -223,6 +268,47 @@ static void nfc_llcp_symm_timer(unsigned long data) | |||
223 | schedule_work(&local->timeout_work); | 268 | schedule_work(&local->timeout_work); |
224 | } | 269 | } |
225 | 270 | ||
271 | static void nfc_llcp_sdreq_timeout_work(struct work_struct *work) | ||
272 | { | ||
273 | unsigned long time; | ||
274 | HLIST_HEAD(nl_sdres_list); | ||
275 | struct hlist_node *n; | ||
276 | struct nfc_llcp_sdp_tlv *sdp; | ||
277 | struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, | ||
278 | sdreq_timeout_work); | ||
279 | |||
280 | mutex_lock(&local->sdreq_lock); | ||
281 | |||
282 | time = jiffies - msecs_to_jiffies(3 * local->remote_lto); | ||
283 | |||
284 | hlist_for_each_entry_safe(sdp, n, &local->pending_sdreqs, node) { | ||
285 | if (time_after(sdp->time, time)) | ||
286 | continue; | ||
287 | |||
288 | sdp->sap = LLCP_SDP_UNBOUND; | ||
289 | |||
290 | hlist_del(&sdp->node); | ||
291 | |||
292 | hlist_add_head(&sdp->node, &nl_sdres_list); | ||
293 | } | ||
294 | |||
295 | if (!hlist_empty(&local->pending_sdreqs)) | ||
296 | mod_timer(&local->sdreq_timer, | ||
297 | jiffies + msecs_to_jiffies(3 * local->remote_lto)); | ||
298 | |||
299 | mutex_unlock(&local->sdreq_lock); | ||
300 | |||
301 | if (!hlist_empty(&nl_sdres_list)) | ||
302 | nfc_genl_llc_send_sdres(local->dev, &nl_sdres_list); | ||
303 | } | ||
304 | |||
305 | static void nfc_llcp_sdreq_timer(unsigned long data) | ||
306 | { | ||
307 | struct nfc_llcp_local *local = (struct nfc_llcp_local *) data; | ||
308 | |||
309 | schedule_work(&local->sdreq_timeout_work); | ||
310 | } | ||
311 | |||
226 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev) | 312 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev) |
227 | { | 313 | { |
228 | struct nfc_llcp_local *local, *n; | 314 | struct nfc_llcp_local *local, *n; |
@@ -766,8 +852,6 @@ static void nfc_llcp_recv_ui(struct nfc_llcp_local *local, | |||
766 | ui_cb->dsap = dsap; | 852 | ui_cb->dsap = dsap; |
767 | ui_cb->ssap = ssap; | 853 | ui_cb->ssap = ssap; |
768 | 854 | ||
769 | printk("%s %d %d\n", __func__, dsap, ssap); | ||
770 | |||
771 | pr_debug("%d %d\n", dsap, ssap); | 855 | pr_debug("%d %d\n", dsap, ssap); |
772 | 856 | ||
773 | /* We're looking for a bound socket, not a client one */ | 857 | /* We're looking for a bound socket, not a client one */ |
@@ -865,7 +949,9 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, | |||
865 | new_sock = nfc_llcp_sock(new_sk); | 949 | new_sock = nfc_llcp_sock(new_sk); |
866 | new_sock->dev = local->dev; | 950 | new_sock->dev = local->dev; |
867 | new_sock->local = nfc_llcp_local_get(local); | 951 | new_sock->local = nfc_llcp_local_get(local); |
868 | new_sock->miu = local->remote_miu; | 952 | new_sock->rw = sock->rw; |
953 | new_sock->miux = sock->miux; | ||
954 | new_sock->remote_miu = local->remote_miu; | ||
869 | new_sock->nfc_protocol = sock->nfc_protocol; | 955 | new_sock->nfc_protocol = sock->nfc_protocol; |
870 | new_sock->dsap = ssap; | 956 | new_sock->dsap = ssap; |
871 | new_sock->target_idx = local->target_idx; | 957 | new_sock->target_idx = local->target_idx; |
@@ -919,11 +1005,11 @@ int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock) | |||
919 | 1005 | ||
920 | pr_debug("Remote ready %d tx queue len %d remote rw %d", | 1006 | pr_debug("Remote ready %d tx queue len %d remote rw %d", |
921 | sock->remote_ready, skb_queue_len(&sock->tx_pending_queue), | 1007 | sock->remote_ready, skb_queue_len(&sock->tx_pending_queue), |
922 | sock->rw); | 1008 | sock->remote_rw); |
923 | 1009 | ||
924 | /* Try to queue some I frames for transmission */ | 1010 | /* Try to queue some I frames for transmission */ |
925 | while (sock->remote_ready && | 1011 | while (sock->remote_ready && |
926 | skb_queue_len(&sock->tx_pending_queue) < sock->rw) { | 1012 | skb_queue_len(&sock->tx_pending_queue) < sock->remote_rw) { |
927 | struct sk_buff *pdu; | 1013 | struct sk_buff *pdu; |
928 | 1014 | ||
929 | pdu = skb_dequeue(&sock->tx_queue); | 1015 | pdu = skb_dequeue(&sock->tx_queue); |
@@ -1144,6 +1230,10 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local, | |||
1144 | u16 tlv_len, offset; | 1230 | u16 tlv_len, offset; |
1145 | char *service_name; | 1231 | char *service_name; |
1146 | size_t service_name_len; | 1232 | size_t service_name_len; |
1233 | struct nfc_llcp_sdp_tlv *sdp; | ||
1234 | HLIST_HEAD(llc_sdres_list); | ||
1235 | size_t sdres_tlvs_len; | ||
1236 | HLIST_HEAD(nl_sdres_list); | ||
1147 | 1237 | ||
1148 | dsap = nfc_llcp_dsap(skb); | 1238 | dsap = nfc_llcp_dsap(skb); |
1149 | ssap = nfc_llcp_ssap(skb); | 1239 | ssap = nfc_llcp_ssap(skb); |
@@ -1158,6 +1248,7 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local, | |||
1158 | tlv = &skb->data[LLCP_HEADER_SIZE]; | 1248 | tlv = &skb->data[LLCP_HEADER_SIZE]; |
1159 | tlv_len = skb->len - LLCP_HEADER_SIZE; | 1249 | tlv_len = skb->len - LLCP_HEADER_SIZE; |
1160 | offset = 0; | 1250 | offset = 0; |
1251 | sdres_tlvs_len = 0; | ||
1161 | 1252 | ||
1162 | while (offset < tlv_len) { | 1253 | while (offset < tlv_len) { |
1163 | type = tlv[0]; | 1254 | type = tlv[0]; |
@@ -1175,14 +1266,14 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local, | |||
1175 | !strncmp(service_name, "urn:nfc:sn:sdp", | 1266 | !strncmp(service_name, "urn:nfc:sn:sdp", |
1176 | service_name_len)) { | 1267 | service_name_len)) { |
1177 | sap = 1; | 1268 | sap = 1; |
1178 | goto send_snl; | 1269 | goto add_snl; |
1179 | } | 1270 | } |
1180 | 1271 | ||
1181 | llcp_sock = nfc_llcp_sock_from_sn(local, service_name, | 1272 | llcp_sock = nfc_llcp_sock_from_sn(local, service_name, |
1182 | service_name_len); | 1273 | service_name_len); |
1183 | if (!llcp_sock) { | 1274 | if (!llcp_sock) { |
1184 | sap = 0; | 1275 | sap = 0; |
1185 | goto send_snl; | 1276 | goto add_snl; |
1186 | } | 1277 | } |
1187 | 1278 | ||
1188 | /* | 1279 | /* |
@@ -1199,7 +1290,7 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local, | |||
1199 | 1290 | ||
1200 | if (sap == LLCP_SAP_MAX) { | 1291 | if (sap == LLCP_SAP_MAX) { |
1201 | sap = 0; | 1292 | sap = 0; |
1202 | goto send_snl; | 1293 | goto add_snl; |
1203 | } | 1294 | } |
1204 | 1295 | ||
1205 | client_count = | 1296 | client_count = |
@@ -1216,8 +1307,37 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local, | |||
1216 | 1307 | ||
1217 | pr_debug("%p %d\n", llcp_sock, sap); | 1308 | pr_debug("%p %d\n", llcp_sock, sap); |
1218 | 1309 | ||
1219 | send_snl: | 1310 | add_snl: |
1220 | nfc_llcp_send_snl(local, tid, sap); | 1311 | sdp = nfc_llcp_build_sdres_tlv(tid, sap); |
1312 | if (sdp == NULL) | ||
1313 | goto exit; | ||
1314 | |||
1315 | sdres_tlvs_len += sdp->tlv_len; | ||
1316 | hlist_add_head(&sdp->node, &llc_sdres_list); | ||
1317 | break; | ||
1318 | |||
1319 | case LLCP_TLV_SDRES: | ||
1320 | mutex_lock(&local->sdreq_lock); | ||
1321 | |||
1322 | pr_debug("LLCP_TLV_SDRES: searching tid %d\n", tlv[2]); | ||
1323 | |||
1324 | hlist_for_each_entry(sdp, &local->pending_sdreqs, node) { | ||
1325 | if (sdp->tid != tlv[2]) | ||
1326 | continue; | ||
1327 | |||
1328 | sdp->sap = tlv[3]; | ||
1329 | |||
1330 | pr_debug("Found: uri=%s, sap=%d\n", | ||
1331 | sdp->uri, sdp->sap); | ||
1332 | |||
1333 | hlist_del(&sdp->node); | ||
1334 | |||
1335 | hlist_add_head(&sdp->node, &nl_sdres_list); | ||
1336 | |||
1337 | break; | ||
1338 | } | ||
1339 | |||
1340 | mutex_unlock(&local->sdreq_lock); | ||
1221 | break; | 1341 | break; |
1222 | 1342 | ||
1223 | default: | 1343 | default: |
@@ -1228,6 +1348,13 @@ send_snl: | |||
1228 | offset += length + 2; | 1348 | offset += length + 2; |
1229 | tlv += length + 2; | 1349 | tlv += length + 2; |
1230 | } | 1350 | } |
1351 | |||
1352 | exit: | ||
1353 | if (!hlist_empty(&nl_sdres_list)) | ||
1354 | nfc_genl_llc_send_sdres(local->dev, &nl_sdres_list); | ||
1355 | |||
1356 | if (!hlist_empty(&llc_sdres_list)) | ||
1357 | nfc_llcp_send_snl_sdres(local, &llc_sdres_list, sdres_tlvs_len); | ||
1231 | } | 1358 | } |
1232 | 1359 | ||
1233 | static void nfc_llcp_rx_work(struct work_struct *work) | 1360 | static void nfc_llcp_rx_work(struct work_struct *work) |
@@ -1348,7 +1475,7 @@ void nfc_llcp_mac_is_down(struct nfc_dev *dev) | |||
1348 | return; | 1475 | return; |
1349 | 1476 | ||
1350 | /* Close and purge all existing sockets */ | 1477 | /* Close and purge all existing sockets */ |
1351 | nfc_llcp_socket_release(local, true); | 1478 | nfc_llcp_socket_release(local, true, 0); |
1352 | } | 1479 | } |
1353 | 1480 | ||
1354 | void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, | 1481 | void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, |
@@ -1413,6 +1540,13 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) | |||
1413 | local->remote_miu = LLCP_DEFAULT_MIU; | 1540 | local->remote_miu = LLCP_DEFAULT_MIU; |
1414 | local->remote_lto = LLCP_DEFAULT_LTO; | 1541 | local->remote_lto = LLCP_DEFAULT_LTO; |
1415 | 1542 | ||
1543 | mutex_init(&local->sdreq_lock); | ||
1544 | INIT_HLIST_HEAD(&local->pending_sdreqs); | ||
1545 | init_timer(&local->sdreq_timer); | ||
1546 | local->sdreq_timer.data = (unsigned long) local; | ||
1547 | local->sdreq_timer.function = nfc_llcp_sdreq_timer; | ||
1548 | INIT_WORK(&local->sdreq_timeout_work, nfc_llcp_sdreq_timeout_work); | ||
1549 | |||
1416 | list_add(&local->list, &llcp_devices); | 1550 | list_add(&local->list, &llcp_devices); |
1417 | 1551 | ||
1418 | return 0; | 1552 | return 0; |
@@ -1427,6 +1561,8 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev) | |||
1427 | return; | 1561 | return; |
1428 | } | 1562 | } |
1429 | 1563 | ||
1564 | local_cleanup(local, false); | ||
1565 | |||
1430 | nfc_llcp_local_put(local); | 1566 | nfc_llcp_local_put(local); |
1431 | } | 1567 | } |
1432 | 1568 | ||
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h index 0eae5c509504..7e87a66b02ec 100644 --- a/net/nfc/llcp/llcp.h +++ b/net/nfc/llcp/llcp.h | |||
@@ -46,6 +46,19 @@ struct llcp_sock_list { | |||
46 | rwlock_t lock; | 46 | rwlock_t lock; |
47 | }; | 47 | }; |
48 | 48 | ||
49 | struct nfc_llcp_sdp_tlv { | ||
50 | u8 *tlv; | ||
51 | u8 tlv_len; | ||
52 | |||
53 | char *uri; | ||
54 | u8 tid; | ||
55 | u8 sap; | ||
56 | |||
57 | unsigned long time; | ||
58 | |||
59 | struct hlist_node node; | ||
60 | }; | ||
61 | |||
49 | struct nfc_llcp_local { | 62 | struct nfc_llcp_local { |
50 | struct list_head list; | 63 | struct list_head list; |
51 | struct nfc_dev *dev; | 64 | struct nfc_dev *dev; |
@@ -86,6 +99,12 @@ struct nfc_llcp_local { | |||
86 | u8 remote_opt; | 99 | u8 remote_opt; |
87 | u16 remote_wks; | 100 | u16 remote_wks; |
88 | 101 | ||
102 | struct mutex sdreq_lock; | ||
103 | struct hlist_head pending_sdreqs; | ||
104 | struct timer_list sdreq_timer; | ||
105 | struct work_struct sdreq_timeout_work; | ||
106 | u8 sdreq_next_tid; | ||
107 | |||
89 | /* sockets array */ | 108 | /* sockets array */ |
90 | struct llcp_sock_list sockets; | 109 | struct llcp_sock_list sockets; |
91 | struct llcp_sock_list connecting_sockets; | 110 | struct llcp_sock_list connecting_sockets; |
@@ -105,7 +124,12 @@ struct nfc_llcp_sock { | |||
105 | char *service_name; | 124 | char *service_name; |
106 | size_t service_name_len; | 125 | size_t service_name_len; |
107 | u8 rw; | 126 | u8 rw; |
108 | u16 miu; | 127 | u16 miux; |
128 | |||
129 | |||
130 | /* Remote link parameters */ | ||
131 | u8 remote_rw; | ||
132 | u16 remote_miu; | ||
109 | 133 | ||
110 | /* Link variables */ | 134 | /* Link variables */ |
111 | u8 send_n; | 135 | u8 send_n; |
@@ -213,12 +237,20 @@ int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock, | |||
213 | /* Commands API */ | 237 | /* Commands API */ |
214 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err); | 238 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err); |
215 | u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length); | 239 | u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length); |
240 | struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdres_tlv(u8 tid, u8 sap); | ||
241 | struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdreq_tlv(u8 tid, char *uri, | ||
242 | size_t uri_len); | ||
243 | void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp); | ||
244 | void nfc_llcp_free_sdp_tlv_list(struct hlist_head *sdp_head); | ||
216 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err); | 245 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err); |
217 | int nfc_llcp_disconnect(struct nfc_llcp_sock *sock); | 246 | int nfc_llcp_disconnect(struct nfc_llcp_sock *sock); |
218 | int nfc_llcp_send_symm(struct nfc_dev *dev); | 247 | int nfc_llcp_send_symm(struct nfc_dev *dev); |
219 | int nfc_llcp_send_connect(struct nfc_llcp_sock *sock); | 248 | int nfc_llcp_send_connect(struct nfc_llcp_sock *sock); |
220 | int nfc_llcp_send_cc(struct nfc_llcp_sock *sock); | 249 | int nfc_llcp_send_cc(struct nfc_llcp_sock *sock); |
221 | int nfc_llcp_send_snl(struct nfc_llcp_local *local, u8 tid, u8 sap); | 250 | int nfc_llcp_send_snl_sdres(struct nfc_llcp_local *local, |
251 | struct hlist_head *tlv_list, size_t tlvs_len); | ||
252 | int nfc_llcp_send_snl_sdreq(struct nfc_llcp_local *local, | ||
253 | struct hlist_head *tlv_list, size_t tlvs_len); | ||
222 | int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason); | 254 | int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason); |
223 | int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock); | 255 | int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock); |
224 | int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | 256 | int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, |
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c index 5332751943a9..f1b377e247fe 100644 --- a/net/nfc/llcp/sock.c +++ b/net/nfc/llcp/sock.c | |||
@@ -223,6 +223,124 @@ error: | |||
223 | return ret; | 223 | return ret; |
224 | } | 224 | } |
225 | 225 | ||
226 | static int nfc_llcp_setsockopt(struct socket *sock, int level, int optname, | ||
227 | char __user *optval, unsigned int optlen) | ||
228 | { | ||
229 | struct sock *sk = sock->sk; | ||
230 | struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); | ||
231 | u32 opt; | ||
232 | int err = 0; | ||
233 | |||
234 | pr_debug("%p optname %d\n", sk, optname); | ||
235 | |||
236 | if (level != SOL_NFC) | ||
237 | return -ENOPROTOOPT; | ||
238 | |||
239 | lock_sock(sk); | ||
240 | |||
241 | switch (optname) { | ||
242 | case NFC_LLCP_RW: | ||
243 | if (sk->sk_state == LLCP_CONNECTED || | ||
244 | sk->sk_state == LLCP_BOUND || | ||
245 | sk->sk_state == LLCP_LISTEN) { | ||
246 | err = -EINVAL; | ||
247 | break; | ||
248 | } | ||
249 | |||
250 | if (get_user(opt, (u32 __user *) optval)) { | ||
251 | err = -EFAULT; | ||
252 | break; | ||
253 | } | ||
254 | |||
255 | if (opt > LLCP_MAX_RW) { | ||
256 | err = -EINVAL; | ||
257 | break; | ||
258 | } | ||
259 | |||
260 | llcp_sock->rw = (u8) opt; | ||
261 | |||
262 | break; | ||
263 | |||
264 | case NFC_LLCP_MIUX: | ||
265 | if (sk->sk_state == LLCP_CONNECTED || | ||
266 | sk->sk_state == LLCP_BOUND || | ||
267 | sk->sk_state == LLCP_LISTEN) { | ||
268 | err = -EINVAL; | ||
269 | break; | ||
270 | } | ||
271 | |||
272 | if (get_user(opt, (u32 __user *) optval)) { | ||
273 | err = -EFAULT; | ||
274 | break; | ||
275 | } | ||
276 | |||
277 | if (opt > LLCP_MAX_MIUX) { | ||
278 | err = -EINVAL; | ||
279 | break; | ||
280 | } | ||
281 | |||
282 | llcp_sock->miux = (u16) opt; | ||
283 | |||
284 | break; | ||
285 | |||
286 | default: | ||
287 | err = -ENOPROTOOPT; | ||
288 | break; | ||
289 | } | ||
290 | |||
291 | release_sock(sk); | ||
292 | |||
293 | pr_debug("%p rw %d miux %d\n", llcp_sock, | ||
294 | llcp_sock->rw, llcp_sock->miux); | ||
295 | |||
296 | return err; | ||
297 | } | ||
298 | |||
299 | static int nfc_llcp_getsockopt(struct socket *sock, int level, int optname, | ||
300 | char __user *optval, int __user *optlen) | ||
301 | { | ||
302 | struct sock *sk = sock->sk; | ||
303 | struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); | ||
304 | int len, err = 0; | ||
305 | |||
306 | pr_debug("%p optname %d\n", sk, optname); | ||
307 | |||
308 | if (level != SOL_NFC) | ||
309 | return -ENOPROTOOPT; | ||
310 | |||
311 | if (get_user(len, optlen)) | ||
312 | return -EFAULT; | ||
313 | |||
314 | len = min_t(u32, len, sizeof(u32)); | ||
315 | |||
316 | lock_sock(sk); | ||
317 | |||
318 | switch (optname) { | ||
319 | case NFC_LLCP_RW: | ||
320 | if (put_user(llcp_sock->rw, (u32 __user *) optval)) | ||
321 | err = -EFAULT; | ||
322 | |||
323 | break; | ||
324 | |||
325 | case NFC_LLCP_MIUX: | ||
326 | if (put_user(llcp_sock->miux, (u32 __user *) optval)) | ||
327 | err = -EFAULT; | ||
328 | |||
329 | break; | ||
330 | |||
331 | default: | ||
332 | err = -ENOPROTOOPT; | ||
333 | break; | ||
334 | } | ||
335 | |||
336 | release_sock(sk); | ||
337 | |||
338 | if (put_user(len, optlen)) | ||
339 | return -EFAULT; | ||
340 | |||
341 | return err; | ||
342 | } | ||
343 | |||
226 | void nfc_llcp_accept_unlink(struct sock *sk) | 344 | void nfc_llcp_accept_unlink(struct sock *sk) |
227 | { | 345 | { |
228 | struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); | 346 | struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); |
@@ -278,6 +396,8 @@ struct sock *nfc_llcp_accept_dequeue(struct sock *parent, | |||
278 | 396 | ||
279 | pr_debug("Returning sk state %d\n", sk->sk_state); | 397 | pr_debug("Returning sk state %d\n", sk->sk_state); |
280 | 398 | ||
399 | sk_acceptq_removed(parent); | ||
400 | |||
281 | return sk; | 401 | return sk; |
282 | } | 402 | } |
283 | 403 | ||
@@ -541,7 +661,7 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, | |||
541 | 661 | ||
542 | llcp_sock->dev = dev; | 662 | llcp_sock->dev = dev; |
543 | llcp_sock->local = nfc_llcp_local_get(local); | 663 | llcp_sock->local = nfc_llcp_local_get(local); |
544 | llcp_sock->miu = llcp_sock->local->remote_miu; | 664 | llcp_sock->remote_miu = llcp_sock->local->remote_miu; |
545 | llcp_sock->ssap = nfc_llcp_get_local_ssap(local); | 665 | llcp_sock->ssap = nfc_llcp_get_local_ssap(local); |
546 | if (llcp_sock->ssap == LLCP_SAP_MAX) { | 666 | if (llcp_sock->ssap == LLCP_SAP_MAX) { |
547 | ret = -ENOMEM; | 667 | ret = -ENOMEM; |
@@ -735,8 +855,8 @@ static const struct proto_ops llcp_sock_ops = { | |||
735 | .ioctl = sock_no_ioctl, | 855 | .ioctl = sock_no_ioctl, |
736 | .listen = llcp_sock_listen, | 856 | .listen = llcp_sock_listen, |
737 | .shutdown = sock_no_shutdown, | 857 | .shutdown = sock_no_shutdown, |
738 | .setsockopt = sock_no_setsockopt, | 858 | .setsockopt = nfc_llcp_setsockopt, |
739 | .getsockopt = sock_no_getsockopt, | 859 | .getsockopt = nfc_llcp_getsockopt, |
740 | .sendmsg = llcp_sock_sendmsg, | 860 | .sendmsg = llcp_sock_sendmsg, |
741 | .recvmsg = llcp_sock_recvmsg, | 861 | .recvmsg = llcp_sock_recvmsg, |
742 | .mmap = sock_no_mmap, | 862 | .mmap = sock_no_mmap, |
@@ -800,8 +920,10 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp) | |||
800 | 920 | ||
801 | llcp_sock->ssap = 0; | 921 | llcp_sock->ssap = 0; |
802 | llcp_sock->dsap = LLCP_SAP_SDP; | 922 | llcp_sock->dsap = LLCP_SAP_SDP; |
803 | llcp_sock->rw = LLCP_DEFAULT_RW; | 923 | llcp_sock->rw = LLCP_MAX_RW + 1; |
804 | llcp_sock->miu = LLCP_DEFAULT_MIU; | 924 | llcp_sock->miux = LLCP_MAX_MIUX + 1; |
925 | llcp_sock->remote_rw = LLCP_DEFAULT_RW; | ||
926 | llcp_sock->remote_miu = LLCP_DEFAULT_MIU; | ||
805 | llcp_sock->send_n = llcp_sock->send_ack_n = 0; | 927 | llcp_sock->send_n = llcp_sock->send_ack_n = 0; |
806 | llcp_sock->recv_n = llcp_sock->recv_ack_n = 0; | 928 | llcp_sock->recv_n = llcp_sock->recv_ack_n = 0; |
807 | llcp_sock->remote_ready = 1; | 929 | llcp_sock->remote_ready = 1; |
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index 504b883439f1..73fd51098f4d 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c | |||
@@ -53,6 +53,15 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = { | |||
53 | [NFC_ATTR_DEVICE_POWERED] = { .type = NLA_U8 }, | 53 | [NFC_ATTR_DEVICE_POWERED] = { .type = NLA_U8 }, |
54 | [NFC_ATTR_IM_PROTOCOLS] = { .type = NLA_U32 }, | 54 | [NFC_ATTR_IM_PROTOCOLS] = { .type = NLA_U32 }, |
55 | [NFC_ATTR_TM_PROTOCOLS] = { .type = NLA_U32 }, | 55 | [NFC_ATTR_TM_PROTOCOLS] = { .type = NLA_U32 }, |
56 | [NFC_ATTR_LLC_PARAM_LTO] = { .type = NLA_U8 }, | ||
57 | [NFC_ATTR_LLC_PARAM_RW] = { .type = NLA_U8 }, | ||
58 | [NFC_ATTR_LLC_PARAM_MIUX] = { .type = NLA_U16 }, | ||
59 | [NFC_ATTR_LLC_SDP] = { .type = NLA_NESTED }, | ||
60 | }; | ||
61 | |||
62 | static const struct nla_policy nfc_sdp_genl_policy[NFC_SDP_ATTR_MAX + 1] = { | ||
63 | [NFC_SDP_ATTR_URI] = { .type = NLA_STRING }, | ||
64 | [NFC_SDP_ATTR_SAP] = { .type = NLA_U8 }, | ||
56 | }; | 65 | }; |
57 | 66 | ||
58 | static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target, | 67 | static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target, |
@@ -348,6 +357,74 @@ free_msg: | |||
348 | return -EMSGSIZE; | 357 | return -EMSGSIZE; |
349 | } | 358 | } |
350 | 359 | ||
360 | int nfc_genl_llc_send_sdres(struct nfc_dev *dev, struct hlist_head *sdres_list) | ||
361 | { | ||
362 | struct sk_buff *msg; | ||
363 | struct nlattr *sdp_attr, *uri_attr; | ||
364 | struct nfc_llcp_sdp_tlv *sdres; | ||
365 | struct hlist_node *n; | ||
366 | void *hdr; | ||
367 | int rc = -EMSGSIZE; | ||
368 | int i; | ||
369 | |||
370 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
371 | if (!msg) | ||
372 | return -ENOMEM; | ||
373 | |||
374 | hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, | ||
375 | NFC_EVENT_LLC_SDRES); | ||
376 | if (!hdr) | ||
377 | goto free_msg; | ||
378 | |||
379 | if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx)) | ||
380 | goto nla_put_failure; | ||
381 | |||
382 | sdp_attr = nla_nest_start(msg, NFC_ATTR_LLC_SDP); | ||
383 | if (sdp_attr == NULL) { | ||
384 | rc = -ENOMEM; | ||
385 | goto nla_put_failure; | ||
386 | } | ||
387 | |||
388 | i = 1; | ||
389 | hlist_for_each_entry_safe(sdres, n, sdres_list, node) { | ||
390 | pr_debug("uri: %s, sap: %d\n", sdres->uri, sdres->sap); | ||
391 | |||
392 | uri_attr = nla_nest_start(msg, i++); | ||
393 | if (uri_attr == NULL) { | ||
394 | rc = -ENOMEM; | ||
395 | goto nla_put_failure; | ||
396 | } | ||
397 | |||
398 | if (nla_put_u8(msg, NFC_SDP_ATTR_SAP, sdres->sap)) | ||
399 | goto nla_put_failure; | ||
400 | |||
401 | if (nla_put_string(msg, NFC_SDP_ATTR_URI, sdres->uri)) | ||
402 | goto nla_put_failure; | ||
403 | |||
404 | nla_nest_end(msg, uri_attr); | ||
405 | |||
406 | hlist_del(&sdres->node); | ||
407 | |||
408 | nfc_llcp_free_sdp_tlv(sdres); | ||
409 | } | ||
410 | |||
411 | nla_nest_end(msg, sdp_attr); | ||
412 | |||
413 | genlmsg_end(msg, hdr); | ||
414 | |||
415 | return genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_ATOMIC); | ||
416 | |||
417 | nla_put_failure: | ||
418 | genlmsg_cancel(msg, hdr); | ||
419 | |||
420 | free_msg: | ||
421 | nlmsg_free(msg); | ||
422 | |||
423 | nfc_llcp_free_sdp_tlv_list(sdres_list); | ||
424 | |||
425 | return rc; | ||
426 | } | ||
427 | |||
351 | static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev, | 428 | static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev, |
352 | u32 portid, u32 seq, | 429 | u32 portid, u32 seq, |
353 | struct netlink_callback *cb, | 430 | struct netlink_callback *cb, |
@@ -859,6 +936,96 @@ exit: | |||
859 | return rc; | 936 | return rc; |
860 | } | 937 | } |
861 | 938 | ||
939 | static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info) | ||
940 | { | ||
941 | struct nfc_dev *dev; | ||
942 | struct nfc_llcp_local *local; | ||
943 | struct nlattr *attr, *sdp_attrs[NFC_SDP_ATTR_MAX+1]; | ||
944 | u32 idx; | ||
945 | u8 tid; | ||
946 | char *uri; | ||
947 | int rc = 0, rem; | ||
948 | size_t uri_len, tlvs_len; | ||
949 | struct hlist_head sdreq_list; | ||
950 | struct nfc_llcp_sdp_tlv *sdreq; | ||
951 | |||
952 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || | ||
953 | !info->attrs[NFC_ATTR_LLC_SDP]) | ||
954 | return -EINVAL; | ||
955 | |||
956 | idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); | ||
957 | |||
958 | dev = nfc_get_device(idx); | ||
959 | if (!dev) { | ||
960 | rc = -ENODEV; | ||
961 | goto exit; | ||
962 | } | ||
963 | |||
964 | device_lock(&dev->dev); | ||
965 | |||
966 | if (dev->dep_link_up == false) { | ||
967 | rc = -ENOLINK; | ||
968 | goto exit; | ||
969 | } | ||
970 | |||
971 | local = nfc_llcp_find_local(dev); | ||
972 | if (!local) { | ||
973 | nfc_put_device(dev); | ||
974 | rc = -ENODEV; | ||
975 | goto exit; | ||
976 | } | ||
977 | |||
978 | INIT_HLIST_HEAD(&sdreq_list); | ||
979 | |||
980 | tlvs_len = 0; | ||
981 | |||
982 | nla_for_each_nested(attr, info->attrs[NFC_ATTR_LLC_SDP], rem) { | ||
983 | rc = nla_parse_nested(sdp_attrs, NFC_SDP_ATTR_MAX, attr, | ||
984 | nfc_sdp_genl_policy); | ||
985 | |||
986 | if (rc != 0) { | ||
987 | rc = -EINVAL; | ||
988 | goto exit; | ||
989 | } | ||
990 | |||
991 | if (!sdp_attrs[NFC_SDP_ATTR_URI]) | ||
992 | continue; | ||
993 | |||
994 | uri_len = nla_len(sdp_attrs[NFC_SDP_ATTR_URI]); | ||
995 | if (uri_len == 0) | ||
996 | continue; | ||
997 | |||
998 | uri = nla_data(sdp_attrs[NFC_SDP_ATTR_URI]); | ||
999 | if (uri == NULL || *uri == 0) | ||
1000 | continue; | ||
1001 | |||
1002 | tid = local->sdreq_next_tid++; | ||
1003 | |||
1004 | sdreq = nfc_llcp_build_sdreq_tlv(tid, uri, uri_len); | ||
1005 | if (sdreq == NULL) { | ||
1006 | rc = -ENOMEM; | ||
1007 | goto exit; | ||
1008 | } | ||
1009 | |||
1010 | tlvs_len += sdreq->tlv_len; | ||
1011 | |||
1012 | hlist_add_head(&sdreq->node, &sdreq_list); | ||
1013 | } | ||
1014 | |||
1015 | if (hlist_empty(&sdreq_list)) { | ||
1016 | rc = -EINVAL; | ||
1017 | goto exit; | ||
1018 | } | ||
1019 | |||
1020 | rc = nfc_llcp_send_snl_sdreq(local, &sdreq_list, tlvs_len); | ||
1021 | exit: | ||
1022 | device_unlock(&dev->dev); | ||
1023 | |||
1024 | nfc_put_device(dev); | ||
1025 | |||
1026 | return rc; | ||
1027 | } | ||
1028 | |||
862 | static struct genl_ops nfc_genl_ops[] = { | 1029 | static struct genl_ops nfc_genl_ops[] = { |
863 | { | 1030 | { |
864 | .cmd = NFC_CMD_GET_DEVICE, | 1031 | .cmd = NFC_CMD_GET_DEVICE, |
@@ -913,6 +1080,11 @@ static struct genl_ops nfc_genl_ops[] = { | |||
913 | .doit = nfc_genl_llc_set_params, | 1080 | .doit = nfc_genl_llc_set_params, |
914 | .policy = nfc_genl_policy, | 1081 | .policy = nfc_genl_policy, |
915 | }, | 1082 | }, |
1083 | { | ||
1084 | .cmd = NFC_CMD_LLC_SDREQ, | ||
1085 | .doit = nfc_genl_llc_sdreq, | ||
1086 | .policy = nfc_genl_policy, | ||
1087 | }, | ||
916 | }; | 1088 | }; |
917 | 1089 | ||
918 | 1090 | ||
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h index 87d914d2876a..94bfe19ba678 100644 --- a/net/nfc/nfc.h +++ b/net/nfc/nfc.h | |||
@@ -46,6 +46,8 @@ struct nfc_rawsock { | |||
46 | #define to_rawsock_sk(_tx_work) \ | 46 | #define to_rawsock_sk(_tx_work) \ |
47 | ((struct sock *) container_of(_tx_work, struct nfc_rawsock, tx_work)) | 47 | ((struct sock *) container_of(_tx_work, struct nfc_rawsock, tx_work)) |
48 | 48 | ||
49 | struct nfc_llcp_sdp_tlv; | ||
50 | |||
49 | #ifdef CONFIG_NFC_LLCP | 51 | #ifdef CONFIG_NFC_LLCP |
50 | 52 | ||
51 | void nfc_llcp_mac_is_down(struct nfc_dev *dev); | 53 | void nfc_llcp_mac_is_down(struct nfc_dev *dev); |
@@ -59,6 +61,8 @@ int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb); | |||
59 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); | 61 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); |
60 | int __init nfc_llcp_init(void); | 62 | int __init nfc_llcp_init(void); |
61 | void nfc_llcp_exit(void); | 63 | void nfc_llcp_exit(void); |
64 | void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp); | ||
65 | void nfc_llcp_free_sdp_tlv_list(struct hlist_head *head); | ||
62 | 66 | ||
63 | #else | 67 | #else |
64 | 68 | ||
@@ -112,6 +116,14 @@ static inline void nfc_llcp_exit(void) | |||
112 | { | 116 | { |
113 | } | 117 | } |
114 | 118 | ||
119 | static inline void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp) | ||
120 | { | ||
121 | } | ||
122 | |||
123 | static inline void nfc_llcp_free_sdp_tlv_list(struct hlist_head *sdp_head) | ||
124 | { | ||
125 | } | ||
126 | |||
115 | #endif | 127 | #endif |
116 | 128 | ||
117 | int __init rawsock_init(void); | 129 | int __init rawsock_init(void); |
@@ -144,6 +156,8 @@ int nfc_genl_dep_link_down_event(struct nfc_dev *dev); | |||
144 | int nfc_genl_tm_activated(struct nfc_dev *dev, u32 protocol); | 156 | int nfc_genl_tm_activated(struct nfc_dev *dev, u32 protocol); |
145 | int nfc_genl_tm_deactivated(struct nfc_dev *dev); | 157 | int nfc_genl_tm_deactivated(struct nfc_dev *dev); |
146 | 158 | ||
159 | int nfc_genl_llc_send_sdres(struct nfc_dev *dev, struct hlist_head *sdres_list); | ||
160 | |||
147 | struct nfc_dev *nfc_get_device(unsigned int idx); | 161 | struct nfc_dev *nfc_get_device(unsigned int idx); |
148 | 162 | ||
149 | static inline void nfc_put_device(struct nfc_dev *dev) | 163 | static inline void nfc_put_device(struct nfc_dev *dev) |
diff --git a/net/rds/message.c b/net/rds/message.c index f0a4658f3273..aba232f9f308 100644 --- a/net/rds/message.c +++ b/net/rds/message.c | |||
@@ -82,10 +82,7 @@ static void rds_message_purge(struct rds_message *rm) | |||
82 | void rds_message_put(struct rds_message *rm) | 82 | void rds_message_put(struct rds_message *rm) |
83 | { | 83 | { |
84 | rdsdebug("put rm %p ref %d\n", rm, atomic_read(&rm->m_refcount)); | 84 | rdsdebug("put rm %p ref %d\n", rm, atomic_read(&rm->m_refcount)); |
85 | if (atomic_read(&rm->m_refcount) == 0) { | 85 | WARN(!atomic_read(&rm->m_refcount), "danger refcount zero on %p\n", rm); |
86 | printk(KERN_CRIT "danger refcount zero on %p\n", rm); | ||
87 | WARN_ON(1); | ||
88 | } | ||
89 | if (atomic_dec_and_test(&rm->m_refcount)) { | 86 | if (atomic_dec_and_test(&rm->m_refcount)) { |
90 | BUG_ON(!list_empty(&rm->m_sock_item)); | 87 | BUG_ON(!list_empty(&rm->m_sock_item)); |
91 | BUG_ON(!list_empty(&rm->m_conn_item)); | 88 | BUG_ON(!list_empty(&rm->m_conn_item)); |
@@ -197,6 +194,9 @@ struct rds_message *rds_message_alloc(unsigned int extra_len, gfp_t gfp) | |||
197 | { | 194 | { |
198 | struct rds_message *rm; | 195 | struct rds_message *rm; |
199 | 196 | ||
197 | if (extra_len > KMALLOC_MAX_SIZE - sizeof(struct rds_message)) | ||
198 | return NULL; | ||
199 | |||
200 | rm = kzalloc(sizeof(struct rds_message) + extra_len, gfp); | 200 | rm = kzalloc(sizeof(struct rds_message) + extra_len, gfp); |
201 | if (!rm) | 201 | if (!rm) |
202 | goto out; | 202 | goto out; |
diff --git a/net/rfkill/rfkill-regulator.c b/net/rfkill/rfkill-regulator.c index 4b5ab21ecb24..d11ac79246e4 100644 --- a/net/rfkill/rfkill-regulator.c +++ b/net/rfkill/rfkill-regulator.c | |||
@@ -51,7 +51,7 @@ static int rfkill_regulator_set_block(void *data, bool blocked) | |||
51 | return 0; | 51 | return 0; |
52 | } | 52 | } |
53 | 53 | ||
54 | struct rfkill_ops rfkill_regulator_ops = { | 54 | static struct rfkill_ops rfkill_regulator_ops = { |
55 | .set_block = rfkill_regulator_set_block, | 55 | .set_block = rfkill_regulator_set_block, |
56 | }; | 56 | }; |
57 | 57 | ||
diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c index e9a77f621c3d..d51852bba01c 100644 --- a/net/sched/sch_qfq.c +++ b/net/sched/sch_qfq.c | |||
@@ -298,6 +298,10 @@ static void qfq_update_agg(struct qfq_sched *q, struct qfq_aggregate *agg, | |||
298 | new_num_classes == q->max_agg_classes - 1) /* agg no more full */ | 298 | new_num_classes == q->max_agg_classes - 1) /* agg no more full */ |
299 | hlist_add_head(&agg->nonfull_next, &q->nonfull_aggs); | 299 | hlist_add_head(&agg->nonfull_next, &q->nonfull_aggs); |
300 | 300 | ||
301 | /* The next assignment may let | ||
302 | * agg->initial_budget > agg->budgetmax | ||
303 | * hold, we will take it into account in charge_actual_service(). | ||
304 | */ | ||
301 | agg->budgetmax = new_num_classes * agg->lmax; | 305 | agg->budgetmax = new_num_classes * agg->lmax; |
302 | new_agg_weight = agg->class_weight * new_num_classes; | 306 | new_agg_weight = agg->class_weight * new_num_classes; |
303 | agg->inv_w = ONE_FP/new_agg_weight; | 307 | agg->inv_w = ONE_FP/new_agg_weight; |
@@ -817,7 +821,7 @@ static void qfq_make_eligible(struct qfq_sched *q) | |||
817 | unsigned long old_vslot = q->oldV >> q->min_slot_shift; | 821 | unsigned long old_vslot = q->oldV >> q->min_slot_shift; |
818 | 822 | ||
819 | if (vslot != old_vslot) { | 823 | if (vslot != old_vslot) { |
820 | unsigned long mask = (1UL << fls(vslot ^ old_vslot)) - 1; | 824 | unsigned long mask = (1ULL << fls(vslot ^ old_vslot)) - 1; |
821 | qfq_move_groups(q, mask, IR, ER); | 825 | qfq_move_groups(q, mask, IR, ER); |
822 | qfq_move_groups(q, mask, IB, EB); | 826 | qfq_move_groups(q, mask, IB, EB); |
823 | } | 827 | } |
@@ -988,12 +992,23 @@ static inline struct sk_buff *qfq_peek_skb(struct qfq_aggregate *agg, | |||
988 | /* Update F according to the actual service received by the aggregate. */ | 992 | /* Update F according to the actual service received by the aggregate. */ |
989 | static inline void charge_actual_service(struct qfq_aggregate *agg) | 993 | static inline void charge_actual_service(struct qfq_aggregate *agg) |
990 | { | 994 | { |
991 | /* compute the service received by the aggregate */ | 995 | /* Compute the service received by the aggregate, taking into |
992 | u32 service_received = agg->initial_budget - agg->budget; | 996 | * account that, after decreasing the number of classes in |
997 | * agg, it may happen that | ||
998 | * agg->initial_budget - agg->budget > agg->bugdetmax | ||
999 | */ | ||
1000 | u32 service_received = min(agg->budgetmax, | ||
1001 | agg->initial_budget - agg->budget); | ||
993 | 1002 | ||
994 | agg->F = agg->S + (u64)service_received * agg->inv_w; | 1003 | agg->F = agg->S + (u64)service_received * agg->inv_w; |
995 | } | 1004 | } |
996 | 1005 | ||
1006 | static inline void qfq_update_agg_ts(struct qfq_sched *q, | ||
1007 | struct qfq_aggregate *agg, | ||
1008 | enum update_reason reason); | ||
1009 | |||
1010 | static void qfq_schedule_agg(struct qfq_sched *q, struct qfq_aggregate *agg); | ||
1011 | |||
997 | static struct sk_buff *qfq_dequeue(struct Qdisc *sch) | 1012 | static struct sk_buff *qfq_dequeue(struct Qdisc *sch) |
998 | { | 1013 | { |
999 | struct qfq_sched *q = qdisc_priv(sch); | 1014 | struct qfq_sched *q = qdisc_priv(sch); |
@@ -1021,7 +1036,7 @@ static struct sk_buff *qfq_dequeue(struct Qdisc *sch) | |||
1021 | in_serv_agg->initial_budget = in_serv_agg->budget = | 1036 | in_serv_agg->initial_budget = in_serv_agg->budget = |
1022 | in_serv_agg->budgetmax; | 1037 | in_serv_agg->budgetmax; |
1023 | 1038 | ||
1024 | if (!list_empty(&in_serv_agg->active)) | 1039 | if (!list_empty(&in_serv_agg->active)) { |
1025 | /* | 1040 | /* |
1026 | * Still active: reschedule for | 1041 | * Still active: reschedule for |
1027 | * service. Possible optimization: if no other | 1042 | * service. Possible optimization: if no other |
@@ -1032,8 +1047,9 @@ static struct sk_buff *qfq_dequeue(struct Qdisc *sch) | |||
1032 | * handle it, we would need to maintain an | 1047 | * handle it, we would need to maintain an |
1033 | * extra num_active_aggs field. | 1048 | * extra num_active_aggs field. |
1034 | */ | 1049 | */ |
1035 | qfq_activate_agg(q, in_serv_agg, requeue); | 1050 | qfq_update_agg_ts(q, in_serv_agg, requeue); |
1036 | else if (sch->q.qlen == 0) { /* no aggregate to serve */ | 1051 | qfq_schedule_agg(q, in_serv_agg); |
1052 | } else if (sch->q.qlen == 0) { /* no aggregate to serve */ | ||
1037 | q->in_serv_agg = NULL; | 1053 | q->in_serv_agg = NULL; |
1038 | return NULL; | 1054 | return NULL; |
1039 | } | 1055 | } |
@@ -1052,7 +1068,15 @@ static struct sk_buff *qfq_dequeue(struct Qdisc *sch) | |||
1052 | qdisc_bstats_update(sch, skb); | 1068 | qdisc_bstats_update(sch, skb); |
1053 | 1069 | ||
1054 | agg_dequeue(in_serv_agg, cl, len); | 1070 | agg_dequeue(in_serv_agg, cl, len); |
1055 | in_serv_agg->budget -= len; | 1071 | /* If lmax is lowered, through qfq_change_class, for a class |
1072 | * owning pending packets with larger size than the new value | ||
1073 | * of lmax, then the following condition may hold. | ||
1074 | */ | ||
1075 | if (unlikely(in_serv_agg->budget < len)) | ||
1076 | in_serv_agg->budget = 0; | ||
1077 | else | ||
1078 | in_serv_agg->budget -= len; | ||
1079 | |||
1056 | q->V += (u64)len * IWSUM; | 1080 | q->V += (u64)len * IWSUM; |
1057 | pr_debug("qfq dequeue: len %u F %lld now %lld\n", | 1081 | pr_debug("qfq dequeue: len %u F %lld now %lld\n", |
1058 | len, (unsigned long long) in_serv_agg->F, | 1082 | len, (unsigned long long) in_serv_agg->F, |
@@ -1217,17 +1241,11 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
1217 | cl->deficit = agg->lmax; | 1241 | cl->deficit = agg->lmax; |
1218 | list_add_tail(&cl->alist, &agg->active); | 1242 | list_add_tail(&cl->alist, &agg->active); |
1219 | 1243 | ||
1220 | if (list_first_entry(&agg->active, struct qfq_class, alist) != cl) | 1244 | if (list_first_entry(&agg->active, struct qfq_class, alist) != cl || |
1221 | return err; /* aggregate was not empty, nothing else to do */ | 1245 | q->in_serv_agg == agg) |
1246 | return err; /* non-empty or in service, nothing else to do */ | ||
1222 | 1247 | ||
1223 | /* recharge budget */ | 1248 | qfq_activate_agg(q, agg, enqueue); |
1224 | agg->initial_budget = agg->budget = agg->budgetmax; | ||
1225 | |||
1226 | qfq_update_agg_ts(q, agg, enqueue); | ||
1227 | if (q->in_serv_agg == NULL) | ||
1228 | q->in_serv_agg = agg; | ||
1229 | else if (agg != q->in_serv_agg) | ||
1230 | qfq_schedule_agg(q, agg); | ||
1231 | 1249 | ||
1232 | return err; | 1250 | return err; |
1233 | } | 1251 | } |
@@ -1261,7 +1279,8 @@ static void qfq_schedule_agg(struct qfq_sched *q, struct qfq_aggregate *agg) | |||
1261 | /* group was surely ineligible, remove */ | 1279 | /* group was surely ineligible, remove */ |
1262 | __clear_bit(grp->index, &q->bitmaps[IR]); | 1280 | __clear_bit(grp->index, &q->bitmaps[IR]); |
1263 | __clear_bit(grp->index, &q->bitmaps[IB]); | 1281 | __clear_bit(grp->index, &q->bitmaps[IB]); |
1264 | } else if (!q->bitmaps[ER] && qfq_gt(roundedS, q->V)) | 1282 | } else if (!q->bitmaps[ER] && qfq_gt(roundedS, q->V) && |
1283 | q->in_serv_agg == NULL) | ||
1265 | q->V = roundedS; | 1284 | q->V = roundedS; |
1266 | 1285 | ||
1267 | grp->S = roundedS; | 1286 | grp->S = roundedS; |
@@ -1284,8 +1303,15 @@ skip_update: | |||
1284 | static void qfq_activate_agg(struct qfq_sched *q, struct qfq_aggregate *agg, | 1303 | static void qfq_activate_agg(struct qfq_sched *q, struct qfq_aggregate *agg, |
1285 | enum update_reason reason) | 1304 | enum update_reason reason) |
1286 | { | 1305 | { |
1306 | agg->initial_budget = agg->budget = agg->budgetmax; /* recharge budg. */ | ||
1307 | |||
1287 | qfq_update_agg_ts(q, agg, reason); | 1308 | qfq_update_agg_ts(q, agg, reason); |
1288 | qfq_schedule_agg(q, agg); | 1309 | if (q->in_serv_agg == NULL) { /* no aggr. in service or scheduled */ |
1310 | q->in_serv_agg = agg; /* start serving this aggregate */ | ||
1311 | /* update V: to be in service, agg must be eligible */ | ||
1312 | q->oldV = q->V = agg->S; | ||
1313 | } else if (agg != q->in_serv_agg) | ||
1314 | qfq_schedule_agg(q, agg); | ||
1289 | } | 1315 | } |
1290 | 1316 | ||
1291 | static void qfq_slot_remove(struct qfq_sched *q, struct qfq_group *grp, | 1317 | static void qfq_slot_remove(struct qfq_sched *q, struct qfq_group *grp, |
@@ -1357,8 +1383,6 @@ static void qfq_deactivate_agg(struct qfq_sched *q, struct qfq_aggregate *agg) | |||
1357 | __set_bit(grp->index, &q->bitmaps[s]); | 1383 | __set_bit(grp->index, &q->bitmaps[s]); |
1358 | } | 1384 | } |
1359 | } | 1385 | } |
1360 | |||
1361 | qfq_update_eligible(q); | ||
1362 | } | 1386 | } |
1363 | 1387 | ||
1364 | static void qfq_qlen_notify(struct Qdisc *sch, unsigned long arg) | 1388 | static void qfq_qlen_notify(struct Qdisc *sch, unsigned long arg) |
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 2b3ef03c6098..12ed45dbe75d 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c | |||
@@ -155,7 +155,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, | |||
155 | 155 | ||
156 | /* SCTP-AUTH extensions*/ | 156 | /* SCTP-AUTH extensions*/ |
157 | INIT_LIST_HEAD(&ep->endpoint_shared_keys); | 157 | INIT_LIST_HEAD(&ep->endpoint_shared_keys); |
158 | null_key = sctp_auth_shkey_create(0, GFP_KERNEL); | 158 | null_key = sctp_auth_shkey_create(0, gfp); |
159 | if (!null_key) | 159 | if (!null_key) |
160 | goto nomem; | 160 | goto nomem; |
161 | 161 | ||
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index c99458df3f3f..b9070736b8d9 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -5653,6 +5653,9 @@ static int sctp_getsockopt_assoc_stats(struct sock *sk, int len, | |||
5653 | if (len < sizeof(sctp_assoc_t)) | 5653 | if (len < sizeof(sctp_assoc_t)) |
5654 | return -EINVAL; | 5654 | return -EINVAL; |
5655 | 5655 | ||
5656 | /* Allow the struct to grow and fill in as much as possible */ | ||
5657 | len = min_t(size_t, len, sizeof(sas)); | ||
5658 | |||
5656 | if (copy_from_user(&sas, optval, len)) | 5659 | if (copy_from_user(&sas, optval, len)) |
5657 | return -EFAULT; | 5660 | return -EFAULT; |
5658 | 5661 | ||
@@ -5686,9 +5689,6 @@ static int sctp_getsockopt_assoc_stats(struct sock *sk, int len, | |||
5686 | /* Mark beginning of a new observation period */ | 5689 | /* Mark beginning of a new observation period */ |
5687 | asoc->stats.max_obs_rto = asoc->rto_min; | 5690 | asoc->stats.max_obs_rto = asoc->rto_min; |
5688 | 5691 | ||
5689 | /* Allow the struct to grow and fill in as much as possible */ | ||
5690 | len = min_t(size_t, len, sizeof(sas)); | ||
5691 | |||
5692 | if (put_user(len, optlen)) | 5692 | if (put_user(len, optlen)) |
5693 | return -EFAULT; | 5693 | return -EFAULT; |
5694 | 5694 | ||
diff --git a/net/sctp/ssnmap.c b/net/sctp/ssnmap.c index 442ad4ed6315..825ea94415b3 100644 --- a/net/sctp/ssnmap.c +++ b/net/sctp/ssnmap.c | |||
@@ -41,8 +41,6 @@ | |||
41 | #include <net/sctp/sctp.h> | 41 | #include <net/sctp/sctp.h> |
42 | #include <net/sctp/sm.h> | 42 | #include <net/sctp/sm.h> |
43 | 43 | ||
44 | #define MAX_KMALLOC_SIZE 131072 | ||
45 | |||
46 | static struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in, | 44 | static struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in, |
47 | __u16 out); | 45 | __u16 out); |
48 | 46 | ||
@@ -65,7 +63,7 @@ struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out, | |||
65 | int size; | 63 | int size; |
66 | 64 | ||
67 | size = sctp_ssnmap_size(in, out); | 65 | size = sctp_ssnmap_size(in, out); |
68 | if (size <= MAX_KMALLOC_SIZE) | 66 | if (size <= KMALLOC_MAX_SIZE) |
69 | retval = kmalloc(size, gfp); | 67 | retval = kmalloc(size, gfp); |
70 | else | 68 | else |
71 | retval = (struct sctp_ssnmap *) | 69 | retval = (struct sctp_ssnmap *) |
@@ -82,7 +80,7 @@ struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out, | |||
82 | return retval; | 80 | return retval; |
83 | 81 | ||
84 | fail_map: | 82 | fail_map: |
85 | if (size <= MAX_KMALLOC_SIZE) | 83 | if (size <= KMALLOC_MAX_SIZE) |
86 | kfree(retval); | 84 | kfree(retval); |
87 | else | 85 | else |
88 | free_pages((unsigned long)retval, get_order(size)); | 86 | free_pages((unsigned long)retval, get_order(size)); |
@@ -124,7 +122,7 @@ void sctp_ssnmap_free(struct sctp_ssnmap *map) | |||
124 | int size; | 122 | int size; |
125 | 123 | ||
126 | size = sctp_ssnmap_size(map->in.len, map->out.len); | 124 | size = sctp_ssnmap_size(map->in.len, map->out.len); |
127 | if (size <= MAX_KMALLOC_SIZE) | 125 | if (size <= KMALLOC_MAX_SIZE) |
128 | kfree(map); | 126 | kfree(map); |
129 | else | 127 | else |
130 | free_pages((unsigned long)map, get_order(size)); | 128 | free_pages((unsigned long)map, get_order(size)); |
diff --git a/net/sctp/tsnmap.c b/net/sctp/tsnmap.c index 5f25e0c92c31..396c45174e5b 100644 --- a/net/sctp/tsnmap.c +++ b/net/sctp/tsnmap.c | |||
@@ -51,7 +51,7 @@ | |||
51 | static void sctp_tsnmap_update(struct sctp_tsnmap *map); | 51 | static void sctp_tsnmap_update(struct sctp_tsnmap *map); |
52 | static void sctp_tsnmap_find_gap_ack(unsigned long *map, __u16 off, | 52 | static void sctp_tsnmap_find_gap_ack(unsigned long *map, __u16 off, |
53 | __u16 len, __u16 *start, __u16 *end); | 53 | __u16 len, __u16 *start, __u16 *end); |
54 | static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 gap); | 54 | static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 size); |
55 | 55 | ||
56 | /* Initialize a block of memory as a tsnmap. */ | 56 | /* Initialize a block of memory as a tsnmap. */ |
57 | struct sctp_tsnmap *sctp_tsnmap_init(struct sctp_tsnmap *map, __u16 len, | 57 | struct sctp_tsnmap *sctp_tsnmap_init(struct sctp_tsnmap *map, __u16 len, |
@@ -124,7 +124,7 @@ int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn, | |||
124 | 124 | ||
125 | gap = tsn - map->base_tsn; | 125 | gap = tsn - map->base_tsn; |
126 | 126 | ||
127 | if (gap >= map->len && !sctp_tsnmap_grow(map, gap)) | 127 | if (gap >= map->len && !sctp_tsnmap_grow(map, gap + 1)) |
128 | return -ENOMEM; | 128 | return -ENOMEM; |
129 | 129 | ||
130 | if (!sctp_tsnmap_has_gap(map) && gap == 0) { | 130 | if (!sctp_tsnmap_has_gap(map) && gap == 0) { |
@@ -360,23 +360,24 @@ __u16 sctp_tsnmap_num_gabs(struct sctp_tsnmap *map, | |||
360 | return ngaps; | 360 | return ngaps; |
361 | } | 361 | } |
362 | 362 | ||
363 | static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 gap) | 363 | static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 size) |
364 | { | 364 | { |
365 | unsigned long *new; | 365 | unsigned long *new; |
366 | unsigned long inc; | 366 | unsigned long inc; |
367 | u16 len; | 367 | u16 len; |
368 | 368 | ||
369 | if (gap >= SCTP_TSN_MAP_SIZE) | 369 | if (size > SCTP_TSN_MAP_SIZE) |
370 | return 0; | 370 | return 0; |
371 | 371 | ||
372 | inc = ALIGN((gap - map->len),BITS_PER_LONG) + SCTP_TSN_MAP_INCREMENT; | 372 | inc = ALIGN((size - map->len), BITS_PER_LONG) + SCTP_TSN_MAP_INCREMENT; |
373 | len = min_t(u16, map->len + inc, SCTP_TSN_MAP_SIZE); | 373 | len = min_t(u16, map->len + inc, SCTP_TSN_MAP_SIZE); |
374 | 374 | ||
375 | new = kzalloc(len>>3, GFP_ATOMIC); | 375 | new = kzalloc(len>>3, GFP_ATOMIC); |
376 | if (!new) | 376 | if (!new) |
377 | return 0; | 377 | return 0; |
378 | 378 | ||
379 | bitmap_copy(new, map->tsn_map, map->max_tsn_seen - map->base_tsn); | 379 | bitmap_copy(new, map->tsn_map, |
380 | map->max_tsn_seen - map->cumulative_tsn_ack_point); | ||
380 | kfree(map->tsn_map); | 381 | kfree(map->tsn_map); |
381 | map->tsn_map = new; | 382 | map->tsn_map = new; |
382 | map->len = len; | 383 | map->len = len; |
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index ada17464b65b..0fd5b3d2df03 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c | |||
@@ -106,6 +106,7 @@ int sctp_ulpq_tail_data(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk, | |||
106 | { | 106 | { |
107 | struct sk_buff_head temp; | 107 | struct sk_buff_head temp; |
108 | struct sctp_ulpevent *event; | 108 | struct sctp_ulpevent *event; |
109 | int event_eor = 0; | ||
109 | 110 | ||
110 | /* Create an event from the incoming chunk. */ | 111 | /* Create an event from the incoming chunk. */ |
111 | event = sctp_ulpevent_make_rcvmsg(chunk->asoc, chunk, gfp); | 112 | event = sctp_ulpevent_make_rcvmsg(chunk->asoc, chunk, gfp); |
@@ -127,10 +128,12 @@ int sctp_ulpq_tail_data(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk, | |||
127 | /* Send event to the ULP. 'event' is the sctp_ulpevent for | 128 | /* Send event to the ULP. 'event' is the sctp_ulpevent for |
128 | * very first SKB on the 'temp' list. | 129 | * very first SKB on the 'temp' list. |
129 | */ | 130 | */ |
130 | if (event) | 131 | if (event) { |
132 | event_eor = (event->msg_flags & MSG_EOR) ? 1 : 0; | ||
131 | sctp_ulpq_tail_event(ulpq, event); | 133 | sctp_ulpq_tail_event(ulpq, event); |
134 | } | ||
132 | 135 | ||
133 | return 0; | 136 | return event_eor; |
134 | } | 137 | } |
135 | 138 | ||
136 | /* Add a new event for propagation to the ULP. */ | 139 | /* Add a new event for propagation to the ULP. */ |
@@ -540,14 +543,19 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_partial(struct sctp_ulpq *ulpq) | |||
540 | ctsn = cevent->tsn; | 543 | ctsn = cevent->tsn; |
541 | 544 | ||
542 | switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) { | 545 | switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) { |
546 | case SCTP_DATA_FIRST_FRAG: | ||
547 | if (!first_frag) | ||
548 | return NULL; | ||
549 | goto done; | ||
543 | case SCTP_DATA_MIDDLE_FRAG: | 550 | case SCTP_DATA_MIDDLE_FRAG: |
544 | if (!first_frag) { | 551 | if (!first_frag) { |
545 | first_frag = pos; | 552 | first_frag = pos; |
546 | next_tsn = ctsn + 1; | 553 | next_tsn = ctsn + 1; |
547 | last_frag = pos; | 554 | last_frag = pos; |
548 | } else if (next_tsn == ctsn) | 555 | } else if (next_tsn == ctsn) { |
549 | next_tsn++; | 556 | next_tsn++; |
550 | else | 557 | last_frag = pos; |
558 | } else | ||
551 | goto done; | 559 | goto done; |
552 | break; | 560 | break; |
553 | case SCTP_DATA_LAST_FRAG: | 561 | case SCTP_DATA_LAST_FRAG: |
@@ -651,6 +659,14 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_first(struct sctp_ulpq *ulpq) | |||
651 | } else | 659 | } else |
652 | goto done; | 660 | goto done; |
653 | break; | 661 | break; |
662 | |||
663 | case SCTP_DATA_LAST_FRAG: | ||
664 | if (!first_frag) | ||
665 | return NULL; | ||
666 | else | ||
667 | goto done; | ||
668 | break; | ||
669 | |||
654 | default: | 670 | default: |
655 | return NULL; | 671 | return NULL; |
656 | } | 672 | } |
@@ -962,20 +978,43 @@ static __u16 sctp_ulpq_renege_list(struct sctp_ulpq *ulpq, | |||
962 | struct sk_buff_head *list, __u16 needed) | 978 | struct sk_buff_head *list, __u16 needed) |
963 | { | 979 | { |
964 | __u16 freed = 0; | 980 | __u16 freed = 0; |
965 | __u32 tsn; | 981 | __u32 tsn, last_tsn; |
966 | struct sk_buff *skb; | 982 | struct sk_buff *skb, *flist, *last; |
967 | struct sctp_ulpevent *event; | 983 | struct sctp_ulpevent *event; |
968 | struct sctp_tsnmap *tsnmap; | 984 | struct sctp_tsnmap *tsnmap; |
969 | 985 | ||
970 | tsnmap = &ulpq->asoc->peer.tsn_map; | 986 | tsnmap = &ulpq->asoc->peer.tsn_map; |
971 | 987 | ||
972 | while ((skb = __skb_dequeue_tail(list)) != NULL) { | 988 | while ((skb = skb_peek_tail(list)) != NULL) { |
973 | freed += skb_headlen(skb); | ||
974 | event = sctp_skb2event(skb); | 989 | event = sctp_skb2event(skb); |
975 | tsn = event->tsn; | 990 | tsn = event->tsn; |
976 | 991 | ||
992 | /* Don't renege below the Cumulative TSN ACK Point. */ | ||
993 | if (TSN_lte(tsn, sctp_tsnmap_get_ctsn(tsnmap))) | ||
994 | break; | ||
995 | |||
996 | /* Events in ordering queue may have multiple fragments | ||
997 | * corresponding to additional TSNs. Sum the total | ||
998 | * freed space; find the last TSN. | ||
999 | */ | ||
1000 | freed += skb_headlen(skb); | ||
1001 | flist = skb_shinfo(skb)->frag_list; | ||
1002 | for (last = flist; flist; flist = flist->next) { | ||
1003 | last = flist; | ||
1004 | freed += skb_headlen(last); | ||
1005 | } | ||
1006 | if (last) | ||
1007 | last_tsn = sctp_skb2event(last)->tsn; | ||
1008 | else | ||
1009 | last_tsn = tsn; | ||
1010 | |||
1011 | /* Unlink the event, then renege all applicable TSNs. */ | ||
1012 | __skb_unlink(skb, list); | ||
977 | sctp_ulpevent_free(event); | 1013 | sctp_ulpevent_free(event); |
978 | sctp_tsnmap_renege(tsnmap, tsn); | 1014 | while (TSN_lte(tsn, last_tsn)) { |
1015 | sctp_tsnmap_renege(tsnmap, tsn); | ||
1016 | tsn++; | ||
1017 | } | ||
979 | if (freed >= needed) | 1018 | if (freed >= needed) |
980 | return freed; | 1019 | return freed; |
981 | } | 1020 | } |
@@ -1002,16 +1041,28 @@ void sctp_ulpq_partial_delivery(struct sctp_ulpq *ulpq, | |||
1002 | struct sctp_ulpevent *event; | 1041 | struct sctp_ulpevent *event; |
1003 | struct sctp_association *asoc; | 1042 | struct sctp_association *asoc; |
1004 | struct sctp_sock *sp; | 1043 | struct sctp_sock *sp; |
1044 | __u32 ctsn; | ||
1045 | struct sk_buff *skb; | ||
1005 | 1046 | ||
1006 | asoc = ulpq->asoc; | 1047 | asoc = ulpq->asoc; |
1007 | sp = sctp_sk(asoc->base.sk); | 1048 | sp = sctp_sk(asoc->base.sk); |
1008 | 1049 | ||
1009 | /* If the association is already in Partial Delivery mode | 1050 | /* If the association is already in Partial Delivery mode |
1010 | * we have noting to do. | 1051 | * we have nothing to do. |
1011 | */ | 1052 | */ |
1012 | if (ulpq->pd_mode) | 1053 | if (ulpq->pd_mode) |
1013 | return; | 1054 | return; |
1014 | 1055 | ||
1056 | /* Data must be at or below the Cumulative TSN ACK Point to | ||
1057 | * start partial delivery. | ||
1058 | */ | ||
1059 | skb = skb_peek(&asoc->ulpq.reasm); | ||
1060 | if (skb != NULL) { | ||
1061 | ctsn = sctp_skb2event(skb)->tsn; | ||
1062 | if (!TSN_lte(ctsn, sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map))) | ||
1063 | return; | ||
1064 | } | ||
1065 | |||
1015 | /* If the user enabled fragment interleave socket option, | 1066 | /* If the user enabled fragment interleave socket option, |
1016 | * multiple associations can enter partial delivery. | 1067 | * multiple associations can enter partial delivery. |
1017 | * Otherwise, we can only enter partial delivery if the | 1068 | * Otherwise, we can only enter partial delivery if the |
@@ -1054,12 +1105,16 @@ void sctp_ulpq_renege(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk, | |||
1054 | } | 1105 | } |
1055 | /* If able to free enough room, accept this chunk. */ | 1106 | /* If able to free enough room, accept this chunk. */ |
1056 | if (chunk && (freed >= needed)) { | 1107 | if (chunk && (freed >= needed)) { |
1057 | __u32 tsn; | 1108 | int retval; |
1058 | tsn = ntohl(chunk->subh.data_hdr->tsn); | 1109 | retval = sctp_ulpq_tail_data(ulpq, chunk, gfp); |
1059 | sctp_tsnmap_mark(&asoc->peer.tsn_map, tsn, chunk->transport); | 1110 | /* |
1060 | sctp_ulpq_tail_data(ulpq, chunk, gfp); | 1111 | * Enter partial delivery if chunk has not been |
1061 | 1112 | * delivered; otherwise, drain the reassembly queue. | |
1062 | sctp_ulpq_partial_delivery(ulpq, gfp); | 1113 | */ |
1114 | if (retval <= 0) | ||
1115 | sctp_ulpq_partial_delivery(ulpq, gfp); | ||
1116 | else if (retval == 1) | ||
1117 | sctp_ulpq_reasm_drain(ulpq); | ||
1063 | } | 1118 | } |
1064 | 1119 | ||
1065 | sk_mem_reclaim(asoc->base.sk); | 1120 | sk_mem_reclaim(asoc->base.sk); |
diff --git a/net/wireless/ap.c b/net/wireless/ap.c index a4a14e8f55cc..324e8d851dc4 100644 --- a/net/wireless/ap.c +++ b/net/wireless/ap.c | |||
@@ -46,65 +46,3 @@ int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, | |||
46 | 46 | ||
47 | return err; | 47 | return err; |
48 | } | 48 | } |
49 | |||
50 | void cfg80211_ch_switch_notify(struct net_device *dev, | ||
51 | struct cfg80211_chan_def *chandef) | ||
52 | { | ||
53 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
54 | struct wiphy *wiphy = wdev->wiphy; | ||
55 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
56 | |||
57 | trace_cfg80211_ch_switch_notify(dev, chandef); | ||
58 | |||
59 | wdev_lock(wdev); | ||
60 | |||
61 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && | ||
62 | wdev->iftype != NL80211_IFTYPE_P2P_GO)) | ||
63 | goto out; | ||
64 | |||
65 | wdev->channel = chandef->chan; | ||
66 | nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL); | ||
67 | out: | ||
68 | wdev_unlock(wdev); | ||
69 | return; | ||
70 | } | ||
71 | EXPORT_SYMBOL(cfg80211_ch_switch_notify); | ||
72 | |||
73 | bool cfg80211_rx_spurious_frame(struct net_device *dev, | ||
74 | const u8 *addr, gfp_t gfp) | ||
75 | { | ||
76 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
77 | bool ret; | ||
78 | |||
79 | trace_cfg80211_rx_spurious_frame(dev, addr); | ||
80 | |||
81 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && | ||
82 | wdev->iftype != NL80211_IFTYPE_P2P_GO)) { | ||
83 | trace_cfg80211_return_bool(false); | ||
84 | return false; | ||
85 | } | ||
86 | ret = nl80211_unexpected_frame(dev, addr, gfp); | ||
87 | trace_cfg80211_return_bool(ret); | ||
88 | return ret; | ||
89 | } | ||
90 | EXPORT_SYMBOL(cfg80211_rx_spurious_frame); | ||
91 | |||
92 | bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, | ||
93 | const u8 *addr, gfp_t gfp) | ||
94 | { | ||
95 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
96 | bool ret; | ||
97 | |||
98 | trace_cfg80211_rx_unexpected_4addr_frame(dev, addr); | ||
99 | |||
100 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && | ||
101 | wdev->iftype != NL80211_IFTYPE_P2P_GO && | ||
102 | wdev->iftype != NL80211_IFTYPE_AP_VLAN)) { | ||
103 | trace_cfg80211_return_bool(false); | ||
104 | return false; | ||
105 | } | ||
106 | ret = nl80211_unexpected_4addr_frame(dev, addr, gfp); | ||
107 | trace_cfg80211_return_bool(ret); | ||
108 | return ret; | ||
109 | } | ||
110 | EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame); | ||
diff --git a/net/wireless/core.c b/net/wireless/core.c index 5ffff039b017..f382cae983ba 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -367,8 +367,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) | |||
367 | rdev->wiphy.rts_threshold = (u32) -1; | 367 | rdev->wiphy.rts_threshold = (u32) -1; |
368 | rdev->wiphy.coverage_class = 0; | 368 | rdev->wiphy.coverage_class = 0; |
369 | 369 | ||
370 | rdev->wiphy.features = NL80211_FEATURE_SCAN_FLUSH | | 370 | rdev->wiphy.features = NL80211_FEATURE_SCAN_FLUSH; |
371 | NL80211_FEATURE_ADVERTISE_CHAN_LIMITS; | ||
372 | 371 | ||
373 | return &rdev->wiphy; | 372 | return &rdev->wiphy; |
374 | } | 373 | } |
@@ -815,6 +814,46 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, | |||
815 | rdev->num_running_monitor_ifaces += num; | 814 | rdev->num_running_monitor_ifaces += num; |
816 | } | 815 | } |
817 | 816 | ||
817 | void cfg80211_leave(struct cfg80211_registered_device *rdev, | ||
818 | struct wireless_dev *wdev) | ||
819 | { | ||
820 | struct net_device *dev = wdev->netdev; | ||
821 | |||
822 | switch (wdev->iftype) { | ||
823 | case NL80211_IFTYPE_ADHOC: | ||
824 | cfg80211_leave_ibss(rdev, dev, true); | ||
825 | break; | ||
826 | case NL80211_IFTYPE_P2P_CLIENT: | ||
827 | case NL80211_IFTYPE_STATION: | ||
828 | mutex_lock(&rdev->sched_scan_mtx); | ||
829 | __cfg80211_stop_sched_scan(rdev, false); | ||
830 | mutex_unlock(&rdev->sched_scan_mtx); | ||
831 | |||
832 | wdev_lock(wdev); | ||
833 | #ifdef CONFIG_CFG80211_WEXT | ||
834 | kfree(wdev->wext.ie); | ||
835 | wdev->wext.ie = NULL; | ||
836 | wdev->wext.ie_len = 0; | ||
837 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; | ||
838 | #endif | ||
839 | __cfg80211_disconnect(rdev, dev, | ||
840 | WLAN_REASON_DEAUTH_LEAVING, true); | ||
841 | cfg80211_mlme_down(rdev, dev); | ||
842 | wdev_unlock(wdev); | ||
843 | break; | ||
844 | case NL80211_IFTYPE_MESH_POINT: | ||
845 | cfg80211_leave_mesh(rdev, dev); | ||
846 | break; | ||
847 | case NL80211_IFTYPE_AP: | ||
848 | cfg80211_stop_ap(rdev, dev); | ||
849 | break; | ||
850 | default: | ||
851 | break; | ||
852 | } | ||
853 | |||
854 | wdev->beacon_interval = 0; | ||
855 | } | ||
856 | |||
818 | static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | 857 | static int cfg80211_netdev_notifier_call(struct notifier_block *nb, |
819 | unsigned long state, | 858 | unsigned long state, |
820 | void *ndev) | 859 | void *ndev) |
@@ -883,38 +922,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
883 | dev->priv_flags |= IFF_DONT_BRIDGE; | 922 | dev->priv_flags |= IFF_DONT_BRIDGE; |
884 | break; | 923 | break; |
885 | case NETDEV_GOING_DOWN: | 924 | case NETDEV_GOING_DOWN: |
886 | switch (wdev->iftype) { | 925 | cfg80211_leave(rdev, wdev); |
887 | case NL80211_IFTYPE_ADHOC: | ||
888 | cfg80211_leave_ibss(rdev, dev, true); | ||
889 | break; | ||
890 | case NL80211_IFTYPE_P2P_CLIENT: | ||
891 | case NL80211_IFTYPE_STATION: | ||
892 | mutex_lock(&rdev->sched_scan_mtx); | ||
893 | __cfg80211_stop_sched_scan(rdev, false); | ||
894 | mutex_unlock(&rdev->sched_scan_mtx); | ||
895 | |||
896 | wdev_lock(wdev); | ||
897 | #ifdef CONFIG_CFG80211_WEXT | ||
898 | kfree(wdev->wext.ie); | ||
899 | wdev->wext.ie = NULL; | ||
900 | wdev->wext.ie_len = 0; | ||
901 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; | ||
902 | #endif | ||
903 | __cfg80211_disconnect(rdev, dev, | ||
904 | WLAN_REASON_DEAUTH_LEAVING, true); | ||
905 | cfg80211_mlme_down(rdev, dev); | ||
906 | wdev_unlock(wdev); | ||
907 | break; | ||
908 | case NL80211_IFTYPE_MESH_POINT: | ||
909 | cfg80211_leave_mesh(rdev, dev); | ||
910 | break; | ||
911 | case NL80211_IFTYPE_AP: | ||
912 | cfg80211_stop_ap(rdev, dev); | ||
913 | break; | ||
914 | default: | ||
915 | break; | ||
916 | } | ||
917 | wdev->beacon_interval = 0; | ||
918 | break; | 926 | break; |
919 | case NETDEV_DOWN: | 927 | case NETDEV_DOWN: |
920 | cfg80211_update_iface_num(rdev, wdev->iftype, -1); | 928 | cfg80211_update_iface_num(rdev, wdev->iftype, -1); |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 3aec0e429d8a..d5d06fdea961 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -330,20 +330,15 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
330 | int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | 330 | int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, |
331 | struct net_device *dev, | 331 | struct net_device *dev, |
332 | struct ieee80211_channel *chan, | 332 | struct ieee80211_channel *chan, |
333 | const u8 *bssid, const u8 *prev_bssid, | 333 | const u8 *bssid, |
334 | const u8 *ssid, int ssid_len, | 334 | const u8 *ssid, int ssid_len, |
335 | const u8 *ie, int ie_len, bool use_mfp, | 335 | struct cfg80211_assoc_request *req); |
336 | struct cfg80211_crypto_settings *crypt, | ||
337 | u32 assoc_flags, struct ieee80211_ht_cap *ht_capa, | ||
338 | struct ieee80211_ht_cap *ht_capa_mask); | ||
339 | int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | 336 | int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, |
340 | struct net_device *dev, struct ieee80211_channel *chan, | 337 | struct net_device *dev, |
341 | const u8 *bssid, const u8 *prev_bssid, | 338 | struct ieee80211_channel *chan, |
339 | const u8 *bssid, | ||
342 | const u8 *ssid, int ssid_len, | 340 | const u8 *ssid, int ssid_len, |
343 | const u8 *ie, int ie_len, bool use_mfp, | 341 | struct cfg80211_assoc_request *req); |
344 | struct cfg80211_crypto_settings *crypt, | ||
345 | u32 assoc_flags, struct ieee80211_ht_cap *ht_capa, | ||
346 | struct ieee80211_ht_cap *ht_capa_mask); | ||
347 | int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | 342 | int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, |
348 | struct net_device *dev, const u8 *bssid, | 343 | struct net_device *dev, const u8 *bssid, |
349 | const u8 *ie, int ie_len, u16 reason, | 344 | const u8 *ie, int ie_len, u16 reason, |
@@ -375,6 +370,8 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | |||
375 | bool no_cck, bool dont_wait_for_ack, u64 *cookie); | 370 | bool no_cck, bool dont_wait_for_ack, u64 *cookie); |
376 | void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa, | 371 | void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa, |
377 | const struct ieee80211_ht_cap *ht_capa_mask); | 372 | const struct ieee80211_ht_cap *ht_capa_mask); |
373 | void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa, | ||
374 | const struct ieee80211_vht_cap *vht_capa_mask); | ||
378 | 375 | ||
379 | /* SME */ | 376 | /* SME */ |
380 | int __cfg80211_connect(struct cfg80211_registered_device *rdev, | 377 | int __cfg80211_connect(struct cfg80211_registered_device *rdev, |
@@ -503,6 +500,9 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, | |||
503 | void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, | 500 | void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, |
504 | enum nl80211_iftype iftype, int num); | 501 | enum nl80211_iftype iftype, int num); |
505 | 502 | ||
503 | void cfg80211_leave(struct cfg80211_registered_device *rdev, | ||
504 | struct wireless_dev *wdev); | ||
505 | |||
506 | #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10 | 506 | #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10 |
507 | 507 | ||
508 | #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS | 508 | #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS |
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 55957a284f6c..0bb93f3061a4 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c | |||
@@ -85,6 +85,7 @@ const struct mesh_setup default_mesh_setup = { | |||
85 | .ie = NULL, | 85 | .ie = NULL, |
86 | .ie_len = 0, | 86 | .ie_len = 0, |
87 | .is_secure = false, | 87 | .is_secure = false, |
88 | .user_mpm = false, | ||
88 | .beacon_interval = MESH_DEFAULT_BEACON_INTERVAL, | 89 | .beacon_interval = MESH_DEFAULT_BEACON_INTERVAL, |
89 | .dtim_period = MESH_DEFAULT_DTIM_PERIOD, | 90 | .dtim_period = MESH_DEFAULT_DTIM_PERIOD, |
90 | }; | 91 | }; |
@@ -233,20 +234,6 @@ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev, | |||
233 | return 0; | 234 | return 0; |
234 | } | 235 | } |
235 | 236 | ||
236 | void cfg80211_notify_new_peer_candidate(struct net_device *dev, | ||
237 | const u8 *macaddr, const u8* ie, u8 ie_len, gfp_t gfp) | ||
238 | { | ||
239 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
240 | |||
241 | trace_cfg80211_notify_new_peer_candidate(dev, macaddr); | ||
242 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT)) | ||
243 | return; | ||
244 | |||
245 | nl80211_send_new_peer_candidate(wiphy_to_dev(wdev->wiphy), dev, | ||
246 | macaddr, ie, ie_len, gfp); | ||
247 | } | ||
248 | EXPORT_SYMBOL(cfg80211_notify_new_peer_candidate); | ||
249 | |||
250 | static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, | 237 | static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, |
251 | struct net_device *dev) | 238 | struct net_device *dev) |
252 | { | 239 | { |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index caddca35d686..390198bf4b36 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -187,30 +187,6 @@ void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len) | |||
187 | } | 187 | } |
188 | EXPORT_SYMBOL(cfg80211_send_disassoc); | 188 | EXPORT_SYMBOL(cfg80211_send_disassoc); |
189 | 189 | ||
190 | void cfg80211_send_unprot_deauth(struct net_device *dev, const u8 *buf, | ||
191 | size_t len) | ||
192 | { | ||
193 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
194 | struct wiphy *wiphy = wdev->wiphy; | ||
195 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
196 | |||
197 | trace_cfg80211_send_unprot_deauth(dev); | ||
198 | nl80211_send_unprot_deauth(rdev, dev, buf, len, GFP_ATOMIC); | ||
199 | } | ||
200 | EXPORT_SYMBOL(cfg80211_send_unprot_deauth); | ||
201 | |||
202 | void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf, | ||
203 | size_t len) | ||
204 | { | ||
205 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
206 | struct wiphy *wiphy = wdev->wiphy; | ||
207 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
208 | |||
209 | trace_cfg80211_send_unprot_disassoc(dev); | ||
210 | nl80211_send_unprot_disassoc(rdev, dev, buf, len, GFP_ATOMIC); | ||
211 | } | ||
212 | EXPORT_SYMBOL(cfg80211_send_unprot_disassoc); | ||
213 | |||
214 | void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) | 190 | void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) |
215 | { | 191 | { |
216 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 192 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
@@ -367,27 +343,38 @@ void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa, | |||
367 | p1[i] &= p2[i]; | 343 | p1[i] &= p2[i]; |
368 | } | 344 | } |
369 | 345 | ||
346 | /* Do a logical ht_capa &= ht_capa_mask. */ | ||
347 | void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa, | ||
348 | const struct ieee80211_vht_cap *vht_capa_mask) | ||
349 | { | ||
350 | int i; | ||
351 | u8 *p1, *p2; | ||
352 | if (!vht_capa_mask) { | ||
353 | memset(vht_capa, 0, sizeof(*vht_capa)); | ||
354 | return; | ||
355 | } | ||
356 | |||
357 | p1 = (u8*)(vht_capa); | ||
358 | p2 = (u8*)(vht_capa_mask); | ||
359 | for (i = 0; i < sizeof(*vht_capa); i++) | ||
360 | p1[i] &= p2[i]; | ||
361 | } | ||
362 | |||
370 | int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | 363 | int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, |
371 | struct net_device *dev, | 364 | struct net_device *dev, |
372 | struct ieee80211_channel *chan, | 365 | struct ieee80211_channel *chan, |
373 | const u8 *bssid, const u8 *prev_bssid, | 366 | const u8 *bssid, |
374 | const u8 *ssid, int ssid_len, | 367 | const u8 *ssid, int ssid_len, |
375 | const u8 *ie, int ie_len, bool use_mfp, | 368 | struct cfg80211_assoc_request *req) |
376 | struct cfg80211_crypto_settings *crypt, | ||
377 | u32 assoc_flags, struct ieee80211_ht_cap *ht_capa, | ||
378 | struct ieee80211_ht_cap *ht_capa_mask) | ||
379 | { | 369 | { |
380 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 370 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
381 | struct cfg80211_assoc_request req; | ||
382 | int err; | 371 | int err; |
383 | bool was_connected = false; | 372 | bool was_connected = false; |
384 | 373 | ||
385 | ASSERT_WDEV_LOCK(wdev); | 374 | ASSERT_WDEV_LOCK(wdev); |
386 | 375 | ||
387 | memset(&req, 0, sizeof(req)); | 376 | if (wdev->current_bss && req->prev_bssid && |
388 | 377 | ether_addr_equal(wdev->current_bss->pub.bssid, req->prev_bssid)) { | |
389 | if (wdev->current_bss && prev_bssid && | ||
390 | ether_addr_equal(wdev->current_bss->pub.bssid, prev_bssid)) { | ||
391 | /* | 378 | /* |
392 | * Trying to reassociate: Allow this to proceed and let the old | 379 | * Trying to reassociate: Allow this to proceed and let the old |
393 | * association to be dropped when the new one is completed. | 380 | * association to be dropped when the new one is completed. |
@@ -399,40 +386,30 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | |||
399 | } else if (wdev->current_bss) | 386 | } else if (wdev->current_bss) |
400 | return -EALREADY; | 387 | return -EALREADY; |
401 | 388 | ||
402 | req.ie = ie; | 389 | cfg80211_oper_and_ht_capa(&req->ht_capa_mask, |
403 | req.ie_len = ie_len; | ||
404 | memcpy(&req.crypto, crypt, sizeof(req.crypto)); | ||
405 | req.use_mfp = use_mfp; | ||
406 | req.prev_bssid = prev_bssid; | ||
407 | req.flags = assoc_flags; | ||
408 | if (ht_capa) | ||
409 | memcpy(&req.ht_capa, ht_capa, sizeof(req.ht_capa)); | ||
410 | if (ht_capa_mask) | ||
411 | memcpy(&req.ht_capa_mask, ht_capa_mask, | ||
412 | sizeof(req.ht_capa_mask)); | ||
413 | cfg80211_oper_and_ht_capa(&req.ht_capa_mask, | ||
414 | rdev->wiphy.ht_capa_mod_mask); | 390 | rdev->wiphy.ht_capa_mod_mask); |
391 | cfg80211_oper_and_vht_capa(&req->vht_capa_mask, | ||
392 | rdev->wiphy.vht_capa_mod_mask); | ||
415 | 393 | ||
416 | req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, | 394 | req->bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, |
417 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); | 395 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); |
418 | if (!req.bss) { | 396 | if (!req->bss) { |
419 | if (was_connected) | 397 | if (was_connected) |
420 | wdev->sme_state = CFG80211_SME_CONNECTED; | 398 | wdev->sme_state = CFG80211_SME_CONNECTED; |
421 | return -ENOENT; | 399 | return -ENOENT; |
422 | } | 400 | } |
423 | 401 | ||
424 | err = cfg80211_can_use_chan(rdev, wdev, req.bss->channel, | 402 | err = cfg80211_can_use_chan(rdev, wdev, chan, CHAN_MODE_SHARED); |
425 | CHAN_MODE_SHARED); | ||
426 | if (err) | 403 | if (err) |
427 | goto out; | 404 | goto out; |
428 | 405 | ||
429 | err = rdev_assoc(rdev, dev, &req); | 406 | err = rdev_assoc(rdev, dev, req); |
430 | 407 | ||
431 | out: | 408 | out: |
432 | if (err) { | 409 | if (err) { |
433 | if (was_connected) | 410 | if (was_connected) |
434 | wdev->sme_state = CFG80211_SME_CONNECTED; | 411 | wdev->sme_state = CFG80211_SME_CONNECTED; |
435 | cfg80211_put_bss(&rdev->wiphy, req.bss); | 412 | cfg80211_put_bss(&rdev->wiphy, req->bss); |
436 | } | 413 | } |
437 | 414 | ||
438 | return err; | 415 | return err; |
@@ -441,21 +418,17 @@ out: | |||
441 | int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | 418 | int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, |
442 | struct net_device *dev, | 419 | struct net_device *dev, |
443 | struct ieee80211_channel *chan, | 420 | struct ieee80211_channel *chan, |
444 | const u8 *bssid, const u8 *prev_bssid, | 421 | const u8 *bssid, |
445 | const u8 *ssid, int ssid_len, | 422 | const u8 *ssid, int ssid_len, |
446 | const u8 *ie, int ie_len, bool use_mfp, | 423 | struct cfg80211_assoc_request *req) |
447 | struct cfg80211_crypto_settings *crypt, | ||
448 | u32 assoc_flags, struct ieee80211_ht_cap *ht_capa, | ||
449 | struct ieee80211_ht_cap *ht_capa_mask) | ||
450 | { | 424 | { |
451 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 425 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
452 | int err; | 426 | int err; |
453 | 427 | ||
454 | mutex_lock(&rdev->devlist_mtx); | 428 | mutex_lock(&rdev->devlist_mtx); |
455 | wdev_lock(wdev); | 429 | wdev_lock(wdev); |
456 | err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid, | 430 | err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, |
457 | ssid, ssid_len, ie, ie_len, use_mfp, crypt, | 431 | ssid, ssid_len, req); |
458 | assoc_flags, ht_capa, ht_capa_mask); | ||
459 | wdev_unlock(wdev); | 432 | wdev_unlock(wdev); |
460 | mutex_unlock(&rdev->devlist_mtx); | 433 | mutex_unlock(&rdev->devlist_mtx); |
461 | 434 | ||
@@ -577,62 +550,6 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, | |||
577 | } | 550 | } |
578 | } | 551 | } |
579 | 552 | ||
580 | void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie, | ||
581 | struct ieee80211_channel *chan, | ||
582 | unsigned int duration, gfp_t gfp) | ||
583 | { | ||
584 | struct wiphy *wiphy = wdev->wiphy; | ||
585 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
586 | |||
587 | trace_cfg80211_ready_on_channel(wdev, cookie, chan, duration); | ||
588 | nl80211_send_remain_on_channel(rdev, wdev, cookie, chan, duration, gfp); | ||
589 | } | ||
590 | EXPORT_SYMBOL(cfg80211_ready_on_channel); | ||
591 | |||
592 | void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie, | ||
593 | struct ieee80211_channel *chan, | ||
594 | gfp_t gfp) | ||
595 | { | ||
596 | struct wiphy *wiphy = wdev->wiphy; | ||
597 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
598 | |||
599 | trace_cfg80211_ready_on_channel_expired(wdev, cookie, chan); | ||
600 | nl80211_send_remain_on_channel_cancel(rdev, wdev, cookie, chan, gfp); | ||
601 | } | ||
602 | EXPORT_SYMBOL(cfg80211_remain_on_channel_expired); | ||
603 | |||
604 | void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, | ||
605 | struct station_info *sinfo, gfp_t gfp) | ||
606 | { | ||
607 | struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; | ||
608 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
609 | |||
610 | trace_cfg80211_new_sta(dev, mac_addr, sinfo); | ||
611 | nl80211_send_sta_event(rdev, dev, mac_addr, sinfo, gfp); | ||
612 | } | ||
613 | EXPORT_SYMBOL(cfg80211_new_sta); | ||
614 | |||
615 | void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp) | ||
616 | { | ||
617 | struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; | ||
618 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
619 | |||
620 | trace_cfg80211_del_sta(dev, mac_addr); | ||
621 | nl80211_send_sta_del_event(rdev, dev, mac_addr, gfp); | ||
622 | } | ||
623 | EXPORT_SYMBOL(cfg80211_del_sta); | ||
624 | |||
625 | void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr, | ||
626 | enum nl80211_connect_failed_reason reason, | ||
627 | gfp_t gfp) | ||
628 | { | ||
629 | struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; | ||
630 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
631 | |||
632 | nl80211_send_conn_failed_event(rdev, dev, mac_addr, reason, gfp); | ||
633 | } | ||
634 | EXPORT_SYMBOL(cfg80211_conn_failed); | ||
635 | |||
636 | struct cfg80211_mgmt_registration { | 553 | struct cfg80211_mgmt_registration { |
637 | struct list_head list; | 554 | struct list_head list; |
638 | 555 | ||
@@ -909,85 +826,6 @@ bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm, | |||
909 | } | 826 | } |
910 | EXPORT_SYMBOL(cfg80211_rx_mgmt); | 827 | EXPORT_SYMBOL(cfg80211_rx_mgmt); |
911 | 828 | ||
912 | void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie, | ||
913 | const u8 *buf, size_t len, bool ack, gfp_t gfp) | ||
914 | { | ||
915 | struct wiphy *wiphy = wdev->wiphy; | ||
916 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
917 | |||
918 | trace_cfg80211_mgmt_tx_status(wdev, cookie, ack); | ||
919 | |||
920 | /* Indicate TX status of the Action frame to user space */ | ||
921 | nl80211_send_mgmt_tx_status(rdev, wdev, cookie, buf, len, ack, gfp); | ||
922 | } | ||
923 | EXPORT_SYMBOL(cfg80211_mgmt_tx_status); | ||
924 | |||
925 | void cfg80211_cqm_rssi_notify(struct net_device *dev, | ||
926 | enum nl80211_cqm_rssi_threshold_event rssi_event, | ||
927 | gfp_t gfp) | ||
928 | { | ||
929 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
930 | struct wiphy *wiphy = wdev->wiphy; | ||
931 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
932 | |||
933 | trace_cfg80211_cqm_rssi_notify(dev, rssi_event); | ||
934 | |||
935 | /* Indicate roaming trigger event to user space */ | ||
936 | nl80211_send_cqm_rssi_notify(rdev, dev, rssi_event, gfp); | ||
937 | } | ||
938 | EXPORT_SYMBOL(cfg80211_cqm_rssi_notify); | ||
939 | |||
940 | void cfg80211_cqm_pktloss_notify(struct net_device *dev, | ||
941 | const u8 *peer, u32 num_packets, gfp_t gfp) | ||
942 | { | ||
943 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
944 | struct wiphy *wiphy = wdev->wiphy; | ||
945 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
946 | |||
947 | trace_cfg80211_cqm_pktloss_notify(dev, peer, num_packets); | ||
948 | |||
949 | /* Indicate roaming trigger event to user space */ | ||
950 | nl80211_send_cqm_pktloss_notify(rdev, dev, peer, num_packets, gfp); | ||
951 | } | ||
952 | EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify); | ||
953 | |||
954 | void cfg80211_cqm_txe_notify(struct net_device *dev, | ||
955 | const u8 *peer, u32 num_packets, | ||
956 | u32 rate, u32 intvl, gfp_t gfp) | ||
957 | { | ||
958 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
959 | struct wiphy *wiphy = wdev->wiphy; | ||
960 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
961 | |||
962 | nl80211_send_cqm_txe_notify(rdev, dev, peer, num_packets, | ||
963 | rate, intvl, gfp); | ||
964 | } | ||
965 | EXPORT_SYMBOL(cfg80211_cqm_txe_notify); | ||
966 | |||
967 | void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid, | ||
968 | const u8 *replay_ctr, gfp_t gfp) | ||
969 | { | ||
970 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
971 | struct wiphy *wiphy = wdev->wiphy; | ||
972 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
973 | |||
974 | trace_cfg80211_gtk_rekey_notify(dev, bssid); | ||
975 | nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp); | ||
976 | } | ||
977 | EXPORT_SYMBOL(cfg80211_gtk_rekey_notify); | ||
978 | |||
979 | void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index, | ||
980 | const u8 *bssid, bool preauth, gfp_t gfp) | ||
981 | { | ||
982 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
983 | struct wiphy *wiphy = wdev->wiphy; | ||
984 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
985 | |||
986 | trace_cfg80211_pmksa_candidate_notify(dev, index, bssid, preauth); | ||
987 | nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp); | ||
988 | } | ||
989 | EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify); | ||
990 | |||
991 | void cfg80211_dfs_channels_update_work(struct work_struct *work) | 829 | void cfg80211_dfs_channels_update_work(struct work_struct *work) |
992 | { | 830 | { |
993 | struct delayed_work *delayed_work; | 831 | struct delayed_work *delayed_work; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 35545ccc30fd..f924d45af1b8 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -370,6 +370,14 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
370 | [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED }, | 370 | [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED }, |
371 | [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 }, | 371 | [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 }, |
372 | [NL80211_ATTR_STA_EXT_CAPABILITY] = { .type = NLA_BINARY, }, | 372 | [NL80211_ATTR_STA_EXT_CAPABILITY] = { .type = NLA_BINARY, }, |
373 | [NL80211_ATTR_SPLIT_WIPHY_DUMP] = { .type = NLA_FLAG, }, | ||
374 | [NL80211_ATTR_DISABLE_VHT] = { .type = NLA_FLAG }, | ||
375 | [NL80211_ATTR_VHT_CAPABILITY_MASK] = { | ||
376 | .len = NL80211_VHT_CAPABILITY_LEN, | ||
377 | }, | ||
378 | [NL80211_ATTR_MDID] = { .type = NLA_U16 }, | ||
379 | [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY, | ||
380 | .len = IEEE80211_MAX_DATA_LEN }, | ||
373 | }; | 381 | }; |
374 | 382 | ||
375 | /* policy for the key attributes */ | 383 | /* policy for the key attributes */ |
@@ -539,7 +547,8 @@ static inline void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq, | |||
539 | } | 547 | } |
540 | 548 | ||
541 | static int nl80211_msg_put_channel(struct sk_buff *msg, | 549 | static int nl80211_msg_put_channel(struct sk_buff *msg, |
542 | struct ieee80211_channel *chan) | 550 | struct ieee80211_channel *chan, |
551 | bool large) | ||
543 | { | 552 | { |
544 | if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_FREQ, | 553 | if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_FREQ, |
545 | chan->center_freq)) | 554 | chan->center_freq)) |
@@ -555,27 +564,36 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, | |||
555 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS)) | 564 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS)) |
556 | goto nla_put_failure; | 565 | goto nla_put_failure; |
557 | if (chan->flags & IEEE80211_CHAN_RADAR) { | 566 | if (chan->flags & IEEE80211_CHAN_RADAR) { |
558 | u32 time = elapsed_jiffies_msecs(chan->dfs_state_entered); | ||
559 | if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR)) | 567 | if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR)) |
560 | goto nla_put_failure; | 568 | goto nla_put_failure; |
561 | if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_STATE, | 569 | if (large) { |
562 | chan->dfs_state)) | 570 | u32 time; |
571 | |||
572 | time = elapsed_jiffies_msecs(chan->dfs_state_entered); | ||
573 | |||
574 | if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_STATE, | ||
575 | chan->dfs_state)) | ||
576 | goto nla_put_failure; | ||
577 | if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME, | ||
578 | time)) | ||
579 | goto nla_put_failure; | ||
580 | } | ||
581 | } | ||
582 | |||
583 | if (large) { | ||
584 | if ((chan->flags & IEEE80211_CHAN_NO_HT40MINUS) && | ||
585 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_MINUS)) | ||
586 | goto nla_put_failure; | ||
587 | if ((chan->flags & IEEE80211_CHAN_NO_HT40PLUS) && | ||
588 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_PLUS)) | ||
589 | goto nla_put_failure; | ||
590 | if ((chan->flags & IEEE80211_CHAN_NO_80MHZ) && | ||
591 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_80MHZ)) | ||
563 | goto nla_put_failure; | 592 | goto nla_put_failure; |
564 | if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME, time)) | 593 | if ((chan->flags & IEEE80211_CHAN_NO_160MHZ) && |
594 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_160MHZ)) | ||
565 | goto nla_put_failure; | 595 | goto nla_put_failure; |
566 | } | 596 | } |
567 | if ((chan->flags & IEEE80211_CHAN_NO_HT40MINUS) && | ||
568 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_MINUS)) | ||
569 | goto nla_put_failure; | ||
570 | if ((chan->flags & IEEE80211_CHAN_NO_HT40PLUS) && | ||
571 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_PLUS)) | ||
572 | goto nla_put_failure; | ||
573 | if ((chan->flags & IEEE80211_CHAN_NO_80MHZ) && | ||
574 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_80MHZ)) | ||
575 | goto nla_put_failure; | ||
576 | if ((chan->flags & IEEE80211_CHAN_NO_160MHZ) && | ||
577 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_160MHZ)) | ||
578 | goto nla_put_failure; | ||
579 | 597 | ||
580 | if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER, | 598 | if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER, |
581 | DBM_TO_MBM(chan->max_power))) | 599 | DBM_TO_MBM(chan->max_power))) |
@@ -851,7 +869,8 @@ nla_put_failure: | |||
851 | } | 869 | } |
852 | 870 | ||
853 | static int nl80211_put_iface_combinations(struct wiphy *wiphy, | 871 | static int nl80211_put_iface_combinations(struct wiphy *wiphy, |
854 | struct sk_buff *msg) | 872 | struct sk_buff *msg, |
873 | bool large) | ||
855 | { | 874 | { |
856 | struct nlattr *nl_combis; | 875 | struct nlattr *nl_combis; |
857 | int i, j; | 876 | int i, j; |
@@ -900,7 +919,8 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy, | |||
900 | nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM, | 919 | nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM, |
901 | c->max_interfaces)) | 920 | c->max_interfaces)) |
902 | goto nla_put_failure; | 921 | goto nla_put_failure; |
903 | if (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, | 922 | if (large && |
923 | nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, | ||
904 | c->radar_detect_widths)) | 924 | c->radar_detect_widths)) |
905 | goto nla_put_failure; | 925 | goto nla_put_failure; |
906 | 926 | ||
@@ -954,426 +974,571 @@ static int nl80211_send_wowlan_tcp_caps(struct cfg80211_registered_device *rdev, | |||
954 | nla_nest_end(msg, nl_tcp); | 974 | nla_nest_end(msg, nl_tcp); |
955 | return 0; | 975 | return 0; |
956 | } | 976 | } |
957 | #endif | ||
958 | 977 | ||
959 | static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flags, | 978 | static int nl80211_send_wowlan(struct sk_buff *msg, |
960 | struct cfg80211_registered_device *dev) | 979 | struct cfg80211_registered_device *dev, |
980 | bool large) | ||
961 | { | 981 | { |
962 | void *hdr; | 982 | struct nlattr *nl_wowlan; |
963 | struct nlattr *nl_bands, *nl_band; | ||
964 | struct nlattr *nl_freqs, *nl_freq; | ||
965 | struct nlattr *nl_rates, *nl_rate; | ||
966 | struct nlattr *nl_cmds; | ||
967 | enum ieee80211_band band; | ||
968 | struct ieee80211_channel *chan; | ||
969 | struct ieee80211_rate *rate; | ||
970 | int i; | ||
971 | const struct ieee80211_txrx_stypes *mgmt_stypes = | ||
972 | dev->wiphy.mgmt_stypes; | ||
973 | 983 | ||
974 | hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_WIPHY); | 984 | if (!dev->wiphy.wowlan.flags && !dev->wiphy.wowlan.n_patterns) |
975 | if (!hdr) | 985 | return 0; |
976 | return -1; | ||
977 | 986 | ||
978 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx) || | 987 | nl_wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED); |
979 | nla_put_string(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)) || | 988 | if (!nl_wowlan) |
980 | nla_put_u32(msg, NL80211_ATTR_GENERATION, | 989 | return -ENOBUFS; |
981 | cfg80211_rdev_list_generation) || | ||
982 | nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT, | ||
983 | dev->wiphy.retry_short) || | ||
984 | nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_LONG, | ||
985 | dev->wiphy.retry_long) || | ||
986 | nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, | ||
987 | dev->wiphy.frag_threshold) || | ||
988 | nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, | ||
989 | dev->wiphy.rts_threshold) || | ||
990 | nla_put_u8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, | ||
991 | dev->wiphy.coverage_class) || | ||
992 | nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, | ||
993 | dev->wiphy.max_scan_ssids) || | ||
994 | nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS, | ||
995 | dev->wiphy.max_sched_scan_ssids) || | ||
996 | nla_put_u16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, | ||
997 | dev->wiphy.max_scan_ie_len) || | ||
998 | nla_put_u16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN, | ||
999 | dev->wiphy.max_sched_scan_ie_len) || | ||
1000 | nla_put_u8(msg, NL80211_ATTR_MAX_MATCH_SETS, | ||
1001 | dev->wiphy.max_match_sets)) | ||
1002 | goto nla_put_failure; | ||
1003 | 990 | ||
1004 | if ((dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) && | 991 | if (((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_ANY) && |
1005 | nla_put_flag(msg, NL80211_ATTR_SUPPORT_IBSS_RSN)) | 992 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) || |
1006 | goto nla_put_failure; | 993 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_DISCONNECT) && |
1007 | if ((dev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) && | 994 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) || |
1008 | nla_put_flag(msg, NL80211_ATTR_SUPPORT_MESH_AUTH)) | 995 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_MAGIC_PKT) && |
1009 | goto nla_put_failure; | 996 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) || |
1010 | if ((dev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) && | 997 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) && |
1011 | nla_put_flag(msg, NL80211_ATTR_SUPPORT_AP_UAPSD)) | 998 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED)) || |
1012 | goto nla_put_failure; | 999 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) && |
1013 | if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) && | 1000 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) || |
1014 | nla_put_flag(msg, NL80211_ATTR_ROAM_SUPPORT)) | 1001 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) && |
1015 | goto nla_put_failure; | 1002 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) || |
1016 | if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) && | 1003 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) && |
1017 | nla_put_flag(msg, NL80211_ATTR_TDLS_SUPPORT)) | 1004 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) || |
1018 | goto nla_put_failure; | 1005 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_RFKILL_RELEASE) && |
1019 | if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) && | 1006 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) |
1020 | nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP)) | 1007 | return -ENOBUFS; |
1021 | goto nla_put_failure; | ||
1022 | 1008 | ||
1023 | if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES, | 1009 | if (dev->wiphy.wowlan.n_patterns) { |
1024 | sizeof(u32) * dev->wiphy.n_cipher_suites, | 1010 | struct nl80211_wowlan_pattern_support pat = { |
1025 | dev->wiphy.cipher_suites)) | 1011 | .max_patterns = dev->wiphy.wowlan.n_patterns, |
1026 | goto nla_put_failure; | 1012 | .min_pattern_len = dev->wiphy.wowlan.pattern_min_len, |
1013 | .max_pattern_len = dev->wiphy.wowlan.pattern_max_len, | ||
1014 | .max_pkt_offset = dev->wiphy.wowlan.max_pkt_offset, | ||
1015 | }; | ||
1027 | 1016 | ||
1028 | if (nla_put_u8(msg, NL80211_ATTR_MAX_NUM_PMKIDS, | 1017 | if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN, |
1029 | dev->wiphy.max_num_pmkids)) | 1018 | sizeof(pat), &pat)) |
1030 | goto nla_put_failure; | 1019 | return -ENOBUFS; |
1020 | } | ||
1031 | 1021 | ||
1032 | if ((dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) && | 1022 | if (large && nl80211_send_wowlan_tcp_caps(dev, msg)) |
1033 | nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE)) | 1023 | return -ENOBUFS; |
1034 | goto nla_put_failure; | ||
1035 | 1024 | ||
1036 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX, | 1025 | nla_nest_end(msg, nl_wowlan); |
1037 | dev->wiphy.available_antennas_tx) || | ||
1038 | nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX, | ||
1039 | dev->wiphy.available_antennas_rx)) | ||
1040 | goto nla_put_failure; | ||
1041 | 1026 | ||
1042 | if ((dev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) && | 1027 | return 0; |
1043 | nla_put_u32(msg, NL80211_ATTR_PROBE_RESP_OFFLOAD, | 1028 | } |
1044 | dev->wiphy.probe_resp_offload)) | 1029 | #endif |
1045 | goto nla_put_failure; | ||
1046 | 1030 | ||
1047 | if ((dev->wiphy.available_antennas_tx || | 1031 | static int nl80211_send_band_rateinfo(struct sk_buff *msg, |
1048 | dev->wiphy.available_antennas_rx) && dev->ops->get_antenna) { | 1032 | struct ieee80211_supported_band *sband) |
1049 | u32 tx_ant = 0, rx_ant = 0; | 1033 | { |
1050 | int res; | 1034 | struct nlattr *nl_rates, *nl_rate; |
1051 | res = rdev_get_antenna(dev, &tx_ant, &rx_ant); | 1035 | struct ieee80211_rate *rate; |
1052 | if (!res) { | 1036 | int i; |
1053 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_TX, | ||
1054 | tx_ant) || | ||
1055 | nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_RX, | ||
1056 | rx_ant)) | ||
1057 | goto nla_put_failure; | ||
1058 | } | ||
1059 | } | ||
1060 | 1037 | ||
1061 | if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES, | 1038 | /* add HT info */ |
1062 | dev->wiphy.interface_modes)) | 1039 | if (sband->ht_cap.ht_supported && |
1063 | goto nla_put_failure; | 1040 | (nla_put(msg, NL80211_BAND_ATTR_HT_MCS_SET, |
1041 | sizeof(sband->ht_cap.mcs), | ||
1042 | &sband->ht_cap.mcs) || | ||
1043 | nla_put_u16(msg, NL80211_BAND_ATTR_HT_CAPA, | ||
1044 | sband->ht_cap.cap) || | ||
1045 | nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR, | ||
1046 | sband->ht_cap.ampdu_factor) || | ||
1047 | nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY, | ||
1048 | sband->ht_cap.ampdu_density))) | ||
1049 | return -ENOBUFS; | ||
1064 | 1050 | ||
1065 | nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); | 1051 | /* add VHT info */ |
1066 | if (!nl_bands) | 1052 | if (sband->vht_cap.vht_supported && |
1067 | goto nla_put_failure; | 1053 | (nla_put(msg, NL80211_BAND_ATTR_VHT_MCS_SET, |
1054 | sizeof(sband->vht_cap.vht_mcs), | ||
1055 | &sband->vht_cap.vht_mcs) || | ||
1056 | nla_put_u32(msg, NL80211_BAND_ATTR_VHT_CAPA, | ||
1057 | sband->vht_cap.cap))) | ||
1058 | return -ENOBUFS; | ||
1068 | 1059 | ||
1069 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 1060 | /* add bitrates */ |
1070 | if (!dev->wiphy.bands[band]) | 1061 | nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES); |
1071 | continue; | 1062 | if (!nl_rates) |
1063 | return -ENOBUFS; | ||
1072 | 1064 | ||
1073 | nl_band = nla_nest_start(msg, band); | 1065 | for (i = 0; i < sband->n_bitrates; i++) { |
1074 | if (!nl_band) | 1066 | nl_rate = nla_nest_start(msg, i); |
1075 | goto nla_put_failure; | 1067 | if (!nl_rate) |
1068 | return -ENOBUFS; | ||
1076 | 1069 | ||
1077 | /* add HT info */ | 1070 | rate = &sband->bitrates[i]; |
1078 | if (dev->wiphy.bands[band]->ht_cap.ht_supported && | 1071 | if (nla_put_u32(msg, NL80211_BITRATE_ATTR_RATE, |
1079 | (nla_put(msg, NL80211_BAND_ATTR_HT_MCS_SET, | 1072 | rate->bitrate)) |
1080 | sizeof(dev->wiphy.bands[band]->ht_cap.mcs), | 1073 | return -ENOBUFS; |
1081 | &dev->wiphy.bands[band]->ht_cap.mcs) || | 1074 | if ((rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) && |
1082 | nla_put_u16(msg, NL80211_BAND_ATTR_HT_CAPA, | 1075 | nla_put_flag(msg, |
1083 | dev->wiphy.bands[band]->ht_cap.cap) || | 1076 | NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE)) |
1084 | nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR, | 1077 | return -ENOBUFS; |
1085 | dev->wiphy.bands[band]->ht_cap.ampdu_factor) || | ||
1086 | nla_put_u8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY, | ||
1087 | dev->wiphy.bands[band]->ht_cap.ampdu_density))) | ||
1088 | goto nla_put_failure; | ||
1089 | 1078 | ||
1090 | /* add VHT info */ | 1079 | nla_nest_end(msg, nl_rate); |
1091 | if (dev->wiphy.bands[band]->vht_cap.vht_supported && | 1080 | } |
1092 | (nla_put(msg, NL80211_BAND_ATTR_VHT_MCS_SET, | ||
1093 | sizeof(dev->wiphy.bands[band]->vht_cap.vht_mcs), | ||
1094 | &dev->wiphy.bands[band]->vht_cap.vht_mcs) || | ||
1095 | nla_put_u32(msg, NL80211_BAND_ATTR_VHT_CAPA, | ||
1096 | dev->wiphy.bands[band]->vht_cap.cap))) | ||
1097 | goto nla_put_failure; | ||
1098 | 1081 | ||
1099 | /* add frequencies */ | 1082 | nla_nest_end(msg, nl_rates); |
1100 | nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS); | ||
1101 | if (!nl_freqs) | ||
1102 | goto nla_put_failure; | ||
1103 | 1083 | ||
1104 | for (i = 0; i < dev->wiphy.bands[band]->n_channels; i++) { | 1084 | return 0; |
1105 | nl_freq = nla_nest_start(msg, i); | 1085 | } |
1106 | if (!nl_freq) | 1086 | |
1107 | goto nla_put_failure; | 1087 | static int |
1088 | nl80211_send_mgmt_stypes(struct sk_buff *msg, | ||
1089 | const struct ieee80211_txrx_stypes *mgmt_stypes) | ||
1090 | { | ||
1091 | u16 stypes; | ||
1092 | struct nlattr *nl_ftypes, *nl_ifs; | ||
1093 | enum nl80211_iftype ift; | ||
1094 | int i; | ||
1108 | 1095 | ||
1109 | chan = &dev->wiphy.bands[band]->channels[i]; | 1096 | if (!mgmt_stypes) |
1097 | return 0; | ||
1110 | 1098 | ||
1111 | if (nl80211_msg_put_channel(msg, chan)) | 1099 | nl_ifs = nla_nest_start(msg, NL80211_ATTR_TX_FRAME_TYPES); |
1112 | goto nla_put_failure; | 1100 | if (!nl_ifs) |
1101 | return -ENOBUFS; | ||
1113 | 1102 | ||
1114 | nla_nest_end(msg, nl_freq); | 1103 | for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) { |
1104 | nl_ftypes = nla_nest_start(msg, ift); | ||
1105 | if (!nl_ftypes) | ||
1106 | return -ENOBUFS; | ||
1107 | i = 0; | ||
1108 | stypes = mgmt_stypes[ift].tx; | ||
1109 | while (stypes) { | ||
1110 | if ((stypes & 1) && | ||
1111 | nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE, | ||
1112 | (i << 4) | IEEE80211_FTYPE_MGMT)) | ||
1113 | return -ENOBUFS; | ||
1114 | stypes >>= 1; | ||
1115 | i++; | ||
1115 | } | 1116 | } |
1117 | nla_nest_end(msg, nl_ftypes); | ||
1118 | } | ||
1116 | 1119 | ||
1117 | nla_nest_end(msg, nl_freqs); | 1120 | nla_nest_end(msg, nl_ifs); |
1118 | 1121 | ||
1119 | /* add bitrates */ | 1122 | nl_ifs = nla_nest_start(msg, NL80211_ATTR_RX_FRAME_TYPES); |
1120 | nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES); | 1123 | if (!nl_ifs) |
1121 | if (!nl_rates) | 1124 | return -ENOBUFS; |
1122 | goto nla_put_failure; | ||
1123 | 1125 | ||
1124 | for (i = 0; i < dev->wiphy.bands[band]->n_bitrates; i++) { | 1126 | for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) { |
1125 | nl_rate = nla_nest_start(msg, i); | 1127 | nl_ftypes = nla_nest_start(msg, ift); |
1126 | if (!nl_rate) | 1128 | if (!nl_ftypes) |
1127 | goto nla_put_failure; | 1129 | return -ENOBUFS; |
1130 | i = 0; | ||
1131 | stypes = mgmt_stypes[ift].rx; | ||
1132 | while (stypes) { | ||
1133 | if ((stypes & 1) && | ||
1134 | nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE, | ||
1135 | (i << 4) | IEEE80211_FTYPE_MGMT)) | ||
1136 | return -ENOBUFS; | ||
1137 | stypes >>= 1; | ||
1138 | i++; | ||
1139 | } | ||
1140 | nla_nest_end(msg, nl_ftypes); | ||
1141 | } | ||
1142 | nla_nest_end(msg, nl_ifs); | ||
1128 | 1143 | ||
1129 | rate = &dev->wiphy.bands[band]->bitrates[i]; | 1144 | return 0; |
1130 | if (nla_put_u32(msg, NL80211_BITRATE_ATTR_RATE, | 1145 | } |
1131 | rate->bitrate)) | ||
1132 | goto nla_put_failure; | ||
1133 | if ((rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) && | ||
1134 | nla_put_flag(msg, | ||
1135 | NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE)) | ||
1136 | goto nla_put_failure; | ||
1137 | 1146 | ||
1138 | nla_nest_end(msg, nl_rate); | 1147 | static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, |
1139 | } | 1148 | struct sk_buff *msg, u32 portid, u32 seq, |
1149 | int flags, bool split, long *split_start, | ||
1150 | long *band_start, long *chan_start) | ||
1151 | { | ||
1152 | void *hdr; | ||
1153 | struct nlattr *nl_bands, *nl_band; | ||
1154 | struct nlattr *nl_freqs, *nl_freq; | ||
1155 | struct nlattr *nl_cmds; | ||
1156 | enum ieee80211_band band; | ||
1157 | struct ieee80211_channel *chan; | ||
1158 | int i; | ||
1159 | const struct ieee80211_txrx_stypes *mgmt_stypes = | ||
1160 | dev->wiphy.mgmt_stypes; | ||
1161 | long start = 0, start_chan = 0, start_band = 0; | ||
1162 | u32 features; | ||
1140 | 1163 | ||
1141 | nla_nest_end(msg, nl_rates); | 1164 | hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_WIPHY); |
1165 | if (!hdr) | ||
1166 | return -ENOBUFS; | ||
1142 | 1167 | ||
1143 | nla_nest_end(msg, nl_band); | 1168 | /* allow always using the variables */ |
1169 | if (!split) { | ||
1170 | split_start = &start; | ||
1171 | band_start = &start_band; | ||
1172 | chan_start = &start_chan; | ||
1144 | } | 1173 | } |
1145 | nla_nest_end(msg, nl_bands); | ||
1146 | 1174 | ||
1147 | nl_cmds = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_COMMANDS); | 1175 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx) || |
1148 | if (!nl_cmds) | 1176 | nla_put_string(msg, NL80211_ATTR_WIPHY_NAME, |
1149 | goto nla_put_failure; | 1177 | wiphy_name(&dev->wiphy)) || |
1178 | nla_put_u32(msg, NL80211_ATTR_GENERATION, | ||
1179 | cfg80211_rdev_list_generation)) | ||
1180 | goto nla_put_failure; | ||
1181 | |||
1182 | switch (*split_start) { | ||
1183 | case 0: | ||
1184 | if (nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT, | ||
1185 | dev->wiphy.retry_short) || | ||
1186 | nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_LONG, | ||
1187 | dev->wiphy.retry_long) || | ||
1188 | nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, | ||
1189 | dev->wiphy.frag_threshold) || | ||
1190 | nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, | ||
1191 | dev->wiphy.rts_threshold) || | ||
1192 | nla_put_u8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, | ||
1193 | dev->wiphy.coverage_class) || | ||
1194 | nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, | ||
1195 | dev->wiphy.max_scan_ssids) || | ||
1196 | nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS, | ||
1197 | dev->wiphy.max_sched_scan_ssids) || | ||
1198 | nla_put_u16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, | ||
1199 | dev->wiphy.max_scan_ie_len) || | ||
1200 | nla_put_u16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN, | ||
1201 | dev->wiphy.max_sched_scan_ie_len) || | ||
1202 | nla_put_u8(msg, NL80211_ATTR_MAX_MATCH_SETS, | ||
1203 | dev->wiphy.max_match_sets)) | ||
1204 | goto nla_put_failure; | ||
1150 | 1205 | ||
1151 | i = 0; | 1206 | if ((dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) && |
1152 | #define CMD(op, n) \ | 1207 | nla_put_flag(msg, NL80211_ATTR_SUPPORT_IBSS_RSN)) |
1153 | do { \ | ||
1154 | if (dev->ops->op) { \ | ||
1155 | i++; \ | ||
1156 | if (nla_put_u32(msg, i, NL80211_CMD_ ## n)) \ | ||
1157 | goto nla_put_failure; \ | ||
1158 | } \ | ||
1159 | } while (0) | ||
1160 | |||
1161 | CMD(add_virtual_intf, NEW_INTERFACE); | ||
1162 | CMD(change_virtual_intf, SET_INTERFACE); | ||
1163 | CMD(add_key, NEW_KEY); | ||
1164 | CMD(start_ap, START_AP); | ||
1165 | CMD(add_station, NEW_STATION); | ||
1166 | CMD(add_mpath, NEW_MPATH); | ||
1167 | CMD(update_mesh_config, SET_MESH_CONFIG); | ||
1168 | CMD(change_bss, SET_BSS); | ||
1169 | CMD(auth, AUTHENTICATE); | ||
1170 | CMD(assoc, ASSOCIATE); | ||
1171 | CMD(deauth, DEAUTHENTICATE); | ||
1172 | CMD(disassoc, DISASSOCIATE); | ||
1173 | CMD(join_ibss, JOIN_IBSS); | ||
1174 | CMD(join_mesh, JOIN_MESH); | ||
1175 | CMD(set_pmksa, SET_PMKSA); | ||
1176 | CMD(del_pmksa, DEL_PMKSA); | ||
1177 | CMD(flush_pmksa, FLUSH_PMKSA); | ||
1178 | if (dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) | ||
1179 | CMD(remain_on_channel, REMAIN_ON_CHANNEL); | ||
1180 | CMD(set_bitrate_mask, SET_TX_BITRATE_MASK); | ||
1181 | CMD(mgmt_tx, FRAME); | ||
1182 | CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL); | ||
1183 | if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { | ||
1184 | i++; | ||
1185 | if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS)) | ||
1186 | goto nla_put_failure; | 1208 | goto nla_put_failure; |
1187 | } | 1209 | if ((dev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) && |
1188 | if (dev->ops->set_monitor_channel || dev->ops->start_ap || | 1210 | nla_put_flag(msg, NL80211_ATTR_SUPPORT_MESH_AUTH)) |
1189 | dev->ops->join_mesh) { | ||
1190 | i++; | ||
1191 | if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL)) | ||
1192 | goto nla_put_failure; | 1211 | goto nla_put_failure; |
1193 | } | 1212 | if ((dev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) && |
1194 | CMD(set_wds_peer, SET_WDS_PEER); | 1213 | nla_put_flag(msg, NL80211_ATTR_SUPPORT_AP_UAPSD)) |
1195 | if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) { | 1214 | goto nla_put_failure; |
1196 | CMD(tdls_mgmt, TDLS_MGMT); | 1215 | if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM) && |
1197 | CMD(tdls_oper, TDLS_OPER); | 1216 | nla_put_flag(msg, NL80211_ATTR_ROAM_SUPPORT)) |
1198 | } | 1217 | goto nla_put_failure; |
1199 | if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) | 1218 | if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) && |
1200 | CMD(sched_scan_start, START_SCHED_SCAN); | 1219 | nla_put_flag(msg, NL80211_ATTR_TDLS_SUPPORT)) |
1201 | CMD(probe_client, PROBE_CLIENT); | 1220 | goto nla_put_failure; |
1202 | CMD(set_noack_map, SET_NOACK_MAP); | 1221 | if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) && |
1203 | if (dev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) { | 1222 | nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP)) |
1204 | i++; | ||
1205 | if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS)) | ||
1206 | goto nla_put_failure; | 1223 | goto nla_put_failure; |
1207 | } | ||
1208 | CMD(start_p2p_device, START_P2P_DEVICE); | ||
1209 | CMD(set_mcast_rate, SET_MCAST_RATE); | ||
1210 | 1224 | ||
1211 | #ifdef CONFIG_NL80211_TESTMODE | 1225 | (*split_start)++; |
1212 | CMD(testmode_cmd, TESTMODE); | 1226 | if (split) |
1213 | #endif | 1227 | break; |
1228 | case 1: | ||
1229 | if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES, | ||
1230 | sizeof(u32) * dev->wiphy.n_cipher_suites, | ||
1231 | dev->wiphy.cipher_suites)) | ||
1232 | goto nla_put_failure; | ||
1214 | 1233 | ||
1215 | #undef CMD | 1234 | if (nla_put_u8(msg, NL80211_ATTR_MAX_NUM_PMKIDS, |
1235 | dev->wiphy.max_num_pmkids)) | ||
1236 | goto nla_put_failure; | ||
1216 | 1237 | ||
1217 | if (dev->ops->connect || dev->ops->auth) { | 1238 | if ((dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) && |
1218 | i++; | 1239 | nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE)) |
1219 | if (nla_put_u32(msg, i, NL80211_CMD_CONNECT)) | ||
1220 | goto nla_put_failure; | 1240 | goto nla_put_failure; |
1221 | } | ||
1222 | 1241 | ||
1223 | if (dev->ops->disconnect || dev->ops->deauth) { | 1242 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX, |
1224 | i++; | 1243 | dev->wiphy.available_antennas_tx) || |
1225 | if (nla_put_u32(msg, i, NL80211_CMD_DISCONNECT)) | 1244 | nla_put_u32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX, |
1245 | dev->wiphy.available_antennas_rx)) | ||
1246 | goto nla_put_failure; | ||
1247 | |||
1248 | if ((dev->wiphy.flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) && | ||
1249 | nla_put_u32(msg, NL80211_ATTR_PROBE_RESP_OFFLOAD, | ||
1250 | dev->wiphy.probe_resp_offload)) | ||
1226 | goto nla_put_failure; | 1251 | goto nla_put_failure; |
1227 | } | ||
1228 | 1252 | ||
1229 | nla_nest_end(msg, nl_cmds); | 1253 | if ((dev->wiphy.available_antennas_tx || |
1254 | dev->wiphy.available_antennas_rx) && | ||
1255 | dev->ops->get_antenna) { | ||
1256 | u32 tx_ant = 0, rx_ant = 0; | ||
1257 | int res; | ||
1258 | res = rdev_get_antenna(dev, &tx_ant, &rx_ant); | ||
1259 | if (!res) { | ||
1260 | if (nla_put_u32(msg, | ||
1261 | NL80211_ATTR_WIPHY_ANTENNA_TX, | ||
1262 | tx_ant) || | ||
1263 | nla_put_u32(msg, | ||
1264 | NL80211_ATTR_WIPHY_ANTENNA_RX, | ||
1265 | rx_ant)) | ||
1266 | goto nla_put_failure; | ||
1267 | } | ||
1268 | } | ||
1230 | 1269 | ||
1231 | if (dev->ops->remain_on_channel && | 1270 | (*split_start)++; |
1232 | (dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) && | 1271 | if (split) |
1233 | nla_put_u32(msg, NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION, | 1272 | break; |
1234 | dev->wiphy.max_remain_on_channel_duration)) | 1273 | case 2: |
1235 | goto nla_put_failure; | 1274 | if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES, |
1275 | dev->wiphy.interface_modes)) | ||
1276 | goto nla_put_failure; | ||
1277 | (*split_start)++; | ||
1278 | if (split) | ||
1279 | break; | ||
1280 | case 3: | ||
1281 | nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); | ||
1282 | if (!nl_bands) | ||
1283 | goto nla_put_failure; | ||
1236 | 1284 | ||
1237 | if ((dev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX) && | 1285 | for (band = *band_start; band < IEEE80211_NUM_BANDS; band++) { |
1238 | nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK)) | 1286 | struct ieee80211_supported_band *sband; |
1239 | goto nla_put_failure; | ||
1240 | 1287 | ||
1241 | if (mgmt_stypes) { | 1288 | sband = dev->wiphy.bands[band]; |
1242 | u16 stypes; | ||
1243 | struct nlattr *nl_ftypes, *nl_ifs; | ||
1244 | enum nl80211_iftype ift; | ||
1245 | 1289 | ||
1246 | nl_ifs = nla_nest_start(msg, NL80211_ATTR_TX_FRAME_TYPES); | 1290 | if (!sband) |
1247 | if (!nl_ifs) | 1291 | continue; |
1248 | goto nla_put_failure; | ||
1249 | 1292 | ||
1250 | for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) { | 1293 | nl_band = nla_nest_start(msg, band); |
1251 | nl_ftypes = nla_nest_start(msg, ift); | 1294 | if (!nl_band) |
1252 | if (!nl_ftypes) | ||
1253 | goto nla_put_failure; | 1295 | goto nla_put_failure; |
1254 | i = 0; | 1296 | |
1255 | stypes = mgmt_stypes[ift].tx; | 1297 | switch (*chan_start) { |
1256 | while (stypes) { | 1298 | case 0: |
1257 | if ((stypes & 1) && | 1299 | if (nl80211_send_band_rateinfo(msg, sband)) |
1258 | nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE, | ||
1259 | (i << 4) | IEEE80211_FTYPE_MGMT)) | ||
1260 | goto nla_put_failure; | 1300 | goto nla_put_failure; |
1261 | stypes >>= 1; | 1301 | (*chan_start)++; |
1262 | i++; | 1302 | if (split) |
1303 | break; | ||
1304 | default: | ||
1305 | /* add frequencies */ | ||
1306 | nl_freqs = nla_nest_start( | ||
1307 | msg, NL80211_BAND_ATTR_FREQS); | ||
1308 | if (!nl_freqs) | ||
1309 | goto nla_put_failure; | ||
1310 | |||
1311 | for (i = *chan_start - 1; | ||
1312 | i < sband->n_channels; | ||
1313 | i++) { | ||
1314 | nl_freq = nla_nest_start(msg, i); | ||
1315 | if (!nl_freq) | ||
1316 | goto nla_put_failure; | ||
1317 | |||
1318 | chan = &sband->channels[i]; | ||
1319 | |||
1320 | if (nl80211_msg_put_channel(msg, chan, | ||
1321 | split)) | ||
1322 | goto nla_put_failure; | ||
1323 | |||
1324 | nla_nest_end(msg, nl_freq); | ||
1325 | if (split) | ||
1326 | break; | ||
1327 | } | ||
1328 | if (i < sband->n_channels) | ||
1329 | *chan_start = i + 2; | ||
1330 | else | ||
1331 | *chan_start = 0; | ||
1332 | nla_nest_end(msg, nl_freqs); | ||
1333 | } | ||
1334 | |||
1335 | nla_nest_end(msg, nl_band); | ||
1336 | |||
1337 | if (split) { | ||
1338 | /* start again here */ | ||
1339 | if (*chan_start) | ||
1340 | band--; | ||
1341 | break; | ||
1263 | } | 1342 | } |
1264 | nla_nest_end(msg, nl_ftypes); | ||
1265 | } | 1343 | } |
1344 | nla_nest_end(msg, nl_bands); | ||
1266 | 1345 | ||
1267 | nla_nest_end(msg, nl_ifs); | 1346 | if (band < IEEE80211_NUM_BANDS) |
1347 | *band_start = band + 1; | ||
1348 | else | ||
1349 | *band_start = 0; | ||
1268 | 1350 | ||
1269 | nl_ifs = nla_nest_start(msg, NL80211_ATTR_RX_FRAME_TYPES); | 1351 | /* if bands & channels are done, continue outside */ |
1270 | if (!nl_ifs) | 1352 | if (*band_start == 0 && *chan_start == 0) |
1353 | (*split_start)++; | ||
1354 | if (split) | ||
1355 | break; | ||
1356 | case 4: | ||
1357 | nl_cmds = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_COMMANDS); | ||
1358 | if (!nl_cmds) | ||
1271 | goto nla_put_failure; | 1359 | goto nla_put_failure; |
1272 | 1360 | ||
1273 | for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) { | 1361 | i = 0; |
1274 | nl_ftypes = nla_nest_start(msg, ift); | 1362 | #define CMD(op, n) \ |
1275 | if (!nl_ftypes) | 1363 | do { \ |
1364 | if (dev->ops->op) { \ | ||
1365 | i++; \ | ||
1366 | if (nla_put_u32(msg, i, NL80211_CMD_ ## n)) \ | ||
1367 | goto nla_put_failure; \ | ||
1368 | } \ | ||
1369 | } while (0) | ||
1370 | |||
1371 | CMD(add_virtual_intf, NEW_INTERFACE); | ||
1372 | CMD(change_virtual_intf, SET_INTERFACE); | ||
1373 | CMD(add_key, NEW_KEY); | ||
1374 | CMD(start_ap, START_AP); | ||
1375 | CMD(add_station, NEW_STATION); | ||
1376 | CMD(add_mpath, NEW_MPATH); | ||
1377 | CMD(update_mesh_config, SET_MESH_CONFIG); | ||
1378 | CMD(change_bss, SET_BSS); | ||
1379 | CMD(auth, AUTHENTICATE); | ||
1380 | CMD(assoc, ASSOCIATE); | ||
1381 | CMD(deauth, DEAUTHENTICATE); | ||
1382 | CMD(disassoc, DISASSOCIATE); | ||
1383 | CMD(join_ibss, JOIN_IBSS); | ||
1384 | CMD(join_mesh, JOIN_MESH); | ||
1385 | CMD(set_pmksa, SET_PMKSA); | ||
1386 | CMD(del_pmksa, DEL_PMKSA); | ||
1387 | CMD(flush_pmksa, FLUSH_PMKSA); | ||
1388 | if (dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) | ||
1389 | CMD(remain_on_channel, REMAIN_ON_CHANNEL); | ||
1390 | CMD(set_bitrate_mask, SET_TX_BITRATE_MASK); | ||
1391 | CMD(mgmt_tx, FRAME); | ||
1392 | CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL); | ||
1393 | if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { | ||
1394 | i++; | ||
1395 | if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS)) | ||
1276 | goto nla_put_failure; | 1396 | goto nla_put_failure; |
1277 | i = 0; | ||
1278 | stypes = mgmt_stypes[ift].rx; | ||
1279 | while (stypes) { | ||
1280 | if ((stypes & 1) && | ||
1281 | nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE, | ||
1282 | (i << 4) | IEEE80211_FTYPE_MGMT)) | ||
1283 | goto nla_put_failure; | ||
1284 | stypes >>= 1; | ||
1285 | i++; | ||
1286 | } | ||
1287 | nla_nest_end(msg, nl_ftypes); | ||
1288 | } | 1397 | } |
1289 | nla_nest_end(msg, nl_ifs); | 1398 | if (dev->ops->set_monitor_channel || dev->ops->start_ap || |
1290 | } | 1399 | dev->ops->join_mesh) { |
1400 | i++; | ||
1401 | if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL)) | ||
1402 | goto nla_put_failure; | ||
1403 | } | ||
1404 | CMD(set_wds_peer, SET_WDS_PEER); | ||
1405 | if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) { | ||
1406 | CMD(tdls_mgmt, TDLS_MGMT); | ||
1407 | CMD(tdls_oper, TDLS_OPER); | ||
1408 | } | ||
1409 | if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) | ||
1410 | CMD(sched_scan_start, START_SCHED_SCAN); | ||
1411 | CMD(probe_client, PROBE_CLIENT); | ||
1412 | CMD(set_noack_map, SET_NOACK_MAP); | ||
1413 | if (dev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) { | ||
1414 | i++; | ||
1415 | if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS)) | ||
1416 | goto nla_put_failure; | ||
1417 | } | ||
1418 | CMD(start_p2p_device, START_P2P_DEVICE); | ||
1419 | CMD(set_mcast_rate, SET_MCAST_RATE); | ||
1291 | 1420 | ||
1292 | #ifdef CONFIG_PM | 1421 | #ifdef CONFIG_NL80211_TESTMODE |
1293 | if (dev->wiphy.wowlan.flags || dev->wiphy.wowlan.n_patterns) { | 1422 | CMD(testmode_cmd, TESTMODE); |
1294 | struct nlattr *nl_wowlan; | 1423 | #endif |
1295 | 1424 | ||
1296 | nl_wowlan = nla_nest_start(msg, | 1425 | #undef CMD |
1297 | NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED); | ||
1298 | if (!nl_wowlan) | ||
1299 | goto nla_put_failure; | ||
1300 | 1426 | ||
1301 | if (((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_ANY) && | 1427 | if (dev->ops->connect || dev->ops->auth) { |
1302 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) || | 1428 | i++; |
1303 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_DISCONNECT) && | 1429 | if (nla_put_u32(msg, i, NL80211_CMD_CONNECT)) |
1304 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) || | ||
1305 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_MAGIC_PKT) && | ||
1306 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) || | ||
1307 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) && | ||
1308 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED)) || | ||
1309 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) && | ||
1310 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) || | ||
1311 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) && | ||
1312 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) || | ||
1313 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) && | ||
1314 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) || | ||
1315 | ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_RFKILL_RELEASE) && | ||
1316 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) | ||
1317 | goto nla_put_failure; | ||
1318 | if (dev->wiphy.wowlan.n_patterns) { | ||
1319 | struct nl80211_wowlan_pattern_support pat = { | ||
1320 | .max_patterns = dev->wiphy.wowlan.n_patterns, | ||
1321 | .min_pattern_len = | ||
1322 | dev->wiphy.wowlan.pattern_min_len, | ||
1323 | .max_pattern_len = | ||
1324 | dev->wiphy.wowlan.pattern_max_len, | ||
1325 | .max_pkt_offset = | ||
1326 | dev->wiphy.wowlan.max_pkt_offset, | ||
1327 | }; | ||
1328 | if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN, | ||
1329 | sizeof(pat), &pat)) | ||
1330 | goto nla_put_failure; | 1430 | goto nla_put_failure; |
1331 | } | 1431 | } |
1332 | 1432 | ||
1333 | if (nl80211_send_wowlan_tcp_caps(dev, msg)) | 1433 | if (dev->ops->disconnect || dev->ops->deauth) { |
1434 | i++; | ||
1435 | if (nla_put_u32(msg, i, NL80211_CMD_DISCONNECT)) | ||
1436 | goto nla_put_failure; | ||
1437 | } | ||
1438 | |||
1439 | nla_nest_end(msg, nl_cmds); | ||
1440 | (*split_start)++; | ||
1441 | if (split) | ||
1442 | break; | ||
1443 | case 5: | ||
1444 | if (dev->ops->remain_on_channel && | ||
1445 | (dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) && | ||
1446 | nla_put_u32(msg, | ||
1447 | NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION, | ||
1448 | dev->wiphy.max_remain_on_channel_duration)) | ||
1449 | goto nla_put_failure; | ||
1450 | |||
1451 | if ((dev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX) && | ||
1452 | nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK)) | ||
1334 | goto nla_put_failure; | 1453 | goto nla_put_failure; |
1335 | 1454 | ||
1336 | nla_nest_end(msg, nl_wowlan); | 1455 | if (nl80211_send_mgmt_stypes(msg, mgmt_stypes)) |
1337 | } | 1456 | goto nla_put_failure; |
1457 | (*split_start)++; | ||
1458 | if (split) | ||
1459 | break; | ||
1460 | case 6: | ||
1461 | #ifdef CONFIG_PM | ||
1462 | if (nl80211_send_wowlan(msg, dev, split)) | ||
1463 | goto nla_put_failure; | ||
1464 | (*split_start)++; | ||
1465 | if (split) | ||
1466 | break; | ||
1467 | #else | ||
1468 | (*split_start)++; | ||
1338 | #endif | 1469 | #endif |
1470 | case 7: | ||
1471 | if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES, | ||
1472 | dev->wiphy.software_iftypes)) | ||
1473 | goto nla_put_failure; | ||
1339 | 1474 | ||
1340 | if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES, | 1475 | if (nl80211_put_iface_combinations(&dev->wiphy, msg, split)) |
1341 | dev->wiphy.software_iftypes)) | 1476 | goto nla_put_failure; |
1342 | goto nla_put_failure; | ||
1343 | 1477 | ||
1344 | if (nl80211_put_iface_combinations(&dev->wiphy, msg)) | 1478 | (*split_start)++; |
1345 | goto nla_put_failure; | 1479 | if (split) |
1480 | break; | ||
1481 | case 8: | ||
1482 | if ((dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) && | ||
1483 | nla_put_u32(msg, NL80211_ATTR_DEVICE_AP_SME, | ||
1484 | dev->wiphy.ap_sme_capa)) | ||
1485 | goto nla_put_failure; | ||
1346 | 1486 | ||
1347 | if ((dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) && | 1487 | features = dev->wiphy.features; |
1348 | nla_put_u32(msg, NL80211_ATTR_DEVICE_AP_SME, | 1488 | /* |
1349 | dev->wiphy.ap_sme_capa)) | 1489 | * We can only add the per-channel limit information if the |
1350 | goto nla_put_failure; | 1490 | * dump is split, otherwise it makes it too big. Therefore |
1491 | * only advertise it in that case. | ||
1492 | */ | ||
1493 | if (split) | ||
1494 | features |= NL80211_FEATURE_ADVERTISE_CHAN_LIMITS; | ||
1495 | if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, features)) | ||
1496 | goto nla_put_failure; | ||
1351 | 1497 | ||
1352 | if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, | 1498 | if (dev->wiphy.ht_capa_mod_mask && |
1353 | dev->wiphy.features)) | 1499 | nla_put(msg, NL80211_ATTR_HT_CAPABILITY_MASK, |
1354 | goto nla_put_failure; | 1500 | sizeof(*dev->wiphy.ht_capa_mod_mask), |
1501 | dev->wiphy.ht_capa_mod_mask)) | ||
1502 | goto nla_put_failure; | ||
1355 | 1503 | ||
1356 | if (dev->wiphy.ht_capa_mod_mask && | 1504 | if (dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME && |
1357 | nla_put(msg, NL80211_ATTR_HT_CAPABILITY_MASK, | 1505 | dev->wiphy.max_acl_mac_addrs && |
1358 | sizeof(*dev->wiphy.ht_capa_mod_mask), | 1506 | nla_put_u32(msg, NL80211_ATTR_MAC_ACL_MAX, |
1359 | dev->wiphy.ht_capa_mod_mask)) | 1507 | dev->wiphy.max_acl_mac_addrs)) |
1360 | goto nla_put_failure; | 1508 | goto nla_put_failure; |
1361 | 1509 | ||
1362 | if (dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME && | 1510 | /* |
1363 | dev->wiphy.max_acl_mac_addrs && | 1511 | * Any information below this point is only available to |
1364 | nla_put_u32(msg, NL80211_ATTR_MAC_ACL_MAX, | 1512 | * applications that can deal with it being split. This |
1365 | dev->wiphy.max_acl_mac_addrs)) | 1513 | * helps ensure that newly added capabilities don't break |
1366 | goto nla_put_failure; | 1514 | * older tools by overrunning their buffers. |
1515 | * | ||
1516 | * We still increment split_start so that in the split | ||
1517 | * case we'll continue with more data in the next round, | ||
1518 | * but break unconditionally so unsplit data stops here. | ||
1519 | */ | ||
1520 | (*split_start)++; | ||
1521 | break; | ||
1522 | case 9: | ||
1523 | if (dev->wiphy.extended_capabilities && | ||
1524 | (nla_put(msg, NL80211_ATTR_EXT_CAPA, | ||
1525 | dev->wiphy.extended_capabilities_len, | ||
1526 | dev->wiphy.extended_capabilities) || | ||
1527 | nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK, | ||
1528 | dev->wiphy.extended_capabilities_len, | ||
1529 | dev->wiphy.extended_capabilities_mask))) | ||
1530 | goto nla_put_failure; | ||
1367 | 1531 | ||
1368 | if (dev->wiphy.extended_capabilities && | 1532 | if (dev->wiphy.vht_capa_mod_mask && |
1369 | (nla_put(msg, NL80211_ATTR_EXT_CAPA, | 1533 | nla_put(msg, NL80211_ATTR_VHT_CAPABILITY_MASK, |
1370 | dev->wiphy.extended_capabilities_len, | 1534 | sizeof(*dev->wiphy.vht_capa_mod_mask), |
1371 | dev->wiphy.extended_capabilities) || | 1535 | dev->wiphy.vht_capa_mod_mask)) |
1372 | nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK, | 1536 | goto nla_put_failure; |
1373 | dev->wiphy.extended_capabilities_len, | ||
1374 | dev->wiphy.extended_capabilities_mask))) | ||
1375 | goto nla_put_failure; | ||
1376 | 1537 | ||
1538 | /* done */ | ||
1539 | *split_start = 0; | ||
1540 | break; | ||
1541 | } | ||
1377 | return genlmsg_end(msg, hdr); | 1542 | return genlmsg_end(msg, hdr); |
1378 | 1543 | ||
1379 | nla_put_failure: | 1544 | nla_put_failure: |
@@ -1383,22 +1548,83 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag | |||
1383 | 1548 | ||
1384 | static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) | 1549 | static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) |
1385 | { | 1550 | { |
1386 | int idx = 0; | 1551 | int idx = 0, ret; |
1387 | int start = cb->args[0]; | 1552 | int start = cb->args[0]; |
1388 | struct cfg80211_registered_device *dev; | 1553 | struct cfg80211_registered_device *dev; |
1554 | s64 filter_wiphy = -1; | ||
1555 | bool split = false; | ||
1556 | struct nlattr **tb = nl80211_fam.attrbuf; | ||
1557 | int res; | ||
1389 | 1558 | ||
1390 | mutex_lock(&cfg80211_mutex); | 1559 | mutex_lock(&cfg80211_mutex); |
1560 | res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, | ||
1561 | tb, nl80211_fam.maxattr, nl80211_policy); | ||
1562 | if (res == 0) { | ||
1563 | split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP]; | ||
1564 | if (tb[NL80211_ATTR_WIPHY]) | ||
1565 | filter_wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]); | ||
1566 | if (tb[NL80211_ATTR_WDEV]) | ||
1567 | filter_wiphy = nla_get_u64(tb[NL80211_ATTR_WDEV]) >> 32; | ||
1568 | if (tb[NL80211_ATTR_IFINDEX]) { | ||
1569 | struct net_device *netdev; | ||
1570 | int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]); | ||
1571 | |||
1572 | netdev = dev_get_by_index(sock_net(skb->sk), ifidx); | ||
1573 | if (!netdev) { | ||
1574 | mutex_unlock(&cfg80211_mutex); | ||
1575 | return -ENODEV; | ||
1576 | } | ||
1577 | if (netdev->ieee80211_ptr) { | ||
1578 | dev = wiphy_to_dev( | ||
1579 | netdev->ieee80211_ptr->wiphy); | ||
1580 | filter_wiphy = dev->wiphy_idx; | ||
1581 | } | ||
1582 | dev_put(netdev); | ||
1583 | } | ||
1584 | } | ||
1585 | |||
1391 | list_for_each_entry(dev, &cfg80211_rdev_list, list) { | 1586 | list_for_each_entry(dev, &cfg80211_rdev_list, list) { |
1392 | if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk))) | 1587 | if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk))) |
1393 | continue; | 1588 | continue; |
1394 | if (++idx <= start) | 1589 | if (++idx <= start) |
1395 | continue; | 1590 | continue; |
1396 | if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).portid, | 1591 | if (filter_wiphy != -1 && dev->wiphy_idx != filter_wiphy) |
1397 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 1592 | continue; |
1398 | dev) < 0) { | 1593 | /* attempt to fit multiple wiphy data chunks into the skb */ |
1399 | idx--; | 1594 | do { |
1400 | break; | 1595 | ret = nl80211_send_wiphy(dev, skb, |
1401 | } | 1596 | NETLINK_CB(cb->skb).portid, |
1597 | cb->nlh->nlmsg_seq, | ||
1598 | NLM_F_MULTI, | ||
1599 | split, &cb->args[1], | ||
1600 | &cb->args[2], | ||
1601 | &cb->args[3]); | ||
1602 | if (ret < 0) { | ||
1603 | /* | ||
1604 | * If sending the wiphy data didn't fit (ENOBUFS | ||
1605 | * or EMSGSIZE returned), this SKB is still | ||
1606 | * empty (so it's not too big because another | ||
1607 | * wiphy dataset is already in the skb) and | ||
1608 | * we've not tried to adjust the dump allocation | ||
1609 | * yet ... then adjust the alloc size to be | ||
1610 | * bigger, and return 1 but with the empty skb. | ||
1611 | * This results in an empty message being RX'ed | ||
1612 | * in userspace, but that is ignored. | ||
1613 | * | ||
1614 | * We can then retry with the larger buffer. | ||
1615 | */ | ||
1616 | if ((ret == -ENOBUFS || ret == -EMSGSIZE) && | ||
1617 | !skb->len && | ||
1618 | cb->min_dump_alloc < 4096) { | ||
1619 | cb->min_dump_alloc = 4096; | ||
1620 | mutex_unlock(&cfg80211_mutex); | ||
1621 | return 1; | ||
1622 | } | ||
1623 | idx--; | ||
1624 | break; | ||
1625 | } | ||
1626 | } while (cb->args[1] > 0); | ||
1627 | break; | ||
1402 | } | 1628 | } |
1403 | mutex_unlock(&cfg80211_mutex); | 1629 | mutex_unlock(&cfg80211_mutex); |
1404 | 1630 | ||
@@ -1412,11 +1638,12 @@ static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1412 | struct sk_buff *msg; | 1638 | struct sk_buff *msg; |
1413 | struct cfg80211_registered_device *dev = info->user_ptr[0]; | 1639 | struct cfg80211_registered_device *dev = info->user_ptr[0]; |
1414 | 1640 | ||
1415 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 1641 | msg = nlmsg_new(4096, GFP_KERNEL); |
1416 | if (!msg) | 1642 | if (!msg) |
1417 | return -ENOMEM; | 1643 | return -ENOMEM; |
1418 | 1644 | ||
1419 | if (nl80211_send_wiphy(msg, info->snd_portid, info->snd_seq, 0, dev) < 0) { | 1645 | if (nl80211_send_wiphy(dev, msg, info->snd_portid, info->snd_seq, 0, |
1646 | false, NULL, NULL, NULL) < 0) { | ||
1420 | nlmsg_free(msg); | 1647 | nlmsg_free(msg); |
1421 | return -ENOBUFS; | 1648 | return -ENOBUFS; |
1422 | } | 1649 | } |
@@ -3023,6 +3250,7 @@ static int parse_station_flags(struct genl_info *info, | |||
3023 | sta_flags = nla_data(nla); | 3250 | sta_flags = nla_data(nla); |
3024 | params->sta_flags_mask = sta_flags->mask; | 3251 | params->sta_flags_mask = sta_flags->mask; |
3025 | params->sta_flags_set = sta_flags->set; | 3252 | params->sta_flags_set = sta_flags->set; |
3253 | params->sta_flags_set &= params->sta_flags_mask; | ||
3026 | if ((params->sta_flags_mask | | 3254 | if ((params->sta_flags_mask | |
3027 | params->sta_flags_set) & BIT(__NL80211_STA_FLAG_INVALID)) | 3255 | params->sta_flags_set) & BIT(__NL80211_STA_FLAG_INVALID)) |
3028 | return -EINVAL; | 3256 | return -EINVAL; |
@@ -3376,6 +3604,136 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) | |||
3376 | return genlmsg_reply(msg, info); | 3604 | return genlmsg_reply(msg, info); |
3377 | } | 3605 | } |
3378 | 3606 | ||
3607 | int cfg80211_check_station_change(struct wiphy *wiphy, | ||
3608 | struct station_parameters *params, | ||
3609 | enum cfg80211_station_type statype) | ||
3610 | { | ||
3611 | if (params->listen_interval != -1) | ||
3612 | return -EINVAL; | ||
3613 | if (params->aid) | ||
3614 | return -EINVAL; | ||
3615 | |||
3616 | /* When you run into this, adjust the code below for the new flag */ | ||
3617 | BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7); | ||
3618 | |||
3619 | switch (statype) { | ||
3620 | case CFG80211_STA_MESH_PEER_KERNEL: | ||
3621 | case CFG80211_STA_MESH_PEER_USER: | ||
3622 | /* | ||
3623 | * No ignoring the TDLS flag here -- the userspace mesh | ||
3624 | * code doesn't have the bug of including TDLS in the | ||
3625 | * mask everywhere. | ||
3626 | */ | ||
3627 | if (params->sta_flags_mask & | ||
3628 | ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
3629 | BIT(NL80211_STA_FLAG_MFP) | | ||
3630 | BIT(NL80211_STA_FLAG_AUTHORIZED))) | ||
3631 | return -EINVAL; | ||
3632 | break; | ||
3633 | case CFG80211_STA_TDLS_PEER_SETUP: | ||
3634 | case CFG80211_STA_TDLS_PEER_ACTIVE: | ||
3635 | if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) | ||
3636 | return -EINVAL; | ||
3637 | /* ignore since it can't change */ | ||
3638 | params->sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); | ||
3639 | break; | ||
3640 | default: | ||
3641 | /* disallow mesh-specific things */ | ||
3642 | if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION) | ||
3643 | return -EINVAL; | ||
3644 | if (params->local_pm) | ||
3645 | return -EINVAL; | ||
3646 | if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE) | ||
3647 | return -EINVAL; | ||
3648 | } | ||
3649 | |||
3650 | if (statype != CFG80211_STA_TDLS_PEER_SETUP && | ||
3651 | statype != CFG80211_STA_TDLS_PEER_ACTIVE) { | ||
3652 | /* TDLS can't be set, ... */ | ||
3653 | if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) | ||
3654 | return -EINVAL; | ||
3655 | /* | ||
3656 | * ... but don't bother the driver with it. This works around | ||
3657 | * a hostapd/wpa_supplicant issue -- it always includes the | ||
3658 | * TLDS_PEER flag in the mask even for AP mode. | ||
3659 | */ | ||
3660 | params->sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); | ||
3661 | } | ||
3662 | |||
3663 | if (statype != CFG80211_STA_TDLS_PEER_SETUP) { | ||
3664 | /* reject other things that can't change */ | ||
3665 | if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD) | ||
3666 | return -EINVAL; | ||
3667 | if (params->sta_modify_mask & STATION_PARAM_APPLY_CAPABILITY) | ||
3668 | return -EINVAL; | ||
3669 | if (params->supported_rates) | ||
3670 | return -EINVAL; | ||
3671 | if (params->ext_capab || params->ht_capa || params->vht_capa) | ||
3672 | return -EINVAL; | ||
3673 | } | ||
3674 | |||
3675 | if (statype != CFG80211_STA_AP_CLIENT) { | ||
3676 | if (params->vlan) | ||
3677 | return -EINVAL; | ||
3678 | } | ||
3679 | |||
3680 | switch (statype) { | ||
3681 | case CFG80211_STA_AP_MLME_CLIENT: | ||
3682 | /* Use this only for authorizing/unauthorizing a station */ | ||
3683 | if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))) | ||
3684 | return -EOPNOTSUPP; | ||
3685 | break; | ||
3686 | case CFG80211_STA_AP_CLIENT: | ||
3687 | /* accept only the listed bits */ | ||
3688 | if (params->sta_flags_mask & | ||
3689 | ~(BIT(NL80211_STA_FLAG_AUTHORIZED) | | ||
3690 | BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
3691 | BIT(NL80211_STA_FLAG_ASSOCIATED) | | ||
3692 | BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) | | ||
3693 | BIT(NL80211_STA_FLAG_WME) | | ||
3694 | BIT(NL80211_STA_FLAG_MFP))) | ||
3695 | return -EINVAL; | ||
3696 | |||
3697 | /* but authenticated/associated only if driver handles it */ | ||
3698 | if (!(wiphy->features & NL80211_FEATURE_FULL_AP_CLIENT_STATE) && | ||
3699 | params->sta_flags_mask & | ||
3700 | (BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
3701 | BIT(NL80211_STA_FLAG_ASSOCIATED))) | ||
3702 | return -EINVAL; | ||
3703 | break; | ||
3704 | case CFG80211_STA_IBSS: | ||
3705 | case CFG80211_STA_AP_STA: | ||
3706 | /* reject any changes other than AUTHORIZED */ | ||
3707 | if (params->sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED)) | ||
3708 | return -EINVAL; | ||
3709 | break; | ||
3710 | case CFG80211_STA_TDLS_PEER_SETUP: | ||
3711 | /* reject any changes other than AUTHORIZED or WME */ | ||
3712 | if (params->sta_flags_mask & ~(BIT(NL80211_STA_FLAG_AUTHORIZED) | | ||
3713 | BIT(NL80211_STA_FLAG_WME))) | ||
3714 | return -EINVAL; | ||
3715 | /* force (at least) rates when authorizing */ | ||
3716 | if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED) && | ||
3717 | !params->supported_rates) | ||
3718 | return -EINVAL; | ||
3719 | break; | ||
3720 | case CFG80211_STA_TDLS_PEER_ACTIVE: | ||
3721 | /* reject any changes */ | ||
3722 | return -EINVAL; | ||
3723 | case CFG80211_STA_MESH_PEER_KERNEL: | ||
3724 | if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE) | ||
3725 | return -EINVAL; | ||
3726 | break; | ||
3727 | case CFG80211_STA_MESH_PEER_USER: | ||
3728 | if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION) | ||
3729 | return -EINVAL; | ||
3730 | break; | ||
3731 | } | ||
3732 | |||
3733 | return 0; | ||
3734 | } | ||
3735 | EXPORT_SYMBOL(cfg80211_check_station_change); | ||
3736 | |||
3379 | /* | 3737 | /* |
3380 | * Get vlan interface making sure it is running and on the right wiphy. | 3738 | * Get vlan interface making sure it is running and on the right wiphy. |
3381 | */ | 3739 | */ |
@@ -3398,6 +3756,13 @@ static struct net_device *get_vlan(struct genl_info *info, | |||
3398 | goto error; | 3756 | goto error; |
3399 | } | 3757 | } |
3400 | 3758 | ||
3759 | if (v->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && | ||
3760 | v->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | ||
3761 | v->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { | ||
3762 | ret = -EINVAL; | ||
3763 | goto error; | ||
3764 | } | ||
3765 | |||
3401 | if (!netif_running(v)) { | 3766 | if (!netif_running(v)) { |
3402 | ret = -ENETDOWN; | 3767 | ret = -ENETDOWN; |
3403 | goto error; | 3768 | goto error; |
@@ -3415,21 +3780,13 @@ nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] __read_mostly = { | |||
3415 | [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 }, | 3780 | [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 }, |
3416 | }; | 3781 | }; |
3417 | 3782 | ||
3418 | static int nl80211_set_station_tdls(struct genl_info *info, | 3783 | static int nl80211_parse_sta_wme(struct genl_info *info, |
3419 | struct station_parameters *params) | 3784 | struct station_parameters *params) |
3420 | { | 3785 | { |
3421 | struct nlattr *tb[NL80211_STA_WME_MAX + 1]; | 3786 | struct nlattr *tb[NL80211_STA_WME_MAX + 1]; |
3422 | struct nlattr *nla; | 3787 | struct nlattr *nla; |
3423 | int err; | 3788 | int err; |
3424 | 3789 | ||
3425 | /* Dummy STA entry gets updated once the peer capabilities are known */ | ||
3426 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) | ||
3427 | params->ht_capa = | ||
3428 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); | ||
3429 | if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) | ||
3430 | params->vht_capa = | ||
3431 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); | ||
3432 | |||
3433 | /* parse WME attributes if present */ | 3790 | /* parse WME attributes if present */ |
3434 | if (!info->attrs[NL80211_ATTR_STA_WME]) | 3791 | if (!info->attrs[NL80211_ATTR_STA_WME]) |
3435 | return 0; | 3792 | return 0; |
@@ -3457,18 +3814,34 @@ static int nl80211_set_station_tdls(struct genl_info *info, | |||
3457 | return 0; | 3814 | return 0; |
3458 | } | 3815 | } |
3459 | 3816 | ||
3817 | static int nl80211_set_station_tdls(struct genl_info *info, | ||
3818 | struct station_parameters *params) | ||
3819 | { | ||
3820 | /* Dummy STA entry gets updated once the peer capabilities are known */ | ||
3821 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) | ||
3822 | params->ht_capa = | ||
3823 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); | ||
3824 | if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) | ||
3825 | params->vht_capa = | ||
3826 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); | ||
3827 | |||
3828 | return nl80211_parse_sta_wme(info, params); | ||
3829 | } | ||
3830 | |||
3460 | static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | 3831 | static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) |
3461 | { | 3832 | { |
3462 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 3833 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
3463 | int err; | ||
3464 | struct net_device *dev = info->user_ptr[1]; | 3834 | struct net_device *dev = info->user_ptr[1]; |
3465 | struct station_parameters params; | 3835 | struct station_parameters params; |
3466 | u8 *mac_addr = NULL; | 3836 | u8 *mac_addr; |
3837 | int err; | ||
3467 | 3838 | ||
3468 | memset(¶ms, 0, sizeof(params)); | 3839 | memset(¶ms, 0, sizeof(params)); |
3469 | 3840 | ||
3470 | params.listen_interval = -1; | 3841 | params.listen_interval = -1; |
3471 | params.plink_state = -1; | 3842 | |
3843 | if (!rdev->ops->change_station) | ||
3844 | return -EOPNOTSUPP; | ||
3472 | 3845 | ||
3473 | if (info->attrs[NL80211_ATTR_STA_AID]) | 3846 | if (info->attrs[NL80211_ATTR_STA_AID]) |
3474 | return -EINVAL; | 3847 | return -EINVAL; |
@@ -3501,19 +3874,23 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
3501 | if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]) | 3874 | if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]) |
3502 | return -EINVAL; | 3875 | return -EINVAL; |
3503 | 3876 | ||
3504 | if (!rdev->ops->change_station) | ||
3505 | return -EOPNOTSUPP; | ||
3506 | |||
3507 | if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms)) | 3877 | if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms)) |
3508 | return -EINVAL; | 3878 | return -EINVAL; |
3509 | 3879 | ||
3510 | if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) | 3880 | if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) { |
3511 | params.plink_action = | 3881 | params.plink_action = |
3512 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); | 3882 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); |
3883 | if (params.plink_action >= NUM_NL80211_PLINK_ACTIONS) | ||
3884 | return -EINVAL; | ||
3885 | } | ||
3513 | 3886 | ||
3514 | if (info->attrs[NL80211_ATTR_STA_PLINK_STATE]) | 3887 | if (info->attrs[NL80211_ATTR_STA_PLINK_STATE]) { |
3515 | params.plink_state = | 3888 | params.plink_state = |
3516 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]); | 3889 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]); |
3890 | if (params.plink_state >= NUM_NL80211_PLINK_STATES) | ||
3891 | return -EINVAL; | ||
3892 | params.sta_modify_mask |= STATION_PARAM_APPLY_PLINK_STATE; | ||
3893 | } | ||
3517 | 3894 | ||
3518 | if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]) { | 3895 | if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]) { |
3519 | enum nl80211_mesh_power_mode pm = nla_get_u32( | 3896 | enum nl80211_mesh_power_mode pm = nla_get_u32( |
@@ -3526,127 +3903,33 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
3526 | params.local_pm = pm; | 3903 | params.local_pm = pm; |
3527 | } | 3904 | } |
3528 | 3905 | ||
3906 | /* Include parameters for TDLS peer (will check later) */ | ||
3907 | err = nl80211_set_station_tdls(info, ¶ms); | ||
3908 | if (err) | ||
3909 | return err; | ||
3910 | |||
3911 | params.vlan = get_vlan(info, rdev); | ||
3912 | if (IS_ERR(params.vlan)) | ||
3913 | return PTR_ERR(params.vlan); | ||
3914 | |||
3529 | switch (dev->ieee80211_ptr->iftype) { | 3915 | switch (dev->ieee80211_ptr->iftype) { |
3530 | case NL80211_IFTYPE_AP: | 3916 | case NL80211_IFTYPE_AP: |
3531 | case NL80211_IFTYPE_AP_VLAN: | 3917 | case NL80211_IFTYPE_AP_VLAN: |
3532 | case NL80211_IFTYPE_P2P_GO: | 3918 | case NL80211_IFTYPE_P2P_GO: |
3533 | /* disallow mesh-specific things */ | ||
3534 | if (params.plink_action) | ||
3535 | return -EINVAL; | ||
3536 | if (params.local_pm) | ||
3537 | return -EINVAL; | ||
3538 | |||
3539 | /* TDLS can't be set, ... */ | ||
3540 | if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) | ||
3541 | return -EINVAL; | ||
3542 | /* | ||
3543 | * ... but don't bother the driver with it. This works around | ||
3544 | * a hostapd/wpa_supplicant issue -- it always includes the | ||
3545 | * TLDS_PEER flag in the mask even for AP mode. | ||
3546 | */ | ||
3547 | params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); | ||
3548 | |||
3549 | /* accept only the listed bits */ | ||
3550 | if (params.sta_flags_mask & | ||
3551 | ~(BIT(NL80211_STA_FLAG_AUTHORIZED) | | ||
3552 | BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
3553 | BIT(NL80211_STA_FLAG_ASSOCIATED) | | ||
3554 | BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) | | ||
3555 | BIT(NL80211_STA_FLAG_WME) | | ||
3556 | BIT(NL80211_STA_FLAG_MFP))) | ||
3557 | return -EINVAL; | ||
3558 | |||
3559 | /* but authenticated/associated only if driver handles it */ | ||
3560 | if (!(rdev->wiphy.features & | ||
3561 | NL80211_FEATURE_FULL_AP_CLIENT_STATE) && | ||
3562 | params.sta_flags_mask & | ||
3563 | (BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
3564 | BIT(NL80211_STA_FLAG_ASSOCIATED))) | ||
3565 | return -EINVAL; | ||
3566 | |||
3567 | /* reject other things that can't change */ | ||
3568 | if (params.supported_rates) | ||
3569 | return -EINVAL; | ||
3570 | if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) | ||
3571 | return -EINVAL; | ||
3572 | if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) | ||
3573 | return -EINVAL; | ||
3574 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY] || | ||
3575 | info->attrs[NL80211_ATTR_VHT_CAPABILITY]) | ||
3576 | return -EINVAL; | ||
3577 | |||
3578 | /* must be last in here for error handling */ | ||
3579 | params.vlan = get_vlan(info, rdev); | ||
3580 | if (IS_ERR(params.vlan)) | ||
3581 | return PTR_ERR(params.vlan); | ||
3582 | break; | ||
3583 | case NL80211_IFTYPE_P2P_CLIENT: | 3919 | case NL80211_IFTYPE_P2P_CLIENT: |
3584 | case NL80211_IFTYPE_STATION: | 3920 | case NL80211_IFTYPE_STATION: |
3585 | /* | ||
3586 | * Don't allow userspace to change the TDLS_PEER flag, | ||
3587 | * but silently ignore attempts to change it since we | ||
3588 | * don't have state here to verify that it doesn't try | ||
3589 | * to change the flag. | ||
3590 | */ | ||
3591 | params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); | ||
3592 | /* Include parameters for TDLS peer (driver will check) */ | ||
3593 | err = nl80211_set_station_tdls(info, ¶ms); | ||
3594 | if (err) | ||
3595 | return err; | ||
3596 | /* disallow things sta doesn't support */ | ||
3597 | if (params.plink_action) | ||
3598 | return -EINVAL; | ||
3599 | if (params.local_pm) | ||
3600 | return -EINVAL; | ||
3601 | /* reject any changes other than AUTHORIZED or WME (for TDLS) */ | ||
3602 | if (params.sta_flags_mask & ~(BIT(NL80211_STA_FLAG_AUTHORIZED) | | ||
3603 | BIT(NL80211_STA_FLAG_WME))) | ||
3604 | return -EINVAL; | ||
3605 | break; | ||
3606 | case NL80211_IFTYPE_ADHOC: | 3921 | case NL80211_IFTYPE_ADHOC: |
3607 | /* disallow things sta doesn't support */ | ||
3608 | if (params.plink_action) | ||
3609 | return -EINVAL; | ||
3610 | if (params.local_pm) | ||
3611 | return -EINVAL; | ||
3612 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY] || | ||
3613 | info->attrs[NL80211_ATTR_VHT_CAPABILITY]) | ||
3614 | return -EINVAL; | ||
3615 | /* reject any changes other than AUTHORIZED */ | ||
3616 | if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED)) | ||
3617 | return -EINVAL; | ||
3618 | break; | ||
3619 | case NL80211_IFTYPE_MESH_POINT: | 3922 | case NL80211_IFTYPE_MESH_POINT: |
3620 | /* disallow things mesh doesn't support */ | ||
3621 | if (params.vlan) | ||
3622 | return -EINVAL; | ||
3623 | if (params.supported_rates) | ||
3624 | return -EINVAL; | ||
3625 | if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) | ||
3626 | return -EINVAL; | ||
3627 | if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) | ||
3628 | return -EINVAL; | ||
3629 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY] || | ||
3630 | info->attrs[NL80211_ATTR_VHT_CAPABILITY]) | ||
3631 | return -EINVAL; | ||
3632 | /* | ||
3633 | * No special handling for TDLS here -- the userspace | ||
3634 | * mesh code doesn't have this bug. | ||
3635 | */ | ||
3636 | if (params.sta_flags_mask & | ||
3637 | ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
3638 | BIT(NL80211_STA_FLAG_MFP) | | ||
3639 | BIT(NL80211_STA_FLAG_AUTHORIZED))) | ||
3640 | return -EINVAL; | ||
3641 | break; | 3923 | break; |
3642 | default: | 3924 | default: |
3643 | return -EOPNOTSUPP; | 3925 | err = -EOPNOTSUPP; |
3926 | goto out_put_vlan; | ||
3644 | } | 3927 | } |
3645 | 3928 | ||
3646 | /* be aware of params.vlan when changing code here */ | 3929 | /* driver will call cfg80211_check_station_change() */ |
3647 | |||
3648 | err = rdev_change_station(rdev, dev, mac_addr, ¶ms); | 3930 | err = rdev_change_station(rdev, dev, mac_addr, ¶ms); |
3649 | 3931 | ||
3932 | out_put_vlan: | ||
3650 | if (params.vlan) | 3933 | if (params.vlan) |
3651 | dev_put(params.vlan); | 3934 | dev_put(params.vlan); |
3652 | 3935 | ||
@@ -3663,6 +3946,9 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
3663 | 3946 | ||
3664 | memset(¶ms, 0, sizeof(params)); | 3947 | memset(¶ms, 0, sizeof(params)); |
3665 | 3948 | ||
3949 | if (!rdev->ops->add_station) | ||
3950 | return -EOPNOTSUPP; | ||
3951 | |||
3666 | if (!info->attrs[NL80211_ATTR_MAC]) | 3952 | if (!info->attrs[NL80211_ATTR_MAC]) |
3667 | return -EINVAL; | 3953 | return -EINVAL; |
3668 | 3954 | ||
@@ -3708,50 +3994,32 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
3708 | params.vht_capa = | 3994 | params.vht_capa = |
3709 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); | 3995 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); |
3710 | 3996 | ||
3711 | if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) | 3997 | if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) { |
3712 | params.plink_action = | 3998 | params.plink_action = |
3713 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); | 3999 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); |
4000 | if (params.plink_action >= NUM_NL80211_PLINK_ACTIONS) | ||
4001 | return -EINVAL; | ||
4002 | } | ||
3714 | 4003 | ||
3715 | if (!rdev->ops->add_station) | 4004 | err = nl80211_parse_sta_wme(info, ¶ms); |
3716 | return -EOPNOTSUPP; | 4005 | if (err) |
4006 | return err; | ||
3717 | 4007 | ||
3718 | if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms)) | 4008 | if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms)) |
3719 | return -EINVAL; | 4009 | return -EINVAL; |
3720 | 4010 | ||
4011 | /* When you run into this, adjust the code below for the new flag */ | ||
4012 | BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7); | ||
4013 | |||
3721 | switch (dev->ieee80211_ptr->iftype) { | 4014 | switch (dev->ieee80211_ptr->iftype) { |
3722 | case NL80211_IFTYPE_AP: | 4015 | case NL80211_IFTYPE_AP: |
3723 | case NL80211_IFTYPE_AP_VLAN: | 4016 | case NL80211_IFTYPE_AP_VLAN: |
3724 | case NL80211_IFTYPE_P2P_GO: | 4017 | case NL80211_IFTYPE_P2P_GO: |
3725 | /* parse WME attributes if sta is WME capable */ | 4018 | /* ignore WME attributes if iface/sta is not capable */ |
3726 | if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) && | 4019 | if (!(rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) || |
3727 | (params.sta_flags_set & BIT(NL80211_STA_FLAG_WME)) && | 4020 | !(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME))) |
3728 | info->attrs[NL80211_ATTR_STA_WME]) { | 4021 | params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD; |
3729 | struct nlattr *tb[NL80211_STA_WME_MAX + 1]; | ||
3730 | struct nlattr *nla; | ||
3731 | |||
3732 | nla = info->attrs[NL80211_ATTR_STA_WME]; | ||
3733 | err = nla_parse_nested(tb, NL80211_STA_WME_MAX, nla, | ||
3734 | nl80211_sta_wme_policy); | ||
3735 | if (err) | ||
3736 | return err; | ||
3737 | |||
3738 | if (tb[NL80211_STA_WME_UAPSD_QUEUES]) | ||
3739 | params.uapsd_queues = | ||
3740 | nla_get_u8(tb[NL80211_STA_WME_UAPSD_QUEUES]); | ||
3741 | if (params.uapsd_queues & | ||
3742 | ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) | ||
3743 | return -EINVAL; | ||
3744 | 4022 | ||
3745 | if (tb[NL80211_STA_WME_MAX_SP]) | ||
3746 | params.max_sp = | ||
3747 | nla_get_u8(tb[NL80211_STA_WME_MAX_SP]); | ||
3748 | |||
3749 | if (params.max_sp & | ||
3750 | ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK) | ||
3751 | return -EINVAL; | ||
3752 | |||
3753 | params.sta_modify_mask |= STATION_PARAM_APPLY_UAPSD; | ||
3754 | } | ||
3755 | /* TDLS peers cannot be added */ | 4023 | /* TDLS peers cannot be added */ |
3756 | if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) | 4024 | if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) |
3757 | return -EINVAL; | 4025 | return -EINVAL; |
@@ -3772,6 +4040,9 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
3772 | return PTR_ERR(params.vlan); | 4040 | return PTR_ERR(params.vlan); |
3773 | break; | 4041 | break; |
3774 | case NL80211_IFTYPE_MESH_POINT: | 4042 | case NL80211_IFTYPE_MESH_POINT: |
4043 | /* ignore uAPSD data */ | ||
4044 | params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD; | ||
4045 | |||
3775 | /* associated is disallowed */ | 4046 | /* associated is disallowed */ |
3776 | if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED)) | 4047 | if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED)) |
3777 | return -EINVAL; | 4048 | return -EINVAL; |
@@ -3780,8 +4051,14 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
3780 | return -EINVAL; | 4051 | return -EINVAL; |
3781 | break; | 4052 | break; |
3782 | case NL80211_IFTYPE_STATION: | 4053 | case NL80211_IFTYPE_STATION: |
3783 | /* associated is disallowed */ | 4054 | case NL80211_IFTYPE_P2P_CLIENT: |
3784 | if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED)) | 4055 | /* ignore uAPSD data */ |
4056 | params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD; | ||
4057 | |||
4058 | /* these are disallowed */ | ||
4059 | if (params.sta_flags_mask & | ||
4060 | (BIT(NL80211_STA_FLAG_ASSOCIATED) | | ||
4061 | BIT(NL80211_STA_FLAG_AUTHENTICATED))) | ||
3785 | return -EINVAL; | 4062 | return -EINVAL; |
3786 | /* Only TDLS peers can be added */ | 4063 | /* Only TDLS peers can be added */ |
3787 | if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) | 4064 | if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) |
@@ -3792,6 +4069,11 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
3792 | /* ... with external setup is supported */ | 4069 | /* ... with external setup is supported */ |
3793 | if (!(rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP)) | 4070 | if (!(rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP)) |
3794 | return -EOPNOTSUPP; | 4071 | return -EOPNOTSUPP; |
4072 | /* | ||
4073 | * Older wpa_supplicant versions always mark the TDLS peer | ||
4074 | * as authorized, but it shouldn't yet be. | ||
4075 | */ | ||
4076 | params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_AUTHORIZED); | ||
3795 | break; | 4077 | break; |
3796 | default: | 4078 | default: |
3797 | return -EOPNOTSUPP; | 4079 | return -EOPNOTSUPP; |
@@ -4336,6 +4618,7 @@ static const struct nla_policy | |||
4336 | [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 }, | 4618 | [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 }, |
4337 | [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 }, | 4619 | [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 }, |
4338 | [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG }, | 4620 | [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG }, |
4621 | [NL80211_MESH_SETUP_USERSPACE_MPM] = { .type = NLA_FLAG }, | ||
4339 | [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY, | 4622 | [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY, |
4340 | .len = IEEE80211_MAX_DATA_LEN }, | 4623 | .len = IEEE80211_MAX_DATA_LEN }, |
4341 | [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG }, | 4624 | [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG }, |
@@ -4474,6 +4757,7 @@ do { \ | |||
4474 | static int nl80211_parse_mesh_setup(struct genl_info *info, | 4757 | static int nl80211_parse_mesh_setup(struct genl_info *info, |
4475 | struct mesh_setup *setup) | 4758 | struct mesh_setup *setup) |
4476 | { | 4759 | { |
4760 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
4477 | struct nlattr *tb[NL80211_MESH_SETUP_ATTR_MAX + 1]; | 4761 | struct nlattr *tb[NL80211_MESH_SETUP_ATTR_MAX + 1]; |
4478 | 4762 | ||
4479 | if (!info->attrs[NL80211_ATTR_MESH_SETUP]) | 4763 | if (!info->attrs[NL80211_ATTR_MESH_SETUP]) |
@@ -4510,8 +4794,14 @@ static int nl80211_parse_mesh_setup(struct genl_info *info, | |||
4510 | setup->ie = nla_data(ieattr); | 4794 | setup->ie = nla_data(ieattr); |
4511 | setup->ie_len = nla_len(ieattr); | 4795 | setup->ie_len = nla_len(ieattr); |
4512 | } | 4796 | } |
4797 | if (tb[NL80211_MESH_SETUP_USERSPACE_MPM] && | ||
4798 | !(rdev->wiphy.features & NL80211_FEATURE_USERSPACE_MPM)) | ||
4799 | return -EINVAL; | ||
4800 | setup->user_mpm = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_MPM]); | ||
4513 | setup->is_authenticated = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]); | 4801 | setup->is_authenticated = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]); |
4514 | setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AMPE]); | 4802 | setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AMPE]); |
4803 | if (setup->is_secure) | ||
4804 | setup->user_mpm = true; | ||
4515 | 4805 | ||
4516 | return 0; | 4806 | return 0; |
4517 | } | 4807 | } |
@@ -5706,14 +5996,10 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) | |||
5706 | { | 5996 | { |
5707 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 5997 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
5708 | struct net_device *dev = info->user_ptr[1]; | 5998 | struct net_device *dev = info->user_ptr[1]; |
5709 | struct cfg80211_crypto_settings crypto; | ||
5710 | struct ieee80211_channel *chan; | 5999 | struct ieee80211_channel *chan; |
5711 | const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL; | 6000 | struct cfg80211_assoc_request req = {}; |
5712 | int err, ssid_len, ie_len = 0; | 6001 | const u8 *bssid, *ssid; |
5713 | bool use_mfp = false; | 6002 | int err, ssid_len = 0; |
5714 | u32 flags = 0; | ||
5715 | struct ieee80211_ht_cap *ht_capa = NULL; | ||
5716 | struct ieee80211_ht_cap *ht_capa_mask = NULL; | ||
5717 | 6003 | ||
5718 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | 6004 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) |
5719 | return -EINVAL; | 6005 | return -EINVAL; |
@@ -5741,41 +6027,58 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) | |||
5741 | ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); | 6027 | ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); |
5742 | 6028 | ||
5743 | if (info->attrs[NL80211_ATTR_IE]) { | 6029 | if (info->attrs[NL80211_ATTR_IE]) { |
5744 | ie = nla_data(info->attrs[NL80211_ATTR_IE]); | 6030 | req.ie = nla_data(info->attrs[NL80211_ATTR_IE]); |
5745 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 6031 | req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); |
5746 | } | 6032 | } |
5747 | 6033 | ||
5748 | if (info->attrs[NL80211_ATTR_USE_MFP]) { | 6034 | if (info->attrs[NL80211_ATTR_USE_MFP]) { |
5749 | enum nl80211_mfp mfp = | 6035 | enum nl80211_mfp mfp = |
5750 | nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]); | 6036 | nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]); |
5751 | if (mfp == NL80211_MFP_REQUIRED) | 6037 | if (mfp == NL80211_MFP_REQUIRED) |
5752 | use_mfp = true; | 6038 | req.use_mfp = true; |
5753 | else if (mfp != NL80211_MFP_NO) | 6039 | else if (mfp != NL80211_MFP_NO) |
5754 | return -EINVAL; | 6040 | return -EINVAL; |
5755 | } | 6041 | } |
5756 | 6042 | ||
5757 | if (info->attrs[NL80211_ATTR_PREV_BSSID]) | 6043 | if (info->attrs[NL80211_ATTR_PREV_BSSID]) |
5758 | prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]); | 6044 | req.prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]); |
5759 | 6045 | ||
5760 | if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT])) | 6046 | if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT])) |
5761 | flags |= ASSOC_REQ_DISABLE_HT; | 6047 | req.flags |= ASSOC_REQ_DISABLE_HT; |
5762 | 6048 | ||
5763 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) | 6049 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) |
5764 | ht_capa_mask = | 6050 | memcpy(&req.ht_capa_mask, |
5765 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]); | 6051 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]), |
6052 | sizeof(req.ht_capa_mask)); | ||
5766 | 6053 | ||
5767 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) { | 6054 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) { |
5768 | if (!ht_capa_mask) | 6055 | if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) |
6056 | return -EINVAL; | ||
6057 | memcpy(&req.ht_capa, | ||
6058 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]), | ||
6059 | sizeof(req.ht_capa)); | ||
6060 | } | ||
6061 | |||
6062 | if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT])) | ||
6063 | req.flags |= ASSOC_REQ_DISABLE_VHT; | ||
6064 | |||
6065 | if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) | ||
6066 | memcpy(&req.vht_capa_mask, | ||
6067 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]), | ||
6068 | sizeof(req.vht_capa_mask)); | ||
6069 | |||
6070 | if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) { | ||
6071 | if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) | ||
5769 | return -EINVAL; | 6072 | return -EINVAL; |
5770 | ht_capa = nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); | 6073 | memcpy(&req.vht_capa, |
6074 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]), | ||
6075 | sizeof(req.vht_capa)); | ||
5771 | } | 6076 | } |
5772 | 6077 | ||
5773 | err = nl80211_crypto_settings(rdev, info, &crypto, 1); | 6078 | err = nl80211_crypto_settings(rdev, info, &req.crypto, 1); |
5774 | if (!err) | 6079 | if (!err) |
5775 | err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid, | 6080 | err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, |
5776 | ssid, ssid_len, ie, ie_len, use_mfp, | 6081 | ssid, ssid_len, &req); |
5777 | &crypto, flags, ht_capa, | ||
5778 | ht_capa_mask); | ||
5779 | 6082 | ||
5780 | return err; | 6083 | return err; |
5781 | } | 6084 | } |
@@ -6355,6 +6658,24 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) | |||
6355 | sizeof(connect.ht_capa)); | 6658 | sizeof(connect.ht_capa)); |
6356 | } | 6659 | } |
6357 | 6660 | ||
6661 | if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_VHT])) | ||
6662 | connect.flags |= ASSOC_REQ_DISABLE_VHT; | ||
6663 | |||
6664 | if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) | ||
6665 | memcpy(&connect.vht_capa_mask, | ||
6666 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]), | ||
6667 | sizeof(connect.vht_capa_mask)); | ||
6668 | |||
6669 | if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) { | ||
6670 | if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) { | ||
6671 | kfree(connkeys); | ||
6672 | return -EINVAL; | ||
6673 | } | ||
6674 | memcpy(&connect.vht_capa, | ||
6675 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]), | ||
6676 | sizeof(connect.vht_capa)); | ||
6677 | } | ||
6678 | |||
6358 | err = cfg80211_connect(rdev, dev, &connect, connkeys); | 6679 | err = cfg80211_connect(rdev, dev, &connect, connkeys); |
6359 | if (err) | 6680 | if (err) |
6360 | kfree(connkeys); | 6681 | kfree(connkeys); |
@@ -7128,6 +7449,9 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) | |||
7128 | return err; | 7449 | return err; |
7129 | } | 7450 | } |
7130 | 7451 | ||
7452 | if (setup.user_mpm) | ||
7453 | cfg.auto_open_plinks = false; | ||
7454 | |||
7131 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | 7455 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { |
7132 | err = nl80211_parse_chandef(rdev, info, &setup.chandef); | 7456 | err = nl80211_parse_chandef(rdev, info, &setup.chandef); |
7133 | if (err) | 7457 | if (err) |
@@ -7327,7 +7651,8 @@ static int nl80211_parse_wowlan_tcp(struct cfg80211_registered_device *rdev, | |||
7327 | return -EINVAL; | 7651 | return -EINVAL; |
7328 | 7652 | ||
7329 | if (nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) > | 7653 | if (nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) > |
7330 | rdev->wiphy.wowlan.tcp->data_interval_max) | 7654 | rdev->wiphy.wowlan.tcp->data_interval_max || |
7655 | nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) == 0) | ||
7331 | return -EINVAL; | 7656 | return -EINVAL; |
7332 | 7657 | ||
7333 | wake_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]); | 7658 | wake_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]); |
@@ -7823,6 +8148,54 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info) | |||
7823 | return 0; | 8148 | return 0; |
7824 | } | 8149 | } |
7825 | 8150 | ||
8151 | static int nl80211_get_protocol_features(struct sk_buff *skb, | ||
8152 | struct genl_info *info) | ||
8153 | { | ||
8154 | void *hdr; | ||
8155 | struct sk_buff *msg; | ||
8156 | |||
8157 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
8158 | if (!msg) | ||
8159 | return -ENOMEM; | ||
8160 | |||
8161 | hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0, | ||
8162 | NL80211_CMD_GET_PROTOCOL_FEATURES); | ||
8163 | if (!hdr) | ||
8164 | goto nla_put_failure; | ||
8165 | |||
8166 | if (nla_put_u32(msg, NL80211_ATTR_PROTOCOL_FEATURES, | ||
8167 | NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP)) | ||
8168 | goto nla_put_failure; | ||
8169 | |||
8170 | genlmsg_end(msg, hdr); | ||
8171 | return genlmsg_reply(msg, info); | ||
8172 | |||
8173 | nla_put_failure: | ||
8174 | kfree_skb(msg); | ||
8175 | return -ENOBUFS; | ||
8176 | } | ||
8177 | |||
8178 | static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info) | ||
8179 | { | ||
8180 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
8181 | struct cfg80211_update_ft_ies_params ft_params; | ||
8182 | struct net_device *dev = info->user_ptr[1]; | ||
8183 | |||
8184 | if (!rdev->ops->update_ft_ies) | ||
8185 | return -EOPNOTSUPP; | ||
8186 | |||
8187 | if (!info->attrs[NL80211_ATTR_MDID] || | ||
8188 | !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | ||
8189 | return -EINVAL; | ||
8190 | |||
8191 | memset(&ft_params, 0, sizeof(ft_params)); | ||
8192 | ft_params.md = nla_get_u16(info->attrs[NL80211_ATTR_MDID]); | ||
8193 | ft_params.ie = nla_data(info->attrs[NL80211_ATTR_IE]); | ||
8194 | ft_params.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | ||
8195 | |||
8196 | return rdev_update_ft_ies(rdev, dev, &ft_params); | ||
8197 | } | ||
8198 | |||
7826 | #define NL80211_FLAG_NEED_WIPHY 0x01 | 8199 | #define NL80211_FLAG_NEED_WIPHY 0x01 |
7827 | #define NL80211_FLAG_NEED_NETDEV 0x02 | 8200 | #define NL80211_FLAG_NEED_NETDEV 0x02 |
7828 | #define NL80211_FLAG_NEED_RTNL 0x04 | 8201 | #define NL80211_FLAG_NEED_RTNL 0x04 |
@@ -8499,6 +8872,19 @@ static struct genl_ops nl80211_ops[] = { | |||
8499 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | 8872 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
8500 | NL80211_FLAG_NEED_RTNL, | 8873 | NL80211_FLAG_NEED_RTNL, |
8501 | }, | 8874 | }, |
8875 | { | ||
8876 | .cmd = NL80211_CMD_GET_PROTOCOL_FEATURES, | ||
8877 | .doit = nl80211_get_protocol_features, | ||
8878 | .policy = nl80211_policy, | ||
8879 | }, | ||
8880 | { | ||
8881 | .cmd = NL80211_CMD_UPDATE_FT_IES, | ||
8882 | .doit = nl80211_update_ft_ies, | ||
8883 | .policy = nl80211_policy, | ||
8884 | .flags = GENL_ADMIN_PERM, | ||
8885 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
8886 | NL80211_FLAG_NEED_RTNL, | ||
8887 | }, | ||
8502 | }; | 8888 | }; |
8503 | 8889 | ||
8504 | static struct genl_multicast_group nl80211_mlme_mcgrp = { | 8890 | static struct genl_multicast_group nl80211_mlme_mcgrp = { |
@@ -8526,7 +8912,8 @@ void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev) | |||
8526 | if (!msg) | 8912 | if (!msg) |
8527 | return; | 8913 | return; |
8528 | 8914 | ||
8529 | if (nl80211_send_wiphy(msg, 0, 0, 0, rdev) < 0) { | 8915 | if (nl80211_send_wiphy(rdev, msg, 0, 0, 0, |
8916 | false, NULL, NULL, NULL) < 0) { | ||
8530 | nlmsg_free(msg); | 8917 | nlmsg_free(msg); |
8531 | return; | 8918 | return; |
8532 | } | 8919 | } |
@@ -8850,21 +9237,31 @@ void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, | |||
8850 | NL80211_CMD_DISASSOCIATE, gfp); | 9237 | NL80211_CMD_DISASSOCIATE, gfp); |
8851 | } | 9238 | } |
8852 | 9239 | ||
8853 | void nl80211_send_unprot_deauth(struct cfg80211_registered_device *rdev, | 9240 | void cfg80211_send_unprot_deauth(struct net_device *dev, const u8 *buf, |
8854 | struct net_device *netdev, const u8 *buf, | 9241 | size_t len) |
8855 | size_t len, gfp_t gfp) | ||
8856 | { | 9242 | { |
8857 | nl80211_send_mlme_event(rdev, netdev, buf, len, | 9243 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
8858 | NL80211_CMD_UNPROT_DEAUTHENTICATE, gfp); | 9244 | struct wiphy *wiphy = wdev->wiphy; |
9245 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
9246 | |||
9247 | trace_cfg80211_send_unprot_deauth(dev); | ||
9248 | nl80211_send_mlme_event(rdev, dev, buf, len, | ||
9249 | NL80211_CMD_UNPROT_DEAUTHENTICATE, GFP_ATOMIC); | ||
8859 | } | 9250 | } |
9251 | EXPORT_SYMBOL(cfg80211_send_unprot_deauth); | ||
8860 | 9252 | ||
8861 | void nl80211_send_unprot_disassoc(struct cfg80211_registered_device *rdev, | 9253 | void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf, |
8862 | struct net_device *netdev, const u8 *buf, | 9254 | size_t len) |
8863 | size_t len, gfp_t gfp) | ||
8864 | { | 9255 | { |
8865 | nl80211_send_mlme_event(rdev, netdev, buf, len, | 9256 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
8866 | NL80211_CMD_UNPROT_DISASSOCIATE, gfp); | 9257 | struct wiphy *wiphy = wdev->wiphy; |
9258 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
9259 | |||
9260 | trace_cfg80211_send_unprot_disassoc(dev); | ||
9261 | nl80211_send_mlme_event(rdev, dev, buf, len, | ||
9262 | NL80211_CMD_UNPROT_DISASSOCIATE, GFP_ATOMIC); | ||
8867 | } | 9263 | } |
9264 | EXPORT_SYMBOL(cfg80211_send_unprot_disassoc); | ||
8868 | 9265 | ||
8869 | static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev, | 9266 | static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev, |
8870 | struct net_device *netdev, int cmd, | 9267 | struct net_device *netdev, int cmd, |
@@ -9067,14 +9464,19 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev, | |||
9067 | nlmsg_free(msg); | 9464 | nlmsg_free(msg); |
9068 | } | 9465 | } |
9069 | 9466 | ||
9070 | void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev, | 9467 | void cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr, |
9071 | struct net_device *netdev, | 9468 | const u8* ie, u8 ie_len, gfp_t gfp) |
9072 | const u8 *macaddr, const u8* ie, u8 ie_len, | ||
9073 | gfp_t gfp) | ||
9074 | { | 9469 | { |
9470 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
9471 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | ||
9075 | struct sk_buff *msg; | 9472 | struct sk_buff *msg; |
9076 | void *hdr; | 9473 | void *hdr; |
9077 | 9474 | ||
9475 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT)) | ||
9476 | return; | ||
9477 | |||
9478 | trace_cfg80211_notify_new_peer_candidate(dev, addr); | ||
9479 | |||
9078 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | 9480 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); |
9079 | if (!msg) | 9481 | if (!msg) |
9080 | return; | 9482 | return; |
@@ -9086,8 +9488,8 @@ void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev, | |||
9086 | } | 9488 | } |
9087 | 9489 | ||
9088 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 9490 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || |
9089 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || | 9491 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || |
9090 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, macaddr) || | 9492 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) || |
9091 | (ie_len && ie && | 9493 | (ie_len && ie && |
9092 | nla_put(msg, NL80211_ATTR_IE, ie_len , ie))) | 9494 | nla_put(msg, NL80211_ATTR_IE, ie_len , ie))) |
9093 | goto nla_put_failure; | 9495 | goto nla_put_failure; |
@@ -9102,6 +9504,7 @@ void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev, | |||
9102 | genlmsg_cancel(msg, hdr); | 9504 | genlmsg_cancel(msg, hdr); |
9103 | nlmsg_free(msg); | 9505 | nlmsg_free(msg); |
9104 | } | 9506 | } |
9507 | EXPORT_SYMBOL(cfg80211_notify_new_peer_candidate); | ||
9105 | 9508 | ||
9106 | void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, | 9509 | void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, |
9107 | struct net_device *netdev, const u8 *addr, | 9510 | struct net_device *netdev, const u8 *addr, |
@@ -9170,7 +9573,7 @@ void nl80211_send_beacon_hint_event(struct wiphy *wiphy, | |||
9170 | nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_BEFORE); | 9573 | nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_BEFORE); |
9171 | if (!nl_freq) | 9574 | if (!nl_freq) |
9172 | goto nla_put_failure; | 9575 | goto nla_put_failure; |
9173 | if (nl80211_msg_put_channel(msg, channel_before)) | 9576 | if (nl80211_msg_put_channel(msg, channel_before, false)) |
9174 | goto nla_put_failure; | 9577 | goto nla_put_failure; |
9175 | nla_nest_end(msg, nl_freq); | 9578 | nla_nest_end(msg, nl_freq); |
9176 | 9579 | ||
@@ -9178,7 +9581,7 @@ void nl80211_send_beacon_hint_event(struct wiphy *wiphy, | |||
9178 | nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_AFTER); | 9581 | nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_AFTER); |
9179 | if (!nl_freq) | 9582 | if (!nl_freq) |
9180 | goto nla_put_failure; | 9583 | goto nla_put_failure; |
9181 | if (nl80211_msg_put_channel(msg, channel_after)) | 9584 | if (nl80211_msg_put_channel(msg, channel_after, false)) |
9182 | goto nla_put_failure; | 9585 | goto nla_put_failure; |
9183 | nla_nest_end(msg, nl_freq); | 9586 | nla_nest_end(msg, nl_freq); |
9184 | 9587 | ||
@@ -9240,31 +9643,42 @@ static void nl80211_send_remain_on_chan_event( | |||
9240 | nlmsg_free(msg); | 9643 | nlmsg_free(msg); |
9241 | } | 9644 | } |
9242 | 9645 | ||
9243 | void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev, | 9646 | void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie, |
9244 | struct wireless_dev *wdev, u64 cookie, | 9647 | struct ieee80211_channel *chan, |
9245 | struct ieee80211_channel *chan, | 9648 | unsigned int duration, gfp_t gfp) |
9246 | unsigned int duration, gfp_t gfp) | ||
9247 | { | 9649 | { |
9650 | struct wiphy *wiphy = wdev->wiphy; | ||
9651 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
9652 | |||
9653 | trace_cfg80211_ready_on_channel(wdev, cookie, chan, duration); | ||
9248 | nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL, | 9654 | nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL, |
9249 | rdev, wdev, cookie, chan, | 9655 | rdev, wdev, cookie, chan, |
9250 | duration, gfp); | 9656 | duration, gfp); |
9251 | } | 9657 | } |
9658 | EXPORT_SYMBOL(cfg80211_ready_on_channel); | ||
9252 | 9659 | ||
9253 | void nl80211_send_remain_on_channel_cancel( | 9660 | void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie, |
9254 | struct cfg80211_registered_device *rdev, | 9661 | struct ieee80211_channel *chan, |
9255 | struct wireless_dev *wdev, | 9662 | gfp_t gfp) |
9256 | u64 cookie, struct ieee80211_channel *chan, gfp_t gfp) | ||
9257 | { | 9663 | { |
9664 | struct wiphy *wiphy = wdev->wiphy; | ||
9665 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
9666 | |||
9667 | trace_cfg80211_ready_on_channel_expired(wdev, cookie, chan); | ||
9258 | nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, | 9668 | nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, |
9259 | rdev, wdev, cookie, chan, 0, gfp); | 9669 | rdev, wdev, cookie, chan, 0, gfp); |
9260 | } | 9670 | } |
9671 | EXPORT_SYMBOL(cfg80211_remain_on_channel_expired); | ||
9261 | 9672 | ||
9262 | void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, | 9673 | void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, |
9263 | struct net_device *dev, const u8 *mac_addr, | 9674 | struct station_info *sinfo, gfp_t gfp) |
9264 | struct station_info *sinfo, gfp_t gfp) | ||
9265 | { | 9675 | { |
9676 | struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; | ||
9677 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
9266 | struct sk_buff *msg; | 9678 | struct sk_buff *msg; |
9267 | 9679 | ||
9680 | trace_cfg80211_new_sta(dev, mac_addr, sinfo); | ||
9681 | |||
9268 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | 9682 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); |
9269 | if (!msg) | 9683 | if (!msg) |
9270 | return; | 9684 | return; |
@@ -9278,14 +9692,17 @@ void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, | |||
9278 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | 9692 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, |
9279 | nl80211_mlme_mcgrp.id, gfp); | 9693 | nl80211_mlme_mcgrp.id, gfp); |
9280 | } | 9694 | } |
9695 | EXPORT_SYMBOL(cfg80211_new_sta); | ||
9281 | 9696 | ||
9282 | void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev, | 9697 | void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp) |
9283 | struct net_device *dev, const u8 *mac_addr, | ||
9284 | gfp_t gfp) | ||
9285 | { | 9698 | { |
9699 | struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; | ||
9700 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
9286 | struct sk_buff *msg; | 9701 | struct sk_buff *msg; |
9287 | void *hdr; | 9702 | void *hdr; |
9288 | 9703 | ||
9704 | trace_cfg80211_del_sta(dev, mac_addr); | ||
9705 | |||
9289 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | 9706 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); |
9290 | if (!msg) | 9707 | if (!msg) |
9291 | return; | 9708 | return; |
@@ -9310,12 +9727,14 @@ void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev, | |||
9310 | genlmsg_cancel(msg, hdr); | 9727 | genlmsg_cancel(msg, hdr); |
9311 | nlmsg_free(msg); | 9728 | nlmsg_free(msg); |
9312 | } | 9729 | } |
9730 | EXPORT_SYMBOL(cfg80211_del_sta); | ||
9313 | 9731 | ||
9314 | void nl80211_send_conn_failed_event(struct cfg80211_registered_device *rdev, | 9732 | void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr, |
9315 | struct net_device *dev, const u8 *mac_addr, | 9733 | enum nl80211_connect_failed_reason reason, |
9316 | enum nl80211_connect_failed_reason reason, | 9734 | gfp_t gfp) |
9317 | gfp_t gfp) | ||
9318 | { | 9735 | { |
9736 | struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; | ||
9737 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
9319 | struct sk_buff *msg; | 9738 | struct sk_buff *msg; |
9320 | void *hdr; | 9739 | void *hdr; |
9321 | 9740 | ||
@@ -9344,6 +9763,7 @@ void nl80211_send_conn_failed_event(struct cfg80211_registered_device *rdev, | |||
9344 | genlmsg_cancel(msg, hdr); | 9763 | genlmsg_cancel(msg, hdr); |
9345 | nlmsg_free(msg); | 9764 | nlmsg_free(msg); |
9346 | } | 9765 | } |
9766 | EXPORT_SYMBOL(cfg80211_conn_failed); | ||
9347 | 9767 | ||
9348 | static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd, | 9768 | static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd, |
9349 | const u8 *addr, gfp_t gfp) | 9769 | const u8 *addr, gfp_t gfp) |
@@ -9388,19 +9808,47 @@ static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd, | |||
9388 | return true; | 9808 | return true; |
9389 | } | 9809 | } |
9390 | 9810 | ||
9391 | bool nl80211_unexpected_frame(struct net_device *dev, const u8 *addr, gfp_t gfp) | 9811 | bool cfg80211_rx_spurious_frame(struct net_device *dev, |
9812 | const u8 *addr, gfp_t gfp) | ||
9392 | { | 9813 | { |
9393 | return __nl80211_unexpected_frame(dev, NL80211_CMD_UNEXPECTED_FRAME, | 9814 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
9394 | addr, gfp); | 9815 | bool ret; |
9816 | |||
9817 | trace_cfg80211_rx_spurious_frame(dev, addr); | ||
9818 | |||
9819 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && | ||
9820 | wdev->iftype != NL80211_IFTYPE_P2P_GO)) { | ||
9821 | trace_cfg80211_return_bool(false); | ||
9822 | return false; | ||
9823 | } | ||
9824 | ret = __nl80211_unexpected_frame(dev, NL80211_CMD_UNEXPECTED_FRAME, | ||
9825 | addr, gfp); | ||
9826 | trace_cfg80211_return_bool(ret); | ||
9827 | return ret; | ||
9395 | } | 9828 | } |
9829 | EXPORT_SYMBOL(cfg80211_rx_spurious_frame); | ||
9396 | 9830 | ||
9397 | bool nl80211_unexpected_4addr_frame(struct net_device *dev, | 9831 | bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, |
9398 | const u8 *addr, gfp_t gfp) | 9832 | const u8 *addr, gfp_t gfp) |
9399 | { | 9833 | { |
9400 | return __nl80211_unexpected_frame(dev, | 9834 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
9401 | NL80211_CMD_UNEXPECTED_4ADDR_FRAME, | 9835 | bool ret; |
9402 | addr, gfp); | 9836 | |
9837 | trace_cfg80211_rx_unexpected_4addr_frame(dev, addr); | ||
9838 | |||
9839 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && | ||
9840 | wdev->iftype != NL80211_IFTYPE_P2P_GO && | ||
9841 | wdev->iftype != NL80211_IFTYPE_AP_VLAN)) { | ||
9842 | trace_cfg80211_return_bool(false); | ||
9843 | return false; | ||
9844 | } | ||
9845 | ret = __nl80211_unexpected_frame(dev, | ||
9846 | NL80211_CMD_UNEXPECTED_4ADDR_FRAME, | ||
9847 | addr, gfp); | ||
9848 | trace_cfg80211_return_bool(ret); | ||
9849 | return ret; | ||
9403 | } | 9850 | } |
9851 | EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame); | ||
9404 | 9852 | ||
9405 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, | 9853 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, |
9406 | struct wireless_dev *wdev, u32 nlportid, | 9854 | struct wireless_dev *wdev, u32 nlportid, |
@@ -9440,15 +9888,17 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, | |||
9440 | return -ENOBUFS; | 9888 | return -ENOBUFS; |
9441 | } | 9889 | } |
9442 | 9890 | ||
9443 | void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev, | 9891 | void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie, |
9444 | struct wireless_dev *wdev, u64 cookie, | 9892 | const u8 *buf, size_t len, bool ack, gfp_t gfp) |
9445 | const u8 *buf, size_t len, bool ack, | ||
9446 | gfp_t gfp) | ||
9447 | { | 9893 | { |
9894 | struct wiphy *wiphy = wdev->wiphy; | ||
9895 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
9448 | struct net_device *netdev = wdev->netdev; | 9896 | struct net_device *netdev = wdev->netdev; |
9449 | struct sk_buff *msg; | 9897 | struct sk_buff *msg; |
9450 | void *hdr; | 9898 | void *hdr; |
9451 | 9899 | ||
9900 | trace_cfg80211_mgmt_tx_status(wdev, cookie, ack); | ||
9901 | |||
9452 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | 9902 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); |
9453 | if (!msg) | 9903 | if (!msg) |
9454 | return; | 9904 | return; |
@@ -9476,17 +9926,21 @@ void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev, | |||
9476 | genlmsg_cancel(msg, hdr); | 9926 | genlmsg_cancel(msg, hdr); |
9477 | nlmsg_free(msg); | 9927 | nlmsg_free(msg); |
9478 | } | 9928 | } |
9929 | EXPORT_SYMBOL(cfg80211_mgmt_tx_status); | ||
9479 | 9930 | ||
9480 | void | 9931 | void cfg80211_cqm_rssi_notify(struct net_device *dev, |
9481 | nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, | 9932 | enum nl80211_cqm_rssi_threshold_event rssi_event, |
9482 | struct net_device *netdev, | 9933 | gfp_t gfp) |
9483 | enum nl80211_cqm_rssi_threshold_event rssi_event, | ||
9484 | gfp_t gfp) | ||
9485 | { | 9934 | { |
9935 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
9936 | struct wiphy *wiphy = wdev->wiphy; | ||
9937 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
9486 | struct sk_buff *msg; | 9938 | struct sk_buff *msg; |
9487 | struct nlattr *pinfoattr; | 9939 | struct nlattr *pinfoattr; |
9488 | void *hdr; | 9940 | void *hdr; |
9489 | 9941 | ||
9942 | trace_cfg80211_cqm_rssi_notify(dev, rssi_event); | ||
9943 | |||
9490 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | 9944 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); |
9491 | if (!msg) | 9945 | if (!msg) |
9492 | return; | 9946 | return; |
@@ -9498,7 +9952,7 @@ nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, | |||
9498 | } | 9952 | } |
9499 | 9953 | ||
9500 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 9954 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || |
9501 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex)) | 9955 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex)) |
9502 | goto nla_put_failure; | 9956 | goto nla_put_failure; |
9503 | 9957 | ||
9504 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_CQM); | 9958 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_CQM); |
@@ -9521,10 +9975,11 @@ nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, | |||
9521 | genlmsg_cancel(msg, hdr); | 9975 | genlmsg_cancel(msg, hdr); |
9522 | nlmsg_free(msg); | 9976 | nlmsg_free(msg); |
9523 | } | 9977 | } |
9978 | EXPORT_SYMBOL(cfg80211_cqm_rssi_notify); | ||
9524 | 9979 | ||
9525 | void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev, | 9980 | static void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev, |
9526 | struct net_device *netdev, const u8 *bssid, | 9981 | struct net_device *netdev, const u8 *bssid, |
9527 | const u8 *replay_ctr, gfp_t gfp) | 9982 | const u8 *replay_ctr, gfp_t gfp) |
9528 | { | 9983 | { |
9529 | struct sk_buff *msg; | 9984 | struct sk_buff *msg; |
9530 | struct nlattr *rekey_attr; | 9985 | struct nlattr *rekey_attr; |
@@ -9566,9 +10021,22 @@ void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev, | |||
9566 | nlmsg_free(msg); | 10021 | nlmsg_free(msg); |
9567 | } | 10022 | } |
9568 | 10023 | ||
9569 | void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev, | 10024 | void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid, |
9570 | struct net_device *netdev, int index, | 10025 | const u8 *replay_ctr, gfp_t gfp) |
9571 | const u8 *bssid, bool preauth, gfp_t gfp) | 10026 | { |
10027 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
10028 | struct wiphy *wiphy = wdev->wiphy; | ||
10029 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
10030 | |||
10031 | trace_cfg80211_gtk_rekey_notify(dev, bssid); | ||
10032 | nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp); | ||
10033 | } | ||
10034 | EXPORT_SYMBOL(cfg80211_gtk_rekey_notify); | ||
10035 | |||
10036 | static void | ||
10037 | nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev, | ||
10038 | struct net_device *netdev, int index, | ||
10039 | const u8 *bssid, bool preauth, gfp_t gfp) | ||
9572 | { | 10040 | { |
9573 | struct sk_buff *msg; | 10041 | struct sk_buff *msg; |
9574 | struct nlattr *attr; | 10042 | struct nlattr *attr; |
@@ -9611,9 +10079,22 @@ void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev, | |||
9611 | nlmsg_free(msg); | 10079 | nlmsg_free(msg); |
9612 | } | 10080 | } |
9613 | 10081 | ||
9614 | void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, | 10082 | void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index, |
9615 | struct net_device *netdev, | 10083 | const u8 *bssid, bool preauth, gfp_t gfp) |
9616 | struct cfg80211_chan_def *chandef, gfp_t gfp) | 10084 | { |
10085 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
10086 | struct wiphy *wiphy = wdev->wiphy; | ||
10087 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
10088 | |||
10089 | trace_cfg80211_pmksa_candidate_notify(dev, index, bssid, preauth); | ||
10090 | nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp); | ||
10091 | } | ||
10092 | EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify); | ||
10093 | |||
10094 | static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, | ||
10095 | struct net_device *netdev, | ||
10096 | struct cfg80211_chan_def *chandef, | ||
10097 | gfp_t gfp) | ||
9617 | { | 10098 | { |
9618 | struct sk_buff *msg; | 10099 | struct sk_buff *msg; |
9619 | void *hdr; | 10100 | void *hdr; |
@@ -9645,11 +10126,36 @@ void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, | |||
9645 | nlmsg_free(msg); | 10126 | nlmsg_free(msg); |
9646 | } | 10127 | } |
9647 | 10128 | ||
9648 | void | 10129 | void cfg80211_ch_switch_notify(struct net_device *dev, |
9649 | nl80211_send_cqm_txe_notify(struct cfg80211_registered_device *rdev, | 10130 | struct cfg80211_chan_def *chandef) |
9650 | struct net_device *netdev, const u8 *peer, | 10131 | { |
9651 | u32 num_packets, u32 rate, u32 intvl, gfp_t gfp) | 10132 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
10133 | struct wiphy *wiphy = wdev->wiphy; | ||
10134 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
10135 | |||
10136 | trace_cfg80211_ch_switch_notify(dev, chandef); | ||
10137 | |||
10138 | wdev_lock(wdev); | ||
10139 | |||
10140 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && | ||
10141 | wdev->iftype != NL80211_IFTYPE_P2P_GO)) | ||
10142 | goto out; | ||
10143 | |||
10144 | wdev->channel = chandef->chan; | ||
10145 | nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL); | ||
10146 | out: | ||
10147 | wdev_unlock(wdev); | ||
10148 | return; | ||
10149 | } | ||
10150 | EXPORT_SYMBOL(cfg80211_ch_switch_notify); | ||
10151 | |||
10152 | void cfg80211_cqm_txe_notify(struct net_device *dev, | ||
10153 | const u8 *peer, u32 num_packets, | ||
10154 | u32 rate, u32 intvl, gfp_t gfp) | ||
9652 | { | 10155 | { |
10156 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
10157 | struct wiphy *wiphy = wdev->wiphy; | ||
10158 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
9653 | struct sk_buff *msg; | 10159 | struct sk_buff *msg; |
9654 | struct nlattr *pinfoattr; | 10160 | struct nlattr *pinfoattr; |
9655 | void *hdr; | 10161 | void *hdr; |
@@ -9665,7 +10171,7 @@ nl80211_send_cqm_txe_notify(struct cfg80211_registered_device *rdev, | |||
9665 | } | 10171 | } |
9666 | 10172 | ||
9667 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 10173 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || |
9668 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || | 10174 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || |
9669 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer)) | 10175 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer)) |
9670 | goto nla_put_failure; | 10176 | goto nla_put_failure; |
9671 | 10177 | ||
@@ -9694,6 +10200,7 @@ nl80211_send_cqm_txe_notify(struct cfg80211_registered_device *rdev, | |||
9694 | genlmsg_cancel(msg, hdr); | 10200 | genlmsg_cancel(msg, hdr); |
9695 | nlmsg_free(msg); | 10201 | nlmsg_free(msg); |
9696 | } | 10202 | } |
10203 | EXPORT_SYMBOL(cfg80211_cqm_txe_notify); | ||
9697 | 10204 | ||
9698 | void | 10205 | void |
9699 | nl80211_radar_notify(struct cfg80211_registered_device *rdev, | 10206 | nl80211_radar_notify(struct cfg80211_registered_device *rdev, |
@@ -9746,15 +10253,18 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev, | |||
9746 | nlmsg_free(msg); | 10253 | nlmsg_free(msg); |
9747 | } | 10254 | } |
9748 | 10255 | ||
9749 | void | 10256 | void cfg80211_cqm_pktloss_notify(struct net_device *dev, |
9750 | nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, | 10257 | const u8 *peer, u32 num_packets, gfp_t gfp) |
9751 | struct net_device *netdev, const u8 *peer, | ||
9752 | u32 num_packets, gfp_t gfp) | ||
9753 | { | 10258 | { |
10259 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
10260 | struct wiphy *wiphy = wdev->wiphy; | ||
10261 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
9754 | struct sk_buff *msg; | 10262 | struct sk_buff *msg; |
9755 | struct nlattr *pinfoattr; | 10263 | struct nlattr *pinfoattr; |
9756 | void *hdr; | 10264 | void *hdr; |
9757 | 10265 | ||
10266 | trace_cfg80211_cqm_pktloss_notify(dev, peer, num_packets); | ||
10267 | |||
9758 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | 10268 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); |
9759 | if (!msg) | 10269 | if (!msg) |
9760 | return; | 10270 | return; |
@@ -9766,7 +10276,7 @@ nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, | |||
9766 | } | 10276 | } |
9767 | 10277 | ||
9768 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 10278 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || |
9769 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || | 10279 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || |
9770 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer)) | 10280 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer)) |
9771 | goto nla_put_failure; | 10281 | goto nla_put_failure; |
9772 | 10282 | ||
@@ -9789,6 +10299,7 @@ nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, | |||
9789 | genlmsg_cancel(msg, hdr); | 10299 | genlmsg_cancel(msg, hdr); |
9790 | nlmsg_free(msg); | 10300 | nlmsg_free(msg); |
9791 | } | 10301 | } |
10302 | EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify); | ||
9792 | 10303 | ||
9793 | void cfg80211_probe_status(struct net_device *dev, const u8 *addr, | 10304 | void cfg80211_probe_status(struct net_device *dev, const u8 *addr, |
9794 | u64 cookie, bool acked, gfp_t gfp) | 10305 | u64 cookie, bool acked, gfp_t gfp) |
@@ -10075,6 +10586,50 @@ static struct notifier_block nl80211_netlink_notifier = { | |||
10075 | .notifier_call = nl80211_netlink_notify, | 10586 | .notifier_call = nl80211_netlink_notify, |
10076 | }; | 10587 | }; |
10077 | 10588 | ||
10589 | void cfg80211_ft_event(struct net_device *netdev, | ||
10590 | struct cfg80211_ft_event_params *ft_event) | ||
10591 | { | ||
10592 | struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy; | ||
10593 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
10594 | struct sk_buff *msg; | ||
10595 | void *hdr; | ||
10596 | int err; | ||
10597 | |||
10598 | trace_cfg80211_ft_event(wiphy, netdev, ft_event); | ||
10599 | |||
10600 | if (!ft_event->target_ap) | ||
10601 | return; | ||
10602 | |||
10603 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
10604 | if (!msg) | ||
10605 | return; | ||
10606 | |||
10607 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FT_EVENT); | ||
10608 | if (!hdr) { | ||
10609 | nlmsg_free(msg); | ||
10610 | return; | ||
10611 | } | ||
10612 | |||
10613 | nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); | ||
10614 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); | ||
10615 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ft_event->target_ap); | ||
10616 | if (ft_event->ies) | ||
10617 | nla_put(msg, NL80211_ATTR_IE, ft_event->ies_len, ft_event->ies); | ||
10618 | if (ft_event->ric_ies) | ||
10619 | nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len, | ||
10620 | ft_event->ric_ies); | ||
10621 | |||
10622 | err = genlmsg_end(msg, hdr); | ||
10623 | if (err < 0) { | ||
10624 | nlmsg_free(msg); | ||
10625 | return; | ||
10626 | } | ||
10627 | |||
10628 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | ||
10629 | nl80211_mlme_mcgrp.id, GFP_KERNEL); | ||
10630 | } | ||
10631 | EXPORT_SYMBOL(cfg80211_ft_event); | ||
10632 | |||
10078 | /* initialisation/exit functions */ | 10633 | /* initialisation/exit functions */ |
10079 | 10634 | ||
10080 | int nl80211_init(void) | 10635 | int nl80211_init(void) |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index b061da4919e1..a4073e808c13 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -29,12 +29,6 @@ void nl80211_send_deauth(struct cfg80211_registered_device *rdev, | |||
29 | void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, | 29 | void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, |
30 | struct net_device *netdev, | 30 | struct net_device *netdev, |
31 | const u8 *buf, size_t len, gfp_t gfp); | 31 | const u8 *buf, size_t len, gfp_t gfp); |
32 | void nl80211_send_unprot_deauth(struct cfg80211_registered_device *rdev, | ||
33 | struct net_device *netdev, | ||
34 | const u8 *buf, size_t len, gfp_t gfp); | ||
35 | void nl80211_send_unprot_disassoc(struct cfg80211_registered_device *rdev, | ||
36 | struct net_device *netdev, | ||
37 | const u8 *buf, size_t len, gfp_t gfp); | ||
38 | void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev, | 32 | void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev, |
39 | struct net_device *netdev, | 33 | struct net_device *netdev, |
40 | const u8 *addr, gfp_t gfp); | 34 | const u8 *addr, gfp_t gfp); |
@@ -54,10 +48,6 @@ void nl80211_send_disconnected(struct cfg80211_registered_device *rdev, | |||
54 | struct net_device *netdev, u16 reason, | 48 | struct net_device *netdev, u16 reason, |
55 | const u8 *ie, size_t ie_len, bool from_ap); | 49 | const u8 *ie, size_t ie_len, bool from_ap); |
56 | 50 | ||
57 | void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev, | ||
58 | struct net_device *netdev, | ||
59 | const u8 *macaddr, const u8* ie, u8 ie_len, | ||
60 | gfp_t gfp); | ||
61 | void | 51 | void |
62 | nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, | 52 | nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, |
63 | struct net_device *netdev, const u8 *addr, | 53 | struct net_device *netdev, const u8 *addr, |
@@ -73,41 +63,10 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev, | |||
73 | struct net_device *netdev, const u8 *bssid, | 63 | struct net_device *netdev, const u8 *bssid, |
74 | gfp_t gfp); | 64 | gfp_t gfp); |
75 | 65 | ||
76 | void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev, | ||
77 | struct wireless_dev *wdev, u64 cookie, | ||
78 | struct ieee80211_channel *chan, | ||
79 | unsigned int duration, gfp_t gfp); | ||
80 | void nl80211_send_remain_on_channel_cancel( | ||
81 | struct cfg80211_registered_device *rdev, | ||
82 | struct wireless_dev *wdev, | ||
83 | u64 cookie, struct ieee80211_channel *chan, gfp_t gfp); | ||
84 | |||
85 | void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, | ||
86 | struct net_device *dev, const u8 *mac_addr, | ||
87 | struct station_info *sinfo, gfp_t gfp); | ||
88 | void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev, | ||
89 | struct net_device *dev, const u8 *mac_addr, | ||
90 | gfp_t gfp); | ||
91 | |||
92 | void nl80211_send_conn_failed_event(struct cfg80211_registered_device *rdev, | ||
93 | struct net_device *dev, const u8 *mac_addr, | ||
94 | enum nl80211_connect_failed_reason reason, | ||
95 | gfp_t gfp); | ||
96 | |||
97 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, | 66 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, |
98 | struct wireless_dev *wdev, u32 nlpid, | 67 | struct wireless_dev *wdev, u32 nlpid, |
99 | int freq, int sig_dbm, | 68 | int freq, int sig_dbm, |
100 | const u8 *buf, size_t len, gfp_t gfp); | 69 | const u8 *buf, size_t len, gfp_t gfp); |
101 | void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev, | ||
102 | struct wireless_dev *wdev, u64 cookie, | ||
103 | const u8 *buf, size_t len, bool ack, | ||
104 | gfp_t gfp); | ||
105 | |||
106 | void | ||
107 | nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, | ||
108 | struct net_device *netdev, | ||
109 | enum nl80211_cqm_rssi_threshold_event rssi_event, | ||
110 | gfp_t gfp); | ||
111 | 70 | ||
112 | void | 71 | void |
113 | nl80211_radar_notify(struct cfg80211_registered_device *rdev, | 72 | nl80211_radar_notify(struct cfg80211_registered_device *rdev, |
@@ -115,31 +74,4 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev, | |||
115 | enum nl80211_radar_event event, | 74 | enum nl80211_radar_event event, |
116 | struct net_device *netdev, gfp_t gfp); | 75 | struct net_device *netdev, gfp_t gfp); |
117 | 76 | ||
118 | void | ||
119 | nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, | ||
120 | struct net_device *netdev, const u8 *peer, | ||
121 | u32 num_packets, gfp_t gfp); | ||
122 | |||
123 | void | ||
124 | nl80211_send_cqm_txe_notify(struct cfg80211_registered_device *rdev, | ||
125 | struct net_device *netdev, const u8 *peer, | ||
126 | u32 num_packets, u32 rate, u32 intvl, gfp_t gfp); | ||
127 | |||
128 | void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev, | ||
129 | struct net_device *netdev, const u8 *bssid, | ||
130 | const u8 *replay_ctr, gfp_t gfp); | ||
131 | |||
132 | void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev, | ||
133 | struct net_device *netdev, int index, | ||
134 | const u8 *bssid, bool preauth, gfp_t gfp); | ||
135 | |||
136 | void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, | ||
137 | struct net_device *dev, | ||
138 | struct cfg80211_chan_def *chandef, gfp_t gfp); | ||
139 | |||
140 | bool nl80211_unexpected_frame(struct net_device *dev, | ||
141 | const u8 *addr, gfp_t gfp); | ||
142 | bool nl80211_unexpected_4addr_frame(struct net_device *dev, | ||
143 | const u8 *addr, gfp_t gfp); | ||
144 | |||
145 | #endif /* __NET_WIRELESS_NL80211_H */ | 77 | #endif /* __NET_WIRELESS_NL80211_H */ |
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h index 422d38291d66..d77e1c1d3a0e 100644 --- a/net/wireless/rdev-ops.h +++ b/net/wireless/rdev-ops.h | |||
@@ -6,11 +6,12 @@ | |||
6 | #include "core.h" | 6 | #include "core.h" |
7 | #include "trace.h" | 7 | #include "trace.h" |
8 | 8 | ||
9 | static inline int rdev_suspend(struct cfg80211_registered_device *rdev) | 9 | static inline int rdev_suspend(struct cfg80211_registered_device *rdev, |
10 | struct cfg80211_wowlan *wowlan) | ||
10 | { | 11 | { |
11 | int ret; | 12 | int ret; |
12 | trace_rdev_suspend(&rdev->wiphy, rdev->wowlan); | 13 | trace_rdev_suspend(&rdev->wiphy, wowlan); |
13 | ret = rdev->ops->suspend(&rdev->wiphy, rdev->wowlan); | 14 | ret = rdev->ops->suspend(&rdev->wiphy, wowlan); |
14 | trace_rdev_return_int(&rdev->wiphy, ret); | 15 | trace_rdev_return_int(&rdev->wiphy, ret); |
15 | return ret; | 16 | return ret; |
16 | } | 17 | } |
@@ -887,4 +888,17 @@ static inline int rdev_set_mac_acl(struct cfg80211_registered_device *rdev, | |||
887 | trace_rdev_return_int(&rdev->wiphy, ret); | 888 | trace_rdev_return_int(&rdev->wiphy, ret); |
888 | return ret; | 889 | return ret; |
889 | } | 890 | } |
891 | |||
892 | static inline int rdev_update_ft_ies(struct cfg80211_registered_device *rdev, | ||
893 | struct net_device *dev, | ||
894 | struct cfg80211_update_ft_ies_params *ftie) | ||
895 | { | ||
896 | int ret; | ||
897 | |||
898 | trace_rdev_update_ft_ies(&rdev->wiphy, dev, ftie); | ||
899 | ret = rdev->ops->update_ft_ies(&rdev->wiphy, dev, ftie); | ||
900 | trace_rdev_return_int(&rdev->wiphy, ret); | ||
901 | return ret; | ||
902 | } | ||
903 | |||
890 | #endif /* __CFG80211_RDEV_OPS */ | 904 | #endif /* __CFG80211_RDEV_OPS */ |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 98532c00242d..e6df52dc8c69 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -184,14 +184,14 @@ static const struct ieee80211_regdomain world_regdom = { | |||
184 | NL80211_RRF_NO_IBSS | | 184 | NL80211_RRF_NO_IBSS | |
185 | NL80211_RRF_NO_OFDM), | 185 | NL80211_RRF_NO_OFDM), |
186 | /* IEEE 802.11a, channel 36..48 */ | 186 | /* IEEE 802.11a, channel 36..48 */ |
187 | REG_RULE(5180-10, 5240+10, 40, 6, 20, | 187 | REG_RULE(5180-10, 5240+10, 80, 6, 20, |
188 | NL80211_RRF_PASSIVE_SCAN | | 188 | NL80211_RRF_PASSIVE_SCAN | |
189 | NL80211_RRF_NO_IBSS), | 189 | NL80211_RRF_NO_IBSS), |
190 | 190 | ||
191 | /* NB: 5260 MHz - 5700 MHz requies DFS */ | 191 | /* NB: 5260 MHz - 5700 MHz requires DFS */ |
192 | 192 | ||
193 | /* IEEE 802.11a, channel 149..165 */ | 193 | /* IEEE 802.11a, channel 149..165 */ |
194 | REG_RULE(5745-10, 5825+10, 40, 6, 20, | 194 | REG_RULE(5745-10, 5825+10, 80, 6, 20, |
195 | NL80211_RRF_PASSIVE_SCAN | | 195 | NL80211_RRF_PASSIVE_SCAN | |
196 | NL80211_RRF_NO_IBSS), | 196 | NL80211_RRF_NO_IBSS), |
197 | 197 | ||
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index f432bd3755b1..bad4c4b5e4eb 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -159,7 +159,7 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) | |||
159 | { | 159 | { |
160 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | 160 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); |
161 | struct cfg80211_connect_params *params; | 161 | struct cfg80211_connect_params *params; |
162 | const u8 *prev_bssid = NULL; | 162 | struct cfg80211_assoc_request req = {}; |
163 | int err; | 163 | int err; |
164 | 164 | ||
165 | ASSERT_WDEV_LOCK(wdev); | 165 | ASSERT_WDEV_LOCK(wdev); |
@@ -186,16 +186,20 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) | |||
186 | BUG_ON(!rdev->ops->assoc); | 186 | BUG_ON(!rdev->ops->assoc); |
187 | wdev->conn->state = CFG80211_CONN_ASSOCIATING; | 187 | wdev->conn->state = CFG80211_CONN_ASSOCIATING; |
188 | if (wdev->conn->prev_bssid_valid) | 188 | if (wdev->conn->prev_bssid_valid) |
189 | prev_bssid = wdev->conn->prev_bssid; | 189 | req.prev_bssid = wdev->conn->prev_bssid; |
190 | err = __cfg80211_mlme_assoc(rdev, wdev->netdev, | 190 | req.ie = params->ie; |
191 | params->channel, params->bssid, | 191 | req.ie_len = params->ie_len; |
192 | prev_bssid, | 192 | req.use_mfp = params->mfp != NL80211_MFP_NO; |
193 | params->ssid, params->ssid_len, | 193 | req.crypto = params->crypto; |
194 | params->ie, params->ie_len, | 194 | req.flags = params->flags; |
195 | params->mfp != NL80211_MFP_NO, | 195 | req.ht_capa = params->ht_capa; |
196 | ¶ms->crypto, | 196 | req.ht_capa_mask = params->ht_capa_mask; |
197 | params->flags, ¶ms->ht_capa, | 197 | req.vht_capa = params->vht_capa; |
198 | ¶ms->ht_capa_mask); | 198 | req.vht_capa_mask = params->vht_capa_mask; |
199 | |||
200 | err = __cfg80211_mlme_assoc(rdev, wdev->netdev, params->channel, | ||
201 | params->bssid, params->ssid, | ||
202 | params->ssid_len, &req); | ||
199 | if (err) | 203 | if (err) |
200 | __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, | 204 | __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, |
201 | NULL, 0, | 205 | NULL, 0, |
diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c index 238ee49b3868..8f28b9f798d8 100644 --- a/net/wireless/sysfs.c +++ b/net/wireless/sysfs.c | |||
@@ -83,6 +83,14 @@ static int wiphy_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
83 | return 0; | 83 | return 0; |
84 | } | 84 | } |
85 | 85 | ||
86 | static void cfg80211_leave_all(struct cfg80211_registered_device *rdev) | ||
87 | { | ||
88 | struct wireless_dev *wdev; | ||
89 | |||
90 | list_for_each_entry(wdev, &rdev->wdev_list, list) | ||
91 | cfg80211_leave(rdev, wdev); | ||
92 | } | ||
93 | |||
86 | static int wiphy_suspend(struct device *dev, pm_message_t state) | 94 | static int wiphy_suspend(struct device *dev, pm_message_t state) |
87 | { | 95 | { |
88 | struct cfg80211_registered_device *rdev = dev_to_rdev(dev); | 96 | struct cfg80211_registered_device *rdev = dev_to_rdev(dev); |
@@ -90,12 +98,19 @@ static int wiphy_suspend(struct device *dev, pm_message_t state) | |||
90 | 98 | ||
91 | rdev->suspend_at = get_seconds(); | 99 | rdev->suspend_at = get_seconds(); |
92 | 100 | ||
93 | if (rdev->ops->suspend) { | 101 | rtnl_lock(); |
94 | rtnl_lock(); | 102 | if (rdev->wiphy.registered) { |
95 | if (rdev->wiphy.registered) | 103 | if (!rdev->wowlan) |
96 | ret = rdev_suspend(rdev); | 104 | cfg80211_leave_all(rdev); |
97 | rtnl_unlock(); | 105 | if (rdev->ops->suspend) |
106 | ret = rdev_suspend(rdev, rdev->wowlan); | ||
107 | if (ret == 1) { | ||
108 | /* Driver refuse to configure wowlan */ | ||
109 | cfg80211_leave_all(rdev); | ||
110 | ret = rdev_suspend(rdev, NULL); | ||
111 | } | ||
98 | } | 112 | } |
113 | rtnl_unlock(); | ||
99 | 114 | ||
100 | return ret; | 115 | return ret; |
101 | } | 116 | } |
diff --git a/net/wireless/trace.h b/net/wireless/trace.h index b7a531380e19..ccadef2106ac 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h | |||
@@ -1785,6 +1785,26 @@ TRACE_EVENT(rdev_set_mac_acl, | |||
1785 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->acl_policy) | 1785 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->acl_policy) |
1786 | ); | 1786 | ); |
1787 | 1787 | ||
1788 | TRACE_EVENT(rdev_update_ft_ies, | ||
1789 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, | ||
1790 | struct cfg80211_update_ft_ies_params *ftie), | ||
1791 | TP_ARGS(wiphy, netdev, ftie), | ||
1792 | TP_STRUCT__entry( | ||
1793 | WIPHY_ENTRY | ||
1794 | NETDEV_ENTRY | ||
1795 | __field(u16, md) | ||
1796 | __dynamic_array(u8, ie, ftie->ie_len) | ||
1797 | ), | ||
1798 | TP_fast_assign( | ||
1799 | WIPHY_ASSIGN; | ||
1800 | NETDEV_ASSIGN; | ||
1801 | __entry->md = ftie->md; | ||
1802 | memcpy(__get_dynamic_array(ie), ftie->ie, ftie->ie_len); | ||
1803 | ), | ||
1804 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", md: 0x%x", | ||
1805 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->md) | ||
1806 | ); | ||
1807 | |||
1788 | /************************************************************* | 1808 | /************************************************************* |
1789 | * cfg80211 exported functions traces * | 1809 | * cfg80211 exported functions traces * |
1790 | *************************************************************/ | 1810 | *************************************************************/ |
@@ -2413,6 +2433,32 @@ TRACE_EVENT(cfg80211_report_wowlan_wakeup, | |||
2413 | TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG) | 2433 | TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG) |
2414 | ); | 2434 | ); |
2415 | 2435 | ||
2436 | TRACE_EVENT(cfg80211_ft_event, | ||
2437 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, | ||
2438 | struct cfg80211_ft_event_params *ft_event), | ||
2439 | TP_ARGS(wiphy, netdev, ft_event), | ||
2440 | TP_STRUCT__entry( | ||
2441 | WIPHY_ENTRY | ||
2442 | NETDEV_ENTRY | ||
2443 | __dynamic_array(u8, ies, ft_event->ies_len) | ||
2444 | MAC_ENTRY(target_ap) | ||
2445 | __dynamic_array(u8, ric_ies, ft_event->ric_ies_len) | ||
2446 | ), | ||
2447 | TP_fast_assign( | ||
2448 | WIPHY_ASSIGN; | ||
2449 | NETDEV_ASSIGN; | ||
2450 | if (ft_event->ies) | ||
2451 | memcpy(__get_dynamic_array(ies), ft_event->ies, | ||
2452 | ft_event->ies_len); | ||
2453 | MAC_ASSIGN(target_ap, ft_event->target_ap); | ||
2454 | if (ft_event->ric_ies) | ||
2455 | memcpy(__get_dynamic_array(ric_ies), ft_event->ric_ies, | ||
2456 | ft_event->ric_ies_len); | ||
2457 | ), | ||
2458 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", target_ap: " MAC_PR_FMT, | ||
2459 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(target_ap)) | ||
2460 | ); | ||
2461 | |||
2416 | #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */ | 2462 | #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */ |
2417 | 2463 | ||
2418 | #undef TRACE_INCLUDE_PATH | 2464 | #undef TRACE_INCLUDE_PATH |